]> jfr.im git - irc/quakenet/qwebirc.git/blobdiff - js/ui/frontends/qui.js
add side tabs
[irc/quakenet/qwebirc.git] / js / ui / frontends / qui.js
index c9bcf3ac3821173195df456bc4b56f144ac113de..57846b0e02c83d5c36c8a1ed3982c14bef8a6966 100644 (file)
@@ -1,9 +1,10 @@
 qwebirc.ui.QUI = new Class({
-  Extends: qwebirc.ui.NewLoginUI,
+  Extends: qwebirc.ui.RootUI,
   initialize: function(parentElement, theme, options) {
     this.parent(parentElement, qwebirc.ui.QUI.Window, "qui", options);
     this.theme = theme;
     this.parentElement = parentElement;
+    this.setModifiableStylesheet("qui");
   },
   postInitialize: function() {
     this.qjsui = new qwebirc.ui.QUI.JSUI("qwebirc-qui", this.parentElement);
@@ -12,24 +13,39 @@ qwebirc.ui.QUI = new Class({
       if($defined(w))
         w.onResize();
     }.bind(this));
-    this.qjsui.top.addClass("tabbar");
-    
+    this.qjsui.top.addClass("outertabbar");
+    this.qjsui.left.addClass("outertabbar");
+
+    this.qjsui.top.addClass("outertabbar_top");
+    this.qjsui.left.addClass("outertabbar_left");
+
     this.qjsui.bottom.addClass("input");
     this.qjsui.right.addClass("nicklist");
     this.qjsui.topic.addClass("topic");
     this.qjsui.middle.addClass("lines");
     
-    this.tabs = this.qjsui.top;
+    this.outerTabs = new Element("div");
+    this.sideTabs = null;
+
+    this.tabs = new Element("div");
+    this.tabs.addClass("tabbar");
+    
+    this.__createDropdownMenu();
+
+    this.outerTabs.appendChild(this.tabs);
     this.origtopic = this.topic = this.qjsui.topic;
-    this.origlines = this.lines = this.qjsui.middle;
+    this.lines = this.qjsui.middle;
     this.orignicklist = this.nicklist = this.qjsui.right;
     
     this.input = this.qjsui.bottom;
     this.reflow = this.qjsui.reflow.bind(this.qjsui);
     
     this.tabs.addEvent("mousewheel", function(x) {
+      if(this.sideTabs)
+        return;
+
       var event = new Event(x);
-      
+
       /* up */
       if(event.wheel > 0) {
         this.nextWindow();
@@ -40,34 +56,36 @@ qwebirc.ui.QUI = new Class({
       event.stop();
     }.bind(this));
     
-    this.__createDropdown();
-    
     this.createInput();
     this.reflow();
+    this.reflow.delay(100); /* Konqueror fix */
+    this.setSideTabs(this.uiOptions.SIDE_TABS);
+
   },
-  __createDropdown: function() {
-    var dropdownMenu = new Element("div");
+  newWindow: function(client, type, name) {
+    var w = this.parent(client, type, name);
+    w.setSideTabs(this.sideTabs);
+    return w;
+  },
+  __createDropdownMenu: function() {
+    var dropdownMenu = new Element("span");
     dropdownMenu.addClass("dropdownmenu");
-    var surface = new Element("div");
-    surface.addClass("surface");
-
-    dropdownMenu.hide = function(noRemove) {
+    
+    dropdownMenu.hide = function() {
       dropdownMenu.setStyle("display", "none");
       dropdownMenu.visible = false;
-      if(!noRemove)
-        this.parentElement.removeChild(surface);
+      document.removeEvent("mousedown", hideEvent);
     }.bind(this);
-    surface.addEvent("click", function() {
-      dropdownMenu.hide();
-    });
-
-    dropdownMenu.hide(true);
+    var hideEvent = function() { dropdownMenu.hide(); };
+    
+    dropdownMenu.hide();
     this.parentElement.appendChild(dropdownMenu);
     
     this.UICommands.forEach(function(x) {
       var text = x[0];
       var fn = this[x[1] + "Window"].bind(this);
       var e = new Element("a");
+      e.addEvent("mousedown", function(e) { new Event(e).stop(); });
       e.addEvent("click", function() {
         dropdownMenu.hide();
         fn();
@@ -76,61 +94,90 @@ qwebirc.ui.QUI = new Class({
       dropdownMenu.appendChild(e);
     }.bind(this));
     
-    var dropdown = new Element("img");
+    var dropdown = new Element("div");
     dropdown.addClass("dropdown-tab");
-    dropdown.setStyle("display", "inline-block");
-    dropdown.set("html", "<img src=images/favicon.png>");
-    this.tabs.appendChild(dropdown);
+    dropdown.appendChild(new Element("img", {src: qwebirc.global.staticBaseURL + "images/icon.png", title: "menu", alt: "menu"}));
+    dropdown.setStyle("opacity", 1);
 
-    dropdownMenu.show = function(x){
+    this.outerTabs.appendChild(dropdown);
+    dropdownMenu.show = function(x) {
       new Event(x).stop();
-      
+
       if(dropdownMenu.visible) {
         dropdownMenu.hide();
         return;
       }
-      this.parentElement.appendChild(surface);
-/*
-      var left = x.client.x;
-      var top = x.client.y;
-      */
-      /* -1 == border */
-      top = this.tabs.getSize().y - 1;
-        
-      dropdownMenu.setStyle("left", left);
-      dropdownMenu.setStyle("top", top);
+      var parentSize = this.outerTabs.parentNode.getSize().y;
+
+      dropdownMenu.setStyle("left", parentSize.x);
+      dropdownMenu.setStyle("top", top-1); /* -1 == top border */
       dropdownMenu.setStyle("display", "inline-block");
       dropdownMenu.visible = true;
+      
+      document.addEvent("mousedown", hideEvent);
     }.bind(this);
+    dropdown.addEvent("mousedown", function(e) { new Event(e).stop(); });
     dropdown.addEvent("click", dropdownMenu.show);
-    
-    var dropdownhint = new Element("div");
-    dropdownhint.addClass("dropdownhint");
-    dropdownhint.set("text", "click the icon for the main menu");
-    var hider = function() {
-      this.parentElement.removeChild(dropdownhint);
-    }.delay(3000, this);
-    this.parentElement.appendChild(dropdownhint);
   },
   createInput: function() {
     var form = new Element("form");
     this.input.appendChild(form);
+    
     form.addClass("input");
     
     var inputbox = new Element("input");
+    this.addEvent("signedOn", function() {
+      inputbox.placeholder = "chat here! you can also use commands, like /JOIN or /HELP";
+      var d = function() { inputbox.addClass("input-flash"); }.delay(250);
+      var d = function() { inputbox.removeClass("input-flash"); }.delay(500);
+      var d = function() { inputbox.addClass("input-flash"); }.delay(750);
+      var d = function() { inputbox.removeClass("input-flash"); }.delay(1000);
+      var d = function() { inputbox.addClass("input-flash"); }.delay(1250);
+      var d = function() { inputbox.removeClass("input-flash"); }.delay(1750);
+    });
     form.appendChild(inputbox);
     this.inputbox = inputbox;
-    
-    form.addEvent("submit", function(e) {
-      new Event(e).stop();
-    
+    this.inputbox.maxLength = 470;
+
+    var sendInput = function() {
       if(inputbox.value == "")
         return;
         
       this.resetTabComplete();
       this.getActiveWindow().historyExec(inputbox.value);
       inputbox.value = "";
-    }.bind(this));
+      inputbox.placeholder = "";
+    }.bind(this);
+
+    if(!qwebirc.util.deviceHasKeyboard()) {
+      inputbox.addClass("mobile-input");
+      var inputButton = new Element("input", {type: "button"});
+      inputButton.addClass("mobile-button");
+      inputButton.addEvent("click", function() {
+        sendInput();
+        inputbox.focus();
+      });
+      inputButton.value = ">";
+      this.input.appendChild(inputButton);
+      var reflowButton = function() {
+        var containerSize = this.input.getSize();
+        var buttonSize = inputButton.getSize();
+        
+        var buttonLeft = containerSize.x - buttonSize.x - 5; /* lovely 5 */
+
+        inputButton.setStyle("left", buttonLeft);
+        inputbox.setStyle("width", buttonLeft - 5);
+        inputButton.setStyle("height", containerSize.y);
+      }.bind(this);
+      this.qjsui.addEvent("reflow", reflowButton);
+    } else {
+      inputbox.addClass("keyboard-input");
+    }
+    
+    form.addEvent("submit", function(e) {
+      new Event(e).stop();
+      sendInput();
+    });
     
     inputbox.addEvent("focus", this.resetTabComplete.bind(this));
     inputbox.addEvent("mousedown", this.resetTabComplete.bind(this));
@@ -143,7 +190,7 @@ qwebirc.ui.QUI = new Class({
         resultfn = this.commandhistory.upLine;
       } else if(e.key == "down") {
         resultfn = this.commandhistory.downLine;
-      } else if(e.key == "tab") {
+      } else if(e.key == "tab" && !e.altKey && !e.ctrlKey && !e.shiftKey) {
         new Event(e).stop();
         this.tabComplete(inputbox);
         return;
@@ -182,6 +229,31 @@ qwebirc.ui.QUI = new Class({
 
     this.topic.parentNode.replaceChild(topic, this.topic);
     this.qjsui.topic = this.topic = topic;
+  },
+  setSideTabs: function(value) {
+    if(value === this.sideTabs)
+      return;
+
+    if(this.sideTabs === true) {
+      this.qjsui.left.removeChild(this.outerTabs);
+    } else if(this.sideTabs === false) {
+      this.qjsui.top.removeChild(this.outerTabs);
+    }
+    if(value) {
+      this.qjsui.left.appendChild(this.outerTabs);
+      this.qjsui.top.style.display = "none";
+      this.qjsui.left.style.display = "";
+    } else {
+      this.qjsui.top.appendChild(this.outerTabs);
+      this.qjsui.top.style.display = "";
+      this.qjsui.left.style.display = "none";
+    }
+    this.sideTabs = value;
+    this.windows.each(function(k, v) {
+      v.each(function(k, v2) {
+        v2.setSideTabs(value);
+      });
+    });
   }
 });
 
@@ -190,7 +262,7 @@ qwebirc.ui.QUI.JSUI = new Class({
   initialize: function(class_, parent, sizer) {
     this.parent = parent;
     this.sizer = $defined(sizer)?sizer:parent;
-    
+
     this.class_ = class_;
     this.create();
     
@@ -203,20 +275,7 @@ qwebirc.ui.QUI.JSUI = new Class({
   applyClasses: function(pos, l) {
     l.addClass("dynamicpanel");    
     l.addClass(this.class_);
-
-    if(pos == "middle") {
-      l.addClass("leftboundpanel");
-    } else if(pos == "top") {
-      l.addClass("topboundpanel");
-      l.addClass("widepanel");
-    } else if(pos == "topic") {
-      l.addClass("widepanel");
-    } else if(pos == "right") {
-      l.addClass("rightboundpanel");
-    } else if(pos == "bottom") {
-      l.addClass("bottomboundpanel");
-      l.addClass("widepanel");
-    }
+    l.addClass(pos + "boundpanel");
   },
   create: function() {
     var XE = function(pos) {
@@ -228,6 +287,7 @@ qwebirc.ui.QUI.JSUI = new Class({
     }.bind(this);
     
     this.top = XE("top");
+    this.left = XE("left");
     this.topic = XE("topic");
     this.middle = XE("middle");
     this.right = XE("right");
@@ -248,41 +308,59 @@ qwebirc.ui.QUI.JSUI = new Class({
     var right = this.right;
     var topic = this.topic;
     var top = this.top;
-    
+    var left = this.left;
+
+    /* |----------------------------------------------|
+     * | top                                          |
+     * |----------------------------------------------|
+     * | left | topic                         | right |
+     * |      |-------------------------------|       |
+     * |      | middle                        |       |
+     * |      |                               |       |
+     * |      |                               |       |
+     * |      |---------------------------------------|
+     * |      | bottom                                |
+     * |----------------------------------------------|
+     */
+
     var topicsize = topic.getSize();
     var topsize = top.getSize();
     var rightsize = right.getSize();
     var bottomsize = bottom.getSize();
+    var leftsize = left.getSize();
     var docsize = this.sizer.getSize();
     
     var mheight = (docsize.y - topsize.y - bottomsize.y - topicsize.y);
     var mwidth = (docsize.x - rightsize.x);
 
-    topic.setStyle("top", topsize.y + "px");
+    left.setStyle("top", topsize.y);
+    topic.setStyle("top", topsize.y);
+    topic.setStyle("left", leftsize.x);
     
-    middle.setStyle("top", (topsize.y + topicsize.y) + "px");
+    middle.setStyle("top", (topsize.y + topicsize.y));
+    middle.setStyle("left", leftsize.x);
     if(mheight > 0) {
-      middle.setStyle("height", mheight + "px");
-      right.setStyle("height", mheight + "px");
+      middle.setStyle("height", mheight);
+      right.setStyle("height", mheight);
     }
     
     if(mwidth > 0)
-      middle.setStyle("width", mwidth + "px");
-    right.setStyle("top", (topsize.y + topicsize.y) + "px");
-    right.setStyle("left", mwidth + "px");
-    
-    bottom.setStyle("top", (docsize.y - bottomsize.y) + "px");
+      middle.setStyle("width", mwidth);
+    right.setStyle("top", (topsize.y + topicsize.y));
+
+    bottom.setStyle("left",  leftsize.x);
     this.fireEvent("reflow");
   },
-  showChannel: function(state) {
+  showChannel: function(state, nicklistVisible) {
     var display = "none";
     if(state)
       display = "block";
 
-    this.right.setStyle("display", display);
+    this.right.setStyle("display", nicklistVisible ? display : "none");
     this.topic.setStyle("display", display);
   },
   showInput: function(state) {
+    this.bottom.isVisible = state;
     this.bottom.setStyle("display", state?"block":"none");
   }
 });
@@ -296,51 +374,57 @@ qwebirc.ui.QUI.Window = new Class({
     this.tab = new Element("a", {"href": "#"});
     this.tab.addClass("tab");
     this.tab.addEvent("focus", function() { this.blur() }.bind(this.tab));;
-    
+
+    this.spaceNode = document.createTextNode(" ");
     parentObject.tabs.appendChild(this.tab);
-    
-    this.tab.appendText(name);
-    this.tab.addEvent("click", function(e) {
-      new Event(e).stop();
-      
-      if(this.closed)
-        return;
-        
-      parentObject.selectWindow(this);
-    }.bind(this));
-    
+    parentObject.tabs.appendChild(this.spaceNode);
+
     if(type != qwebirc.ui.WINDOW_STATUS && type != qwebirc.ui.WINDOW_CONNECT) {
       var tabclose = new Element("span");
+      this.tabclose = tabclose;
       tabclose.set("text", "X");
       tabclose.addClass("tabclose");
       var close = function(e) {
         new Event(e).stop();
-        
+
         if(this.closed)
           return;
-          
+
         if(type == qwebirc.ui.WINDOW_CHANNEL)
           this.client.exec("/PART " + name);
 
         this.close();
-        
-        parentObject.inputbox.focus();
+
+        //parentObject.inputbox.focus();
       }.bind(this);
-      
+
       tabclose.addEvent("click", close);
       this.tab.addEvent("mouseup", function(e) {
         var button = 1;
-        
+
         if(Browser.Engine.trident)
           button = 4;
 
         if(e.event.button == button)
           close(e);
       }.bind(this));
-      
+
       this.tab.appendChild(tabclose);
+    } else {
+      this.tabclose = null;
     }
 
+    this.tab.appendText(name);
+    this.tab.addEvent("click", function(e) {
+      new Event(e).stop();
+      
+      if(this.closed)
+        return;
+        
+      parentObject.selectWindow(this);
+    }.bind(this));
+    
+
     this.lines = new Element("div");
     this.parentObject.qjsui.applyClasses("middle", this.lines);
     this.lines.addClass("lines");
@@ -354,9 +438,11 @@ qwebirc.ui.QUI.Window = new Class({
     
     if(type == qwebirc.ui.WINDOW_CHANNEL) {
       this.topic = new Element("div");
+      this.parentObject.qjsui.applyClasses("topic", this.topic);
       this.topic.addClass("topic");
       this.topic.addClass("tab-invisible");
       this.topic.set("html", "&nbsp;");
+      this.topic.addEvent("dblclick", this.editTopic.bind(this));
       this.parentObject.qjsui.applyClasses("topic", this.topic);
       
       this.prevNick = null;
@@ -364,14 +450,31 @@ qwebirc.ui.QUI.Window = new Class({
       this.nicklist.addClass("nicklist");
       this.nicklist.addClass("tab-invisible");
       this.nicklist.addEvent("click", this.removePrevMenu.bind(this));
-      this.parentObject.qjsui.applyClasses("nicklist", this.nicklist);
+      this.parentObject.qjsui.applyClasses("right", this.nicklist);
     }
     
-    if(type == qwebirc.ui.WINDOW_CHANNEL) {
+    if(type == qwebirc.ui.WINDOW_CHANNEL)
       this.updateTopic("");
-    } else {
-      this.reflow();
+
+    this.nicksColoured = this.parentObject.uiOptions.NICK_COLOURS;
+    this.reflow();
+  },
+  rename: function(name) {
+    this.tab.replaceChild(document.createTextNode(name), this.tab.firstChild);
+  },
+  editTopic: function() {
+    if(!this.client.nickOnChanHasPrefix(this.client.nickname, this.name, "@")) {
+/*      var cmodes = this.client.getChannelModes(channel);
+      if(cmodes.indexOf("t")) {*/
+        alert("Sorry, you need to be a channel operator to change the topic!");
+        return;
+      /*}*/
     }
+    var newTopic = prompt("Change topic of " + this.name + " to:", this.topic.topicText);
+    if(newTopic === null)
+      return;
+
+    this.client.exec("/TOPIC " + newTopic);
   },
   reflow: function() {
     this.parentObject.reflow();
@@ -396,15 +499,19 @@ qwebirc.ui.QUI.Window = new Class({
     parent.appendChild(e);
     e.addClass("menu");
     
+    var nickArray = [nick];
     qwebirc.ui.MENU_ITEMS.forEach(function(x) {
+      if(!x.predicate || x.predicate !== true && !x.predicate.apply(this, nickArray))
+        return;
+      
       var e2 = new Element("a");
       e.appendChild(e2);
-      
+
       e2.href = "#";
-      e2.set("text", "- " + x[0]);
-      
+      e2.set("text", "- " + x.text);
+
       e2.addEvent("focus", function() { this.blur() }.bind(e2));
-      e2.addEvent("click", function(ev) { new Event(ev.stop()); this.menuClick(x[1]); }.bind(this));
+      e2.addEvent("click", function(ev) { new Event(ev.stop()); this.menuClick(x.fn); }.bind(this));
     }.bind(this));
     return e;
   },
@@ -436,13 +543,22 @@ qwebirc.ui.QUI.Window = new Class({
     this.prevNick = null;
   },
   nickListAdd: function(nick, position) {
+    var realNick = this.client.stripPrefix(nick);
+    
     var e = new Element("a");
     qwebirc.ui.insertAt(position, this.nicklist, e);
     
     e.href = "#";
-    e.appendChild(document.createTextNode(nick));
+    var span = new Element("span");
+    if(this.parentObject.uiOptions.NICK_COLOURS) {
+      var colour = realNick.toHSBColour(this.client);
+      if($defined(colour))
+        span.setStyle("color", colour.rgbToHex());
+    }
+    span.set("text", nick);
+    e.appendChild(span);
     
-    e.realNick = this.client.stripPrefix(nick);
+    e.realNick = realNick;
     
     e.addEvent("click", function(x) {
       if(this.prevNick == e) {
@@ -454,13 +570,9 @@ qwebirc.ui.QUI.Window = new Class({
       this.prevNick = e;
       e.addClass("selected");
       this.moveMenuClass();
-      e.menu = this.createMenu(x.realNick, e);
+      e.menu = this.createMenu(e.realNick, e);
       new Event(x).stop();
     }.bind(this));
-    e.addEvent("dblclick", function(x) {
-      new Event(x).stop();
-      this.client.exec("/QUERY " + e.realNick);
-    }.bind(this));
     
     e.addEvent("focus", function() { this.blur() }.bind(e));
     this.moveMenuClass();
@@ -477,8 +589,10 @@ qwebirc.ui.QUI.Window = new Class({
       t.removeChild(t.firstChild);
 
     if(topic) {
+      t.topicText = topic;
       this.parent(topic, t);
     } else {
+      t.topicText = topic;
       var e = new Element("div");
       e.set("text", "(no topic set)");
       e.addClass("emptytopic");
@@ -495,7 +609,7 @@ qwebirc.ui.QUI.Window = new Class({
     this.parentObject.setLines(this.lines);
     this.parentObject.setChannelItems(this.nicklist, this.topic);
     this.parentObject.qjsui.showInput(inputVisible);
-    this.parentObject.qjsui.showChannel($defined(this.nicklist));
+    this.parentObject.qjsui.showChannel($defined(this.nicklist), this.parentObject.uiOptions.SHOW_NICKLIST);
 
     this.reflow();
     
@@ -503,6 +617,25 @@ qwebirc.ui.QUI.Window = new Class({
     
     if(inputVisible)
       this.parentObject.inputbox.focus();
+
+    if(this.type == qwebirc.ui.WINDOW_CHANNEL && this.nicksColoured != this.parentObject.uiOptions.NICK_COLOURS) {
+      this.nicksColoured = this.parentObject.uiOptions.NICK_COLOURS;
+      
+      var nodes = this.nicklist.childNodes;
+      if(this.parentObject.uiOptions.NICK_COLOURS) {
+        for(var i=0;i<nodes.length;i++) {
+          var e = nodes[i], span = e.firstChild;
+          var colour = e.realNick.toHSBColour(this.client);
+          if($defined(colour))
+            span.setStyle("color", colour.rgbToHex());
+        };
+      } else {
+        for(var i=0;i<nodes.length;i++) {
+          var span = nodes[i].firstChild;
+          span.setStyle("color", null);
+        };
+      }
+    }
   },
   deselect: function() {
     this.parent();
@@ -514,6 +647,8 @@ qwebirc.ui.QUI.Window = new Class({
     this.parent();
     
     this.parentObject.tabs.removeChild(this.tab);
+    this.parentObject.tabs.removeChild(this.spaceNode);
+    this.reflow();
   },
   addLine: function(type, line, colourClass) {
     var e = new Element("div");
@@ -530,7 +665,7 @@ qwebirc.ui.QUI.Window = new Class({
     this.parent(type, line, colourClass, e);
   },
   setHilighted: function(state) {
-    laststate = this.hilighted;
+    var laststate = this.hilighted;
     
     this.parent(state);
 
@@ -552,5 +687,15 @@ qwebirc.ui.QUI.Window = new Class({
         this.tab.addClass("tab-hilight-activity");
         break;
     }
+  },
+  setSideTabs: function(value) {
+    if(this.tabclose === null)
+      return;
+    this.tab.removeChild(this.tabclose);
+    if(value) {
+      this.tab.insertBefore(this.tabclose, this.tab.firstChild);
+    } else {
+      this.tab.appendChild(this.tabclose);
+    }
   }
 });