Where are the arguments to the jQueryUI Dialog submit handler coming from? - javascript

Take a look at the following code:
this.dialog({
width: 500,
height: 260,
title: "Setup database",
content: $("<form>").append(table),
buttons: {
submit: function(_alert, dialog) {
dialog.find("form").each(function() {
var arr = $(this).serializeArray();
var data = {
mysql: true
};
var empty = false;
$(this).find("input").removeClass("error");
for (var k in arr) {
if ($.trim(arr[k].value) !== "") {
data[arr[k].name] = arr[k].value;
} else {
empty = true;
$(this).find("input[name='" + arr[k].name + "']").each(function() {
$(this).addClass("error");
});
break;
}
}
if (!empty) {
self.ajax({
url: url,
data: data
}, function(result) {
callback(result);
}, function() {
self.mysql(url, callback, _db_name, _db_user, _db_pass, is_dialog);
});
}
_alert.remove();
if($.isFunction(callback_submit)) {
callback_submit();
}
});
}
}
});
There are two parameters passed into the anonymous function that is supposed to trigger when the button "submit" is clicked. But I have no idea where these parameters are supposed to come from. Can someone explain? Is this related to passing parameters to an anonymous function in Javascript in general?

I don't think you get any argument passed to you when a button event callback is fired on jquery-ui dialog box
http://jsfiddle.net/3d7QC/1577/
buttons: {
"I've read and understand this": function() {
console.log(arguments);
// look at your console
$(this).dialog("close");
}
Only argument you get passed through to you is the customary jQuery event object.

There should only be one parameter passed to submit, which is the event object of the button itself, when clicked. So the context set is the submit button, if you need to access the dialog and modify it, you can do so by accessing the event.target property.
this.dialog({
buttons: {
submit: function(event) {
$(event).dialog('close'); //is the same as...
$(this).dialog('close');
}
});

The first argument _alert is the JS event object that is passed to every event handler in JavaScript. This is not specific to jQuery. javascript.info explains this as follows:
W3C way
Browsers which follow W3C standards always pass the event object as
the first argument for the handler.
For instance:
element.onclick = function(event) {
// process data from event
}
In the jQueryUI API reference they confirm that i
Specifies which buttons should be displayed on the dialog. The context
of the callback is the dialog element; if you need access to the
button, it is available as the target of the event object.
I illustrated this in a fiddle. Not sure what the second argument (dialog in your case) does, though. It's not passed in my example code.

Related

Same RadioButton-Setting Function from Both Startup / Change in jQuery

I have a single shared jQuery function that checks a RadioButton selection: if 1 is selected, it hides a span, otherwise it shows it.
This shared function is called both on startup and on Change, because on startup, it needs to do the same thing. The startup works, but the onChange reference does NOT work:
JS_OBJ = {
toggleTier : function() {
if ($('input[name="tier"]:checked').val() == 'Y_YES')
{
$('#tierSpan').hide();
}
else
{
$('#tierSpan').show();
}
},
// this is called from document.onReady - it comes here, OK
onReady : function() {
// on startup, toggle Tier - works OK
this.toggleTier();
// Also link the radio button Change to this shared function
$('input[name="tier"]:radio').change(function () {
alert('About to enter toggle...');
// NEVER COMES HERE - Object doesn't support this property or method
this.toggleTier();
});
}
};
the this is changing value as it is passing thru the different zones. when it is first instantiated, it has a good value, but the radiobutton:change has a different this
I was able to change it get it to work:
$('input[name="tier"]:radio').change(function () {
alert('About to enter toggle...');
self; //closure
toggleTier();
});
see this: What underlies this JavaScript idiom: var self = this?
Inside the change event, this does not refer to the current JS_OBJ, it refers to the current event target in stead. You want to explicitly save your reference to this, so you can use it inside the event.
Example:
onReady : function() {
var me = this;
me.toggleTier();
// Also link the radio button Change to this shared function
$('input[name="tier"]:radio').change(function () {
me.toggleTier();
});
}

addEventListener seems to trap my global variable

I have a non-jquery script with an addEventListener on a buttonclick. This works fine the first run but I want it to change "sendingurl" to some other value after the first click. (the succesfull insert of form becomes an update form). However, even though sendingurl fills with the new id value, it doesnt change after the event is fired again. Instead by the second click it fires the newly created event tohether with the old one with the old value.
The resulting values in console.log:
1st click: event "click" is fired with url: input.php
2nd click:
event "click" is fired with url: input.php
event "click" is fired with url: update.php?io=items&id=693
So I want to get rid of the input being triggered after the first click. Does someone know how to solve this?
var itemid = getHash();
ini(prepare); // using window.onload to execute
function prepare() {
if (itemid) {
// update
var sendingurl = 'update.php?io=items&id=' + itemid;
} else {
// input
var sendingurl = 'input.php';
}
// submitevent
æ($("submitBtn"), 'click', function() {
console.log("event \"click\" is fired with url: " + sendingurl);
var json = new FormData(document.forms[0]);
ajax(sendingurl, json, submittedInput);
});
}
// callback function after ajax did his magic
function submittedInput(response) {
if (response) {
if (!itemid) {
itemid = response;
prepare();
}
} else {
$("status").innerHTML = "something went wrong with the input";
}
}
// function to add events without the use of jquery or prototype
function æ(el, evType, fn, useCapture) {
if (el.addEventListener) {
el.removeEventListener(evType, fn, useCapture);
el.addEventListener(evType, fn, useCapture);
return true;
} else if (el.attachEvent) {
el.detachEvent('on' + evType, fn);
var r = el.attachEvent('on' + evType, fn);
return r;
} else {
el['on' + evType] = fn;
}
}
The first time through, there is no event handler to remove and your anonymous function is added as an event handler. The anonymous function creates as closure, so the value of sendingurl is now "constant" no matter how the external sendingurl changes. That is why you are getting the old value.
The second time through, the event handler function being passed to removeEventListener is not yet tied to an event because the second anonymous function is not the same function as the anonymous function on the first pass. So no event handler is removed. You then add a second event with the new anonymous function with the revised value of sendingurl. That is why you are seeing both functions fire.
Convert your anonymous function to a normal function and use the normal function name instead.

Event object eaten by jQuery animation callback

I have a problem with event object passed to the function in drop event. In my code, div#dropArea has it's drop event handled by firstDrop function which does some animations and then calls the proper function dropFromDesktop which handles the e.dataTransfer.files object. I need this approach in two separate functions because the latter is also used further by some other divs in the HTML document (no need to duplicate the code). First one is used only once, to hide some 'welcome' texts.
Generally, this mechanism lets you drag files from desktop and drop them into an area on my website.
Here's, how it looks (in a shortcut):
function firstDrop(ev) {
var $this = $(this);
//when I call the function here, it passes the event with files inside it
//dropFromDesktop.call($this, ev);
$this.children('.welcomeText').animate({
opacity: '0',
height: '0'
}, 700, function() {
$('#raw .menu').first().slideDown('fast', function() {
//when I call the function here, it passes the event, but 'files' object is empty
dropFromDesktop.call($this, ev);
});
});
}
function dropFromDesktop(ev) {
var files = ev.originalEvent.dataTransfer.files;
(...) //handling the files
}
$('#dropArea').one('drop', firstDrop);
$('some_other_div').on('drop', dropFromDesktop);
The problem is somewhere in jQuery.animation's callback - when I call my function inside it, the event object is passed correctly, but files object from dataTransfer is empty!
Whole script is put inside $(document).ready(function() { ... }); so the order of function declarations doesn't matter, I guess.
I suspect your problem is related with the lifetime of the Event object. Unfortunately, I have no clue about the cause of it. But, there is a way to workaround it that I can think of and it is keeping a reference to Event.dataTransfer.files instead.
var handleFileList = function(fn) {
return function(evt) {
evt.preventDefault();
return fn.call(this, evt.originalEvent.dataTransfer.files);
};
};
var firstDrop = function(fileList) { ... }
var dropFromDesktop = function(fileList) { ... }
$('#dropArea').one('drop', handleFileList(firstDrop));
$('some_other_div').on('drop', handleFileList(dropFromDesktop));​

Replacing jQuery.bind with jQuery.on

I've written a program that includes a form that the user interacts with. Because there are lots of events bound to different buttons I have written a loop that parses some JS that contains the form input information. Here is some example data:
var value = 0,
forms = {
place_controls : {
attrs : {
'class' : 'place-form'
},
input : {
place_x : {
attrs : {
type : 'text',
},
events : {
change : function () {
value = 10;
}
}
},
place_y : {
attrs : {
type : 'text',
},
events : {
change : function () {
value = 50
}
}
}
}
}
}
The data is then parsed by this:
$.each(forms, function (form_index, form) {
var $form_markup = $('<form>').attr(form.attrs);
// Next: loop through each input element of the form we've reached
$.each(form.input, function (element_index, element) {
var $elem = $('<input>').attr(element.attrs);
$elem.appendTo($form_markup);
if (element.events !== undefined) {
$.each(element.events, function (event_index, event) {
$elem.bind(event_index, event);
//$form_markup.on(event_index, $elem, event);
});
}
});
$form_markup.appendTo($form_goes_here);
});
As you can see, I'm using .bind() at the moment, however I want to use .on(). Unfortunately, when I do this all of the items within a form are bound to the last event parsed by the function. When I use .bind() everything works as planned - i.e. Clicking on 'place_x' sets value to 10, clicking 'place_y' sets value to 50.
When using .on(), whichever I change sets value to 50, which I am assuming is because the last function is becoming bound to each event.
Can anybody see what I have done wrong?
Update: There are many different ways to do this, and I have subsequently changed how my code works, however this question is related to why .bind() is working and why .on() is not.
//$elem.bind(event_index, event);
//It looks like you should just be using .on() like this
$elem.on(event_index, event);
The way it looks like you are trying to use .on() is in the live -bubbling- event sort of way, it looks like only the last event you are created is sticking, why each value just gets set to 50.
//$form_markup.on(event_index, $elem, event);
You can create elements with property maps that include handler functions in one simple call:
var $elem = $('<input/>', properties);
The "properties" object can contain event handlers:
var $elem = $('<input/>', {
type: 'text',
name: 'somethingUseful',
click: function(ev) { /* click handler */ },
change: function(ev) { /* change handler */ },
css: { color: "red" }
});

Javascript: How to pass an argument to a method being called without parentheses

Sorry for how stupid this is going to sound. My JS vocabulary is terrible and I had absolutely no idea what to search for.
I'm using jQuery.
So I've got this code:
var example = {
open: function(element){
alert(element.text());
},
init: function(){
$("a").click(example.open);
}
};
$(document).ready(function(){example.init();)
So here's the problem: I want to pass an argument to example.open() when I click the "a" element. It doesn't seem like I can, though. In order for the example.open method to just…exist on page-load and not just run, it can't have parentheses. I think. So there's no way to pass it an argument.
So I guess my question is…how do you pass an argument to a function that can't have parentheses?
Thanks so much.
Insert another anonymous function:
var example = {
open: function(element){
alert(element.text());
},
init: function(){
$("a").click(function()
{
example.open($(this));
});
}
};
You can also try this version because jQuery set the function's context (this) to the DOM element:
var example = {
open: function(){
alert($(this).text());
},
init: function(){
$("button").click(example.open);
}
};
Since jQuery binds the HTML element that raised the event into the this variable, you just have to pass it as a regular parameter:
var example = {
open: function(element){
alert(element.text());
},
init: function(){
$("a").click(function() {
// jQuery binds "this" to the element that initiated the event
example.open(this);
});
}
}
$(document).ready(function(){example.init();)
You can pass the anchor through its own handler:
var example = {
open: function( element ){
alert(element.text());
},
init: function(){
$("a").on("click", function() {
example.open( $(this) );
});
}
};
$(document).ready(function() {
example.init();
});
I don't understand what you actually want to do;
however, I can give a try:
var example = {
open: function(event){
event.preventDefault();
alert($(event.target).text()+' : '+event.data.x);
},
init: function(){
$("a").bind('click',{x:10},example.open);
}
};
$(example.init);
demo:
http://jsfiddle.net/rahen/EM2g9/2/
Sorry, I misunderstood the question.
There are several ways to handle this:
Wrap the call in a function:
$('a').click( function(){ example.open( $(this) ) } );
Where $(this) can be replaced by your argument list
Call a different event creator function, which takes the arguments as a parameter:
$('a').bind( 'click', {yourvariable:yourvalue}, example.open );
Where open takes a parameter called event and you can access your variable through the event.data (in the above it'd be event.data.yourvariable)
Errors and Other Info
However your element.text() won't just work unless element is a jQuery object. So you can jQueryify the object before passing it to the function, or after it's received by the function:
jQuery the passed object:
function(){ example.open(this) } /* to */ function(){ example.open($(this)) }
jQuery the received object:
alert(element.text()); /* to */ alert($(element).text());
That said, when calling an object without parameters this will refer to the object in scope (that generated the event). So, really, if you don't need to pass extra parameters you can get away with something like:
var example = {
open: function(){ // no argument needed
alert($(this).text()); // this points to element being clicked
},
init: function(){
$("a").click(example.open);
}
};
$(document).ready(function(){
example.init();
}); // your ready function was missing closing brace '}'

Categories

Resources