I'm trying to learn to use class.
And I have a class that creates a div element for me.
Which got an id.
And, I have a function that overrides the id, but how do I do that?
My Class:
var count = 0;
class Element {
constructor(width,height,into) {
this.createElement("",into,width,height)
}
createElement(type,into,width,height) {
if (!type)
type = "div"
let element = document.createElement(type);
element.style.width = width;
element.style.height = height;
element.style.border = 1+"px solid"
element.style.position = "relative";
element.name = "element" + count;
document.querySelector(into).append(element)
count ++
}
addID(name,clasName) {
clasName = clasName.id
return document.querySelector(`.+${clasName}`) = this.name
}
}
My Script:
var test = new Element(100 + "%", 100 + "px", "body");
test.addID("MainDiv", test.id)
Thx for u help
I think what you're looking for is this.className = className.id;. The question is a bit vague but the this keyword will give you a reference to your class instance.
Problems & solution:
Element Class not return id .So test.id is undefined one.So you must declare with this.id for Better understand in class refer doc
Add embedded the id with element using element.id=this.id in createElement function
And document.querySelector target classname selector.But if you are passing id use with # instead of .
And return statement in addID is not working .Because You are passing the value to element .Use textContent for pass value to div
var count = 0;
class Element {
constructor(width,height,into) {
this.createElement("",into,width,height)
this.id='one';
this.name="is this name"
}
createElement(type,into,width,height) {
if (!type)
type = "div"
let element = document.createElement(type);
element.style.width = width;
element.style.height = height;
element.style.border = 1+"px solid"
element.style.position = "relative";
element.name = "element" + count;
element.id=this.id;
document.querySelector(into).append(element)
count ++
}
addID(name,clasName) {
clasName = clasName.id;
document.querySelector(`#${clasName}`).textContent = name
}
}
var test = new Element(100 + "%", 100 + "px", "body");
test.addID("MainDiv", test.id)
Solution
first of all I had to use the referrer this.!
For adding or removing classnames or id, you also can manipulate your created element in progress.
'use strict'
var count = 0;
class Element {
constructor(type, width, height, into, functionName, value) {
if (into)
this.createElement(type, into, width, height, functionName, value)
}
createElement(type, into, width, height, functionName, value) {
if (!type)
type = "div"
this.element = document.createElement(type);
this.element.style.width = width;
this.element.style.height = height;
this.element.style.border = 1 + "px solid"
this.element.style.position = "relative";
// this.element.id = this.id
if (type == "button")
this.extendButton(this.element, functionName, value);
document.querySelector(into).append(this.element);
count++;
}
extendButton(element, functionName, value) {
this.element.onclick = functionName;
this.element.innerHTML = value;
}
addID(name, clasName) {
return this.element.id = name
}
} //END
Script:
var test = new Element("",100 + "%", 100 + "px", "body");
test.addID("try");
test.addID("MainDiv")
var test2 = new Element("",80 + "%", 80 + "px", "#MainDiv");
test2.addID("harry");
var buttonTest = new Element("button","","","#MainDiv","showOutgoings","testet")
Guys thank you for your suggestion =)
Related
Hello i am trying to make a class to have numerous object changing background images on a site without creating each object one by one.
So i have done this to change the background image of one "object" :
let x = 0; //index
const image = ["assets/img1.jpeg", "assets/img2.jpeg", "assets/img3.jpeg"]; //images to show
function displayNextImage() {
x = (x === 2) ? 0 : x + 1;
document.getElementById("myID").setAttribute("style", "background-image: url(" + image[x] + ")") //change images
};
function startTimer() {
setInterval(displayNextImage, 3000); //start looping
}
startTimer();
It work and so i want to make it a class :
class changingImageObject {
constructor(img1, img2, img3, id) {
this.image = [img1, img2, img3];
this.id = id;
this.x = 0;
};
displayNextImage() { //Change the showed image x+1
this.x = (this.x === 2) ? 0 : this.x + 1;
document.getElementById(this.id).setAttribute("style", "background-image: url(" + this.image[this.x] + ")");
};
startTimer() { //Change image after 3sec (looping)
setInterval(this.displayNextImage, 3000);
};
}
const changingImages = new changingImageObject("assets/img1.jpeg", "assets/img2.jpeg", "assets/img3.jpeg", "myID");
changingImages.startTimer();
I added the script at the end of the html, it create the object but the displayNextImage function give a error : Uncaught TypeError: Cannot read property 'setAttribute' of null
at displayNextImage
Thx for reading
It seems i needed to bind my method to the constructor, thanks to Mubaraq.
Code with correction.
constructor(img1, img2, img3, id) {
this.image = [img1, img2, img3];
this.id = id;
this.x = 0;
this.displayNextImage = this.displayNextImage.bind(this);
};
Now i need to learn the use of bind :)
I've been working on a code snippet for a template module that I have been creating and I've hit a wall so to speak. I'm trying to loop through all textareas on my page, and apply formatting with some very basic validation.
Javascript is not my strongest suit but I can understand it to a point, my question is how do I collect the ID's and then use them to apply the formatting.
For example,
for each (textarea)
{
collect character restriction from html
display character restriction in a formatted manner
}
I have included my JSFiddle which I have been using to build this snippet.
I would suggest creating a prototype class for this, that can be extended to do other things aswell:
var CharWatcher = function(input){
this.max = input.getAttribute('max-length');
this.input = input;
input.onKeyDown = this.update.bind(this);
this.wrapper = document.createElement('div');
this.wrapper.innerHTML = 'Chars left: '+ (max - input.value.length);
/* style wrapper element */
/* append around input */
};
CharWatcher.prototype = {
update: function(){
this.wrapper.innerHTML = 'Chars left: ' + (this.max - this.input.value.length);
}
};
/* Somewhere else */
var textareas = document.getElementsByTagName('textarea');
for(var i = 0, l = textareas.length; i < l; i++)
new CharWatcher(textareas[i]);
I've based on #FodorZoltán's class. My class does now:
append the counter below the textarea;
position the counter in the below part of the textarea;
Yeah, I'm lazy and the code has grown up. I added some events and renamed the class name to "TextAreaRanger". It's working here:
var TextAreaRanger = function(input) {
this.MAX = parseInt(input.getAttribute('maxlength'));
this.INPUT = input;
// add input events
input["oncut"] =
input["onpaste"] =
input["onkeydown"] =
input["onkeyup"] = this.update.bind(this);
// create wrapper element
this.wrapper = document.createElement('div');
this.wrapper.innerHTML = 'Chars left: '+ (this.MAX - input.value.length);
/* input parent element */
var ipar = input.parentNode;
// find input's i
for (var i = 0, el; el = ipar.children[i]; i ++) {
if(el === input) break;
}
// append wrapper below the input
if (ipar.children[++i]) {
ipar.insertBefore(this.wrapper, ipar.children[i]);
} else ipar.appendChild(this.wrapper);
/* stylize wrapper */
this.wrapper.style.position = "relative";
this.wrapper.style.color = '#f00';
this.wrapper.style.fontSize = '11px';
this.wrapper.style.left = (input.offsetLeft + (input.offsetWidth - 100)) + "px";
this.wrapper.style.top = (-parseInt(this.wrapper.style.fontSize) * 2) + "px";
};
// Update the counter
TextAreaRanger.prototype["update"] = function() {
this.wrapper.innerHTML = 'Chars left: ' + (this.MAX - this.INPUT.value.length);
};
I have jQuery code to resize several Iframes based on the container they are in. When I did this without the .each() operator All of the iframes used the same div to base their size off of. With .each() the operator runs as evidenced by an alert but does not continue down the function.
Codepen: https://codepen.io/bjackson2016/pen/oLQopy?editors=0010
$(document).ready(function(){
function resize() {
var elements = $('.resize');
var eachElement = $.makeArray(elements);
alert(eachElement);
$.each(eachElement, function(index, value) {
alert(index + " " + value);
var multi = value.data('wfactor');
alert(multi);
var ratio = value.data('ratio');
alert(ratio);
var minX = value.data('minw');
alert(minX);
var minY = value.data('minh');
alert(minY);
var ruler = value.siblings('.widthTest');
alert(ruler);
var pWidth = ruler.width();
alert(pWidth);
var adjWidth = pWidth * multi;
alert(adjWidth);
var eHeight = (Math.round(ratio * adjWidth));
alert(eHeight);
var unadjHeight = Math.round(ratio * pWidth);
alert(unadjHeight);
var eWidth = (Math.round(adjWidth));
alert(eWidth);
if (eHeight < minY) {
$(this).height(minY);
alert('changed height');
} else {
value.height(eHeight);
alert('normal height');
}
if (eWidth < minX) {
value.css('width', pWidth).css('height', unadjHeight);
alert('changed width');
} else {
value.width(eWidth);
alert('kept width');
}
});
}
resize();
$(window).resize(function() {
resize();
});
});
The problem is that there is no value.data().
data() is a jQuery function, and iterating with $.each unwraps the elements, so you're trying to call data() on a native DOM node
$.each(eachElement, function(index, value) {
// value is not a jQuery object here, you'd have to do
var elem = $(value); // where you wrap it again.
});
Try instead
$(document).ready(function() {
$(window).on('resize', resize).trigger('resize');
function resize() {
$('.resize').each(function(index, element) {
var elem = $(element);
var multi = elem.data('wfactor'),
ratio = elem.data('ratio'),
... etc
});
}
});
I would like to mod the JavaScript below to select by class name, rather than element id:
https://github.com/sarathsaleem/grained/blob/master/grained.js
and then ideally initialize, like so:
grained(".classname", options);
This modified version of Sarath Saleem's grained.js gets all elements with a given class name selector (i.e. '.foo') and gives them the specified noise background. I have not tested this code very much, so it is definitely not production quality in terms of efficiency. The key is just to change the element variable to elements and use document.getElementsByClassName where the, newly named, elements variable is defined. This will return an HTMLCollection of all the HTML elements with the given class (i.e. 'foo'). Then, in the part where the element's position and overflow attributes are set, use a for loop and iterate through the HTMLCollection to set the position and overflow attributes for each of the found elements with the given class.
Note: At the bottom of the grained.js file is where I call the grained function.
Also, I adjusted the places that used, previously named, elementId variable to use a new elementClass variable that is based off the given class name.
You can do this anywhere after the grained.js iife as it is in the global namespace after that.
/*! Grained.js
* Author : Sarath Saleem - https://github.com/sarathsaleem
* MIT license: http://opensource.org/licenses/MIT
* GitHub : https://github.com/sarathsaleem/grained
* v0.0.1
*/
(function (window, doc) {
"use strict";
function grained(ele, opt) {
var elements = null,
elementClass = null,
selectorElement = null;
//1
if (typeof ele === 'string') {
elements = doc.getElementsByClassName(ele.split('.')[1]);
}
//1
if (!elements) {
console.error('Grained: cannot find any elements with class ' + ele);
return;
} else {
elementClass = elements[0].className;
}
var elementsLength = elements.length
for( var i = 0; i < elementsLength; i++) {
//set style for parent
if (elements[i].style.position !== 'absolute') {
elements[i].style.position = 'relative';
}
elements[i].style.overflow = 'hidden';
};
var prefixes = ["", "-moz-", "-o-animation-", "-webkit-", "-ms-"];
//default option values
var options = {
animate: true,
patternWidth: 100,
patternHeight: 100,
grainOpacity: 0.1,
grainDensity: 1,
grainWidth: 1,
grainHeight: 1,
grainChaos: 0.5,
grainSpeed: 20
};
Object.keys(opt).forEach(function (key) {
options[key] = opt[key];
});
var generateNoise = function () {
var canvas = doc.createElement('canvas');
var ctx = canvas.getContext('2d');
canvas.width = options.patternWidth;
canvas.height = options.patternHeight;
for (var w = 0; w < options.patternWidth; w += options.grainDensity) {
for (var h = 0; h < options.patternHeight; h += options.grainDensity) {
var rgb = Math.random() * 256 | 0;
ctx.fillStyle = 'rgba(' + [rgb, rgb, rgb, options.grainOpacity].join() + ')';
ctx.fillRect(w, h, options.grainWidth, options.grainHeight);
}
}
return canvas.toDataURL('image/png');
};
function addCSSRule(sheet, selector, rules, index) {
var ins = '';
if (selector.length) {
ins = selector + "{" + rules + "}";
} else {
ins = rules;
}
if ("insertRule" in sheet) {
sheet.insertRule(ins, index);
} else if ("addRule" in sheet) {
sheet.addRule(selector, rules, index);
}
}
var noise = generateNoise();
var animation = '',
keyFrames = ['0%:-10%,10%', '10%:-25%,0%', '20%:-30%,10%', '30%:-30%,30%', '40%::-20%,20%', '50%:-15%,10%', '60%:-20%,20%', '70%:-5%,20%', '80%:-25%,5%', '90%:-30%,25%', '100%:-10%,10%'];
var pre = prefixes.length;
while (pre--) {
animation += '#' + prefixes[pre] + 'keyframes grained{';
for (var key = 0; key < keyFrames.length; key++) {
var keyVal = keyFrames[key].split(':');
animation += keyVal[0] + '{';
animation += prefixes[pre] + 'transform:translate(' + keyVal[1] + ');';
animation += '}';
}
animation += '}';
}
//add animation keyframe
var animationAdded = doc.getElementById('grained-animation');
if (animationAdded) {
animationAdded.parentElement.removeChild(animationAdded);
}
var style = doc.createElement("style");
style.type = "text/css";
style.id = 'grained-animation';
style.innerHTML = animation;
doc.body.appendChild(style);
//add custimozed style
var styleAdded = doc.getElementById('grained-animation-' + elementClass);
if (styleAdded) {
styleAdded.parentElement.removeChild(styleAdded);
}
style = doc.createElement("style");
style.type = "text/css";
style.id = 'grained-animation-' + elementClass;
doc.body.appendChild(style);
var rule = 'background-image: url(' + noise + ');';
rule += 'position: absolute;content: "";height: 300%;width: 300%;left: -100%;top: -100%;';
pre = prefixes.length;
if (options.animate) {
while (pre--) {
rule += prefixes[pre] + 'animation-name:grained;';
rule += prefixes[pre] + 'animation-iteration-count: infinite;';
rule += prefixes[pre] + 'animation-duration: ' + options.grainChaos + 's;';
rule += prefixes[pre] + 'animation-timing-function: steps(' +options.grainSpeed + ', end);';
}
}
//selecter element to add grains
selectorElement = '.' + elementClass + '::before';
addCSSRule(style.sheet, selectorElement, rule, 0);
}
window.grained = grained;
//END
})(window, document);
grained('.foo', {});
<!doctype html>
<html>
<head>
<title>Example</title>
<style>
.foo {
height: 100px;
width: 100px;
}
</style>
</head>
<body>
<div class="foo">
<div class="contents">
<p>Hello World</p>
</div>
</div>
<p>No Noise For Me!</p>
<div class="foo">
<div class="contents">
<p>Hello World</p>
</div>
</div>
<script type="text/javascript" src="grained.js"></script>
<script type="text/javascript" src="index.js"></script>
</body>
</html>
Hope this helps! If you have any questions, please ask! I like to help :D.
This code is from here http://unstoppablerobotninja.com/entry/fluid-images
It takes all the images from a page and makes them fluid. It works great and i am sure many of you know it already.
My question is how can i apply this code only to certain images on the page, either through an ID or through a CLASS. something like this:
<img alt="" src="fluid_image.png" id="makeitfuild"/>
I don't want all my pictures to be fluid but still i want to use the code to certain images.
Please help as i don't know what i need to modify in the code
var imgSizer = {
Config : {
imgCache : []
,spacer : "/path/to/your/spacer.gif"
}
,collate : function(aScope) {
var isOldIE = (document.all && !window.opera && !window.XDomainRequest) ? 1 : 0;
if (isOldIE && document.getElementsByTagName) {
var c = imgSizer;
var imgCache = c.Config.imgCache;
var images = (aScope && aScope.length) ? aScope : document.getElementsByTagName("img");
for (var i = 0; i < images.length; i++) {
images.origWidth = images.offsetWidth;
images.origHeight = images.offsetHeight;
imgCache.push(images);
c.ieAlpha(images);
images.style.width = "100%";
}
if (imgCache.length) {
c.resize(function() {
for (var i = 0; i < imgCache.length; i++) {
var ratio = (imgCache.offsetWidth / imgCache.origWidth);
imgCache.style.height = (imgCache.origHeight * ratio) + "px";
}
});
}
}
}
,ieAlpha : function(img) {
var c = imgSizer;
if (img.oldSrc) {
img.src = img.oldSrc;
}
var src = img.src;
img.style.width = img.offsetWidth + "px";
img.style.height = img.offsetHeight + "px";
img.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + src + "', sizingMethod='scale')"
img.oldSrc = src;
img.src = c.Config.spacer;
}
// Ghettomodified version of Simon Willison's addLoadEvent() -- http://simonwillison.net/2004/May/26/addLoadEvent/
,resize : function(func) {
var oldonresize = window.onresize;
if (typeof window.onresize != 'function') {
window.onresize = func;
} else {
window.onresize = function() {
if (oldonresize) {
oldonresize();
}
func();
}
}
}
}
You'll want to change the following line:
var images = (aScope && aScope.length) ? aScope : document.getElementsByTagName("img");
to something that will get your images by a class name. There are a few ways to do that: you can use jQuery, in which case it simply becomes
var images = (aScope && aScope.length) ? aScope : $("#myClassName");
or, you can look up any of the questions about how to get elements simply by class using only javascript (How to getElementByClass instead of GetElementById with Javascript? and How to Get Element By Class in JavaScript? both quickly jump to mind).