This is a JavaScript function used for creating dynamic buttons. I want to access innerHTML of button.
function mynumber() {
var i,j = 1, num = 0; # i used for making three buttons in row and j used for repeat same process no of time and num is int text on button
do {
for (i = 1; i <= 3; i++) {
var btn = document.createElement("BUTTON"); # create button using javascript
var txt = document.createTextNode(num++); # creat text on button
btn.appendChild(txt); # attached text on button
btn.id = ('obj'+ k++) ;
document.getElementById("btnsize").appendChild(btn); # atache button with text in div
}
var next = document.createElement("BR");
document.getElementById("btnsize").appendChild(next);
j++;
}
while(j<4)
}
("btn").click(function()
{
var val = document.getElementById(this.id).innerHTML;
document.getElementById("demo").value = val;
})
You can apply css class to the button as shown in https://jsfiddle.net/3u71kzrh/
Declare a style as below in your stylesheet or between the <style> and </style> tag in the html <head>.
.aClassName{
width:40px;
height:40px;
}
Add the following line just below the code where you create the button element.
btn.className = "aClassName";
use below script in your script code where "100" is variable whatever you want to give but that would be a number ;)
btn.style.width="100px"
btn.style.height="100px"
First of all, I'd change your <button>-creation script to the following:
function mynumber () {
// a reference to the element to which we want
// to add the newly-created <button> elements:
var appendTo = document.getElementById('btnsize'),
// creating a document fragment to contain
// the elements to be added; to prevent the
// document from redrawing every time an
// element is added:
fragment = document.createDocumentFragment(),
// creating a <button> element:
button = document.createElement('button'),
// creating a <br> element:
br = document.createElement('br'),
// initialising an empty variable, for
// use within the loop:
clone;
// you want nine buttons, so use one loop
// that will run nine times:
for (var i = 0; i < 9; i++) {
// using the empty variable to
// hold the cloned <button> element:
clone = button.cloneNode();
// setting the text of the <button>
// to the current index/iteration
// (i) of the loop:
clone.textContent = i;
// appending the cloned <button>
// to the document fragment:
fragment.appendChild(clone);
// we want rows of three, but
// JavaScript is zero-based, so
// we add 1 to i, and check the
// remainder of the division by
// 3; if it's zero the number is
// evenly-divisible by 3 therefore
// it's time to add a <br>:
if ((i+1)%3 === 0) {
// appendin a cloned <br> element:
fragment.appendChild(br.cloneNode())
}
}
// appending the fragment to the
// container element:
appendTo.appendChild(fragment);
}
// calling the function:
mynumber();
function mynumber() {
var appendTo = document.getElementById('btnsize'),
fragment = document.createDocumentFragment(),
button = document.createElement('button'),
br = document.createElement('br'),
clone;
for (var i = 0; i < 9; i++) {
clone = button.cloneNode();
clone.textContent = i;
fragment.appendChild(clone);
if ((i + 1) % 3 === 0) {
fragment.appendChild(br.cloneNode())
}
}
appendTo.appendChild(fragment);
}
mynumber();
<div id="btnsize"></div>
External JS Fiddle demo, for experimentation.
But, because I like to be able to change things – and this also helps address your sizing requirement – I'd amend that to the following, which allows you to call the function, and supply some user-defined options:
// the 'opts' is an Object, containing
// user-defined settings:
function mynumber(opts) {
// these are the defaults:
var settings = {
'container': 'btnsize',
'elements': 'button',
'elementClass': 'newButton',
'height': 'equal',
'width': 'equal',
'rows': 3,
'cols': 3
};
// here we iterate over the properties in the
// opts Object, using for...in:
for (var property in opts) {
// if the object's property is user-defined:
if (opts.hasOwnProperty(property)) {
// we update the settings property to
// match (note: no sanity-checking):
settings[property] = opts[property];
}
}
// finding the element to which we're appending the
// content; using the settings.container property
// (which should contain the 'id' of the element,
// as we're using document.getElementById()):
var appendTo = document.getElementById(settings.container),
fragment = document.createDocumentFragment(),
// 'button' is perhaps a misnomer, since we're creating
// whatever element the user defined, with the
// settings.elements property:
button = document.createElement(settings.elements),
br = document.createElement('br'),
clone;
// if there is a class-name set for the created elements,
// we set that on the created-element (which will be
// copied to all clones, in the loop):
if (settings.elementClass) {
button.classList.add(settings.elementClass);
}
// if the settings.height property is not 'equal', and
// the settings.height can be parsed as a number (a
// naive check, and we're not validating units):
if (settings.height !== 'equal' && parseFloat(settings.height)) {
// we set the height of the created element to
// the value of the settings.height property:
button.style.height = settings.height;
}
// As above, but for height:
if (settings.width !== 'equal' && parseFloat(settings.width)) {
button.style.width = settings.width;
}
// iterating from 0 to the result of multiplying the
// required number of rows by the required number of columns:
for (var i = 0, len = (settings.rows * settings.cols); i < len; i++) {
clone = button.cloneNode();
clone.textContent = i;
fragment.appendChild(clone);
if ((i + 1) % settings.cols === 0) {
fragment.appendChild(br.cloneNode())
}
}
appendTo.appendChild(fragment);
// To avoid running the same test, in subsequent
// if assessments, we create a couple of Booleans
// to test whether settings.width, or
// settings.height, were set to the string 'equal':
var widthEqual = settings.width === 'equal',
heightEqual = settings.height === 'equal';
// if either of those assessments returned true:
if (widthEqual || heightEqual) {
// we find all the elements contained within the
// appended node (to which the elements were
// appended) that have the tagName of the
// created elements:
var appended = appendTo.getElementsByTagName(settings.elements),
// we get the width, and height, of the last
// of those elements - on the assumption that
// that element will have the highest, and
// therefore longest/largest number:
width = appended[appended.length - 1].clientWidth,
height = appended[appended.length - 1].clientHeight;
// if both settings.width and settings.height were
// set to 'equal':
if (widthEqual && heightEqual) {
// we use Function.prototype.call(), to apply
// Array.prototype.forEach() to the Array-like
// NodeList returned by document.getElementsByTagName()
// (from earlier):
Array.prototype.forEach.call(appended, function (btn) {
// btn - the first (and, here, only) argument
// to the anonymous function is the array-
// element over which we're iterating:
// setting the width and height of the
// current element to be equal to the
// found width/height of the last
// element:
btn.style.width = width + 'px';
btn.style.height = height + 'px';
});
// otherwise, if only the width was 'equal':
} else if (widthEqual) {
// As above, setting only the width:
Array.prototype.forEach.call(appended, function (btn) {
btn.style.width = width + 'px';
});
// As above, addressing only the height:
} else if (heightEqual) {
Array.prototype.forEach.call(appended, function (btn) {
btn.style.height = height + 'px';
});
}
}
}
// calling the function, using only the defaults:
mynumber();
// calling the function, setting
// custom values:
mynumber({
'container' : 'anotherElement',
'rows' : 5,
'cols': 4,
'elementClass': 'arbitraryClassName'
});
// calling the function, this time
// explicitly setting the height
// and width:
mynumber({
'container' : 'more',
'elements' : 'span',
'width' : '3em',
'height' : '2em'
});
function mynumber(opts) {
var settings = {
'container': 'btnsize',
'elements': 'button',
'elementClass': 'newButton',
'height': 'equal',
'width': 'equal',
'rows': 3,
'cols': 3
};
for (var property in opts) {
if (opts.hasOwnProperty(property)) {
settings[property] = opts[property];
}
}
var appendTo = document.getElementById(settings.container),
fragment = document.createDocumentFragment(),
button = document.createElement(settings.elements),
br = document.createElement('br'),
clone;
if (settings.elementClass) {
button.classList.add(settings.elementClass);
}
if (settings.height !== 'equal' && parseFloat(settings.height)) {
button.style.height = settings.height;
}
if (settings.width !== 'equal' && parseFloat(settings.width)) {
button.style.width = settings.width;
}
for (var i = 0, len = (settings.rows * settings.cols); i < len; i++) {
clone = button.cloneNode();
clone.textContent = i;
fragment.appendChild(clone);
if ((i + 1) % settings.cols === 0) {
fragment.appendChild(br.cloneNode())
}
}
appendTo.appendChild(fragment);
var widthEqual = settings.width === 'equal',
heightEqual = settings.height === 'equal';
if (widthEqual || heightEqual) {
var appended = appendTo.getElementsByTagName(settings.elements),
width = appended[appended.length - 1].clientWidth,
height = appended[appended.length - 1].clientHeight;
if (widthEqual && heightEqual) {
Array.prototype.forEach.call(appended, function(btn) {
btn.style.width = width + 'px';
btn.style.height = height + 'px';
});
} else if (widthEqual) {
Array.prototype.forEach.call(appended, function(btn) {
btn.style.width = width + 'px';
});
} else if (heightEqual) {
Array.prototype.forEach.call(appended, function(btn) {
btn.style.height = height + 'px';
});
}
}
}
mynumber();
mynumber({
'container': 'anotherElement',
'rows': 5,
'cols': 4,
'elementClass': 'arbitraryClassName'
});
mynumber({
'container': 'more',
'width': '3em',
'height': '2em'
});
button {
font-size: 2em;
}
.arbitraryClassName {
color: #fff;
border: 1px solid limegreen;
text-shadow: 0 0 2px #000;
}
<div id="btnsize"></div>
<div id="anotherElement"></div>
<div id="more"></div>
External JS Fiddle demo, for experimentation/developement.
Now, to address your question in the simplest terms possible, using the code you originally posted (incidentally, in JavaScript, the # character is not valid for comments; it's a syntax error: Uncaught SyntaxError: Unexpected token ILLEGAL), you could simply use CSS such as below:
function mynumber() {
var i, j = 1,
num = 0; // i used for making three buttons in row and j used for repeat same process no of time and num is int text on button
do {
for (i = 1; i <= 3; i++) {
var btn = document.createElement("BUTTON"); // create button using javascript
var txt = document.createTextNode(num++); // creat text on button
btn.appendChild(txt); // attached text on button
document.getElementById("btnsize").appendChild(btn); // atache button with text in div
}
var next = document.createElement("BR");
document.getElementById("btnsize").appendChild(next);
j++;
}
while (j < 4)
}
mynumber();
button {
width: 3em;
height: 4em;
}
<div id="btnsize"></div>
External JS Fiddle demo.
This CSS, of course, matches all <button> elements in the page; however you could amend the selector to be more specific to only those <button> elements within the btnsize element:
#btnsize button {
width: 3em;
height: 2em;
color: #f00;
}
function mynumber() {
var i, j = 1,
num = 0; // i used for making three buttons in row and j used for repeat same process no of time and num is int text on button
do {
for (i = 1; i <= 3; i++) {
var btn = document.createElement("BUTTON"); // create button using javascript
var txt = document.createTextNode(num++); // creat text on button
btn.appendChild(txt); // attached text on button
document.getElementById("btnsize").appendChild(btn); // atache button with text in div
}
var next = document.createElement("BR");
document.getElementById("btnsize").appendChild(next);
j++;
}
while (j < 4)
}
mynumber();
#btnsize button {
width: 3em;
height: 4em;
color: #f00;
}
<div id="btnsize"></div>
<button>Just to demonstrate that I'm not being styled</button>
External JS Fiddle demo.
Or you could add a class-name while you create your <button> elements:
#btnsize button {
width: 3em;
height: 2em;
color: #f00;
}
function mynumber() {
var i, j = 1,
num = 0; // i used for making three buttons in row and j used for repeat same process no of time and num is int text on button
do {
for (i = 1; i <= 3; i++) {
var btn = document.createElement("BUTTON"); // create button using javascript
// adding a class-name:
btn.classList.add('buttonClassName');
var txt = document.createTextNode(num++); // creat text on button
btn.appendChild(txt); // attached text on button
document.getElementById("btnsize").appendChild(btn); // atache button with text in div
}
var next = document.createElement("BR");
document.getElementById("btnsize").appendChild(next);
j++;
}
while (j < 4)
}
mynumber();
.buttonClassName {
width: 3em;
height: 4em;
color: #f00;
}
<div id="btnsize"></div>
<button>Just to demonstrate that I'm not being styled</button>
External JS Fiddle demo.
References:
Array.prototype.forEach().
document.createDocumentFragment().
document.createElement().
document.getElementById().
Element.classList.
for...in.
Function.prototype.call().
HTMLElement.style.
% (modulo) operator.
Node.appendChild().
Node.cloneNode().
Node.textContent.
Object.hasOwnProperty().
Related
I am using the code showed below to create 46 small circles within a wrapper (div) draw-shapes;
let elem = document.getElementById('draw-shapes');
let params = { width: 1024, height: 768 };
let two = new Two(params).appendTo(elem);
for (let i = 1; i < 47; i++) {
circle = two.makeCircle(x, y, radius);
circle.fill = 'green';
circle.stroke = 'white';
circle.linewidth = 1;
circle.id = i;
}
All drawings are made with the Two.js library. I read in the documentation I can change the id of the created element, but I also need to assign a class to each element. I have tried everything from pure js setAttribute to jQuery .attr and .addClass methods, but none of them worked, so I started to wonder if this is even possible to do? If someone knows a way, please let me know how. Thank.
There is not internal utility or property to get to the DOM node of each Two element.
But the id you specify is indeed added as two-<specified-id> to the actual node.
So you can use the normal document.getElementById.
So in your case
let elem = document.getElementById('draw-shapes');
let params = {
width: 300,
height: 300
};
let two = new Two(params).appendTo(elem);
for (let i = 1; i < 20; i++) {
const circle = two.makeCircle(i * 10, i * 10, 40);
circle.fill = 'green';
circle.stroke = 'white';
circle.linewidth = 1;
circle.id = `two-circle-${i}`;
}
two.update();
// add classname to every fifth element;
for (let i = 1; i < 20; i += 5) {
const circleNode = document.getElementById(`two-circle-${i}`);
circleNode.classList.add('classname');
circleNode.addEventListener('mouseover', function() {
const path = two.scene.getById(this.id)
path.scale = 1.2;
two.update();
});
circleNode.addEventListener('mouseout', function() {
const path = two.scene.getById(this.id)
path.scale = 1;
two.update();
});
}
.classname {
stroke-width: 5;
stroke: red;
fill:yellow;
cursor:pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/two.js/0.6.0/two.js"></script>
<div id="draw-shapes"></div>
So I have this div and this function to add a class when one of the sizes is selected.
function Selected(n) {
var i;
var price;
var x = document.getElementsByClassName("SizesId");
for (i = 0; i < x.length; i++) {
document.getElementById("size" + i).style.backgroundColor = "#c6c6c6";
document.getElementById("size" + i).style.color = "black";
document.getElementById("size" + i).className = "SizesId";
}
document.getElementById(n).style.backgroundColor = "#666";
document.getElementById(n).style.color = "white";
document.getElementById(n).className += " selected";
}
<div class="Sizes">
<h3 class="SizesId" onclick="Selected('size0')" id="size0">5</h3>
<h3 class="SizesId" onclick="Selected('size1')" id="size1">6</h3>
<h3 class="SizesId" onclick="Selected('size2')" id="size2">7</h3>
<h3 class="SizesId" onclick="Selected('size3')" id="size3">8</h3>
</div>
How can I change the value of this :- <h2 id="pretFinal">Pret: 150 RON</h2>
For example if the size 5 is selected the price will be "Price: 100 RON" , if the size 6 is selected the price will be "Price: 120 RON" etc.
I can't get it to work, any help is appreciated.
To update the text of the given element, that of #pretFinal the following would work:
// retrieves the required element via its id property:
document.getElementById('pretFinal')
// updates the text-content of that element (assuming
// it exists; if no element is found this will result
// in an error):
.textContent =
// here we concatenate the strings:
'Pret: ' +
// the outer-most parentheses prevent the
// wrapped calculation from concatenated as
// a String, allowing the result of the
// calculation to be concatenated:
(
// this parenthesis allows the result of
// the innermost calculation to be
// multiplied by the 20 (given that
// the order of precedence in math
// would otherwise perform the
// multiplication before the addition):
(
// using the '+' to coerce the string,
// after replacing all ('g') its non-numeric
// characters ('\D' ) with an empty space,
// to a number to which 5 is added:
+n.replace(/\D/g, '') + 5
)
* 20
// finally we add the remainder of the String to be set:
) + ' RON';
function Selected(n) {
var i, price,
x = document.getElementsByClassName("SizesId");
for (i = 0; i < x.length; i++) {
document.getElementById("size" + i).style.backgroundColor = "#c6c6c6";
document.getElementById("size" + i).style.color = "black";
document.getElementById("size" + i).className = "SizesId";
}
document.getElementById(n).style.backgroundColor = "#666";
document.getElementById(n).style.color = "white";
document.getElementById(n).className += " selected";
document.getElementById('pretFinal').textContent = 'Pret: ' + (((+n.replace(/size/gi, '') + 5) * 20)) + ' RON';
}
<h2 id="pretFinal">Pret: 150 RON</h2>
<div class="Sizes">
<h3 class="SizesId" onclick="Selected('size0')" id="size0">5</h3>
<h3 class="SizesId" onclick="Selected('size1')" id="size1">6</h3>
<h3 class="SizesId" onclick="Selected('size2')" id="size2">7</h3>
<h3 class="SizesId" onclick="Selected('size3')" id="size3">8</h3>
</div>
JS Fiddle demo.
While the above approach works, so far as you've described your requirements in your question, it is a poor approach to take: in-line JavaScript results in difficult-to-manage, maintain and update code. A better approach is to use unobtrusive JavaScript, in which event-handlers are bound using JavaScript itself, which in your case leads to the following. Also, worth noting, is that CSS is far better – and gives a better interface in many situations – than using JavaScript to apply new styles. So the following approach also uses CSS to supply the styling:
// using the same named-function, but note that we
// are not explicitly passing in any variables:
function Selected() {
// defining the variables for use:
var i, price,
x = document.getElementsByClassName("SizesId"),
// 'this' is passed in automatically from the later
// use of EventTarget.addEventListener():
clicked = this,
// finding any currently-selected element, the one
// that has both the 'SizesID' and 'selected' classes,
// using document.querySelector() (since there should)
// be only one element that has both classes):
existing = document.querySelector('.SizesId.selected');
// if an element exists with both classes:
if (existing) {
// we remove the 'selected' class-name using
// the HTMLElement.classList API:
existing.classList.remove('selected');
}
// adding the 'selected' class-name to the
//clicked element:
clicked.classList.add('selected');
// setting the textContent of the element identified
// via the id of 'pretFinal', setting it to the string
// of the text-content from the clicked element (again using
// the + to coerce to a number) and then multiplying that with
// '20' (which again seems to be what you want):
document.getElementById('pretFinal').textContent = (+clicked.textContent * 20);
}
// finding the elements with the 'SizesId' selector, converting that
// non-live NodeList to an Array and then iterating over that Array
// using Array.prototype.forEach():
Array.from(document.querySelectorAll('.SizesId')).forEach(
// using an Arrow function, to the currently-selected
// Array element, of the Array of elements, 'el' to use
// EventTarget.addEventListener() to bind a 'click'
// event-listener which will run the named function
// (here 'Selected') and note the lack of parentheses:
el => el.addEventListener('click', Selected)
);
The CSS for the following is:
/* setting the styles for the elements
of this class-name: */
.SizesId {
color: #000;
background-color: #c6c6c6;
}
/* setting the styles for the 'selected'
elements with each of the class-names
below: */
.SizesId.selected {
color: #fff;
background-color: #666;
}
/* this sets the text of 'Pret'
as the text of the ::before
pseudo-element (which means
it doesn't need to be present
in the HTML, making the String
concatenation/generation far
easier): */
#pretFinal::before {
content: 'Pret: ';
}
/* this sets the text of 'RON'
as the text-content of the
::after pseudo-element: */
#pretFinal::after {
content: ' RON';
}
function Selected() {
var i, price,
x = document.getElementsByClassName("SizesId"),
clicked = this,
existing = document.querySelector('.SizesId.selected');
if (existing) {
existing.classList.remove('selected');
}
clicked.classList.add('selected');
document.getElementById('pretFinal').textContent = (+clicked.textContent * 20);
}
Array.from(document.querySelectorAll('.SizesId')).forEach(
el => el.addEventListener('click', Selected)
);
.SizesId {
color: #000;
background-color: #c6c6c6;
}
.SizesId.selected {
color: #fff;
background-color: #666;
}
#pretFinal::before {
content: 'Pret: ';
}
#pretFinal::after {
content: ' RON';
}
<h2 id="pretFinal">150</h2>
<div class="Sizes">
<h3 class="SizesId" id="size0">5</h3>
<h3 class="SizesId" id="size1">6</h3>
<h3 class="SizesId" id="size2">7</h3>
<h3 class="SizesId" id="size3">8</h3>
</div>
JS Fiddle demo.
Use this:
var val = document.getElementById(n).innerHTML;
document.getElementById('pretFinal').innerHTML = 'Price: ' + val * 20 + ' RON';
You can use switch statement and use document.getElementById('id').innerHTML to change its value
function Selected(n) {
var i;
var price;
switch (n) {
case 'size0' :
price = '100';
break;
case 'size1' :
price = '120';
break;
case 'size2' :
price = '140';
break;
case 'size3' :
price = '160';
break;
}
var x = document.getElementsByClassName("SizesId");
for(i = 0; i < x.length; i++)
{
document.getElementById("size" + i).style.backgroundColor = "#c6c6c6";
document.getElementById("size" + i).style.color = "black";
// document.getElementById("size" + i).className = "SizesId";
}
document.getElementById(n).style.backgroundColor = "#666";
document.getElementById(n).style.color = "white";
document.getElementById(n).className += " selected";
document.getElementById("pretFinal").innerHTML = 'Pret: '+price+' RON';
//SelectedColor(-1);
}
<div class="Sizes">
<h3 class="SizesId" onclick="Selected('size0')" id="size0">5</h3>
<h3 class="SizesId" onclick="Selected('size1')" id="size1">6</h3>
<h3 class="SizesId" onclick="Selected('size2')" id="size2">7</h3>
<h3 class="SizesId" onclick="Selected('size3')" id="size3">8</h3>
</div>
<h2 id="pretFinal">Pret: 150 RON</h2>
Use this:
document.getElementById("pretFinal").innerHTML = "YOUR TEXT"
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);
};
The goal I am trying to achieve is to use jQuery to collect, all the CLASS css stylings of any HTML page and then loop through each of the classes and gather the height, width, top and left of each class, which I'll then put into an Array and log it to the console.
Below is where I am currently at with the code. I'm able to gather all the page classes, but struggling to loop through them to give me the height, width, top and left of each class. Below is the code, would anyone be able to guide me in the right direction or possible give an example on how to build it?. Any help will be appreciated :)
$(document).ready(function() {
// VARIABLES
var allClassNames = [];
var eachClassName = "";
// GET CLASS NAMES FROM THE HTML PAGE
$('[class]').each(function eachClassName(){
$.each($(this).attr('class').split(' '), function(i, className) {
if (className.length && $.inArray(className, allClassNames) === -1) {
allClassNames.push(className);
}
});
});
// GET THE CSS STYLING FOR EACH CLASS
function getStyleRuleValue(style, selector) {
for (var i = 0; i < document.styleSheets.length; i++) {
var mysheet = document.styleSheets[i];
var myrules = mysheet.cssRules ? mysheet.cssRules : mysheet.rules;
for (k = 0; k < allClassNames.length; k++) {
console.log(allClassNames[k]);
}
for (var j = 0; j < myrules.length; j++) {
if (myrules[j].selectorText && myrules[j].selectorText.toLowerCase() === selector) {
return myrules[j].style[style];
}
}
}
};
// I'M TRYING TO LOOP THROUGH THE CLASSES WHERE IT SAYS .TWO??
console.log( getStyleRuleValue('top', '.two') );
});
Do not mix jQuery and JavaScript pure code, if you are using jQuery use its methods:
HTML Code:
<div class="div1 value1"></div>
<div class="div1 value2"></div>
<div class="div1 value3"></div>
CSS Code:
.value1{
top: 100px;
}
.value2{
top: 200px;
}
.value3{
top: 300px;
}
jQuery Code:
function getStyleRuleValue(style, selector){
$("." + selector).each(function(){
console.log( $(this).css(style) );
});
}
getStyleRuleValue("top", "div1");
// 100px
// 200px
// 300px
jsfiddle
EDIT:
If you want to use the allClassNames Array with all the page classes (You do not need this Array to iterate into all page elements):
var allClassNames = [];
$("[class]").each(function eachClassName(){
$.each($(this).attr("class").split(" "), function(i, className) {
if (className.length && $.inArray(className, allClassNames) === -1) {
allClassNames.push(className);
}
});
});
$("." + allClassNames.join(",.")).each(function(){
console.log( $(this).css(['top', 'left', 'width', 'height']) );
});
jsfiddle
I'd start by building a map of selectors to styles, based on the stylesheets, and then use that to look up each of the classes I found on the document.
function getStyles() {
var allRules = {};
var selectorIndex = {};
// This will map each individual class to a selector that mentions it
// i.e. if you have a selector like ".top a", this will create two entries, one for ".top" and
// one for "a". Each entry will point to the string ".top a", which can then be used to look up
// the rule in the allRules map.
var indexSelectors = function (selectorText) {
if(typeof selectorText === "string" && selectorText.length) {
$.each(selectorText.split(' '), function (i, sel) {
var currentSelectors = selectorIndex[sel];
if (typeof currentSelectors === 'undefined') {
currentSelectors = [];
}
currentSelectors.push(selectorText);
selectorIndex[sel] = currentSelectors;
});
}
};
// Make a map of all top/left/width/height styles based on the selectors. This will be a "last one
// wins" map -- later entries will overwrite earlier ones. If you don't want "last one wins," you
// can use the array.push strategy that the indexSelectors function uses.
var extractStyles = function (i, rule) {
indexSelectors(rule.selectorText);
if(rule.style) {
var topStyle = rule.style['top'];
var leftStyle = rule.style['left'];
var widthStyle = rule.style['width'];
var heightStyle = rule.style['height'];
// only make an entry if there's at least one non-empty style in the list we're interested in
if(topStyle.length || leftStyle.length || widthStyle.length || heightStyle.length) {
allRules[rule.selectorText] = {
top: rule.style['top'],
left: rule.style['left'],
width: rule.style['width'],
height: rule.style['height']
}
}
}
};
var extractFromStyleSheet = function (i, styleSheet) {
var rules;
if (styleSheet) {
rules = styleSheet.cssRules ? styleSheet.cssRules : styleSheet.rules;
if (rules !== null) {
$.each(rules, extractStyles);
}
}
};
// build allRules dictionary
$(document.styleSheets).each(extractFromStyleSheet);
$('[class]').each(function eachClassName(){
$.each($(this).attr('class').split(' '),function(i,className) {
if (typeof className === 'string' && className.length) {
className = '.' + className;
var selectors = selectorIndex[className];
if (selectors) {
$.each(selectors, function (i, sel) {
var found = allRules[sel];
if (found) {
console.log(className, sel, found);
}
});
}
}
});
});
}
I'm not sure I completely understand what you're trying to do here, and particularly how do you want to handle CSS styles like this?
.two {
top: 12px;
}
.two a {
top: 24px;
}
Still, the code above should get you started (assuming I've correctly understood what you're looking for).
As if we make a div element with it contenteditable="true" and then when if this is seen in console then
1st. In console there is simple a div tag.
<div id="typbody" contenteditable="true" style="width:100%; height:200px; border:1px solid #ccc; "></div>
2nd. If I press enter in div tag then in console it is written <div><br></div>!
and If I write anything in that the it is also written inside <div>.
so my question is:
1) Is there any way to give these newly created div tag an id ?
2) Is there also any way to give them different ids or class to all new div's?
Do I have to learn any other language other than javascript or php?
"Is there is any way to give these newly created div tag an id ?"
"Is there is also any way to give them different ids or class to all new div's?"
Yes, there is!
Look at MutationObserver MDN,
and DOM MutationObserver – reacting to DOM changes without killing browser performance.
Demonstration with JS
(function () {
"use strict";
var target = document.getElementById("typbody"),
config = {
childList: true,
},
eCollection = [],
i = 0,
id = target.id + "_",
observer = new MutationObserver(function (mutations) {
mutations.forEach(function (mutation) {
if (mutation.addedNodes) {
[].forEach.call(mutation.addedNodes, function (node) {
if (node.nodeName.toLowerCase() === "div") {
var index = eCollection.indexOf(node.nextSibling);
node.id = id + i++;
eCollection.push(node);
if (node.nextSibling && index > -1) {
node.id = node.nextSibling.id;
for (var j = index; j < eCollection.length - 1; j++) {
eCollection[j].id = id + (+eCollection[j].id.substr(id.length) + 1);
}
}
eCollection.sort(sortC);
}
});
}
if (mutation.removedNodes) {
[].forEach.call(mutation.removedNodes, function (node) {
if (node.nodeName.toLowerCase() === "div") {
var index = eCollection.indexOf(node);
eCollection.splice(index, 1);
for (var j = index; j < eCollection.length; j++) {
eCollection[j].id = id + (eCollection[j].id.substr(id.length) - 1);
}
i--;
eCollection.sort(sortC);
}
});
}
});
});
observer.observe(target, config);
function sortC(a, b) {
return a.id.substr(id.length) - b.id.substr(id.length);
}
}());
But why you want such behavior?
If you want to add some style to those elements, why not simply use css:
Demo with CSS
#typbody > div:nth-child(odd) {
color: green;
}
#typbody > div:nth-child(even) {
color: blue;
}
Add the id when you create it. If you want it to be dynamic, just make the id variable dynamic.
var frag = document.createDocumentFragment(),
var item = document.createElement('div');
item.id = whatever;
frag.appendChild(item);
and then insert the frag into your DOM wherever you want. For instance, after an element 'foo':
foo.parentNode.insertBefore(frag, foo.nextSibling);