abp.jquery.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  1. var abp = abp || {};
  2. (function($) {
  3. if (!$) {
  4. throw "abp/jquery library requires the jquery library included to the page!";
  5. }
  6. // ABP CORE OVERRIDES /////////////////////////////////////////////////////
  7. abp.message._showMessage = function (message, title) {
  8. alert((title || '') + ' ' + message);
  9. return $.Deferred(function ($dfd) {
  10. $dfd.resolve();
  11. });
  12. };
  13. abp.message.confirm = function (message, titleOrCallback, callback) {
  14. if (titleOrCallback && !(typeof titleOrCallback == 'string')) {
  15. callback = titleOrCallback;
  16. }
  17. var result = confirm(message);
  18. callback && callback(result);
  19. return $.Deferred(function ($dfd) {
  20. $dfd.resolve(result);
  21. });
  22. };
  23. abp.utils.isFunction = function (obj) {
  24. return $.isFunction(obj);
  25. };
  26. // JQUERY EXTENSIONS //////////////////////////////////////////////////////
  27. $.fn.findWithSelf = function (selector) {
  28. return this.filter(selector).add(this.find(selector));
  29. };
  30. // DOM ////////////////////////////////////////////////////////////////////
  31. abp.dom = abp.dom || {};
  32. abp.dom.onNodeAdded = function (callback) {
  33. abp.event.on('abp.dom.nodeAdded', callback);
  34. };
  35. abp.dom.onNodeRemoved = function (callback) {
  36. abp.event.on('abp.dom.nodeRemoved', callback);
  37. };
  38. var mutationObserverCallback = function (mutationsList) {
  39. for (var i = 0; i < mutationsList.length; i++) {
  40. var mutation = mutationsList[i];
  41. if (mutation.type === 'childList') {
  42. if (mutation.addedNodes && mutation.removedNodes.length) {
  43. for (var k = 0; k < mutation.removedNodes.length; k++) {
  44. abp.event.trigger(
  45. 'abp.dom.nodeRemoved',
  46. {
  47. $el: $(mutation.removedNodes[k])
  48. }
  49. );
  50. }
  51. }
  52. if (mutation.addedNodes && mutation.addedNodes.length) {
  53. for (var j = 0; j < mutation.addedNodes.length; j++) {
  54. abp.event.trigger(
  55. 'abp.dom.nodeAdded',
  56. {
  57. $el: $(mutation.addedNodes[j])
  58. }
  59. );
  60. }
  61. }
  62. }
  63. }
  64. };
  65. $(function(){
  66. new MutationObserver(mutationObserverCallback).observe(
  67. $('body')[0],
  68. {
  69. subtree: true,
  70. childList: true
  71. }
  72. );
  73. });
  74. // AJAX ///////////////////////////////////////////////////////////////////
  75. abp.ajax = function (userOptions) {
  76. userOptions = userOptions || {};
  77. var options = $.extend(true, {}, abp.ajax.defaultOpts, userOptions);
  78. options.success = undefined;
  79. options.error = undefined;
  80. var xhr = null;
  81. var promise = $.Deferred(function ($dfd) {
  82. xhr = $.ajax(options)
  83. .done(function (data, textStatus, jqXHR) {
  84. $dfd.resolve(data);
  85. userOptions.success && userOptions.success(data);
  86. }).fail(function (jqXHR) {
  87. if(jqXHR.statusText === 'abort') {
  88. //ajax request is abort, ignore error handle.
  89. return;
  90. }
  91. if (jqXHR.getResponseHeader('_AbpErrorFormat') === 'true') {
  92. abp.ajax.handleAbpErrorResponse(jqXHR, userOptions, $dfd);
  93. } else {
  94. abp.ajax.handleNonAbpErrorResponse(jqXHR, userOptions, $dfd);
  95. }
  96. });
  97. }).promise();
  98. promise['jqXHR'] = xhr;
  99. return promise;
  100. };
  101. $.extend(abp.ajax, {
  102. defaultOpts: {
  103. dataType: 'json',
  104. type: 'POST',
  105. contentType: 'application/json',
  106. headers: {
  107. 'X-Requested-With': 'XMLHttpRequest'
  108. }
  109. },
  110. defaultError: {
  111. message: 'An error has occurred!',
  112. details: 'Error detail not sent by server.'
  113. },
  114. defaultError401: {
  115. message: 'You are not authenticated!',
  116. details: 'You should be authenticated (sign in) in order to perform this operation.'
  117. },
  118. defaultError403: {
  119. message: 'You are not authorized!',
  120. details: 'You are not allowed to perform this operation.'
  121. },
  122. defaultError404: {
  123. message: 'Resource not found!',
  124. details: 'The resource requested could not found on the server.'
  125. },
  126. logError: function (error) {
  127. abp.log.error(error);
  128. },
  129. showError: function (error) {
  130. if (error.details) {
  131. return abp.message.error(error.details, error.message);
  132. } else {
  133. return abp.message.error(error.message || abp.ajax.defaultError.message);
  134. }
  135. },
  136. handleTargetUrl: function (targetUrl) {
  137. if (!targetUrl) {
  138. location.href = abp.appPath;
  139. } else {
  140. location.href = targetUrl;
  141. }
  142. },
  143. handleErrorStatusCode: function (status) {
  144. switch (status) {
  145. case 401:
  146. abp.ajax.handleUnAuthorizedRequest(
  147. abp.ajax.showError(abp.ajax.defaultError401),
  148. abp.appPath
  149. );
  150. break;
  151. case 403:
  152. abp.ajax.showError(abp.ajax.defaultError403);
  153. break;
  154. case 404:
  155. abp.ajax.showError(abp.ajax.defaultError404);
  156. break;
  157. default:
  158. abp.ajax.showError(abp.ajax.defaultError);
  159. break;
  160. }
  161. },
  162. handleNonAbpErrorResponse: function (jqXHR, userOptions, $dfd) {
  163. if (userOptions.abpHandleError !== false) {
  164. abp.ajax.handleErrorStatusCode(jqXHR.status);
  165. }
  166. $dfd.reject.apply(this, arguments);
  167. userOptions.error && userOptions.error.apply(this, arguments);
  168. },
  169. handleAbpErrorResponse: function (jqXHR, userOptions, $dfd) {
  170. var messagePromise = null;
  171. if (userOptions.abpHandleError !== false) {
  172. messagePromise = abp.ajax.showError(jqXHR.responseJSON.error);
  173. }
  174. abp.ajax.logError(jqXHR.responseJSON.error);
  175. $dfd && $dfd.reject(jqXHR.responseJSON.error, jqXHR);
  176. userOptions.error && userOptions.error(jqXHR.responseJSON.error, jqXHR);
  177. if (jqXHR.status === 401 && userOptions.abpHandleError !== false) {
  178. abp.ajax.handleUnAuthorizedRequest(messagePromise);
  179. }
  180. },
  181. handleUnAuthorizedRequest: function (messagePromise, targetUrl) {
  182. if (messagePromise) {
  183. messagePromise.done(function () {
  184. abp.ajax.handleTargetUrl(targetUrl);
  185. });
  186. } else {
  187. abp.ajax.handleTargetUrl(targetUrl);
  188. }
  189. },
  190. blockUI: function (options) {
  191. if (options.blockUI) {
  192. if (options.blockUI === true) { //block whole page
  193. abp.ui.setBusy();
  194. } else { //block an element
  195. abp.ui.setBusy(options.blockUI);
  196. }
  197. }
  198. },
  199. unblockUI: function (options) {
  200. if (options.blockUI) {
  201. if (options.blockUI === true) { //unblock whole page
  202. abp.ui.clearBusy();
  203. } else { //unblock an element
  204. abp.ui.clearBusy(options.blockUI);
  205. }
  206. }
  207. },
  208. ajaxSendHandler: function (event, request, settings) {
  209. var token = abp.security.antiForgery.getToken();
  210. if (!token) {
  211. return;
  212. }
  213. if (!settings.headers || settings.headers[abp.security.antiForgery.tokenHeaderName] === undefined) {
  214. request.setRequestHeader(abp.security.antiForgery.tokenHeaderName, token);
  215. }
  216. }
  217. });
  218. $(document).ajaxSend(function (event, request, settings) {
  219. return abp.ajax.ajaxSendHandler(event, request, settings);
  220. });
  221. abp.event.on('abp.configurationInitialized', function () {
  222. var l = abp.localization.getResource('AbpUi');
  223. abp.ajax.defaultError.message = l('DefaultErrorMessage');
  224. abp.ajax.defaultError.details = l('DefaultErrorMessageDetail');
  225. abp.ajax.defaultError401.message = l('DefaultErrorMessage401');
  226. abp.ajax.defaultError401.details = l('DefaultErrorMessage401Detail');
  227. abp.ajax.defaultError403.message = l('DefaultErrorMessage403');
  228. abp.ajax.defaultError403.details = l('DefaultErrorMessage403Detail');
  229. abp.ajax.defaultError404.message = l('DefaultErrorMessage404');
  230. abp.ajax.defaultError404.details = l('DefaultErrorMessage404Detail');
  231. });
  232. // RESOURCE LOADER ////////////////////////////////////////////////////////
  233. /* UrlStates enum */
  234. var UrlStates = {
  235. LOADING: 'LOADING',
  236. LOADED: 'LOADED',
  237. FAILED: 'FAILED'
  238. };
  239. /* UrlInfo class */
  240. function UrlInfo(url) {
  241. this.url = url;
  242. this.state = UrlStates.LOADING;
  243. this.loadCallbacks = [];
  244. this.failCallbacks = [];
  245. }
  246. UrlInfo.prototype.succeed = function () {
  247. this.state = UrlStates.LOADED;
  248. for (var i = 0; i < this.loadCallbacks.length; i++) {
  249. this.loadCallbacks[i]();
  250. }
  251. };
  252. UrlInfo.prototype.failed = function () {
  253. this.state = UrlStates.FAILED;
  254. for (var i = 0; i < this.failCallbacks.length; i++) {
  255. this.failCallbacks[i]();
  256. }
  257. };
  258. UrlInfo.prototype.handleCallbacks = function (loadCallback, failCallback) {
  259. switch (this.state) {
  260. case UrlStates.LOADED:
  261. loadCallback && loadCallback();
  262. break;
  263. case UrlStates.FAILED:
  264. failCallback && failCallback();
  265. break;
  266. case UrlStates.LOADING:
  267. this.addCallbacks(loadCallback, failCallback);
  268. break;
  269. }
  270. };
  271. UrlInfo.prototype.addCallbacks = function (loadCallback, failCallback) {
  272. loadCallback && this.loadCallbacks.push(loadCallback);
  273. failCallback && this.failCallbacks.push(failCallback);
  274. };
  275. /* ResourceLoader API */
  276. abp.ResourceLoader = (function () {
  277. var _urlInfos = {};
  278. function getCacheKey(url) {
  279. return url;
  280. }
  281. function appendTimeToUrl(url) {
  282. if (url.indexOf('?') < 0) {
  283. url += '?';
  284. } else {
  285. url += '&';
  286. }
  287. url += '_=' + new Date().getTime();
  288. return url;
  289. }
  290. var _loadFromUrl = function (url, loadCallback, failCallback, serverLoader) {
  291. var cacheKey = getCacheKey(url);
  292. var urlInfo = _urlInfos[cacheKey];
  293. if (urlInfo) {
  294. urlInfo.handleCallbacks(loadCallback, failCallback);
  295. return;
  296. }
  297. _urlInfos[cacheKey] = urlInfo = new UrlInfo(url);
  298. urlInfo.addCallbacks(loadCallback, failCallback);
  299. serverLoader(urlInfo);
  300. };
  301. var _loadScript = function (url, loadCallback, failCallback) {
  302. _loadFromUrl(url, loadCallback, failCallback, function (urlInfo) {
  303. $.get({
  304. url: url,
  305. dataType: 'text'
  306. })
  307. .done(function (script) {
  308. $.globalEval(script);
  309. urlInfo.succeed();
  310. })
  311. .fail(function () {
  312. urlInfo.failed();
  313. });
  314. });
  315. };
  316. var _loadStyle = function (url) {
  317. _loadFromUrl(url, undefined, undefined, function (urlInfo) {
  318. $('<link/>', {
  319. rel: 'stylesheet',
  320. type: 'text/css',
  321. href: appendTimeToUrl(url)
  322. }).appendTo('head');
  323. });
  324. };
  325. return {
  326. loadScript: _loadScript,
  327. loadStyle: _loadStyle
  328. }
  329. })();
  330. })(jQuery);