Alice
view release on metacpan or search on metacpan
share/static/alice.js view on Meta::CPAN
var args = update([0.01], arguments);
return this.delay.apply(this, args);
}
function wrap(wrapper) {
var __method = this;
return function() {
var a = update([__method.bind(this)], arguments);
return wrapper.apply(this, a);
}
}
function methodize() {
if (this._methodized) return this._methodized;
var __method = this;
return this._methodized = function() {
var a = update([this], arguments);
return __method.apply(null, a);
};
}
return {
argumentNames: argumentNames,
bind: bind,
bindAsEventListener: bindAsEventListener,
curry: curry,
delay: delay,
defer: defer,
wrap: wrap,
methodize: methodize
}
})());
(function(proto) {
function toISOString() {
return this.getUTCFullYear() + '-' +
(this.getUTCMonth() + 1).toPaddedString(2) + '-' +
this.getUTCDate().toPaddedString(2) + 'T' +
this.getUTCHours().toPaddedString(2) + ':' +
this.getUTCMinutes().toPaddedString(2) + ':' +
this.getUTCSeconds().toPaddedString(2) + 'Z';
}
function toJSON() {
return this.toISOString();
}
if (!proto.toISOString) proto.toISOString = toISOString;
if (!proto.toJSON) proto.toJSON = toJSON;
})(Date.prototype);
RegExp.prototype.match = RegExp.prototype.test;
RegExp.escape = function(str) {
return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
};
var PeriodicalExecuter = Class.create({
initialize: function(callback, frequency) {
this.callback = callback;
this.frequency = frequency;
this.currentlyExecuting = false;
this.registerCallback();
},
registerCallback: function() {
this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
},
execute: function() {
this.callback(this);
},
stop: function() {
if (!this.timer) return;
clearInterval(this.timer);
this.timer = null;
},
onTimerEvent: function() {
if (!this.currentlyExecuting) {
try {
this.currentlyExecuting = true;
this.execute();
this.currentlyExecuting = false;
} catch(e) {
this.currentlyExecuting = false;
throw e;
}
}
}
});
Object.extend(String, {
interpret: function(value) {
return value == null ? '' : String(value);
},
specialChar: {
'\b': '\\b',
'\t': '\\t',
'\n': '\\n',
'\f': '\\f',
'\r': '\\r',
'\\': '\\\\'
}
});
Object.extend(String.prototype, (function() {
var NATIVE_JSON_PARSE_SUPPORT = window.JSON &&
typeof JSON.parse === 'function' &&
JSON.parse('{"test": true}').test;
function prepareReplacement(replacement) {
if (Object.isFunction(replacement)) return replacement;
var template = new Template(replacement);
return function(match) { return template.evaluate(match) };
}
function gsub(pattern, replacement) {
var result = '', source = this, match;
replacement = prepareReplacement(replacement);
if (Object.isString(pattern))
pattern = RegExp.escape(pattern);
if (!(pattern.length || pattern.source)) {
replacement = replacement('');
return replacement + source.split('').join(replacement) + replacement;
}
while (source.length > 0) {
if (match = source.match(pattern)) {
result += source.slice(0, match.index);
result += String.interpret(replacement(match));
source = source.slice(match.index + match[0].length);
} else {
result += source, source = '';
}
}
return result;
}
function sub(pattern, replacement, count) {
replacement = prepareReplacement(replacement);
count = Object.isUndefined(count) ? 1 : count;
return this.gsub(pattern, function(match) {
if (--count < 0) return match[0];
return replacement(match);
});
}
function scan(pattern, iterator) {
this.gsub(pattern, iterator);
return String(this);
}
function truncate(length, truncation) {
length = length || 30;
truncation = Object.isUndefined(truncation) ? '...' : truncation;
return this.length > length ?
this.slice(0, length - truncation.length) + truncation : String(this);
}
function strip() {
return this.replace(/^\s+/, '').replace(/\s+$/, '');
}
function stripTags() {
return this.replace(/<\w+(\s+("[^"]*"|'[^']*'|[^>])+)?>|<\/\w+>/gi, '');
}
function stripScripts() {
return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
}
function extractScripts() {
var matchAll = new RegExp(Prototype.ScriptFragment, 'img'),
matchOne = new RegExp(Prototype.ScriptFragment, 'im');
return (this.match(matchAll) || []).map(function(scriptTag) {
return (scriptTag.match(matchOne) || ['', ''])[1];
});
}
function evalScripts() {
return this.extractScripts().map(function(script) { return eval(script) });
}
function escapeHTML() {
return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
}
function unescapeHTML() {
return this.stripTags().replace(/</g,'<').replace(/>/g,'>').replace(/&/g,'&');
}
function toQueryParams(separator) {
var match = this.strip().match(/([^?#]*)(#.*)?$/);
if (!match) return { };
return match[1].split(separator || '&').inject({ }, function(hash, pair) {
if ((pair = pair.split('='))[0]) {
var key = decodeURIComponent(pair.shift()),
value = pair.length > 1 ? pair.join('=') : pair[0];
if (value != undefined) value = decodeURIComponent(value);
if (key in hash) {
if (!Object.isArray(hash[key])) hash[key] = [hash[key]];
hash[key].push(value);
}
else hash[key] = value;
}
return hash;
});
}
function toArray() {
return this.split('');
}
function succ() {
return this.slice(0, this.length - 1) +
String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
}
function times(count) {
return count < 1 ? '' : new Array(count + 1).join(this);
}
function camelize() {
return this.replace(/-+(.)?/g, function(match, chr) {
return chr ? chr.toUpperCase() : '';
});
}
function capitalize() {
return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
}
function underscore() {
return this.replace(/::/g, '/')
.replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2')
.replace(/([a-z\d])([A-Z])/g, '$1_$2')
.replace(/-/g, '_')
.toLowerCase();
}
function dasherize() {
return this.replace(/_/g, '-');
}
function inspect(useDoubleQuotes) {
var escapedString = this.replace(/[\x00-\x1f\\]/g, function(character) {
if (character in String.specialChar) {
return String.specialChar[character];
}
return '\\u00' + character.charCodeAt().toPaddedString(2, 16);
});
if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
return "'" + escapedString.replace(/'/g, '\\\'') + "'";
}
function unfilterJSON(filter) {
return this.replace(filter || Prototype.JSONFilter, '$1');
}
function isJSON() {
var str = this;
if (str.blank()) return false;
str = str.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@');
str = str.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']');
str = str.replace(/(?:^|:|,)(?:\s*\[)+/g, '');
return (/^[\],:{}\s]*$/).test(str);
}
function evalJSON(sanitize) {
var json = this.unfilterJSON(),
cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
if (cx.test(json)) {
json = json.replace(cx, function (a) {
return '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
});
}
try {
if (!sanitize || json.isJSON()) return eval('(' + json + ')');
} catch (e) { }
throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
}
function parseJSON() {
var json = this.unfilterJSON();
return JSON.parse(json);
}
function include(pattern) {
return this.indexOf(pattern) > -1;
}
function startsWith(pattern) {
return this.lastIndexOf(pattern, 0) === 0;
}
function endsWith(pattern) {
var d = this.length - pattern.length;
return d >= 0 && this.indexOf(pattern, d) === d;
}
function empty() {
return this == '';
}
function blank() {
return /^\s*$/.test(this);
}
function interpolate(object, pattern) {
return new Template(this, pattern).evaluate(object);
}
return {
gsub: gsub,
sub: sub,
scan: scan,
truncate: truncate,
strip: String.prototype.trim || strip,
stripTags: stripTags,
stripScripts: stripScripts,
extractScripts: extractScripts,
evalScripts: evalScripts,
escapeHTML: escapeHTML,
unescapeHTML: unescapeHTML,
toQueryParams: toQueryParams,
parseQuery: toQueryParams,
toArray: toArray,
succ: succ,
times: times,
camelize: camelize,
capitalize: capitalize,
underscore: underscore,
dasherize: dasherize,
inspect: inspect,
unfilterJSON: unfilterJSON,
isJSON: isJSON,
evalJSON: NATIVE_JSON_PARSE_SUPPORT ? parseJSON : evalJSON,
include: include,
startsWith: startsWith,
endsWith: endsWith,
empty: empty,
blank: blank,
interpolate: interpolate
};
})());
var Template = Class.create({
initialize: function(template, pattern) {
this.template = template.toString();
this.pattern = pattern || Template.Pattern;
},
evaluate: function(object) {
if (object && Object.isFunction(object.toTemplateReplacements))
object = object.toTemplateReplacements();
return this.template.gsub(this.pattern, function(match) {
if (object == null) return (match[1] + '');
var before = match[1] || '';
if (before == '\\') return match[2];
var ctx = object, expr = match[3],
pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/;
match = pattern.exec(expr);
if (match == null) return before;
while (match != null) {
var comp = match[1].startsWith('[') ? match[2].replace(/\\\\]/g, ']') : match[1];
ctx = ctx[comp];
if (null == ctx || '' == match[3]) break;
expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);
match = pattern.exec(expr);
}
return before + String.interpret(ctx);
});
}
});
Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
var $break = { };
share/static/alice.js view on Meta::CPAN
if (number < 1) return array;
while ((index += number) < array.length)
slices.push(array.slice(index, index+number));
return slices.collect(iterator, context);
}
function all(iterator, context) {
iterator = iterator || Prototype.K;
var result = true;
this.each(function(value, index) {
result = result && !!iterator.call(context, value, index);
if (!result) throw $break;
});
return result;
}
function any(iterator, context) {
iterator = iterator || Prototype.K;
var result = false;
this.each(function(value, index) {
if (result = !!iterator.call(context, value, index))
throw $break;
});
return result;
}
function collect(iterator, context) {
iterator = iterator || Prototype.K;
var results = [];
this.each(function(value, index) {
results.push(iterator.call(context, value, index));
});
return results;
}
function detect(iterator, context) {
var result;
this.each(function(value, index) {
if (iterator.call(context, value, index)) {
result = value;
throw $break;
}
});
return result;
}
function findAll(iterator, context) {
var results = [];
this.each(function(value, index) {
if (iterator.call(context, value, index))
results.push(value);
});
return results;
}
function grep(filter, iterator, context) {
iterator = iterator || Prototype.K;
var results = [];
if (Object.isString(filter))
filter = new RegExp(RegExp.escape(filter));
this.each(function(value, index) {
if (filter.match(value))
results.push(iterator.call(context, value, index));
});
return results;
}
function include(object) {
if (Object.isFunction(this.indexOf))
if (this.indexOf(object) != -1) return true;
var found = false;
this.each(function(value) {
if (value == object) {
found = true;
throw $break;
}
});
return found;
}
function inGroupsOf(number, fillWith) {
fillWith = Object.isUndefined(fillWith) ? null : fillWith;
return this.eachSlice(number, function(slice) {
while(slice.length < number) slice.push(fillWith);
return slice;
});
}
function inject(memo, iterator, context) {
this.each(function(value, index) {
memo = iterator.call(context, memo, value, index);
});
return memo;
}
function invoke(method) {
var args = $A(arguments).slice(1);
return this.map(function(value) {
return value[method].apply(value, args);
});
}
function max(iterator, context) {
iterator = iterator || Prototype.K;
var result;
this.each(function(value, index) {
value = iterator.call(context, value, index);
if (result == null || value >= result)
result = value;
});
return result;
}
function min(iterator, context) {
iterator = iterator || Prototype.K;
var result;
this.each(function(value, index) {
value = iterator.call(context, value, index);
share/static/alice.js view on Meta::CPAN
['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
Ajax.Response = Class.create({
initialize: function(request){
this.request = request;
var transport = this.transport = request.transport,
readyState = this.readyState = transport.readyState;
if ((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) {
this.status = this.getStatus();
this.statusText = this.getStatusText();
this.responseText = String.interpret(transport.responseText);
this.headerJSON = this._getHeaderJSON();
}
if (readyState == 4) {
var xml = transport.responseXML;
this.responseXML = Object.isUndefined(xml) ? null : xml;
this.responseJSON = this._getResponseJSON();
}
},
status: 0,
statusText: '',
getStatus: Ajax.Request.prototype.getStatus,
getStatusText: function() {
try {
return this.transport.statusText || '';
} catch (e) { return '' }
},
getHeader: Ajax.Request.prototype.getHeader,
getAllHeaders: function() {
try {
return this.getAllResponseHeaders();
} catch (e) { return null }
},
getResponseHeader: function(name) {
return this.transport.getResponseHeader(name);
},
getAllResponseHeaders: function() {
return this.transport.getAllResponseHeaders();
},
_getHeaderJSON: function() {
var json = this.getHeader('X-JSON');
if (!json) return null;
json = decodeURIComponent(escape(json));
try {
return json.evalJSON(this.request.options.sanitizeJSON ||
!this.request.isSameOrigin());
} catch (e) {
this.request.dispatchException(e);
}
},
_getResponseJSON: function() {
var options = this.request.options;
if (!options.evalJSON || (options.evalJSON != 'force' &&
!(this.getHeader('Content-type') || '').include('application/json')) ||
this.responseText.blank())
return null;
try {
return this.responseText.evalJSON(options.sanitizeJSON ||
!this.request.isSameOrigin());
} catch (e) {
this.request.dispatchException(e);
}
}
});
Ajax.Updater = Class.create(Ajax.Request, {
initialize: function($super, container, url, options) {
this.container = {
success: (container.success || container),
failure: (container.failure || (container.success ? null : container))
};
options = Object.clone(options);
var onComplete = options.onComplete;
options.onComplete = (function(response, json) {
this.updateContent(response.responseText);
if (Object.isFunction(onComplete)) onComplete(response, json);
}).bind(this);
$super(url, options);
},
updateContent: function(responseText) {
var receiver = this.container[this.success() ? 'success' : 'failure'],
options = this.options;
if (!options.evalScripts) responseText = responseText.stripScripts();
if (receiver = $(receiver)) {
if (options.insertion) {
if (Object.isString(options.insertion)) {
var insertion = { }; insertion[options.insertion] = responseText;
receiver.insert(insertion);
}
else options.insertion(receiver, responseText);
}
else receiver.update(responseText);
}
}
});
Ajax.PeriodicalUpdater = Class.create(Ajax.Base, {
share/static/alice.js view on Meta::CPAN
'target':document,
'keycode':false
}
if(!opt) opt = default_options;
else {
for(var dfo in default_options) {
if(typeof opt[dfo] == 'undefined') opt[dfo] = default_options[dfo];
}
}
var ele = opt.target;
if(typeof opt.target == 'string') ele = document.getElementById(opt.target);
var ths = this;
shortcut_combination = shortcut_combination.toLowerCase();
var func = function(e) {
e = e || window.event;
if(opt['disable_in_input']) { //Don't enable shortcut keys in Input, Textarea fields
var element;
if(e.target) element=e.target;
else if(e.srcElement) element=e.srcElement;
if(element.nodeType==3) element=element.parentNode;
if(element.tagName == 'INPUT' || element.tagName == 'TEXTAREA') return;
}
if (e.keyCode) code = e.keyCode;
else if (e.which) code = e.which;
var character = String.fromCharCode(code).toLowerCase();
if(code == 188) character=","; //If the user presses , when the type is onkeydown
if(code == 190) character="."; //If the user presses , when the type is onkeydown
var keys = shortcut_combination.split("+");
var kp = 0;
var shift_nums = {
"`":"~",
"1":"!",
"2":"@",
"3":"#",
"4":"$",
"5":"%",
"6":"^",
"7":"&",
"8":"*",
"9":"(",
"0":")",
"-":"_",
"=":"+",
";":":",
"'":"\"",
",":"<",
".":">",
"/":"?",
"\\":"|"
}
var special_keys = {
'esc':27,
'escape':27,
'tab':9,
'space':32,
'return':13,
'enter':13,
'backspace':8,
'scrolllock':145,
'scroll_lock':145,
'scroll':145,
'capslock':20,
'caps_lock':20,
'caps':20,
'numlock':144,
'num_lock':144,
'num':144,
'pause':19,
'break':19,
'insert':45,
'home':36,
'delete':46,
'end':35,
'pageup':33,
'page_up':33,
'pu':33,
'pagedown':34,
'page_down':34,
'pd':34,
'left':37,
'up':38,
'right':39,
'down':40,
'f1':112,
'f2':113,
'f3':114,
'f4':115,
'f5':116,
'f6':117,
'f7':118,
'f8':119,
'f9':120,
'f10':121,
'f11':122,
'f12':123
}
var modifiers = {
shift: { wanted:false, pressed:false},
ctrl : { wanted:false, pressed:false},
alt : { wanted:false, pressed:false},
meta : { wanted:false, pressed:false} //Meta is Mac specific
};
if(e.ctrlKey) modifiers.ctrl.pressed = true;
if(e.shiftKey) modifiers.shift.pressed = true;
share/static/alice.js view on Meta::CPAN
/**
* Test if the browser is running flash lite.
* @return {boolean} True if flash lite is running, false otherwise.
*/
WebSocket.__isFlashLite = function() {
if (!window.navigator || !window.navigator.mimeTypes) {
return false;
}
var mimeType = window.navigator.mimeTypes["application/x-shockwave-flash"];
if (!mimeType || !mimeType.enabledPlugin || !mimeType.enabledPlugin.filename) {
return false;
}
return mimeType.enabledPlugin.filename.match(/flashlite/i) ? true : false;
};
if (!window.WEB_SOCKET_DISABLE_AUTO_INITIALIZATION) {
if (window.addEventListener) {
window.addEventListener("load", function(){
WebSocket.__initialize();
}, false);
} else {
window.attachEvent("onload", function(){
WebSocket.__initialize();
});
}
}
})();
var Alice = { };
Object.extend(Alice, {
RE: {
img: /^http[^\s]*\.(?:jpe?g|gif|png|bmp|svg)[^\/]*$/i,
audio: /^http[^\s]*\.(?:wav|mp3|ogg|aiff?|m4[ar])[^\/]*$/i,
url: /(https?:\/\/[^\s<"]*)/ig
},
cleanupCopy: function(node) {
if (!node.select("li.message").length) return;
var lines = [];
node.select("li.message").each(function(line) {
var left = line.down("div.left span.nick");
var message = line.down("div.msg");
var clean = [];
if (left) {
var nick = left.innerHTML.stripTags();
nick = nick.replace(/^\s+/, "");
nick = nick.replace(/\s+$/, "");
clean.push("<"+nick+">");
}
if (message) {
var body = message.innerHTML.stripTags();
body = body.replace(/^\s+/, "");
body = body.replace(/\s+$/, "");
clean.push(body);
}
if (clean.length) lines.push(
clean.join(" ").replace(/\n/g, "").escapeHTML());
});
node.update(lines.join("<br>"));
node.cleanWhitespace();
},
epochToLocal: function(epoch, format) {
var date = new Date(parseInt(epoch) * 1000);
if (!date) return epoch;
var hours = date.getHours();
if (format == "12") {
var ap;
if (hours >= 12) {
if (hours > 12) hours -= 12;
ap = "p";
} else {
ap = "a"
}
return sprintf("%d:%02d%s", hours, date.getMinutes(), ap);
}
return sprintf("%02d:%02d", hours, date.getMinutes());
},
makeLinksClickable: function(elem) {
var children = elem.childNodes;
var length = children.length;
for (var i=0; i < length; i++) {
var node = children[i];
if (node.nodeName != "#text") {
Alice.makeLinksClickable(node);
}
else if (node.nodeValue.match(Alice.RE.url)) {
var span = new Element("SPAN");
span.innerHTML = node.nodeValue.escapeHTML().replace(
Alice.RE.url, '<a href="$1" target="_blank" rel="noreferrer">$1</a>');
node.parentNode.replaceChild(span, node);
}
}
},
growlNotify: function(message) {
if (window.fluid) {
window.fluid.showGrowlNotification({
title: message.subject,
description: message.body,
priority: 1,
sticky: false,
identifier: message.msgid
});
}
else if (window.webkitNotifications) {
if (window.webkitNotifications.checkPermission() == 0) {
var popup = window.webkitNotifications.createNotification(
"http://static.usealice.org/image/alice.png",
message.subject,
message.body
);
popup.ondisplay = function() {
setTimeout(function () {popup.cancel();}, 5000);
};
popup.show();
}
}
},
isSpecialKey: function(keyCode) {
var special_keys = [
16,27,9,32,13,8,145,20,144,19,45,36,46,35,33,34,37,38,39,
40,17,18,91,112,113,114,115,116,117,118,119,120,121,122,123,
224
];
return special_keys.indexOf(keyCode) > -1;
},
playAudio: function(image, audio) {
image.src = '/static/image/pause.png';
if (! audio) {
var url = image.nextSibling.href;
audio = new Audio(url);
audio.addEventListener('ended', function () {
image.src = '/static/image/play.png';
image.onclick = function () { Alice.playAudio(image, audio) };
});
}
audio.play();
image.onclick = function() {
audio.pause();
this.src = '/static/image/play.png';
this.onclick = function () { Alice.playAudio(this, audio) };
};
},
joinChannel: function() {
var network = $('join_network').value;
var channel = $('join_channel').value;
if (!network || !channel) {
alert("Must select a channel and network!");
return;
}
var win = alice.activeWindow();
alice.connection.sendMessage({
source: win.id,
msg: "/join -"+network+" "+channel
});
alice.input.disabled = false;
$('join').remove();
},
tabsets: {
addSet: function () {
var name = prompt("Please enter a name for this tab set.");
if (name && !Alice.tabsets.hasTabset(name)) {
Alice.tabsets.clearActive();
$('sets').insert('<li class="active">'+name.escapeHTML()+'</li>');
var list = $('empty_tabset').clone(true).addClassName('active').show();
list.id = null;
$('tabset_data').insert(list);
}
else {
alert("Invalid tab set name.");
}
},
hasTabset: function (name) {
var sets = $$('#sets li');
for (var i=0; i < sets.length; i++) {
if (sets[i].innerHTML == name) {
return true;
}
}
return false;
},
submit: function (params) {
new Ajax.Request("/savetabsets", {
method: "post",
parameters: Object.toQueryString(params),
onSuccess: function(transport){
$('tabset_menu').replace(transport.responseText);
Alice.tabsets.remove()
}
});
return false;
},
params: function () {
var values = Alice.tabsets.values();
return Alice.tabsets.sets().inject({}, function(acc, set, index) {
acc[set] = values[index];
return acc;
});
},
sets: function () {
if (!$('sets')) return [];
return $('sets').select('li').map(function(li) {return li.innerHTML.unescapeHTML()});
},
values: function () {
if (!$('tabset_data')) return [];
return $$('#tabset_data ul').map(function(ul) {
var windows = ul.select('input').filter(function(input) {
return input.checked;
}).map(function(input){return input.name});
return windows.length ? windows : 'empty';
});
},
remove: function () {
alice.input.disabled = false;
$('tabsets').remove();
},
clearActive: function () {
$('tabset_data').select('.active').invoke('removeClassName', 'active');
$('sets').select('.active').invoke('removeClassName', 'active');
},
removeSet: function () {
$('tabsets').down('.active').remove();
$('tabset_data').down('.active').remove();
},
focusIndex: function (i) {
Alice.tabsets.clearActive();
$('tabset_data').select('ul')[i].addClassName('active');
$('sets').select('li')[i].addClassName('active');
},
focusSet: function (e) {
var li = e.findElement('li');
if (li) {
Alice.tabsets.focusIndex(li.previousSiblings().length);
}
},
},
prefs: {
addHighlight: function (alias) {
var channel = prompt("Enter a word to highlight.");
if (channel)
$('highlights').insert("<option value=\""+channel+"\">"+channel+"</option>");
return false;
},
removeHighlights: function (alias) {
$A($('highlights').options).each(function (option) {
if (option.selected) option.remove()});
return false;
},
addNick: function (nick) {
var nick = prompt("Enter a nick.");
if (nick)
$('monospace_nicks').insert("<option value=\""+nick+"\">"+nick+"</option>");
share/static/alice.js view on Meta::CPAN
setTimeout(function(){
this.windows().invoke("updateTabLayout");
this.activeWindow().shiftTab();
}.bind(this), 100);
}.bind(this)
});
},
addMissed: function() {
if (!window.fluid) return;
window.fluid.dockBadge ? window.fluid.dockBadge++ :
window.fluid.dockBadge = 1;
},
clearMissed: function() {
if (!window.fluid) return;
window.fluid.dockBadge = "";
},
ready: function() {
this.freeze();
setTimeout(this.updateOverflowMenus.bind(this), 1000);
this.fetchOembeds(function() {
this.connection.connect(function() {
this.focusHash() || this.activeWindow().focus();
}.bind(this));
}.bind(this));
},
log: function () {
var win = this.activeWindow();
for (var i=0; i < arguments.length; i++) {
if (window.console && window.console.log) {
console.log(arguments[i]);
}
if (this.options.debug == "true") {
if (win) {
win.addMessage({
html: '<li class="message monospace"><div class="left">console</div><div class="msg">'+arguments[i].toString()+'</div></li>'
});
}
}
}
},
msgid: function() {
var ids = this.windows().map(function(w){return w.msgid});
return Math.max.apply(Math, ids);
},
setSource: function(id) {
$('source').value = id;
},
showSet: function(name) {
var ids = this.tabsets[name];
if (ids) {
var elem = $('tabset_menu').select('li').find(function(li) {
return li.innerHTML.unescapeHTML() == name;
});
elem.up('ul').select('li').invoke('removeClassName', 'selectedset');
elem.addClassName('selectedset');
this.windows().each(function(win) {
ids.indexOf(win.id) >= 0 || win.type == "privmsg" ? win.show() : win.hide();
});
this.selectSet(name);
var active = this.activeWindow();
if (!active.visible) {
active = this.nextWindow();
}
if (active) active.shiftTab();
setTimeout(this.updateOverflowMenus.bind(this), 2000);
}
},
selectSet: function(name) {
var hash = window.location.hash;
hash = hash.replace(/^[^\/]*/, name);
window.location.hash = hash;
window.location = window.location.toString();
this.selectedSet = name;
},
clearSet: function(elem) {
elem.up('ul').select('li').invoke('removeClassName', 'selectedset');
elem.addClassName('selectedset');
this.windows().invoke("show");
this.selectSet('');
this.updateOverflowMenus();
this.activeWindow().shiftTab();
},
currentSetContains: function(win) {
var set = this.selectedSet;
if (win.type == "channel" && set && this.tabsets[set]) {
return (this.tabsets[set].indexOf(win.id) >= 0);
}
return true;
},
displayTopic: function(new_topic) {
this.topic.update(new_topic || "no topic set");
Alice.makeLinksClickable(this.topic);
},
displayNicks: function(nicks) {
this.nicklist.innerHTML = nicks.sort(function(a, b) {
a = a.toLowerCase();
b = b.toLowerCase();
if (a > b)
return 1
if (a < b)
return -1
return 0;
}).map(function(nick) {
return '<li><a>'+nick.escapeHTML()+'</a></li>';
}).join("");
},
toggleNicklist: function() {
var windows = $('windows');
var win = this.activeWindow();
var position = win.captureScrollPosition();
if (windows.hasClassName('nicklist'))
windows.removeClassName('nicklist');
else
windows.addClassName('nicklist');
win.scrollToPosition(position);
},
setupNicklist: function() {
this.nicklist.observe("click", function(e) {
var li = e.findElement('a');
if (li) {
var nick = a.innerHTML;
this.connection.requestWindow(nick, this.activeWindow().id);
}
}.bind(this));
},
setupTopic: function() {
this.topic.observe(this.supportsTouch ? "touchstart" : "click", function(e) {
if (this.supportsTouch) e.stop();
if (this.topic.getStyle("height") == this.topic_height) {
this.topic.setStyle({height: "auto"});
} else {
this.topic.setStyle({height: this.topic_height});
}
}.bind(this));
},
setupMenus: function() {
var click = this.supportsTouch ? "touchend" : "mouseup";
$('join_button').observe(click, function (e) {
e.stop();
this.toggleJoin();
}.bind(this));
$('config_menu').on(click, ".dropdown li", function(e,li) {
e.stop();
var text = li.textContent;
if (text.match(/Help/)) {
this.toggleHelp();
} else if (text.match(/Preferences/)) {
this.togglePrefs();
} else if (text.match(/Connections/)) {
this.toggleConfig();
}
$$('.dropdown.open').invoke("removeClassName", "open");
}.bind(this));
$('tabset_dropdown').on(click, ".dropdown li span", function(e,li) {
e.stop();
var name = li.innerHTML.unescapeHTML();
if (name == "Edit Sets")
this.toggleTabsets();
else if (name == "All tabs")
this.clearSet(li);
else if (this.tabsets[name])
this.showSet(name);
$$('.dropdown.open').invoke("removeClassName", "open");
}.bind(this));
['tab_menu_left', 'tab_menu_right'].each(function(side) {
$(side).on(click, ".dropdown li", function(e, li) {
e.stop();
if (li.getAttribute("rel")) {
$(side).removeClassName("open");
var win = this.getWindow(li.getAttribute("rel"));
if (win) win.focus();
}
}.bind(this));
}.bind(this));
},
baseFilters: function() {
return [
function(li, win) {
Alice.makeLinksClickable(li.down("div.msg"));
},
function(li, win) {
if (li.hasClassName("avatar")) {
if (this.options.avatars == "show") {
var avatar = li.getAttribute("avatar");
if (avatar)
li.down("a.nick").insert('<img src="'+alice.options.image_prefix+avatar+'" />');
}
else {
li.removeClassName("avatar");
}
}
},
function(li, win) {
if (li.hasClassName("consecutive")) {
var prev = li.previous();
if (!prev) return;
if (prev && prev.hasClassName("avatar") && !prev.hasClassName("consecutive"))
prev.down('div.msg').setStyle({minHeight: '0px'});
if (prev && prev.hasClassName("monospaced"))
prev.down('div.msg').setStyle({paddingBottom: '0px'});
}
},
function(li, win) {
var stamp = li.down('.timestamp');
if (!stamp) return;
var remove = false;
var seconds = stamp.innerHTML.strip();
if (li.hasClassName("message")) {
var time = new Date(seconds * 1000);
var diff = (time - win.lasttimestamp) / 1000;
remove = !(diff >= 300 || (diff > 60 && time.getMinutes() % 5 == 0));
if (!remove) win.lasttimestamp = time;
}
if (remove) {
stamp.remove();
}
else {
stamp.update(Alice.epochToLocal(seconds, this.options.timeformat));
stamp.style.opacity = 1;
}
},
function(li, win) {
if (!this.overlayVisible || !li.hasClassName("avatar")) return;
var nick = li.down('span.nick');
if (nick) nick.style.opacity = 1;
},
function(li, win) {
if (win.bulk_insert) return;
if (li.hasClassName("message") && !win.active && win.title != "info") {
if (li.hasClassName("highlight") || win.type == "privmsg")
win.markUnread("highlight");
else if (!li.hasClassName("self"))
win.markUnread();
}
},
function(li, win) {
if (this.options.alerts != "show" && this.options.audio != "show") return;
if (this.isFocused || win.bulk_insert || li.hasClassName("self")) return;
if (li.hasClassName("highlight") || win.type == "privmsg") {
var prefix = "";
if (win.type != "privmsg")
prefix = li.down("span.nick").innerHTML.stripTags().unescapeHTML() + " in ";
var message = {
body: li.down(".msg").innerHTML.stripTags().unescapeHTML(),
subject: prefix + win.title.stripTags().unescapeHTML()
};
var time = (new Date()).getTime();
if (time - this.lastnotify > 5000) {
this.lastnotify = time;
if (this.options.alerts == "show")
Alice.growlNotify(message);
if (this.options.audio == "show") {
this.beep.currentTime = 0;
this.beep.play();
}
}
this.addMissed();
}
}
];
},
toggleOverlay: function () {
this.overlayVisible = !this.overlayVisible;
var opacity = this.overlayVisible ? 1 : 0;
$$("li.avatar span.nick").each(function(span){
span.style.opacity = opacity;
});
}
});
Alice.Connection = {
gotoLogin: function() {
window.location = "/login";
},
connect: function(cb) {
if (this.reconnect_count > 3) {
this.aborting = true;
this.changeStatus("ok");
if (this.type == "websocket") {
this.application.activeWindow().showAlert("WebSocket connection failed, falling back...");
this.application.connection = new Alice.Connection.XHR(this.application);
this.application.connection.connect();
return;
}
this.application.activeWindow().showAlert("Alice server is not responding (<a href='javascript:alice.connection.reconnect()'>reconnect</a>)");
return;
}
this.pings = [];
this.closeConnection();
this.len = 0;
this.reconnect_count++;
this.changeStatus("loading");
this._connect(cb);
},
changeStatus: function(classname) {
$('connection_status').className = classname;
},
share/static/alice.js view on Meta::CPAN
this.application.displayTopic(this.topic);
document.title = this.title;
return this;
},
setWindowHash: function () {
var new_hash = "#" + this.application.selectedSet + this.hashtag;
if (new_hash != window.location.hash) {
window.location.hash = encodeURI(new_hash);
window.location = window.location.toString();
}
},
markRead: function () {
this.tab.removeClassName("unread");
this.tab.removeClassName("highlight");
this.statuses = [];
this.application.unHighlightChannelSelect(this.id);
},
markUnread: function(classname) {
var classes = ["unread"];
if (classname) classes.push(classname);
classes.each(function(c){this.tab.addClassName(c)}.bind(this));
this.application.highlightChannelSelect(this.id, classes);
this.statuses = classes;
},
disable: function () {
this.markRead();
this.tab.addClassName('disabled');
},
enable: function () {
this.tab.removeClassName('disabled');
},
close: function(event) {
this.tab.remove();
this.element.remove();
this.application.removeWindow(this);
},
showHappyAlert: function (message) {
this.messages.insert(
"<li class='event happynotice'><div class='msg'>"+message+"</div></li>"
);
this.scrollToPosition(0);
},
showAlert: function (message) {
this.messages.insert(
"<li class='event notice'><div class='msg'>"+message+"</div></li>"
);
this.scrollToPosition(0);
},
announce: function (message) {
message = message.escapeHTML();
this.messages.insert(
"<li class='message monospaced announce'><div class='msg'>"+message+"</div></li>"
);
this.scrollToPosition(0);
},
trimMessages: function() {
this.messages.select("li").reverse().slice(this.messageLimit).invoke("remove");
},
addChunk: function(chunk) {
if (chunk.nicks) this.updateNicks(chunk.nicks);
clearTimeout(this.scrollListener);
if (chunk.range.length == 0) {
this.scrollBackEmpty = true;
this.tab.removeClassName("loading");
return;
}
var position = this.captureScrollPosition();
if (chunk['range'][0] > this.msgid) {
this.messages.insert({"bottom": chunk['html']});
this.trimMessages();
this.msgid = chunk['range'][1];
}
else {
this.bulk_insert = true;
this.messages.insert({"top": chunk['html']});
}
this.messages.select("li:not(.filtered)").each(function (li) {
this.application.applyFilters(li, this);
}.bind(this));
this.bulk_insert = false;
this.scrollToPosition(position);
setTimeout(function(){this.removeClassName("loading")}.bind(this.tab), 1000);
this.scrollListener = setTimeout(this.checkScrollBack.bind(this), 1000);
},
addMessage: function(message) {
if (!message.html || message.msgid <= this.msgid) return;
if (message.msgid) this.msgid = message.msgid;
if (message.nicks) this.updateNicks(message.nicks);
var position = this.captureScrollPosition();
this.messages.insert(message.html);
this.trimMessages();
this.scrollToPosition(position);
var li = this.messages.select("li").last();
this.application.applyFilters(li, this);
this.scrollToPosition(position);
share/static/alice.js view on Meta::CPAN
fontFamily: this.element.getStyle("fontFamily"),
fontSize: this.element.getStyle("fontSize"),
lineHeight: this.element.getStyle("lineHeight"),
whiteSpace: "pre-wrap",
wordWrap: "break-word"
});
if (this.editor) element.addClassName("editor");
var value = this.getValue();
element.update(value.replace(/\n$/, "\n\n").replace("\n", "<br>"));
$(document.body).insert(element);
var height = element.getHeight();
element.remove();
return height;
},
canContentEditable: function() {
var element = new Element("div", {contentEditable: "true"});
return ! (element.contentEditable == null || this.application.isMobile || Prototype.Browser.IE);
},
updateRange: function (e) {
var selection = window.getSelection();
if (selection.rangeCount > 0) {
var range = selection.getRangeAt(0);
this.range = range;
}
},
pasteHandler: function(e) {
if (!e.clipboardData) return;
var items = e.clipboardData.items;
if (items) {
var output = "";
for (var i=0; i < items.length; i++) {
var blob = items[i].getAsFile();
if (blob && blob.type.match(/image/)) {
e.stop();
var fd = new FormData();
fd.append("image", blob);
fd.append("key", "f1f60f1650a07bfe5f402f35205dffd4");
var xhr = new XMLHttpRequest();
xhr.open("POST", "http://api.imgur.com/2/upload.json");
xhr.onload = function() {
var url = xhr.responseText.evalJSON();
this.editor.insertHTML(url.upload.links.original);
this.updateRange();
}.bind(this);
xhr.send(fd);
return;
}
}
}
var text = e.clipboardData.getData("Text");
if (text) {
e.preventDefault();
text = text.escapeHTML().replace(/\n+/g, "<br>\n");
this.editor.insertHTML(text);
this.updateRange();
return;
}
var url = e.clipboardData.getData("URL");
if (url) {
e.preventDefault();
this.editor.insertHTML(url);
this.updateRange();
return;
}
}
});
Alice.Keyboard = Class.create({
initialize: function(application) {
this.application = application;
this.isMac = navigator.platform.match(/mac/i);
this.lastCycle = 0;
this.cycleDelay = 300;
this.enable();
if (!this.application.isMobile) {
this.shortcut("Cmd+C", { propagate: true });
this.shortcut("Ctrl+C", { propagate: true });
this.shortcut("Cmd+B");
this.shortcut("Cmd+I");
this.shortcut("Cmd+Shift+U");
this.shortcut("Opt+Up");
this.shortcut("Opt+Down");
this.shortcut("Cmd+Shift+M");
this.shortcut("Cmd+Shift+J");
this.shortcut("Cmd+Shift+K");
this.shortcut("Cmd+K");
this.shortcut("Cmd+Shift+Left");
this.shortcut("Cmd+Shift+Right");
this.shortcut("Cmd+Shift+H");
this.shortcut("Cmd+Shift+L");
this.shortcut("Cmd+U");
this.shortcut("Esc");
this.shortcut("Cmd", { propagate: true });
this.shortcut("Tab", { propagate: true });
this.shortcut("Shift+Tab", { propagate: true });
for (var i = 0; i < 10; i++) {
this.shortcut("Cmd+"+i);
if (!this.isMac) this.shortcut("Opt+"+i);
}
}
this.shortcut("Enter");
},
shortcut: function(name, options) {
var meta = this.isMac ? "Meta" : "Ctrl";
var keystroke = name.replace("Cmd", meta).replace("Opt", "Alt"),
method = "on" + name.replace(/\+/g, "");
share/static/alice.js view on Meta::CPAN
var selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(range);
},
next: function() {
if (!this.matches.length) return;
if (++this.matchIndex == this.matches.length) this.matchIndex = 0;
this.complete();
},
prev: function() {
if (!this.matches.length) return;
if (--this.matchIndex <= 0) this.matchIndex = this.matches.length - 1;
this.complete();
},
complete: function() {
var match = this.matches[this.matchIndex];
match += this.leftOffset == 0 ? ":\u00a0" : "\u00a0";
this.restore(match, this.leftOffset + match.length);
},
restore: function(stem, index) {
if (!this.element.parentNode)
this.addTextNode();
this.element.data = this.stemLeft + (stem || this.stem) + this.stemRight;
this.setCursorToIndex(Object.isUndefined(index) ? this.index : index);
},
setCursorToIndex: function(index) {
var range = this.getRange();
range.setStart(this.element, index);
range.setEnd(this.element, index);
this.setRange(range);
},
findStem: function() {
var left = [], right = [], chr, index, length = this.value.length;
for (index = this.index - 1; index >= 0; index--) {
chr = this.value.charAt(index);
if (!Alice.Completion.PATTERN.test(chr)) break;
left.unshift(chr);
}
for (index = this.index; index < length; index++) {
chr = this.value.charAt(index);
if (!Alice.Completion.PATTERN.test(chr)) break;
right.push(chr);
}
this.stem = left.concat(right).join("");
this.stemLeft = this.value.substr(0, this.index - left.length);
this.stemRight = this.value.substr(this.index + right.length);
this.leftOffset = this.index - left.length;
},
matchAgainst: function(candidates) {
return candidates.grep(new RegExp("^" + RegExp.escape(this.stem), "i"));
}
});
Alice.Completion.PATTERN = /[A-Za-z0-9\[\\\]^_{|}-]/;
if (window == window.parent) {
document.observe("dom:loaded", function () {
var alice = new Alice.Application();
window.alice = alice;
$('helpclose').observe("click", function () { $('help').hide(); });
$('nicklist_toggle').observe("click", function () { alice.toggleNicklist() });
$$('.dropdown').each(function (menu) {
menu.observe(alice.supportsTouch ? "touchstart" : "mousedown", function (e) {
e.stop();
var element = e.element('.dropdown');
if (element.hasClassName("dropdown")) {
if (menu.hasClassName("open")) {
menu.removeClassName("open");
}
else {
$$(".dropdown.open").invoke("removeClassName", "open");
menu.addClassName("open");
}
}
});
});
document.observe(alice.supportsTouch ? "touchend" : "mouseup", function (e) {
if (e.findElement('.dropdown')) return;
$$('.dropdown.open').invoke("removeClassName", "open");
});
if (alice.isMobile) {
$('nicklist_toggle').addClassName('visible');
}
else {
window.onkeydown = function (e) {
if (!alice.input.disabled && !Alice.isSpecialKey(e.which))
alice.input.focus();
};
var windows = $('windows');
var toggle = $('nicklist_toggle');
var resize = function () {
var active = alice.activeWindow();
var position = active.captureScrollPosition();
var end = function(){
alice.freeze();
alice.tabs_width = $('tabs_container').getWidth();
alice.updateOverflowMenus();
active.scrollToPosition(position);
active.shiftTab();
window.onresize = resize;
};
( run in 0.749 second using v1.01-cache-2.11-cpan-8f98c5d2c55 )