Here I have a problem:
I created one div and passed some data into it:
var div = $("<div />");
$.data(div, "a", 1);
div.on("click", function(event) {
console.log($.data(event.target, "a")); // print undefined
});
It looks like I could not retrieve data bound with an UI element this way. I would like to know why and whether there is any alternative for this - get a piece of data associated with an UI element within an event.
Thanks!
Try this ;-)
var div = $("<div>clic</div>").appendTo('body');
div.data("a", 1);
div.on("click", function() {
console.log($(this).data("a"));
});
JsFiddle : http://jsfiddle.net/t3n8y2xz/
Related
So I have a list of items with anchor a that successfully listen to the following event:
$('body[data-link="media"] #media_content a').on('click',function(e){
e.preventDefault();
var page = $('.page.active a')[0].innerHTML;
var date = $('.year_sorting .filter_years').val();
var id = $(e.currentTarget).data('media');
window.location.href = 'http://'+basePath+'media/content/'+id+'?date='+date+'&page='+page;
})
However in the same page, there is a filter allowing the user to change the year filter and once changed, the following execute and append a list of items that has the exact same layout as the a above $('body[data-link="media"] #media_content a'), which supposes to listen to the above event as well. the filter event is below:
$('.activity.filter_years').on('change',function(){
$('.pagination_ul').remove();
r_year = $(this).val();
$.get("media/getActivity",{type:'0',key:r_year}).done(function(d){
if(d.length>0){
$('#media_content').html('');
var ul = '<ul class="ap pagination-sm pagination_ul"></ul>';
$('.pagination_menu').append(ul);
for(var i=0;i<d.length;i++){
var p = ['',''];
if(!d[i].event_period){
p = ['style="color:#8A8A8A;"','style="color:#C7C7C7;"'];
}
if(locale=='en'){
var event = $('<div class="div_media_content_f2 '+d[i].pagination+' pagination-tr"> <div class="div_media_content_f2_3"> <span class="font12_bold">'+d[i].event_date+'</span> <div>'+d[i].event_title+'</div></div></div>')
}else if(locale=='hk'){
var event = $('<div class="div_media_content_f2 '+d[i].pagination+' pagination-tr"> <div class="div_media_content_f2_3"> <span class="font12_bold">'+d[i].event_date+'</span> <div>'+d[i].event_title_zh+'</div></div></div>')
}else {
var event = $('<div class="div_media_content_f2 '+d[i].pagination+' pagination-tr"> <div class="div_media_content_f2_3"> <span class="font12_bold">'+d[i].event_date+'</span> <div>'+d[i].event_title_cn+'</div></div></div>')
}
$('#media_content').append(event);
}
pagination('.pagination_ul','.pagination-tr',Math.ceil(d.length/20),false);
}else{
$('#div_news_content_right').html('').append('<div class="not_available">No content available</div>');
}
})
})
in which you can see the list of items are being appended into the layout by JS. However, even with the same layout $('body[data-link="media"] #media_content a'), such appended list of items do not listen to the onclick event. the above js codes are together in a separate js file apart from the html file where I tried to put the first a event into the html file but the new appended list of items still do not listen.
Cannot think of other work around at the moment, please help to see what would be the cause of it. Thank you.
Maybe simple try this.
$(document).on('click', 'body[data-link="media"] #media_content a')
If your element is dynamic create you should bind the click event on document and target what's element should dispatch the event.This is different to bind click only on element because the event will unbind while you remove the element.
Updated:
I'm not sure I've understand all the script you have but I try to simplify the issue.
This is the jsbin and its work correctly.
JSBin
var = cooldynamicelement
How could I store the inner html I grab with jQuery from my div ie. <div class="username"> </div> to store as an accessible variable in jQuery eg. cooldynamicelement so I can grab and use at different areas of my site by just calling ie. $cooldynamicelement and updates with the dynamic .username element value.
1. Store HTML into localStorage
var dynamicElementHTML = localstorage.dynamicElementHTML || $(".username").html() || "";
localstorage["dynamicElementHTML"] = dynamicElementHTML;
To make it available to other pages a way would be to use the power of localstorage
https://developer.mozilla.org/en/docs/Web/API/Window/localStorage
If you're actually interested in the whole element (not only it's inner HTML) than instead of .html() use .prop("outerHTML")
2. Binding using jQuery (essential idea)
If you only want a way to reflect some variable HTML as actual html and make it alive you could do like:
var $myElement = $("<div />", {
class : "userData",
append : $someDynamicElements,
appendTo : $someParentElement,
on : {
contentUpdate : function() {
$(this).html( $someDynamicElements );
}
}
});
than whenever your $someDynamicElements changes you can trigger a contentUpdate
$myElement.trigger("contentUpdate")
3. Binding using jQuery (concept)
Here's the same elements binding concept gone wild:
// Here we will store our elements
var EL = {};
// Create desired HTML elements like this:
var LIST = {
username: $("<b/>", {
html : "UNKNOWN",
click : function() {
alert( $(this).text() );
}
}),
email: $("<a/>", {
html : "test#test.test",
href : "mailto:"+ "test#test.test"
}),
// add more here, you got the idea.
// don't forget that you can assign any JS / jQuery propery to your element.
// You can go insane using .on() and later .trigger()
};
// Our small "program" that replaces data-bind elements
// with dynamic elements from our list
$("[data-bind]").replaceWith(function(i){
var bind = this.dataset.bind;
if(!LIST[bind]) return;
if(!EL.hasOwnProperty(bind)) EL[bind] = [];
var klon = LIST[bind].clone(true)[0];
EL[bind].push(klon);
return klon;
});
// That's it. Now goes your code ///////////////
$(EL.username).css({color:"red"}); // just to test if it works :D
$("[data-target]").on("input", function(){
var target = this.dataset.target;
$(EL[target]).html( this.value );
});
// P.S: Even having thousands of elements inside EL
// say you have "EL.tableRows" you can do fabulously
// quick stuff like i.e: sorting, cause you iterate over a plain JS array.
// After the sorting of EL.tableRows is done and you need a jQuery
// representation simply use $(EL.tableRows).
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h2>Dynamic element Binding in jQuery</h2>
Enter some text and see the update trigger in different places<br>
<input data-target="username"><br>
Welcome <span data-bind="username"></span> !!<br>
You name is <span data-bind="username"></span> Click the red text!<br>
<span data-bind="email"></span>
Well if you want to have the jqueryObject in a variable, just do this:
$(function(){
window.$cooldynamicelement = $("div.username");
})
that way you're able to use $cooldynamicelement in a global context. If is that what you want. This way you're saving a reference to your .username element and thus every time you use it will be updated.
NOTE: If you decide to do this, be careful with polluting your global context.:
I know if I wanted to bind events to generated HTML, I'd need to use something like .on(), but I've only used it when binding events like .click().
I'm creating a web app that applys a list of colors. Colors are generated from a JSON file. Once fetched, I add it to the page, with certain information contained in attributes. I'd like to do something with the new generated HTML, which is list-elements. But what console.log() is showing me is there is nothing in the parent ul. Even though on the page I see the newly added content.
Here's the entire code based around it.
var setColors = function(){
getColors = function(){
$.getJSON('js/colors.json', function(colors) {
$.each(colors, function(i, colors) {
//console.log(colors);
$('<li>', {
text: colors['color'],
'name' : colors['color'],
'data-hex' : colors['hex'],
'data-var' : colors['var']
}).appendTo('#picker');
})
});
addColors();
}
addColors = function(){
var el = $('#picker').children;
$(el).each(function(){
console.log($(this));
});
}
return getColors();
}
$(function(){
setColors();
});
addColors() is where I'm having trouble with. The error says 'Uncaught TypeError: Cannot read property 'firstChild' of null. How can I work with the newly generated HTML?
You are missing parentheses on the children method:
var el = $('#picker').children();
Also, if you want the addColor method to be executed on the newly generated html, then you must add a call to it after the html is generated, from within the getJSON callback method.
addColors = function(){
var el = $('#picker').children;
$(el).each(function(){
console.log($(this));
});
}
A few issues:
missing end semi-color
missing parentheses on .children()
children() returns a jQuery object, no need for $(el)
Updated:
window.addColors = function(){
var $el = $('#picker').children();
$el.each(function(){
// do stuff here, but could attach each() to above, after children()
});
};
I am using Select2 which works great. However I am using below code to create new dynamic select2 drop down but they do not react/open when clicking on them.
var relationshipcounter = 0;
$('#AddMoreRelationships').click(function () {
var $relationship = $('.relationship'); // div containing select2 dropdown
var $clone = $relationship.eq(0).clone();
$clone[0].id = 'id_' + ++relationshipcounter;
$relationship.eq(-1).after($clone);
$relationship.find('select').trigger('change'); // not working
});
Screenshot:
JSFIDDLE:
http://jsfiddle.net/pHSdP/133/
I had this exact problem and, of course, the first thing I tried was a deep copy with data:
el.clone(true,true);
Which did not work. Instead the best method I found was:
el=other_el.clone()_etc; // cloning the old row
el.find('.select2-container').remove();
el.find('select').select2({width: 268});
el in both of these snippets is the div row that contains the select and so the Select2 element.
Essentially what I do in the second snippet is remove the "old" select2 which will always have the class of .select2-container and then recreate it on all found select elements within my new row.
You need to call clone with the true argument to copy over events and data as well. Otherwise only the element gets cloned, not the events that are bound to it.
$relationship.eq(0).clone(true);
Docs:http://api.jquery.com/clone/
Ok so issue is resolved, fiddle:
http://jsfiddle.net/WrSxV/1/
// add another select2
var counter = 0;
$('#addmore').click(function(){
var $relationship = $('.relationship');
var $clone = $("#RelationshipType").clone();
$clone[0].id = 'id_' + ++counter;
$clone.show();
$relationship.eq(-1).after($clone);
$clone.select2({ "width" : "200px" });// convert normal select to select2
//$('body').select2().on('change', 'select', function(){
// alert(this.id);
//}).trigger('change');
return false;
});
After cloning your object you have to reassign event for em:
var $clone = $relationship.eq(0).clone();
$clone.on("click", function_name);
Use .on to bind dynamically inserted elements to events like
$('body').on('click','#AddMoreRelationships',function () {
});
I asked this question regarding changing the position of a bootstrap popover depending on the size of the screen.
The answer was great - however I also now want to change the action for popovers (so it's on click for mobile) as well as the location, and am having difficulty re-factoring the code. This is what I have:
$(document).ready(function(){
$('#my_list li').popover({
placement: wheretoplace
});
});
function wheretoplace(){
var width = window.innerWidth;
if (width<500) return 'below';
return 'left';
}
How would I amend the wheretoplace function to return two things: the placement value along with a trigger value? I've got the existing stuff in a jsFiddle.
Edit - I've amended my jsFiddle above to show the complete solution, adding a click event to #James' answer below.
If you are trying to return two values from the function, try assigning them as properties of an object and then return that object.
eg.
function wheretoplace(){
var data = {};
var width = window.innerWidth;
if (width<500)
{
data.placement = 'below';
}
else
{
data.placement = 'left';
}
data.trigger = "myEvent";
return data;
}
Then in the function calling wheretoplace:
$(document).ready(function(){
$('#my_list li').popover({
placement: wheretoplace().placement,
trigger: wheretoplace().trigger
});
});
Is this what you are trying to do?
EDIT: In Response to the comment below:
As with the jsFiddle demo
By assigning the trigger as "manual" on document ready, you are then able to call $(element).popover("toggle") in a click handler which will toggle the appearance of the popover.