How can I dynamically update a HTML attribute - javascript

I have this code
<div class="g-popupgrid-item g-zoom" data-size="395x385">
I want to populate the 395x385 dynamically with the image size.
I have a JS function which gets the image size, I don't know how to print/echo/document.write it to be within the HTML tag.

I would avoid using jQuery for such a trivial task unless you are already using it in your project. Plain javascript:
var div = document.querySelector('.g-popupgrid-item');
var newSize = '100x100'; // for example
div.setAttribue('data-size', newSize);

Get the Node using JavaScript, then modify it to fit your needs:
var container = document.querySelector(".g-popupgrid-item .g-zoom")
container.setAttribute("data-size", value)
Keep in mind this will only affect the first element with those classes, if you want affect them all, use the code below:
var containers = document.querySelectorAll(".g-popupgrid-item .g-zoom")
containers.forEach(function(container) {
container.setAttribute("data-size", value)
})
Also keep in mind that containers is not an Array it's a NodeList. Read more here
EDIT: According to #Eoin, the .forEach() method on NodeLists is not supported in Firefox. You can also use a standard for loop in place of it:
var containers = document.querySelectorAll(".g-popupgrid-item .g-zoom")
for (var i = 0; i < containers.length; i++) {
containers[i].setAttribute("data-size", value)
}

Related

.appendChild() is not a function when using jQuery

I am trying to transition from pure JavaScript to jQuery. I have a for loop that dynamically creates HTML elements with data from an API. Here is my old code:
recipeDiv = [];
recipeDiv[i] = document.createElement("div");
recipeDiv[i].setAttribute("class", "recipeBlock");
recipeDiv[i].appendChild(someElement);
However, when I transitioned to jQuery and used this instead
recipeDiv = [];
recipeDiv[i] = $("<div/>").addClass("recipeBlock");
recipeDiv[i].appendChild(someElement);
I get the following error: recipeDiv[i].appendChild is not a function
I know that .appendChild() isn't jQuery (JS), but shouldn't it still work? Even if I use the jQuery .append() function, I still get an error.
Any help is greatly appreciated.
You seem to be confusing yourself by inter-changing jQuery and DOM APIs. They cannot be used interchangeably. document.createElement returns an Element and $("<div />") returns the jQuery object. Element object has the appendChild method and jQuery object has the append method.
As a good practice, I would suggest you choose between DOM APIs or jQuery, and stick to it. Here is a pure jQuery based solution to your problem
var recipeContainer = $("<div/>")
.addClass("recipeContainer")
.appendTo("body");
var recipeDiv = [];
var likes = [];
for (var i = 0; i < 20; i++) {
//Create divs so you get a div for each recipe
recipeDiv[i] = $("<div/>").addClass("recipeBlock");
//Create divs to contain number of likes
likes[i] = $("<div/>")
.addClass("likes")
.html("<b>Likes</b>");
//Append likes blocks to recipe blocks
recipeDiv[i].append(likes[i]);
//Append recipe blocks to container
recipeContainer.append(recipeDiv[i]);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
Maybe someElement is not created? Does the code need to be as follows?
recipeDiv = [];
var someElement = $("<div/>").addClass("recipeBlock");
recipeDiv[i].appendChild(someElement);

How to use function on every element by class name?

Now I am using "Perfect Scroller" which is a custom scroll bar plugin.
I followed the Document to setup.Here
I use code like below and every was good.
var container = document.getElementById('container');
Ps.initialize(container);
However, I want to use it by "ClassName" not by "ID" because there are lots of areas.
I know I can use
var container = document.getElementsByClassName('selected_area')[0];
But this is only one element.
My question is how to do it by ClassName?
You can do in a loop:
var container = document.getElementsByClassName('selected_area');
for(var i in container) {
Ps.initialize(container[i]);
}
This iterates all containers and initialize it independently.
var container = document.getElementsByClassName('selected_area');
for(var i = 0; i < container.size; i++){
Ps.initialize(container[i]);
}
Although I haven't had a look at this plugin you are using, so I don't know if it should be initialised more than once. Hope this helps
you can also use:
var container = document.querySelectorAll('.selected_area');
furthermore you can transform it to an array(it's only necessary if you want to use standard array methods)
var contArr = [].slice.call(container)
in this case you can then use it with forEach
contArr.forEach(function(x){Ps.initialize(x)}

Extract property of a tag in HTML using Javascript

Is it possible to extract properties of a HTML tag using Javascript.
For example, I want to know the values present inside with the <div> which has align = "center".
<div align="center">Hello</div>
What I know is:
var division=document.querySelectorAll("div");
but it selects the elements between <div> & </div> and not the properties inside it.
I want to use this in the Greasemonkey script where I can check for some malicious properties of a tag in a website using Javascript.
Hope I'm clear..!!
You are looking for the getAttribute function. Which is accessible though the element.
You would use it like this.
var division = document.querySelectorAll('div')
for(var i=0,length=division.length;i < length;i++)
{
var element = division[i];
var alignData = division.getAttribute('align'); //alignData = center
if(alignData === 'center')
{
console.log('Data Found!');
}
}
If you're looking to see what attributes are available on the element, these are available though
division.attributes
MDN Attributes
So for instance in your example if you wanted to see if an align property was available you could write this.
//Test to see if attribute exists on element
if(division.attributes.hasOwnProperty('align'))
{
//It does!
}
var test = document.querySelectorAll('div[align="center"]');

Getting all the style properties using JQuery. Basically I want an equivalent of getComputedStyle() and I dont want to handle cross-browser stuff

I would like to get the currentStyle/computedStyle object and I dont want to manually check for the type of browser. (I wanted to get rid of cross-browser handling that is why I came to Jquery).
Actually I want the style object returning all the style-property: value map.
Please help.
Well, there is a soultion for a similiar problem offered by Keith Bentrup: jQuery CSS plugin that returns computed style of element to pseudo clone that element?
He used a list of attributes from Firebug and created a computed style object with jQuery to be able to clone styles from one object to another:
jQuery.fn.css2 = jQuery.fn.css;
jQuery.fn.css = function() {
if (arguments.length) return jQuery.fn.css2.apply(this, arguments);
var attr = ['font-family','font-size','font-weight','font-style','color',
'text-transform','text-decoration','letter-spacing','word-spacing',
'line-height','text-align','vertical-align','direction','background-color',
'background-image','background-repeat','background-position',
'background-attachment','opacity','width','height','top','right','bottom',
'left','margin-top','margin-right','margin-bottom','margin-left',
'padding-top','padding-right','padding-bottom','padding-left',
'border-top-width','border-right-width','border-bottom-width',
'border-left-width','border-top-color','border-right-color',
'border-bottom-color','border-left-color','border-top-style',
'border-right-style','border-bottom-style','border-left-style','position',
'display','visibility','z-index','overflow-x','overflow-y','white-space',
'clip','float','clear','cursor','list-style-image','list-style-position',
'list-style-type','marker-offset'];
var len = attr.length, obj = {};
for (var i = 0; i < len; i++)
obj[attr[i]] = jQuery.fn.css2.call(this, attr[i]);
return obj;
}
This seems to do exactly what you are looking for.
There are also a couple of plugins for that:
http://github.com/peol/jquery-computed-style
http://www.jupiterit.com/news/get-multiple-computed-styles-fast-with-the-curstyles-jquery-plugin

getElementsByName in IE7

I have some code doing this :
var changes = document.getElementsByName(from);
for (var c=0; c<changes.length; c++) {
var ch = changes[c];
var current = new String(ch.innerHTML);
etc.
}
This works fine in FF and Chrome but not in IE7. Presumably because getElementsByName isn't working in IE. What's the best workaround?
In case you don't know why this isn't working in IE, here is the MSDN documentation on that function:
When you use the getElementsByName method, all elements in the document that have the specified NAME attribute or ID attribute value are returned.
Elements that support both the NAME attribute and the ID attribute are included in the collection returned by the getElementsByName method, but elements with a NAME expando are not included in the collection; therefore, this method cannot be used to retrieve custom tags by name.
Firefox allows getElementsByName() to retrieve elements that use a NAME expando, which is why it works. Whether or not that is a Good Thing™ may be up for debate, but that is the reality of it.
So, one option is to use the getAttribute() DOM method to ask for the NAME attribute and then test the value to see if it is what you want, and if so, add it to an array. This would require, however, that you iterate over all of the nodes in the page or at least within a subsection, which wouldn't be the most efficient. You could constrain that list beforehand by using something like getElementsByTagName() perhaps.
Another way to do this, if you are in control of the HTML of the page, is to give all of the elements of interest an Id that varies only by number, e.g.:
<div id="Change0">...</div>
<div id="Change1">...</div>
<div id="Change2">...</div>
<div id="Change3">...</div>
And then have JavaScript like this:
// assumes consecutive numbering, starting at 0
function getElementsByModifiedId(baseIdentifier) {
var allWantedElements = [];
var idMod = 0;
while(document.getElementById(baseIdentifier + idMod)) { // will stop when it can't find any more
allWantedElements.push(document.getElementById(baseIdentifier + idMod++));
}
return allWantedElements;
}
// call it like so:
var changes = getElementsByModifiedId("Change");
That is a hack, of course, but it would do the job you need and not be too inefficient compare to some other hacks.
If you are using a JavaScript framework/toolkit of some kind, you options are much better, but I don't have time to get into those specifics unless you indicate you are using one. Personally, I don't know how people live without one, they save so much time, effort and frustration that you can't afford not to use one.
There are a couple of problems:
IE is indeed confusing id="" with name=""
name="" isn't allowed on <span>
To fix, I suggest:
Change all the name="" to class=""
Change your code like this:
-
var changes = document.getElementById('text').getElementsByTagName('span');
for (var c=0; c<changes.length; c++) {
var ch = changes[c];
if (ch.className != from)
continue;
var current = new String(ch.innerHTML);
It's not very common to find elements using the NAME property. I would recommend switching to the ID property.
You can however find elements with a specific name using jQuery:
$("*[name='whatevernameYouWant']");
this will return all elements with the given name.
getElementsByName is supported in IE, but there are bugs. In particular it returns elements whose ‘id’ match the given value, as well as ‘name’. Can't tell if that's the problem you're having without a bit more context, code and actual error messages though.
In general, getElementsByName is probably best avoided, because the ‘name’ attribute in HTML has several overlapping purposes which can confuse. Using getElementById is much more reliable. When specifically working with form fields, you can more reliably use form.elements[name] to retrieve the fields you're looking for.
I've had success using a wrapper to return an array of the elements. Works in IE 6, and 7 too. Keep in mind it's not 100% the exact same thing as document.getElementsByName, since it's not a NodeList. But for what I need it for, which is to just run a for loop on an array of elements to do simple things like setting .disabled = true, it works well enough.
Even though this function still uses getElementsByName, it works if used this way. See for yourself.
function getElementsByNameWrapper(name) {
a = new Array();
for (var i = 0; i < document.getElementsByName(name).length; ++i) {
a.push(document.getElementsByName(name)[i]);
}
return a;
}
Workaround
var listOfElements = document.getElementsByName('aName'); // Replace aName with the name you're looking for
// IE hack, because it doesn't properly support getElementsByName
if (listOfElements.length == 0) { // If IE, which hasn't returned any elements
var listOfElements = [];
var spanList = document.getElementsByTagName('*'); // If all the elements are the same type of tag, enter it here (e.g.: SPAN)
for(var i = 0; i < spanList.length; i++) {
if(spanList[i].getAttribute('name') == 'aName') {
listOfElements.push(spanList[i]);
}
}
}
Just another DOM bug in IE:
Bug 1: Click here
Bug 2: Click here

Categories