Changing custom attribute source with jQuery does not update it - javascript

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.

Related

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

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');
}

Removing data attributes from HTML using jQuery

Can't seem to get this one to work...
I have a page that hides certain links. When the DOM is loaded, I'm using jQuery to toggle some of those elements. This is driven by using a data attribute like so:
<div class="d_btn" data-usr='48'>
<div class="hidden_button">
Then, I have the code:
$.each($(".d_btn"), function() {
var btn = $(this).data('usr');
if ( btn == '48' ){
$(this).children('.hidden_button').toggle();
}
The above all works as planned. The problem is that I am trying to remove the data-usr from the class .d_btn once the if statement is evaluated. I've tried the following and nothing works (i.e., after the page is loaded, the source still shows the data-usr attribute:
$(this).removeAttr("data-usr");
$(this).removeData("usr");
I've been working on this for a couple of hours now and...nothing! Help is greatly appreciated!
UPDATE
I've tried the great suggestions of setting the data attribute to an empty string but I'm still not getting the desired result.
To explain a little further, The reason I'm trying to remove the attribute is so when an ajax response adds another item to the page, the previously added items would already have the button either shown or hidden. Upon AJAX response, I'm calling the same function once the DOM is loaded.
Currently, when something is added via AJAX, it toggles all the buttons (showing the ones that were hidden and vice versa.) Ugh...
I'm also fully willing to try alternatives to my approach. Thanks!
UPDATE
Well, the light bulb just flashed and I am able to do what I want to do by just using .show() instead of .toggle()
Anyway, I'd still like to find an answer to this question because the page will be potentially checking hundreds of items whenever something is added - this seems horribly inefficient (even for a computer, hahaha.)
Why don't you set the value to a random value or empty variable instead if removeAttr does not work..
$(this).attr("data-usr" , '');
$(this).prop("data-usr" , '');
Changing the DOM doesn't affect the source. It affects the DOM, which you can view with the Inspector/Developer Tools. Right click => View Source will give you the original source of the page, not the actual current source as modified by JavaScript.
Set it to a blank string:
$(this).attr("data-usr", "");
I second what Kolink said: check the DOM, not the source. (Chrome: Ctrl + Shift + i).
As others have stated. Checking the source will only show the original unedited source for the webpage. What you need to do is check the DOM using developer tools.
I've just checked everything in Chrome's inspector on jsfiddle here and the attribute is definitely being removed as well as the data.

If ID has class, set attribute of another element

I'm trying to detect if a class is present and, if so, set the background attribute of another element. This is what I have but it's not working.
if(jQuery("#slider-banner").hasClass('living-nutrients'))
{
jQuery("#home-middle-first").css("background-image","[path to new background image]");
}
BTW - My next step is for this to detect it whenever the ID "slider-banner" changes, but so far I can't even get it to work once on page load. Any help would be greatly appreciated... Thanks!
EDIT: I changed from .attr to .css as instructed. Makes sense... but still not working. I've tried adding console.log message within the IF statement and got nothing also. Does that give anyone any more ideas?
Example HTML where class changes:
<img id="slider-banner" class="living-nutrients" src="[image path]">
Example HTML where I want to change background image:
<div class="home-middle-one-third" id="home-middle-first">
</div>
UPDATE:
For everyone who said it "should work"... you are right! Turns out that, as written, it doesn't like being in the footer of the page, but when I moved it to the head, presto!
The final piece of this puzzle is to have it detect and evaluate based on the #slider-banner changing, (or more accurately, which class is present for the ID'd area), not just the page loading, as is currently.
The ID is for one element of a slide within a slider. There are three possible classes I could assign to the ID depending on which slide is visible. So I need the script to evaluate every time a slide changes.
Any ideas? Thank you all!
background-image is a element's style property, not its own one.
So .css("background-image","[path to new background image]");
Almost!
if(jQuery("#slider-banner").hasClass('living-nutrients'))
{
jQuery("#home-middle-first").css("background-image","[path to new background image]");
}
css is the correct function to set a CSS attribute.
The attr will set an HTML attribute. <div attr='attr value'>
Edit
I'm kind of guessing about the functionality of your script here in the following example.
When you set the background-image of a HTML node, that's all it does is set the background image. You must also set the width and height accordingly, to all the node to be large enough to even see the background of the node. Background images will not automatically resize the node.
var slider = jQuery("#slider-banner"); // jQuery("#slider-banner") is slow, so we save it to a var if we use it more than once
console.log(slider); // should be this in Chrome: [<img id="slider-banner" class="living-nutrients" src="[image path]">]
if(slider.hasClass('living-nutrients'))
{
jQuery("#home-middle-first").css({
"background-image":"url("+slider.attr('src')+")", // url() for good meassures
//"background-image":slider.css('background-image'), //try this if that doesn't work
"height":slider.height(),
"width":slider.width()
});
}
Here is a working example.
Try this
jQuery("#home-middle-first").css("background-image","url([path])");

Is there a way to make images inside display:none not get downloaded by the browser?

I want the browser (mobile webkit especially) to NOT download images that are inside display:none divs. Right now, they get downloaded and not rendered.
Is there a jquery plugin to do this?
you can use data-* attributes. that way, you can have jQuery load them on demand:
<img data-source="image_path">
//this one gets all images and loads them
$('img').each(function(){
//loads the source from data-source
this.src = this.getAttribute('data-source');
});
<img data-source="image_path" class="foo">
<img data-source="image_path" class="foo">
//this one gets all images that have class foo and loads them
$('img.foo').each(function(){
//loads the source from data-source
this.src = this.getAttribute('data-source');
});
ofcourse you need to wrap this in a function so that you can call which images on demand. like:
function loadImg(selector){
$(selector).each(function(){
this.src = this.getAttribute('data-source');
});
}
//load images with class foo:
loadImg('.foo');
I don't think so. To be sure, you would need your original HTML DOM to exclude the hidden images, which you could do with server-side programming based on user agent sniffing (although that is not recommended). Modifying the DOM after document.ready or document.load will mean that the browser has already had a chance to request assets from the server even if they might not be displayed.
It would be unusual but if you still want to use jQuery you could follow #Pointy's advice and make all images placeholders in your markup. Then replace the :visible placeholders with the images you want using an attribute as the data source. No plugin is needed, just use something like replaceWith() or attr() to swap out the placeholder node for the image you want downloaded or change the src attribute.
I would use a 1x1 transparent gif as the placeholder with the correct height and width attributes rather than no source <img> for a placeholder. That way the page flow will be determined correctly when the page renders so it won't jump around as your images lazily load.

How to use onmouseover?

I have a list being displayed on a JSP. On mouse hover on any of the value i need to show a description corresponding that value. Need to show description not as an alert and also cannot make the values as hyperlink.
eg.
suppose the value is ABC so on mouse hover should show AppleBoyCat.
need to use onmouseover. let me know how to do it..
What do you want to do? If you just want to show a tooltip, you can set the title attribute of any element and it will be displayed as a tooltip.
Also, the abbr tag can be used as tooltips too:
<abbr title="test">stuff</abbr>
You can go about it in two ways:
1 - a hidden dom object (a div for instance) which reveals itself when you roll over whatever
or
2 - you can rewrite the html of the particular element you're mousing over.
You can load this data in when you load everything else (either as Javascript objects, or as markup, though that's much bulkier) or you can asynchronously load the description data from a service when you mouse over (though you'll have more lag).
jQuery is a quick and dirty way to achieve this (more quick than dirty), but straight JS or pretty much any other JS library will do as well.
Perhaps not the cleanest solution but something like this:
<a class='hover' rel='tooltip'>Link</a>
//Some hidden div, putting css inline just for example
<div id='tooltip' style='display:none;'>Content</div>
$(function() {
$('.hover').mouseover(function() {
var tooltip = $(this).attr('rel');
$('#' + tooltip).fadeIn();
});
});
And offcourse add a callback hiding it again. It just takes the value from rel of the link and use as an id for the div to show.
This is a quick and dirty solution, can be made alot smoother if you just work with it a little;)
There also alot of plugins out there allowing the same functionality in a cleaner fashion.
*Edit: Just noticed you added a comment on another post that you can't use jQuery.. shouldn't tag a post with something you're not intending to use.
As TJHeuvel already said, you can simply use the title attribute.
Best approach is to build the list with both the value and title attribute from within JSP, if not possible for some reason, you can build client side array of each value and its corresponding description then using JavaScript dynamically assign the title on mouseover.
Show us some more code to get more/better help.
For simple tooltips, the title attribute is most effective, as pointed out by TJHeuvel
If you need more advanced tooltips with HTML and CSS formatting, I'd suggest you use an external library.
One that works nicely without jQuery ist wz_tooltip download here, documentation here
When included correctly, you can add tooltips by calling the functions Tip() and UnTip() as follows:
Homepage

Categories

Resources