// change delegation, happens here so we have bind.
if ( !jQuery.support.changeBubbles ) {
-jQuery.event.special.change = {
- filters: {
- click: function( e ) {
- var elem = e.target;
+var formElems = /textarea|input|select/i;
- if ( elem.nodeName.toLowerCase() === "input" && elem.type === "checkbox" ) {
- return trigger( "change", this, arguments );
- }
+function getVal( elem ) {
+ var type = elem.type, val = elem.value;
- return changeFilters.keyup.call( this, e );
- },
- keyup: function( e ) {
- var elem = e.target, data, index = elem.selectedIndex + "";
+ if ( type === "radio" || type === "checkbox" ) {
+ val = elem.checked;
- if ( elem.nodeName.toLowerCase() === "select" ) {
- data = jQuery.data( elem, "_change_data" );
- jQuery.data( elem, "_change_data", index );
+ } else if ( type === "select-multiple" ) {
+ val = elem.selectedIndex > -1 ?
+ jQuery.map( elem.options, function( elem ) {
+ return elem.selected;
+ }).join("-") :
+ "";
- if ( (elem.type === "select-multiple" || data != null) && data !== index ) {
- return trigger( "change", this, arguments );
- }
- }
- },
- beforeactivate: function( e ) {
- var elem = e.target;
+ } else if ( elem.nodeName.toLowerCase() === "select" ) {
+ val = elem.selectedIndex;
+ }
+
+ return val;
+}
+
+function testChange( e ) {
+ var elem = e.target, data, val;
+
+ if ( !formElems.test( elem.nodeName ) || elem.readOnly ) {
+ return;
+ }
+
+ data = jQuery.data( elem, "_change_data" );
+ val = getVal(elem);
- if ( elem.nodeName.toLowerCase() === "input" && elem.type === "radio" && !elem.checked ) {
- return trigger( "change", this, arguments );
+ if ( val === data ) {
+ return;
+ }
+
+ // the current data will be also retrieved by beforeactivate
+ if ( e.type !== "focusout" || elem.type !== "radio" ) {
+ jQuery.data( elem, "_change_data", val );
+ }
+
+ if ( elem.type !== "select" && (data != null || val) ) {
+ e.type = "change";
+ return jQuery.event.trigger( e, arguments[1], this );
+ }
+}
+
+jQuery.event.special.change = {
+ filters: {
+ focusout: testChange,
+
+ click: function( e ) {
+ var elem = e.target, type = elem.type;
+
+ if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) {
+ return testChange.call( this, e );
}
},
- blur: function( e ) {
- var elem = e.target, nodeName = elem.nodeName.toLowerCase();
- if ( (nodeName === "textarea" || (nodeName === "input" && (elem.type === "text" || elem.type === "password")))
- && jQuery.data(elem, "_change_data") !== elem.value ) {
+ // Change has to be called before submit
+ // Keydown will be called before keypress, wich is used in submit-event delegation
+ keydown: function( e ) {
+ var elem = e.target, type = elem.type;
- return trigger( "change", this, arguments );
+ if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") ||
+ (e.keyCode === 32 && (type === "checkbox" || type === "radio")) ||
+ type === "select-multiple" ) {
+ return testChange.call( this, e );
}
},
- focus: function( e ) {
- var elem = e.target, nodeName = elem.nodeName.toLowerCase();
- if ( nodeName === "textarea" || (nodeName === "input" && (elem.type === "text" || elem.type === "password" ) ) ) {
- jQuery.data( elem, "_change_data", elem.value );
+ // Beforeactivate happens also before the previous element is blurred
+ // with this event you can't trigger a change event, but you can store
+ // information/focus[in] is not needed anymore
+ beforeactivate: function( e ) {
+ var elem = e.target;
+
+ if ( elem.nodeName.toLowerCase() === "input" && elem.type === "radio" ) {
+ return jQuery.data( elem, "_change_data", getVal(elem) );
}
}
},
for ( var type in changeFilters ) {
jQuery.event.add( this, type + ".specialChange." + fn.guid, changeFilters[type] );
}
-
- // always want to listen for change for trigger
- return false;
+
+ return formElems.test( this.nodeName );
},
remove: function( namespaces, fn ) {
for ( var type in changeFilters ) {
jQuery.event.remove( this, type + ".specialChange" + (fn ? "."+fn.guid : ""), changeFilters[type] );
}
+
+ return formElems.test( this.nodeName );
}
};
<head>\r
<script src='../dist/jquery.js' type='text/javascript'></script>\r
<style>\r
- .red {\r
- background-color: red;\r
- border: solid 3px red;\r
- }\r
+ .red {\r
+ background-color: red;\r
+ border: solid 3px red;\r
+ }\r
</style>\r
</head>\r
<body>\r
<h2>Change Tests</h2>\r
<table>\r
- <tr>\r
- <td>\r
- Change each:\r
- </td>\r
- <td>\r
- <select class='select_test'>\r
- <option value='one'>change me 1</option>\r
- <option value='two'>change me 2</option>\r
- <option value='three'>change me 3</option>\r
- </select>\r
- </td>\r
- <td>\r
- <select class='mselect_test' multiple="multiple">\r
- <option value='one'>change me 1</option>\r
- <option value='two'>change me 2</option>\r
- <option value='three'>change me 3</option>\r
- </select>\r
- </td>\r
- <td>\r
- <input type="checkbox" class="checkbox_test" name="mycheckbox" id="checkbox1"/>\r
- <label for="checkbox1">Checkbox 1 label</label><br/>\r
- <input type="checkbox" class="checkbox_test" name="mycheckbox" id="checkbox2"/>\r
- <label for="checkbox2">Checkbox 2 label</label>\r
- </td>\r
- <td>\r
- <input type="radio" class="radio_test" name="myradio" id="radio1"/>\r
- <label for="radio1">Radio 1 label</label><br/>\r
- <input type="radio" class="radio_test" name="myradio" id="radio2"/>\r
- <label for="radio2">Radio 2 label</label>\r
- </td>\r
- <td>\r
- <input class='test' value='' id='input' size='10' />\r
- </td>\r
- <td>\r
- <textarea rows='2'></textarea>\r
- </td>\r
- <td>$().bind('change')</td>\r
- </tr>\r
- <tr>\r
- <td>Results:</td>\r
- <td id='select' class="red">SELECT</td>\r
- <td id='mselect' class="red">MULTI</td>\r
- <td id='checkbox' class="red">CHECKBOX</td>\r
- <td id='radio' class="red">RADIO</td>\r
- <td id='text' class="red">TEXT</td>\r
- <td id='textarea' class="red">TEXTAREA</td>\r
- <td id='boundChange' class="red">DOCUMENT</td>\r
- </tr>\r
+ <tr>\r
+ <td>\r
+ Change each:\r
+ </td>\r
+ <td>\r
+ <select class='select_test'>\r
+ <option value='one'>change me 1</option>\r
+ <option value='two'>change me 2</option>\r
+ <option value='three'>change me 3</option>\r
+ </select>\r
+ </td>\r
+ <td>\r
+ <select class='mselect_test' multiple="multiple">\r
+ <option value='one'>change me 1</option>\r
+ <option value='two'>change me 2</option>\r
+ <option value='three'>change me 3</option>\r
+ </select>\r
+ </td>\r
+ <td>\r
+ <input type="checkbox" class="checkbox_test" name="mycheckbox" id="checkbox1"/>\r
+ <label for="checkbox1">Checkbox 1</label><br/>\r
+ <input type="checkbox" class="checkbox_test" name="mycheckbox" id="checkbox2"/>\r
+ <label for="checkbox2">Checkbox 2</label>\r
+ <input type="checkbox" class="checkbox_test" name="mycheckbox" id="checkbox3" disabled="disabled"/>\r
+ <label for="checkbox3">Checkbox 3</label>\r
+ </td>\r
+ </td>\r
+ </td>\r
+ <td>\r
+ <input type="radio" class="radio_test" name="myradio" id="radio1"/>\r
+ <label for="radio1">Radio1</label><br/>\r
+ <input type="radio" class="radio_test" name="myradio" id="radio2"/>\r
+ <label for="radio2">Radio2</label>\r
+ <input type="radio" class="radio_test" name="myradio" id="radio3" disabled="disabled"/>\r
+ <label for="radio3">Radio3</label>\r
+ </td>\r
+ <td>\r
+ <input class='test' value='' id='input' size='10' />\r
+ <input class='test' value='test' id='input2' size='10' readonly="readonly" />\r
+ </td>\r
+ <td>\r
+ <textarea rows='2'></textarea>\r
+ </td>\r
+ <td>$(document).bind('change')</td>\r
+ </tr>\r
+ <tr>\r
+ <td>Live:</td>\r
+ <td id='select' class="red">SELECT</td>\r
+ <td id='mselect' class="red">MULTI</td>\r
+ <td id='checkbox' class="red">CHECKBOX</td>\r
+ <td id='radio' class="red">RADIO</td>\r
+ <td id='text' class="red">TEXT</td>\r
+ <td id='textarea' class="red">TEXTAREA</td>\r
+ <td id='boundChange' class="red">DOCUMENT</td>\r
+ </tr>\r
+ <tr>\r
+ <td>Bind:</td>\r
+ <td id='selectbind' class="red">SELECT</td>\r
+ <td id='mselectbind' class="red">MULTI</td>\r
+ <td id='checkboxbind' class="red">CHECKBOX</td>\r
+ <td id='radiobind' class="red">RADIO</td>\r
+ <td id='textbind' class="red">TEXT</td>\r
+ <td id='textareabind' class="red">TEXTAREA</td>\r
+ </tr>\r
</table>\r
<h2>Submit Tests</h2>\r
<table>\r
- <tr>\r
- <td>\r
- Submit each:\r
- </td>\r
- <td>\r
- <form action="" id="text_submit">\r
- <input class='test' type='text' value='Key Return To Submit'/>\r
- </form>\r
- </td>\r
- <td>\r
- <form action="" id="password_submit">\r
- <input class='test' type='password' value=''/>\r
- </form>\r
- </td>\r
- <td>\r
- <form action="" id="submit_submit">\r
- <input type='submit' value="Click Me To Submit" />\r
- </form>\r
- </td>\r
- <td>$().bind('submit')</td>\r
- </tr>\r
- <tr>\r
- <td>Results:</td>\r
- <td id='textSubmit' class="red">TEXT</td>\r
- <td id='passwordSubmit' class="red">PASSWORD</td>\r
- <td id='submitSubmit' class="red">BUTTON</td>\r
- <td id='boundSubmit' class="red">DOCUMENT</td>\r
- </tr>\r
+ <tr>\r
+ <td>\r
+ Submit each:\r
+ </td>\r
+ <td>\r
+ <form action="" id="text_submit">\r
+ <input class='test' type='text' value='Key Return To Submit'/>\r
+ </form>\r
+ </td>\r
+ <td>\r
+ <form action="" id="password_submit">\r
+ <input class='test' type='password' value=''/>\r
+ </form>\r
+ </td>\r
+ <td>\r
+ <form action="" id="submit_submit">\r
+ <input type='submit' value="Click Me To Submit" />\r
+ </form>\r
+ </td>\r
+ <td>$(document).bind('submit')</td>\r
+ </tr>\r
+ <tr>\r
+ <td>Results:</td>\r
+ <td id='textSubmit' class="red">TEXT</td>\r
+ <td id='passwordSubmit' class="red">PASSWORD</td>\r
+ <td id='submitSubmit' class="red">BUTTON</td>\r
+ <td id='boundSubmit' class="red">DOCUMENT</td>\r
+ </tr>\r
</table>\r
- \r
+\r
+ <ul id="log"></ul>\r
\r
<script type='text/javascript'>\r
- makeChangeFunc = function(id, prevent){\r
- return function(e){\r
- if(prevent)\r
- e.preventDefault();\r
- $(id).css("backgroundColor","green").css("border","solid 3px green");\r
- setTimeout(function(){\r
- $(id).css("backgroundColor","");\r
- }, 700)\r
- }\r
- }\r
- \r
- $(".select_test").live("change",makeChangeFunc("#select"))\r
- $(".mselect_test").live("change",makeChangeFunc("#mselect"))\r
- $(".checkbox_test").live("change",makeChangeFunc("#checkbox"))\r
- $(".radio_test").live("change",makeChangeFunc("#radio"))\r
- $('textarea').live('change', makeChangeFunc("#textarea"))\r
- $('#input').live('change', makeChangeFunc("#text"))\r
- $(document).bind('change', makeChangeFunc("#boundChange"))\r
- \r
- $("#text_submit").live("submit", makeChangeFunc("#textSubmit", true) )\r
- $("#password_submit").live("submit", makeChangeFunc("#passwordSubmit", true) )\r
- $("#submit_submit").live("submit", makeChangeFunc("#submitSubmit", true) )\r
- $(document).bind('submit', makeChangeFunc("#boundSubmit"))\r
- \r
+ jQuery.fn.addChangeTest = function( id, prevent ) {\r
+ return this.bind("change", function(e){\r
+ jQuery(id + "bind").blink();\r
+ }).live("change", function(e){\r
+ if ( prevent ) {\r
+ e.preventDefault();\r
+ }\r
+\r
+ jQuery(id).blink();\r
+ });\r
+ };\r
+\r
+ jQuery.fn.addSubmitTest = function( id, prevent ) {\r
+ return this.live("submit", function(e){\r
+ if ( prevent ) {\r
+ e.preventDefault();\r
+ }\r
+\r
+ jQuery(id).blink();\r
+ });\r
+ };\r
+\r
+ jQuery.fn.blink = function(){\r
+ return this.css("backgroundColor","green").css("border","solid 3px green").delay(700).queue(function(next){\r
+ jQuery(this).css("backgroundColor","");\r
+ next();\r
+ });\r
+ };\r
+ \r
+ $(".select_test").addChangeTest("#select");\r
+ $(".mselect_test").addChangeTest("#mselect");\r
+ $(".checkbox_test").addChangeTest("#checkbox");\r
+ $(".radio_test").addChangeTest("#radio");\r
+ $('textarea').addChangeTest("#textarea");\r
+ $('#input').addChangeTest("#text");\r
+ $(document).bind("change", function(){\r
+ jQuery("#boundChange").blink();\r
+ });\r
+ \r
+ $("#text_submit").addSubmitTest("#textSubmit", true);\r
+ $("#password_submit").addSubmitTest("#passwordSubmit", true);\r
+ $("#submit_submit").addSubmitTest("#submitSubmit", true);\r
+ $(document).bind("submit", function(){\r
+ jQuery("#boundSubmit").blink();\r
+ });\r
+ \r
</script>\r
</body>\r
</html>\r
// test click on select
- // first click sets data
- if ( !jQuery.support.changeBubbles ) {
- select[0].selectedIndex = 1;
- select.trigger("keyup");
- }
-
// second click that changed it
selectChange = 0;
select[0].selectedIndex = select[0].selectedIndex ? 0 : 1;
- select.trigger(jQuery.support.changeBubbles ? "change" : "click");
+ select.trigger("change");
equals( selectChange, 1, "Change on click." );
// test keys on select
selectChange = 0;
select[0].selectedIndex = select[0].selectedIndex ? 0 : 1;
- select.trigger(jQuery.support.changeBubbles ? "change" : "keyup");
+ select.trigger("change");
equals( selectChange, 1, "Change on keyup." );
// test click on checkbox
- checkbox.trigger(jQuery.support.changeBubbles ? "change" : "click");
+ checkbox.trigger("change");
equals( checkboxChange, 1, "Change on checkbox." );
// test before activate on radio
textareaChange++;
});
- if ( !jQuery.support.changeBubbles ) {
- textarea.trigger("focus");
- }
-
textarea.val(oldVal + "foo");
- textarea.trigger(jQuery.support.changeBubbles ? "change" : "blur");
+ textarea.trigger("change");
equals( textareaChange, 1, "Change on textarea." );
textarea.val(oldVal);
textChange++;
});
- if ( !jQuery.support.changeBubbles ) {
- text.trigger("focus");
- }
-
text.val(oldVal+"foo");
- text.trigger(jQuery.support.changeBubbles ? "change" : "blur");
+ text.trigger("change");
equals( textChange, 1, "Change on text input." );
text.val(oldTextVal);
passwordChange++;
});
- if ( !jQuery.support.changeBubbles ) {
- password.trigger("focus");
- }
-
password.val(oldPasswordVal + "foo");
- password.trigger(jQuery.support.changeBubbles ? "change" : "blur");
+ password.trigger("change");
equals( passwordChange, 1, "Change on password input." );
password.val(oldPasswordVal);
selectChange = 0;
select.die("change");
select[0].selectedIndex = select[0].selectedIndex ? 0 : 1;
- select.trigger(jQuery.support.changeBubbles ? "change" : "click");
+ select.trigger("change");
equals( selectChange, 0, "Die on click works." );
selectChange = 0;
select[0].selectedIndex = select[0].selectedIndex ? 0 : 1;
- select.trigger(jQuery.support.changeBubbles ? "change" : "keyup");
+ select.trigger("change");
equals( selectChange, 0, "Die on keyup works." );
// die specific checkbox
checkbox.die("change", checkboxFunction);
- checkbox.trigger(jQuery.support.changeBubbles ? "change" : "click");
+ checkbox.trigger("change");
equals( checkboxChange, 1, "Die on checkbox." );
});