From 72b556efaac1364776121393a1fee5e9eee49694 Mon Sep 17 00:00:00 2001 From: Fabian Jakobs Date: Mon, 12 Apr 2010 09:23:46 +0200 Subject: [PATCH] reorganize file structure and use labjs for loading --- .gitignore | 1 + editor.css => css/editor.css | 0 demo/LAB.js | 2 + demo/LAB.src.js | 358 ++++++++++++++++++ demo/editor.html | 52 +++ demo/fLAB.js | 191 ++++++++++ Editor.mm => doc/Editor.mm | 23 +- editor.html | 52 --- experiments/tokenizer.html | 7 +- experiments/triple_click.html | 2 +- .../BackgroundTokenizer.js | 0 CursorLayer.js => src/CursorLayer.js | 0 Editor.js => src/Editor.js | 0 GutterLayer.js => src/GutterLayer.js | 0 JavaScript.js => src/JavaScript.js | 0 MarkerLayer.js => src/MarkerLayer.js | 0 TextDocument.js => src/TextDocument.js | 0 TextInput.js => src/TextInput.js | 0 TextLayer.js => src/TextLayer.js | 0 Tokenizer.js => src/Tokenizer.js | 0 VirtualRenderer.js => src/VirtualRenderer.js | 0 XML.js => src/XML.js | 0 lib.js => src/lib.js | 0 23 files changed, 632 insertions(+), 56 deletions(-) create mode 100644 .gitignore rename editor.css => css/editor.css (100%) create mode 100755 demo/LAB.js create mode 100755 demo/LAB.src.js create mode 100644 demo/editor.html create mode 100755 demo/fLAB.js rename Editor.mm => doc/Editor.mm (61%) delete mode 100644 editor.html rename BackgroundTokenizer.js => src/BackgroundTokenizer.js (100%) rename CursorLayer.js => src/CursorLayer.js (100%) rename Editor.js => src/Editor.js (100%) rename GutterLayer.js => src/GutterLayer.js (100%) rename JavaScript.js => src/JavaScript.js (100%) rename MarkerLayer.js => src/MarkerLayer.js (100%) rename TextDocument.js => src/TextDocument.js (100%) rename TextInput.js => src/TextInput.js (100%) rename TextLayer.js => src/TextLayer.js (100%) rename Tokenizer.js => src/Tokenizer.js (100%) rename VirtualRenderer.js => src/VirtualRenderer.js (100%) rename XML.js => src/XML.js (100%) rename lib.js => src/lib.js (100%) diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..496ee2ca --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.DS_Store \ No newline at end of file diff --git a/editor.css b/css/editor.css similarity index 100% rename from editor.css rename to css/editor.css diff --git a/demo/LAB.js b/demo/LAB.js new file mode 100755 index 00000000..db515343 --- /dev/null +++ b/demo/LAB.js @@ -0,0 +1,2 @@ +// LAB.js (LABjs :: Loading And Blocking JavaScript) | v1.0.2rc1 (c) Kyle Simpson | MIT License +(function(j){var p="string",w="head",H="body",Y="script",t="readyState",k="preloaddone",y="loadtrigger",I="srcuri",D="preload",Z="complete",z="done",A="which",J="preserve",E="onreadystatechange",ba="onload",K="hasOwnProperty",bb="script/cache",L="[object ",bv=L+"Function]",bw=L+"Array]",e=null,h=true,i=false,s=j.document,bx=j.location,bc=j.ActiveXObject,B=j.setTimeout,bd=j.clearTimeout,M=function(a){return s.getElementsByTagName(a)},N=Object.prototype.toString,O=function(){},q={},P={},be=/^[^?#]*\//.exec(bx.href)[0],bf=/^\w+\:\/\/\/?[^\/]+/.exec(be)[0],by=M(Y),bg=j.opera&&N.call(j.opera)==L+"Opera]",bh=(function(a){a[a]=a+"";return a[a]!=a+""})(new String("__count__")),u={cache:!(bh||bg),order:bh||bg,xhr:h,dupe:h,base:"",which:w};u[J]=i;u[D]=h;q[w]=M(w);q[H]=M(H);function Q(a){return N.call(a)===bv}function R(a,b){var c=/^\w+\:\/\//,d;if(typeof a!==p)a="";if(typeof b!==p)b="";d=(c.test(a)?"":b)+a;return((c.test(d)?"":(d.charAt(0)==="/"?bf:be))+d)}function bz(a){return(R(a).indexOf(bf)===0)}function bA(a){var b,c=-1;while(b=by[++c]){if(typeof b.src===p&&a===R(b.src)&&b.type!==bb)return h}return i}function F(v,l){v=!(!v);if(l==e)l=u;var bi=i,C=v&&l[D],bj=C&&l.cache,G=C&&l.order,bk=C&&l.xhr,bB=l[J],bC=l.which,bD=l.base,bl=O,S=i,x,r=h,m={},T=[],U=e;C=bj||bk||G;function bm(a,b){if((a[t]&&a[t]!==Z&&a[t]!=="loaded")||b[z]){return i}a[ba]=a[E]=e;return h}function V(a,b,c){c=!(!c);if(!c&&!(bm(a,b)))return;b[z]=h;for(var d in m){if(m[K](d)&&!(m[d][z]))return}bi=h;bl()}function bn(a){if(Q(a[y])){a[y]();a[y]=e}}function bE(a,b){if(!bm(a,b))return;b[k]=h;B(function(){q[b[A]].removeChild(a);bn(b)},0)}function bF(a,b){if(a[t]===4){a[E]=O;b[k]=h;B(function(){bn(b)},0)}}function W(b,c,d,g,f,n){var o=b[A];B(function(){if("item"in q[o]){if(!q[o][0]){B(arguments.callee,25);return}q[o]=q[o][0]}var a=s.createElement(Y);a.type=d;if(typeof g===p)a.charset=g;if(Q(f)){a[ba]=a[E]=function(){f(a,b)};a.src=c}q[o].insertBefore(a,(o===w?q[o].firstChild:e));if(typeof n===p){a.text=n;V(a,b,h)}},0)}function bo(a,b,c,d){P[a[I]]=h;W(a,b,c,d,V)}function bp(a,b,c,d){var g=arguments;if(r&&a[k]==e){a[k]=i;W(a,b,bb,d,bE)}else if(!r&&a[k]!=e&&!a[k]){a[y]=function(){bp.apply(e,g)}}else if(!r){bo.apply(e,g)}}function bq(a,b,c,d){var g=arguments,f;if(r&&a[k]==e){a[k]=i;f=a.xhr=(bc?new bc("Microsoft.XMLHTTP"):new j.XMLHttpRequest());f[E]=function(){bF(f,a)};f.open("GET",b);f.send("")}else if(!r&&a[k]!=e&&!a[k]){a[y]=function(){bq.apply(e,g)}}else if(!r){P[a[I]]=h;W(a,b,c,d,e,a.xhr.responseText);a.xhr=e}}function br(a){if(a.allowDup==e)a.allowDup=l.dupe;var b=a.src,c=a.type,d=a.charset,g=a.allowDup,f=R(b,bD),n,o=bz(f);if(typeof c!==p)c="text/javascript";if(typeof d!==p)d=e;g=!(!g);if(!g&&((P[f]!=e)||(r&&m[f])||bA(f))){if(m[f]!=e&&m[f][k]&&!m[f][z]&&o){V(e,m[f],h)}return}if(m[f]==e)m[f]={};n=m[f];if(n[A]==e)n[A]=bC;n[z]=i;n[I]=f;S=h;if(!G&&bk&&o)bq(n,f,c,d);else if(!G&&bj)bp(n,f,c,d);else bo(n,f,c,d)}function bs(a){T.push(a)}function X(a){if(v&&!G)bs(a);if(!v||C)a()}function bt(a){var b=[],c;for(c=-1;++c") type dom-ready hack is present in the page + if ("item" in append_to[_script_which]) { // check if ref is still a live node list + if (!append_to[_script_which][0]) { // append_to node not yet ready + fSETTIMEOUT(arguments.callee,25); // try again in a little bit -- note, will recall the anonymous functoin in the outer setTimeout, not the parent createScriptTag() + return; + } + append_to[_script_which] = append_to[_script_which][0]; // reassign from live node list ref to pure node ref -- avoids nasty IE bug where changes to DOM invalidate live node lists + } + var scriptElem = oDOC.createElement(sSCRIPT); + scriptElem.type = type; + if (typeof charset === sSTRING) scriptElem.charset = charset; + if (isFunc(onload)) { // load script via 'src' attribute, set onload/onreadystatechange listeners + scriptElem[sONLOAD] = scriptElem[sONREADYSTATECHANGE] = function(){onload(scriptElem,scriptentry);}; + scriptElem.src = src; + } + // only for appending to , fix a bug in IE6 if tag is present -- otherwise, insertBefore(...,null) acts just like appendChild() + append_to[_script_which].insertBefore(scriptElem,(_script_which===sHEAD?append_to[_script_which].firstChild:nNULL)); + if (typeof scriptText === sSTRING) { // script text already avaiable from XHR preload, so just inject it + scriptElem.text = scriptText; + handleScriptLoad(scriptElem,scriptentry,bTRUE); // manually call 'load' callback function, skipReadyCheck=true + } + },0); + } + function loadScriptElem(scriptentry,src,type,charset) { + all_scripts[scriptentry[sSRCURI]] = bTRUE; + createScriptTag(scriptentry,src,type,charset,handleScriptLoad); + } + function loadScriptCache(scriptentry,src,type,charset) { + var args = arguments; + if (first_pass && scriptentry[sPRELOADDONE] == nNULL) { // need to preload into cache + scriptentry[sPRELOADDONE] = bFALSE; + createScriptTag(scriptentry,src,sSCRIPTCACHE,charset,handleScriptPreload); // fake mimetype causes a fetch into cache, but no execution + } + else if (!first_pass && scriptentry[sPRELOADDONE] != nNULL && !scriptentry[sPRELOADDONE]) { // preload still in progress, make sure trigger is set for execution later + scriptentry[sLOADTRIGGER] = function(){loadScriptCache.apply(nNULL,args);}; + } + else if (!first_pass) { // preload done, so reload (from cache, hopefully!) as regular script element + loadScriptElem.apply(nNULL,args); + } + } + function loadScriptXHR(scriptentry,src,type,charset) { + var args = arguments, xhr; + if (first_pass && scriptentry[sPRELOADDONE] == nNULL) { // need to preload + scriptentry[sPRELOADDONE] = bFALSE; + xhr = scriptentry.xhr = (oACTIVEX ? new oACTIVEX("Microsoft.XMLHTTP") : new global.XMLHttpRequest()); + xhr[sONREADYSTATECHANGE] = function(){handleXHRPreload(xhr,scriptentry);}; + xhr.open("GET",src); + xhr.send(""); + } + else if (!first_pass && scriptentry[sPRELOADDONE] != nNULL && !scriptentry[sPRELOADDONE]) { // preload XHR still in progress, make sure trigger is set for execution later + scriptentry[sLOADTRIGGER] = function(){loadScriptXHR.apply(nNULL,args);}; + } + else if (!first_pass) { // preload done, so "execute" script via injection + all_scripts[scriptentry[sSRCURI]] = bTRUE; + createScriptTag(scriptentry,src,type,charset,nNULL,scriptentry.xhr.responseText); + scriptentry.xhr = nNULL; + } + } + function loadScript(o) { + if (o.allowDup == nNULL) o.allowDup = opts.dupe; + var src = o.src, type = o.type, charset = o.charset, allowDup = o.allowDup, + src_uri = canonicalScriptURI(src,_base_path), scriptentry, same_domain = sameDomain(src_uri); + if (typeof type !== sSTRING) type = "text/javascript"; + if (typeof charset !== sSTRING) charset = nNULL; + allowDup = !(!allowDup); + if (!allowDup && + ( + (all_scripts[src_uri] != nNULL) || (first_pass && scripts[src_uri]) || scriptTagExists(src_uri) + ) + ) { + if (scripts[src_uri] != nNULL && scripts[src_uri][sPRELOADDONE] && !scripts[src_uri][sDONE] && same_domain) { + // this script was preloaded via XHR, but is a duplicate, and dupes are not allowed + handleScriptLoad(nNULL,scripts[src_uri],bTRUE); // mark the entry as done and check if chain group is done + } + return; + } + if (scripts[src_uri] == nNULL) scripts[src_uri] = {}; + scriptentry = scripts[src_uri]; + if (scriptentry[sWHICH] == nNULL) scriptentry[sWHICH] = _which; + scriptentry[sDONE] = bFALSE; + scriptentry[sSRCURI] = src_uri; + scripts_loading = bTRUE; + + if (!_use_script_order && _use_xhr_preload && same_domain) loadScriptXHR(scriptentry,src_uri,type,charset); + else if (!_use_script_order && _use_cache_preload) loadScriptCache(scriptentry,src_uri,type,charset); + else loadScriptElem(scriptentry,src_uri,type,charset); + } + function onlyQueue(execBody) { + exec.push(execBody); + } + function queueAndExecute(execBody) { // helper for publicAPI functions below + if (queueExec && !_use_script_order) onlyQueue(execBody); + if (!queueExec || _use_preload) execBody(); // if engine is either not queueing, or is queuing in preload mode, go ahead and execute + } + function serializeArgs(args) { + var sargs = [], idx; + for (idx=-1; ++idx 1.3.2 has been patched to take advantage of document.readyState, which is enabled by this hack. But 1.3.2 and before are **not** safe or + affected by this hack, and should therefore **not** be lazy-loaded by script loader tools such as LABjs. + */ + (function(addEvent,domLoaded,handler){ + if (oDOC[sREADYSTATE] == nNULL && oDOC[addEvent]){ + oDOC[sREADYSTATE] = "loading"; + oDOC[addEvent](domLoaded,handler = function(){ + oDOC.removeEventListener(domLoaded,handler,bFALSE); + oDOC[sREADYSTATE] = sCOMPLETE; + },bFALSE); + } + })("addEventListener","DOMContentLoaded"); + +})(window); \ No newline at end of file diff --git a/demo/editor.html b/demo/editor.html new file mode 100644 index 00000000..b7c3e4f5 --- /dev/null +++ b/demo/editor.html @@ -0,0 +1,52 @@ + + + + + + Editor + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + \ No newline at end of file diff --git a/demo/fLAB.js b/demo/fLAB.js new file mode 100755 index 00000000..fcabff0d --- /dev/null +++ b/demo/fLAB.js @@ -0,0 +1,191 @@ +// fLAB.js (file:// protocol adapter for LABjs 1.0+) +// v0.2 (c) Kyle Simpson +// MIT License + +(function(global){ + var orig_$LAB = global.$LAB, + oDOC = global.document, + oDOCLOC = oDOC.location, + local_filesystem = (oDOCLOC.protocol === "file:") + ; + if (!orig_$LAB || !local_filesystem) return; // only adapt LABjs with fLABjs wrapper if LABjs exists and we're currently in local filesystem + + var sUNDEF = "undefined", // constants used for compression optimization + sSTRING = "string", + sHEAD = "head", + sBODY = "body", + sFUNCTION = "function", + sSCRIPT = "script", + sSRCURI = "srcuri", + sDONE = "done", + sWHICH = "which", + bTRUE = true, + bFALSE = false, + fSETTIMEOUT = global.setTimeout, + fGETELEMENTSBYTAGNAME = function(tn){return oDOC.getElementsByTagName(tn);}, + fOBJTOSTRING = Object.prototype.toString, + fNOOP = function(){}, + append_to = {}, + all_scripts = {}, + PAGEROOT = /^[^?#]*\//.exec(oDOCLOC.href)[0], + DOCROOT = /^file:\/\/(localhost)?(\/[a-z]:)?/i.exec(PAGEROOT)[0], + docScripts = fGETELEMENTSBYTAGNAME(sSCRIPT), + + is_ie = !+"\v1", // feature detection based on Andrea Giammarchi's solution: http://webreflection.blogspot.com/2009/01/32-bytes-to-know-if-your-browser-is-ie.html + sync_script_loading = is_ie, // only IE is currently known to do synchronous loading of file:// scripts, others require core LABjs async functionality + + global_defs = { + dupe:bFALSE, // allow duplicate scripts? + preserve:bFALSE, // preserve execution order of all loaded scripts (regardless of preloading) + base:"", // base path to prepend to all non-absolute-path scripts + which:sHEAD // which DOM object ("head" or "body") to append scripts to + } + ; + + append_to[sHEAD] = fGETELEMENTSBYTAGNAME(sHEAD); + append_to[sBODY] = fGETELEMENTSBYTAGNAME(sBODY); + + function canonicalScriptURI(src,base_path) { + if (typeof src !== sSTRING) src = ""; + if (typeof base_path !== sSTRING) base_path = ""; + var ret = (/^file\:\/\//.test(src) ? "" : base_path) + src; + return ((/^file\:\/\//.test(ret) ? "" : (ret.charAt(0) === "/" ? DOCROOT : PAGEROOT)) + ret); + } + function scriptTagExists(uri) { // checks if a script uri has ever been loaded into this page's DOM + var i = 0, script; + while (script = docScripts[i++]) { + if (typeof script.src === sSTRING && uri === canonicalScriptURI(script.src)) return bTRUE; + } + return bFALSE; + } + function engine(opts) { + if (typeof opts === sUNDEF) opts = global_defs; + + var ready = bFALSE, + _which = opts.which, + _base_path = opts.base, + waitFunc = fNOOP, + scripts_loading = bFALSE, + publicAPI, + scripts = {}, + orig_engine = null + ; + + function createScriptTag(scriptentry,src,type,charset) { + if (append_to[scriptentry[sWHICH]][0] === null) { // append_to object not yet ready + fSETTIMEOUT(arguments.callee,25); + return; + } + var scriptElem = oDOC.createElement(sSCRIPT), fSETATTRIBUTE = function(attr,val){scriptElem.setAttribute(attr,val);}; + fSETATTRIBUTE("type",type); + if (typeof charset === sSTRING) fSETATTRIBUTE("charset",charset); + fSETATTRIBUTE("src",src); + append_to[scriptentry[sWHICH]][0].appendChild(scriptElem); + } + function loadScript(o) { + if (typeof o.allowDup === sUNDEF) o.allowDup = opts.dupe; + var src = o.src, type = o.type, charset = o.charset, allowDup = o.allowDup, + src_uri = canonicalScriptURI(src,_base_path), scriptentry; + if (typeof type !== sSTRING) type = "text/javascript"; + if (typeof charset !== sSTRING) charset = null; + allowDup = !(!allowDup); + + if (!allowDup && + ( + (typeof all_scripts[src_uri] !== sUNDEF && all_scripts[src_uri] !== null) || + scriptTagExists(src_uri) + ) + ) { + return; + } + if (typeof scripts[src_uri] === sUNDEF) scripts[src_uri] = {}; + scriptentry = scripts[src_uri]; + if (typeof scriptentry[sWHICH] === sUNDEF) scriptentry[sWHICH] = _which; + scriptentry[sDONE] = bFALSE; + scriptentry[sSRCURI] = src_uri; + scripts_loading = bTRUE; + + all_scripts[scriptentry[sSRCURI]] = bTRUE; + createScriptTag(scriptentry,src_uri,type,charset); + } + function serializeArgs(args) { + var sargs = [], i; + for (i=0; i + @@ -24,12 +25,32 @@ - + + + + + + + + + + + + + + + + + + + + + diff --git a/editor.html b/editor.html deleted file mode 100644 index dcd024fd..00000000 --- a/editor.html +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - Editor - - - - - - - - - - - - - - - - - - - - - -
-
- - - - - \ No newline at end of file diff --git a/experiments/tokenizer.html b/experiments/tokenizer.html index c2f40f49..c1a6e48a 100644 --- a/experiments/tokenizer.html +++ b/experiments/tokenizer.html @@ -12,7 +12,10 @@ - + + + + +