From 5f0a8c30ef84dc7272443a181f0ca42f43082143 Mon Sep 17 00:00:00 2001 From: Dangyi Liu Date: Thu, 23 Jun 2016 22:41:48 +0800 Subject: [PATCH 01/72] Rakefile: change exec to system exec will replace rake itself! --- Rakefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Rakefile b/Rakefile index e0e44e67..049051a6 100644 --- a/Rakefile +++ b/Rakefile @@ -11,7 +11,7 @@ namespace :test do desc %(Starts the test server which reloads everything on each refresh) task :reloadable do - exec "bundle exec shotgun test/config.ru -p #{PORT} --server thin" + system "bundle exec shotgun test/config.ru -p #{PORT} --server thin" end task :open do From 997bf8ae03b1cb8d945c4d2a43f5661b1041100b Mon Sep 17 00:00:00 2001 From: Dangyi Liu Date: Thu, 23 Jun 2016 22:55:18 +0800 Subject: [PATCH 02/72] Build the script using webpack and ready to rock See liudangyi/jquery-ujs#2 Note: shotgun has a delay in handling HTTP request and may break the test from time to time. So we call test:server instead of test:reloadable in development. --- .gitignore | 1 + Rakefile | 15 ++++++++++++++- dist/.gitignore | 2 ++ package.json | 30 ++++++++++++++++++++++++++++++ test/server.rb | 2 +- test/views/layout.erb | 2 +- webpack.config.js | 15 +++++++++++++++ 7 files changed, 64 insertions(+), 3 deletions(-) create mode 100644 dist/.gitignore create mode 100644 package.json create mode 100644 webpack.config.js diff --git a/.gitignore b/.gitignore index 251f2cfc..9a7ed07f 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ node_modules .bundle .DS_Store *~ +/npm-debug.log diff --git a/Rakefile b/Rakefile index 049051a6..0afb95ea 100644 --- a/Rakefile +++ b/Rakefile @@ -1,5 +1,18 @@ desc %(Starts the test server and opens it in a web browser) -multitask :default => ['test:server', 'test:open'] +multitask :default => ['webpack:build', 'test:server', 'test:open'] +multitask :develop => ['webpack:reloadable', 'test:server', 'test:open'] + +namespace :webpack do + desc %(Build source files into dist/rails.js) + task :build do + system "npm run build" + end + + desc %(Build dist/rails.js with reloading, for development purpose) + task :reloadable do + system "npm run dev" + end +end PORT = 4567 diff --git a/dist/.gitignore b/dist/.gitignore new file mode 100644 index 00000000..d6b7ef32 --- /dev/null +++ b/dist/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/package.json b/package.json new file mode 100644 index 00000000..0c0e61c0 --- /dev/null +++ b/package.json @@ -0,0 +1,30 @@ +{ + "name": "rails-ujs", + "version": "0.0.1", + "description": "Unobtrusive JavaScript used in Rails", + "main": "dist/rails.js", + "directories": { + "test": "test" + }, + "scripts": { + "test": "rake", + "dev": "webpack -d --watch", + "build": "webpack -p" + }, + "repository": { + "type": "git", + "url": "https://github.com/liudangyi/jquery-ujs.git" + }, + "author": { + "name": "All contributors", + "url": "https://github.com/liudangyi/jquery-ujs/graphs/contributors" + }, + "license": "MIT", + "bugs": { + "url": "https://github.com/liudangyi/jquery-ujs/issues" + }, + "homepage": "https://github.com/liudangyi/jquery-ujs#readme", + "devDependencies": { + "webpack": "^1.13.1" + } +} diff --git a/test/server.rb b/test/server.rb index 85f11db2..abea0dbd 100644 --- a/test/server.rb +++ b/test/server.rb @@ -3,7 +3,7 @@ JQUERY_VERSIONS = %w[ 1.8.0 1.8.1 1.8.2 1.8.3 1.9.0 1.9.1 1.10.0 1.10.1 1.10.2 1.11.0 2.0.0 2.1.0].freeze -use Rack::Static, :urls => ["/src"], :root => File.expand_path('..', settings.root) +use Rack::Static, :urls => ["/dist"], :root => File.expand_path('..', settings.root) helpers do def jquery_link version diff --git a/test/views/layout.erb b/test/views/layout.erb index eb791b6a..237cc448 100644 --- a/test/views/layout.erb +++ b/test/views/layout.erb @@ -27,7 +27,7 @@ $.rails.linkClickSelector += ', a[data-custom-remote-link]'; }); - <%= script_tag "/src/rails.js" %> + <%= script_tag "/dist/rails.js" %> diff --git a/webpack.config.js b/webpack.config.js new file mode 100644 index 00000000..0343f0e8 --- /dev/null +++ b/webpack.config.js @@ -0,0 +1,15 @@ +module.exports = { + entry: './src/rails.js', + output: { + path: 'dist', + filename: 'rails.js', + }, + module: { + loaders: [ + // { + // test: /\.js$/, + // loader: 'babel' + // } + ], + }, +} From 20b1859fd68731b546257e491f0cff5a9d0a737a Mon Sep 17 00:00:00 2001 From: Dangyi Liu Date: Thu, 23 Jun 2016 23:28:54 +0800 Subject: [PATCH 03/72] Remove .jshintrc because it's too old --- .jshintrc | 71 ------------------------------------------------------- 1 file changed, 71 deletions(-) delete mode 100644 .jshintrc diff --git a/.jshintrc b/.jshintrc deleted file mode 100644 index 9bfd6603..00000000 --- a/.jshintrc +++ /dev/null @@ -1,71 +0,0 @@ -{ - "maxerr" : 50, // {int} Maximum error before stopping - - // Enforcing - "bitwise" : true, // true: Prohibit bitwise operators (&, |, ^, etc.) - "camelcase" : true, // true: Identifiers must be in camelCase - "curly" : false, // true: Require {} for every new block or scope - "eqeqeq" : true, // true: Require triple equals (===) for comparison - "forin" : true, // true: Require filtering for..in loops with obj.hasOwnProperty() - "freeze" : true, // true: prohibits overwriting prototypes of native objects such as Array, Date etc. - "immed" : false, // true: Require immediate invocations to be wrapped in parens e.g. `(function () { } ());` - "indent" : 2, // {int} Number of spaces to use for indentation - "latedef" : false, // true: Require variables/functions to be defined before being used - "newcap" : false, // true: Require capitalization of all constructor functions e.g. `new F()` - "noarg" : true, // true: Prohibit use of `arguments.caller` and `arguments.callee` - "noempty" : true, // true: Prohibit use of empty blocks - "nonbsp" : true, // true: Prohibit "non-breaking whitespace" characters. - "nonew" : false, // true: Prohibit use of constructors for side-effects (without assignment) - "plusplus" : false, // true: Prohibit use of `++` & `--` - "quotmark" : "single", // Quotation mark consistency: - // false : do nothing (default) - // true : ensure whatever is used is consistent - // "single" : require single quotes - // "double" : require double quotes - "undef" : true, // true: Require all non-global variables to be declared (prevents global leaks) - "unused" : true, // Unused variables: - // true : all variables, last function parameter - // "vars" : all variables only - // "strict" : all variables, all function parameters - "strict" : true, // true: Requires all functions run in ES5 Strict Mode - "maxparams" : false, // {int} Max number of formal params allowed per function - "maxdepth" : false, // {int} Max depth of nested blocks (within functions) - "maxstatements" : false, // {int} Max number statements per function - "maxcomplexity" : false, // {int} Max cyclomatic complexity per function - "maxlen" : false, // {int} Max number of characters per line - - // Relaxing - "asi" : false, // true: Tolerate Automatic Semicolon Insertion (no semicolons) - "boss" : false, // true: Tolerate assignments where comparisons would be expected - "debug" : false, // true: Allow debugger statements e.g. browser breakpoints. - "eqnull" : false, // true: Tolerate use of `== null` - "es5" : false, // true: Allow ES5 syntax (ex: getters and setters) - "esnext" : false, // true: Allow ES.next (ES6) syntax (ex: `const`) - "moz" : false, // true: Allow Mozilla specific syntax (extends and overrides esnext features) - // (ex: `for each`, multiple try/catch, function expression…) - "evil" : false, // true: Tolerate use of `eval` and `new Function()` - "expr" : false, // true: Tolerate `ExpressionStatement` as Programs - "funcscope" : false, // true: Tolerate defining variables inside control statements - "globalstrict" : false, // true: Allow global "use strict" (also enables 'strict') - "iterator" : false, // true: Tolerate using the `__iterator__` property - "lastsemic" : false, // true: Tolerate omitting a semicolon for the last statement of a 1-line block - "laxbreak" : false, // true: Tolerate possibly unsafe line breakings - "laxcomma" : false, // true: Tolerate comma-first style coding - "loopfunc" : false, // true: Tolerate functions being defined in loops - "multistr" : false, // true: Tolerate multi-line strings - "noyield" : false, // true: Tolerate generator functions with no yield statement in them. - "notypeof" : false, // true: Tolerate invalid typeof operator values - "proto" : false, // true: Tolerate using the `__proto__` property - "scripturl" : false, // true: Tolerate script-targeted URLs - "shadow" : false, // true: Allows re-define variables later in code e.g. `var x=1; x=2;` - "sub" : false, // true: Tolerate using `[]` notation when it can still be expressed in dot notation - "supernew" : false, // true: Tolerate `new function () { ... };` and `new Object;` - "validthis" : false, // true: Tolerate using this in a non-constructor function - - // Environments - "browser" : true, // Web Browser (window, document, etc) - "jquery" : true, - "devel" : true, // Development/debugging (alert, confirm, etc) - - "globals" : {} -} From 6b812b556c07503bdd170342df306405ff6cdba0 Mon Sep 17 00:00:00 2001 From: Dangyi Liu Date: Fri, 24 Jun 2016 16:18:00 +0800 Subject: [PATCH 04/72] Remove all semicolons from JavaScript files See liudangyi/jquery-ujs#3 --- src/rails.js | 354 +++++++++---------- test/public/test/call-remote-callbacks.js | 412 +++++++++++----------- test/public/test/call-remote.js | 162 ++++----- test/public/test/csrf-refresh.js | 18 +- test/public/test/csrf-token.js | 28 +- test/public/test/data-confirm.js | 232 ++++++------ test/public/test/data-disable-with.js | 385 ++++++++++---------- test/public/test/data-disable.js | 302 ++++++++-------- test/public/test/data-method.js | 66 ++-- test/public/test/data-remote.js | 254 ++++++------- test/public/test/override.js | 60 ++-- test/public/test/settings.js | 52 +-- 12 files changed, 1162 insertions(+), 1163 deletions(-) diff --git a/src/rails.js b/src/rails.js index 9e192a2e..cc7f45a7 100644 --- a/src/rails.js +++ b/src/rails.js @@ -12,15 +12,15 @@ // Cut down on the number of issues from people inadvertently including jquery_ujs twice // by detecting and raising an error when it happens. - 'use strict'; + 'use strict' if ( $.rails !== undefined ) { - $.error('jquery-ujs has already been loaded!'); + $.error('jquery-ujs has already been loaded!') } // Shorthand to make it a little easier to call public rails functions from within rails.js - var rails; - var $document = $(document); + var rails + var $document = $(document) $.rails = rails = { // Link elements bound by jquery-ujs @@ -58,86 +58,86 @@ // Up-to-date Cross-Site Request Forgery token csrfToken: function() { - return $('meta[name=csrf-token]').attr('content'); + return $('meta[name=csrf-token]').attr('content') }, // URL param that must contain the CSRF token csrfParam: function() { - return $('meta[name=csrf-param]').attr('content'); + return $('meta[name=csrf-param]').attr('content') }, // Make sure that every Ajax request sends the CSRF token CSRFProtection: function(xhr) { - var token = rails.csrfToken(); - if (token) xhr.setRequestHeader('X-CSRF-Token', token); + var token = rails.csrfToken() + if (token) xhr.setRequestHeader('X-CSRF-Token', token) }, // Make sure that all forms have actual up-to-date tokens (cached forms contain old ones) refreshCSRFTokens: function(){ - $('form input[name="' + rails.csrfParam() + '"]').val(rails.csrfToken()); + $('form input[name="' + rails.csrfParam() + '"]').val(rails.csrfToken()) }, // Triggers an event on an element and returns false if the event result is false fire: function(obj, name, data) { - var event = $.Event(name); - obj.trigger(event, data); - return event.result !== false; + var event = $.Event(name) + obj.trigger(event, data) + return event.result !== false }, // Default confirm dialog, may be overridden with custom confirm dialog in $.rails.confirm confirm: function(message) { - return confirm(message); + return confirm(message) }, // Default ajax function, may be overridden with custom function in $.rails.ajax ajax: function(options) { - return $.ajax(options); + return $.ajax(options) }, // Default way to get an element's href. May be overridden at $.rails.href. href: function(element) { - return element[0].href; + return element[0].href }, // Checks "data-remote" if true to handle the request through a XHR request. isRemote: function(element) { - return element.data('remote') !== undefined && element.data('remote') !== false; + return element.data('remote') !== undefined && element.data('remote') !== false }, // Submits "remote" forms and links with ajax handleRemote: function(element) { - var method, url, data, withCredentials, dataType, options; + var method, url, data, withCredentials, dataType, options if (rails.fire(element, 'ajax:before')) { - withCredentials = element.data('with-credentials') || null; - dataType = element.data('type') || ($.ajaxSettings && $.ajaxSettings.dataType); + withCredentials = element.data('with-credentials') || null + dataType = element.data('type') || ($.ajaxSettings && $.ajaxSettings.dataType) if (element.is('form')) { - method = element.data('ujs:submit-button-formmethod') || element.attr('method'); - url = element.data('ujs:submit-button-formaction') || element.attr('action'); - data = $(element[0]).serializeArray(); + method = element.data('ujs:submit-button-formmethod') || element.attr('method') + url = element.data('ujs:submit-button-formaction') || element.attr('action') + data = $(element[0]).serializeArray() // memoized value from clicked submit button - var button = element.data('ujs:submit-button'); + var button = element.data('ujs:submit-button') if (button) { - data.push(button); - element.data('ujs:submit-button', null); + data.push(button) + element.data('ujs:submit-button', null) } - element.data('ujs:submit-button-formmethod', null); - element.data('ujs:submit-button-formaction', null); + element.data('ujs:submit-button-formmethod', null) + element.data('ujs:submit-button-formaction', null) } else if (element.is(rails.inputChangeSelector)) { - method = element.data('method'); - url = element.data('url'); - data = element.serialize(); - if (element.data('params')) data = data + '&' + element.data('params'); + method = element.data('method') + url = element.data('url') + data = element.serialize() + if (element.data('params')) data = data + '&' + element.data('params') } else if (element.is(rails.buttonClickSelector)) { - method = element.data('method') || 'get'; - url = element.data('url'); - data = element.serialize(); - if (element.data('params')) data = data + '&' + element.data('params'); + method = element.data('method') || 'get' + url = element.data('url') + data = element.serialize() + if (element.data('params')) data = data + '&' + element.data('params') } else { - method = element.data('method'); - url = rails.href(element); - data = element.data('params') || null; + method = element.data('method') + url = rails.href(element) + data = element.data('params') || null } options = { @@ -145,53 +145,53 @@ // stopping the "ajax:beforeSend" event will cancel the ajax request beforeSend: function(xhr, settings) { if (settings.dataType === undefined) { - xhr.setRequestHeader('accept', '*/*;q=0.5, ' + settings.accepts.script); + xhr.setRequestHeader('accept', '*/*;q=0.5, ' + settings.accepts.script) } if (rails.fire(element, 'ajax:beforeSend', [xhr, settings])) { - element.trigger('ajax:send', xhr); + element.trigger('ajax:send', xhr) } else { - return false; + return false } }, success: function(data, status, xhr) { - element.trigger('ajax:success', [data, status, xhr]); + element.trigger('ajax:success', [data, status, xhr]) }, complete: function(xhr, status) { - element.trigger('ajax:complete', [xhr, status]); + element.trigger('ajax:complete', [xhr, status]) }, error: function(xhr, status, error) { - element.trigger('ajax:error', [xhr, status, error]); + element.trigger('ajax:error', [xhr, status, error]) }, crossDomain: rails.isCrossDomain(url) - }; + } // There is no withCredentials for IE6-8 when // "Enable native XMLHTTP support" is disabled if (withCredentials) { options.xhrFields = { withCredentials: withCredentials - }; + } } // Only pass url to `ajax` options if not blank - if (url) { options.url = url; } + if (url) { options.url = url } - return rails.ajax(options); + return rails.ajax(options) } else { - return false; + return false } }, // Determines if the request is a cross domain request. isCrossDomain: function(url) { - var originAnchor = document.createElement('a'); - originAnchor.href = location.href; - var urlAnchor = document.createElement('a'); + var originAnchor = document.createElement('a') + originAnchor.href = location.href + var urlAnchor = document.createElement('a') try { - urlAnchor.href = url; + urlAnchor.href = url // This is a workaround to a IE bug. - urlAnchor.href = urlAnchor.href; + urlAnchor.href = urlAnchor.href // If URL protocol is false or is a string containing a single colon // *and* host are false, assume it is not a cross-domain request @@ -200,10 +200,10 @@ // protocol and host. return !(((!urlAnchor.protocol || urlAnchor.protocol === ':') && !urlAnchor.host) || (originAnchor.protocol + '//' + originAnchor.host === - urlAnchor.protocol + '//' + urlAnchor.host)); + urlAnchor.protocol + '//' + urlAnchor.host)) } catch (e) { // If there is an error parsing the URL, assume it is crossDomain. - return true; + return true } }, @@ -216,23 +216,23 @@ csrfToken = rails.csrfToken(), csrfParam = rails.csrfParam(), form = $('
'), - metadataInput = ''; + metadataInput = '' if (csrfParam !== undefined && csrfToken !== undefined && !rails.isCrossDomain(href)) { - metadataInput += ''; + metadataInput += '' } - if (target) { form.attr('target', target); } + if (target) { form.attr('target', target) } - form.hide().append(metadataInput).appendTo('body'); - form.submit(); + form.hide().append(metadataInput).appendTo('body') + form.submit() }, // Helper function that returns form elements that match the specified CSS selector // If form is actually a "form" element this will return associated elements outside the from that have // the html form attribute set formElements: function(form, selector) { - return form.is('form') ? $(form[0].elements).filter(selector) : form.find(selector); + return form.is('form') ? $(form[0].elements).filter(selector) : form.find(selector) }, /* Disables form elements: @@ -242,23 +242,23 @@ */ disableFormElements: function(form) { rails.formElements(form, rails.disableSelector).each(function() { - rails.disableFormElement($(this)); - }); + rails.disableFormElement($(this)) + }) }, disableFormElement: function(element) { - var method, replacement; + var method, replacement - method = element.is('button') ? 'html' : 'val'; - replacement = element.data('disable-with'); + method = element.is('button') ? 'html' : 'val' + replacement = element.data('disable-with') if (replacement !== undefined) { - element.data('ujs:enable-with', element[method]()); - element[method](replacement); + element.data('ujs:enable-with', element[method]()) + element[method](replacement) } - element.prop('disabled', true); - element.data('ujs:disabled', true); + element.prop('disabled', true) + element.data('ujs:disabled', true) }, /* Re-enables disabled form elements: @@ -267,18 +267,18 @@ */ enableFormElements: function(form) { rails.formElements(form, rails.enableSelector).each(function() { - rails.enableFormElement($(this)); - }); + rails.enableFormElement($(this)) + }) }, enableFormElement: function(element) { - var method = element.is('button') ? 'html' : 'val'; + var method = element.is('button') ? 'html' : 'val' if (element.data('ujs:enable-with') !== undefined) { - element[method](element.data('ujs:enable-with')); - element.removeData('ujs:enable-with'); // clean up cache + element[method](element.data('ujs:enable-with')) + element.removeData('ujs:enable-with') // clean up cache } - element.prop('disabled', false); - element.removeData('ujs:disabled'); + element.prop('disabled', false) + element.removeData('ujs:disabled') }, /* For 'data-confirm' attribute: @@ -286,25 +286,25 @@ - Shows the confirmation dialog - Fires the `confirm:complete` event - Returns `true` if no function stops the chain and user chose yes; `false` otherwise. + Returns `true` if no function stops the chain and user chose yes `false` otherwise. Attaching a handler to the element's `confirm` event that returns a `falsy` value cancels the confirmation dialog. Attaching a handler to the element's `confirm:complete` event that returns a `falsy` value makes this function return false. The `confirm:complete` event is fired whether or not the user answered true or false to the dialog. */ allowAction: function(element) { var message = element.data('confirm'), - answer = false, callback; - if (!message) { return true; } + answer = false, callback + if (!message) { return true } if (rails.fire(element, 'confirm')) { try { - answer = rails.confirm(message); + answer = rails.confirm(message) } catch (e) { - (console.error || console.log).call(console, e.stack || e); + (console.error || console.log).call(console, e.stack || e) } - callback = rails.fire(element, 'confirm:complete', [answer]); + callback = rails.fire(element, 'confirm:complete', [answer]) } - return answer && callback; + return answer && callback }, // Helper function which checks for blank inputs in a form that match the specified CSS selector @@ -316,16 +316,16 @@ radioName, selector = specifiedSelector || 'input,textarea', requiredInputs = form.find(selector), - checkedRadioButtonNames = {}; + checkedRadioButtonNames = {} requiredInputs.each(function() { - input = $(this); + input = $(this) if (input.is('input[type=radio]')) { // Don't count unchecked required radio as blank if other radio with same name is checked, // regardless of whether same-name radio input has required attribute or not. The spec // states https://www.w3.org/TR/html5/forms.html#the-required-attribute - radioName = input.attr('name'); + radioName = input.attr('name') // Skip if we've already seen the radio with this name. if (!checkedRadioButtonNames[radioName]) { @@ -333,65 +333,65 @@ // If none checked if (form.find('input[type=radio]:checked[name="' + radioName + '"]').length === 0) { radiosForNameWithNoneSelected = form.find( - 'input[type=radio][name="' + radioName + '"]'); - foundInputs = foundInputs.add(radiosForNameWithNoneSelected); + 'input[type=radio][name="' + radioName + '"]') + foundInputs = foundInputs.add(radiosForNameWithNoneSelected) } // We only need to check each name once. - checkedRadioButtonNames[radioName] = radioName; + checkedRadioButtonNames[radioName] = radioName } } else { - valueToCheck = input.is('input[type=checkbox],input[type=radio]') ? input.is(':checked') : !!input.val(); + valueToCheck = input.is('input[type=checkbox],input[type=radio]') ? input.is(':checked') : !!input.val() if (valueToCheck === nonBlank) { - foundInputs = foundInputs.add(input); + foundInputs = foundInputs.add(input) } } - }); - return foundInputs.length ? foundInputs : false; + }) + return foundInputs.length ? foundInputs : false }, // Helper function which checks for non-blank inputs in a form that match the specified CSS selector nonBlankInputs: function(form, specifiedSelector) { - return rails.blankInputs(form, specifiedSelector, true); // true specifies nonBlank + return rails.blankInputs(form, specifiedSelector, true) // true specifies nonBlank }, // Helper function, needed to provide consistent behavior in IE stopEverything: function(e) { - $(e.target).trigger('ujs:everythingStopped'); - e.stopImmediatePropagation(); - return false; + $(e.target).trigger('ujs:everythingStopped') + e.stopImmediatePropagation() + return false }, // Replace element's html with the 'data-disable-with' after storing original html // and prevent clicking on it disableElement: function(element) { - var replacement = element.data('disable-with'); + var replacement = element.data('disable-with') if (replacement !== undefined) { - element.data('ujs:enable-with', element.html()); // store enabled state - element.html(replacement); + element.data('ujs:enable-with', element.html()) // store enabled state + element.html(replacement) } element.bind('click.railsDisable', function(e) { // prevent further clicking - return rails.stopEverything(e); - }); - element.data('ujs:disabled', true); + return rails.stopEverything(e) + }) + element.data('ujs:disabled', true) }, // Restore element to its original state which was disabled by 'disableElement' above enableElement: function(element) { if (element.data('ujs:enable-with') !== undefined) { - element.html(element.data('ujs:enable-with')); // set to old enabled state - element.removeData('ujs:enable-with'); // clean up cache + element.html(element.data('ujs:enable-with')) // set to old enabled state + element.removeData('ujs:enable-with') // clean up cache } - element.unbind('click.railsDisable'); // enable element - element.removeData('ujs:disabled'); + element.unbind('click.railsDisable') // enable element + element.removeData('ujs:disabled') } - }; + } if (rails.fire($document, 'rails:attachBindings')) { - $.ajaxPrefilter(function(options, originalOptions, xhr){ if ( !options.crossDomain ) { rails.CSRFProtection(xhr); }}); + $.ajaxPrefilter(function(options, originalOptions, xhr){ if ( !options.crossDomain ) { rails.CSRFProtection(xhr) }}) // This event works the same as the load event, except that it fires every // time the page is loaded. @@ -400,156 +400,156 @@ // See https://developer.mozilla.org/en-US/docs/Using_Firefox_1.5_caching $(window).on('pageshow.rails', function () { $($.rails.enableSelector).each(function () { - var element = $(this); + var element = $(this) if (element.data('ujs:disabled')) { - $.rails.enableFormElement(element); + $.rails.enableFormElement(element) } - }); + }) $($.rails.linkDisableSelector).each(function () { - var element = $(this); + var element = $(this) if (element.data('ujs:disabled')) { - $.rails.enableElement(element); + $.rails.enableElement(element) } - }); - }); + }) + }) $document.delegate(rails.linkDisableSelector, 'ajax:complete', function() { - rails.enableElement($(this)); - }); + rails.enableElement($(this)) + }) $document.delegate(rails.buttonDisableSelector, 'ajax:complete', function() { - rails.enableFormElement($(this)); - }); + rails.enableFormElement($(this)) + }) $document.delegate(rails.linkClickSelector, 'click.rails', function(e) { - var link = $(this), method = link.data('method'), data = link.data('params'), metaClick = e.metaKey || e.ctrlKey; - if (!rails.allowAction(link)) return rails.stopEverything(e); + var link = $(this), method = link.data('method'), data = link.data('params'), metaClick = e.metaKey || e.ctrlKey + if (!rails.allowAction(link)) return rails.stopEverything(e) - if (!metaClick && link.is(rails.linkDisableSelector)) rails.disableElement(link); + if (!metaClick && link.is(rails.linkDisableSelector)) rails.disableElement(link) if (rails.isRemote(link)) { - if (metaClick && (!method || method === 'GET') && !data) { return true; } + if (metaClick && (!method || method === 'GET') && !data) { return true } - var handleRemote = rails.handleRemote(link); + var handleRemote = rails.handleRemote(link) // Response from rails.handleRemote() will either be false or a deferred object promise. if (handleRemote === false) { - rails.enableElement(link); + rails.enableElement(link) } else { - handleRemote.fail( function() { rails.enableElement(link); } ); + handleRemote.fail( function() { rails.enableElement(link) } ) } - return false; + return false } else if (method) { - rails.handleMethod(link); - return false; + rails.handleMethod(link) + return false } - }); + }) $document.delegate(rails.buttonClickSelector, 'click.rails', function(e) { - var button = $(this); + var button = $(this) - if (!rails.allowAction(button) || !rails.isRemote(button)) return rails.stopEverything(e); + if (!rails.allowAction(button) || !rails.isRemote(button)) return rails.stopEverything(e) - if (button.is(rails.buttonDisableSelector)) rails.disableFormElement(button); + if (button.is(rails.buttonDisableSelector)) rails.disableFormElement(button) - var handleRemote = rails.handleRemote(button); + var handleRemote = rails.handleRemote(button) // Response from rails.handleRemote() will either be false or a deferred object promise. if (handleRemote === false) { - rails.enableFormElement(button); + rails.enableFormElement(button) } else { - handleRemote.fail( function() { rails.enableFormElement(button); } ); + handleRemote.fail( function() { rails.enableFormElement(button) } ) } - return false; - }); + return false + }) $document.delegate(rails.inputChangeSelector, 'change.rails', function(e) { - var link = $(this); - if (!rails.allowAction(link) || !rails.isRemote(link)) return rails.stopEverything(e); + var link = $(this) + if (!rails.allowAction(link) || !rails.isRemote(link)) return rails.stopEverything(e) - rails.handleRemote(link); - return false; - }); + rails.handleRemote(link) + return false + }) $document.delegate(rails.formSubmitSelector, 'submit.rails', function(e) { var form = $(this), remote = rails.isRemote(form), blankRequiredInputs, - nonBlankFileInputs; + nonBlankFileInputs - if (!rails.allowAction(form)) return rails.stopEverything(e); + if (!rails.allowAction(form)) return rails.stopEverything(e) // Skip other logic when required values are missing or file upload is present if (form.attr('novalidate') === undefined) { if (form.data('ujs:formnovalidate-button') === undefined) { - blankRequiredInputs = rails.blankInputs(form, rails.requiredInputSelector, false); + blankRequiredInputs = rails.blankInputs(form, rails.requiredInputSelector, false) if (blankRequiredInputs && rails.fire(form, 'ajax:aborted:required', [blankRequiredInputs])) { - return rails.stopEverything(e); + return rails.stopEverything(e) } } else { // Clear the formnovalidate in case the next button click is not on a formnovalidate button // Not strictly necessary to do here, since it is also reset on each button click, but just to be certain - form.data('ujs:formnovalidate-button', undefined); + form.data('ujs:formnovalidate-button', undefined) } } if (remote) { - nonBlankFileInputs = rails.nonBlankInputs(form, rails.fileInputSelector); + nonBlankFileInputs = rails.nonBlankInputs(form, rails.fileInputSelector) if (nonBlankFileInputs) { // Slight timeout so that the submit button gets properly serialized // (make it easy for event handler to serialize form without disabled values) - setTimeout(function(){ rails.disableFormElements(form); }, 13); - var aborted = rails.fire(form, 'ajax:aborted:file', [nonBlankFileInputs]); + setTimeout(function(){ rails.disableFormElements(form) }, 13) + var aborted = rails.fire(form, 'ajax:aborted:file', [nonBlankFileInputs]) // Re-enable form elements if event bindings return false (canceling normal form submission) - if (!aborted) { setTimeout(function(){ rails.enableFormElements(form); }, 13); } + if (!aborted) { setTimeout(function(){ rails.enableFormElements(form) }, 13) } - return aborted; + return aborted } - rails.handleRemote(form); - return false; + rails.handleRemote(form) + return false } else { // Slight timeout so that the submit button gets properly serialized - setTimeout(function(){ rails.disableFormElements(form); }, 13); + setTimeout(function(){ rails.disableFormElements(form) }, 13) } - }); + }) $document.delegate(rails.formInputClickSelector, 'click.rails', function(event) { - var button = $(this); + var button = $(this) - if (!rails.allowAction(button)) return rails.stopEverything(event); + if (!rails.allowAction(button)) return rails.stopEverything(event) // Register the pressed submit button var name = button.attr('name'), - data = name ? {name:name, value:button.val()} : null; + data = name ? {name:name, value:button.val()} : null - var form = button.closest('form'); + var form = button.closest('form') if (form.length === 0) { - form = $('#' + button.attr('form')); + form = $('#' + button.attr('form')) } - form.data('ujs:submit-button', data); + form.data('ujs:submit-button', data) // Save attributes from button - form.data('ujs:formnovalidate-button', button.attr('formnovalidate')); - form.data('ujs:submit-button-formaction', button.attr('formaction')); - form.data('ujs:submit-button-formmethod', button.attr('formmethod')); - }); + form.data('ujs:formnovalidate-button', button.attr('formnovalidate')) + form.data('ujs:submit-button-formaction', button.attr('formaction')) + form.data('ujs:submit-button-formmethod', button.attr('formmethod')) + }) $document.delegate(rails.formSubmitSelector, 'ajax:send.rails', function(event) { - if (this === event.target) rails.disableFormElements($(this)); - }); + if (this === event.target) rails.disableFormElements($(this)) + }) $document.delegate(rails.formSubmitSelector, 'ajax:complete.rails', function(event) { - if (this === event.target) rails.enableFormElements($(this)); - }); + if (this === event.target) rails.enableFormElements($(this)) + }) $(function(){ - rails.refreshCSRFTokens(); - }); + rails.refreshCSRFTokens() + }) } -})( jQuery ); +})( jQuery ) diff --git a/test/public/test/call-remote-callbacks.js b/test/public/test/call-remote-callbacks.js index e7ee0dab..80fee6d0 100644 --- a/test/public/test/call-remote-callbacks.js +++ b/test/public/test/call-remote-callbacks.js @@ -4,39 +4,39 @@ module('call-remote-callbacks', { setup: function() { $('#qunit-fixture').append($('
', { action: '/echo', method: 'get', 'data-remote': 'true' - })); + })) }, teardown: function() { - $(document).undelegate('form[data-remote]', 'ajax:beforeSend'); - $(document).undelegate('form[data-remote]', 'ajax:before'); - $(document).undelegate('form[data-remote]', 'ajax:send'); - $(document).undelegate('form[data-remote]', 'ajax:complete'); - $(document).undelegate('form[data-remote]', 'ajax:success'); - $(document).unbind('ajaxStop'); - $(document).unbind('iframe:loading'); + $(document).undelegate('form[data-remote]', 'ajax:beforeSend') + $(document).undelegate('form[data-remote]', 'ajax:before') + $(document).undelegate('form[data-remote]', 'ajax:send') + $(document).undelegate('form[data-remote]', 'ajax:complete') + $(document).undelegate('form[data-remote]', 'ajax:success') + $(document).unbind('ajaxStop') + $(document).unbind('iframe:loading') } -}); +}) function start_after_submit(form) { form.bind('ajax:complete', function() { - ok(true, 'ajax:complete'); - start(); - }); + ok(true, 'ajax:complete') + start() + }) } function submit(fn) { - var form = $('form'); - start_after_submit(form); + var form = $('form') + start_after_submit(form) - if (fn) fn(form); - form.trigger('submit'); + if (fn) fn(form) + form.trigger('submit') } function submit_with_button(submit_button) { - var form = $('form'); - start_after_submit(form); + var form = $('form') + start_after_submit(form) - submit_button.trigger('click'); + submit_button.trigger('click') } asyncTest('modifying form fields with "ajax:before" sends modified data in request', 4, function(){ @@ -44,200 +44,200 @@ asyncTest('modifying form fields with "ajax:before" sends modified data in reque .append($('')) .append($('')) .bind('ajax:before', function() { - var form = $(this); + var form = $(this) form .append($('',{name: 'other_user_name',value: 'jonathan'})) - .find('input[name="removed_user_name"]').remove(); + .find('input[name="removed_user_name"]').remove() form - .find('input[name="user_name"]').val('steve'); - }); + .find('input[name="user_name"]').val('steve') + }) submit(function(form) { form.bind('ajax:success', function(e, data, status, xhr) { - equal(data.params.user_name, 'steve', 'modified field value should have been submitted'); - equal(data.params.other_user_name, 'jonathan', 'added field value should have been submitted'); - equal(data.params.removed_user_name, undefined, 'removed field value should be undefined'); - }); - }); -}); + equal(data.params.user_name, 'steve', 'modified field value should have been submitted') + equal(data.params.other_user_name, 'jonathan', 'added field value should have been submitted') + equal(data.params.removed_user_name, undefined, 'removed field value should be undefined') + }) + }) +}) asyncTest('modifying data("type") with "ajax:before" requests new dataType in request', 2, function(){ $('form[data-remote]').data('type','html') .bind('ajax:before', function() { - var form = $(this); - form.data('type','xml'); - }); + var form = $(this) + form.data('type','xml') + }) submit(function(form) { form.bind('ajax:beforeSend', function(e, xhr, settings) { - equal(settings.dataType, 'xml', 'modified dataType should have been requested'); - }); - }); -}); + equal(settings.dataType, 'xml', 'modified dataType should have been requested') + }) + }) +}) asyncTest('setting data("with-credentials",true) with "ajax:before" uses new setting in request', 2, function(){ $('form[data-remote]').data('with-credentials',false) .bind('ajax:before', function() { - var form = $(this); - form.data('with-credentials',true); - }); + var form = $(this) + form.data('with-credentials',true) + }) submit(function(form) { form.bind('ajax:beforeSend', function(e, xhr, settings) { - equal(settings.xhrFields && settings.xhrFields.withCredentials, true, 'setting modified in ajax:before should have forced withCredentials request'); - }); - }); -}); + equal(settings.xhrFields && settings.xhrFields.withCredentials, true, 'setting modified in ajax:before should have forced withCredentials request') + }) + }) +}) asyncTest('stopping the "ajax:beforeSend" event aborts the request', 1, function() { submit(function(form) { form.bind('ajax:beforeSend', function() { - ok(true, 'aborting request in ajax:beforeSend'); - return false; - }); + ok(true, 'aborting request in ajax:beforeSend') + return false + }) form.unbind('ajax:send').bind('ajax:send', function() { - ok(false, 'ajax:send should not run'); - }); + ok(false, 'ajax:send should not run') + }) form.unbind('ajax:complete').bind('ajax:complete', function() { - ok(false, 'ajax:complete should not run'); - }); + ok(false, 'ajax:complete should not run') + }) form.bind('ajax:error', function(e, xhr, status, error) { - ok(false, 'ajax:error should not run'); - }); + ok(false, 'ajax:error should not run') + }) $(document).bind('ajaxStop', function() { - start(); - }); - }); -}); + start() + }) + }) +}) asyncTest('blank required form input field should abort request and trigger "ajax:aborted:required" event', 5, function() { $(document).bind('iframe:loading', function() { - ok(false, 'form should not get submitted'); - }); + ok(false, 'form should not get submitted') + }) var form = $('form[data-remote]') .append($('')) .append($('')) .bind('ajax:beforeSend', function() { - ok(false, 'ajax:beforeSend should not run'); + ok(false, 'ajax:beforeSend should not run') }) .bind('ajax:aborted:required', function(e,data){ - ok(data.length == 2, 'ajax:aborted:required event is passed all blank required inputs (jQuery objects)'); - ok(data.first().is('input[name="user_name"]') , 'ajax:aborted:required adds blank required input to data'); - ok(data.last().is('textarea[name="user_bio"]'), 'ajax:aborted:required adds blank required textarea to data'); - ok(true, 'ajax:aborted:required should run'); + ok(data.length == 2, 'ajax:aborted:required event is passed all blank required inputs (jQuery objects)') + ok(data.first().is('input[name="user_name"]') , 'ajax:aborted:required adds blank required input to data') + ok(data.last().is('textarea[name="user_bio"]'), 'ajax:aborted:required adds blank required textarea to data') + ok(true, 'ajax:aborted:required should run') }) - .trigger('submit'); + .trigger('submit') setTimeout(function() { - form.find('input[required],textarea[required]').val('Tyler'); - form.unbind('ajax:beforeSend'); - submit(); - }, 13); -}); + form.find('input[required],textarea[required]').val('Tyler') + form.unbind('ajax:beforeSend') + submit() + }, 13) +}) asyncTest('blank required form input for non-remote form should abort normal submission', 1, function() { var form = $('form[data-remote]') .append($('')) .removeAttr('data-remote') .bind('ujs:everythingStopped', function() { - ok(true, 'ujs:everythingStopped should run'); + ok(true, 'ujs:everythingStopped should run') }) - .trigger('submit'); + .trigger('submit') setTimeout(function() { - start(); - }, 13); -}); + start() + }, 13) +}) asyncTest('form should be submitted with blank required fields if handler is bound to "ajax:aborted:required" event that returns false', 1, function(){ var form = $('form[data-remote]') .append($('')) .bind('ajax:beforeSend', function() { - ok(true, 'ajax:beforeSend should run'); + ok(true, 'ajax:beforeSend should run') }) .bind('ajax:aborted:required', function() { - return false; + return false }) - .trigger('submit'); + .trigger('submit') setTimeout(function() { - start(); - }, 13); -}); + start() + }, 13) +}) asyncTest('disabled fields should not be included in blank required check', 2, function() { var form = $('form[data-remote]') .append($('')) .append($('')) .bind('ajax:beforeSend', function() { - ok(true, 'ajax:beforeSend should run'); + ok(true, 'ajax:beforeSend should run') }) .bind('ajax:aborted:required', function() { - ok(false, 'ajax:aborted:required should not run'); - }); + ok(false, 'ajax:aborted:required should not run') + }) - submit(); -}); + submit() +}) asyncTest('form should be submitted with blank required fields if it has the "novalidate" attribute', 2, function(){ var form = $('form[data-remote]') .append($('')) .attr("novalidate", "novalidate") .bind('ajax:beforeSend', function() { - ok(true, 'ajax:beforeSend should run'); + ok(true, 'ajax:beforeSend should run') }) .bind('ajax:aborted:required', function() { - ok(false, 'ajax:aborted:required should not run'); - }); + ok(false, 'ajax:aborted:required should not run') + }) - submit(); -}); + submit() +}) asyncTest('form should be submitted with blank required fields if the button has the "formnovalidate" attribute', 2, function(){ - var submit_button = $(''); + var submit_button = $('') var form = $('form[data-remote]') .append($('')) .append(submit_button) .bind('ajax:beforeSend', function() { - ok(true, 'ajax:beforeSend should run'); + ok(true, 'ajax:beforeSend should run') }) .bind('ajax:aborted:required', function() { - ok(false, 'ajax:aborted:required should not run'); - }); + ok(false, 'ajax:aborted:required should not run') + }) - submit_with_button(submit_button); -}); + submit_with_button(submit_button) +}) asyncTest('blank required form input for non-remote form with "novalidate" attribute should not abort normal submission', 1, function() { $(document).bind('iframe:loading', function() { - ok(true, 'form should get submitted'); - }); + ok(true, 'form should get submitted') + }) var form = $('form[data-remote]') .append($('')) .removeAttr('data-remote') .attr("novalidate","novalidate") - .trigger('submit'); + .trigger('submit') setTimeout(function() { - start(); - }, 13); -}); + start() + }, 13) +}) asyncTest('unchecked required checkbox should abort form submission', 1, function() { var form = $('form[data-remote]') .append($('')) .removeAttr('data-remote') .bind('ujs:everythingStopped', function() { - ok(true, 'ujs:everythingStopped should run'); + ok(true, 'ujs:everythingStopped should run') }) - .trigger('submit'); + .trigger('submit') setTimeout(function() { - start(); - }, 13); -}); + start() + }, 13) +}) asyncTest('unchecked required radio should abort form submission', 1, function() { var form = $('form[data-remote]') @@ -245,40 +245,40 @@ asyncTest('unchecked required radio should abort form submission', 1, function() .append($('')) .removeAttr('data-remote') .bind('ujs:everythingStopped', function() { - ok(true, 'ujs:everythingStopped should run'); + ok(true, 'ujs:everythingStopped should run') }) - .trigger('submit'); + .trigger('submit') setTimeout(function() { - start(); - }, 13); -}); + start() + }, 13) +}) asyncTest('required radio should only require one to be checked', 1, function() { $(document).bind('iframe:loading', function() { - ok(true, 'form should get submitted'); - }); + ok(true, 'form should get submitted') + }) var form = $('form[data-remote]') .append($('')) .append($('')) .removeAttr('data-remote') .bind('ujs:everythingStopped', function() { - ok(false, 'ujs:everythingStopped should not run'); + ok(false, 'ujs:everythingStopped should not run') }) .find('#checkme').prop('checked', true) .end() - .trigger('submit'); + .trigger('submit') setTimeout(function() { - start(); - }, 13); -}); + start() + }, 13) +}) asyncTest('required radio should only require one to be checked if not all radios are required', 1, function() { $(document).bind('iframe:loading', function() { - ok(true, 'form should get submitted'); - }); + ok(true, 'form should get submitted') + }) var form = $('form[data-remote]') // Check the radio that is not required @@ -289,16 +289,16 @@ asyncTest('required radio should only require one to be checked if not all radio .append($('')) .removeAttr('data-remote') .bind('ujs:everythingStopped', function() { - ok(false, 'ujs:everythingStopped should not run'); + ok(false, 'ujs:everythingStopped should not run') }) .find('#checkme').prop('checked', true) .end() - .trigger('submit'); + .trigger('submit') setTimeout(function() { - start(); - }, 13); -}); + start() + }, 13) +}) function skipIt() { // This test cannot work due to the security feature in browsers which makes the value @@ -308,158 +308,158 @@ function skipIt() { var form = $('form[data-remote]') .append($('')) .bind('ajax:beforeSend', function() { - ok(false, 'ajax:beforeSend should not run'); + ok(false, 'ajax:beforeSend should not run') }) .bind('iframe:loading', function() { - ok(true, 'form should get submitted'); + ok(true, 'form should get submitted') }) .bind('ajax:aborted:file', function(e,data) { - ok(data.length == 1, 'ajax:aborted:file event is passed all non-blank file inputs (jQuery objects)'); - ok(data.first().is('input[name="attachment"]') , 'ajax:aborted:file adds non-blank file input to data'); - ok(true, 'ajax:aborted:file event should run'); + ok(data.length == 1, 'ajax:aborted:file event is passed all non-blank file inputs (jQuery objects)') + ok(data.first().is('input[name="attachment"]') , 'ajax:aborted:file adds non-blank file input to data') + ok(true, 'ajax:aborted:file event should run') }) - .trigger('submit'); + .trigger('submit') setTimeout(function() { - form.find('input[type="file"]').val(''); - form.unbind('ajax:beforeSend'); - submit(); - }, 13); - }); + form.find('input[type="file"]').val('') + form.unbind('ajax:beforeSend') + submit() + }, 13) + }) asyncTest('file form input field should not abort remote request if file form input does not have a name attribute', 5, function() { var form = $('form[data-remote]') .append($('')) .bind('ajax:beforeSend', function() { - ok(true, 'ajax:beforeSend should run'); + ok(true, 'ajax:beforeSend should run') }) .bind('iframe:loading', function() { - ok(true, 'form should get submitted'); + ok(true, 'form should get submitted') }) .bind('ajax:aborted:file', function(e,data) { - ok(false, 'ajax:aborted:file should not run'); + ok(false, 'ajax:aborted:file should not run') }) - .trigger('submit'); + .trigger('submit') setTimeout(function() { - form.find('input[type="file"]').val(''); - form.unbind('ajax:beforeSend'); - submit(); - }, 13); - }); + form.find('input[type="file"]').val('') + form.unbind('ajax:beforeSend') + submit() + }, 13) + }) asyncTest('blank file input field should abort request entirely if handler bound to "ajax:aborted:file" event that returns false', 1, function() { var form = $('form[data-remote]') .append($('')) .bind('ajax:beforeSend', function() { - ok(false, 'ajax:beforeSend should not run'); + ok(false, 'ajax:beforeSend should not run') }) .bind('iframe:loading', function() { - ok(false, 'form should not get submitted'); + ok(false, 'form should not get submitted') }) .bind('ajax:aborted:file', function() { - return false; + return false }) - .trigger('submit'); + .trigger('submit') setTimeout(function() { - form.find('input[type="file"]').val(''); - form.unbind('ajax:beforeSend'); - submit(); - }, 13); - }); + form.find('input[type="file"]').val('') + form.unbind('ajax:beforeSend') + submit() + }, 13) + }) } asyncTest('"ajax:beforeSend" can be observed and stopped with event delegation', 1, function() { $(document).delegate('form[data-remote]', 'ajax:beforeSend', function() { - ok(true, 'ajax:beforeSend observed with event delegation'); - return false; - }); + ok(true, 'ajax:beforeSend observed with event delegation') + return false + }) submit(function(form) { form.unbind('ajax:send').bind('ajax:send', function() { - ok(false, 'ajax:send should not run'); - }); + ok(false, 'ajax:send should not run') + }) form.unbind('ajax:complete').bind('ajax:complete', function() { - ok(false, 'ajax:complete should not run'); - }); + ok(false, 'ajax:complete should not run') + }) $(document).bind('ajaxStop', function() { - start(); - }); - }); -}); + start() + }) + }) +}) asyncTest('"ajax:beforeSend", "ajax:send", "ajax:success" and "ajax:complete" are triggered', 9, function() { submit(function(form) { form.bind('ajax:beforeSend', function(e, xhr, settings) { - ok(xhr.setRequestHeader, 'first argument to "ajax:beforeSend" should be an XHR object'); - equal(settings.url, '/echo', 'second argument to "ajax:beforeSend" should be a settings object'); - }); + ok(xhr.setRequestHeader, 'first argument to "ajax:beforeSend" should be an XHR object') + equal(settings.url, '/echo', 'second argument to "ajax:beforeSend" should be a settings object') + }) form.bind('ajax:send', function(e, xhr) { - ok(xhr.abort, 'first argument to "ajax:send" should be an XHR object'); - }); + ok(xhr.abort, 'first argument to "ajax:send" should be an XHR object') + }) form.bind('ajax:success', function(e, data, status, xhr) { - ok(data.REQUEST_METHOD, 'first argument to ajax:success should be a data object'); - equal(status, 'success', 'second argument to ajax:success should be a status string'); - ok(xhr.getResponseHeader, 'third argument to "ajax:success" should be an XHR object'); - }); + ok(data.REQUEST_METHOD, 'first argument to ajax:success should be a data object') + equal(status, 'success', 'second argument to ajax:success should be a status string') + ok(xhr.getResponseHeader, 'third argument to "ajax:success" should be an XHR object') + }) form.bind('ajax:complete', function(e, xhr, status) { - ok(xhr.getResponseHeader, 'first argument to "ajax:complete" should be an XHR object'); - equal(status, 'success', 'second argument to ajax:complete should be a status string'); - }); - }); -}); + ok(xhr.getResponseHeader, 'first argument to "ajax:complete" should be an XHR object') + equal(status, 'success', 'second argument to ajax:complete should be a status string') + }) + }) +}) if(window.phantom !== undefined) { asyncTest('"ajax:beforeSend", "ajax:send", "ajax:error" and "ajax:complete" are triggered on error', 7, function() { submit(function(form) { - form.attr('action', '/error'); - form.bind('ajax:beforeSend', function(arg) { ok(true, 'ajax:beforeSend') }); - form.bind('ajax:send', function(arg) { ok(true, 'ajax:send') }); + form.attr('action', '/error') + form.bind('ajax:beforeSend', function(arg) { ok(true, 'ajax:beforeSend') }) + form.bind('ajax:send', function(arg) { ok(true, 'ajax:send') }) form.bind('ajax:error', function(e, xhr, status, error) { - ok(xhr.getResponseHeader, 'first argument to "ajax:error" should be an XHR object'); - equal(status, 'error', 'second argument to ajax:error should be a status string'); + ok(xhr.getResponseHeader, 'first argument to "ajax:error" should be an XHR object') + equal(status, 'error', 'second argument to ajax:error should be a status string') // Firefox 8 returns "Forbidden " with trailing space - equal($.trim(error), 'Forbidden', 'third argument to ajax:error should be an HTTP status response'); + equal($.trim(error), 'Forbidden', 'third argument to ajax:error should be an HTTP status response') // Opera returns "0" for HTTP code - equal(xhr.status, window.opera ? 0 : 403, 'status code should be 403'); - }); - }); - }); + equal(xhr.status, window.opera ? 0 : 403, 'status code should be 403') + }) + }) + }) } // IF THIS TEST IS FAILING, TRY INCREASING THE TIMEOUT AT THE BOTTOM TO > 100 asyncTest('binding to ajax callbacks via .delegate() triggers handlers properly', 4, function() { $(document) .delegate('form[data-remote]', 'ajax:beforeSend', function() { - ok(true, 'ajax:beforeSend handler is triggered'); + ok(true, 'ajax:beforeSend handler is triggered') }) .delegate('form[data-remote]', 'ajax:send', function() { - ok(true, 'ajax:send handler is triggered'); + ok(true, 'ajax:send handler is triggered') }) .delegate('form[data-remote]', 'ajax:complete', function() { - ok(true, 'ajax:complete handler is triggered'); + ok(true, 'ajax:complete handler is triggered') }) .delegate('form[data-remote]', 'ajax:success', function() { - ok(true, 'ajax:success handler is triggered'); - }); - $('form[data-remote]').trigger('submit'); + ok(true, 'ajax:success handler is triggered') + }) + $('form[data-remote]').trigger('submit') setTimeout(function() { - start(); - }, 63); -}); + start() + }, 63) +}) asyncTest('binding to ajax:send event to call jquery methods on ajax object', 2, function() { $('form[data-remote]') .bind('ajax:send', function(e, xhr) { - ok(true, 'event should fire'); - equal(typeof(xhr.abort), 'function', 'event should pass jqXHR object'); - xhr.abort(); + ok(true, 'event should fire') + equal(typeof(xhr.abort), 'function', 'event should pass jqXHR object') + xhr.abort() }) - .trigger('submit'); + .trigger('submit') - setTimeout(function() { start(); }, 35); -}); + setTimeout(function() { start() }, 35) +}) -})(); +})() diff --git a/test/public/test/call-remote.js b/test/public/test/call-remote.js index 2a6e3a61..167e8488 100644 --- a/test/public/test/call-remote.js +++ b/test/public/test/call-remote.js @@ -1,188 +1,188 @@ (function(){ function buildForm(attrs) { - attrs = $.extend({ action: '/echo', 'data-remote': 'true' }, attrs); + attrs = $.extend({ action: '/echo', 'data-remote': 'true' }, attrs) $('#qunit-fixture').append($('', attrs)) - .find('form').append($('')); -}; + .find('form').append($('')) +} -module('call-remote'); +module('call-remote') function submit(fn) { $('form') .bind('ajax:success', fn) .bind('ajax:complete', function() { start() }) - .trigger('submit'); + .trigger('submit') } asyncTest('form method is read from "method" and not from "data-method"', 1, function() { - buildForm({ method: 'post', 'data-method': 'get' }); + buildForm({ method: 'post', 'data-method': 'get' }) submit(function(e, data, status, xhr) { - App.assertPostRequest(data); - }); -}); + App.assertPostRequest(data) + }) +}) asyncTest('form method is not read from "data-method" attribute in case of missing "method"', 1, function() { - buildForm({ 'data-method': 'put' }); + buildForm({ 'data-method': 'put' }) submit(function(e, data, status, xhr) { - App.assertGetRequest(data); - }); -}); + App.assertGetRequest(data) + }) +}) asyncTest('form method is read from submit button "formmethod" if submit is triggered by that button', 1, function() { var submitButton = $('') - buildForm({ method: 'post' }); + buildForm({ method: 'post' }) $('#qunit-fixture').find('form').append(submitButton) .bind('ajax:success', function(e, data, status, xhr) { - App.assertGetRequest(data); + App.assertGetRequest(data) }) - .bind('ajax:complete', function() { start() }); + .bind('ajax:complete', function() { start() }) - submitButton.trigger('click'); -}); + submitButton.trigger('click') +}) asyncTest('form default method is GET', 1, function() { - buildForm(); + buildForm() submit(function(e, data, status, xhr) { - App.assertGetRequest(data); - }); -}); + App.assertGetRequest(data) + }) +}) asyncTest('form url is picked up from "action"', 1, function() { - buildForm({ method: 'post' }); + buildForm({ method: 'post' }) submit(function(e, data, status, xhr) { - App.assertRequestPath(data, '/echo'); - }); -}); + App.assertRequestPath(data, '/echo') + }) +}) asyncTest('form url is read from "action" not "href"', 1, function() { - buildForm({ method: 'post', href: '/echo2' }); + buildForm({ method: 'post', href: '/echo2' }) submit(function(e, data, status, xhr) { - App.assertRequestPath(data, '/echo'); - }); -}); + App.assertRequestPath(data, '/echo') + }) +}) asyncTest('form url is read from submit button "formaction" if submit is triggered by that button', 1, function() { var submitButton = $('') - buildForm({ method: 'post', href: '/echo2' }); + buildForm({ method: 'post', href: '/echo2' }) $('#qunit-fixture').find('form').append(submitButton) .bind('ajax:success', function(e, data, status, xhr) { - App.assertRequestPath(data, '/echo'); + App.assertRequestPath(data, '/echo') }) - .bind('ajax:complete', function() { start() }); + .bind('ajax:complete', function() { start() }) - submitButton.trigger('click'); -}); + submitButton.trigger('click') +}) asyncTest('prefer JS, but accept any format', 1, function() { - buildForm({ method: 'post' }); + buildForm({ method: 'post' }) submit(function(e, data, status, xhr) { - var accept = data.HTTP_ACCEPT; - ok(accept.indexOf('*/*;q=0.5, text/javascript, application/javascript') === 0, 'Accept: ' + accept); - }); -}); + var accept = data.HTTP_ACCEPT + ok(accept.indexOf('*/*;q=0.5, text/javascript, application/javascript') === 0, 'Accept: ' + accept) + }) +}) asyncTest('accept application/json if "data-type" is json', 1, function() { - buildForm({ method: 'post', 'data-type': 'json' }); + buildForm({ method: 'post', 'data-type': 'json' }) submit(function(e, data, status, xhr) { - equal(data.HTTP_ACCEPT, 'application/json, text/javascript, */*; q=0.01'); - }); -}); + equal(data.HTTP_ACCEPT, 'application/json, text/javascript, */*; q=0.01') + }) +}) asyncTest('allow empty "data-remote" attribute', 1, function() { - var form = $('#qunit-fixture').append($('')).find('form'); + var form = $('#qunit-fixture').append($('')).find('form') submit(function() { - ok(true, 'form with empty "data-remote" attribute is also allowed'); - }); -}); + ok(true, 'form with empty "data-remote" attribute is also allowed') + }) +}) asyncTest('allow empty form "action"', 1, function() { - var currentLocation, ajaxLocation; + var currentLocation, ajaxLocation - buildForm({ action: '' }); + buildForm({ action: '' }) $('#qunit-fixture').find('form') .bind('ajax:beforeSend', function(e, xhr, settings) { // Get current location (the same way jQuery does) try { - currentLocation = location.href; + currentLocation = location.href } catch(e) { - currentLocation = document.createElement( "a" ); - currentLocation.href = ""; - currentLocation = currentLocation.href; + currentLocation = document.createElement( "a" ) + currentLocation.href = "" + currentLocation = currentLocation.href } - currentLocation = currentLocation.replace(/\?$/, ''); + currentLocation = currentLocation.replace(/\?$/, '') // Actual location (strip out settings.data that jQuery serializes and appends) // HACK: can no longer use settings.data below to see what was appended to URL, as of // jQuery 1.6.3 (see http://bugs.jquery.com/ticket/10202 and https://github.com/jquery/jquery/pull/544) - ajaxLocation = settings.url.replace("user_name=john","").replace(/&$/, "").replace(/\?$/, ""); - equal(ajaxLocation.match(/^(.*)/)[1], currentLocation, 'URL should be current page by default'); + ajaxLocation = settings.url.replace("user_name=john","").replace(/&$/, "").replace(/\?$/, "") + equal(ajaxLocation.match(/^(.*)/)[1], currentLocation, 'URL should be current page by default') // Prevent the request from actually getting sent to the current page and // causing an error. - return false; + return false }) - .trigger('submit'); + .trigger('submit') - setTimeout(function() { start(); }, 13); -}); + setTimeout(function() { start() }, 13) +}) asyncTest('sends CSRF token in custom header', 1, function() { - buildForm({ method: 'post' }); - $('#qunit-fixture').append(''); + buildForm({ method: 'post' }) + $('#qunit-fixture').append('') submit(function(e, data, status, xhr) { - equal(data.HTTP_X_CSRF_TOKEN, 'cf50faa3fe97702ca1ae', 'X-CSRF-Token header should be sent'); - }); -}); + equal(data.HTTP_X_CSRF_TOKEN, 'cf50faa3fe97702ca1ae', 'X-CSRF-Token header should be sent') + }) +}) asyncTest('intelligently guesses crossDomain behavior when target URL has a different protocol and/or hostname', 1, function(e, xhr) { // Don't set data-cross-domain here, just set action to be a different domain than localhost - buildForm({ action: 'http://www.alfajango.com' }); - $('#qunit-fixture').append(''); + buildForm({ action: 'http://www.alfajango.com' }) + $('#qunit-fixture').append('') $('#qunit-fixture').find('form') .bind('ajax:beforeSend', function(e, xhr, settings) { - equal(settings.crossDomain, true, 'crossDomain should be set to true'); + equal(settings.crossDomain, true, 'crossDomain should be set to true') // prevent request from actually getting sent off-domain - return false; + return false }) - .trigger('submit'); + .trigger('submit') - setTimeout(function() { start(); }, 13); -}); + setTimeout(function() { start() }, 13) +}) asyncTest('intelligently guesses crossDomain behavior when target URL consists of only a path', 1, function(e, xhr) { // Don't set data-cross-domain here, just set action to be a different domain than localhost - buildForm({ action: '/just/a/path' }); - $('#qunit-fixture').append(''); + buildForm({ action: '/just/a/path' }) + $('#qunit-fixture').append('') $('#qunit-fixture').find('form') .bind('ajax:beforeSend', function(e, xhr, settings) { - equal(settings.crossDomain, false, 'crossDomain should be set to false'); + equal(settings.crossDomain, false, 'crossDomain should be set to false') // prevent request from actually getting sent off-domain - return false; + return false }) - .trigger('submit'); + .trigger('submit') - setTimeout(function() { start(); }, 13); -}); -})(); + setTimeout(function() { start() }, 13) +}) +})() diff --git a/test/public/test/csrf-refresh.js b/test/public/test/csrf-refresh.js index 65642433..0cfe00a7 100644 --- a/test/public/test/csrf-refresh.js +++ b/test/public/test/csrf-refresh.js @@ -1,9 +1,9 @@ (function(){ -module('csrf-refresh', {}); +module('csrf-refresh', {}) asyncTest('refresh all csrf tokens', 1, function() { - var correctToken = "cf50faa3fe97702ca1ae"; + var correctToken = "cf50faa3fe97702ca1ae" var form = $('') var input = $('').attr({ type: 'hidden', name: 'authenticity_token', id: 'authenticity_token', value: 'foo' }) @@ -12,13 +12,13 @@ asyncTest('refresh all csrf tokens', 1, function() { $('#qunit-fixture') .append('') .append('') - .append(form); + .append(form) - $.rails.refreshCSRFTokens(); - currentToken = $('#qunit-fixture #authenticity_token').val(); + $.rails.refreshCSRFTokens() + currentToken = $('#qunit-fixture #authenticity_token').val() - start(); - equal(currentToken, correctToken); -}); + start() + equal(currentToken, correctToken) +}) -})(); +})() diff --git a/test/public/test/csrf-token.js b/test/public/test/csrf-token.js index dfed3781..ddbf6f65 100644 --- a/test/public/test/csrf-token.js +++ b/test/public/test/csrf-token.js @@ -1,27 +1,27 @@ (function(){ -module('csrf-token', {}); +module('csrf-token', {}) asyncTest('find csrf token', 1, function() { - var correctToken = "cf50faa3fe97702ca1ae"; + var correctToken = "cf50faa3fe97702ca1ae" - $('#qunit-fixture').append(''); + $('#qunit-fixture').append('') - currentToken = $.rails.csrfToken(); + currentToken = $.rails.csrfToken() - start(); - equal(currentToken, correctToken); -}); + start() + equal(currentToken, correctToken) +}) asyncTest('find csrf param', 1, function() { - var correctParam = "authenticity_token"; + var correctParam = "authenticity_token" - $('#qunit-fixture').append(''); + $('#qunit-fixture').append('') - currentParam = $.rails.csrfParam(); + currentParam = $.rails.csrfParam() - start(); - equal(currentParam, correctParam); -}); + start() + equal(currentParam, correctParam) +}) -})(); +})() diff --git a/test/public/test/data-confirm.js b/test/public/test/data-confirm.js index 8add713c..d0eafdb4 100644 --- a/test/public/test/data-confirm.js +++ b/test/public/test/data-confirm.js @@ -5,261 +5,261 @@ module('data-confirm', { 'data-remote': 'true', 'data-confirm': 'Are you absolutely sure?', text: 'my social security number' - })); + })) $('#qunit-fixture').append($(''); - form.append(button); + var form = $('form[data-remote]'), button = $('') + form.append(button) - App.checkEnabledState(button, 'Submit'); + App.checkEnabledState(button, 'Submit') form.bind('ajax:success', function(e, data) { setTimeout(function() { - App.checkEnabledState(button, 'Submit'); - start(); - }, 13); - }); - form.trigger('submit'); + App.checkEnabledState(button, 'Submit') + start() + }, 13) + }) + form.trigger('submit') - App.checkDisabledState(button, 'submitting ...'); -}); + App.checkDisabledState(button, 'submitting ...') +}) asyncTest('form input[type=submit][data-disable-with] disables', 6, function(){ - var form = $('form:not([data-remote])'), input = form.find('input[type=submit]'); + var form = $('form:not([data-remote])'), input = form.find('input[type=submit]') - App.checkEnabledState(input, 'Submit'); + App.checkEnabledState(input, 'Submit') // WEEIRDD: attaching this handler makes the test work in IE7 - $(document).bind('iframe:loading', function(e, form) {}); + $(document).bind('iframe:loading', function(e, form) {}) $(document).bind('iframe:loaded', function(e, data) { setTimeout(function() { - App.checkDisabledState(input, 'submitting ...'); - start(); - }, 30); - }); - form.trigger('submit'); + App.checkDisabledState(input, 'submitting ...') + start() + }, 30) + }) + form.trigger('submit') setTimeout(function() { - App.checkDisabledState(input, 'submitting ...'); - }, 30); -}); + App.checkDisabledState(input, 'submitting ...') + }, 30) +}) test('form input[type=submit][data-disable-with] re-enables when `pageshow` event is triggered', function(){ - var form = $('form:not([data-remote])'), input = form.find('input[type=submit]'); + var form = $('form:not([data-remote])'), input = form.find('input[type=submit]') - App.checkEnabledState(input, 'Submit'); + App.checkEnabledState(input, 'Submit') // Emulate the disabled state without submitting the form at all, what is the // state after going back on firefox after submitting a form. // // See https://github.com/rails/jquery-ujs/issues/357 - $.rails.disableFormElements(form); + $.rails.disableFormElements(form) - App.checkDisabledState(input, 'submitting ...'); + App.checkDisabledState(input, 'submitting ...') - $(window).trigger('pageshow'); + $(window).trigger('pageshow') - App.checkEnabledState(input, 'Submit'); -}); + App.checkEnabledState(input, 'Submit') +}) asyncTest('form[data-remote] input[type=submit][data-disable-with] is replaced in ajax callback', 2, function(){ - var form = $('form:not([data-remote])').attr('data-remote', 'true'), origFormContents = form.html(); + var form = $('form:not([data-remote])').attr('data-remote', 'true'), origFormContents = form.html() form.bind('ajax:success', function(){ - form.html(origFormContents); + form.html(origFormContents) setTimeout(function(){ - var input = form.find('input[type=submit]'); - App.checkEnabledState(input, 'Submit'); - start(); - }, 30); - }).trigger('submit'); -}); + var input = form.find('input[type=submit]') + App.checkEnabledState(input, 'Submit') + start() + }, 30) + }).trigger('submit') +}) asyncTest('form[data-remote] input[data-disable-with] is replaced with disabled field in ajax callback', 2, function(){ var form = $('form:not([data-remote])').attr('data-remote', 'true'), input = form.find('input[type=submit]'), - newDisabledInput = input.clone().attr('disabled', 'disabled'); + newDisabledInput = input.clone().attr('disabled', 'disabled') form.bind('ajax:success', function(){ - input.replaceWith(newDisabledInput); + input.replaceWith(newDisabledInput) setTimeout(function(){ - App.checkEnabledState(newDisabledInput, 'Submit'); - start(); - }, 30); - }).trigger('submit'); -}); + App.checkEnabledState(newDisabledInput, 'Submit') + start() + }, 30) + }).trigger('submit') +}) asyncTest('form input[type=submit][data-disable-with] using "form" attribute disables', 6, function() { - var form = $('#not_remote'), input = $('input[form=not_remote]'); - App.checkEnabledState(input, 'Form Attr Submit'); + var form = $('#not_remote'), input = $('input[form=not_remote]') + App.checkEnabledState(input, 'Form Attr Submit') // WEEIRDD: attaching this handler makes the test work in IE7 - $(document).bind('iframe:loading', function(e, form) {}); + $(document).bind('iframe:loading', function(e, form) {}) $(document).bind('iframe:loaded', function(e, data) { setTimeout(function() { - App.checkDisabledState(input, 'form attr submitting'); - start(); - }, 30); - }); - form.trigger('submit'); + App.checkDisabledState(input, 'form attr submitting') + start() + }, 30) + }) + form.trigger('submit') setTimeout(function() { - App.checkDisabledState(input, 'form attr submitting'); - }, 30); + App.checkDisabledState(input, 'form attr submitting') + }, 30) -}); +}) asyncTest('form[data-remote] textarea[data-disable-with] attribute', 3, function() { var form = $('form[data-remote]'), - textarea = $('').appendTo(form); + textarea = $('').appendTo(form) form.bind('ajax:success', function(e, data) { setTimeout(function() { - equal(data.params.user_bio, 'born, lived, died.'); - start(); - }, 13); - }); - form.trigger('submit'); + equal(data.params.user_bio, 'born, lived, died.') + start() + }, 13) + }) + form.trigger('submit') - App.checkDisabledState(textarea, 'processing ...'); -}); + App.checkDisabledState(textarea, 'processing ...') +}) asyncTest('a[data-disable-with] disables', 4, function() { - var link = $('a[data-disable-with]'); + var link = $('a[data-disable-with]') - App.checkEnabledState(link, 'Click me'); + App.checkEnabledState(link, 'Click me') - link.trigger('click'); - App.checkDisabledState(link, 'clicking...'); - start(); -}); + link.trigger('click') + App.checkDisabledState(link, 'clicking...') + start() +}) test('a[data-disable-with] re-enables when `pageshow` event is triggered', function() { - var link = $('a[data-disable-with]'); + var link = $('a[data-disable-with]') - App.checkEnabledState(link, 'Click me'); + App.checkEnabledState(link, 'Click me') - link.trigger('click'); - App.checkDisabledState(link, 'clicking...'); + link.trigger('click') + App.checkDisabledState(link, 'clicking...') - $(window).trigger('pageshow'); - App.checkEnabledState(link, 'Click me'); -}); + $(window).trigger('pageshow') + App.checkEnabledState(link, 'Click me') +}) asyncTest('a[data-remote][data-disable-with] disables and re-enables', 6, function() { - var link = $('a[data-disable-with]').attr('data-remote', true); + var link = $('a[data-disable-with]').attr('data-remote', true) - App.checkEnabledState(link, 'Click me'); + App.checkEnabledState(link, 'Click me') link .bind('ajax:beforeSend', function() { - App.checkDisabledState(link, 'clicking...'); + App.checkDisabledState(link, 'clicking...') }) .bind('ajax:complete', function() { setTimeout( function() { - App.checkEnabledState(link, 'Click me'); - start(); - }, 15); + App.checkEnabledState(link, 'Click me') + start() + }, 15) }) - .trigger('click'); -}); + .trigger('click') +}) asyncTest('a[data-remote][data-disable-with] re-enables when `ajax:before` event is cancelled', 6, function() { - var link = $('a[data-disable-with]').attr('data-remote', true); + var link = $('a[data-disable-with]').attr('data-remote', true) - App.checkEnabledState(link, 'Click me'); + App.checkEnabledState(link, 'Click me') link .bind('ajax:before', function() { - App.checkDisabledState(link, 'clicking...'); - return false; + App.checkDisabledState(link, 'clicking...') + return false }) - .trigger('click'); + .trigger('click') setTimeout(function() { - App.checkEnabledState(link, 'Click me'); - start(); - }, 30); -}); + App.checkEnabledState(link, 'Click me') + start() + }, 30) +}) asyncTest('a[data-remote][data-disable-with] re-enables when `ajax:beforeSend` event is cancelled', 6, function() { - var link = $('a[data-disable-with]').attr('data-remote', true); + var link = $('a[data-disable-with]').attr('data-remote', true) - App.checkEnabledState(link, 'Click me'); + App.checkEnabledState(link, 'Click me') link .bind('ajax:beforeSend', function() { - App.checkDisabledState(link, 'clicking...'); - return false; + App.checkDisabledState(link, 'clicking...') + return false }) - .trigger('click'); + .trigger('click') setTimeout(function() { - App.checkEnabledState(link, 'Click me'); - start(); - }, 30); -}); + App.checkEnabledState(link, 'Click me') + start() + }, 30) +}) asyncTest('a[data-remote][data-disable-with] re-enables when `ajax:error` event is triggered', 6, function() { - var link = $('a[data-disable-with]').attr('data-remote', true).attr('href', '/error'); + var link = $('a[data-disable-with]').attr('data-remote', true).attr('href', '/error') - App.checkEnabledState(link, 'Click me'); + App.checkEnabledState(link, 'Click me') link .bind('ajax:beforeSend', function() { - App.checkDisabledState(link, 'clicking...'); + App.checkDisabledState(link, 'clicking...') }) - .trigger('click'); + .trigger('click') setTimeout(function() { - App.checkEnabledState(link, 'Click me'); - start(); - }, 30); -}); + App.checkEnabledState(link, 'Click me') + start() + }, 30) +}) asyncTest('form[data-remote] input|button|textarea[data-disable-with] does not disable when `ajax:beforeSend` event is cancelled', 8, function() { var form = $('form[data-remote]'), input = form.find('input:text'), button = $('').appendTo(form), textarea = $('').appendTo(form), - submit = $('').appendTo(form); + submit = $('').appendTo(form) form .bind('ajax:beforeSend', function() { - return false; + return false }) - .trigger('submit'); + .trigger('submit') - App.checkEnabledState(input, 'john'); - App.checkEnabledState(button, 'Submit'); - App.checkEnabledState(textarea, 'born, lived, died.'); - App.checkEnabledState(submit, 'Submit'); + App.checkEnabledState(input, 'john') + App.checkEnabledState(button, 'Submit') + App.checkEnabledState(textarea, 'born, lived, died.') + App.checkEnabledState(submit, 'Submit') - start(); -}); + start() +}) asyncTest('ctrl-clicking on a link does not disables the link', 6, function() { - var link = $('a[data-disable-with]'), e; - e = $.Event('click'); - e.metaKey = true; + var link = $('a[data-disable-with]'), e + e = $.Event('click') + e.metaKey = true - App.checkEnabledState(link, 'Click me'); + App.checkEnabledState(link, 'Click me') - link.trigger(e); - App.checkEnabledState(link, 'Click me'); + link.trigger(e) + App.checkEnabledState(link, 'Click me') - e = $.Event('click'); - e.ctrlKey = true; + e = $.Event('click') + e.ctrlKey = true - link.trigger(e); - App.checkEnabledState(link, 'Click me'); - start(); -}); + link.trigger(e) + App.checkEnabledState(link, 'Click me') + start() +}) asyncTest('button[data-remote][data-disable-with] disables and re-enables', 6, function() { - var button = $('button[data-remote][data-disable-with]'); + var button = $('button[data-remote][data-disable-with]') - App.checkEnabledState(button, 'Click me'); + App.checkEnabledState(button, 'Click me') button .bind('ajax:send', function() { - App.checkDisabledState(button, 'clicking...'); + App.checkDisabledState(button, 'clicking...') }) .bind('ajax:complete', function() { setTimeout( function() { - App.checkEnabledState(button, 'Click me'); - start(); - }, 15); + App.checkEnabledState(button, 'Click me') + start() + }, 15) }) - .trigger('click'); -}); + .trigger('click') +}) asyncTest('button[data-remote][data-disable-with] re-enables when `ajax:before` event is cancelled', 6, function() { - var button = $('button[data-remote][data-disable-with]'); + var button = $('button[data-remote][data-disable-with]') - App.checkEnabledState(button, 'Click me'); + App.checkEnabledState(button, 'Click me') button .bind('ajax:before', function() { - App.checkDisabledState(button, 'clicking...'); - return false; + App.checkDisabledState(button, 'clicking...') + return false }) - .trigger('click'); + .trigger('click') setTimeout(function() { - App.checkEnabledState(button, 'Click me'); - start(); - }, 30); -}); + App.checkEnabledState(button, 'Click me') + start() + }, 30) +}) asyncTest('button[data-remote][data-disable-with] re-enables when `ajax:beforeSend` event is cancelled', 6, function() { - var button = $('button[data-remote][data-disable-with]'); + var button = $('button[data-remote][data-disable-with]') - App.checkEnabledState(button, 'Click me'); + App.checkEnabledState(button, 'Click me') button .bind('ajax:beforeSend', function() { - App.checkDisabledState(button, 'clicking...'); - return false; + App.checkDisabledState(button, 'clicking...') + return false }) - .trigger('click'); + .trigger('click') setTimeout(function() { - App.checkEnabledState(button, 'Click me'); - start(); - }, 30); -}); + App.checkEnabledState(button, 'Click me') + start() + }, 30) +}) asyncTest('button[data-remote][data-disable-with] re-enables when `ajax:error` event is triggered', 6, function() { - var button = $('a[data-disable-with]').attr('data-remote', true).attr('href', '/error'); + var button = $('a[data-disable-with]').attr('data-remote', true).attr('href', '/error') - App.checkEnabledState(button, 'Click me'); + App.checkEnabledState(button, 'Click me') button .bind('ajax:send', function() { - App.checkDisabledState(button, 'clicking...'); + App.checkDisabledState(button, 'clicking...') }) - .trigger('click'); + .trigger('click') setTimeout(function() { - App.checkEnabledState(button, 'Click me'); - start(); - }, 30); -}); + App.checkEnabledState(button, 'Click me') + start() + }, 30) +}) diff --git a/test/public/test/data-disable.js b/test/public/test/data-disable.js index 3df1bb9c..04087abf 100644 --- a/test/public/test/data-disable.js +++ b/test/public/test/data-disable.js @@ -6,7 +6,7 @@ module('data-disable', { method: 'post' })) .find('form') - .append($('')); + .append($('')) $('#qunit-fixture').append($('', { action: '/echo', @@ -14,313 +14,313 @@ module('data-disable', { })) .find('form:last') // WEEIRDD: the form won't submit to an iframe if the button is name="submit" (??!) - .append($('')); + .append($('')) $('#qunit-fixture').append($('', { text: 'Click me', href: '/echo', 'data-disable': 'true' - })); + })) $('#qunit-fixture').append($(''); - form.append(button); + var form = $('form[data-remote]'), button = $('') + form.append(button) - App.checkEnabledState(button, 'Submit'); + App.checkEnabledState(button, 'Submit') form.bind('ajax:success', function(e, data) { setTimeout(function() { - App.checkEnabledState(button, 'Submit'); - start(); + App.checkEnabledState(button, 'Submit') + start() }, 13) }) - form.trigger('submit'); + form.trigger('submit') - App.checkDisabledState(button, 'Submit'); - equal(button.data('ujs:enable-with'), undefined); -}); + App.checkDisabledState(button, 'Submit') + equal(button.data('ujs:enable-with'), undefined) +}) asyncTest('form input[type=submit][data-disable] disables', 6, function(){ - var form = $('form:not([data-remote])'), input = form.find('input[type=submit]'); + var form = $('form:not([data-remote])'), input = form.find('input[type=submit]') - App.checkEnabledState(input, 'Submit'); + App.checkEnabledState(input, 'Submit') // WEEIRDD: attaching this handler makes the test work in IE7 - $(document).bind('iframe:loading', function(e, form) {}); + $(document).bind('iframe:loading', function(e, form) {}) $(document).bind('iframe:loaded', function(e, data) { setTimeout(function() { - App.checkDisabledState(input, 'Submit'); - start(); - }, 30); - }); - form.trigger('submit'); + App.checkDisabledState(input, 'Submit') + start() + }, 30) + }) + form.trigger('submit') setTimeout(function() { - App.checkDisabledState(input, 'Submit'); - }, 30); -}); + App.checkDisabledState(input, 'Submit') + }, 30) +}) asyncTest('form[data-remote] input[type=submit][data-disable] is replaced in ajax callback', 2, function(){ - var form = $('form:not([data-remote])').attr('data-remote', 'true'), origFormContents = form.html(); + var form = $('form:not([data-remote])').attr('data-remote', 'true'), origFormContents = form.html() form.bind('ajax:success', function(){ - form.html(origFormContents); + form.html(origFormContents) setTimeout(function(){ - var input = form.find('input[type=submit]'); - App.checkEnabledState(input, 'Submit'); - start(); - }, 30); - }).trigger('submit'); -}); + var input = form.find('input[type=submit]') + App.checkEnabledState(input, 'Submit') + start() + }, 30) + }).trigger('submit') +}) asyncTest('form[data-remote] input[data-disable] is replaced with disabled field in ajax callback', 2, function(){ var form = $('form:not([data-remote])').attr('data-remote', 'true'), input = form.find('input[type=submit]'), - newDisabledInput = input.clone().attr('disabled', 'disabled'); + newDisabledInput = input.clone().attr('disabled', 'disabled') form.bind('ajax:success', function(){ - input.replaceWith(newDisabledInput); + input.replaceWith(newDisabledInput) setTimeout(function(){ - App.checkEnabledState(newDisabledInput, 'Submit'); - start(); - }, 30); - }).trigger('submit'); -}); + App.checkEnabledState(newDisabledInput, 'Submit') + start() + }, 30) + }).trigger('submit') +}) asyncTest('form[data-remote] textarea[data-disable] attribute', 3, function() { var form = $('form[data-remote]'), - textarea = $('').appendTo(form); + textarea = $('').appendTo(form) form.bind('ajax:success', function(e, data) { setTimeout(function() { - equal(data.params.user_bio, 'born, lived, died.'); - start(); + equal(data.params.user_bio, 'born, lived, died.') + start() }, 13) }) - form.trigger('submit'); + form.trigger('submit') - App.checkDisabledState(textarea, 'born, lived, died.'); -}); + App.checkDisabledState(textarea, 'born, lived, died.') +}) asyncTest('a[data-disable] disables', 5, function() { - var link = $('a[data-disable]'); + var link = $('a[data-disable]') - App.checkEnabledState(link, 'Click me'); + App.checkEnabledState(link, 'Click me') - link.trigger('click'); - App.checkDisabledState(link, 'Click me'); - equal(link.data('ujs:enable-with'), undefined); - start(); -}); + link.trigger('click') + App.checkDisabledState(link, 'Click me') + equal(link.data('ujs:enable-with'), undefined) + start() +}) asyncTest('a[data-remote][data-disable] disables and re-enables', 6, function() { - var link = $('a[data-disable]').attr('data-remote', true); + var link = $('a[data-disable]').attr('data-remote', true) - App.checkEnabledState(link, 'Click me'); + App.checkEnabledState(link, 'Click me') link .bind('ajax:send', function() { - App.checkDisabledState(link, 'Click me'); + App.checkDisabledState(link, 'Click me') }) .bind('ajax:complete', function() { setTimeout( function() { - App.checkEnabledState(link, 'Click me'); - start(); - }, 15); + App.checkEnabledState(link, 'Click me') + start() + }, 15) }) - .trigger('click'); -}); + .trigger('click') +}) asyncTest('a[data-remote][data-disable] re-enables when `ajax:before` event is cancelled', 6, function() { - var link = $('a[data-disable]').attr('data-remote', true); + var link = $('a[data-disable]').attr('data-remote', true) - App.checkEnabledState(link, 'Click me'); + App.checkEnabledState(link, 'Click me') link .bind('ajax:before', function() { - App.checkDisabledState(link, 'Click me'); - return false; + App.checkDisabledState(link, 'Click me') + return false }) - .trigger('click'); + .trigger('click') setTimeout(function() { - App.checkEnabledState(link, 'Click me'); - start(); - }, 30); -}); + App.checkEnabledState(link, 'Click me') + start() + }, 30) +}) asyncTest('a[data-remote][data-disable] re-enables when `ajax:beforeSend` event is cancelled', 6, function() { - var link = $('a[data-disable]').attr('data-remote', true); + var link = $('a[data-disable]').attr('data-remote', true) - App.checkEnabledState(link, 'Click me'); + App.checkEnabledState(link, 'Click me') link .bind('ajax:beforeSend', function() { - App.checkDisabledState(link, 'Click me'); - return false; + App.checkDisabledState(link, 'Click me') + return false }) - .trigger('click'); + .trigger('click') setTimeout(function() { - App.checkEnabledState(link, 'Click me'); - start(); - }, 30); -}); + App.checkEnabledState(link, 'Click me') + start() + }, 30) +}) asyncTest('a[data-remote][data-disable] re-enables when `ajax:error` event is triggered', 6, function() { - var link = $('a[data-disable]').attr('data-remote', true).attr('href', '/error'); + var link = $('a[data-disable]').attr('data-remote', true).attr('href', '/error') - App.checkEnabledState(link, 'Click me'); + App.checkEnabledState(link, 'Click me') link .bind('ajax:send', function() { - App.checkDisabledState(link, 'Click me'); + App.checkDisabledState(link, 'Click me') }) - .trigger('click'); + .trigger('click') setTimeout(function() { - App.checkEnabledState(link, 'Click me'); - start(); - }, 30); -}); + App.checkEnabledState(link, 'Click me') + start() + }, 30) +}) asyncTest('form[data-remote] input|button|textarea[data-disable] does not disable when `ajax:beforeSend` event is cancelled', 8, function() { var form = $('form[data-remote]'), input = form.find('input:text'), button = $('').appendTo(form), textarea = $('').appendTo(form), - submit = $('').appendTo(form); + submit = $('').appendTo(form) form .bind('ajax:beforeSend', function() { - return false; + return false }) - .trigger('submit'); + .trigger('submit') - App.checkEnabledState(input, 'john'); - App.checkEnabledState(button, 'Submit'); - App.checkEnabledState(textarea, 'born, lived, died.'); - App.checkEnabledState(submit, 'Submit'); + App.checkEnabledState(input, 'john') + App.checkEnabledState(button, 'Submit') + App.checkEnabledState(textarea, 'born, lived, died.') + App.checkEnabledState(submit, 'Submit') - start(); -}); + start() +}) asyncTest('ctrl-clicking on a link does not disables the link', 6, function() { - var link = $('a[data-disable]'), e; - e = $.Event('click'); - e.metaKey = true; + var link = $('a[data-disable]'), e + e = $.Event('click') + e.metaKey = true - App.checkEnabledState(link, 'Click me'); + App.checkEnabledState(link, 'Click me') - link.trigger(e); - App.checkEnabledState(link, 'Click me'); + link.trigger(e) + App.checkEnabledState(link, 'Click me') - e = $.Event('click'); - e.ctrlKey = true; + e = $.Event('click') + e.ctrlKey = true - link.trigger(e); - App.checkEnabledState(link, 'Click me'); - start(); -}); + link.trigger(e) + App.checkEnabledState(link, 'Click me') + start() +}) asyncTest('button[data-remote][data-disable] disables and re-enables', 6, function() { - var button = $('button[data-remote][data-disable]'); + var button = $('button[data-remote][data-disable]') - App.checkEnabledState(button, 'Click me'); + App.checkEnabledState(button, 'Click me') button .bind('ajax:send', function() { - App.checkDisabledState(button, 'Click me'); + App.checkDisabledState(button, 'Click me') }) .bind('ajax:complete', function() { setTimeout( function() { - App.checkEnabledState(button, 'Click me'); - start(); - }, 15); + App.checkEnabledState(button, 'Click me') + start() + }, 15) }) - .trigger('click'); -}); + .trigger('click') +}) asyncTest('button[data-remote][data-disable] re-enables when `ajax:before` event is cancelled', 6, function() { - var button = $('button[data-remote][data-disable]'); + var button = $('button[data-remote][data-disable]') - App.checkEnabledState(button, 'Click me'); + App.checkEnabledState(button, 'Click me') button .bind('ajax:before', function() { - App.checkDisabledState(button, 'Click me'); - return false; + App.checkDisabledState(button, 'Click me') + return false }) - .trigger('click'); + .trigger('click') setTimeout(function() { - App.checkEnabledState(button, 'Click me'); - start(); - }, 30); -}); + App.checkEnabledState(button, 'Click me') + start() + }, 30) +}) asyncTest('button[data-remote][data-disable] re-enables when `ajax:beforeSend` event is cancelled', 6, function() { - var button = $('button[data-remote][data-disable]'); + var button = $('button[data-remote][data-disable]') - App.checkEnabledState(button, 'Click me'); + App.checkEnabledState(button, 'Click me') button .bind('ajax:beforeSend', function() { - App.checkDisabledState(button, 'Click me'); - return false; + App.checkDisabledState(button, 'Click me') + return false }) - .trigger('click'); + .trigger('click') setTimeout(function() { - App.checkEnabledState(button, 'Click me'); - start(); - }, 30); -}); + App.checkEnabledState(button, 'Click me') + start() + }, 30) +}) asyncTest('button[data-remote][data-disable] re-enables when `ajax:error` event is triggered', 6, function() { - var button = $('a[data-disable]').attr('data-remote', true).attr('href', '/error'); + var button = $('a[data-disable]').attr('data-remote', true).attr('href', '/error') - App.checkEnabledState(button, 'Click me'); + App.checkEnabledState(button, 'Click me') button .bind('ajax:send', function() { - App.checkDisabledState(button, 'Click me'); + App.checkDisabledState(button, 'Click me') }) - .trigger('click'); + .trigger('click') setTimeout(function() { - App.checkEnabledState(button, 'Click me'); - start(); - }, 30); -}); + App.checkEnabledState(button, 'Click me') + start() + }, 30) +}) diff --git a/test/public/test/data-method.js b/test/public/test/data-method.js index 57528377..eaf8dfa8 100644 --- a/test/public/test/data-method.js +++ b/test/public/test/data-method.js @@ -4,72 +4,72 @@ module('data-method', { setup: function() { $('#qunit-fixture').append($('', { href: '/echo', 'data-method': 'delete', text: 'destroy!' - })); + })) }, teardown: function() { - $(document).unbind('iframe:loaded'); + $(document).unbind('iframe:loaded') } -}); +}) function submit(fn, options) { $(document).bind('iframe:loaded', function(e, data) { - fn(data); - start(); - }); + fn(data) + start() + }) $('#qunit-fixture').find('a') - .trigger('click'); + .trigger('click') } asyncTest('link with "data-method" set to "delete"', 3, function() { submit(function(data) { - equal(data.REQUEST_METHOD, 'DELETE'); - strictEqual(data.params.authenticity_token, undefined); - strictEqual(data.HTTP_X_CSRF_TOKEN, undefined); - }); -}); + equal(data.REQUEST_METHOD, 'DELETE') + strictEqual(data.params.authenticity_token, undefined) + strictEqual(data.HTTP_X_CSRF_TOKEN, undefined) + }) +}) asyncTest('link with "data-method" and CSRF', 1, function() { $('#qunit-fixture') .append('') - .append(''); + .append('') submit(function(data) { - equal(data.params.authenticity_token, 'cf50faa3fe97702ca1ae'); - }); -}); + equal(data.params.authenticity_token, 'cf50faa3fe97702ca1ae') + }) +}) asyncTest('link "target" should be carried over to generated form', 1, function() { - $('a[data-method]').attr('target', 'super-special-frame'); + $('a[data-method]').attr('target', 'super-special-frame') submit(function(data) { - equal(data.params._target, 'super-special-frame'); - }); -}); + equal(data.params._target, 'super-special-frame') + }) +}) asyncTest('link with "data-method" and cross origin', 1, function() { - var data = {}; + var data = {} $('#qunit-fixture') .append('') - .append(''); + .append('') $(document).on('submit', 'form', function(e) { $(e.currentTarget).serializeArray().map(function(item) { - data[item.name] = item.value; - }); + data[item.name] = item.value + }) - return false; - }); + return false + }) - var link = $('#qunit-fixture').find('a'); + var link = $('#qunit-fixture').find('a') - link.attr('href', 'http://www.alfajango.com'); + link.attr('href', 'http://www.alfajango.com') - link.trigger('click'); + link.trigger('click') - start(); + start() - notEqual(data.authenticity_token, 'cf50faa3fe97702ca1ae'); -}); + notEqual(data.authenticity_token, 'cf50faa3fe97702ca1ae') +}) -})(); +})() diff --git a/test/public/test/data-remote.js b/test/public/test/data-remote.js index e751c8e0..2523f98f 100644 --- a/test/public/test/data-remote.js +++ b/test/public/test/data-remote.js @@ -25,13 +25,13 @@ module('data-remote', { disabled: 'disabled', text: 'Disabed link' })) - .find('form').append($('')); + .find('form').append($('')) } -}); +}) asyncTest('ctrl-clicking on a link does not fire ajaxyness', 0, function() { - var link = $('a[data-remote]'), e; + var link = $('a[data-remote]'), e // Ideally, we'd setup an iframe to intercept normal link clicks // and add a test to make sure the iframe:loaded event is triggered. @@ -40,56 +40,56 @@ asyncTest('ctrl-clicking on a link does not fire ajaxyness', 0, function() { link .removeAttr('data-params') .bind('ajax:beforeSend', function() { - ok(false, 'ajax should not be triggered'); - }); + ok(false, 'ajax should not be triggered') + }) - e = $.Event('click'); - e.metaKey = true; - link.trigger(e); + e = $.Event('click') + e.metaKey = true + link.trigger(e) - e = $.Event('click'); - e.ctrlKey = true; - link.trigger(e); + e = $.Event('click') + e.ctrlKey = true + link.trigger(e) - setTimeout(function(){ start(); }, 13); -}); + setTimeout(function(){ start() }, 13) +}) asyncTest('ctrl-clicking on a link still fires ajax for non-GET links and for links with "data-params"', 2, function() { - var link = $('a[data-remote]'), e; - e = $.Event('click'); - e.metaKey = true; + var link = $('a[data-remote]'), e + e = $.Event('click') + e.metaKey = true link .removeAttr('data-params') .attr('data-method', 'POST') .bind('ajax:beforeSend', function() { - ok(true, 'ajax should be triggered'); + ok(true, 'ajax should be triggered') }) - .trigger(e); + .trigger(e) - e = $.Event('click'); - e.metaKey = true; + e = $.Event('click') + e.metaKey = true link .removeAttr('data-method') .attr('data-params', 'name=steve') - .trigger(e); + .trigger(e) - setTimeout(function(){ start(); }, 13); -}); + setTimeout(function(){ start() }, 13) +}) asyncTest('clicking on a link with data-remote attribute', 5, function() { $('a[data-remote]') .bind('ajax:success', function(e, data, status, xhr) { - App.assertCallbackInvoked('ajax:success'); - App.assertRequestPath(data, '/echo'); - equal(data.params.data1, 'value1', 'ajax arguments should have key data1 with right value'); - equal(data.params.data2, 'value2', 'ajax arguments should have key data2 with right value'); - App.assertGetRequest(data); + App.assertCallbackInvoked('ajax:success') + App.assertRequestPath(data, '/echo') + equal(data.params.data1, 'value1', 'ajax arguments should have key data1 with right value') + equal(data.params.data2, 'value2', 'ajax arguments should have key data2 with right value') + App.assertGetRequest(data) }) .bind('ajax:complete', function() { start() }) - .trigger('click'); -}); + .trigger('click') +}) asyncTest('clicking on a link with disabled attribute', 0, function() { $('a[disabled]') @@ -100,22 +100,22 @@ asyncTest('clicking on a link with disabled attribute', 0, function() { .trigger('click') setTimeout(function() { - start(); - }, 13); -}); + start() + }, 13) +}) asyncTest('clicking on a button with data-remote attribute', 5, function() { $('button[data-remote]') .bind('ajax:success', function(e, data, status, xhr) { - App.assertCallbackInvoked('ajax:success'); - App.assertRequestPath(data, '/echo'); - equal(data.params.data1, 'value1', 'ajax arguments should have key data1 with right value'); - equal(data.params.data2, 'value2', 'ajax arguments should have key data2 with right value'); - App.assertGetRequest(data); + App.assertCallbackInvoked('ajax:success') + App.assertRequestPath(data, '/echo') + equal(data.params.data1, 'value1', 'ajax arguments should have key data1 with right value') + equal(data.params.data2, 'value2', 'ajax arguments should have key data2 with right value') + App.assertGetRequest(data) }) .bind('ajax:complete', function() { start() }) - .trigger('click'); -}); + .trigger('click') +}) asyncTest('changing a select option with data-remote attribute', 5, function() { $('form') @@ -128,74 +128,74 @@ asyncTest('changing a select option with data-remote attribute', 5, function() { }) .append($('