jquery.unobtrusive-ajax.js 6.8 KB

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