]>
jfr.im git - irc/quakenet/qwebirc.git/blob - js/ui/frontends/qui.js
1 qwebirc
.ui
.QUI
= new Class({
2 Extends: qwebirc
.ui
.RootUI
,
3 initialize: function(parentElement
, theme
, options
) {
4 this.parent(parentElement
, qwebirc
.ui
.QUI
.Window
, "qui", options
);
6 this.parentElement
= parentElement
;
7 this.setModifiableStylesheet("qui");
9 postInitialize: function() {
10 this.qjsui
= new qwebirc
.ui
.QUI
.JSUI("qwebirc-qui", this.parentElement
);
11 this.qjsui
.addEvent("reflow", function() {
12 var w
= this.getActiveWindow();
16 this.qjsui
.top
.addClass("outertabbar");
17 this.qjsui
.left
.addClass("outertabbar");
19 this.qjsui
.top
.addClass("outertabbar_top");
20 this.qjsui
.left
.addClass("outertabbar_left");
22 this.qjsui
.bottom
.addClass("input");
23 this.qjsui
.right
.addClass("nicklist");
24 this.qjsui
.topic
.addClass("topic");
25 this.qjsui
.middle
.addClass("lines");
27 this.outerTabs
= new Element("div");
30 this.tabs
= new Element("div");
31 this.tabs
.addClass("tabbar");
33 this.__createDropdownMenu();
35 this.outerTabs
.appendChild(this.tabs
);
36 this.origtopic
= this.topic
= this.qjsui
.topic
;
37 this.lines
= this.qjsui
.middle
;
38 this.orignicklist
= this.nicklist
= this.qjsui
.right
;
40 this.input
= this.qjsui
.bottom
;
41 this.reflow
= this.qjsui
.reflow
.bind(this.qjsui
);
43 var scrollHandler = function(x
) {
44 var event
= new Event(x
);
47 var p
= this.qjsui
.left
;
49 /* don't scroll if we're scrollable */
50 if(p
.getScrollSize().y
> p
.clientHeight
)
54 down
= event
.wheel
> 0;
57 down
= event
.wheel
< 0;
67 this.qjsui
.left
.addEvent("mousewheel", scrollHandler
);
68 this.qjsui
.top
.addEvent("mousewheel", scrollHandler
);
72 for(var i
=50;i
<1000;i
+=50)
73 this.reflow
.delay(i
, true);
74 for(var i
=1000;i
<2000;i
+=100)
76 for(var i
=2000;i
<15000;i
+=500)
79 this.setSideTabs(this.uiOptions
.SIDE_TABS
);
82 newWindow: function(client
, type
, name
) {
83 var w
= this.parent(client
, type
, name
);
84 w
.setSideTabs(this.sideTabs
);
87 __createDropdownMenu: function() {
88 var dropdownMenu
= new Element("span");
89 dropdownMenu
.addClass("dropdownmenu");
91 dropdownMenu
.hide = function() {
92 dropdownMenu
.setStyle("display", "none");
93 dropdownMenu
.visible
= false;
94 document
.removeEvent("mousedown", hideEvent
);
96 var hideEvent = function() { dropdownMenu
.hide(); };
99 this.parentElement
.appendChild(dropdownMenu
);
101 this.UICommands
.forEach(function(x
) {
103 var fn
= this[x
[1] + "Window"].bind(this);
104 var e
= new Element("a");
105 e
.addEvent("mousedown", function(e
) { new Event(e
).stop(); });
106 e
.addEvent("click", function() {
111 dropdownMenu
.appendChild(e
);
114 var dropdown
= new Element("div");
115 dropdown
.addClass("dropdown-tab");
116 dropdown
.appendChild(new Element("img", {src: qwebirc
.global
.staticBaseURL
+ "images/icon.png", title: "menu", alt: "menu"}));
117 dropdown
.setStyle("opacity", 1);
119 this.outerTabs
.appendChild(dropdown
);
120 dropdownMenu
.show = function(x
) {
123 if(dropdownMenu
.visible
) {
127 var parentSize
= this.outerTabs
.parentNode
.getSize().y
;
129 dropdownMenu
.setStyle("left", parentSize
.x
);
130 dropdownMenu
.setStyle("top", top
-1); /* -1 == top border */
131 dropdownMenu
.setStyle("display", "inline-block");
132 dropdownMenu
.visible
= true;
134 document
.addEvent("mousedown", hideEvent
);
136 dropdown
.addEvent("mousedown", function(e
) { new Event(e
).stop(); });
137 dropdown
.addEvent("click", dropdownMenu
.show
);
139 createInput: function() {
140 var form
= new Element("form");
141 this.input
.appendChild(form
);
143 form
.addClass("input");
145 var inputbox
= new Element("input");
146 this.addEvent("signedOn", function() {
147 inputbox
.placeholder
= "chat here! you can also use commands, like /JOIN or /HELP";
148 var d = function() { inputbox
.addClass("input-flash"); }.delay(250);
149 var d = function() { inputbox
.removeClass("input-flash"); }.delay(500);
150 var d = function() { inputbox
.addClass("input-flash"); }.delay(750);
151 var d = function() { inputbox
.removeClass("input-flash"); }.delay(1000);
152 var d = function() { inputbox
.addClass("input-flash"); }.delay(1250);
153 var d = function() { inputbox
.removeClass("input-flash"); }.delay(1750);
155 form
.appendChild(inputbox
);
156 this.inputbox
= inputbox
;
157 this.inputbox
.maxLength
= 470;
159 var sendInput = function() {
160 if(inputbox
.value
== "")
163 this.resetTabComplete();
164 this.getActiveWindow().historyExec(inputbox
.value
);
166 inputbox
.placeholder
= "";
169 if(!qwebirc
.util
.deviceHasKeyboard()) {
170 inputbox
.addClass("mobile-input");
171 var inputButton
= new Element("input", {type: "button"});
172 inputButton
.addClass("mobile-button");
173 inputButton
.addEvent("click", function() {
177 inputButton
.value
= ">";
178 this.input
.appendChild(inputButton
);
179 var reflowButton = function() {
180 var containerSize
= this.input
.getSize();
181 var buttonSize
= inputButton
.getSize();
183 var buttonLeft
= containerSize
.x
- buttonSize
.x
- 5; /* lovely 5 */
185 inputButton
.setStyle("left", buttonLeft
);
186 inputbox
.setStyle("width", buttonLeft
- 5);
187 inputButton
.setStyle("height", containerSize
.y
);
189 this.qjsui
.addEvent("reflow", reflowButton
);
191 inputbox
.addClass("keyboard-input");
194 form
.addEvent("submit", function(e
) {
199 var reset
= this.resetTabComplete
.bind(this);
200 inputbox
.addEvent("focus", reset
);
201 inputbox
.addEvent("mousedown", reset
);
202 inputbox
.addEvent("keypress", reset
);
204 inputbox
.addEvent("keydown", function(e
) {
206 var cvalue
= inputbox
.value
;
208 if(e
.alt
|| e
.control
|| e
.meta
)
211 if(e
.key
== "up" && !e
.shift
) {
212 resultfn
= this.commandhistory
.upLine
;
213 } else if(e
.key
== "down" && !e
.shift
) {
214 resultfn
= this.commandhistory
.downLine
;
215 } else if(e
.key
== "tab") {
216 this.tabComplete(inputbox
, e
.shift
);
225 this.resetTabComplete();
226 if((cvalue
!= "") && (this.lastcvalue
!= cvalue
))
227 this.commandhistory
.addLine(cvalue
, true);
229 var result
= resultfn
.bind(this.commandhistory
)();
236 this.lastcvalue
= result
;
238 inputbox
.value
= result
;
239 qwebirc
.util
.setAtEnd(inputbox
);
242 setLines: function(lines
) {
243 this.lines
.parentNode
.replaceChild(lines
, this.lines
);
244 this.qjsui
.middle
= this.lines
= lines
;
246 setChannelItems: function(nicklist
, topic
) {
247 if(!$defined(nicklist
)) {
248 nicklist
= this.orignicklist
;
249 topic
= this.origtopic
;
251 this.nicklist
.parentNode
.replaceChild(nicklist
, this.nicklist
);
252 this.qjsui
.right
= this.nicklist
= nicklist
;
254 this.topic
.parentNode
.replaceChild(topic
, this.topic
);
255 this.qjsui
.topic
= this.topic
= topic
;
257 setSideTabs: function(value
) {
258 if(value
=== this.sideTabs
)
261 if(this.sideTabs
=== true) {
262 this.qjsui
.left
.removeChild(this.outerTabs
);
263 } else if(this.sideTabs
=== false) {
264 this.qjsui
.top
.removeChild(this.outerTabs
);
267 this.qjsui
.left
.appendChild(this.outerTabs
);
268 this.qjsui
.top
.style
.display
= "none";
269 this.qjsui
.left
.style
.display
= "";
271 this.qjsui
.top
.appendChild(this.outerTabs
);
272 this.qjsui
.top
.style
.display
= "";
273 this.qjsui
.left
.style
.display
= "none";
275 this.sideTabs
= value
;
276 this.windows
.each(function(k
, v
) {
277 v
.each(function(k
, v2
) {
278 v2
.setSideTabs(value
);
284 qwebirc
.ui
.QUI
.JSUI
= new Class({
285 Implements: [Events
],
286 initialize: function(class_
, parent
, sizer
) {
287 this.parent
= parent
;
288 this.sizer
= $defined(sizer
)?sizer:parent
;
290 this.class_
= class_
;
293 this.reflowevent
= null;
295 window
.addEvent("resize", function() {
299 applyClasses: function(pos
, l
) {
300 l
.addClass("dynamicpanel");
301 l
.addClass(this.class_
);
302 l
.addClass(pos
+ "boundpanel");
305 var XE = function(pos
) {
306 var element
= new Element("div");
307 this.applyClasses(pos
, element
);
309 this.parent
.appendChild(element
);
313 this.top
= XE("top");
314 this.left
= XE("left");
315 this.topic
= XE("topic");
316 this.middle
= XE("middle");
317 this.right
= XE("right");
318 this.bottom
= XE("bottom");
320 reflow: function(delay
) {
325 $clear(this.reflowevent
);
327 this.reflowevent
= this.__reflow
.delay(delay
, this);
329 __reflow: function() {
330 var bottom
= this.bottom
;
331 var middle
= this.middle
;
332 var right
= this.right
;
333 var topic
= this.topic
;
335 var left
= this.left
;
337 /* |----------------------------------------------|
339 * |----------------------------------------------|
340 * | left | topic | right |
341 * | |-------------------------------| |
345 * | |---------------------------------------|
347 * |----------------------------------------------|
350 var topicsize
= topic
.getSize();
351 var topsize
= top
.getSize();
352 var rightsize
= right
.getSize();
353 var bottomsize
= bottom
.getSize();
354 var leftsize
= left
.getSize();
355 var docsize
= this.sizer
.getSize();
357 var mheight
= (docsize
.y
- topsize
.y
- bottomsize
.y
- topicsize
.y
);
358 var mwidth
= (docsize
.x
- rightsize
.x
- leftsize
.x
);
360 left
.setStyle("top", topsize
.y
);
361 topic
.setStyle("top", topsize
.y
);
362 topic
.setStyle("left", leftsize
.x
);
363 topic
.setStyle("width", docsize
.x
- leftsize
.x
);
365 middle
.setStyle("top", (topsize
.y
+ topicsize
.y
));
366 middle
.setStyle("left", leftsize
.x
);
368 middle
.setStyle("height", mheight
);
369 right
.setStyle("height", mheight
);
373 middle
.setStyle("width", mwidth
);
374 right
.setStyle("top", (topsize
.y
+ topicsize
.y
));
376 bottom
.setStyle("left", leftsize
.x
);
377 this.fireEvent("reflow");
379 showChannel: function(state
, nicklistVisible
) {
380 var display
= "none";
384 this.right
.setStyle("display", nicklistVisible
? display : "none");
385 this.topic
.setStyle("display", display
);
387 showInput: function(state
) {
388 this.bottom
.isVisible
= state
;
389 this.bottom
.setStyle("display", state
?"block":"none");
393 qwebirc
.ui
.QUI
.Window
= new Class({
394 Extends: qwebirc
.ui
.Window
,
396 initialize: function(parentObject
, client
, type
, name
, identifier
) {
397 this.parent(parentObject
, client
, type
, name
, identifier
);
399 this.tab
= new Element("a");
400 this.tab
.addClass("tab");
401 this.tab
.addEvent("focus", function() { this.blur() }.bind(this.tab
));;
403 this.spaceNode
= document
.createTextNode(" ");
404 parentObject
.tabs
.appendChild(this.tab
);
405 parentObject
.tabs
.appendChild(this.spaceNode
);
407 if(type
!= qwebirc
.ui
.WINDOW_STATUS
&& type
!= qwebirc
.ui
.WINDOW_CONNECT
) {
408 var tabclose
= new Element("span");
409 this.tabclose
= tabclose
;
410 tabclose
.set("text", "X");
411 tabclose
.addClass("tabclose");
412 var close = function(e
) {
418 if(type
== qwebirc
.ui
.WINDOW_CHANNEL
)
419 this.client
.exec("/PART " + name
);
423 //parentObject.inputbox.focus();
426 tabclose
.addEvent("click", close
);
427 this.tab
.addEvent("mouseup", function(e
) {
430 if(Browser
.Engine
.trident
)
433 if(e
.event
.button
== button
)
437 this.tab
.appendChild(tabclose
);
439 this.tabclose
= null;
442 this.tab
.appendText(name
);
443 this.tab
.addEvent("click", function(e
) {
449 parentObject
.selectWindow(this);
453 this.lines
= new Element("div");
454 this.parentObject
.qjsui
.applyClasses("middle", this.lines
);
455 this.lines
.addClass("lines");
456 if(type
!= qwebirc
.ui
.WINDOW_CUSTOM
&& type
!= qwebirc
.ui
.WINDOW_CONNECT
)
457 this.lines
.addClass("ircwindow");
459 this.lines
.addEvent("scroll", function() {
460 this.scrolleddown
= this.scrolledDown();
461 this.scrollpos
= this.getScrollParent().getScroll();
464 if(type
== qwebirc
.ui
.WINDOW_CHANNEL
) {
465 this.topic
= new Element("div");
466 this.parentObject
.qjsui
.applyClasses("topic", this.topic
);
467 this.topic
.addClass("topic");
468 this.topic
.addClass("tab-invisible");
469 this.topic
.set("html", " ");
470 this.topic
.addEvent("dblclick", this.editTopic
.bind(this));
471 this.parentObject
.qjsui
.applyClasses("topic", this.topic
);
473 this.prevNick
= null;
474 this.nicklist
= new Element("div");
475 this.nicklist
.addClass("nicklist");
476 this.nicklist
.addClass("tab-invisible");
477 this.nicklist
.addEvent("click", this.removePrevMenu
.bind(this));
478 this.parentObject
.qjsui
.applyClasses("right", this.nicklist
);
480 this.updateTopic("");
483 this.nicksColoured
= this.parentObject
.uiOptions
.NICK_COLOURS
;
486 rename: function(name
) {
487 var newNode
= document
.createTextNode(name
);
488 if(this.parentObject
.sideTabs
) {
489 this.tab
.replaceChild(newNode
, this.tab
.childNodes
[1]);
491 this.tab
.replaceChild(newNode
, this.tab
.firstChild
);
494 if(this.type
== qwebirc
.ui
.WINDOW_QUERY
)
495 this.updateTopic("");
497 editTopic: function() {
498 if(this.type
!= qwebirc
.ui
.WINDOW_CHANNEL
)
501 if(!this.client
.nickOnChanHasPrefix(this.client
.nickname
, this.name
, "@")) {
502 /* var cmodes = this.client.getChannelModes(channel);
503 if(cmodes.indexOf("t")) {*/
504 alert("Sorry, you need to be a channel operator to change the topic!");
508 var newTopic
= prompt("Change topic of " + this.name
+ " to:", this.topic
.topicText
);
509 if(newTopic
=== null)
512 this.client
.exec("/TOPIC " + newTopic
);
515 this.parentObject
.reflow();
517 onResize: function() {
518 if(this.scrolleddown
) {
519 if(Browser
.Engine
.trident
) {
520 this.scrollToBottom
.delay(5, this);
522 this.scrollToBottom();
524 } else if($defined(this.scrollpos
)) {
525 if(Browser
.Engine
.trident
) {
526 this.getScrollParent().scrollTo(this.scrollpos
.x
, this.scrollpos
.y
);
528 this.getScrollParent().scrollTo
.delay(5, this, [this.scrollpos
.x
, this.scrollpos
.y
]);
532 createMenu: function(nick
, parent
) {
533 var e
= new Element("div");
534 parent
.appendChild(e
);
537 var nickArray
= [nick
];
538 qwebirc
.ui
.MENU_ITEMS
.forEach(function(x
) {
539 if(!x
.predicate
|| x
.predicate
!== true && !x
.predicate
.apply(this, nickArray
))
542 var e2
= new Element("a");
545 e2
.set("text", "- " + x
.text
);
547 e2
.addEvent("focus", function() { this.blur() }.bind(e2
));
548 e2
.addEvent("click", function(ev
) { new Event(ev
.stop()); this.menuClick(x
.fn
); }.bind(this));
552 menuClick: function(fn
) {
554 this.prevNick.removeChild(this.prevNick.menu);
555 this.prevNick.menu = null;
557 fn
.bind(this)(this.prevNick
.realNick
);
558 this.removePrevMenu();
560 moveMenuClass: function() {
563 if(this.nicklist
.firstChild
== this.prevNick
) {
564 this.prevNick
.removeClass("selected-middle");
566 this.prevNick
.addClass("selected-middle");
569 removePrevMenu: function() {
573 this.prevNick
.removeClass("selected");
574 this.prevNick
.removeClass("selected-middle");
575 if(this.prevNick
.menu
)
576 this.prevNick
.removeChild(this.prevNick
.menu
);
577 this.prevNick
= null;
579 nickListAdd: function(nick
, position
) {
580 var realNick
= this.client
.stripPrefix(nick
);
582 var e
= new Element("a");
583 qwebirc
.ui
.insertAt(position
, this.nicklist
, e
);
584 var span
= new Element("span");
585 if(this.parentObject
.uiOptions
.NICK_COLOURS
) {
586 var colour
= realNick
.toHSBColour(this.client
);
588 span
.setStyle("color", colour
.rgbToHex());
590 span
.set("text", nick
);
593 e
.realNick
= realNick
;
595 e
.addEvent("click", function(x
) {
596 if(this.prevNick
== e
) {
597 this.removePrevMenu();
601 this.removePrevMenu();
603 e
.addClass("selected");
604 this.moveMenuClass();
605 e
.menu
= this.createMenu(e
.realNick
, e
);
609 e
.addEvent("focus", function() { this.blur() }.bind(e
));
610 this.moveMenuClass();
613 nickListRemove: function(nick
, stored
) {
614 this.nicklist
.removeChild(stored
);
615 this.moveMenuClass();
617 updateTopic: function(topic
) {
621 t
.removeChild(t
.firstChild
);
624 if(this.type
== qwebirc
.ui
.WINDOW_CHANNEL
) {
629 qwebirc
.ui
.Colourise(this.name
+ suffix
, t
, null, null, this);
631 if(this.type
== qwebirc
.ui
.WINDOW_CHANNEL
) {
634 this.parent(topic
, t
);
636 t
.appendChild(document
.createTextNode("(no topic set)"));
643 var inputVisible
= this.type
!= qwebirc
.ui
.WINDOW_CONNECT
&& this.type
!= qwebirc
.ui
.WINDOW_CUSTOM
;
645 this.tab
.removeClass("tab-unselected");
646 this.tab
.addClass("tab-selected");
648 this.parentObject
.setLines(this.lines
);
649 this.parentObject
.setChannelItems(this.nicklist
, this.topic
);
650 this.parentObject
.qjsui
.showInput(inputVisible
);
651 this.parentObject
.qjsui
.showChannel($defined(this.nicklist
), this.parentObject
.uiOptions
.SHOW_NICKLIST
);
658 this.parentObject
.inputbox
.focus();
660 if(this.type
== qwebirc
.ui
.WINDOW_CHANNEL
&& this.nicksColoured
!= this.parentObject
.uiOptions
.NICK_COLOURS
) {
661 this.nicksColoured
= this.parentObject
.uiOptions
.NICK_COLOURS
;
663 var nodes
= this.nicklist
.childNodes
;
664 if(this.parentObject
.uiOptions
.NICK_COLOURS
) {
665 for(var i
=0;i
<nodes
.length
;i
++) {
666 var e
= nodes
[i
], span
= e
.firstChild
;
667 var colour
= e
.realNick
.toHSBColour(this.client
);
669 span
.setStyle("color", colour
.rgbToHex());
672 for(var i
=0;i
<nodes
.length
;i
++) {
673 var span
= nodes
[i
].firstChild
;
674 span
.setStyle("color", null);
679 deselect: function() {
682 this.tab
.removeClass("tab-selected");
683 this.tab
.addClass("tab-unselected");
688 this.parentObject
.tabs
.removeChild(this.tab
);
689 this.parentObject
.tabs
.removeChild(this.spaceNode
);
692 addLine: function(type
, line
, colourClass
) {
693 var e
= new Element("div");
696 e
.addClass(colourClass
);
697 } else if(this.lastcolour
) {
698 e
.addClass("linestyle1");
700 e
.addClass("linestyle2");
702 this.lastcolour
= !this.lastcolour
;
704 this.parent(type
, line
, colourClass
, e
);
706 setHilighted: function(state
) {
707 var laststate
= this.hilighted
;
711 if(state
== laststate
)
714 this.tab
.removeClass("tab-hilight-activity");
715 this.tab
.removeClass("tab-hilight-us");
716 this.tab
.removeClass("tab-hilight-speech");
718 switch(this.hilighted
) {
719 case qwebirc
.ui
.HILIGHT_US:
720 this.tab
.addClass("tab-hilight-us");
722 case qwebirc
.ui
.HILIGHT_SPEECH:
723 this.tab
.addClass("tab-hilight-speech");
725 case qwebirc
.ui
.HILIGHT_ACTIVITY:
726 this.tab
.addClass("tab-hilight-activity");
730 setSideTabs: function(value
) {
731 if(this.tabclose
=== null)
733 this.tab
.removeChild(this.tabclose
);
735 this.tab
.insertBefore(this.tabclose
, this.tab
.firstChild
);
737 this.tab
.appendChild(this.tabclose
);