I'm trying to create a more generic local-storage setup for my application so I don't have to create a function for each time I add a new element to the page that I want to store in local storage. I have my jquery setup like so.
/* SET LOCAL STORAGE */
$( document ).on( "keyup",".localStorage",function(){
var id = $(this).attr('id');
if(id) {
id = "#" + id;
localStorage.setItem(id, $(this).val());
}
});
The part that seems to be having some difficulty, is when the page is loaded, looping through each ".localStorage" element and applying the proper data (somewhat like saving as a draft).
I can't seem to use jQuery's $each() function, as that doesn't work with elements loaded through $ajax().
So what's the best way to find elements on a page even if they are loaded dynamically? Any help is greatly appreciated. Thanks!
You CAN in fact access elements added dynamically to the page. I would just try something like this in your event code:
var elements = $('.localstorage');
for (var i in elements) {
doStuf(elements[i]);
}
Related
I'm fairly new to Javascript, and am trying to get an 'on click enlarge' kind of effect, where clicking on the enlarged image reduces it again. The enlarging happens by replacing the thumbnail by the original image. I also want to get a slideshow using images from my database later on.
In order to do that, I made a test where I replace the id which indicates enlarging is possible by a class and I also use a global variable so that I can keep a track of the url I'm using. Not sure this is the best practice but I haven't found a better solution.
The first part works fine, my image gets changed no problem, values are also updated according to the 'alert' statement. However, the second part, the one with the class never triggers.
What am I doing wrong (apart from the very likely numerous bad practices) ?
If instead of changing the class I change the id directly (replacing .image_enlarged by #image_enlarged, etc.), it seems to call the first function, the one with the id, yet outputs the updated id, which is rather confusing.
var old_url = "";
$(function(){
$('#imageid').on('click', function ()
{
if($(this).attr('class')!='image_enlarged'){
old_url = $(this).attr('src');
var new_url = removeURLPart($(this).attr('src'));
$(this).attr('src',new_url); //image does enlarge
$(this).attr('class',"image_enlarged");
$(this).attr('id',"");
alert($(this).attr('class')); //returns updated class
}
});
$('.image_enlarged').on('click', function (){
alert(1); //never triggered
$(this).attr('src',old_url);
$(this).attr('class',"");
$(this).attr('id',"imageid");
});
});
function removeURLPart(e){
var tmp = e;
var tmp1 = tmp.replace('thumbnails/thumbnails_small/','');
var tmp2 = tmp1.replace('thumbnails/thumbnails_medium/','');
var tmp3 = tmp2.replace('thumbnails/thumbnails_large/','');
return tmp3;
}
As for the html, it's really simple :
<figure>
<img src = "http://localhost/Project/test/thumbnails/thumbnails_small/image.jpg" id="imageid" />
<figcaption>Test + Price thing</figcaption>
</figure>
<script>
document.write('<script src="js/jquery-1.11.1.min.js"><\/script>');
</script>
<script type="text/javascript" src="http://localhost/Project/js/onclickenlarge.js"></script>
From the API: http://api.jquery.com/on/
The .on() method attaches event handlers to the currently selected
set of elements in the jQuery object.
When you do $('.image_enlarged').on(...) there is no element with that class. Therefore, the function is not registered in any element.
If you want to do so, then you have to register the event after changing the class.
Here's an example based on your code: http://jsfiddle.net/8401mLf4/
But this registers the event multiple times (every time you click) and it would be wrong. So I would do something like:
$('#imageid').on('click', function () {
if (!$(this).hasClass('image_enlarged')) {
/* enlarge */
} else {
/* restore */
}
}
JSfiddle: http://jsfiddle.net/8401mLf4/2/
Try using:
addClass('image-enlarged')
instead of:
.attr('class',"image_enlarged");
the best way to do this would be to have a small-image class and a large image class that would contain the desired css for both and then use addClass() and removeClass depending on which you wanted to show.
So I'm trying to use ajax to put content into a div, and trying to have it change all internal links before it adds the content so that they will use the funciton and load with ajax instead of navigating to another page. My function is supposed to get the data with ajax, change the href and onclick attributes of the link, then put it into the div... However, all it's doing is changing the href and not adding an onclick attribute at all. Here's what I was using so far:
function loadHTML(url, destination) {
$.get(url, function(data){
html = $(data);
$('a', html).each(function(){
if ( $.isUrlInternal( this.href )){
this.onclick = loadHTML(this.href,"forum_frame"); // I've tried using both a string and just putting the function here, neither seem to work.
this.href = "javascript:void(0)";
}
});
$(destination).html(html);
});
};
Also, I'm using jquery-urlinternal. Just thought that was relevant.
You can get the effect you want with less effort by doing this on your destination element ahead of time:
$(destination).on("click", "A", function(e) {
if ($.isUrlInternal(this.href)) {
e.preventDefault();
loadHTML(this.href, "forum_frame");
}
});
Now any <a> that ends up inside the destination container will be handled automatically, even content added in the future by DOM manipulations.
When setting a function to onclick through js it will not show on the markup as an attribute. However in this case it is not working because the function is not being set correctly. Easy approach to make it work,
....
var theHref=this.href;
this.onclick = function(){loadHTML(theHref,"forum_frame");}
....
simple demo http://jsbin.com/culoviro/1/edit
I am creating a table run time in the memory and later appending it to dom.
Something like this :
var myTable = $('<table></table>').attr({ id: "dataMatrixtable" }).attr({class: "tipTable",cellpadding: "5",cellspacing: "0"});
myTable.appendTo(this.top.$("#tableContainer"));
This.top because table is in a iframe.
Now I wrote a plugin something like this.
(function($){
$.fn.extend({
mailServer : function() {
this.addClass("blah");
},
})
})(jQuery)
when i am calling this function mailServer after appending the table to dom
$("#dataMatrixtable").mailServer();
or
this.top.$("#dataMatrixtable").mailServer();
either way its not working (not appending the class)
Where as it works for the elements which is already in the dom when page loads..
How to solve this issue.please help
Actually I found a way its working now ..
What I did is
myTable.mailServer(); (its working and I am able to access the plugin funciton mailServer()
In place of doing
$("#dataMatrixtable").mailServer();
I'm using jquery data() to attach the name of a div I'd like to show when another div (.panel_button) is clicked. I'm doing the attaching of this div's id to the button when the document is ready. Is this an okay way to do this? Or is it too resource intensive and unprofessional-looking?
$(document).ready(function(){
$('#sample_button').data('panel', 'sample_kit_container');
$('#mail_button').data('panel', 'mail_container');
$('#mbillboard_button').data('panel', 'mbillboard_container');
$('.panel_button').on('click', function(){
$('.secondary_panel').hide();
var panel = $(this).data('panel');
$('#' + panel).show();
});
});
Yeah, that should work just fine. As an alternate, you could store the actual element itself (assuming it already exists) rather than finding it each time:
$('#sample_button').data('panel', $('#sample_kit_container'));
$('#mail_button').data('panel', $('#mail_container'));
$('#mbillboard_button').data('panel', $('#mbillboard_container'));
$('.panel_button').on('click', function(){
$('.secondary_panel').hide();
var panel = $(this).data('panel');
panel.show();
});
Another option would be to store the actual jQuery element in the data property, so no need to do a second selection:
$(function(){
$('#sample_button').data('panel', $('#sample_kit_container'));
$('#mail_button').data('panel', $('#mail_container'));
$('#mbillboard_button').data('panel', $('#mbillboard_container'));
$('.panel_button').on('click', function(){
$('.secondary_panel').hide();
var panel = $(this).data('panel');
panel.show();
});
});
#thomas, in my opnion, your solution is actually better than those in the other answers.
Including the whole object inside the data attribute may not always work. For example, what if the $('#sample_kit_container') object doesn't exist on load, but rather ofter an ajax load.
...
Only one tiny comment! why don't you call the data object: panelId. It would be more a bit intuitive.
Imagine a normal page calling javscript in head. The trouble is some of the content isnt loaded untill i click on a link. Subsequently when this link loads the content it wont work. This is because i guess the javascript has already been run and therefor doesnt attach itself to those elements called later on. There is only standard html being called.
So for example this is the code which calls my external html.
$.get('content.inc.php', {id:id}, function(data){
$('#feature').children().fadeTo('fast', 0).parent().slideUp('slow', function(){
$(this).html(data).slideDown('slow');
});
});
If the html i was calling for example and H1 tag was already in the page the cufon would work. However because i am loading the content via the above method H1 tags will not be changed with my chosen font.This is only an example. The same will apply for any javascript.
I was wonering whether there is a way around this without calling the the javascript as well the html when its received from the above function
If you want to attach events to elements on the page that are dynamically created take a look at the "live" keyword.
$('H1').live("click", function() { alert('it works!'); });
Hope this is what you were looking for.
Does Cufon.refresh() do what you want?
As you said Cufon was just an example, I'd also suggest a more general:
$.get(url, options, function(html, status) {
var dom = $(html);
// call your function to manipulate the new elements and attach
// event handlers etc:
enhance(dom);
// insert DOM into page and animate:
dom.hide();
$target_element.append(dom); // <-- append/prepend/replace whatever.
dom.show(); // <-- replace with custom animation
});
You can attach event handlers to the data that you get via the get() inside of the callback function. For example
$.get('content.inc.php', {id:id}, function(data){
$('#feature').children().fadeTo('fast', 0).parent().slideUp('slow', function(){
$(this).html(data).find('a').click(function(e) {
// specify an event handler for <a> elements in returned data
}).end().slideDown('slow');
});
});
live() may also be an option for you, depending on what events you want to bind to (since live() uses event delegation, not all events are supported).
Andy try this. It will call the Cufon code after each AJAX request is complete and before the html is actually added to the page.
$.get('content.inc.php', {id:id}, function(data){
$('#feature').children().fadeTo('fast', 0).parent().slideUp('slow', function(){
$(this).html(data);
Cufon.replace('h1');
$(this).slideDown('slow');
});
});
JavaScript is not executed because of a security reason OR beccause jQuery is just setting this element's innerHTML to some text (which is not interpreted as a JavScript) if it's contained. So the security is the beside effect.
How to solve it?
try to find all SCRIPT tags in Your response and execute them as fallows:
var scripts = myelement.getElementsByTagName("SCRIPT");
var i = 0;
for (i = 0; i < scripts.length; i++)
eval(scripts[i].innerHTML);