view release on metacpan or search on metacpan
share/static/alice.js view on Meta::CPAN
var Class = (function() {
var IS_DONTENUM_BUGGY = (function(){
for (var p in { toString: 1 }) {
if (p === 'toString') return false;
}
return true;
})();
function subclass() {};
function create() {
var parent = null, properties = $A(arguments);
if (Object.isFunction(properties[0]))
parent = properties.shift();
function klass() {
this.initialize.apply(this, arguments);
}
Object.extend(klass, Class.Methods);
klass.superclass = parent;
klass.subclasses = [];
if (parent) {
subclass.prototype = parent.prototype;
klass.prototype = new subclass;
parent.subclasses.push(klass);
}
for (var i = 0, length = properties.length; i < length; i++)
klass.addMethods(properties[i]);
if (!klass.prototype.initialize)
klass.prototype.initialize = Prototype.emptyFunction;
klass.prototype.constructor = klass;
return klass;
}
function addMethods(source) {
var ancestor = this.superclass && this.superclass.prototype,
properties = Object.keys(source);
if (IS_DONTENUM_BUGGY) {
if (source.toString != Object.prototype.toString)
properties.push("toString");
if (source.valueOf != Object.prototype.valueOf)
properties.push("valueOf");
}
for (var i = 0, length = properties.length; i < length; i++) {
var property = properties[i], value = source[property];
if (ancestor && Object.isFunction(value) &&
value.argumentNames()[0] == "$super") {
var method = value;
value = (function(m) {
return function() { return ancestor[m].apply(this, arguments); };
})(property).wrap(method);
value.valueOf = method.valueOf.bind(method);
value.toString = method.toString.bind(method);
}
this.prototype[property] = value;
}
return this;
}
return {
create: create,
Methods: {
addMethods: addMethods
}
};
})();
(function() {
var _toString = Object.prototype.toString,
NULL_TYPE = 'Null',
UNDEFINED_TYPE = 'Undefined',
BOOLEAN_TYPE = 'Boolean',
NUMBER_TYPE = 'Number',
STRING_TYPE = 'String',
OBJECT_TYPE = 'Object',
BOOLEAN_CLASS = '[object Boolean]',
NUMBER_CLASS = '[object Number]',
STRING_CLASS = '[object String]',
ARRAY_CLASS = '[object Array]',
NATIVE_JSON_STRINGIFY_SUPPORT = window.JSON &&
typeof JSON.stringify === 'function' &&
JSON.stringify(0) === '0' &&
typeof JSON.stringify(Prototype.K) === 'undefined';
function Type(o) {
switch(o) {
case null: return NULL_TYPE;
case (void 0): return UNDEFINED_TYPE;
}
var type = typeof o;
switch(type) {
case 'boolean': return BOOLEAN_TYPE;
case 'number': return NUMBER_TYPE;
case 'string': return STRING_TYPE;
}
return OBJECT_TYPE;
}
function extend(destination, source) {
for (var property in source)
destination[property] = source[property];
return destination;
}
function inspect(object) {
try {
if (isUndefined(object)) return 'undefined';
if (object === null) return 'null';
return object.inspect ? object.inspect() : String(object);
} catch (e) {
if (e instanceof RangeError) return '...';
throw e;
share/static/alice.js view on Meta::CPAN
function isHash(object) {
return object instanceof Hash;
}
function isFunction(object) {
return typeof object === "function";
}
function isString(object) {
return _toString.call(object) === STRING_CLASS;
}
function isNumber(object) {
return _toString.call(object) === NUMBER_CLASS;
}
function isUndefined(object) {
return typeof object === "undefined";
}
extend(Object, {
extend: extend,
inspect: inspect,
toJSON: NATIVE_JSON_STRINGIFY_SUPPORT ? stringify : toJSON,
toQueryString: toQueryString,
toHTML: toHTML,
keys: Object.keys || keys,
values: values,
clone: clone,
isElement: isElement,
isArray: isArray,
isHash: isHash,
isFunction: isFunction,
isString: isString,
isNumber: isNumber,
isUndefined: isUndefined
});
})();
Object.extend(Function.prototype, (function() {
var slice = Array.prototype.slice;
function update(array, args) {
var arrayLength = array.length, length = args.length;
while (length--) array[arrayLength + length] = args[length];
return array;
}
function merge(array, args) {
array = slice.call(array, 0);
return update(array, args);
}
function argumentNames() {
var names = this.toString().match(/^[\s\(]*function[^(]*\(([^)]*)\)/)[1]
.replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g, '')
.replace(/\s+/g, '').split(',');
return names.length == 1 && !names[0] ? [] : names;
}
function bind(context) {
if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this;
var __method = this, args = slice.call(arguments, 1);
return function() {
var a = merge(args, arguments);
return __method.apply(context, a);
}
}
function bindAsEventListener(context) {
var __method = this, args = slice.call(arguments, 1);
return function(event) {
var a = update([event || window.event], args);
return __method.apply(context, a);
}
}
function curry() {
if (!arguments.length) return this;
var __method = this, args = slice.call(arguments, 0);
return function() {
var a = merge(args, arguments);
return __method.apply(this, a);
}
}
function delay(timeout) {
var __method = this, args = slice.call(arguments, 1);
timeout = timeout * 1000;
return window.setTimeout(function() {
return __method.apply(__method, args);
}, timeout);
}
function defer() {
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;
share/static/alice.js view on Meta::CPAN
onCreate: function() { Ajax.activeRequestCount++ },
onComplete: function() { Ajax.activeRequestCount-- }
});
Ajax.Base = Class.create({
initialize: function(options) {
this.options = {
method: 'post',
asynchronous: true,
contentType: 'application/x-www-form-urlencoded',
encoding: 'UTF-8',
parameters: '',
evalJSON: true,
evalJS: true
};
Object.extend(this.options, options || { });
this.options.method = this.options.method.toLowerCase();
if (Object.isString(this.options.parameters))
this.options.parameters = this.options.parameters.toQueryParams();
else if (Object.isHash(this.options.parameters))
this.options.parameters = this.options.parameters.toObject();
}
});
Ajax.Request = Class.create(Ajax.Base, {
_complete: false,
initialize: function($super, url, options) {
$super(options);
this.transport = Ajax.getTransport();
this.request(url);
},
request: function(url) {
this.url = url;
this.method = this.options.method;
var params = Object.clone(this.options.parameters);
if (!['get', 'post'].include(this.method)) {
params['_method'] = this.method;
this.method = 'post';
}
this.parameters = params;
if (params = Object.toQueryString(params)) {
if (this.method == 'get')
this.url += (this.url.include('?') ? '&' : '?') + params;
else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))
params += '&_=';
}
try {
var response = new Ajax.Response(this);
if (this.options.onCreate) this.options.onCreate(response);
Ajax.Responders.dispatch('onCreate', this, response);
this.transport.open(this.method.toUpperCase(), this.url,
this.options.asynchronous);
if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);
this.transport.onreadystatechange = this.onStateChange.bind(this);
this.setRequestHeaders();
this.body = this.method == 'post' ? (this.options.postBody || params) : null;
this.transport.send(this.body);
/* Force Firefox to handle ready state 4 for synchronous requests */
if (!this.options.asynchronous && this.transport.overrideMimeType)
this.onStateChange();
}
catch (e) {
this.dispatchException(e);
}
},
onStateChange: function() {
var readyState = this.transport.readyState;
if (readyState > 1 && !((readyState == 4) && this._complete))
this.respondToReadyState(this.transport.readyState);
},
setRequestHeaders: function() {
var headers = {
'X-Requested-With': 'XMLHttpRequest',
'X-Prototype-Version': Prototype.Version,
'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
};
if (this.method == 'post') {
headers['Content-type'] = this.options.contentType +
(this.options.encoding ? '; charset=' + this.options.encoding : '');
/* Force "Connection: close" for older Mozilla browsers to work
* around a bug where XMLHttpRequest sends an incorrect
* Content-length header. See Mozilla Bugzilla #246651.
*/
if (this.transport.overrideMimeType &&
(navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
headers['Connection'] = 'close';
}
if (typeof this.options.requestHeaders == 'object') {
var extras = this.options.requestHeaders;
if (Object.isFunction(extras.push))
for (var i = 0, length = extras.length; i < length; i += 2)
headers[extras[i]] = extras[i+1];
else
$H(extras).each(function(pair) { headers[pair.key] = pair.value });
}
for (var name in headers)
this.transport.setRequestHeader(name, headers[name]);
},
success: function() {
var status = this.getStatus();
return !status || (status >= 200 && status < 300);
},
share/static/alice.js view on Meta::CPAN
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, {
initialize: function($super, container, url, options) {
$super(options);
this.onComplete = this.options.onComplete;
this.frequency = (this.options.frequency || 2);
this.decay = (this.options.decay || 1);
this.updater = { };
this.container = container;
this.url = url;
this.start();
},
start: function() {
this.options.onComplete = this.updateComplete.bind(this);
this.onTimerEvent();
},
stop: function() {
this.updater.options.onComplete = undefined;
clearTimeout(this.timer);
(this.onComplete || Prototype.emptyFunction).apply(this, arguments);
},
updateComplete: function(response) {
if (this.options.decay) {
this.decay = (response.responseText == this.lastText ?
this.decay * this.options.decay : 1);
this.lastText = response.responseText;
}
this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency);
},
onTimerEvent: function() {
this.updater = new Ajax.Updater(this.container, this.url, this.options);
}
});
function $(element) {
if (arguments.length > 1) {
for (var i = 0, elements = [], length = arguments.length; i < length; i++)
elements.push($(arguments[i]));
return elements;
}
if (Object.isString(element))
element = document.getElementById(element);
return Element.extend(element);
}
if (Prototype.BrowserFeatures.XPath) {
document._getElementsByXPath = function(expression, parentElement) {
var results = [];
var query = document.evaluate(expression, $(parentElement) || document,
null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
for (var i = 0, length = query.snapshotLength; i < length; i++)
results.push(Element.extend(query.snapshotItem(i)));
return results;
};
}
/*--------------------------------------------------------------------------*/
if (!Node) var Node = { };
if (!Node.ELEMENT_NODE) {
Object.extend(Node, {
ELEMENT_NODE: 1,
ATTRIBUTE_NODE: 2,
TEXT_NODE: 3,
CDATA_SECTION_NODE: 4,
ENTITY_REFERENCE_NODE: 5,
ENTITY_NODE: 6,
PROCESSING_INSTRUCTION_NODE: 7,
COMMENT_NODE: 8,
DOCUMENT_NODE: 9,
DOCUMENT_TYPE_NODE: 10,
DOCUMENT_FRAGMENT_NODE: 11,
NOTATION_NODE: 12
});
}
(function(global) {
var HAS_EXTENDED_CREATE_ELEMENT_SYNTAX = (function(){
try {
var el = document.createElement('<input name="x">');
return el.tagName.toLowerCase() === 'input' && el.name === 'x';
}
share/static/alice.js view on Meta::CPAN
el.innerHTML = "<tbody><tr><td>test</td></tr></tbody>";
var isBuggy = typeof el.tBodies[0] == "undefined";
el = null;
return isBuggy;
}
} catch (e) {
return true;
}
})();
var SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING = (function () {
var s = document.createElement("script"),
isBuggy = false;
try {
s.appendChild(document.createTextNode(""));
isBuggy = !s.firstChild ||
s.firstChild && s.firstChild.nodeType !== 3;
} catch (e) {
isBuggy = true;
}
s = null;
return isBuggy;
})();
function update(element, content) {
element = $(element);
if (content && content.toElement)
content = content.toElement();
if (Object.isElement(content))
return element.update().insert(content);
content = Object.toHTML(content);
var tagName = element.tagName.toUpperCase();
if (tagName === 'SCRIPT' && SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING) {
element.text = content;
return element;
}
if (SELECT_ELEMENT_INNERHTML_BUGGY || TABLE_ELEMENT_INNERHTML_BUGGY) {
if (tagName in Element._insertionTranslations.tags) {
while (element.firstChild) {
element.removeChild(element.firstChild);
}
Element._getContentFromAnonymousElement(tagName, content.stripScripts())
.each(function(node) {
element.appendChild(node)
});
}
else {
element.innerHTML = content.stripScripts();
}
}
else {
element.innerHTML = content.stripScripts();
}
content.evalScripts.bind(content).defer();
return element;
}
return update;
})(),
replace: function(element, content) {
element = $(element);
if (content && content.toElement) content = content.toElement();
else if (!Object.isElement(content)) {
content = Object.toHTML(content);
var range = element.ownerDocument.createRange();
range.selectNode(element);
content.evalScripts.bind(content).defer();
content = range.createContextualFragment(content.stripScripts());
}
element.parentNode.replaceChild(content, element);
return element;
},
insert: function(element, insertions) {
element = $(element);
if (Object.isString(insertions) || Object.isNumber(insertions) ||
Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML)))
insertions = {bottom:insertions};
var content, insert, tagName, childNodes;
for (var position in insertions) {
content = insertions[position];
position = position.toLowerCase();
insert = Element._insertionTranslations[position];
if (content && content.toElement) content = content.toElement();
if (Object.isElement(content)) {
insert(element, content);
continue;
}
content = Object.toHTML(content);
tagName = ((position == 'before' || position == 'after')
? element.parentNode : element).tagName.toUpperCase();
childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
if (position == 'top' || position == 'after') childNodes.reverse();
childNodes.each(insert.curry(element));
content.evalScripts.bind(content).defer();
}
return element;
},
wrap: function(element, wrapper, attributes) {
element = $(element);
if (Object.isElement(wrapper))
$(wrapper).writeAttribute(attributes || { });
else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes);
else wrapper = new Element('div', wrapper);
if (element.parentNode)
element.parentNode.replaceChild(wrapper, element);
wrapper.appendChild(element);
return wrapper;
},
inspect: function(element) {
element = $(element);
var result = '<' + element.tagName.toLowerCase();
$H({'id': 'id', 'className': 'class'}).each(function(pair) {
var property = pair.first(),
attribute = pair.last(),
value = (element[property] || '').toString();
if (value) result += ' ' + attribute + '=' + value.inspect(true);
});
return result + '>';
},
recursivelyCollect: function(element, property, maximumLength) {
element = $(element);
maximumLength = maximumLength || -1;
var elements = [];
while (element = element[property]) {
if (element.nodeType == 1)
elements.push(Element.extend(element));
if (elements.length == maximumLength)
break;
}
return elements;
},
ancestors: function(element) {
return Element.recursivelyCollect(element, 'parentNode');
},
descendants: function(element) {
return Element.select(element, "*");
},
firstDescendant: function(element) {
element = $(element).firstChild;
while (element && element.nodeType != 1) element = element.nextSibling;
return $(element);
},
immediateDescendants: function(element) {
var results = [], child = $(element).firstChild;
share/static/alice.js view on Meta::CPAN
};
}
else if (Prototype.Browser.WebKit) {
Element.Methods.setOpacity = function(element, value) {
element = $(element);
element.style.opacity = (value == 1 || value === '') ? '' :
(value < 0.00001) ? 0 : value;
if (value == 1)
if (element.tagName.toUpperCase() == 'IMG' && element.width) {
element.width++; element.width--;
} else try {
var n = document.createTextNode(' ');
element.appendChild(n);
element.removeChild(n);
} catch (e) { }
return element;
};
Element.Methods.cumulativeOffset = function(element) {
var valueT = 0, valueL = 0;
do {
valueT += element.offsetTop || 0;
valueL += element.offsetLeft || 0;
if (element.offsetParent == document.body)
if (Element.getStyle(element, 'position') == 'absolute') break;
element = element.offsetParent;
} while (element);
return Element._returnOffset(valueL, valueT);
};
}
if ('outerHTML' in document.documentElement) {
Element.Methods.replace = function(element, content) {
element = $(element);
if (content && content.toElement) content = content.toElement();
if (Object.isElement(content)) {
element.parentNode.replaceChild(content, element);
return element;
}
content = Object.toHTML(content);
var parent = element.parentNode, tagName = parent.tagName.toUpperCase();
if (Element._insertionTranslations.tags[tagName]) {
var nextSibling = element.next(),
fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
parent.removeChild(element);
if (nextSibling)
fragments.each(function(node) { parent.insertBefore(node, nextSibling) });
else
fragments.each(function(node) { parent.appendChild(node) });
}
else element.outerHTML = content.stripScripts();
content.evalScripts.bind(content).defer();
return element;
};
}
Element._returnOffset = function(l, t) {
var result = [l, t];
result.left = l;
result.top = t;
return result;
};
Element._getContentFromAnonymousElement = function(tagName, html) {
var div = new Element('div'),
t = Element._insertionTranslations.tags[tagName];
if (t) {
div.innerHTML = t[0] + html + t[1];
for (var i = t[2]; i--; ) {
div = div.firstChild;
}
}
else {
div.innerHTML = html;
}
return $A(div.childNodes);
};
Element._insertionTranslations = {
before: function(element, node) {
element.parentNode.insertBefore(node, element);
},
top: function(element, node) {
element.insertBefore(node, element.firstChild);
},
bottom: function(element, node) {
element.appendChild(node);
},
after: function(element, node) {
element.parentNode.insertBefore(node, element.nextSibling);
},
tags: {
TABLE: ['<table>', '</table>', 1],
TBODY: ['<table><tbody>', '</tbody></table>', 2],
TR: ['<table><tbody><tr>', '</tr></tbody></table>', 3],
TD: ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4],
SELECT: ['<select>', '</select>', 1]
}
};
(function() {
var tags = Element._insertionTranslations.tags;
Object.extend(tags, {
THEAD: tags.TBODY,
TFOOT: tags.TBODY,
TH: tags.TD
});
})();
Element.Methods.Simulated = {
hasAttribute: function(element, attribute) {
attribute = Element._attributeTranslations.has[attribute] || attribute;
share/static/alice.js view on Meta::CPAN
Abstract.TimedObserver = Class.create(PeriodicalExecuter, {
initialize: function($super, element, frequency, callback) {
$super(callback, frequency);
this.element = $(element);
this.lastValue = this.getValue();
},
execute: function() {
var value = this.getValue();
if (Object.isString(this.lastValue) && Object.isString(value) ?
this.lastValue != value : String(this.lastValue) != String(value)) {
this.callback(this.element, value);
this.lastValue = value;
}
}
});
Form.Element.Observer = Class.create(Abstract.TimedObserver, {
getValue: function() {
return Form.Element.getValue(this.element);
}
});
Form.Observer = Class.create(Abstract.TimedObserver, {
getValue: function() {
return Form.serialize(this.element);
}
});
/*--------------------------------------------------------------------------*/
Abstract.EventObserver = Class.create({
initialize: function(element, callback) {
this.element = $(element);
this.callback = callback;
this.lastValue = this.getValue();
if (this.element.tagName.toLowerCase() == 'form')
this.registerFormCallbacks();
else
this.registerCallback(this.element);
},
onElementEvent: function() {
var value = this.getValue();
if (this.lastValue != value) {
this.callback(this.element, value);
this.lastValue = value;
}
},
registerFormCallbacks: function() {
Form.getElements(this.element).each(this.registerCallback, this);
},
registerCallback: function(element) {
if (element.type) {
switch (element.type.toLowerCase()) {
case 'checkbox':
case 'radio':
Event.observe(element, 'click', this.onElementEvent.bind(this));
break;
default:
Event.observe(element, 'change', this.onElementEvent.bind(this));
break;
}
}
}
});
Form.Element.EventObserver = Class.create(Abstract.EventObserver, {
getValue: function() {
return Form.Element.getValue(this.element);
}
});
Form.EventObserver = Class.create(Abstract.EventObserver, {
getValue: function() {
return Form.serialize(this.element);
}
});
(function() {
var Event = {
KEY_BACKSPACE: 8,
KEY_TAB: 9,
KEY_RETURN: 13,
KEY_ESC: 27,
KEY_LEFT: 37,
KEY_UP: 38,
KEY_RIGHT: 39,
KEY_DOWN: 40,
KEY_DELETE: 46,
KEY_HOME: 36,
KEY_END: 35,
KEY_PAGEUP: 33,
KEY_PAGEDOWN: 34,
KEY_INSERT: 45,
cache: {}
};
var docEl = document.documentElement;
var MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED = 'onmouseenter' in docEl
&& 'onmouseleave' in docEl;
var _isButton;
if (Prototype.Browser.IE) {
var buttonMap = { 0: 1, 1: 4, 2: 2 };
_isButton = function(event, code) {
return event.button === buttonMap[code];
};
} else if (Prototype.Browser.WebKit) {
_isButton = function(event, code) {
switch (code) {
case 0: return event.which == 1 && !event.metaKey;
case 1: return event.which == 1 && event.metaKey;
default: return false;
}
};
} else {
_isButton = function(event, code) {
return event.which ? (event.which === code + 1) : (event.button === code);
};
share/static/alice.js view on Meta::CPAN
}
var responder = responders.find( function(r) { return r.handler === handler; });
if (!responder) return element;
if (eventName.include(':')) {
if (element.removeEventListener)
element.removeEventListener("dataavailable", responder, false);
else {
element.detachEvent("ondataavailable", responder);
element.detachEvent("onfilterchange", responder);
}
} else {
var actualEventName = _getDOMEventName(eventName);
if (element.removeEventListener)
element.removeEventListener(actualEventName, responder, false);
else
element.detachEvent('on' + actualEventName, responder);
}
registry.set(eventName, responders.without(responder));
return element;
}
function fire(element, eventName, memo, bubble) {
element = $(element);
if (Object.isUndefined(bubble))
bubble = true;
if (element == document && document.createEvent && !element.dispatchEvent)
element = document.documentElement;
var event;
if (document.createEvent) {
event = document.createEvent('HTMLEvents');
event.initEvent('dataavailable', true, true);
} else {
event = document.createEventObject();
event.eventType = bubble ? 'ondataavailable' : 'onfilterchange';
}
event.eventName = eventName;
event.memo = memo || { };
if (document.createEvent)
element.dispatchEvent(event);
else
element.fireEvent(event.eventType, event);
return Event.extend(event);
}
Event.Handler = Class.create({
initialize: function(element, eventName, selector, callback) {
this.element = $(element);
this.eventName = eventName;
this.selector = selector;
this.callback = callback;
this.handler = this.handleEvent.bind(this);
},
start: function() {
Event.observe(this.element, this.eventName, this.handler);
return this;
},
stop: function() {
Event.stopObserving(this.element, this.eventName, this.handler);
return this;
},
handleEvent: function(event) {
var element = this.selector ? event.findElement(this.selector) :
this.element;
if (element) this.callback.call(element, event, element);
}
});
function on(element, eventName, selector, callback) {
element = $(element);
if (Object.isFunction(selector) && Object.isUndefined(callback)) {
callback = selector, selector = null;
}
return new Event.Handler(element, eventName, selector, callback).start();
}
Object.extend(Event, Event.Methods);
Object.extend(Event, {
fire: fire,
observe: observe,
stopObserving: stopObserving,
on: on
});
Element.addMethods({
fire: fire,
observe: observe,
stopObserving: stopObserving,
on: on
});
Object.extend(document, {
fire: fire.methodize(),
observe: observe.methodize(),
stopObserving: stopObserving.methodize(),
on: on.methodize(),
loaded: false
});
if (window.Event) Object.extend(window.Event, Event);
share/static/alice.js view on Meta::CPAN
$A(elements).each( function(element, index) {
new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay }));
});
},
PAIRS: {
'slide': ['SlideDown','SlideUp'],
'blind': ['BlindDown','BlindUp'],
'appear': ['Appear','Fade']
},
toggle: function(element, effect, options) {
element = $(element);
effect = (effect || 'appear').toLowerCase();
return Effect[ Effect.PAIRS[ effect ][ element.visible() ? 1 : 0 ] ](element, Object.extend({
queue: { position:'end', scope:(element.id || 'global'), limit: 1 }
}, options || {}));
}
};
Effect.DefaultOptions.transition = Effect.Transitions.sinoidal;
/* ------------- core effects ------------- */
Effect.ScopedQueue = Class.create(Enumerable, {
initialize: function() {
this.effects = [];
this.interval = null;
},
_each: function(iterator) {
this.effects._each(iterator);
},
add: function(effect) {
var timestamp = new Date().getTime();
var position = Object.isString(effect.options.queue) ?
effect.options.queue : effect.options.queue.position;
switch(position) {
case 'front':
this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) {
e.startOn += effect.finishOn;
e.finishOn += effect.finishOn;
});
break;
case 'with-last':
timestamp = this.effects.pluck('startOn').max() || timestamp;
break;
case 'end':
timestamp = this.effects.pluck('finishOn').max() || timestamp;
break;
}
effect.startOn += timestamp;
effect.finishOn += timestamp;
if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit))
this.effects.push(effect);
if (!this.interval)
this.interval = setInterval(this.loop.bind(this), 15);
},
remove: function(effect) {
this.effects = this.effects.reject(function(e) { return e==effect });
if (this.effects.length == 0) {
clearInterval(this.interval);
this.interval = null;
}
},
loop: function() {
var timePos = new Date().getTime();
for(var i=0, len=this.effects.length;i<len;i++)
this.effects[i] && this.effects[i].loop(timePos);
}
});
Effect.Queues = {
instances: $H(),
get: function(queueName) {
if (!Object.isString(queueName)) return queueName;
return this.instances.get(queueName) ||
this.instances.set(queueName, new Effect.ScopedQueue());
}
};
Effect.Queue = Effect.Queues.get('global');
Effect.Base = Class.create({
position: null,
start: function(options) {
if (options && options.transition === false) options.transition = Effect.Transitions.linear;
this.options = Object.extend(Object.extend({ },Effect.DefaultOptions), options || { });
this.currentFrame = 0;
this.state = 'idle';
this.startOn = this.options.delay*1000;
this.finishOn = this.startOn+(this.options.duration*1000);
this.fromToDelta = this.options.to-this.options.from;
this.totalTime = this.finishOn-this.startOn;
this.totalFrames = this.options.fps*this.options.duration;
this.render = (function() {
function dispatch(effect, eventName) {
if (effect.options[eventName + 'Internal'])
effect.options[eventName + 'Internal'](effect);
if (effect.options[eventName])
effect.options[eventName](effect);
}
return function(pos) {
if (this.state === "idle") {
this.state = "running";
dispatch(this, 'beforeSetup');
if (this.setup) this.setup();
dispatch(this, 'afterSetup');
}
if (this.state === "running") {
pos = (this.options.transition(pos) * this.fromToDelta) + this.options.from;
this.position = pos;
dispatch(this, 'beforeUpdate');
if (this.update) this.update(pos);
dispatch(this, 'afterUpdate');
share/static/alice.js view on Meta::CPAN
loop: function(timePos) {
if (timePos >= this.startOn) {
if (timePos >= this.finishOn) {
this.render(1.0);
this.cancel();
this.event('beforeFinish');
if (this.finish) this.finish();
this.event('afterFinish');
return;
}
var pos = (timePos - this.startOn) / this.totalTime,
frame = (pos * this.totalFrames).round();
if (frame > this.currentFrame) {
this.render(pos);
this.currentFrame = frame;
}
}
},
cancel: function() {
if (!this.options.sync)
Effect.Queues.get(Object.isString(this.options.queue) ?
'global' : this.options.queue.scope).remove(this);
this.state = 'finished';
},
event: function(eventName) {
if (this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
if (this.options[eventName]) this.options[eventName](this);
},
inspect: function() {
var data = $H();
for(property in this)
if (!Object.isFunction(this[property])) data.set(property, this[property]);
return '#<Effect:' + data.inspect() + ',options:' + $H(this.options).inspect() + '>';
}
});
Effect.Parallel = Class.create(Effect.Base, {
initialize: function(effects) {
this.effects = effects || [];
this.start(arguments[1]);
},
update: function(position) {
this.effects.invoke('render', position);
},
finish: function(position) {
this.effects.each( function(effect) {
effect.render(1.0);
effect.cancel();
effect.event('beforeFinish');
if (effect.finish) effect.finish(position);
effect.event('afterFinish');
});
}
});
Effect.Tween = Class.create(Effect.Base, {
initialize: function(object, from, to) {
object = Object.isString(object) ? $(object) : object;
var args = $A(arguments), method = args.last(),
options = args.length == 5 ? args[3] : null;
this.method = Object.isFunction(method) ? method.bind(object) :
Object.isFunction(object[method]) ? object[method].bind(object) :
function(value) { object[method] = value };
this.start(Object.extend({ from: from, to: to }, options || { }));
},
update: function(position) {
this.method(position);
}
});
Effect.Event = Class.create(Effect.Base, {
initialize: function() {
this.start(Object.extend({ duration: 0 }, arguments[0] || { }));
},
update: Prototype.emptyFunction
});
Effect.Opacity = Class.create(Effect.Base, {
initialize: function(element) {
this.element = $(element);
if (!this.element) throw(Effect._elementDoesNotExistError);
if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
this.element.setStyle({zoom: 1});
var options = Object.extend({
from: this.element.getOpacity() || 0.0,
to: 1.0
}, arguments[1] || { });
this.start(options);
},
update: function(position) {
this.element.setOpacity(position);
}
});
Effect.Move = Class.create(Effect.Base, {
initialize: function(element) {
this.element = $(element);
if (!this.element) throw(Effect._elementDoesNotExistError);
var options = Object.extend({
x: 0,
y: 0,
mode: 'relative'
}, arguments[1] || { });
this.start(options);
},
setup: function() {
this.element.makePositioned();
this.originalLeft = parseFloat(this.element.getStyle('left') || '0');
this.originalTop = parseFloat(this.element.getStyle('top') || '0');
if (this.options.mode == 'absolute') {
this.options.x = this.options.x - this.originalLeft;
this.options.y = this.options.y - this.originalTop;
}
},
update: function(position) {
this.element.setStyle({
left: (this.options.x * position + this.originalLeft).round() + 'px',
top: (this.options.y * position + this.originalTop).round() + 'px'
});
}
});
Effect.MoveBy = function(element, toTop, toLeft) {
return new Effect.Move(element,
Object.extend({ x: toLeft, y: toTop }, arguments[3] || { }));
};
Effect.Scale = Class.create(Effect.Base, {
initialize: function(element, percent) {
this.element = $(element);
if (!this.element) throw(Effect._elementDoesNotExistError);
var options = Object.extend({
scaleX: true,
scaleY: true,
scaleContent: true,
scaleFromCenter: false,
scaleMode: 'box', // 'box' or 'contents' or { } with provided values
scaleFrom: 100.0,
scaleTo: percent
}, arguments[2] || { });
this.start(options);
},
setup: function() {
this.restoreAfterFinish = this.options.restoreAfterFinish || false;
this.elementPositioning = this.element.getStyle('position');
this.originalStyle = { };
['top','left','width','height','fontSize'].each( function(k) {
this.originalStyle[k] = this.element.style[k];
}.bind(this));
this.originalTop = this.element.offsetTop;
this.originalLeft = this.element.offsetLeft;
var fontSize = this.element.getStyle('font-size') || '100%';
['em','px','%','pt'].each( function(fontSizeType) {
if (fontSize.indexOf(fontSizeType)>0) {
this.fontSize = parseFloat(fontSize);
this.fontSizeType = fontSizeType;
}
}.bind(this));
this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;
this.dims = null;
if (this.options.scaleMode=='box')
this.dims = [this.element.offsetHeight, this.element.offsetWidth];
if (/^content/.test(this.options.scaleMode))
this.dims = [this.element.scrollHeight, this.element.scrollWidth];
if (!this.dims)
this.dims = [this.options.scaleMode.originalHeight,
this.options.scaleMode.originalWidth];
},
update: function(position) {
var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position);
if (this.options.scaleContent && this.fontSize)
this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType });
this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale);
},
finish: function(position) {
if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle);
},
setDimensions: function(height, width) {
var d = { };
if (this.options.scaleX) d.width = width.round() + 'px';
if (this.options.scaleY) d.height = height.round() + 'px';
if (this.options.scaleFromCenter) {
var topd = (height - this.dims[0])/2;
var leftd = (width - this.dims[1])/2;
if (this.elementPositioning == 'absolute') {
if (this.options.scaleY) d.top = this.originalTop-topd + 'px';
if (this.options.scaleX) d.left = this.originalLeft-leftd + 'px';
} else {
if (this.options.scaleY) d.top = -topd + 'px';
if (this.options.scaleX) d.left = -leftd + 'px';
}
}
this.element.setStyle(d);
}
});
Effect.Highlight = Class.create(Effect.Base, {
initialize: function(element) {
this.element = $(element);
if (!this.element) throw(Effect._elementDoesNotExistError);
var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || { });
this.start(options);
},
setup: function() {
if (this.element.getStyle('display')=='none') { this.cancel(); return; }
this.oldStyle = { };
if (!this.options.keepBackgroundImage) {
this.oldStyle.backgroundImage = this.element.getStyle('background-image');
this.element.setStyle({backgroundImage: 'none'});
}
if (!this.options.endcolor)
this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff');
if (!this.options.restorecolor)
this.options.restorecolor = this.element.getStyle('background-color');
this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this));
this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this));
},
update: function(position) {
this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){
return m+((this._base[i]+(this._delta[i]*position)).round().toColorPart()); }.bind(this)) });
},
finish: function() {
this.element.setStyle(Object.extend(this.oldStyle, {
backgroundColor: this.options.restorecolor
}));
}
});
Effect.ScrollTo = function(element) {
var options = arguments[1] || { },
scrollOffsets = document.viewport.getScrollOffsets(),
elementOffsets = $(element).cumulativeOffset();
if (options.offset) elementOffsets[1] += options.offset;
return new Effect.Tween(null,
scrollOffsets.top,
elementOffsets[1],
options,
function(p){ scrollTo(scrollOffsets.left, p.round()); }
);
};
/* ------------- combination effects ------------- */
Effect.Fade = function(element) {
element = $(element);
var oldOpacity = element.getInlineOpacity();
var options = Object.extend({
from: element.getOpacity() || 1.0,
to: 0.0,
afterFinishInternal: function(effect) {
if (effect.options.to!=0) return;
effect.element.hide().setStyle({opacity: oldOpacity});
}
}, arguments[1] || { });
return new Effect.Opacity(element,options);
};
Effect.Appear = function(element) {
element = $(element);
var options = Object.extend({
from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0),
to: 1.0,
afterFinishInternal: function(effect) {
effect.element.forceRerendering();
},
beforeSetup: function(effect) {
effect.element.setOpacity(effect.options.from).show();
}}, arguments[1] || { });
return new Effect.Opacity(element,options);
};
Effect.Puff = function(element) {
element = $(element);
var oldStyle = {
opacity: element.getInlineOpacity(),
position: element.getStyle('position'),
top: element.style.top,
left: element.style.left,
share/static/alice.js view on Meta::CPAN
this.element = $(element);
if (!this.element) throw(Effect._elementDoesNotExistError);
var options = Object.extend({
style: { }
}, arguments[1] || { });
if (!Object.isString(options.style)) this.style = $H(options.style);
else {
if (options.style.include(':'))
this.style = options.style.parseStyle();
else {
this.element.addClassName(options.style);
this.style = $H(this.element.getStyles());
this.element.removeClassName(options.style);
var css = this.element.getStyles();
this.style = this.style.reject(function(style) {
return style.value == css[style.key];
});
options.afterFinishInternal = function(effect) {
effect.element.addClassName(effect.options.style);
effect.transforms.each(function(transform) {
effect.element.style[transform.style] = '';
});
};
}
}
this.start(options);
},
setup: function(){
function parseColor(color){
if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff';
color = color.parseColor();
return $R(0,2).map(function(i){
return parseInt( color.slice(i*2+1,i*2+3), 16 );
});
}
this.transforms = this.style.map(function(pair){
var property = pair[0], value = pair[1], unit = null;
if (value.parseColor('#zzzzzz') != '#zzzzzz') {
value = value.parseColor();
unit = 'color';
} else if (property == 'opacity') {
value = parseFloat(value);
if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
this.element.setStyle({zoom: 1});
} else if (Element.CSS_LENGTH.test(value)) {
var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/);
value = parseFloat(components[1]);
unit = (components.length == 3) ? components[2] : null;
}
var originalValue = this.element.getStyle(property);
return {
style: property.camelize(),
originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0),
targetValue: unit=='color' ? parseColor(value) : value,
unit: unit
};
}.bind(this)).reject(function(transform){
return (
(transform.originalValue == transform.targetValue) ||
(
transform.unit != 'color' &&
(isNaN(transform.originalValue) || isNaN(transform.targetValue))
)
);
});
},
update: function(position) {
var style = { }, transform, i = this.transforms.length;
while(i--)
style[(transform = this.transforms[i]).style] =
transform.unit=='color' ? '#'+
(Math.round(transform.originalValue[0]+
(transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() +
(Math.round(transform.originalValue[1]+
(transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() +
(Math.round(transform.originalValue[2]+
(transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() :
(transform.originalValue +
(transform.targetValue - transform.originalValue) * position).toFixed(3) +
(transform.unit === null ? '' : transform.unit);
this.element.setStyle(style, true);
}
});
Effect.Transform = Class.create({
initialize: function(tracks){
this.tracks = [];
this.options = arguments[1] || { };
this.addTracks(tracks);
},
addTracks: function(tracks){
tracks.each(function(track){
track = $H(track);
var data = track.values().first();
this.tracks.push($H({
ids: track.keys().first(),
effect: Effect.Morph,
options: { style: data }
}));
}.bind(this));
return this;
},
play: function(){
return new Effect.Parallel(
this.tracks.map(function(track){
var ids = track.get('ids'), effect = track.get('effect'), options = track.get('options');
var elements = [$(ids) || $$(ids)].flatten();
return elements.map(function(e){ return new effect(e, Object.extend({ sync:true }, options)) });
}).flatten(),
this.options
);
}
});
Element.CSS_PROPERTIES = $w(
'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' +
'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' +
'borderRightColor borderRightStyle borderRightWidth borderSpacing ' +
'borderTopColor borderTopStyle borderTopWidth bottom clip color ' +
'fontSize fontWeight height left letterSpacing lineHeight ' +
'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+
'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' +
'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' +
'right textIndent top width wordSpacing zIndex');
Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;
String.__parseStyleElement = document.createElement('div');
String.prototype.parseStyle = function(){
var style, styleRules = $H();
if (Prototype.Browser.WebKit)
style = new Element('div',{style:this}).style;
else {
String.__parseStyleElement.innerHTML = '<div style="' + this + '"></div>';
style = String.__parseStyleElement.childNodes[0].style;
}
Element.CSS_PROPERTIES.each(function(property){
if (style[property]) styleRules.set(property, style[property]);
});
if (Prototype.Browser.IE && this.include('opacity'))
styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]);
return styleRules;
};
if (document.defaultView && document.defaultView.getComputedStyle) {
Element.getStyles = function(element) {
var css = document.defaultView.getComputedStyle($(element), null);
return Element.CSS_PROPERTIES.inject({ }, function(styles, property) {
styles[property] = css[property];
return styles;
});
};
} else {
Element.getStyles = function(element) {
element = $(element);
var css = element.currentStyle, styles;
styles = Element.CSS_PROPERTIES.inject({ }, function(results, property) {
share/static/alice.js view on Meta::CPAN
Position.within(drop.element, point[0], point[1]) );
},
deactivate: function(drop) {
if(drop.hoverclass)
Element.removeClassName(drop.element, drop.hoverclass);
this.last_active = null;
},
activate: function(drop) {
if(drop.hoverclass)
Element.addClassName(drop.element, drop.hoverclass);
this.last_active = drop;
},
show: function(point, element) {
if(!this.drops.length) return;
var drop, affected = [];
this.drops.each( function(drop) {
if(Droppables.isAffected(point, element, drop))
affected.push(drop);
});
if(affected.length>0)
drop = Droppables.findDeepestChild(affected);
if(this.last_active && this.last_active != drop) this.deactivate(this.last_active);
if (drop) {
Position.within(drop.element, point[0], point[1]);
if(drop.onHover)
drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element));
if (drop != this.last_active) Droppables.activate(drop);
}
},
fire: function(event, element) {
if(!this.last_active) return;
Position.prepare();
if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active))
if (this.last_active.onDrop) {
this.last_active.onDrop(element, this.last_active.element, event);
return true;
}
},
reset: function() {
if(this.last_active)
this.deactivate(this.last_active);
}
};
var Draggables = {
drags: [],
observers: [],
register: function(draggable) {
if(this.drags.length == 0) {
this.eventMouseUp = this.endDrag.bindAsEventListener(this);
this.eventMouseMove = this.updateDrag.bindAsEventListener(this);
this.eventKeypress = this.keyPress.bindAsEventListener(this);
Event.observe(document, "mouseup", this.eventMouseUp);
Event.observe(document, "mousemove", this.eventMouseMove);
Event.observe(document, "keypress", this.eventKeypress);
}
this.drags.push(draggable);
},
unregister: function(draggable) {
this.drags = this.drags.reject(function(d) { return d==draggable });
if(this.drags.length == 0) {
Event.stopObserving(document, "mouseup", this.eventMouseUp);
Event.stopObserving(document, "mousemove", this.eventMouseMove);
Event.stopObserving(document, "keypress", this.eventKeypress);
}
},
activate: function(draggable) {
if(draggable.options.delay) {
this._timeout = setTimeout(function() {
Draggables._timeout = null;
window.focus();
Draggables.activeDraggable = draggable;
}.bind(this), draggable.options.delay);
} else {
window.focus(); // allows keypress events if window isn't currently focused, fails for Safari
this.activeDraggable = draggable;
}
},
deactivate: function() {
this.activeDraggable = null;
},
updateDrag: function(event) {
if(!this.activeDraggable) return;
var pointer = [Event.pointerX(event), Event.pointerY(event)];
if(this._lastPointer && (this._lastPointer.inspect() == pointer.inspect())) return;
this._lastPointer = pointer;
this.activeDraggable.updateDrag(event, pointer);
},
endDrag: function(event) {
if(this._timeout) {
clearTimeout(this._timeout);
this._timeout = null;
}
if(!this.activeDraggable) return;
this._lastPointer = null;
this.activeDraggable.endDrag(event);
this.activeDraggable = null;
},
keyPress: function(event) {
if(this.activeDraggable)
this.activeDraggable.keyPress(event);
},
addObserver: function(observer) {
this.observers.push(observer);
this._cacheObserverCallbacks();
},
removeObserver: function(element) { // element instead of observer fixes mem leaks
this.observers = this.observers.reject( function(o) { return o.element==element });
this._cacheObserverCallbacks();
},
notify: function(eventName, draggable, event) { // 'onStart', 'onEnd', 'onDrag'
if(this[eventName+'Count'] > 0)
this.observers.each( function(o) {
if(o[eventName]) o[eventName](eventName, draggable, event);
});
if(draggable.options[eventName]) draggable.options[eventName](draggable, event);
},
_cacheObserverCallbacks: function() {
['onStart','onEnd','onDrag'].each( function(eventName) {
Draggables[eventName+'Count'] = Draggables.observers.select(
function(o) { return o[eventName]; }
).length;
});
}
share/static/alice.js view on Meta::CPAN
/*--------------------------------------------------------------------------*/
var Draggable = Class.create({
initialize: function(element) {
var defaults = {
handle: false,
reverteffect: function(element, top_offset, left_offset) {
var dur = Math.sqrt(Math.abs(top_offset^2)+Math.abs(left_offset^2))*0.02;
new Effect.Move(element, { x: -left_offset, y: -top_offset, duration: dur,
queue: {scope:'_draggable', position:'end'}
});
},
endeffect: function(element) {
var toOpacity = Object.isNumber(element._opacity) ? element._opacity : 1.0;
new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity,
queue: {scope:'_draggable', position:'end'},
afterFinish: function(){
Draggable._dragging[element] = false
}
});
},
zindex: 1000,
revert: false,
quiet: false,
scroll: false,
scrollSensitivity: 20,
scrollSpeed: 15,
snap: false, // false, or xy or [x,y] or function(x,y){ return [x,y] }
delay: 0
};
if(!arguments[1] || Object.isUndefined(arguments[1].endeffect))
Object.extend(defaults, {
starteffect: function(element) {
element._opacity = Element.getOpacity(element);
Draggable._dragging[element] = true;
new Effect.Opacity(element, {duration:0.2, from:element._opacity, to:0.7});
}
});
var options = Object.extend(defaults, arguments[1] || { });
this.element = $(element);
if(options.handle && Object.isString(options.handle))
this.handle = this.element.down('.'+options.handle, 0);
if(!this.handle) this.handle = $(options.handle);
if(!this.handle) this.handle = this.element;
if(options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) {
options.scroll = $(options.scroll);
this._isScrollChild = Element.childOf(this.element, options.scroll);
}
Element.makePositioned(this.element); // fix IE
this.options = options;
this.dragging = false;
this.eventMouseDown = this.initDrag.bindAsEventListener(this);
Event.observe(this.handle, "mousedown", this.eventMouseDown);
Draggables.register(this);
},
destroy: function() {
Event.stopObserving(this.handle, "mousedown", this.eventMouseDown);
Draggables.unregister(this);
},
currentDelta: function() {
return([
parseInt(Element.getStyle(this.element,'left') || '0'),
parseInt(Element.getStyle(this.element,'top') || '0')]);
},
initDrag: function(event) {
if(!Object.isUndefined(Draggable._dragging[this.element]) &&
Draggable._dragging[this.element]) return;
if(Event.isLeftClick(event)) {
var src = Event.element(event);
if((tag_name = src.tagName.toUpperCase()) && (
tag_name=='INPUT' ||
tag_name=='SELECT' ||
tag_name=='OPTION' ||
tag_name=='BUTTON' ||
tag_name=='TEXTAREA')) return;
var pointer = [Event.pointerX(event), Event.pointerY(event)];
var pos = this.element.cumulativeOffset();
this.offset = [0,1].map( function(i) { return (pointer[i] - pos[i]) });
Draggables.activate(this);
Event.stop(event);
}
},
startDrag: function(event) {
this.dragging = true;
if(!this.delta)
this.delta = this.currentDelta();
if(this.options.zindex) {
this.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0);
this.element.style.zIndex = this.options.zindex;
}
if(this.options.ghosting) {
this._clone = this.element.cloneNode(true);
this._originallyAbsolute = (this.element.getStyle('position') == 'absolute');
if (!this._originallyAbsolute)
Position.absolutize(this.element);
this.element.parentNode.insertBefore(this._clone, this.element);
}
if(this.options.scroll) {
if (this.options.scroll == window) {
var where = this._getWindowScroll(this.options.scroll);
this.originalScrollLeft = where.left;
this.originalScrollTop = where.top;
share/static/alice.js view on Meta::CPAN
var dropped = false;
if(success) {
dropped = Droppables.fire(event, this.element);
if (!dropped) dropped = false;
}
if(dropped && this.options.onDropped) this.options.onDropped(this.element);
Draggables.notify('onEnd', this, event);
var revert = this.options.revert;
if(revert && Object.isFunction(revert)) revert = revert(this.element);
var d = this.currentDelta();
if(revert && this.options.reverteffect) {
if (dropped == 0 || revert != 'failure')
this.options.reverteffect(this.element,
d[1]-this.delta[1], d[0]-this.delta[0]);
} else {
this.delta = d;
}
if(this.options.zindex)
this.element.style.zIndex = this.originalZ;
if(this.options.endeffect)
this.options.endeffect(this.element);
Draggables.deactivate(this);
Droppables.reset();
},
keyPress: function(event) {
if(event.keyCode!=Event.KEY_ESC) return;
this.finishDrag(event, false);
Event.stop(event);
},
endDrag: function(event) {
if(!this.dragging) return;
this.stopScrolling();
this.finishDrag(event, true);
Event.stop(event);
},
draw: function(point) {
var pos = this.element.cumulativeOffset();
if(this.options.ghosting) {
var r = Position.realOffset(this.element);
pos[0] += r[0] - Position.deltaX; pos[1] += r[1] - Position.deltaY;
}
var d = this.currentDelta();
pos[0] -= d[0]; pos[1] -= d[1];
if(this.options.scroll && (this.options.scroll != window && this._isScrollChild)) {
pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft;
pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop;
}
var p = [0,1].map(function(i){
return (point[i]-pos[i]-this.offset[i])
}.bind(this));
if(this.options.snap) {
if(Object.isFunction(this.options.snap)) {
p = this.options.snap(p[0],p[1],this);
} else {
if(Object.isArray(this.options.snap)) {
p = p.map( function(v, i) {
return (v/this.options.snap[i]).round()*this.options.snap[i] }.bind(this));
} else {
p = p.map( function(v) {
return (v/this.options.snap).round()*this.options.snap }.bind(this));
}
}}
var style = this.element.style;
if((!this.options.constraint) || (this.options.constraint=='horizontal'))
style.left = p[0] + "px";
if((!this.options.constraint) || (this.options.constraint=='vertical'))
style.top = p[1] + "px";
if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering
},
stopScrolling: function() {
if(this.scrollInterval) {
clearInterval(this.scrollInterval);
this.scrollInterval = null;
Draggables._lastScrollPointer = null;
}
},
startScrolling: function(speed) {
if(!(speed[0] || speed[1])) return;
this.scrollSpeed = [speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed];
this.lastScrolled = new Date();
this.scrollInterval = setInterval(this.scroll.bind(this), 10);
},
scroll: function() {
var current = new Date();
var delta = current - this.lastScrolled;
this.lastScrolled = current;
if(this.options.scroll == window) {
with (this._getWindowScroll(this.options.scroll)) {
if (this.scrollSpeed[0] || this.scrollSpeed[1]) {
var d = delta / 1000;
this.options.scroll.scrollTo( left + d*this.scrollSpeed[0], top + d*this.scrollSpeed[1] );
}
}
} else {
this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000;
this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000;
}
Position.prepare();
Droppables.show(Draggables._lastPointer, this.element);
Draggables.notify('onDrag', this);
if (this._isScrollChild) {
Draggables._lastScrollPointer = Draggables._lastScrollPointer || $A(Draggables._lastPointer);
Draggables._lastScrollPointer[0] += this.scrollSpeed[0] * delta / 1000;
Draggables._lastScrollPointer[1] += this.scrollSpeed[1] * delta / 1000;
if (Draggables._lastScrollPointer[0] < 0)
Draggables._lastScrollPointer[0] = 0;
if (Draggables._lastScrollPointer[1] < 0)
Draggables._lastScrollPointer[1] = 0;
this.draw(Draggables._lastScrollPointer);
}
if(this.options.change) this.options.change(this);
},
_getWindowScroll: function(w) {
var T, L, W, H;
with (w.document) {
if (w.document.documentElement && documentElement.scrollTop) {
T = documentElement.scrollTop;
L = documentElement.scrollLeft;
} else if (w.document.body) {
T = body.scrollTop;
L = body.scrollLeft;
}
if (w.innerWidth) {
W = w.innerWidth;
H = w.innerHeight;
} else if (w.document.documentElement && documentElement.clientWidth) {
W = documentElement.clientWidth;
H = documentElement.clientHeight;
} else {
W = body.offsetWidth;
H = body.offsetHeight;
}
}
return { top: T, left: L, width: W, height: H };
}
});
share/static/alice.js view on Meta::CPAN
modifiers.ctrl.wanted = true;
} else if(k == 'shift') {
kp++;
modifiers.shift.wanted = true;
} else if(k == 'alt') {
kp++;
modifiers.alt.wanted = true;
} else if(k == 'meta') {
kp++;
modifiers.meta.wanted = true;
} else if(k.length > 1) { //If it is a special key
if(special_keys[k] == code) kp++;
} else if(opt['keycode']) {
if(opt['keycode'] == code) kp++;
} else { //The special keys did not match
if(character == k) kp++;
else {
if(shift_nums[character] && e.shiftKey) { //Stupid Shift key bug created by using lowercase
character = shift_nums[character];
if(character == k) kp++;
}
}
}
}
if(kp == keys.length &&
modifiers.ctrl.pressed == modifiers.ctrl.wanted &&
modifiers.shift.pressed == modifiers.shift.wanted &&
modifiers.alt.pressed == modifiers.alt.wanted &&
modifiers.meta.pressed == modifiers.meta.wanted) {
callback(e);
if(!opt['propagate']) { //Stop the event
e.cancelBubble = true;
e.returnValue = false;
if (e.stopPropagation) {
e.stopPropagation();
e.preventDefault();
}
return false;
}
}
}
this.all_shortcuts[shortcut_combination] = {
'callback':func,
'target':ele,
'event': opt['type']
};
if(ele.addEventListener) ele.addEventListener(opt['type'], func, false);
else if(ele.attachEvent) ele.attachEvent('on'+opt['type'], func);
else ele['on'+opt['type']] = func;
},
'remove':function(shortcut_combination) {
shortcut_combination = shortcut_combination.toLowerCase();
var binding = this.all_shortcuts[shortcut_combination];
delete(this.all_shortcuts[shortcut_combination])
if(!binding) return;
var type = binding['event'];
var ele = binding['target'];
var callback = binding['callback'];
if(ele.detachEvent) ele.detachEvent('on'+type, callback);
else if(ele.removeEventListener) ele.removeEventListener(type, callback, false);
else ele['on'+type] = false;
}
};
function str_repeat(i, m) {
for (var o = []; m > 0; o[--m] = i);
return o.join('');
}
function sprintf() {
var i = 0, a, f = arguments[i++], o = [], m, p, c, x, s = '';
while (f) {
if (m = /^[^\x25]+/.exec(f)) {
o.push(m[0]);
}
else if (m = /^\x25{2}/.exec(f)) {
o.push('%');
}
else if (m = /^\x25(?:(\d+)\$)?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(f)) {
if (((a = arguments[m[1] || i++]) == null) || (a == undefined)) {
throw('Too few arguments.');
}
if (/[^s]/.test(m[7]) && (typeof(a) != 'number')) {
throw('Expecting number but found ' + typeof(a));
}
switch (m[7]) {
case 'b': a = a.toString(2); break;
case 'c': a = String.fromCharCode(a); break;
case 'd': a = parseInt(a); break;
case 'e': a = m[6] ? a.toExponential(m[6]) : a.toExponential(); break;
case 'f': a = m[6] ? parseFloat(a).toFixed(m[6]) : parseFloat(a); break;
case 'o': a = a.toString(8); break;
case 's': a = ((a = String(a)) && m[6] ? a.substring(0, m[6]) : a); break;
case 'u': a = Math.abs(a); break;
case 'x': a = a.toString(16); break;
case 'X': a = a.toString(16).toUpperCase(); break;
}
a = (/[def]/.test(m[7]) && m[2] && a >= 0 ? '+'+ a : a);
c = m[3] ? m[3] == '0' ? '0' : m[3].charAt(1) : ' ';
x = m[5] - String(a).length - s.length;
p = m[5] ? str_repeat(c, x) : '';
o.push(s + (m[4] ? a + p : p + a));
}
else {
throw('Huh ?!');
}
f = f.substring(m[0].length);
}
return o.join('');
}
/* WysiHat - WYSIWYG JavaScript framework, version 0.2.1
* (c) 2008-2010 Joshua Peek
*
* WysiHat is freely distributable under the terms of an MIT-style license.
*--------------------------------------------------------------------------*/
share/static/alice.js view on Meta::CPAN
getRangeAt: function(index) {
var textRange = this._document.selection.createRange();
if (this._selectionExists(textRange))
return Range._fromTextRange(textRange, this._document);
return null;
},
toString: function() {
return this._document.selection.createRange().text;
}
};
return Selection;
})();
window.getSelection = (function() {
var selection = new Selection(document);
return function() { return selection; };
})();
}
Object.extend(Range.prototype, (function() {
function beforeRange(range) {
if (!range || !range.compareBoundaryPoints) return false;
return (this.compareBoundaryPoints(this.START_TO_START, range) == -1 &&
this.compareBoundaryPoints(this.START_TO_END, range) == -1 &&
this.compareBoundaryPoints(this.END_TO_END, range) == -1 &&
this.compareBoundaryPoints(this.END_TO_START, range) == -1);
}
function afterRange(range) {
if (!range || !range.compareBoundaryPoints) return false;
return (this.compareBoundaryPoints(this.START_TO_START, range) == 1 &&
this.compareBoundaryPoints(this.START_TO_END, range) == 1 &&
this.compareBoundaryPoints(this.END_TO_END, range) == 1 &&
this.compareBoundaryPoints(this.END_TO_START, range) == 1);
}
function betweenRange(range) {
if (!range || !range.compareBoundaryPoints) return false;
return !(this.beforeRange(range) || this.afterRange(range));
}
function equalRange(range) {
if (!range || !range.compareBoundaryPoints) return false;
return (this.compareBoundaryPoints(this.START_TO_START, range) == 0 &&
this.compareBoundaryPoints(this.START_TO_END, range) == 1 &&
this.compareBoundaryPoints(this.END_TO_END, range) == 0 &&
this.compareBoundaryPoints(this.END_TO_START, range) == -1);
}
function getNode() {
var parent = this.commonAncestorContainer;
while (parent.nodeType == Node.TEXT_NODE)
parent = parent.parentNode;
var child = parent.childElements().detect(function(child) {
var range = document.createRange();
range.selectNodeContents(child);
return this.betweenRange(range);
}.bind(this));
return $(child || parent);
}
return {
beforeRange: beforeRange,
afterRange: afterRange,
betweenRange: betweenRange,
equalRange: equalRange,
getNode: getNode
};
})());
if (Prototype.Browser.IE) {
Object.extend(Selection.prototype, (function() {
function getNode() {
var range = this._document.selection.createRange();
return $(range.parentElement());
}
function selectNode(element) {
var range = this._document.body.createTextRange();
range.moveToElementText(element);
range.select();
}
return {
getNode: getNode,
selectNode: selectNode
}
})());
} else {
if (typeof Selection == 'undefined') {
var Selection = {}
Selection.prototype = window.getSelection().__proto__;
}
Object.extend(Selection.prototype, (function() {
function getNode() {
if (this.rangeCount > 0)
return this.getRangeAt(0).getNode();
else
return null;
}
function selectNode(element) {
var range = document.createRange();
range.selectNode(element);
this.removeAllRanges();
this.addRange(range);
}
return {
getNode: getNode,
selectNode: selectNode
}
})());
}
document.on("dom:loaded", function() {
function fieldChangeHandler(event, element) {
share/static/alice.js view on Meta::CPAN
} else if (this.unorderedListSelected()) {
selection.selectNode(node.up("ul"));
}
this.execCommand('insertorderedlist', false, null);
}
function insertOrderedList() {
this.toggleOrderedList();
}
function orderedListSelected() {
var element = window.getSelection().getNode();
if (element) return element.match('*[contenteditable=""] ol, *[contenteditable=true] ol, *[contenteditable=""] ol *, *[contenteditable=true] ol *');
return false;
}
function toggleUnorderedList() {
var selection, node;
selection = window.getSelection();
node = selection.getNode();
if (this.unorderedListSelected() && !node.match("ul li:last-child, ul li:last-child *")) {
selection.selectNode(node.up("ul"));
} else if (this.orderedListSelected()) {
selection.selectNode(node.up("ol"));
}
this.execCommand('insertunorderedlist', false, null);
}
function insertUnorderedList() {
this.toggleUnorderedList();
}
function unorderedListSelected() {
var element = window.getSelection().getNode();
if (element) return element.match('*[contenteditable=""] ul, *[contenteditable=true] ul, *[contenteditable=""] ul *, *[contenteditable=true] ul *');
return false;
}
function insertImage(url) {
this.execCommand('insertImage', false, url);
}
function insertHTML(html) {
if (Prototype.Browser.IE) {
var range = window.document.selection.createRange();
range.pasteHTML(html);
range.collapse(false);
range.select();
} else {
this.execCommand('insertHTML', false, html);
}
}
function execCommand(command, ui, value) {
var handler = this.commands.get(command);
if (handler) {
handler.bind(this)(value);
} else {
try {
window.document.execCommand(command, ui, value);
} catch(e) { return null; }
}
document.activeElement.fire("field:change");
}
function queryCommandState(state) {
var handler = this.queryCommands.get(state);
if (handler) {
return handler.bind(this)();
} else {
try {
return window.document.queryCommandState(state);
} catch(e) { return null; }
}
}
function getSelectedStyles() {
var styles = $H({});
var editor = this;
editor.styleSelectors.each(function(style){
var node = editor.selection.getNode();
styles.set(style.first(), Element.getStyle(node, style.last()));
});
return styles;
}
return {
boldSelection: boldSelection,
boldSelected: boldSelected,
underlineSelection: underlineSelection,
underlineSelected: underlineSelected,
italicSelection: italicSelection,
italicSelected: italicSelected,
strikethroughSelection: strikethroughSelection,
indentSelection: indentSelection,
outdentSelection: outdentSelection,
toggleIndentation: toggleIndentation,
indentSelected: indentSelected,
fontSelection: fontSelection,
fontSizeSelection: fontSizeSelection,
colorSelection: colorSelection,
backgroundColorSelection: backgroundColorSelection,
alignSelection: alignSelection,
alignSelected: alignSelected,
linkSelection: linkSelection,
unlinkSelection: unlinkSelection,
linkSelected: linkSelected,
formatblockSelection: formatblockSelection,
toggleOrderedList: toggleOrderedList,
insertOrderedList: insertOrderedList,
orderedListSelected: orderedListSelected,
toggleUnorderedList: toggleUnorderedList,
insertUnorderedList: insertUnorderedList,
unorderedListSelected: unorderedListSelected,
insertImage: insertImage,
insertHTML: insertHTML,
execCommand: execCommand,
queryCommandState: queryCommandState,
getSelectedStyles: getSelectedStyles,
commands: $H({}),
queryCommands: $H({
link: linkSelected,
orderedlist: orderedListSelected,
unorderedlist: unorderedListSelected
}),
styleSelectors: $H({
share/static/alice.js view on Meta::CPAN
function accumulate(node) {
if (mode != EXPECTING_LIST_ITEM) {
if (!line) line = lineContainer = createLine();
previousAccumulation = node;
lineContainer.appendChild(node);
}
}
function getPreviouslyAccumulatedTagName() {
if (previousAccumulation && previousAccumulation.nodeType == Node.ELEMENT_NODE) {
return previousAccumulation.tagName.toLowerCase();
}
}
function flush() {
if (line && line.childNodes.length) {
container.appendChild(line);
line = lineContainer = null;
}
}
function createLine() {
if (mode == ACCUMULATING_LINE) {
return new Element("div");
} else if (mode == ACCUMULATING_LIST_ITEM) {
return new Element("li");
}
}
function insertList(tagName) {
var list = new Element(tagName);
result.appendChild(list);
return list;
}
result = container = new Element("div");
walk(element.childNodes);
flush();
return result.innerHTML;
}
};
})();
WysiHat.Toolbar = Class.create((function() {
function initialize(editor) {
this.editor = editor;
this.element = this.createToolbarElement();
}
function createToolbarElement() {
var toolbar = new Element('div', { 'class': 'editor_toolbar' });
this.editor.insert({before: toolbar});
return toolbar;
}
function addButtonSet(set) {
$A(set).each(function(button){
this.addButton(button);
}.bind(this));
}
function addButton(options, handler) {
options = $H(options);
if (!options.get('name'))
options.set('name', options.get('label').toLowerCase());
var name = options.get('name');
var button = this.createButtonElement(this.element, options);
var handler = this.buttonHandler(name, options);
this.observeButtonClick(button, handler);
var handler = this.buttonStateHandler(name, options);
this.observeStateChanges(button, name, handler);
}
function createButtonElement(toolbar, options) {
var button = new Element('a', {
'class': 'button', 'href': '#'
});
button.update('<span>' + options.get('label') + '</span>');
button.addClassName(options.get('name'));
toolbar.appendChild(button);
return button;
}
function buttonHandler(name, options) {
if (options.handler)
return options.handler;
else if (options.get('handler'))
return options.get('handler');
else
return function(editor) { editor.execCommand(name); };
}
function observeButtonClick(element, handler) {
element.on('click', function(event) {
handler(this.editor);
event.stop();
}.bind(this));
}
function buttonStateHandler(name, options) {
if (options.query)
return options.query;
else if (options.get('query'))
return options.get('query');
else
return function(editor) { return editor.queryCommandState(name); };
}
function observeStateChanges(element, name, handler) {
var previousState;
this.editor.on("selection:change", function(event) {
var state = handler(this.editor);
if (state != previousState) {
previousState = state;
this.updateButtonState(element, name, state);
}
}.bind(this));
}
function updateButtonState(element, name, state) {
if (state)
element.addClassName('selected');
else
element.removeClassName('selected');
}
return {
initialize: initialize,
createToolbarElement: createToolbarElement,
addButtonSet: addButtonSet,
addButton: addButton,
createButtonElement: createButtonElement,
buttonHandler: buttonHandler,
observeButtonClick: observeButtonClick,
buttonStateHandler: buttonStateHandler,
observeStateChanges: observeStateChanges,
updateButtonState: updateButtonState
};
})());
WysiHat.Toolbar.ButtonSets = {};
WysiHat.Toolbar.ButtonSets.Basic = $A([
{ label: "Bold" },
{ label: "Underline" },
{ label: "Italic" }
]);
var Alice = { };
Object.extend(Alice, {
uncacheGravatar: function(content) {
if (!this.timestamp) {
var date = new Date();
this.timestamp = date.getTime();
}
return content.replace(
/(src=".*?gravatar.com\/avatar\/[^?]*\?)/gi,
"$1time=" + this.timestamp + "&"
);
},
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) {
hours -= 12;
ap = "p";
} else {
ap = "a"
}
return sprintf("%d:%02d%s", hours, date.getMinutes(), ap);
share/static/alice.js view on Meta::CPAN
submit: function(form) {
$$('#servers .channelselect').each(function(select) {
$A(select.options).each(function(option) {
option.selected = true;
});
});
new Ajax.Request('/save', {
method: 'get',
parameters: form.serialize(),
onSuccess: function(){Alice.connections.remove()}
});
return false;
},
remove: function() {
alice.windows().each(function(win) {
win.input.disabled = false;
});
$('servers').remove();
},
serverConnection: function(alias, action) {
new Ajax.Request('/say', {
method: 'get',
parameters: {
msg: '/' + action + ' ' + alias,
source: alice.activeWindow().id
}
});
return false;
}
}
});
Element.addMethods({
redraw: function(element){
element = $(element);
var n = document.createTextNode(' ');
element.appendChild(n);
(function(){n.parentNode.removeChild(n)}).defer();
return element;
}
});
Alice.Application = Class.create({
initialize: function() {
this.isFocused = true;
this.window_map = new Hash();
this.previousFocus = 0;
this.connection = new Alice.Connection(this);
this.filters = [];
this.keyboard = new Alice.Keyboard(this);
this.isPhone = window.navigator.platform.match(/(android|iphone)/i) ? 1 : 0;
this.isMobile = this.isPhone || Prototype.Browser.MobileSafari;
window.onload = function () {
setTimeout(this.connection.connect.bind(this.connection), 1000);
}.bind(this);
this.makeSortable();
},
actionHandlers: {
join: function (action) {
var win = this.getWindow(action['window'].id);
if (!win) {
this.insertWindow(action['window'].id, action.html);
win = new Alice.Window(this, action['window'].id, action['window'].title, false, action['window'].hashtag);
this.addWindow(win);
} else {
win.enable();
}
win.nicks = action.nicks;
},
part: function (action) {
this.closeWindow(action['window'].id);
},
nicks: function (action) {
var win = this.getWindow(action['window'].id);
if (win) win.nicks = action.nicks;
},
alert: function (action) {
this.activeWindow().showAlert(action['body']);
},
clear: function (action) {
var win = this.getWindow(action['window'].id);
if (win) {
win.messages.down("ul").update("");
win.lastNick = "";
}
},
connect: function (action) {
action.windows.each(function (win_info) {
var win = this.getWindow(win_info.id);
if (win) {
win.enable();
}
}.bind(this));
if ($('servers')) {
Alice.connections.connectServer(action.session);
}
},
disconnect: function (action) {
action.windows.each(function (win_info) {
var win = this.getWindow(win_info.id);
if (win) {
win.disable();
}
}.bind(this));
if ($('servers')) {
Alice.connections.disconnectServer(action.session);
}
},
focus: function (action) {
if (!action.window_number) return;
if (action.window_number == "next") {
this.nextWindow();
}
else if (action.window_number.match(/^prev/)) {
this.previousWindow();
}
else if (action.window_number.match(/^\d+$/)) {
var tab = $('tabs').down('li', action.window_number);
if (tab) {
var window_id = tab.id.replace('_tab','');
this.getWindow(window_id).focus();
}
}
}
},
toggleHelp: function() {
var help = $('help');
help.visible() ? help.hide() : help.show();
},
toggleConfig: function(e) {
this.connection.getConfig(function (transport) {
alice.activeWindow().input.disabled = true;
$('container').insert(transport.responseText);
}.bind(this));
e.stop();
},
togglePrefs: function(e) {
this.connection.getPrefs(function (transport) {
alice.activeWindow().input.disabled = true;
$('container').insert(transport.responseText);
}.bind(this));
e.stop();
},
toggleLogs: function(e) {
if (this.logWindow && !this.logWindow.closed && this.logWindow.focus) {
this.logWindow.focus();
} else {
this.logWindow = window.open(null, "logs", "resizable=no,scrollbars=no,statusbar=no, toolbar=no,location=no,width=500,height=480");
this.connection.getLog(function (transport) {
this.logWindow.document.write(transport.responseText);
}.bind(this));
}
e.stop();
},
windows: function () {
return this.window_map.values();
},
nth_window: function(n) {
var tab = $('tabs').down('li', n);
if (tab) {
var m = tab.id.match(/([^_]+)_tab/);
if (m) {
return this.window_map.get(m[1]);
}
}
},
openWindow: function(element, title, active, hashtag) {
var win = new Alice.Window(this, element, title, active, hashtag);
this.addWindow(win);
if (active) {
win.focus();
}
return win;
},
addWindow: function(win) {
this.window_map.set(win.id, win);
if (window.fluid)
window.fluid.addDockMenuItem(win.title, win.focus.bind(win));
},
removeWindow: function(win) {
if (win.active) this.focusLast();
if (window.fluid)
window.fluid.removeDockMenuItem(win.title);
if (win.id == this.previousFocus.id) {
this.previousFocus = 0;
}
this.window_map.unset(win.id);
this.connection.closeWindow(win);
win = null;
},
getWindow: function(windowId) {
return this.window_map.get(windowId);
},
activeWindow: function() {
var windows = this.windows();
for (var i=0; i < windows.length; i++) {
if (windows[i].active) return windows[i];
}
if (windows[0]) return windows[0];
},
addFilters: function(list) {
this.filters = this.filters.concat(list);
},
applyFilters: function(content) {
return this.filters.inject(content, function(value, filter) {
return filter(value);
});
},
nextWindow: function() {
var active = this.activeWindow();
var nextTab = active.tab.next();
if (!nextTab)
nextTab = $$('ul#tabs li').first();
if (!nextTab) return;
var id = nextTab.id.replace('_tab','');
if (id != active.id) {
this.getWindow(id).focus();
}
},
focusLast: function() {
if (this.previousFocus && this.previousFocus.id != this.activeWindow().id)
this.previousFocus.focus();
else
this.previousWindow();
},
previousWindow: function() {
var active = this.activeWindow();
share/static/alice.js view on Meta::CPAN
$('tab_overflow_button').removeClassName('unread');
},
updateChannelSelect: function() {
var windows = this.windows();
for (var i=0; i < windows.length; i++) {
var win = windows[i];
if ((win.tab.hasClassName('unread') || win.tab.hasClassName('highlight')) && win.isTabWrapped()) {
this.highlightChannelSelect();
return;
}
}
this.unHighlightChannelSelect();
},
handleAction: function(action) {
if (this.actionHandlers[action.event]) {
this.actionHandlers[action.event].call(this,action);
}
},
displayMessage: function(message) {
var win = this.getWindow(message['window'].id);
if (win) {
win.addMessage(message);
} else {
this.connection.requestWindow(
message['window'].title, message['window'].id, message
);
}
},
focusHash: function(hash) {
if (!hash) hash = window.location.hash;
if (hash) {
hash = decodeURIComponent(hash);
hash = hash.replace(/^#/, "");
var windows = this.windows();
for (var i = 0; i < windows.length; i++) {
var win = windows[i];
if (win.hashtag == hash) {
if (win && !win.active) win.focus();
return;
}
}
}
},
makeSortable: function() {
Sortable.create('tabs', {
overlap: 'horizontal',
constraint: 'horizontal',
format: /(.+)/,
onUpdate: function (res) {
var tabs = res.childElements();
var order = tabs.collect(function(t){
var m = t.id.match(/([^_]+)_tab/);
if (m) return m[1]
});
if (order.length) this.connection.sendTabOrder(order);
}.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 = "";
}
});
Alice.Connection = Class.create({
initialize: function(application) {
this.application = application;
this.len = 0;
this.aborting = false;
this.request = null;
this.seperator = "--xalicex\n";
this.msgid = 0;
this.reconnect_count = 0;
this.reconnecting = false;
},
closeConnection: function() {
this.aborting = true;
if (this.request && this.request.transport)
this.request.transport.abort();
this.aborting = false;
},
connect: function() {
if (this.reconnect_count > 3) {
this.aborting = true;
this.application.activeWindow().showAlert("Alice server is not responding (<a href='javascript:alice.connection.reconnect()'>reconnect</a>)");
return;
}
this.closeConnection();
this.len = 0;
this.reconnect_count++;
var now = new Date();
console.log("opening new connection starting at message " + this.msgid);
this.request = new Ajax.Request('/stream', {
method: 'get',
parameters: {msgid: this.msgid, t: now.getTime() / 1000},
onException: this.handleException.bind(this),
onInteractive: this.handleUpdate.bind(this),
onComplete: this.handleComplete.bind(this)
});
},
reconnect: function () {
this.reconnecting = true;
this.reconnect_count = 0;
this.connect();
},
handleException: function(request, exception) {
console.log("encountered an error with stream.");
if (!this.aborting)
setTimeout(this.connect.bind(this), 2000);
},
handleComplete: function(transport) {
console.log("connection was closed cleanly.");
if (!this.aborting)
setTimeout(this.connect.bind(this), 2000);
},
handleUpdate: function(transport) {
if (this.reconnecting) {
this.application.activeWindow().showHappyAlert("Reconnected to the Alice server");
this.reconnecting = false;
}
this.reconnect_count = 0;
var time = new Date();
var data = transport.responseText.slice(this.len);
var start, end;
start = data.indexOf(this.seperator);
if (start > -1) {
start += this.seperator.length;
end = data.indexOf(this.seperator, start);
if (end == -1) return;
}
else return;
this.len += (end + this.seperator.length) - start;
data = data.slice(start, end);
try {
data = data.evalJSON();
var queue = data.queue;
var length = queue.length;
for (var i=0; i<length; i++) {
if (queue[i].type == "action")
this.application.handleAction(queue[i]);
else if (queue[i].type == "message") {
if (queue[i].msgid) this.msgid = queue[i].msgid;
if (queue[i].timestamp)
queue[i].timestamp = Alice.epochToLocal(queue[i].timestamp);
this.application.displayMessage(queue[i]);
}
}
}
catch (e) {
console.log(e.toString());
}
var lag = time / 1000 - data.time;
if (lag > 5) {
console.log("lag is " + Math.round(lag) + "s, reconnecting.");
this.connect();
}
},
requestWindow: function(title, windowId, message) {
new Ajax.Request('/say', {
method: 'post',
parameters: {source: windowId, msg: "/create " + title},
onSuccess: function (transport) {
this.handleUpdate(transport);
if (message) {
setTimeout(function() {
this.application.displayMessage(message)
}.bind(this), 1000);
}
}.bind(this)
});
},
closeWindow: function(win) {
new Ajax.Request('/say', {
method: 'post',
parameters: {source: win.id, msg: "/close"}
});
},
getConfig: function(callback) {
new Ajax.Request('/config', {
method: 'get',
onSuccess: callback
});
},
getPrefs: function(callback) {
new Ajax.Request('/prefs', {
method: 'get',
onSuccess: callback
});
},
getLog: function(callback) {
new Ajax.Request('/logs', {
method: 'get',
onSuccess: callback
});
},
sendMessage: function(form) {
new Ajax.Request('/say', {
method: 'post',
parameters: form.serialize(),
onException: function (request, exception) {
alert("There was an error sending a message.");
}
});
},
sendTabOrder: function (windows) {
new Ajax.Request('/tabs', {
method: 'post',
parameters: {tabs: windows}
});
},
sendPing: function() {
new Ajax.Request('/ping');
}
});
Alice.Window = Class.create({
initialize: function(application, element, title, active, hashtag) {
this.application = application;
this.element = $(element);
this.title = title;
this.hashtag = hashtag;
this.id = this.element.identify();
this.active = active;
this.tab = $(this.id + "_tab");
this.input = new Alice.Input(this, this.id + "_msg");
this.tabButton = $(this.id + "_tab_button");
this.tabOverflowButton = $(this.id + "_tab_overflow_button");
this.form = $(this.id + "_form");
this.topic = $(this.id + "_topic");
if (this.topic) {
var orig_height = this.topic.getStyle("height");
this.topic.observe("click", function(e) {
if (this.topic.getStyle("height") == orig_height) {
this.topic.setStyle({height: "auto"});
} else {
this.topic.setStyle({height: orig_height});
}
}.bind(this));
}
this.messages = this.element.down('.message_wrap');
this.submit = $(this.id + "_submit");
this.nicksVisible = false;
this.visibleNick = "";
this.visibleNickTimeout = "";
this.nicks = [];
this.messageLimit = 250;
this.submit.observe("click", function (e) {this.input.send(); e.stop()}.bind(this));
this.tab.observe("mousedown", function(e) {
if (!this.active) {this.focus(); this.focusing = true}
}.bind(this));
this.tab.observe("click", function(e) {this.focusing = false}.bind(this));
this.tabButton.observe("click", function(e) {
if (this.active && !this.focusing) this.close()}.bind(this));
this.messages.observe("mouseover", this.showNick.bind(this));
if (Prototype.Browser.Gecko) {
this.resizeMessagearea();
this.scrollToBottom();
}
else if (this.application.isMobile) {
this.messageLimit = 50;
this.messages.select("li").reverse().slice(50).invoke("remove");
}
if (this.active) this.scrollToBottom(true);
this.makeTopicClickable();
setTimeout(function () {
this.messages.select('li.message div.msg').each(function (msg) {
msg.innerHTML = application.applyFilters(msg.innerHTML);
});
}.bind(this), 1000);
},
isTabWrapped: function() {
return this.tab.offsetTop > 0;
},
unFocus: function() {
this.active = false;
this.input.uncancelNextFocus();
this.element.removeClassName('active');
this.tab.removeClassName('active');
this.tabOverflowButton.selected = false;
},
showNick: function (e) {
var li = e.findElement("#" + this.id + " ul.messages li.message");
if (li) {
if (this.nicksVisible || li == this.visibleNick) return;
clearTimeout(this.visibleNickTimeout);
this.visibleNick = li;
var nick; var time;
if (li.hasClassName("consecutive")) {
var stem = li.previous("li:not(.consecutive)");
if (!stem) return;
nick = stem.down(".nickhint");
time = stem.down(".timehint");
} else {
nick = li.down(".nickhint");
time = li.down(".timehint");
}
if (nick || time) {
this.visibleNickTimeout = setTimeout(function(nick, time) {
if (nick) {
nick.style.opacity = 1;
nick.style.webkitTransition = "opacity 0.1s ease-in-out";
}
if (time) {
time.style.webkitTransition = "opacity 0.1s ease-in-out";
time.style.opacity = 1;
}
setTimeout(function(){
if (this.nicksVisible) return;
if (nick) {
nick.style.webkitTransition = "opacity 0.25s ease-in";
nick.style.opacity = 0;
}
if (time) {
time.style.webkitTransition = "opacity 0.25s ease-in";
time.style.opacity = 0;
}
}.bind(this, nick, time) , 1000);
}.bind(this, nick, time), 500);
}
}
else {
this.visibleNick = "";
clearTimeout(this.visibleNickTimeout);
}
},
toggleNicks: function () {
if (this.nicksVisible) {
this.messages.select("span.nickhint").each(function(span){
span.style.webkitTransition = "opacity 0.1s ease-in";
span.style.opacity = 0;
});
this.messages.select("div.timehint").each(function(span){
span.style.webkitTransition = "opacity 0.1s ease-in";
span.style.opacity = 0;
});
}
else {
this.messages.select("span.nickhint").each(function(span){
span.style.webkitTransition = "opacity 0.1s ease-in-out";
span.style.opacity = 1;
});
this.messages.select("div.timehint").each(function(span){
span.style.webkitTransition = "opacity 0.1s ease-in-out";
span.style.opacity = 1;
});
}
this.nicksVisible = !this.nicksVisible;
},
focus: function(event) {
document.title = this.title;
this.application.previousFocus = this.application.activeWindow();
this.application.windows().invoke("unFocus");
this.active = true;
this.tab.addClassName('active');
this.element.addClassName('active');
this.tabOverflowButton.selected = true;
this.markRead();
this.scrollToBottom(true);
if (!this.application.isMobile) this.input.focus();
if (Prototype.Browser.Gecko) {
this.resizeMessagearea();
this.scrollToBottom();
}
this.element.redraw();
window.location.hash = this.hashtag;
window.location = window.location.toString();
this.application.updateChannelSelect();
},
markRead: function () {
this.tab.removeClassName("unread");
this.tab.removeClassName("highlight");
this.tabOverflowButton.removeClassName("unread");
},
share/static/alice.js view on Meta::CPAN
if (message.consecutive) {
var prev = li.previous();
if (prev && prev.hasClassName("avatar") && !prev.hasClassName("consecutive")) {
prev.down('div.msg').setStyle({minHeight: '0px'});
}
}
if (message.event == "say") {
var msg = li.down('div.msg');
msg.innerHTML = this.application.applyFilters(msg.innerHTML);
var nick = li.down('span.nickhint');
if (nick && this.nicksVisible) {
nick.style.webkitTransition = 'none 0 linear';
nick.style.opacity = 1;
}
var time = li.down('div.timehint');
if (time && this.nicksVisible) {
time.style.webkitTransition = 'none 0 linear';
time.style.opacity = 1;
}
if (message.consecutive) {
var avatar = li.previous(".avatar:not(.consecutive)");
if (avatar) avatar.down(".timehint").innerHTML = message.timestamp;
}
}
else if (message.event == "topic") {
this.displayTopic(message.body.escapeHTML());
}
if (!this.application.isFocused && message.highlight && message.window.title != "info") {
message.body = li.down(".msg").innerHTML.stripTags();
Alice.growlNotify(message);
this.application.addMissed();
}
if (message.nicks && message.nicks.length)
this.nicks = message.nicks;
if (this.element.hasClassName('active'))
this.scrollToBottom();
else if (this.title != "info") {
if (message.event == "say") {
this.tab.addClassName("unread");
this.tabOverflowButton.addClassName("unread");
if (this.isTabWrapped()) this.application.highlightChannelSelect();
}
if (message.highlight) {
this.tab.addClassName("highlight");
}
}
var messages = this.messages.down('ul').childElements();
if (messages.length > this.messageLimit) messages.first().remove();
li.select("span.timestamp").each(function(elem) {
elem.innerHTML = Alice.epochToLocal(elem.innerHTML.strip(), this.application.options.timeformat);
elem.style.opacity = 1;
}.bind(this));
this.element.redraw();
},
scrollToBottom: function(force) {
var bottom, height;
if (!force) {
var lastmsg = this.messages.down('ul.messages > li:last-child');
if (!lastmsg) return;
var msgheight = lastmsg.offsetHeight;
bottom = this.messages.scrollTop + this.messages.offsetHeight;
height = this.messages.scrollHeight;
}
if (force || bottom + msgheight + 100 >= height) {
this.messages.scrollTop = this.messages.scrollHeight;
this.element.redraw();
}
},
getNicknames: function() {
return this.nicks;
}
});
Alice.Toolbar = Class.create(WysiHat.Toolbar, {
createButtonElement: function(toolbar, options) {
var button = Element('button');
button.update(options.get('label'));
button.addClassName(options.get('name'));
toolbar.appendChild(button);
return button;
},
observeButtonClick: function(element, handler) {
element.on('click', function(event) {
handler(this.editor, element, this);
this.editor.fire("selection:change");
event.stop();
}.bind(this));
}
});
Alice.Toolbar.ButtonSet = WysiHat.Toolbar.ButtonSets.Basic.concat(
[
{
label: "Colors",
handler: function (editor, button, toolbar) {
var cb = function (color, fg) {
fg ? editor.colorSelection(color) : editor.backgroundColorSelection(color)
};
if (toolbar.picker) {
toolbar.picker.remove();
toolbar.picker = undefined;
} else {
toolbar.picker = new Alice.Colorpicker(button, cb);
}
}
},
{
label: "»",
handler: function (editor, button, toolbar) {
button.up("div.editor_toolbar").removeClassName("visible");
if (toolbar.picker) {
toolbar.picker.remove();
toolbar.picker = undefined;
}
}
}
]
);
Alice.Colorpicker = Class.create({
initialize: function(button, callback) {
var elem = new Element("div").addClassName("color_picker");
var toggle = new Element("div").addClassName("toggle");
var blank = new Element("span").addClassName("blank").addClassName("color");
blank.setStyle({"background-color": "none"});
blank.insert("⃠");
toggle.insert('<span id="fg" class="active">fg</span><span id="bg">bg</span>');
toggle.insert(blank);
elem.insert(toggle);
var colorcontainer = new Element("div").addClassName("colors");
this.colors().each(function(color) {
var box = new Element("span").addClassName("color");
box.setStyle({"background-color": color});
colorcontainer.insert(box);
});
elem.insert(colorcontainer);
button.up('.window').insert(elem);
elem.observe("mousedown", this.clicked.bind(this));
this.elem = elem;
this.cb = callback;
this.fg = true;
},
clicked: function(e) {
e.stop();
var box = e.findElement("span.color");
if (box) {
var color = box.getStyle("background-color");
if (color) this.cb(color, this.fg);
return;
}
if (e.findElement("span#fg")) {
this.elem.down("#bg").removeClassName("active");
this.elem.down("#fg").addClassName("active");
this.fg = true;
return;
}
if (e.findElement("span#bg")) {
this.elem.down("#fg").removeClassName("active");
this.elem.down("#bg").addClassName("active");
this.fg = false;
return;
}
},
remove: function() {
this.elem.remove();
},
colors: function() {
return ["#fff", "#000", "#008", "#080", "#f00", "#800", "#808", "#f80",
"#ff0", "#0f0", "#088", "#0ff", "#00f", "#f0f", "#888", "#ccc"];
}
});
Alice.Input = Class.create({
initialize: function(win, element) {
this.window = win;
this.application = this.window.application;
this.textarea = $(element);
this.disabled = false;
if (this.canContentEditable()) {
this.editor = WysiHat.Editor.attach(this.textarea);
this.element = this.editor;
this.toolbar = new Alice.Toolbar(this.element)
this.toolbar.addButtonSet(Alice.Toolbar.ButtonSet);
this.toolbar.element.observe("click", function(e) {
if (this.toolbar.element.hasClassName("visible")) return;
this.toolbar.element.addClassName("visible");
this.focus();
}.bind(this));
var input = new Element("input", {type: "hidden", name: "html", value: 1});
this.textarea.form.appendChild(input);
document.observe("mousedown", function(e) {
if (!e.findElement(".editor")) this.uncancelNextFocus();
}.bind(this));
this.editor.observe("keydown", function(){this.cancelNextFocus()}.bind(this));
this.editor.observe("keyup", this.updateRange.bind(this));
this.editor.observe("mouseup", this.updateRange.bind(this));
this.editor.observe("paste", this.pasteHandler.bind(this));
this.toolbar.element.on("mouseup","button",function(){
this.cancelNextFocus();
}.bind(this));
} else {
this.element = this.textarea;
}
this.history = [];
this.index = -1;
this.buffer = "";
this.completion = false;
this.focused = false;
this.element.observe("keypress", this.onKeyPress.bind(this));
this.element.observe("blur", this.onBlur.bind(this));
this.element.observe("keydown", this.resize.bind(this));
this.element.observe("cut", this.resize.bind(this));
this.element.observe("paste", this.resize.bind(this));
this.element.observe("change", this.resize.bind(this));
},
setValue: function(value) {
this.editor ? this.editor.update(value) : this.textarea.setValue(value);
},
getValue: function() {
if (this.editor) {
return this.editor.innerHTML;
}
return this.textarea.getValue();
},
onKeyPress: function(event) {
if (event.keyCode != Event.KEY_TAB) {
this.completion = false;
}
},
uncancelNextFocus: function() {
this.skipThisFocus = false;
},
cancelNextFocus: function() {
this.skipThisFocus = true;
},
focus: function(force) {
if (this.disabled) return;
if (!force) {
if (this.focused) return;
if (this.skipThisFocus) {
this.skipThisFocus = false;
return;
}
}
this.focused = true;
if (this.editor) {
var selection = window.getSelection();
selection.removeAllRanges();
if (this.range) {
selection.addRange(this.range);
} else {
var text = document.createTextNode("");
this.editor.appendChild(text);
selection.selectNode(text);
this.range = selection.getRangeAt(0);
}
this.editor.focus();
} else {
this.textarea.focus();
}
},
onBlur: function(e) {
share/static/alice.js view on Meta::CPAN
newLine: function() {
console.log("newLine");
},
send: function() {
this.application.connection.sendMessage(this.textarea.form);
this.history.push(this.getValue());
this.setValue("");
if (this.editor) this.editor.update();
this.index = -1;
this.stash();
this.update();
this.focus(1);
},
completeNickname: function() {
if (this.disabled) return;
if (!this.completion) {
this.completion = new Alice.Completion(this.window.getNicknames());
}
this.completion.next();
},
stopCompletion: function() {
if (this.completion) {
this.completion.restore();
this.completion = false;
}
},
stash: function() {
this.buffer = this.getValue();
},
update: function() {
this.setValue(this.getCommand(this.index));
},
getCommand: function(index) {
if (index == -1) {
return this.buffer;
} else {
return this.history[index];
}
},
resize: function() {
if (this.editor) {
this.textarea.setValue(this.editor.innerHTML);
}
(function() {
if (!this.window.active) return;
var height = this.getContentHeight();
if (height == 0) {
this.element.setStyle({ height: null, top: 0 });
} else if (height <= 150) {
this.element.setStyle({ height: height + "px", top: "-1px" });
}
}).bind(this).defer();
},
getContentHeight: function() {
var element = new Element("div").setStyle({
position: "absolute",
visibility: "hidden",
left: "-" + this.element.getWidth() + "px",
width: this.element.getWidth() - 7 + "px",
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;
},
updateRange: function (e) {
var selection = window.getSelection();
if (selection.rangeCount > 0) {
var range = selection.getRangeAt(0);
this.range = range;
}
},
pasteHandler: function(e) {
var url = e.clipboardData.getData("URL");
if (url) {
e.preventDefault();
this.editor.insertHTML(url);
this.updateRange();
return;
}
var text = e.clipboardData.getData("Text");
if (text) {
e.preventDefault();
text = text.escapeHTML().replace(/\n+/g, "<br>");
this.editor.insertHTML(text);
this.updateRange();
return;
}
}
});
Alice.Keyboard = Class.create({
initialize: function(application) {
this.application = application;
this.isMac = navigator.platform.match(/mac/i);
this.enable();
this.shortcut("Cmd+C", { propagate: true });
this.shortcut("Ctrl+C", { propagate: true });
this.shortcut("Cmd+K");
this.shortcut("Cmd+B");
this.shortcut("Cmd+F");
this.shortcut("Opt+Up");
this.shortcut("Opt+Down");
this.shortcut("Opt+Enter");
this.shortcut("Cmd+Shift+M");
this.shortcut("Cmd+Shift+J");
this.shortcut("Cmd+Shift+K");
this.shortcut("Cmd+Shift+H");
this.shortcut("Enter");
this.shortcut("Esc");
this.shortcut("Tab");
for (var i = 0; i < 10; i++) {
this.shortcut("Cmd+"+i);
if (!this.isMac) this.shortcut("Opt+"+i);
}
},
shortcut: function(name, options) {
var meta = this.isMac ? "Meta" : "Ctrl";
var keystroke = name.replace("Cmd", meta).replace("Opt", "Alt"),
method = "on" + name.replace(/\+/g, "");
window.shortcut.add(keystroke, function(event) {
if (this.enabled) {
this.activeWindow = this.application.activeWindow();
if (method.match(/\d$/)) {
this.onNumeric.call(this, event, method.substr(-1));
}
else {
this[method].call(this, event);
}
delete this.activeWindow;
}
}.bind(this), options);
},
onNumeric: function(event, number) {
var win = this.application.nth_window(number);
if (win) win.focus();
},
onCmdC: function(event) {
if (!this.activeWindow.input.focused)
this.activeWindow.input.cancelNextFocus();
},
onCtrlC: function(event) {
this.onCmdC(event);
},
onCmdK: function() {
this.activeWindow.messages.down("ul").update("");
this.activeWindow.lastNick = "";
},
onCmdShiftM: function() {
this.application.windows().invoke('markRead');
},
onCmdShiftJ: function() {
this.activeWindow.scrollToBottom(1);
},
onCmdShiftK: function() {
this.activeWindow.toggleNicks();
},
onCmdShiftH: function() {
this.application.toggleHelp();
},
onCmdB: function() {
this.application.previousWindow();
},
onCmdF: function() {
this.application.nextWindow();
},
onOptUp: function() {
this.activeWindow.input.previousCommand();
},
onOptDown: function() {
this.activeWindow.input.nextCommand();
},
onOptEnter: function() {
this.activeWindow.input.newLine();
},
onEnter: function() {
this.activeWindow.input.send();
},
share/static/alice.js view on Meta::CPAN
$('helpclose').observe("click", function () { $('help').hide(); });
$$('#config_overlay option').each(function(opt){opt.selected = false});
$('tab_overflow_overlay').observe("change", function (e) {
var win = alice.getWindow($('tab_overflow_overlay').value);
if (win) win.focus();
});
$('config_overlay').observe("change", function (e) {
switch ($('config_overlay').value) {
case "Logs":
alice.toggleLogs(e);
break;
case "Connections":
alice.toggleConfig(e);
break;
case "Preferences":
alice.togglePrefs(e);
break;
case "Logout":
if (confirm("Logout?")) window.location = "/logout";
break;
case "Help":
alice.toggleHelp();
break;
}
$$('#config_overlay option').each(function(opt){opt.selected = false});
});
window.onkeydown = function (e) {
var win = alice.activeWindow();
if (win && !$('config') && !Alice.isSpecialKey(e.which))
win.input.focus();
};
window.onresize = function () {
if (alice.activeWindow()) {
if (Prototype.Browser.Gecko) alice.activeWindow().resizeMessagearea();
alice.activeWindow().scrollToBottom();
}
};
window.onfocus = function () {
if (!alice.isMobile)
window.document.body.removeClassName("blurred");
if (alice.activeWindow())
alice.activeWindow().input.focus();
alice.isFocused = true
alice.clearMissed();
};
window.status = " ";
window.onblur = function () {
if (!alice.isMobile)
window.document.body.addClassName("blurred");
alice.isFocused = false
};
window.onhashchange = alice.focusHash.bind(alice);
window.onorientationchange = function() {
alice.activeWindow().scrollToBottom(true);
};
alice.addFilters([
function(content) {
var filtered = content;
filtered = filtered.replace(
/(<a href=\"(:?.*?\.(:?wav|mp3|ogg|aiff|m4a))")/gi,
"<img src=\"/static/image/play.png\" " +
"onclick=\"Alice.playAudio(this)\" class=\"audio\"/>$1");
return filtered;
},
function (content) {
var filtered = content;
if (alice.options.images == "show") {
filtered = filtered.replace(
/(<a[^>]*>)([^<]*\.(:?jpe?g|gif|png|bmp|svg)(:?\?v=0)?)</gi,
"$1<img src=\"http://i.usealice.org/$2\" onload=\"Alice.loadInlineImage(this)\" " +
"alt=\"Loading Image...\" title=\"$2\" style=\"display:none\"/><");
}
return filtered;
}
]);
});
}