jquery.unobtrusive-ajax.js 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. // Unobtrusive Ajax support library for jQuery
  2. // Copyright (c) .NET Foundation. All rights reserved.
  3. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
  4. // @version v3.2.6
  5. //
  6. // Microsoft grants you the right to use these script files for the sole
  7. // purpose of either: (i) interacting through your browser with the Microsoft
  8. // website or online service, subject to the applicable licensing or use
  9. // terms; or (ii) using the files as included with a Microsoft product subject
  10. // to that product's license terms. Microsoft reserves all other rights to the
  11. // files not expressly granted by Microsoft, whether by implication, estoppel
  12. // or otherwise. Insofar as a script file is dual licensed under GPL,
  13. // Microsoft neither took the code under GPL nor distributes it thereunder but
  14. // under the terms set out in this paragraph. All notices and licenses
  15. // below are for informational purposes only.
  16. /*jslint white: true, browser: true, onevar: true, undef: true, nomen: true, eqeqeq: true, plusplus: true, bitwise: true, regexp: true, newcap: true, immed: true, strict: false */
  17. /*global window: false, jQuery: false */
  18. (function ($) {
  19. var data_click = "unobtrusiveAjaxClick",
  20. data_target = "unobtrusiveAjaxClickTarget",
  21. data_validation = "unobtrusiveValidation";
  22. function getFunction(code, argNames) {
  23. var fn = window, parts = (code || "").split(".");
  24. while (fn && parts.length) {
  25. fn = fn[parts.shift()];
  26. }
  27. if (typeof (fn) === "function") {
  28. return fn;
  29. }
  30. argNames.push(code);
  31. return Function.constructor.apply(null, argNames);
  32. }
  33. function isMethodProxySafe(method) {
  34. return method === "GET" || method === "POST";
  35. }
  36. function asyncOnBeforeSend(xhr, method) {
  37. if (!isMethodProxySafe(method)) {
  38. xhr.setRequestHeader("X-HTTP-Method-Override", method);
  39. }
  40. }
  41. function asyncOnSuccess(element, data, contentType) {
  42. var mode;
  43. if (contentType.indexOf("application/x-javascript") !== -1) { // jQuery already executes JavaScript for us
  44. return;
  45. }
  46. mode = (element.getAttribute("data-ajax-mode") || "").toUpperCase();
  47. $(element.getAttribute("data-ajax-update")).each(function (i, update) {
  48. var top;
  49. switch (mode) {
  50. case "BEFORE":
  51. $(update).prepend(data);
  52. break;
  53. case "AFTER":
  54. $(update).append(data);
  55. break;
  56. case "REPLACE-WITH":
  57. $(update).replaceWith(data);
  58. break;
  59. default:
  60. $(update).html(data);
  61. break;
  62. }
  63. });
  64. }
  65. function asyncRequest(element, options) {
  66. var confirm, loading, method, duration;
  67. confirm = element.getAttribute("data-ajax-confirm");
  68. if (confirm && !window.confirm(confirm)) {
  69. return;
  70. }
  71. loading = $(element.getAttribute("data-ajax-loading"));
  72. duration = parseInt(element.getAttribute("data-ajax-loading-duration"), 10) || 0;
  73. $.extend(options, {
  74. type: element.getAttribute("data-ajax-method") || undefined,
  75. url: element.getAttribute("data-ajax-url") || undefined,
  76. cache: (element.getAttribute("data-ajax-cache") || "").toLowerCase() === "true",
  77. beforeSend: function (xhr) {
  78. var result;
  79. asyncOnBeforeSend(xhr, method);
  80. result = getFunction(element.getAttribute("data-ajax-begin"), ["xhr"]).apply(element, arguments);
  81. if (result !== false) {
  82. loading.show(duration);
  83. }
  84. return result;
  85. },
  86. complete: function () {
  87. loading.hide(duration);
  88. getFunction(element.getAttribute("data-ajax-complete"), ["xhr", "status"]).apply(element, arguments);
  89. },
  90. success: function (data, status, xhr) {
  91. asyncOnSuccess(element, data, xhr.getResponseHeader("Content-Type") || "text/html");
  92. getFunction(element.getAttribute("data-ajax-success"), ["data", "status", "xhr"]).apply(element, arguments);
  93. },
  94. error: function () {
  95. getFunction(element.getAttribute("data-ajax-failure"), ["xhr", "status", "error"]).apply(element, arguments);
  96. }
  97. });
  98. options.data.push({ name: "X-Requested-With", value: "XMLHttpRequest" });
  99. method = options.type.toUpperCase();
  100. if (!isMethodProxySafe(method)) {
  101. options.type = "POST";
  102. options.data.push({ name: "X-HTTP-Method-Override", value: method });
  103. }
  104. // change here:
  105. // Check for a Form POST with enctype=multipart/form-data
  106. // add the input file that were not previously included in the serializeArray()
  107. // set processData and contentType to false
  108. var $element = $(element);
  109. if ($element.is("form") && $element.attr("enctype") == "multipart/form-data") {
  110. var formdata = new FormData();
  111. $.each(options.data, function (i, v) {
  112. formdata.append(v.name, v.value);
  113. });
  114. $("input[type=file]", $element).each(function () {
  115. var file = this;
  116. $.each(file.files, function (n, v) {
  117. formdata.append(file.name, v);
  118. });
  119. });
  120. $.extend(options, {
  121. processData: false,
  122. contentType: false,
  123. data: formdata
  124. });
  125. }
  126. // end change
  127. $.ajax(options);
  128. }
  129. function validate(form) {
  130. var validationInfo = $(form).data(data_validation);
  131. return !validationInfo || !validationInfo.validate || validationInfo.validate();
  132. }
  133. $(document).on("click", "a[data-ajax=true]", function (evt) {
  134. evt.preventDefault();
  135. asyncRequest(this, {
  136. url: this.href,
  137. type: "GET",
  138. data: []
  139. });
  140. });
  141. $(document).on("click", "form[data-ajax=true] input[type=image]", function (evt) {
  142. var name = evt.target.name,
  143. target = $(evt.target),
  144. form = $(target.parents("form")[0]),
  145. offset = target.offset();
  146. form.data(data_click, [
  147. { name: name + ".x", value: Math.round(evt.pageX - offset.left) },
  148. { name: name + ".y", value: Math.round(evt.pageY - offset.top) }
  149. ]);
  150. setTimeout(function () {
  151. form.removeData(data_click);
  152. }, 0);
  153. });
  154. $(document).on("click", "form[data-ajax=true] :submit", function (evt) {
  155. var name = evt.currentTarget.name,
  156. target = $(evt.target),
  157. form = $(target.parents("form")[0]);
  158. form.data(data_click, name ? [{ name: name, value: evt.currentTarget.value }] : []);
  159. form.data(data_target, target);
  160. setTimeout(function () {
  161. form.removeData(data_click);
  162. form.removeData(data_target);
  163. }, 0);
  164. });
  165. $(document).on("submit", "form[data-ajax=true]", function (evt) {
  166. var clickInfo = $(this).data(data_click) || [],
  167. clickTarget = $(this).data(data_target),
  168. isCancel = clickTarget && (clickTarget.hasClass("cancel") || clickTarget.attr('formnovalidate') !== undefined);
  169. evt.preventDefault();
  170. if (!isCancel && !validate(this)) {
  171. return;
  172. }
  173. asyncRequest(this, {
  174. url: this.action,
  175. type: this.method || "GET",
  176. data: clickInfo.concat($(this).serializeArray())
  177. });
  178. });
  179. }(jQuery));