Toggling an html IMG element's class using JS (no Jquery) - javascript

I give up... All of your answers were just different ways of targeting the local element.
If you bothered to actually read what I was saying you would realise that it was not a problem with the code I already had, just that the code DID NOT work on IMG tags.
While faffing around trying to demonstrate my problem (and that none of your solutions did anything different to what was already happening) I found that I can achieve exactly what I want by applying a Grayscale filter to a DIV element placed over each image. The mouseover event then triggers an opacity change in the DIV element.
It is a little heavier that I wanted but it answered my ACTUAL question. The answer being:
Yes, there probably is a way to toggle class of IMG tags. But no, I am probably not going to find it here without causing arguments or being told i'm using "bad code". So yes, it IS easier and more efficient to target DIV elements.
By the way, page load times are about how large data packages are. Larger data packages (images, html/css/js documents, etc) take longer to download and so the page takes longer to load. The website I am trying to create proves this thesis, I have an almost complete and (almost) fully functional website with loads of 'clever' little effects all under 20mb, about 15mb of which is images. This website is clean and simple, is hosted on my Samsung Galaxy Tab 4 (using Papaya) and loads almost instantly.
THIS is what I meant by "I want this to be VERY lite". Thank you all for your attempts to help, it's just a shame that I couldn't get anyone to understand what was going on.

If you add onClick to image element you don't need to pass anything, you will receive MouseEvent which contains all information. You need target from event.
I suggest to not use onClick on element as it is not scalable, you have to add it to all elements. Better to add listener to wrapping/container element and then filter target by some attribute e.g data-something Please check fiddle
So you have wrapping element and you images:
<div class="images-container">
<img src="https://placeholdit.imgix.net/~text?txtsize=33&txt=350%C3%97150&w=350&h=150" data-toggleable class="thumb-gray thumb-color" />
<img src="https://placeholdit.imgix.net/~text?txtsize=33&txt=350%C3%97150&w=350&h=150" data-toggleable class="thumb-gray" />
<img src="https://placeholdit.imgix.net/~text?txtsize=33&txt=350%C3%97150&w=350&h=150" data-toggleable class="thumb-gray" />
</div>
and you attach listener to you wrapping element. It is best practice as you don't attach listeners to each element and same time you are able easily scale your solution
var imagesContainerEl = document.querySelector('.images-container');
imagesContainerEl.addEventListener('click', function(event) {
var element = event.target;
if (element.hasAttribute('data-toggleable')) {
element.classList.toggle('thumb-color');
}
});
The same code can be extended to support mouseover and mouseout. Check fiddle2. One function to rule them all and in the darkness bind them..
var imagesContainerEl = document.querySelector('.images-container');
imagesContainerEl.addEventListener('mouseover', onToggleImage);
imagesContainerEl.addEventListener('mouseout', onToggleImage);
function onToggleImage(event) {
var element = event.target;
if (element.hasAttribute('data-toggleable')) {
element.classList.toggle('thumb-color');
}
}
Also updated fiddle which shows how to make image grayscale/color

Is what you refer to in your question as
onClick="colorFunction(image1)"
an inline javascript event listener?
If so, try replacing it with:
onClick="colorFunction(this)"
and rewrite colorFunction() as:
function colorFunction(image) {
image.classList.toggle('thumb-color');
}

Related

JavaScript: backgroundImage isn't changing with onMouseOver

I'm pretty new to JavaScript, and I'm trying to figure something out. I have a series of images within a table, and I'd like each image to display within a div element when you hover over one. The problem is, the code doesn't appear to be doing anything. I hover over the div element, and no changes are being made to the #bigdisplay element. If I replace the backgroundImage with a property such as color, it works completely fine. What am I doing wrong? This is the code for my div element.
<div id="image1" onmouseover="document.getElementById('bigdisplay').style.backgroundImage='url('images/Slideshow1.png')';">
/* ... */
</div>
If I must provide any other code from my site I will (although I don't believe any of it is relevant). Any help would be greatly appreciated! Thank you!
Your code is fine. I separated the js just to make it easier to read. Your problem is either you have no height to the div or your path is wrong
function test(){ document.getElementById('bigdisplay').style.backgroundImage=
'url("https://res.cloudinary.com/rss81/image/upload/gw.jpg")'}
html,body,div{
height:100%;
}
<div id="bigdisplay" onmouseover="test()">
test
</div>
You're not properly escaping the string in the attribute. Attach the listener in Javascript instead, rather than in HTML attributes (which is as bad as eval) and it'll be easier to read and write:
const bigdisplay = document.querySelector('#bigdisplay');
document.querySelector('#image1').addEventListener('mouseover', () => {
bigdisplay.style.backgroundImage = "url('images/Slideshow1.png')";
});
I think one problem is that you used single quote to quote 'images/Slideshow1.png'. But you used single quote also for 'url('images/Slideshow1.png')'. So there is a conflict. Try 'url("images/Slideshow1.png")'. A part for this I find better to define the event handler function in the js document linked to the html document.

Changing custom attribute source with jQuery does not update it

Quick Intro:
I'm using jQuery.elevateZoom-3.0.8 as to show zoomed picture.
SRC attribute is path to smaller/normal image
DATA-ZOOM-IMAGE attribute is path to bigger image that serves as a zoom.
HTML Code Below:
<section id="designer-single" class="col-md-7" >
<div class="magnifier-thumb-wrapper mc">
<img class="front-magnify"
src="../../public/img/burn/purple-front.png"
data-zoom-image="../../public/img/burn/purple-front-lg.png">
</div>
</section>
<button class='back-image'>Click me</button>
Now I want image to change when user presses a button. Smaller image will change (SRC attribute), but bigger one will not refresh (data-zoom-image attribute) even though i change it with jQuery.
$('.back-image').on('click', function(){
$('.front-magnify').attr('src', 'public/img/burn/purple-back.png');
$('.front-magnify').attr('data-zoom-image', 'public/img/burn/purple-back-lg.png');
});
Question is: how do I update state of custom attribute "data-zoom-image" in elevateZoom.js so that it updates on DOM?
https://i.stack.imgur.com/hFvG7.png => without clicking
https://i.stack.imgur.com/r0tUw.png => when changing
Example on Codepen:
https://codepen.io/kenanbalija/pen/MojOEp
What seems likely to be the problem is that you're changing the attribute successfully, but the code in elevateZoom.js is initing based on the original value and isn't watching for changes.
Based on your comment below and a quick look at the plugin source code, my earlier guesses (reinstantiate the plugin by calling .elevateZoom again, or use the responsive option) won't work. This is a one-shot plugin, it's really not designed to be controllable after it's instantiated, so your options are pretty limited.
You could go brute-force and destroy the existing plugin (by removing the whole DOM element) before replacing it with a new one and reinstantiating the plugin.
Or, since you appear to be toggling between two different zoomable images, it may be simpler to instantiate them both separately and hide / reveal each as necessary, something along the lines of
$('.image').on('click', function(){
$('.front-magnify, .back-magnify').toggleClass('hidden');
})
That'd be a tradeoff between bandwidth and code complexity, of course.

JavaScript - dynamic SVG - onload attribute - event not triggered

Inserting dynamic SVG content into the DOM does not work as expected, having the SVG element onload attribute (containing JavaScript) regarding: "setInterval()".
As noted in the search tags of this question; this is plain (valilla) JavaScript (not jQuery); here's a breakdown of the issue:
I have some SVG code (plain text) that gets inserted into a <div> as innerHTML
the SVG element has an onload attribute with some JavaScript inside it
the JavaScript contains setInterval(...) - (which does not work at all)
I grab the SVG element from the temporary div and return it as the result of a function.
this result is appended into some element in the live DOM (body)
the strange issue:
any other code inside that onload attribute works fine,
only setInterval & setTimeout is completely ignored
More info:
During runtime (start-up), the SVG code is grabbed from an existing embed element .getSVGDocument() (after it has loaded) and prepared as plain HTML which can just be used as a template to create many others from the same source-code. I'm not using cloneNode(true) -because: the interval is for animation (continuous slow & smooth rotation) - which could have a heavy impact on client-side resources, hence, I thought it best to grab the code and keep it as template - then remove the original from the DOM.
With all the above in mind, everything works fine:
The (new) SVG shows up on screen, all nice and dandy-like
When I console.log the (inline) SVG code that is used, all looks perfect
I get no errors, and there is no error handler that mutes errors (window.onerror == null)
The JavaScript (text) inside the SVG node's onload attribute works for things like: console.log(this) - (which produces the SVG element in the log) - however, as mentioned: setInterval() & setTimeout() is just simply ignored - without any error and no warning.
The following code is a very short example, and (regrettably) it works; however, in my production app it doesn't.
The code:
var html = '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" onload="setInterval(function(){ console.log(\'testing\'); },500);">';
var temp = document.createElement('div'); temp.innerHTML = html;
var node = temp.getElementsByTagName('svg')[0];
document.body.appendChild(node);
If you test the above code in a new js file, it works; however, for the life of me I can't find the reason why it breaks in my app; as explained, it's quite simple really.
The question:
Does anyone know if there is some "gotcha" I'm not aware of regarding this? Maybe name-spacing?
If the source-code is required, I can load it up on JSFiddle, or CodePen -if required, but, it's a lot of code, and many files, which may not be necessary for publication.
I'm sure it's just something small; like, how timers register according to scope, and maybe how it's affected in .bind() ?
I'm really stuck with this, and I kinda need it working for a good impression for a job-interview; so if you know anything that could help, I would appreciate your input very much.
Thank you.
embedded content, onload attributes & the DOM
The following may help in related scenarios:
when targeting an asynchronous source, make sure the contentDocument or getSVGDocument() contains the resources you need to access. The window.onload, or the DOMContentLoaded event is relative to the current DOM, so it may help constructing your own listener->trigger for a cross-browser solution, because the contents you need may not be ready in a synchronous fashion.
the onload attribute/event is not triggered when inserting dynamic content that is not asynchronously loaded, but may fire under certain circumstances, so, again, a custom:
listen->trigger will solve that.
question specific
The question is directly related to the 2nd point above, and the answer is quite simple really:
in the "onload" attribute of said SVG, set a simple value as property of this like:
<svg onload="this.ready = true; setTinterval(...)"
in the constructor function, after the element was dynamically created, simply check if the svg-node's onload event was fired like so:
if (!svgNode.ready){ svgNode.onload(); }
If there is an error in your code, but no error is shown, make sure window.onerror is either null -or if it's a function, make sure it does NOT return true - else it may suppress errors and you'll have a hard time tracking down what's wrong.
Please feel free to either improve this answer, or comment and I'll improve it accordingly; however, better answers will be appreciated.
6 years later...
With vanilla JavaScript Web Components you can do:
<load-svg></load-svg>
<script>
customElements.define("load-svg", class extends HTMLElement {
connectedCallback() {
this.innerHTML = `<svg></svg>`;
setInterval(() => {
console.log("testing");
}, 500);
}
});
</script>

(JavaScript ?) Display div with different content on choice?

I'm looking for a solution that will allow me to display a div when I click on a single link (which will change the way css style) with variable content (eg a sub-div with service1, service2, service3 ). This div will be displayed also propose several offers that will only display the div payment when one of these offers will be selected.
It's maybe hard to explain (i'm not english so sorry for really noob level), so maybe with this image you will "understand" a little bit more:
http://image.noelshack.com/fichiers/2015/38/1442422045-fonctionnement.jpg
I confess to being a bit lost with JavaScript for this kind of thing. I know it's probably achievable, but how? :-(
Thank you for your help folks!
If you want to go the way with altering CSS with javascript, assuming you are not creating the variable content on the fly, have the divs css for display set to none.
#divID {
display = none;
}
Then set an event listener on your link to change the display style to block.
document.getElementById("linkID").addEventListener("click", function() {
document.getElementById("divID").style.display = "block";
}
Ok so I created a crude representation of what you asked without much effects. But the fiddle I created completely functions as you intended. If you click buttons on div 1 the content of div 2 gets updated. If you click anything on div2 the information is displayed in div3. Here is the example: Working Example
window.function1 = function(){
var edits = document.getElementById('2');
edits.style.background="aliceblue";
}
//SAMPLE CODE TO EDIT ANY ELEMENT BY REFERRING BY ID. CALL SUCH FUNCTION ONCLICK
Please check the example to understand it fully.

HTML: How to make scrolling work faster here

I have developed an application about product and their detials. In that application, at a page, it loads almost 10,000 product details on single page only.
I have attached a raw screenshot here :
http://img51.imageshack.us/img51/4430/uploadm.jpg
As the first step, the page loads an empty structure with no product detials in it.
Then using javascript BigPipe, it adds details of products in the structure.
The Product Detail Structure :
<div class="product_disp"
onclick="return clickEffect(this,event);"
onmousemove="return show_img_trail('product_details');"
onmouseout="return hide_img_trail(this);" align="left" >
<img src="pic.jpg" class="prodcuts_img"/>
<span style="overflow:hidden;" align="left"> <b> Product_3 </b> <br/>
id : 8146 <br /></span>
<span style="padding:0px;width: 100%;" align="right">Available </span>
</div>
But when i try to scroll down the scroller for product_details <div> , it scrolls slowly.
what can i do to make scroll like normal?
i dont know what exactly making it slower.
There are a lot of options, and they might not all be applicable, but here are some:
Don't load 10,000 items on a single page, instead opting to load maybe 100 and then allowing users to page through (either using a traditional page selector, or with a "load more" link when they hit the bottom, or even autoloading more as they scroll to the bottom).
Move JavaScript event bindings for any events that bubble from the individual elements to the parent, then handle them there. To do this easily, use jQuery.live('event', function(){ ... });.
Use a stylesheet instead of putting styles inline. And make sure that your selectors are high-performance (don't over-qualify them, prefer IDs and a class to adding long chains of element names, etc.).
Generally speaking (it doesn't appear you're doing this) avoid CSS3 effects like drop shadows until they become more performance-friendly.
Make sure you're not executing excessive JavaScript queries (cough, using onscroll or using onmouseover for every element on the page, cough).
Without seeing what you're doing in your JavaScript and what your CSS looks like, it's hard to give you more specific details about your situation, though.
The best idea is to give a full test page or URL if you want specific answer for your case.
You can keep 10 000 products in memory (as a Javascript object) without displaying all of them as a part of your page. It makes layout computation much faster. Try listing in groups of 10-20-30 items or adding/removing them on scroll event.
Use event delegation to improve performance (a root element handles all the events)
function normalize(e) {
e = e || window.event;
e.target || (e.target = e.srcElement);
return e;
}
var root = document.getElementById("root");
root.onclick = function(e) {
e = normalize(e);
return clickEffect(e.target, e);
}
root.onmouseout = function(e) {
e = normalize(e);
return hide_img_trail(e.target);
}
Use mouseover instead of mousemove (delegated as well)
root.onmouseover = function(e) {
return show_img_trail('product_details');
}
Separate presentation (CSS) from markup (HTML). It won't affect performance, but makes your code readable and maintainable.
I ran across similar problem few days a go! What kind of other creative interface we possible can provide in there?
Currently i am using event delegation on my page but i am quite curious about other possible interfaces in such scenarios. Pagination or load more are not an options in my case so what else i can do there?

Categories

Resources