1/** 2 * Jokuwiki - a tool for managing javascript widgets 3 * 4 * Jokuwiki is intended to provide a framework (initially for Dokuwiki) to 5 * 1) isolate widgets from having to deal with dependencies (widget declared before dependencies available) 6 * 2) handle a strict Content Security Policy (i.e. no inline scripts) 7 * 3) non-standard content loading techniques (e.g. pjax) 8 * 9 * For simplicity the PJax page initializaton plugin is appended below 10 */ 11var jokuwiki= 12{ 13 widgets: [], /* contains a list of [widgetname]=initFunction */ 14 failcount: 0, /* limits frequent re-running after failures */ 15 urls: [], /* maintains a list of script URLs loaded or about to be loaded */ 16 iters: 0, /* track number of times worklist has been scanned */ 17 pjaxloads: 0, /* count of times jokuwiki has been initialised */ 18 attempts: 10, /* maximum number of attempts at runQueue per init invocation */ 19 maxPjax: 200, /* max number of consecutive pjax loads before a full page load */ 20 pjaxContainer: 'pjax_content', /* element ID used for pjax container (optional -see disablePjax below) */ 21/** 22 * init should be called when the page is loaded or content injected 23 */ 24 init: function () { 25 jokuwiki.iters=0; 26 jokuwiki.failcount=0; 27 jokuwiki.pjaxloads++; 28 jokuwiki.attempts=10; 29 jokuwiki.runQueue(); 30 }, 31/** 32 * private method 33 * 34 * scans the DOM for widgets to invoke 35 * automatically reschedules itself for stuff which throws an exception 36 */ 37 runQueue: function () { 38 if (jQuery.pjax && jokuwiki.pjaxloads>jokuwiki.maxPjax) { 39 jokuwiki.disablePjax(); 40 } 41 jokuwiki.iters++; 42 console.log(jokuwiki.iters + "(" + jokuwiki.pjaxloads + ") jokuwiki.runQueue iteration"); 43 var els=jQuery("[data-jw]"); 44 var success=false; 45 for(var i=0; i<els.length; i++) { 46 success=false; 47 try { 48 payload=jQuery.parseJSON(els[i].getAttribute('data-jw')); 49 jokuwiki.widgets[payload.jokuwiki](payload.data); 50 success=true; 51 } catch(e) { 52 jokuwiki.failcount++; 53 console.log(jokuwiki.iters + "(" + jokuwiki.pjaxloads + ") Error processing " + els[i].getAttribute('data-jw')); 54 } 55 console.log(jokuwiki.iters + "(" + jokuwiki.pjaxloads + ") still here - success = " + success); 56 if (success) { 57 /* our work here is done - remove from the list */ 58 console.log(jokuwiki.iters + "(" + jokuwiki.pjaxloads + ') removing' + els[i].id + ' from jokuwiki queue'); 59 els[i].removeAttribute('data-jw'); 60 } 61 } 62 if (jQuery("[data-jw]").length && --jokuwiki.attempts) { 63 /* try to process the failed ones later */ 64 console.log(jokuwiki.iters + "(" + jokuwiki.pjaxloads + ") scheduling for another go"); 65 setTimeout(jokuwiki.runQueue, 200 + Math.min(jokuwiki.iters*100,1000)); 66 } 67 }, 68/** 69 * public method for creating mappings between widgetnames and initfunctions 70 * @param string widgetname - the 'name' attribute of the widget 71 * @param function handler - the function to call (with the data from the parsed json) to invoke 72 * @param string url - optional url to load (will only be loaded once) 73 */ 74 register: function (widgetname, handler, url) { 75 if (url) { 76 jokuwiki.loadScript(url); 77 } 78 jokuwiki.widgets[widgetname]=handler; 79 }, 80/** 81 * public method for deleting mappings between widgetnames and initfunctions 82 * @param string widgetname - the 'name' attribute of the widget 83 * 84 * Not really sure why this is here. 85 * Note that this does not remove any scripts which have been added 86 */ 87 unregister: function (name) { /* removes mapping between names and initFunctions */ 88 delete jokuwiki.widgets[name]; 89 }, 90/** 91 * public method for loading a script asynchnronously 92 * @param string url 93 * 94 * There are some issues with jQuery's getScript, notably 95 * it doesn't intrinsically prevent the same script being 96 * injected multiple times 97 */ 98 loadScript: function (url) { 99 if (!jokuwiki.urls[url]) { 100 jokuwiki.urls[url]=1; 101 jQuery(document).ready(function () { 102 var script = document.createElement("script"); 103 script.type = "text/javascript"; 104 script.src = url; 105 document.body.appendChild(script); 106 }); 107 } 108 109 }, 110/** 111 * public method to allow full page loads/break pjax loading 112 * 113 */ 114 disablePjax: function () { /* do a full page load occasionally to clean up leaks */ 115 try { 116 console.log(jokuwiki.iters + "(" + jokuwiki.pjaxloads + ') next page should be full reload'); 117 document.getElementById(jokuwiki.pjaxContainer).id='DoNotReload'; 118 } catch (e) { console.log('....or not');} 119 } 120}; 121 122// --------- initialize the jokuwiki ------- 123 124/* for full page load */ 125jQuery(document).ready(jokuwiki.init); 126/* for pjax load */ 127jQuery(document).on('pjax:success', jokuwiki.init); 128 129/* -------- register handler to update title ---- */ 130/* NB has no dependencies therefore run in its own try....catch */ 131/* - if it doesn't work the first time then it aint gonna work! */ 132jokuwiki.register('pjaxTitle', function(jw) { 133 try { 134 document.title=jw.title; 135 } catch (e) { 136 } 137}); 138 139/* ------------ add a widget -------- */ 140jokuwiki.register('slideshow',function (jw) { 141 var i = new fadeSlideShow(jw); 142}, 'res/fader.js'); 143 144/* ------ consol.log hack ---------- */ 145if (!window.console) console = {log: function() {}}; 146 147