]>
jfr.im git - irc/quakenet/qwebirc.git/blob - js/ui/baseui.js
1 qwebirc
. ui
. WINDOW_STATUS
= 0x01 ;
2 qwebirc
. ui
. WINDOW_QUERY
= 0x02 ;
3 qwebirc
. ui
. WINDOW_CHANNEL
= 0x04 ;
4 qwebirc
. ui
. WINDOW_CUSTOM
= 0x08 ;
5 qwebirc
. ui
. WINDOW_CONNECT
= 0x10 ;
6 qwebirc
. ui
. WINDOW_MESSAGES
= 0x20 ;
8 qwebirc
. ui
. CUSTOM_CLIENT
= "custom" ;
9 qwebirc
. ui
. DEFAULT_HUE
= 210 ; /* nice blue */
11 qwebirc
. ui
. BaseUI
= new Class ({
13 initialize : function ( parentElement
, windowClass
, uiName
, options
) {
14 this . options
= options
;
16 this . windows
= new QHash ();
17 this . clients
= new QHash ();
18 this . windows
. put ( qwebirc
. ui
. CUSTOM_CLIENT
, new QHash ());
19 this . windowArray
= [];
20 this . windowClass
= windowClass
;
21 this . parentElement
= parentElement
;
22 this . parentElement
. addClass ( "qwebirc" );
23 this . parentElement
. addClass ( "qwebirc-" + uiName
);
24 this . firstClient
= false ;
25 this . commandhistory
= new qwebirc
. irc
. CommandHistory ();
28 this . windowFocused
= true ;
30 if ( Browser
. Engine
. trident
) {
31 var checkFocus = function () {
32 var hasFocus
= document
. hasFocus ();
33 if ( hasFocus
!= this . windowFocused
) {
34 this . windowFocused
= hasFocus
;
35 this . focusChange ( hasFocus
);
39 checkFocus
. periodical ( 100 , this );
41 var blur = function () { if ( this . windowFocused
) { this . windowFocused
= false ; this . focusChange ( false ); } }. bind ( this );
42 var focus = function () { if (! this . windowFocused
) { this . windowFocused
= true ; this . focusChange ( true ); } }. bind ( this );
44 /* firefox requires both */
46 document
. addEvent ( "blur" , blur
);
47 window
. addEvent ( "blur" , blur
);
48 document
. addEvent ( "focus" , focus
);
49 window
. addEvent ( "focus" , focus
);
52 qwebirc
. util
. __log = function ( x
) {
54 if ( typeof console
!= "undefined" )
56 this . getActiveWindow (). addLine ( null , x
);
60 newClient : function ( client
) {
61 client
. id
= String ( this . clientId
++);
62 client
. hilightController
= new qwebirc
. ui
. HilightController ( client
);
63 client
. addEvent ( "signedOn" , function () {
64 this . poller
= new qwebirc
. xdomain
. Poller ( this . oobMessage
. bind ( this ));
65 this . fireEvent ( "signedOn" , client
);
67 this . windows
. put ( client
. id
, new QHash ());
68 this . clients
. put ( client
. id
, client
);
69 var w
= this . newWindow ( client
, qwebirc
. ui
. WINDOW_STATUS
, "Status" );
71 if (! this . firstClient
) {
72 this . firstClient
= true ;
73 w
. addLine ( "" , "qwebirc v" + qwebirc
. VERSION
);
74 w
. addLine ( "" , "Copyright (C) 2008-2017 Chris Porter and the qwebirc project." );
75 w
. addLine ( "" , "http://www.qwebirc.org" );
76 w
. addLine ( "" , "Licensed under the GNU General Public License, Version 2." );
80 getClientId : function ( client
) {
81 if ( client
== qwebirc
. ui
. CUSTOM_CLIENT
) {
82 return qwebirc
. ui
. CUSTOM_CLIENT
;
87 getWindowIdentifier : function ( client
, type
, name
) {
88 if ( type
== qwebirc
. ui
. WINDOW_MESSAGES
)
90 if ( type
== qwebirc
. ui
. WINDOW_STATUS
)
93 if ( client
== qwebirc
. ui
. CUSTOM_CLIENT
) /* HACK */
96 return "_" + client
. toIRCLower ( name
);
98 newWindow : function ( client
, type
, name
) {
99 var w
= this . getWindow ( client
, type
, name
);
103 var wId
= this . getWindowIdentifier ( client
, type
, name
);
104 var w
= new this . windowClass ( this , client
, type
, name
, wId
);
105 this . windows
. get ( this . getClientId ( client
)). put ( wId
, w
);
106 this . windowArray
. push ( w
);
110 getWindow : function ( client
, type
, name
) {
111 var c
= this . windows
. get ( this . getClientId ( client
));
115 return c
. get ( this . getWindowIdentifier ( client
, type
, name
));
117 getActiveWindow : function () {
120 getStatusWindow : function ( client
) {
121 return this . windows
. get ( this . getClientId ( client
)). get ( this . getWindowIdentifier ( client
, qwebirc
. ui
. WINDOW_STATUS
));
123 getActiveIRCWindow : function ( client
) {
124 if (! this . active
|| this . active
. type
== qwebirc
. ui
. WINDOW_CUSTOM
) {
125 return this . getStatusWindow ( client
);
130 __setActiveWindow : function ( window
) {
131 this . active
= window
;
133 renameWindow : function ( window
, name
) {
134 if ( this . getWindow ( window
. client
, window
. type
, name
))
137 var clientId
= this . getClientId ( window
. client
);
138 var index
= this . windowArray
. indexOf ( window
);
142 this . windows
. get ( clientId
). remove ( window
. identifier
);
144 var window
= this . windowArray
[ index
];
146 window
. identifier
= this . getWindowIdentifier ( window
. client
, window
. type
, window
. name
);
148 this . windows
. get ( clientId
). put ( window
. identifier
, this . windowArray
[ index
]);
151 this . updateTitle ( window
. name
+ " - " + this . options
. appTitle
);
153 window
. rename ( window
. name
);
156 selectWindow : function ( window
) {
158 this . active
. deselect ();
159 window
. select (); /* calls setActiveWindow */
160 this . updateTitle ( window
. name
+ " - " + this . options
. appTitle
);
162 updateTitle : function ( text
) {
163 document
. title
= text
;
165 nextWindow : function ( direction
) {
166 if ( this . windowArray
. length
== 0 || ! this . active
)
172 var index
= this . windowArray
. indexOf ( this . active
);
176 index
= index
+ direction
;
178 index
= this . windowArray
. length
- 1 ;
179 } else if ( index
>= this . windowArray
. length
) {
183 this . selectWindow ( this . windowArray
[ index
]);
185 prevWindow : function () {
188 __closed : function ( window
) {
190 this . active
= undefined ;
191 if ( this . windowArray
. length
== 1 ) {
192 this . windowArray
= [];
194 var index
= this . windowArray
. indexOf ( window
);
197 } else if ( index
== 0 ) {
198 this . selectWindow ( this . windowArray
[ 1 ]);
200 this . selectWindow ( this . windowArray
[ index
- 1 ]);
205 this . windowArray
= this . windowArray
. erase ( window
);
206 this . windows
. get ( this . getClientId ( window
. client
)). remove ( window
. identifier
);
209 this shouldn't be called by overriding classes!
210 they should implement their own!
211 some form of user input MUST be received before an
212 IRC connection is made, else users are going to get
213 tricked into getting themselves glined
215 loginBox : function ( callback
, initialNickname
, initialChannels
, autoConnect
, autoNick
) {
216 this . postInitialize ();
218 this . addCustomWindow ( "Connect" , qwebirc
. ui
. ConnectPane
, "connectpane" , {
219 initialNickname : initialNickname
, initialChannels : initialChannels
, autoConnect : autoConnect
, callback : callback
, autoNick : autoNick
,
220 uiOptions : this . options
221 }, qwebirc
. ui
. WINDOW_CONNECT
);
223 focusChange : function ( newValue
) {
224 var window_
= this . getActiveWindow ();
225 if ($ defined ( window_
))
226 window_
. focusChange ( newValue
);
228 oobMessage : function ( message
) {
229 var c
= message
. splitMax ( " " , 2 );
237 var d
= c
[ 1 ]. splitMax ( " " , 2 );
243 if ( command
== "SAY" ) {
244 var w
= this . getActiveIRCWindow ();
245 if ($ defined ( w
) && ( w
. type
== qwebirc
. ui
. WINDOW_CHANNEL
|| w
. type
== qwebirc
. ui
. WINDOW_QUERY
)) {
246 w
. client
. exec ( "/SAY " + args
);
253 qwebirc
. ui
. StandardUI
= new Class ({
254 Extends : qwebirc
. ui
. BaseUI
,
255 initialize : function ( parentElement
, windowClass
, uiName
, options
) {
256 this . parent ( parentElement
, windowClass
, uiName
, options
);
258 this . UICommands
= this . __build_menu_items ( options
);
260 this . __styleValues
= { hue : qwebirc
. ui
. DEFAULT_HUE
, saturation : 0 , lightness : 0 , textHue : null , textSaturation : null , textLightness : null };
261 if ($ defined ( this . options
. hue
)) this . __styleValues
. hue
= this . options
. hue
;
262 this . tabCompleter
= new qwebirc
. ui
. TabCompleterFactory ( this );
263 this . uiOptions
= new qwebirc
. ui
. DefaultOptionsClass ( this , options
. uiOptionsArg
);
264 this . customWindows
= new QHash ();
266 if ($ defined ( this . options
. saturation
)) this . __styleValues
. saturation
= this . options
. saturation
;
267 if ($ defined ( this . options
. lightness
)) this . __styleValues
. lightness
= this . options
. lightness
;
268 if ($ defined ( this . options
. tsaturation
)) this . __styleValues
. textSaturation
= this . options
. tsaturation
;
269 if ($ defined ( this . options
. tlightness
)) this . __styleValues
. textLightness
= this . options
. tlightness
;
271 if ($ defined ( this . options
. hue
)) { /* overridden in url */
272 /* ugh... this will go away when we add proper options for hue/sat/light for text and background */
273 this . uiOptions
. setValueByPrefix ( "STYLE_HUE" , this . __styleValues
. hue
);
275 this . __styleValues
. hue
= this . uiOptions
. STYLE_HUE
; /* otherwise copy from serialised store */
277 this . __styleValues
. textHue
= $ defined ( this . options
. thue
) ? this . options
. thue : this . __styleValues
. hue
;
279 document
. addEvent ( "keydown" , this . __handleHotkey
. bind ( this ));
281 __build_menu_items : function ( options
) {
283 var seenAbout
= null ;
285 for ( var i
= 0 ; i
< qwebirc
. ui
. UI_COMMANDS_P1
. length
; i
++)
286 r
. push ([ true , qwebirc
. ui
. UI_COMMANDS_P1
[ i
]]);
287 for ( var i
= 0 ; i
< options
. customMenuItems
. length
; i
++)
288 r
. push ([ false , options
. customMenuItems
[ i
]]);
289 for ( var i
= 0 ; i
< qwebirc
. ui
. UI_COMMANDS_P2
. length
; i
++)
290 r
. push ([ true , qwebirc
. ui
. UI_COMMANDS_P2
[ i
]]);
293 for ( var i
= 0 ; i
< r
. length
; i
++) {
294 var preset
= r
[ i
][ 0 ], c
= r
[ i
][ 1 ];
296 if ( c
[ 0 ] == "About qwebirc" ) { /* HACK */
300 } else if ( seenAbout
) {
307 r2
. push ([ c
[ 0 ], this [ c
[ 1 ] + "Window" ]. bind ( this )]);
309 r2
. push ([ c
[ 0 ], ( function ( c
) { return function () {
310 this . addCustomWindow ( c
[ 0 ], qwebirc
. ui
. URLPane
, "urlpane" , { url : c
[ 1 ]});
311 }. bind ( this ); }). call ( this , c
)]);
317 __handleHotkey : function ( x
) {
319 if (! x
. alt
&& ! x
. control
&& ! x
. shift
&& ! x
. meta
) {
320 if (( x
. key
== "backspace" || x
. key
== "/" ) && ! this . getInputFocused ( x
)) {
323 } else if (! x
. alt
|| x
. control
|| x
. meta
) {
325 } else if ( x
. key
== "a" || x
. key
== "A" ) {
327 var highestIndex
= - 1 ;
330 for ( var i
= 0 ; i
< this . windowArray
. length
; i
++) {
331 var h
= this . windowArray
[ i
]. hilighted
;
337 if ( highestIndex
> - 1 )
338 this . selectWindow ( this . windowArray
[ highestIndex
]);
339 } else if (( x
. key
>= '0' && x
. key
<= '9' ) && ! x
. shift
) {
342 number
= x
. key
- '0' ;
348 if ( number
>= this . windowArray
. length
)
351 this . selectWindow ( this . windowArray
[ number
]);
352 } else if (( x
. key
== "left" || x
. key
== "up" ) && ! x
. shift
) {
355 } else if (( x
. key
== "right" || x
. key
== "down" ) && ! x
. shift
) {
365 getInputFocused : function ( x
) {
366 if ($$( "input" ). indexOf ( x
. target
) == - 1 && $$( "textarea" ). indexOf ( x
. target
) == - 1 )
370 newCustomWindow : function ( name
, select
, type
) {
372 type
= qwebirc
. ui
. WINDOW_CUSTOM
;
374 var w
= this . newWindow ( qwebirc
. ui
. CUSTOM_CLIENT
, type
, name
);
375 w
. addEvent ( "close" , function ( w
) {
376 this . windows
. get ( qwebirc
. ui
. CUSTOM_CLIENT
). remove ( w
. identifier
);
380 this . selectWindow ( w
);
384 addCustomWindow : function ( windowName
, class_
, cssClass
, options
, type
) {
385 if (!$ defined ( options
))
388 if ( this . customWindows
. contains ( windowName
)) {
389 this . selectWindow ( this . customWindows
. get ( windowName
));
393 var d
= this . newCustomWindow ( windowName
, true , type
);
394 this . customWindows
. put ( windowName
, d
);
396 d
. addEvent ( "close" , function () {
397 this . customWindows
. remove ( windowName
);
401 d
. lines
. addClass ( "qwebirc-" + cssClass
);
403 var ew
= new class_ ( d
. lines
, options
);
404 ew
. addEvent ( "close" , function () {
410 embeddedWindow : function () {
411 this . addCustomWindow ( "Add webchat to your site" , qwebirc
. ui
. EmbedWizard
, "embeddedwizard" , { baseURL : this . options
. baseURL
, uiOptions : this . uiOptions
, optionsCallback : function () {
412 this . optionsWindow ();
415 optionsWindow : function () {
416 this . addCustomWindow ( "Options" , qwebirc
. ui
. OptionsPane
, "optionspane" , this . uiOptions
);
418 aboutWindow : function () {
419 this . addCustomWindow ( "About qwebirc" , qwebirc
. ui
. AboutPane
, "aboutpane" , this . uiOptions
);
421 feedbackWindow : function () {
422 this . addCustomWindow ( "Feedback" , qwebirc
. ui
. FeedbackPane
, "feedbackpane" , this . uiOptions
);
424 urlDispatcher : function ( name
, window
) {
425 if ( name
== "embedded" )
426 return [ "a" , this . embeddedWindow
. bind ( this )];
428 if ( name
== "options" )
429 return [ "a" , this . optionsWindow
. bind ( this )];
431 /* doesn't really belong here */
432 if ( name
== "whois" ) {
433 return [ "span" , function ( nick
) {
434 if ( this . uiOptions
. QUERY_ON_NICK_CLICK
) {
435 window
. client
. exec ( "/QUERY " + nick
);
437 window
. client
. exec ( "/WHOIS " + nick
);
444 tabComplete : function ( element
, backwards
) {
445 this . tabCompleter
. tabComplete ( element
, backwards
);
447 resetTabComplete : function () {
448 this . tabCompleter
. reset ();
450 setModifiableStylesheet : function ( name
) {
451 this . __styleSheet
= new qwebirc
. ui
. style
. ModifiableStylesheet ( qwebirc
. global
. staticBaseURL
+ "css/" + ( QWEBIRC_DEBUG
? "debug/" : "" ) + name
+ qwebirc
. FILE_SUFFIX
+ ".mcss" );
452 this . setModifiableStylesheetValues ({});
454 setModifiableStylesheetValues : function ( values
) {
455 for ( var k
in values
)
456 this . __styleValues
[ k
] = values
[ k
];
458 if (!$ defined ( this . __styleSheet
))
461 var back
= { hue : this . __styleValues
. hue
, lightness : this . __styleValues
. lightness
, saturation : this . __styleValues
. saturation
};
463 if (!$ defined ( this . __styleValues
. textHue
) && !$ defined ( this . __styleValues
. textLightness
) && !$ defined ( this . __styleValues
. textSaturation
)) {
466 front
= { hue : Number ( this . __styleValues
. textHue
), lightness : Number ( this . __styleValues
. textLightness
), saturation : Number ( this . __styleValues
. textSaturation
)}
473 this . __styleSheet
. set ( function () {
474 var mode
= arguments
[ 0 ];
476 var t
= colours
[ arguments
[ 2 ]];
477 var x
= new Color ( arguments
[ 1 ]);
478 var c
= x
. setHue ( t
. hue
). setSaturation ( x
. hsb
[ 1 ] + t
. saturation
). setBrightness ( x
. hsb
[ 2 ] + t
. lightness
);
479 if ( c
== "255,255,255" ) /* IE confuses white with transparent... */
482 return "rgb(" + c
+ ")" ;
483 } else if ( mode
== "o" ) {
484 return this . uiOptions
[ arguments
[ 1 ]] ? arguments
[ 2 ] : arguments
[ 3 ];
490 qwebirc
. ui
. NotificationUI
= new Class ({
491 Extends : qwebirc
. ui
. StandardUI
,
492 initialize : function ( parentElement
, windowClass
, uiName
, options
) {
493 this . parent ( parentElement
, windowClass
, uiName
, options
);
495 this . __beeper
= new qwebirc
. ui
. Beeper ( this . uiOptions
);
496 this . __flasher
= new qwebirc
. ui
. Flasher ( this . uiOptions
);
497 this . __notifier
= new qwebirc
. ui
. Notifier ( this . uiOptions
);
499 this . cancelFlash
= this . __flasher
. cancelFlash
. bind ( this . __flasher
);
502 this . __beeper
. beep ();
504 notify : function ( title
, message
, callback
) {
505 this . __beeper
. beep ();
506 this . __flasher
. flash ();
507 this . __notifier
. notify ( title
, message
, callback
);
509 setBeepOnMention : function ( value
) {
511 this . __beeper
. soundInit ();
513 setNotifications : function ( value
) {
514 this . __notifier
. setEnabled ( value
);
516 updateTitle : function ( text
) {
517 if ( this . __flasher
. updateTitle ( text
))
520 focusChange : function ( value
) {
522 this . __flasher
. focusChange ( value
);
523 this . __notifier
. focusChange ( value
);
527 qwebirc
. ui
. QuakeNetUI
= new Class ({
528 Extends : qwebirc
. ui
. NotificationUI
,
529 urlDispatcher : function ( name
, window
) {
530 if ( name
== "qwhois" ) {
531 return [ "span" , function ( auth
) {
532 if ($ defined ( this . parentObject
. options
. accountWhoisCommand
))
533 this . client
. exec ( this . parentObject
. options
. accountWhoisCommand
+ auth
);
536 return this . parent ( name
, window
);
539 if (! qwebirc
. auth
. loggedin ())
541 if ( confirm ( "Log out?" )) {
542 this . clients
. each ( function ( k
, v
) {
543 v
. quit ( "Logged out" );
547 var foo = function () { document
. location
= qwebirc
. global
. dynamicBaseURL
+ "auth?logout=1" ; };
553 qwebirc
. ui
. RootUI
= qwebirc
. ui
. QuakeNetUI
;
555 qwebirc
. ui
. RequestTransformHTML = function ( options
) {
556 var HREF_ELEMENTS
= {
560 var update
= options
. update
;
561 var onSuccess
= options
. onSuccess
;
563 var fixUp = function ( node
) {
564 if ( node
. nodeType
!= 1 )
567 var tagName
= node
. nodeName
. toUpperCase ();
568 if ( HREF_ELEMENTS
[ tagName
]) {
569 var attr
= node
. getAttribute ( "transform_attr" );
570 var value
= node
. getAttribute ( "transform_value" );
571 if ($ defined ( attr
) && $ defined ( value
)) {
572 node
. removeAttribute ( "transform_attr" );
573 node
. removeAttribute ( "transform_value" );
574 node
. setAttribute ( attr
, qwebirc
. global
. staticBaseURL
+ value
);
578 for ( var i
= 0 ; i
< node
. childNodes
. length
; i
++)
579 fixUp ( node
. childNodes
[ i
]);
582 delete options
[ "update" ];
583 options
. onSuccess = function ( tree
, elements
, html
, js
) {
584 var container
= new Element ( "div" );
585 container
. set ( "html" , html
);
589 while ( container
. childNodes
. length
> 0 ) {
590 var x
= container
. firstChild
;
591 container
. removeChild ( x
);
592 update
. appendChild ( x
);
597 return new Request
. HTML ( options
);