diff options
Diffstat (limited to 'mod/beechat/views')
17 files changed, 5047 insertions, 0 deletions
| diff --git a/mod/beechat/views/default/beechat/beechat.js.php b/mod/beechat/views/default/beechat/beechat.js.php new file mode 100644 index 000000000..09f4e8852 --- /dev/null +++ b/mod/beechat/views/default/beechat/beechat.js.php @@ -0,0 +1,2498 @@ +/** + * Beechat + *  + * @package beechat + * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html GNU Public License version 2 + * @author Beechannels <contact@beechannels.com> + * @copyright Beechannels 2007-2010 + * @link http://beechannels.com/ + */  + +/** Globals + * + */ +g_beechat_user = null; +g_beechat_roster_items = null; +g_beechat_rooms = new Array(); + +function debugXMPP(msg) { +	try { +		//console.log(msg) +	} +		catch (err) { +	} +	//$('#layout_footer').html($('#layout_footer').html()+'<br/>'+msg); +} + +/** Class: BeeChat + *  An object container for all BeeChat mod functions + * + */ +BeeChat = { +    BOSH_SERVICE: '/http-bind/', +    DOMAIN: '<?php echo $vars['config']->chatsettings['domain'] ?>', +    RESOURCE: 'beebac', +    INACTIVITY_PERIOD_LENGTH: 60, + +    NS: { +	CHAT_STATES: 'http://jabber.org/protocol/chatstates' +    }, + +    Message: { +	Types: { +	    NORMAL: 'normal', +	    CHAT: 'chat', +	    GROUPCHAT: 'groupchat', +	    HEADLINE: 'headline', +	    ERROR: 'error' +	}, + +	ChatStates: { +	    COMPOSING: 'composing', +	    PAUSED: 'paused', +	    ACTIVE: 'active', +	    INACTIVE: 'inactive', +	    GONE: 'gone' +	} +    }, + +    IQ: { +	Types: { +	    GET: 'get', +	    RESULT: 'result', +	    SET: 'set', +	    ERROR: 'error' +	} +    }, + +    Presence: { +	Types: { +	    UNAVAILABLE: 'unavailable', +	    SUBSCRIBE: 'subscribe', +	    SUBSCRIBED: 'subscribed', +	    UNSUBSCRIBE: 'unsubscribe', +	    UNSUBSCRIBED: 'unsubscribed', +	    PROBE: 'probe', +	    ERROR: 'error' +	}, + +	ChildElements: { +	    SHOW: 'show', +	    STATUS: 'status', +	    PRIORITY: 'priority' +	}, + +	ShowElements: { +	    CHAT: 'chat', +	    DND: 'dnd', +	    AWAY: 'away', +	    XA: 'xa' +	} +    }, + +    Roster: { +	DEFAULT_GROUP: 'Contacts' +    }, + + +    Events: { +	Identifiers: { +	    UPDATE_CONNECTION_STATE: 0, +	    UPDATE_ROSTER: 1, +	    RECV_PRESENCE: 2, +	    RECV_CHAT_MESSAGE: 3 +	}, +	Messages: { +	    ConnectionStates: { +		CONNECTING: "<?php echo elgg_echo('beechat:connection:state:connecting'); ?>", +		AUTHENTICATING: "<?php echo elgg_echo('beechat:connection:state:authenticating'); ?>", +		FAILED: "<?php echo elgg_echo('beechat:connection:state:failed'); ?>", +		DISCONNECTING: "<?php echo elgg_echo('beechat:connection:state:disconnecting'); ?>", +		OFFLINE: "<?php echo elgg_echo('beechat:connection:state:offline'); ?>", +		ONLINE: "<?php echo elgg_echo('beechat:connection:state:online'); ?>" +	    } +	} +    } +}; + + +/** Class: BeeChat.Core + *  An object container for all BeeChat Core functions + * + */ +BeeChat.Core = { +    ReferenceTables: { +	AvailabilityRates: { +	    AVAILABLE: 0, +	    ONLINE: 0, +	    CHAT: 0, +	    DND: 1, +	    AWAY: 2, +	    XA: 3, +	    UNAVAILABLE: 10, +	    OFFLINE: 10 +	} +    } +}; + + +/** Class: BeeChat.Core.User + *  Create a BeeChat.Core.User object + * + *  Parameters: + *    (String) jid - The user's jabber id + * + *  Returns: + *    A new BeeChat.Core.User. + */ +BeeChat.Core.User = function(jid) +{ +    if (!(this instanceof arguments.callee)) +	return new BeeChat.Core.User(jid); + +    /** Private members +     * +     */ +    var _connection = null; +    var _attached = false; +    var _initialized = false; +    var _jid = null; +    var _roster = null; +    var _msgTemp = []; +    var _funcs = []; + +    /** Constructor +     * +     */ +    this.init = function(jid) +    { +	_jid = jid; +	_roster = new BeeChat.Core.Roster(); +    } + +    /** Accessors +     * +     */ +    this.getConnection = function() +    { +	return _connection; +    } + +    this.getJid = function() +    { +	return _jid; +    } + +    this.getRoster = function() +    { +	return _roster; +    } + +    this.isAttached = function() +    { +	return _attached; +    } + +    this.isInitialized = function() +    { +	return _initialized; +    } + +    /** Mutators +     * +     */ +    this.setInitialized = function(isInitialized) +    { +	_initialized = isInitialized; +    } + +    /** Function: addObserver +     *  Add an observer for a specified type of event +     * +     *  Parameters: +     *    (BeeChat.Events.Identifiers) eventType - The type of event to observer +     *    (Object) pFunc - A function to call when the event will be triggered +     */ +    this.addObserver = function(eventType, pFunc) +    { +	if (jQuery.inArray(pFunc, _funcs) == -1) { +	    if (!_funcs[eventType]) +		_funcs[eventType] = []; +	    _funcs[eventType].push(pFunc); +	} +    } + +    /** Function: removeObserver +     *  Remove an observer +     * +     *  Parameters: +     *    (Object) pFunc - The registered function +     */ +    this.removeObserver = function(pFunc) +    { +	var index = null; + +	for (var key in _funcs) { +	    if (typeof _funcs[key] != 'object') +		continue; +	    if ((index = jQuery.inArray(pFunc, _funcs[key])) != -1) +		_funcs.splice(index, 1); +	} +    } + +    /** Function: connect +     *  Connect the user to the BOSH service +     * +     *  Parameters: +     *    (String) password - The user's password +     * +     */ +    this.connect = function(password) +    { +	debugXMPP('connect'); +	if (_connection == null) +	    _connection = new Strophe.Connection(BeeChat.BOSH_SERVICE); +	_connection.connect(_jid, password, _onConnect); +    } + +    /** Function: attach +     *  Attach user's connection to an existing XMPP session +     * +     *  Parameters: +     *    (String) sid - The SID of the existing XMPP session +     *    (String) rid - The RID of the existing XMPP session +     */ +    this.attach = function(sid, rid) +    { +	if (_connection == null) { +	    _connection = new Strophe.Connection(BeeChat.BOSH_SERVICE); +	} +	_connection.attach(_jid, sid, rid, _onConnect); +	_attached = true; +	_onConnect(Strophe.Status.CONNECTED); +    } + +    /** Function: disconnect +     *  Disconnect the user from the BOSH service +     * +     */ +    this.disconnect = function() +    { +	debugXMPP('disconnect'); +	if (_connection != null) { +	    _connection.disconnect(); +	    _connection = null; +	} +    } + +    /** Function: requestSessionPause +     *  Request a session pause to the server connection manager +     * +     */ +    this.requestSessionPause = function() +    { +	var req = $build('body', { +		rid: _connection.rid, +		sid: _connection.sid, +		pause: BeeChat.INACTIVITY_PERIOD_LENGTH, +		xmlns: Strophe.NS.HTTPBIND +	    }); + +	_attached = false; +	_connection.send(req.tree()); +    } + +    /** Function: requestRoster +     *  Request a new roster to the server +     * +     */ +    this.requestRoster = function() +    { +	var req = $iq({from: _jid, type: BeeChat.IQ.Types.GET}) +	.c('query', {xmlns: Strophe.NS.ROSTER}); + +	_connection.send(req.tree()); +    } + +    /** Function: sendInitialPresence +     *  Send initial presence to the server in order to signal availability for communications +     * +     */ +    this.sendInitialPresence = function() +    { +	_connection.send($pres().tree()); +	_initialized = true; +    } + +    /** Function: sendChatMessage +     *  Send a chat message to the server +     * +     *  Parameters: +     *    (String) addressee - The addressee of the chat message +     *    (String) msg - The chat message +     * +     */ +    this.sendChatMessage = function(addressee, msg, msgtype) +    { +	if (msgtype == null) +		msgtype = BeeChat.Message.Types.CHAT; +	var req = $msg({ +		type: msgtype, +		to: addressee, +		from: _connection.jid +	    }).c('body').t(msg).up().c(BeeChat.Message.ChatStates.ACTIVE, {xmlns: BeeChat.NS.CHAT_STATES}); + +	_connection.send(req.tree()); +    } + +    /** Function: sendChatStateMessage +     *  Send a chat state message to the server +     * +     *  Parameters: +     *    (String) addressee - The addressee of the chat state message +     *    (BeeChat.Message.ChatsState) state - The chat state that will be send +     * +     */ +    this.sendChatStateMessage = function(addressee, state) +    { +	var req = $msg({ +		type: BeeChat.Message.Types.CHAT, +		to: addressee, +		from: _connection.jid +	    }).c(state, {xmlns: BeeChat.NS.CHAT_STATES}); + +	_connection.send(req.tree()); +    } + +    /** Function: sendPresenceAvailabiliy +     *  Send a detailed presence stanza to the server +     * +     *  Parameters: +     *    (BeeChat.Presence.ShowElements) availability - The availability status +     *    (String) details - Detailed status information +     * +     */ +    this.sendPresenceAvailability = function(availability, details) +    { +	var req = $pres() +	.c(BeeChat.Presence.ChildElements.SHOW).t(availability).up() +	.c(BeeChat.Presence.ChildElements.STATUS).t(details).up() +	.c(BeeChat.Presence.ChildElements.PRIORITY).t('1'); + +	_connection.send(req.tree()); +    } + +    /** PrivateFunction: _fire +     *  Triggers registered funcs of registered observers for a specified type of event +     * +     */ +    function _fire(eventType, data, scope) +    { +	if (_funcs[eventType] != undefined) { +	    for (var i = 0; i < _funcs[eventType].length; i++) +		_funcs[eventType][i].call((scope || window), data); +	} +    } +    this.joinRoom = function(roomname, room_guid) { +	    var roomJid = roomname; +	    _connection['muc'].join(roomJid, BeeChat.UI.Resources.Strings.ChatMessages.SELF, false, false, ''); +	    if (!(roomJid in g_beechat_rooms)) { +		    g_beechat_rooms[roomJid] = room_guid; +		    $.ajax({ +			url: BeeChat.UI.addActionTokens('<?php echo $vars['url'] . "action/beechat/join_groupchat?group_guid="; ?>'+room_guid, '&'), +			async: true   }); +	    } + + +    } + +    this.reconnectRooms = function() { +	$('#' + BeeChat.UI.Resources.Elements.ID_DIV_CHATBOXES).children().each(function() { +		if (roomJid in g_beechat_rooms) +			delete g_beechat_rooms[roomJid]; +		var contactBareJid = $(this).attr('bareJid'); +		var isroom = ($(this).attr('isroom')=='true')?true:false; +		if (isroom) { +		    _connection['muc'].join(contactBareJid, BeeChat.UI.Resources.Strings.ChatMessages.SELF, false, false, ''); +		} +	}); +    } + +    this.leaveRoom = function(roomJid) { +	    if (roomJid in g_beechat_rooms) { +			$.ajax({ +				url: BeeChat.UI.addActionTokens('<?php echo $vars['url'] . "action/beechat/leave_groupchat?group_guid="; ?>'+g_beechat_rooms[roomJid], '&'), +				async: true   }); + +	    } +	    _connection['muc'].leave(roomJid, BeeChat.UI.Resources.Strings.ChatMessages.SELF, function(){}); +    } + +    /** PrivateFunction: _onConnect +     *  Connection state manager +     * +     *  Parameters: +     *    (Strophe.Status) status - A Strophe connection status constant +     * +     */ +    function _onConnect(status) +    { +	var msg = null; + +	if (status == Strophe.Status.CONNECTING)  +{ +	    msg = BeeChat.Events.Messages.ConnectionStates.CONNECTING; +	} +	else if (status == Strophe.Status.AUTHENTICATING) { +	    msg = BeeChat.Events.Messages.ConnectionStates.AUTHENTICATING; +	} +	else if (status == Strophe.Status.AUTHFAIL) +	    msg = BeeChat.Events.Messages.ConnectionStates.FAILED; + 	else if (status == Strophe.Status.CONNFAIL) +	    msg = BeeChat.Events.Messages.ConnectionStates.FAILED; + 	else if (status == Strophe.Status.DISCONNECTING) +	    msg = BeeChat.Events.Messages.ConnectionStates.DISCONNECTING; + 	else if (status == Strophe.Status.DISCONNECTED) +	    msg = BeeChat.Events.Messages.ConnectionStates.OFFLINE; + 	else if (status == Strophe.Status.CONNECTED) { +	    msg = BeeChat.Events.Messages.ConnectionStates.ONLINE; +	    _connection.addHandler(_onIQResult, null, 'iq', BeeChat.IQ.Types.RESULT, null, null); +	    _connection.addHandler(_onPresence, null, 'presence', null, null, null); +	    _connection.addHandler(_onMessageChat, null, 'message', BeeChat.Message.Types.CHAT, null, null); +	    _connection.addHandler(_onMessageChatRoom, null, 'message', BeeChat.Message.Types.GROUPCHAT, null, null); +	} + +	_fire(BeeChat.Events.Identifiers.UPDATE_CONNECTION_STATE, msg); +    } + +    /** PrivateFunction: _onIQResult +     *  Manage received IQ stanza of 'result' type +     * +     *  Parameters: +     *    (XMLElement) iq - The iq stanza received +     * +     */ +    function _onIQResult(iq) +    { +	_roster.updateFromIQResult(iq); +	_fire(BeeChat.Events.Identifiers.UPDATE_ROSTER, _roster.getItems()); + +	return true; +    } + +    /** PrivateFunction: _onPresence +     *  Manage received presence stanza +     * +     *  Parameters: +     *    (XMLElement) presence - The presence stanza received +     * +     */ +    function _onPresence(presence) +    { +	var xquery = presence.getElementsByTagName("x"); +	debugXMPP('_onPresence'+xquery); +	if (xquery.length > 0) +	{ +	    //Ignore MUC user protocol +	    for (var i = 0; i < xquery.length; i++) +	    { +		var xmlns = xquery[i].getAttribute("xmlns"); +		if (xmlns && xmlns.match(Strophe.NS.MUC + '#user')) +		{ +			var contactBareJid = $(presence).attr('from').split('/')[0]; +			var userNick = $(presence).attr('from').split('/')[1]; +			var chatBoxElm = BeeChat.UI.ChatBoxes.getChatBoxElm(contactBareJid); +			if ($(presence).attr('type') != 'unavailable') { +				BeeChat.UI.ChatBoxes.updateRoster(contactBareJid, userNick, presence); +			} +			else { +				if (chatBoxElm.length) { +					BeeChat.UI.ChatBoxes.updateRoster(contactBareJid, userNick, presence); +				} +			} +			return true; +		} +	 +		if (xmlns && xmlns.match(Strophe.NS.MUC)) +		{ +			var contactBareJid = $(presence).attr('from').split('/')[0]; +			var chatBoxElm = BeeChat.UI.ChatBoxes.getChatBoxElm(contactBareJid); + +		        if ($(presence).attr('type') != 'unavailable' && $(presence).attr('type') != 'error') { +				if (chatBoxElm.length == 0) { +					    BeeChat.UI.ScrollBoxes.add(contactBareJid); +				} +			} +			return true; +		} + +	     } +	} + +	if (Strophe.getBareJidFromJid($(presence).attr('from')).toLowerCase() != Strophe.getBareJidFromJid(_jid).toLowerCase()) { +	    _roster.updateFromPresence(presence); +	} +	_fire(BeeChat.Events.Identifiers.RECV_PRESENCE, _roster.getOnlineItems()); +	return true; +    } + +    /** PrivateFunction: _onMessageChat +     *  Manage received message stanza of 'chat' type +     * +     *  Parameters: +     *    (XMLElement) message - The message stanza received +     * +     */ +    function _onMessageChatRoom(message) +    { +	var roomJid = $(message).attr('from').split('/'); +	 +//	BeeChat.UI.ChatBoxes.updateChatState($(message).attr('from'), message); +	BeeChat.UI.ChatBoxes.update(roomJid[0], roomJid[1], Strophe.getText($(message).find('body')[0]), true); + +        return true; +    } + +    function _onMessageChat(message) +    { +	var data = { +	    contactBareJid: Strophe.getBareJidFromJid($(message).attr('from')), +	    msg: message +	}; +	_msgTemp.push(data); +	//alert("message"); +	if (_initialized == true) { +	    for (var key in _msgTemp) { +		if (typeof _msgTemp[key] != 'object') +		    continue; +		_fire(BeeChat.Events.Identifiers.RECV_CHAT_MESSAGE, _msgTemp[key]); +		_msgTemp.shift(); +	    } +	} + +	return true; +    } + +    this.init(jid); +}; + + +/** Constructor: BeeChat.Core.Roster + *  Create a BeeChat.Core.Roster object + * + *  Parameters: + *    (Object) items - The roster's items in object notation + * + *  Returns: + *    A new BeeChat.Core.Roster. + */ +BeeChat.Core.Roster = function() +{ +    if (!(this instanceof arguments.callee)) +	return new BeeChat.Core.Roster(); + +    /** Private members +     * +     */ +    _items = null; + + +    /** Constructor +     * +     */ +    this.init = function() +    { +	_items = (arguments.length > 0) ? arguments[0] : {}; +    } + +    /** Accessors +     * +     */ +    this.getItems = function() +    { +	return _items; +    } + +    /** Mutators +     * +     */ +    this.setItems = function(items) +    { +	for (var key in items) { +	    _items[key] = new BeeChat.Core.RosterItem(items[key]); +		var contactBareJid = items[key].bareJid; +		var chatBoxElm = BeeChat.UI.ChatBoxes.getChatBoxElm(contactBareJid); +		var status = items[key].status; +                        /*if (status != 'unavailable' && status != 'error') { +                                if (chatBoxElm.length == 0) { +                                            BeeChat.UI.ScrollBoxes.add(contactBareJid); +                                } +			}*/ + +	} +    } + +    this.setIcons = function(icons) +    { +	if (_items) { +	    for (var key in icons) { +	        if (_items[key]) { +	            _items[key].icon_small = icons[key].small; +	            _items[key].icon_tiny = icons[key].tiny; +		} +	    } +	} +    } + +    this.setStatuses = function(statuses) +    { +	if (_items) { +	    for (var key in statuses)  { +		if (_items[key]) { +		    _items[key].status = statuses[key]; +		} +	    } +	} +    } + +    /** Function: updateFromIQResult +     *  Update the roster items from an IQ result stanza +     * +     *  Parameters: +     *    (XMLElement) iq - The IQ result stanza +     */ +    this.updateFromIQResult = function(iq) +    { +	$(iq).find('item').each(function() { +		var attr = { +		    bareJid: Strophe.getBareJidFromJid($(this).attr('jid')).toLowerCase(), +		    name: $(this).attr('name'), +		    subscription: $(this).attr('subscription'), +		    groups: [], +		    presences: {} +		}; + +		$(this).find('group').each(function() { +			attr['groups'].push($(this).text()); +		    }); + +		if (attr['groups'].length == 0) +		    attr['groups'].push(BeeChat.Roster.DEFAULT_GROUP); + +		if (!_items[attr.bareJid]) +		    _items[attr.bareJid] = new BeeChat.Core.RosterItem(attr); +		else { +		    _items[attr.bareJid].bareJid = attr.bareJid; +		    _items[attr.bareJid].name = attr.name; +		    _items[attr.bareJid].subscription = attr.subscription; +		    _items[attr.bareJid].groups = attr.groups; +		} +	    }); +    } + +    /** Function: updateFromPresence +     *  Update the roster items from a presence stanza +     * +     *  Parameters: +     *    (XMLElement) presence - The presence stanza +     * +     *  Returns: +     *    (String) The bare jid of the roster item who updated his presence +     */ +    this.updateFromPresence = function(presence) +    { +	var jid = $(presence).attr('from').toLowerCase(); +	var attr = { +	    bareJid: Strophe.getBareJidFromJid(jid), +	    name: null, +	    subscription: null, +	    groups: null, +	    presences: {} +	}; + +	attr.presences[jid] = {}; +	attr.presences[jid].type = (!$(presence).attr('type')) ? 'available' : $(presence).attr('type'); +	//alert($(presence).attr('from')+presence.toString()); +	//alert("presencetype"+attr.presences[jid].type); + +	if (attr.presences[jid].type == 'available') { +	    $(presence).children().each(function() { +		    if (this.tagName == BeeChat.Presence.ChildElements.SHOW) +			attr.presences[jid].show = $(this).text(); +		    if (this.tagName == BeeChat.Presence.ChildElements.STATUS) +			attr.presences[jid].status = $(this).text(); +		}); + +	    if (!attr.presences[jid].show) +		attr.presences[jid].show = 'chat'; +	} else { +	    attr.presences[jid].show = 'offline'; +	} + +	if (!_items[attr.bareJid]) +	    _items[attr.bareJid] = new BeeChat.Core.RosterItem(attr); +	else +	    _items[attr.bareJid].presences[jid] = attr.presences[jid]; +    } + +    /** Function: getOnlineItems +     * +     * +     */ +    this.getOnlineItems = function() +    { +	var sortedOnlineBareJid = []; +	var sortedOnlineItems = {}; + +	for (var key in _items) { +	    if (typeof _items[key] != 'object') +		continue; + +	    var pres = _items[key].getStrongestPresence(); + +	    if (pres != null && pres.type == 'available') { +		sortedOnlineBareJid.push(key); +	    } +	} + +	if (sortedOnlineBareJid.length > 1) { +	    sortedOnlineBareJid.sort(); +	    sortedOnlineBareJid.sort(statusSort); +	} + +	for (var key in sortedOnlineBareJid) { +	    sortedOnlineItems[sortedOnlineBareJid[key]] = _items[sortedOnlineBareJid[key]]; +	} + +	return (sortedOnlineItems); +    } + +    /** Function: getSizeOnlineItems +     *  Return the number of available items +     * +     *  Returns: +     *    (int) The number of available items +     */ +    this.getSizeOnlineItems = function() +    { +	var n = 0; + +	for (var key in _items) { +	    if (typeof _items[key] != 'object') +		continue; + +	    var pres = _items[key].getStrongestPresence(); + +	    if (pres != null && pres.type == 'available') +		++n; +	} +	return (n); +    } + +    /** Function: getItemsUsernamesAsList +     * +     */ +    this.getItemsUsernamesAsList = function() +    { +	var data = ''; + +	for (var key in _items) { +	    if (typeof _items[key] != 'object') +		continue; +	    data = data + Strophe.getBareJidFromJid(key) + ','; +	  //  data = data + Strophe.getNodeFromJid(key) + ','; +	} + +	return (data); +    } + +    /** PrivateFunction: statusSort +     * +     */ +    function statusSort(x, y) +    { +	var xPres = _items[x].getStrongestPresence(); +	var yPres = _items[y].getStrongestPresence(); + +	if (xPres != null && yPres != null) +	    return (BeeChat.Core.Roster.Utils.comparePresences(xPres, yPres)); +	return (0); +    } + +    this.init(); +}; + +BeeChat.Core.Roster.Utils = { + +    /** Function: comparePresences +     *  Compare the two presences x and y +     * +     *  Parameters: +     *    (Object) xPres - The x presence in object notation +     *    (Object) yPres - The y presence in object notation +     * +     *  Returns: +     *    0 if presence are equal, 1 if x > y, -1 if y > x +     * +     *  Note: +     *    Presences are tagged in the following order: +     *      ONLINE < DND < AWAY < XA < OFFLINE +     * +     */ +    comparePresences: function(xPres, yPres) +    { +	var xRate = 0; +	var yRate = 0; + +	if (xPres.type == 'unavailable') +	    xRate += BeeChat.Core.ReferenceTables.AvailabilityRates[xPres.type.toUpperCase()]; +	if (yPres.type == 'unavailable') +	    yRate += BeeChat.Core.ReferenceTables.AvailabilityRates[yPres.type.toUpperCase()]; + +	if (xPres.show != null) +	    xRate += BeeChat.Core.ReferenceTables.AvailabilityRates[xPres.show.toUpperCase()]; +	if (yPres.show != null) +	    yRate =+ BeeChat.Core.ReferenceTables.AvailabilityRates[yPres.show.toUpperCase()]; + +	if (xRate > yRate) +	    return (1); +	else if (xRate == yRate) +	    return (0); +	return (-1); +    } +}; + + +/** Constructor: BeeChat.Core.RosterItem + *  Create a BeeChat.Core.RosterItem object + * + *  Parameters: + *    (Object) attr - The RosterItem's attributes in object notation + * + *  Returns: + *    A new BeeChat.Core.RosterItem. + */ +BeeChat.Core.RosterItem = function() +{ +    this.bareJid = (arguments.length > 0) ? arguments[0].bareJid : null; +    this.name = (arguments.length > 0) ? arguments[0].name : null; +    this.subscription = (arguments.length > 0) ? arguments[0].subscription : null; +    this.groups = (arguments.length > 0) ? arguments[0].groups : null; +    this.presences = (arguments.length > 0) ? arguments[0].presences : null; +    this.icon_small = (arguments.length > 0) ? arguments[0].icon_small : null; +    this.icon_tiny = (arguments.length > 0) ? arguments[0].icon_tiny : null; +    this.status = (arguments.length > 0) ? arguments[0].status : null; +}; +BeeChat.Core.RosterItem.prototype = { +    /** Function: getStrongestPresence +     *  Return the strongest presence of the RosterItem +     * +     */ +    getStrongestPresence: function() +    { +	var res = null; + +	for (var key in this.presences) { +	    if (typeof this.presences[key] != 'object') +		continue; +	    if (res == null) +		res = this.presences[key]; +	    else +		if (BeeChat.Core.Roster.Utils.comparePresences(this.presences[key], res) == -1) +		    res = this.presences[key]; +	} +	return (res); +    } +}; + + +/** Class: BeeChat.UI + *  An object container for all BeeChat UI functions + * + */ +BeeChat.UI = { +    HAS_FOCUS: true, + +    Resources: { +	Paths: { +	    ICONS: '<?php echo $vars['config']->url; ?>mod/beechat/graphics/icons/', +	    MEMBER_PROFILE: '<?php echo $vars['url']; ?>profile/' +	}, + +	Sounds: { +	    NEW_MESSAGE: 'beechat_sounds_new_message' +	}, + +	/* +	Cookies: { +	    DOMAIN: 'beechannels.com', +	    FILENAME_CONN: 'beechat_conn' +	}, +	*/ + +	Emoticons: { +    	    FILENAME_SMILE: 'emoticon_smile.png', +	    FILENAME_UNHAPPY: 'emoticon_unhappy.png', +	    FILENAME_GRIN: 'emoticon_grin.png', +	    FILENAME_EVILGRIN: 'emoticon_evilgrin.png', +	    FILENAME_SURPRISED: 'emoticon_surprised.png', +	    FILENAME_TONGUE: 'emoticon_tongue.png', +	    FILENAME_WINK: 'emoticon_wink.png' +	}, + +	Strings: { +	    Availability: { +		AVAILABLE: "<?php echo elgg_echo('beechat:availability:available'); ?>", +		CHAT: "<?php echo elgg_echo('beechat:availability:available'); ?>", +		ONLINE: "<?php echo elgg_echo('beechat:availability:available'); ?>", +		DND: "<?php echo elgg_echo('beechat:availability:dnd'); ?>", +		AWAY: "<?php echo elgg_echo('beechat:availability:away'); ?>", +		XA:"<?php echo elgg_echo('beechat:availability:xa'); ?>", +		OFFLINE: "<?php echo elgg_echo('beechat:availability:offline'); ?>" +	    }, + +	    Contacts: { +		BUTTON: "<?php echo elgg_echo('beechat:contacts:button'); ?>" +	    }, + +	    ChatMessages: { +		SELF: "<?php echo $_SESSION['user']->name; ?>", +		COMPOSING: "<?php echo elgg_echo('beechat:chat:composing'); ?>" +	    }, + +	    Box: { +		MINIMIZE: "<?php echo elgg_echo('beechat:box:minimize'); ?>", +		CLOSE: "<?php echo elgg_echo('beechat:box:close'); ?>", +		SHOWHIDE: "<?php echo elgg_echo('beechat:box:showhide'); ?>" +	    } +	}, + +	StyleClasses: { +	    Availability: { +		Left: { +		    ONLINE: 'beechat_left_availability_chat', +		    DND: 'beechat_left_availability_dnd', +		    AWAY: 'beechat_left_availability_away', +		    XA: 'beechat_left_availability_xa', +		    OFFLINE: 'beechat_left_availability_offline', +		    ROOM: 'beechat_left_availability_room' +		}, + +		Right: { +		    ONLINE: 'beechat_right_availability_chat', +		    DND: 'beechat_right_availability_dnd', +		    AWAY: 'beechat_right_availability_away', +		    XA: 'beechat_right_availability_xa', +		    OFFLINE: 'beechat_right_availability_offline', +		    ROOM: 'beechat_right_availability_room' +		}, + +		Control: { +		    UP: 'beechat_availability_switcher_control_up', +		    DOWN: 'beechat_availability_switcher_control_down' +		} +	    }, + +	    ChatBox: { +		MAIN: 'beechat_chatbox', +		MAINROOM: 'beechat_chatbox_room', +		TOP: 'beechat_chatbox_top', +		SUBTOP: 'beechat_chatbox_subtop', +		TOP_ICON: 'beechat_chatbox_top_icon', +		TOP_CONTROLS: 'beechat_chatbox_top_controls', +		CONTENT: 'beechat_chatbox_content', +		INPUT: 'beechat_chatbox_input', +		BOTTOM: 'beechat_chatbox_bottom', +		CONTROL: 'beechat_chatbox_control', +		STATE: 'beechat_chatbox_state', +		MESSAGE: 'beechat_chatbox_message', +		MESSAGE_SENDER: 'beechat_chatbox_message_sender', +		MESSAGE_DATE: 'beechat_chatbox_message_date', +		CHATROOM: 'beechat_chatbox_chatroom', +		ROOMROSTER: 'beechat_chatbox_roomroster', +		ROSTER_ITEM: 'beechat_chatbox_roomrosteritem' +	    }, + +	    ScrollBox: { +		SELECTED: 'beechat_scrollbox_selected' +	    }, + +	    BOX_CONTROL: 'beechat_box_control', +	    LABEL: 'beechat_label', +	    UNREAD_COUNT: 'beechat_unread_count' +	}, + +	Elements: { +	    ID_DIV_BAR: 'beechat', +	    ID_DIV_BAR_CENTER: 'beechat_center', +	    ID_DIV_BAR_RIGHT: 'beechat_right', + +	    ID_TOOLTIP_TRIGGER: 'beechat_tooltip_trigger', + +	    ID_SPAN_CONTACTS_BUTTON: 'beechat_contacts_button', +	    ID_SPAN_CLOSE_BOX: 'beechat_box_control_close', + +	    ID_DIV_CONTACTS: 'beechat_contacts', +	    ID_DIV_CONTACTS_CONTROLS: 'beechat_contacts_controls', +	    ID_SPAN_CONTACTS_CONTROL_MINIMIZE: 'beechat_contacts_control_minimize', +	    ID_DIV_CONTACTS_CONTENT: 'beechat_contacts_content', +	    ID_UL_CONTACTS_LIST: 'beechat_contacts_list', + +	    ID_DIV_AVAILABILITY_SWITCHER: 'beechat_availability_switcher', +	    ID_SPAN_AVAILABILITY_SWITCHER_CONTROL: 'beechat_availability_switcher_control', +	    ID_SPAN_CURRENT_AVAILABILITY: 'beechat_current_availability', +	    ID_UL_AVAILABILITY_SWITCHER_LIST: 'beechat_availability_switcher_list', + +	    ID_DIV_CHATBOXES: 'beechat_chatboxes', + +	    ID_DIV_SCROLLBOXES: 'beechat_scrollboxes' +	} +    }, + + +    /** Function: initialize +     *  Initialize the BeeChat UI +     * +     */ +    initialize: function(ts, token) +    { +	this.ts = ts; +	this.token = token; +	$('#' + BeeChat.UI.Resources.Elements.ID_TOOLTIP_TRIGGER).tooltip({ +		offset: [-3, 8], +		effect: 'fade' +	    }); + +	$('#accountlinks').find('li').filter('[class=last]').bind('click', function() { +		if (g_beechat_user != null) +		    g_beechat_user.disconnect(); +	    }); + +	BeeChat.UI.AvailabilitySwitcher.initialize(BeeChat.Presence.ShowElements.CHAT); +	BeeChat.UI.ContactsList.initialize(); +	BeeChat.UI.ScrollBoxes.initialize(); +	BeeChat.UI.loadConnection(); +    }, + +    /** Function: getUserDetails +     *  Retrieve user details +     * +     *  Returns: +     *    User details in object notation. +     * +     */ +    addActionTokens: function(url_string, sep) +    { +	if (sep == null) +		sep = "?"; +	return url_string + sep + "__elgg_ts="+this.ts + "&__elgg_token=" + this.token; +    }, + +    getUserDetails: function(cb_func) +    { +	var json = null; +	var self = this; + +	$.ajax({ +		url: self.addActionTokens('<?php echo $vars['url'] . "action/beechat/get_details"; ?>'), +		async: true, +		dataType: 'json', +		success: function(data) { +			cb_func(data); +		} +	    }); + +	return (json); +    }, + +    /** Function: connect +     *  Create the user and connect him to the BOSH service +     * +     *  Parameters: +     *    (Object) conn - Running connection informations in object notation +     */ +    connect: function() +    { +	var conn = (arguments.length > 0) ? arguments[0] : null; +	var userDetails = { +	    jid: (conn != null) ? conn.jid : null, +	    password: null +	} +	var self = this; +	//alert("connect"); +	if (conn == null || (conn != null && conn.attached)) { +	    BeeChat.UI.getUserDetails(function(retrievedUserDetails) { +	    	userDetails.jid = retrievedUserDetails.username + '@' + BeeChat.DOMAIN + '/' + BeeChat.RESOURCE; +	    	userDetails.password = retrievedUserDetails.password; +		self.connect_end(conn, userDetails) +	    }); +	} +	else +	        this.connect_end(conn, userDetails) +    }, + +    connect_end: function(conn, userDetails) +    { +	g_beechat_user = new BeeChat.Core.User(userDetails.jid); +	g_beechat_user.addObserver(BeeChat.Events.Identifiers.UPDATE_CONNECTION_STATE, BeeChat.UI.updateConnectionStatus); +	g_beechat_user.addObserver(BeeChat.Events.Identifiers.UPDATE_ROSTER, BeeChat.UI.onRosterUpdate); +	g_beechat_user.addObserver(BeeChat.Events.Identifiers.RECV_PRESENCE, BeeChat.UI.ContactsList.update); +	g_beechat_user.addObserver(BeeChat.Events.Identifiers.RECV_CHAT_MESSAGE, BeeChat.UI.onChatMessage); + +	if (conn == null || (conn != null && conn.attached)) +	    g_beechat_user.connect(userDetails.password); +	else +	    g_beechat_user.attach(conn.sid, conn.rid); +    }, +  +    /** Function: disconnect +     *  Terminate the user's XMPP session +     * +     */ +    disconnect: function() +    { +	g_beechat_user.disconnect(); +    }, + +    /** Function: updateConnectionStatus +     * +     */ +    updateConnectionStatus: function(connStatusMsg) +    { +	BeeChat.UI.ContactsList.updateButtonText(connStatusMsg); +	if (connStatusMsg == BeeChat.Events.Messages.ConnectionStates.ONLINE) { +	    if (!g_beechat_user.isAttached()) { +		debugXMPP("not attached"); +		BeeChat.UI.ScrollBoxes.isOpened = true; +		g_beechat_user.requestRoster(); +		g_beechat_user.reconnectRooms(); +		//BeeChat.UI.ContactsList.toggleDisplay(); +		$('#' + BeeChat.UI.Resources.Elements.ID_UL_CONTACTS_LIST).show(); +		$('.' + BeeChat.UI.Resources.StyleClasses.ChatBox.INPUT + '>textarea').removeAttr('disabled'); +		for (room_idx in g_user_rooms) { +			var room = g_user_rooms[room_idx]; +			var chatBox = BeeChat.UI.ChatBoxes.getChatBoxElm(room[0]); +			if (chatBox.length == 0) { +				g_beechat_user.joinRoom(room[0], room[1]) +			} +		} + +	    } +	    if (g_beechat_user.isAttached()) { +		debugXMPP("attached"); +		BeeChat.UI.loadState(); +	    } + + +	    $('#' + BeeChat.UI.Resources.Elements.ID_SPAN_CONTACTS_BUTTON).attr('class', 'online'); +	    BeeChat.UI.saveConnection(); +	} +	else if (connStatusMsg == BeeChat.Events.Messages.ConnectionStates.OFFLINE) { +	    var contactsBoxElm = $('#' + BeeChat.UI.Resources.Elements.ID_DIV_CONTACTS); + +	    if (!contactsBoxElm.is(':hidden')) +		BeeChat.UI.ContactsList.toggleDisplay(); + +	    $('#' + BeeChat.UI.Resources.Elements.ID_UL_CONTACTS_LIST).empty(); +	    BeeChat.UI.AvailabilitySwitcher.initialize(BeeChat.Presence.ShowElements.CHAT); +	    BeeChat.UI.ContactsList.updateButtonText(BeeChat.UI.Resources.Strings.Contacts.BUTTON); +	    $('#' + BeeChat.UI.Resources.Elements.ID_SPAN_CONTACTS_BUTTON).attr('class', 'offline'); +	    $('.' + BeeChat.UI.Resources.StyleClasses.ChatBox.INPUT + '>textarea').attr('disabled', 'true'); +	    $('#' + BeeChat.UI.Resources.Elements.ID_DIV_CHATBOXES).children().hide(); +	    $('#' + BeeChat.UI.Resources.Elements.ID_DIV_SCROLLBOXES).find('ul').children() +	    .attr('class', BeeChat.UI.Resources.StyleClasses.LABEL + ' ' + BeeChat.UI.Resources.ReferenceTables.Styles.Availability.Left[BeeChat.Presence.Types.UNAVAILABLE.toUpperCase()]); +	    g_beechat_user = null; +	    BeeChat.UI.saveConnection(); +	} +    }, + +    /** Function: saveConnection +     *  Save connection informations (non sensible data) in $_SESSION. +     * +     */ +    saveConnection: function() +    { +	var conn = null; + +	if (g_beechat_user != null) { +	    var userConn = g_beechat_user.getConnection(); + +	    conn = { +		'jid': userConn.jid, +		'sid': userConn.sid, +		'rid': userConn.rid, +		'attached': g_beechat_user.isAttached() +	    }; +	} +	var self = this; + +	$.ajax({ +		type: 'POST', +		async: false, +		url: self.addActionTokens('<?php echo $vars['url'] . "action/beechat/save_state"; ?>'), +		data: { beechat_conn: JSON.stringify(conn) } +	    }); + +	/* +	$.cookie(BeeChat.UI.Resources.Cookies.FILENAME_CONN, null); +	$.cookie(BeeChat.UI.Resources.Cookies.FILENAME_CONN, JSON.stringify(conn), {path: '/', domain: BeeChat.UI.Resources.Cookies.DOMAIN}); +	*/ +    }, + +    /** Function: loadConnection +     *  Check if a connection already exists. In the case that a connection exists, +     *  this function triggers the connection process. +     * +     */ +    loadConnection: function() +    { +	var self = this; +	$.ajax({ +		type: 'GET', +		async: false, +		cache: false, +		dataType: 'json', +		url: self.addActionTokens('<?php echo $vars['url'] . "action/beechat/get_connection"; ?>'), +		success: function(conn) { +		    if (conn != null) { +			if (conn.attached) +			    BeeChat.UI.connect(); +			else +			    BeeChat.UI.connect(conn); +			} +		}, +		error: function() { +		    BeeChat.UI.connect(); +		} +	    }); + +	/* +	var conn = JSON.parse($.cookie(BeeChat.UI.Resources.Cookies.FILENAME_CONN)); + +	if (conn != null) { +	    if (conn.attached) +		BeeChat.UI.connect(); +	    else +		BeeChat.UI.connect(conn); +	} else +	    BeeChat.UI.connect(); +	*/ +    }, + +    /** Function: saveState +     *  Save app state in $_SESSION +     * +     */ +    saveState: function() +    { +	var self = this; +	var currentAvailabilityClass = $('#' + BeeChat.UI.Resources.Elements.ID_SPAN_CURRENT_AVAILABILITY).attr('class'); +	var currentAvailability = currentAvailabilityClass.substr(currentAvailabilityClass.lastIndexOf('_') + 1); + +	var data = { +	    availability: currentAvailability, +	    contacts: g_beechat_roster_items, +	    chats: {}, +	    contacts_list: { +		minimized: $('#' + BeeChat.UI.Resources.Elements.ID_DIV_CONTACTS).is(':hidden') +	    } +	}; + +	$('#' + BeeChat.UI.Resources.Elements.ID_DIV_CHATBOXES).children().each(function() { +		var contactBareJid = $(this).attr('bareJid'); +		//var contactBareJid = $(this).data('bareJid'); +		var isroom = ($(this).attr('isroom') == 'true'); +		if (isroom) +			var roster = $(this).find('div').filter('[class=' + BeeChat.UI.Resources.StyleClasses.ChatBox.ROOMROSTER + ']'); +		var html_content = $(this).children().filter('[bareJid="' + contactBareJid + '"]').html(); +		data.chats[contactBareJid] = { +		    'html_content': escape(html_content), +		    'roster_content': isroom?escape(roster.html()):'', +		    'isroom': $(this).attr('isroom'), +		    'group_guid': (contactBareJid in g_beechat_rooms)?g_beechat_rooms[contactBareJid]:0, +		    'minimized': $(this).is(':hidden'), +		    'unread': BeeChat.UI.UnreadCountBox.getElm(contactBareJid).text() +		}; +	    }); + +	$.ajax({ +		type: 'POST', +		async: false, +		url: self.addActionTokens('<?php echo $vars['url'] . "action/beechat/save_state"; ?>'), +		data: { beechat_state: JSON.stringify(data) } +	    }); +    }, + +    /** Function: loadState +     *  Load app state from $_SESSION +     * +     */ +    loadState: function() +    { +	var self = this; +	$.ajax({ +		type: 'GET', +		async: true, +		cache: false, +		dataType: 'json', +		url: self.addActionTokens('<?php echo $vars['url'] . "action/beechat/get_state"; ?>'), +		error: function() { +			alert('error getting state'); +		}, +		success: function(json) { +		    debugXMPP('loadState'); +		    BeeChat.UI.AvailabilitySwitcher.initialize(json.availability); + +		    if (!json.contacts_list.minimized) { +			$('#' + BeeChat.UI.Resources.Elements.ID_DIV_CONTACTS).show(); +			BeeChat.UI.ContactsList.showedStyle(); +		    } + +		    g_beechat_user.getRoster().setItems(json.contacts); +                    self.loadRosterItemsIcons(false); +                    self.loadRosterItemsStatuses(false); +		    g_beechat_roster_items = g_beechat_user.getRoster().getItems(); +		    BeeChat.UI.ContactsList.update(g_beechat_user.getRoster().getOnlineItems()) +		    g_beechat_user.setInitialized(true); + +		    var scrollBoxesElm = $('#' + BeeChat.UI.Resources.Elements.ID_DIV_SCROLLBOXES); +		    var scrollBoxElmToShow = null; + +		    // Load saved chats +		    for (var key in json.chats) { +			var isroom = (json.chats[key].isroom == 'true'); +			if (isroom) +				BeeChat.UI.ScrollBoxes.addRoom(key); +			else +				BeeChat.UI.ScrollBoxes.add(key); + +			var chatBoxElm = BeeChat.UI.ChatBoxes.getChatBoxElm(key); +			debugXMPP("load chat " + key); +			chatBoxElm.hide(); + +			if (!json.chats[key].minimized) { +			    scrollBoxElmToShow = BeeChat.UI.ScrollBoxes.getScrollBoxElm(key); +			} + +			var chatBoxContentElm = chatBoxElm.children().filter('[bareJid="' + key + '"]'); + +			chatBoxContentElm.append(unescape(json.chats[key].html_content)); +			chatBoxContentElm.attr({scrollTop: chatBoxContentElm.attr('scrollHeight')}); +			if (isroom) { +				g_beechat_rooms[key] = json.chats[key].room_guid; +				var rosterElm = chatBoxElm.find('div').filter('[class=' + BeeChat.UI.Resources.StyleClasses.ChatBox.ROOMROSTER + ']'); +				rosterElm.append(unescape(json.chats[key].roster_content)); +			} + +			BeeChat.UI.UnreadCountBox.update(key, json.chats[key].unread); +		    } +		    if (scrollBoxElmToShow != null) +			scrollBoxesElm.trigger('goto', scrollBoxesElm.find('ul').children().index(scrollBoxElmToShow)); +		    else +			scrollBoxesElm.trigger('goto', 0); + +		   // g_beechat_user.sendPresenceAvailability(json.availability, ''); +		    BeeChat.UI.ScrollBoxes.isInitialized = true; +		    BeeChat.UI.ScrollBoxes.isOpened = true; + +			  for (var key in json.chats) { +					if (json.chats[key].minimized) { +						BeeChat.UI.ChatBoxes.getChatBoxElm(key).hide(); +						BeeChat.UI.ScrollBoxes.unselect(key); +					} +					else { +						BeeChat.UI.ChatBoxes.getChatBoxElm(key).show(); +						BeeChat.UI.ScrollBoxes.select(key); +					} +				} +		    for (room_idx in g_user_rooms) { +			var room = g_user_rooms[room_idx]; +			var chatBox = BeeChat.UI.ChatBoxes.getChatBoxElm(room[0]); +			if (chatBox.length == 0) { +				g_beechat_user.joinRoom(room[0], room[1]) +			} +		    } + +		}, +		error: function() { +		    BeeChat.UI.ContactsList.initialize(); +		} +	    }); +    }, + +    /** Function: loadRosterItemsIcons +     * +     */ +    loadRosterItemsIcons: function(is_async, cb) +    { +	var data = g_beechat_user.getRoster().getItemsUsernamesAsList(); +	var self = this; + +	$.ajax({ +		type: 'POST', +		url: self.addActionTokens('<?php echo $vars['url'] . "action/beechat/get_icons"; ?>'), +		async: is_async, +		cache: false, +		data: {'beechat_roster_items_usernames': data}, +		dataType: 'json', +		success: function(json) { +		    g_beechat_user.getRoster().setIcons(json); +		    g_beechat_roster_items = g_beechat_user.getRoster().getItems(); + +		    BeeChat.UI.ContactsList.update(g_beechat_user.getRoster().getOnlineItems()) +		    if (cb) { +			cb(); +		    } +		} +	    }); +    }, + +    /** Function: loadRosterItemsStatuses +     * +     */ +    loadRosterItemsStatuses: function(is_async, cb) +    { +	var data = g_beechat_user.getRoster().getItemsUsernamesAsList(); +//alert(data) +	var self = this; +	$.ajax({ +		type: 'POST', +		url: self.addActionTokens('<?php echo $vars['url'] . "action/beechat/get_statuses"; ?>'), +		async: true, // force +		cache: false, +		data: {'beechat_roster_items_usernames': data}, +		dataType: 'json', +		success: function(json) { +		    g_beechat_user.getRoster().setStatuses(json); +		    g_beechat_roster_items = g_beechat_user.getRoster().getItems(); +		    BeeChat.UI.ContactsList.update(g_beechat_user.getRoster().getOnlineItems()) +		    if (cb) { +			cb(); +		    } +		} +	    }); +    }, + +    /** Function: onRosterUpdate +     *  Notified by core on a roster update +     * +     */ +    onRosterUpdate: function(rosterItems) +    { +	g_beechat_roster_items = rosterItems; +		//alert("get roster"); +	if (!g_beechat_user.isInitialized()) { +		//alert("load roster" + rosterItems.length); +	    BeeChat.UI.loadRosterItemsStatuses(true, +				function() { BeeChat.UI.loadRosterItemsIcons(true, +				function() {g_beechat_user.sendInitialPresence();}); }); +	    //BeeChat.UI.loadRosterItemsIcons(false); +	    //g_beechat_user.sendInitialPresence(); +	} +    }, + +    /** Function: onChatMessage +     * +     */ +    onChatMessage: function(data) +    { +	if ($(data.msg).find('body').length == 0) { +	    BeeChat.UI.ChatBoxes.updateChatState(data.contactBareJid, data.msg); +	} +	else { +	    BeeChat.UI.ChatBoxes.update(data.contactBareJid, BeeChat.UI.Utils.getContactName(data.contactBareJid), Strophe.getText($(data.msg).find('body')[0])); +	} +    } +}; + + +/** Class: BeeChat.UI.Resources.ReferenceTables + *  An object container for all reference tables + * + */ +BeeChat.UI.Resources.ReferenceTables = { +    Styles: { +	Availability: { +	    Left: { +		AVAILABLE: BeeChat.UI.Resources.StyleClasses.Availability.Left.ONLINE, +		CHAT: BeeChat.UI.Resources.StyleClasses.Availability.Left.ONLINE, +		DND: BeeChat.UI.Resources.StyleClasses.Availability.Left.DND, +		AWAY: BeeChat.UI.Resources.StyleClasses.Availability.Left.AWAY, +		XA: BeeChat.UI.Resources.StyleClasses.Availability.Left.XA, +		UNAVAILABLE: BeeChat.UI.Resources.StyleClasses.Availability.Left.OFFLINE, +		OFFLINE: BeeChat.UI.Resources.StyleClasses.Availability.Left.OFFLINE, +		ROOM: BeeChat.UI.Resources.StyleClasses.Availability.Left.ROOM +	    }, + +	    Right: { +		AVAILABLE: BeeChat.UI.Resources.StyleClasses.Availability.Right.ONLINE, +		CHAT: BeeChat.UI.Resources.StyleClasses.Availability.Right.ONLINE, +		DND: BeeChat.UI.Resources.StyleClasses.Availability.Right.DND, +		AWAY: BeeChat.UI.Resources.StyleClasses.Availability.Right.AWAY, +		XA: BeeChat.UI.Resources.StyleClasses.Availability.Right.XA, +		UNAVAILABLE: BeeChat.UI.Resources.StyleClasses.Availability.Right.OFFLINE, +		OFFLINE: BeeChat.UI.Resources.StyleClasses.Availability.Right.OFFLINE, +		ROOM: BeeChat.UI.Resources.StyleClasses.Availability.Right.ROOM +	    } +	} +    } +}; + + +/** Class: BeeChat.UI.ContactsList + *  An object container for all ContactsList functions + * + */ +BeeChat.UI.ContactsList = { +    /** Function: initialize +     *  Initialize the contacts list by binding elements +     * +     */ +    initialize: function() +    { +		$('#' + BeeChat.UI.Resources.Elements.ID_SPAN_CONTACTS_CONTROL_MINIMIZE).unbind('click').bind('click', BeeChat.UI.ContactsList.toggleDisplay); +	$('#' + BeeChat.UI.Resources.Elements.ID_SPAN_CONTACTS_BUTTON).unbind('click').bind('click', function() { +		if (g_beechat_user == null) +		    BeeChat.UI.connect(); +		else +		    BeeChat.UI.ContactsList.toggleDisplay(); +	    }); +    }, + +    /** Function: update +     *  Update the contacts list content +     * +     *  Parameters: +     *    (Object)(BeeChat.Core.RosterItem) onlineRosterItems - A hash of RosterItems in object notation +     * +     */ +    update: function(onlineRosterItems) +    { +	var contactsListElm = $('#' + BeeChat.UI.Resources.Elements.ID_UL_CONTACTS_LIST); + +	contactsListElm.children().each(function() { +		var contactBareJid = $(this).attr('bareJid'); + +		if (g_beechat_roster_items != null) { +		    if ($.inArray(contactBareJid, onlineRosterItems) == -1) { +			BeeChat.UI.ScrollBoxes.updateAvailability(contactBareJid); +			$(this).remove(); +		    } +		} +	    }); + +	for (var key in onlineRosterItems) { +	    if (typeof onlineRosterItems[key] != 'object') +		continue; + +	    var contactElm = contactsListElm.find('li').filter('[bareJid="' + key + '"]'); + +	    if (contactElm.length == 0) { +		contactElm = $('<li></li>') +		    .attr('bareJid', key) +		    .append($('<img />') +			    .attr('src', g_beechat_roster_items[key].icon_tiny)) +		    .append(BeeChat.UI.Utils.getTruncatedContactName(key, 25)) +		    .appendTo(contactsListElm) +		    .bind('click', function() { +					if (!BeeChat.UI.ChatBoxes.getChatBoxElm($(this).attr('bareJid')).is(':visible')) { +						BeeChat.UI.ContactsList.toggleDisplay(); +					} + +			    BeeChat.UI.ScrollBoxes.add($(this).attr('bareJid'), false, true); +			}); +	    } + +	    BeeChat.UI.ContactsList.updateContactAvailability(contactElm, key); +	} + +	BeeChat.UI.ContactsList.updateButtonText(BeeChat.UI.Resources.Strings.Contacts.BUTTON + ' (<strong>' + g_beechat_user.getRoster().getSizeOnlineItems() + '</strong>)'); +    }, + +    /** Function: updateContactAvailability +     * +     */ +    updateContactAvailability: function(contactElm, contactBareJid) +    { +	// Update from contactsList +	contactElm.attr('class', BeeChat.UI.Resources.ReferenceTables.Styles.Availability.Right[g_beechat_roster_items[contactBareJid].getStrongestPresence().show.toUpperCase()]); + +	// Update from scrollBoxes +	BeeChat.UI.ScrollBoxes.updateAvailability(contactBareJid); +    }, + +    /** Function: updateButtonText +     * +     * +     */ +    updateButtonText: function(msg) +    { +	$('#' + BeeChat.UI.Resources.Elements.ID_SPAN_CONTACTS_BUTTON).html(msg); +    }, + +    /** Function: toggleDisplay +     *  Toggle the contacts box display (hide | show) +     * +     */ +    toggleDisplay: function() +    { +	var contactsBoxElm = $('#' + BeeChat.UI.Resources.Elements.ID_DIV_CONTACTS); + +	contactsBoxElm.toggle(); +	if (contactsBoxElm.is(':hidden')) { +	    BeeChat.UI.ContactsList.hiddenStyle(); +	} else { +	    BeeChat.UI.ContactsList.showedStyle(); +	} +	$('#' + BeeChat.UI.Resources.Elements.ID_UL_AVAILABILITY_SWITCHER_LIST).hide(); +    }, + +    /** Function: hiddenStyle +     * +     */ +    hiddenStyle: function() +    { +	$('#' + BeeChat.UI.Resources.Elements.ID_DIV_BAR_RIGHT).css({'border-left': '1px solid #BBBBBB', 'border-right': '1px solid #BBBBBB', 'background-color': '#DDDDDD'}); +    }, + +    /** Function: showedStyle +     * +     */ +    showedStyle: function() +    { +	$('#' + BeeChat.UI.Resources.Elements.ID_DIV_BAR_RIGHT).css({'border-left': '1px solid #666666', 'border-right': '1px solid #666666', 'background-color': 'white'}); +    } +}; + + +/** Class: BeeChat.UI.AvailabilitySwitcher + *  An object container for all AvailabilitySwitcher functions + * + */ +BeeChat.UI.AvailabilitySwitcher = { +    /** Function: initialize +     *  Initialize the availability switcher by setting the current user's availability +     *  and binding actions +     * +     */ +    initialize: function(availability) +    { +		$('#' + BeeChat.UI.Resources.Elements.ID_SPAN_CURRENT_AVAILABILITY).unbind('click').bind('click', BeeChat.UI.AvailabilitySwitcher.toggleListDisplay); +		 +		$('#' + BeeChat.UI.Resources.Elements.ID_SPAN_AVAILABILITY_SWITCHER_CONTROL).unbind('click').bind('click', BeeChat.UI.AvailabilitySwitcher.toggleListDisplay); +		 +		$('#' + BeeChat.UI.Resources.Elements.ID_UL_AVAILABILITY_SWITCHER_LIST).find('li').each(function() { +		$(this).unbind('click').bind('click', function() { +			var availabilityClass = $(this).attr('class'); +			var availability = availabilityClass.substr(availabilityClass.lastIndexOf('_') + 1); + +			if (availability == 'offline') +			    BeeChat.UI.disconnect(); +			else { +			    g_beechat_user.sendPresenceAvailability(availability, ''); +			    BeeChat.UI.AvailabilitySwitcher.update(availability); +			    $('#' + BeeChat.UI.Resources.Elements.ID_UL_AVAILABILITY_SWITCHER_LIST).hide('slow'); +			    $('#' + BeeChat.UI.Resources.Elements.ID_UL_CONTACTS_LIST).show('slow'); +			} +		    }); +	    }); +	BeeChat.UI.AvailabilitySwitcher.update(availability); +    }, + +    /** Function: update +     *  Update the current user's availability +     * +     *  Parameters: +     *    (BeeChat.Presence.ShowElements) availability - The current user's availability +     */ +    update: function(availability) +    { +	var upperCasedAvailability = availability.toUpperCase(); + +	$('#' + BeeChat.UI.Resources.Elements.ID_SPAN_CURRENT_AVAILABILITY) +	.attr('class', BeeChat.UI.Resources.ReferenceTables.Styles.Availability.Left[upperCasedAvailability]) +	.text(BeeChat.UI.Resources.Strings.Availability[upperCasedAvailability]); + +	if (availability == 'chat') +	    $('#' + BeeChat.UI.Resources.Elements.ID_SPAN_CONTACTS_BUTTON).attr('class', 'online'); +	else if (availability == 'xa' || availability == 'away') +	    $('#' + BeeChat.UI.Resources.Elements.ID_SPAN_CONTACTS_BUTTON).attr('class', 'away'); +	else if (availability == 'dnd') +	    $('#' + BeeChat.UI.Resources.Elements.ID_SPAN_CONTACTS_BUTTON).attr('class', 'dnd'); +    }, + +    /** Function: switchControlClass +     * +     */ +    switchControlClass: function() +    { +	var switcherControlElm = $('#' + BeeChat.UI.Resources.Elements.ID_SPAN_AVAILABILITY_SWITCHER_CONTROL); + +	if (switcherControlElm.attr('class') == BeeChat.UI.Resources.StyleClasses.Availability.Control.UP) +	    switcherControlElm.attr('class', BeeChat.UI.Resources.StyleClasses.Availability.Control.DOWN); +	else +	    switcherControlElm.attr('class', BeeChat.UI.Resources.StyleClasses.Availability.Control.UP); +    }, + +    /** Function: toggleListDisplay +     * +     */ +    toggleListDisplay: function() +    { +		BeeChat.UI.AvailabilitySwitcher.switchControlClass(); +		$('#' + BeeChat.UI.Resources.Elements.ID_UL_CONTACTS_LIST).toggle('slow'); +		$('#' + BeeChat.UI.Resources.Elements.ID_UL_AVAILABILITY_SWITCHER_LIST).toggle('slow'); +    } +}; + + +/** Class: BeeChat.UI.ScrollBoxes + *  An object container for all ScrollBoxes related functions + * + */ +BeeChat.UI.ScrollBoxes = { +    isInitialized: false, +    isOpened: false, + +    /** Function: initialize +     * +     */ +    initialize: function() { +	var $prev = $('#beechat_center_prev'), +	$next = $('#beechat_center_next'); + +	$('#' + BeeChat.UI.Resources.Elements.ID_DIV_BAR_CENTER).serialScroll({ +		    target: '#beechat_scrollboxes', +		    items: 'li', +		    prev: '#beechat_center_prev', +		    next: '#beechat_center_next', +		    axys: 'x', +		    start: 2, +		    step: -1, +		    interval: 0, +		    duration: 0, +		    cycle: false, +		    force: true, +		    jump: true, +		    lock: true, +		    lazy: true, +		    constant: true, + +		    onBefore: function(e, elem, $pane, $items, pos) { +		      $next.add($prev).hide(); +		      $prev.add($next).hide(); +		      if (pos != 0) { +			  $next.show(); +		      } +		      if (pos != $items.length - 1) +			  $prev.show(); +		    }, + +		    onAfter: function(elem) { +		    	BeeChat.UI.ChatBoxes.takeStand($(elem).attr('bareJid')); +			BeeChat.UI.ScrollBoxes.isInitialized = true; +		    } +	    }); +    }, + +    /** Function: add +     *  Add a scrollbox to the scrollboxes bar +     * +     */ +    addRoom: function(contactBareJid) +    { +	debugXMPP('addRoom' + contactBareJid); +        BeeChat.UI.ScrollBoxes.add(contactBareJid, true); +	var scrollBoxElm = BeeChat.UI.ScrollBoxes.getScrollBoxElm(contactBareJid); +	scrollBoxElm.attr('class', BeeChat.UI.Resources.StyleClasses.Availability.Left.ROOM); +    }, + +    add: function(contactBareJid, isroom) +    { +	var scrollBoxesElm = $('#' + BeeChat.UI.Resources.Elements.ID_DIV_SCROLLBOXES); +	var scrollBoxElm = scrollBoxesElm.find('ul').children().filter('[bareJid="' + contactBareJid + '"]'); +	debugXMPP("add " + contactBareJid + " " + scrollBoxElm.length); +	if (scrollBoxElm.length == 0) { +	    var availClass = null; +            var pres = null; +            if (g_beechat_roster_items != undefined) +	        pres = g_beechat_roster_items[contactBareJid] != null ? g_beechat_roster_items[contactBareJid].getStrongestPresence() : null; + +	    if (pres != null) +		availClass = BeeChat.UI.Resources.ReferenceTables.Styles.Availability.Left[pres.show.toUpperCase()]; +	    else +		availClass = BeeChat.UI.Resources.ReferenceTables.Styles.Availability.Left[BeeChat.Presence.Types.UNAVAILABLE.toUpperCase()]; + +	    scrollBoxElm = $('<li></li>') +		.attr('class', BeeChat.UI.Resources.StyleClasses.LABEL + ' ' + availClass) +		.attr('bareJid', contactBareJid) +		.attr('isroom', isroom?'true':'false') +		.attr('title', BeeChat.UI.Resources.Strings.Box.SHOWHIDE) +		.text(BeeChat.UI.Utils.getTruncatedContactName(contactBareJid, 11)) +		.append($('<span></span>') +			.attr('class', BeeChat.UI.Resources.StyleClasses.BOX_CONTROL) +			.attr('id', BeeChat.UI.Resources.Elements.ID_SPAN_CLOSE_BOX) +			.text('X') +			.attr('title', BeeChat.UI.Resources.Strings.Box.CLOSE) +			.bind('click', function() { +				if (isroom) +					g_beechat_user.leaveRoom(contactBareJid); +				var scrollBoxesElm = $('#' + BeeChat.UI.Resources.Elements.ID_DIV_SCROLLBOXES); + +				BeeChat.UI.ChatBoxes.remove($(this).parent().attr('bareJid')); +				BeeChat.UI.UnreadCountBox.remove($(this).parent().attr('bareJid')); +				scrollBoxesElm.trigger('goto', scrollBoxesElm.find('ul').children().index(BeeChat.UI.ScrollBoxes.getSelectedScrollBoxElm())); +	    			BeeChat.UI.saveState(); +			    })); + +	    scrollBoxesElm.find('ul').append(scrollBoxElm); +	    BeeChat.UI.ChatBoxes.add(contactBareJid, isroom); +	    if (arguments.length == 3 && arguments[2]) +		scrollBoxesElm.trigger('goto', scrollBoxesElm.find('ul').children().index(scrollBoxElm)); +	    if (!isroom) { +		    BeeChat.UI.loadRosterItemsStatuses(true, function () { BeeChat.UI.loadRosterItemsIcons(true); }); +	    } +	} else { +	    scrollBoxesElm.trigger('goto', scrollBoxesElm.find('ul').children().index(scrollBoxElm)); +	} +    }, + +    /** Function: remove +     * +     */ +    remove: function(contactBareJid) +    { +	BeeChat.UI.ScrollBoxes.getScrollBoxElm(contactBareJid).remove(); +    }, + +    /** Function: unselect +     * +     */ +    unselect: function(contactBareJid) +    { +	var scrollBoxElm = BeeChat.UI.ScrollBoxes.getScrollBoxElm(contactBareJid); +	scrollBoxElm.attr('class', (scrollBoxElm.attr('class')).replace(/beechat_scrollbox_selected/, '')); +    }, + +    /** Function: select +     * +     */ +    select: function(contactBareJid) +    { +	var scrollBoxElm = BeeChat.UI.ScrollBoxes.getScrollBoxElm(contactBareJid); +	var scrollBoxElmClasses = scrollBoxElm.attr('class'); + +	if (scrollBoxElmClasses.search(/beechat_scrollbox_selected/) == -1) +	    scrollBoxElm.attr('class', scrollBoxElmClasses + ' ' + BeeChat.UI.Resources.StyleClasses.ScrollBox.SELECTED); +    }, + +    /** Function: updateAvailability +     * +     */ +    updateAvailability: function(contactBareJid) +    { +	var pres = g_beechat_roster_items[contactBareJid].getStrongestPresence(); +	var scrollBoxElm = BeeChat.UI.ScrollBoxes.getScrollBoxElm(contactBareJid); +	var scrollBoxElmClasses = scrollBoxElm.attr('class'); +	var updatedAvailability = null; + +	if (pres != null) +	    updatedAvailability = BeeChat.UI.Resources.ReferenceTables.Styles.Availability.Left[pres.show.toUpperCase()]; +	else +	    updatedAvailability = BeeChat.UI.Resources.ReferenceTables.Styles.Availability.Left[BeeChat.Presence.Types.UNAVAILABLE.toUpperCase()]; + +	if (scrollBoxElmClasses == undefined || scrollBoxElmClasses.search(/(beechat_left_availability_)/g) == -1) { +	    scrollBoxElm.attr('class', BeeChat.UI.Resources.StyleClasses.LABEL + ' ' + updatedAvailability); +	} else { +	    updatedAvailability = updatedAvailability.replace(/(beechat_left_availability)/g, ''); + +	    scrollBoxElmClasses = scrollBoxElmClasses.replace(/(_chat)/g, updatedAvailability); +	    scrollBoxElmClasses = scrollBoxElmClasses.replace(/(_dnd)/g, updatedAvailability); +	    scrollBoxElmClasses = scrollBoxElmClasses.replace(/(_away)/g, updatedAvailability); +	    scrollBoxElmClasses = scrollBoxElmClasses.replace(/(_xa)/g, updatedAvailability); +	    scrollBoxElmClasses = scrollBoxElmClasses.replace(/(_offline)/g, updatedAvailability); + +	    scrollBoxElm.attr('class', scrollBoxElmClasses); +	} +    }, + +    /** Function: getSelectedScrollBoxElm +     * +     */ +    getSelectedScrollBoxElm: function(contactBareJid) +    { +	var elm = undefined; + +	$('#' + BeeChat.UI.Resources.Elements.ID_DIV_SCROLLBOXES).find('ul').children().each(function() { +		if ($(this).attr('class').search(/beechat_scrollbox_selected/) != -1) +		    elm = $(this); +	    }); + +	return (elm); +    }, + +    /** Function: getScrollBoxElm +     * +     */ +    getScrollBoxElm: function(contactBareJid) +    { +	return $('#' + BeeChat.UI.Resources.Elements.ID_DIV_SCROLLBOXES).find('ul').children().filter('[bareJid="' + contactBareJid + '"]'); +    } +}; + + +/** Class: BeeChat.UI.ChatBoxes + *  An object container for all ChatBoxes related functions + * + */ +BeeChat.UI.ChatBoxes = { +    dateLastComposing: {}, +    lastTimedPauses: {}, + +    /** Function: add +     * +     */ +    add: function(contactBareJid, isroom) +    { +	var chatBoxes = $('#' + BeeChat.UI.Resources.Elements.ID_DIV_CHATBOXES); + +	if ($(chatBoxes).children().filter('[bareJid="' + contactBareJid + '"]').length == 0) { +		debugXMPP("create chatbox " + contactBareJid); +	    var chatBox = $('<div></div>') +		.attr('class', isroom ? BeeChat.UI.Resources.StyleClasses.ChatBox.MAIN : BeeChat.UI.Resources.StyleClasses.ChatBox.MAIN) +		.attr('bareJid', contactBareJid) +		.attr('isroom', isroom ? 'true' : 'false') +		.hide(); + +	    var chatBoxTop = $('<div></div>') +		.attr('class', BeeChat.UI.Resources.StyleClasses.ChatBox.TOP); +	    if (!isroom) +		chatBoxTop.append($('<a></a>') +			.attr('href', BeeChat.UI.Resources.Paths.MEMBER_PROFILE + Strophe.getNodeFromJid(contactBareJid)) +			.append($('<img />') +				.attr('class', BeeChat.UI.Resources.StyleClasses.ChatBox.TOP_ICON) +				.attr('src', (g_beechat_roster_items != null && g_beechat_roster_items[contactBareJid] != undefined)?g_beechat_roster_items[contactBareJid].icon_small:''))) +	    chatBoxTop.append($('<span></span>') +			.attr('class', BeeChat.UI.Resources.StyleClasses.LABEL) +			.html(isroom?BeeChat.UI.Utils.getTruncatedContactName(contactBareJid).split('@')[0]:'<a href="' + BeeChat.UI.Resources.Paths.MEMBER_PROFILE + Strophe.getNodeFromJid(contactBareJid) + '">' + BeeChat.UI.Utils.getTruncatedContactName(contactBareJid) + '</a>')) +		.append($('<div></div>') +			.attr('class', BeeChat.UI.Resources.StyleClasses.ChatBox.TOP_CONTROLS) +			.append($('<span></span>') +				.attr('class', BeeChat.UI.Resources.StyleClasses.ChatBox.CONTROL) +				.attr('id', BeeChat.UI.Resources.Elements.ID_SPAN_CLOSE_BOX) +				.text('X') +				.attr('title', BeeChat.UI.Resources.Strings.Box.CLOSE) +				.bind('click', function() { +					if (isroom) +						g_beechat_user.leaveRoom(contactBareJid); +					BeeChat.UI.ChatBoxes.remove(contactBareJid); +				    })) +			.append($('<span></span>') +				.attr('class', BeeChat.UI.Resources.StyleClasses.ChatBox.CONTROL) +				.attr('id', BeeChat.UI.Resources.Elements.ID_SPAN_CLOSE_BOX) +				.text('_') +				.attr('title', BeeChat.UI.Resources.Strings.Box.MINIMIZE) +				.css({'font-size': '1.6em', 'position': 'relative', 'line-height': '4px'}) +				.bind('click', function() { +					BeeChat.UI.ScrollBoxes.unselect($(this).parent().parent().parent().attr('bareJid')); +					$(this).parent().parent().parent().fadeOut('slow'); +				    }))); + +	    var chatBoxSubTop = $('<div></div>') +		.attr('class', BeeChat.UI.Resources.StyleClasses.ChatBox.SUBTOP) +		.append(BeeChat.UI.Utils.getTruncatedContactStatus((g_beechat_roster_items != null && g_beechat_roster_items[contactBareJid] != undefined && g_beechat_roster_items[contactBareJid].status != undefined) ? g_beechat_roster_items[contactBareJid].status : '')); + +	    var chatBoxContent = $('<div></div>') +		.attr('class', BeeChat.UI.Resources.StyleClasses.ChatBox.CONTENT) +		.attr('bareJid', contactBareJid); + +	    var chatBoxInput = $('<div></div>') +		.attr('class', BeeChat.UI.Resources.StyleClasses.ChatBox.INPUT) +		.append($('<textarea></textarea>') +			.attr('bareJid', contactBareJid) +			.bind('keypress', isroom?BeeChat.UI.ChatBoxes.onRoomTypingMessage:BeeChat.UI.ChatBoxes.onTypingMessage) +			.bind('keyup', function(e) { +				if ((e.keyCode ? e.keyCode : e.which) == 13) +				    $(this).attr('value', ''); +			    })); + +	    var chatBoxBottom = $('<div></div>') +		.attr('class', BeeChat.UI.Resources.StyleClasses.ChatBox.BOTTOM) +		.append($('<span></span>') +			.append($('<span></span>'))); +	    if (isroom) { +		//var chatBoxBox = $('<div></div>') +		//	.attr('class', BeeChat.UI.Resources.StyleClasses.ChatBox.CHATROOM) +		var chatBoxRoster = $('<div></div>') +			.attr('class', BeeChat.UI.Resources.StyleClasses.ChatBox.ROOMROSTER) +	        //chatBoxBox.append(chatBoxTop).append(chatBoxSubTop).append(chatBoxContent).append(chatBoxInput).append(chatBoxBottom) +		//chatBox.append(chatBoxRoster).append(chatBoxBox).appendTo(chatBoxes); +	        chatBox.append(chatBoxTop).append(chatBoxSubTop).append(chatBoxContent).append(chatBoxInput).append(chatBoxBottom).append(chatBoxRoster).appendTo(chatBoxes); +	    } +	    else +	        chatBox.append(chatBoxTop).append(chatBoxSubTop).append(chatBoxContent).append(chatBoxInput).append(chatBoxBottom).appendTo(chatBoxes); +	} +	else { +		/*debugXMPP("show chatbox " + contactBareJid); +		var chatBox = $(chatBoxes).children().filter('[bareJid="' + contactBareJid + '"]'); +		chatBox.show();*/ +	} +    }, + +    /** Function: takeStand +     * +     */ +    takeStand: function(contactBareJid) +    { +	var chatBoxesElm = $('#' + BeeChat.UI.Resources.Elements.ID_DIV_CHATBOXES).children(); +	var chatBoxElm = chatBoxesElm.filter('[bareJid="' + contactBareJid + '"]'); +	var chatBoxContentElm = chatBoxElm.children().filter('[bareJid="' + contactBareJid + '"]'); +	var scrollBoxesElm = $('#' + BeeChat.UI.Resources.Elements.ID_DIV_SCROLLBOXES); +	var scrollBoxElm = BeeChat.UI.ScrollBoxes.getScrollBoxElm(contactBareJid); + +	if (!chatBoxElm.is(':hidden')) { +	    BeeChat.UI.ScrollBoxes.unselect(contactBareJid); +	    chatBoxElm.hide(); +	} else { +	    // Hide all other chatboxes +	    $.each(chatBoxesElm.filter('[bareJid!="' + contactBareJid + '"]'), function() { +		    BeeChat.UI.ScrollBoxes.unselect($(this).attr('bareJid')); +		    $(this).hide(); +		}); +	    // Add selected scrollbox style +	    BeeChat.UI.ScrollBoxes.select(contactBareJid); +	    // Remove UnreadCountBox +	    BeeChat.UI.UnreadCountBox.remove(contactBareJid); +	    // Position the chatbox +	    var pos = scrollBoxElm.position().left - (chatBoxElm.width() - scrollBoxElm.width()) + 24; +	    chatBoxElm.css({'left': pos}); +	    if (!BeeChat.UI.ScrollBoxes.isOpened) +			return; +	    chatBoxElm.show().css({'left': pos}); +	    // Scroll down the content of the chatbox +	    chatBoxContentElm.attr({scrollTop: chatBoxContentElm.attr('scrollHeight')}); +	    // Focus textarea +	    chatBoxElm.children().filter('[class=' + BeeChat.UI.Resources.StyleClasses.ChatBox.INPUT + ']').find('textarea').focus(); +	} +    }, + +    /** Function: onTypingMessage +     * +     */ +    onRoomTypingMessage: function(e) { +        BeeChat.UI.ChatBoxes._onTypingMessage(e, true, this); +    }, + +    onTypingMessage: function(e) { +        BeeChat.UI.ChatBoxes._onTypingMessage(e, false, this); +    }, + +    _onTypingMessage: function(e, isroom, self) +    { +	var keyCode = (e.keyCode) ? e.keyCode : e.which; +	var contactBareJid = $(self).attr('bareJid'); + +	var msgtype = BeeChat.Message.Types.CHAT; +	if (isroom) + 		msgtype = BeeChat.Message.Types.GROUPCHAT; + +	if (keyCode == 13 && $(self).val() != '') { +	    g_beechat_user.sendChatMessage(contactBareJid, jQuery.trim($(self).val()), msgtype); +	    if (!isroom) +	    	BeeChat.UI.ChatBoxes.update(contactBareJid, BeeChat.UI.Utils.truncateString(BeeChat.UI.Resources.Strings.ChatMessages.SELF, 24), $(self).val(), isroom); +	    clearTimeout(BeeChat.UI.ChatBoxes.lastTimedPauses[contactBareJid]); +	    BeeChat.UI.ChatBoxes.lastTimedPauses[contactBareJid] = null; +	} else { +	    var nowTime = new Date().getTime(); + +	    if (BeeChat.UI.ChatBoxes.dateLastComposing[contactBareJid] == null || BeeChat.UI.ChatBoxes.dateLastComposing[contactBareJid] + 2000 < nowTime) { +		BeeChat.UI.ChatBoxes.dateLastComposing[contactBareJid] = nowTime; +		g_beechat_user.sendChatStateMessage(contactBareJid, BeeChat.Message.ChatStates.COMPOSING); +	    } + +	    clearTimeout(BeeChat.UI.ChatBoxes.lastTimedPauses[contactBareJid]); +	    BeeChat.UI.ChatBoxes.lastTimedPauses[contactBareJid] = setTimeout('g_beechat_user.sendChatStateMessage(\'' + contactBareJid + '\', BeeChat.Message.ChatStates.PAUSED)', 2000); + +	    var chatBoxTextAreaElm = BeeChat.UI.ChatBoxes.getChatBoxElm(contactBareJid).children().filter('[class=' + BeeChat.UI.Resources.StyleClasses.ChatBox.INPUT + ']').find('textarea'); +	    chatBoxTextAreaElm.attr({scrollTop: chatBoxTextAreaElm.attr('scrollHeight')}); +	} +    }, + +    updateRoster: function(contactBareJid, fromName, presence) +    { +	var availability = $(presence).attr('type'); +	var item = $(presence).find('item'); +	var chatBoxElm = BeeChat.UI.ChatBoxes.getChatBoxElm(contactBareJid); + +	if (chatBoxElm.length == 0) { +	    	BeeChat.UI.ScrollBoxes.add(contactBareJid); +	    	//BeeChat.UI.ScrollBoxes.addRoom(contactBareJid); +	    chatBoxElm = BeeChat.UI.ChatBoxes.getChatBoxElm(contactBareJid); +	} + +	//var chatBoxContentElm = chatBoxElm.children().filter('[bareJid="' + contactBareJid + '"]'); + +	var roster = chatBoxElm.find('div').filter('[class=' + BeeChat.UI.Resources.StyleClasses.ChatBox.ROOMROSTER + ']'); +	if (availability == 'unavailable') { +		roster.find('div').filter('[contactName='+fromName+']').remove(); +	} +	else { +		var hasName = roster.find('div').filter('[contactName='+fromName+']'); +		if (hasName.length == 0) { +			roster.append($('<div>' + fromName + '</div>') +				.attr('class', BeeChat.UI.Resources.StyleClasses.ChatBox.ROSTER_ITEM) +				.attr('title', item.attr('affiliation') + '/' + item.attr('role')) +				.attr('contactName', fromName)) +		} +	} +    }, + + +    /** Function: update +     * +     */ +    update: function(contactBareJid, fromName, msg, isroom) +    { +	var chatBoxElm = BeeChat.UI.ChatBoxes.getChatBoxElm(contactBareJid); +	debugXMPP(contactBareJid + " " + msg + " " + chatBoxElm.length); +	if (chatBoxElm.length == 0) { +            if (isroom) { +	    	BeeChat.UI.ScrollBoxes.addRoom(contactBareJid); +	        BeeChat.UI.ChatBoxes.show(contactBareJid); +	        BeeChat.UI.ChatBoxes.takeStand(contactBareJid); +		} +	    else { +	    	BeeChat.UI.ScrollBoxes.add(contactBareJid,false,true); +	//        BeeChat.UI.ChatBoxes.show(contactBareJid); +	        BeeChat.UI.ChatBoxes.takeStand(contactBareJid); +		} +	    chatBoxElm = BeeChat.UI.ChatBoxes.getChatBoxElm(contactBareJid); +	} + +	var chatBoxContentElm = chatBoxElm.children().filter('[bareJid="' + contactBareJid + '"]'); + +	chatBoxContentElm.find('p').filter('[class=' + BeeChat.UI.Resources.StyleClasses.ChatBox.STATE + ']').remove(); + +	var chatBoxLastMessageElm = $(chatBoxContentElm).find('div').filter('[class=' + BeeChat.UI.Resources.StyleClasses.ChatBox.MESSAGE + ']').filter(':last'); + +	if (chatBoxLastMessageElm && chatBoxLastMessageElm.find('span').filter('[class=' + BeeChat.UI.Resources.StyleClasses.ChatBox.MESSAGE_SENDER + ']').text() == fromName) { +	    chatBoxLastMessageElm.append('<p>' + BeeChat.UI.Utils.getPrintableChatMessage(msg) + '</p>'); +	} else { +	    chatBoxContentElm.append($('<div></div>') +				     .attr('class', BeeChat.UI.Resources.StyleClasses.ChatBox.MESSAGE) +				     .append($('<span></span>') +					     .attr('class', BeeChat.UI.Resources.StyleClasses.ChatBox.MESSAGE_SENDER) +					     .text(fromName)) +				     .append($('<span></span>') +					     .attr('class', BeeChat.UI.Resources.StyleClasses.ChatBox.MESSAGE_DATE) +					     .text(BeeChat.UI.Utils.getNowFormattedTime())) +				     .append('<p>' + BeeChat.UI.Utils.getPrintableChatMessage(msg) + '</p>')); +	} + +	chatBoxContentElm.attr({scrollTop: chatBoxContentElm.attr('scrollHeight')}); + +	var scrollBoxesElm = $('#' + BeeChat.UI.Resources.Elements.ID_DIV_SCROLLBOXES); +	var scrollBoxElm = BeeChat.UI.ScrollBoxes.getScrollBoxElm(contactBareJid); + +	if (BeeChat.UI.ScrollBoxes.isInitialized == false) { +	    scrollBoxesElm.trigger('goto', scrollBoxesElm.find('ul').children().index(scrollBoxElm)); +	} + +        debugXMPP("about to update number!"); +	if (chatBoxElm.is(':hidden')) { +	    debugXMPP("update number!"); +	    BeeChat.UI.UnreadCountBox.update(contactBareJid); +//	    if (BeeChat.UI.HAS_FOCUS) +//		document.getElementById(BeeChat.UI.Resources.Sounds.NEW_MESSAGE).Play(); +	} + +//	if (!BeeChat.UI.HAS_FOCUS) +//	    document.getElementById(BeeChat.UI.Resources.Sounds.NEW_MESSAGE).Play(); +    }, + +    /** Function: updateChatState +     * +     */ +    updateChatState: function(contactBareJid, msg) +    { +	var chatBoxContentElm = BeeChat.UI.ChatBoxes.getChatBoxElm(contactBareJid).children().filter('[bareJid="' + contactBareJid + '"]'); + +	$(msg).children().each(function() { +		if (this.tagName == BeeChat.Message.ChatStates.COMPOSING) { +		    if (chatBoxContentElm.find('p').filter('[class=' + BeeChat.UI.Resources.StyleClasses.ChatBox.STATE + ']').length == 0) { +			$('<p></p>') +			    .attr('class', BeeChat.UI.Resources.StyleClasses.ChatBox.STATE) +			    .html(BeeChat.UI.Utils.getContactName(contactBareJid) + BeeChat.UI.Resources.Strings.ChatMessages.COMPOSING + "</br />") +			    .appendTo(chatBoxContentElm); +		    } +		} else if (this.tagName == BeeChat.Message.ChatStates.PAUSED) { +		    chatBoxContentElm.find('p').filter('[class=' + BeeChat.UI.Resources.StyleClasses.ChatBox.STATE + ']').remove(); +		} +	    }); +	chatBoxContentElm.attr({scrollTop: chatBoxContentElm.attr('scrollHeight')}); +    }, + +    /** Function: remove +     * +     */ +    remove: function(contactBareJid) +    { +	BeeChat.UI.ChatBoxes.getChatBoxElm(contactBareJid).remove(); +	BeeChat.UI.ScrollBoxes.getScrollBoxElm(contactBareJid).remove(); +    }, + +    /** Function: show +     * +     */ +    show: function(contactBareJid) +    { +	BeeChat.UI.ChatBoxes.getChatBoxElm(contactBareJid).show(); +    }, + +    /** Function: hide +     * +     */ +    hide: function(contactBareJid) +    { +	BeeChat.UI.ChatBoxes.getChatBoxElm(contactBareJid).hide(); +    }, + +    /** Function: getChatBoxElm +     * +     */ +    getChatBoxElm: function(contactBareJid) +    { +	return $('#' + BeeChat.UI.Resources.Elements.ID_DIV_CHATBOXES).children().filter('[bareJid="' + contactBareJid + '"]'); +    } +}; + +BeeChat.UI.UnreadCountBox = { +    /** Function: add +     * +     */ +    add: function(contactBareJid) +    { +	BeeChat.UI.ScrollBoxes.getScrollBoxElm(contactBareJid) +	.append($('<span></span>') +		.attr('class', BeeChat.UI.Resources.StyleClasses.UNREAD_COUNT)); +    }, + +    /** Function: remove +     * +     */ +    remove: function(contactBareJid) +    { +	BeeChat.UI.UnreadCountBox.getElm(contactBareJid).remove(); +    }, + +    /** Function: update +     * +     */ +    update: function(contactBareJid) +    { +	if (arguments.length > 1 && !arguments[1]) +	    return; + +	var unreadCountBoxElm = BeeChat.UI.UnreadCountBox.getElm(contactBareJid); +	if (unreadCountBoxElm.length == 0) { +	    BeeChat.UI.UnreadCountBox.add(contactBareJid); +	    unreadCountBoxElm = BeeChat.UI.UnreadCountBox.getElm(contactBareJid); +	} +	if (arguments.length == 1) { +	    var unreadCount = unreadCountBoxElm.text(); +	    unreadCountBoxElm.text(++unreadCount); +	} else +	    unreadCountBoxElm.text(arguments[1]); +    }, + +    /** Function: getElm +     * +     */ +    getElm: function(contactBareJid) +    { +	return BeeChat.UI.ScrollBoxes.getScrollBoxElm(contactBareJid).find('span').filter('[class=' + BeeChat.UI.Resources.StyleClasses.UNREAD_COUNT +' ]'); +    } +}; + +/** Class: BeeChat.UI.Utils + *  An object container for all UI utilities functions + * + */ +BeeChat.UI.Utils = { +    /** Function: getTruncatedContactName +     * +     */ +    getTruncatedContactName: function(bareJid) +    { +	return (BeeChat.UI.Utils.truncateString(BeeChat.UI.Utils.getContactName(bareJid), (arguments.length == 2) ? arguments[1] : 21)); +    }, + +    /** Function: getTruncatedContactStatus +     * +     */ +    getTruncatedContactStatus: function(contactStatus) +    { +	return (BeeChat.UI.Utils.truncateString(contactStatus, (arguments.length == 2 ? arguments[1] : 50))); +    }, + +    /** Function: getContactName +     * +     */ +    getContactName: function(bareJid) +    { +	var contactName = bareJid; + +	if (g_beechat_roster_items != null && g_beechat_roster_items[bareJid]) +	    contactName = g_beechat_roster_items[bareJid].name; +	// no contact name so we show bareJid +	if (!contactName || contactName == '') +		contactName = bareJid; + +	return (contactName); +    }, + +    /** Function: getPrintableChatMessage +     * +     */ +    getPrintableChatMessage: function(msg) +    { +	var val = new String; +	val = $('<div>' + msg + '</div>'); +	msg = val.text(); + +	msg = jQuery.trim(msg); +	msg = BeeChat.UI.Utils.replaceLinks(msg); +	msg = BeeChat.UI.Utils.replaceSmileys(msg); + +	return msg; +    }, + +    /** Function: getNowFormattedTime +     * +     */ +    getNowFormattedTime: function() +    { +	var date = new Date(); + +	var hours = date.getHours(); +	var minutes = date.getMinutes(); +	var seconds = date.getSeconds(); + +	if (hours < 10) +	    hours = '0' + hours; +	if (minutes < 10) +	    minutes = '0' + minutes; +	if (seconds < 10) +	    seconds = '0' + seconds; +	return (hours + ':' + minutes + ':' + seconds); +    }, + + +    /** Function: replaceSmileys +     *  Replace smileys founded in a string to beautiful icons :) +     * +     *  Parameters: +     *    (String) str - The string containing smileys +     * +     */ +    replaceSmileys: function(str) +    { +	str = str.replace(/(;\))/gi, '<img src="' + BeeChat.UI.Resources.Paths.ICONS + BeeChat.UI.Resources.Emoticons.FILENAME_WINK + '" />'); +	str = str.replace(/(:\))/gi, '<img src="' + BeeChat.UI.Resources.Paths.ICONS + BeeChat.UI.Resources.Emoticons.FILENAME_SMILE + '" />'); +	str = str.replace(/(:\()/gi, '<img src="' + BeeChat.UI.Resources.Paths.ICONS + BeeChat.UI.Resources.Emoticons.FILENAME_UNHAPPY + '" />'); +	str = str.replace(/(:D)/gi, '<img src="' + BeeChat.UI.Resources.Paths.ICONS + BeeChat.UI.Resources.Emoticons.FILENAME_GRIN + '" />'); +	str = str.replace(/(:o)/gi, '<img src="' + BeeChat.UI.Resources.Paths.ICONS + BeeChat.UI.Resources.Emoticons.FILENAME_SURPRISED + '" />'); +	str = str.replace(/(xD)/gi, '<img src="' + BeeChat.UI.Resources.Paths.ICONS + BeeChat.UI.Resources.Emoticons.FILENAME_EVILGRIN + '" />'); +	str = str.replace(/(:p)/gi, '<img src="' + BeeChat.UI.Resources.Paths.ICONS + BeeChat.UI.Resources.Emoticons.FILENAME_TONGUE + '" />'); + +	return (str); +    }, + +    /** Function: replaceLinks +     *  Transform links founded in a string to clickable links +     * +     *  Parameters: +     *    (String) str - The string where will be replaced links +     */ +    replaceLinks: function(str) +    { +	var xpr = +	/((ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?)/gi; + +	return (str.replace(xpr, '<a href="$1" target="_blank">$1</a>')); +    }, + +    /** Function: truncateString +     *  Truncate a string at a specified length +     * +     *  Parameters: +     *    (String) str - The string to truncate +     *    (int) len - The maximum length of str +     */ +    truncateString: function(str, len) +    { +	if (str != null && str.length > len) +	    return ((str.substr(0, len) + '...')); +	return (str); +    } +}; + + +/** Executed when the DOM is ready + * + */ +function init_beechat(ts, token) { +	if (typeof document.body.style.maxHeight === "undefined") { // IE6 +	    return; +	} + +	BeeChat.UI.initialize(ts, token); +} + +/** Window resizing + * + */ +$(window).resize(function() { +	if (typeof document.body.style.maxHeight === "undefined") { // IE6 +	    return; +	} + +	$('#' + BeeChat.UI.Resources.Elements.ID_DIV_CHATBOXES).children().each(function() { +		var scrollBoxElm = BeeChat.UI.ScrollBoxes.getScrollBoxElm($(this).attr('bareJid')); +		var pos = scrollBoxElm.position().left - ($(this).width() - scrollBoxElm.width()) + 24; + +		$(this).css({'left': pos}); +	    }); +}); + + +/** Executed when the page is unloaded + * + */ +$(window).unload(function() { +	if (typeof document.body.style.maxHeight === "undefined") { // IE6 +	    return; +	} + +	if (!$('#beechat').length) +		return; + +	if (g_beechat_user != null) { +	    g_beechat_user.requestSessionPause(); +	    BeeChat.UI.saveState(); +	} + +	BeeChat.UI.saveConnection(); +    }); + + +/** Check whether the BeeChat tab is active or not + * + */ +$(window).bind('blur', function() { +	BeeChat.UI.HAS_FOCUS = false; +    }); + +$(window).bind('focus', function() { +	BeeChat.UI.HAS_FOCUS = true; +    }); diff --git a/mod/beechat/views/default/beechat/beechat.php b/mod/beechat/views/default/beechat/beechat.php new file mode 100644 index 000000000..397d35f74 --- /dev/null +++ b/mod/beechat/views/default/beechat/beechat.php @@ -0,0 +1,84 @@ +<?php +	/** +	 * Beechat +	 *  +	 * @package beechat +	 * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html GNU Public License version 2 +	 * @author Beechannels <contact@beechannels.com> +	 * @copyright Beechannels 2007-2010 +	 * @link http://beechannels.com/ +	 */ + +if (elgg_is_logged_in() && elgg_get_logged_in_user_entity()->chatenabled && elgg_get_context() != 'admin') { +?>	  +<div id="beechat"> +  <div id="beechat_left"> +    <a id="beechat_tooltip_trigger" href="<?php echo $vars['url']; ?>"><img src="<?php echo $vars['config']->wwwroot; ?>favicon.ico" /></a> +    <div class="tooltip tooltipchat"> +      <h3><?php echo elgg_echo('beechat:icons:home'); ?></h3> +    </div> +  </div> +  <div id="beechat_center"> +    <span id="beechat_center_prev" class="prev"></span> +    <div id="beechat_scrollboxes"><ul></ul></div> +    <span id="beechat_center_next" class="next"></span> +  </div> +  <div id="beechat_right"> +    <span id="beechat_contacts_button" class="offline"> +      <?php echo elgg_echo('beechat:contacts:button'); ?> +    </span> +  </div> +  <div id="beechat_contacts"> +    <div id="beechat_contacts_top"> +      <span class="beechat_label"><?php echo elgg_echo('beechat:contacts:button'); ?></span> +      <div id="beechat_contacts_controls"> +	<span id="beechat_contacts_control_minimize" class="beechat_control" title="<?php echo elgg_echo('beechat:box:minimize'); ?>">_</span> +      </div> +      <br clear="all" /> +    </div> +    <div id="beechat_availability_switcher"> +      <span id="beechat_current_availability"></span> +      <span class="beechat_availability_switcher_control_down" id="beechat_availability_switcher_control"></span> +    </div> +    <div id="beechat_contacts_content"> +      <ul id="beechat_contacts_list"></ul> +      <ul id="beechat_availability_switcher_list"> +	<li class="beechat_left_availability_chat"><?php echo elgg_echo('beechat:availability:available'); ?></li> +	<li class="beechat_left_availability_dnd"><?php echo elgg_echo('beechat:availability:dnd'); ?></li> +	<li class="beechat_left_availability_away"><?php echo elgg_echo('beechat:availability:away'); ?></li> +	<li class="beechat_left_availability_xa"><?php echo elgg_echo('beechat:availability:xa'); ?></li> +	<li class="beechat_left_availability_offline"><?php echo elgg_echo('beechat:availability:offline'); ?></li> +      </ul> +    </div> +    <div id="beechat_contacts_bottom"> +      <span id="beechat_contacts_bottom_bar"></span> +    </div> +  </div> +  <div id="beechat_chatboxes"></div> +</div> +<!-- SOUNDS --> +<!-- +<embed src="<?php echo $vars['config']->staticurl; ?>mod/beechat/sounds/newmessage.wav" autostart=false width=0 height=0 +       id="beechat_sounds_new_message" +       enablejavascript="true" /> +--> + +<?php +        $ts = time(); +        $token = generate_action_token($ts); +?> + +<script> +	$(function () { +		var e = document.createElement('script'); +		e.async = true; +		e.type = 'text/javascript'; +                e.text = 'init_beechat("<?php echo $ts; ?>","<?php echo $token; ?>");'; +                document.getElementById('beechat').appendChild(e); + +	}) +</script>        + +<?php + } +?> diff --git a/mod/beechat/views/default/beechat/beechat.userjs.php b/mod/beechat/views/default/beechat/beechat.userjs.php new file mode 100644 index 000000000..ed59b683f --- /dev/null +++ b/mod/beechat/views/default/beechat/beechat.userjs.php @@ -0,0 +1,54 @@ +<script type="text/javascript"> +BeeChat.Events.Messages = { +	    ConnectionStates: { +		CONNECTING: "<?php echo elgg_echo('beechat:connection:state:connecting'); ?>", +		AUTHENTICATING: "<?php echo elgg_echo('beechat:connection:state:authenticating'); ?>", +		FAILED: "<?php echo elgg_echo('beechat:connection:state:failed'); ?>", +		DISCONNECTING: "<?php echo elgg_echo('beechat:connection:state:disconnecting'); ?>", +		OFFLINE: "<?php echo elgg_echo('beechat:connection:state:offline'); ?>", +		ONLINE: "<?php echo elgg_echo('beechat:connection:state:online'); ?>" +	    } +	} + +BeeChat.UI.Resources.Strings = { +	    Availability: { +		AVAILABLE: "<?php echo elgg_echo('beechat:availability:available'); ?>", +		CHAT: "<?php echo elgg_echo('beechat:availability:available'); ?>", +		ONLINE: "<?php echo elgg_echo('beechat:availability:available'); ?>", +		DND: "<?php echo elgg_echo('beechat:availability:dnd'); ?>", +		AWAY: "<?php echo elgg_echo('beechat:availability:away'); ?>", +		XA:"<?php echo elgg_echo('beechat:availability:xa'); ?>", +		OFFLINE: "<?php echo elgg_echo('beechat:availability:offline'); ?>" +	    }, + +	    Contacts: { +		BUTTON: "<?php echo elgg_echo('beechat:contacts:button'); ?>" +	    }, + +	    ChatMessages: { +		SELF: "<?php echo $_SESSION['user']->name; ?>", +		COMPOSING: "<?php echo elgg_echo('beechat:chat:composing'); ?>" +	    }, + +	    Box: { +		MINIMIZE: "<?php echo elgg_echo('beechat:box:minimize'); ?>", +		CLOSE: "<?php echo elgg_echo('beechat:box:close'); ?>", +		SHOWHIDE: "<?php echo elgg_echo('beechat:box:showhide'); ?>" +	    } +	} +g_user_rooms = new Array(); +<?php +if (elgg_is_logged_in()) { +	$user = elgg_get_logged_in_user_entity(); +	$chatrooms = elgg_get_entities_from_relationship(array('relationship' => 'groupchat', +								'relationship_guid' => $user->guid, +								'inverse_relationship' => false, +								'limit' => 0)); +	if (!empty($chatrooms)) { +	  foreach($chatrooms as $chatroom) { +	    echo "g_user_rooms.push(['".beechat_friendly_title($chatroom->name)."@".elgg_get_plugin_setting("groupdomain", "beechat")."', '".$chatroom->guid."']);"; +	  } +	} +} +?> +</script> diff --git a/mod/beechat/views/default/beechat/screen.css.php b/mod/beechat/views/default/beechat/screen.css.php new file mode 100644 index 000000000..930e60089 --- /dev/null +++ b/mod/beechat/views/default/beechat/screen.css.php @@ -0,0 +1,672 @@ +<?php +   global $CONFIG; +   $url = $CONFIG->wwwroot; + +?> +/** + * Beechat + * + * @package beechat + * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html GNU Public License version 2 + * @author Beechannels <contact@beechannels.com> + * @copyright Beechannels 2007-2010 + * @link http://beechannels.com/ + */ + +div#beechat { +    display: block !important; +    display: none; +    position: fixed; +    left: 1%; +    right: 1%; +    bottom: 0; +    margin: 0; +    padding: 0; +    height: 20px; +    z-index: 999; + +    font-family: Arial, Helvetica, "Liberation Sans", FreeSans, sans-serif; +    font-size: 0.9em; +    color: #222222; +    background-color: #DDDDDD; +    border-top: 1px solid #BBBBBB; +    border-left: 1px solid #BBBBBB; +} +div#beechat a img { +    border: none; +} +div#beechat a { +    text-decoration: none; +} +div#beechat img { +    vertical-align: middle; +} +div#beechat a:hover { +    text-decoration: underline; +} +.beechat_control { +    cursor: pointer; +    color: #CCCCFF; +    font-size: 1.6em; +} +.beechat_control:hover { +    color: white; +} +.beechat_box_control { +    cursor: pointer; +    color: #888888; +    font-size: 1em; +} +.beechat_box_control:hover { +    color: #222222; +} +.beechat_chatbox_control { +    cursor: pointer; +    color: #CCCCFF; +    font-size: 1.6em; +} +.beechat_chatbox_control:hover { +    color: white; +} +.beechat_label { +    font-weight: bold; +    font-size: 1.1em; +} + +/* +** - +** left side +** - +*/ +div#beechat_left { +    position: absolute; +    top: 0; +    left: 0; +    width: 116px; +    height: 18px; +    margin: 0; +    padding: 1px 2px; +} + + +/* +** - +** right side +** - +*/ +div#beechat_right { +    position: absolute; +    top: 0; +    right: 0; +    width: 220px; +    height: 20px; +    margin: 0; +    padding: 0 0 0 0; + +    border-left: 1px solid #BBBBBB; +    border-right: 1px solid #BBBBBB; +} +div#beechat_contacts { +    position: absolute; +    right: 0px; +    bottom: 0; +    width: 222px; +    height: 240px; +    margin: 0 auto 20px auto; +    padding: 0; +    display: none; + +    background-color: white; +} +div#beechat_contacts_top { +    color: white; +    background-color: #193C60; +    width: 220px; +    height: 32px; + +    border-top: 1px solid #0B2C4F; +    border-left: 1px solid #0B2C4F; +    border-right: 1px solid #0B2C4F; +} +div#beechat_contacts_top .beechat_label { +    float: left; +    height: 20px; +    padding: 6px; +} +div#beechat_contacts_controls { +    margin: 0; +    padding: 0; +} +div#beechat_contacts_controls span#beechat_contacts_control_minimize { +    position: relative; +    top: -7px; +    float: right; +    display: block; +    width: 20px; +    height: 20px; +    padding: 2px; + +    font-size: 1.6em; +    font-weight: bold; +    text-align: center; +} +span#beechat_contacts_button { +    display: block; +    width: 190px; +    padding: 2px 6px 0 24px; +    height: 18px; +    cursor: pointer; +    font-size: 1.1em; +    font-weight: normal; + +    background-image: url('<?php echo $url; ?>mod/beechat/graphics/icons/statuses.png'); +} +span#beechat_contacts_button.online { +    background-position: 4px -750px; +    background-repeat: no-repeat; +} +span#beechat_contacts_button.dnd { +    background-position: 4px -796px; +    background-repeat: no-repeat; +} +span#beechat_contacts_button.away { +    background-position: 4px -842px; +    background-repeat: no-repeat; +} +span#beechat_contacts_button.offline { +    background-position: 4px -888px; +    background-repeat: no-repeat; +} +span#beechat_contacts_button:hover { +    background-color: white; +} +div#beechat_availability_switcher { +    width: 218px; +    height: 24px; +    margin: 0; +    padding: 0 0 0 2px; + +    background-color: #EEEEEE; +    border-left: 1px solid #666666; +    border-right: 1px solid #666666; +    border-bottom: 1px solid #BBBBBB; +} +span#beechat_current_availability { +    float: left; +    padding: 4px 4px 4px 22px; + +    font-weight: bold; +    cursor: pointer; +} +span#beechat_current_availability:hover { +    text-decoration: underline; +} +span#beechat_availability_switcher_control { +    float: right; +    width: 24px; +    height: 20px; +    cursor: pointer; +} +span.beechat_availability_switcher_control_up { +    background: no-repeat 50% 50% url('<?php echo $url; ?>mod/beechat/graphics/icons/bullet_arrow_up.png'); +} +span.beechat_availability_switcher_control_down { +    background: no-repeat 50% 50% url('<?php echo $url; ?>mod/beechat/graphics/icons/bullet_arrow_down.png'); +} +ul#beechat_availability_switcher_list { +    display: none; +    padding:0; +    margin:0; +    list-style:none; +} +ul#beechat_availability_switcher_list li { +    margin: 0; +    padding: 4px 4px 4px 24px; + +    cursor: pointer; +} +ul#beechat_availability_switcher_list li:hover { +    background-color: #EEEEEE; +} +div#beechat_contacts_content { +    width: 220px; +    height: 164px; +    overflow: auto; + +    border-left: 1px solid #666666; +    border-right: 1px solid #666666; +    background-color: white; +} +ul#beechat_contacts_list { +    background-color: white; +    padding:0; +    margin:0; +    list-style:none; +} +ul#beechat_contacts_list li img { +    margin: 0 4px 0 0; +    width: 25px; +    height: 25px; +} +ul#beechat_contacts_list li { +    margin: 0; +    padding: 4px 4px 4px 6px; + +    cursor: pointer; +    color: #333; +} +ul#beechat_contacts_list li:hover { +    background-color: #F5F6F8; +    color: #333; +} +div#beechat_contacts_bottom { +    width: 220px; +    height: 18px; + +    border-left: 1px solid #666666; +    border-right: 1px solid #666666; +} +span#beechat_contacts_bottom_bar { +    position: absolute; +    display: block; +    bottom: 0; +    width: 210px; +    height: 1px; + +    background-color: #BBBBBB; +    margin: auto 4px; +} + + +/* +** - +** center area +** - +*/ +div#beechat_center { +    float: right; +    display: block; +    width: 586px; +    height: 20px; +    margin: 0 220px 0 100px; +    *margin: 0 312px 0 100px; +    padding: 0; +} +div#beechat_center .next, div#beechat_center .prev { +    display: none; + +    border-left: 1px solid #BBBBBB; +    cursor: pointer; +} +div#beechat_center .next { +    position: absolute; +    right: 220px; +    width: 24px; +    height: 20px; + +    background: no-repeat 50% url("<?php echo $url; ?>mod/beechat/graphics/icons/resultset_next.png"); +} +div#beechat_center .prev { +    position: absolute; +    right: 872px; +    width: 24px; +    height: 20px; + +    background: no-repeat 50% url("<?php echo $url; ?>mod/beechat/graphics/icons/resultset_previous.png"); +} +div#beechat_scrollboxes { +    float: right; +    overflow: hidden; +    width: 628px; +    height: 21px; +    margin: 0 24px 0 24px; +    text-align: left; +} +div#beechat_scrollboxes ul { +    width: 200000em; +    list-style: none; +    padding:0; +    margin:0; +} +div#beechat_scrollboxes ul li { +    float: right; +    display: block; +    width: 130px; +    height: 20px; +    padding: 1px 0 0 22px; + +    cursor: pointer; +    border-left: 1px solid #BBBBBB; +} +div#beechat_scrollboxes ul li:hover { +    color: #000000; +    background-color: white; +} +div#beechat_scrollboxes ul li.beechat_scrollbox_selected { +    border-left: 1px solid #666666; +    border-right: 1px solid #666666; +    background-color: white; +} +div#beechat_scrollboxes ul li span.beechat_unread_count { +    float: right; +    display: block; +    width: 16px; +    height: 14px; +    padding-top: 2px; +    margin: 0 6px 0 0; + +    text-align: center; +    font-size: 0.7em; +    color: white; +    background: no-repeat 0% 50% url('<?php echo $url; ?>mod/beechat/graphics/icons/notification_pink.png'); +} +div#beechat_scrollboxes ul li span#beechat_box_control_close { +    float: right; +    width: auto; +    padding: 1px 4px; +    height: 20px; +} + +/* +** -- +** availability classes +** -- +*/ +.beechat_left_availability_chat { +    background: no-repeat 2% 50% url('<?php echo $url; ?>mod/beechat/graphics/icons/bullet_green.png'); +} +.beechat_left_availability_dnd { +    background: no-repeat 2% 50% url('<?php echo $url; ?>mod/beechat/graphics/icons/bullet_delete.png'); +} +.beechat_left_availability_away { +    background: no-repeat 2% 50% url('<?php echo $url; ?>mod/beechat/graphics/icons/bullet_orange.png'); +} +.beechat_left_availability_xa { +    background: no-repeat 2% 50% url('<?php echo $url; ?>mod/beechat/graphics/icons/bullet_red.png'); +} +.beechat_left_availability_offline { +    background: no-repeat 2% 50% url('<?php echo $url; ?>mod/beechat/graphics/icons/bullet_black.png'); +} +.beechat_left_availability_room { +    background: no-repeat 2% 50% url('<?php echo $url; ?>mod/beechat/graphics/icons/muc_icon.png'); +} + + + +.beechat_right_availability_chat { +    background: no-repeat 96% 50% url('<?php echo $url; ?>mod/beechat/graphics/icons/bullet_green.png'); +} +.beechat_right_availability_dnd { +    background: no-repeat 96% 50% url('<?php echo $url; ?>mod/beechat/graphics/icons/bullet_delete.png'); +} +.beechat_right_availability_away { +    background: no-repeat 96% 50% url('<?php echo $url; ?>mod/beechat/graphics/icons/bullet_orange.png'); +} +.beechat_right_availability_xa { +    background: no-repeat 96% 50% url('<?php echo $url; ?>mod/beechat/graphics/icons/bullet_red.png'); +} +.beechat_right_availability_offline { +    background: no-repeat 96% 50% url('<?php echo $url; ?>mod/beechat/graphics/icons/bullet_black.png'); +} +.beechat_right_availability_room { +    background: no-repeat 96% 50% url('<?php echo $url; ?>mod/beechat/graphics/icons/muc_icon.png'); +} + +/* +** -- +** tooltips +** -- +*/ +div.tooltip.tooltipchat { +    display: none; +    padding: 4px; +    width: auto; +    background: transparent no-repeat left bottom url('<?php echo $url; ?>mod/beechat/graphics/icons/pointer.png'); +} +div.tooltip.tooltipchat h3 { +    margin: 0; +    padding: 4px; + +    font-weight: normal; +    font-size: 0.9em; +    color: white; +    background-color: #222222; +} + + +/* +** -- +** chatboxes +** -- +*/ +div.beechat_chatbox { +    position: absolute; +    width: 240px; +    height: 300px; +    bottom: 25px; +    margin: 0; +    padding: 0; + +    background-color: #DDDDDD; +} +div.beechat_chatbox a { +    color: white; +} +div.beechat_chatbox a:hover { +    text-decoration: underline; +} +div.beechat_chatbox_roomroster { +    position: absolute; +    width: 100px; +    height: 276px; +    left: -101px; +    bottom: -2px; +    margin: 0; +    padding: 0; +    overflow: auto; + +    border: 1px solid #4B6C8F; + +    background-color: #EEEEEE; +} +div.beechat_chatbox_roomrosteritem { +    background-color: #FFFFFF; +    margin: 3px; +    padding-left: 2px; +} +div.beechat_chatbox_chatroom { +    position: absolute; +    width: 240px; +    height: 300px; +    left: 100px; +    bottom: 0px; +    margin: 0; +    padding: 0; + +    background-color: #DDDDDD; +} +div.beechat_chatbox_chatroom a { +    color: white; +} +div.beechat_chatbox_chatroom a:hover { +    text-decoration: underline; +} + +div.beechat_chatbox_room { +    position: absolute; +    width: 340px; +    height: 300px; +    bottom: 25px; +    margin: 0; +    padding: 0; + +    background-color: #DDDDDD; +} +div.beechat_chatbox_room a { +    color: white; +} +div.beechat_chatbox_room a:hover { +    text-decoration: underline; +} +div.beechat_chatbox_top { +    width: 238px; +    height: 24px; +    margin: 0; +    padding: 0; + +    font-size: 0.9em; +    color: white; +    background-color: #193C60; +    border-top: 1px solid #0B2C4F; +    border-left: 1px solid #0B2C4F; +    border-right: 1px solid #0B2C4F; +} +div.beechat_chatbox_top .beechat_chatbox_top_icon { +    position: absolute; +    top: 4px; +    left: 4px; +    z-index: 2; + +    width: 50px; +    height: 50px; +} +div.beechat_chatbox_top .beechat_label { +    float: left; +    height: 13px; +    padding: 4px 6px 6px 6px; + +    margin-left: 54px; +} +div.beechat_chatbox_top_controls { +    margin: 0; +    padding: 0; +} +div.beechat_chatbox_top_controls .beechat_chatbox_control { +    float: right; +    display: block; +    width: 20px; +    height: 19px; +    padding: 2px; +    margin: 0; + +    font-size: 1.2em; +    font-weight: bold; +    text-align: center; +} +div.beechat_chatbox_subtop { +    width: 172px; +    height: 30px; +    padding: 2px 6px 2px 60px; + +    border-left: 1px solid #666666; +    border-right: 1px solid #666666; +    border-bottom: 1px solid #CCCCCC; +    background-color: #DDDDDD; +} +div.beechat_chatbox_content { +    width: 238px; +    height: 202px; +    margin: 0; +    padding: 0; +    overflow: auto; + +    border-left: 1px solid #666666; +    border-right: 1px solid #666666; +    background-color: white; +} +div.beechat_chatbox_content div.beechat_chatbox_message { +    width: auto; +    height: auto; +    margin: 0; +    padding: 2px; +    border-top: 1px solid #DDDDDD; +} +div.beechat_chatbox_message span.beechat_chatbox_message_sender { +    position: relative; +    top: 0; +    left: 6px; +    font-weight: bold; +    font-size: 1em; +} +div.beechat_chatbox_message span.beechat_chatbox_message_date { +    float: right; +    margin: 0 6px 0 0; +} +div.beechat_chatbox_content a { +    color: #003399; +} +div.beechat_chatbox_content a:hover { +    text-decoration: underline; +} +div.beechat_chatbox_content p { +    margin: 0; +    padding: 2px 6px; +} +div.beechat_chatbox_content p.beechat_chatbox_state { +    font-size: 1em; +    color: #888888; +} +div.beechat_chatbox_input { +    width: 238px; +    height: 40px; +    margin: 0; +    padding: 0; + +    border-top: 2px solid #BBBBBB; +    border-left: 1px solid #666666; +    border-right: 1px solid #666666; +    background-color: #DDDDDD; +} +div.beechat_chatbox_input textarea { +    width: 204px; +    height: 32px; +    max-width: 240px; +    max-height: 40px; +    padding: 4px 4px 4px 30px; +    margin: auto; +    overflow: hidden; +    vertical-align: top; +    resize: none; + +    font-size: 1em; +    font-family: Arial, Helvetica, "Liberation Sans", FreeSans, sans-serif; +    outline: none; +    border: none; +    background: white no-repeat 4px 3px url('<?php echo $url; ?>mod/beechat/graphics/icons/chat_icon.png'); +} +div.beechat_chatbox_input textarea:focus { +    outline: none; +    border: none; +    background-color: white; +} +div.beechat_chatbox_bottom { +    position: absolute; +    width: 238px; +    height: 1px; + +    background-color: white; +    border-left: 1px solid #666666; +    border-right: 1px solid #666666; +    border-bottom: 1px solid #666666; +    z-index: 2; +} +div.beechat_chatbox_bottom span { +    position: absolute; +    display: block; +    right: 0; +    top: 0; +    width: 152px; +    height: 1px; + +    border-bottom: 1px solid white; +} +div.beechat_chatbox_bottom span span { +    position: absolute; +    display: block; +    width: 146px; +    height: 1px; +    right: 4px; +    top: 0; + +    border-bottom: 1px solid #BBBBBB; +} diff --git a/mod/beechat/views/default/js/b64.js.php b/mod/beechat/views/default/js/b64.js.php new file mode 100644 index 000000000..201bdbd7c --- /dev/null +++ b/mod/beechat/views/default/js/b64.js.php @@ -0,0 +1,74 @@ +// This code was written by Tyler Akins and has been placed in the +// public domain.  It would be nice if you left this header intact. +// Base64 code from Tyler Akins -- http://rumkin.com + +var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; + +/** + * Encodes a string in base64 + * @param {String} input The string to encode in base64. + */ +function encode64(input) { +   var output = ""; +   var chr1, chr2, chr3; +   var enc1, enc2, enc3, enc4; +   var i = 0; + +   do { +      chr1 = input.charCodeAt(i++); +      chr2 = input.charCodeAt(i++); +      chr3 = input.charCodeAt(i++); + +      enc1 = chr1 >> 2; +      enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); +      enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); +      enc4 = chr3 & 63; + +      if (isNaN(chr2)) { +         enc3 = enc4 = 64; +      } else if (isNaN(chr3)) { +         enc4 = 64; +      } + +      output = output + keyStr.charAt(enc1) + keyStr.charAt(enc2) + +         keyStr.charAt(enc3) + keyStr.charAt(enc4); +   } while (i < input.length); + +   return output; +} + +/** + * Decodes a base64 string. + * @param {String} input The string to decode. + */ +function decode64(input) { +   var output = ""; +   var chr1, chr2, chr3; +   var enc1, enc2, enc3, enc4; +   var i = 0; + +   // remove all characters that are not A-Z, a-z, 0-9, +, /, or = +   input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ""); + +   do { +      enc1 = keyStr.indexOf(input.charAt(i++)); +      enc2 = keyStr.indexOf(input.charAt(i++)); +      enc3 = keyStr.indexOf(input.charAt(i++)); +      enc4 = keyStr.indexOf(input.charAt(i++)); + +      chr1 = (enc1 << 2) | (enc2 >> 4); +      chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); +      chr3 = ((enc3 & 3) << 6) | enc4; + +      output = output + String.fromCharCode(chr1); + +      if (enc3 != 64) { +         output = output + String.fromCharCode(chr2); +      } +      if (enc4 != 64) { +         output = output + String.fromCharCode(chr3); +      } +   } while (i < input.length); + +   return output; +} diff --git a/mod/beechat/views/default/js/jquery.cookie.min.js.php b/mod/beechat/views/default/js/jquery.cookie.min.js.php new file mode 100644 index 000000000..cb09af984 --- /dev/null +++ b/mod/beechat/views/default/js/jquery.cookie.min.js.php @@ -0,0 +1,10 @@ +/** + * Cookie plugin + * + * Copyright (c) 2006 Klaus Hartl (stilbuero.de) + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html + * + */ +jQuery.cookie=function(name,value,options){if(typeof value!='undefined'){options=options||{};if(value===null){value='';options=$.extend({},options);options.expires=-1;}var expires='';if(options.expires&&(typeof options.expires=='number'||options.expires.toUTCString)){var date;if(typeof options.expires=='number'){date=new Date();date.setTime(date.getTime()+(options.expires*24*60*60*1000));}else{date=options.expires;}expires='; expires='+date.toUTCString();}var path=options.path?'; path='+(options.path):'';var domain=options.domain?'; domain='+(options.domain):'';var secure=options.secure?'; secure':'';document.cookie=[name,'=',encodeURIComponent(value),expires,path,domain,secure].join('');}else{var cookieValue=null;if(document.cookie&&document.cookie!=''){var cookies=document.cookie.split(';');for(var i=0;i<cookies.length;i++){var cookie=jQuery.trim(cookies[i]);if(cookie.substring(0,name.length+1)==(name+'=')){cookieValue=decodeURIComponent(cookie.substring(name.length+1));break;}}}return cookieValue;}};
\ No newline at end of file diff --git a/mod/beechat/views/default/js/jquery.localscroll-1.2.7-min.js.php b/mod/beechat/views/default/js/jquery.localscroll-1.2.7-min.js.php new file mode 100644 index 000000000..fa583a451 --- /dev/null +++ b/mod/beechat/views/default/js/jquery.localscroll-1.2.7-min.js.php @@ -0,0 +1,9 @@ +/** + * jQuery.LocalScroll - Animated scrolling navigation, using anchors. + * Copyright (c) 2007-2009 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com + * Dual licensed under MIT and GPL. + * Date: 3/11/2009 + * @author Ariel Flesler + * @version 1.2.7 + **/ +;(function($){var l=location.href.replace(/#.*/,'');var g=$.localScroll=function(a){$('body').localScroll(a)};g.defaults={duration:1e3,axis:'y',event:'click',stop:true,target:window,reset:true};g.hash=function(a){if(location.hash){a=$.extend({},g.defaults,a);a.hash=false;if(a.reset){var e=a.duration;delete a.duration;$(a.target).scrollTo(0,a);a.duration=e}i(0,location,a)}};$.fn.localScroll=function(b){b=$.extend({},g.defaults,b);return b.lazy?this.bind(b.event,function(a){var e=$([a.target,a.target.parentNode]).filter(d)[0];if(e)i(a,e,b)}):this.find('a,area').filter(d).bind(b.event,function(a){i(a,this,b)}).end().end();function d(){return!!this.href&&!!this.hash&&this.href.replace(this.hash,'')==l&&(!b.filter||$(this).is(b.filter))}};function i(a,e,b){var d=e.hash.slice(1),f=document.getElementById(d)||document.getElementsByName(d)[0];if(!f)return;if(a)a.preventDefault();var h=$(b.target);if(b.lock&&h.is(':animated')||b.onBefore&&b.onBefore.call(b,a,f,h)===false)return;if(b.stop)h.stop(true);if(b.hash){var j=f.id==d?'id':'name',k=$('<a> </a>').attr(j,d).css({position:'absolute',top:$(window).scrollTop(),left:$(window).scrollLeft()});f[j]='';$('body').prepend(k);location=e.hash;k.remove();f[j]=d}h.scrollTo(f,b).trigger('notify.serialScroll',[f])}})(jQuery);
\ No newline at end of file diff --git a/mod/beechat/views/default/js/jquery.scrollTo-min.js.php b/mod/beechat/views/default/js/jquery.scrollTo-min.js.php new file mode 100755 index 000000000..5e7877810 --- /dev/null +++ b/mod/beechat/views/default/js/jquery.scrollTo-min.js.php @@ -0,0 +1,11 @@ +/** + * jQuery.ScrollTo - Easy element scrolling using jQuery. + * Copyright (c) 2007-2009 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com + * Dual licensed under MIT and GPL. + * Date: 5/25/2009 + * @author Ariel Flesler + * @version 1.4.2 + * + * http://flesler.blogspot.com/2007/10/jqueryscrollto.html + */ +;(function(d){var k=d.scrollTo=function(a,i,e){d(window).scrollTo(a,i,e)};k.defaults={axis:'xy',duration:parseFloat(d.fn.jquery)>=1.3?0:1};k.window=function(a){return d(window)._scrollable()};d.fn._scrollable=function(){return this.map(function(){var a=this,i=!a.nodeName||d.inArray(a.nodeName.toLowerCase(),['iframe','#document','html','body'])!=-1;if(!i)return a;var e=(a.contentWindow||a).document||a.ownerDocument||a;return d.browser.safari||e.compatMode=='BackCompat'?e.body:e.documentElement})};d.fn.scrollTo=function(n,j,b){if(typeof j=='object'){b=j;j=0}if(typeof b=='function')b={onAfter:b};if(n=='max')n=9e9;b=d.extend({},k.defaults,b);j=j||b.speed||b.duration;b.queue=b.queue&&b.axis.length>1;if(b.queue)j/=2;b.offset=p(b.offset);b.over=p(b.over);return this._scrollable().each(function(){var q=this,r=d(q),f=n,s,g={},u=r.is('html,body');switch(typeof f){case'number':case'string':if(/^([+-]=)?\d+(\.\d+)?(px|%)?$/.test(f)){f=p(f);break}f=d(f,this);case'object':if(f.is||f.style)s=(f=d(f)).offset()}d.each(b.axis.split(''),function(a,i){var e=i=='x'?'Left':'Top',h=e.toLowerCase(),c='scroll'+e,l=q[c],m=k.max(q,i);if(s){g[c]=s[h]+(u?0:l-r.offset()[h]);if(b.margin){g[c]-=parseInt(f.css('margin'+e))||0;g[c]-=parseInt(f.css('border'+e+'Width'))||0}g[c]+=b.offset[h]||0;if(b.over[h])g[c]+=f[i=='x'?'width':'height']()*b.over[h]}else{var o=f[h];g[c]=o.slice&&o.slice(-1)=='%'?parseFloat(o)/100*m:o}if(/^\d+$/.test(g[c]))g[c]=g[c]<=0?0:Math.min(g[c],m);if(!a&&b.queue){if(l!=g[c])t(b.onAfterFirst);delete g[c]}});t(b.onAfter);function t(a){r.animate(g,j,b.easing,a&&function(){a.call(this,n,b)})}}).end()};k.max=function(a,i){var e=i=='x'?'Width':'Height',h='scroll'+e;if(!d(a).is('html,body'))return a[h]-d(a)[e.toLowerCase()]();var c='client'+e,l=a.ownerDocument.documentElement,m=a.ownerDocument.body;return Math.max(l[h],m[h])-Math.min(l[c],m[c])};function p(a){return typeof a=='object'?a:{top:a,left:a}}})(jQuery);
\ No newline at end of file diff --git a/mod/beechat/views/default/js/jquery.serialScroll-min.js.php b/mod/beechat/views/default/js/jquery.serialScroll-min.js.php new file mode 100755 index 000000000..d716124f9 --- /dev/null +++ b/mod/beechat/views/default/js/jquery.serialScroll-min.js.php @@ -0,0 +1,10 @@ +/* + * jQuery.SerialScroll - Animated scrolling of series + * Copyright (c) 2007-2009 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com + * Dual licensed under MIT and GPL. + * Date: 06/14/2009 + * @author Ariel Flesler + * @version 1.2.2 + * http://flesler.blogspot.com/2008/02/jqueryserialscroll.html + */ +;(function(a){var b=a.serialScroll=function(c){return a(window).serialScroll(c)};b.defaults={duration:1e3,axis:"x",event:"click",start:0,step:1,lock:!0,cycle:!0,constant:!0};a.fn.serialScroll=function(c){return this.each(function(){var t=a.extend({},b.defaults,c),s=t.event,i=t.step,r=t.lazy,e=t.target?this:document,u=a(t.target||this,e),p=u[0],m=t.items,h=t.start,g=t.interval,k=t.navigation,l;if(!r){m=d()}if(t.force){f({},h)}a(t.prev||[],e).bind(s,-i,q);a(t.next||[],e).bind(s,i,q);if(!p.ssbound){u.bind("prev.serialScroll",-i,q).bind("next.serialScroll",i,q).bind("goto.serialScroll",f)}if(g){u.bind("start.serialScroll",function(v){if(!g){o();g=!0;n()}}).bind("stop.serialScroll",function(){o();g=!1})}u.bind("notify.serialScroll",function(x,w){var v=j(w);if(v>-1){h=v}});p.ssbound=!0;if(t.jump){(r?u:d()).bind(s,function(v){f(v,j(v.target))})}if(k){k=a(k,e).bind(s,function(v){v.data=Math.round(d().length/k.length)*k.index(this);f(v,this)})}function q(v){v.data+=h;f(v,this)}function f(B,z){if(!isNaN(z)){B.data=z;z=p}var C=B.data,v,D=B.type,A=t.exclude?d().slice(0,-t.exclude):d(),y=A.length,w=A[C],x=t.duration;if(D){B.preventDefault()}if(g){o();l=setTimeout(n,t.interval)}if(!w){v=C<0?0:y-1;if(h!=v){C=v}else{if(!t.cycle){return}else{C=y-v-1}}w=A[C]}if(!w||t.lock&&u.is(":animated")||D&&t.onBefore&&t.onBefore(B,w,u,d(),C)===!1){return}if(t.stop){u.queue("fx",[]).stop()}if(t.constant){x=Math.abs(x/i*(h-C))}u.scrollTo(w,x,t).trigger("notify.serialScroll",[C])}function n(){u.trigger("next.serialScroll")}function o(){clearTimeout(l)}function d(){return a(m,p)}function j(w){if(!isNaN(w)){return w}var x=d(),v;while((v=x.index(w))==-1&&w!=p){w=w.parentNode}return v}})}})(jQuery);
\ No newline at end of file diff --git a/mod/beechat/views/default/js/jquery.tools.min.js.php b/mod/beechat/views/default/js/jquery.tools.min.js.php new file mode 100644 index 000000000..1574af45b --- /dev/null +++ b/mod/beechat/views/default/js/jquery.tools.min.js.php @@ -0,0 +1,49 @@ +/* + * jQuery Tools 1.2.2 - The missing UI library for the Web + *  + * [tabs, tabs.slideshow, tooltip, tooltip.slide, tooltip.dynamic, scrollable, scrollable.autoscroll, scrollable.navigator, overlay] + *  + * NO COPYRIGHTS OR LICENSES. DO WHAT YOU LIKE. + *  + * http://flowplayer.org/tools/ + *  + * File generated: Mon Jun 07 08:32:38 GMT 2010 + */ +(function(c){function p(d,a,b){var e=this,l=d.add(this),h=d.find(b.tabs),j=a.jquery?a:d.children(a),i;h.length||(h=d.children());j.length||(j=d.parent().find(a));j.length||(j=c(a));c.extend(this,{click:function(f,g){var k=h.eq(f);if(typeof f=="string"&&f.replace("#","")){k=h.filter("[href*="+f.replace("#","")+"]");f=Math.max(h.index(k),0)}if(b.rotate){var n=h.length-1;if(f<0)return e.click(n,g);if(f>n)return e.click(0,g)}if(!k.length){if(i>=0)return e;f=b.initialIndex;k=h.eq(f)}if(f===i)return e; +g=g||c.Event();g.type="onBeforeClick";l.trigger(g,[f]);if(!g.isDefaultPrevented()){o[b.effect].call(e,f,function(){g.type="onClick";l.trigger(g,[f])});i=f;h.removeClass(b.current);k.addClass(b.current);return e}},getConf:function(){return b},getTabs:function(){return h},getPanes:function(){return j},getCurrentPane:function(){return j.eq(i)},getCurrentTab:function(){return h.eq(i)},getIndex:function(){return i},next:function(){return e.click(i+1)},prev:function(){return e.click(i-1)}});c.each("onBeforeClick,onClick".split(","), +function(f,g){c.isFunction(b[g])&&c(e).bind(g,b[g]);e[g]=function(k){c(e).bind(g,k);return e}});if(b.history&&c.fn.history){c.tools.history.init(h);b.event="history"}h.each(function(f){c(this).bind(b.event,function(g){e.click(f,g);return g.preventDefault()})});j.find("a[href^=#]").click(function(f){e.click(c(this).attr("href"),f)});if(location.hash)e.click(location.hash);else if(b.initialIndex===0||b.initialIndex>0)e.click(b.initialIndex)}c.tools=c.tools||{version:"1.2.2"};c.tools.tabs={conf:{tabs:"a", +current:"current",onBeforeClick:null,onClick:null,effect:"default",initialIndex:0,event:"click",rotate:false,history:false},addEffect:function(d,a){o[d]=a}};var o={"default":function(d,a){this.getPanes().hide().eq(d).show();a.call()},fade:function(d,a){var b=this.getConf(),e=b.fadeOutSpeed,l=this.getPanes();e?l.fadeOut(e):l.hide();l.eq(d).fadeIn(b.fadeInSpeed,a)},slide:function(d,a){this.getPanes().slideUp(200);this.getPanes().eq(d).slideDown(400,a)},ajax:function(d,a){this.getPanes().eq(0).load(this.getTabs().eq(d).attr("href"), +a)}},m;c.tools.tabs.addEffect("horizontal",function(d,a){m||(m=this.getPanes().eq(0).width());this.getCurrentPane().animate({width:0},function(){c(this).hide()});this.getPanes().eq(d).animate({width:m},function(){c(this).show();a.call()})});c.fn.tabs=function(d,a){var b=this.data("tabs");if(b)return b;if(c.isFunction(a))a={onBeforeClick:a};a=c.extend({},c.tools.tabs.conf,a);this.each(function(){b=new p(c(this),d,a);c(this).data("tabs",b)});return a.api?b:this}})(jQuery); +(function(d){function r(g,a){function p(f){var e=d(f);return e.length<2?e:g.parent().find(f)}var c=this,j=g.add(this),b=g.data("tabs"),h,l,m,n=false,o=p(a.next).click(function(){b.next()}),k=p(a.prev).click(function(){b.prev()});d.extend(c,{getTabs:function(){return b},getConf:function(){return a},play:function(){if(!h){var f=d.Event("onBeforePlay");j.trigger(f);if(f.isDefaultPrevented())return c;n=false;h=setInterval(b.next,a.interval);j.trigger("onPlay");b.next()}},pause:function(){if(!h)return c; +var f=d.Event("onBeforePause");j.trigger(f);if(f.isDefaultPrevented())return c;h=clearInterval(h);m=clearInterval(m);j.trigger("onPause")},stop:function(){c.pause();n=true}});d.each("onBeforePlay,onPlay,onBeforePause,onPause".split(","),function(f,e){d.isFunction(a[e])&&c.bind(e,a[e]);c[e]=function(s){return c.bind(e,s)}});if(a.autopause){var t=b.getTabs().add(o).add(k).add(b.getPanes());t.hover(function(){c.pause();l=clearInterval(l)},function(){n||(l=setTimeout(c.play,a.interval))})}if(a.autoplay)m= +setTimeout(c.play,a.interval);else c.stop();a.clickable&&b.getPanes().click(function(){b.next()});if(!b.getConf().rotate){var i=a.disabledClass;b.getIndex()||k.addClass(i);b.onBeforeClick(function(f,e){if(e){k.removeClass(i);e==b.getTabs().length-1?o.addClass(i):o.removeClass(i)}else k.addClass(i)})}}var q;q=d.tools.tabs.slideshow={conf:{next:".forward",prev:".backward",disabledClass:"disabled",autoplay:false,autopause:true,interval:3E3,clickable:true,api:false}};d.fn.slideshow=function(g){var a= +this.data("slideshow");if(a)return a;g=d.extend({},q.conf,g);this.each(function(){a=new r(d(this),g);d(this).data("slideshow",a)});return g.api?a:this}})(jQuery); +(function(f){function p(a,b,c){var h=c.relative?a.position().top:a.offset().top,e=c.relative?a.position().left:a.offset().left,i=c.position[0];h-=b.outerHeight()-c.offset[0];e+=a.outerWidth()+c.offset[1];var j=b.outerHeight()+a.outerHeight();if(i=="center")h+=j/2;if(i=="bottom")h+=j;i=c.position[1];a=b.outerWidth()+a.outerWidth();if(i=="center")e-=a/2;if(i=="left")e-=a;return{top:h,left:e}}function t(a,b){var c=this,h=a.add(c),e,i=0,j=0,m=a.attr("title"),q=n[b.effect],k,r=a.is(":input"),u=r&&a.is(":checkbox, :radio, select, :button"), +s=a.attr("type"),l=b.events[s]||b.events[r?u?"widget":"input":"def"];if(!q)throw'Nonexistent effect "'+b.effect+'"';l=l.split(/,\s*/);if(l.length!=2)throw"Tooltip: bad events configuration for "+s;a.bind(l[0],function(d){if(b.predelay){clearTimeout(i);j=setTimeout(function(){c.show(d)},b.predelay)}else c.show(d)}).bind(l[1],function(d){if(b.delay){clearTimeout(j);i=setTimeout(function(){c.hide(d)},b.delay)}else c.hide(d)});if(m&&b.cancelDefault){a.removeAttr("title");a.data("title",m)}f.extend(c, +{show:function(d){if(!e){if(m)e=f(b.layout).addClass(b.tipClass).appendTo(document.body).hide().append(m);else if(b.tip)e=f(b.tip).eq(0);else{e=a.next();e.length||(e=a.parent().next())}if(!e.length)throw"Cannot find tooltip for "+a;}if(c.isShown())return c;e.stop(true,true);var g=p(a,e,b);d=d||f.Event();d.type="onBeforeShow";h.trigger(d,[g]);if(d.isDefaultPrevented())return c;g=p(a,e,b);e.css({position:"absolute",top:g.top,left:g.left});k=true;q[0].call(c,function(){d.type="onShow";k="full";h.trigger(d)}); +g=b.events.tooltip.split(/,\s*/);e.bind(g[0],function(){clearTimeout(i);clearTimeout(j)});g[1]&&!a.is("input:not(:checkbox, :radio), textarea")&&e.bind(g[1],function(o){o.relatedTarget!=a[0]&&a.trigger(l[1].split(" ")[0])});return c},hide:function(d){if(!e||!c.isShown())return c;d=d||f.Event();d.type="onBeforeHide";h.trigger(d);if(!d.isDefaultPrevented()){k=false;n[b.effect][1].call(c,function(){d.type="onHide";k=false;h.trigger(d)});return c}},isShown:function(d){return d?k=="full":k},getConf:function(){return b}, +getTip:function(){return e},getTrigger:function(){return a}});f.each("onHide,onBeforeShow,onShow,onBeforeHide".split(","),function(d,g){f.isFunction(b[g])&&f(c).bind(g,b[g]);c[g]=function(o){f(c).bind(g,o);return c}})}f.tools=f.tools||{version:"1.2.2"};f.tools.tooltip={conf:{effect:"toggle",fadeOutSpeed:"fast",predelay:0,delay:30,opacity:1,tip:0,position:["top","center"],offset:[0,0],relative:false,cancelDefault:true,events:{def:"mouseenter,mouseleave",input:"focus,blur",widget:"focus mouseenter,blur mouseleave", +tooltip:"mouseenter,mouseleave"},layout:"<div/>",tipClass:"tooltip"},addEffect:function(a,b,c){n[a]=[b,c]}};var n={toggle:[function(a){var b=this.getConf(),c=this.getTip();b=b.opacity;b<1&&c.css({opacity:b});c.show();a.call()},function(a){this.getTip().hide();a.call()}],fade:[function(a){var b=this.getConf();this.getTip().fadeTo(b.fadeInSpeed,b.opacity,a)},function(a){this.getTip().fadeOut(this.getConf().fadeOutSpeed,a)}]};f.fn.tooltip=function(a){var b=this.data("tooltip");if(b)return b;a=f.extend(true, +{},f.tools.tooltip.conf,a);if(typeof a.position=="string")a.position=a.position.split(/,?\s/);this.each(function(){b=new t(f(this),a);f(this).data("tooltip",b)});return a.api?b:this}})(jQuery); +(function(d){var i=d.tools.tooltip;d.extend(i.conf,{direction:"up",bounce:false,slideOffset:10,slideInSpeed:200,slideOutSpeed:200,slideFade:!d.browser.msie});var e={up:["-","top"],down:["+","top"],left:["-","left"],right:["+","left"]};i.addEffect("slide",function(g){var a=this.getConf(),f=this.getTip(),b=a.slideFade?{opacity:a.opacity}:{},c=e[a.direction]||e.up;b[c[1]]=c[0]+"="+a.slideOffset;a.slideFade&&f.css({opacity:0});f.show().animate(b,a.slideInSpeed,g)},function(g){var a=this.getConf(),f=a.slideOffset, +b=a.slideFade?{opacity:0}:{},c=e[a.direction]||e.up,h=""+c[0];if(a.bounce)h=h=="+"?"-":"+";b[c[1]]=h+"="+f;this.getTip().animate(b,a.slideOutSpeed,function(){d(this).hide();g.call()})})})(jQuery); +(function(g){function j(a){var c=g(window),d=c.width()+c.scrollLeft(),h=c.height()+c.scrollTop();return[a.offset().top<=c.scrollTop(),d<=a.offset().left+a.width(),h<=a.offset().top+a.height(),c.scrollLeft()>=a.offset().left]}function k(a){for(var c=a.length;c--;)if(a[c])return false;return true}var i=g.tools.tooltip;i.dynamic={conf:{classNames:"top right bottom left"}};g.fn.dynamic=function(a){if(typeof a=="number")a={speed:a};a=g.extend({},i.dynamic.conf,a);var c=a.classNames.split(/\s/),d;this.each(function(){var h= +g(this).tooltip().onBeforeShow(function(e,f){e=this.getTip();var b=this.getConf();d||(d=[b.position[0],b.position[1],b.offset[0],b.offset[1],g.extend({},b)]);g.extend(b,d[4]);b.position=[d[0],d[1]];b.offset=[d[2],d[3]];e.css({visibility:"hidden",position:"absolute",top:f.top,left:f.left}).show();f=j(e);if(!k(f)){if(f[2]){g.extend(b,a.top);b.position[0]="top";e.addClass(c[0])}if(f[3]){g.extend(b,a.right);b.position[1]="right";e.addClass(c[1])}if(f[0]){g.extend(b,a.bottom);b.position[0]="bottom";e.addClass(c[2])}if(f[1]){g.extend(b, +a.left);b.position[1]="left";e.addClass(c[3])}if(f[0]||f[2])b.offset[0]*=-1;if(f[1]||f[3])b.offset[1]*=-1}e.css({visibility:"visible"}).hide()});h.onBeforeShow(function(){var e=this.getConf();this.getTip();setTimeout(function(){e.position=[d[0],d[1]];e.offset=[d[2],d[3]]},0)});h.onHide(function(){var e=this.getTip();e.removeClass(a.classNames)});ret=h});return a.api?ret:this}})(jQuery); +(function(e){function n(f,c){var a=e(c);return a.length<2?a:f.parent().find(c)}function t(f,c){var a=this,l=f.add(a),g=f.children(),k=0,m=c.vertical;j||(j=a);if(g.length>1)g=e(c.items,f);e.extend(a,{getConf:function(){return c},getIndex:function(){return k},getSize:function(){return a.getItems().size()},getNaviButtons:function(){return o.add(p)},getRoot:function(){return f},getItemWrap:function(){return g},getItems:function(){return g.children(c.item).not("."+c.clonedClass)},move:function(b,d){return a.seekTo(k+ +b,d)},next:function(b){return a.move(1,b)},prev:function(b){return a.move(-1,b)},begin:function(b){return a.seekTo(0,b)},end:function(b){return a.seekTo(a.getSize()-1,b)},focus:function(){return j=a},addItem:function(b){b=e(b);if(c.circular){e(".cloned:last").before(b);e(".cloned:first").replaceWith(b.clone().addClass(c.clonedClass))}else g.append(b);l.trigger("onAddItem",[b]);return a},seekTo:function(b,d,h){if(c.circular&&b===0&&k==-1&&d!==0)return a;if(!c.circular&&b<0||b>a.getSize()||b<-1)return a; +var i=b;if(b.jquery)b=a.getItems().index(b);else i=a.getItems().eq(b);var q=e.Event("onBeforeSeek");if(!h){l.trigger(q,[b,d]);if(q.isDefaultPrevented()||!i.length)return a}i=m?{top:-i.position().top}:{left:-i.position().left};k=b;j=a;if(d===undefined)d=c.speed;g.animate(i,d,c.easing,h||function(){l.trigger("onSeek",[b])});return a}});e.each(["onBeforeSeek","onSeek","onAddItem"],function(b,d){e.isFunction(c[d])&&e(a).bind(d,c[d]);a[d]=function(h){e(a).bind(d,h);return a}});if(c.circular){var r=a.getItems().slice(-1).clone().prependTo(g), +s=a.getItems().eq(1).clone().appendTo(g);r.add(s).addClass(c.clonedClass);a.onBeforeSeek(function(b,d,h){if(!b.isDefaultPrevented())if(d==-1){a.seekTo(r,h,function(){a.end(0)});return b.preventDefault()}else d==a.getSize()&&a.seekTo(s,h,function(){a.begin(0)})});a.seekTo(0,0)}var o=n(f,c.prev).click(function(){a.prev()}),p=n(f,c.next).click(function(){a.next()});!c.circular&&a.getSize()>1&&a.onBeforeSeek(function(b,d){o.toggleClass(c.disabledClass,d<=0);p.toggleClass(c.disabledClass,d>=a.getSize()- +1)});c.mousewheel&&e.fn.mousewheel&&f.mousewheel(function(b,d){if(c.mousewheel){a.move(d<0?1:-1,c.wheelSpeed||50);return false}});c.keyboard&&e(document).bind("keydown.scrollable",function(b){if(!(!c.keyboard||b.altKey||b.ctrlKey||e(b.target).is(":input")))if(!(c.keyboard!="static"&&j!=a)){var d=b.keyCode;if(m&&(d==38||d==40)){a.move(d==38?-1:1);return b.preventDefault()}if(!m&&(d==37||d==39)){a.move(d==37?-1:1);return b.preventDefault()}}});e(a).trigger("onBeforeSeek",[c.initialIndex])}e.tools=e.tools|| +{version:"1.2.2"};e.tools.scrollable={conf:{activeClass:"active",circular:false,clonedClass:"cloned",disabledClass:"disabled",easing:"swing",initialIndex:0,item:null,items:".items",keyboard:true,mousewheel:false,next:".next",prev:".prev",speed:400,vertical:false,wheelSpeed:0}};var j;e.fn.scrollable=function(f){var c=this.data("scrollable");if(c)return c;f=e.extend({},e.tools.scrollable.conf,f);this.each(function(){c=new t(e(this),f);e(this).data("scrollable",c)});return f.api?c:this}})(jQuery); +(function(c){var g=c.tools.scrollable;g.autoscroll={conf:{autoplay:true,interval:3E3,autopause:true}};c.fn.autoscroll=function(d){if(typeof d=="number")d={interval:d};var b=c.extend({},g.autoscroll.conf,d),h;this.each(function(){var a=c(this).data("scrollable");if(a)h=a;var e,i,f=true;a.play=function(){if(!e){f=false;e=setInterval(function(){a.next()},b.interval);a.next()}};a.pause=function(){e=clearInterval(e)};a.stop=function(){a.pause();f=true};b.autopause&&a.getRoot().add(a.getNaviButtons()).hover(function(){a.pause(); +clearInterval(i)},function(){f||(i=setTimeout(a.play,b.interval))});b.autoplay&&setTimeout(a.play,b.interval)});return b.api?h:this}})(jQuery); +(function(d){function p(c,g){var h=d(g);return h.length<2?h:c.parent().find(g)}var m=d.tools.scrollable;m.navigator={conf:{navi:".navi",naviItem:null,activeClass:"active",indexed:false,idPrefix:null,history:false}};d.fn.navigator=function(c){if(typeof c=="string")c={navi:c};c=d.extend({},m.navigator.conf,c);var g;this.each(function(){function h(a,b,i){e.seekTo(b);if(j){if(location.hash)location.hash=a.attr("href").replace("#","")}else return i.preventDefault()}function f(){return k.find(c.naviItem|| +"> *")}function n(a){var b=d("<"+(c.naviItem||"a")+"/>").click(function(i){h(d(this),a,i)}).attr("href","#"+a);a===0&&b.addClass(l);c.indexed&&b.text(a+1);c.idPrefix&&b.attr("id",c.idPrefix+a);return b.appendTo(k)}function o(a,b){a=f().eq(b.replace("#",""));a.length||(a=f().filter("[href="+b+"]"));a.click()}var e=d(this).data("scrollable"),k=p(e.getRoot(),c.navi),q=e.getNaviButtons(),l=c.activeClass,j=c.history&&d.fn.history;if(e)g=e;e.getNaviButtons=function(){return q.add(k)};f().length?f().each(function(a){d(this).click(function(b){h(d(this), +a,b)})}):d.each(e.getItems(),function(a){n(a)});e.onBeforeSeek(function(a,b){var i=f().eq(b);!a.isDefaultPrevented()&&i.length&&f().removeClass(l).eq(b).addClass(l)});e.onAddItem(function(a,b){b=n(e.getItems().index(b));j&&b.history(o)});j&&f().history(o)});return c.api?g:this}})(jQuery); +(function(a){function t(d,b){var c=this,i=d.add(c),o=a(window),k,f,m,g=a.tools.expose&&(b.mask||b.expose),n=Math.random().toString().slice(10);if(g){if(typeof g=="string")g={color:g};g.closeOnClick=g.closeOnEsc=false}var p=b.target||d.attr("rel");f=p?a(p):d;if(!f.length)throw"Could not find Overlay: "+p;d&&d.index(f)==-1&&d.click(function(e){c.load(e);return e.preventDefault()});a.extend(c,{load:function(e){if(c.isOpened())return c;var h=q[b.effect];if(!h)throw'Overlay: cannot find effect : "'+b.effect+ +'"';b.oneInstance&&a.each(s,function(){this.close(e)});e=e||a.Event();e.type="onBeforeLoad";i.trigger(e);if(e.isDefaultPrevented())return c;m=true;g&&a(f).expose(g);var j=b.top,r=b.left,u=f.outerWidth({margin:true}),v=f.outerHeight({margin:true});if(typeof j=="string")j=j=="center"?Math.max((o.height()-v)/2,0):parseInt(j,10)/100*o.height();if(r=="center")r=Math.max((o.width()-u)/2,0);h[0].call(c,{top:j,left:r},function(){if(m){e.type="onLoad";i.trigger(e)}});g&&b.closeOnClick&&a.mask.getMask().one("click", +c.close);b.closeOnClick&&a(document).bind("click."+n,function(l){a(l.target).parents(f).length||c.close(l)});b.closeOnEsc&&a(document).bind("keydown."+n,function(l){l.keyCode==27&&c.close(l)});return c},close:function(e){if(!c.isOpened())return c;e=e||a.Event();e.type="onBeforeClose";i.trigger(e);if(!e.isDefaultPrevented()){m=false;q[b.effect][1].call(c,function(){e.type="onClose";i.trigger(e)});a(document).unbind("click."+n).unbind("keydown."+n);g&&a.mask.close();return c}},getOverlay:function(){return f}, +getTrigger:function(){return d},getClosers:function(){return k},isOpened:function(){return m},getConf:function(){return b}});a.each("onBeforeLoad,onStart,onLoad,onBeforeClose,onClose".split(","),function(e,h){a.isFunction(b[h])&&a(c).bind(h,b[h]);c[h]=function(j){a(c).bind(h,j);return c}});k=f.find(b.close||".close");if(!k.length&&!b.close){k=a('<div class="close"></div>');f.prepend(k)}k.click(function(e){c.close(e)});b.load&&c.load()}a.tools=a.tools||{version:"1.2.2"};a.tools.overlay={addEffect:function(d, +b,c){q[d]=[b,c]},conf:{close:null,closeOnClick:true,closeOnEsc:true,closeSpeed:"fast",effect:"default",fixed:!a.browser.msie||a.browser.version>6,left:"center",load:false,mask:null,oneInstance:true,speed:"normal",target:null,top:"10%"}};var s=[],q={};a.tools.overlay.addEffect("default",function(d,b){var c=this.getConf(),i=a(window);if(!c.fixed){d.top+=i.scrollTop();d.left+=i.scrollLeft()}d.position=c.fixed?"fixed":"absolute";this.getOverlay().css(d).fadeIn(c.speed,b)},function(d){this.getOverlay().fadeOut(this.getConf().closeSpeed, +d)});a.fn.overlay=function(d){var b=this.data("overlay");if(b)return b;if(a.isFunction(d))d={onBeforeLoad:d};d=a.extend(true,{},a.tools.overlay.conf,d);this.each(function(){b=new t(a(this),d);s.push(b);a(this).data("overlay",b)});return d.api?b:this}})(jQuery); diff --git a/mod/beechat/views/default/js/json2.js.php b/mod/beechat/views/default/js/json2.js.php new file mode 100644 index 000000000..7ae503202 --- /dev/null +++ b/mod/beechat/views/default/js/json2.js.php @@ -0,0 +1,476 @@ +/* +    http://www.JSON.org/json2.js +    2009-06-29 + +    Public Domain. + +    NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. + +    See http://www.JSON.org/js.html + +    This file creates a global JSON object containing two methods: stringify +    and parse. + +        JSON.stringify(value, replacer, space) +            value       any JavaScript value, usually an object or array. + +            replacer    an optional parameter that determines how object +                        values are stringified for objects. It can be a +                        function or an array of strings. + +            space       an optional parameter that specifies the indentation +                        of nested structures. If it is omitted, the text will +                        be packed without extra whitespace. If it is a number, +                        it will specify the number of spaces to indent at each +                        level. If it is a string (such as '\t' or ' '), +                        it contains the characters used to indent at each level. + +            This method produces a JSON text from a JavaScript value. + +            When an object value is found, if the object contains a toJSON +            method, its toJSON method will be called and the result will be +            stringified. A toJSON method does not serialize: it returns the +            value represented by the name/value pair that should be serialized, +            or undefined if nothing should be serialized. The toJSON method +            will be passed the key associated with the value, and this will be +            bound to the object holding the key. + +            For example, this would serialize Dates as ISO strings. + +                Date.prototype.toJSON = function (key) { +                    function f(n) { +                        // Format integers to have at least two digits. +                        return n < 10 ? '0' + n : n; +                    } + +                    return this.getUTCFullYear()   + '-' + +                         f(this.getUTCMonth() + 1) + '-' + +                         f(this.getUTCDate())      + 'T' + +                         f(this.getUTCHours())     + ':' + +                         f(this.getUTCMinutes())   + ':' + +                         f(this.getUTCSeconds())   + 'Z'; +                }; + +            You can provide an optional replacer method. It will be passed the +            key and value of each member, with this bound to the containing +            object. The value that is returned from your method will be +            serialized. If your method returns undefined, then the member will +            be excluded from the serialization. + +            If the replacer parameter is an array of strings, then it will be +            used to select the members to be serialized. It filters the results +            such that only members with keys listed in the replacer array are +            stringified. + +            Values that do not have JSON representations, such as undefined or +            functions, will not be serialized. Such values in objects will be +            dropped; in arrays they will be replaced with null. You can use +            a replacer function to replace those with JSON values. +            JSON.stringify(undefined) returns undefined. + +            The optional space parameter produces a stringification of the +            value that is filled with line breaks and indentation to make it +            easier to read. + +            If the space parameter is a non-empty string, then that string will +            be used for indentation. If the space parameter is a number, then +            the indentation will be that many spaces. + +            Example: + +            text = JSON.stringify(['e', {pluribus: 'unum'}]); +            // text is '["e",{"pluribus":"unum"}]' + + +            text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t'); +            // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]' + +            text = JSON.stringify([new Date()], function (key, value) { +                return this[key] instanceof Date ? +                    'Date(' + this[key] + ')' : value; +            }); +            // text is '["Date(---current time---)"]' + + +        JSON.parse(text, reviver) +            This method parses a JSON text to produce an object or array. +            It can throw a SyntaxError exception. + +            The optional reviver parameter is a function that can filter and +            transform the results. It receives each of the keys and values, +            and its return value is used instead of the original value. +            If it returns what it received, then the structure is not modified. +            If it returns undefined then the member is deleted. + +            Example: + +            // Parse the text. Values that look like ISO date strings will +            // be converted to Date objects. + +            myData = JSON.parse(text, function (key, value) { +                var a; +                if (typeof value === 'string') { +                    a = +/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value); +                    if (a) { +                        return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], +                            +a[5], +a[6])); +                    } +                } +                return value; +            }); + +            myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) { +                var d; +                if (typeof value === 'string' && +                        value.slice(0, 5) === 'Date(' && +                        value.slice(-1) === ')') { +                    d = new Date(value.slice(5, -1)); +                    if (d) { +                        return d; +                    } +                } +                return value; +            }); + + +    This is a reference implementation. You are free to copy, modify, or +    redistribute. + +    This code should be minified before deployment. +    See http://javascript.crockford.com/jsmin.html + +    USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO +    NOT CONTROL. +*/ + +/*jslint evil: true */ + +/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply, +    call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours, +    getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join, +    lastIndex, length, parse, prototype, push, replace, slice, stringify, +    test, toJSON, toString, valueOf +*/ + +// Create a JSON object only if one does not already exist. We create the +// methods in a closure to avoid creating global variables. + +var JSON = JSON || {}; + +(function () { + +    function f(n) { +        // Format integers to have at least two digits. +        return n < 10 ? '0' + n : n; +    } + +    if (typeof Date.prototype.toJSON !== 'function') { + +        Date.prototype.toJSON = function (key) { + +            return isFinite(this.valueOf()) ? +                   this.getUTCFullYear()   + '-' + +                 f(this.getUTCMonth() + 1) + '-' + +                 f(this.getUTCDate())      + 'T' + +                 f(this.getUTCHours())     + ':' + +                 f(this.getUTCMinutes())   + ':' + +                 f(this.getUTCSeconds())   + 'Z' : null; +        }; + +        String.prototype.toJSON = +        Number.prototype.toJSON = +        Boolean.prototype.toJSON = function (key) { +            return this.valueOf(); +        }; +    } + +    var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, +        escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, +        gap, +        indent, +        meta = {    // table of character substitutions +            '\b': '\\b', +            '\t': '\\t', +            '\n': '\\n', +            '\f': '\\f', +            '\r': '\\r', +            '"' : '\\"', +            '\\': '\\\\' +        }, +        rep; + + +    function quote(string) { + +// If the string contains no control characters, no quote characters, and no +// backslash characters, then we can safely slap some quotes around it. +// Otherwise we must also replace the offending characters with safe escape +// sequences. + +        escapable.lastIndex = 0; +        return escapable.test(string) ? +            '"' + string.replace(escapable, function (a) { +                var c = meta[a]; +                return typeof c === 'string' ? c : +                    '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); +            }) + '"' : +            '"' + string + '"'; +    } + + +    function str(key, holder) { + +// Produce a string from holder[key]. + +        var i,          // The loop counter. +            k,          // The member key. +            v,          // The member value. +            length, +            mind = gap, +            partial, +            value = holder[key]; + +// If the value has a toJSON method, call it to obtain a replacement value. + +        if (value && typeof value === 'object' && +                typeof value.toJSON === 'function') { +            value = value.toJSON(key); +        } + +// If we were called with a replacer function, then call the replacer to +// obtain a replacement value. + +        if (typeof rep === 'function') { +            value = rep.call(holder, key, value); +        } + +// What happens next depends on the value's type. + +        switch (typeof value) { +        case 'string': +            return quote(value); + +        case 'number': + +// JSON numbers must be finite. Encode non-finite numbers as null. + +            return isFinite(value) ? String(value) : 'null'; + +        case 'boolean': +        case 'null': + +// If the value is a boolean or null, convert it to a string. Note: +// typeof null does not produce 'null'. The case is included here in +// the remote chance that this gets fixed someday. + +            return String(value); + +// If the type is 'object', we might be dealing with an object or an array or +// null. + +        case 'object': + +// Due to a specification blunder in ECMAScript, typeof null is 'object', +// so watch out for that case. + +            if (!value) { +                return 'null'; +            } + +// Make an array to hold the partial results of stringifying this object value. + +            gap += indent; +            partial = []; + +// Is the value an array? + +            if (Object.prototype.toString.apply(value) === '[object Array]') { + +// The value is an array. Stringify every element. Use null as a placeholder +// for non-JSON values. + +                length = value.length; +                for (i = 0; i < length; i += 1) { +                    partial[i] = str(i, value) || 'null'; +                } + +// Join all of the elements together, separated with commas, and wrap them in +// brackets. + +                v = partial.length === 0 ? '[]' : +                    gap ? '[\n' + gap + +                            partial.join(',\n' + gap) + '\n' + +                                mind + ']' : +                          '[' + partial.join(',') + ']'; +                gap = mind; +                return v; +            } + +// If the replacer is an array, use it to select the members to be stringified. + +            if (rep && typeof rep === 'object') { +                length = rep.length; +                for (i = 0; i < length; i += 1) { +                    k = rep[i]; +                    if (typeof k === 'string') { +                        v = str(k, value); +                        if (v) { +                            partial.push(quote(k) + (gap ? ': ' : ':') + v); +                        } +                    } +                } +            } else { + +// Otherwise, iterate through all of the keys in the object. + +                for (k in value) { +                    if (Object.hasOwnProperty.call(value, k)) { +                        v = str(k, value); +                        if (v) { +                            partial.push(quote(k) + (gap ? ': ' : ':') + v); +                        } +                    } +                } +            } + +// Join all of the member texts together, separated with commas, +// and wrap them in braces. + +            v = partial.length === 0 ? '{}' : +                gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + +                        mind + '}' : '{' + partial.join(',') + '}'; +            gap = mind; +            return v; +        } +    } + +// If the JSON object does not yet have a stringify method, give it one. + +    if (typeof JSON.stringify !== 'function') { +        JSON.stringify = function (value, replacer, space) { + +// The stringify method takes a value and an optional replacer, and an optional +// space parameter, and returns a JSON text. The replacer can be a function +// that can replace values, or an array of strings that will select the keys. +// A default replacer method can be provided. Use of the space parameter can +// produce text that is more easily readable. + +            var i; +            gap = ''; +            indent = ''; + +// If the space parameter is a number, make an indent string containing that +// many spaces. + +            if (typeof space === 'number') { +                for (i = 0; i < space; i += 1) { +                    indent += ' '; +                } + +// If the space parameter is a string, it will be used as the indent string. + +            } else if (typeof space === 'string') { +                indent = space; +            } + +// If there is a replacer, it must be a function or an array. +// Otherwise, throw an error. + +            rep = replacer; +            if (replacer && typeof replacer !== 'function' && +                    (typeof replacer !== 'object' || +                     typeof replacer.length !== 'number')) { +                throw new Error('JSON.stringify'); +            } + +// Make a fake root object containing our value under the key of ''. +// Return the result of stringifying the value. + +            return str('', {'': value}); +        }; +    } + + +// If the JSON object does not yet have a parse method, give it one. + +    if (typeof JSON.parse !== 'function') { +        JSON.parse = function (text, reviver) { + +// The parse method takes a text and an optional reviver function, and returns +// a JavaScript value if the text is a valid JSON text. + +            var j; + +            function walk(holder, key) { + +// The walk method is used to recursively walk the resulting structure so +// that modifications can be made. + +                var k, v, value = holder[key]; +                if (value && typeof value === 'object') { +                    for (k in value) { +                        if (Object.hasOwnProperty.call(value, k)) { +                            v = walk(value, k); +                            if (v !== undefined) { +                                value[k] = v; +                            } else { +                                delete value[k]; +                            } +                        } +                    } +                } +                return reviver.call(holder, key, value); +            } + + +// Parsing happens in four stages. In the first stage, we replace certain +// Unicode characters with escape sequences. JavaScript handles many characters +// incorrectly, either silently deleting them, or treating them as line endings. + +            cx.lastIndex = 0; +            if (cx.test(text)) { +                text = text.replace(cx, function (a) { +                    return '\\u' + +                        ('0000' + a.charCodeAt(0).toString(16)).slice(-4); +                }); +            } + +// In the second stage, we run the text against regular expressions that look +// for non-JSON patterns. We are especially concerned with '()' and 'new' +// because they can cause invocation, and '=' because it can cause mutation. +// But just to be safe, we want to reject all unexpected forms. + +// We split the second stage into 4 regexp operations in order to work around +// crippling inefficiencies in IE's and Safari's regexp engines. First we +// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we +// replace all simple value tokens with ']' characters. Third, we delete all +// open brackets that follow a colon or comma or that begin the text. Finally, +// we look to see that the remaining characters are only whitespace or ']' or +// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval. + +            if (/^[\],:{}\s]*$/. +test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@'). +replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']'). +replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { + +// In the third stage we use the eval function to compile the text into a +// JavaScript structure. The '{' operator is subject to a syntactic ambiguity +// in JavaScript: it can begin a block or an object literal. We wrap the text +// in parens to eliminate the ambiguity. + +                j = eval('(' + text + ')'); + +// In the optional fourth stage, we recursively walk the new structure, passing +// each name/value pair to a reviver function for possible transformation. + +                return typeof reviver === 'function' ? +                    walk({'': j}, '') : j; +            } + +// If the text is not JSON parseable, then a SyntaxError is thrown. + +            throw new SyntaxError('JSON.parse'); +        }; +    } +}()); diff --git a/mod/beechat/views/default/js/md5.js.php b/mod/beechat/views/default/js/md5.js.php new file mode 100644 index 000000000..4284f62bb --- /dev/null +++ b/mod/beechat/views/default/js/md5.js.php @@ -0,0 +1,261 @@ +/* + * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message + * Digest Algorithm, as defined in RFC 1321. + * Version 2.1 Copyright (C) Paul Johnston 1999 - 2002. + * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet + * Distributed under the BSD License + * See http://pajhome.org.uk/crypt/md5 for more info. + */ + +/* + * Configurable variables. You may need to tweak these to be compatible with + * the server-side, but the defaults work in most cases. + */ +var hexcase = 0;  /* hex output format. 0 - lowercase; 1 - uppercase        */ +var b64pad  = ""; /* base-64 pad character. "=" for strict RFC compliance   */ +var chrsz   = 8;  /* bits per input character. 8 - ASCII; 16 - Unicode      */ + +/* + * These are the functions you'll usually want to call + * They take string arguments and return either hex or base-64 encoded strings + */ +function hex_md5(s){ return binl2hex(core_md5(str2binl(s), s.length * chrsz));} +function b64_md5(s){ return binl2b64(core_md5(str2binl(s), s.length * chrsz));} +function str_md5(s){ return binl2str(core_md5(str2binl(s), s.length * chrsz));} +function hex_hmac_md5(key, data) { return binl2hex(core_hmac_md5(key, data)); } +function b64_hmac_md5(key, data) { return binl2b64(core_hmac_md5(key, data)); } +function str_hmac_md5(key, data) { return binl2str(core_hmac_md5(key, data)); } + +/* + * Perform a simple self-test to see if the VM is working + */ +function md5_vm_test() +{ +  return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72"; +} + +/* + * Calculate the MD5 of an array of little-endian words, and a bit length + */ +function core_md5(x, len) +{ +  /* append padding */ +  x[len >> 5] |= 0x80 << ((len) % 32); +  x[(((len + 64) >>> 9) << 4) + 14] = len; + +  var a =  1732584193; +  var b = -271733879; +  var c = -1732584194; +  var d =  271733878; + +  var olda, oldb, oldc, oldd; +  for(var i = 0; i < x.length; i += 16) +  { +    olda = a; +    oldb = b; +    oldc = c; +    oldd = d; + +    a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936); +    d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586); +    c = md5_ff(c, d, a, b, x[i+ 2], 17,  606105819); +    b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330); +    a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897); +    d = md5_ff(d, a, b, c, x[i+ 5], 12,  1200080426); +    c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341); +    b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983); +    a = md5_ff(a, b, c, d, x[i+ 8], 7 ,  1770035416); +    d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417); +    c = md5_ff(c, d, a, b, x[i+10], 17, -42063); +    b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162); +    a = md5_ff(a, b, c, d, x[i+12], 7 ,  1804603682); +    d = md5_ff(d, a, b, c, x[i+13], 12, -40341101); +    c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290); +    b = md5_ff(b, c, d, a, x[i+15], 22,  1236535329); + +    a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510); +    d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632); +    c = md5_gg(c, d, a, b, x[i+11], 14,  643717713); +    b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302); +    a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691); +    d = md5_gg(d, a, b, c, x[i+10], 9 ,  38016083); +    c = md5_gg(c, d, a, b, x[i+15], 14, -660478335); +    b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848); +    a = md5_gg(a, b, c, d, x[i+ 9], 5 ,  568446438); +    d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690); +    c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961); +    b = md5_gg(b, c, d, a, x[i+ 8], 20,  1163531501); +    a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467); +    d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784); +    c = md5_gg(c, d, a, b, x[i+ 7], 14,  1735328473); +    b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734); + +    a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558); +    d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463); +    c = md5_hh(c, d, a, b, x[i+11], 16,  1839030562); +    b = md5_hh(b, c, d, a, x[i+14], 23, -35309556); +    a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060); +    d = md5_hh(d, a, b, c, x[i+ 4], 11,  1272893353); +    c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632); +    b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640); +    a = md5_hh(a, b, c, d, x[i+13], 4 ,  681279174); +    d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222); +    c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979); +    b = md5_hh(b, c, d, a, x[i+ 6], 23,  76029189); +    a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487); +    d = md5_hh(d, a, b, c, x[i+12], 11, -421815835); +    c = md5_hh(c, d, a, b, x[i+15], 16,  530742520); +    b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651); + +    a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844); +    d = md5_ii(d, a, b, c, x[i+ 7], 10,  1126891415); +    c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905); +    b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055); +    a = md5_ii(a, b, c, d, x[i+12], 6 ,  1700485571); +    d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606); +    c = md5_ii(c, d, a, b, x[i+10], 15, -1051523); +    b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799); +    a = md5_ii(a, b, c, d, x[i+ 8], 6 ,  1873313359); +    d = md5_ii(d, a, b, c, x[i+15], 10, -30611744); +    c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380); +    b = md5_ii(b, c, d, a, x[i+13], 21,  1309151649); +    a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070); +    d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379); +    c = md5_ii(c, d, a, b, x[i+ 2], 15,  718787259); +    b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551); + +    a = safe_add(a, olda); +    b = safe_add(b, oldb); +    c = safe_add(c, oldc); +    d = safe_add(d, oldd); +  } +  return [a, b, c, d]; +} + +/* + * These functions implement the four basic operations the algorithm uses. + */ +function md5_cmn(q, a, b, x, s, t) +{ +  return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b); +} +function md5_ff(a, b, c, d, x, s, t) +{ +  return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t); +} +function md5_gg(a, b, c, d, x, s, t) +{ +  return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t); +} +function md5_hh(a, b, c, d, x, s, t) +{ +  return md5_cmn(b ^ c ^ d, a, b, x, s, t); +} +function md5_ii(a, b, c, d, x, s, t) +{ +  return md5_cmn(c ^ (b | (~d)), a, b, x, s, t); +} + +/* + * Calculate the HMAC-MD5, of a key and some data + */ +function core_hmac_md5(key, data) +{ +  var bkey = str2binl(key); +  if(bkey.length > 16) { bkey = core_md5(bkey, key.length * chrsz); } + +  var ipad = new Array(16), opad = new Array(16); +  for(var i = 0; i < 16; i++) +  { +    ipad[i] = bkey[i] ^ 0x36363636; +    opad[i] = bkey[i] ^ 0x5C5C5C5C; +  } + +  var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz); +  return core_md5(opad.concat(hash), 512 + 128); +} + +/* + * Add integers, wrapping at 2^32. This uses 16-bit operations internally + * to work around bugs in some JS interpreters. + */ +function safe_add(x, y) +{ +  var lsw = (x & 0xFFFF) + (y & 0xFFFF); +  var msw = (x >> 16) + (y >> 16) + (lsw >> 16); +  return (msw << 16) | (lsw & 0xFFFF); +} + +/* + * Bitwise rotate a 32-bit number to the left. + */ +function bit_rol(num, cnt) +{ +  return (num << cnt) | (num >>> (32 - cnt)); +} + +/* + * Convert a string to an array of little-endian words + * If chrsz is ASCII, characters >255 have their hi-byte silently ignored. + */ +function str2binl(str) +{ +  var bin = []; +  var mask = (1 << chrsz) - 1; +  for(var i = 0; i < str.length * chrsz; i += chrsz) +  { +    bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32); +  } +  return bin; +} + +/* + * Convert an array of little-endian words to a string + */ +function binl2str(bin) +{ +  var str = ""; +  var mask = (1 << chrsz) - 1; +  for(var i = 0; i < bin.length * 32; i += chrsz) +  { +    str += String.fromCharCode((bin[i>>5] >>> (i % 32)) & mask); +  } +  return str; +} + +/* + * Convert an array of little-endian words to a hex string. + */ +function binl2hex(binarray) +{ +  var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef"; +  var str = ""; +  for(var i = 0; i < binarray.length * 4; i++) +  { +    str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) + +           hex_tab.charAt((binarray[i>>2] >> ((i%4)*8  )) & 0xF); +  } +  return str; +} + +/* + * Convert an array of little-endian words to a base-64 string + */ +function binl2b64(binarray) +{ +  var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +  var str = ""; +  var triplet, j; +  for(var i = 0; i < binarray.length * 4; i += 3) +  { +    triplet = (((binarray[i   >> 2] >> 8 * ( i   %4)) & 0xFF) << 16) | +              (((binarray[i+1 >> 2] >> 8 * ((i+1)%4)) & 0xFF) << 8 ) | +              ((binarray[i+2 >> 2] >> 8 * ((i+2)%4)) & 0xFF); +    for(j = 0; j < 4; j++) +    { +      if(i * 8 + j * 6 > binarray.length * 32) { str += b64pad; } +      else { str += tab.charAt((triplet >> 6*(3-j)) & 0x3F); } +    } +  } +  return str; +} diff --git a/mod/beechat/views/default/js/sha1.js.php b/mod/beechat/views/default/js/sha1.js.php new file mode 100644 index 000000000..db3bf0544 --- /dev/null +++ b/mod/beechat/views/default/js/sha1.js.php @@ -0,0 +1,207 @@ +/* + * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined + * in FIPS PUB 180-1 + * Version 2.1a Copyright Paul Johnston 2000 - 2002. + * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet + * Distributed under the BSD License + * See http://pajhome.org.uk/crypt/md5 for details. + */ + +/* + * Configurable variables. You may need to tweak these to be compatible with + * the server-side, but the defaults work in most cases. + */ +var hexcase = 0;  /* hex output format. 0 - lowercase; 1 - uppercase        */ +var b64pad  = ""; /* base-64 pad character. "=" for strict RFC compliance   */ +var chrsz   = 8;  /* bits per input character. 8 - ASCII; 16 - Unicode      */ + +/* + * These are the functions you'll usually want to call + * They take string arguments and return either hex or base-64 encoded strings + */ +function hex_sha1(s){return binb2hex(core_sha1(str2binb(s),s.length * chrsz));} +function b64_sha1(s){return binb2b64(core_sha1(str2binb(s),s.length * chrsz));} +function str_sha1(s){return binb2str(core_sha1(str2binb(s),s.length * chrsz));} +function hex_hmac_sha1(key, data){ return binb2hex(core_hmac_sha1(key, data));} +function b64_hmac_sha1(key, data){ return binb2b64(core_hmac_sha1(key, data));} +function str_hmac_sha1(key, data){ return binb2str(core_hmac_sha1(key, data));} + +/* + * Perform a simple self-test to see if the VM is working + */ +function sha1_vm_test() +{ +  return hex_sha1("abc") == "a9993e364706816aba3e25717850c26c9cd0d89d"; +} + +/* + * Calculate the SHA-1 of an array of big-endian words, and a bit length + */ +function core_sha1(x, len) +{ +  /* append padding */ +  x[len >> 5] |= 0x80 << (24 - len % 32); +  x[((len + 64 >> 9) << 4) + 15] = len; + +  var w = new Array(80); +  var a =  1732584193; +  var b = -271733879; +  var c = -1732584194; +  var d =  271733878; +  var e = -1009589776; + +  var i, j, t, olda, oldb, oldc, oldd, olde; +  for (i = 0; i < x.length; i += 16) +  { +    olda = a; +    oldb = b; +    oldc = c; +    oldd = d; +    olde = e; + +    for (j = 0; j < 80; j++) +    { +      if (j < 16) { w[j] = x[i + j]; } +      else { w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1); } +      t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)), +                       safe_add(safe_add(e, w[j]), sha1_kt(j))); +      e = d; +      d = c; +      c = rol(b, 30); +      b = a; +      a = t; +    } + +    a = safe_add(a, olda); +    b = safe_add(b, oldb); +    c = safe_add(c, oldc); +    d = safe_add(d, oldd); +    e = safe_add(e, olde); +  } +  return [a, b, c, d, e]; +} + +/* + * Perform the appropriate triplet combination function for the current + * iteration + */ +function sha1_ft(t, b, c, d) +{ +  if (t < 20) { return (b & c) | ((~b) & d); } +  if (t < 40) { return b ^ c ^ d; } +  if (t < 60) { return (b & c) | (b & d) | (c & d); } +  return b ^ c ^ d; +} + +/* + * Determine the appropriate additive constant for the current iteration + */ +function sha1_kt(t) +{ +  return (t < 20) ?  1518500249 : (t < 40) ?  1859775393 : +         (t < 60) ? -1894007588 : -899497514; +} + +/* + * Calculate the HMAC-SHA1 of a key and some data + */ +function core_hmac_sha1(key, data) +{ +  var bkey = str2binb(key); +  if (bkey.length > 16) { bkey = core_sha1(bkey, key.length * chrsz); } + +  var ipad = new Array(16), opad = new Array(16); +  for (var i = 0; i < 16; i++) +  { +    ipad[i] = bkey[i] ^ 0x36363636; +    opad[i] = bkey[i] ^ 0x5C5C5C5C; +  } + +  var hash = core_sha1(ipad.concat(str2binb(data)), 512 + data.length * chrsz); +  return core_sha1(opad.concat(hash), 512 + 160); +} + +/* + * Add integers, wrapping at 2^32. This uses 16-bit operations internally + * to work around bugs in some JS interpreters. + */ +function safe_add(x, y) +{ +  var lsw = (x & 0xFFFF) + (y & 0xFFFF); +  var msw = (x >> 16) + (y >> 16) + (lsw >> 16); +  return (msw << 16) | (lsw & 0xFFFF); +} + +/* + * Bitwise rotate a 32-bit number to the left. + */ +function rol(num, cnt) +{ +  return (num << cnt) | (num >>> (32 - cnt)); +} + +/* + * Convert an 8-bit or 16-bit string to an array of big-endian words + * In 8-bit function, characters >255 have their hi-byte silently ignored. + */ +function str2binb(str) +{ +  var bin = []; +  var mask = (1 << chrsz) - 1; +  for (var i = 0; i < str.length * chrsz; i += chrsz) +  { +    bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (32 - chrsz - i%32); +  } +  return bin; +} + +/* + * Convert an array of big-endian words to a string + */ +function binb2str(bin) +{ +  var str = ""; +  var mask = (1 << chrsz) - 1; +  for (var i = 0; i < bin.length * 32; i += chrsz) +  { +    str += String.fromCharCode((bin[i>>5] >>> (32 - chrsz - i%32)) & mask); +  } +  return str; +} + +/* + * Convert an array of big-endian words to a hex string. + */ +function binb2hex(binarray) +{ +  var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef"; +  var str = ""; +  for (var i = 0; i < binarray.length * 4; i++) +  { +    str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) + +           hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8  )) & 0xF); +  } +  return str; +} + +/* + * Convert an array of big-endian words to a base-64 string + */ +function binb2b64(binarray) +{ +  var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +  var str = ""; +  var triplet, j; +  for (var i = 0; i < binarray.length * 4; i += 3) +  { +    triplet = (((binarray[i   >> 2] >> 8 * (3 -  i   %4)) & 0xFF) << 16) | +              (((binarray[i+1 >> 2] >> 8 * (3 - (i+1)%4)) & 0xFF) << 8 ) | +               ((binarray[i+2 >> 2] >> 8 * (3 - (i+2)%4)) & 0xFF); +    for (j = 0; j < 4; j++) +    { +      if (i * 8 + j * 6 > binarray.length * 32) { str += b64pad; } +      else { str += tab.charAt((triplet >> 6*(3-j)) & 0x3F); } +    } +  } +  return str; +} diff --git a/mod/beechat/views/default/js/strophe.min.js.php b/mod/beechat/views/default/js/strophe.min.js.php new file mode 100644 index 000000000..f0eb17906 --- /dev/null +++ b/mod/beechat/views/default/js/strophe.min.js.php @@ -0,0 +1 @@ +var Base64=(function(){var keyStr="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";var obj={encode:function(input){var output="";var chr1,chr2,chr3;var enc1,enc2,enc3,enc4;var i=0;do{chr1=input.charCodeAt(i++);chr2=input.charCodeAt(i++);chr3=input.charCodeAt(i++);enc1=chr1>>2;enc2=((chr1&3)<<4)|(chr2>>4);enc3=((chr2&15)<<2)|(chr3>>6);enc4=chr3&63;if(isNaN(chr2)){enc3=enc4=64}else{if(isNaN(chr3)){enc4=64}}output=output+keyStr.charAt(enc1)+keyStr.charAt(enc2)+keyStr.charAt(enc3)+keyStr.charAt(enc4)}while(i<input.length);return output},decode:function(input){var output="";var chr1,chr2,chr3;var enc1,enc2,enc3,enc4;var i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,"");do{enc1=keyStr.indexOf(input.charAt(i++));enc2=keyStr.indexOf(input.charAt(i++));enc3=keyStr.indexOf(input.charAt(i++));enc4=keyStr.indexOf(input.charAt(i++));chr1=(enc1<<2)|(enc2>>4);chr2=((enc2&15)<<4)|(enc3>>2);chr3=((enc3&3)<<6)|enc4;output=output+String.fromCharCode(chr1);if(enc3!=64){output=output+String.fromCharCode(chr2)}if(enc4!=64){output=output+String.fromCharCode(chr3)}}while(i<input.length);return output}};return obj})();var MD5=(function(){var hexcase=0;var b64pad="";var chrsz=8;var safe_add=function(x,y){var lsw=(x&65535)+(y&65535);var msw=(x>>16)+(y>>16)+(lsw>>16);return(msw<<16)|(lsw&65535)};var bit_rol=function(num,cnt){return(num<<cnt)|(num>>>(32-cnt))};var str2binl=function(str){var bin=[];var mask=(1<<chrsz)-1;for(var i=0;i<str.length*chrsz;i+=chrsz){bin[i>>5]|=(str.charCodeAt(i/chrsz)&mask)<<(i%32)}return bin};var binl2str=function(bin){var str="";var mask=(1<<chrsz)-1;for(var i=0;i<bin.length*32;i+=chrsz){str+=String.fromCharCode((bin[i>>5]>>>(i%32))&mask)}return str};var binl2hex=function(binarray){var hex_tab=hexcase?"0123456789ABCDEF":"0123456789abcdef";var str="";for(var i=0;i<binarray.length*4;i++){str+=hex_tab.charAt((binarray[i>>2]>>((i%4)*8+4))&15)+hex_tab.charAt((binarray[i>>2]>>((i%4)*8))&15)}return str};var binl2b64=function(binarray){var tab="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";var str="";var triplet,j;for(var i=0;i<binarray.length*4;i+=3){triplet=(((binarray[i>>2]>>8*(i%4))&255)<<16)|(((binarray[i+1>>2]>>8*((i+1)%4))&255)<<8)|((binarray[i+2>>2]>>8*((i+2)%4))&255);for(j=0;j<4;j++){if(i*8+j*6>binarray.length*32){str+=b64pad}else{str+=tab.charAt((triplet>>6*(3-j))&63)}}}return str};var md5_cmn=function(q,a,b,x,s,t){return safe_add(bit_rol(safe_add(safe_add(a,q),safe_add(x,t)),s),b)};var md5_ff=function(a,b,c,d,x,s,t){return md5_cmn((b&c)|((~b)&d),a,b,x,s,t)};var md5_gg=function(a,b,c,d,x,s,t){return md5_cmn((b&d)|(c&(~d)),a,b,x,s,t)};var md5_hh=function(a,b,c,d,x,s,t){return md5_cmn(b^c^d,a,b,x,s,t)};var md5_ii=function(a,b,c,d,x,s,t){return md5_cmn(c^(b|(~d)),a,b,x,s,t)};var core_md5=function(x,len){x[len>>5]|=128<<((len)%32);x[(((len+64)>>>9)<<4)+14]=len;var a=1732584193;var b=-271733879;var c=-1732584194;var d=271733878;var olda,oldb,oldc,oldd;for(var i=0;i<x.length;i+=16){olda=a;oldb=b;oldc=c;oldd=d;a=md5_ff(a,b,c,d,x[i+0],7,-680876936);d=md5_ff(d,a,b,c,x[i+1],12,-389564586);c=md5_ff(c,d,a,b,x[i+2],17,606105819);b=md5_ff(b,c,d,a,x[i+3],22,-1044525330);a=md5_ff(a,b,c,d,x[i+4],7,-176418897);d=md5_ff(d,a,b,c,x[i+5],12,1200080426);c=md5_ff(c,d,a,b,x[i+6],17,-1473231341);b=md5_ff(b,c,d,a,x[i+7],22,-45705983);a=md5_ff(a,b,c,d,x[i+8],7,1770035416);d=md5_ff(d,a,b,c,x[i+9],12,-1958414417);c=md5_ff(c,d,a,b,x[i+10],17,-42063);b=md5_ff(b,c,d,a,x[i+11],22,-1990404162);a=md5_ff(a,b,c,d,x[i+12],7,1804603682);d=md5_ff(d,a,b,c,x[i+13],12,-40341101);c=md5_ff(c,d,a,b,x[i+14],17,-1502002290);b=md5_ff(b,c,d,a,x[i+15],22,1236535329);a=md5_gg(a,b,c,d,x[i+1],5,-165796510);d=md5_gg(d,a,b,c,x[i+6],9,-1069501632);c=md5_gg(c,d,a,b,x[i+11],14,643717713);b=md5_gg(b,c,d,a,x[i+0],20,-373897302);a=md5_gg(a,b,c,d,x[i+5],5,-701558691);d=md5_gg(d,a,b,c,x[i+10],9,38016083);c=md5_gg(c,d,a,b,x[i+15],14,-660478335);b=md5_gg(b,c,d,a,x[i+4],20,-405537848);a=md5_gg(a,b,c,d,x[i+9],5,568446438);d=md5_gg(d,a,b,c,x[i+14],9,-1019803690);c=md5_gg(c,d,a,b,x[i+3],14,-187363961);b=md5_gg(b,c,d,a,x[i+8],20,1163531501);a=md5_gg(a,b,c,d,x[i+13],5,-1444681467);d=md5_gg(d,a,b,c,x[i+2],9,-51403784);c=md5_gg(c,d,a,b,x[i+7],14,1735328473);b=md5_gg(b,c,d,a,x[i+12],20,-1926607734);a=md5_hh(a,b,c,d,x[i+5],4,-378558);d=md5_hh(d,a,b,c,x[i+8],11,-2022574463);c=md5_hh(c,d,a,b,x[i+11],16,1839030562);b=md5_hh(b,c,d,a,x[i+14],23,-35309556);a=md5_hh(a,b,c,d,x[i+1],4,-1530992060);d=md5_hh(d,a,b,c,x[i+4],11,1272893353);c=md5_hh(c,d,a,b,x[i+7],16,-155497632);b=md5_hh(b,c,d,a,x[i+10],23,-1094730640);a=md5_hh(a,b,c,d,x[i+13],4,681279174);d=md5_hh(d,a,b,c,x[i+0],11,-358537222);c=md5_hh(c,d,a,b,x[i+3],16,-722521979);b=md5_hh(b,c,d,a,x[i+6],23,76029189);a=md5_hh(a,b,c,d,x[i+9],4,-640364487);d=md5_hh(d,a,b,c,x[i+12],11,-421815835);c=md5_hh(c,d,a,b,x[i+15],16,530742520);b=md5_hh(b,c,d,a,x[i+2],23,-995338651);a=md5_ii(a,b,c,d,x[i+0],6,-198630844);d=md5_ii(d,a,b,c,x[i+7],10,1126891415);c=md5_ii(c,d,a,b,x[i+14],15,-1416354905);b=md5_ii(b,c,d,a,x[i+5],21,-57434055);a=md5_ii(a,b,c,d,x[i+12],6,1700485571);d=md5_ii(d,a,b,c,x[i+3],10,-1894986606);c=md5_ii(c,d,a,b,x[i+10],15,-1051523);b=md5_ii(b,c,d,a,x[i+1],21,-2054922799);a=md5_ii(a,b,c,d,x[i+8],6,1873313359);d=md5_ii(d,a,b,c,x[i+15],10,-30611744);c=md5_ii(c,d,a,b,x[i+6],15,-1560198380);b=md5_ii(b,c,d,a,x[i+13],21,1309151649);a=md5_ii(a,b,c,d,x[i+4],6,-145523070);d=md5_ii(d,a,b,c,x[i+11],10,-1120210379);c=md5_ii(c,d,a,b,x[i+2],15,718787259);b=md5_ii(b,c,d,a,x[i+9],21,-343485551);a=safe_add(a,olda);b=safe_add(b,oldb);c=safe_add(c,oldc);d=safe_add(d,oldd)}return[a,b,c,d]};var core_hmac_md5=function(key,data){var bkey=str2binl(key);if(bkey.length>16){bkey=core_md5(bkey,key.length*chrsz)}var ipad=new Array(16),opad=new Array(16);for(var i=0;i<16;i++){ipad[i]=bkey[i]^909522486;opad[i]=bkey[i]^1549556828}var hash=core_md5(ipad.concat(str2binl(data)),512+data.length*chrsz);return core_md5(opad.concat(hash),512+128)};var obj={hexdigest:function(s){return binl2hex(core_md5(str2binl(s),s.length*chrsz))},b64digest:function(s){return binl2b64(core_md5(str2binl(s),s.length*chrsz))},hash:function(s){return binl2str(core_md5(str2binl(s),s.length*chrsz))},hmac_hexdigest:function(key,data){return binl2hex(core_hmac_md5(key,data))},hmac_b64digest:function(key,data){return binl2b64(core_hmac_md5(key,data))},hmac_hash:function(key,data){return binl2str(core_hmac_md5(key,data))},test:function(){return MD5.hexdigest("abc")==="900150983cd24fb0d6963f7d28e17f72"}};return obj})();if(!Function.prototype.bind){Function.prototype.bind=function(obj){var func=this;return function(){return func.apply(obj,arguments)}}}if(!Function.prototype.prependArg){Function.prototype.prependArg=function(arg){var func=this;return function(){var newargs=[arg];for(var i=0;i<arguments.length;i++){newargs.push(arguments[i])}return func.apply(this,newargs)}}}if(!Array.prototype.indexOf){Array.prototype.indexOf=function(elt){var len=this.length;var from=Number(arguments[1])||0;from=(from<0)?Math.ceil(from):Math.floor(from);if(from<0){from+=len}for(;from<len;from++){if(from in this&&this[from]===elt){return from}}return -1}}(function(callback){var Strophe;function $build(name,attrs){return new Strophe.Builder(name,attrs)}function $msg(attrs){return new Strophe.Builder("message",attrs)}function $iq(attrs){return new Strophe.Builder("iq",attrs)}function $pres(attrs){return new Strophe.Builder("presence",attrs)}Strophe={VERSION:"1.0.1",NS:{HTTPBIND:"http://jabber.org/protocol/httpbind",BOSH:"urn:xmpp:xbosh",CLIENT:"jabber:client",AUTH:"jabber:iq:auth",ROSTER:"jabber:iq:roster",PROFILE:"jabber:iq:profile",DISCO_INFO:"http://jabber.org/protocol/disco#info",DISCO_ITEMS:"http://jabber.org/protocol/disco#items",MUC:"http://jabber.org/protocol/muc",SASL:"urn:ietf:params:xml:ns:xmpp-sasl",STREAM:"http://etherx.jabber.org/streams",BIND:"urn:ietf:params:xml:ns:xmpp-bind",SESSION:"urn:ietf:params:xml:ns:xmpp-session",VERSION:"jabber:iq:version",STANZAS:"urn:ietf:params:xml:ns:xmpp-stanzas"},addNamespace:function(name,value){Strophe.NS[name]=value},Status:{ERROR:0,CONNECTING:1,CONNFAIL:2,AUTHENTICATING:3,AUTHFAIL:4,CONNECTED:5,DISCONNECTED:6,DISCONNECTING:7,ATTACHED:8},LogLevel:{DEBUG:0,INFO:1,WARN:2,ERROR:3,FATAL:4},ElementType:{NORMAL:1,TEXT:3},TIMEOUT:1.1,SECONDARY_TIMEOUT:0.1,forEachChild:function(elem,elemName,func){var i,childNode;for(i=0;i<elem.childNodes.length;i++){childNode=elem.childNodes[i];if(childNode.nodeType==Strophe.ElementType.NORMAL&&(!elemName||this.isTagEqual(childNode,elemName))){func(childNode)}}},isTagEqual:function(el,name){return el.tagName.toLowerCase()==name.toLowerCase()},_xmlGenerator:null,_makeGenerator:function(){var doc;if(window.ActiveXObject){doc=new ActiveXObject("Microsoft.XMLDOM");doc.appendChild(doc.createElement("strophe"))}else{doc=document.implementation.createDocument("jabber:client","strophe",null)}return doc},xmlElement:function(name){if(!name){return null}var node=null;if(!Strophe._xmlGenerator){Strophe._xmlGenerator=Strophe._makeGenerator()}node=Strophe._xmlGenerator.createElement(name);var a,i,k;for(a=1;a<arguments.length;a++){if(!arguments[a]){continue}if(typeof(arguments[a])=="string"||typeof(arguments[a])=="number"){node.appendChild(Strophe.xmlTextNode(arguments[a]))}else{if(typeof(arguments[a])=="object"&&typeof(arguments[a].sort)=="function"){for(i=0;i<arguments[a].length;i++){if(typeof(arguments[a][i])=="object"&&typeof(arguments[a][i].sort)=="function"){node.setAttribute(arguments[a][i][0],arguments[a][i][1])}}}else{if(typeof(arguments[a])=="object"){for(k in arguments[a]){if(arguments[a].hasOwnProperty(k)){node.setAttribute(k,arguments[a][k])}}}}}}return node},xmlescape:function(text){text=text.replace(/\&/g,"&");text=text.replace(/</g,"<");text=text.replace(/>/g,">");return text},xmlTextNode:function(text){text=Strophe.xmlescape(text);if(!Strophe._xmlGenerator){Strophe._xmlGenerator=Strophe._makeGenerator()}return Strophe._xmlGenerator.createTextNode(text)},getText:function(elem){if(!elem){return null}var str="";if(elem.childNodes.length===0&&elem.nodeType==Strophe.ElementType.TEXT){str+=elem.nodeValue}for(var i=0;i<elem.childNodes.length;i++){if(elem.childNodes[i].nodeType==Strophe.ElementType.TEXT){str+=elem.childNodes[i].nodeValue}}return str},copyElement:function(elem){var i,el;if(elem.nodeType==Strophe.ElementType.NORMAL){el=Strophe.xmlElement(elem.tagName);for(i=0;i<elem.attributes.length;i++){el.setAttribute(elem.attributes[i].nodeName.toLowerCase(),elem.attributes[i].value)}for(i=0;i<elem.childNodes.length;i++){el.appendChild(Strophe.copyElement(elem.childNodes[i]))}}else{if(elem.nodeType==Strophe.ElementType.TEXT){el=Strophe.xmlTextNode(elem.nodeValue)}}return el},escapeNode:function(node){return node.replace(/^\s+|\s+$/g,"").replace(/\\/g,"\\5c").replace(/ /g,"\\20").replace(/\"/g,"\\22").replace(/\&/g,"\\26").replace(/\'/g,"\\27").replace(/\//g,"\\2f").replace(/:/g,"\\3a").replace(/</g,"\\3c").replace(/>/g,"\\3e").replace(/@/g,"\\40")},unescapeNode:function(node){return node.replace(/\\20/g," ").replace(/\\22/g,'"').replace(/\\26/g,"&").replace(/\\27/g,"'").replace(/\\2f/g,"/").replace(/\\3a/g,":").replace(/\\3c/g,"<").replace(/\\3e/g,">").replace(/\\40/g,"@").replace(/\\5c/g,"\\")},getNodeFromJid:function(jid){if(jid.indexOf("@")<0){return null}return jid.split("@")[0]},getDomainFromJid:function(jid){var bare=Strophe.getBareJidFromJid(jid);if(bare.indexOf("@")<0){return bare}else{var parts=bare.split("@");parts.splice(0,1);return parts.join("@")}},getResourceFromJid:function(jid){var s=jid.split("/");if(s.length<2){return null}s.splice(0,1);return s.join("/")},getBareJidFromJid:function(jid){return jid.split("/")[0]},log:function(level,msg){return},debug:function(msg){this.log(this.LogLevel.DEBUG,msg)},info:function(msg){this.log(this.LogLevel.INFO,msg)},warn:function(msg){this.log(this.LogLevel.WARN,msg)},error:function(msg){this.log(this.LogLevel.ERROR,msg)},fatal:function(msg){this.log(this.LogLevel.FATAL,msg)},serialize:function(elem){var result;if(!elem){return null}if(typeof(elem.tree)==="function"){elem=elem.tree()}var nodeName=elem.nodeName;var i,child;if(elem.getAttribute("_realname")){nodeName=elem.getAttribute("_realname")}result="<"+nodeName;for(i=0;i<elem.attributes.length;i++){if(elem.attributes[i].nodeName!="_realname"){result+=" "+elem.attributes[i].nodeName.toLowerCase()+"='"+elem.attributes[i].value.replace("&","&").replace("'","'").replace("<","<")+"'"}}if(elem.childNodes.length>0){result+=">";for(i=0;i<elem.childNodes.length;i++){child=elem.childNodes[i];if(child.nodeType==Strophe.ElementType.NORMAL){result+=Strophe.serialize(child)}else{if(child.nodeType==Strophe.ElementType.TEXT){result+=child.nodeValue}}}result+="</"+nodeName+">"}else{result+="/>"}return result},_requestId:0,_connectionPlugins:{},addConnectionPlugin:function(name,ptype){Strophe._connectionPlugins[name]=ptype}};Strophe.Builder=function(name,attrs){if(name=="presence"||name=="message"||name=="iq"){if(attrs&&!attrs.xmlns){attrs.xmlns=Strophe.NS.CLIENT}else{if(!attrs){attrs={xmlns:Strophe.NS.CLIENT}}}}this.nodeTree=Strophe.xmlElement(name,attrs);this.node=this.nodeTree};Strophe.Builder.prototype={tree:function(){return this.nodeTree},toString:function(){return Strophe.serialize(this.nodeTree)},up:function(){this.node=this.node.parentNode;return this},attrs:function(moreattrs){for(var k in moreattrs){if(moreattrs.hasOwnProperty(k)){this.node.setAttribute(k,moreattrs[k])}}return this},c:function(name,attrs){var child=Strophe.xmlElement(name,attrs);this.node.appendChild(child);this.node=child;return this},cnode:function(elem){this.node.appendChild(elem);this.node=elem;return this},t:function(text){var child=Strophe.xmlTextNode(text);this.node.appendChild(child);return this}};Strophe.Handler=function(handler,ns,name,type,id,from,options){this.handler=handler;this.ns=ns;this.name=name;this.type=type;this.id=id;this.options=options||{matchbare:false};if(!this.options.matchBare){this.options.matchBare=false}if(this.options.matchBare){this.from=Strophe.getBareJidFromJid(from)}else{this.from=from}this.user=true};Strophe.Handler.prototype={isMatch:function(elem){var nsMatch;var from=null;if(this.options.matchBare){from=Strophe.getBareJidFromJid(elem.getAttribute("from"))}else{from=elem.getAttribute("from")}nsMatch=false;if(!this.ns){nsMatch=true}else{var self=this;Strophe.forEachChild(elem,null,function(elem){if(elem.getAttribute("xmlns")==self.ns){nsMatch=true}});nsMatch=nsMatch||elem.getAttribute("xmlns")==this.ns}if(nsMatch&&(!this.name||Strophe.isTagEqual(elem,this.name))&&(!this.type||elem.getAttribute("type")===this.type)&&(!this.id||elem.getAttribute("id")===this.id)&&(!this.from||from===this.from)){return true}return false},run:function(elem){var result=null;try{result=this.handler(elem)}catch(e){if(e.sourceURL){Strophe.fatal("error: "+this.handler+" "+e.sourceURL+":"+e.line+" - "+e.name+": "+e.message)}else{if(e.fileName){if(typeof(console)!="undefined"){console.trace();console.error(this.handler," - error - ",e,e.message)}Strophe.fatal("error: "+this.handler+" "+e.fileName+":"+e.lineNumber+" - "+e.name+": "+e.message)}else{Strophe.fatal("error: "+this.handler)}}throw e}return result},toString:function(){return"{Handler: "+this.handler+"("+this.name+","+this.id+","+this.ns+")}"}};Strophe.TimedHandler=function(period,handler){this.period=period;this.handler=handler;this.lastCalled=new Date().getTime();this.user=true};Strophe.TimedHandler.prototype={run:function(){this.lastCalled=new Date().getTime();return this.handler()},reset:function(){this.lastCalled=new Date().getTime()},toString:function(){return"{TimedHandler: "+this.handler+"("+this.period+")}"}};Strophe.Request=function(elem,func,rid,sends){this.id=++Strophe._requestId;this.xmlData=elem;this.data=Strophe.serialize(elem);this.origFunc=func;this.func=func;this.rid=rid;this.date=NaN;this.sends=sends||0;this.abort=false;this.dead=null;this.age=function(){if(!this.date){return 0}var now=new Date();return(now-this.date)/1000};this.timeDead=function(){if(!this.dead){return 0}var now=new Date();return(now-this.dead)/1000};this.xhr=this._newXHR()};Strophe.Request.prototype={getResponse:function(){var node=null;if(this.xhr.responseXML&&this.xhr.responseXML.documentElement){node=this.xhr.responseXML.documentElement;if(node.tagName=="parsererror"){Strophe.error("invalid response received");Strophe.error("responseText: "+this.xhr.responseText);Strophe.error("responseXML: "+Strophe.serialize(this.xhr.responseXML));throw"parsererror"}}else{if(this.xhr.responseText){Strophe.error("invalid response received");Strophe.error("responseText: "+this.xhr.responseText);Strophe.error("responseXML: "+Strophe.serialize(this.xhr.responseXML))}}return node},_newXHR:function(){var xhr=null;if(window.XMLHttpRequest){xhr=new XMLHttpRequest();if(xhr.overrideMimeType){xhr.overrideMimeType("text/xml")}}else{if(window.ActiveXObject){xhr=new ActiveXObject("Microsoft.XMLHTTP")}}xhr.onreadystatechange=this.func.prependArg(this);return xhr}};Strophe.Connection=function(service){this.service=service;this.jid="";this.rid=Math.floor(Math.random()*4294967295);this.sid=null;this.streamId=null;this.do_session=false;this.do_bind=false;this.timedHandlers=[];this.handlers=[];this.removeTimeds=[];this.removeHandlers=[];this.addTimeds=[];this.addHandlers=[];this._idleTimeout=null;this._disconnectTimeout=null;this.authenticated=false;this.disconnecting=false;this.connected=false;this.errors=0;this.paused=false;this.hold=1;this.wait=60;this.window=5;this._data=[];this._requests=[];this._uniqueId=Math.round(Math.random()*10000);this._sasl_success_handler=null;this._sasl_failure_handler=null;this._sasl_challenge_handler=null;this._idleTimeout=setTimeout(this._onIdle.bind(this),100);for(var k in Strophe._connectionPlugins){if(Strophe._connectionPlugins.hasOwnProperty(k)){var ptype=Strophe._connectionPlugins[k];var F=function(){};F.prototype=ptype;this[k]=new F();this[k].init(this)}}};Strophe.Connection.prototype={reset:function(){this.rid=Math.floor(Math.random()*4294967295);this.sid=null;this.streamId=null;this.do_session=false;this.do_bind=false;this.timedHandlers=[];this.handlers=[];this.removeTimeds=[];this.removeHandlers=[];this.addTimeds=[];this.addHandlers=[];this.authenticated=false;this.disconnecting=false;this.connected=false;this.errors=0;this._requests=[];this._uniqueId=Math.round(Math.random()*10000)},pause:function(){this.paused=true},resume:function(){this.paused=false},getUniqueId:function(suffix){if(typeof(suffix)=="string"||typeof(suffix)=="number"){return ++this._uniqueId+":"+suffix}else{return ++this._uniqueId+""}},connect:function(jid,pass,callback,wait,hold){this.jid=jid;this.pass=pass;this.connect_callback=callback;this.disconnecting=false;this.connected=false;this.authenticated=false;this.errors=0;this.wait=wait||this.wait;this.hold=hold||this.hold;this.domain=Strophe.getDomainFromJid(this.jid);var body=this._buildBody().attrs({to:this.domain,"xml:lang":"en",wait:this.wait,hold:this.hold,content:"text/xml; charset=utf-8",ver:"1.6","xmpp:version":"1.0","xmlns:xmpp":Strophe.NS.BOSH});this._changeConnectStatus(Strophe.Status.CONNECTING,null);this._requests.push(new Strophe.Request(body.tree(),this._onRequestStateChange.bind(this).prependArg(this._connect_cb.bind(this)),body.tree().getAttribute("rid")));this._throttledRequestHandler()},attach:function(jid,sid,rid,callback,wait,hold,wind){this.jid=jid;this.sid=sid;this.rid=rid;this.connect_callback=callback;this.domain=Strophe.getDomainFromJid(this.jid);this.authenticated=true;this.connected=true;this.wait=wait||this.wait;this.hold=hold||this.hold;this.window=wind||this.window;this._changeConnectStatus(Strophe.Status.ATTACHED,null)},xmlInput:function(elem){return},xmlOutput:function(elem){return},rawInput:function(data){return},rawOutput:function(data){return},send:function(elem){if(elem===null){return}if(typeof(elem.sort)==="function"){for(var i=0;i<elem.length;i++){this._queueData(elem[i])}}else{if(typeof(elem.tree)==="function"){this._queueData(elem.tree())}else{this._queueData(elem)}}this._throttledRequestHandler();clearTimeout(this._idleTimeout);this._idleTimeout=setTimeout(this._onIdle.bind(this),100)},flush:function(){clearTimeout(this._idleTimeout);this._onIdle()},sendIQ:function(elem,callback,errback,timeout){var timeoutHandler=null;var that=this;if(typeof(elem.tree)==="function"){elem=elem.tree()}var id=elem.getAttribute("id");if(!id){id=this.getUniqueId("sendIQ");elem.setAttribute("id",id)}var handler=this.addHandler(function(stanza){if(timeoutHandler){that.deleteTimedHandler(timeoutHandler)}var iqtype=stanza.getAttribute("type");if(iqtype==="result"){if(callback){callback(stanza)}}else{if(iqtype==="error"){if(errback){errback(stanza)}}else{throw {name:"StropheError",message:"Got bad IQ type of "+iqtype}}}},null,"iq",null,id);if(timeout){timeoutHandler=this.addTimedHandler(timeout,function(){that.deleteHandler(handler);if(errback){errback(null)}return false})}this.send(elem);return id},_queueData:function(element){if(element===null||!element.tagName||!element.childNodes){throw {name:"StropheError",message:"Cannot queue non-DOMElement."}}this._data.push(element)},_sendRestart:function(){this._data.push("restart");this._throttledRequestHandler();clearTimeout(this._idleTimeout);this._idleTimeout=setTimeout(this._onIdle.bind(this),100)},addTimedHandler:function(period,handler){var thand=new Strophe.TimedHandler(period,handler);this.addTimeds.push(thand);return thand},deleteTimedHandler:function(handRef){this.removeTimeds.push(handRef)},addHandler:function(handler,ns,name,type,id,from,options){var hand=new Strophe.Handler(handler,ns,name,type,id,from,options);this.addHandlers.push(hand);return hand},deleteHandler:function(handRef){this.removeHandlers.push(handRef)},disconnect:function(reason){this._changeConnectStatus(Strophe.Status.DISCONNECTING,reason);Strophe.info("Disconnect was called because: "+reason);if(this.connected){this._disconnectTimeout=this._addSysTimedHandler(3000,this._onDisconnectTimeout.bind(this));this._sendTerminate()}},_changeConnectStatus:function(status,condition){for(var k in Strophe._connectionPlugins){if(Strophe._connectionPlugins.hasOwnProperty(k)){var plugin=this[k];if(plugin.statusChanged){try{plugin.statusChanged(status,condition)}catch(err){Strophe.error(""+k+" plugin caused an exception changing status: "+err)}}}}if(this.connect_callback){try{this.connect_callback(status,condition)}catch(e){Strophe.error("User connection callback caused an exception: "+e)}}},_buildBody:function(){var bodyWrap=$build("body",{rid:this.rid++,xmlns:Strophe.NS.HTTPBIND});if(this.sid!==null){bodyWrap.attrs({sid:this.sid})}return bodyWrap},_removeRequest:function(req){Strophe.debug("removing request");var i;for(i=this._requests.length-1;i>=0;i--){if(req==this._requests[i]){this._requests.splice(i,1)}}req.xhr.onreadystatechange=function(){};this._throttledRequestHandler()},_restartRequest:function(i){var req=this._requests[i];if(req.dead===null){req.dead=new Date()}this._processRequest(i)},_processRequest:function(i){var req=this._requests[i];var reqStatus=-1;try{if(req.xhr.readyState==4){reqStatus=req.xhr.status}}catch(e){Strophe.error("caught an error in _requests["+i+"], reqStatus: "+reqStatus)}if(typeof(reqStatus)=="undefined"){reqStatus=-1}var time_elapsed=req.age();var primaryTimeout=(!isNaN(time_elapsed)&&time_elapsed>Math.floor(Strophe.TIMEOUT*this.wait));var secondaryTimeout=(req.dead!==null&&req.timeDead()>Math.floor(Strophe.SECONDARY_TIMEOUT*this.wait));var requestCompletedWithServerError=(req.xhr.readyState==4&&(reqStatus<1||reqStatus>=500));if(primaryTimeout||secondaryTimeout||requestCompletedWithServerError){if(secondaryTimeout){Strophe.error("Request "+this._requests[i].id+" timed out (secondary), restarting")}req.abort=true;req.xhr.abort();req.xhr.onreadystatechange=function(){};this._requests[i]=new Strophe.Request(req.xmlData,req.origFunc,req.rid,req.sends);req=this._requests[i]}if(req.xhr.readyState===0){Strophe.debug("request id "+req.id+"."+req.sends+" posting");req.date=new Date();try{req.xhr.open("POST",this.service,true)}catch(e2){Strophe.error("XHR open failed.");if(!this.connected){this._changeConnectStatus(Strophe.Status.CONNFAIL,"bad-service")}this.disconnect();return}var sendFunc=function(){req.xhr.send(req.data)};if(req.sends>1){var backoff=Math.pow(req.sends,3)*1000;setTimeout(sendFunc,backoff)}else{sendFunc()}req.sends++;this.xmlOutput(req.xmlData);this.rawOutput(req.data)}else{Strophe.debug("_processRequest: "+(i===0?"first":"second")+" request has readyState of "+req.xhr.readyState)}},_throttledRequestHandler:function(){if(!this._requests){Strophe.debug("_throttledRequestHandler called with undefined requests")}else{Strophe.debug("_throttledRequestHandler called with "+this._requests.length+" requests")}if(!this._requests||this._requests.length===0){return}if(this._requests.length>0){this._processRequest(0)}if(this._requests.length>1&&Math.abs(this._requests[0].rid-this._requests[1].rid)<this.window-1){this._processRequest(1)}},_onRequestStateChange:function(func,req){Strophe.debug("request id "+req.id+"."+req.sends+" state changed to "+req.xhr.readyState);if(req.abort){req.abort=false;return}var reqStatus;if(req.xhr.readyState==4){reqStatus=0;try{reqStatus=req.xhr.status}catch(e){}if(typeof(reqStatus)=="undefined"){reqStatus=0}if(this.disconnecting){if(reqStatus>=400){this._hitError(reqStatus);return}}var reqIs0=(this._requests[0]==req);var reqIs1=(this._requests[1]==req);if((reqStatus>0&&reqStatus<500)||req.sends>5){this._removeRequest(req);Strophe.debug("request id "+req.id+" should now be removed")}if(reqStatus==200){if(reqIs1||(reqIs0&&this._requests.length>0&&this._requests[0].age()>Math.floor(Strophe.SECONDARY_TIMEOUT*this.wait))){this._restartRequest(0)}Strophe.debug("request id "+req.id+"."+req.sends+" got 200");func(req);this.errors=0}else{Strophe.error("request id "+req.id+"."+req.sends+" error "+reqStatus+" happened");if(reqStatus===0||(reqStatus>=400&&reqStatus<600)||reqStatus>=12000){this._hitError(reqStatus);if(reqStatus>=400&&reqStatus<500){this._changeConnectStatus(Strophe.Status.DISCONNECTING,null);this._doDisconnect()}}}if(!((reqStatus>0&&reqStatus<10000)||req.sends>5)){this._throttledRequestHandler()}}},_hitError:function(reqStatus){this.errors++;Strophe.warn("request errored, status: "+reqStatus+", number of errors: "+this.errors);if(this.errors>4){this._onDisconnectTimeout()}},_doDisconnect:function(){Strophe.info("_doDisconnect was called");this.authenticated=false;this.disconnecting=false;this.sid=null;this.streamId=null;this.rid=Math.floor(Math.random()*4294967295);if(this.connected){this._changeConnectStatus(Strophe.Status.DISCONNECTED,null);this.connected=false}this.handlers=[];this.timedHandlers=[];this.removeTimeds=[];this.removeHandlers=[];this.addTimeds=[];this.addHandlers=[]},_dataRecv:function(req){try{var elem=req.getResponse()}catch(e){if(e!="parsererror"){throw e}this.disconnect("strophe-parsererror")}if(elem===null){return}this.xmlInput(elem);this.rawInput(Strophe.serialize(elem));var i,hand;while(this.removeHandlers.length>0){hand=this.removeHandlers.pop();i=this.handlers.indexOf(hand);if(i>=0){this.handlers.splice(i,1)}}while(this.addHandlers.length>0){this.handlers.push(this.addHandlers.pop())}if(this.disconnecting&&this._requests.length===0){this.deleteTimedHandler(this._disconnectTimeout);this._disconnectTimeout=null;this._doDisconnect();return}var typ=elem.getAttribute("type");var cond,conflict;if(typ!==null&&typ=="terminate"){cond=elem.getAttribute("condition");conflict=elem.getElementsByTagName("conflict");if(cond!==null){if(cond=="remote-stream-error"&&conflict.length>0){cond="conflict"}this._changeConnectStatus(Strophe.Status.CONNFAIL,cond)}else{this._changeConnectStatus(Strophe.Status.CONNFAIL,"unknown")}this.disconnect();return}var self=this;Strophe.forEachChild(elem,null,function(child){var i,newList;newList=self.handlers;self.handlers=[];for(i=0;i<newList.length;i++){var hand=newList[i];if(hand.isMatch(child)&&(self.authenticated||!hand.user)){if(hand.run(child)){self.handlers.push(hand)}}else{self.handlers.push(hand)}}})},_sendTerminate:function(){Strophe.info("_sendTerminate was called");var body=this._buildBody().attrs({type:"terminate"});if(this.authenticated){body.c("presence",{xmlns:Strophe.NS.CLIENT,type:"unavailable"})}this.disconnecting=true;var req=new Strophe.Request(body.tree(),this._onRequestStateChange.bind(this).prependArg(this._dataRecv.bind(this)),body.tree().getAttribute("rid"));this._requests.push(req);this._throttledRequestHandler()},_connect_cb:function(req){Strophe.info("_connect_cb was called");this.connected=true;var bodyWrap=req.getResponse();if(!bodyWrap){return}this.xmlInput(bodyWrap);this.rawInput(Strophe.serialize(bodyWrap));var typ=bodyWrap.getAttribute("type");var cond,conflict;if(typ!==null&&typ=="terminate"){cond=bodyWrap.getAttribute("condition");conflict=bodyWrap.getElementsByTagName("conflict");if(cond!==null){if(cond=="remote-stream-error"&&conflict.length>0){cond="conflict"}this._changeConnectStatus(Strophe.Status.CONNFAIL,cond)}else{this._changeConnectStatus(Strophe.Status.CONNFAIL,"unknown")}return}if(!this.sid){this.sid=bodyWrap.getAttribute("sid")}if(!this.stream_id){this.stream_id=bodyWrap.getAttribute("authid")}var wind=bodyWrap.getAttribute("requests");if(wind){this.window=parseInt(wind,10)}var hold=bodyWrap.getAttribute("hold");if(hold){this.hold=parseInt(hold,10)}var wait=bodyWrap.getAttribute("wait");if(wait){this.wait=parseInt(wait,10)}var do_sasl_plain=false;var do_sasl_digest_md5=false;var do_sasl_anonymous=false;var mechanisms=bodyWrap.getElementsByTagName("mechanism");var i,mech,auth_str,hashed_auth_str;if(mechanisms.length>0){for(i=0;i<mechanisms.length;i++){mech=Strophe.getText(mechanisms[i]);if(mech=="DIGEST-MD5"){do_sasl_digest_md5=true}else{if(mech=="PLAIN"){do_sasl_plain=true}else{if(mech=="ANONYMOUS"){do_sasl_anonymous=true}}}}}else{var body=this._buildBody();this._requests.push(new Strophe.Request(body.tree(),this._onRequestStateChange.bind(this).prependArg(this._connect_cb.bind(this)),body.tree().getAttribute("rid")));this._throttledRequestHandler();return}if(Strophe.getNodeFromJid(this.jid)===null&&do_sasl_anonymous){this._changeConnectStatus(Strophe.Status.AUTHENTICATING,null);this._sasl_success_handler=this._addSysHandler(this._sasl_success_cb.bind(this),null,"success",null,null);this._sasl_failure_handler=this._addSysHandler(this._sasl_failure_cb.bind(this),null,"failure",null,null);this.send($build("auth",{xmlns:Strophe.NS.SASL,mechanism:"ANONYMOUS"}).tree())}else{if(Strophe.getNodeFromJid(this.jid)===null){this._changeConnectStatus(Strophe.Status.CONNFAIL,"x-strophe-bad-non-anon-jid");this.disconnect()}else{if(do_sasl_digest_md5){this._changeConnectStatus(Strophe.Status.AUTHENTICATING,null);this._sasl_challenge_handler=this._addSysHandler(this._sasl_challenge1_cb.bind(this),null,"challenge",null,null);this._sasl_failure_handler=this._addSysHandler(this._sasl_failure_cb.bind(this),null,"failure",null,null);this.send($build("auth",{xmlns:Strophe.NS.SASL,mechanism:"DIGEST-MD5"}).tree())}else{if(do_sasl_plain){auth_str=Strophe.getBareJidFromJid(this.jid);auth_str=auth_str+"\u0000";auth_str=auth_str+Strophe.getNodeFromJid(this.jid);auth_str=auth_str+"\u0000";auth_str=auth_str+this.pass;this._changeConnectStatus(Strophe.Status.AUTHENTICATING,null);this._sasl_success_handler=this._addSysHandler(this._sasl_success_cb.bind(this),null,"success",null,null);this._sasl_failure_handler=this._addSysHandler(this._sasl_failure_cb.bind(this),null,"failure",null,null);hashed_auth_str=Base64.encode(auth_str);this.send($build("auth",{xmlns:Strophe.NS.SASL,mechanism:"PLAIN"}).t(hashed_auth_str).tree())}else{this._changeConnectStatus(Strophe.Status.AUTHENTICATING,null);this._addSysHandler(this._auth1_cb.bind(this),null,null,null,"_auth_1");this.send($iq({type:"get",to:this.domain,id:"_auth_1"}).c("query",{xmlns:Strophe.NS.AUTH}).c("username",{}).t(Strophe.getNodeFromJid(this.jid)).tree())}}}}},_sasl_challenge1_cb:function(elem){var attribMatch=/([a-z]+)=("[^"]+"|[^,"]+)(?:,|$)/;var challenge=Base64.decode(Strophe.getText(elem));var cnonce=MD5.hexdigest(Math.random()*1234567890);var realm="";var host=null;var nonce="";var qop="";var matches;this.deleteHandler(this._sasl_failure_handler);while(challenge.match(attribMatch)){matches=challenge.match(attribMatch);challenge=challenge.replace(matches[0],"");matches[2]=matches[2].replace(/^"(.+)"$/,"$1");switch(matches[1]){case"realm":realm=matches[2];break;case"nonce":nonce=matches[2];break;case"qop":qop=matches[2];break;case"host":host=matches[2];break}}var digest_uri="xmpp/"+this.domain;if(host!==null){digest_uri=digest_uri+"/"+host}var A1=MD5.hash(Strophe.getNodeFromJid(this.jid)+":"+realm+":"+this.pass)+":"+nonce+":"+cnonce;var A2="AUTHENTICATE:"+digest_uri;var responseText="";responseText+="username="+this._quote(Strophe.getNodeFromJid(this.jid))+",";responseText+="realm="+this._quote(realm)+",";responseText+="nonce="+this._quote(nonce)+",";responseText+="cnonce="+this._quote(cnonce)+",";responseText+='nc="00000001",';responseText+='qop="auth",';responseText+="digest-uri="+this._quote(digest_uri)+",";responseText+="response="+this._quote(MD5.hexdigest(MD5.hexdigest(A1)+":"+nonce+":00000001:"+cnonce+":auth:"+MD5.hexdigest(A2)))+",";responseText+='charset="utf-8"';this._sasl_challenge_handler=this._addSysHandler(this._sasl_challenge2_cb.bind(this),null,"challenge",null,null);this._sasl_success_handler=this._addSysHandler(this._sasl_success_cb.bind(this),null,"success",null,null);this._sasl_failure_handler=this._addSysHandler(this._sasl_failure_cb.bind(this),null,"failure",null,null);this.send($build("response",{xmlns:Strophe.NS.SASL}).t(Base64.encode(responseText)).tree());return false},_quote:function(str){return'"'+str.replace(/\\/g,"\\\\").replace(/"/g,'\\"')+'"'},_sasl_challenge2_cb:function(elem){this.deleteHandler(this._sasl_success_handler);this.deleteHandler(this._sasl_failure_handler);this._sasl_success_handler=this._addSysHandler(this._sasl_success_cb.bind(this),null,"success",null,null);this._sasl_failure_handler=this._addSysHandler(this._sasl_failure_cb.bind(this),null,"failure",null,null);this.send($build("response",{xmlns:Strophe.NS.SASL}).tree());return false},_auth1_cb:function(elem){var iq=$iq({type:"set",id:"_auth_2"}).c("query",{xmlns:Strophe.NS.AUTH}).c("username",{}).t(Strophe.getNodeFromJid(this.jid)).up().c("password").t(this.pass);if(!Strophe.getResourceFromJid(this.jid)){this.jid=Strophe.getBareJidFromJid(this.jid)+"/strophe"}iq.up().c("resource",{}).t(Strophe.getResourceFromJid(this.jid));this._addSysHandler(this._auth2_cb.bind(this),null,null,null,"_auth_2");this.send(iq.tree());return false},_sasl_success_cb:function(elem){Strophe.info("SASL authentication succeeded.");this.deleteHandler(this._sasl_failure_handler);this._sasl_failure_handler=null;if(this._sasl_challenge_handler){this.deleteHandler(this._sasl_challenge_handler);this._sasl_challenge_handler=null}this._addSysHandler(this._sasl_auth1_cb.bind(this),null,"stream:features",null,null);this._sendRestart();return false},_sasl_auth1_cb:function(elem){var i,child;for(i=0;i<elem.childNodes.length;i++){child=elem.childNodes[i];if(child.nodeName=="bind"){this.do_bind=true}if(child.nodeName=="session"){this.do_session=true}}if(!this.do_bind){this._changeConnectStatus(Strophe.Status.AUTHFAIL,null);return false}else{this._addSysHandler(this._sasl_bind_cb.bind(this),null,null,null,"_bind_auth_2");var resource=Strophe.getResourceFromJid(this.jid);if(resource){this.send($iq({type:"set",id:"_bind_auth_2"}).c("bind",{xmlns:Strophe.NS.BIND}).c("resource",{}).t(resource).tree())}else{this.send($iq({type:"set",id:"_bind_auth_2"}).c("bind",{xmlns:Strophe.NS.BIND}).tree())}}return false},_sasl_bind_cb:function(elem){if(elem.getAttribute("type")=="error"){Strophe.info("SASL binding failed.");this._changeConnectStatus(Strophe.Status.AUTHFAIL,null);return false}var bind=elem.getElementsByTagName("bind");var jidNode;if(bind.length>0){jidNode=bind[0].getElementsByTagName("jid");if(jidNode.length>0){this.jid=Strophe.getText(jidNode[0]);if(this.do_session){this._addSysHandler(this._sasl_session_cb.bind(this),null,null,null,"_session_auth_2");this.send($iq({type:"set",id:"_session_auth_2"}).c("session",{xmlns:Strophe.NS.SESSION}).tree())}else{this.authenticated=true;this._changeConnectStatus(Strophe.Status.CONNECTED,null)}}}else{Strophe.info("SASL binding failed.");this._changeConnectStatus(Strophe.Status.AUTHFAIL,null);return false}},_sasl_session_cb:function(elem){if(elem.getAttribute("type")=="result"){this.authenticated=true;this._changeConnectStatus(Strophe.Status.CONNECTED,null)}else{if(elem.getAttribute("type")=="error"){Strophe.info("Session creation failed.");this._changeConnectStatus(Strophe.Status.AUTHFAIL,null);return false}}return false},_sasl_failure_cb:function(elem){if(this._sasl_success_handler){this.deleteHandler(this._sasl_success_handler);this._sasl_success_handler=null}if(this._sasl_challenge_handler){this.deleteHandler(this._sasl_challenge_handler);this._sasl_challenge_handler=null}this._changeConnectStatus(Strophe.Status.AUTHFAIL,null);return false},_auth2_cb:function(elem){if(elem.getAttribute("type")=="result"){this.authenticated=true;this._changeConnectStatus(Strophe.Status.CONNECTED,null)}else{if(elem.getAttribute("type")=="error"){this._changeConnectStatus(Strophe.Status.AUTHFAIL,null);this.disconnect()}}return false},_addSysTimedHandler:function(period,handler){var thand=new Strophe.TimedHandler(period,handler);thand.user=false;this.addTimeds.push(thand);return thand},_addSysHandler:function(handler,ns,name,type,id){var hand=new Strophe.Handler(handler,ns,name,type,id);hand.user=false;this.addHandlers.push(hand);return hand},_onDisconnectTimeout:function(){Strophe.info("_onDisconnectTimeout was called");var req;while(this._requests.length>0){req=this._requests.pop();req.abort=true;req.xhr.abort();req.xhr.onreadystatechange=function(){}}this._doDisconnect();return false},_onIdle:function(){var i,thand,since,newList;while(this.removeTimeds.length>0){thand=this.removeTimeds.pop();i=this.timedHandlers.indexOf(thand);if(i>=0){this.timedHandlers.splice(i,1)}}while(this.addTimeds.length>0){this.timedHandlers.push(this.addTimeds.pop())}var now=new Date().getTime();newList=[];for(i=0;i<this.timedHandlers.length;i++){thand=this.timedHandlers[i];if(this.authenticated||!thand.user){since=thand.lastCalled+thand.period;if(since-now<=0){if(thand.run()){newList.push(thand)}}else{newList.push(thand)}}}this.timedHandlers=newList;var body,time_elapsed;if(this.authenticated&&this._requests.length===0&&this._data.length===0&&!this.disconnecting){Strophe.info("no requests during idle cycle, sending blank request");this._data.push(null)}if(this._requests.length<2&&this._data.length>0&&!this.paused){body=this._buildBody();for(i=0;i<this._data.length;i++){if(this._data[i]!==null){if(this._data[i]==="restart"){body.attrs({to:this.domain,"xml:lang":"en","xmpp:restart":"true","xmlns:xmpp":Strophe.NS.BOSH})}else{body.cnode(this._data[i]).up()}}}delete this._data;this._data=[];this._requests.push(new Strophe.Request(body.tree(),this._onRequestStateChange.bind(this).prependArg(this._dataRecv.bind(this)),body.tree().getAttribute("rid")));this._processRequest(this._requests.length-1)}if(this._requests.length>0){time_elapsed=this._requests[0].age();if(this._requests[0].dead!==null){if(this._requests[0].timeDead()>Math.floor(Strophe.SECONDARY_TIMEOUT*this.wait)){this._throttledRequestHandler()}}if(time_elapsed>Math.floor(Strophe.TIMEOUT*this.wait)){Strophe.warn("Request "+this._requests[0].id+" timed out, over "+Math.floor(Strophe.TIMEOUT*this.wait)+" seconds since last activity");this._throttledRequestHandler()}}clearTimeout(this._idleTimeout);this._idleTimeout=setTimeout(this._onIdle.bind(this),100)}};if(callback){callback(Strophe,$build,$msg,$iq,$pres)}})(function(){window.Strophe=arguments[0];window.$build=arguments[1];window.$msg=arguments[2];window.$iq=arguments[3];window.$pres=arguments[4]});
\ No newline at end of file diff --git a/mod/beechat/views/default/js/strophe.muc.js b/mod/beechat/views/default/js/strophe.muc.js new file mode 100644 index 000000000..954ca8730 --- /dev/null +++ b/mod/beechat/views/default/js/strophe.muc.js @@ -0,0 +1,300 @@ +/* +Plugin to implement the MUC extension. http://xmpp.org/extensions/xep-0045.html +*/ +/* jslint configuration: */ +/* global document, window, setTimeout, clearTimeout, console, +    XMLHttpRequest, ActiveXObject, +    Base64, MD5, +    Strophe, $build, $msg, $iq, $pres  +*/ + +Strophe.addConnectionPlugin('muc', { +    _connection: null, +    // The plugin must have the init function +    /***Function +    Initialize the MUC plugin. Sets the correct connection object and +    extends the namesace. +    */ +    init: function(conn) { +        this._connection = conn; +        /* extend name space  +         *  NS.MUC - XMPP Multi-user chat namespace +         *              from XEP 45.   +         * +         */ +        Strophe.addNamespace('MUC_OWNER', Strophe.NS.MUC+"#owner"); +        Strophe.addNamespace('MUC_ADMIN', Strophe.NS.MUC+"#admin"); +    }, +    /***Function +    Join a multi-user chat room +    Parameters: +    (String) room - The multi-user chat room to join. +    (String) nick - The nickname to use in the chat room. Optional +    (Function) msg_handler_cb - The function call to handle messages from the +    specified chat room. +    (Function) pres_handler_cb - The function call back to handle presence +    in the chat room. +    (String) password - The optional password to use. (password protected +    rooms only) +    */ +    join: function(room, nick, msg_handler_cb, pres_handler_cb, password) { +        var room_nick = this.test_append_nick(room, nick);         +        var msg = $pres({from: this._connection.jid, +                         to: room_nick}) +            .c("x",{xmlns: Strophe.NS.MUC}); +        if (password) +        { +            var password_elem = Strophe.xmlElement("password",  +                                                   [], +                                                   password); +            msg.cnode(password_elem); +        } +        if (msg_handler_cb) +        { +            this._connection.addHandler(function(stanza) { +                var from = stanza.getAttribute('from'); +                var roomname = from.split("/"); +                // filter on room name +                if (roomname.length > 1 && roomname[0] == room) +                { +                    return msg_handler_cb(stanza); +                } +                else +                { +                    return true; +                } +            }, +                                        null, +                                        "message", +                                        null, +                                        null, +                                        null); +        } +        if (pres_handler_cb) +        { +            this._connection.addHandler(function(stanza) { +                var xquery = stanza.getElementsByTagName("x"); +                if (xquery.length > 0) +                { +                    //Handle only MUC user protocol +                    for (var i = 0; i < xquery.length; i++) +                    { +                        var xmlns = xquery[i].getAttribute("xmlns"); +                         +                        if (xmlns && xmlns.match(Strophe.NS.MUC)) +                        { +                            return pres_handler_cb(stanza); +                        } +                    } +                } +                return true;                 +            }, +                                        null, +                                        "presence", +                                        null, +                                        null, +                                        null); +        } +        this._connection.send(msg); +    }, +    /***Function +    Leave a multi-user chat room +    Parameters: +    (String) room - The multi-user chat room to leave. +    (String) nick - The nick name used in the room. +    (Function) handler_cb - Optional function to handle the successful leave. +    Returns: +    iqid - The unique id for the room leave. +    */ +    leave: function(room, nick, handler_cb) { +        var room_nick = this.test_append_nick(room, nick);         +        var presenceid = this._connection.getUniqueId(); +        var presence = $pres({type: "unavailable", +                              id: presenceid, +                              from: this._connection.jid, +                              to: room_nick}) +            .c("x",{xmlns: Strophe.NS.MUC}); +        this._connection.addHandler(handler_cb, +                                    null, +                                    "presence", +                                    null, +                                    presenceid, +                                    null); +        this._connection.send(presence); +        return presenceid; +    }, +    /***Function +    Parameters: +    (String) room - The multi-user chat room name. +    (String) nick - The nick name used in the chat room. +    (String) message - The message to send to the room. +    Returns: +    msgiq - the unique id used to send the message +    */ +    message: function(room, nick, message) { +        var room_nick = this.test_append_nick(room, nick);         +        var msgid = this._connection.getUniqueId(); +        var msg = $msg({to: room_nick, +                        from: this._connection.jid, +                        type: "groupchat", +                        id: msgid}).c("body", +                                      {xmlns: Strophe.NS.CLIENT}).t(message); +        msg.up().c("x", {xmlns: "jabber:x:event"}).c("composing"); +        this._connection.send(msg); +        return msgid; +    }, +    /***Function +    Start a room configuration. +    Parameters: +    (String) room - The multi-user chat room name. +    Returns: +    id - the unique id used to send the configuration request +    */ +    configure: function(room) { +        //send iq to start room configuration +        var config = $iq({to:room, +                          type: "get"}).c("query", +                                          {xmlns: Strophe.NS.MUC_OWNER}); +        var stanza = config.tree(); +        return this._connection.sendIQ(stanza, +                               function(){}, +                               function(){}); +    }, +    /***Function +    Cancel the room configuration +    Parameters: +    (String) room - The multi-user chat room name. +    Returns: +    id - the unique id used to cancel the configuration. +    */ +    cancelConfigure: function(room) { +        //send iq to start room configuration +        var config = $iq({to: room, +                          type: "set"}) +            .c("query", {xmlns: Strophe.NS.MUC_OWNER}) +            .c("x", {xmlns: "jabber:x:data", type: "cancel"}); +        var stanza = config.tree(); +        return this._connection.sendIQ(stanza, +                                       function(){}, +                                       function(){}); +    }, +    /***Function +    Save a room configuration. +    Parameters: +    (String) room - The multi-user chat room name. +    (Array) configarray - an array of form elements used to configure the room. +    Returns: +    id - the unique id used to save the configuration. +    */ +    saveConfiguration: function(room, configarray) { +        var config = $iq({to: room, +                          type: "set"}) +            .c("query", {xmlns: Strophe.NS.MUC_OWNER}) +            .c("x", {xmlns: "jabber:x:data", type: "submit"}); +        for (var i = 0; i >= configarray.length; i++) { +            config.cnode(configarray[i]); +        } +        var stanza = config.tree(); +        return this._connection.sendIQ(stanza, +                                       function(){}, +                                       function(){});         +    }, +    /***Function +    Parameters: +    (String) room - The multi-user chat room name. +    Returns: +    id - the unique id used to create the chat room. +    */ +    createInstantRoom: function(room) { +        var roomiq = $iq({to: room, +                          type: "set"}) +            .c("query", {xmlns: Strophe.NS.MUC_OWNER}) +            .c("x", {xmlns: "jabber:x:data", +                     type: "submit"}); +        return this._connection.sendIQ(roomiq.tree(), +                                       function() {}, +                                       function() {}); +    }, +    /*** +     Set the topic of the chat room. +     Parameters: +     (String) room - The multi-user chat room name. +     (String) topic - Topic message. +     */ +    setTopic: function(room, topic) { +        var msg = $msg({to: room, +                        from: this._connection.jid, +                        type: "groupchat"}) +            .c("subject", {xmlns: "jabber:client"}).t(topic); +        this._connection.send(msg.tree()); +    }, +    /***Function +    Changes the role and affiliation of a member of a MUC room. +    The modification can only be done by a room moderator. An error will be +    returned if the user doesn't have permission. +    Parameters: +    (String) room - The multi-user chat room name. +    (String) nick - The nick name of the user to modify. +    (String) role - The new role of the user. +    (String) affiliation - The new affiliation of the user. +    (String) reason - The reason for the change. +    Returns: +    iq - the id of the mode change request. +    */ +    modifyUser: function(room, nick, role, affiliation, reason) { +        var item_attrs = {nick: Strophe.escapeNode(nick)}; +        if (role !== null) +        { +            item_attrs.role = role; +        } +        if (affiliation !== null) +        { +            item_attrs.affiliation = affiliation; +        } +        var item = $build("item", item_attrs); +        if (reason !== null) +        { +            item.cnode(Strophe.xmlElement("reason", reason)); +        } +        var roomiq = $iq({to: room, +                          type: "set"}) +            .c("query", {xmlns: Strophe.NS.MUC_OWNER}).cnode(item.tree()); +        return this._connection.sendIQ(roomiq.tree(), +                                       function() {}, +                                       function() {}); +    }, +    /***Function +    Change the current users nick name. +    Parameters: +    (String) room - The multi-user chat room name. +    (String) user - The new nick name. +    */ +    changeNick: function(room, user) { +        var room_nick = this.test_append_nick(room, user); +        var presence = $pres({from: this._connection.jid, +                              to: room_nick}) +            .c("x",{xmlns: Strophe.NS.MUC}); +        this._connection.send(presence.tree()); +    }, +    /***Function +    List all chat room available on a server. +    Parameters: +    (String) server - name of chat server. +    (String) handle_cb - Function to call for room list return. +    */ +    listRooms: function(server, handle_cb) { +        var iq = $iq({to: server, +                      from: this._connection.jid, +                      type: "get"}) +            .c("query",{xmlns: Strophe.NS.DISCO_ITEMS});         +        this._connection.sendIQ(iq, handle_cb, function(){});         +    }, +    test_append_nick: function(room, nick) { +        var room_nick = room; +        if (nick)  +        { +            room_nick += "/" + Strophe.escapeNode(nick);  +        } +        return room_nick; +    } +});
\ No newline at end of file diff --git a/mod/beechat/views/default/js/strophe.muc.js.php b/mod/beechat/views/default/js/strophe.muc.js.php new file mode 100644 index 000000000..e10750d02 --- /dev/null +++ b/mod/beechat/views/default/js/strophe.muc.js.php @@ -0,0 +1,300 @@ +/* +Plugin to implement the MUC extension. http://xmpp.org/extensions/xep-0045.html +*/ +/* jslint configuration: */ +/* global document, window, setTimeout, clearTimeout, console, +    XMLHttpRequest, ActiveXObject, +    Base64, MD5, +    Strophe, $build, $msg, $iq, $pres  +*/ + +Strophe.addConnectionPlugin('muc', { +    _connection: null, +    // The plugin must have the init function +    /***Function +    Initialize the MUC plugin. Sets the correct connection object and +    extends the namesace. +    */ +    init: function(conn) { +        this._connection = conn; +        /* extend name space  +         *  NS.MUC - XMPP Multi-user chat namespace +         *              from XEP 45.   +         * +         */ +        Strophe.addNamespace('MUC_OWNER', Strophe.NS.MUC+"#owner"); +        Strophe.addNamespace('MUC_ADMIN', Strophe.NS.MUC+"#admin"); +    }, +    /***Function +    Join a multi-user chat room +    Parameters: +    (String) room - The multi-user chat room to join. +    (String) nick - The nickname to use in the chat room. Optional +    (Function) msg_handler_cb - The function call to handle messages from the +    specified chat room. +    (Function) pres_handler_cb - The function call back to handle presence +    in the chat room. +    (String) password - The optional password to use. (password protected +    rooms only) +    */ +    join: function(room, nick, msg_handler_cb, pres_handler_cb, password) { +        var room_nick = this.test_append_nick(room, nick);         +        var msg = $pres({from: this._connection.jid, +                         to: room_nick}) +            .c("x",{xmlns: Strophe.NS.MUC}); +        if (password) +        { +            var password_elem = Strophe.xmlElement("password",  +                                                   [], +                                                   password); +            msg.cnode(password_elem); +        } +        if (msg_handler_cb) +        { +            this._connection.addHandler(function(stanza) { +                var from = stanza.getAttribute('from'); +                var roomname = from.split("/"); +                // filter on room name +                if (roomname.length > 1 && roomname[0] == room) +                { +                    return msg_handler_cb(stanza); +                } +                else +                { +                    return true; +                } +            }, +                                        null, +                                        "message", +                                        null, +                                        null, +                                        null); +        } +        if (pres_handler_cb) +        { +            this._connection.addHandler(function(stanza) { +                var xquery = stanza.getElementsByTagName("x"); +                if (xquery.length > 0) +                { +                    //Handle only MUC user protocol +                    for (var i = 0; i < xquery.length; i++) +                    { +                        var xmlns = xquery[i].getAttribute("xmlns"); +                         +                        if (xmlns && xmlns.match(Strophe.NS.MUC)) +                        { +                            return pres_handler_cb(stanza); +                        } +                    } +                } +                return true;                 +            }, +                                        null, +                                        "presence", +                                        null, +                                        null, +                                        null); +        } +        this._connection.send(msg); +    }, +    /***Function +    Leave a multi-user chat room +    Parameters: +    (String) room - The multi-user chat room to leave. +    (String) nick - The nick name used in the room. +    (Function) handler_cb - Optional function to handle the successful leave. +    Returns: +    iqid - The unique id for the room leave. +    */ +    leave: function(room, nick, handler_cb) { +        var room_nick = this.test_append_nick(room, nick);         +        var presenceid = this._connection.getUniqueId(); +        var presence = $pres({type: "unavailable", +                              id: presenceid, +                              from: this._connection.jid, +                              to: room_nick}) +            .c("x",{xmlns: Strophe.NS.MUC}); +        this._connection.addHandler(handler_cb, +                                    null, +                                    "presence", +                                    null, +                                    presenceid, +                                    null); +        this._connection.send(presence); +        return presenceid; +    }, +    /***Function +    Parameters: +    (String) room - The multi-user chat room name. +    (String) nick - The nick name used in the chat room. +    (String) message - The message to send to the room. +    Returns: +    msgiq - the unique id used to send the message +    */ +    message: function(room, nick, message) { +        var room_nick = this.test_append_nick(room, nick);         +        var msgid = this._connection.getUniqueId(); +        var msg = $msg({to: room_nick, +                        from: this._connection.jid, +                        type: "groupchat", +                        id: msgid}).c("body", +                                      {xmlns: Strophe.NS.CLIENT}).t(message); +        msg.up().c("x", {xmlns: "jabber:x:event"}).c("composing"); +        this._connection.send(msg); +        return msgid; +    }, +    /***Function +    Start a room configuration. +    Parameters: +    (String) room - The multi-user chat room name. +    Returns: +    id - the unique id used to send the configuration request +    */ +    configure: function(room) { +        //send iq to start room configuration +        var config = $iq({to:room, +                          type: "get"}).c("query", +                                          {xmlns: Strophe.NS.MUC_OWNER}); +        var stanza = config.tree(); +        return this._connection.sendIQ(stanza, +                               function(){}, +                               function(){}); +    }, +    /***Function +    Cancel the room configuration +    Parameters: +    (String) room - The multi-user chat room name. +    Returns: +    id - the unique id used to cancel the configuration. +    */ +    cancelConfigure: function(room) { +        //send iq to start room configuration +        var config = $iq({to: room, +                          type: "set"}) +            .c("query", {xmlns: Strophe.NS.MUC_OWNER}) +            .c("x", {xmlns: "jabber:x:data", type: "cancel"}); +        var stanza = config.tree(); +        return this._connection.sendIQ(stanza, +                                       function(){}, +                                       function(){}); +    }, +    /***Function +    Save a room configuration. +    Parameters: +    (String) room - The multi-user chat room name. +    (Array) configarray - an array of form elements used to configure the room. +    Returns: +    id - the unique id used to save the configuration. +    */ +    saveConfiguration: function(room, configarray) { +        var config = $iq({to: room, +                          type: "set"}) +            .c("query", {xmlns: Strophe.NS.MUC_OWNER}) +            .c("x", {xmlns: "jabber:x:data", type: "submit"}); +        for (var i = 0; i >= configarray.length; i++) { +            config.cnode(configarray[i]); +        } +        var stanza = config.tree(); +        return this._connection.sendIQ(stanza, +                                       function(){}, +                                       function(){});         +    }, +    /***Function +    Parameters: +    (String) room - The multi-user chat room name. +    Returns: +    id - the unique id used to create the chat room. +    */ +    createInstantRoom: function(room) { +        var roomiq = $iq({to: room, +                          type: "set"}) +            .c("query", {xmlns: Strophe.NS.MUC_OWNER}) +            .c("x", {xmlns: "jabber:x:data", +                     type: "submit"}); +        return this._connection.sendIQ(roomiq.tree(), +                                       function() {}, +                                       function() {}); +    }, +    /*** +     Set the topic of the chat room. +     Parameters: +     (String) room - The multi-user chat room name. +     (String) topic - Topic message. +     */ +    setTopic: function(room, topic) { +        var msg = $msg({to: room, +                        from: this._connection.jid, +                        type: "groupchat"}) +            .c("subject", {xmlns: "jabber:client"}).t(topic); +        this._connection.send(msg.tree()); +    }, +    /***Function +    Changes the role and affiliation of a member of a MUC room. +    The modification can only be done by a room moderator. An error will be +    returned if the user doesn't have permission. +    Parameters: +    (String) room - The multi-user chat room name. +    (String) nick - The nick name of the user to modify. +    (String) role - The new role of the user. +    (String) affiliation - The new affiliation of the user. +    (String) reason - The reason for the change. +    Returns: +    iq - the id of the mode change request. +    */ +    modifyUser: function(room, nick, role, affiliation, reason) { +        var item_attrs = {nick: Strophe.escapeNode(nick)}; +        if (role !== null) +        { +            item_attrs.role = role; +        } +        if (affiliation !== null) +        { +            item_attrs.affiliation = affiliation; +        } +        var item = $build("item", item_attrs); +        if (reason !== null) +        { +            item.cnode(Strophe.xmlElement("reason", reason)); +        } +        var roomiq = $iq({to: room, +                          type: "set"}) +            .c("query", {xmlns: Strophe.NS.MUC_OWNER}).cnode(item.tree()); +        return this._connection.sendIQ(roomiq.tree(), +                                       function() {}, +                                       function() {}); +    }, +    /***Function +    Change the current users nick name. +    Parameters: +    (String) room - The multi-user chat room name. +    (String) user - The new nick name. +    */ +    changeNick: function(room, user) { +        var room_nick = this.test_append_nick(room, user); +        var presence = $pres({from: this._connection.jid, +                              to: room_nick}) +            .c("x",{xmlns: Strophe.NS.MUC}); +        this._connection.send(presence.tree()); +    }, +    /***Function +    List all chat room available on a server. +    Parameters: +    (String) server - name of chat server. +    (String) handle_cb - Function to call for room list return. +    */ +    listRooms: function(server, handle_cb) { +        var iq = $iq({to: server, +                      from: this._connection.jid, +                      type: "get"}) +            .c("query",{xmlns: Strophe.NS.DISCO_ITEMS});         +        this._connection.sendIQ(iq, handle_cb, function(){});         +    }, +    test_append_nick: function(room, nick) { +        var room_nick = room; +        if (nick)  +        { +            room_nick += "/" + Strophe.escapeNode(nick);  +        } +        return room_nick; +    } +}); diff --git a/mod/beechat/views/default/settings/beechat/edit.php b/mod/beechat/views/default/settings/beechat/edit.php new file mode 100755 index 000000000..ec4ab08de --- /dev/null +++ b/mod/beechat/views/default/settings/beechat/edit.php @@ -0,0 +1,31 @@ +<?php +/** + *	Barter Plugin + *	@package Barters + **/ +	$domain = elgg_get_plugin_setting("domain", "beechat"); +	//$group_domain = elgg_get_plugin_setting("groupdomain", "beechat"); +	$xmlrpc_ip = elgg_get_plugin_setting("xmlrpcip", "beechat"); +	$dbname = elgg_get_plugin_setting("dbname", "beechat"); +	$dbhost = elgg_get_plugin_setting("dbhost", "beechat"); +	$dbuser = elgg_get_plugin_setting("dbuser", "beechat"); +	$dbpassword = elgg_get_plugin_setting("dbpassword", "beechat"); +?> +<p> +	<?php echo elgg_echo('beechat:domain'); ?> +	<?php echo elgg_view('input/text', array('internalname' => 'params[domain]','value' => $domain)); ?> +	<!--<?php echo elgg_echo('beechat:groupdomain'); ?> +	<?php echo elgg_view('input/text', array('internalname' => 'params[groupdomain]','value' => $group_domain)); ?>--> +	<?php echo elgg_echo('beechat:xmlrpcip'); ?> +	<?php echo elgg_view('input/text', array('internalname' => 'params[xmlrpcip]','value' => $xmlrpc_ip)); ?> +	<?php echo elgg_echo('beechat:dbname'); ?> +	<?php echo elgg_view('input/text', array('internalname' => 'params[dbname]','value' => $dbname)); ?> +	<?php echo elgg_echo('beechat:dbhost'); ?> +	<?php echo elgg_view('input/text', array('internalname' => 'params[dbhost]','value' => $dbhost)); ?> +	<?php echo elgg_echo('beechat:dbuser'); ?> +	<?php echo elgg_view('input/text', array('internalname' => 'params[dbuser]','value' => $dbuser)); ?> +	<?php echo elgg_echo('beechat:dbpassword'); ?> +	<?php echo elgg_view('input/password', array('internalname' => 'params[dbpassword]','value' => $dbpassword)); ?> + +</p> + | 
