Administrator
2023-04-21 195945efc5db921a4c9eb8cf9421c172273293f5
提交 | 用户 | 时间
58d006 1 (function(){
A 2 if( !('ace' in window) ) window['ace'] = {}
3
4 ace.config = {
5  storage_method: 0, //0 means use localStorage if available otherwise cookies, 1 means localStorage, 2 means cookies
6  cookie_expiry : 604800, //(cookie only) 1 week duration for saved settings
7  cookie_path: ''//(cookie only)
8 }
9 if( !('vars' in window['ace']) ) window['ace'].vars = {}
10 ace.vars['very_old_ie']    = !('querySelector' in document.documentElement);
11
12 ace.settings = {
13     saveState : function(element, attrName, attrVal, append) {
14         if( !element || (typeof element == 'string' && !(element = document.getElementById(element))) || !element.hasAttribute('id') ) return false;
15         if( !ace.hasClass(element, 'ace-save-state') ) return false;
16         
17         var attrName = attrName || 'class';
18         var id = element.getAttribute('id');
19         
20         var attrList = ace.data.get('state', 'id-'+id) || {};
21         if(typeof attrList == 'string') {
22             try {
23                 attrList = JSON.parse(attrList);
24             }
25             catch(e) {
26                 attrList = {}
27             }
28         }
29
30         var newVal, hasCustomVal = typeof attrVal !== 'undefined', $delete = false;
31         
32         var re1 = /class/i
33         var re2 = /checked|disabled|readonly|value/i
34
35         if(re2.test(attrName)) newVal = hasCustomVal ? attrVal : element[attrName];
36         else {
37             if(element.hasAttribute(attrName)) {
38                 newVal = hasCustomVal ? attrVal : element.getAttribute(attrName);
39             }
40             else if(!hasCustomVal) $delete = true;
41             //delete this, because element has no such attribute and we haven't given a custom value! (no attrVal)
42         }
43         
44     
45         if($delete) {
46             delete attrList[attrName];
47         }
48         else {
49             //save class names as an object which indicated which classes should be included or excluded (true/false)
50             if( re1.test(attrName) ) {//class
51             
52                 
53                 if( !attrList.hasOwnProperty(attrName) ) attrList[attrName] = {}
54                 if(append === true) {
55                     //append to previous value                    
56                     attrList[attrName][newVal] = 1;
57                 }
58                 else if(append === false) {
59                     //remove from previous value
60                     attrList[attrName][newVal] = -1;
61                 }
62                 else {
63                     attrList[attrName]['className'] = newVal;
64                 }
65             }
66             
67             else {
68                 attrList[attrName] = newVal;
69             }
70         }
71         
72         ace.data.set('state', 'id-'+id , JSON.stringify(attrList));
73     },
74     
75     loadState : function(element, attrName) {
76         if( !element || (typeof element == 'string' && !(element = document.getElementById(element))) || !element.hasAttribute('id') ) return false;
77         
78         var id = element.getAttribute('id');
79         var attrList = ace.data.get('state', 'id-'+id) || {};
80         if(typeof attrList == 'string') {
81             try {
82                 attrList = JSON.parse(attrList);
83             }
84             catch(e) {
85                 attrList = {}
86             }
87         }
88         
89         var setAttr = function(element, attr, val) {
90             var re1 = /class/i
91             var re2 = /checked|disabled|readonly|value/i
92             
93             if(re1.test(attr)) {
94                 if(typeof val === 'object') {
95                     if('className' in val) element.setAttribute('class', val['className']);
96                     for(var key in val) if(val.hasOwnProperty(key)) {
97                         var append = val[key];
98                         if(append == 1) ace.addClass(element, key);
99                         else if(append == -1) ace.removeClass(element, key);
100                     }
101                 }
102                 //else if(typeof ace.addClass(element, val);
103             }
104             else if(re2.test(attr)) element[attr] = val;
105             else element.setAttribute(attr, val);
106         }
107         
108         if(attrName !== undefined) {
109             if(attrList.hasOwnProperty(attrName) && attrList[attrName] !== null) setAttr(element, attrName, attrList[attrName]);
110         }
111         else {
112             for(var name in attrList) {
113                 if(attrList.hasOwnProperty(name) && attrList[name] !== null) setAttr(element, name, attrList[name]);
114             }
115         }
116     },
117     
118     clearState : function(element) {
119         var id = null;
120         if(typeof element === 'string') {
121             id = element;
122         }
123         else if('hasAttribute' in element && element.hasAttribute('id')) {
124             id = element.getAttribute('id');
125         }
126         if(id) ace.data.remove('state', 'id-'+id);
127     }
128 };
129
130
131
132
133 (function() {
134     //detect if it is supported
135     //https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Animations/Detecting_CSS_animation_support
136     var animationSupport = function() {
137         var animation = false,
138         animationstring = 'animation',
139         keyframeprefix = '',
140         domPrefixes = 'Webkit Moz O ms Khtml'.split(' '),
141         pfx  = '',
142         elm = document.createElement('div');
143
144         if( elm.style.animationName !== undefined ) { animation = true; }    
145
146         if( animation === false ) {
147           for( var i = 0; i < domPrefixes.length; i++ ) {
148             if( elm.style[ domPrefixes[i] + 'AnimationName' ] !== undefined ) {
149               pfx = domPrefixes[ i ];
150               animationstring = pfx + 'Animation';
151               keyframeprefix = '-' + pfx.toLowerCase() + '-';
152               animation = true;
153               break;
154             }
155           }
156         }
157         
158         return animation;
159     }
160     
161     ace.vars['animation'] = animationSupport();
162     if( ace.vars['animation'] ) {
163         //based on http://www.backalleycoder.com/2012/04/25/i-want-a-damnodeinserted/
164
165         var animationCSS = "@keyframes nodeInserted{from{outline-color:#fff}to{outline-color:#000}}@-moz-keyframes nodeInserted{from{outline-color:#fff}to{outline-color:#000}}@-webkit-keyframes nodeInserted{from{outline-color:#fff}to{outline-color:#000}}@-ms-keyframes nodeInserted{from{outline-color:#fff}to{outline-color:#000}}@-o-keyframes nodeInserted{from{outline-color:#fff}to{outline-color:#000}}.ace-save-state{animation-duration:10ms;-o-animation-duration:10ms;-ms-animation-duration:10ms;-moz-animation-duration:10ms;-webkit-animation-duration:10ms;animation-delay:0s;-o-animation-delay:0s;-ms-animation-delay:0s;-moz-animation-delay:0s;-webkit-animation-delay:0s;animation-name:nodeInserted;-o-animation-name:nodeInserted;-ms-animation-name:nodeInserted;-moz-animation-name:nodeInserted;-webkit-animation-name:nodeInserted}";
166         var animationNode = document.createElement('style');
167         animationNode.innerHTML = animationCSS;
168         document.head.appendChild(animationNode);
169     
170         var domInsertEvent = function(event) {
171             var element = event.target;
172             if( !element || !ace.hasClass(element, 'ace-save-state') ) return;
173             
174             ace.settings.loadState(element);
175         }
176
177         document.addEventListener('animationstart', domInsertEvent, false);
178         document.addEventListener('MSAnimationStart', domInsertEvent, false);
179         document.addEventListener('webkitAnimationStart', domInsertEvent, false);
180     }
181     else {
182         //if animation events are not supported, wait for document ready event
183         var documentReady = function() {
184             var list = document.querySelectorAll('.ace-save-state');
185             for(var i = 0 ; i < list.length ; i++) ace.settings.loadState(list[i]);
186         }
187         
188         if(document.readyState == 'complete') documentReady();
189         else if(document.addEventListener) document.addEventListener('DOMContentLoaded', documentReady, false);
190         else if(document.attachEvent) document.attachEvent('onreadystatechange', function(){
191             if (document.readyState == 'complete') documentReady();
192         });
193     }
194 })();
195
196
197
198
199
200
201 //save/retrieve data using localStorage or cookie
202 //method == 1, use localStorage
203 //method == 2, use cookies
204 //method not specified, use localStorage if available, otherwise cookies
205 ace.data_storage = function(method, undefined) {
206     var prefix = 'ace_';
207
208     var storage = null;
209     var type = 0;
210     
211     if((method == 1 || method === undefined || method == 0) && 'localStorage' in window && window['localStorage'] !== null) {
212         storage = ace.storage;
213         type = 1;
214     }
215     else if(storage == null && (method == 2 || method === undefined) && 'cookie' in document && document['cookie'] !== null) {
216         storage = ace.cookie;
217         type = 2;
218     }
219     
220
221     this.set = function(namespace, key, value, path, is_obj, undefined) {
222         if(!storage) return;
223         
224         if(value === undefined) {//no namespace here?
225             value = key;
226             key = namespace;
227
228             if(value == null) storage.remove(prefix+key)
229             else {
230                 if(type == 1)
231                     storage.set(prefix+key, value)
232                 else if(type == 2)
233                     storage.set(prefix+key, value, ace.config.cookie_expiry, path || ace.config.cookie_path)
234             }
235         }
236         else {
237             if(type == 1) {//localStorage
238                 if(value == null) storage.remove(prefix+namespace+'_'+key)
239                 else {
240                     if(is_obj && typeof value == 'object') {
241                         value = JSON.stringify(value);
242                     }
243                     storage.set(prefix+namespace+'_'+key, value);
244                 }
245             }
246             else if(type == 2) {//cookie
247                 var val = storage.get(prefix+namespace);
248                 var tmp = val ? JSON.parse(val) : {};
249
250                 if(value == null) {
251                     delete tmp[key];//remove
252                     if(ace.sizeof(tmp) == 0) {//no other elements in this cookie, so delete it
253                         storage.remove(prefix+namespace);
254                         return;
255                     }
256                 }
257                 
258                 else {
259                     tmp[key] = value;
260                 }
261
262                 storage.set(prefix+namespace , JSON.stringify(tmp), ace.config.cookie_expiry, path || ace.config.cookie_path)
263             }
264         }
265     }
266
267     this.get = function(namespace, key, is_obj, undefined) {
268         if(!storage) return null;
269         
270         if(key === undefined) {//no namespace here?
271             key = namespace;
272             return storage.get(prefix+key);
273         }
274         else {
275             if(type == 1) {//localStorage
276                 var value = storage.get(prefix+namespace+'_'+key);
277                 if(is_obj && value) {
278                     try { value = JSON.parse(value) } catch(e) {}
279                 }
280                 return value;
281             }
282             else if(type == 2) {//cookie
283                 var val = storage.get(prefix+namespace);
284                 var tmp = val ? JSON.parse(val) : {};
285                 return key in tmp ? tmp[key] : null;
286             }
287         }
288     }
289
290     
291     this.remove = function(namespace, key, undefined) {
292         if(!storage) return;
293         
294         if(key === undefined) {
295             key = namespace
296             this.set(key, null);
297         }
298         else {
299             this.set(namespace, key, null);
300         }
301     }
302 }
303
304
305
306
307
308 //cookie storage
309 ace.cookie = {
310     // The following settingFunction are from Cookie.js class in TinyMCE, Moxiecode, used under LGPL.
311
312     /**
313      * Get a cookie.
314      */
315     get : function(name) {
316         var cookie = document.cookie, e, p = name + "=", b;
317
318         if ( !cookie )
319             return;
320
321         b = cookie.indexOf("; " + p);
322
323         if ( b == -1 ) {
324             b = cookie.indexOf(p);
325
326             if ( b != 0 )
327                 return null;
328
329         } else {
330             b += 2;
331         }
332
333         e = cookie.indexOf(";", b);
334
335         if ( e == -1 )
336             e = cookie.length;
337
338         return decodeURIComponent( cookie.substring(b + p.length, e) );
339     },
340
341     /**
342      * Set a cookie.
343      *
344      * The 'expires' arg can be either a JS Date() object set to the expiration date (back-compat)
345      * or the number of seconds until expiration
346      */
347     set : function(name, value, expires, path, domain, secure) {
348         var d = new Date();
349
350         if ( typeof(expires) == 'object' && expires.toGMTString ) {
351             expires = expires.toGMTString();
352         } else if ( parseInt(expires, 10) ) {
353             d.setTime( d.getTime() + ( parseInt(expires, 10) * 1000 ) ); // time must be in miliseconds
354             expires = d.toGMTString();
355         } else {
356             expires = '';
357         }
358
359         document.cookie = name + "=" + encodeURIComponent(value) +
360             ((expires) ? "; expires=" + expires : "") +
361             ((path) ? "; path=" + path : "") +
362             ((domain) ? "; domain=" + domain : "") +
363             ((secure) ? "; secure" : "");
364     },
365
366     /**
367      * Remove a cookie.
368      *
369      * This is done by setting it to an empty value and setting the expiration time in the past.
370      */
371     remove : function(name, path) {
372         this.set(name, '', -1000, path);
373     }
374 };
375
376
377 //local storage
378 ace.storage = {
379     get: function(key) {
380         return window['localStorage'].getItem(key);
381     },
382     set: function(key, value) {
383         window['localStorage'].setItem(key , value);
384     },
385     remove: function(key) {
386         window['localStorage'].removeItem(key);
387     }
388 };
389
390
391
392
393
394
395 //count the number of properties in an object
396 //useful for getting the number of elements in an associative array
397 ace.sizeof = function(obj) {
398     var size = 0;
399     for(var key in obj) if(obj.hasOwnProperty(key)) size++;
400     return size;
401 }
402
403 //because jQuery may not be loaded at this stage, we use our own toggleClass
404 ace.hasClass = function(elem, className) {    return (" " + elem.className + " ").indexOf(" " + className + " ") > -1; }
405
406 ace.addClass = function(elem, className) {
407  var parts = className.split(/\s+/);
408  for(var p = 0; p < parts.length; p++) {
409     if ( parts[p].length > 0 && !ace.hasClass(elem, parts[p]) ) {
410         var currentClass = elem.className;
411         elem.className = currentClass + (currentClass.length ? " " : "") + parts[p];
412     }
413  }
414 }
415
416 ace.removeClass = function(elem, className) {
417  var parts = className.split(/\s+/);
418  for(var p = 0; p < parts.length; p++) {
419     if( parts[p].length > 0 ) ace.replaceClass(elem, parts[p]);
420  }
421  ace.replaceClass(elem, className);
422 }
423
424 ace.replaceClass = function(elem, className, newClass) {
425  var classToRemove = new RegExp(("(^|\\s)" + className + "(\\s|$)"), "i");
426  elem.className = elem.className.replace(classToRemove, function (match, p1, p2) {
427     return newClass ? (p1 + newClass + p2) : " ";
428  }).replace(/^\s+|\s+$/g, "");
429 }
430
431
432 ace.toggleClass = function(elem, className) {
433     if(ace.hasClass(elem, className))
434         ace.removeClass(elem, className);
435     else ace.addClass(elem, className);
436 }
437
438 ace.isHTMlElement = function(elem) {
439  return window.HTMLElement ? elem instanceof HTMLElement : ('nodeType' in elem ? elem.nodeType == 1 : false);
440 }
441
442
443  //data_storage instance used inside ace.settings etc
444  ace.data = new ace.data_storage(ace.config.storage_method);
445
446 })();
447