1modules.chain=(function(){ 2 'use strict'; 3 //the undo redo chain. funny name, but i've grown attached to it. 4 //this chain isn't project specific, so methods should be provided to encode and decode the hash. 5 6 var chain={}; 7 var lists=modules.lists; 8 var actions=modules.actions; 9 var base64=modules.base64; 10 11 chain.actiontypes={}; 12 var totype=function(type,command){ 13 return chain.actiontypes[command.type][type](command); 14 }; 15 16 chain.actions=[]; 17 chain.unactions=[]; 18 chain.do=function(command,spec){ 19 spec=spec||{}; 20 command.hash=totype('hash',command); 21 chain.actions.push(command); 22 totype('do',command); 23 chain.unactions=[]; 24 if (!spec.fromhash){ 25 chain.updatehash(); 26 } 27 }; 28 chain.unhash=function(command,spec){ 29 //trigger an action from a hash rather than a command. 30 chain.do(totype('unhash',command),{fromhash:true}); 31 }; 32 chain.undo=function(){ 33 if (chain.actions.length===0){ 34 return; 35 } 36 var command=chain.actions.pop(); 37 totype('undo',command); 38 chain.unactions.push(command); 39 chain.updatehash(); 40 }; 41 chain.redo=function(){ 42 if (chain.unactions.length===0){ 43 return; 44 } 45 var command=chain.unactions.pop(); 46 chain.actions.push(command); 47 totype('do',command); 48 chain.updatehash(); 49 }; 50 chain.reset=function(){ 51 if (chain.resetmethod){ 52 //if possible, use a quick reset method the app provides 53 chain.resetmethod(); 54 if (chain.actions.length>0){ 55 chain.unactions=chain.unactions.concat(chain.actions.reverse()); 56 chain.actions=[]; 57 } 58 chain.updatehash(); 59 } 60 else{ 61 //as a fallback, just undo a million times. 62 while(chain.actions.length){ 63 chain.undo(); 64 } 65 } 66 }; 67 chain.squash=function(commands){ 68 //need a better name for these things. 69 //hopefully this is the right order to squash in. 70 //first numbers become the biggest ones. 71 return lists.reduce(commands,function(memo,command){ 72 return {squashed:memo*command.max+command.value,max:memo.max*command.max}; 73 },{squashed:0,max:0}); 74 }; 75 chain.expand=function(squashed,max){ 76 //should be able to be an array or a single value. 77 //pulls out biggest numbers first. 78 var expanded=[]; 79 if (Array.isArray(max)){ 80 lists.each(max,function(thismax){ 81 expanded.push(squashed%thismax); 82 squashed=Math.floor(squashed/thismax); 83 }); 84 return {expanded:expanded}; 85 } 86 else{ 87 while(squashed>0){ 88 expanded.push(squashed%max); 89 squashed=Math.floor(squashed/max); 90 } 91 return {expanded:expanded,remainder:squashed}; 92 } 93 }; 94 chain.updatehash=function(){ 95 if (!chain.encodemethod){ 96 console.log('ERROR: no encode method for chain'); 97 return; 98 } 99 var hash='#'; 100 hash=hash+chain.encodemethod(); 101 chain.hash=hash; 102 if (window.location&&window.location.replace){ 103 window.location.replace(hash); 104 } 105 }; 106 chain.decode=function(string){ 107 if (!chain.decodemethod){ 108 console.log('ERROR: no decode method for chain'); 109 return; 110 } 111 chain.reset(); 112 //ditch the # and pass to the project decode method. 113 chain.decodemethod(string.substr(1)); 114 chain.updatehash(); 115 }; 116 window.addEventListener("hashchange", function(){ 117 var newhash=window.location.hash; 118 if (newhash!==chain.hash&&((newhash+'#')!==chain.hash)){ 119 chain.decode(newhash); 120 } 121 }, false); 122 return chain; 123}());
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.