Need to understand how javascript functions are called - javascript

This is part of a code. The question is, does this line "$("#b_facetNewChild").button().click(function(){" means that the following should be fired when the button "facetNewChild" is clicked? Because there is no "onClick" function at the button. Also, can you explain briefly, what does it mean to have this nested into another function "newChildFacet()" and how to call it?
Sorry, but I am new to javascript.Thanks!
function newChildFacet()
{
// button click
$("#b_facetNewChild").button().click(function(){
//get selected fId
var $fId=getSfSelectedFIds();
if($fId.length>0 && $fId.split(",").length!=1)
{
messageBox("Tip","Please select <b>ONE</b> as the parent facet. If no facet is selected, the new facet will be created under <b>root</b>.");
return false;
}
//some more stuff here!
});
// newChildFacetDialog
$("#newChildFacetDialog").dialog({
autoOpen: false,
modal: true,
title: "New Child Facet",
buttons: {
"Cancel": function() {
$(this).dialog('close');
},
"Create": function() {
//get data
var $parentId=getSfSelectedFIds();
});
$(this).dialog('close');
}
}
});
}

First, yes it bound as a click event handler, so it'll run when #b_facetNewChild is clicked - you won't see this in source, it's stored elsewhere in the DOM.
You can call it by invoking the click event handlers on that element, like this:
$("#b_facetNewChild").click();
It doesn't matter that it's a nested/anonymous function, all we care about here is it's a click event handler on that element, so you can trigger it any of the following ways:
$("#b_facetNewChild").click();
$("#b_facetNewChild").trigger("click");
$("#b_facetNewChild").triggerHandler("click");

You got it right.
$("#b_facetNewChild").button().click(function(){ ... }) does exactly what you mean. However, you won't see an onclick handler in the HTML, but rather only if you inspect the DOM/JS element itself (for example, by using FireBug).
The fact that this call is located inside a function simply means it will only be called (i.e. callback attached to the button) once the wrapping function is called.

Related

onclick needs to be double clicked

When using onclick in JavaScript to call the function nowClicked(), I need to click the object twice in order for the alert to show. Below is the code for my function.
function nowClicked() {
$('.object').click(function() {
$('.object').removeClass("clicked");
var myClass = $(this).attr("id");
alert(myClass);
$(this).addClass("clicked");
e.stopImmediatePropagation();
});
};
What is the problem?
Here's what happens the first time you click your button:
nowClicked is called because you've set it up on the button's onclick
nowClicked sets up a jQuery click handler for .object
The code inside the jQuery click handler only runs the next time you click on the button.
It looks like you are mixing up two ways of handling clicks -- one is using the onclick event, and the second is using jQuery. You need to pick one and stick to it instead of using both.
There is no need to put it inside another function,because click is itself handling a callback function.Remove the outer function nowClicked else remove the $('.object').click(function() {.In the second case you may to pass the context as a function argument.
$('.object').click(function() {
$('.object').removeClass("clicked");
var myClass = $(this).attr("id");
alert(myClass);
$(this).addClass("clicked");
e.stopImmediatePropagation();
});

Magnific-Popup close callback does not execute

For each <a> that has mfp-ajax class will be executed as a pop-up box, and this pop-up box use the plugin in Magnific-Popup.
HTML:
View List
Javascript:
magnificSetting: {
type: 'ajax',
mainClass: 'mfp-fade',
ajax: {
settings: {
cache: false
}
}
},
modals: function () {
var self = this;
$('a.mfp-ajax').each(function () {
var $this = $(this);
$this.magnificPopup(self.settings.magnificSetting);
});
}
The codes works fine, however <a> is sometimes dynamically generated in the DOM and I have to create a separate script for Magnific-Popup callbacks. So what I did is I followed what is in the documentation, see the codes below:
$(document).on('mfpClose', '.multiselect-modal', function () {
console.log('test');
});
I tried this code but this does not get executed, how do I attach this in an element that is being generated dynamically in the DOM and when the pop-up opens and the user close it, it will go to the above code. Am I missing something here?
Unfortunately Magnific Popup internally uses triggerHandler() rather than trigger() to implement custom events ,so there is no event for the document to "listen to" so this may never work with current versions
$(document).on('mfpClose', '.multiselect-modal', function () {
console.log('test');
});
There is one fix but that requires you to create global events which is a bad practise so i advice you to make use of callbacks which is close in your case goes like this
$.magnificPopup.instance.close = function() {
//do your stuff here
//this calls the original close to close popup
//you may well comment it out which would totally disable the close button or execute conditional in if else
$.magnificPopup.proto.close.call();
};
these are some properties
//property
magnificPopup.currItem // current item
magnificPopup.index // current item index
// Navigation
magnificPopup.next(); // go to next item
magnificPopup.prev(); // go to prev item
magnificPopup.goTo(4); // go to slide #4

Binding a click event in my JavaScript module

Since I started structuring my JavaScript as a module pattern, some of my click events no longer work. Since other parts of my JavaScript add HTML to the DOM, I need to use $('body').on('click') for a button.
This is what my module currently looks like:
var s,
MyApp = {
settings: {
fooButton: $(".foo-button"),
barButton: $(".bar-button")
},
init: function() {
s = this.settings;
this.bindEvents();
},
bindEvents: function() {
// this works
s.fooButton.on("click", function() {
MyApp.clickButton("foo");
});
// this does NOT work
$('body').on('click', s.barButton, function (event) {
MyApp.clickButton("bar");
});
},
clickButton: function(button) {
console.log("You clicked " + button)
}
};
The first click event is working, the second isn't. How can I bind and event for an element that was created by JavaScript code?
The second argument for your handler when the event is delegated is expected to be a string.
In your case it is a jQuery Object.
That is the root cause your click event is not working.
Change
barButton: $(".bar-button")
to
barButton: ".bar-button"
If you're creating the element in JS, you have to bind the event AFTER the element is created.
So put the binding event in a function, then call that function after your JS code has created the element. :)
When using .on() for event delegation, the second parameter has to be a string. Passing anything else won't work.
http://api.jquery.com/on/#on-events-selector-data

jQuery callback function accumulating

I wrote some code for a custom confirm box that calls a function when confirm button (yes-button) is pressed and passes another function as a parameter and I bind it to 2 different button clicks with different functions as a parameter. For example:
$('#button1').click(function() {
callFunction(function() { alert("test"); });
});
$('#button2').click(function() {
callFunction(function() { alert("test2"); });
});
function callFunction(callback) {
//code to display custom confirm box
console.log(callback);
$('.confirm-box .yes-button').click(function() {
callback();
});
}
Everything happens as expected, confirm box appears and on confirm button click I get a callback function executed and it alerts "test" (or "test2" depending on which button called the confirm box). The problem arises when I click button1 that sends a function that alerts "test", then instead of confirming I cancel that (nothing happens as expected), and then click button2 that passes alert("test2") as a callback function. Now once I press the yes-button instead of alerting just "test2", I get both "test2" and "test" alerts even though that console.log I wrote logs just the function that alerts "test2" at the time of that button2 click. It seems like these callback functions get stacked somewhere, but I don't understand where and why.
The .click() function can add more than one handler to an element, and I think that's what's happening here. Try this:
// ...
$('.confirm-box .yes-button').unbind('click').click(function() {
callback();
});
This removes any previous click handler before applying the new one.
When you execute the code:
$('.confirm-box .yes-button').click(function() {
callback();
});
you are binding an event handler to the .yes-button element. If you run that code twice, it will have two events bound to it. And so on.
One solution is to use .one instead, so that the event handler will be removed after the first time it is fired:
$('.confirm-box .yes-button').one("click", function() {
callback();
});
This of course has issues if there are two confirm boxes open simultaneously or if there are two .yes-button elements, but for a simple use case it works fine.
What is happening is that each time a button is clicked the callFunction method is executing. It runs through that code block and applies an event listener to the $('.confirm-box .yes-button') button. So clicking your button N times will apply the click listener N times as well. One solution is to store the function in a variable.
Not sure what the end goal is, but this is one solution.
Another solution would be to remove buttons event listeners each time.
var functionToCallOnYes = function() {};
$('#button1').click(function() {
functionToCallOnYes = function() {
alert("test");
};
});
$('#button2').click(function() {
functionToCallOnYes = function() {
alert("test2");
};
});
$('.confirm-box .yes-button').click(function() {
console.log(functionToCallOnYes);
functionToCallOnYes();
});
You can do it by setting an identity by classes,
var button = $('.confirm-box .yes-button');
$('#button1').click(function() {
button.removeClass("b").addClass("a");
});
$('#button2').click(function() {
button.removeClass("a").addClass("b");
});
button.click(function() {
if($(this).hasClass("a")){
callBackForButton1();
} else {
callBackForButton2();
}
});
It is a bad practice to stack up the event handler for a single element.
Yes, extra callbacks are getting stacked up. In $('button1').click(f), the function f will be called with no parameters every time button1 is clicked. In this case, f is callFunction-- a function that itself attaches a new handler to any .confirm-box .yes-button element each time it's invoked. So on the Nth click, you should have N-1 alerts.
To make things like this easier, you can refer to functions by name in JavaScript. So if you had function test() { console.log("test"); };, you could write $(".confirm-box").click(test) just once and every click on a .confirm-box from then on would print test to the console.
Usually if you have callbacks whose sole purpose is to call a callback, you can just remove that callback.

jQuery Text Editor (jqte), using change event

I am trying to write some code for change() event using jQuery Text Editor (jqte), I have two functions which give jqte functionality to textarea's
One for editors loaded with JavaScript, when clicking some elements in a page:
function onLoadEditor(){
jQuery(".comment-editor").jqte({
// some jqte params, such as fsize: false,indent: false...
change: function(){ observeEditor(); }
});
}
And other, generic function, for pages with one single editor
jQuery(function() {
jQuery(".comment-editor").jqte({
// some jqte params, such as fsize: false,indent: false...
change: function(){ observeEditor(); }
});
});
I want to access the id of the concrete textarea (all textareas in the page have an id) which has fired the change() event
How should I write observeEditor() function to achieve this? Or... how I should define the function in jqte change property?
After reading this jQuery blur event with ID and value I have solved it, with following code (simplified)
function onLoadEditor(){
jQuery(".comment-editor").each(function(idx, elem) {
jQuery(this).jqte({
// some jqte params, such as fsize: false,indent: false...
change: observeEditor(elem.id),
});
}
jQuery(function() {
onLoadEditor();
});
But now I have another problem...
As you can read in the original question, onLoadEditor() is called when clicking some elements in a page. Then another javascript function jsComment() is called, builds a form (with a textarea.comment-editor field included) and it is rendered this way
function jsComment(){
...
var form = '<div class="comments_wrapper ... ';
jQuery(form).insertAfter(some_element).fadeIn('fast');
onLoadEditor();
}
Problem is change() event is being fired only once, when form fades in, while the idea is the opposite, event should fire when user adds some text, not when appearing... Any tips?
UPDATE
After reading Event binding on dynamically created elements? I have solved it this way
function onLoadEditor(){
jQuery('.comment-editor').each(function(idx, elem) {
jQuery(this).jqte({
// some jqte params, such as fsize: false,indent: false...
});
jQuery(document).on('change',
jQuery('.comment-editor'),
function(){
observeEditor(elem.id);
}
);
});
}
jQuery(function() {
onLoadEditor();
});
Although finally I am not using change() event, as it was being fired constantly. Performing better with keyup() & paste(), for instance

Categories