User:PerfektesChaos/js/localEdit/Firefox/chrome/content/wikilocaledit.js

/// chrome://wikilocaledit/content/wikilocaledit.js /// Manage main app, which is browser panel toolbarbutton // Requires: //    * content/fileIO.js //     * content/permissions.js //     * content/prefs.js //     * locale/locale.js //  Used by windows: //    * content/wikilocaledit.xul /// 2012-12-12 PerfektesChaos@de.wikipedia /// Fingerprint: #0#0# /// /*jshint curly:true, eqeqeq:true, strict:true, undef:true, white:false */ /*global document, gBrowser, HTMLDocument, window                     */ /*jslint white: true                                                  */ /*globals gBrowser: true, HTMLDocument: true, document: true, window: true                                */

( function ( w ) {  "use strict";   var EVENTS, IO, PAGES, PREFS, TOOL, WLE, First;   if ( ! w.wikiLocalEdit ) {     w.wikiLocalEdit  =  { };   }   WLE        =  w.wikiLocalEdit;   WLE.pages  =  { };   PAGES      =  WLE.pages;   PREFS      =  WLE.prefs;   WLE.live   =  PREFS.getLeading;   EVENTS     =  { listening: false };   IO         =  { search:    "*.txt; *.text; *.wiki",                   select:    "Wikitext: *.txt, *.text, *.wiki" };   TOOL       =  { };

First =  function  { // Initialize package. Start event listeners. // Uses: //   w      //    TOOL.fresh // Remark: Used as event handler -- 'this' is not WLE // 2012-11-30 PerfektesChaos@de.wikipedia w.removeEventListener( "load", First, false );  // myself TOOL.fresh( false ); };  // First w.addEventListener( "load", First, false );  // -> gBrowser

EVENTS.fresh =  function  { // Update listener mode // Postcondition: //   Listeners are activated or stopped // Uses: //   this //   >  .pages.userURLstatics //   >  EVENTS.connect //   >  .live //   >  gBrowser //   >< EVENTS.listening //   .pages.fresh //   DOM.addEventListener //   DOM.removeEventListener //   (EVENTS.onPageLoad) //   (EVENTS.onButton) // 2012-11-30 PerfektesChaos@de.wikipedia var e,         i,          n  =  this.connect.length; PAGES.fresh; if ( WLE.live &&           ! this.listening  &&           PAGES.userURLstatics ) { for ( i = 0; i < n;  i++ ) { e =  this.connect[ i ]; gBrowser.addEventListener( e[ 0 ], e[ 1 ],  true,  true ); }  // for i         this.listening  =  true; } else if ( this.listening ) { for ( i = 0; i < n;  i++ ) { e =  this.connect[ i ]; gBrowser.removeEventListener( e[ 0 ], e[ 1 ],  true ); }  // for i         this.listening  =  false; }  };   // EVENTS.fresh

EVENTS.onPageLoad =  function ( event ) { // Any page has been loaded into user browser. // Postcondition: //   Returns true for continued event processing // Uses: //   .pages.isPageUser //   .pages.fiat //   .pages.form //   .pages.first //   .pages.furnish // Remark: Used as event handler -- 'this' is not WLE // 2012-11-30 PerfektesChaos@de.wikipedia var doc, doit, emit   =  event.originalTarget,                // Mozilla spec got    =  PAGES.isPageUser( emit ), socket; if ( got ) { doc    =  got[ 0 ]; doit   =  got[ 1 ]; socket =  PAGES.fiat( doc ); if ( doit ) { PAGES.form( doc, socket ); } else { PAGES.first( socket ); PAGES.furnish( doc ); }     }      return true; };  // EVENTS.onPageLoad

EVENTS.onPressButton =  function ( event ) { // Any page has been loaded into user browser. // Postcondition: //   Returns false for captured event processing // Uses: //   .pages.isPageUser //   DOM.getAttribute //   .pages.file //   IO.find //   .pages.flush //   .prefs.fetchBasedir //   .pages.setDirBase //   IO.fetchSubdir //   .pages.setDirSub // Remark: Used as event handler -- 'this' is not WLE // 2012-12-12 PerfektesChaos@de.wikipedia var emit  =  event.originalTarget,                // Mozilla spec doc   =  emit.ownerDocument, call  =  PAGES.isPageUser( doc ), stuff =  false, scan, serve, specific, suffix, suggest; if ( call ) { serve    =  emit.getAttribute( "action" ); specific =  emit.getAttribute( "specific" ); if ( call[ 1 ] ) { if ( serve === "OpenFile" ||  serve === "SaveFileAs" ) { scan    =  emit.getAttribute( "scan" ); suffix  =  emit.getAttribute( "suffix" ); suffix  =  ( suffix ? suffix : false ); suffix  =  suffix.replace( /[^a-zA-Z0-9]/g, "" ); }           switch ( serve ) { case "OpenFile" : // +text/saved leer oder gleich stuff =  emit.getAttribute( "lowcode" ); PAGES.file( specific,                             scan,                              suffix,                              call[ 0 ],                              ( stuff === "true" ) ); break; case "SaveFileAs" : suggest =  emit.getAttribute( "suggest" ); stuff   =  IO.find( specific,                                       scan,                                       suggest,                                       suffix,                                       true ); case "SaveFile" :  // fall through IO.flush( doc, stuff ); break; case "Abort" : break; }  // switch serve } else { switch ( serve ) { case "DirBase" : WLE.prefs.fetchBasedir; PAGES.setDirBase( doc ); break; case "DirSub" : IO.fetchSubdir( specific ); PAGES.setDirSub( doc, specific ); break; }  // switch serve }     }      return false; };  // EVENTS.onPressButton

EVENTS.connect =  [ [ "load",               EVENTS.onPageLoad ], [ "wikilocaleditButton", EVENTS.onPressButton ] ];

IO.fetchSubdir =  function ( account ) { // Perform local directory sub project selection and storing // Precondition: //   account  -- DBname. user name // Uses: //   >  .locale.selectDirSub //   .prefs.getDirBase //   .prefs.getDirSub //   .fileIO.find //   .prefs.setDirSub // 2012-12-12 PerfektesChaos@de.wikipedia var n, s,         start  =  WLE.prefs.getDirBase; s =  WLE.fileIO.find( start + WLE.prefs.getDirSub( account ),                             false,                             false,                             false,                             WLE.locale.selectDirSub + "\n" + account,                             false ); if ( typeof s ===  "string" ) { n =  start.length; if ( s.substr( 0, n ) ===  start ) { s =  s.substr( n ); } else { s =  ""; }        WLE.prefs.setDirSub( s, account ); }  };   // IO.fetchSubdir

IO.file =  function ( account, achieve, assign, access, ansi ) { // Retrieve file name and content and put into textarea // Precondition: //   account  -- sub path for:  DBname / user name //   achieve  -- pattern string //   assign   -- suffix for new file //   access   -- document of user edit web page //   ansi     -- input file is not utf-8 // Uses: //   IO.find //   .fileIO.feed //   (IO.filled) // 2012-12-12 PerfektesChaos@de.wikipedia var stuff =  IO.find( account, achieve, false, assign, false ); if ( stuff ) { WLE.fileIO.feed( stuff, access, this.filled, ansi ); }  };   // IO.file

IO.filled =  function ( arglist ) { // Callback after asynchronous reading from local file // Precondition: //   arglist  -- Array, or false //               [0]  path (appoint) //               [1]  true: write protected //               [2]  content, or false //               [3]  document of user web page //   achieved  -- string with file content // Uses: //   >< .pages.windows //   .pages.fiat //   .pages.form //   .pages.fill // Remark: Used as event handler -- 'this' is not IO     // 2012-11-30 PerfektesChaos@de.wikipedia var doc, props, socket; if ( arglist ) { doc    =  arglist[ 3 ]; socket =  PAGES.fiat( doc ); if ( socket ) { props =  PAGES.windows[ socket ]; if ( props ) { props.filepath =  arglist[ 0 ]; PAGES.form( doc, socket ); PAGES.fill( doc, arglist[ 2 ] ); }        }      }   };   // IO.filled

IO.find =  function ( account, achieve, assign, add, allow ) { // Find text file name // Precondition: //   account  -- sub path for:  DBname / user name //   achieve  -- pattern string //   assign   -- suggestion for file name //   add      -- suffix for new file, or false //   allow    -- save a non-existing file // Postcondition: //   Returns  string with path, or false // Uses: //   this //   >  IO.search //   >  IO.select //   >  .locale.selectFile //   .prefs.getDirBase //   .prefs.getDirSub //   .fileIO.find // 2012-12-12 PerfektesChaos@de.wikipedia var r,         pattern  =  [ "", achieve ], start   =  PREFS.getDirBase, suffix  =  add, suggest =  assign; if ( start && account ) { start =  start  +  PREFS.getDirSub( account ); }     if ( ! achieve ) { pattern[ 1 ] =  this.search; }     if ( pattern[ 1 ]  ===  this.search ) { pattern[ 0 ] =  this.select; }     if ( suffix ) { suffix =  ( suffix === "*"  ?  ""  :  suffix ); } else { suffix =  "txt"; }     r       =  WLE.fileIO.find( start,                                  pattern,                                  suggest,                                  suffix,                                  WLE.locale.selectFile,                                  allow ); return r;  };   // IO.find

IO.flush =  function ( access, as ) { // Write content into text file // Precondition: //   access  -- document of user edit web page //   as      -- SaveAs file path, or false // Postcondition: //   Returns true if failed // Uses: //   this //   w      //    >  .pages.windows //   .pages.fiat //   .pages.feed //   .fileIO.flush //   (IO.flushed) // 2012-11-30 PerfektesChaos@de.wikipedia var r,         socket  =  PAGES.fiat( access ), store  =  ( as  ?  as  :  PAGES.windows[ socket ].filepath ), story  =  PAGES.feed( access ); r =  WLE.fileIO.flush( story,                              store,                              access,                              this.flushed,                              [ access, story, store, socket ] ); if ( r ) { // Handle error! w.alert( "IO.flush " + r ); }     return r;   };   // IO.flush

IO.flushed =  function ( approve, arglist ) { // Callback after asynchronous written text file // Precondition: //   approve  -- status code //   arglist  -- Array // Uses: //   w      //    .pages.flushed // Remark: Used as event handler -- 'this' is not IO     // 2012-11-30 PerfektesChaos@de.wikipedia if ( w.Components.isSuccessCode( approve ) ) { PAGES.flushed( arglist[ 0 ],                       arglist[ 1 ],                        arglist[ 2 ],                        arglist[ 3 ] ); } else { w.alert( "IO.flushed error=" + approve); // Handle error! }  };   // IO.flushed

PAGES.feed =  function ( access ) { // Retrieve content from textarea // Precondition: //   access  -- document of user edit web page // Postcondition: //   Returns text // Uses: //   DOM.getElementById // 2012-11-30 PerfektesChaos@de.wikipedia var elt =  access.getElementById( "wpTextbox1" ), r   =  false; if ( elt ) { r =  elt.value; }     return r;   };   // .pages.feed

PAGES.fetch =  function ( ask ) { // Retrieve unique 64-bit ID number of user window // Precondition: //   ask  -- document of user web page // Postcondition: //   Returns ID number string (tabbrowser window count) // Uses: //   w      // 2012-11-30 PerfektesChaos@de.wikipedia var cif, util, r    =  false, win  =  ask.defaultView; if ( win ) { cif  =  w.Components.interfaces; util =  win.QueryInterface( cif.nsIInterfaceRequestor ) .getInterface( cif.nsIDOMWindowUtils ); if ( util ) { r =  "w#" + util.outerWindowID; }     }      return r;   };   // .pages.fetch

PAGES.fiat =  function ( ask ) { // Ensure persistent window information for this tabbrowser // Precondition: //   ask  -- document of user web page // Postcondition: //   Returns ID number string // Uses: //   this //   >< .pages.windows //   .pages.fetch //   .pages.first // 2012-11-30 PerfektesChaos@de.wikipedia var r =  this.fetch( ask ); if ( r ) { if ( ! this.windows ) { this.windows =  { }; }        if ( ! this.windows[ r ] ) { this.first( r ); }     }      return r;   };   // .pages.fiat

PAGES.file =  function ( account, achieve, assign, access, ansi ) { // If save, retrieve file name and content and put into textarea // Precondition: //   account  -- sub path for:  DBname / user name //   achieve  -- pattern string //   assign   -- suffix for new file //   access   -- document of user edit web page //   ansi     -- input file is not utf-8 // Uses: //   this //   w      //    >  .pages.windows //   >  .locale.saveFirst //   .pages.feed //   .pages.fiat //   IO.file // 2012-11-30 PerfektesChaos@de.wikipedia var leeway =  true, screen =  this.feed( access ), socket, store; if ( screen ) { socket =  this.fiat( access ); store  =  this.windows[ socket ].wikitext; if ( store ) { leeway =  ( screen === store ); if ( ! leeway ) { w.alert( WLE.locale.saveFirst ); }        }      }      if ( leeway ) { IO.file( account, achieve, assign, access, ansi ); }  };   // .pages.file

PAGES.fill =  function ( access, apply ) { // Fill textarea with file content // Precondition: //   access  -- document of user edit web page //   apply   -- content // Uses: //   this //    < .pages.windows //   DOM.getElementById //   DOM.createEvent //   DOM.initEvent //   DOM.dispatchEvent //   .pages.fiat // 2012-11-30 PerfektesChaos@de.wikipedia var elt    =  access.getElementById( "wpTextbox1" ), event, k,         socket, story  =  apply; if ( elt ) { elt.value =  story; event     =  access.createEvent( "Events" ); event.initEvent( "wikilocaleditFilled", true, false ); elt.dispatchEvent( event ); // Byte Order Mark k =  story.charCodeAt(0); if ( k === 255 ) { if ( story.charCodeAt(1) === 254 ) { story =  story.substr( 2 ); }        } else if ( k === 65534 ) { story =  story.substr( 1 ); }        socket  =  this.fiat( access ); this.windows[ socket ].wikitext =  story; }  };   // .pages.fill

PAGES.first =  function ( assign ) { // Initialize page window object //   assign   -- windows ID      // Precondition: // Uses: //   this //    < .pages.windows // 2012-11-30 PerfektesChaos@de.wikipedia this.windows[ assign ] =  { filepath: false, letwrite: true, wikitext: false }; };  // .pages.first

PAGES.flushed =  function ( adjust, apply, address, assign ) { // File content has been written // Precondition: //   adjust   -- document of static user page //   apply    -- content //   address  -- text file path //   assign   -- windows ID      // Uses: //   this //   >< .pages.windows //   DOM.getElementById //   DOM.createEvent //   DOM.initEvent //   DOM.dispatchEvent //   .pages.setFile // 2012-11-30 PerfektesChaos@de.wikipedia var elt   =  adjust.getElementById( "wpTextbox1" ), event; if ( elt ) { event =  adjust.createEvent("Events"); event.initEvent( "wikilocaleditSaved", true, false ); elt.dispatchEvent( event ); this.windows[ assign ].wikitext  =  apply; PAGES.windows[ assign ].filepath =  address; this.setFile( adjust, address ); }  };   // .pages.flushed

PAGES.form =  function ( adjust, aim ) { // Decorate edit/submit user page of /LocalEdit // Precondition: //   adjust  -- document of static user page //   aim     -- unique window identifier // Uses: //   this //   >  .pages.windows //   .pages.setFile // 2012-12-12 PerfektesChaos@de.wikipedia var elt   =  adjust.getElementById( "WLE_select_SaveFile" ), props =  this.windows[ aim ], s     =  props.filepath; if ( elt ) { if ( s ) { this.setFile( adjust, s ); elt.disabled =  ! props.letwrite; } else { this.setFile( adjust, "" ); elt.disabled =  true; }     }   };   // .pages.form

PAGES.fresh =  function  { // Update userpage list and page URL listener // Uses: //   this //   >< .pages.userURLstatics //   >< .pages.userURLsubmits //   .prefs.getUserlist // Remark: Used by content/config.js      // 2012-11-30 PerfektesChaos@de.wikipedia var i, j, n, s, s0, s1, sift, site, userlist =  WLE.prefs.getUserlist; if ( userlist ) { n =  userlist.length; this.userURLstatics =  new Array( n ); this.userURLsubmits =  new Array( n ); for ( i = 0; i < n;  i++ ) { s =  userlist[ i ]; j =  s.indexOf( "/wiki/" ); if ( j > 15 ) { site =  s.substr( 0,  j + 1 ); sift =  s.substr( j + 6 )  +  "/LocalEdit"; s0   =  site + "wiki/" + sift; s1   =  site + "w/index.php?title=" + sift + "&action="; } else { s0 =  ""; s1 =  ""; }           this.userURLstatics[ i ]  =  s0; this.userURLsubmits[ i ] =  s1; }  // for i      } else if ( this.userURLstatics ) { delete this.userURLstatics; delete this.userURLsubmits; }  };   // .pages.fresh

PAGES.furnish =  function ( adjust ) { // Decorate static user page of /wiki/ /LocalEdit // Precondition: //   adjust  -- document of static user page // Uses: //   this //   DOM.getElementById //   DOM.setAttribute //   .pages.setDirBase //   .pages.setDirSub // 2012-11-30 PerfektesChaos@de.wikipedia var elt, s, specific; elt =  adjust.getElementById( "WLE.inactive" ); elt.setAttribute( "style", "display:none" ); elt =  adjust.getElementById( "WLE.active" ); elt.removeAttribute( "style" ); elt =  adjust.getElementById( "WLE.client" ); s   =  elt.getAttribute( "src" ); elt =  adjust.getElementById( "WLE.stateIMG" ); elt.setAttribute( "src", s ); this.setDirBase( adjust ); elt =  adjust.getElementById( "WLE.DirBase" ); elt.removeAttribute( "style" ); elt      =  adjust.getElementById( "WLE.specific" ); specific =  elt.textContent; this.setDirSub( adjust, specific ); elt =  adjust.getElementById( "WLE.startEdit" ); elt.removeAttribute( "style" ); };  // .pages.furnish

PAGES.isPageUser =  function ( approve ) { // Check whether event has been launched from registered user page // Precondition: //   approve  -- document to be checked for origin // Postcondition: //   Returns  Array  iff dispatched from requested user page //              [0]  document //              [1]  false: static, else dynamic action // Uses: //   this //   >  .reDomain //   >  .pages.userURLstatics //   >  .pages.userURLsubmits // 2012-11-30 PerfektesChaos@de.wikipedia var i, n, doc, s, src, r =  false; if ( this.userURLstatics ) { doc =  approve; if ( doc instanceof HTMLDocument ) { // is this an inner frame? if ( doc.defaultView.frameElement ) { // Frame within a tab was loaded. // Find the root document: while ( doc.defaultView.frameElement ) { doc =  doc.defaultView.frameElement.ownerDocument; }           }         }         src  =  doc.URL; if ( WLE.reDomain.test( src ) ) { n  =  this.userURLstatics.length; for ( i = 0; i < n;  i++ ) { if ( src === this.userURLstatics[ i ] ) { r =  [ doc, false ]; break; }           }   // for i            if ( ! r ) { for ( i = 0; i < n;  i++ ) { s =  this.userURLsubmits[ i ]; if ( src.indexOf( s ) ===  0 ) { r =  [ doc,  src.substr( s.length ) ]; break; }              }   // for i            } }     }      return r;   };   // .pages.isPageUser

PAGES.setDirBase =  function ( adjust ) { // Write base directory path into static /LocalEdit user page // Precondition: //   adjust  -- document of static user page // Postcondition: //   Returns base directory // Uses: //   DOM.getElementById //   .prefs.getDirBase // 2012-11-30 PerfektesChaos@de.wikipedia var elt =  adjust.getElementById( "WLE.dirbase" ), r   =  PREFS.getDirBase; if ( elt ) { elt.textContent =  r;      } return r;  };   // .pages.setDirBase

PAGES.setDirSub =  function ( adjust, account ) { // Write project directory path into static /LocalEdit user page // Precondition: //   adjust   -- document of static user page //   account  -- DBname. user name // Uses: //   DOM.getElementById //   .prefs.getDirBase //   DOM.removeAttribute //   DOM.setAttribute // 2012-11-30 PerfektesChaos@de.wikipedia var eltButt =  adjust.getElementById( "WLE.DirSub" ), eltPath =  adjust.getElementById( "WLE.dirsub" ); if ( eltButt && eltPath ) { if ( PREFS.getDirBase ) { eltButt.removeAttribute( "style" ); eltPath.removeAttribute( "style" ); eltPath.textContent =  PREFS.getDirSub( account ); } else { eltButt.setAttribute( "style", "display:none" ); eltPath.setAttribute( "style", "display:none" ); }     }   };   // .pages.setDirSub

PAGES.setFile =  function ( adjust, address ) { // Write text file path into user page // Precondition: //   adjust   -- document of static user page //   address  -- text file path // Uses: //   DOM.getElementById //   DOM.setAttribute // 2012-11-30 PerfektesChaos@de.wikipedia var elt   =  adjust.getElementById( "LocalEditFilePath" ), style; if ( elt ) { if ( address ) { elt.textContent =  address; style =    "margin-bottom: 1em;" + "border-bottom: solid 2px #0000FF;"; } else { style =  "display:none"; }        elt  =  adjust.getElementById( "LocalEditFileDiv" ); elt.setAttribute( "style", style ); }  };   // .pages.setFile

WLE.toolBarClicked =  function  { // Button on panel has been clicked. // Start or stop listening on events. // Uses: //   >< .live //   TOOL.fresh // Remark: Used as event handler -- 'this' is not WLE // 2012-11-30 PerfektesChaos@de.wikipedia WLE.live =  ! WLE.live; TOOL.fresh( false ); };  // .toolBarClicked

TOOL.fresh =  function ( all ) { // Update toolbar menu state // Uses: //   this //   >  TOOL.panelButton //   >  .live //   DOM.getElementById //   EVENTS.fresh // 2012-11-30 PerfektesChaos@de.wikipedia var show; if ( ! this.panelButton ) { this.panelButton = document.getElementById( "wikilocaleditToolbarbutton" ); }     if ( this.panelButton ) { show =  "chrome://wikilocaledit/skin/wikilocaledit-24" + "x24" + ( WLE.live ? "" : "-off" )  +  ".png"; this.panelButton.image =  show; if ( all ) { this.panelButton.tooltipText =  ""; }     }      EVENTS.fresh; };  // TOOL.fresh

} ( window ) );

/// EOF  content/wikilocaledit.js