summaryrefslogtreecommitdiff
path: root/Source/WebInspectorUI/UserInterface/Object.js
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebInspectorUI/UserInterface/Object.js')
-rw-r--r--Source/WebInspectorUI/UserInterface/Object.js235
1 files changed, 235 insertions, 0 deletions
diff --git a/Source/WebInspectorUI/UserInterface/Object.js b/Source/WebInspectorUI/UserInterface/Object.js
new file mode 100644
index 000000000..a68da9663
--- /dev/null
+++ b/Source/WebInspectorUI/UserInterface/Object.js
@@ -0,0 +1,235 @@
+/*
+ * Copyright (C) 2008, 2013 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. OR
+ * CONTRIBUTORS 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.
+ */
+
+/**
+ * @constructor
+ */
+WebInspector.Object = function() {
+}
+
+/**
+ * @param {function} constructor
+ */
+WebInspector.Object.addConstructorFunctions = function(subclassConstructor)
+{
+ // Copies the relevant functions the subclass constructor.
+ for (var property in WebInspector.Object) {
+ var value = WebInspector.Object[property];
+ if (typeof value !== "function")
+ continue;
+ if (value === arguments.callee)
+ continue;
+ subclassConstructor[property] = value;
+ }
+}
+
+/**
+ * @param {string} eventType
+ * @param {function(WebInspector.Event)} listener
+ * @param {Object=} thisObject
+ */
+WebInspector.Object.addEventListener = function(eventType, listener, thisObject)
+{
+ thisObject = thisObject || null;
+
+ console.assert(eventType);
+ if (!eventType)
+ return;
+
+ console.assert(listener);
+ if (!listener)
+ return;
+
+ if (!this._listeners)
+ this._listeners = {};
+
+ var listeners = this._listeners[eventType];
+ if (!listeners)
+ listeners = this._listeners[eventType] = [];
+
+ // Prevent registering multiple times.
+ for (var i = 0; i < listeners.length; ++i) {
+ if (listeners[i].listener === listener && listeners[i].thisObject === thisObject)
+ return;
+ }
+
+ listeners.push({thisObject: thisObject, listener: listener});
+};
+
+/**
+ * @param {string} eventType
+ * @param {function(WebInspector.Event)} listener
+ * @param {Object=} thisObject
+ */
+WebInspector.Object.removeEventListener = function(eventType, listener, thisObject)
+{
+ eventType = eventType || null;
+ listener = listener || null;
+ thisObject = thisObject || null;
+
+ if (!this._listeners)
+ return;
+
+ if (!eventType) {
+ for (eventType in this._listeners)
+ this.removeEventListener(eventType, listener, thisObject);
+ return;
+ }
+
+ var listeners = this._listeners[eventType];
+ if (!listeners)
+ return;
+
+ for (var i = listeners.length - 1; i >= 0; --i) {
+ if (listener && listeners[i].listener === listener && listeners[i].thisObject === thisObject)
+ listeners.splice(i, 1);
+ else if (!listener && thisObject && listeners[i].thisObject === thisObject)
+ listeners.splice(i, 1);
+ }
+
+ if (!listeners.length)
+ delete this._listeners[eventType];
+
+ if (!Object.keys(this._listeners).length)
+ delete this._listeners;
+};
+
+WebInspector.Object.removeAllListeners = function()
+{
+ delete this._listeners;
+};
+
+/**
+ * @param {string} eventType
+ * @return {boolean}
+ */
+WebInspector.Object.hasEventListeners = function(eventType)
+{
+ if (!this._listeners || !this._listeners[eventType])
+ return false;
+ return true;
+};
+
+WebInspector.Object.prototype = {
+ constructor: WebInspector.Object,
+
+ /**
+ * @param {string} eventType
+ * @param {function(WebInspector.Event)} listener
+ * @param {Object=} thisObject
+ */
+ addEventListener: WebInspector.Object.addEventListener,
+
+ /**
+ * @param {string} eventType
+ * @param {function(WebInspector.Event)} listener
+ * @param {Object=} thisObject
+ */
+ removeEventListener: WebInspector.Object.removeEventListener,
+
+ removeAllListeners: WebInspector.Object.removeAllListeners,
+
+ /**
+ * @param {string} eventType
+ * @return {boolean}
+ */
+ hasEventListeners: WebInspector.Object.hasEventListeners,
+
+ /**
+ * @param {string} eventType
+ * @param {*=} eventData
+ * @return {boolean}
+ */
+ dispatchEventToListeners: function(eventType, eventData)
+ {
+ var event = new WebInspector.Event(this, eventType, eventData);
+
+ function dispatch(object)
+ {
+ if (!object || !object._listeners || !object._listeners[eventType] || event._stoppedPropagation)
+ return;
+
+ // Make a copy with slice so mutations during the loop doesn't affect us.
+ var listenersForThisEvent = object._listeners[eventType].slice(0);
+
+ // Iterate over the listeners and call them. Stop if stopPropagation is called.
+ for (var i = 0; i < listenersForThisEvent.length; ++i) {
+ listenersForThisEvent[i].listener.call(listenersForThisEvent[i].thisObject, event);
+ if (event._stoppedPropagation)
+ break;
+ }
+ }
+
+ // Dispatch to listeners of this specific object.
+ dispatch(this);
+
+ // Allow propagation again so listeners on the constructor always have a crack at the event.
+ event._stoppedPropagation = false;
+
+ // Dispatch to listeners on all constructors up the prototype chain, including the immediate constructor.
+ var constructor = this.constructor;
+ while (constructor) {
+ dispatch(constructor);
+
+ if (!constructor.prototype.__proto__)
+ break;
+
+ constructor = constructor.prototype.__proto__.constructor;
+ }
+
+ return event.defaultPrevented;
+ }
+}
+
+/**
+ * @constructor
+ * @param {WebInspector.Object} target
+ * @param {string} type
+ * @param {*=} data
+ */
+WebInspector.Event = function(target, type, data)
+{
+ this.target = target;
+ this.type = type;
+ this.data = data;
+ this.defaultPrevented = false;
+ this._stoppedPropagation = false;
+}
+
+WebInspector.Event.prototype = {
+ constructor: WebInspector.Event,
+
+ stopPropagation: function()
+ {
+ this._stoppedPropagation = true;
+ },
+
+ preventDefault: function()
+ {
+ this.defaultPrevented = true;
+ }
+}
+
+WebInspector.notifications = new WebInspector.Object;