I have a contenteditable container with some images inserted. Also I have defined some internal values to these images with the jQuery.data() function.
Everything is working well untill I move these images inside the contenteditable. Then, all data associated with the images is gone.
Do you know how to avoid this? or if there is a better solution to assign information to DOM elements?
I used to assign values to DOM elements within their data- attributes.
So instead of data(), i'd use
set: $('image').attr('data-attr1', 'value1');
get: $('image').attr('data-attr1');
Related
I have a set of 5 images each with a unique filter attribute in a list of filters and the main image in a separate div.
The main image does not have a filter applied to it.
I would like to have users click on any of the images on the sidebar and then apply the selected filter to the main image.
I tried using an event listener for that but I don't really understand what's happening.
Here's my code:
<img src='http://res.cloudinary.com/demo/image/upload/c_fill,e_art:audrey,h_80,w_120/sample' filter='audrey' className='filter' />
and an event listener that gets called when a user selects an image.
onFilterSelect = event => {
console.log(evenet.target) // returnsimg element
console.log(event.target.src) // returns src of img element
console.log(event.target.filter) // returns undefined
}
I would like to use the filter='filter' prop to dispatch an action that sets the state to the newly selected filter but I keep on getting undefined as a result.
HTMLImageElement.prototype does not have a filter property (which you are trying to access).
Your image has a filter-attribute (which makes your HTML invalid because it is not a valid attribute on img elements).
If you need to stick with that invalid attribute name, you can access it using
console.log(event.target.getAttribute('filter'))
The better solution would be to change that attribute to a data-filter attribute, which you can access like this:
console.log(event.target.dataset.filter)
Please note that there is a special naming convention in the .dataset object:
data-filter="Audrey"
can be accessed using
img.dataset.filter
but
data-image-filter="Audrey"
would be accessed using
img.dataset.imageFilter
Notice the automatic conversion of kebab-case to camel-case!
console.log(event.target.getAttribute('filter'))
Not all HTML attributes are in element's properties. Also using data is better for custom attributes, as suggested by others.
jQuery (all versions tested up through 2.1.0) allows me to call .val("some value") on a DIV object to set a value on the DIV. It is not displayed and doesn't show up as an HTML5 data property in Chrome Developer Tools. And yet I can fetch the result later with a call to .val().
For example (from http://jsfiddle.net/X2nr6/ ):
HTML:
<div id="mydiv" style="display: none;">Some text</div>
<div id="debug"></div>
Javascript:
$('#mydiv').val('A value attached .');
$('#debug').text( $('#mydiv').val() );
Displayed result:
A value attached.
Where is the value stored? Not knowing where it is stored makes me worry that I am relying on a hack.
jQuery is just assigning to a value property on the div object (the HTMLDivElement instance for that div), even though it doesn't normally have one. Creating new properties on elements is allowed in every browser I've ever seen, so it works. I wouldn't use val with divs on a regular basis, though.
Here's a non-jQuery example:
var div = document.createElement('div');
console.log('value' in div); // false, divs don't normally have a value property
div.value = 42;
console.log('value' in div); // true, we've created a property on the element
console.log(div.value); // 42
Or the same sort of thing using jQuery:
var $div = $("<div>");
display(typeof $div.prop('value'));
$div.val(42);
display(typeof $div.prop('value'));
display($div.prop('value'));
This business of creating new, custom, non-standard properties on elements is called creating "expando" properties. They can be very handy. (jQuery uses them internally, for instance, to manage the data cache and a few other things — if you look closely at a DOM element you've set data on using data, you'll see a property with a name like jQuery1110028597884019836783; that's the key jQuery uses to find the element's data in jQuery's internal data cache. jQuery doesn't store the data in an expando on the element, because of IE garbage collection issues; it stores the key there, and the data in a JavaScript object.)
It stores it on a value property on the DOM object. You can see if by running your code and then inspecting the element in a DOM inspector. In Chrome, the value property will be listed under div#mydiv in the properties tab.
HTMLDivElement objects don't officially support such a property, so you are relying on a hack.
Use data() to store arbitrary data on an element.
$('#mydiv').data("myCustomValue", 'A value attached .');
Although the above answers are accurate, I'd like to complete something out.
jQuery is designed around the concept of wrapping all HTML elements in the jQuery object. That jQuery object happens to be an array that can hold more than one element.
jQuery also goes out of its way to hide this fact from you so that the average jQuery developer never has to worry about exactly what he has -- simply call the right method and the magic happens.
(You see this if you do a $(".someClassYouHaveLotsOf").hide() or $(".someClassYouHaveNoneOf").hide()`.)
jQuery's val() method is just a wrapper for accessing an HTML input element's value property. Since jQuery doesn't throw errors unless there is really no way what-so-ever, it silently helps you by accessing the value property on whatever HTML element it happens to have. div span or whatever.
In most browsers, this works -- mostly enough.
If you are really interested in setting values on HTML elements for use later, the data() method is far better suited. Straight HTML would use <element>.setAttribute("data-key", "value");
And that is about the only time you'll see me using the HTML attributes over properties, BTW.
Using jquery data() to set data attribute of an element, like so:
HTML:
<div id="some-el" data-number="0"></div>
JQ:
$("#some-el").data("number",1);
As we know, data changes variable internally. So inside inspector you cannot actually see that new value is 1. But this aside, if I do clone on the element with new data value, jquery clones original dom element without current data value!!!
$("#some-el").clone();
Results in <div id="some-el" data-number="0"></div> both internally and visibly!
I was thinking I could avoid this problem by simply using attr("data-number",1);
Anyways, I wanted to ask you if this is correct behaviour of dat()? Is what I'm seeing expected? and WHY?
I think clone can accept a boolean to indicate a Clone with data and events, so Clone(true) should work: http://api.jquery.com/clone/
Here's a fiddle that works: http://jsfiddle.net/2pdNL/
.data() is not setting the value in DOM.
The data- attributes are pulled in the first time the data property is
accessed and then are no longer accessed or mutated (all data values
are then stored internally in jQuery)
But here is a workaround, instead of using
$("#some-el").data("number",1);
Interact directly to DOM like
$("#some-el").attr("data-number",1);
JSFiddle
Also check this answer
I'm appending values into a div through jQuery, but I've realized what gets appended isn't affected by my javascript functions.
$(".div").append("<input type='text' class='textForm' placement='Value' />");
What I have setup in my javascript code is that it takes the attribute placement of any class "textForm" and makes it a value. But I've realized that once a value is appended, it isn't effected by my javascript. Any ideas on how to fix this issue?
If you are currently using
$(".textForm").click(){}
then now use
$(document).on("click",".textForm",function(){//Dtuff here})
This will attach the .on("click") to the document object and as such it will be enabled on all elements that exist and all elements that are created matching the .textForm selector.
I guess you have some events bounded to some elements like which are not working after the append . something like this.
$(function(){
$(".someClass").click(function(){
//dome some thing
});
});
If you want the same functionality to work on the newly injected( dynamically added via append /jquery ajax etc...) DOM elements, you should consider using jquery on. So your code should be changed like this
$(function(){
$(document).on("click",".someClass",function(){
//dome some thing
});
});
on will work for current and future elements
I'm not sure I understand the bit about why you're copying values from the placement attribute into the input value, but I can offer this suggestion to get your form fields to appear.
$("div").each(function() {
$(this).append($("<input type='text' class='textForm' placement='Value' />"))
});
I'm assuming that you want to identify your div via the tag name, and not the class name. If this is the case, your jQuery selector will need to be "div", and not ".div". Also, you need to wrap your HTML in $() in order to generate a DOM element.
I want to add some properties to a <div> element. All of the below works except for the .data(). I cannot see it appear in Firefox/Firebug.
$('#menu-container')
.css('background-image','url("'+big_image+'")')
.addClass('click_2')
.data("new_link", "new_link.html")
.css('z-index',"99");
Am I doing it wrong?
data is not just any ordinary attribute you can add, it is a way to attach objects and data to DOM elements. You can't see it in the HTML source or in Firebug, but you can query it using .data()
The data itself is not stored on the element. It's actually stored in $.cache
.data() is working but it won't show up as an element's attribute.
If you wanted to see it working you can try console.log($('#menu-container').data('new-link'));
If attributes are what you want then you can do .attr('new-link','new-link.html')
Use
$('#menu-container').attr('data-new_link','new_link.html');
it will appear in firebug, and you can also use the expected jQuery behavior
$('#menu-container').data('new_link');
to retrieve the value stored..
But there is really no need to do it this way. It gets stored at the .data() collection, regardless of being added as an attribute to the DOM element..