infinite scroll loading dom elements, then applying jquery to the elements? - javascript

I have a script called showContents.js with the following.
jQuery(function() {
//hide element
jQuery(".targetDiv").css("display", "none");
// Hook the button click
jQuery(".showEpisodes").click(function(e) {
// To prevent reloading of page
e.preventDefault();
//toggle and hide all other div tags
jQuery('#'+$(this).attr('target')).slideToggle('fast', function(){
jQuery('.targetDiv').not($(this)).slideUp();
});
});
});
This will on element click with the class of 'showEpisodes' show the corresponding div and hide all others.
I have a JavaScript file that generates articles with info from a JSON file and expands a div if clicked on.
This works fine, but scaling this process takes a while to load all elements immediately. So I wanted to load rows of articles on scroll.
window.onscroll = function(ev) {
if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight) {
i += 3;
parseMovieRow(Json, i);
}
};
They come in rows of 3. As soon as I do this, the script showContents.js is not applied to the generated articles.
How do I dynamically apply jQuery functions to items generated in JavaScript?

You can bind the click event to nearest static ancestor. document will work in this case, albeit it will not be very efficient.
jQuery(document).on("click", ".showEpisodes", function(e){
//...
});

Before appending the elements to the document. You should make them into jQuery objects and then bind your events to them.
var myHtml = "<div>foo</div>";
var el = $(myHtml);
el.on("click", your_callback);
$("#my_container").append(el);
Edit: the accepted answer will scan all the elements (that are in the click event) and their parents every time there is a click on the page in order to see if it matches your .showEpisodes which is slow and as he mentioned inefficient. It works, but you should not use it when possible.

Related

onClick function used on dynamic content not working properly

I hit a problem with the onclick function when i add divs with ids like "n_block"+(1-~). When I use the jquery zoom function on the objects to make them smaller or bigger onClick doesn't work anymore. I'm not really good at programming so the code might be kind of confusing.
Heres the code i use for the onClick of items:
$(document).on("click",function (e, ui){
//When the document gets clicked, check if one of the items was clicked.
if($(e.target).is($("#n_block" + cloneCount1)) || $(e.target).is($("#n_block" + cloneCount1+ " span"))){
//Set current item.
var item = $("#n_block" + cloneCount1);
//Set style to current item.
item.css("border-color", "Black");
item.css("border-width","2px");
item.css("background-color", "floralwhite");
jsPlumb.repaintEverything();
//Check if key Delete was pressed while item selected & delete that item with his children.
$('html').keydown(function(e){
if(item.css("border-width")=="2px"){
if(e.keyCode == 46) {
/* Prevents line bugging*/
jsPlumb.detachEveryConnection();
jsPlumb.deleteEveryEndpoint();
var razred = getClass(item, "b_"),
id = item.prop("id");
item.remove();
if(razred == "b_2"){
$(".ovoj."+id).remove();
}
else if (razred == "b_4"){
$(".ovojLoop."+id).remove();
$(".empty_block_c."+id).remove();
}
if ( $('.objects').find('div').length == 2) {
$(".objects").empty();
$(".objects").append('<div class="b_s" id="start_block">START</div><p id="start_text">Insert symbols here!</p><div class="b_s" id="end_block">STOP</div> ');
}else{
/* Connects objects together with line. ****/
povezi(cloneCount, tip_crte, ".objects");
}
}
jsPlumb.repaintEverything();
}
});
}
// If item is not clicked set this css to the current item.
else{
$("#n_block" + cloneCount1).css("border-width","1px");
jsPlumb.repaintEverything();
}
});
And heres the zoom code for zooming in when button is clicked:
var currentZoom = 1.0;
$(".zoomin").click(function (){
//Detaches the connections from item to item.
jsPlumb.detachEveryConnection();
jsPlumb.deleteEveryEndpoint();
//Prevents spamming of button, animates the objects
$(".project").stop().animate({ "zoom": currentZoom += .1}, "slow", function() {
if(!$(".objects").children().is($("p"))){
povezi(cloneCount, tip_crte, ".objects");
}
});
});
Use event delegation for binding events to dynamically added elements.
$(document).on('click', ".zoomin", function (){
//Your code.
});
When you use normal .click() to bind event to an element, then that even gets bound to only those elements which exist in the DOM at the moment of the execution of code. Using event delegation, you can tell jQuery that we need to add the handler to every '.zoomin' element which comes inside a particular element no matter when it is added.
The solution depends when exactly is the script which tries to bind the events are executed.
For Eg: Lets assume this script is in document ready function of jquery
$(document).ready(function(){
$(".zoomin").click(function (){
//your logic here
});
});
Here this script is executed when the page HTML is completed loading into the browser. Now when the script executes it tries to find a element with the class zoomin and if found it will add a event to that element and move on. If the element is not found the script just moves on. So we should actually take care of when the script is executed and is the intended element available at that particular instant of time. If the element is not yet available in the HTML (element might come in later dynamically using jquery) we have 2 options to bind event to the element.
1) Execute the script when the element is being added into the HTML: Lets say I have a event which brings up a pop up with some image. Now I want to zoomin and zoomout the image. Since the image in the popup is added dynamically and I have control of when its being added, I can do this.
$(document).ready(function(){
$('.ViewImage').on('click',function(){
// some code is executed which brings up the popup
// now we know that the image is added into html we can now run the script
$(".zoomin").click(function (){
//your logic here
});
});
});
2) We have no Clue/ Control when the element is added into HTML but still want to bind a event to it: This is scenario where we have no control on when the element is being added or not sure where it is being added from (might be from some external plugin used etc) or not having control at all on the element which is added. Thats when we use this syntax as suggested by #Rejith R Krishnan
$(document).on('click', ".zoomin", function (){
//Your code.
});
This will work on all the elements which are in the HTML at the time of execution of the script and on the elements which will be added in the future with the class name zoomin. So this script can be placed inside/ outside of jquery document ready event

L.DomEvent.addListener() vs on(): why does one NOT work?

I created the following jquery script to cycle through each div in my HTML using a for loop. In this for loop, I define the the div and add a listener to it:
for (var i = 0; i < 3; i++) {
// Define listing
var listing = $('div[data-rid="' + i + '"]');
// Add listener to each listing div
// See below...
}
I have tried two different ways to add a listener. The first uses L.DomEvent.addListener() as such:
L.DomEvent.addListener(listing, 'mouseover', function(e) {
// Do stuff to listing div
}
The second uses the action mouseover():
listing.mouseover(function(e) {
// Do stuff to listing div
}
The L.DomEvent.addListener approach does not work. The mouseover approach works (i.e., it triggers for each div mouseover), but the "Do stuff to listing div" code only happens to the last listing div in the for loop. For example, I might mouseover div #1, but it "does stuff" div #3.
Does anyone have an idea how I might fix this issue?
Thanks!
Jesse
Try
L.DomEvent.addListener(listing[0], 'mouseover', function(e) {
// Do stuff to listing div
}
The case is, that the element jquery returns, is an array of the elements it found. listing[0] gets the first element in said array.

JQuery/ Jquery Mobile - best way to remove instance of class from div by toggling

I'm using JQuery mobile framework here, so i've got two 'pages' which in reality both exist in one HTML document. You can navigate between the two via the hamburger menu icon on the top left.
There is an events page. each events has an 'add to favourites' button. when clicked the event populates the favourites page. I'm doing this by cloning the div class.
var add = $('.add-to-fav');
add.on('click', function(){
//change button status
if ($(this).text() == "Add to favourites")
{
$(this).text("Remove from favourites");
$(this).closest(".event-block").clone().appendTo('#fav-list');
} else {
$(this).text("Add to favourites");
//get this instance of event block and remove from #fav-list
}
});
My issue comes with trying to remove (or unfavourite) the event by clicking again on the same button. I want this to be achievable from both the events page and the favourites page.
What's the most elegant way to achieve this?
here's a codepen - i've tried to remove as much unrelated code as possible
http://codepen.io/MartinBort/pen/EajBXB/
First of all, you are using the same panel for both pages with same ID. Either use an external panel or give each one a unique ID. If you plan to use an external panel, place it outside any page and initialize it manually.
$(function () {
$("#menu-panel").panel().enhanceWithin();
});
To add listeners, use pagecreate it fires once per page. This way, you can assign different functions for buttons based on containing page. Use event.target to target buttons .add-fav within created page not other ones in DOM.
You can remove "Event" from favourites page from public-events page by retrieving its' header's text since you aren't using IDs' or classes to differentiate between events.
$(document).on("pagecreate", "#public-events", function (event) {
$('.add-to-fav', event.target).on('click', function () {
if ($(this).text() == "Add to favourites") {
$(this).text("Remove from favourites");
$(this).closest(".event-block").clone().appendTo('#fav-list');
} else {
$(this).text("Add to favourites");
/* retrieve event title */
var eventTitle = $(this).closest(".event-block").find("h2").text();
/* loops through event blocks in favourite page */
$('#favourites #fav-list .event-block h2').each(function () {
if ($(this).text() == eventTitle) {
/* remove matching event */
$(this).closest(".event-block").remove();
}
});
}
});
}).on("pagecreate", "#favourites", function (event) {
$('.add-to-fav', event.target).on('click', function () {
$(this).closest(".event-block").remove();
});
});
Demo

jQuery: mouseover makes image visible that has the same last 4 numbers in their id as the trigger

I am currently working on a website and got stuck with the following problem:
On the website I have small dots (images) with the ids "dot0001", "dot0002", "dot0003", etc. . I also have hidden images (visibility:hidden) with the ids "info0001", "info00002", "info0003", etc.
I am looking for a jQuery solution. What I need is a code that allows the following events:
When users move the mouse over "dot0001" the image "info0001" becomes visible and when they leave "dot0001", "info0001" becomes invisible again. Same applies to "dot0002"-"info0002" , "dot0003"-"info0003" etc. So only the info-images with the corresponding 4 digit number become visible.
I gave it endless tries but got nowhere and there is not even a point in pasting my code.
Any help appreciated!
Something like this should work (though untested):
$('[id^="dot"]').on({
mouseenter: function(e) {
var infoId = this.id.replace('dot', 'info');
$('#' + infoId).show();
},
mouseleave: function(e) {
var infoId = this.id.replace('dot', 'info');
$('#' + infoId).hide();
}
});
That uses an attribute-starts-with selector to select all elements with an id beginning with "dot", then binds the event handlers to them. The event handler functions themselves simply replace the "dot" part of the id with "info" to form the correct new one, then show or hide the element as appropriate.
Don't forget to wrap that code in a DOM ready event handler so that it executes once the elements actually exist, otherwise it won't work.
Get all elements which id starts with "dot" and show/hide related "info" on mouseover/out:
$("[id^=dot]").hover(
function(){
$("#info" + this.id.substring(3)).css({"visibility":"visible"});
},
function(){
$("#info" + this.id.substring(3)).css({"visibility":"hidden"});
}
);
http://jsfiddle.net/EGBnR/

using preventDefault() with on() in jQuery AJAX tabs

I have a set of jQuery UI AJAX tabs that load individual .php pages when they are clicked. All of my styling, etc. conveys, because the pages that hold the tabs widget provide the already linked CSS, and scripts. When it comes to the actual pages that load when clicking on the tabs however, I can't seen to get preventDefault() to work with .on() on these newly created DOM elements.
I'm using jQuery BBQ with my tabs so I can't have "#"s being appended to the URL. This is caused when links within the tab panels are clicked.
I've been able to successfully use preventDefault() on DOM elements that are initially loaded, but not ones that are being fetched into the tabs widget via AJAX.
My function for a content toggler is...
$(function(){
$(".showMoreOrLess").on('click', (function() {
if (this.className.indexOf('clicked') != -1 ) {
$(this).removeClass('clicked');
$(this).prev().slideUp(500);
$(this).html("Read More" + "<span class='moreUiIcon'></span>");
}
else {
$(this).addClass('clicked');
$(this).prev().slideDown(500);
$(this).html("See Less" + "<span class='lessUiIcon'></span>");
}
}));
});
I'd like to combine the preventDefault() from this function into it.
// prevents default link behavior on BBQ history stated tab panels with "showMoreOrLess" links
$(".showMoreOrLess").click(function (event)
{
event.preventDefault();
//here you can also do all sort of things
});
// /prevents default behavior on "showMoreOrLess" links
I've tried several ways using .on("click", function(work)), etc. I've used .on() in a separate function and also tried to combine it in the first function above. Does anyone know what I'm doing wrong? The code works on tab content that is static, just not content loaded via AJAX. Any help would be greatly appreciated. Can't seem to figure this out. Thanks in advance.
the part $(".showMoreOrLess").click just applies to already accessable links on your page
try to use event delegation (here the clicks are captured on an every time existing element and you just pass the selector it is watching for... as a nice side effect you save listeners
$(document).on("click", ".showMoreOrLess", function(event) {
event.preventDefault();
//here you can also do all sort of things
});
rather than document use a certain id from your page $("#myContainerId") (EDIT: of course the elements you are clicking on need to be inside of the element with the id)
$("body").on('click', ".showMoreOrLess", function(event) {
event.preventDefault();
var self = $(this);
if (self.hasClass('clicked')) {
self.html("Read More" + "<span class='moreUiIcon'></span>").removeClass('clicked').prev().slideUp(500);
}else {
self.html("See Less" + "<span class='lessUiIcon'></span>").addClass('clicked').prev().slideDown(500);
}
});

Categories

Resources