Change div background image with JS - javascript

I am trying to place background images for divs with JS and change those images on mouse over and on click. I am trying to do it like this:
window.onload; {
var replies = document.getElementsByClassName("reply-wrapper");
var retweets = document.getElementsByClassName("retweet-wrapper");
var favs = document.getElementsByClassName("fav-wrapper");
for (var i = 0; i < replies.length; i++) {
replies[i].style.backgroundImage = "url(images/reply.png);";
}
for (var i = 0; i < retweets.length; i++) {
retweets[i].style.backgroundImage = "url(images/retweet.png);";
}
for (var i = 0; i < favs.length; i++) {
favs[i].style.backgroundImage = "url(images/favorite.png);";
}
}
But for some reason it won't work. Aprropriate divs have right classes and adding them to collection works fine, but placing images itself doesn't work. What am I doing wrong?
P.S. Wanna write it in pure JS, no jQuery.
P.P.S For some reason placing image with innerHTML works fine. Why?

It looks like you've made a slight mistake when assigning your code to the window.onload event.
Your code needs to be in a function assigned to the onload event.
window.onload = function () { /* Your Code */ };
instead of:
window.onload; { /* Your Code /* }

There are two issues:
Like Jamie Dixon mentioned it needs to be window.onload = function(){}
favs[i].style.backgroundImage = "url(images/favorite.png);"; should be favs[i].style.backgroundImage = "url(images/favorite.png)"; The extra ; will cause your link not to work. So remove the extra semi-colon from the rest of your links.
Update with explanation:
#room1 {
background-image: url('image/example.png');
}
In the example above you'll notice the semi-colon. Like in any programming language this is to say that this is the end of the command. Sometimes semi-colon's are optional ( like in certain cases found in js ).
JS isn't CSS. Even if you apply a style to your html element, you are using JS and not CSS. This is why you don't need the ; inside the quotes.

The event handler window.onload needs to be assigned a function to invoke. So, you just need to add the keyword 'function' before the block of code and then assign that to window.onload. Additionally, if you want to play nice with other code on the page you could grab a reference to any existing onload handler and then invoke in your onload function.
var oldOnLoad = window.onload;
window.onload = function() {
if (typeof oldOnLoad === 'function') {
oldOnLoad();
}
var replies = document.getElementsByClassName("reply-wrapper");
var retweets = document.getElementsByClassName("retweet-wrapper");
var favs = document.getElementsByClassName("fav-wrapper");
for (var i = 0; i < replies.length; i++) {
replies[i].style.backgroundImage = "url(images/reply.png)";
}
for (var i = 0; i < retweets.length; i++) {
retweets[i].style.backgroundImage = "url(images/retweet.png)";
}
for (var i = 0; i < favs.length; i++) {
favs[i].style.backgroundImage = "url(images/favorite.png)";
}
};
Note: it might be worth mentioning that loading the background images in the onload event handler could cause your page to appear to load slow because it will wait for all other content on the page to finish loading. You might want to do something like instead:
<div id="reply-wrapper" style="display: block; width: 250px; height: 250px;"></div>
<script>
(function() {
document.getElementById('reply-wrapper').style.backgroundImage = "url(//dummyimage.com/250x250/000/fff)";
})();
</script>

I don't see a function name for the code.
Is it incomplete?
this might be the error.
window.onLoad;
Try this:
function fn_load(){
// Your statements
}
and in the body do this:

i should be:
window.onload = function() {
var replies = document.getElementsByClassName("reply-wrapper");
var retweets = document.getElementsByClassName("retweet-wrapper");
var favs = document.getElementsByClassName("fav-wrapper");
for (var i = 0; i < replies.length; i++) {
replies[i].style.backgroundImage = "url(images/reply.png);";
}
for (var i = 0; i < retweets.length; i++) {
retweets[i].style.backgroundImage = "url(images/retweet.png);";
}
for (var i = 0; i < favs.length; i++) {
favs[i].style.backgroundImage = "url(images/favorite.png);";
}
}
you DOM is calling even before window got load.

Related

Code Working in Console BUT NOT From Script

I have a script that I'm running to detect a line break in a flex-wrapped UL.
I have this javascript function at the top of my scripts.js file outside of the $(document).ready call.
var detectWrap = function(className) {
var wrappedItems = [];
var prevItem = {};
var currItem = {};
var items = document.getElementsByClassName(className);
for (var i = 0; i < items.length; i++) {
currItem = items[i].getBoundingClientRect();
if (prevItem && prevItem.top < currItem.top) {
wrappedItems.push(items[i]);
}
prevItem = currItem;
};
return wrappedItems;
}
Inside of a $(document).ready call, I have this:
$( ".menu-item-has-children" ).click(function() {
var wrappedItems = detectWrap('menu-item-object-practice-area');
for (var k = 0; k < wrappedItems.length; k++) {
wrappedItems[k].className = "wrapped";
}
});
If I load the page and click the "Practice Areas", I get nothing. If I open up the console and drop in the following it works fine:
var wrappedItems = detectWrap('menu-item-object-practice-area');
for (var k = 0; k < wrappedItems.length; k++) {
wrappedItems[k].className = "wrapped";
}
I'm assuming this has something to do with the timing and/or what is loaded up but I'm not adding content into the DOM...I'm just adding a class.
For reference, here is the site: https://myersbrierkelly.djykrmv8-liquidwebsites.com/
When you click the drop-down menu, two separate event handlers respond:
Yours, to measure for wrapped items
The library you're using, to toggle the display of the submenu
However, as there is nothing to manage the order of these, what ends up happening is that your wrap-detector runs before the submenu is shown, and if the submenu isn't shown yet then you can't measure getBoundingClientRect() since it doesn't exist. A simple console.log(currItem) would have revealed this.
If you can't guarantee the order of events (which may well be the case when using a library), then you should delay your code by a frame.
$(".menu-item-has-children").click(function() {
requestAnimationFrame(function() {
var wrappedItems...
});
});

Toggle is-visible Class to Div Next to Trigger Element (Plain JS)

This is supposed to be a very simple dropdown FAQ system, I know how to do this in jQuery but I want to learn plain JS.
I just want the individual clicked triggers to toggle the is-visible class to the content divs next to the clicked trigger. Like $(this).next addClass — just in JS.
I've really tried to search for this issue but 90% that shows up is how to do it in jQuery :-p
https://jsfiddle.net/48ea3ruz/
var allTriggers = document.querySelectorAll('.faq-trigger');
for (var i = 0; i < allTriggers.length; i++) {
// access to individual triggers:
var trigger = allTriggers[i];
}
var allContent = document.querySelectorAll('.faq-content');
for (var i = 0; i < allContent.length; i++) {
// access to individual content divs:
var content = allContent[i];
}
// I don't know how to target the faq-content div next to the clicked faq-trigger
this.addEventListener('click', function() {
content.classList.toggle('is-visible');
});
Would really appreciate some advice! :-)
Use nextSibling, when you are iterating .faq-trigger
var allTriggers = document.querySelectorAll('.faq-trigger');
for (var i = 0; i < allTriggers.length; i++) {
allTriggers[i].addEventListener('click', function() {
this.nextSibling.classList.toggle('is-visible');
});
}
nextSibling will also consider text-nodes, try nextElementSibling also
var allTriggers = document.querySelectorAll('.faq-trigger');
for (var i = 0; i < allTriggers.length; i++) {
allTriggers[i].addEventListener('click', function() {
this.nextElementSibling.classList.toggle('is-visible');
});
}

Can you use "this" attribute on onclick of an HTML tag?

Can you use the this tag for the onclick on an HTML tag?
Here's my JS code...
function changeImage() {
this/*<-- right there <--*/.src=a;
}
document.getElementsByTagName('img').onclick = function(){
changeImage();
} ;
Am I doing something wrong?
Use it this way...
function changeImage(curr) {
console.log(curr.src);
}
document.getElementsByTagName('img').onclick = function(){
changeImage(this);
} ;
You could use the .call() method to invoke the function with the context of this.
In this case, you would use:
changeImage.call(this)
Example Here
function changeImage() {
this.src = 'http://placehold.it/200/f00';
}
document.getElementsByTagName('img')[0].onclick = function(){
changeImage.call(this);
};
As a side note, getElementsByTagName returns a live HTMLCollection of elements. You need to apply the onclick handler to an element within that collection.
If you want to apply the event listener to the collection of elements, you iterate through them and add event listeners like this:
Updated Example
function changeImage() {
this.src = 'http://placehold.it/200/f00';
}
Array.prototype.forEach.call(document.getElementsByTagName('img'), function(el, i) {
el.addEventListener('click', changeImage);
});
Or you could simplify it:
Example Here
Array.prototype.forEach.call(document.getElementsByTagName('img'), function(el, i) {
el.addEventListener('click', function () {
this.src = 'http://placehold.it/200/f00';
});
});
You are doing two things wrong.
You are assigning the event handler to a NodeList instead of to an element (or set of elements)
You are calling changeImage without any context (so this will be undefined or window depending on if you are in strict mode or now).
A fixed version would look like this:
var images = document.getElementsByTagName('img');
for (var i = 0; i < images.length; i++) {
images[i].onclick = function () {
changeImage.call(this);
};
}
But a tidier version would skip the anonymous function that does nothing except call another function:
var images = document.getElementsByTagName('img');
for (var i = 0; i < images.length; i++) {
images[i].onclick = changeImage;
}
And modern code would use addEventListener.
var images = document.getElementsByTagName('img');
for (var i = 0; i < images.length; i++) {
images[i].addEventListener('click', changeImage);
}
However, images are not interactive controls. You can't (by default) focus them, so this approach would make them inaccessible to people who didn't use a pointing device. Better to use controls that are designed for interaction in the first place.
Generally, this should be a plain button. You can use CSS to remove the default padding / border / background.
If you can't put a button in your plain HTML, you can add it with JS.
var images = document.getElementsByTagName('img');
for (var i = 0; i < images.length; i++) {
var image = images[i];
var button = document.createElement('button');
button.type = "button";
image.parentNode.replaceChild(button, image);
button.appendChild(image);
button.addEventListener('click', changeImage);
}
function changeImage(event) {
this.firstChild.src = a;
}

simple hover and hover out issue in javascript

I am trying to create hover and hover out via javascript.
I have
test.prototype.build = function(){
other codes...
link.href = '#';
link.innerHTML += 'test'
link.onmouseover = hover
link.onmouseout = hoverOut
other codes...
}
function hover(){
var div = document.createElement('div');
div.class='testDiv';
div.innerHTML = 'test';
$(this).prepend(div);
}
function hoverOut(){
var div = document.getElementsByClassName('testDiv');
div.style.display='none';
}
My task is to create a hover and hover out function. My problem is I am not sure how to hide the testDiv when the user hover out of the link.
getElementsByClassName doesn't seem to work in my case. Are there better way to do this in javascript? Thanks a lot!
document.getElementsByClassName('testDiv') returns an collection, not a single object, but you can probably just use this to refer to the current object. Since you showed some jQuery in your original code, I assume that is OK here.
function hoverOut(){
$(this).find(".testDiv").hide();
}
or, in plain javascript, it could be:
function hoverOut(){
var elems = this.getElementsByClassName("testDiv");
for (var i = 0; i < elems.length; i++) {
elems[i].style.display = "none";
}
}
Your hover and hoverOut code don't match though because you're creating a new div on hover every time in hover and then only hiding it in hoverOut so they will accumulate.
If you want to remove the div you added in hoverOut(), you can do that like this:
function hoverOut(){
$(this).find(".testDiv").remove();
}
or in plain javascript:
function hoverOut(){
var elems = this.getElementsByClassName("testDiv");
for (var i = 0; i < elems.length; i++) {
elems[i].parentNode.removeChild(elems[i]);
}
}

Removing JavaScript from a link

The link's code is as follows:
<td class="buttonColumn">
Leave to Google
</td>
<td class="buttonColumn">
Leave to Yahoo
</td>
There are multiple buttons on the page with the exact same format that need to be changed as well. I was thinking something like this:
var fix = document.getElementsByClassName('actionButtonNew');
for (var i=0; i<fix.length; i++) {
I am not sure how to finish the code. I tried this:
var fix = document.getElementsByClassName('actionButtonNew');
for(var i = 0; i < fix.length; i++) {
try {
var l = fix[i];
var h = fix[i].parentNode.getElementsByClassName('actionButtonNew')[0].href.replace("javascript:confirmDialog('Are you sure you want to go?',", "");
l.href = h;
} catch(e) {}
}
I know it is very messy and bad. It does change the link to: 'http://google.com');
So I think I may be on the right track. Please help me. Thanks in advance!
Here's an idea: rather than deal with messy regular expressions that are bound to break on some edge case, replace confirmDialog with a function that redirects without confirming:
window.noConfirm = function(m, url) {
document.location.href = url;
}
var fix = document.getElementsByClassName('actionButtonNew');
for (var i = 0; i < fix.length; i++) {
fix[i].href = fix[i].href.replace('confirmDialog', 'noConfirm');
}
http://jsfiddle.net/AV4tB/
And another funny idea: change it call a function that immediately fixes the link, then trigger a click:
window.fixMe = function(m, url) {
this.href = url;
}
var linksToFix = document.getElementsByClassName('actionButtonNew');
for (var i = 0; i < linksToFix.length; i++) {
window.a = linksToFix[i];
linksToFix[i].href = linksToFix[i].href.replace('confirmDialog(', 'fixMe.call(a, ');
linksToFix[i].click();
}
http://jsfiddle.net/AV4tB/1/
Try this:
var fix = document.getElementsByClassName('actionButtonNew');
for (var i = 0; i < fix.length; i++) {
fix[i].href = fix[i].href.replace(/javascript:confirmDialog\(\'Are you sure you want go\?\'\, \'(http\:\/\/.*\.(.){2,3})'\);/gi,'$1');
}
Which uses regex to replace the confirm JS with just the links.
E.g. "javascript:confirmDialog('Are you sure you want go?', 'http://yahoo.com');" becomes "http://yahoo.com"
Pretty annoying to say to users "do you really want to do that?" every time they click on a link. After all, the back button will usually bring them straight back, or the escape key will cancel navigation if they're quick.
Since A elements may not all be links (some are targets), you can get all the links in a page using the document.links collection, then iterate over that:
// Function to call
function navPrompt() {
var text = this.textContent || this.innerText
return confirm('Are you sure you want to go to ' + text + '?');
}
// Attach to all listeners
window.onload = function() {
var links = document.links;
var i = links.length;
while (i--) {
links[i].onclick = navPrompt;
}
}
On the otherhand, if you want to remove the comfirm box and change:
href="javascript:confirmDialog('Are you sure you want go?', 'http://google.com');"
to:
href="http://google.com"
you can do:
window.onload = function() {
var link, links = document.links;
var i = links.length;
while (i--) {
link = links[i];
link.href = link.href.replace(/.*(http[^\'\"]+).+/i,'$1');
}
}
Which will strip out the URL and assign it to the href property.

Categories