Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(402)

Unified Diff: remoting/webapp/base.js

Issue 245923002: Bring events to JavaScript components (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Last round of CL Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « remoting/webapp/all_js_load.gtestjs ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: remoting/webapp/base.js
diff --git a/remoting/webapp/base.js b/remoting/webapp/base.js
new file mode 100644
index 0000000000000000000000000000000000000000..19d574d71536a09d91f79610d0ce12d193bdeb44
--- /dev/null
+++ b/remoting/webapp/base.js
@@ -0,0 +1,228 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview
+ * A module that contains basic utility components and methods for the
+ * chromoting project
+ *
+ */
+
+'use strict';
+
+var base = {};
+base.debug = function () {};
+
+/**
+ * Whether to break in debugger and alert when an assertion fails.
+ * Set it to true for debugging.
+ * @type {boolean}
+ */
+base.debug.breakOnAssert = false;
+
+/**
+ * Assert that |expr| is true else print the |opt_msg|.
+ * @param {boolean} expr
+ * @param {string=} opt_msg
+ */
+base.debug.assert = function(expr, opt_msg) {
+ if (!expr) {
+ var msg = 'Assertion Failed.';
+ if (opt_msg) {
+ msg += ' ' + opt_msg;
+ }
+ console.error(msg);
+ if (base.debug.breakOnAssert) {
+ alert(msg);
+ debugger;
+ }
+ }
+};
+
+/**
+ * @return {string} The callstack of the current method.
+ */
+base.debug.callstack = function() {
+ try {
+ throw new Error();
+ } catch (e) {
+ var error = /** @type {Error} */ e;
+ var callstack = error.stack
+ .replace(/^\s+(at eval )?at\s+/gm, '') // Remove 'at' and indentation.
+ .split('\n')
+ .splice(0,2); // Remove the stack of the current function.
+ }
+ return callstack.join('\n');
+};
+
+/**
+ * @interface
+ */
+base.Disposable = function() {};
+base.Disposable.prototype.dispose = function() {};
+
+/**
+ * A utility function to invoke |obj|.dispose without a null check on |obj|.
+ * @param {base.Disposable} obj
+ */
+base.dispose = function(obj) {
+ if (obj) {
+ base.debug.assert(typeof obj.dispose == 'function');
+ obj.dispose();
+ }
+};
+
+/**
+ * Copy all properties from src to dest.
+ * @param {Object} dest
+ * @param {Object} src
+ */
+base.mix = function(dest, src) {
+ for (var prop in src) {
+ if (src.hasOwnProperty(prop)) {
+ base.debug.assert(!dest.hasOwnProperty(prop),"Don't override properties");
+ dest[prop] = src[prop];
+ }
+ }
+};
+
+/**
+ * Adds a mixin to a class.
+ * @param {Object} dest
+ * @param {Object} src
+ * @suppress {checkTypes}
+ */
+base.extend = function(dest, src) {
+ base.mix(dest.prototype, src.prototype || src);
+};
+
+base.doNothing = function() {};
+
+/**
+ * A mixin for classes with events.
+ *
+ * For example, to create an alarm event for SmokeDetector:
+ * functionSmokeDetector() {
+ * this.defineEvents(['alarm']);
+ * };
+ * base.extend(SmokeDetector, base.EventSource);
+ *
+ * To fire an event:
+ * SmokeDetector.prototype.onCarbonMonoxideDetected = function() {
+ * var param = {} // optional parameters
+ * this.raiseEvent('alarm', param);
+ * }
+ *
+ * To listen to an event:
+ * var smokeDetector = new SmokeDetector();
+ * smokeDetector.addEventListener('alarm', listenerObj.someCallback)
+ *
+ */
+
+/**
+ * Helper interface for the EventSource.
+ * @constructor
+ */
+base.EventEntry = function() {
+ /** @type {Array.<function():void>} */
+ this.listeners = [];
+};
+
+/**
+ * @constructor
+ * Since this class is implemented as a mixin, the constructor may not be
+ * called. All initializations should be done in defineEvents.
+ */
+base.EventSource = function() {
+ /** @type {Object.<string, base.EventEntry>} */
+ this.eventMap_;
+};
+
+/**
+ * @param {base.EventSource} obj
+ * @param {string} type
+ */
+base.EventSource.isDefined = function(obj, type) {
+ base.debug.assert(Boolean(obj.eventMap_),
+ "The object doesn't support events");
+ base.debug.assert(Boolean(obj.eventMap_[type]), 'Event <' + type +
+ '> is undefined for the current object');
+};
+
+base.EventSource.prototype = {
+ /**
+ * Define |events| for this event source.
+ * @param {Array.<string>} events
+ */
+ defineEvents: function(events) {
+ base.debug.assert(!Boolean(this.eventMap_),
+ 'defineEvents can only be called once.');
+ this.eventMap_ = {};
+ events.forEach(
+ /**
+ * @this {base.EventSource}
+ * @param {string} type
+ */
+ function(type) {
+ base.debug.assert(typeof type == 'string');
+ this.eventMap_[type] = new base.EventEntry();
+ }, this);
+ },
+
+ /**
+ * Add a listener |fn| to listen to |type| event.
+ * @param {string} type
+ * @param {function(?=):void} fn
+ */
+ addEventListener: function(type, fn) {
+ base.debug.assert(typeof fn == 'function');
+ base.EventSource.isDefined(this, type);
+
+ var listeners = this.eventMap_[type].listeners;
+ listeners.push(fn);
+ },
+
+ /**
+ * Remove the listener |fn| from the event source.
+ * @param {string} type
+ * @param {function(?=):void} fn
+ */
+ removeEventListener: function(type, fn) {
+ base.debug.assert(typeof fn == 'function');
+ base.EventSource.isDefined(this, type);
+
+ var listeners = this.eventMap_[type].listeners;
+ // find the listener to remove.
+ for (var i = 0; i < listeners.length; i++) {
+ var listener = listeners[i];
+ if (listener == fn) {
+ listeners.splice(i, 1);
+ break;
+ }
+ }
+ },
+
+ /**
+ * Fire an event of a particular type on this object.
+ * @param {string} type
+ * @param {*=} opt_details The type of |opt_details| should be ?= to
+ * match what is defined in add(remove)EventListener. However, JSCompile
+ * cannot handle invoking an unknown type as an argument to |listener|
+ * As a hack, we set the type to *=.
+ */
+ raiseEvent: function(type, opt_details) {
+ base.EventSource.isDefined(this, type);
+
+ var entry = this.eventMap_[type];
+ var listeners = entry.listeners.slice(0); // Make a copy of the listeners.
+
+ listeners.forEach(
+ /** @param {function(*=):void} listener */
+ function(listener){
+ if (listener) {
+ listener(opt_details);
+ }
+ });
+ }
+};
« no previous file with comments | « remoting/webapp/all_js_load.gtestjs ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698