Alice
view release on metacpan or search on metacpan
share/static/alice.js view on Meta::CPAN
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.
*--------------------------------------------------------------------------*/
var WysiHat = {};
WysiHat.Editor = {
attach: function(textarea) {
var editArea;
textarea = $(textarea);
var id = textarea.id + '_editor';
if (editArea = $(id)) return editArea;
editArea = new Element('div', {
'id': id,
'class': 'editor',
'contentEditable': 'true'
});
editArea.update(WysiHat.Formatting.getBrowserMarkupFrom(textarea.value));
Object.extend(editArea, WysiHat.Commands);
textarea.insert({before: editArea});
textarea.hide();
return editArea;
}
};
WysiHat.BrowserFeatures = (function() {
function createTmpIframe(callback) {
var frame, frameDocument;
frame = new Element('iframe');
frame.setStyle({
position: 'absolute',
left: '-1000px'
});
frame.onFrameLoaded(function() {
if (typeof frame.contentDocument !== 'undefined') {
frameDocument = frame.contentDocument;
} else if (typeof frame.contentWindow !== 'undefined' && typeof frame.contentWindow.document !== 'undefined') {
frameDocument = frame.contentWindow.document;
}
frameDocument.designMode = 'on';
callback(frameDocument);
frame.remove();
});
$(document.body).insert(frame);
}
var features = {};
function detectParagraphType(document) {
document.body.innerHTML = '';
document.execCommand('insertparagraph', false, null);
var tagName;
element = document.body.childNodes[0];
if (element && element.tagName)
tagName = element.tagName.toLowerCase();
if (tagName == 'div')
features.paragraphType = "div";
else if (document.body.innerHTML == "<p><br></p>")
features.paragraphType = "br";
else
features.paragraphType = "p";
}
function detectIndentType(document) {
document.body.innerHTML = 'tab';
document.execCommand('indent', false, null);
var tagName;
element = document.body.childNodes[0];
if (element && element.tagName)
tagName = element.tagName.toLowerCase();
features.indentInsertsBlockquote = (tagName == 'blockquote');
}
features.run = function run() {
share/static/alice.js view on Meta::CPAN
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) {
var value;
if (element.contentEditable == 'true')
value = element.innerHTML;
else if (element.getValue)
value = element.getValue();
if (value && element.previousValue != value) {
element.fire("field:change");
element.previousValue = value;
}
}
$(document.body).on("keyup", 'input,textarea,*[contenteditable=""],*[contenteditable=true]', fieldChangeHandler);
});
WysiHat.Commands = (function(window) {
function boldSelection() {
this.execCommand('bold', false, null);
}
function boldSelected() {
return this.queryCommandState('bold');
}
function underlineSelection() {
this.execCommand('underline', false, null);
}
function underlineSelected() {
return this.queryCommandState('underline');
}
function italicSelection() {
this.execCommand('italic', false, null);
}
function italicSelected() {
return this.queryCommandState('italic');
}
function strikethroughSelection() {
this.execCommand('strikethrough', false, null);
}
function indentSelection() {
if (Prototype.Browser.Gecko) {
var selection, range, node, blockquote;
selection = window.getSelection();
range = selection.getRangeAt(0);
node = selection.getNode();
if (range.collapsed) {
range = document.createRange();
range.selectNodeContents(node);
selection.removeAllRanges();
selection.addRange(range);
}
blockquote = new Element('blockquote');
range = selection.getRangeAt(0);
range.surroundContents(blockquote);
} else {
this.execCommand('indent', false, null);
}
}
function outdentSelection() {
this.execCommand('outdent', false, null);
}
function toggleIndentation() {
if (this.indentSelected()) {
share/static/alice.js view on Meta::CPAN
function backgroundColorSelection(color) {
if(Prototype.Browser.Gecko) {
this.execCommand('hilitecolor', false, color);
} else {
this.execCommand('backcolor', false, color);
}
}
function alignSelection(alignment) {
this.execCommand('justify' + alignment);
}
function alignSelected() {
var node = window.getSelection().getNode();
return Element.getStyle(node, 'textAlign');
}
function linkSelection(url) {
this.execCommand('createLink', false, url);
}
function unlinkSelection() {
var node = window.getSelection().getNode();
if (this.linkSelected())
window.getSelection().selectNode(node);
this.execCommand('unlink', false, null);
}
function linkSelected() {
var node = window.getSelection().getNode();
return node ? node.tagName.toUpperCase() == 'A' : false;
}
function formatblockSelection(element){
this.execCommand('formatblock', false, element);
}
function toggleOrderedList() {
var selection, node;
selection = window.getSelection();
node = selection.getNode();
if (this.orderedListSelected() && !node.match("ol li:last-child, ol li:last-child *")) {
selection.selectNode(node.up("ol"));
} 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({
fontname: 'fontFamily',
fontsize: 'fontSize',
forecolor: 'color',
hilitecolor: 'backgroundColor',
backcolor: 'backgroundColor'
})
};
})(window);
if (Prototype.Browser.IE) {
Object.extend(Selection.prototype, (function() {
function setBookmark() {
share/static/alice.js view on Meta::CPAN
function accumulateInlineElement(tagName, node) {
var element = node.cloneNode(false);
if (tagName == "span") {
if ($(node).getStyle("fontWeight") == "bold") {
element = new Element("strong");
} else if ($(node).getStyle("fontStyle") == "italic") {
element = new Element("em");
}
}
accumulate(element);
lineContainer = element;
}
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" }
]);
/* SWFObject v2.2 <http://code.google.com/p/swfobject/>
is released under the MIT License <http://www.opensource.org/licenses/mit-license.php>
*/
var swfobject=function(){var D="undefined",r="object",S="Shockwave Flash",W="ShockwaveFlash.ShockwaveFlash",q="application/x-shockwave-flash",R="SWFObjectExprInst",x="onreadystatechange",O=window,j=document,t=navigator,T=false,U=[h],o=[],N=[],I=[],l,...
(function() {
if (window.WebSocket && !window.WEB_SOCKET_FORCE_FLASH) return;
var logger;
if (window.WEB_SOCKET_LOGGER) {
logger = WEB_SOCKET_LOGGER;
} else if (window.console && window.console.log && window.console.error) {
logger = window.console;
} else {
logger = {log: function(){ }, error: function(){ }};
}
if (swfobject.getFlashPlayerVersion().major < 10) {
logger.error("Flash Player >= 10.0.0 is required.");
return;
}
if (location.protocol == "file:") {
logger.error(
"WARNING: web-socket-js doesn't work in file:///... URL " +
share/static/alice.js view on Meta::CPAN
removeImage: function(e) {
e.stop();
var div = e.findElement('div.image');
if (div) {
var a = div.down("a");
var id = a.identify();
a.update(a.href);
a.style.display = "inline";
div.replace(a);
var contain = a.up();
contain.innerHTML = contain.innerHTML.replace("\n", "");
var a = $(id);
a.observe("click", function(e){e.stop();this.inlineImage(a)}.bind(this));
}
},
inlineImage: function(a) {
a.stopObserving("click");
var src = a.readAttribute("img") || a.innerHTML;
var prefix = alice.options.image_prefix;
var img = new Element("IMG", {src: prefix + src});
img.hide();
img.observe("load", function(){
var wrap = new Element("DIV", {"class": "image"});
var hide = new Element("A", {"class": "hideimg"});
var position = this.captureScrollPosition();
img.show();
a.replace(wrap);
wrap.insert(a);
a.update(img);
a.insert(hide);
a.style.display = "inline-block";
hide.observe("click", this.removeImage.bind(this));
hide.update("hide");
this.scrollToPosition(position);
}.bind(this));
a.insert({after: img});
}
});
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(e) {e.stop()});
element.on('mouseup', function(event) {
alice.input.focus();
handler(this.editor, element, this);
this.editor.fire("selection:change");
event.stop();
}.bind(this));
},
});
Object.extend(Alice.Toolbar, {
updateColors: function (editor) {
var range = alice.input.range || editor;
if (range) {
var node = range.getNode();
var fg = node.getStyle("color");
var bg = node.getStyle("background-color");
var button = alice.input.toolbar.element.down("button.colors");
button.setStyle({"border-color": fg, "background-color": bg});
}
return 1;
}
});
Alice.Toolbar.ButtonSet = [
{
label: "",
name: "colors",
query: Alice.Toolbar.updateColors,
handler: function (editor, button, toolbar) {
var cb = function (color, fg) {
if (fg) {
button.setStyle({"border-color": color})
editor.colorSelection(color);
} else {
button.setStyle({"background-color": color});
editor.backgroundColorSelection(color);
}
};
if (toolbar.picker) {
toolbar.picker.remove();
toolbar.picker = undefined;
} else {
toolbar.picker = new Alice.Colorpicker(button, cb);
}
}
},
{
label: "b",
name: "bold",
handler: function (editor, button, toolbar) {
editor.boldSelection();
}
},
{
label: "i",
name: "italic",
handler: function (editor, button, toolbar) {
editor.italicSelection();
}
},
{
label: "u",
name: "underline",
handler: function (editor, button, toolbar) {
var elem = toolbar.element.down(".underline");
if (elem.hasClassName("selected"))
elem.removeClassName("selected");
else
elem.addClassName("selected");
editor.underlineSelection();
}
}
];
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);
document.body.insert(elem);
elem.observe("mousedown", this.clicked.bind(this));
elem.observe("mouseup", function(e) {e.stop()});
this.button = button;
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(application, element) {
this.application = 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);
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.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));
}
this.history = [];
this.index = -1;
this.buffer = "";
this.completion = false;
this.focused = false;
if (!this.application.isMobile) this.focus();
this.element.observe("blur", this.onBlur.bind(this));
},
setValue: function(value) {
this.textarea.setValue(value);
if (this.editor) {
this.editor.update(value);
var text = document.createElement("BR");
this.editor.appendChild(text);
}
},
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;
this.element.stopObserving("keypress");
}
},
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) {
this.focused = false;
},
previousCommand: function() {
if (this.index-- == -1) {
this.index = this.history.length - 1;
this.stash();
}
this.update();
},
nextCommand: function() {
if (this.index++ == -1) {
this.stash();
} else if (this.index == this.history.length) {
this.index = -1;
}
this.update();
},
newLine: function() {
this.application.log("newLine");
},
send: function() {
var msg = this.getValue();
if (msg.length > 1024*2) {
alert("That message is way too long, dude.");
return;
}
if (this.editor) this.textarea.value = msg;
var success = this.application.connection.sendMessage(this.textarea.form);
if (success) {
this.history.push(msg);
this.setValue("");
if (this.editor) this.editor.update();
this.index = -1;
this.stash();
this.update();
this.focus(1);
}
else {
alert("Could not send message, not connected!");
}
},
completeNickname: function(prev) {
if (this.disabled) return;
if (!this.completion) {
this.completion = new Alice.Completion(this.application.activeWindow().getNicknames(), this.editor);
this.element.observe("keypress", this.onKeyPress.bind(this));
}
if (prev)
this.completion.prev();
else
this.completion.next();
},
stopCompletion: function() {
if (this.completion) {
this.completion.restore();
this.completion = false;
this.element.stopObserving("keypress");
}
},
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() {
(function() {
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: "0px" });
}
}).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 || Prototype.Browser.IE);
},
updateRange: function (e) {
var selection = window.getSelection();
if (selection.rangeCount > 0) {
var range = selection.getRangeAt(0);
this.range = range;
}
},
pasteHandler: function(e) {
if (!e.clipboardData) return;
var items = e.clipboardData.items;
if (items) {
var output = "";
for (var i=0; i < items.length; i++) {
var blob = items[i].getAsFile();
if (blob && blob.type.match(/image/)) {
e.stop();
var fd = new FormData();
fd.append("image", blob);
fd.append("key", "f1f60f1650a07bfe5f402f35205dffd4");
var xhr = new XMLHttpRequest();
xhr.open("POST", "http://api.imgur.com/2/upload.json");
xhr.onload = function() {
var url = xhr.responseText.evalJSON();
this.editor.insertHTML(url.upload.links.original);
this.updateRange();
}.bind(this);
xhr.send(fd);
return;
}
}
}
var text = e.clipboardData.getData("Text");
if (text) {
e.preventDefault();
text = text.escapeHTML().replace(/\n+/g, "<br>\n");
this.editor.insertHTML(text);
this.updateRange();
return;
}
var url = e.clipboardData.getData("URL");
if (url) {
e.preventDefault();
this.editor.insertHTML(url);
this.updateRange();
return;
}
}
});
Alice.Keyboard = Class.create({
initialize: function(application) {
this.application = application;
this.isMac = navigator.platform.match(/mac/i);
this.lastCycle = 0;
this.cycleDelay = 300;
this.enable();
if (!this.application.isMobile) {
this.shortcut("Cmd+C", { propagate: true });
this.shortcut("Ctrl+C", { propagate: true });
this.shortcut("Cmd+B");
this.shortcut("Cmd+I");
this.shortcut("Cmd+Shift+U");
this.shortcut("Opt+Up");
this.shortcut("Opt+Down");
this.shortcut("Cmd+Shift+M");
this.shortcut("Cmd+Shift+J");
this.shortcut("Cmd+Shift+K");
this.shortcut("Cmd+K");
this.shortcut("Cmd+Shift+Left");
this.shortcut("Cmd+Shift+Right");
this.shortcut("Cmd+Shift+H");
this.shortcut("Cmd+Shift+L");
this.shortcut("Cmd+U");
this.shortcut("Esc");
this.shortcut("Cmd", { propagate: true });
this.shortcut("Tab", { propagate: true });
this.shortcut("Shift+Tab", { propagate: true });
for (var i = 0; i < 10; i++) {
this.shortcut("Cmd+"+i);
if (!this.isMac) this.shortcut("Opt+"+i);
}
}
this.shortcut("Enter");
},
shortcut: function(name, options) {
var meta = this.isMac ? "Meta" : "Ctrl";
var keystroke = name.replace("Cmd", meta).replace("Opt", "Alt"),
method = "on" + name.replace(/\+/g, "");
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);
},
onCmd: function(e) {
if (e.keyCode == 186) {
e.stop();
this.application.nextUnreadWindow();
}
},
onNumeric: function(event, number) {
var win = this.application.nth_window(number);
if (number == 0) {
win = this.application.info_window();
}
if (win) win.focus();
},
onCmdC: function(event) {
this.application.input.cancelNextFocus();
},
onCtrlC: function(event) {
this.onCmdC(event);
},
onCmdK: function() {
this.activeWindow.clearMessages();
this.application.connection.sendMessage({
msg: "/clear",
source: this.activeWindow.id,
});
},
onCmdB: function() {
if (this.application.input.editor) {
this.application.input.focus();
this.application.input.editor.boldSelection();
}
},
onCmdShiftU: function() {
if (this.application.input.editor) {
this.application.input.focus();
this.application.input.editor.underlineSelection();
}
},
onCmdI: function() {
if (this.application.input.editor) {
this.application.input.focus();
this.application.input.editor.italicSelection();
}
},
onCmdU: function() {
this.application.nextUnreadWindow();
},
onCmdShiftM: function() {
this.application.windows().invoke('markRead');
},
onCmdShiftJ: function() {
this.activeWindow.scrollToPosition(0);
},
onCmdShiftK: function() {
this.application.toggleOverlay();
},
onCmdRight: function() {
this.application.nextWindow();
},
onCmdShiftL: function() {
this.application.nextWindow();
},
onCmdShiftRight: function() {
this.application.nextWindow();
},
onCmdLeft: function() {
this.application.previousWindow();
},
onCmdShiftH: function() {
this.application.previousWindow();
},
onCmdShiftLeft: function() {
this.application.previousWindow();
},
onOptUp: function() {
this.application.input.previousCommand();
},
onOptDown: function() {
this.application.input.nextCommand();
},
onEnter: function() {
this.application.input.send();
},
onTab: function(e) {
if (!e.findElement('div.config')) {
e.stop();
this.application.input.completeNickname();
}
},
onShiftTab: function(e) {
if (!e.findElement('div.config')) {
e.stop();
this.application.input.completeNickname(true);
}
},
onEsc: function() {
this.application.input.stopCompletion();
},
enable: function() {
this.enabled = true;
},
disable: function() {
this.enabled = false;
}
});
Alice.Completion = Class.create({
initialize: function(candidates, editor) {
var range = this.getRange();
if (!range) return;
this.element = range.startContainer;
this.editor = editor;
if (this.element == this.editor) {
this.addTextNode();
}
this.value = this.element.data || "";
this.index = range.startOffset;
this.findStem();
this.matches = this.matchAgainst(candidates);
this.matchIndex = -1;
},
addTextNode: function() {
this.editor.innerHTML = "";
var node = document.createTextNode("");
this.editor.appendChild(node);
var selection = window.getSelection();
selection.removeAllRanges();
selection.selectNode(node);
range = selection.getRangeAt(0);
this.element = node;
},
getRange: function() {
var selection = window.getSelection();
if (selection.rangeCount > 0) {
return selection.getRangeAt(0);
}
if (document.createRange) {
return document.createRange();
}
return null;
},
setRange: function(range) {
if (!range) return;
var selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(range);
},
next: function() {
if (!this.matches.length) return;
if (++this.matchIndex == this.matches.length) this.matchIndex = 0;
this.complete();
},
prev: function() {
if (!this.matches.length) return;
if (--this.matchIndex <= 0) this.matchIndex = this.matches.length - 1;
this.complete();
},
complete: function() {
var match = this.matches[this.matchIndex];
match += this.leftOffset == 0 ? ":\u00a0" : "\u00a0";
this.restore(match, this.leftOffset + match.length);
},
restore: function(stem, index) {
if (!this.element.parentNode)
this.addTextNode();
this.element.data = this.stemLeft + (stem || this.stem) + this.stemRight;
this.setCursorToIndex(Object.isUndefined(index) ? this.index : index);
},
setCursorToIndex: function(index) {
var range = this.getRange();
range.setStart(this.element, index);
range.setEnd(this.element, index);
this.setRange(range);
},
findStem: function() {
var left = [], right = [], chr, index, length = this.value.length;
( run in 0.522 second using v1.01-cache-2.11-cpan-39bf76dae61 )