// Copyright (c) 2006 spinelz.org (http://script.spinelz.org/) // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. /** * Element class */ Object.extend(Element, { elementNode: 1, textNode: 3, isElementNode: function(element) { return element.nodeType == Element.elementNode; }, isTextNode: function(element) { return element.nodeType == Element.textNode; }, isWhitespace: function(element) { return (Element.isTextNode(element) && !/\S/.test(element.nodeValue)); }, hasTagName: function(element, tagName) { return (Element.isElementNode(element) && element.tagName.toLowerCase() == tagName.toLowerCase()); }, getTagNodes: function(element, tree) { return this.getElementsByNodeType(element, Element.elementNode, tree); }, getTextNodes: function(element, tree) { return this.getElementsByNodeType(element, Element.textNode, tree); }, getChildNodesWithoutWhitespace: function(element) { return $A(element.childNodes).select(function(node) { return Element.isElementNode(node) || !Element.isWhitespace(node); }); }, getElementsByNodeType: function(element, nodeType, tree) { element = ($(element) || document.body); var nodes = element.childNodes; var result = []; for (var i = 0; i < nodes.length; i++) { if (nodes[i].nodeType == nodeType) result.push(nodes[i]); if (tree && Element.isElementNode(nodes[i])) result = result.concat(this.getElementsByNodeType(nodes[i], nodeType, tree)); } return result; }, getParentByClassName: function(className, element) { var parent = element.parentNode; if (!parent || (parent.tagName == 'BODY')) return null; else if (!parent.className) return Element.getParentByClassName(className, parent); else if (Element.hasClassName(parent, className)) return parent; else return Element.getParentByClassName(className, parent); }, getParentByTagName: function(tagNames, element) { var parent = element.parentNode; if (parent.tagName == 'BODY') return null; var index = tagNames.join('/').toUpperCase().indexOf(parent.tagName.toUpperCase(), 0); if (index >= 0) return parent; else return Element.getParentByTagName(tagNames, parent); }, getFirstElementByClassNames: function(element, classNames, tree) { if (!element || !((typeof(classNames) == 'object') && (classNames.constructor == Array))) { return; } element = (element || document.body); var nodes = element.childNodes; for (var i = 0; i < nodes.length; i++) { for (var j = 0; j < classNames.length; j++) { if (!Element.isElementNode(nodes[i])) { continue; } else if (Element.hasClassName(nodes[i], classNames[j])) { return nodes[i]; } else if (tree) { var result = this.getFirstElementByClassNames(nodes[i], classNames, tree); if (result) return result; } } } return; }, getElementsByClassNames: function(element, classNames) { if (!element || !((typeof(classNames) == 'object') && (classNames.constructor == Array))) { return; } var nodes = []; classNames.each(function(c) { nodes = nodes.concat(document.getElementsByClassName(c, element)); }); return nodes; }, getWindowHeight: function() { if (window.innerHeight) { return window.innerHeight; // Mozilla, Opera, NN4 } else if (UserAgent.isIE() && !UserAgent.isIE7()) { return Element.body().clientHeight; } else { return Element.body().offsetHeight; } return 0; }, getWindowWidth:function() { if (UserAgent.isIE() && !UserAgent.isIE7()) { return Element.body().clientWidth; } else { return Element.body().offsetWidth; } return 0; }, getMaxZindex: function(element) { element = $(element); if (!element) { element = document.body; } if (!Element.isElementNode(element)) return 0; var maxZindex = 0; if (element.style) maxZindex = parseInt(Element.getStyle(element, "z-index")); if (isNaN(maxZindex)) maxZindex = 0; var tmpZindex = 0; var elements = element.childNodes; for (var i = 0; i < elements.length; i++) { if (elements[i] && elements[i].tagName) { tmpZindex = Element.getMaxZindex(elements[i]); if (maxZindex < tmpZindex) maxZindex = tmpZindex; } } return maxZindex; }, select: function(element, value) { $A($(element).options).each(function(opt) { opt.selected = (opt.value == value); }); }, selectAll: function(element) { $A($(element).options).each(function(opt) { opt.selected = true; }); }, removeOptions: function(element) { $A($(element).options).each(function(opt) { if (opt.selected) Element.remove(opt); }); }, getSelectedOptions: function(element) { return $A($(element).options).select(function(opt) { return opt.selected; }); }, check: function(elements, id) { elements.each(function(element) { element = $(element); if (element) element.checked = (element.id == id); }); }, outerHTML: function(element) { element = $(element); var html = ''; if (Element.isTextNode(element)) { html = element.nodeValue; } else if (Element.isElementNode(element)) { if (element.outerHTML) { html = element.outerHTML; } else { var attrList = [element.tagName]; var attributes = element.attributes; if (attributes) { $A(attributes).each(function(attr) { attrList.push(attr.name + '="' + attr.value.escapeHTML().replace(/"/, '"') + '"'); }); } html = "<" + attrList.join(' ') + ">" + element.innerHTML + ""; } } return html; }, // too late eventHTML: function(element) { return $A(element.attributes).map(function(attr) { if (attr.name.match(/^on(\w)+/)) { return attr.name + '="' + attr.value + '"'; } else { return ''; } }).join(' '); }, attributeHTML: function(element, attribute) { var html = ''; if (element[attribute]) { html = element[attribute].toString().replace(/\'/g, '\"'); html = attribute + "='(" + html + ")()'"; } return html; }, replaceOptions: function(element, options) { element = $(element); element.innerHTML = ''; var df = document.createDocumentFragment(); options.each(function(values) { df.appendChild(Builder.node('option', {value: values.last()}, [values.first().unescapeHTML()])); }); $(element).appendChild(df); }, body: function() { return document.documentElement || document.body; }, scrollTop: function() { return Element.body().scrollTop; }, scrollLeft: function() { return Element.body().scrollLeft; }, // for performance setStyle: function(element, style) { element = $(element); var eStyle = element.style; for (var name in style) eStyle[name.camelize()] = style[name]; return element; }, appendToBody: function(element) { element = $(element); Element.removeFromBody(element.id) document.body.appendChild(element); }, removeFromBody: function(dom_id) { $A(document.body.childNodes).each(function(node){ if (node.id == dom_id) node.remove(); }); } }); Element.addMethods({setStyle: Element.setStyle}); /** * Array */ Object.extend(Array.prototype, { insert : function(index, element) { this.splice(index, 0 , element); }, remove : function(index) { this.splice(index, 1); } }); /** * String */ Object.extend(String.prototype, { getPrefix: function(delimiter) { if (!delimiter) delimiter = '_'; return this.split(delimiter)[0]; }, getSuffix: function(delimiter) { if (!delimiter) delimiter = '_'; return this.split(delimiter).pop(); }, appendPrefix: function(prefix, delimiter) { if (!delimiter) delimiter = '_'; return this + delimiter + prefix; }, appendSuffix: function(suffix, delimiter) { if (!delimiter) delimiter = '_'; return this + delimiter + suffix; }, toElement: function() { var tmpNode = document.createElement('div'); tmpNode.innerHTML = this; return tmpNode.firstChild; } }); /** * CssUtil */ var CssUtil = Class.create(); CssUtil.getInstance = function(prefix, style) { var newStyle = CssUtil.appendPrefix(prefix, style); return new CssUtil([style, newStyle]); } CssUtil.appendPrefix = function(prefix, suffixes) { var newHash = {}; $H(suffixes).each(function(pair) { newHash[pair[0]] = prefix + suffixes[pair[0]]; }); return newHash; } CssUtil.getCssRules = function(sheet) { return sheet.rules || sheet.cssRules; } CssUtil.getCssRuleBySelectorText = function(selector) { var rule = null; $A(document.styleSheets).each(function(s) { var rules = CssUtil.getCssRules(s); rule = $A(rules).detect(function(r) { if (!r.selectorText) return false; return r.selectorText.toLowerCase() == selector.toLowerCase(); }); if (rule) throw $break; }); return rule; } /* CssUtil.require = function(file, attributes, parent) { var links = document.getElementsByTagName('link'); var regex = /^.*\.css/; var match = file.match(regex) alert(file) regex.compile(match); $A(links).each(function(ln) { if (ln.href.match(regex)) { } }); // attributes = Object.extend({ // href: file, // media: 'screen', // rel: 'stylesheet', // type: 'text/css'}, attributes); // var node = Builder.node('link', attributes); // if (!parent) parent = document.body; // parent.appendChild(node); // alert(file); } */ CssUtil.prototype = { initialize: function(styles) { if (!((typeof(styles) == 'object') && (styles.constructor == Array))) { throw 'CssUtil#initialize: argument must be a Array object!'; } this.styles = styles; }, getClasses: function(key) { return this.styles.collect(function(s) { return s[key]; }); }, joinClassNames: function(key) { return this.getClasses(key).join(' '); }, allJoinClassNames: function() { var classes = {}; $H(this.styles.first()).each(function(pair) { classes[pair.key] = this.joinClassNames(pair.key); }.bind(this)); return classes; }, addClassNames: function(element, key) { this.styles.each(function(s) { Element.addClassName(element, s[key]); }); }, removeClassNames: function(element, key) { this.styles.each(function(s) { Element.removeClassName(element, s[key]); }); }, refreshClassNames: function(element, key) { element.className = ''; this.addClassNames(element, key); }, hasClassName: function(element, key) { return this.styles.any(function(s) { return Element.hasClassName(element, s[key]); }); } } /** * Hover */ var Hover = Class.create(); Hover.prototype = { initialize: function(element) { this.options = Object.extend({ defaultClass: '', hoverClass: '', cssUtil: '', list: false, beforeToggle: function() { return true; } }, arguments[1] || {}); var element = $(element); if (this.options.list) { var nodes = element.childNodes; for (var i = 0; i < nodes.length; i++) { if (Element.isElementNode(nodes[i])) { this.build(nodes[i]); } } } else { this.build(element); } this.element = element; }, build: function(element) { this.normal = this.getNormalClass(element); this.hover = this.getHoverClass(this.normal); if (this.options.cssUtil) { this.normal = this.options.cssUtil.joinClassNames(normal); this.hover = this.options.cssUtil.joinClassNames(hover); } this.setHoverEvent(element); }, setHoverEvent: function(element) { this.mouseout = this.toggle.bindAsEventListener(this, element, this.normal); this.mouseover = this.toggle.bindAsEventListener(this, element, this.hover); Event.observe(element, "mouseout", this.mouseout); Event.observe(element, "mouseover", this.mouseover); }, toggle: function(event, element, className) { Event.stop(event); if (this.options.beforeToggle()) element.className = className; }, getNormalClass: function(element) { var className = (this.options.defaultClass || element.className); return (className || ''); }, getHoverClass: function(defaultClass) { var className = this.options.hoverClass; if (!className) { className = defaultClass.split(' ').collect(function(c) { return c + 'Hover'; }).join(' '); } return className; }, destroy: function() { Event.stopObserving(this.element, 'mouseout', this.mouseout); Event.stopObserving(this.element, 'mouseover', this.mouseover); this.mouseout = null; this.mouseover = null; }, refresh: function() { this.destroy(); this.build(this.element); } } /** * Date */ Object.extend(Date.prototype, { msPerDay: function() { return 24 * 60 * 60 * 1000; }, advance: function(options) { return new Date(this.getTime() + this.msPerDay() * options.days); }, days: function() { var date = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0); return Math.round(date.getTime() / this.msPerDay()); }, toHash: function() { return { year: this.getFullYear(), month: this.getMonth(), day: this.getDate(), hour: this.getHours(), min: this.getMinutes(), sec: this.getSeconds() } }, sameYear: function(date) { return this.getFullYear() == date.getFullYear(); }, sameMonth: function(date) { return this.sameYear(date) && this.getMonth() == date.getMonth(); }, sameDate: function(date) { return this.sameYear(date) && this.sameMonth(date) && this.getDate() == date.getDate(); }, betweenDate: function(start, finish) { var myDays = this.days(); return (start.days() <= myDays && myDays <= finish.days()); }, betweenTime: function(start, finish) { var myTime = this.getTime(); return (start.getTime() <= myTime && myTime <= finish.getTime()); }, strftime: function(format) { return DateUtil.simpleFormat(format)(this); } }); /** * DateUtil */ var DateUtil = { dayOfWeek: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], months: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], daysOfMonth: [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31], numberOfDays: function(start, finish) { return finish.days() - start.days(); }, isLeapYear: function(year) { if (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0)) return true; return false; }, nextDate: function(date) { return new Date(date.getFullYear(), date.getMonth(), date.getDate() + 1); }, previousDate: function(date) { return new Date(date.getFullYear(), date.getMonth(), date.getDate() - 1); }, afterDays: function(date, after) { return new Date(date.getFullYear(), date.getMonth(), date.getDate() + after); }, getLastDate: function(year, month) { var last = this.daysOfMonth[month]; if ((month == 1) && this.isLeapYear(year)) { return new Date(year, month, last + 1); } return new Date(year, month, last); }, getFirstDate: function(year, month) { if (year.constructor == Date) { return new Date(year.getFullYear(), year.getMonth(), 1); } return new Date(year, month, 1); }, getWeekTurn: function(date, firstDWeek) { var limit = 6 - firstDWeek + 1; var turn = 0; while (limit < date) { date -= 7; turn++; } return turn; }, toDateString: function(date) { return date.toDateString(); }, toLocaleDateString: function(date) { return date.toLocaleDateString(); }, simpleFormat: function(formatStr) { return function(date) { var formated = formatStr.replace(/M+/g, DateUtil.zerofill((date.getMonth() + 1).toString(), 2)); formated = formated.replace(/d+/g, DateUtil.zerofill(date.getDate().toString(), 2)); formated = formated.replace(/y{4}/g, date.getFullYear()); formated = formated.replace(/y{1,3}/g, new String(date.getFullYear()).substr(2)); formated = formated.replace(/E+/g, DateUtil.dayOfWeek[date.getDay()]); return formated; } }, zerofill: function(date,digit){ var result = date; if(date.length < digit){ var tmp = digit - date.length; for(i=0; i < tmp; i++){ result = "0" + result; } } return result; }, toDate: function(hash) { return new Date(hash.year, hash.month, hash.day, hash.hour || 0, hash.min || 0, hash.sec || 0); } } /** * ZindexManager */ var ZindexManager = { zIndex: 1000, getIndex: function(zIndex) { if (zIndex) { if (isNaN(zIndex)) { zIndex = Element.getMaxZindex() + 1; } else if (ZindexManager.zIndex > zIndex) { zIndex = ZindexManager.zIndex; } } else { zIndex = ZindexManager.zIndex; } ZindexManager.zIndex = zIndex + 1; return zIndex; } } /** * Modal */ var Modal = { maskId: 'modalMask', maskClass: 'modal_mask', maskClassIE: 'modal_mask_ie', element: null, snaps: null, listener: null, resizeListener: null, cover: null, excepteds: null, maskCallbacks: [], unmaskCallbacks: [], mask: function(excepted) { this._mask.callAfterLoading(this, excepted); }, unmask: function() { // this._unmask.callAfterLoading(this); this._unmask(); }, addMaskCallback: function(callback) { if (!this.maskCallbacks.any(function(c) { return c == callback; })) { this.maskCallbacks.push(callback); } }, removeMaskCallback: function(callback) { this.maskCallbacks = this.maskCallbacks.reject(function(c) { return c == callback; }); }, clearMaskCallback: function() { this.maskCallbacks = []; }, addUnmaskCallback: function(callback) { if (!this.unmaskCallbacks.any(function(c) { return c == callback; })) { this.unmaskCallbacks.push(callback); } }, removeUnmaskCallback: function(callback) { this.unmaskCallbacks = this.unmaskCallbacks.reject(function(c) { return c == callback; }); }, clearUnmaskCallback: function() { this.unmaskCallbacks = []; }, _mask: function(excepted) { var options = Object.extend({ cssPrefix: 'custom_', zIndex: null }, arguments[1] || {}); if (Modal.element) { Modal._snap(excepted); Modal._rebuildMask(); } else { Modal.snaps = []; Modal.excepteds = []; Modal._buildMask(options.cssPrefix); Modal.cover = new IECover(Modal.element, {transparent: true}); } Modal._setZindex(excepted, options.zIndex); Modal._setFullSize(); if (!Modal.hasExcepted(excepted)) Modal.excepteds.push(excepted); this.maskCallbacks.each(function(callback) { callback(excepted); }); }, _unmask: function() { if (Modal.element) { if (Modal.snaps.length == 0) { Element.hide(Modal.element); Modal._removeEvent(); Modal.excepteds = []; Element.remove(Modal.element); Modal.element = null; } else { Element.setStyle(Modal.element, {zIndex: Modal.snaps.pop()}); Modal.excepteds.pop(); } } this.unmaskCallbacks.each(function(callback) { callback(); }); }, _addEvent: function() { if (!Modal.listener) { Modal.listener = Modal._handleEvent.bindAsEventListener(); Modal.resizeListener = Modal._onResize.bindAsEventListener(); } Event.observe(document, "keypress", Modal.listener); Event.observe(document, "keydown", Modal.listener); Event.observe(document, "keyup", Modal.listener); Event.observe(document, "focus", Modal.listener); Event.observe(window, "resize", Modal.resizeListener); }, _removeEvent: function() { Event.stopObserving(document, "keypress", Modal.listener); Event.stopObserving(document, "keydown", Modal.listener); Event.stopObserving(document, "keyup", Modal.listener); Event.stopObserving(document, "focus", Modal.listener); Event.stopObserving(window, "resize", Modal.resizeListener); }, _isMasked: function() { return Modal.element && Element.visible(Modal.element); }, _snap: function(excepted) { var index = Element.getStyle(Modal.element, 'zIndex'); if (index && Modal._isMasked() && !Modal.hasExcepted(excepted)) Modal.snaps.push(index); }, _setZindex: function(excepted, zIndex) { zIndex = ZindexManager.getIndex(zIndex); Element.setStyle(Modal.element, {zIndex: zIndex}); excepted = Element.makePositioned($(excepted)); Element.setStyle(excepted, {zIndex: ++zIndex}); }, _setFullSize: function() { Modal.element.setStyle({ width: Element.getWindowWidth() + 'px', height: Element.getWindowHeight() + 'px' }); if (Modal.cover) Modal.cover.resetSize(); }, _buildMask: function(cssPrefix) { var mask = Builder.node('div', {id: Modal.maskId}); Modal._setClassNames(mask, cssPrefix); document.body.appendChild(mask); Modal.element = mask; Modal._addEvent(); }, _setClassNames: function(element, cssPrefix) { var className = (UserAgent.isIE()) ? Modal.maskClassIE : Modal.maskClass; Element.addClassName(element, className); Element.addClassName(element, cssPrefix + className); }, _rebuildMask: function() { document.body.appendChild(Modal.element); Element.show(Modal.element); }, _isOutOfModal: function(src) { if (!Modal.element) return; var limit = Element.getStyle(Modal.element, 'zIndex'); var zIndex = null; while ((src = src.parentNode) && src != document.body) { if (src.style && (zIndex = Element.getStyle(src, 'zIndex'))) { if (zIndex > limit) { return true; } else { return false; } } } return false; }, _handleEvent: function (event) { var src = Event.element(event); if (!Modal._isOutOfModal(src)) { Event.stop(event); } }, _onResize: function(event) { Modal._setFullSize(); }, hasExcepted: function(excepted) { return (Modal.excepteds || []).any(function(element) { return element.id == excepted.id; }); } } /** * IECover */ var IECover = Class.create(); IECover.src = 'javascript:false;'; IECover.prototype = { idSuffix: 'iecover', initialize: function(parent) { this.options = Object.extend({ transparent : false, padding : 0 }, arguments[1] || {}); if (document.all) { parent = $(parent); this.id = parent.id.appendSuffix(this.idSuffix); this._build(parent); this.resetSize(); } }, resetSize: function() { if (this.element) { var parent = this.element.parentNode; var padding = this.options.padding; this.element.width = parent.offsetWidth - padding + 'px'; this.element.height = Element.getHeight(parent) - padding + 'px'; } }, _build: function(parent) { var padding = this.options.padding / 2; var styles = { position : 'absolute', top : padding + 'px', left : padding + 'px' }; if (this.options.transparent) styles.filter = 'alpha(opacity=0)'; if (parent.buildedIECover && $(this.id)) { this.element = $(this.id); } else { this.element = Builder.node('iframe', {src: IECover.src, id: this.id, frameborder: 0}); } Element.setStyle(this.element, styles); var firstNode = Element.down(parent, 0); if (firstNode) Element.makePositioned(firstNode); parent.insertBefore(this.element, parent.firstChild); parent.buildedIECover = true; } } /** * UserAgent */ var UserAgent = { getUserAgent: function() { return navigator.userAgent; }, isIE: function() { return (document.all && this.getUserAgent().toLowerCase().indexOf('msie') != -1); }, isIE7: function() { return (document.all && this.getUserAgent().toLowerCase().indexOf('msie 7') != -1); }, isSafari: function() { return (this.getUserAgent().toLowerCase().indexOf('safari') != -1); }, isMac: function() { return (this.getUserAgent().toLowerCase().indexOf('macintosh') != -1); } } /** * ShortcutManager */ var ShortcutManager = Class.create(); ShortcutManager.prototype = { initialize: function() { var defaultOptions = { detectKeyup:false, initialStarted:true, preventDefault:true } this.options = Object.extend(defaultOptions, arguments[0] || {}); this.keydownListener = this.eventKeydown.bindAsEventListener(this); if(this.options.detectKeyup) { this.keyupListener = this.eventKeyup.bindAsEventListener(this); } this.keydownFunc = new Object(); this.keydownFunc['a'] = new Object(); this.keydownFunc['ac'] = new Object(); this.keydownFunc['as'] = new Object(); this.keydownFunc['acs'] = new Object(); this.keydownFunc['c'] = new Object(); this.keydownFunc['cs'] = new Object(); this.keydownFunc['n'] = new Object(); this.keydownFunc['s'] = new Object(); this.keyupFunc = new Object(); this.keyCode = { 'backspace': 8, 'tab': 9, 'return': 13, 'enter': 13, 'pause': 19, 'break': 19, 'caps': 20, 'capslock': 20, 'esc': 27, 'escape': 27, 'space': 32, 'pageup': 33, 'pgup': 33, 'pagedown': 34, 'pgdn': 34, 'end': 35, 'home': 36, 'left': 37, 'up': 38, 'right': 39, 'down': 40, 'insert': 45, 'delete': 46, '0': 48, '1': 49, '2': 50, '3': 51, '4': 52, '5': 53, '6': 54, '7': 55, '8': 56, '9': 57, 'a': 65, 'b': 66, 'c': 67, 'd': 68, 'e': 69, 'f': 70, 'g': 71, 'h': 72, 'i': 73, 'j': 74, 'k': 75, 'l': 76, 'm': 77, 'n': 78, 'o': 79, 'p': 80, 'q': 81, 'r': 82, 's': 83, 't': 84, 'u': 85, 'v': 86, 'w': 87, 'x': 88, 'y': 89, 'z': 90, 'f1': 112, 'f2': 113, 'f3': 114, 'f4': 115, 'f5': 116, 'f6': 117, 'f7': 118, 'f8': 119, 'f9': 120, 'f10': 121, 'f11': 122, 'f12': 123, 'numlock': 144, 'nmlk': 144, 'scrolllock': 145, 'scflk': 145, 'cmd': 224, 'command': 224 }; this.numKeys = { 96: 48, 97: 49, 98: 50, 99: 51, 100: 52, 101: 53, 102: 54, 103: 55, 104: 56, 105: 57 }; if(this.options.initialStarted) { this.start(); } else { this.stop(); } Event.observe(document, 'keydown', this.keydownListener); if(this.options.detectKeyup) { Event.observe(document, 'keyup', this.keyupListener); } }, add: function(c1, c2, keyup) { if(c1.constructor == Array) { var self = this; c1.each( function(pair) { self._add_or_remove_function(pair[0], pair[1], keyup); } ); } else { this._add_or_remove_function(c1, c2, keyup); } }, destroy: function() { Event.stopObserving(document, 'keydown', this.keydownListener); if(this.options.detectKeyup) { Event.stopObserving(document, 'keyup', this.keyupListener); } }, eventKeydown: function(event) { if(this.executable) { var code; var key = ''; event = event || window.event; if(event.keyCode) { if(event.altKey) { key += 'a'; } if(event.ctrlKey) { key += 'c'; } if(event.shiftKey) { key += 's'; } if(key == '') { key = 'n'; } code = this._mergeNumKey(event.keyCode); if(this.keydownFunc[key][code]) { this.keydownFunc[key][code](); if(this.options.preventDefault) { Event.stop(event); } } } } }, eventKeyup: function(event) { if(this.executable) { var code; event = event || window.event; if(event.keyCode) { code = this._mergeNumKey(event.keyCode); if(this.keyupFunc[code]) { this.keyupFunc[code](); if(this.options.preventDefault) { Event.stop(event); } } } } }, remove: function(shortcut) { this._add_or_remove_function(shortcut); }, start: function() { this.executable = true; }, stop: function() { this.executable = false; }, _add_or_remove_function: function(shortcut, callback, keyup) { var pressed_key_code; var additional_keys = new Array(); var self = this; $A(shortcut.toLowerCase().split("+")).each( function(key) { if(key == 'alt') { additional_keys.push('a'); } else if(key == 'ctrl') { additional_keys.push('c'); } else if(key == 'shift') { additional_keys.push('s'); } else { pressed_key_code = self.keyCode[key]; } } ); var key = additional_keys.sortBy(function(value, index) {return value;}).join(''); if(key == '') { key = 'n'; } if(callback) { if(keyup) { this.keyupFunc[pressed_key_code] = callback; } else { this.keydownFunc[key][pressed_key_code] = callback; } } else { if(keyup) { this.keyupFunc[pressed_key_code] = null; } else { this.keydownFunc[key][pressed_key_code] = null; } } }, _mergeNumKey: function(code) { return (this.numKeys[code]) ? this.numKeys[code] : code; } } /** * Function */ Function.prototype.callAfterLoading = function() { var args = $A(arguments); var self = this; var object = args.shift() || this; if (UserAgent.isIE() && (document.readyState != 'complete')) { Event.observe(window, 'load', function() { self.apply(object, args) }); } else { this.apply(object, args); } } /** * SpinelzUtil */ var SpinelzUtil = { idCount: 0, getId: function(idBase) { idBase = idBase || ''; return idBase.appendSuffix(++SpinelzUtil.idCount); }, toAttriteString: function(attributes, frontSpace) { var html = attributes.map(function(pair) { return pair.key + "='" + pair.value + "'"; }).join(' '); if (frontSpace && (html.length > 0)) html = " " + html; return html; }, concat: function(base, suffixes) { var hash = {}; suffixes.each(function(suffix) { hash[suffix] = base.appendSuffix(suffix); }); return hash; } } /** * prototype.js */ var $A = Array.from = function(iterable) { if (!iterable) return []; if (iterable.toArray) { return iterable.toArray(); } else { var results = []; for (var i = 0, len = iterable.length; i < len; i++) results.push(iterable[i]); return results; } }