]> git.donarmstrong.com Git - dactyl.git/blobdiff - common/content/statusline.js
Import r6923 from upstream hg supporting Firefox up to 22.0a1
[dactyl.git] / common / content / statusline.js
index 54943425f6a650e99a916fd708911faba1dc896c..0de02088a37cb79f91c3f8b811796feff49f07f2 100644 (file)
@@ -1,6 +1,6 @@
 // Copyright (c) 2006-2008 by Martin Stubenschrott <stubenschrott@vimperator.org>
 // Copyright (c) 2007-2011 by Doug Kearns <dougkearns@gmail.com>
-// Copyright (c) 2008-2011 by Kris Maglione <maglione.k@gmail.com>
+// Copyright (c) 2008-2012 Kris Maglione <maglione.k@gmail.com>
 //
 // This work is licensed for reuse under an MIT license. Details are
 // given in the LICENSE.txt file included with this file.
@@ -12,77 +12,82 @@ var StatusLine = Module("statusline", {
     init: function init() {
         this._statusLine = document.getElementById("status-bar");
         this.statusBar = document.getElementById("addon-bar") || this._statusLine;
-        this.statusBar.collapsed = true;
         this.baseGroup = this.statusBar == this._statusLine ? "StatusLine " : "";
 
         if (this.statusBar.localName == "toolbar") {
-            styles.system.add("addon-bar", config.styleableChrome, <css><![CDATA[
+            styles.system.add("addon-bar", config.styleableChrome, literal(/*
                 #status-bar { margin-top: 0 !important; }
                 #addon-bar > statusbar { -moz-box-flex: 1 }
                 #addon-bar > #addonbar-closebutton { visibility: collapse; }
                 #addon-bar > xul|toolbarspring { visibility: collapse; }
-            ]]></css>);
+            */));
 
-            util.overlayWindow(window, { append: <><statusbar id="status-bar" ordinal="0"/></> });
+            overlay.overlayWindow(window, {
+                append: [
+                    ["statusbar", { id: "status-bar", ordinal: "0" }]]
+            });
 
-            highlight.loadCSS(util.compileMacro(<![CDATA[
-                !AddonBar;#addon-bar  {
+            highlight.loadCSS(util.compileMacro(literal(/*
+                !AddonBar;#addon-bar {
                     padding-left: 0 !important;
                     min-height: 18px !important;
                     -moz-appearance: none !important;
                     <padding>
                 }
-                !AddonButton;#addon-bar xul|toolbarbutton  {
+                !AddonButton;#addon-bar xul|toolbarbutton {
                     -moz-appearance: none !important;
                     padding: 0 !important;
                     border-width: 0px !important;
                     min-width: 0 !important;
                     color: inherit !important;
                 }
-                AddonButton:not(:hover)  background: transparent !important;
-            ]]>)({ padding: util.OS.isMacOSX ? "padding-right: 10px !important;" : "" }));
+                AddonButton:not(:hover)  background: transparent;
+            */))({ padding: config.OS.isMacOSX ? "padding-right: 10px !important;" : "" }));
 
             if (document.getElementById("appmenu-button"))
-                highlight.loadCSS(<![CDATA[
+                highlight.loadCSS(literal(/*
                     AppmenuButton       min-width: 0 !important; padding: 0 .5em !important;
-                ]]>);
+                */));
         }
 
-        XML.ignoreWhitespace = true;
         let _commandline = "if (window.dactyl) return dactyl.modules.commandline";
-        let prepend = <e4x xmlns={XUL} xmlns:dactyl={NS}>
-            <button id="appmenu-button" label="" image="chrome://branding/content/icon16.png" highlight="AppmenuButton" />
-            <toolbarbutton id="appmenu-toolbar-button" label="" image="chrome://branding/content/icon16.png" />
-            <statusbar id="status-bar" highlight="StatusLine">
-                <!-- insertbefore="dactyl.statusBefore;" insertafter="dactyl.statusAfter;" -->
-                <hbox key="container" hidden="false" align="center"  flex="1">
-                    <stack orient="horizontal"       align="stretch" flex="1" highlight="CmdLine StatusCmdLine" class="dactyl-container">
-                        <hbox                                                 highlight="CmdLine StatusCmdLine" class="dactyl-container">
-                            <label key="mode"          crop="end"                                               class="plain" collapsed="true"/>
-                            <stack  id="dactyl-statusline-stack"     flex="1" highlight="CmdLine StatusCmdLine" class="dactyl-container">
-                                <textbox key="url"     crop="end"    flex="1"                                   class="plain dactyl-status-field-url" readonly="true"/>
-                                <textbox key="message" crop="end"    flex="1" highlight="Normal StatusNormal"   class="plain"                         readonly="true"/>
-                            </stack>
-                        </hbox>
-                    </stack>
-                    <label class="plain" key="inputbuffer"    flex="0"/>
-                    <label class="plain" key="progress"       flex="0"/>
-                    <label class="plain" key="tabcount"       flex="0"/>
-                    <label class="plain" key="bufferposition" flex="0"/>
-                    <label class="plain" key="zoomlevel"      flex="0"/>
-                </hbox>
-                <!-- just hide them since other elements expect them -->
-                <statusbarpanel id="statusbar-display"       hidden="true"/>
-                <statusbarpanel id="statusbar-progresspanel" hidden="true"/>
-            </statusbar>
-        </e4x>;
-
-        for each (let attr in prepend..@key)
-            attr.parent().@id = "dactyl-statusline-field-" + attr;
-
-        util.overlayWindow(window, {
+        let prepend = [
+            ["button", { id: "appmenu-button", label: "", image: "chrome://branding/content/icon16.png", highlight: "AppmenuButton", xmlns: "xul" }],
+            ["toolbarbutton", { id: "appmenu-toolbar-button", label: "", image: "chrome://branding/content/icon16.png" }],
+            ["statusbar", { id: "status-bar", highlight: "StatusLine", xmlns: "xul" },
+                // <!-- insertbefore="dactyl.statusBefore;" insertafter="dactyl.statusAfter;" -->
+                ["hbox", { key: "container", hidden: "false", align: "center",  flex: "1" },
+                    ["stack", { orient: "horizontal",       align: "stretch", flex: "1", highlight: "CmdLine StatusCmdLine", class: "dactyl-container" },
+                        ["hbox", {                                                       highlight: "CmdLine StatusCmdLine", class: "dactyl-container" },
+                            ["label", { key: "mode",          crop: "end",                                                   class: "plain", collapsed: "true" }],
+                            ["stack", {  id: "dactyl-statusline-stack",       flex: "1", highlight: "CmdLine StatusCmdLine", class: "dactyl-container" },
+                                ["textbox", { key: "url",     crop: "end",    flex: "1", style: "background: transparent;",  class: "plain dactyl-status-field-url",
+                                              readonly: "true" }],
+                                ["hbox", { key: "message-box" },
+                                    ["label", { key: "message-pre", highlight: "WarningMsg StatusWarningMsg", class: "plain", readonly: "true" }],
+                                    ["textbox", { key: "message", crop: "end",    flex: "1", highlight: "Normal StatusNormal",   class: "plain",
+                                                  readonly: "true" }]]]]],
+                    ["label", { class: "plain", key: "inputbuffer",    flex: "0" }],
+                    ["label", { class: "plain", key: "progress",       flex: "0" }],
+                    ["label", { class: "plain", key: "tabcount",       flex: "0" }],
+                    ["label", { class: "plain", key: "bufferposition", flex: "0" }],
+                    ["label", { class: "plain", key: "zoomlevel",      flex: "0" }]],
+                // just hide them since other elements expect them
+                ["statusbarpanel", { id: "statusbar-display",       hidden: "true" }],
+                ["statusbarpanel", { id: "statusbar-progresspanel", hidden: "true" }]]];
+
+        (function rec(ary) {
+            ary.forEach(function (elem) {
+                if ("key" in elem[1])
+                    elem[1].id = "dactyl-statusline-field-" + elem[1].key;
+                if (elem.length > 2)
+                    rec(elem.slice(2));
+            });
+        })(prepend);
+
+        overlay.overlayWindow(window, {
             objects: this.widgets = { get status() this.container },
-            prepend: prepend.elements()
+            prepend: prepend
         });
 
         try {
@@ -96,7 +101,7 @@ var StatusLine = Module("statusline", {
     signals: {
         "browser.locationChange": function (webProgress, request, uri) {
             let win = webProgress.DOMWindow;
-            this.status = buffer.uri;
+            this.status = uri;
             this.progress = uri && win && win.dactylProgress || "";
 
             // if this is not delayed we get the position of the old buffer
@@ -108,9 +113,11 @@ var StatusLine = Module("statusline", {
         "browser.overLink": function (link) {
             switch (options["showstatuslinks"]) {
             case "status":
+                this.overLink = link ? _("status.link", link) : null;
                 this.status = link ? _("status.link", link) : buffer.uri;
                 break;
             case "command":
+                this.overLink = null;
                 if (link)
                     dactyl.echo(_("status.link", link), commandline.FORCE_SINGLELINE);
                 else
@@ -138,16 +145,32 @@ var StatusLine = Module("statusline", {
                 webProgress.DOMWindow.document.dactylSecurity = this.security;
         },
         "browser.stateChange": function onStateChange(webProgress, request, flags, status) {
-            if (flags & Ci.nsIWebProgressListener.STATE_START)
-                this.progress = 0;
-            if (flags & Ci.nsIWebProgressListener.STATE_STOP) {
-                this.progress = "";
-                this.status = buffer.uri;
-            }
+            const L = Ci.nsIWebProgressListener;
+
+            if (flags & (L.STATE_IS_DOCUMENT | L.STATE_IS_WINDOW))
+                if (flags & L.STATE_START)
+                    this.progress = 0;
+                else if (flags & L.STATE_STOP)
+                    this.progress = "";
+
+            if (flags & L.STATE_STOP)
+                this.updateStatus();
         },
         "browser.statusChange": function onStatusChange(webProgress, request, status, message) {
-            this.status = message || buffer.uri;
+            this.timeout(function () {
+                this.status = message || buffer.uri;
+            });
         },
+        "fullscreen": function onFullscreen(fullscreen) {
+            let go = options.get("guioptions");
+            if (fullscreen) {
+                this.wasVisible = go.has("s");
+                go.op("-", "s");
+            }
+            else if (this.wasVisible) {
+                go.op("+", "s");
+            }
+        }
     },
 
     /**
@@ -175,7 +198,7 @@ var StatusLine = Module("statusline", {
 
     // update all fields of the statusline
     update: function update() {
-        this.status = buffer.uri;
+        this.updateStatus();
         this.inputBuffer = "";
         this.progress = "";
         this.updateTabCount();
@@ -183,34 +206,8 @@ var StatusLine = Module("statusline", {
         this.updateZoomLevel();
     },
 
-    // ripped from Firefox; modified
-    unsafeURI: util.regexp(String.replace(<![CDATA[
-            [
-                \s
-                // Invisible characters (bug 452979)
-                U001C U001D U001E U001F // file/group/record/unit separator
-                U00AD // Soft hyphen
-                UFEFF // BOM
-                U2060 // Word joiner
-                U2062 U2063  // Invisible times/separator
-                U200B UFFFC // Zero-width space/no-break space
-
-                // Bidi formatting characters. (RFC 3987 sections 3.2 and 4.1 paragraph 6)
-                U200E U200F U202A U202B U202C U202D U202E
-            ]
-        ]]>, /U/g, "\\u"),
-        "gx"),
-    losslessDecodeURI: function losslessDecodeURI(url) {
-        return url.split("%25").map(function (url) {
-                // Non-UTF-8 compliant URLs cause "malformed URI sequence" errors.
-                try {
-                    return decodeURI(url).replace(this.unsafeURI, encodeURIComponent);
-                }
-                catch (e) {
-                    return url;
-                }
-            }, this).join("%25");
-    },
+    unsafeURI: deprecated("util.unsafeURI", { get: function unsafeURI() util.unsafeURI }),
+    losslessDecodeURI: deprecated("util.losslessDecodeURI", function losslessDecodeURI() util.losslessDecodeURI.apply(util, arguments)),
 
     /**
      * Update the URL displayed in the status line. Also displays status
@@ -230,29 +227,26 @@ var StatusLine = Module("statusline", {
             if (uri.equals(buffer.uri) && window.getWebNavigation) {
                 let sh = window.getWebNavigation().sessionHistory;
                 if (sh && sh.index > 0)
-                    modified += "+";
-                if (sh && sh.index < sh.count - 1)
                     modified += "-";
-            }
-
-            if (modules.bookmarkcache) {
-                if (bookmarkcache.isBookmarked(uri))
+                if (sh && sh.index < sh.count - 1)
+                    modified += "+";
+                if (this.bookmarked)
                     modified += UTF8("❤");
             }
 
             if (modules.quickmarks)
                 modified += quickmarks.find(uri.spec.replace(/#.*/, "")).join("");
 
-            url = this.losslessDecodeURI(uri.spec);
+            url = util.losslessDecodeURI(uri.spec);
         }
 
         if (url == "about:blank") {
             if (!buffer.title)
-                url = "[No Name]";
+                url = _("buffer.noName");
         }
         else {
-            url = url.replace(RegExp("^dactyl://help/(\\S+)#(.*)"), function (m, n1, n2) n1 + " " + decodeURIComponent(n2) + " [Help]")
-                     .replace(RegExp("^dactyl://help/(\\S+)"), "$1 [Help]");
+            url = url.replace(RegExp("^dactyl://help/(\\S+)#(.*)"), function (m, n1, n2) n1 + " " + decodeURIComponent(n2) + " " + _("buffer.help"))
+                     .replace(RegExp("^dactyl://help/(\\S+)"), "$1 " + _("buffer.help"));
         }
 
         if (modified)
@@ -260,10 +254,20 @@ var StatusLine = Module("statusline", {
 
         this.widgets.url.value = url;
         this._status = uri;
+    },
 
+    get bookmarked() this._bookmarked,
+    set bookmarked(val) {
+        this._bookmarked = val;
+        if (this.status)
+            this.status = this.status;
     },
 
-    updateStatus: function updateStatus() { this.status = buffer.uri; },
+    updateStatus: function updateStatus() {
+        this.timeout(function () {
+            this.status = this.overLink || buffer.uri;
+        });
+    },
 
     updateUrl: deprecated("statusline.status", function updateUrl(url) { this.status = url || buffer.uri }),
 
@@ -291,15 +295,15 @@ var StatusLine = Module("statusline", {
      */
     progress: Modes.boundProperty({
         get: function progress() this._progress,
-        set: function  progress(progress) {
+        set: function progress(progress) {
             this._progress = progress || "";
 
-            if (typeof progress == "string")
+            if (isinstance(progress, ["String", _]))
                 this.widgets.progress.value = this._progress;
             else if (typeof progress == "number") {
                 let progressStr = "";
                 if (this._progress <= 0)
-                    progressStr = "[ Loading...         ]";
+                    progressStr = /*L*/"[ Loading...         ]";
                 else if (this._progress < 1) {
                     let progress = Math.round(this._progress * 20);
                     progressStr = "["