jquery.unobtrusive-ajax.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. /// <reference path="jquery-1.5.1.js" />
  2. /*!
  3. ** Unobtrusive Ajax support library for jQuery
  4. ** Copyright (C) Microsoft Corporation. All rights reserved.
  5. */
  6. /*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 */
  7. /*global window: false, jQuery: false */
  8. (function ($) {
  9. var data_click = "unobtrusiveAjaxClick",
  10. data_validation = "unobtrusiveValidation";
  11. function getFunction(code, argNames) {
  12. var fn = window, parts = (code || "").split(".");
  13. while (fn && parts.length) {
  14. fn = fn[parts.shift()];
  15. }
  16. if (typeof (fn) === "function") {
  17. return fn;
  18. }
  19. argNames.push(code);
  20. return Function.constructor.apply(null, argNames);
  21. }
  22. function isMethodProxySafe(method) {
  23. return method === "GET" || method === "POST";
  24. }
  25. function asyncOnBeforeSend(xhr, method) {
  26. if (!isMethodProxySafe(method)) {
  27. xhr.setRequestHeader("X-HTTP-Method-Override", method);
  28. }
  29. }
  30. function asyncOnSuccess(element, data, contentType) {
  31. var mode;
  32. if (contentType.indexOf("application/x-javascript") !== -1) { // jQuery already executes JavaScript for us
  33. return;
  34. }
  35. mode = (element.getAttribute("data-ajax-mode") || "").toUpperCase();
  36. $(element.getAttribute("data-ajax-update")).each(function (i, update) {
  37. var top;
  38. switch (mode) {
  39. case "BEFORE":
  40. top = update.firstChild;
  41. $("<div />").html(data).contents().each(function () {
  42. update.insertBefore(this, top);
  43. });
  44. break;
  45. case "AFTER":
  46. $("<div />").html(data).contents().each(function () {
  47. update.appendChild(this);
  48. });
  49. break;
  50. default:
  51. $(update).html(data);
  52. break;
  53. }
  54. });
  55. }
  56. function asyncRequest(element, options) {
  57. var confirm, loading, method, duration;
  58. confirm = element.getAttribute("data-ajax-confirm");
  59. if (confirm && !window.confirm(confirm)) {
  60. return;
  61. }
  62. loading = $(element.getAttribute("data-ajax-loading"));
  63. duration = element.getAttribute("data-ajax-loading-duration") || 0;
  64. $.extend(options, {
  65. type: element.getAttribute("data-ajax-method") || undefined,
  66. url: element.getAttribute("data-ajax-url") || undefined,
  67. beforeSend: function (xhr) {
  68. var result;
  69. asyncOnBeforeSend(xhr, method);
  70. result = getFunction(element.getAttribute("data-ajax-begin"), ["xhr"]).apply(this, arguments);
  71. if (result !== false) {
  72. loading.show(duration);
  73. }
  74. return result;
  75. },
  76. complete: function () {
  77. loading.hide(duration);
  78. getFunction(element.getAttribute("data-ajax-complete"), ["xhr", "status"]).apply(this, arguments);
  79. },
  80. success: function (data, status, xhr) {
  81. asyncOnSuccess(element, data, xhr.getResponseHeader("Content-Type") || "text/html");
  82. getFunction(element.getAttribute("data-ajax-success"), ["data", "status", "xhr"]).apply(this, arguments);
  83. },
  84. error: getFunction(element.getAttribute("data-ajax-failure"), ["xhr", "status", "error"])
  85. });
  86. options.data.push({ name: "X-Requested-With", value: "XMLHttpRequest" });
  87. method = options.type.toUpperCase();
  88. if (!isMethodProxySafe(method)) {
  89. options.type = "POST";
  90. options.data.push({ name: "X-HTTP-Method-Override", value: method });
  91. }
  92. $.ajax(options);
  93. }
  94. function validate(form) {
  95. var validationInfo = $(form).data(data_validation);
  96. return !validationInfo || !validationInfo.validate || validationInfo.validate();
  97. }
  98. $("a[data-ajax=true]").live("click", function (evt) {
  99. evt.preventDefault();
  100. asyncRequest(this, {
  101. url: this.href,
  102. type: "GET",
  103. data: []
  104. });
  105. });
  106. $("form[data-ajax=true] input[type=image]").live("click", function (evt) {
  107. var name = evt.target.name,
  108. $target = $(evt.target),
  109. form = $target.parents("form")[0],
  110. offset = $target.offset();
  111. $(form).data(data_click, [
  112. { name: name + ".x", value: Math.round(evt.pageX - offset.left) },
  113. { name: name + ".y", value: Math.round(evt.pageY - offset.top) }
  114. ]);
  115. setTimeout(function () {
  116. $(form).removeData(data_click);
  117. }, 0);
  118. });
  119. $("form[data-ajax=true] :submit").live("click", function (evt) {
  120. var name = evt.target.name,
  121. form = $(evt.target).parents("form")[0];
  122. $(form).data(data_click, name ? [{ name: name, value: evt.target.value }] : []);
  123. setTimeout(function () {
  124. $(form).removeData(data_click);
  125. }, 0);
  126. });
  127. $("form[data-ajax=true]").live("submit", function (evt) {
  128. var clickInfo = $(this).data(data_click) || [];
  129. evt.preventDefault();
  130. if (!validate(this)) {
  131. return;
  132. }
  133. asyncRequest(this, {
  134. url: this.action,
  135. type: this.method || "GET",
  136. data: clickInfo.concat($(this).serializeArray())
  137. });
  138. });
  139. }(jQuery));