]>
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");
18 this.qjsui
.bottom
.addClass("input");
19 this.qjsui
.right
.addClass("nicklist");
20 this.qjsui
.topic
.addClass("topic");
21 this.qjsui
.middle
.addClass("lines");
23 this.outerTabs
= this.qjsui
.top
;
25 this.tabs
= new Element("div");
26 this.tabs
.addClass("tabbar");
28 this.__createDropdownMenu();
30 this.outerTabs
.appendChild(this.tabs
);
31 this.origtopic
= this.topic
= this.qjsui
.topic
;
32 this.origlines
= this.lines
= this.qjsui
.middle
;
33 this.orignicklist
= this.nicklist
= this.qjsui
.right
;
35 this.input
= this.qjsui
.bottom
;
36 this.reflow
= this.qjsui
.reflow
.bind(this.qjsui
);
38 this.tabs
.addEvent("mousewheel", function(x
) {
39 var event
= new Event(x
);
44 } else if(event
.wheel
< 0) {
53 this.reflow
.delay(100); /* Konqueror fix */
55 /* HACK, in Chrome this should work immediately but doesn't */
56 this.__createDropdownHint
.delay(100, this);
58 __createDropdownMenu: function() {
59 var dropdownMenu
= new Element("span");
60 dropdownMenu
.addClass("dropdownmenu");
62 dropdownMenu
.hide = function() {
63 dropdownMenu
.setStyle("display", "none");
64 dropdownMenu
.visible
= false;
65 document
.removeEvent("mousedown", hideEvent
);
67 var hideEvent = function() { dropdownMenu
.hide(); };
70 this.parentElement
.appendChild(dropdownMenu
);
72 this.UICommands
.forEach(function(x
) {
74 var fn
= this[x
[1] + "Window"].bind(this);
75 var e
= new Element("a");
76 e
.addEvent("mousedown", function(e
) { new Event(e
).stop(); });
77 e
.addEvent("click", function() {
82 dropdownMenu
.appendChild(e
);
85 var dropdown
= new Element("div");
86 dropdown
.addClass("dropdown-tab");
87 dropdown
.appendChild(new Element("img", {src: qwebirc
.global
.staticBaseURL
+ "images/icon.png", title: "menu", alt: "menu"}));
88 dropdown
.setStyle("opacity", 1);
90 var dropdownEffect
= new Fx
.Tween(dropdown
, {duration: "long", property: "opacity", link: "chain"});
91 dropdownEffect
.start(0.25);
92 dropdownEffect
.start(1);
93 dropdownEffect
.start(0.33);
94 dropdownEffect
.start(1);
96 this.outerTabs
.appendChild(dropdown
);
97 dropdownMenu
.show = function(x
) {
101 if(dropdownMenu
.visible
) {
105 var top
= this.outerTabs
.getSize().y
;
107 dropdownMenu
.setStyle("left", 0);
108 dropdownMenu
.setStyle("top", top
-1); /* -1 == top border */
109 dropdownMenu
.setStyle("display", "inline-block");
110 dropdownMenu
.visible
= true;
112 document
.addEvent("mousedown", hideEvent
);
114 dropdown
.addEvent("mousedown", function(e
) { new Event(e
).stop(); });
115 dropdown
.addEvent("click", dropdownMenu
.show
);
117 __createDropdownHint: function() {
118 var dropdownhint
= new Element("div");
119 dropdownhint
.addClass("dropdownhint");
120 dropdownhint
.set("text", "Click the icon for the main menu.");
121 dropdownhint
.setStyle("top", this.outerTabs
.getSize().y
+ 5);
123 this.parentElement
.appendChild(dropdownhint
);
124 new Fx
.Morph(dropdownhint
, {duration: "normal", transition: Fx
.Transitions
.Sine
.easeOut
}).start({left: [900, 5]});
126 var hider = function() {
127 new Fx
.Morph(dropdownhint
, {duration: "long"}).start({left: [5, -900]});
130 var hider2 = function() {
131 if(dropdownhint
.hidden
)
133 this.parentElement
.removeChild(dropdownhint
);
134 dropdownhint
.hidden
= 1;
137 this.hideHint
= hider2
;
139 document
.addEvent("mousedown", hider2
);
140 document
.addEvent("keypress", hider2
);
142 createInput: function() {
143 var form
= new Element("form");
144 this.input
.appendChild(form
);
146 form
.addClass("input");
148 var inputbox
= new Element("input");
149 this.addEvent("signedOn", function() {
150 inputbox
.placeholder
= "chat here! you can also use commands, like /JOIN or /HELP";
151 var d = function() { inputbox
.addClass("input-flash"); }.delay(250);
152 var d = function() { inputbox
.removeClass("input-flash"); }.delay(500);
153 var d = function() { inputbox
.addClass("input-flash"); }.delay(750);
154 var d = function() { inputbox
.removeClass("input-flash"); }.delay(1000);
155 var d = function() { inputbox
.addClass("input-flash"); }.delay(1250);
156 var d = function() { inputbox
.removeClass("input-flash"); }.delay(1750);
158 form
.appendChild(inputbox
);
159 this.inputbox
= inputbox
;
160 this.inputbox
.maxLength
= 470;
162 var sendInput = function() {
163 if(inputbox
.value
== "")
166 this.resetTabComplete();
167 this.getActiveWindow().historyExec(inputbox
.value
);
169 inputbox
.placeholder
= "";
172 if(!qwebirc
.util
.deviceHasKeyboard()) {
173 inputbox
.addClass("mobile-input");
174 var inputButton
= new Element("input", {type: "button"});
175 inputButton
.addClass("mobile-button");
176 inputButton
.addEvent("click", function() {
180 inputButton
.value
= ">";
181 this.input
.appendChild(inputButton
);
182 var reflowButton = function() {
183 var containerSize
= this.input
.getSize();
184 var buttonSize
= inputButton
.getSize();
186 var buttonLeft
= containerSize
.x
- buttonSize
.x
- 5; /* lovely 5 */
188 inputButton
.setStyle("left", buttonLeft
);
189 inputbox
.setStyle("width", buttonLeft
- 5);
190 inputButton
.setStyle("height", containerSize
.y
);
192 this.qjsui
.addEvent("reflow", reflowButton
);
194 inputbox
.addClass("keyboard-input");
197 form
.addEvent("submit", function(e
) {
202 inputbox
.addEvent("focus", this.resetTabComplete
.bind(this));
203 inputbox
.addEvent("mousedown", this.resetTabComplete
.bind(this));
205 inputbox
.addEvent("keydown", function(e
) {
207 var cvalue
= inputbox
.value
;
210 resultfn
= this.commandhistory
.upLine
;
211 } else if(e
.key
== "down") {
212 resultfn
= this.commandhistory
.downLine
;
213 } else if(e
.key
== "tab" && !e
.altKey
&& !e
.ctrlKey
&& !e
.shiftKey
) {
215 this.tabComplete(inputbox
);
218 /* ideally alt and other keys wouldn't break this */
219 this.resetTabComplete();
223 this.resetTabComplete();
224 if((cvalue
!= "") && (this.lastcvalue
!= cvalue
))
225 this.commandhistory
.addLine(cvalue
, true);
227 var result
= resultfn
.bind(this.commandhistory
)();
232 this.lastcvalue
= result
;
234 inputbox
.value
= result
;
235 qwebirc
.util
.setAtEnd(inputbox
);
238 setLines: function(lines
) {
239 this.lines
.parentNode
.replaceChild(lines
, this.lines
);
240 this.qjsui
.middle
= this.lines
= lines
;
242 setChannelItems: function(nicklist
, topic
) {
243 if(!$defined(nicklist
)) {
244 nicklist
= this.orignicklist
;
245 topic
= this.origtopic
;
247 this.nicklist
.parentNode
.replaceChild(nicklist
, this.nicklist
);
248 this.qjsui
.right
= this.nicklist
= nicklist
;
250 this.topic
.parentNode
.replaceChild(topic
, this.topic
);
251 this.qjsui
.topic
= this.topic
= topic
;
255 qwebirc
.ui
.QUI
.JSUI
= new Class({
256 Implements: [Events
],
257 initialize: function(class_
, parent
, sizer
) {
258 this.parent
= parent
;
259 this.sizer
= $defined(sizer
)?sizer:parent
;
261 this.class_
= class_
;
264 this.reflowevent
= null;
266 window
.addEvent("resize", function() {
270 applyClasses: function(pos
, l
) {
271 l
.addClass("dynamicpanel");
272 l
.addClass(this.class_
);
274 if(pos
== "middle") {
275 l
.addClass("leftboundpanel");
276 } else if(pos
== "top") {
277 l
.addClass("topboundpanel");
278 l
.addClass("widepanel");
279 } else if(pos
== "topic") {
280 l
.addClass("widepanel");
281 } else if(pos
== "right") {
282 l
.addClass("rightboundpanel");
283 } else if(pos
== "bottom") {
284 l
.addClass("bottomboundpanel");
285 l
.addClass("widepanel");
289 var XE = function(pos
) {
290 var element
= new Element("div");
291 this.applyClasses(pos
, element
);
293 this.parent
.appendChild(element
);
297 this.top
= XE("top");
298 this.topic
= XE("topic");
299 this.middle
= XE("middle");
300 this.right
= XE("right");
301 this.bottom
= XE("bottom");
303 reflow: function(delay
) {
308 $clear(this.reflowevent
);
310 this.reflowevent
= this.__reflow
.delay(delay
, this);
312 __reflow: function() {
313 var bottom
= this.bottom
;
314 var middle
= this.middle
;
315 var right
= this.right
;
316 var topic
= this.topic
;
319 var topicsize
= topic
.getSize();
320 var topsize
= top
.getSize();
321 var rightsize
= right
.getSize();
322 var bottomsize
= bottom
.getSize();
323 var docsize
= this.sizer
.getSize();
325 var mheight
= (docsize
.y
- topsize
.y
- bottomsize
.y
- topicsize
.y
);
326 var mwidth
= (docsize
.x
- rightsize
.x
);
328 topic
.setStyle("top", topsize
.y
);
330 middle
.setStyle("top", (topsize
.y
+ topicsize
.y
));
332 middle
.setStyle("height", mheight
);
333 right
.setStyle("height", mheight
);
337 middle
.setStyle("width", mwidth
);
338 right
.setStyle("top", (topsize
.y
+ topicsize
.y
));
339 right
.setStyle("left", mwidth
);
341 bottom
.setStyle("top", (docsize
.y
- bottomsize
.y
));
342 this.fireEvent("reflow");
344 showChannel: function(state
, nicklistVisible
) {
345 var display
= "none";
349 this.right
.setStyle("display", nicklistVisible
? display : "none");
350 this.topic
.setStyle("display", display
);
352 showInput: function(state
) {
353 this.bottom
.isVisible
= state
;
354 this.bottom
.setStyle("display", state
?"block":"none");
358 qwebirc
.ui
.QUI
.Window
= new Class({
359 Extends: qwebirc
.ui
.Window
,
361 initialize: function(parentObject
, client
, type
, name
, identifier
) {
362 this.parent(parentObject
, client
, type
, name
, identifier
);
364 this.tab
= new Element("a", {"href": "#"});
365 this.tab
.addClass("tab");
366 this.tab
.addEvent("focus", function() { this.blur() }.bind(this.tab
));;
368 this.spaceNode
= document
.createTextNode(" ");
369 parentObject
.tabs
.appendChild(this.tab
);
370 parentObject
.tabs
.appendChild(this.spaceNode
);
372 this.tab
.appendText(name
);
373 this.tab
.addEvent("click", function(e
) {
379 parentObject
.selectWindow(this);
382 if(type
!= qwebirc
.ui
.WINDOW_STATUS
&& type
!= qwebirc
.ui
.WINDOW_CONNECT
) {
383 var tabclose
= new Element("span");
384 tabclose
.set("text", "X");
385 tabclose
.addClass("tabclose");
386 var close = function(e
) {
392 if(type
== qwebirc
.ui
.WINDOW_CHANNEL
)
393 this.client
.exec("/PART " + name
);
397 //parentObject.inputbox.focus();
400 tabclose
.addEvent("click", close
);
401 this.tab
.addEvent("mouseup", function(e
) {
404 if(Browser
.Engine
.trident
)
407 if(e
.event
.button
== button
)
411 this.tab
.appendChild(tabclose
);
414 this.lines
= new Element("div");
415 this.parentObject
.qjsui
.applyClasses("middle", this.lines
);
416 this.lines
.addClass("lines");
417 if(type
!= qwebirc
.ui
.WINDOW_CUSTOM
&& type
!= qwebirc
.ui
.WINDOW_CONNECT
)
418 this.lines
.addClass("ircwindow");
420 this.lines
.addEvent("scroll", function() {
421 this.scrolleddown
= this.scrolledDown();
422 this.scrollpos
= this.getScrollParent().getScroll();
425 if(type
== qwebirc
.ui
.WINDOW_CHANNEL
) {
426 this.topic
= new Element("div");
427 this.topic
.addClass("topic");
428 this.topic
.addClass("tab-invisible");
429 this.topic
.set("html", " ");
430 this.topic
.addEvent("dblclick", this.editTopic
.bind(this));
431 this.parentObject
.qjsui
.applyClasses("topic", this.topic
);
433 this.prevNick
= null;
434 this.nicklist
= new Element("div");
435 this.nicklist
.addClass("nicklist");
436 this.nicklist
.addClass("tab-invisible");
437 this.nicklist
.addEvent("click", this.removePrevMenu
.bind(this));
438 this.parentObject
.qjsui
.applyClasses("nicklist", this.nicklist
);
441 if(type
== qwebirc
.ui
.WINDOW_CHANNEL
)
442 this.updateTopic("");
444 this.nicksColoured
= this.parentObject
.uiOptions
.NICK_COLOURS
;
447 rename: function(name
) {
448 this.tab
.replaceChild(document
.createTextNode(name
), this.tab
.firstChild
);
450 editTopic: function() {
451 if(!this.client
.nickOnChanHasPrefix(this.client
.nickname
, this.name
, "@")) {
452 /* var cmodes = this.client.getChannelModes(channel);
453 if(cmodes.indexOf("t")) {*/
454 alert("Sorry, you need to be a channel operator to change the topic!");
458 var newTopic
= prompt("Change topic of " + this.name
+ " to:", this.topic
.topicText
);
459 if(newTopic
=== null)
462 this.client
.exec("/TOPIC " + newTopic
);
465 this.parentObject
.reflow();
467 onResize: function() {
468 if(this.scrolleddown
) {
469 if(Browser
.Engine
.trident
) {
470 this.scrollToBottom
.delay(5, this);
472 this.scrollToBottom();
474 } else if($defined(this.scrollpos
)) {
475 if(Browser
.Engine
.trident
) {
476 this.getScrollParent().scrollTo(this.scrollpos
.x
, this.scrollpos
.y
);
478 this.getScrollParent().scrollTo
.delay(5, this, [this.scrollpos
.x
, this.scrollpos
.y
]);
482 createMenu: function(nick
, parent
) {
483 var e
= new Element("div");
484 parent
.appendChild(e
);
487 var nickArray
= [nick
];
488 qwebirc
.ui
.MENU_ITEMS
.forEach(function(x
) {
489 if(!x
.predicate
|| x
.predicate
!== true && !x
.predicate
.apply(this, nickArray
))
492 var e2
= new Element("a");
496 e2
.set("text", "- " + x
.text
);
498 e2
.addEvent("focus", function() { this.blur() }.bind(e2
));
499 e2
.addEvent("click", function(ev
) { new Event(ev
.stop()); this.menuClick(x
.fn
); }.bind(this));
503 menuClick: function(fn
) {
505 this.prevNick.removeChild(this.prevNick.menu);
506 this.prevNick.menu = null;
508 fn
.bind(this)(this.prevNick
.realNick
);
509 this.removePrevMenu();
511 moveMenuClass: function() {
514 if(this.nicklist
.firstChild
== this.prevNick
) {
515 this.prevNick
.removeClass("selected-middle");
517 this.prevNick
.addClass("selected-middle");
520 removePrevMenu: function() {
524 this.prevNick
.removeClass("selected");
525 this.prevNick
.removeClass("selected-middle");
526 if(this.prevNick
.menu
)
527 this.prevNick
.removeChild(this.prevNick
.menu
);
528 this.prevNick
= null;
530 nickListAdd: function(nick
, position
) {
531 var realNick
= this.client
.stripPrefix(nick
);
533 var e
= new Element("a");
534 qwebirc
.ui
.insertAt(position
, this.nicklist
, e
);
537 var span
= new Element("span");
538 if(this.parentObject
.uiOptions
.NICK_COLOURS
) {
539 var colour
= realNick
.toHSBColour(this.client
);
541 span
.setStyle("color", colour
.rgbToHex());
543 span
.set("text", nick
);
546 e
.realNick
= realNick
;
548 e
.addEvent("click", function(x
) {
549 if(this.prevNick
== e
) {
550 this.removePrevMenu();
554 this.removePrevMenu();
556 e
.addClass("selected");
557 this.moveMenuClass();
558 e
.menu
= this.createMenu(e
.realNick
, e
);
562 e
.addEvent("focus", function() { this.blur() }.bind(e
));
563 this.moveMenuClass();
566 nickListRemove: function(nick
, stored
) {
567 this.nicklist
.removeChild(stored
);
568 this.moveMenuClass();
570 updateTopic: function(topic
) {
574 t
.removeChild(t
.firstChild
);
578 this.parent(topic
, t
);
581 var e
= new Element("div");
582 e
.set("text", "(no topic set)");
583 e
.addClass("emptytopic");
589 var inputVisible
= this.type
!= qwebirc
.ui
.WINDOW_CONNECT
&& this.type
!= qwebirc
.ui
.WINDOW_CUSTOM
;
591 this.tab
.removeClass("tab-unselected");
592 this.tab
.addClass("tab-selected");
594 this.parentObject
.setLines(this.lines
);
595 this.parentObject
.setChannelItems(this.nicklist
, this.topic
);
596 this.parentObject
.qjsui
.showInput(inputVisible
);
597 this.parentObject
.qjsui
.showChannel($defined(this.nicklist
), this.parentObject
.uiOptions
.SHOW_NICKLIST
);
604 this.parentObject
.inputbox
.focus();
606 if(this.type
== qwebirc
.ui
.WINDOW_CHANNEL
&& this.nicksColoured
!= this.parentObject
.uiOptions
.NICK_COLOURS
) {
607 this.nicksColoured
= this.parentObject
.uiOptions
.NICK_COLOURS
;
609 var nodes
= this.nicklist
.childNodes
;
610 if(this.parentObject
.uiOptions
.NICK_COLOURS
) {
611 for(var i
=0;i
<nodes
.length
;i
++) {
612 var e
= nodes
[i
], span
= e
.firstChild
;
613 var colour
= e
.realNick
.toHSBColour(this.client
);
615 span
.setStyle("color", colour
.rgbToHex());
618 for(var i
=0;i
<nodes
.length
;i
++) {
619 var span
= nodes
[i
].firstChild
;
620 span
.setStyle("color", null);
625 deselect: function() {
628 this.tab
.removeClass("tab-selected");
629 this.tab
.addClass("tab-unselected");
634 this.parentObject
.tabs
.removeChild(this.tab
);
635 this.parentObject
.tabs
.removeChild(this.spaceNode
);
638 addLine: function(type
, line
, colourClass
) {
639 var e
= new Element("div");
642 e
.addClass(colourClass
);
643 } else if(this.lastcolour
) {
644 e
.addClass("linestyle1");
646 e
.addClass("linestyle2");
648 this.lastcolour
= !this.lastcolour
;
650 this.parent(type
, line
, colourClass
, e
);
652 setHilighted: function(state
) {
653 var laststate
= this.hilighted
;
657 if(state
== laststate
)
660 this.tab
.removeClass("tab-hilight-activity");
661 this.tab
.removeClass("tab-hilight-us");
662 this.tab
.removeClass("tab-hilight-speech");
664 switch(this.hilighted
) {
665 case qwebirc
.ui
.HILIGHT_US:
666 this.tab
.addClass("tab-hilight-us");
668 case qwebirc
.ui
.HILIGHT_SPEECH:
669 this.tab
.addClass("tab-hilight-speech");
671 case qwebirc
.ui
.HILIGHT_ACTIVITY:
672 this.tab
.addClass("tab-hilight-activity");