UNPKG

three-codeeditor

Version:

codeeditor for three.js

1,513 lines (1,346 loc) 1.03 MB
// This THREEx helper makes it easy to handle the mouse events in your 3D scene // // * CHANGES NEEDED // * handle drag/drop // * notify events not object3D - like DOM // * so single object with property // * DONE bubling implement bubling/capturing // * DONE implement event.stopPropagation() // * DONE implement event.type = "click" and co // * DONE implement event.target // // # Lets get started // // First you include it in your page // // ```<script src='threex.domevent.js'>< /script>``` // // # use the object oriented api // // You bind an event like this // // ```mesh.on('click', function(object3d){ ... })``` // // To unbind an event, just do // // ```mesh.off('click', function(object3d){ ... })``` // // As an alternative, there is another naming closer DOM events. // Pick the one you like, they are doing the same thing // // ```mesh.addEventListener('click', function(object3d){ ... })``` // ```mesh.removeEventListener('click', function(object3d){ ... })``` // // # Supported Events // // Always in a effort to stay close to usual pratices, the events name are the same as in DOM. // The semantic is the same too. // Currently, the available events are // [click, dblclick, mouseup, mousedown](http://www.quirksmode.org/dom/events/click.html), // [mouseover and mouse out](http://www.quirksmode.org/dom/events/mouseover.html). // // # use the standalone api // // The object-oriented api modifies THREE.Object3D class. // It is a global class, so it may be legitimatly considered unclean by some people. // If this bother you, simply do ```THREEx.DomEvents.noConflict()``` and use the // standalone API. In fact, the object oriented API is just a thin wrapper // on top of the standalone API. // // First, you instanciate the object // // ```var domEvent = new THREEx.DomEvent();``` // // Then you bind an event like this // // ```domEvent.bind(mesh, 'click', function(object3d){ object3d.scale.x *= 2; });``` // // To unbind an event, just do // // ```domEvent.unbind(mesh, 'click', callback);``` // // // # Code // /** @namespace */ var THREEx = THREEx || {}; // # Constructor THREEx.DomEvents = function(camera, domElement) { this._camera = camera || null; this._domElement= domElement || document; this._raycaster = new THREE.Raycaster(); this._selected = null; this._boundObjs = {}; // Bind dom event for mouse and touch var _this = this; this._$onClick = function(){ _this._onClick.apply(_this, arguments); }; this._$onDblClick = function(){ _this._onDblClick.apply(_this, arguments); }; this._$onMouseMove = function(){ _this._onMouseMove.apply(_this, arguments); }; this._$onMouseDown = function(){ _this._onMouseDown.apply(_this, arguments); }; this._$onMouseUp = function(){ _this._onMouseUp.apply(_this, arguments); }; this._$onTouchMove = function(){ _this._onTouchMove.apply(_this, arguments); }; this._$onTouchStart = function(){ _this._onTouchStart.apply(_this, arguments); }; this._$onTouchEnd = function(){ _this._onTouchEnd.apply(_this, arguments); }; this._$onContextmenu = function(){ _this._onContextmenu.apply(_this, arguments); }; this._domElement.addEventListener( 'click' , this._$onClick , false ); this._domElement.addEventListener( 'dblclick' , this._$onDblClick , false ); this._domElement.addEventListener( 'mousemove' , this._$onMouseMove , false ); this._domElement.addEventListener( 'mousedown' , this._$onMouseDown , false ); this._domElement.addEventListener( 'mouseup' , this._$onMouseUp , false ); this._domElement.addEventListener( 'touchmove' , this._$onTouchMove , false ); this._domElement.addEventListener( 'touchstart' , this._$onTouchStart , false ); this._domElement.addEventListener( 'touchend' , this._$onTouchEnd , false ); this._domElement.addEventListener( 'contextmenu', this._$onContextmenu , false ); } // # Destructor THREEx.DomEvents.prototype.destroy = function() { // unBind dom event for mouse and touch this._domElement.removeEventListener( 'click' , this._$onClick , false ); this._domElement.removeEventListener( 'dblclick' , this._$onDblClick , false ); this._domElement.removeEventListener( 'mousemove' , this._$onMouseMove , false ); this._domElement.removeEventListener( 'mousedown' , this._$onMouseDown , false ); this._domElement.removeEventListener( 'mouseup' , this._$onMouseUp , false ); this._domElement.removeEventListener( 'touchmove' , this._$onTouchMove , false ); this._domElement.removeEventListener( 'touchstart' , this._$onTouchStart , false ); this._domElement.removeEventListener( 'touchend' , this._$onTouchEnd , false ); this._domElement.removeEventListener( 'contextmenu' , this._$onContextmenu , false ); } THREEx.DomEvents.eventNames = [ "click", "dblclick", "mouseover", "mouseout", "mousemove", "mousedown", "mouseup", "contextmenu", "touchstart", "touchend" ]; THREEx.DomEvents.prototype._getRelativeMouseXY = function(domEvent){ var element = domEvent.target || domEvent.srcElement; if (element.nodeType === 3) { element = element.parentNode; // Safari fix -- see http://www.quirksmode.org/js/events_properties.html } //get the real position of an element relative to the page starting point (0, 0) //credits go to brainjam on answering http://stackoverflow.com/questions/5755312/getting-mouse-position-relative-to-content-area-of-an-element var elPosition = { x : 0 , y : 0}; var tmpElement = element; //store padding var style = getComputedStyle(tmpElement, null); elPosition.y += parseInt(style.getPropertyValue("padding-top"), 10); elPosition.x += parseInt(style.getPropertyValue("padding-left"), 10); //add positions do { elPosition.x += tmpElement.offsetLeft; elPosition.y += tmpElement.offsetTop; style = getComputedStyle(tmpElement, null); elPosition.x += parseInt(style.getPropertyValue("border-left-width"), 10); elPosition.y += parseInt(style.getPropertyValue("border-top-width"), 10); } while(tmpElement = tmpElement.offsetParent); var elDimension = { width : (element === window) ? window.innerWidth : element.offsetWidth, height : (element === window) ? window.innerHeight : element.offsetHeight }; return { x : +((domEvent.pageX - elPosition.x) / elDimension.width ) * 2 - 1, y : -((domEvent.pageY - elPosition.y) / elDimension.height) * 2 + 1 }; }; /********************************************************************************/ /* domevent context */ /********************************************************************************/ // handle domevent context in object3d instance THREEx.DomEvents.prototype._objectCtxInit = function(object3d){ object3d._3xDomEvent = {}; } THREEx.DomEvents.prototype._objectCtxDeinit = function(object3d){ delete object3d._3xDomEvent; } THREEx.DomEvents.prototype._objectCtxIsInit = function(object3d){ return object3d._3xDomEvent ? true : false; } THREEx.DomEvents.prototype._objectCtxGet = function(object3d){ return object3d._3xDomEvent; } /********************************************************************************/ /* */ /********************************************************************************/ /** * Getter/Setter for camera */ THREEx.DomEvents.prototype.camera = function(value) { if( value ) this._camera = value; return this._camera; } THREEx.DomEvents.prototype.bind = function(object3d, eventName, callback, useCapture) { console.assert( THREEx.DomEvents.eventNames.indexOf(eventName) !== -1, "not available events:"+eventName ); if( !this._objectCtxIsInit(object3d) ) this._objectCtxInit(object3d); var objectCtx = this._objectCtxGet(object3d); if( !objectCtx[eventName+'Handlers'] ) objectCtx[eventName+'Handlers'] = []; objectCtx[eventName+'Handlers'].push({ callback : callback, useCapture : useCapture }); // add this object in this._boundObjs if( this._boundObjs[eventName] === undefined ){ this._boundObjs[eventName] = []; } this._boundObjs[eventName].push(object3d); } THREEx.DomEvents.prototype.addEventListener = THREEx.DomEvents.prototype.bind THREEx.DomEvents.prototype.unbind = function(object3d, eventName, callback, useCapture) { console.assert( THREEx.DomEvents.eventNames.indexOf(eventName) !== -1, "not available events:"+eventName ); if( !this._objectCtxIsInit(object3d) ) this._objectCtxInit(object3d); var objectCtx = this._objectCtxGet(object3d); if( !objectCtx[eventName+'Handlers'] ) objectCtx[eventName+'Handlers'] = []; var handlers = objectCtx[eventName+'Handlers']; for(var i = 0; i < handlers.length; i++){ var handler = handlers[i]; if( callback != handler.callback ) continue; if( useCapture != handler.useCapture ) continue; handlers.splice(i, 1) break; } // from this object from this._boundObjs var index = this._boundObjs[eventName].indexOf(object3d); console.assert( index !== -1 ); this._boundObjs[eventName].splice(index, 1); } THREEx.DomEvents.prototype.removeEventListener = THREEx.DomEvents.prototype.unbind THREEx.DomEvents.prototype._bound = function(eventName, object3d) { var objectCtx = this._objectCtxGet(object3d); if( !objectCtx ) return false; return objectCtx[eventName+'Handlers'] ? true : false; } /********************************************************************************/ /* onMove */ /********************************************************************************/ // # handle mousemove kind of events THREEx.DomEvents.prototype._onMove = function(eventName, mouseX, mouseY, origDomEvent) { //console.log('eventName', eventName, 'boundObjs', this._boundObjs[eventName]) // get objects bound to this event var boundObjs = this._boundObjs[eventName]; if( boundObjs === undefined || boundObjs.length === 0 ) return; // compute the intersection var vector = new THREE.Vector2(); // update the picking ray with the camera and mouse position vector.set( mouseX, mouseY ); this._raycaster.setFromCamera( vector, this._camera ); var intersects = this._raycaster.intersectObjects( boundObjs ); var oldSelected = this._selected; if( intersects.length > 0 ){ var notifyOver, notifyOut, notifyMove; var intersect = intersects[ 0 ]; var newSelected = intersect.object; this._selected = newSelected; // if newSelected bound mousemove, notify it notifyMove = this._bound('mousemove', newSelected); if( oldSelected != newSelected ){ // if newSelected bound mouseenter, notify it notifyOver = this._bound('mouseover', newSelected); // if there is a oldSelect and oldSelected bound mouseleave, notify it notifyOut = oldSelected && this._bound('mouseout', oldSelected); } }else{ // if there is a oldSelect and oldSelected bound mouseleave, notify it notifyOut = oldSelected && this._bound('mouseout', oldSelected); this._selected = null; } // notify mouseMove - done at the end with a copy of the list to allow callback to remove handlers notifyMove && this._notify('mousemove', newSelected, origDomEvent, intersect); // notify mouseEnter - done at the end with a copy of the list to allow callback to remove handlers notifyOver && this._notify('mouseover', newSelected, origDomEvent, intersect); // notify mouseLeave - done at the end with a copy of the list to allow callback to remove handlers notifyOut && this._notify('mouseout' , oldSelected, origDomEvent, intersect); } /********************************************************************************/ /* onEvent */ /********************************************************************************/ // # handle click kind of events THREEx.DomEvents.prototype._onEvent = function(eventName, mouseX, mouseY, origDomEvent) { //console.log('eventName', eventName, 'boundObjs', this._boundObjs[eventName]) // get objects bound to this event var boundObjs = this._boundObjs[eventName]; if( boundObjs === undefined || boundObjs.length === 0 ) return; // compute the intersection var vector = new THREE.Vector2(); // update the picking ray with the camera and mouse position vector.set( mouseX, mouseY ); this._raycaster.setFromCamera( vector, this._camera ); var intersects = this._raycaster.intersectObjects( boundObjs, true); // if there are no intersections, return now if( intersects.length === 0 ) return; // init some variables var intersect = intersects[0]; var object3d = intersect.object; var objectCtx = this._objectCtxGet(object3d); var objectParent = object3d.parent; while ( typeof(objectCtx) == 'undefined' && objectParent ) { objectCtx = this._objectCtxGet(objectParent); objectParent = objectParent.parent; } if( !objectCtx ) return; // notify handlers this._notify(eventName, object3d, origDomEvent, intersect); } THREEx.DomEvents.prototype._notify = function(eventName, object3d, origDomEvent, intersect) { var objectCtx = this._objectCtxGet(object3d); var handlers = objectCtx ? objectCtx[eventName+'Handlers'] : null; // parameter check console.assert(arguments.length === 4) // do bubbling if( !objectCtx || !handlers || handlers.length === 0 ){ object3d.parent && this._notify(eventName, object3d.parent, origDomEvent, intersect); return; } // notify all handlers var handlers = objectCtx[eventName+'Handlers']; for(var i = 0; i < handlers.length; i++){ var handler = handlers[i]; var toPropagate = true; handler.callback({ type : eventName, target : object3d, origDomEvent : origDomEvent, intersect : intersect, stopPropagation : function(){ toPropagate = false; } }); if( !toPropagate ) continue; // do bubbling if( handler.useCapture === false ){ object3d.parent && this._notify(eventName, object3d.parent, origDomEvent, intersect); } } } /********************************************************************************/ /* handle mouse events */ /********************************************************************************/ // # handle mouse events THREEx.DomEvents.prototype._onMouseDown = function(event){ return this._onMouseEvent('mousedown', event); } THREEx.DomEvents.prototype._onMouseUp = function(event){ return this._onMouseEvent('mouseup' , event); } THREEx.DomEvents.prototype._onMouseEvent = function(eventName, domEvent) { var mouseCoords = this._getRelativeMouseXY(domEvent); this._onEvent(eventName, mouseCoords.x, mouseCoords.y, domEvent); } THREEx.DomEvents.prototype._onMouseMove = function(domEvent) { var mouseCoords = this._getRelativeMouseXY(domEvent); this._onMove('mousemove', mouseCoords.x, mouseCoords.y, domEvent); this._onMove('mouseover', mouseCoords.x, mouseCoords.y, domEvent); this._onMove('mouseout' , mouseCoords.x, mouseCoords.y, domEvent); } THREEx.DomEvents.prototype._onClick = function(event) { // TODO handle touch ? this._onMouseEvent('click' , event); } THREEx.DomEvents.prototype._onDblClick = function(event) { // TODO handle touch ? this._onMouseEvent('dblclick' , event); } THREEx.DomEvents.prototype._onContextmenu = function(event) { //TODO don't have a clue about how this should work with touch.. this._onMouseEvent('contextmenu' , event); } /********************************************************************************/ /* handle touch events */ /********************************************************************************/ // # handle touch events THREEx.DomEvents.prototype._onTouchStart = function(event){ return this._onTouchEvent('touchstart', event); } THREEx.DomEvents.prototype._onTouchEnd = function(event){ return this._onTouchEvent('touchend' , event); } THREEx.DomEvents.prototype._onTouchMove = function(domEvent) { if( domEvent.touches.length != 1 ) return undefined; domEvent.preventDefault(); var mouseX = +(domEvent.touches[ 0 ].pageX / window.innerWidth ) * 2 - 1; var mouseY = -(domEvent.touches[ 0 ].pageY / window.innerHeight) * 2 + 1; this._onMove('mousemove', mouseX, mouseY, domEvent); this._onMove('mouseover', mouseX, mouseY, domEvent); this._onMove('mouseout' , mouseX, mouseY, domEvent); } THREEx.DomEvents.prototype._onTouchEvent = function(eventName, domEvent) { if( domEvent.touches.length != 1 ) return undefined; domEvent.preventDefault(); var mouseX = +(domEvent.touches[ 0 ].pageX / window.innerWidth ) * 2 - 1; var mouseY = -(domEvent.touches[ 0 ].pageY / window.innerHeight) * 2 + 1; this._onEvent(eventName, mouseX, mouseY, domEvent); }; /* ***** BEGIN LICENSE BLOCK ***** * Distributed under the BSD license: * * Copyright (c) 2010, Ajax.org B.V. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of Ajax.org B.V. nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * ***** END LICENSE BLOCK ***** */ /** * Define a module along with a payload * @param module a name for the payload * @param payload a function to call with (require, exports, module) params */ (function() { var ACE_NAMESPACE = "ace"; var global = (function() { return this; })(); if (!ACE_NAMESPACE && typeof requirejs !== "undefined") return; var _define = function(module, deps, payload) { if (typeof module !== 'string') { if (_define.original) _define.original.apply(window, arguments); else { console.error('dropping module because define wasn\'t a string.'); console.trace(); } return; } if (arguments.length == 2) payload = deps; if (!_define.modules) { _define.modules = {}; _define.payloads = {}; } _define.payloads[module] = payload; _define.modules[module] = null; }; /** * Get at functionality ace.define()ed using the function above */ var _require = function(parentId, module, callback) { if (Object.prototype.toString.call(module) === "[object Array]") { var params = []; for (var i = 0, l = module.length; i < l; ++i) { var dep = lookup(parentId, module[i]); if (!dep && _require.original) return _require.original.apply(window, arguments); params.push(dep); } if (callback) { callback.apply(null, params); } } else if (typeof module === 'string') { var payload = lookup(parentId, module); if (!payload && _require.original) return _require.original.apply(window, arguments); if (callback) { callback(); } return payload; } else { if (_require.original) return _require.original.apply(window, arguments); } }; var normalizeModule = function(parentId, moduleName) { // normalize plugin requires if (moduleName.indexOf("!") !== -1) { var chunks = moduleName.split("!"); return normalizeModule(parentId, chunks[0]) + "!" + normalizeModule(parentId, chunks[1]); } // normalize relative requires if (moduleName.charAt(0) == ".") { var base = parentId.split("/").slice(0, -1).join("/"); moduleName = base + "/" + moduleName; while(moduleName.indexOf(".") !== -1 && previous != moduleName) { var previous = moduleName; moduleName = moduleName.replace(/\/\.\//, "/").replace(/[^\/]+\/\.\.\//, ""); } } return moduleName; }; /** * Internal function to lookup moduleNames and resolve them by calling the * definition function if needed. */ var lookup = function(parentId, moduleName) { moduleName = normalizeModule(parentId, moduleName); var module = _define.modules[moduleName]; if (!module) { module = _define.payloads[moduleName]; if (typeof module === 'function') { var exports = {}; var mod = { id: moduleName, uri: '', exports: exports, packaged: true }; var req = function(module, callback) { return _require(moduleName, module, callback); }; var returnValue = module(req, exports, mod); exports = returnValue || mod.exports; _define.modules[moduleName] = exports; delete _define.payloads[moduleName]; } module = _define.modules[moduleName] = exports || module; } return module; }; function exportAce(ns) { var require = function(module, callback) { return _require("", module, callback); }; var root = global; if (ns) { if (!global[ns]) global[ns] = {}; root = global[ns]; } if (!root.define || !root.define.packaged) { _define.original = root.define; root.define = _define; root.define.packaged = true; } if (!root.require || !root.require.packaged) { _require.original = root.require; root.require = require; root.require.packaged = true; } } exportAce(ACE_NAMESPACE); })(); ace.define("ace/lib/regexp",["require","exports","module"], function(require, exports, module) { "use strict"; var real = { exec: RegExp.prototype.exec, test: RegExp.prototype.test, match: String.prototype.match, replace: String.prototype.replace, split: String.prototype.split }, compliantExecNpcg = real.exec.call(/()??/, "")[1] === undefined, // check `exec` handling of nonparticipating capturing groups compliantLastIndexIncrement = function () { var x = /^/g; real.test.call(x, ""); return !x.lastIndex; }(); if (compliantLastIndexIncrement && compliantExecNpcg) return; RegExp.prototype.exec = function (str) { var match = real.exec.apply(this, arguments), name, r2; if ( typeof(str) == 'string' && match) { if (!compliantExecNpcg && match.length > 1 && indexOf(match, "") > -1) { r2 = RegExp(this.source, real.replace.call(getNativeFlags(this), "g", "")); real.replace.call(str.slice(match.index), r2, function () { for (var i = 1; i < arguments.length - 2; i++) { if (arguments[i] === undefined) match[i] = undefined; } }); } if (this._xregexp && this._xregexp.captureNames) { for (var i = 1; i < match.length; i++) { name = this._xregexp.captureNames[i - 1]; if (name) match[name] = match[i]; } } if (!compliantLastIndexIncrement && this.global && !match[0].length && (this.lastIndex > match.index)) this.lastIndex--; } return match; }; if (!compliantLastIndexIncrement) { RegExp.prototype.test = function (str) { var match = real.exec.call(this, str); if (match && this.global && !match[0].length && (this.lastIndex > match.index)) this.lastIndex--; return !!match; }; } function getNativeFlags (regex) { return (regex.global ? "g" : "") + (regex.ignoreCase ? "i" : "") + (regex.multiline ? "m" : "") + (regex.extended ? "x" : "") + // Proposed for ES4; included in AS3 (regex.sticky ? "y" : ""); } function indexOf (array, item, from) { if (Array.prototype.indexOf) // Use the native array method if available return array.indexOf(item, from); for (var i = from || 0; i < array.length; i++) { if (array[i] === item) return i; } return -1; } }); ace.define("ace/lib/es5-shim",["require","exports","module"], function(require, exports, module) { function Empty() {} if (!Function.prototype.bind) { Function.prototype.bind = function bind(that) { // .length is 1 var target = this; if (typeof target != "function") { throw new TypeError("Function.prototype.bind called on incompatible " + target); } var args = slice.call(arguments, 1); // for normal call var bound = function () { if (this instanceof bound) { var result = target.apply( this, args.concat(slice.call(arguments)) ); if (Object(result) === result) { return result; } return this; } else { return target.apply( that, args.concat(slice.call(arguments)) ); } }; if(target.prototype) { Empty.prototype = target.prototype; bound.prototype = new Empty(); Empty.prototype = null; } return bound; }; } var call = Function.prototype.call; var prototypeOfArray = Array.prototype; var prototypeOfObject = Object.prototype; var slice = prototypeOfArray.slice; var _toString = call.bind(prototypeOfObject.toString); var owns = call.bind(prototypeOfObject.hasOwnProperty); var defineGetter; var defineSetter; var lookupGetter; var lookupSetter; var supportsAccessors; if ((supportsAccessors = owns(prototypeOfObject, "__defineGetter__"))) { defineGetter = call.bind(prototypeOfObject.__defineGetter__); defineSetter = call.bind(prototypeOfObject.__defineSetter__); lookupGetter = call.bind(prototypeOfObject.__lookupGetter__); lookupSetter = call.bind(prototypeOfObject.__lookupSetter__); } if ([1,2].splice(0).length != 2) { if(function() { // test IE < 9 to splice bug - see issue #138 function makeArray(l) { var a = new Array(l+2); a[0] = a[1] = 0; return a; } var array = [], lengthBefore; array.splice.apply(array, makeArray(20)); array.splice.apply(array, makeArray(26)); lengthBefore = array.length; //46 array.splice(5, 0, "XXX"); // add one element lengthBefore + 1 == array.length if (lengthBefore + 1 == array.length) { return true;// has right splice implementation without bugs } }()) {//IE 6/7 var array_splice = Array.prototype.splice; Array.prototype.splice = function(start, deleteCount) { if (!arguments.length) { return []; } else { return array_splice.apply(this, [ start === void 0 ? 0 : start, deleteCount === void 0 ? (this.length - start) : deleteCount ].concat(slice.call(arguments, 2))) } }; } else {//IE8 Array.prototype.splice = function(pos, removeCount){ var length = this.length; if (pos > 0) { if (pos > length) pos = length; } else if (pos == void 0) { pos = 0; } else if (pos < 0) { pos = Math.max(length + pos, 0); } if (!(pos+removeCount < length)) removeCount = length - pos; var removed = this.slice(pos, pos+removeCount); var insert = slice.call(arguments, 2); var add = insert.length; if (pos === length) { if (add) { this.push.apply(this, insert); } } else { var remove = Math.min(removeCount, length - pos); var tailOldPos = pos + remove; var tailNewPos = tailOldPos + add - remove; var tailCount = length - tailOldPos; var lengthAfterRemove = length - remove; if (tailNewPos < tailOldPos) { // case A for (var i = 0; i < tailCount; ++i) { this[tailNewPos+i] = this[tailOldPos+i]; } } else if (tailNewPos > tailOldPos) { // case B for (i = tailCount; i--; ) { this[tailNewPos+i] = this[tailOldPos+i]; } } // else, add == remove (nothing to do) if (add && pos === lengthAfterRemove) { this.length = lengthAfterRemove; // truncate array this.push.apply(this, insert); } else { this.length = lengthAfterRemove + add; // reserves space for (i = 0; i < add; ++i) { this[pos+i] = insert[i]; } } } return removed; }; } } if (!Array.isArray) { Array.isArray = function isArray(obj) { return _toString(obj) == "[object Array]"; }; } var boxedString = Object("a"), splitString = boxedString[0] != "a" || !(0 in boxedString); if (!Array.prototype.forEach) { Array.prototype.forEach = function forEach(fun /*, thisp*/) { var object = toObject(this), self = splitString && _toString(this) == "[object String]" ? this.split("") : object, thisp = arguments[1], i = -1, length = self.length >>> 0; if (_toString(fun) != "[object Function]") { throw new TypeError(); // TODO message } while (++i < length) { if (i in self) { fun.call(thisp, self[i], i, object); } } }; } if (!Array.prototype.map) { Array.prototype.map = function map(fun /*, thisp*/) { var object = toObject(this), self = splitString && _toString(this) == "[object String]" ? this.split("") : object, length = self.length >>> 0, result = Array(length), thisp = arguments[1]; if (_toString(fun) != "[object Function]") { throw new TypeError(fun + " is not a function"); } for (var i = 0; i < length; i++) { if (i in self) result[i] = fun.call(thisp, self[i], i, object); } return result; }; } if (!Array.prototype.filter) { Array.prototype.filter = function filter(fun /*, thisp */) { var object = toObject(this), self = splitString && _toString(this) == "[object String]" ? this.split("") : object, length = self.length >>> 0, result = [], value, thisp = arguments[1]; if (_toString(fun) != "[object Function]") { throw new TypeError(fun + " is not a function"); } for (var i = 0; i < length; i++) { if (i in self) { value = self[i]; if (fun.call(thisp, value, i, object)) { result.push(value); } } } return result; }; } if (!Array.prototype.every) { Array.prototype.every = function every(fun /*, thisp */) { var object = toObject(this), self = splitString && _toString(this) == "[object String]" ? this.split("") : object, length = self.length >>> 0, thisp = arguments[1]; if (_toString(fun) != "[object Function]") { throw new TypeError(fun + " is not a function"); } for (var i = 0; i < length; i++) { if (i in self && !fun.call(thisp, self[i], i, object)) { return false; } } return true; }; } if (!Array.prototype.some) { Array.prototype.some = function some(fun /*, thisp */) { var object = toObject(this), self = splitString && _toString(this) == "[object String]" ? this.split("") : object, length = self.length >>> 0, thisp = arguments[1]; if (_toString(fun) != "[object Function]") { throw new TypeError(fun + " is not a function"); } for (var i = 0; i < length; i++) { if (i in self && fun.call(thisp, self[i], i, object)) { return true; } } return false; }; } if (!Array.prototype.reduce) { Array.prototype.reduce = function reduce(fun /*, initial*/) { var object = toObject(this), self = splitString && _toString(this) == "[object String]" ? this.split("") : object, length = self.length >>> 0; if (_toString(fun) != "[object Function]") { throw new TypeError(fun + " is not a function"); } if (!length && arguments.length == 1) { throw new TypeError("reduce of empty array with no initial value"); } var i = 0; var result; if (arguments.length >= 2) { result = arguments[1]; } else { do { if (i in self) { result = self[i++]; break; } if (++i >= length) { throw new TypeError("reduce of empty array with no initial value"); } } while (true); } for (; i < length; i++) { if (i in self) { result = fun.call(void 0, result, self[i], i, object); } } return result; }; } if (!Array.prototype.reduceRight) { Array.prototype.reduceRight = function reduceRight(fun /*, initial*/) { var object = toObject(this), self = splitString && _toString(this) == "[object String]" ? this.split("") : object, length = self.length >>> 0; if (_toString(fun) != "[object Function]") { throw new TypeError(fun + " is not a function"); } if (!length && arguments.length == 1) { throw new TypeError("reduceRight of empty array with no initial value"); } var result, i = length - 1; if (arguments.length >= 2) { result = arguments[1]; } else { do { if (i in self) { result = self[i--]; break; } if (--i < 0) { throw new TypeError("reduceRight of empty array with no initial value"); } } while (true); } do { if (i in this) { result = fun.call(void 0, result, self[i], i, object); } } while (i--); return result; }; } if (!Array.prototype.indexOf || ([0, 1].indexOf(1, 2) != -1)) { Array.prototype.indexOf = function indexOf(sought /*, fromIndex */ ) { var self = splitString && _toString(this) == "[object String]" ? this.split("") : toObject(this), length = self.length >>> 0; if (!length) { return -1; } var i = 0; if (arguments.length > 1) { i = toInteger(arguments[1]); } i = i >= 0 ? i : Math.max(0, length + i); for (; i < length; i++) { if (i in self && self[i] === sought) { return i; } } return -1; }; } if (!Array.prototype.lastIndexOf || ([0, 1].lastIndexOf(0, -3) != -1)) { Array.prototype.lastIndexOf = function lastIndexOf(sought /*, fromIndex */) { var self = splitString && _toString(this) == "[object String]" ? this.split("") : toObject(this), length = self.length >>> 0; if (!length) { return -1; } var i = length - 1; if (arguments.length > 1) { i = Math.min(i, toInteger(arguments[1])); } i = i >= 0 ? i : length - Math.abs(i); for (; i >= 0; i--) { if (i in self && sought === self[i]) { return i; } } return -1; }; } if (!Object.getPrototypeOf) { Object.getPrototypeOf = function getPrototypeOf(object) { return object.__proto__ || ( object.constructor ? object.constructor.prototype : prototypeOfObject ); }; } if (!Object.getOwnPropertyDescriptor) { var ERR_NON_OBJECT = "Object.getOwnPropertyDescriptor called on a " + "non-object: "; Object.getOwnPropertyDescriptor = function getOwnPropertyDescriptor(object, property) { if ((typeof object != "object" && typeof object != "function") || object === null) throw new TypeError(ERR_NON_OBJECT + object); if (!owns(object, property)) return; var descriptor, getter, setter; descriptor = { enumerable: true, configurable: true }; if (supportsAccessors) { var prototype = object.__proto__; object.__proto__ = prototypeOfObject; var getter = lookupGetter(object, property); var setter = lookupSetter(object, property); object.__proto__ = prototype; if (getter || setter) { if (getter) descriptor.get = getter; if (setter) descriptor.set = setter; return descriptor; } } descriptor.value = object[property]; return descriptor; }; } if (!Object.getOwnPropertyNames) { Object.getOwnPropertyNames = function getOwnPropertyNames(object) { return Object.keys(object); }; } if (!Object.create) { var createEmpty; if (Object.prototype.__proto__ === null) { createEmpty = function () { return { "__proto__": null }; }; } else { createEmpty = function () { var empty = {}; for (var i in empty) empty[i] = null; empty.constructor = empty.hasOwnProperty = empty.propertyIsEnumerable = empty.isPrototypeOf = empty.toLocaleString = empty.toString = empty.valueOf = empty.__proto__ = null; return empty; } } Object.create = function create(prototype, properties) { var object; if (prototype === null) { object = createEmpty(); } else { if (typeof prototype != "object") throw new TypeError("typeof prototype["+(typeof prototype)+"] != 'object'"); var Type = function () {}; Type.prototype = prototype; object = new Type(); object.__proto__ = prototype; } if (properties !== void 0) Object.defineProperties(object, properties); return object; }; } function doesDefinePropertyWork(object) { try { Object.defineProperty(object, "sentinel", {}); return "sentinel" in object; } catch (exception) { } } if (Object.defineProperty) { var definePropertyWorksOnObject = doesDefinePropertyWork({}); var definePropertyWorksOnDom = typeof document == "undefined" || doesDefinePropertyWork(document.createElement("div")); if (!definePropertyWorksOnObject || !definePropertyWorksOnDom) { var definePropertyFallback = Object.defineProperty; } } if (!Object.defineProperty || definePropertyFallback) { var ERR_NON_OBJECT_DESCRIPTOR = "Property description must be an object: "; var ERR_NON_OBJECT_TARGET = "Object.defineProperty called on non-object: " var ERR_ACCESSORS_NOT_SUPPORTED = "getters & setters can not be defined " + "on this javascript engine"; Object.defineProperty = function defineProperty(object, property, descriptor) { if ((typeof object != "object" && typeof object != "function") || object === null) throw new TypeError(ERR_NON_OBJECT_TARGET + object); if ((typeof descriptor != "object" && typeof descriptor != "function") || descriptor === null) throw new TypeError(ERR_NON_OBJECT_DESCRIPTOR + descriptor); if (definePropertyFallback) { try { return definePropertyFallback.call(Object, object, property, descriptor); } catch (exception) { } } if (owns(descriptor, "value")) { if (supportsAccessors && (lookupGetter(object, property) || lookupSetter(object, property))) { var prototype = object.__proto__; object.__proto__ = prototypeOfObject; delete object[property]; object[property] = descriptor.value; object.__proto__ = prototype; } else { object[property] = descriptor.value; } } else { if (!supportsAccessors) throw new TypeError(ERR_ACCESSORS_NOT_SUPPORTED); if (owns(descriptor, "get")) defineGetter(object, property, descriptor.get); if (owns(descriptor, "set")) defineSetter(object, property, descriptor.set); } return object; }; } if (!Object.defineProperties) { Object.defineProperties = function defineProperties(object, properties) { for (var property in properties) { if (owns(properties, property)) Object.defineProperty(object, property, properties[property]); } return object; }; } if (!Object.seal) { Object.seal = function seal(object) { return object; }; } if (!Object.freeze) { Object.freeze = function freeze(object) { return object; }; } try { Object.freeze(function () {}); } catch (exception) { Object.freeze = (function freeze(freezeObject) { return function freeze(object) { if (typeof object == "function") { return object; } else { return freezeObject(object); } }; })(Object.freeze); } if (!Object.preventExtensions) { Object.preventExtensions = function preventExtensions(object) { return object; }; } if (!Object.isSealed) { Object.isSealed = function isSealed(object) { return false; }; } if (!Object.isFrozen) { Object.isFrozen = function isFrozen(object) { return false; }; } if (!Object.isExtensible) { Object.isExtensible = function isExtensible(object) { if (Object(object) === object) { throw new TypeError(); // TODO message } var name = ''; while (owns(object, name)) { name += '?'; } object[name] = true; var returnValue = owns(object, name); delete object[name]; return returnValue; }; } if (!Object.keys) { var hasDontEnumBug = true, dontEnums = [ "toString", "toLocaleString", "valueOf", "hasOwnProperty", "isPrototypeOf", "propertyIsEnumerable", "constructor" ], dontEnumsLength = dontEnums.length; for (var key in {"toString": null}) { hasDontEnumBug = false; } Object.keys = function keys(object) { if ( (typeof object != "object" && typeof object != "function") || object === null ) { throw new TypeError("Object.keys called on a non-object"); } var keys = []; for (var name in object) { if (owns(object, name)) { keys.push(name); } } if (hasDontEnumBug) { for (var i = 0, ii = dontEnumsLength; i < ii; i++) { var dontEnum = dontEnums[i]; if (owns(object, dontEnum)) { keys.push(dontEnum); } } } return keys; }; } if (!Date.now) { Date.now = function now() { return new Date().getTime(); }; } var ws = "\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003" + "\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028" + "\u2029\uFEFF"; if (!String.prototype.trim || ws.trim()) { ws = "[" + ws + "]"; var trimBeginRegexp = new RegExp("^" + ws + ws + "*"), trimEndRegexp = new RegExp(ws + ws + "*$"); String.prototype.trim = function trim() { return String(this).replace(trimBeginRegexp, "").replace(trimEndRegexp, ""); }; } function toInteger(n) { n = +n; if (n !== n) { // isNaN n = 0; } else if (n !== 0 && n !== (1/0) && n !== -(1/0)) { n = (n > 0 || -1) * Math.floor(Math.abs(n)); } return n; } function isPrimitive(input) { var type = typeof input; return ( input === null || type === "undefined" || type === "boolean" || type === "number" || type === "string" ); } function toPrimitive(input) { var val, valueOf, toString; if (isPrimitive(input)) { return input; } valueOf = input.valueOf; if (typeof valueOf === "function") { val = valueOf.call(input); if (isPrimitive(val)) { return val; } } toString = input.toString; if (typeof toString === "function") { val = toString.call(input); if (isPrimitive(val)) { return val; } } throw new TypeError(); } var toObject = function (o) { if (o == null) { // this matches both null and undefined throw new TypeError("can't convert "+o+" to object"); } return Object(o); }; }); ace.define("ace/lib/fixoldbrowsers",["require","exports","module","ace/lib/regexp","ace/lib/es5-shim"], function(require, exports, module) { "use strict"; require("./regexp"); require("./es5-shim"); }); ace.define("ace/lib/dom",["require","exports","module"], function(require, exports, module) { "use strict"; var XHTML_NS = "http://www.w3.org/1999/xhtml"; exports.getDocumentHead = function(doc) { if (!doc) doc = document; return doc.head || doc.getElementsByTagName("head")[0] || doc.documentElement; } exports.createElement = function(tag, ns) { return document.createElementNS ? document.createElementNS(ns || XHTML_NS, tag) : document.createElement(tag); }; exports.hasCssClass = function(el, name) { var classes = (el.className || "").split(/\s+/g); return classes.indexOf(name) !== -1; }; exports.addCssClass = function(el, name) { if (!exports.hasCssClass(el, name)) { el.className += " " + name; } }; exports.removeCssClass = function(el, name) { var classes = el.className.split(/\s+/g); while (true) { var index = classes.indexOf(name); if (index == -1) { break; } classes.splice(index, 1); } el.className = classes.join(" "); }; exports.toggleCssClass = function(el, name) { var classes = el.className.split(/\s+/g), add = true; while (true) { var index = classes.indexOf(name); if (index == -1) { break; } add = false; classes.splice(index, 1); } if(add) classes.push(name); el.className = classes.join(" "); return add; }; exports.setCssClass = function(node, className, include) { if (include) { exports.addCssClass(node, className); } else { exports.removeCssClass(node, className); } }; exports.hasCssString = function(id, doc) { var index = 0, sheets; doc = doc || document; if (doc.createStyleSheet && (sheets = doc.styleSheets)) { while (index < sheets.length) if (sheets[index++].owningElement.id === id) return true; } else if ((sheets = doc.getElementsByTagName("style"))) { while (index < sheets.length) if (sheets[index++].id === id) return true; } return false; }; exports.importCssString = function importCssString(cssText, id, doc) { doc = doc || document; if (id && exports.hasCssString(id, doc)) return null; var style; if (doc.createStyleSheet) { style = doc.createStyleSheet(); style.cssText = cssText; if (id) style.owningElement.id = id; } else { style = doc.createElementNS ? doc.createElementNS(XHTML_NS, "style") : doc.createElement("style"); style.appendChild(doc.createTextNode(cssText)); if (id) style.id = id;