Lots of scrolling
authorDarren <darren@darrenwhitlen.com>
Wed, 18 Jul 2012 21:33:45 +0000 (22:33 +0100)
committerDarren <darren@darrenwhitlen.com>
Wed, 18 Jul 2012 21:33:46 +0000 (22:33 +0100)
client_backbone/index.html
client_backbone/style.css
client_backbone/view.js

index 739872cbd6ec9444dfc5ad909f078905d0170dfa..443fc50b78a49f2a55aa87d46a483fddeab43365 100644 (file)
@@ -18,7 +18,7 @@
         </div>
 
         <div id="panels">
-            <div class="container1"></div>
+            <div class="panel_container container1"></div>
         </div>
 
         <div id="memberlists"></div>
index 3e4ab266e94e39a1ef851518e7c24f94f84eb98e..51a509e41f7c8574726560d501025e7fee0a47f5 100644 (file)
@@ -16,7 +16,7 @@ body {
  * Main layout blocks
  */
 #toolbar { position:absolute; top:0px; width:100%; background-color:#1B1B1B; font-size:0.9em; }
-#panels { position:absolute; left:0px; right:200px; bottom:100px; top:100px; overflow-y:scroll; }
+#panels { position:absolute; left:0px; right:200px; bottom:100px; top:100px; }
 #memberlists { position:absolute; right:0px; width:200px; bottom:100px; top:100px; }
 #controlbox { position: absolute; bottom:0px; width:100%; background-color:#1B1B1B; }
 
@@ -72,10 +72,12 @@ body {
 
 
 
+.panel_container { overflow-y:scroll; height:100%; }
+
+
 
 .messages {
     overflow-x:wrap;
-    overflow-y:scroll;
     border:none; display: none;
     height: 100%;
 }
index 695f22ab8c2e2ab93a8a54a65e5f0aaaaf2f646b..ec70c2f1b9484a51189c55b361db9bccce4c369d 100644 (file)
-/*jslint white:true, regexp: true, nomen: true, devel: true, undef: true, browser: true, continue: true, sloppy: true, forin: true, newcap: true, plusplus: true, maxerr: 50, indent: 4 */
-/*global kiwi */
-
-kiwi.view = {};
-
-kiwi.view.MemberList = Backbone.View.extend({
-    tagName: "ul",
-    events: {
-        "click .nick": "nickClick"
-    },
-    initialize: function (options) {
-        this.model.bind('all', this.render, this);
-        $(this.el).appendTo('#memberlists');
-    },
-    render: function () {
-        var $this = $(this.el);
-        $this.empty();
-        this.model.forEach(function (member) {
-            $('<li><a class="nick"><span class="prefix">' + member.get("prefix") + '</span>' + member.get("nick") + '</a></li>').appendTo($this).data('member', member);
-        });
-    },
-    nickClick: function (x) {
-        console.log(x);
-    },
-    show: function () {
-        $('#memberlists').children().removeClass('active');
-        $(this.el).addClass('active');
-    }
-});
-
-kiwi.view.Panel = Backbone.View.extend({
-    tagName: "div",
-    className: "messages",
-    events: {
-        "click .chan": "chanClick"
-    },
-    initialize: function (options) {
-        this.initializePanel(options);
-    },
-
-    initializePanel: function (options) {
-        this.$el.css('display', 'none');
-
-        this.$container = $('#panels .container1');
-        this.$el.appendTo(this.$container);
-
-        this.model.bind('msg', this.newMsg, this);
-        this.msg_count = 0;
-
-        this.model.set({"view": this}, {"silent": true});
-    },
-
-    render: function () {
-        var $this = $(this.el);
-        $this.empty();
-        this.model.get("backscroll").forEach(this.newMsg);
-    },
-    newMsg: function (msg) {
-        // TODO: make sure that the message pane is scrolled to the bottom (Or do we? ~Darren)
-        var re, line_msg, $this = this.$el;
-
-        // Make the channels clickable
-        // TODO: HTML parsing may be going into the model.. move this?
-        re = new RegExp('\\B(' + kiwi.gateway.channel_prefix + '[^ ,.\\007]+)', 'g');
-        msg.msg = msg.msg.replace(re, function (match) {
-            return '<a class="chan">' + match + '</a>';
-        });
-
-        // Build up and add the line
-        line_msg = '<div class="msg <%= type %>"><div class="time"><%- time %></div><div class="nick"><%- nick %></div><div class="text" style="<%= style %>"><%= msg %> </div></div>';
-        $this.append(_.template(line_msg, msg));
-
-        // Scroll to the bottom of the channel
-        // TODO: Don't scroll down if we're scrolled up the channel a little
-        $this[0].scrollTop = $this[0].scrollHeight;
-
-        // Make sure our DOM isn't getting too large (Acts as scrollback)
-        this.msg_count++;
-        if (this.msg_count > 250) {
-            $('.msg:first', this.div).remove();
-            this.msg_count--;
-        }
-    },
-    chanClick: function (x) {
-        console.log(x);
-    },
-    show: function () {
-        var $this = this.$el;
-
-        // Hide all other panels and show this one
-        this.$container.children().css('display', 'none');
-        $this.css('display', 'block');
-
-        // Show this panels memberlist
-        var members = this.model.get("members");
-        if (members) {
-            members.view.show();
-        } else {
-            // Memberlist not found for this panel, hide any active ones
-            $('#memberlists').children().removeClass('active');
-        }
-
-        // TODO: Why is kiwi.app not defined when this is fist called :/
-        if (kiwi.app) {
-            kiwi.app.setCurrentTopic(this.model.get("topic") || "");
-        }
-
-        kiwi.current_panel = this.model;
-
-        this.trigger('active', this.model);
-    }
-});
-
-kiwi.view.Channel = kiwi.view.Panel.extend({
-    initialize: function (options) {
-        this.initializePanel(options);
-        this.model.bind('change:topic', this.topic, this);
-    },
-
-    topic: function (topic) {
-        if (typeof topic !== 'string' || !topic) {
-            topic = this.model.get("topic");
-        }
-        
-        this.model.addMsg('', '=== Topic for ' + this.model.get('name') + ' is: ' + topic, 'topic');
-
-        // If this is the active channel then update the topic bar
-        if (kiwi.current_panel === this) {
-            kiwi.app.setCurrentTopic(this.model.get("topic"));
-        }
-    }
-});
-
-// Model for this = kiwi.model.PanelList
-kiwi.view.Tabs = Backbone.View.extend({
-    events: {
-        "click li": "tabClick",
-        'click li img': 'partClick'
-    },
-
-    initialize: function () {
-        this.model.on("add", this.panelAdded, this);
-        this.model.on("remove", this.panelRemoved, this);
-        this.model.on("reset", this.render, this);
-    },
-    render: function () {
-        var that = this;
-        $this = $(this.el);
-        $this.empty();
-        
-        // Add the server tab first
-        $('<li><span>' + kiwi.gateway.get('name') + '</span></li>')
-            .data('panel_id', this.model.server.cid)
-            .appendTo($this);
-
-        this.model.forEach(function (panel) {
-            // If this is the server panel, ignore as it's already added
-            if (panel == that.model.server) return;
-
-            $('<li><span>' + panel.get("name") + '</span></li>')
-                .data('panel_id', panel.cid)
-                .appendTo($this);
-        });
-    },
-
-    panelAdded: function (panel) {
-        // Add a tab to the panel
-        panel.tab = $('<li><span>' + panel.get("name") + '</span></li>');
-        panel.tab.data('panel_id', panel.cid)
-            .appendTo(this.$el);
-
-        panel.view.on('active', this.panelActive, this);
-    },
-    panelRemoved: function (panel) {
-        panel.tab.remove();
-        delete panel.tab;
-    },
-
-    panelActive: function (panel) {
-        // Remove any existing tabs or part images
-        $('img', this.$el).remove();
-        this.$el.children().removeClass('active');
-
-        panel.tab.addClass('active');
-        panel.tab.append('<img src="img/redcross.png" />');
-    },
-
-    tabClick: function (e) {
-        var panel = this.model.getByCid($(e.currentTarget).data('panel_id'));
-        if (!panel) {
-            // A panel wasn't found for this tab... wadda fuck
-            return;
-        }
-
-        panel.view.show();
-    },
-
-    partClick: function (e) {
-        var panel = this.model.getByCid($(e.currentTarget).parent().data('panel_id'));
-        kiwi.gateway.part(panel.get('name'));
-    }
-});
-
-
-
-kiwi.view.ControlBox = Backbone.View.extend({
-    that: this,
-
-    buffer: [],  // Stores previously run commands
-    buffer_pos: 0,  // The current position in the buffer
-
-    events: {
-        'keydown input': 'process'
-    },
-
-    initialize: function () {
-        that = this;
-
-        kiwi.gateway.bind('change:nick', function () {
-            $('.nick', that.$el).text(this.get('nick'));
-        });
-    },
-
-    process: function (ev) {
-        var inp = $(ev.currentTarget);
-
-        switch (true) {
-            case (ev.keyCode === 13):              // return
-                this.processInput(inp.val());
-
-                this.buffer.push(inp.val());
-                this.buffer_pos = this.buffer.length;
-
-                inp.val('');
-
-                break;
-
-            case (ev.keyCode === 38):              // up
-                if (this.buffer_pos > 0) {
-                    this.buffer_pos--;
-                    inp.val(this.buffer[this.buffer_pos]);
-                }
-                break;
-
-            case (ev.keyCode === 40):              // down
-                if (this.buffer_pos < this.buffer.length) {
-                    this.buffer_pos++;
-                    inp.val(this.buffer[this.buffer_pos]);
-                }
-        }
-    },
-
-
-    processInput: function (command_raw) {
-        var command,
-            params = command_raw.split(' ');
-        
-        // Extract the command and parameters
-        if (params[0][0] === '/') {
-            command = params[0].substr(1).toLowerCase();
-            params = params.splice(1);
-        } else {
-            command = 'msg';
-        }
-
-        // Trigger the command events
-        this.trigger('command', {command: command, params: params});
-        this.trigger('command_' + command, {command: command, params: params});
-
-        // If we didn't have any listeners for this event, fire a special case
-        // TODO: This feels dirty. Should this really be done..?
-        if (!this._callbacks['command' + command]) {
-            this.trigger('unknown_command', {command: command, params: params});
-        }
-    }
-});
-
-
-
-
-
-// This *may* be needed in future
-kiwi.view.Application = Backbone.View.extend({
-    initialize: function () {
-        $(window).resize(this.doLayout);
-        $('#toolbar').resize(this.doLayout);
-        $('#controlbox').resize(this.doLayout);
-
-        this.doLayout();
-
-        $(window).keydown(this.setKeyFocus);
-    },
-
-
-    // Globally shift focus to the command input box on a keypress
-    setKeyFocus: function (ev) {
-        // If we're copying text, don't shift focus
-        if (ev.ctrlKey || ev.altKey) {
-            return;
-        }
-
-        // If we're typing into an input box somewhere, ignore
-        if (ev.srcElement.tagName.toLowerCase() === 'input') {
-            return;
-        }
-
-        $('#controlbox .inp').focus();
-    },
-
-
-    doLayout: function () {
-        var el_panels = $('#panels');
-        var el_memberlists = $('#memberlists');
-        var el_toolbar = $('#toolbar');
-        var el_controlbox = $('#controlbox');
-
-        var css_heights = {
-            top: el_toolbar.outerHeight(true),
-            bottom: el_controlbox.outerHeight(true)
-        };
-
-        el_panels.css(css_heights);
-        el_memberlists.css(css_heights);
-    }
+/*jslint white:true, regexp: true, nomen: true, devel: true, undef: true, browser: true, continue: true, sloppy: true, forin: true, newcap: true, plusplus: true, maxerr: 50, indent: 4 */\r
+/*global kiwi */\r
+\r
+kiwi.view = {};\r
+\r
+kiwi.view.MemberList = Backbone.View.extend({\r
+    tagName: "ul",\r
+    events: {\r
+        "click .nick": "nickClick"\r
+    },\r
+    initialize: function (options) {\r
+        this.model.bind('all', this.render, this);\r
+        $(this.el).appendTo('#memberlists');\r
+    },\r
+    render: function () {\r
+        var $this = $(this.el);\r
+        $this.empty();\r
+        this.model.forEach(function (member) {\r
+            $('<li><a class="nick"><span class="prefix">' + member.get("prefix") + '</span>' + member.get("nick") + '</a></li>').appendTo($this).data('member', member);\r
+        });\r
+    },\r
+    nickClick: function (x) {\r
+        console.log(x);\r
+    },\r
+    show: function () {\r
+        $('#memberlists').children().removeClass('active');\r
+        $(this.el).addClass('active');\r
+    }\r
+});\r
+\r
+kiwi.view.Panel = Backbone.View.extend({\r
+    tagName: "div",\r
+    className: "messages",\r
+    events: {\r
+        "click .chan": "chanClick"\r
+    },\r
+\r
+    // The container this panel is within\r
+    $container: null,\r
+\r
+    initialize: function (options) {\r
+        this.initializePanel(options);\r
+    },\r
+\r
+    initializePanel: function (options) {\r
+        this.$el.css('display', 'none');\r
+\r
+        if (options.container) {\r
+            this.$container = $(options.container);\r
+        } else {\r
+            this.$container = $('#panels .container1');\r
+        }\r
+\r
+        this.$el.appendTo(this.$container);\r
+\r
+        this.model.bind('msg', this.newMsg, this);\r
+        this.msg_count = 0;\r
+\r
+        this.model.set({"view": this}, {"silent": true});\r
+    },\r
+\r
+    render: function () {\r
+        this.$el.empty();\r
+        this.model.get("backscroll").forEach(this.newMsg);\r
+    },\r
+    newMsg: function (msg) {\r
+        // TODO: make sure that the message pane is scrolled to the bottom (Or do we? ~Darren)\r
+        var re, line_msg, $this = this.$el;\r
+\r
+        // Make the channels clickable\r
+        // TODO: HTML parsing may be going into the model.. move this?\r
+        re = new RegExp('\\B(' + kiwi.gateway.channel_prefix + '[^ ,.\\007]+)', 'g');\r
+        msg.msg = msg.msg.replace(re, function (match) {\r
+            return '<a class="chan">' + match + '</a>';\r
+        });\r
+\r
+        // Build up and add the line\r
+        line_msg = '<div class="msg <%= type %>"><div class="time"><%- time %></div><div class="nick"><%- nick %></div><div class="text" style="<%= style %>"><%= msg %> </div></div>';\r
+        $this.append(_.template(line_msg, msg));\r
+\r
+        this.scrollToBottom();\r
+\r
+        // Make sure our DOM isn't getting too large (Acts as scrollback)\r
+        this.msg_count++;\r
+        if (this.msg_count > 250) {\r
+            $('.msg:first', this.div).remove();\r
+            this.msg_count--;\r
+        }\r
+    },\r
+    chanClick: function (x) {\r
+        console.log(x);\r
+    },\r
+    show: function () {\r
+        var $this = this.$el;\r
+\r
+        // Hide all other panels and show this one\r
+        this.$container.children().css('display', 'none');\r
+        $this.css('display', 'block');\r
+\r
+        // Show this panels memberlist\r
+        var members = this.model.get("members");\r
+        if (members) {\r
+            members.view.show();\r
+        } else {\r
+            // Memberlist not found for this panel, hide any active ones\r
+            $('#memberlists').children().removeClass('active');\r
+        }\r
+\r
+        // TODO: Why is kiwi.app not defined when this is fist called :/\r
+        if (kiwi.app) {\r
+            kiwi.app.setCurrentTopic(this.model.get("topic") || "");\r
+        }\r
+\r
+        this.scrollToBottom();\r
+\r
+        kiwi.current_panel = this.model;\r
+\r
+        this.trigger('active', this.model);\r
+    },\r
+\r
+\r
+    // Scroll to the bottom of the panel\r
+    scrollToBottom: function () {\r
+        // TODO: Don't scroll down if we're scrolled up the panel a little\r
+        this.$container[0].scrollTop = this.$container[0].scrollHeight;\r
+    }\r
+});\r
+\r
+kiwi.view.Channel = kiwi.view.Panel.extend({\r
+    initialize: function (options) {\r
+        this.initializePanel(options);\r
+        this.model.bind('change:topic', this.topic, this);\r
+    },\r
+\r
+    topic: function (topic) {\r
+        if (typeof topic !== 'string' || !topic) {\r
+            topic = this.model.get("topic");\r
+        }\r
+        \r
+        this.model.addMsg('', '=== Topic for ' + this.model.get('name') + ' is: ' + topic, 'topic');\r
+\r
+        // If this is the active channel then update the topic bar\r
+        if (kiwi.current_panel === this) {\r
+            kiwi.app.setCurrentTopic(this.model.get("topic"));\r
+        }\r
+    }\r
+});\r
+\r
+// Model for this = kiwi.model.PanelList\r
+kiwi.view.Tabs = Backbone.View.extend({\r
+    events: {\r
+        "click li": "tabClick",\r
+        'click li img': 'partClick'\r
+    },\r
+\r
+    initialize: function () {\r
+        this.model.on("add", this.panelAdded, this);\r
+        this.model.on("remove", this.panelRemoved, this);\r
+        this.model.on("reset", this.render, this);\r
+    },\r
+    render: function () {\r
+        var that = this;\r
+        $this = $(this.el);\r
+        $this.empty();\r
+        \r
+        // Add the server tab first\r
+        $('<li><span>' + kiwi.gateway.get('name') + '</span></li>')\r
+            .data('panel_id', this.model.server.cid)\r
+            .appendTo($this);\r
+\r
+        this.model.forEach(function (panel) {\r
+            // If this is the server panel, ignore as it's already added\r
+            if (panel == that.model.server) return;\r
+\r
+            $('<li><span>' + panel.get("name") + '</span></li>')\r
+                .data('panel_id', panel.cid)\r
+                .appendTo($this);\r
+        });\r
+    },\r
+\r
+    panelAdded: function (panel) {\r
+        // Add a tab to the panel\r
+        panel.tab = $('<li><span>' + panel.get("name") + '</span></li>');\r
+        panel.tab.data('panel_id', panel.cid)\r
+            .appendTo(this.$el);\r
+\r
+        panel.view.on('active', this.panelActive, this);\r
+    },\r
+    panelRemoved: function (panel) {\r
+        panel.tab.remove();\r
+        delete panel.tab;\r
+    },\r
+\r
+    panelActive: function (panel) {\r
+        // Remove any existing tabs or part images\r
+        $('img', this.$el).remove();\r
+        this.$el.children().removeClass('active');\r
+\r
+        panel.tab.addClass('active');\r
+        panel.tab.append('<img src="img/redcross.png" />');\r
+    },\r
+\r
+    tabClick: function (e) {\r
+        var panel = this.model.getByCid($(e.currentTarget).data('panel_id'));\r
+        if (!panel) {\r
+            // A panel wasn't found for this tab... wadda fuck\r
+            return;\r
+        }\r
+\r
+        panel.view.show();\r
+    },\r
+\r
+    partClick: function (e) {\r
+        var panel = this.model.getByCid($(e.currentTarget).parent().data('panel_id'));\r
+        kiwi.gateway.part(panel.get('name'));\r
+    }\r
+});\r
+\r
+\r
+\r
+kiwi.view.ControlBox = Backbone.View.extend({\r
+    that: this,\r
+\r
+    buffer: [],  // Stores previously run commands\r
+    buffer_pos: 0,  // The current position in the buffer\r
+\r
+    events: {\r
+        'keydown input': 'process'\r
+    },\r
+\r
+    initialize: function () {\r
+        that = this;\r
+\r
+        kiwi.gateway.bind('change:nick', function () {\r
+            $('.nick', that.$el).text(this.get('nick'));\r
+        });\r
+    },\r
+\r
+    process: function (ev) {\r
+        var inp = $(ev.currentTarget);\r
+\r
+        switch (true) {\r
+            case (ev.keyCode === 13):              // return\r
+                this.processInput(inp.val());\r
+\r
+                this.buffer.push(inp.val());\r
+                this.buffer_pos = this.buffer.length;\r
+\r
+                inp.val('');\r
+\r
+                break;\r
+\r
+            case (ev.keyCode === 38):              // up\r
+                if (this.buffer_pos > 0) {\r
+                    this.buffer_pos--;\r
+                    inp.val(this.buffer[this.buffer_pos]);\r
+                }\r
+                break;\r
+\r
+            case (ev.keyCode === 40):              // down\r
+                if (this.buffer_pos < this.buffer.length) {\r
+                    this.buffer_pos++;\r
+                    inp.val(this.buffer[this.buffer_pos]);\r
+                }\r
+        }\r
+    },\r
+\r
+\r
+    processInput: function (command_raw) {\r
+        var command,\r
+            params = command_raw.split(' ');\r
+        \r
+        // Extract the command and parameters\r
+        if (params[0][0] === '/') {\r
+            command = params[0].substr(1).toLowerCase();\r
+            params = params.splice(1);\r
+        } else {\r
+            command = 'msg';\r
+        }\r
+\r
+        // Trigger the command events\r
+        this.trigger('command', {command: command, params: params});\r
+        this.trigger('command_' + command, {command: command, params: params});\r
+\r
+        // If we didn't have any listeners for this event, fire a special case\r
+        // TODO: This feels dirty. Should this really be done..?\r
+        if (!this._callbacks['command' + command]) {\r
+            this.trigger('unknown_command', {command: command, params: params});\r
+        }\r
+    }\r
+});\r
+\r
+\r
+\r
+\r
+\r
+// This *may* be needed in future\r
+kiwi.view.Application = Backbone.View.extend({\r
+    initialize: function () {\r
+        $(window).resize(this.doLayout);\r
+        $('#toolbar').resize(this.doLayout);\r
+        $('#controlbox').resize(this.doLayout);\r
+\r
+        this.doLayout();\r
+\r
+        $(window).keydown(this.setKeyFocus);\r
+    },\r
+\r
+\r
+    // Globally shift focus to the command input box on a keypress\r
+    setKeyFocus: function (ev) {\r
+        // If we're copying text, don't shift focus\r
+        if (ev.ctrlKey || ev.altKey) {\r
+            return;\r
+        }\r
+\r
+        // If we're typing into an input box somewhere, ignore\r
+        if (ev.srcElement.tagName.toLowerCase() === 'input') {\r
+            return;\r
+        }\r
+\r
+        $('#controlbox .inp').focus();\r
+    },\r
+\r
+\r
+    doLayout: function () {\r
+        var el_panels = $('#panels');\r
+        var el_memberlists = $('#memberlists');\r
+        var el_toolbar = $('#toolbar');\r
+        var el_controlbox = $('#controlbox');\r
+\r
+        var css_heights = {\r
+            top: el_toolbar.outerHeight(true),\r
+            bottom: el_controlbox.outerHeight(true)\r
+        };\r
+\r
+        el_panels.css(css_heights);\r
+        el_memberlists.css(css_heights);\r
+    }\r
 });
\ No newline at end of file