Now has backbone.js as a client-side dependency.
Only UI change so far is a duplication of channel tabs, but the foundations are there.
- if (debug)
script(type="text/javascript", src="/js/underscore.min.js")
script(type="text/javascript", src="/js/util.js")
+ script(type="text/javascript", src="/js/backbone-0.5.3-min.js");
script(type="text/javascript", src="/js/gateway.js")
+ script(type="text/javascript", src="/js/model.js")
+ script(type="text/javascript", src="/js/view.js")
script(type="text/javascript", src="/js/front.js")
script(type="text/javascript", src="/js/front.events.js")
script(type="text/javascript", src="/js/front.ui.js")
--- /dev/null
+// Backbone.js 0.5.3
+// (c) 2010 Jeremy Ashkenas, DocumentCloud Inc.
+// Backbone may be freely distributed under the MIT license.
+// For all details and documentation:
+// http://documentcloud.github.com/backbone
+(function(){var h=this,p=h.Backbone,e;e=typeof exports!=="undefined"?exports:h.Backbone={};e.VERSION="0.5.3";var f=h._;if(!f&&typeof require!=="undefined")f=require("underscore")._;var g=h.jQuery||h.Zepto;e.noConflict=function(){h.Backbone=p;return this};e.emulateHTTP=!1;e.emulateJSON=!1;e.Events={bind:function(a,b,c){var d=this._callbacks||(this._callbacks={});(d[a]||(d[a]=[])).push([b,c]);return this},unbind:function(a,b){var c;if(a){if(c=this._callbacks)if(b){c=c[a];if(!c)return this;for(var d=
+0,e=c.length;d<e;d++)if(c[d]&&b===c[d][0]){c[d]=null;break}}else c[a]=[]}else this._callbacks={};return this},trigger:function(a){var b,c,d,e,f=2;if(!(c=this._callbacks))return this;for(;f--;)if(b=f?a:"all",b=c[b])for(var g=0,h=b.length;g<h;g++)(d=b[g])?(e=f?Array.prototype.slice.call(arguments,1):arguments,d[0].apply(d[1]||this,e)):(b.splice(g,1),g--,h--);return this}};e.Model=function(a,b){var c;a||(a={});if(c=this.defaults)f.isFunction(c)&&(c=c.call(this)),a=f.extend({},c,a);this.attributes={};
+this._escapedAttributes={};this.cid=f.uniqueId("c");this.set(a,{silent:!0});this._changed=!1;this._previousAttributes=f.clone(this.attributes);if(b&&b.collection)this.collection=b.collection;this.initialize(a,b)};f.extend(e.Model.prototype,e.Events,{_previousAttributes:null,_changed:!1,idAttribute:"id",initialize:function(){},toJSON:function(){return f.clone(this.attributes)},get:function(a){return this.attributes[a]},escape:function(a){var b;if(b=this._escapedAttributes[a])return b;b=this.attributes[a];
+return this._escapedAttributes[a]=(b==null?"":""+b).replace(/&(?!\w+;|#\d+;|#x[\da-f]+;)/gi,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/")},has:function(a){return this.attributes[a]!=null},set:function(a,b){b||(b={});if(!a)return this;if(a.attributes)a=a.attributes;var c=this.attributes,d=this._escapedAttributes;if(!b.silent&&this.validate&&!this._performValidation(a,b))return!1;if(this.idAttribute in a)this.id=a[this.idAttribute];
+var e=this._changing;this._changing=!0;for(var g in a){var h=a[g];if(!f.isEqual(c[g],h))c[g]=h,delete d[g],this._changed=!0,b.silent||this.trigger("change:"+g,this,h,b)}!e&&!b.silent&&this._changed&&this.change(b);this._changing=!1;return this},unset:function(a,b){if(!(a in this.attributes))return this;b||(b={});var c={};c[a]=void 0;if(!b.silent&&this.validate&&!this._performValidation(c,b))return!1;delete this.attributes[a];delete this._escapedAttributes[a];a==this.idAttribute&&delete this.id;this._changed=
+!0;b.silent||(this.trigger("change:"+a,this,void 0,b),this.change(b));return this},clear:function(a){a||(a={});var b,c=this.attributes,d={};for(b in c)d[b]=void 0;if(!a.silent&&this.validate&&!this._performValidation(d,a))return!1;this.attributes={};this._escapedAttributes={};this._changed=!0;if(!a.silent){for(b in c)this.trigger("change:"+b,this,void 0,a);this.change(a)}return this},fetch:function(a){a||(a={});var b=this,c=a.success;a.success=function(d,e,f){if(!b.set(b.parse(d,f),a))return!1;c&&
+c(b,d)};a.error=i(a.error,b,a);return(this.sync||e.sync).call(this,"read",this,a)},save:function(a,b){b||(b={});if(a&&!this.set(a,b))return!1;var c=this,d=b.success;b.success=function(a,e,f){if(!c.set(c.parse(a,f),b))return!1;d&&d(c,a,f)};b.error=i(b.error,c,b);var f=this.isNew()?"create":"update";return(this.sync||e.sync).call(this,f,this,b)},destroy:function(a){a||(a={});if(this.isNew())return this.trigger("destroy",this,this.collection,a);var b=this,c=a.success;a.success=function(d){b.trigger("destroy",
+b,b.collection,a);c&&c(b,d)};a.error=i(a.error,b,a);return(this.sync||e.sync).call(this,"delete",this,a)},url:function(){var a=k(this.collection)||this.urlRoot||l();if(this.isNew())return a;return a+(a.charAt(a.length-1)=="/"?"":"/")+encodeURIComponent(this.id)},parse:function(a){return a},clone:function(){return new this.constructor(this)},isNew:function(){return this.id==null},change:function(a){this.trigger("change",this,a);this._previousAttributes=f.clone(this.attributes);this._changed=!1},hasChanged:function(a){if(a)return this._previousAttributes[a]!=
+this.attributes[a];return this._changed},changedAttributes:function(a){a||(a=this.attributes);var b=this._previousAttributes,c=!1,d;for(d in a)f.isEqual(b[d],a[d])||(c=c||{},c[d]=a[d]);return c},previous:function(a){if(!a||!this._previousAttributes)return null;return this._previousAttributes[a]},previousAttributes:function(){return f.clone(this._previousAttributes)},_performValidation:function(a,b){var c=this.validate(a);if(c)return b.error?b.error(this,c,b):this.trigger("error",this,c,b),!1;return!0}});
+e.Collection=function(a,b){b||(b={});if(b.comparator)this.comparator=b.comparator;f.bindAll(this,"_onModelEvent","_removeReference");this._reset();a&&this.reset(a,{silent:!0});this.initialize.apply(this,arguments)};f.extend(e.Collection.prototype,e.Events,{model:e.Model,initialize:function(){},toJSON:function(){return this.map(function(a){return a.toJSON()})},add:function(a,b){if(f.isArray(a))for(var c=0,d=a.length;c<d;c++)this._add(a[c],b);else this._add(a,b);return this},remove:function(a,b){if(f.isArray(a))for(var c=
+0,d=a.length;c<d;c++)this._remove(a[c],b);else this._remove(a,b);return this},get:function(a){if(a==null)return null;return this._byId[a.id!=null?a.id:a]},getByCid:function(a){return a&&this._byCid[a.cid||a]},at:function(a){return this.models[a]},sort:function(a){a||(a={});if(!this.comparator)throw Error("Cannot sort a set without a comparator");this.models=this.sortBy(this.comparator);a.silent||this.trigger("reset",this,a);return this},pluck:function(a){return f.map(this.models,function(b){return b.get(a)})},
+reset:function(a,b){a||(a=[]);b||(b={});this.each(this._removeReference);this._reset();this.add(a,{silent:!0});b.silent||this.trigger("reset",this,b);return this},fetch:function(a){a||(a={});var b=this,c=a.success;a.success=function(d,f,e){b[a.add?"add":"reset"](b.parse(d,e),a);c&&c(b,d)};a.error=i(a.error,b,a);return(this.sync||e.sync).call(this,"read",this,a)},create:function(a,b){var c=this;b||(b={});a=this._prepareModel(a,b);if(!a)return!1;var d=b.success;b.success=function(a,e,f){c.add(a,b);
+d&&d(a,e,f)};a.save(null,b);return a},parse:function(a){return a},chain:function(){return f(this.models).chain()},_reset:function(){this.length=0;this.models=[];this._byId={};this._byCid={}},_prepareModel:function(a,b){if(a instanceof e.Model){if(!a.collection)a.collection=this}else{var c=a;a=new this.model(c,{collection:this});a.validate&&!a._performValidation(c,b)&&(a=!1)}return a},_add:function(a,b){b||(b={});a=this._prepareModel(a,b);if(!a)return!1;var c=this.getByCid(a);if(c)throw Error(["Can't add the same model to a set twice",
+c.id]);this._byId[a.id]=a;this._byCid[a.cid]=a;this.models.splice(b.at!=null?b.at:this.comparator?this.sortedIndex(a,this.comparator):this.length,0,a);a.bind("all",this._onModelEvent);this.length++;b.silent||a.trigger("add",a,this,b);return a},_remove:function(a,b){b||(b={});a=this.getByCid(a)||this.get(a);if(!a)return null;delete this._byId[a.id];delete this._byCid[a.cid];this.models.splice(this.indexOf(a),1);this.length--;b.silent||a.trigger("remove",a,this,b);this._removeReference(a);return a},
+_removeReference:function(a){this==a.collection&&delete a.collection;a.unbind("all",this._onModelEvent)},_onModelEvent:function(a,b,c,d){(a=="add"||a=="remove")&&c!=this||(a=="destroy"&&this._remove(b,d),b&&a==="change:"+b.idAttribute&&(delete this._byId[b.previous(b.idAttribute)],this._byId[b.id]=b),this.trigger.apply(this,arguments))}});f.each(["forEach","each","map","reduce","reduceRight","find","detect","filter","select","reject","every","all","some","any","include","contains","invoke","max",
+"min","sortBy","sortedIndex","toArray","size","first","rest","last","without","indexOf","lastIndexOf","isEmpty","groupBy"],function(a){e.Collection.prototype[a]=function(){return f[a].apply(f,[this.models].concat(f.toArray(arguments)))}});e.Router=function(a){a||(a={});if(a.routes)this.routes=a.routes;this._bindRoutes();this.initialize.apply(this,arguments)};var q=/:([\w\d]+)/g,r=/\*([\w\d]+)/g,s=/[-[\]{}()+?.,\\^$|#\s]/g;f.extend(e.Router.prototype,e.Events,{initialize:function(){},route:function(a,
+b,c){e.history||(e.history=new e.History);f.isRegExp(a)||(a=this._routeToRegExp(a));e.history.route(a,f.bind(function(d){d=this._extractParameters(a,d);c.apply(this,d);this.trigger.apply(this,["route:"+b].concat(d))},this))},navigate:function(a,b){e.history.navigate(a,b)},_bindRoutes:function(){if(this.routes){var a=[],b;for(b in this.routes)a.unshift([b,this.routes[b]]);b=0;for(var c=a.length;b<c;b++)this.route(a[b][0],a[b][1],this[a[b][1]])}},_routeToRegExp:function(a){a=a.replace(s,"\\$&").replace(q,
+"([^/]*)").replace(r,"(.*?)");return RegExp("^"+a+"$")},_extractParameters:function(a,b){return a.exec(b).slice(1)}});e.History=function(){this.handlers=[];f.bindAll(this,"checkUrl")};var j=/^#*/,t=/msie [\w.]+/,m=!1;f.extend(e.History.prototype,{interval:50,getFragment:function(a,b){if(a==null)if(this._hasPushState||b){a=window.location.pathname;var c=window.location.search;c&&(a+=c);a.indexOf(this.options.root)==0&&(a=a.substr(this.options.root.length))}else a=window.location.hash;return decodeURIComponent(a.replace(j,
+""))},start:function(a){if(m)throw Error("Backbone.history has already been started");this.options=f.extend({},{root:"/"},this.options,a);this._wantsPushState=!!this.options.pushState;this._hasPushState=!(!this.options.pushState||!window.history||!window.history.pushState);a=this.getFragment();var b=document.documentMode;if(b=t.exec(navigator.userAgent.toLowerCase())&&(!b||b<=7))this.iframe=g('<iframe src="javascript:0" tabindex="-1" />').hide().appendTo("body")[0].contentWindow,this.navigate(a);
+this._hasPushState?g(window).bind("popstate",this.checkUrl):"onhashchange"in window&&!b?g(window).bind("hashchange",this.checkUrl):setInterval(this.checkUrl,this.interval);this.fragment=a;m=!0;a=window.location;b=a.pathname==this.options.root;if(this._wantsPushState&&!this._hasPushState&&!b)return this.fragment=this.getFragment(null,!0),window.location.replace(this.options.root+"#"+this.fragment),!0;else if(this._wantsPushState&&this._hasPushState&&b&&a.hash)this.fragment=a.hash.replace(j,""),window.history.replaceState({},
+document.title,a.protocol+"//"+a.host+this.options.root+this.fragment);if(!this.options.silent)return this.loadUrl()},route:function(a,b){this.handlers.unshift({route:a,callback:b})},checkUrl:function(){var a=this.getFragment();a==this.fragment&&this.iframe&&(a=this.getFragment(this.iframe.location.hash));if(a==this.fragment||a==decodeURIComponent(this.fragment))return!1;this.iframe&&this.navigate(a);this.loadUrl()||this.loadUrl(window.location.hash)},loadUrl:function(a){var b=this.fragment=this.getFragment(a);
+return f.any(this.handlers,function(a){if(a.route.test(b))return a.callback(b),!0})},navigate:function(a,b){var c=(a||"").replace(j,"");if(!(this.fragment==c||this.fragment==decodeURIComponent(c))){if(this._hasPushState){var d=window.location;c.indexOf(this.options.root)!=0&&(c=this.options.root+c);this.fragment=c;window.history.pushState({},document.title,d.protocol+"//"+d.host+c)}else if(window.location.hash=this.fragment=c,this.iframe&&c!=this.getFragment(this.iframe.location.hash))this.iframe.document.open().close(),
+this.iframe.location.hash=c;b&&this.loadUrl(a)}}});e.View=function(a){this.cid=f.uniqueId("view");this._configure(a||{});this._ensureElement();this.delegateEvents();this.initialize.apply(this,arguments)};var u=/^(\S+)\s*(.*)$/,n=["model","collection","el","id","attributes","className","tagName"];f.extend(e.View.prototype,e.Events,{tagName:"div",$:function(a){return g(a,this.el)},initialize:function(){},render:function(){return this},remove:function(){g(this.el).remove();return this},make:function(a,
+b,c){a=document.createElement(a);b&&g(a).attr(b);c&&g(a).html(c);return a},delegateEvents:function(a){if(a||(a=this.events))for(var b in f.isFunction(a)&&(a=a.call(this)),g(this.el).unbind(".delegateEvents"+this.cid),a){var c=this[a[b]];if(!c)throw Error('Event "'+a[b]+'" does not exist');var d=b.match(u),e=d[1];d=d[2];c=f.bind(c,this);e+=".delegateEvents"+this.cid;d===""?g(this.el).bind(e,c):g(this.el).delegate(d,e,c)}},_configure:function(a){this.options&&(a=f.extend({},this.options,a));for(var b=
+0,c=n.length;b<c;b++){var d=n[b];a[d]&&(this[d]=a[d])}this.options=a},_ensureElement:function(){if(this.el){if(f.isString(this.el))this.el=g(this.el).get(0)}else{var a=this.attributes||{};if(this.id)a.id=this.id;if(this.className)a["class"]=this.className;this.el=this.make(this.tagName,a)}}});e.Model.extend=e.Collection.extend=e.Router.extend=e.View.extend=function(a,b){var c=v(this,a,b);c.extend=this.extend;return c};var w={create:"POST",update:"PUT","delete":"DELETE",read:"GET"};e.sync=function(a,
+b,c){var d=w[a];c=f.extend({type:d,dataType:"json"},c);if(!c.url)c.url=k(b)||l();if(!c.data&&b&&(a=="create"||a=="update"))c.contentType="application/json",c.data=JSON.stringify(b.toJSON());if(e.emulateJSON)c.contentType="application/x-www-form-urlencoded",c.data=c.data?{model:c.data}:{};if(e.emulateHTTP&&(d==="PUT"||d==="DELETE")){if(e.emulateJSON)c.data._method=d;c.type="POST";c.beforeSend=function(a){a.setRequestHeader("X-HTTP-Method-Override",d)}}if(c.type!=="GET"&&!e.emulateJSON)c.processData=
+!1;return g.ajax(c)};var o=function(){},v=function(a,b,c){var d;d=b&&b.hasOwnProperty("constructor")?b.constructor:function(){return a.apply(this,arguments)};f.extend(d,a);o.prototype=a.prototype;d.prototype=new o;b&&f.extend(d.prototype,b);c&&f.extend(d,c);d.prototype.constructor=d;d.__super__=a.prototype;return d},k=function(a){if(!a||!a.url)return null;return f.isFunction(a.url)?a.url():a.url},l=function(){throw Error('A "url" property or function must be specified');},i=function(a,b,c){return function(d){a?
+a(b,d,c):b.trigger("error",b,d,c)}}}).call(this);
+
/**\r
* Binds all of the event handlers to their events\r
*/\r
- bindAll: function () {\r
+ bindAll: function () {\r
$(kiwi.gateway).bind('onmsg', this.onMsg)\r
.bind('onnotice', this.onNotice)\r
.bind('onaction', this.onAction)\r
.bind('onctcp_response', this.onCTCPResponse)\r
.bind('onirc_error', this.onIRCError)\r
.bind('onkiwi', this.onKiwi);\r
- },\r
+ },\r
\r
/**\r
* Handles the msg event\r
tab = new Tabview(plugin_event.destination);\r
}\r
tab.addMsg(null, plugin_event.nick, plugin_event.msg);\r
+ \r
+ var chan = kiwi.bbchans.detect(function (c) {\r
+ return c.get("name") === plugin_event.destination;\r
+ });\r
+ chan.addMsg(null, plugin_event.nick, plugin_event.msg);\r
},\r
\r
/**\r
\r
tab.addMsg(null, ' ', '--> ' + data.nick + ' [' + data.ident + '@' + data.hostname + '] has joined', 'action join', 'color:#009900;');\r
\r
+ var c = new kiwi.model.Channel({"name": data.channel.toLowerCase()});\r
+ c.get("members").add(new kiwi.model.Member({"nick": data.nick, "modes": []}));\r
+ kiwi.bbchans.add(c);\r
if (data.nick === kiwi.gateway.nick) {\r
return; // Not needed as it's already in nicklist\r
}\r
kiwi.front.ui.doLayout();
kiwi.front.ui.barsHide();
+ kiwi.bbchans = new kiwi.model.ChannelList();
+ kiwi.bbtabs = new kiwi.view.Tabs({"el": $('#kiwi .windowlist ul')[0], "model": kiwi.bbchans});
+
+
server_tabview = new Tabview('server');
server_tabview.userlist.setWidth(0); // Disable the userlist
server_tabview.setIcon('/img/app_menu.png');
};
};
-
/**
* @constructor
* @param {String} name The name of the UserList
$('#kiwi .windows .scroller').append('<div id="' + tmp_divname + '" class="messages"></div>');
// Create the window tab
+
tmp_tab = $('<li id="' + tmp_tabname + '"><span></span></li>');
$('span', tmp_tab).text(v_name);
$('#kiwi .windowlist ul').append(tmp_tab);
--- /dev/null
+/*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
+kiwi.model = {};\r
+\r
+kiwi.model.MemberList = Backbone.Collection.extend({\r
+ model: kiwi.model.Member,\r
+ comparator: function (a, b) {\r
+ var i, a_modes, b_modes, a_idx, b_idx, a_nick, b_nick;\r
+ a_modes = a.get("modes");\r
+ b_modes = b.get("modes");\r
+ // Try to sort by modes first\r
+ if (a_modes.length > 0) {\r
+ // a has modes, but b doesn't so a should appear first\r
+ if (b_modes.length === 0) {\r
+ return -1;\r
+ }\r
+ a_idx = b_idx = -1;\r
+ // Compare the first (highest) mode\r
+ for (i = 0; i < kiwi.gateway.user_prefixes.length; i++) {\r
+ if (kiwi.gateway.user_prefixes[i].mode === a_modes[0]) {\r
+ a_idx = i;\r
+ }\r
+ }\r
+ for (i = 0; i < kiwi.gateway.user_prefixes.length; i++) {\r
+ if (kiwi.gateway.user_prefixes[i].mode === b_modes[0]) {\r
+ b_idx = i;\r
+ }\r
+ }\r
+ if (a_idx < b_idx) {\r
+ return -1;\r
+ } else if (a_idx > b_idx) {\r
+ return 1;\r
+ }\r
+ // If we get to here both a and b have the same highest mode so have to resort to lexicographical sorting\r
+\r
+ } else if (b_modes.length > 0) {\r
+ // b has modes but a doesn't so b should appear first\r
+ return 1;\r
+ }\r
+ a_nick = a.get("nick").toLocaleUpperCase();\r
+ b_nick = b.get("nick").toLocaleUpperCase();\r
+ // Lexicographical sorting\r
+ if (a_nick < b_nick) {\r
+ return -1;\r
+ } else if (a_nick > b_nick) {\r
+ return 1;\r
+ } else {\r
+ // This should never happen; both users have the same nick.\r
+ console.log('Something\'s gone wrong somewhere - two users have the same nick!');\r
+ return 0;\r
+ }\r
+ }\r
+});\r
+\r
+kiwi.model.Member = Backbone.Model.extend({\r
+ sortModes: function (modes) {\r
+ return modes.sort(function (a, b) {\r
+ var a_idx, b_idx, i;\r
+ for (i = 0; i < kiwi.gateway.user_prefixes.length; i++) {\r
+ if (kiwi.gateway.user_prefixes[i].mode === a) {\r
+ a_idx = i;\r
+ }\r
+ }\r
+ for (i = 0; i < kiwi.gateway.user_prefixes.length; i++) {\r
+ if (kiwi.gateway.user_prefixes[i].mode === b) {\r
+ b_idx = i;\r
+ }\r
+ }\r
+ if (a_idx < b_idx) {\r
+ return -1;\r
+ } else if (a_idx > b_idx) {\r
+ return 1;\r
+ } else {\r
+ return 0;\r
+ }\r
+ });\r
+ },\r
+ initialize: function (attributes) {\r
+ var nick, modes, prefix;\r
+ nick = this.stripPrefix(this.get("nick"));\r
+\r
+ modes = this.get("modes");\r
+ modes = modes || [];\r
+ modes.sort(this.sortModes);\r
+\r
+ this.set({"nick": nick, "modes": modes, "prefix": this.getPrefix(modes)}, {silent: true});\r
+ },\r
+ addMode: function (mode) {\r
+ var modes, prefix;\r
+ modes = this.get("modes");\r
+ modes.push(mode);\r
+ modes = this.sortModes(modes);\r
+ this.set({"prefix": this.getPrefix(modes), "modes": modes});\r
+ },\r
+ removeMode: function (mode) {\r
+ var modes, prefix;\r
+ modes = this.get("modes");\r
+ modes = _.reject(modes, function(m) {\r
+ return m === mode;\r
+ });\r
+ this.set({"prefix": this.getPrefix(modes), "modes": modes});\r
+ },\r
+ getPrefix: function (modes) {\r
+ var prefix = '';\r
+ if (typeof modes[0] !== 'undefined') {\r
+ prefix = _.detect(kiwi.gateway.user_prefixes, function (prefix) {\r
+ return prefix.mode === modes[0];\r
+ });\r
+ prefix = (prefix) ? prefix.symbol : '';\r
+ }\r
+ return prefix;\r
+ },\r
+ stripPrefix: function (nick) {\r
+ var tmp = nick, i, j, k;\r
+ i = 0;\r
+ for (j = 0; j < nick.length; j++) {\r
+ for (k = 0; k < kiwi.gateway.user_prefixes.length; k++) {\r
+ if (nick.charAt(j) === kiwi.gateway.user_prefixes[k].symbol) {\r
+ i++;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ return tmp.substr(i);\r
+ }\r
+});\r
+\r
+kiwi.model.ChannelList = Backbone.Collection.extend({\r
+ model: kiwi.model.Channel,\r
+ comparator: function (chan) {\r
+ return chan.get("name");\r
+ }\r
+});\r
+\r
+kiwi.model.Channel = Backbone.Model.extend({\r
+ initialize: function (attributes) {\r
+ var name = this.get("name") || "";\r
+ this.set({\r
+ "members": new kiwi.model.MemberList(),\r
+ "name": name,\r
+ "backscroll": []\r
+ }, {"silent": true});\r
+ this.view = new kiwi.view.Channel({"model": this, "name": name});\r
+ },\r
+ addMsg: function (time, nick, msg, type, style) {\r
+ var tmp, bs;\r
+\r
+ tmp = {"msg": msg, "time": time, "nick": nick, "chan": this.get("name")};\r
+ tmp = kiwi.plugs.run('addmsg', tmp);\r
+ if (!tmp) {\r
+ return;\r
+ }\r
+ if (tmp.time === null) {\r
+ d = new Date();\r
+ tmp.time = d.getHours().toString().lpad(2, "0") + ":" + d.getMinutes().toString().lpad(2, "0") + ":" + d.getSeconds().toString().lpad(2, "0");\r
+ }\r
+\r
+ // The CSS class (action, topic, notice, etc)\r
+ if (typeof tmp.type !== "string") {\r
+ tmp.type = '';\r
+ }\r
+\r
+ // Make sure we don't have NaN or something\r
+ if (typeof tmp.msg !== "string") {\r
+ tmp.msg = '';\r
+ }\r
+\r
+ bs = this.get("backscroll");\r
+ bs.push(tmp)\r
+ this.set({"backscroll": bs}, {silent:true});\r
+ this.trigger("msg", tmp);\r
+ }\r
+});
\ No newline at end of file
}
return false;
- }
- },
+ }
+ },
*/
{
}
},
- {
- name: "kiwitest",
- oninit: function (event, opts) {
- console.log('registering namespace');
- $(gateway).bind("kiwi.lol.browser", function (e, data) {
- console.log('YAY kiwitest');
- console.log(data);
- });
- }
- }
+ {
+ name: "kiwitest",
+ oninit: function (event, opts) {
+ console.log('registering namespace');
+ $(gateway).bind("kiwi.lol.browser", function (e, data) {
+ console.log('YAY kiwitest');
+ console.log(data);
+ });
+ }
+ }
];
--- /dev/null
+/*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.el).attr("id", 'kiwi_userlist_' + options.name);\r
+ this.model.get("members").bind('change', this.render, this);\r
+ },\r
+ render: function () {\r
+ var $this = $(this.el);\r
+ $this.empty();\r
+ this.model.get("members").forEach(function (member) {\r
+ $this.append('<li><a class="nick"><span class="prefix">' + user.prefix + user.nick + '</a></li>');\r
+ });\r
+ },\r
+ nickClick: function (x) {\r
+ console.log(x);\r
+ }\r
+});\r
+\r
+kiwi.view.Channel = Backbone.View.extend({\r
+ tagName: "div",\r
+ className: "messages",\r
+ events: {\r
+ "click .chan": "chanClick"\r
+ },\r
+ initialize: function (options) {\r
+ this.htmlsafe_name = 'chan_' + randomString(15);\r
+ $(this.el).attr("id", 'kiwi_window_' + this.htmlsafe_name);\r
+ this.model.bind('msg', this.newMsg, this);\r
+ this.msg_count = 0;\r
+ this.model.set({"view": this}, {"silent": true});\r
+ },\r
+ render: function () {\r
+ var $this = $(this.el);\r
+ $this.empty();\r
+ this.model.get("backscroll").forEach(this.newMsg);\r
+ },\r
+ newMsg: function (msg) {\r
+ var re, line_msg, $this = $(this.el);\r
+ // Make the channels clickable\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
+ msg.msg = kiwi.front.formatIRCMsg(msg.msg);\r
+\r
+ // Build up and add the line\r
+ line_msg = $('<div class="msg ' + msg.type + '"><div class="time">' + msg.time + '</div><div class="nick">' + msg.nick + '</div><div class="text" style="' + msg.style + '">' + msg.msg + ' </div></div>');\r
+ $this.append(line_msg);\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
+});\r
+\r
+kiwi.view.Tabs = Backbone.View.extend({\r
+ events: {\r
+ "click li": "tabClick"\r
+ },\r
+ initialize: function () {\r
+ this.model.bind("add", this.addTab, this);\r
+ this.model.bind("remove", this.removeTab, this);\r
+ this.model.bind("reset", this.render, this);\r
+ },\r
+ render: function () {\r
+ $this = $(this.el);\r
+ $this.empty();\r
+ this.model.forEach(function (tab) {\r
+ var tabname = $(tab.get("view").el).attr("id");\r
+ $this.append($('<li id="tab_' + tabname + '"><span>' + tab.get("name") + '</span></li>'));\r
+ });\r
+ },\r
+ addTab: function (tab) {\r
+ var tabname = $(tab.get("view").el).attr("id"),\r
+ $this = $(this.el);\r
+ $this.append($('<li id="tab_' + tabname + '"><span>' + tab.get("name") + '</span></li>'));\r
+ },\r
+ removeTab: function (tab) {\r
+ $('#tab_' + $(tab.get("view").el).attr("id")).remove();\r
+ },\r
+ tabClick: function (x) {\r
+ console.log(x);\r
+ }\r
+});\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
min.underscore = fs.readFileSync(public_http_path + 'js/underscore.min.js');
min.util = fs.readFileSync(public_http_path + 'js/util.js');
+ min.backbone = fs.readFileSync(public_http_path + 'js/backbone-0.5.3-min.js');
min.gateway = fs.readFileSync(public_http_path + 'js/gateway.js');
+ min.model = fs.readFileSync(public_http_path + 'js/model.js');
+ min.view = fs.readFileSync(public_http_path + 'js/view.js');
min.front = fs.readFileSync(public_http_path + 'js/front.js');
min.front_events = fs.readFileSync(public_http_path + 'js/front.events.js');
min.front_ui = fs.readFileSync(public_http_path + 'js/front.ui.js');
min.iscroll = fs.readFileSync(public_http_path + 'js/iscroll.js');
- min.ast = jsp.parse(min.underscore + min.util + min.gateway + min.front + min.front_events + min.front_ui + min.iscroll);
+ min.ast = jsp.parse(min.underscore + min.util + min.backbone + min.gateway + min.model + min.view + min.front + min.front_events + min.front_ui + min.iscroll);
min.ast = pro.ast_mangle(min.ast);
min.ast = pro.ast_squeeze(min.ast);
min.final_code = pro.gen_code(min.ast);