HTML/CSS/Javascript, trying to get image to change on click - javascript

Quite a simple question, yet it has been bugging me all week!
Firstly, I do not expect someone to write me this huge piece of code, then me take it away and claim it for my own. Would prefer someone to actually help me write this :)
I am attempting to show a playlist on my website as a png image.
I have 2 playlists that must be shown.
The playlist will change on an image press.
I have 4 button images, 'CD1up', 'CD1down', 'CD2up' and 'CD2down'.
I would like to have these buttons changing what current playlist is being shown, but also showing the buttons correct state. For example, is playlist1 is being shown, then 'CD1up' must be shown, and 'CD2down' shown.
I would post my current code here, but I basically scrapped it all and decided to start from scratch since I'm terrible with web javascript.
All help is greatly appreciated!
I can basically fluent in HTML and CSS, but horrible at web javascript.

Some notes:
If you give each image an id attribute, you can use document.getElementById to get a reference to that element once the page is loaded.
Then you can set the src property on that element to a new URL to change the image.
Make sure your script tag is after the elements in the HTML (just before the closing </body> works) so that the elements exist when you want them.
You can add a click event handler to any element on the page. Most browsers support addEventListener but some older versions of IE still require you to use attachEvent to hook up the handler. So you see people with functions that look something like this:
function hookEvent(element, eventName, handler) {
if (element.addEventListener) {
element.addEventListener(eventName, handler, false);
}
else if (element.attachEvent) {
element.attachEvent("on" + eventName, handler);
}
else {
element["on" + eventName] = function(event) {
return handler.call(this, event || window.event);
};
}
}
So for example, if you have this img:
<img id="myImage" src="/path/to/img.png">
This cycles through four images on click:
<!-- This must be AFTER the `img` above in the HTML,
just before your closing /body tag is good -->
<script>
(function() {
var myImage = document.getElementById("myImage"),
images = [
"/path/to/img1.png",
"/path/to/img2.png",
"/path/to/img3.png",
"/path/to/img4.png"
],
index = -1;
hookEvent(myImage, "click", imageClick);
function imageClick() {
++index;
if (index >= images.length) {
index = 0;
}
myImage.src = images[index];
}
})();
</script>
You can get a lot of utility functionality and smooth over browser differences using a decent library like jQuery, YUI, Closure, or any of several others, although if all you want to do on the page is change the images sometimes and handle a click or two, that might be overkill.

Related

An AJAX Search Plugin is removing my Event Listeners from an 'Accordion' style list

I'm using Search & Filter pro WP plugin for the ease of a client using it.
I've created a results page and filter on a demo site (for testing) that works fine but I know the categories will get large on the real site. So I turned the plugins' filters into an Accordion style list.
It works fine until certain searches reload all those filter results with AJAX and they remove my event listeners (which are sitting on elements for the moment, I know it's not ideal but for now I just want to see if it could work).
I imagine because my script has already been parsed when the DOM loaded, the AJAX from the plugin is just redefining those elements and they are then missing the Event Listeners or something.
Any help would be appreciated.
Here's my script:
<?php
add_action( 'wp_footer', function () { ?>
<script>
const clicker = document.querySelectorAll('#search-filter-form-4346 > ul > li > h4');
// looping through the <h4> elements and adding an event listener onto each, the class toggle just adds an animation to a pseudo-element spinner
for (let i = 0; i < clicker.length; i++) {
clicker[i].addEventListener("click", function() {
this.classList.toggle("open-filter-dropdown");
console.log('EL was created');
// declaring the <ul> as a variable
const openFilterPanel = this.nextElementSibling;
// animating the <ul> elements max-height
if (openFilterPanel.style.maxHeight) {
openFilterPanel.style.maxHeight = null;
} else {
openFilterPanel.style.maxHeight = openFilterPanel.scrollHeight + "px";
}
console.log('openFilterPanel style is changed');
});
}
</script>
<?php } );
I'm pretty new to javascript, I get the basic concepts but this kind of an interference is above my head. I tried refactoring my code, forcing the page to refresh and other such measures. None of these work very well. I also thought I could use a 'loadend' event on the document to re-add my ELs but that didn't work either.
Hoping there is a workaround here, otherwise I might have to find another solution or plugin.
Thanks in advance!

Calling two functions from same onclick failure

I have a problem when calling 2 JS functions that work fine separately. I am not well versed in JS: I took the scripts from some posts here and adapted them, and I cannot make them work together. My goal is to make appear the side panel and to change the color of a box within that panel when clicking on the related link in the main text (and to undo it by clicking again on it).
This is the function that I use for showing the side panel:
function showRightPanel() {
var elem = document.getElementById("right-panel");
if (elem.classList) {
console.log("classList supported");
elem.classList.toggle("show");
} else {
var classes = elem.className;
if (classes.indexOf("show") >= 0) {
elem.className = classes.replace("show", "");
} else {
elem.className = classes + " show";
}
console.log(elem.className);
}
}
And this is the function for changing the color:
var els = document.getElementsByClassName('change-color'),
target = document.getElementById('footnotes'),
changeColor = function() {
target.style.backgroundColor = this.getAttribute('data-color');
};
for(var i=els.length-1; i>=0; --i) {
els[i].onclick = changeColor;
}
And this is the html that calls both functions it:
<a href="#footnote1-chapter1" class="change-color" data-color="#E0FFC2"
onclick="showRightPanel();changeColor();"></a>
And this is the box that has to appear and change color:
<div id="footnotes"><p class="footnote" data-id="footnote1-chapter1">
</p></div>
Both scripts are in separate .js files that are referred to in the header, and I know this might be the problem for the second script, as it was mentioned that:
"You should put the javascript at the end of your body (just before ), or wrap it in a function listening load or DOMContentLoaded event (e.g. using addEventListener). If not, document.getElementById is executed before the element is loaded to the DOM, so it return null. – " in this post change background color of div.
But I do not know how to "wrap it in a function listening load or DOMContentLoaded event".
Can someone please help me?
Thank you for your help in advance!
You could wrap your code in an on load function, but the general consensus seems to suggest putting your scripts at the end of the body tag instead, according to this StackOverflow answer and the YUI team. This accomplishes the same thing as wrapping your code, and might fix your problem if it's related to DOM dependencies.
So I would recommend you put your scripts at the end of your body tag instead of in your head tag, and see if that helps.
As Nathan mentioned, your anchor has the attribute onclick as onclick="showRightPanel();changeColor();"
But your javascript replaces this attribute, see: els[i].onclick = changeColor;
So only changeColor function will be called.
[update]
As in the comments, the accepted answer:
els[i].onclick = function(){showRightPanel();changeColor.apply(this);}

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.

What are some ways to speed up an img swap in jquery / javascript?

I have a slightly vague question. I have the following in my code: http://jsfiddle.net/PMnmw/2/
In the jsfiddle example, it runs smoothly. The images are swapped quickly and without any hassle. When it is in my codebase though, there is a definite lag.
I'm trying to figure out why that lag is happening. The structure of the jquery is exactly the same as above. I.e. Inside the $(document).ready (...) function, I have a check to see if the user clicked on the img (based on the classname) and then I execute the same code as in the jsfiddle.
I'm at my wits end trying to figure out what to do here... Clearly I'm not doing the swap right, or I'm being very heavy handed in doing it. Prior to this, one of my colleagues was using AJAX to do the swap, but that seems to be even more heavy duty (a full fledged get request to get the other icon...).
I've modified your fiddle: http://jsfiddle.net/PMnmw/12/
Things I've optimized:
Created a variable for both img1 and img2, so that you won't have to navigate the DOM to reference those two images anymore, thusly improving performance.
Applied a click handler to the images themselves, so you don't have to search the children of the wrapper.
The basic idea was to reduce the number of jquery selections as much as possible.
Let me know if this helped speed things up.
$(document).ready(function() {
var img1 = $('#img1');
var img2 = $('#img2');
$(".toggle_img").click(function(e) {
var target = $(e.target);
if(target.is(img1)){
img1.hide();
img2.show();
}
else if (target.is(img2)) {
img2.hide();
img1.show();
}
});
});
Images that are not visible are normally not loaded by the browser before they are made visible. If there seems to be a problem, start by downloading an image optimizer like RIOT or pngCrush to optimize your images.
If it's only two arrows, you should consider joining them into a CSS sprite.
You could try not doing everything with jQuery, but it shouldn't really make that much difference.
Something like this maybe, with the hidden image loaded in JS and some traversing done outside jQuery (but that is probably not the problem, although the code seems overly long for a simple image swap?) :
$(document).ready(function() {
var img=new Image();
img.src='http://i.imgur.com/ZFSRC.png'; //hidden image url
$(".wrapper").click(function(e) {
if(e.target.className=='toggle_img') {
$('.toggle_img').toggle();
if (e.target.parentNode.childNodes[1].style.display=='none') {
console.log("hello");
} else {
console.log("goodbye");
}
}
});
});
FIDDLE
​

jQuery Image Gallery stops working in IE7&8 after using for small period of time

I have the following code I am using for a photo gallery. In Internet Explorer 7 & 8 the gallery stops working. The image fades out after several clicks and the new image does not fade in. After this occurrence happens (about 6 or so clicks) the gallery does not function at all. All other browsers work flawlessly. I have also used this code in several other pages with no problems.
$("#list-image-carousel").find('a').click(function(e) {
e.preventDefault();
var src = $(this).attr("href");
$("#main-img").find('img').fadeOut(400,
function() {
$("<img/>").attr("src", src).load(function() {
$("#main-img").find('img').attr("src", this.src).fadeIn(400);
})
})
});
Any ideas are greatly appreciated. Thanks in advance!
Here's one possibility: it looks like you're establishing the "load" handler on your temporary image element after you're initializing the "src". That's a problem in IE - reverse the order of those things and see if that helps.
$("#main-img").find('img').fadeOut(400,
function() {
$("<img/>").load(function() {
$("#main-img").find('img').attr("src", this.src).fadeIn(400);
}).attr("src", src);
})
If the image is in the cache, then when you assign the "src" attribute IE will immediately ready the element. If there's no "load" handler defined at that point, it won't queue up the event at all.
Also, just as a note, the construct
$('#main-img').find("img")
could be written:
$('#main-img img')
Doing it like that is a little shorter, but in truth it may or may not actually be faster. Probably would be, I think.

Categories