1 /*!
2 ** Unobtrusive Ajax support library for jQuery
3 ** Copyright (C) Microsoft Corporation. All rights reserved.
4 */
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 /*
9 data-ajax=true //开启绑定
10
11 data-ajax-mode//更新的形式 BEFORE插入到对象之前 AFTER插入到对象之后 为空就是覆盖
12 data-ajax-update//更新的对象
13 data-ajax-confirm//设置一个确定取消弹出框的文字,没有则不设置
14 data-ajax-loading//显示loading的对象
15 data-ajax-loading-duration//持续时间 默认是0
16 data-ajax-method//提交方式
17 data-ajax-url//提交url
18 data-ajax-begin//ajax前触发的函数或者一段程序
19 data-ajax-complete//完成后,此时还没有加载返回的数据,请求成功或失败时均调用
20 data-ajax-success//成功,加载完成的数据
21 data-ajax-failure//失败
22
23 */
24
25 (function ($) {
26 var data_click = "unobtrusiveAjaxClick",
27 data_validation = "unobtrusiveValidation";
28 //第二核心,判断是否函数,不是则构造一个匿名函数
29 function getFunction(code, argNames) {
30 var fn = window, parts = (code || "").split(".");
31 while (fn && parts.length) {
32 fn = fn[parts.shift()];
33 }//查找函数名有时候是命名空间比如xxx.xxx
34 if (typeof (fn) === "function") {
35 return fn;
36 }
37 argNames.push(code);
38 //如果不是函数对象则自己构造一个并返回,吊!
39 return Function.constructor.apply(null, argNames);
40 }
41
42 function isMethodProxySafe(method) {
43 return method === "GET" || method === "POST";
44 }
45 //可以添加各种提交方式,应该是为Web Api做的补充
46 function asyncOnBeforeSend(xhr, method) {
47 if (!isMethodProxySafe(method)) {
48 xhr.setRequestHeader("X-HTTP-Method-Override", method);
49 }
50 //注:X-HTTP-Method-Override是一个非标准的HTTP报头。
51 //这是为不能发送某些HTTP请求类型(如PUT或DELETE)的客户端而设计的
52 }
53 //完成后的
54 function asyncOnSuccess(element, data, contentType) {
55 var mode;
56
57 if (contentType.indexOf("application/x-javascript") !== -1) { // jQuery already executes JavaScript for us
58 return;
59 }
60
61 mode = (element.getAttribute("data-ajax-mode") || "").toUpperCase();
62 $(element.getAttribute("data-ajax-update")).each(function (i, update) {
63 var top;
64
65 switch (mode) {
66 case "BEFORE":
67 top = update.firstChild;
68 $("<div />").html(data).contents().each(function () {
69 update.insertBefore(this, top);
70 });
71 break;
72 case "AFTER":
73 $("<div />").html(data).contents().each(function () {
74 update.appendChild(this);
75 });
76 break;
77 default:
78 $(update).html(data);
79 break;
80 }
81 });
82 }
83 //主要函数
84 //绑定的对象和参数
85 function asyncRequest(element, options) {
86 var confirm, loading, method, duration;
87
88 confirm = element.getAttribute("data-ajax-confirm");
89 if (confirm && !window.confirm(confirm)) {
90 return;
91 }
92
93 loading = $(element.getAttribute("data-ajax-loading"));//
94 duration = element.getAttribute("data-ajax-loading-duration") || 0;//默认是0
95
96 $.extend(options, {
97 type: element.getAttribute("data-ajax-method") || undefined,
98 url: element.getAttribute("data-ajax-url") || undefined,
99 beforeSend: function (xhr) {//ajax前触发,此处的xhr将在下面用apply传递出去
100 var result;
101 asyncOnBeforeSend(xhr, method);//判断是否添加特种的提交方式
102 result = getFunction(element.getAttribute("data-ajax-begin"), ["xhr"]).apply(this, arguments);//argument:替换函数对象的其中一个属性对象,存储参数。这里是将原先的参数传递出去,吊!
103 if (result !== false) {
104 loading.show(duration);
105 }
106 return result;
107 },
108 complete: function () {
109 loading.hide(duration);
110 getFunction(element.getAttribute("data-ajax-complete"), ["xhr", "status"]).apply(this, arguments);
111 },
112 success: function (data, status, xhr) {
113 asyncOnSuccess(element, data, xhr.getResponseHeader("Content-Type") || "text/html");
114 getFunction(element.getAttribute("data-ajax-success"), ["data", "status", "xhr"]).apply(this, arguments);
115 },
116 error: getFunction(element.getAttribute("data-ajax-failure"), ["xhr", "status", "error"])
117 });
118
119 options.data.push({ name: "X-Requested-With", value: "XMLHttpRequest" });
120
121 method = options.type.toUpperCase();//大写
122 if (!isMethodProxySafe(method)) {
123 options.type = "POST";
124 options.data.push({ name: "X-HTTP-Method-Override", value: method });
125 }
126 //最后都是调用jquery的ajax
127 $.ajax(options);
128 }
129
130 function validate(form) {
131 //可以取消验证
132 var validationInfo = $(form).data(data_validation);
133 return !validationInfo || !validationInfo.validate || validationInfo.validate();
134 }
135
136 $(document).on("click", "a[data-ajax=true]", function (evt) {
137 evt.preventDefault();
138 asyncRequest(this, {
139 url: this.href,
140 type: "GET",
141 data: []
142 });
143 });
144
145 $(document).on("click", "form[data-ajax=true] input[type=image]", function (evt) {//这个不常用
146 var name = evt.target.name,
147 $target = $(evt.target),
148 form = $target.parents("form")[0],
149 offset = $target.offset();
150
151 $(form).data(data_click, [
152 { name: name + ".x", value: Math.round(evt.pageX - offset.left) },
153 { name: name + ".y", value: Math.round(evt.pageY - offset.top) }
154 ]);
155
156 setTimeout(function () {
157 $(form).removeData(data_click);
158 }, 0);
159 });
160
161 $(document).on("click", "form[data-ajax=true] :submit", function (evt) {
162 var name = evt.target.name,
163 form = $(evt.target).parents("form")[0];
164
165 $(form).data(data_click, name ? [{ name: name, value: evt.target.value }] : []);
166
167 setTimeout(function () {
168 $(form).removeData(data_click);
169 }, 0);
170 });
171
172 $(document).on("submit", "form[data-ajax=true]", function (evt) {
173 var clickInfo = $(this).data(data_click) || [];
174 evt.preventDefault();
175 if (!validate(this)) {
176 return;
177 }
178 asyncRequest(this, {
179 url: this.action,
180 type: this.method || "GET",
181 data: clickInfo.concat($(this).serializeArray())//写得好,序列化表单并拼接,以后的ajax都可以这样,方便啊
182 });
183 });
184 }(jQuery));