change css classes of element added to DOM at runtime - javascript

I've included some JavaScript from a third party in my page. This adds the following element to the page some time after the page is loaded:
<a class="foo">some link</a>
I need to ensure that this is changed to:
<a class="bar">some link</a>
ASAP after the element is added to the page. I tried adding the following to a JQuery ready handler
$('a.gullSearchBtn').removeClass('gullSearchBtn').addClass('roundButton');
But this executes before the element is added and therefore doesn't work. I've searched the web and it seems like the jQuery feature known as "livequery" might be the solution to my problem, but I can't seem to get it to work.

Binding to the DOMNodeInserted or DOMSubtreeModified may help accomplish this. But according to the following post this won't work with IE
How to detect new element creation in jQuery?

You could just go native styles and use a setTimeout function to check if it exits. But this will only work if you have a unique way to identify that element eg: it is the only anchor element with the foo class
My Recommended Loop
$(document).ready(function(){
checkTimer();
});
function checkTimer(){
var ele = $('a.foo');
if(ele.length == 0){
setTimeout(function(){
checkTimer();
},100);
}
else {
ele.attr('class','bar');
}
}
Some will suggest that you use a setInterval() which provides the same functionality as the loop above. I know from personal experience how prone this is to breaking though, but here is the code for that version.
setInterval() Loop
var timer;
$(document).ready(function(){
timer = setInterval(function(){
checkTimer();
},100);
});
function checkTimer(){
var ele = $('a.foo');
if(ele.length != 0){
ele.attr('class','bar');
clearTimeout(timer)
}
}

Have you considered this?
original CSS
.roundButton {
[your rules]
}
changed CSS
.gullSearchBtn, .roundButton {
[your rules]
}

demo: http://so.devilmaycode.it/change-css-classes-of-element-added-to-dom-at-runtime
$(function() {
$('.foo').click(function(e) {
$('body').append('<p class="gullSearchBtn">text</p>');
return false;
});
setInterval(function() {
if ($('.gullSearchBtn').length)
$('.gullSearchBtn').removeClass('gullSearchBtn').addClass('roundButton');
//clearInterval() optional if you don't need to loop anymore...
}, 100);
});

Related

Dom manipulation not working

I wrote the below code to remove an element with class rc-anchor-pt (if it is present in the DOM) after 5 seconds,
checkContainer();
counter = 1;
function checkContainer () {
alert("checkContainer");
$('.rc-anchor-pt').remove();
$('.rc-anchor-logo-portrait').append('Privacy & Terms');
if($('.rc-anchor-pt').is(':visible')){ //if the container is visible on the page
var privacy = $('.rc-anchor-pt').find('a');
} else {
if (counter === 1)
{
setTimeout(checkContainer, 5000); //wait 50000 ms, then try again
counter++;
}
}
}
But the below line is not removing the element from the DOM. Can you please tell me what is the reason. Thanks in advance.I am running inside document.ready only The element is present in the page –
$('.rc-anchor-pt').remove();
I am not really sure what you are trying to accomplish with your code. You have stated in your question that you wish to remove an element from the DOM after 5 seconds...You should be able to accomplish that with the following code:
$('.rc-anchor-logo-portrait').append('<br>Privacy & Terms');
setTimeout(function(){
$('.rc-anchor-pt').remove();
}, 5000);
The way you have your code laid out, the rc-anchor-pt class will never be visible. It would really have no purpose then. If you want the append function to run after 5 seconds as well, just put it in the setTimeout function.
Here is a fiddle: https://jsfiddle.net/1399u65t/3/

onclick event handler in javascript code, not html tag

when trying to ensure my webpage is using unobtrusive javascript I cant seem to get the onclick event to work in my javascript, it only works as an event in the html tag. here is the code
var dow = document.getElementById("dowDiv");
dow.onclick=function () {}
any reason that this isnt working for me? as all the answers i can find say this is the way to do it, thanks in advance
There could be several reasons based on the information provided.
Most likely, the event function code is being attached before the DOM has finished loading.
Alternatively, you might be using a browser which doesn't support onclick (though this is unlikely!). To guarantee it will work, you can use fallbacks for the main routes of attaching an event:
if (dow.addEventListener) {
dow.addEventListener('click', thefunction, false);
} else if (dow.attachEvent) {
dow.attachEvent('onclick', thefunction);
} else {
dow.onclick = thefunction;
}
Make sure that you only have one element with the id dowDiv. If you have z-index's on elements and something is over the div it might be blocking the click event on the div.
var dow = document.getElementById("dowDiv");
var out = document.getElementById("out");
var clickCount = 0;
dow.onclick = function() {
clickCount += 1;
out.innerHTML = clickCount
}
<div id="dowDiv">Hello onclick <span id="out"></span>!</div>
You can use jQuery to achieve a simple o'clock function.
Make you include jQuery BEFORE you reference your .js file:
<script src="path/to/jQuery.js"></script>
<script src="file.js></script>
With jQuery you can say
$('#dowDIV').click(function(){
Do stuff here;
})

'onclick' Storing Value Not Working

so I have this <a> tag:
<a href="/book-testdrive" class="addtocart" value="YX57WDL" title="Book Test Drive">
<i class="glyphicon glyphicon-road"></i>
<span> Book Test Drive</span>
</a>
As you can see it is given a value of value="YX57WDL" now what I would like to do is capture that value when the a tag is clicked and placed into a variable.
There are many <a> tags on my page with many different values that are created dynamically. If a user presses another a tag I'd like it storing in the same variable but replace the value with that of the unique <a> tag value.
Also the variable needs to be stored site wide, I guess the solution to this would be Web Storage API.
So far I've tried using this Javascript:
var links = document.querySelectorAll('.addtocart ');
links.onclick = function(){
localstorage['storedValue'] = this.value ;
}
However when I console.log() the links variable it contains nothing.
Any idea why this might be happening?
Thanks
The problem is that document.querySelectorAll returns a (non-live) node list. This means that it is basically an array, so you could do a loop for each one instead:
for (var i = 0; i < links.length; i++) {
links[i].onclick = function(){
localStorage['storedValue'] = this.value ;
}
}
Also note that I changed localstorage to localStorage because it's case sensitive.
You will need to wait until the DOM is loaded, or else the call to document.querySelectorAll() will not find anything if the element you are looking for has not been added to the DOM yet.
I see you added jquery as a tag, so I assume you are using jquery. If that is the case, you can wrap your code with the jquery function to wait for the DOM to be ready, like this:
$(document).ready(function() {
var links = document.querySelectorAll('.addtocart ');
links.onclick = function(){
localStorage['storedValue'] = this.value ;
}
});
Also if you are using jquery, you could be using its on function to make this a lot simpler.
$(document).ready(function() {
$('.addtocart').on('click', function() {
localStorage['storedValue'] = this.value;
}
});
If you are not using jquery, see this question about how to wait for the DOM to load without the jquery $(document).ready() function.
Try ".getAttribute('value')" instead of ".value":
var links = document.querySelector('a.addtocart');
links.onclick = function(){
localStorage['storedValue'] = links.getAttribute('value');
}
Since you are using jQuery, you can do something like this:
$("body").on("click", ".addtocart", function(e) {
localstorage['storedValue'] = $(this).val();
});
You surely wonder why did your attempt fail. In fact, you were not too far from the solution, but you probably ran your script before your links were created. With the .on() function of jQuery you have a listener to the current and future elements matching the selector (which is ".addtocart").

addEventListener to div element

I am trying to fire a script when the contents of a div are altered, specifically when a div receives the next set of results from a js loaded paginator.
I have this:
<script script type="text/javascript" language="javascript">
document.addEventListener("DOMCharacterDataModified", ssdOnloadEvents, false);
function ssdOnloadEvents (evt) {
var jsInitChecktimer = setInterval (checkForJS_Finish, 111);
function checkForJS_Finish () {
if ( document.querySelector ("#tester")
) {
clearInterval (jsInitChecktimer);
//do the actual work
var reqs = document.getElementById('requests');
var reqVal = reqs.get('value');
var buttons = $$('.clicker');
Array.each(buttons, function(va, index){
alert(va.get('value'));
});
}
}
}
</script>
This works well when the doc loads (as the results take a few seconds to arrive) but I need to narrow this down to the actual div contents, so other changes on the page do not fire the events.
I have tried:
var textNode = document.getElementById("sitepage_content_content");
textNode.addEventListener("DOMCharacterDataModified", function(evt) {
alert("Text changed");
}, false);
But the above does not return anything.
Can what I am trying to do be done in this way? If yes where am I going wrong?
Using Social Engine (Zend) framework with MooTools.
I did this in the end with a little cheat :-(
There is a google map loading on the page that sets markers to match the location of the results. So I added my events to the end this code namely: function setMarker() {}.
I will not mark this as the correct answer as it is not really an answer to my question, but rather a solution to my problem, which is localised to the Social engine framework.
I will add a Social engine tag to my original question in the hope it may help someone else in the future.
Thanks guys.

force DOM redraw with javascript on demand

The title of the question expresses what I think is the ultimate question behind my particular case.
My case:
Inside a click handler, I want to make an image visible (a 'loading' animation) right before a busy function starts. Then I want to make it invisible again after the function has completed.
Instead of what I expected I realize that the image never becomes visible. I guess that this is due to the browser waiting for the handler to end, before it can do any redrawing (I am sure there are good performance reasons for that).
The code (also in this fiddle: http://jsfiddle.net/JLmh4/2/)
html:
<img id="kitty" src="http://placekitten.com/50/50" style="display:none">
<div>click to see the cat </div>
js:
$(document).ready(function(){
$('#enlace').click(function(){
var kitty = $('#kitty');
kitty.css('display','block');
// see: http://unixpapa.com/js/sleep.html
function sleepStupidly(usec)
{
var endtime= new Date().getTime() + usec;
while (new Date().getTime() < endtime)
;
}
// simulates bussy proccess, calling some function...
sleepStupidly(4000);
// when this triggers the img style do refresh!
// but not before
alert('now you do see it');
kitty.css('display','none');
});
});
I have added the alert call right after the sleepStupidly function to show that in that moment of rest, the browser does redraw, but not before. I innocently expected it to redraw right after setting the 'display' to 'block';
For the record, I have also tried appending html tags, or swapping css classes, instead of the image showing and hiding in this code. Same result.
After all my research I think that what I would need is the ability to force the browser to redraw and stop every other thing until then.
Is it possible? Is it possible in a crossbrowser way? Some plugin I wasn't able to find maybe...?
I thought that maybe something like 'jquery css callback' (as in this question: In JQuery, Is it possible to get callback function after setting new css rule?) would do the trick ... but that doesn't exist.
I have also tried to separte the showing, function call and hiding in different handlers for the same event ... but nothing. Also adding a setTimeout to delay the execution of the function (as recommended here: Force DOM refresh in JavaScript).
Thanks and I hope it also helps others.
javier
EDIT (after setting my preferred answer):
Just to further explain why I selected the window.setTimeout strategy.
In my real use case I have realized that in order to give the browser time enough to redraw the page, I had to give it about 1000 milliseconds (much more than the 50 for the fiddle example). This I believe is due to a deeper DOM tree (in fact, unnecessarily deep).
The setTimeout let approach lets you do that.
Use JQuery show and hide callbacks (or other way to display something like fadeIn/fadeOut).
http://jsfiddle.net/JLmh4/3/
$(document).ready(function () {
$('#enlace').click(function () {
var kitty = $('#kitty');
// see: http://unixpapa.com/js/sleep.html
function sleepStupidly(usec) {
var endtime = new Date().getTime() + usec;
while (new Date().getTime() < endtime);
}
kitty.show(function () {
// simulates bussy proccess, calling some function...
sleepStupidly(4000);
// when this triggers the img style do refresh!
// but not before
alert('now you do see it');
kitty.hide();
});
});
});
Use window.setTimeout() with some short unnoticeable delay to run slow function:
$(document).ready(function() {
$('#enlace').click(function() {
showImage();
window.setTimeout(function() {
sleepStupidly(4000);
alert('now you do see it');
hideImage();
}, 50);
});
});
Live demo
To force redraw, you can use offsetHeight or getComputedStyle().
var foo = window.getComputedStyle(el, null);
or
var bar = el.offsetHeight;
"el" being a DOM element
I do not know if this works in your case (as I have not tested it), but when manipulating CSS with JavaScript/jQuery it is sometimes necessary to force redrawing of a specific element to make changes take effect.
This is done by simply requesting a CSS property.
In your case, I would try putting a kitty.position().left; before the function call prior to messing with setTimeout.
What worked for me is setting the following:
$(element).css('display','none');
After that you can do whatever you want, and eventually you want to do:
$(element).css('display','block');

Categories