1 | /*
|
---|
2 |
|
---|
3 | Greenstone 3 'Client-side transformer'
|
---|
4 | Performs client-side transformations of XSLT, using HTML5 local storage (simulated if the browser doesn't support it).
|
---|
5 |
|
---|
6 | Currently only supports Firefox 3 and greater, since it's the only browser (at the time of writing) that can do this properly.
|
---|
7 |
|
---|
8 | @author Steven McTainsh
|
---|
9 | @date 14/02/2011
|
---|
10 |
|
---|
11 | */
|
---|
12 |
|
---|
13 | /* These URLs and file paths are fetched dynamically */
|
---|
14 | var gsweb = ""; // The file path to the Greenstone 3 web directory
|
---|
15 | var gsurl = ""; // The root URL for this Greenstone 3 installation
|
---|
16 |
|
---|
17 | /* Misc. switches and paths */
|
---|
18 | var keyUrl = ''; // Used across methods to build up query string for text retrieval (client-side transformed version)
|
---|
19 | var on = true; // Set to false to disable operation
|
---|
20 |
|
---|
21 | var index = 0; // Used for query array (to keep track of number of elements)
|
---|
22 | var deferredEls = new Array(); // Elements to defer text retrieval for until later
|
---|
23 | var queryArr = new Array(); // Text to query for (the text for the corresponding deferred element)
|
---|
24 |
|
---|
25 | /* Methods */
|
---|
26 | // This is generally only called from in-line JS in the head (i.e. var text = getText(...);)
|
---|
27 | function getText(key, el) {
|
---|
28 | if(localStorage.getItem(key) != null)
|
---|
29 | return localStorage.getItem(key);
|
---|
30 | else {
|
---|
31 | push(deferredEls, el);
|
---|
32 | queryArr[el] = key; // Have it queried for too
|
---|
33 | return "";
|
---|
34 | }
|
---|
35 | }
|
---|
36 |
|
---|
37 | function processEl(el, attr, key, append, isText, theText) {
|
---|
38 | // Assumes all necessary text has been loaded from the servlet
|
---|
39 | var displayText = (isText) ? theText : localStorage.getItem(key);
|
---|
40 |
|
---|
41 | if(el == document && attr == 'title') {
|
---|
42 | // Handle document titles
|
---|
43 | if(append)
|
---|
44 | document.title += displayText;
|
---|
45 | else
|
---|
46 | document.title = displayText;
|
---|
47 | } else if(attr == 'innerText') {
|
---|
48 | // Handle element 'inner text'
|
---|
49 | if(append)
|
---|
50 | $(el).html($(el).html() + displayText);
|
---|
51 | else
|
---|
52 | $(el).html(displayText);
|
---|
53 | } else if(attr == 'value') {
|
---|
54 | // Handle value attribute
|
---|
55 | if(append)
|
---|
56 | $(el).val($el.val() + displayText);
|
---|
57 | else
|
---|
58 | $(el).val(displayText);
|
---|
59 | } else {
|
---|
60 | // All other cases (generic attributes)
|
---|
61 | if(append)
|
---|
62 | $(el).attr(attr, $(el).attr(attr) + displayText);
|
---|
63 | else
|
---|
64 | $(el).attr(attr, displayText);
|
---|
65 | }
|
---|
66 | }
|
---|
67 |
|
---|
68 | function notSupported() {
|
---|
69 | // Set not supported cookie here
|
---|
70 | document.cookie = 'supportsXSLT=false; expires=0; path=/';
|
---|
71 | // Fall back to server version
|
---|
72 | var location = window.location.search.substring(1);
|
---|
73 | if(location == '') {
|
---|
74 | // Start with a question mark
|
---|
75 | location = window.location + "?o=server";
|
---|
76 | } else {
|
---|
77 | // Start with an ampersand
|
---|
78 | location = window.location + "&o=server";
|
---|
79 | }
|
---|
80 | window.location = location;
|
---|
81 | }
|
---|
82 |
|
---|
83 | $(document).ready(function() {
|
---|
84 | if(on && isSupported()) {
|
---|
85 | if(placeholder) {
|
---|
86 | // Need to prepare page placeholders
|
---|
87 | transform(false);
|
---|
88 | }
|
---|
89 | else {
|
---|
90 | // Need to place text into the page (placeholders ready)
|
---|
91 | applyText(false);
|
---|
92 | }
|
---|
93 | }
|
---|
94 | });
|
---|
95 |
|
---|
96 | function applyText(trial) {
|
---|
97 |
|
---|
98 | try {
|
---|
99 | // Wait for document to be ready before propogating this URL (otherwise undefined)
|
---|
100 | keyUrl = 'grabtext?i='+$('#interface').html()+'&l='+$('#language').html()+'&k='
|
---|
101 |
|
---|
102 | // First, see if the local storage should be emptied for a new language...
|
---|
103 | if(localStorage.getItem("_activeLanguage") != $('#language').html()) {
|
---|
104 | // Languages are different, clear existing strings
|
---|
105 | localStorage.clear();
|
---|
106 | localStorage.setItem("_activeLanguage", $('#language').html());
|
---|
107 | }
|
---|
108 |
|
---|
109 | $('#loading').show();
|
---|
110 |
|
---|
111 | var query = '';
|
---|
112 |
|
---|
113 | $('.getTextFor').each(function() {
|
---|
114 |
|
---|
115 | // Build up query
|
---|
116 | // Get the three parts to the class - 'getTextFor' 'element inner text to affect' 'attributes to affect'
|
---|
117 | // Proper splitting on spaces
|
---|
118 | var parts = parseAction($(this).attr('class'), ' ')
|
---|
119 | // parts[1] is this element's innerText key, parts[2] may or may not contain keys
|
---|
120 | // Can add null to the array
|
---|
121 | if(!contains(queryArr, parts[1]) && localStorage.getItem(parts[1]) == null)
|
---|
122 | // If the key has not already been queried for and is not in local storage...
|
---|
123 | // NO duplicates!
|
---|
124 | queryArr[index++] = parts[1];
|
---|
125 |
|
---|
126 | if(parts.length == 3 && parts[2] != '') {
|
---|
127 | var affected = parts[2].split(',');
|
---|
128 |
|
---|
129 | for(var j = 0; j < affected.length; j++) {
|
---|
130 | var els = parseAction(affected[j], ".");
|
---|
131 | // els[2] will contain key
|
---|
132 | // Ignore text, and those elements with text already in local storage and that will already be queried for
|
---|
133 | if(els[2].indexOf('text:') != 0 && !contains(queryArr, els[2]) && localStorage.getItem(els[2]) == null)
|
---|
134 | queryArr[index++] = els[2].replace("[a]", "");
|
---|
135 | }
|
---|
136 | }
|
---|
137 | });
|
---|
138 |
|
---|
139 | query = queryArr.join(",");
|
---|
140 |
|
---|
141 | // Fetch!
|
---|
142 | if(query != '') { // There is something to query for
|
---|
143 |
|
---|
144 | $.get(keyUrl + query, function(data) {
|
---|
145 |
|
---|
146 | // Process dictionary, load into local storage
|
---|
147 | $(data).find("item").each(function() {
|
---|
148 | localStorage.setItem($(this).attr('key'), $(this).attr('value'));
|
---|
149 | });
|
---|
150 |
|
---|
151 | assignText();
|
---|
152 |
|
---|
153 | }, 'xml');
|
---|
154 |
|
---|
155 | } else { assignText(trial); }
|
---|
156 | } catch (e) { if(trial) notSupportedCookie(); else notSupported(); }
|
---|
157 | }
|
---|
158 |
|
---|
159 | function assignText(trial) {
|
---|
160 |
|
---|
161 | try {
|
---|
162 | $('.getTextFor').each(function() {
|
---|
163 |
|
---|
164 | var parts = parseAction($(this).attr('class'), " ");
|
---|
165 | var me = parts[1];
|
---|
166 |
|
---|
167 | // Process it's own inner text first
|
---|
168 | processEl($(this), 'innerText', me);
|
---|
169 |
|
---|
170 | if(parts.length >= 3 && parts[2] != '') { // Otherwise 'x y ' mucks it up
|
---|
171 |
|
---|
172 | // Affecting elements are listed
|
---|
173 | var affectees = parts[2];
|
---|
174 |
|
---|
175 | var all = affectees.split(',');
|
---|
176 |
|
---|
177 | for(var i = 0; i < all.length; i++) {
|
---|
178 | var parts = parseAction(all[i], ".");
|
---|
179 |
|
---|
180 | var append = false;
|
---|
181 | var isText = false;
|
---|
182 | var theText = '';
|
---|
183 |
|
---|
184 | if(parts[2].indexOf("[a]") != -1) {
|
---|
185 | parts[2] = parts[2].replace("[a]", "");
|
---|
186 | append = true;
|
---|
187 | }
|
---|
188 |
|
---|
189 | if(parts[2].indexOf("text:'") != -1) {
|
---|
190 | // This action is plain text
|
---|
191 | isText = true;
|
---|
192 | theText = parts[2].substring(6, parts[2].length - 1);
|
---|
193 | }
|
---|
194 |
|
---|
195 | if(parts[0] == 'parent') {
|
---|
196 | // Affects the parent
|
---|
197 | processEl($(this).parent(), parts[1], parts[2], append, isText, theText);
|
---|
198 | } else if(parts[0] == 'this') {
|
---|
199 | // Affects this element
|
---|
200 | processEl($(this), parts[1], parts[2], append, isText, theText);
|
---|
201 | } else if(parts[0] == 'document') {
|
---|
202 | // Affects document itself
|
---|
203 | processEl(document, parts[1], parts[2], append, isText, theText);
|
---|
204 | }
|
---|
205 |
|
---|
206 |
|
---|
207 | }
|
---|
208 | }
|
---|
209 |
|
---|
210 | // Process deferred elements now
|
---|
211 | for(var def in deferredEls) {
|
---|
212 | $(def).html(localStorage[deferredEls[def]]); //dict[deferredEls[def]]);
|
---|
213 | }
|
---|
214 |
|
---|
215 | });
|
---|
216 |
|
---|
217 | var xsltClientCapable = document.cookie.indexOf('supportsXSLT') != -1;
|
---|
218 |
|
---|
219 | // At this point, the browser has proven itself capable of XSL transformations
|
---|
220 | // So, modify all document links into JavaScript links that use AJAX to get content
|
---|
221 | if(xsltClientCapable) {
|
---|
222 | // Could set cookie here too?
|
---|
223 | $('.clientDocView').each(function() {
|
---|
224 | var link = $(this).attr('href');
|
---|
225 | var startIndex = link.indexOf("&d=");
|
---|
226 | var endIndex = link.indexOf('&', startIndex + 7);
|
---|
227 | // If the endIndex == -1, end not found; just use end index
|
---|
228 | endIndex = (endIndex == -1) ? link.length : endIndex;
|
---|
229 | var docID = link.substring(startIndex, endIndex);
|
---|
230 | docID = docID.replace("&d=", "");
|
---|
231 | $(this).attr('id', docID);
|
---|
232 | $(this).attr('onclick', "getNodeContent(this); return false;"); // .bind doesn't work for dynamically added HTML!
|
---|
233 |
|
---|
234 | if(typeof initialHash != 'undefined') // Prevent errors when searching
|
---|
235 | if(docID == initialHash) {
|
---|
236 | // Load it!
|
---|
237 | getNodeContent($(this).get()[0]); // Talk about round the houses! This was the only way that produced something!
|
---|
238 | }
|
---|
239 | });
|
---|
240 |
|
---|
241 | document.cookie = 'supportsXSLT=true; expires=0; path=/';
|
---|
242 | }
|
---|
243 |
|
---|
244 | // Also undo escaping of necessary entities
|
---|
245 | $('body').each(function() {
|
---|
246 |
|
---|
247 | var text = $(this).html();
|
---|
248 | text = text.replace(/</g, "<");
|
---|
249 | text = text.replace(/>/g, ">");
|
---|
250 | text = text.replace(/&/g, "&");
|
---|
251 | $(this).html(text);
|
---|
252 |
|
---|
253 | });
|
---|
254 |
|
---|
255 | // Remove dead elements
|
---|
256 | $('[xmlns]').each(function() {
|
---|
257 | if($(this).get(0).tagName.toLowerCase() != "html") {
|
---|
258 | // use toLower() in case of browser inconsistencies
|
---|
259 | $(this).hide();
|
---|
260 | }
|
---|
261 | });
|
---|
262 |
|
---|
263 | //alert('Language is: ' + $('#language').html() + ', interface is: ' + $('#interface').html());
|
---|
264 |
|
---|
265 | $('#loading').fadeOut();
|
---|
266 |
|
---|
267 | } catch (e) { if(trial) notSupportedCookie(); else notSupported(); }
|
---|
268 |
|
---|
269 | }
|
---|
270 |
|
---|
271 | function transform(trial) {
|
---|
272 |
|
---|
273 | try {
|
---|
274 | var queryStr = window.location.search.substring(1);
|
---|
275 | var rooturl = window.location;
|
---|
276 | //var absolute = gsurl;
|
---|
277 | var lead = queryStr == '' ? '?' : '&';
|
---|
278 | var skinurl = rooturl+lead+"o=skinandlibdoc";
|
---|
279 | var xmlurl = rooturl+lead+"o=xml";
|
---|
280 |
|
---|
281 | var skindoc = "";
|
---|
282 | var xmldoc = "";
|
---|
283 |
|
---|
284 | $.get(rooturl + lead + "o=clientside", function(data) {
|
---|
285 |
|
---|
286 | data = data.replace(/gs3:id/g, "gs3id");
|
---|
287 | data = parseFromString(data, "text/xml");
|
---|
288 |
|
---|
289 | // data contains the XML and the stylesheet too!
|
---|
290 | var skindoc = $(data).find("xslt\\:stylesheet")[0];
|
---|
291 | var xmldoc = $(data).find("page")[0];
|
---|
292 |
|
---|
293 | gsurl = $($(xmldoc).find("metadata[name=siteURL]")[0]).text();
|
---|
294 | gsweb = new RegExp($($(xmldoc).find("param[name=filepath]")[0]).text().replace(/\\/g, "\\\\"), "g");
|
---|
295 |
|
---|
296 | // Find xsl:include elements and update hrefs accordingly
|
---|
297 | $(skindoc).find("xsl\\:include").each(function() {
|
---|
298 | $(this).attr('href', $(this).attr('href').replace(gsweb, gsurl).replace(/\\/g, "/"));
|
---|
299 | });
|
---|
300 |
|
---|
301 | $(xmldoc).find("xsl\\:include").each(function() {
|
---|
302 | $(this).attr('href', $(this).attr('href').replace(gsweb, gsurl).replace(/\\/g, "/"));
|
---|
303 | });
|
---|
304 |
|
---|
305 | // Convert temporarily to text here
|
---|
306 | skindoc = convertToString(skindoc);
|
---|
307 | xmldoc = convertToString(xmldoc);
|
---|
308 |
|
---|
309 | // This could just be done on the server (later)
|
---|
310 | //data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n" /*+ "<?xml-stylesheet type=\"text/xsl\" href=\"" + skinurl + "\"?>\r\n"*/ + data;
|
---|
311 | // replace all!
|
---|
312 | // Be careful with regex syntax and the use of special characters!
|
---|
313 | skindoc = skindoc.replace(/util\:exists\(\$meta, ''\)/g, "$meta!=''"); // For now - use regex instead
|
---|
314 | skindoc = skindoc.replace(/%3A/g, ":"); // undo colon escaping
|
---|
315 |
|
---|
316 | // Convert to XML
|
---|
317 | xmldoc = parseFromString(xmldoc, "text/xml");
|
---|
318 | skindoc = parseFromString(skindoc, "text/xml");
|
---|
319 |
|
---|
320 | var output = '';
|
---|
321 | var library_name = $('/page/xsltparams/param[name=library_name]', xmldoc).text();
|
---|
322 | var interface_name = $('/page/xsltparams/param[name=interface_name]', xmldoc).text();
|
---|
323 |
|
---|
324 | // And post-process...
|
---|
325 | if(window.ActiveXObject) {
|
---|
326 | // IE
|
---|
327 | var procFactory = new ActiveXObject("MSXML2.XSLTemplate");
|
---|
328 | procFactory.stylesheet = skindoc;
|
---|
329 | var proc = procFactory.createProcessor();
|
---|
330 | proc.input = xmldoc;
|
---|
331 |
|
---|
332 | proc.addParameter('library_name', library_name);
|
---|
333 | proc.addParameter('interface_name', interface_name);
|
---|
334 |
|
---|
335 | proc.transform();
|
---|
336 | output = proc.output;
|
---|
337 | } else {
|
---|
338 | // Fx
|
---|
339 | xsltProc = new XSLTProcessor();
|
---|
340 | // The leading slash is oh-so important here
|
---|
341 | xsltProc.setParameter(null, 'library_name', library_name);
|
---|
342 | xsltProc.setParameter(null, 'interface_name', interface_name);
|
---|
343 | xsltProc.importStylesheet(skindoc);
|
---|
344 | result = xsltProc.transformToDocument(xmldoc);
|
---|
345 | output = (new XMLSerializer()).serializeToString(result);
|
---|
346 | }
|
---|
347 |
|
---|
348 | //output = output.replace('var placeholder = false;', 'var placeholder = false; var xsltClientCapable = true;');
|
---|
349 |
|
---|
350 | var doc = document.open();
|
---|
351 | doc.write(output);
|
---|
352 | doc.close();
|
---|
353 |
|
---|
354 | document.cookie = 'supportsXSLT=true; expires=0; path=/';
|
---|
355 |
|
---|
356 | }, 'html');
|
---|
357 | } catch (e) { if(trial) notSupportedCookie(); else notSupported(); }
|
---|
358 | }
|
---|
359 |
|
---|
360 | function notSupportedCookie() {
|
---|
361 | document.cookie = 'supportsXSLT=false; expires=0; path=/';
|
---|
362 | }
|
---|
363 |
|
---|
364 | function getNodeContent(node) {
|
---|
365 | var hash = $(node).attr('id');
|
---|
366 |
|
---|
367 | // Some document titles appear within spans, some do not, so these adjustments are necessary
|
---|
368 | $('.clientDocView').next().css('font-weight', 'normal');
|
---|
369 | $('.clientDocView').parent().css('font-weight', 'normal');
|
---|
370 | $(node).parent().css('font-weight', 'bold');
|
---|
371 | $(node).next().css('font-weight', 'bold');
|
---|
372 |
|
---|
373 | var loadingimg = '<img src="interfaces/default/images/loading.gif" alt="Loading" />';
|
---|
374 |
|
---|
375 | // Fetch me some fresh XML
|
---|
376 | $('.documenttext').html(loadingimg);
|
---|
377 | var url = $(node).attr('href') + "&o=xml";
|
---|
378 | url = url.replace('&', '&');
|
---|
379 | $.get(url, function(data) {
|
---|
380 |
|
---|
381 | gsurl = $($(data).find("metadata[name=siteURL]")[0]).text();
|
---|
382 |
|
---|
383 | $.get(gsurl + '/interfaces/basic/transform/document_text.xsl', function(text) {
|
---|
384 |
|
---|
385 | var output = '';
|
---|
386 | var result = '';
|
---|
387 |
|
---|
388 | try {
|
---|
389 | // FF only
|
---|
390 | xsltProc = new XSLTProcessor();
|
---|
391 | // The leading slash is oh-so important here
|
---|
392 | xsltProc.setParameter(null, 'library_name', $('/page/xsltparams/param[name=library_name]', data).text());
|
---|
393 | xsltProc.setParameter(null, 'interface_name', $('/page/xsltparams/param[name=interface_name]', data).text());
|
---|
394 | xsltProc.importStylesheet(text);
|
---|
395 | result = xsltProc.transformToDocument(data);
|
---|
396 | output = (new XMLSerializer()).serializeToString(result);
|
---|
397 | } catch(e) { window.location = $(node).attr('href'); } // will naturally cascade to client-side, then if necessary, server-side
|
---|
398 |
|
---|
399 | // Get the book name
|
---|
400 | var book = $('#documentheading').text();
|
---|
401 | var title_arr = new Array();
|
---|
402 | var temp_arr = new Array();
|
---|
403 |
|
---|
404 | title_arr.push(book);
|
---|
405 |
|
---|
406 | // Go up the tree, until you reach the 'Table of Contents' node
|
---|
407 | $(node).parentsUntil('#tocstart').each(function() {
|
---|
408 | if($(this).get()[0].tagName == 'LI') {
|
---|
409 | // Only list elements...
|
---|
410 | // next child = a, next sibling = text node
|
---|
411 | temp_arr.push($(this).children('span').text());
|
---|
412 | }
|
---|
413 | });
|
---|
414 |
|
---|
415 | // Store these temporarily to reverse them and get it right
|
---|
416 | temp_arr = temp_arr.reverse();
|
---|
417 | title_arr = title_arr.concat(temp_arr);
|
---|
418 | document.title = title_arr.join('::');
|
---|
419 |
|
---|
420 | // Fix up entity encoding first
|
---|
421 | output = output.replace(/&/g, '&');
|
---|
422 | output = output.replace(/</g, '<');
|
---|
423 | output = output.replace(/>/g, '>');
|
---|
424 | $('.documenttext').html(output);
|
---|
425 |
|
---|
426 | }, 'xml');
|
---|
427 |
|
---|
428 | }, 'xml');
|
---|
429 | }
|
---|
430 |
|
---|
431 | function parseAction(str, chr) {
|
---|
432 |
|
---|
433 | // Problem with split - seems to discard the rest of string if it encounters splitable characters but doesn't split on them
|
---|
434 | // But, then all the split characters are missing from the array! So, need to slice the substring out.
|
---|
435 | // Get additional text
|
---|
436 | var parts = str.split(chr, 3);
|
---|
437 |
|
---|
438 | var trimIndex = parts[0].length + parts[1].length + 2;
|
---|
439 | parts[2] = str.substring(trimIndex);
|
---|
440 |
|
---|
441 | return parts;
|
---|
442 |
|
---|
443 | }
|
---|
444 |
|
---|
445 | // Method equivalent to PHP's in_array method
|
---|
446 | function contains(array, value) {
|
---|
447 |
|
---|
448 | for(var val in array)
|
---|
449 | if(array[val] == value)
|
---|
450 | return true;
|
---|
451 |
|
---|
452 | return false;
|
---|
453 | }
|
---|
454 |
|
---|
455 | // Method equivalent to PHP's own
|
---|
456 | function print_r(arr) {
|
---|
457 |
|
---|
458 | var result = "";
|
---|
459 |
|
---|
460 | for(var a in arr) {
|
---|
461 | result += a + " => " + arr[a] + "\r\n";
|
---|
462 | }
|
---|
463 |
|
---|
464 | return result;
|
---|
465 | }
|
---|
466 |
|
---|
467 | function convertToString(content) {
|
---|
468 | try {
|
---|
469 | // If this fails, it's another indication that the browser doesn't have the support we need
|
---|
470 | if(typeof XMLSerializer != 'undefined') {
|
---|
471 | return (new XMLSerializer()).serializeToString(content);
|
---|
472 | } else {
|
---|
473 | return content.xml;
|
---|
474 | }
|
---|
475 | } catch (e) { notSupported(); }
|
---|
476 | }
|
---|
477 |
|
---|
478 | function parseFromString(content, contentType) {
|
---|
479 | try {
|
---|
480 | var retobj;
|
---|
481 |
|
---|
482 | if(typeof window.DOMParser != 'undefined') {
|
---|
483 | // Fx
|
---|
484 | retobj = (new DOMParser()).parseFromString(content, contentType);
|
---|
485 | } else {
|
---|
486 | // IE
|
---|
487 | var retobj = new ActiveXObject("Microsoft.XMLDOM");
|
---|
488 | retobj.async = "false";
|
---|
489 | retobj.loadXML(content);
|
---|
490 | }
|
---|
491 |
|
---|
492 | return retobj;
|
---|
493 | } catch(e) { var obj = new ActiveXObject('MSXML.DomDocument'); obj.async = false; obj.loadXML(content); return obj; }
|
---|
494 | }
|
---|
495 |
|
---|
496 | function isSupported() {
|
---|
497 | // Are cookies enabled?
|
---|
498 | if(navigator.cookieEnabled && typeof navigator.cookieEnabled != 'undefined') {
|
---|
499 | // Is there a cookie?
|
---|
500 | if(document.cookie.indexOf('supportsXSLT=') > -1) {
|
---|
501 | // Cookie exists - don't try the transformation, as the server will
|
---|
502 | // read the cookie and determine which version to serve up.
|
---|
503 | // If it happens to be client-side, allow transformation to proceed
|
---|
504 | return (document.cookie.indexOf('supportsXSLT=true') > -1);
|
---|
505 | } else {
|
---|
506 | // Cookie doesn't exist - test!
|
---|
507 | transform(true);
|
---|
508 | applyText(true);
|
---|
509 | return (document.cookie.indexOf('supportsXSLT=true') > -1);
|
---|
510 | }
|
---|
511 | } else {
|
---|
512 | return false;
|
---|
513 | }
|
---|
514 | }
|
---|
515 |
|
---|
516 | /* Simulating web storage for browsers that don't support it */
|
---|
517 | /* Credit: http://www.thewojogroup.com/2010/01/simulating-html5-local-storage/ */
|
---|
518 | (function(){var k=this;if(!k.localStorage&&navigator.cookieEnabled){var x="storageData_",y="++",z="::",l=function(a,c,b){var e=new Date;e.setTime(e.getTime()+b);b="; expires="+e.toGMTString();document.cookie=a+"="+c+b+"; path=/"},h=function(a){a=a+"=";for(var c=document.cookie.split(";"),b=0,e=c.length;b<e;b++){for(var d=c[b];d.charAt(0)==" ";)d=d.substring(1,d.length);if(d.indexOf(a)===0)return d.substring(a.length,d.length)}return null},m=function(a){l(a,"",-1)},i=function(){for(var a="",c=0;h(y+c)!==null;)a+=h(y+
|
---|
519 | c++);return a==""?[]:a.split(y)},n=function(a){for(var c=Math.ceil(a.length/4E3),b=0;b<c||h(y+b)!==null;){b<c?l(y+b,a.substr(b*4E3,(b+1)*4E3>a.length?a.length-b*4E3:4E3),2592E3):m(y+b);b++}},f=k.localStorage={length:0,setItem:function(a,c){var b=i(),e=0,d=b.length,g=false;for(e=0;e<d;e++){var j=b[e].split(z);if(j[0]==a){j[1]=c;g=true;b[e]=j.join(z);e=d}}if(!g){b.push(a+z+c.replace(/::/g,": :").replace(/\+\+/g,"+ +"));this.a.push(a);this.length++}n(b.join(y))},
|
---|
520 | getItem:function(a){var c=i(),b=0,e=c.length;for(b=0;b<e;b++){var d=c[b].split(z);if(d[0]==a&&d[1])return d[1]}return null},removeItem:function(a){var c=i(),b=0,e=c.length,d=false,g=[];for(b=0;b<e;b++)if(c[b].split(z)[0]!=a)g.push(c[b]);else d=true;if(d){n(g.join(y));o()}},clear:function(){for(var a=0;h(y+a)!==null;)m(y+a++);this.a=[];this.length=0},key:function(a){return a<this.length?this.a[a]:null},a:[]},o=function(){f.a=i();for(var a=0;f.a[a];)f.a[a]=f.a[a++].split(z)[0];
|
---|
521 | f.length=f.a.length};o()}})(); |
---|