jQuery $.data(): Possible misuse? - javascript

Perhaps I'm using $.data incorrectly.
Assigning the data:
var course_li = sprintf('<li class="draggable course">%s</li>', course["fields"]["name"]);
$(course_li).data('pk', course['pk']);
alert(course['pk']); // shows a correct value
alert($(course_li).data('pk')); // shows null. curious...
course_li is later appended to the DOM.
Moving the li to a different ul:
function moveToTerm(item, term) {
item.fadeOut(function() {
item.appendTo(term).fadeIn();
});
}
Trying to access the data later:
$.each($(term).children(".course"), function(index, course) {
var pk = $(course).data('pk');
// pk is undefined
courses.push(pk);
});
What am I doing wrong? I have confirmed that the course li on which I am setting the data is the same as the one on which I am looking for it. (Unless I'm messing that up by calling appendTo() on it?)

When you store the data:
$(course_li).data('pk', course['pk']);
you're creating an element but not saving it, so it's lost. Your alert test test the wrong value; it should be:
$(course_li).data('pk', course['pk']);
alert($(course_li).data('pk'));
which is null. Consider:
$(course_li);
$(course_li);
This creates two different elements with source equal to course_li, which are then promptly lost. What you need to do is create the element first, then work with that single element (i.e. don't call $(course_li) more than once). For example,
var course_li = $(sprintf('<li class="draggable course">%s</li>',
course["fields"]["name"]));
course_li.data('pk', course['pk']);
parent.append(course_li);
Note that course_li now holds an element, rather than a string.

try checking to see if the element being created by this call:
$(course_li)
is a single 'li' element, or a div. From the doco:
When the HTML is more complex than a single tag without attributes, as it is in the above example... snip ...Specifically, jQuery creates a new <div> element and sets the innerHTML property of the element to the HTML snippet that was passed in
So it's probably creating a div that you are assigning the data to, so when you select the 'li' itself, you are getting a child of the actual element that you set the data on.

Related

.appendChild() an HTML element on click

I wanted to copy an entire row including its' siblings and contents on button click. When I click the button the element, it appears in the console but doesn't append to the page. This is my code:
It doesn't show any error messages. I've tried innerHTML/outerHTML or append() it doesn't work.
$(document).ready(function() {
$('#addSubFBtn').on('click', function() {
var itm = document.getElementById("trFb");
var wrapper = document.createElement('div');
var el = wrapper.appendChild(itm);
document.getElementById("tbFb").append(el);
console.log(el);
});
});
Seems like what you're trying to do is clone the item after you get it from your document. W3schools website explains how to accomplish this. Check out the link: https://www.w3schools.com/jsref/met_node_clonenode.asp
Once you clone the node, [appendchild] should work as intended
Not sure (as said without seeing related HTML) but i see flaw in your logic:
var itm = document.getElementById("trFb");
still exist on the document(so in the page) so you've to retrieve it before you want to add/move it to another place.
using .removeElement will return you removed element(or null if no element matche the selector) so correct script should be:
var itm=document.getElementById("trFb").parentNode.removeChild(document.getElementById("trFb"));
as shown here to remove element you've to use method on to parent element.
So you can add it to any other element existing.
For more specific use or element created in global JS variable (such an createElement not yet appended) you can see :document.createDocumentFragment(); as explained here https://developer.mozilla.org/en-US/docs/Web/API/Document/createDocumentFragment

jQuery cannot find class element from some html returned via ajax call

I am running an ajax call that returns some HTML as a string. For the purpose of this question I will call this <div class='abc'>ABC123</div> when I get this back I want to check and see if the class "abc" has a value and what that value is. However when I run a .find() I cannot find the class, I can find the div, but not the specific class. Just using the div is not adequate because in the real live code the HTML is very complex and has many divs and classes. Below is some JS that illustrates my point.
var x = "<div class='abc'></div>";
$(x).hasClass("abc"); // returns true
$(x).find(".abc"); // Returns empty array
Why is it that the first line returns true, but the selector cannot find the element?
Thanks!
Because $x is the div with class abc.
jquery .find() tries to find any children within the div.abc with class abc which it won't find.
This is more like it.
var x = "<div class='abc'><div class='def'></div></div>";
$(x).hasClass("abc"); // returns true
$(x).find(".def"); // returns $('div.def')
When we append html element to the page, sometimes JQuery can't find this element due to parent and child relationship.
For example: a button having class submit inside a div having id append_area and we want to run a function on click on this button. Then we can use the below code.
HTML Code:
<div id="append_area">
</div>
Jquery Code:
$("#results").delegate('.submit', 'click', function(){ });

Show tooltip text according to an element's class

I have some words wrapped inside span element with class "tooltipX", where "X" is a number. The number grows with an array "Data" which holds description for the tooltip. How can I show the description for the right element? I hope for something like the code below, but I don't know how to loop it.
$( document ).tooltip({
items: ".tooltip"+X+"",
content: Data[X].desc
});
JSFiddle
Instead of using specific classes, you could broaden the class and select them all. In addition, use a data-* attribute to store the index of the Data to use for the tooltip. So, change your HTML to follow this:
<span class="tooltip" data-tooltip-index="0">
(obviously changing the data-tooltip-index value per span)
Also, instead of passing a string to content, you can pass a function, and have it dynamically return the specific item from Data that you want. This function will execute every time the tooltip needs to be shown and uses the returned value as its contents. In this function, you would get the element's data-tooltip-index value (using this), and get the corresponding array value from Data. So, change your JavaScript to this:
$(document).tooltip({
items: ".tooltip",
content: function () {
var index = $(this).attr("data-tooltip-index");
return Data[index].desc;
}
});
DEMO
References:
Tooltip content option
data-* attributes
jQuery.attr

Variable with HTML content parsing

I have this variable called $reservas that contains a string with HTML Tables. I want to remove parts of the tables (.tdRemove), BEFORE I assign them to the div #cenas.
if ($reservas){
$($reservas).find('.tdRemove').each(function(){
console.log($(this).html());
$(this).remove();
});
$("#cenas").html($reservas);
}
I tried this, but it doesn't seem to remove anything.
I've also tried:
$($reservas).find('.tdRemove').remove(); and $($reservas).remove('.tdRemove');
Nothing works. Any suggestions?
Is there any way to tell jQuery that the variable holds html content, and should be parsed as that? If so, how? ..
After converting your string to a jQuery object, it is now a series of DOM objects (in a document fragment) held in the jQuery object. After removing the .tdRemove objects in that fragment, you can then just append that directly to your DOM. No need to go back to HTML:
if ($reservas){
var item = $($reservas);
item.find('.tdRemove').remove();
$("#cenas").empty().append(item);
}
Also, your code didn't work because the $reservas string of HTML was never modified.
I think, from what the documentation tells me, you can only remove() what is already inside the DOM.
Remove the set of matched elements from the DOM.
Maybe you want to add your table first, set it to ? display: none`, then filter for elements to remove and finally display the table.
if ($reservas) {
$("#cenas")
.hide()
.html($reservas)
.find('.tdRemove').each(function(){
console.log($(this).html());
$(this).remove();
})
.show();
}

Why are jQuery set attributes not reflected in .html()?

I am trying to set some attributes on HTML snippets. The purpose is to repopulate a form with previous inputed values. I set attributes with .attr() but after I do a .html(), I do not see my changed attributes.
I have done a basic example here http://jsfiddle.net/ejanderson4/CSYnU/
My function looks like this:
function setValue(html,value,name){
var element=$(html);
$(element).find("[name='"+name+"']").attr('value',value)
return element.html();
}
It is setting it, but for reasons unknown to me, you can't directly query the value attribute of an input element. You need to call .val() on that element to get it.
Updated your example here
parse the html string using $.parseXML and then set the attr value
var html="<div><label id='el_c5c0f78656138c39c5eb91a9bf1d3bf6'> table input 1 </label><input type='text' value='' name='table_input_1' class='select-mini' id='table_input_1' /></div>";
var value= 'xxxxxxxxxxxxx';
var name='table_input_1';
function setValue(html,value,name){
var xml = html,
xmlDoc = $.parseXML( xml ),
$xml = $( xmlDoc ),
$title = $xml.find( "[name='"+name+"']" );
$title.attr("value",value);
//var element=$(html);
//element.find("[name='"+name+"']").attr('value',value)
return $title.attr("value");
}
alert(setValue(html,value,name));
here is the working fiddle http://jsfiddle.net/CSYnU/4/
also this solution requires you to use jquery version 1.5.2 and higher
update
sry for overdoing it in your scenario you have to do
function setValue(html,value,name){
var element=$(html);
$(element).find("[name='"+name+"']").attr('value',value);
return $(element).find("[name='"+name+"']").attr('value');
}
here is the fiddle http://jsfiddle.net/CSYnU/5/
you are wrapping the html in $(html) then there is no need to again wrap the cached html in $
var element = $(html);
element.find ...
see here http://jsfiddle.net/CSYnU/6/
I think the short answer here is that setting an attribute on a DOM object does not necessarily change what the browser returns for innerHTML. If you want to retrieve a particular attribute, then you should just retrieve that attribute directly.
You also have an error in your code (which jQuery might be tolerating). You've already turned element into a jQuery object so you don't need to do that again with $(element).find, you can just use element.find.
function setValue(html,value,name){
var element=$(html);
element.find("[name='"+name+"']").attr('value',value)
return element.html();
}
Depend on your code, the first problem is about element variable. It doesn't denote "table_input_1" element. To get this element, you should replace by :
var element=$(html).find("[name='"+name+"']");
The second problem is in the your return statement. Since you changed the value of input element, you have to get this value by method val() or attr('value') rather than html(). The html() method is used to get the content inside tags of a element, but in this case value is a attribute, not content.
return element.attr('value'); // element.val();
Here is the complete code:
function setValue(html,value,name){
var element=$(html).find("[name='"+name+"']");
element.attr('value',value); // element.val(value);
return element.attr('value'); // element.val();
}
One reason is that the jQuery attr method gets confused between HTML attributes and DOM properties. The imlpementation of setAttribute and getAttribute was (probably still is) buggy in IE, so in general forget about HTML attributes and use DOM properties.
In most browsers, modifying the HTML attribute (say using setAttribute) will modify the related DOM property. But in many browsers, changing the DOM property will not modify the HTML attribute.
Further, some browsers will modify an element's innerHTML based on the current DOM property, others will use the HTML attribute (which might have a different value in most browsers). HTML 5 is the first attempt to standardise the behaviour of innerHTML, note that it is not a W3C standard yet and is not consistently implemented.
The best approach is to be consistent and always set DOM properties to the values you want. Expect that an element's innerHTML may be inconsistent across browsers.
Setting the current value of an input element doesn't change the initial value, which is what the value attribute is.
There is no property to change the initial value, so you can't alter the HTML code that way.
Edit:
If you want to use the elements in the page, then just make the function return a jQuery object containing the elements instead of returning HTML code:
function setValue(html, value, name){
var elements = $(html);
elements.find("[name='"+name+"']").val(value)
return elements;
}
Adding the elements to the page works the same as using a string. Example:
var html = '<div><input type="text" name="city" /></div>';
$('#SomeForm').append(setValue(html, 'York', 'city'));

Categories