提交 | 用户 | 时间
|
58d006
|
1 |
/** |
A |
2 |
<b>Load content via Ajax </b>. For more information please refer to documentation #basics/ajax |
|
3 |
*/ |
|
4 |
|
|
5 |
(function($ , undefined) { |
|
6 |
var ajax_loaded_scripts = {} |
|
7 |
|
|
8 |
function AceAjax(contentArea, settings) { |
|
9 |
var $contentArea = $(contentArea); |
|
10 |
var self = this; |
|
11 |
$contentArea.attr('data-ajax-content', 'true'); |
|
12 |
|
|
13 |
//get a list of 'data-*' attributes that override 'defaults' and 'settings' |
|
14 |
var attrib_values = ace.helper.getAttrSettings(contentArea, $.fn.ace_ajax.defaults); |
|
15 |
this.settings = $.extend({}, $.fn.ace_ajax.defaults, settings, attrib_values); |
|
16 |
|
|
17 |
|
|
18 |
var working = false; |
|
19 |
var $overlay = $();//empty set |
|
20 |
|
|
21 |
this.force_reload = false;//set jQuery ajax's cache option to 'false' to reload content |
|
22 |
this.loadUrl = function(hash, cache, manual_trigger) { |
|
23 |
var url = false; |
|
24 |
hash = hash.replace(/^(\#\!)?\#/, ''); |
|
25 |
|
|
26 |
this.force_reload = (cache === false) |
|
27 |
|
|
28 |
if(typeof this.settings.content_url === 'function') url = this.settings.content_url(hash); |
|
29 |
if(typeof url === 'string') this.getUrl(url, hash, manual_trigger); |
|
30 |
} |
|
31 |
|
|
32 |
this.loadAddr = function(url, hash, cache) { |
|
33 |
this.force_reload = (cache === false); |
|
34 |
this.getUrl(url, hash, false); |
|
35 |
} |
|
36 |
|
|
37 |
|
|
38 |
this.reload = function() { |
|
39 |
var hash = $.trim(window.location.hash); |
|
40 |
if(!hash && this.settings.default_url) hash = this.settings.default_url; |
|
41 |
|
|
42 |
this.loadUrl(hash, false); |
|
43 |
} |
|
44 |
this.post = function(url, data, updateView, extraParams) { |
|
45 |
var url = url || $.trim(location.href.replace(location.hash,'')); |
|
46 |
if(!url) return; |
|
47 |
var data = data || {} |
|
48 |
var updateView = updateView || false; |
|
49 |
this.getUrl(url, null, false, 'POST', data, updateView, extraParams); |
|
50 |
} |
|
51 |
|
|
52 |
|
|
53 |
this.getUrl = function(url, hash, manual_trigger, method, data, updateView, extraParams) { |
|
54 |
if(working) { |
|
55 |
return; |
|
56 |
} |
|
57 |
|
|
58 |
var method = method || 'GET'; |
|
59 |
var updateView = (method == 'GET') || (method == 'POST' && updateView == true) |
|
60 |
var data = data || null; |
|
61 |
|
|
62 |
var event |
|
63 |
$contentArea.trigger(event = $.Event('ajaxloadstart'), {url: url, hash: hash, method: method, data: data}) |
|
64 |
if (event.isDefaultPrevented()) return; |
|
65 |
|
|
66 |
self.startLoading(); |
|
67 |
|
|
68 |
|
|
69 |
var ajax_params = method == 'GET' ? {'url': url, 'cache': !this.force_reload} : {'url': url, 'method' : 'POST', 'data': data} |
|
70 |
if(method == 'POST' && typeof extraParams == 'object') ajax_params = $.extend({}, ajax_params, extraParams); |
|
71 |
|
|
72 |
$.ajax(ajax_params) |
|
73 |
.error(function() { |
|
74 |
$contentArea.trigger('ajaxloaderror', {url: url, hash: hash, method: method, data: data}); |
|
75 |
|
|
76 |
self.stopLoading(true); |
|
77 |
}) |
|
78 |
.done(function(result) { |
|
79 |
$contentArea.trigger('ajaxloaddone', {url: url, hash: hash, method: method, data: data}); |
|
80 |
if(method == 'POST') { |
|
81 |
var event |
|
82 |
$contentArea.trigger(event = $.Event('ajaxpostdone', {url: url, data: data, result: result})) |
|
83 |
if( event.isDefaultPrevented() ) updateView = false; |
|
84 |
} |
|
85 |
|
|
86 |
|
|
87 |
var link_element = null, link_text = ''; |
|
88 |
if(typeof self.settings.update_active === 'function') { |
|
89 |
link_element = self.settings.update_active.call(null, hash, url, method, updateView); |
|
90 |
} |
|
91 |
else if(self.settings.update_active === true && hash) { |
|
92 |
link_element = $('a[data-url="'+hash+'"]'); |
|
93 |
if(link_element.length > 0) { |
|
94 |
var nav = link_element.closest('.nav'); |
|
95 |
if(nav.length > 0) { |
|
96 |
nav.find('.active').each(function(){ |
|
97 |
var $class = 'active'; |
|
98 |
if( $(this).hasClass('hover') || self.settings.close_active ) $class += ' open'; |
|
99 |
|
|
100 |
$(this).removeClass($class); |
|
101 |
if(self.settings.close_active) { |
|
102 |
$(this).find(' > .submenu').css('display', ''); |
|
103 |
} |
|
104 |
}) |
|
105 |
|
|
106 |
var active_li = link_element.closest('li').addClass('active').parents('.nav li').addClass('active open'); |
|
107 |
nav.closest('.sidebar[data-sidebar-scroll=true]').each(function() { |
|
108 |
var $this = $(this); |
|
109 |
$this.ace_sidebar_scroll('reset'); |
|
110 |
if(manual_trigger == true) $this.ace_sidebar_scroll('scroll_to_active');//first time only |
|
111 |
}) |
|
112 |
} |
|
113 |
} |
|
114 |
} |
|
115 |
|
|
116 |
///////// |
|
117 |
if(typeof self.settings.update_breadcrumbs === 'function') { |
|
118 |
link_text = self.settings.update_breadcrumbs.call(null, hash, url, link_element, method, updateView); |
|
119 |
} |
|
120 |
else if(self.settings.update_breadcrumbs === true && link_element != null && link_element.length > 0) { |
|
121 |
link_text = updateBreadcrumbs(link_element); |
|
122 |
} |
|
123 |
///////// |
|
124 |
|
|
125 |
$overlay.addClass('content-loaded').detach(); |
|
126 |
if(updateView) { |
|
127 |
//convert "title" and "link" tags to "div" tags for later processing |
|
128 |
result = String(result) |
|
129 |
.replace(/<(title|link)([\s\>])/gi,'<div class="hidden ajax-append-$1"$2') |
|
130 |
.replace(/<\/(title|link)\>/gi,'</div>') |
|
131 |
$contentArea.empty().html(result); |
|
132 |
} |
|
133 |
|
|
134 |
$(self.settings.loading_overlay || $contentArea).append($overlay); |
|
135 |
|
|
136 |
|
|
137 |
|
|
138 |
//remove previous stylesheets inserted via ajax |
|
139 |
if(updateView) setTimeout(function() { |
|
140 |
$('head').find('link.ace-ajax-stylesheet').remove(); |
|
141 |
|
|
142 |
var main_selectors = ['link.ace-main-stylesheet', 'link#main-ace-style', 'link[href*="/ace.min.css"]', 'link[href*="/ace.css"]'] |
|
143 |
var ace_style = []; |
|
144 |
for(var m = 0; m < main_selectors.length; m++) { |
|
145 |
ace_style = $('head').find(main_selectors[m]).first(); |
|
146 |
if(ace_style.length > 0) break; |
|
147 |
} |
|
148 |
|
|
149 |
$contentArea.find('.ajax-append-link').each(function(e) { |
|
150 |
var $link = $(this); |
|
151 |
if ( $link.attr('href') ) { |
|
152 |
var new_link = jQuery('<link />', {type : 'text/css', rel: 'stylesheet', 'class': 'ace-ajax-stylesheet'}) |
|
153 |
if( ace_style.length > 0 ) new_link.insertBefore(ace_style); |
|
154 |
else new_link.appendTo('head'); |
|
155 |
new_link.attr('href', $link.attr('href'));//we set "href" after insertion, for IE to work |
|
156 |
} |
|
157 |
$link.remove(); |
|
158 |
}) |
|
159 |
}, 10); |
|
160 |
|
|
161 |
////////////////////// |
|
162 |
|
|
163 |
if(typeof self.settings.update_title === 'function') { |
|
164 |
self.settings.update_title.call(null, hash, url, link_text, method, updateView); |
|
165 |
} |
|
166 |
else if(self.settings.update_title === true && method == 'GET') { |
|
167 |
updateTitle(link_text); |
|
168 |
} |
|
169 |
|
|
170 |
if( !manual_trigger && updateView ) { |
|
171 |
$('html,body').animate({scrollTop: 0}, 250); |
|
172 |
} |
|
173 |
|
|
174 |
////////////////////// |
|
175 |
$contentArea.trigger('ajaxloadcomplete', {url: url, hash: hash, method: method, data:data}); |
|
176 |
////////////////////// |
|
177 |
|
|
178 |
|
|
179 |
//if result contains call to "loadScripts" then don't stopLoading now |
|
180 |
var re = /\.(?:\s*)ace(?:_a|A)jax(?:\s*)\((?:\s*)(?:\'|\")loadScripts(?:\'|\")/; |
|
181 |
if(result.match(re)) self.stopLoading(); |
|
182 |
else self.stopLoading(true); |
|
183 |
}) |
|
184 |
} |
|
185 |
|
|
186 |
|
|
187 |
/////////////////////// |
|
188 |
var fixPos = false; |
|
189 |
var loadTimer = null; |
|
190 |
this.startLoading = function() { |
|
191 |
if(working) return; |
|
192 |
working = true; |
|
193 |
|
|
194 |
if(!this.settings.loading_overlay && $contentArea.css('position') == 'static') { |
|
195 |
$contentArea.css('position', 'relative');//for correct icon positioning |
|
196 |
fixPos = true; |
|
197 |
} |
|
198 |
|
|
199 |
$overlay.remove(); |
|
200 |
$overlay = $('<div class="ajax-loading-overlay"><i class="ajax-loading-icon '+(this.settings.loading_icon || '')+'"></i> '+this.settings.loading_text+'</div>') |
|
201 |
|
|
202 |
if(this.settings.loading_overlay == 'body') $('body').append($overlay.addClass('ajax-overlay-body')); |
|
203 |
else if(this.settings.loading_overlay) $(this.settings.loading_overlay).append($overlay); |
|
204 |
else $contentArea.append($overlay); |
|
205 |
|
|
206 |
|
|
207 |
if(this.settings.max_load_wait !== false) |
|
208 |
loadTimer = setTimeout(function() { |
|
209 |
loadTimer = null; |
|
210 |
if(!working) return; |
|
211 |
|
|
212 |
var event |
|
213 |
$contentArea.trigger(event = $.Event('ajaxloadlong')) |
|
214 |
if (event.isDefaultPrevented()) return; |
|
215 |
|
|
216 |
self.stopLoading(true); |
|
217 |
}, this.settings.max_load_wait * 1000); |
|
218 |
} |
|
219 |
|
|
220 |
this.stopLoading = function(stopNow) { |
|
221 |
if(stopNow === true) { |
|
222 |
working = false; |
|
223 |
|
|
224 |
$overlay.remove(); |
|
225 |
if(fixPos) { |
|
226 |
$contentArea.css('position', '');//restore previous 'position' value |
|
227 |
fixPos = false; |
|
228 |
} |
|
229 |
|
|
230 |
if(loadTimer != null) { |
|
231 |
clearTimeout(loadTimer); |
|
232 |
loadTimer = null; |
|
233 |
} |
|
234 |
} |
|
235 |
else { |
|
236 |
$overlay.addClass('almost-loaded'); |
|
237 |
|
|
238 |
$contentArea.one('ajaxscriptsloaded.inner_call', function() { |
|
239 |
self.stopLoading(true); |
|
240 |
/** |
|
241 |
if(window.Pace && Pace.running == true) { |
|
242 |
Pace.off('done'); |
|
243 |
Pace.once('done', function() { self.stopLoading(true) }) |
|
244 |
} |
|
245 |
else self.stopLoading(true); |
|
246 |
*/ |
|
247 |
}) |
|
248 |
} |
|
249 |
} |
|
250 |
|
|
251 |
this.working = function() { |
|
252 |
return working; |
|
253 |
} |
|
254 |
/////////////////////// |
|
255 |
|
|
256 |
|
|
257 |
|
|
258 |
function updateBreadcrumbs(link_element) { |
|
259 |
var link_text = ''; |
|
260 |
|
|
261 |
//update breadcrumbs |
|
262 |
var breadcrumbs = $('.breadcrumb'); |
|
263 |
if(breadcrumbs.length > 0 && breadcrumbs.is(':visible')) { |
|
264 |
breadcrumbs.find('> li:not(:first-child)').remove(); |
|
265 |
|
|
266 |
var i = 0; |
|
267 |
link_element.parents('.nav li').each(function() { |
|
268 |
var link = $(this).find('> a'); |
|
269 |
|
|
270 |
var link_clone = link.clone(); |
|
271 |
link_clone.find('i,.fa,.glyphicon,.ace-icon,.menu-icon,.badge,.label').remove(); |
|
272 |
var text = link_clone.text(); |
|
273 |
link_clone.remove(); |
|
274 |
|
|
275 |
var href = link.attr('href'); |
|
276 |
|
|
277 |
if(i == 0) { |
|
278 |
var li = $('<li class="active"></li>').appendTo(breadcrumbs); |
|
279 |
li.text(text); |
|
280 |
link_text = text; |
|
281 |
} |
|
282 |
else { |
|
283 |
var li = $('<li><a /></li>').insertAfter(breadcrumbs.find('> li:first-child')); |
|
284 |
li.find('a').attr('href', href).text(text); |
|
285 |
} |
|
286 |
i++; |
|
287 |
}) |
|
288 |
} |
|
289 |
|
|
290 |
return link_text; |
|
291 |
} |
|
292 |
|
|
293 |
function updateTitle(link_text) { |
|
294 |
var $title = $contentArea.find('.ajax-append-title'); |
|
295 |
if($title.length > 0) { |
|
296 |
document.title = $title.text(); |
|
297 |
$title.remove(); |
|
298 |
} |
|
299 |
else if(link_text.length > 0) { |
|
300 |
var extra = $.trim(String(document.title).replace(/^(.*)[\-]/, ''));//for example like " - Ace Admin" |
|
301 |
if(extra) extra = ' - ' + extra; |
|
302 |
link_text = $.trim(link_text) + extra; |
|
303 |
} |
|
304 |
} |
|
305 |
|
|
306 |
|
|
307 |
this.loadScripts = function(scripts, callback) { |
|
308 |
var scripts = scripts || []; |
|
309 |
$.ajaxPrefilter('script', function(opts) {opts.cache = true}); |
|
310 |
setTimeout(function() { |
|
311 |
//let's keep a list of loaded scripts so that we don't load them more than once! |
|
312 |
|
|
313 |
function finishLoading() { |
|
314 |
if(typeof callback === 'function') callback(); |
|
315 |
$('.btn-group[data-toggle="buttons"] > .btn').button(); |
|
316 |
|
|
317 |
$contentArea.trigger('ajaxscriptsloaded'); |
|
318 |
} |
|
319 |
|
|
320 |
//var deferreds = []; |
|
321 |
var deferred_count = 0;//deferreds count |
|
322 |
var resolved = 0; |
|
323 |
for(var i = 0; i < scripts.length; i++) if(scripts[i]) { |
|
324 |
(function() { |
|
325 |
var script_name = "js-"+scripts[i].replace(/[^\w\d\-]/g, '-').replace(/\-\-/g, '-'); |
|
326 |
if( ajax_loaded_scripts[script_name] !== true ) deferred_count++; |
|
327 |
})() |
|
328 |
} |
|
329 |
|
|
330 |
|
|
331 |
function nextScript(index) { |
|
332 |
index += 1; |
|
333 |
if(index < scripts.length) loadScript(index); |
|
334 |
else { |
|
335 |
finishLoading(); |
|
336 |
} |
|
337 |
} |
|
338 |
|
|
339 |
function loadScript(index) { |
|
340 |
index = index || 0; |
|
341 |
if(!scripts[index]) {//could be null sometimes |
|
342 |
return nextScript(index); |
|
343 |
} |
|
344 |
|
|
345 |
var script_name = "js-"+scripts[index].replace(/[^\w\d\-]/g, '-').replace(/\-\-/g, '-'); |
|
346 |
//only load scripts that are not loaded yet! |
|
347 |
if( ajax_loaded_scripts[script_name] !== true ) { |
|
348 |
$.getScript(scripts[index]) |
|
349 |
.done(function() { |
|
350 |
ajax_loaded_scripts[script_name] = true; |
|
351 |
}) |
|
352 |
//.fail(function() { |
|
353 |
//}) |
|
354 |
.complete(function() { |
|
355 |
resolved++; |
|
356 |
if(resolved >= deferred_count && working) { |
|
357 |
finishLoading(); |
|
358 |
} |
|
359 |
else { |
|
360 |
nextScript(index); |
|
361 |
} |
|
362 |
}) |
|
363 |
} |
|
364 |
else {//script previoisly loaded |
|
365 |
nextScript(index); |
|
366 |
} |
|
367 |
} |
|
368 |
|
|
369 |
|
|
370 |
if (deferred_count > 0) { |
|
371 |
loadScript(); |
|
372 |
} |
|
373 |
else { |
|
374 |
finishLoading(); |
|
375 |
} |
|
376 |
|
|
377 |
}, 10) |
|
378 |
} |
|
379 |
|
|
380 |
|
|
381 |
|
|
382 |
///////////////// |
|
383 |
$(window) |
|
384 |
.off('hashchange.ace_ajax') |
|
385 |
.on('hashchange.ace_ajax', function(e, manual_trigger) { |
|
386 |
var hash = $.trim(window.location.hash); |
|
387 |
if(!hash || hash.length == 0) return; |
|
388 |
|
|
389 |
if(self.settings.close_mobile_menu) { |
|
390 |
try {$(self.settings.close_mobile_menu).ace_sidebar('mobileHide')} catch(e){} |
|
391 |
} |
|
392 |
if(self.settings.close_dropdowns) { |
|
393 |
$('.dropdown.open .dropdown-toggle').dropdown('toggle'); |
|
394 |
} |
|
395 |
|
|
396 |
self.loadUrl(hash, null, manual_trigger); |
|
397 |
}).trigger('hashchange.ace_ajax', [true]); |
|
398 |
|
|
399 |
var hash = $.trim(window.location.hash); |
|
400 |
if(!hash && this.settings.default_url) window.location.hash = this.settings.default_url; |
|
401 |
|
|
402 |
}//AceAjax |
|
403 |
|
|
404 |
|
|
405 |
|
|
406 |
$.fn.aceAjax = $.fn.ace_ajax = function (option, value, value2, value3, value4) { |
|
407 |
var method_call; |
|
408 |
|
|
409 |
var $set = this.each(function () { |
|
410 |
var $this = $(this); |
|
411 |
var data = $this.data('ace_ajax'); |
|
412 |
var options = typeof option === 'object' && option; |
|
413 |
|
|
414 |
if (!data) $this.data('ace_ajax', (data = new AceAjax(this, options))); |
|
415 |
if (typeof option === 'string' && typeof data[option] === 'function') { |
|
416 |
if(value4 !== undefined) method_call = data[option](value, value2, value3, value4); |
|
417 |
else if(value3 !== undefined) method_call = data[option](value, value2, value3); |
|
418 |
else if(value2 !== undefined) method_call = data[option](value, value2); |
|
419 |
else method_call = data[option](value); |
|
420 |
} |
|
421 |
}); |
|
422 |
|
|
423 |
return (method_call === undefined) ? $set : method_call; |
|
424 |
} |
|
425 |
|
|
426 |
|
|
427 |
|
|
428 |
$.fn.aceAjax.defaults = $.fn.ace_ajax.defaults = { |
|
429 |
content_url: false, |
|
430 |
default_url: false, |
|
431 |
loading_icon: 'fa fa-spin fa-spinner fa-2x orange', |
|
432 |
loading_text: '', |
|
433 |
loading_overlay: null, |
|
434 |
update_breadcrumbs: true, |
|
435 |
update_title: true, |
|
436 |
update_active: true, |
|
437 |
close_active: false, |
|
438 |
max_load_wait: false, |
|
439 |
close_mobile_menu: false, |
|
440 |
close_dropdowns: false |
|
441 |
} |
|
442 |
|
|
443 |
})(window.jQuery); |
|
444 |
|