Bind JQuery event to html created after pageload via jquery - javascript

I am developing a jquery module for add delete edit view etc.
My problem is when page load complete, a list of items populate. After selecting an item this item's subitems loaded via jquery and html built, appended. But on this table event not fired up. Jquery Live is no longer available. Instead "On" is not working.
I tried :
$(document).on('click', selector , function () { foo(); });
But when a button is clicked it triggers other buttons as well.
My code is below.
I have a working code except links on table which loaded by jquery.
var myModule = {
el: {
listbutton: $('#list-button'),
listcontainer: $('#list'),
detailbutton: $(".item-detail"),
deletebutton: $(".item-delete"),
editbutton: $(".item-edit")
},
init: function() {
...
myModule.el.listbutton.on("click",myModule.getMainData);
},
getMainData: function() {
...
success: function(data) {
myModule.BuildTable(data.Value.DataList);
}
...
},
BuildTable: function (hws) {
var c = "";
c += "<table>";
$.each(hws, function() {
c +=
'<tr>' +
'<td>' + this.Title + '</td>' +
'<td></td>' +
'<td></td>' +
'<td></td>' +
'<tr>';
});
c += "</table>";
myModule.el.listcontainer.empty().append(c);
myModule.TableLinks();
},
itemDetails: function () {
alert("Detail clicked");
},
itemDelete: function () {
alert("Delete clicked");
},
itemEdit: function () {
alert("Edit clicked");
},
TableLinks: function () {
$(document).on('click', myModule.el.detailbutton, function () { myModule.itemDetails(); });
$(document).on('click', myModule.el.deletebutton, function () { myModule.itemDelete(); });
$(document).on('click', myModule.el.editbutton, function () { myModule.itemEdit(); });
},
};
myModule.init();

Can you try following:
TableLinks: function () {
$(document).on('click',
".item-detail",
function (ev) {
myModule.itemDetails();
ev.stopPropagation();
}
);
$(document).on('click',
".item-delete",
function (ev) {
myModule.itemDelete();
ev.stopPropagation();
});
$(document).on('click',
".item-edit",
function (ev) {
myModule.itemEdit();
ev.stopPropagation();
});
},

you need the delegation
$("selector on which item is added").on("click", "new item selector", function(){
});
ON and Delegate

You have to do something like this to use the "on" method.
$("table").on("click", myModule.el.detailbutton, myModule.itemDetails());
UPDATE: Just noticed, you have to used a selector not a jQuery object in the second parameter.
So $("table").on("click", ".item-detail", myModule.itemDetails());

your approach using on is exactly what you need, but should have been bit more careful on constructing the element object
el: {
listbutton: '#list-button',
listcontainer: '#list',
detailbutton: ".item-detail",
deletebutton: ".item-delete",
editbutton: ".item-edit"
},
and use it like this
init: function () {
$(myModule.el.listbutton).on("click", myModule.getMainData);
},
what you did is
TableLinks: function () {
$(document).on('click', myModule.el.detailbutton, function () { myModule.itemDetails(); });
...
},
which is similar to and which is wrong
TableLinks: function () {
$(document).on('click', $(".item-detail"), function () { myModule.itemDetails(); });
....
},
working fiddle

Related

How to combine two jQuery functions

Good Morning.
I want to combine my jQuery functions into one.
$('body').on('click', '.toggle2', function() {
console.log(123);
$('body').find('.dateshow').toggleClass('show');
});
$('body').on('click', '.toogle3', function() {
$('body').find('.autorshow').toggleClass('show');
});
$('body').on('click', '.toogle4', function() {
console.log(123);
$('body').find('.starshow').toggleClass('show');
});
Many thanks in advance
If you change all of your toggle links to have the following markup:
click
click
click
Then you can add a more generic handler such as:
$('.toggle').on('click', function() {
var targetSelector = $(this).attr('data-toggle');
$('.' + targetSelector).toggleClass('show');
});
Codepen: http://codepen.io/anon/pen/aBKJEb
When a callback is called jQuery will pass in an event object. You can check the target of the event and process as needed.
$('body').on('click', '.toggle2, .toogle3, .toogle4', function(e) {
var $target = jQuery(e.target),
$targetObject;
if($target.hasClass('toggle2')) {
$targetObject = jQuery('body').find('.dateshow');
}
if($target.hasClass('toogle3') {
$targetObject = jQuery('body').find('.autorshow');
}
if($target.hasClass('toogle4') {
$targetObject = jQuery('body').find('.starshow');
}
$targetObject.toggleClass('show');
});
$('body').on('click', '.toggle2,.toogle3,.toogle4', function() {
var mapper = {
'toggle2': { cls: '.dateshow', console:true },
'toggle3': { cls: '.autorshow', console:false },
'toggle4': { cls: '.starshow', console:true }
};
this.classList.forEach(function(cls) {
var obj = mapper[cls];
if(obj) {
obj.console && console.log(123);
$('body').find(obj.cls).toggleClass('show');
}
});
});

how to bind event to element after generateing

I have this script :
$(window).load(function () {
$(document).on('click', '.btn-delete-confirm', function () {...});
});
and I have this element :
<div id="attachments"></div>
and I have this script to load some html :
$(document).on('click', '.nav-tabs li a[href="#attach"]', function () {
$.ajax({
url: loadAttachmentsURL,
data: { equipmentId: equipmentId },
success: function (data) {
$("#attachments").html(data);
}
});
});
in my result from ajax I have some button that have .btn-delete-confirm class but when clicked on them nothing happen .
the sample of result like this :
<td><a data-id="73b2db39-199c-845c-8807-6c6164d2d97d" data-url="/Admin/EquipmentAttachment/Delete" class="btn-delete-confirm btn">Delete</a></td>
how can I resolve this ?
one way will be by attaching click event after html is set:
$(document).on('click', '.nav-tabs li a[href="#attach"]', function() {
var equipmentId = "?";
var loadAttachmentsURL = "/url";
$.ajax({
url: loadAttachmentsURL,
data: {
equipmentId: equipmentId
},
success: function(data) {
$("#attachments").html(data);
$(".btn-delete-confirm").click(function() {
alert("click!");
});
}
});
});
another will be attaching the click event to the document context:
$(document).on('click', ".btn-delete-confirm", function() {
alert("click!");
});
$(document).on('click', '.nav-tabs li a[href="#attach"]', function() {
var equipmentId = "?";
var loadAttachmentsURL = "/url";
$.ajax({
url: loadAttachmentsURL,
data: {
equipmentId: equipmentId
},
success: function(data) {
$("#attachments").html(data);
}
});
});
You are trying to add an eventlistener to something that isnt there yet.
This will result in an error, and the event wont fire again.
So try to add the listener AFTER the ajax import.
$(document).on('click', '.nav-tabs li a[href="#attach"]', function () {
$.ajax({
url: loadAttachmentsURL,
data: { equipmentId: equipmentId },
success: function (data) {
$('#attachments').html(data);
$('.btn-delete-confirm').on('click', function () {...});
}
});
});
Though .delegate() method is deprecated in jquery-3.0, its description is still worth to have a look:
Attach a handler to one or more events for all elements that match the
selector, now or in the future, based on a specific set of root
elements.
Exmaple:
// jQuery 1.4.3+
$( elements ).delegate( selector, events, data, handler );
// jQuery 1.7+
$( elements ).on( events, selector, data, handler );
Using document as a root element is not a big problem, but have you tried #attachments ?
$(window).load(function () {
$("#attachments").on('click', '.btn-delete-confirm', function () {...});
});

Super Simple Slider not working after AJAX load

I am trying to trigger the ready event after the user clicks on #mail-wrap which loads in another page with AJAX so that sss() can be refired. However, it's not refiring. What am I doing wrong?
jQuery(document).ready(function($) {
function sss() {
$(document).trigger('ready');
$('.slider').sss({
speed: 5000
});
}
// User event
$('#mail-wrap').on('click', function(e) {
e.preventDefault();
sss();
});
$('.slider').sss({
speed: 5000
});
});
Full relevant code (code is surrounded by document ready and the sss() function is outside of it):
(function($) {
var contactButton = $('#contact-button');
// Load the Contact page
function loadContact() {
$('#content').fadeOut(50, function() {
$('<span class="loading-icon page-loading-icon"></span>').insertBefore('#content');
}).load(site.url + '/contact/ #contact-keebs', function() {
$('.page-loading-icon').remove();
$(this).fadeIn(50);
$('body').addClass('contact');
$('#projects-list').removeClass('fadeInUp');
$('#contact-info, #clients').addClass('fadeInUp');
});
// Change the Contact button to 'Projects'
$(contactButton).removeClass('contact-button').addClass('project-button').attr('data-title', 'Projects').css('width', '71px').text('Projects').shuffleLetters();
myIcons.to('work');
// Change the title of the document
$('head').find('title').text('Contact | Keebs');
//Reinitialize SSS
sssInit();
}
// Load the Projects page
function loadProjects() {
$('#content').fadeOut(50, function() {
$('<span class="loading-icon page-loading-icon"></span>').insertBefore('#content');
}).load(site.url + '/ #primary', function() {
$('.page-loading-icon').remove();
$(this).fadeIn(50);
$('body').removeClass('contact');
$('#contact-info, #clients').removeClass('fadeInUp');
$('#projects-list').addClass('fadeInUp');
TweenLite.to("body.single #project-wrapper", 0.3, {height:0, force3D:true, ease:Power4.easeOut});
});
// Change the Projects button to 'Contact'
$(contactButton).removeClass('project-button').addClass('contact-button').attr('data-title', 'Get in touch').css('width', '96px').text('Get in touch').shuffleLetters();
myIcons.to('mail');
// Change the title of the document
$('head').find('title').text(site.title);
}
// User event
$('#mail-wrap').on('click', function(e) {
e.preventDefault();
// Prevent accidental double clicks
if (!$(this).data('isClicked')) {
var link = $(this);
if (!contactButton.hasClass('project-button')) {
var data1 = { contact_page: site.url + '/contact/ #contact-keebs' };
History.pushState(data1, 'Contact | Keebs', site.url + '/contact/');
loadContact();
} else {
var data2 = { home_page_contact: site.url + '/ #primary' };
History.pushState(data2, site.title, site.url + '/');
loadProjects();
}
link.data('isClicked', true);
setTimeout(function() {
link.removeData('isClicked');
}, 500);
}
});
})(jQuery);
It's not clear what your Ajax event does and if you are using sss() bound to the jQuery object defining your own function sss is confusing. Did you really mean to do something like this;
function sssInit() {
jQuery('.slider').sss({
speed: 5000
});
}
jQuery(document).ready(function($) {
sssInit();
// User event
$('#mail-wrap').on('click', function(e) {
e.preventDefault();
sssInit();
});
});
EDIT: You are using .load() so your sssInit call will need to go in the complete function parameter e.g;
$('#content').fadeOut(50, function() {
$('<span class="loading-icon page-loading-icon"> </span>').insertBefore('#content');
}).load(site.url + '/contact/ #contact-keebs', function() {
$('.page-loading-icon').remove();
$(this).fadeIn(50);
$('body').addClass('contact');
$('#projects-list').removeClass('fadeInUp');
$('#contact-info, #clients').addClass('fadeInUp');
sssInit();
});
ISSUE: The Super Simple Slider hooks up it's events using $(window).load(function() { ... }) adding elements to the DOM after load will not get the event handlers and prevents the slider working.
trying to trigger the ready event after the user clicks on #mail-wrap
which loads in another page with AJAX so that sss() can be refired.
However, it's not refiring. What am I doing wrong?
.ready() already called when $(document).trigger('ready'); called ?
Try utilizing $.holdReady()
// do stuff before `.ready()` event called
$.holdReady(true);
// User event
$('#mail-wrap').on('click', function(e) {
e.preventDefault();
sss();
// call `.ready()` event by setting `$.holdReady()` to `false`
$.holdReady(false);
});
function sss() {
jQuery('.slider').sss({
speed: 5000
});
}
jQuery(document).ready(sss);
e.g.,
$.holdReady(true);
// User event
$('#mail-wrap').on('click', function(e) {
e.preventDefault();
sss("$.holdReady(true) within `click` event", this);
$.holdReady(false);
});
function sss() {
console.log(arguments[1]); // `#mail-wrap` , `document`
$("body").append("<br>" + arguments[0] + " " + $.now())
}
jQuery(document).ready(function($) {
sss("$.holdReady(false) within $(document).ready()", this)
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
<div id="mail-wrap">click</div>

Trying to condense javascript into for loop

I've got the following code that I am trying to condense to a for loop but am having no luck:
$("#motion1-sub1-1").hover( function () {
$("#motion1-sub1-1 div").show();
},
function () { $("#motion1-sub1-1 div").hide();
}
);
$("#motion1-sub1-2").hover( function () {
$("#motion1-sub1-2 div").show();
},
function () { $("#motion1-sub1-2 div").hide();
}
);
$("#motion1-sub1-3").hover( function () {
$("#motion1-sub1-3 div").show();
},
function () { $("#motion1-sub1-3 div").hide();
}
);
$("#motion1-sub1-4").hover( function () {
$("#motion1-sub1-4 div").show();
},
function () { $("#motion1-sub1-4 div").hide();
}
);
$("#motion1-sub1-5").hover( function () {
$("#motion1-sub1-5 div").show();
},
function () { $("#motion1-sub1-5 div").hide();
}
);
Here's the for loop code that have to condense the above code:
for (var i = 1; i <= 5; i++) {
$("motion1-sub1-" + i).hover( function () { $("motion1-sub1-" + i + "div").show();
},
function () { $("motion1-sub1-" + i + "div").hide();
}
);
}
No need for a for-loop, just bind to those elements that have a certain id pattern, and use this to reference them from within the hover functions:
$("[id^='motion1-sub1-']").hover(
function(){
$("div", this).show();
},
function(){
$("div", this).hide();
}
);
I don't know what type of element we're binding to, but you should provide that tag as part of the selector. For instance, if this is a div we're hovering, modify the selector to include that:
$("div[id^='motion1-sub1-']")
Or an even shorter, more DRY version:
$("[id^='motion1-sub1-']").on("mouseenter mouseleave", function(e){
$("div", this).toggle( e.type === "mouseenter" );
});
How about giving all your divs a class of motion-sub and then doing
$(".motion-sub").hover(function() {
$(this).show() }, function() { $(this).hide(); }
});
You're missing a space on motion1-sub1-x div selector right before the div
$("motion1-sub1-" + i + " div")

How can I trigger a 'focusout' after I click on an element?

I have the following markup:
<select style="display:none">
<option value='1'>1</option>
<option vlaue='2'>2</option>
</select>
<input type="text" id="comboBox" />
<ul id="comboBoxData" style="display:none">
<li id='1'>1</li>
<li id='2'>2</li>
</ul>
and the following JQuery code:
$(document).ready(function() {
$('select').each(function() {
var parent = this;
$('#comboBoxData').on('click', 'li', function() {
var value = $(this).prop('id');
$(parent).val(value);
$('#comboBox').val(value);
});
});
$('#comboBox').bind('focusin', function () {
$('#comboBoxData').show();
});
$('#comboBox').bind('focusout', function () {
$('#comboBoxData').hide();
});
});
When I click on one of the LI's the 'comboBoxData' element disappears before the click trigger happens. Is there a way around this or an alternate event that I can use instead to have the same effect as a focusout?
Put mouseenter and mouseleave events and change the value of a global variable say isOver.
$('select').each(function() {
var parent = this;
$('#comboBoxData').on('click', 'li', function() {
var value = $(this).prop('id');
$(parent).val(value);
$('#comboBox').val(value);
$('#comboBoxData').hide();
});
});
$('#comboBoxData').mouseover(function(){
isOver = true;
}).mouseleave(function(){
isOver = false;
});
$('#comboBox').bind('focusin', function () {
$('#comboBoxData').show();
});
$('#comboBox').bind('focusout', function () {
if(!isOver){
$('#comboBoxData').hide();
}
});
You do not require this:
$('#comboBox').bind('focusout', function () {
$('#comboBoxData').hide();
});
instead use this inside $('#comboBoxData').on('click', 'li', function() {
if you are fine with plugin , you could just use this way:
$('#menu').bind('clickoutside', function (event) {
$(this).hide();
});
You can get that plugin here
Also, I have changed the code without using the plugin:
Please check the updated answer:
DEMO
try with blur() function
$('#comboBox').blur(function () {
$('#comboBoxData').hide();
});
The blur event is sent to an element when it loses focus.
from http://api.jquery.com/blur/
Not exactly elegant but it works.
$("body").click(function(event){
if(!$(event.target).is("#comboBoxData") && !$(event.target).is("#comboBox") ){
$("#comboBoxData").hide(); }
});
$(document).ready(function() {
$('select').each(function() {
$('#comboBoxData').on('click', 'li', function() {
var value = $(this).prop('id');
$('#comboBox').val(value);
$('#comboBoxData').hide();
});
});
$('#comboBox').bind('focusin', function () {
$('#comboBoxData').show();
});
});

Categories

Resources