diff options
Diffstat (limited to 'ecomp-portal-FE/client/bower_components/lodash/vendor')
88 files changed, 0 insertions, 50045 deletions
diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/backbone/LICENSE b/ecomp-portal-FE/client/bower_components/lodash/vendor/backbone/LICENSE deleted file mode 100644 index 02c89b26..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/backbone/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -Copyright (c) 2010-2016 Jeremy Ashkenas, DocumentCloud - -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. diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/backbone/backbone.js b/ecomp-portal-FE/client/bower_components/lodash/vendor/backbone/backbone.js deleted file mode 100644 index 55ccb22b..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/backbone/backbone.js +++ /dev/null @@ -1,1920 +0,0 @@ -// Backbone.js 1.3.3 - -// (c) 2010-2016 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors -// Backbone may be freely distributed under the MIT license. -// For all details and documentation: -// http://backbonejs.org - -(function(factory) { - - // Establish the root object, `window` (`self`) in the browser, or `global` on the server. - // We use `self` instead of `window` for `WebWorker` support. - var root = (typeof self == 'object' && self.self === self && self) || - (typeof global == 'object' && global.global === global && global); - - // Set up Backbone appropriately for the environment. Start with AMD. - if (typeof define === 'function' && define.amd) { - define(['underscore', 'jquery', 'exports'], function(_, $, exports) { - // Export global even in AMD case in case this script is loaded with - // others that may still expect a global Backbone. - root.Backbone = factory(root, exports, _, $); - }); - - // Next for Node.js or CommonJS. jQuery may not be needed as a module. - } else if (typeof exports !== 'undefined') { - var _ = require('underscore'), $; - try { $ = require('jquery'); } catch (e) {} - factory(root, exports, _, $); - - // Finally, as a browser global. - } else { - root.Backbone = factory(root, {}, root._, (root.jQuery || root.Zepto || root.ender || root.$)); - } - -})(function(root, Backbone, _, $) { - - // Initial Setup - // ------------- - - // Save the previous value of the `Backbone` variable, so that it can be - // restored later on, if `noConflict` is used. - var previousBackbone = root.Backbone; - - // Create a local reference to a common array method we'll want to use later. - var slice = Array.prototype.slice; - - // Current version of the library. Keep in sync with `package.json`. - Backbone.VERSION = '1.3.3'; - - // For Backbone's purposes, jQuery, Zepto, Ender, or My Library (kidding) owns - // the `$` variable. - Backbone.$ = $; - - // Runs Backbone.js in *noConflict* mode, returning the `Backbone` variable - // to its previous owner. Returns a reference to this Backbone object. - Backbone.noConflict = function() { - root.Backbone = previousBackbone; - return this; - }; - - // Turn on `emulateHTTP` to support legacy HTTP servers. Setting this option - // will fake `"PATCH"`, `"PUT"` and `"DELETE"` requests via the `_method` parameter and - // set a `X-Http-Method-Override` header. - Backbone.emulateHTTP = false; - - // Turn on `emulateJSON` to support legacy servers that can't deal with direct - // `application/json` requests ... this will encode the body as - // `application/x-www-form-urlencoded` instead and will send the model in a - // form param named `model`. - Backbone.emulateJSON = false; - - // Proxy Backbone class methods to Underscore functions, wrapping the model's - // `attributes` object or collection's `models` array behind the scenes. - // - // collection.filter(function(model) { return model.get('age') > 10 }); - // collection.each(this.addView); - // - // `Function#apply` can be slow so we use the method's arg count, if we know it. - var addMethod = function(length, method, attribute) { - switch (length) { - case 1: return function() { - return _[method](this[attribute]); - }; - case 2: return function(value) { - return _[method](this[attribute], value); - }; - case 3: return function(iteratee, context) { - return _[method](this[attribute], cb(iteratee, this), context); - }; - case 4: return function(iteratee, defaultVal, context) { - return _[method](this[attribute], cb(iteratee, this), defaultVal, context); - }; - default: return function() { - var args = slice.call(arguments); - args.unshift(this[attribute]); - return _[method].apply(_, args); - }; - } - }; - var addUnderscoreMethods = function(Class, methods, attribute) { - _.each(methods, function(length, method) { - if (_[method]) Class.prototype[method] = addMethod(length, method, attribute); - }); - }; - - // Support `collection.sortBy('attr')` and `collection.findWhere({id: 1})`. - var cb = function(iteratee, instance) { - if (_.isFunction(iteratee)) return iteratee; - if (_.isObject(iteratee) && !instance._isModel(iteratee)) return modelMatcher(iteratee); - if (_.isString(iteratee)) return function(model) { return model.get(iteratee); }; - return iteratee; - }; - var modelMatcher = function(attrs) { - var matcher = _.matches(attrs); - return function(model) { - return matcher(model.attributes); - }; - }; - - // Backbone.Events - // --------------- - - // A module that can be mixed in to *any object* in order to provide it with - // a custom event channel. You may bind a callback to an event with `on` or - // remove with `off`; `trigger`-ing an event fires all callbacks in - // succession. - // - // var object = {}; - // _.extend(object, Backbone.Events); - // object.on('expand', function(){ alert('expanded'); }); - // object.trigger('expand'); - // - var Events = Backbone.Events = {}; - - // Regular expression used to split event strings. - var eventSplitter = /\s+/; - - // Iterates over the standard `event, callback` (as well as the fancy multiple - // space-separated events `"change blur", callback` and jQuery-style event - // maps `{event: callback}`). - var eventsApi = function(iteratee, events, name, callback, opts) { - var i = 0, names; - if (name && typeof name === 'object') { - // Handle event maps. - if (callback !== void 0 && 'context' in opts && opts.context === void 0) opts.context = callback; - for (names = _.keys(name); i < names.length ; i++) { - events = eventsApi(iteratee, events, names[i], name[names[i]], opts); - } - } else if (name && eventSplitter.test(name)) { - // Handle space-separated event names by delegating them individually. - for (names = name.split(eventSplitter); i < names.length; i++) { - events = iteratee(events, names[i], callback, opts); - } - } else { - // Finally, standard events. - events = iteratee(events, name, callback, opts); - } - return events; - }; - - // Bind an event to a `callback` function. Passing `"all"` will bind - // the callback to all events fired. - Events.on = function(name, callback, context) { - return internalOn(this, name, callback, context); - }; - - // Guard the `listening` argument from the public API. - var internalOn = function(obj, name, callback, context, listening) { - obj._events = eventsApi(onApi, obj._events || {}, name, callback, { - context: context, - ctx: obj, - listening: listening - }); - - if (listening) { - var listeners = obj._listeners || (obj._listeners = {}); - listeners[listening.id] = listening; - } - - return obj; - }; - - // Inversion-of-control versions of `on`. Tell *this* object to listen to - // an event in another object... keeping track of what it's listening to - // for easier unbinding later. - Events.listenTo = function(obj, name, callback) { - if (!obj) return this; - var id = obj._listenId || (obj._listenId = _.uniqueId('l')); - var listeningTo = this._listeningTo || (this._listeningTo = {}); - var listening = listeningTo[id]; - - // This object is not listening to any other events on `obj` yet. - // Setup the necessary references to track the listening callbacks. - if (!listening) { - var thisId = this._listenId || (this._listenId = _.uniqueId('l')); - listening = listeningTo[id] = {obj: obj, objId: id, id: thisId, listeningTo: listeningTo, count: 0}; - } - - // Bind callbacks on obj, and keep track of them on listening. - internalOn(obj, name, callback, this, listening); - return this; - }; - - // The reducing API that adds a callback to the `events` object. - var onApi = function(events, name, callback, options) { - if (callback) { - var handlers = events[name] || (events[name] = []); - var context = options.context, ctx = options.ctx, listening = options.listening; - if (listening) listening.count++; - - handlers.push({callback: callback, context: context, ctx: context || ctx, listening: listening}); - } - return events; - }; - - // Remove one or many callbacks. If `context` is null, removes all - // callbacks with that function. If `callback` is null, removes all - // callbacks for the event. If `name` is null, removes all bound - // callbacks for all events. - Events.off = function(name, callback, context) { - if (!this._events) return this; - this._events = eventsApi(offApi, this._events, name, callback, { - context: context, - listeners: this._listeners - }); - return this; - }; - - // Tell this object to stop listening to either specific events ... or - // to every object it's currently listening to. - Events.stopListening = function(obj, name, callback) { - var listeningTo = this._listeningTo; - if (!listeningTo) return this; - - var ids = obj ? [obj._listenId] : _.keys(listeningTo); - - for (var i = 0; i < ids.length; i++) { - var listening = listeningTo[ids[i]]; - - // If listening doesn't exist, this object is not currently - // listening to obj. Break out early. - if (!listening) break; - - listening.obj.off(name, callback, this); - } - - return this; - }; - - // The reducing API that removes a callback from the `events` object. - var offApi = function(events, name, callback, options) { - if (!events) return; - - var i = 0, listening; - var context = options.context, listeners = options.listeners; - - // Delete all events listeners and "drop" events. - if (!name && !callback && !context) { - var ids = _.keys(listeners); - for (; i < ids.length; i++) { - listening = listeners[ids[i]]; - delete listeners[listening.id]; - delete listening.listeningTo[listening.objId]; - } - return; - } - - var names = name ? [name] : _.keys(events); - for (; i < names.length; i++) { - name = names[i]; - var handlers = events[name]; - - // Bail out if there are no events stored. - if (!handlers) break; - - // Replace events if there are any remaining. Otherwise, clean up. - var remaining = []; - for (var j = 0; j < handlers.length; j++) { - var handler = handlers[j]; - if ( - callback && callback !== handler.callback && - callback !== handler.callback._callback || - context && context !== handler.context - ) { - remaining.push(handler); - } else { - listening = handler.listening; - if (listening && --listening.count === 0) { - delete listeners[listening.id]; - delete listening.listeningTo[listening.objId]; - } - } - } - - // Update tail event if the list has any events. Otherwise, clean up. - if (remaining.length) { - events[name] = remaining; - } else { - delete events[name]; - } - } - return events; - }; - - // Bind an event to only be triggered a single time. After the first time - // the callback is invoked, its listener will be removed. If multiple events - // are passed in using the space-separated syntax, the handler will fire - // once for each event, not once for a combination of all events. - Events.once = function(name, callback, context) { - // Map the event into a `{event: once}` object. - var events = eventsApi(onceMap, {}, name, callback, _.bind(this.off, this)); - if (typeof name === 'string' && context == null) callback = void 0; - return this.on(events, callback, context); - }; - - // Inversion-of-control versions of `once`. - Events.listenToOnce = function(obj, name, callback) { - // Map the event into a `{event: once}` object. - var events = eventsApi(onceMap, {}, name, callback, _.bind(this.stopListening, this, obj)); - return this.listenTo(obj, events); - }; - - // Reduces the event callbacks into a map of `{event: onceWrapper}`. - // `offer` unbinds the `onceWrapper` after it has been called. - var onceMap = function(map, name, callback, offer) { - if (callback) { - var once = map[name] = _.once(function() { - offer(name, once); - callback.apply(this, arguments); - }); - once._callback = callback; - } - return map; - }; - - // Trigger one or many events, firing all bound callbacks. Callbacks are - // passed the same arguments as `trigger` is, apart from the event name - // (unless you're listening on `"all"`, which will cause your callback to - // receive the true name of the event as the first argument). - Events.trigger = function(name) { - if (!this._events) return this; - - var length = Math.max(0, arguments.length - 1); - var args = Array(length); - for (var i = 0; i < length; i++) args[i] = arguments[i + 1]; - - eventsApi(triggerApi, this._events, name, void 0, args); - return this; - }; - - // Handles triggering the appropriate event callbacks. - var triggerApi = function(objEvents, name, callback, args) { - if (objEvents) { - var events = objEvents[name]; - var allEvents = objEvents.all; - if (events && allEvents) allEvents = allEvents.slice(); - if (events) triggerEvents(events, args); - if (allEvents) triggerEvents(allEvents, [name].concat(args)); - } - return objEvents; - }; - - // A difficult-to-believe, but optimized internal dispatch function for - // triggering events. Tries to keep the usual cases speedy (most internal - // Backbone events have 3 arguments). - var triggerEvents = function(events, args) { - var ev, i = -1, l = events.length, a1 = args[0], a2 = args[1], a3 = args[2]; - switch (args.length) { - case 0: while (++i < l) (ev = events[i]).callback.call(ev.ctx); return; - case 1: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1); return; - case 2: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2); return; - case 3: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2, a3); return; - default: while (++i < l) (ev = events[i]).callback.apply(ev.ctx, args); return; - } - }; - - // Aliases for backwards compatibility. - Events.bind = Events.on; - Events.unbind = Events.off; - - // Allow the `Backbone` object to serve as a global event bus, for folks who - // want global "pubsub" in a convenient place. - _.extend(Backbone, Events); - - // Backbone.Model - // -------------- - - // Backbone **Models** are the basic data object in the framework -- - // frequently representing a row in a table in a database on your server. - // A discrete chunk of data and a bunch of useful, related methods for - // performing computations and transformations on that data. - - // Create a new model with the specified attributes. A client id (`cid`) - // is automatically generated and assigned for you. - var Model = Backbone.Model = function(attributes, options) { - var attrs = attributes || {}; - options || (options = {}); - this.cid = _.uniqueId(this.cidPrefix); - this.attributes = {}; - if (options.collection) this.collection = options.collection; - if (options.parse) attrs = this.parse(attrs, options) || {}; - var defaults = _.result(this, 'defaults'); - attrs = _.defaults(_.extend({}, defaults, attrs), defaults); - this.set(attrs, options); - this.changed = {}; - this.initialize.apply(this, arguments); - }; - - // Attach all inheritable methods to the Model prototype. - _.extend(Model.prototype, Events, { - - // A hash of attributes whose current and previous value differ. - changed: null, - - // The value returned during the last failed validation. - validationError: null, - - // The default name for the JSON `id` attribute is `"id"`. MongoDB and - // CouchDB users may want to set this to `"_id"`. - idAttribute: 'id', - - // The prefix is used to create the client id which is used to identify models locally. - // You may want to override this if you're experiencing name clashes with model ids. - cidPrefix: 'c', - - // Initialize is an empty function by default. Override it with your own - // initialization logic. - initialize: function(){}, - - // Return a copy of the model's `attributes` object. - toJSON: function(options) { - return _.clone(this.attributes); - }, - - // Proxy `Backbone.sync` by default -- but override this if you need - // custom syncing semantics for *this* particular model. - sync: function() { - return Backbone.sync.apply(this, arguments); - }, - - // Get the value of an attribute. - get: function(attr) { - return this.attributes[attr]; - }, - - // Get the HTML-escaped value of an attribute. - escape: function(attr) { - return _.escape(this.get(attr)); - }, - - // Returns `true` if the attribute contains a value that is not null - // or undefined. - has: function(attr) { - return this.get(attr) != null; - }, - - // Special-cased proxy to underscore's `_.matches` method. - matches: function(attrs) { - return !!_.iteratee(attrs, this)(this.attributes); - }, - - // Set a hash of model attributes on the object, firing `"change"`. This is - // the core primitive operation of a model, updating the data and notifying - // anyone who needs to know about the change in state. The heart of the beast. - set: function(key, val, options) { - if (key == null) return this; - - // Handle both `"key", value` and `{key: value}` -style arguments. - var attrs; - if (typeof key === 'object') { - attrs = key; - options = val; - } else { - (attrs = {})[key] = val; - } - - options || (options = {}); - - // Run validation. - if (!this._validate(attrs, options)) return false; - - // Extract attributes and options. - var unset = options.unset; - var silent = options.silent; - var changes = []; - var changing = this._changing; - this._changing = true; - - if (!changing) { - this._previousAttributes = _.clone(this.attributes); - this.changed = {}; - } - - var current = this.attributes; - var changed = this.changed; - var prev = this._previousAttributes; - - // For each `set` attribute, update or delete the current value. - for (var attr in attrs) { - val = attrs[attr]; - if (!_.isEqual(current[attr], val)) changes.push(attr); - if (!_.isEqual(prev[attr], val)) { - changed[attr] = val; - } else { - delete changed[attr]; - } - unset ? delete current[attr] : current[attr] = val; - } - - // Update the `id`. - if (this.idAttribute in attrs) this.id = this.get(this.idAttribute); - - // Trigger all relevant attribute changes. - if (!silent) { - if (changes.length) this._pending = options; - for (var i = 0; i < changes.length; i++) { - this.trigger('change:' + changes[i], this, current[changes[i]], options); - } - } - - // You might be wondering why there's a `while` loop here. Changes can - // be recursively nested within `"change"` events. - if (changing) return this; - if (!silent) { - while (this._pending) { - options = this._pending; - this._pending = false; - this.trigger('change', this, options); - } - } - this._pending = false; - this._changing = false; - return this; - }, - - // Remove an attribute from the model, firing `"change"`. `unset` is a noop - // if the attribute doesn't exist. - unset: function(attr, options) { - return this.set(attr, void 0, _.extend({}, options, {unset: true})); - }, - - // Clear all attributes on the model, firing `"change"`. - clear: function(options) { - var attrs = {}; - for (var key in this.attributes) attrs[key] = void 0; - return this.set(attrs, _.extend({}, options, {unset: true})); - }, - - // Determine if the model has changed since the last `"change"` event. - // If you specify an attribute name, determine if that attribute has changed. - hasChanged: function(attr) { - if (attr == null) return !_.isEmpty(this.changed); - return _.has(this.changed, attr); - }, - - // Return an object containing all the attributes that have changed, or - // false if there are no changed attributes. Useful for determining what - // parts of a view need to be updated and/or what attributes need to be - // persisted to the server. Unset attributes will be set to undefined. - // You can also pass an attributes object to diff against the model, - // determining if there *would be* a change. - changedAttributes: function(diff) { - if (!diff) return this.hasChanged() ? _.clone(this.changed) : false; - var old = this._changing ? this._previousAttributes : this.attributes; - var changed = {}; - for (var attr in diff) { - var val = diff[attr]; - if (_.isEqual(old[attr], val)) continue; - changed[attr] = val; - } - return _.size(changed) ? changed : false; - }, - - // Get the previous value of an attribute, recorded at the time the last - // `"change"` event was fired. - previous: function(attr) { - if (attr == null || !this._previousAttributes) return null; - return this._previousAttributes[attr]; - }, - - // Get all of the attributes of the model at the time of the previous - // `"change"` event. - previousAttributes: function() { - return _.clone(this._previousAttributes); - }, - - // Fetch the model from the server, merging the response with the model's - // local attributes. Any changed attributes will trigger a "change" event. - fetch: function(options) { - options = _.extend({parse: true}, options); - var model = this; - var success = options.success; - options.success = function(resp) { - var serverAttrs = options.parse ? model.parse(resp, options) : resp; - if (!model.set(serverAttrs, options)) return false; - if (success) success.call(options.context, model, resp, options); - model.trigger('sync', model, resp, options); - }; - wrapError(this, options); - return this.sync('read', this, options); - }, - - // Set a hash of model attributes, and sync the model to the server. - // If the server returns an attributes hash that differs, the model's - // state will be `set` again. - save: function(key, val, options) { - // Handle both `"key", value` and `{key: value}` -style arguments. - var attrs; - if (key == null || typeof key === 'object') { - attrs = key; - options = val; - } else { - (attrs = {})[key] = val; - } - - options = _.extend({validate: true, parse: true}, options); - var wait = options.wait; - - // If we're not waiting and attributes exist, save acts as - // `set(attr).save(null, opts)` with validation. Otherwise, check if - // the model will be valid when the attributes, if any, are set. - if (attrs && !wait) { - if (!this.set(attrs, options)) return false; - } else if (!this._validate(attrs, options)) { - return false; - } - - // After a successful server-side save, the client is (optionally) - // updated with the server-side state. - var model = this; - var success = options.success; - var attributes = this.attributes; - options.success = function(resp) { - // Ensure attributes are restored during synchronous saves. - model.attributes = attributes; - var serverAttrs = options.parse ? model.parse(resp, options) : resp; - if (wait) serverAttrs = _.extend({}, attrs, serverAttrs); - if (serverAttrs && !model.set(serverAttrs, options)) return false; - if (success) success.call(options.context, model, resp, options); - model.trigger('sync', model, resp, options); - }; - wrapError(this, options); - - // Set temporary attributes if `{wait: true}` to properly find new ids. - if (attrs && wait) this.attributes = _.extend({}, attributes, attrs); - - var method = this.isNew() ? 'create' : (options.patch ? 'patch' : 'update'); - if (method === 'patch' && !options.attrs) options.attrs = attrs; - var xhr = this.sync(method, this, options); - - // Restore attributes. - this.attributes = attributes; - - return xhr; - }, - - // Destroy this model on the server if it was already persisted. - // Optimistically removes the model from its collection, if it has one. - // If `wait: true` is passed, waits for the server to respond before removal. - destroy: function(options) { - options = options ? _.clone(options) : {}; - var model = this; - var success = options.success; - var wait = options.wait; - - var destroy = function() { - model.stopListening(); - model.trigger('destroy', model, model.collection, options); - }; - - options.success = function(resp) { - if (wait) destroy(); - if (success) success.call(options.context, model, resp, options); - if (!model.isNew()) model.trigger('sync', model, resp, options); - }; - - var xhr = false; - if (this.isNew()) { - _.defer(options.success); - } else { - wrapError(this, options); - xhr = this.sync('delete', this, options); - } - if (!wait) destroy(); - return xhr; - }, - - // Default URL for the model's representation on the server -- if you're - // using Backbone's restful methods, override this to change the endpoint - // that will be called. - url: function() { - var base = - _.result(this, 'urlRoot') || - _.result(this.collection, 'url') || - urlError(); - if (this.isNew()) return base; - var id = this.get(this.idAttribute); - return base.replace(/[^\/]$/, '$&/') + encodeURIComponent(id); - }, - - // **parse** converts a response into the hash of attributes to be `set` on - // the model. The default implementation is just to pass the response along. - parse: function(resp, options) { - return resp; - }, - - // Create a new model with identical attributes to this one. - clone: function() { - return new this.constructor(this.attributes); - }, - - // A model is new if it has never been saved to the server, and lacks an id. - isNew: function() { - return !this.has(this.idAttribute); - }, - - // Check if the model is currently in a valid state. - isValid: function(options) { - return this._validate({}, _.extend({}, options, {validate: true})); - }, - - // Run validation against the next complete set of model attributes, - // returning `true` if all is well. Otherwise, fire an `"invalid"` event. - _validate: function(attrs, options) { - if (!options.validate || !this.validate) return true; - attrs = _.extend({}, this.attributes, attrs); - var error = this.validationError = this.validate(attrs, options) || null; - if (!error) return true; - this.trigger('invalid', this, error, _.extend(options, {validationError: error})); - return false; - } - - }); - - // Underscore methods that we want to implement on the Model, mapped to the - // number of arguments they take. - var modelMethods = {keys: 1, values: 1, pairs: 1, invert: 1, pick: 0, - omit: 0, chain: 1, isEmpty: 1}; - - // Mix in each Underscore method as a proxy to `Model#attributes`. - addUnderscoreMethods(Model, modelMethods, 'attributes'); - - // Backbone.Collection - // ------------------- - - // If models tend to represent a single row of data, a Backbone Collection is - // more analogous to a table full of data ... or a small slice or page of that - // table, or a collection of rows that belong together for a particular reason - // -- all of the messages in this particular folder, all of the documents - // belonging to this particular author, and so on. Collections maintain - // indexes of their models, both in order, and for lookup by `id`. - - // Create a new **Collection**, perhaps to contain a specific type of `model`. - // If a `comparator` is specified, the Collection will maintain - // its models in sort order, as they're added and removed. - var Collection = Backbone.Collection = function(models, options) { - options || (options = {}); - if (options.model) this.model = options.model; - if (options.comparator !== void 0) this.comparator = options.comparator; - this._reset(); - this.initialize.apply(this, arguments); - if (models) this.reset(models, _.extend({silent: true}, options)); - }; - - // Default options for `Collection#set`. - var setOptions = {add: true, remove: true, merge: true}; - var addOptions = {add: true, remove: false}; - - // Splices `insert` into `array` at index `at`. - var splice = function(array, insert, at) { - at = Math.min(Math.max(at, 0), array.length); - var tail = Array(array.length - at); - var length = insert.length; - var i; - for (i = 0; i < tail.length; i++) tail[i] = array[i + at]; - for (i = 0; i < length; i++) array[i + at] = insert[i]; - for (i = 0; i < tail.length; i++) array[i + length + at] = tail[i]; - }; - - // Define the Collection's inheritable methods. - _.extend(Collection.prototype, Events, { - - // The default model for a collection is just a **Backbone.Model**. - // This should be overridden in most cases. - model: Model, - - // Initialize is an empty function by default. Override it with your own - // initialization logic. - initialize: function(){}, - - // The JSON representation of a Collection is an array of the - // models' attributes. - toJSON: function(options) { - return this.map(function(model) { return model.toJSON(options); }); - }, - - // Proxy `Backbone.sync` by default. - sync: function() { - return Backbone.sync.apply(this, arguments); - }, - - // Add a model, or list of models to the set. `models` may be Backbone - // Models or raw JavaScript objects to be converted to Models, or any - // combination of the two. - add: function(models, options) { - return this.set(models, _.extend({merge: false}, options, addOptions)); - }, - - // Remove a model, or a list of models from the set. - remove: function(models, options) { - options = _.extend({}, options); - var singular = !_.isArray(models); - models = singular ? [models] : models.slice(); - var removed = this._removeModels(models, options); - if (!options.silent && removed.length) { - options.changes = {added: [], merged: [], removed: removed}; - this.trigger('update', this, options); - } - return singular ? removed[0] : removed; - }, - - // Update a collection by `set`-ing a new list of models, adding new ones, - // removing models that are no longer present, and merging models that - // already exist in the collection, as necessary. Similar to **Model#set**, - // the core operation for updating the data contained by the collection. - set: function(models, options) { - if (models == null) return; - - options = _.extend({}, setOptions, options); - if (options.parse && !this._isModel(models)) { - models = this.parse(models, options) || []; - } - - var singular = !_.isArray(models); - models = singular ? [models] : models.slice(); - - var at = options.at; - if (at != null) at = +at; - if (at > this.length) at = this.length; - if (at < 0) at += this.length + 1; - - var set = []; - var toAdd = []; - var toMerge = []; - var toRemove = []; - var modelMap = {}; - - var add = options.add; - var merge = options.merge; - var remove = options.remove; - - var sort = false; - var sortable = this.comparator && at == null && options.sort !== false; - var sortAttr = _.isString(this.comparator) ? this.comparator : null; - - // Turn bare objects into model references, and prevent invalid models - // from being added. - var model, i; - for (i = 0; i < models.length; i++) { - model = models[i]; - - // If a duplicate is found, prevent it from being added and - // optionally merge it into the existing model. - var existing = this.get(model); - if (existing) { - if (merge && model !== existing) { - var attrs = this._isModel(model) ? model.attributes : model; - if (options.parse) attrs = existing.parse(attrs, options); - existing.set(attrs, options); - toMerge.push(existing); - if (sortable && !sort) sort = existing.hasChanged(sortAttr); - } - if (!modelMap[existing.cid]) { - modelMap[existing.cid] = true; - set.push(existing); - } - models[i] = existing; - - // If this is a new, valid model, push it to the `toAdd` list. - } else if (add) { - model = models[i] = this._prepareModel(model, options); - if (model) { - toAdd.push(model); - this._addReference(model, options); - modelMap[model.cid] = true; - set.push(model); - } - } - } - - // Remove stale models. - if (remove) { - for (i = 0; i < this.length; i++) { - model = this.models[i]; - if (!modelMap[model.cid]) toRemove.push(model); - } - if (toRemove.length) this._removeModels(toRemove, options); - } - - // See if sorting is needed, update `length` and splice in new models. - var orderChanged = false; - var replace = !sortable && add && remove; - if (set.length && replace) { - orderChanged = this.length !== set.length || _.some(this.models, function(m, index) { - return m !== set[index]; - }); - this.models.length = 0; - splice(this.models, set, 0); - this.length = this.models.length; - } else if (toAdd.length) { - if (sortable) sort = true; - splice(this.models, toAdd, at == null ? this.length : at); - this.length = this.models.length; - } - - // Silently sort the collection if appropriate. - if (sort) this.sort({silent: true}); - - // Unless silenced, it's time to fire all appropriate add/sort/update events. - if (!options.silent) { - for (i = 0; i < toAdd.length; i++) { - if (at != null) options.index = at + i; - model = toAdd[i]; - model.trigger('add', model, this, options); - } - if (sort || orderChanged) this.trigger('sort', this, options); - if (toAdd.length || toRemove.length || toMerge.length) { - options.changes = { - added: toAdd, - removed: toRemove, - merged: toMerge - }; - this.trigger('update', this, options); - } - } - - // Return the added (or merged) model (or models). - return singular ? models[0] : models; - }, - - // When you have more items than you want to add or remove individually, - // you can reset the entire set with a new list of models, without firing - // any granular `add` or `remove` events. Fires `reset` when finished. - // Useful for bulk operations and optimizations. - reset: function(models, options) { - options = options ? _.clone(options) : {}; - for (var i = 0; i < this.models.length; i++) { - this._removeReference(this.models[i], options); - } - options.previousModels = this.models; - this._reset(); - models = this.add(models, _.extend({silent: true}, options)); - if (!options.silent) this.trigger('reset', this, options); - return models; - }, - - // Add a model to the end of the collection. - push: function(model, options) { - return this.add(model, _.extend({at: this.length}, options)); - }, - - // Remove a model from the end of the collection. - pop: function(options) { - var model = this.at(this.length - 1); - return this.remove(model, options); - }, - - // Add a model to the beginning of the collection. - unshift: function(model, options) { - return this.add(model, _.extend({at: 0}, options)); - }, - - // Remove a model from the beginning of the collection. - shift: function(options) { - var model = this.at(0); - return this.remove(model, options); - }, - - // Slice out a sub-array of models from the collection. - slice: function() { - return slice.apply(this.models, arguments); - }, - - // Get a model from the set by id, cid, model object with id or cid - // properties, or an attributes object that is transformed through modelId. - get: function(obj) { - if (obj == null) return void 0; - return this._byId[obj] || - this._byId[this.modelId(obj.attributes || obj)] || - obj.cid && this._byId[obj.cid]; - }, - - // Returns `true` if the model is in the collection. - has: function(obj) { - return this.get(obj) != null; - }, - - // Get the model at the given index. - at: function(index) { - if (index < 0) index += this.length; - return this.models[index]; - }, - - // Return models with matching attributes. Useful for simple cases of - // `filter`. - where: function(attrs, first) { - return this[first ? 'find' : 'filter'](attrs); - }, - - // Return the first model with matching attributes. Useful for simple cases - // of `find`. - findWhere: function(attrs) { - return this.where(attrs, true); - }, - - // Force the collection to re-sort itself. You don't need to call this under - // normal circumstances, as the set will maintain sort order as each item - // is added. - sort: function(options) { - var comparator = this.comparator; - if (!comparator) throw new Error('Cannot sort a set without a comparator'); - options || (options = {}); - - var length = comparator.length; - if (_.isFunction(comparator)) comparator = _.bind(comparator, this); - - // Run sort based on type of `comparator`. - if (length === 1 || _.isString(comparator)) { - this.models = this.sortBy(comparator); - } else { - this.models.sort(comparator); - } - if (!options.silent) this.trigger('sort', this, options); - return this; - }, - - // Pluck an attribute from each model in the collection. - pluck: function(attr) { - return this.map(attr + ''); - }, - - // Fetch the default set of models for this collection, resetting the - // collection when they arrive. If `reset: true` is passed, the response - // data will be passed through the `reset` method instead of `set`. - fetch: function(options) { - options = _.extend({parse: true}, options); - var success = options.success; - var collection = this; - options.success = function(resp) { - var method = options.reset ? 'reset' : 'set'; - collection[method](resp, options); - if (success) success.call(options.context, collection, resp, options); - collection.trigger('sync', collection, resp, options); - }; - wrapError(this, options); - return this.sync('read', this, options); - }, - - // Create a new instance of a model in this collection. Add the model to the - // collection immediately, unless `wait: true` is passed, in which case we - // wait for the server to agree. - create: function(model, options) { - options = options ? _.clone(options) : {}; - var wait = options.wait; - model = this._prepareModel(model, options); - if (!model) return false; - if (!wait) this.add(model, options); - var collection = this; - var success = options.success; - options.success = function(m, resp, callbackOpts) { - if (wait) collection.add(m, callbackOpts); - if (success) success.call(callbackOpts.context, m, resp, callbackOpts); - }; - model.save(null, options); - return model; - }, - - // **parse** converts a response into a list of models to be added to the - // collection. The default implementation is just to pass it through. - parse: function(resp, options) { - return resp; - }, - - // Create a new collection with an identical list of models as this one. - clone: function() { - return new this.constructor(this.models, { - model: this.model, - comparator: this.comparator - }); - }, - - // Define how to uniquely identify models in the collection. - modelId: function(attrs) { - return attrs[this.model.prototype.idAttribute || 'id']; - }, - - // Private method to reset all internal state. Called when the collection - // is first initialized or reset. - _reset: function() { - this.length = 0; - this.models = []; - this._byId = {}; - }, - - // Prepare a hash of attributes (or other model) to be added to this - // collection. - _prepareModel: function(attrs, options) { - if (this._isModel(attrs)) { - if (!attrs.collection) attrs.collection = this; - return attrs; - } - options = options ? _.clone(options) : {}; - options.collection = this; - var model = new this.model(attrs, options); - if (!model.validationError) return model; - this.trigger('invalid', this, model.validationError, options); - return false; - }, - - // Internal method called by both remove and set. - _removeModels: function(models, options) { - var removed = []; - for (var i = 0; i < models.length; i++) { - var model = this.get(models[i]); - if (!model) continue; - - var index = this.indexOf(model); - this.models.splice(index, 1); - this.length--; - - // Remove references before triggering 'remove' event to prevent an - // infinite loop. #3693 - delete this._byId[model.cid]; - var id = this.modelId(model.attributes); - if (id != null) delete this._byId[id]; - - if (!options.silent) { - options.index = index; - model.trigger('remove', model, this, options); - } - - removed.push(model); - this._removeReference(model, options); - } - return removed; - }, - - // Method for checking whether an object should be considered a model for - // the purposes of adding to the collection. - _isModel: function(model) { - return model instanceof Model; - }, - - // Internal method to create a model's ties to a collection. - _addReference: function(model, options) { - this._byId[model.cid] = model; - var id = this.modelId(model.attributes); - if (id != null) this._byId[id] = model; - model.on('all', this._onModelEvent, this); - }, - - // Internal method to sever a model's ties to a collection. - _removeReference: function(model, options) { - delete this._byId[model.cid]; - var id = this.modelId(model.attributes); - if (id != null) delete this._byId[id]; - if (this === model.collection) delete model.collection; - model.off('all', this._onModelEvent, this); - }, - - // Internal method called every time a model in the set fires an event. - // Sets need to update their indexes when models change ids. All other - // events simply proxy through. "add" and "remove" events that originate - // in other collections are ignored. - _onModelEvent: function(event, model, collection, options) { - if (model) { - if ((event === 'add' || event === 'remove') && collection !== this) return; - if (event === 'destroy') this.remove(model, options); - if (event === 'change') { - var prevId = this.modelId(model.previousAttributes()); - var id = this.modelId(model.attributes); - if (prevId !== id) { - if (prevId != null) delete this._byId[prevId]; - if (id != null) this._byId[id] = model; - } - } - } - this.trigger.apply(this, arguments); - } - - }); - - // Underscore methods that we want to implement on the Collection. - // 90% of the core usefulness of Backbone Collections is actually implemented - // right here: - var collectionMethods = {forEach: 3, each: 3, map: 3, collect: 3, reduce: 0, - foldl: 0, inject: 0, reduceRight: 0, foldr: 0, find: 3, detect: 3, filter: 3, - select: 3, reject: 3, every: 3, all: 3, some: 3, any: 3, include: 3, includes: 3, - contains: 3, invoke: 0, max: 3, min: 3, toArray: 1, size: 1, first: 3, - head: 3, take: 3, initial: 3, rest: 3, tail: 3, drop: 3, last: 3, - without: 0, difference: 0, indexOf: 3, shuffle: 1, lastIndexOf: 3, - isEmpty: 1, chain: 1, sample: 3, partition: 3, groupBy: 3, countBy: 3, - sortBy: 3, indexBy: 3, findIndex: 3, findLastIndex: 3}; - - // Mix in each Underscore method as a proxy to `Collection#models`. - addUnderscoreMethods(Collection, collectionMethods, 'models'); - - // Backbone.View - // ------------- - - // Backbone Views are almost more convention than they are actual code. A View - // is simply a JavaScript object that represents a logical chunk of UI in the - // DOM. This might be a single item, an entire list, a sidebar or panel, or - // even the surrounding frame which wraps your whole app. Defining a chunk of - // UI as a **View** allows you to define your DOM events declaratively, without - // having to worry about render order ... and makes it easy for the view to - // react to specific changes in the state of your models. - - // Creating a Backbone.View creates its initial element outside of the DOM, - // if an existing element is not provided... - var View = Backbone.View = function(options) { - this.cid = _.uniqueId('view'); - _.extend(this, _.pick(options, viewOptions)); - this._ensureElement(); - this.initialize.apply(this, arguments); - }; - - // Cached regex to split keys for `delegate`. - var delegateEventSplitter = /^(\S+)\s*(.*)$/; - - // List of view options to be set as properties. - var viewOptions = ['model', 'collection', 'el', 'id', 'attributes', 'className', 'tagName', 'events']; - - // Set up all inheritable **Backbone.View** properties and methods. - _.extend(View.prototype, Events, { - - // The default `tagName` of a View's element is `"div"`. - tagName: 'div', - - // jQuery delegate for element lookup, scoped to DOM elements within the - // current view. This should be preferred to global lookups where possible. - $: function(selector) { - return this.$el.find(selector); - }, - - // Initialize is an empty function by default. Override it with your own - // initialization logic. - initialize: function(){}, - - // **render** is the core function that your view should override, in order - // to populate its element (`this.el`), with the appropriate HTML. The - // convention is for **render** to always return `this`. - render: function() { - return this; - }, - - // Remove this view by taking the element out of the DOM, and removing any - // applicable Backbone.Events listeners. - remove: function() { - this._removeElement(); - this.stopListening(); - return this; - }, - - // Remove this view's element from the document and all event listeners - // attached to it. Exposed for subclasses using an alternative DOM - // manipulation API. - _removeElement: function() { - this.$el.remove(); - }, - - // Change the view's element (`this.el` property) and re-delegate the - // view's events on the new element. - setElement: function(element) { - this.undelegateEvents(); - this._setElement(element); - this.delegateEvents(); - return this; - }, - - // Creates the `this.el` and `this.$el` references for this view using the - // given `el`. `el` can be a CSS selector or an HTML string, a jQuery - // context or an element. Subclasses can override this to utilize an - // alternative DOM manipulation API and are only required to set the - // `this.el` property. - _setElement: function(el) { - this.$el = el instanceof Backbone.$ ? el : Backbone.$(el); - this.el = this.$el[0]; - }, - - // Set callbacks, where `this.events` is a hash of - // - // *{"event selector": "callback"}* - // - // { - // 'mousedown .title': 'edit', - // 'click .button': 'save', - // 'click .open': function(e) { ... } - // } - // - // pairs. Callbacks will be bound to the view, with `this` set properly. - // Uses event delegation for efficiency. - // Omitting the selector binds the event to `this.el`. - delegateEvents: function(events) { - events || (events = _.result(this, 'events')); - if (!events) return this; - this.undelegateEvents(); - for (var key in events) { - var method = events[key]; - if (!_.isFunction(method)) method = this[method]; - if (!method) continue; - var match = key.match(delegateEventSplitter); - this.delegate(match[1], match[2], _.bind(method, this)); - } - return this; - }, - - // Add a single event listener to the view's element (or a child element - // using `selector`). This only works for delegate-able events: not `focus`, - // `blur`, and not `change`, `submit`, and `reset` in Internet Explorer. - delegate: function(eventName, selector, listener) { - this.$el.on(eventName + '.delegateEvents' + this.cid, selector, listener); - return this; - }, - - // Clears all callbacks previously bound to the view by `delegateEvents`. - // You usually don't need to use this, but may wish to if you have multiple - // Backbone views attached to the same DOM element. - undelegateEvents: function() { - if (this.$el) this.$el.off('.delegateEvents' + this.cid); - return this; - }, - - // A finer-grained `undelegateEvents` for removing a single delegated event. - // `selector` and `listener` are both optional. - undelegate: function(eventName, selector, listener) { - this.$el.off(eventName + '.delegateEvents' + this.cid, selector, listener); - return this; - }, - - // Produces a DOM element to be assigned to your view. Exposed for - // subclasses using an alternative DOM manipulation API. - _createElement: function(tagName) { - return document.createElement(tagName); - }, - - // Ensure that the View has a DOM element to render into. - // If `this.el` is a string, pass it through `$()`, take the first - // matching element, and re-assign it to `el`. Otherwise, create - // an element from the `id`, `className` and `tagName` properties. - _ensureElement: function() { - if (!this.el) { - var attrs = _.extend({}, _.result(this, 'attributes')); - if (this.id) attrs.id = _.result(this, 'id'); - if (this.className) attrs['class'] = _.result(this, 'className'); - this.setElement(this._createElement(_.result(this, 'tagName'))); - this._setAttributes(attrs); - } else { - this.setElement(_.result(this, 'el')); - } - }, - - // Set attributes from a hash on this view's element. Exposed for - // subclasses using an alternative DOM manipulation API. - _setAttributes: function(attributes) { - this.$el.attr(attributes); - } - - }); - - // Backbone.sync - // ------------- - - // Override this function to change the manner in which Backbone persists - // models to the server. You will be passed the type of request, and the - // model in question. By default, makes a RESTful Ajax request - // to the model's `url()`. Some possible customizations could be: - // - // * Use `setTimeout` to batch rapid-fire updates into a single request. - // * Send up the models as XML instead of JSON. - // * Persist models via WebSockets instead of Ajax. - // - // Turn on `Backbone.emulateHTTP` in order to send `PUT` and `DELETE` requests - // as `POST`, with a `_method` parameter containing the true HTTP method, - // as well as all requests with the body as `application/x-www-form-urlencoded` - // instead of `application/json` with the model in a param named `model`. - // Useful when interfacing with server-side languages like **PHP** that make - // it difficult to read the body of `PUT` requests. - Backbone.sync = function(method, model, options) { - var type = methodMap[method]; - - // Default options, unless specified. - _.defaults(options || (options = {}), { - emulateHTTP: Backbone.emulateHTTP, - emulateJSON: Backbone.emulateJSON - }); - - // Default JSON-request options. - var params = {type: type, dataType: 'json'}; - - // Ensure that we have a URL. - if (!options.url) { - params.url = _.result(model, 'url') || urlError(); - } - - // Ensure that we have the appropriate request data. - if (options.data == null && model && (method === 'create' || method === 'update' || method === 'patch')) { - params.contentType = 'application/json'; - params.data = JSON.stringify(options.attrs || model.toJSON(options)); - } - - // For older servers, emulate JSON by encoding the request into an HTML-form. - if (options.emulateJSON) { - params.contentType = 'application/x-www-form-urlencoded'; - params.data = params.data ? {model: params.data} : {}; - } - - // For older servers, emulate HTTP by mimicking the HTTP method with `_method` - // And an `X-HTTP-Method-Override` header. - if (options.emulateHTTP && (type === 'PUT' || type === 'DELETE' || type === 'PATCH')) { - params.type = 'POST'; - if (options.emulateJSON) params.data._method = type; - var beforeSend = options.beforeSend; - options.beforeSend = function(xhr) { - xhr.setRequestHeader('X-HTTP-Method-Override', type); - if (beforeSend) return beforeSend.apply(this, arguments); - }; - } - - // Don't process data on a non-GET request. - if (params.type !== 'GET' && !options.emulateJSON) { - params.processData = false; - } - - // Pass along `textStatus` and `errorThrown` from jQuery. - var error = options.error; - options.error = function(xhr, textStatus, errorThrown) { - options.textStatus = textStatus; - options.errorThrown = errorThrown; - if (error) error.call(options.context, xhr, textStatus, errorThrown); - }; - - // Make the request, allowing the user to override any Ajax options. - var xhr = options.xhr = Backbone.ajax(_.extend(params, options)); - model.trigger('request', model, xhr, options); - return xhr; - }; - - // Map from CRUD to HTTP for our default `Backbone.sync` implementation. - var methodMap = { - 'create': 'POST', - 'update': 'PUT', - 'patch': 'PATCH', - 'delete': 'DELETE', - 'read': 'GET' - }; - - // Set the default implementation of `Backbone.ajax` to proxy through to `$`. - // Override this if you'd like to use a different library. - Backbone.ajax = function() { - return Backbone.$.ajax.apply(Backbone.$, arguments); - }; - - // Backbone.Router - // --------------- - - // Routers map faux-URLs to actions, and fire events when routes are - // matched. Creating a new one sets its `routes` hash, if not set statically. - var Router = Backbone.Router = function(options) { - options || (options = {}); - if (options.routes) this.routes = options.routes; - this._bindRoutes(); - this.initialize.apply(this, arguments); - }; - - // Cached regular expressions for matching named param parts and splatted - // parts of route strings. - var optionalParam = /\((.*?)\)/g; - var namedParam = /(\(\?)?:\w+/g; - var splatParam = /\*\w+/g; - var escapeRegExp = /[\-{}\[\]+?.,\\\^$|#\s]/g; - - // Set up all inheritable **Backbone.Router** properties and methods. - _.extend(Router.prototype, Events, { - - // Initialize is an empty function by default. Override it with your own - // initialization logic. - initialize: function(){}, - - // Manually bind a single named route to a callback. For example: - // - // this.route('search/:query/p:num', 'search', function(query, num) { - // ... - // }); - // - route: function(route, name, callback) { - if (!_.isRegExp(route)) route = this._routeToRegExp(route); - if (_.isFunction(name)) { - callback = name; - name = ''; - } - if (!callback) callback = this[name]; - var router = this; - Backbone.history.route(route, function(fragment) { - var args = router._extractParameters(route, fragment); - if (router.execute(callback, args, name) !== false) { - router.trigger.apply(router, ['route:' + name].concat(args)); - router.trigger('route', name, args); - Backbone.history.trigger('route', router, name, args); - } - }); - return this; - }, - - // Execute a route handler with the provided parameters. This is an - // excellent place to do pre-route setup or post-route cleanup. - execute: function(callback, args, name) { - if (callback) callback.apply(this, args); - }, - - // Simple proxy to `Backbone.history` to save a fragment into the history. - navigate: function(fragment, options) { - Backbone.history.navigate(fragment, options); - return this; - }, - - // Bind all defined routes to `Backbone.history`. We have to reverse the - // order of the routes here to support behavior where the most general - // routes can be defined at the bottom of the route map. - _bindRoutes: function() { - if (!this.routes) return; - this.routes = _.result(this, 'routes'); - var route, routes = _.keys(this.routes); - while ((route = routes.pop()) != null) { - this.route(route, this.routes[route]); - } - }, - - // Convert a route string into a regular expression, suitable for matching - // against the current location hash. - _routeToRegExp: function(route) { - route = route.replace(escapeRegExp, '\\$&') - .replace(optionalParam, '(?:$1)?') - .replace(namedParam, function(match, optional) { - return optional ? match : '([^/?]+)'; - }) - .replace(splatParam, '([^?]*?)'); - return new RegExp('^' + route + '(?:\\?([\\s\\S]*))?$'); - }, - - // Given a route, and a URL fragment that it matches, return the array of - // extracted decoded parameters. Empty or unmatched parameters will be - // treated as `null` to normalize cross-browser behavior. - _extractParameters: function(route, fragment) { - var params = route.exec(fragment).slice(1); - return _.map(params, function(param, i) { - // Don't decode the search params. - if (i === params.length - 1) return param || null; - return param ? decodeURIComponent(param) : null; - }); - } - - }); - - // Backbone.History - // ---------------- - - // Handles cross-browser history management, based on either - // [pushState](http://diveintohtml5.info/history.html) and real URLs, or - // [onhashchange](https://developer.mozilla.org/en-US/docs/DOM/window.onhashchange) - // and URL fragments. If the browser supports neither (old IE, natch), - // falls back to polling. - var History = Backbone.History = function() { - this.handlers = []; - this.checkUrl = _.bind(this.checkUrl, this); - - // Ensure that `History` can be used outside of the browser. - if (typeof window !== 'undefined') { - this.location = window.location; - this.history = window.history; - } - }; - - // Cached regex for stripping a leading hash/slash and trailing space. - var routeStripper = /^[#\/]|\s+$/g; - - // Cached regex for stripping leading and trailing slashes. - var rootStripper = /^\/+|\/+$/g; - - // Cached regex for stripping urls of hash. - var pathStripper = /#.*$/; - - // Has the history handling already been started? - History.started = false; - - // Set up all inheritable **Backbone.History** properties and methods. - _.extend(History.prototype, Events, { - - // The default interval to poll for hash changes, if necessary, is - // twenty times a second. - interval: 50, - - // Are we at the app root? - atRoot: function() { - var path = this.location.pathname.replace(/[^\/]$/, '$&/'); - return path === this.root && !this.getSearch(); - }, - - // Does the pathname match the root? - matchRoot: function() { - var path = this.decodeFragment(this.location.pathname); - var rootPath = path.slice(0, this.root.length - 1) + '/'; - return rootPath === this.root; - }, - - // Unicode characters in `location.pathname` are percent encoded so they're - // decoded for comparison. `%25` should not be decoded since it may be part - // of an encoded parameter. - decodeFragment: function(fragment) { - return decodeURI(fragment.replace(/%25/g, '%2525')); - }, - - // In IE6, the hash fragment and search params are incorrect if the - // fragment contains `?`. - getSearch: function() { - var match = this.location.href.replace(/#.*/, '').match(/\?.+/); - return match ? match[0] : ''; - }, - - // Gets the true hash value. Cannot use location.hash directly due to bug - // in Firefox where location.hash will always be decoded. - getHash: function(window) { - var match = (window || this).location.href.match(/#(.*)$/); - return match ? match[1] : ''; - }, - - // Get the pathname and search params, without the root. - getPath: function() { - var path = this.decodeFragment( - this.location.pathname + this.getSearch() - ).slice(this.root.length - 1); - return path.charAt(0) === '/' ? path.slice(1) : path; - }, - - // Get the cross-browser normalized URL fragment from the path or hash. - getFragment: function(fragment) { - if (fragment == null) { - if (this._usePushState || !this._wantsHashChange) { - fragment = this.getPath(); - } else { - fragment = this.getHash(); - } - } - return fragment.replace(routeStripper, ''); - }, - - // Start the hash change handling, returning `true` if the current URL matches - // an existing route, and `false` otherwise. - start: function(options) { - if (History.started) throw new Error('Backbone.history has already been started'); - History.started = true; - - // Figure out the initial configuration. Do we need an iframe? - // Is pushState desired ... is it available? - this.options = _.extend({root: '/'}, this.options, options); - this.root = this.options.root; - this._wantsHashChange = this.options.hashChange !== false; - this._hasHashChange = 'onhashchange' in window && (document.documentMode === void 0 || document.documentMode > 7); - this._useHashChange = this._wantsHashChange && this._hasHashChange; - this._wantsPushState = !!this.options.pushState; - this._hasPushState = !!(this.history && this.history.pushState); - this._usePushState = this._wantsPushState && this._hasPushState; - this.fragment = this.getFragment(); - - // Normalize root to always include a leading and trailing slash. - this.root = ('/' + this.root + '/').replace(rootStripper, '/'); - - // Transition from hashChange to pushState or vice versa if both are - // requested. - if (this._wantsHashChange && this._wantsPushState) { - - // If we've started off with a route from a `pushState`-enabled - // browser, but we're currently in a browser that doesn't support it... - if (!this._hasPushState && !this.atRoot()) { - var rootPath = this.root.slice(0, -1) || '/'; - this.location.replace(rootPath + '#' + this.getPath()); - // Return immediately as browser will do redirect to new url - return true; - - // Or if we've started out with a hash-based route, but we're currently - // in a browser where it could be `pushState`-based instead... - } else if (this._hasPushState && this.atRoot()) { - this.navigate(this.getHash(), {replace: true}); - } - - } - - // Proxy an iframe to handle location events if the browser doesn't - // support the `hashchange` event, HTML5 history, or the user wants - // `hashChange` but not `pushState`. - if (!this._hasHashChange && this._wantsHashChange && !this._usePushState) { - this.iframe = document.createElement('iframe'); - this.iframe.src = 'javascript:0'; - this.iframe.style.display = 'none'; - this.iframe.tabIndex = -1; - var body = document.body; - // Using `appendChild` will throw on IE < 9 if the document is not ready. - var iWindow = body.insertBefore(this.iframe, body.firstChild).contentWindow; - iWindow.document.open(); - iWindow.document.close(); - iWindow.location.hash = '#' + this.fragment; - } - - // Add a cross-platform `addEventListener` shim for older browsers. - var addEventListener = window.addEventListener || function(eventName, listener) { - return attachEvent('on' + eventName, listener); - }; - - // Depending on whether we're using pushState or hashes, and whether - // 'onhashchange' is supported, determine how we check the URL state. - if (this._usePushState) { - addEventListener('popstate', this.checkUrl, false); - } else if (this._useHashChange && !this.iframe) { - addEventListener('hashchange', this.checkUrl, false); - } else if (this._wantsHashChange) { - this._checkUrlInterval = setInterval(this.checkUrl, this.interval); - } - - if (!this.options.silent) return this.loadUrl(); - }, - - // Disable Backbone.history, perhaps temporarily. Not useful in a real app, - // but possibly useful for unit testing Routers. - stop: function() { - // Add a cross-platform `removeEventListener` shim for older browsers. - var removeEventListener = window.removeEventListener || function(eventName, listener) { - return detachEvent('on' + eventName, listener); - }; - - // Remove window listeners. - if (this._usePushState) { - removeEventListener('popstate', this.checkUrl, false); - } else if (this._useHashChange && !this.iframe) { - removeEventListener('hashchange', this.checkUrl, false); - } - - // Clean up the iframe if necessary. - if (this.iframe) { - document.body.removeChild(this.iframe); - this.iframe = null; - } - - // Some environments will throw when clearing an undefined interval. - if (this._checkUrlInterval) clearInterval(this._checkUrlInterval); - History.started = false; - }, - - // Add a route to be tested when the fragment changes. Routes added later - // may override previous routes. - route: function(route, callback) { - this.handlers.unshift({route: route, callback: callback}); - }, - - // Checks the current URL to see if it has changed, and if it has, - // calls `loadUrl`, normalizing across the hidden iframe. - checkUrl: function(e) { - var current = this.getFragment(); - - // If the user pressed the back button, the iframe's hash will have - // changed and we should use that for comparison. - if (current === this.fragment && this.iframe) { - current = this.getHash(this.iframe.contentWindow); - } - - if (current === this.fragment) return false; - if (this.iframe) this.navigate(current); - this.loadUrl(); - }, - - // Attempt to load the current URL fragment. If a route succeeds with a - // match, returns `true`. If no defined routes matches the fragment, - // returns `false`. - loadUrl: function(fragment) { - // If the root doesn't match, no routes can match either. - if (!this.matchRoot()) return false; - fragment = this.fragment = this.getFragment(fragment); - return _.some(this.handlers, function(handler) { - if (handler.route.test(fragment)) { - handler.callback(fragment); - return true; - } - }); - }, - - // Save a fragment into the hash history, or replace the URL state if the - // 'replace' option is passed. You are responsible for properly URL-encoding - // the fragment in advance. - // - // The options object can contain `trigger: true` if you wish to have the - // route callback be fired (not usually desirable), or `replace: true`, if - // you wish to modify the current URL without adding an entry to the history. - navigate: function(fragment, options) { - if (!History.started) return false; - if (!options || options === true) options = {trigger: !!options}; - - // Normalize the fragment. - fragment = this.getFragment(fragment || ''); - - // Don't include a trailing slash on the root. - var rootPath = this.root; - if (fragment === '' || fragment.charAt(0) === '?') { - rootPath = rootPath.slice(0, -1) || '/'; - } - var url = rootPath + fragment; - - // Strip the hash and decode for matching. - fragment = this.decodeFragment(fragment.replace(pathStripper, '')); - - if (this.fragment === fragment) return; - this.fragment = fragment; - - // If pushState is available, we use it to set the fragment as a real URL. - if (this._usePushState) { - this.history[options.replace ? 'replaceState' : 'pushState']({}, document.title, url); - - // If hash changes haven't been explicitly disabled, update the hash - // fragment to store history. - } else if (this._wantsHashChange) { - this._updateHash(this.location, fragment, options.replace); - if (this.iframe && fragment !== this.getHash(this.iframe.contentWindow)) { - var iWindow = this.iframe.contentWindow; - - // Opening and closing the iframe tricks IE7 and earlier to push a - // history entry on hash-tag change. When replace is true, we don't - // want this. - if (!options.replace) { - iWindow.document.open(); - iWindow.document.close(); - } - - this._updateHash(iWindow.location, fragment, options.replace); - } - - // If you've told us that you explicitly don't want fallback hashchange- - // based history, then `navigate` becomes a page refresh. - } else { - return this.location.assign(url); - } - if (options.trigger) return this.loadUrl(fragment); - }, - - // Update the hash location, either replacing the current entry, or adding - // a new one to the browser history. - _updateHash: function(location, fragment, replace) { - if (replace) { - var href = location.href.replace(/(javascript:|#).*$/, ''); - location.replace(href + '#' + fragment); - } else { - // Some browsers require that `hash` contains a leading #. - location.hash = '#' + fragment; - } - } - - }); - - // Create the default Backbone.history. - Backbone.history = new History; - - // Helpers - // ------- - - // Helper function to correctly set up the prototype chain for subclasses. - // Similar to `goog.inherits`, but uses a hash of prototype properties and - // class properties to be extended. - var extend = function(protoProps, staticProps) { - var parent = this; - var child; - - // The constructor function for the new subclass is either defined by you - // (the "constructor" property in your `extend` definition), or defaulted - // by us to simply call the parent constructor. - if (protoProps && _.has(protoProps, 'constructor')) { - child = protoProps.constructor; - } else { - child = function(){ return parent.apply(this, arguments); }; - } - - // Add static properties to the constructor function, if supplied. - _.extend(child, parent, staticProps); - - // Set the prototype chain to inherit from `parent`, without calling - // `parent`'s constructor function and add the prototype properties. - child.prototype = _.create(parent.prototype, protoProps); - child.prototype.constructor = child; - - // Set a convenience property in case the parent's prototype is needed - // later. - child.__super__ = parent.prototype; - - return child; - }; - - // Set up inheritance for the model, collection, router, view and history. - Model.extend = Collection.extend = Router.extend = View.extend = History.extend = extend; - - // Throw an error when a URL is needed, and none is supplied. - var urlError = function() { - throw new Error('A "url" property or function must be specified'); - }; - - // Wrap an optional error callback with a fallback error event. - var wrapError = function(model, options) { - var error = options.error; - options.error = function(resp) { - if (error) error.call(options.context, model, resp, options); - model.trigger('error', model, resp, options); - }; - }; - - return Backbone; -}); diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/backbone/test/collection.js b/ecomp-portal-FE/client/bower_components/lodash/vendor/backbone/test/collection.js deleted file mode 100644 index dd98aca5..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/backbone/test/collection.js +++ /dev/null @@ -1,1998 +0,0 @@ -(function() { - - var a, b, c, d, e, col, otherCol; - - QUnit.module('Backbone.Collection', { - - beforeEach: function(assert) { - a = new Backbone.Model({id: 3, label: 'a'}); - b = new Backbone.Model({id: 2, label: 'b'}); - c = new Backbone.Model({id: 1, label: 'c'}); - d = new Backbone.Model({id: 0, label: 'd'}); - e = null; - col = new Backbone.Collection([a, b, c, d]); - otherCol = new Backbone.Collection(); - } - - }); - - QUnit.test('new and sort', function(assert) { - assert.expect(6); - var counter = 0; - col.on('sort', function(){ counter++; }); - assert.deepEqual(col.pluck('label'), ['a', 'b', 'c', 'd']); - col.comparator = function(m1, m2) { - return m1.id > m2.id ? -1 : 1; - }; - col.sort(); - assert.equal(counter, 1); - assert.deepEqual(col.pluck('label'), ['a', 'b', 'c', 'd']); - col.comparator = function(model) { return model.id; }; - col.sort(); - assert.equal(counter, 2); - assert.deepEqual(col.pluck('label'), ['d', 'c', 'b', 'a']); - assert.equal(col.length, 4); - }); - - QUnit.test('String comparator.', function(assert) { - assert.expect(1); - var collection = new Backbone.Collection([ - {id: 3}, - {id: 1}, - {id: 2} - ], {comparator: 'id'}); - assert.deepEqual(collection.pluck('id'), [1, 2, 3]); - }); - - QUnit.test('new and parse', function(assert) { - assert.expect(3); - var Collection = Backbone.Collection.extend({ - parse: function(data) { - return _.filter(data, function(datum) { - return datum.a % 2 === 0; - }); - } - }); - var models = [{a: 1}, {a: 2}, {a: 3}, {a: 4}]; - var collection = new Collection(models, {parse: true}); - assert.strictEqual(collection.length, 2); - assert.strictEqual(collection.first().get('a'), 2); - assert.strictEqual(collection.last().get('a'), 4); - }); - - QUnit.test('clone preserves model and comparator', function(assert) { - assert.expect(3); - var Model = Backbone.Model.extend(); - var comparator = function(model){ return model.id; }; - - var collection = new Backbone.Collection([{id: 1}], { - model: Model, - comparator: comparator - }).clone(); - collection.add({id: 2}); - assert.ok(collection.at(0) instanceof Model); - assert.ok(collection.at(1) instanceof Model); - assert.strictEqual(collection.comparator, comparator); - }); - - QUnit.test('get', function(assert) { - assert.expect(6); - assert.equal(col.get(0), d); - assert.equal(col.get(d.clone()), d); - assert.equal(col.get(2), b); - assert.equal(col.get({id: 1}), c); - assert.equal(col.get(c.clone()), c); - assert.equal(col.get(col.first().cid), col.first()); - }); - - QUnit.test('get with non-default ids', function(assert) { - assert.expect(5); - var MongoModel = Backbone.Model.extend({idAttribute: '_id'}); - var model = new MongoModel({_id: 100}); - var collection = new Backbone.Collection([model], {model: MongoModel}); - assert.equal(collection.get(100), model); - assert.equal(collection.get(model.cid), model); - assert.equal(collection.get(model), model); - assert.equal(collection.get(101), void 0); - - var collection2 = new Backbone.Collection(); - collection2.model = MongoModel; - collection2.add(model.attributes); - assert.equal(collection2.get(model.clone()), collection2.first()); - }); - - QUnit.test('has', function(assert) { - assert.expect(15); - assert.ok(col.has(a)); - assert.ok(col.has(b)); - assert.ok(col.has(c)); - assert.ok(col.has(d)); - assert.ok(col.has(a.id)); - assert.ok(col.has(b.id)); - assert.ok(col.has(c.id)); - assert.ok(col.has(d.id)); - assert.ok(col.has(a.cid)); - assert.ok(col.has(b.cid)); - assert.ok(col.has(c.cid)); - assert.ok(col.has(d.cid)); - var outsider = new Backbone.Model({id: 4}); - assert.notOk(col.has(outsider)); - assert.notOk(col.has(outsider.id)); - assert.notOk(col.has(outsider.cid)); - }); - - QUnit.test('update index when id changes', function(assert) { - assert.expect(4); - var collection = new Backbone.Collection(); - collection.add([ - {id: 0, name: 'one'}, - {id: 1, name: 'two'} - ]); - var one = collection.get(0); - assert.equal(one.get('name'), 'one'); - collection.on('change:name', function(model) { assert.ok(this.get(model)); }); - one.set({name: 'dalmatians', id: 101}); - assert.equal(collection.get(0), null); - assert.equal(collection.get(101).get('name'), 'dalmatians'); - }); - - QUnit.test('at', function(assert) { - assert.expect(2); - assert.equal(col.at(2), c); - assert.equal(col.at(-2), c); - }); - - QUnit.test('pluck', function(assert) { - assert.expect(1); - assert.equal(col.pluck('label').join(' '), 'a b c d'); - }); - - QUnit.test('add', function(assert) { - assert.expect(14); - var added, opts, secondAdded; - added = opts = secondAdded = null; - e = new Backbone.Model({id: 10, label: 'e'}); - otherCol.add(e); - otherCol.on('add', function() { - secondAdded = true; - }); - col.on('add', function(model, collection, options){ - added = model.get('label'); - opts = options; - }); - col.add(e, {amazing: true}); - assert.equal(added, 'e'); - assert.equal(col.length, 5); - assert.equal(col.last(), e); - assert.equal(otherCol.length, 1); - assert.equal(secondAdded, null); - assert.ok(opts.amazing); - - var f = new Backbone.Model({id: 20, label: 'f'}); - var g = new Backbone.Model({id: 21, label: 'g'}); - var h = new Backbone.Model({id: 22, label: 'h'}); - var atCol = new Backbone.Collection([f, g, h]); - assert.equal(atCol.length, 3); - atCol.add(e, {at: 1}); - assert.equal(atCol.length, 4); - assert.equal(atCol.at(1), e); - assert.equal(atCol.last(), h); - - var coll = new Backbone.Collection(new Array(2)); - var addCount = 0; - coll.on('add', function(){ - addCount += 1; - }); - coll.add([undefined, f, g]); - assert.equal(coll.length, 5); - assert.equal(addCount, 3); - coll.add(new Array(4)); - assert.equal(coll.length, 9); - assert.equal(addCount, 7); - }); - - QUnit.test('add multiple models', function(assert) { - assert.expect(6); - var collection = new Backbone.Collection([{at: 0}, {at: 1}, {at: 9}]); - collection.add([{at: 2}, {at: 3}, {at: 4}, {at: 5}, {at: 6}, {at: 7}, {at: 8}], {at: 2}); - for (var i = 0; i <= 5; i++) { - assert.equal(collection.at(i).get('at'), i); - } - }); - - QUnit.test('add; at should have preference over comparator', function(assert) { - assert.expect(1); - var Col = Backbone.Collection.extend({ - comparator: function(m1, m2) { - return m1.id > m2.id ? -1 : 1; - } - }); - - var collection = new Col([{id: 2}, {id: 3}]); - collection.add(new Backbone.Model({id: 1}), {at: 1}); - - assert.equal(collection.pluck('id').join(' '), '3 1 2'); - }); - - QUnit.test('add; at should add to the end if the index is out of bounds', function(assert) { - assert.expect(1); - var collection = new Backbone.Collection([{id: 2}, {id: 3}]); - collection.add(new Backbone.Model({id: 1}), {at: 5}); - - assert.equal(collection.pluck('id').join(' '), '2 3 1'); - }); - - QUnit.test("can't add model to collection twice", function(assert) { - var collection = new Backbone.Collection([{id: 1}, {id: 2}, {id: 1}, {id: 2}, {id: 3}]); - assert.equal(collection.pluck('id').join(' '), '1 2 3'); - }); - - QUnit.test("can't add different model with same id to collection twice", function(assert) { - assert.expect(1); - var collection = new Backbone.Collection; - collection.unshift({id: 101}); - collection.add({id: 101}); - assert.equal(collection.length, 1); - }); - - QUnit.test('merge in duplicate models with {merge: true}', function(assert) { - assert.expect(3); - var collection = new Backbone.Collection; - collection.add([{id: 1, name: 'Moe'}, {id: 2, name: 'Curly'}, {id: 3, name: 'Larry'}]); - collection.add({id: 1, name: 'Moses'}); - assert.equal(collection.first().get('name'), 'Moe'); - collection.add({id: 1, name: 'Moses'}, {merge: true}); - assert.equal(collection.first().get('name'), 'Moses'); - collection.add({id: 1, name: 'Tim'}, {merge: true, silent: true}); - assert.equal(collection.first().get('name'), 'Tim'); - }); - - QUnit.test('add model to multiple collections', function(assert) { - assert.expect(10); - var counter = 0; - var m = new Backbone.Model({id: 10, label: 'm'}); - m.on('add', function(model, collection) { - counter++; - assert.equal(m, model); - if (counter > 1) { - assert.equal(collection, col2); - } else { - assert.equal(collection, col1); - } - }); - var col1 = new Backbone.Collection([]); - col1.on('add', function(model, collection) { - assert.equal(m, model); - assert.equal(col1, collection); - }); - var col2 = new Backbone.Collection([]); - col2.on('add', function(model, collection) { - assert.equal(m, model); - assert.equal(col2, collection); - }); - col1.add(m); - assert.equal(m.collection, col1); - col2.add(m); - assert.equal(m.collection, col1); - }); - - QUnit.test('add model with parse', function(assert) { - assert.expect(1); - var Model = Backbone.Model.extend({ - parse: function(obj) { - obj.value += 1; - return obj; - } - }); - - var Col = Backbone.Collection.extend({model: Model}); - var collection = new Col; - collection.add({value: 1}, {parse: true}); - assert.equal(collection.at(0).get('value'), 2); - }); - - QUnit.test('add with parse and merge', function(assert) { - var collection = new Backbone.Collection(); - collection.parse = function(attrs) { - return _.map(attrs, function(model) { - if (model.model) return model.model; - return model; - }); - }; - collection.add({id: 1}); - collection.add({model: {id: 1, name: 'Alf'}}, {parse: true, merge: true}); - assert.equal(collection.first().get('name'), 'Alf'); - }); - - QUnit.test('add model to collection with sort()-style comparator', function(assert) { - assert.expect(3); - var collection = new Backbone.Collection; - collection.comparator = function(m1, m2) { - return m1.get('name') < m2.get('name') ? -1 : 1; - }; - var tom = new Backbone.Model({name: 'Tom'}); - var rob = new Backbone.Model({name: 'Rob'}); - var tim = new Backbone.Model({name: 'Tim'}); - collection.add(tom); - collection.add(rob); - collection.add(tim); - assert.equal(collection.indexOf(rob), 0); - assert.equal(collection.indexOf(tim), 1); - assert.equal(collection.indexOf(tom), 2); - }); - - QUnit.test('comparator that depends on `this`', function(assert) { - assert.expect(2); - var collection = new Backbone.Collection; - collection.negative = function(num) { - return -num; - }; - collection.comparator = function(model) { - return this.negative(model.id); - }; - collection.add([{id: 1}, {id: 2}, {id: 3}]); - assert.deepEqual(collection.pluck('id'), [3, 2, 1]); - collection.comparator = function(m1, m2) { - return this.negative(m2.id) - this.negative(m1.id); - }; - collection.sort(); - assert.deepEqual(collection.pluck('id'), [1, 2, 3]); - }); - - QUnit.test('remove', function(assert) { - assert.expect(12); - var removed = null; - var result = null; - col.on('remove', function(model, collection, options) { - removed = model.get('label'); - assert.equal(options.index, 3); - assert.equal(collection.get(model), undefined, '#3693: model cannot be fetched from collection'); - }); - result = col.remove(d); - assert.equal(removed, 'd'); - assert.strictEqual(result, d); - //if we try to remove d again, it's not going to actually get removed - result = col.remove(d); - assert.strictEqual(result, undefined); - assert.equal(col.length, 3); - assert.equal(col.first(), a); - col.off(); - result = col.remove([c, d]); - assert.equal(result.length, 1, 'only returns removed models'); - assert.equal(result[0], c, 'only returns removed models'); - result = col.remove([c, b]); - assert.equal(result.length, 1, 'only returns removed models'); - assert.equal(result[0], b, 'only returns removed models'); - result = col.remove([]); - assert.deepEqual(result, [], 'returns empty array when nothing removed'); - }); - - QUnit.test('add and remove return values', function(assert) { - assert.expect(13); - var Even = Backbone.Model.extend({ - validate: function(attrs) { - if (attrs.id % 2 !== 0) return 'odd'; - } - }); - var collection = new Backbone.Collection; - collection.model = Even; - - var list = collection.add([{id: 2}, {id: 4}], {validate: true}); - assert.equal(list.length, 2); - assert.ok(list[0] instanceof Backbone.Model); - assert.equal(list[1], collection.last()); - assert.equal(list[1].get('id'), 4); - - list = collection.add([{id: 3}, {id: 6}], {validate: true}); - assert.equal(collection.length, 3); - assert.equal(list[0], false); - assert.equal(list[1].get('id'), 6); - - var result = collection.add({id: 6}); - assert.equal(result.cid, list[1].cid); - - result = collection.remove({id: 6}); - assert.equal(collection.length, 2); - assert.equal(result.id, 6); - - list = collection.remove([{id: 2}, {id: 8}]); - assert.equal(collection.length, 1); - assert.equal(list[0].get('id'), 2); - assert.equal(list[1], null); - }); - - QUnit.test('shift and pop', function(assert) { - assert.expect(2); - var collection = new Backbone.Collection([{a: 'a'}, {b: 'b'}, {c: 'c'}]); - assert.equal(collection.shift().get('a'), 'a'); - assert.equal(collection.pop().get('c'), 'c'); - }); - - QUnit.test('slice', function(assert) { - assert.expect(2); - var collection = new Backbone.Collection([{a: 'a'}, {b: 'b'}, {c: 'c'}]); - var array = collection.slice(1, 3); - assert.equal(array.length, 2); - assert.equal(array[0].get('b'), 'b'); - }); - - QUnit.test('events are unbound on remove', function(assert) { - assert.expect(3); - var counter = 0; - var dj = new Backbone.Model(); - var emcees = new Backbone.Collection([dj]); - emcees.on('change', function(){ counter++; }); - dj.set({name: 'Kool'}); - assert.equal(counter, 1); - emcees.reset([]); - assert.equal(dj.collection, undefined); - dj.set({name: 'Shadow'}); - assert.equal(counter, 1); - }); - - QUnit.test('remove in multiple collections', function(assert) { - assert.expect(7); - var modelData = { - id: 5, - title: 'Othello' - }; - var passed = false; - var m1 = new Backbone.Model(modelData); - var m2 = new Backbone.Model(modelData); - m2.on('remove', function() { - passed = true; - }); - var col1 = new Backbone.Collection([m1]); - var col2 = new Backbone.Collection([m2]); - assert.notEqual(m1, m2); - assert.ok(col1.length === 1); - assert.ok(col2.length === 1); - col1.remove(m1); - assert.equal(passed, false); - assert.ok(col1.length === 0); - col2.remove(m1); - assert.ok(col2.length === 0); - assert.equal(passed, true); - }); - - QUnit.test('remove same model in multiple collection', function(assert) { - assert.expect(16); - var counter = 0; - var m = new Backbone.Model({id: 5, title: 'Othello'}); - m.on('remove', function(model, collection) { - counter++; - assert.equal(m, model); - if (counter > 1) { - assert.equal(collection, col1); - } else { - assert.equal(collection, col2); - } - }); - var col1 = new Backbone.Collection([m]); - col1.on('remove', function(model, collection) { - assert.equal(m, model); - assert.equal(col1, collection); - }); - var col2 = new Backbone.Collection([m]); - col2.on('remove', function(model, collection) { - assert.equal(m, model); - assert.equal(col2, collection); - }); - assert.equal(col1, m.collection); - col2.remove(m); - assert.ok(col2.length === 0); - assert.ok(col1.length === 1); - assert.equal(counter, 1); - assert.equal(col1, m.collection); - col1.remove(m); - assert.equal(null, m.collection); - assert.ok(col1.length === 0); - assert.equal(counter, 2); - }); - - QUnit.test('model destroy removes from all collections', function(assert) { - assert.expect(3); - var m = new Backbone.Model({id: 5, title: 'Othello'}); - m.sync = function(method, model, options) { options.success(); }; - var col1 = new Backbone.Collection([m]); - var col2 = new Backbone.Collection([m]); - m.destroy(); - assert.ok(col1.length === 0); - assert.ok(col2.length === 0); - assert.equal(undefined, m.collection); - }); - - QUnit.test('Collection: non-persisted model destroy removes from all collections', function(assert) { - assert.expect(3); - var m = new Backbone.Model({title: 'Othello'}); - m.sync = function(method, model, options) { throw 'should not be called'; }; - var col1 = new Backbone.Collection([m]); - var col2 = new Backbone.Collection([m]); - m.destroy(); - assert.ok(col1.length === 0); - assert.ok(col2.length === 0); - assert.equal(undefined, m.collection); - }); - - QUnit.test('fetch', function(assert) { - assert.expect(4); - var collection = new Backbone.Collection; - collection.url = '/test'; - collection.fetch(); - assert.equal(this.syncArgs.method, 'read'); - assert.equal(this.syncArgs.model, collection); - assert.equal(this.syncArgs.options.parse, true); - - collection.fetch({parse: false}); - assert.equal(this.syncArgs.options.parse, false); - }); - - QUnit.test('fetch with an error response triggers an error event', function(assert) { - assert.expect(1); - var collection = new Backbone.Collection(); - collection.on('error', function() { - assert.ok(true); - }); - collection.sync = function(method, model, options) { options.error(); }; - collection.fetch(); - }); - - QUnit.test('#3283 - fetch with an error response calls error with context', function(assert) { - assert.expect(1); - var collection = new Backbone.Collection(); - var obj = {}; - var options = { - context: obj, - error: function() { - assert.equal(this, obj); - } - }; - collection.sync = function(method, model, opts) { - opts.error.call(opts.context); - }; - collection.fetch(options); - }); - - QUnit.test('ensure fetch only parses once', function(assert) { - assert.expect(1); - var collection = new Backbone.Collection; - var counter = 0; - collection.parse = function(models) { - counter++; - return models; - }; - collection.url = '/test'; - collection.fetch(); - this.syncArgs.options.success([]); - assert.equal(counter, 1); - }); - - QUnit.test('create', function(assert) { - assert.expect(4); - var collection = new Backbone.Collection; - collection.url = '/test'; - var model = collection.create({label: 'f'}, {wait: true}); - assert.equal(this.syncArgs.method, 'create'); - assert.equal(this.syncArgs.model, model); - assert.equal(model.get('label'), 'f'); - assert.equal(model.collection, collection); - }); - - QUnit.test('create with validate:true enforces validation', function(assert) { - assert.expect(3); - var ValidatingModel = Backbone.Model.extend({ - validate: function(attrs) { - return 'fail'; - } - }); - var ValidatingCollection = Backbone.Collection.extend({ - model: ValidatingModel - }); - var collection = new ValidatingCollection(); - collection.on('invalid', function(coll, error, options) { - assert.equal(error, 'fail'); - assert.equal(options.validationError, 'fail'); - }); - assert.equal(collection.create({'foo': 'bar'}, {validate: true}), false); - }); - - QUnit.test('create will pass extra options to success callback', function(assert) { - assert.expect(1); - var Model = Backbone.Model.extend({ - sync: function(method, model, options) { - _.extend(options, {specialSync: true}); - return Backbone.Model.prototype.sync.call(this, method, model, options); - } - }); - - var Collection = Backbone.Collection.extend({ - model: Model, - url: '/test' - }); - - var collection = new Collection; - - var success = function(model, response, options) { - assert.ok(options.specialSync, 'Options were passed correctly to callback'); - }; - - collection.create({}, {success: success}); - this.ajaxSettings.success(); - }); - - QUnit.test('create with wait:true should not call collection.parse', function(assert) { - assert.expect(0); - var Collection = Backbone.Collection.extend({ - url: '/test', - parse: function() { - assert.ok(false); - } - }); - - var collection = new Collection; - - collection.create({}, {wait: true}); - this.ajaxSettings.success(); - }); - - QUnit.test('a failing create returns model with errors', function(assert) { - var ValidatingModel = Backbone.Model.extend({ - validate: function(attrs) { - return 'fail'; - } - }); - var ValidatingCollection = Backbone.Collection.extend({ - model: ValidatingModel - }); - var collection = new ValidatingCollection(); - var m = collection.create({foo: 'bar'}); - assert.equal(m.validationError, 'fail'); - assert.equal(collection.length, 1); - }); - - QUnit.test('initialize', function(assert) { - assert.expect(1); - var Collection = Backbone.Collection.extend({ - initialize: function() { - this.one = 1; - } - }); - var coll = new Collection; - assert.equal(coll.one, 1); - }); - - QUnit.test('toJSON', function(assert) { - assert.expect(1); - assert.equal(JSON.stringify(col), '[{"id":3,"label":"a"},{"id":2,"label":"b"},{"id":1,"label":"c"},{"id":0,"label":"d"}]'); - }); - - QUnit.test('where and findWhere', function(assert) { - assert.expect(8); - var model = new Backbone.Model({a: 1}); - var coll = new Backbone.Collection([ - model, - {a: 1}, - {a: 1, b: 2}, - {a: 2, b: 2}, - {a: 3} - ]); - assert.equal(coll.where({a: 1}).length, 3); - assert.equal(coll.where({a: 2}).length, 1); - assert.equal(coll.where({a: 3}).length, 1); - assert.equal(coll.where({b: 1}).length, 0); - assert.equal(coll.where({b: 2}).length, 2); - assert.equal(coll.where({a: 1, b: 2}).length, 1); - assert.equal(coll.findWhere({a: 1}), model); - assert.equal(coll.findWhere({a: 4}), void 0); - }); - - QUnit.test('Underscore methods', function(assert) { - assert.expect(21); - assert.equal(col.map(function(model){ return model.get('label'); }).join(' '), 'a b c d'); - assert.equal(col.some(function(model){ return model.id === 100; }), false); - assert.equal(col.some(function(model){ return model.id === 0; }), true); - assert.equal(col.reduce(function(m1, m2) {return m1.id > m2.id ? m1 : m2;}).id, 3); - assert.equal(col.reduceRight(function(m1, m2) {return m1.id > m2.id ? m1 : m2;}).id, 3); - assert.equal(col.indexOf(b), 1); - assert.equal(col.size(), 4); - assert.equal(col.rest().length, 3); - assert.ok(!_.includes(col.rest(), a)); - assert.ok(_.includes(col.rest(), d)); - assert.ok(!col.isEmpty()); - assert.ok(!_.includes(col.without(d), d)); - - var wrapped = col.chain(); - assert.equal(wrapped.map('id').max().value(), 3); - assert.equal(wrapped.map('id').min().value(), 0); - assert.deepEqual(wrapped - .filter(function(o){ return o.id % 2 === 0; }) - .map(function(o){ return o.id * 2; }) - .value(), - [4, 0]); - assert.deepEqual(col.difference([c, d]), [a, b]); - assert.ok(col.includes(col.sample())); - - var first = col.first(); - assert.deepEqual(col.groupBy(function(model){ return model.id; })[first.id], [first]); - assert.deepEqual(col.countBy(function(model){ return model.id; }), {0: 1, 1: 1, 2: 1, 3: 1}); - assert.deepEqual(col.sortBy(function(model){ return model.id; })[0], col.at(3)); - assert.ok(col.indexBy('id')[first.id] === first); - }); - - QUnit.test('Underscore methods with object-style and property-style iteratee', function(assert) { - assert.expect(26); - var model = new Backbone.Model({a: 4, b: 1, e: 3}); - var coll = new Backbone.Collection([ - {a: 1, b: 1}, - {a: 2, b: 1, c: 1}, - {a: 3, b: 1}, - model - ]); - assert.equal(coll.find({a: 0}), undefined); - assert.deepEqual(coll.find({a: 4}), model); - assert.equal(coll.find('d'), undefined); - assert.deepEqual(coll.find('e'), model); - assert.equal(coll.filter({a: 0}), false); - assert.deepEqual(coll.filter({a: 4}), [model]); - assert.equal(coll.some({a: 0}), false); - assert.equal(coll.some({a: 1}), true); - assert.equal(coll.reject({a: 0}).length, 4); - assert.deepEqual(coll.reject({a: 4}), _.without(coll.models, model)); - assert.equal(coll.every({a: 0}), false); - assert.equal(coll.every({b: 1}), true); - assert.deepEqual(coll.partition({a: 0})[0], []); - assert.deepEqual(coll.partition({a: 0})[1], coll.models); - assert.deepEqual(coll.partition({a: 4})[0], [model]); - assert.deepEqual(coll.partition({a: 4})[1], _.without(coll.models, model)); - assert.deepEqual(coll.map({a: 2}), [false, true, false, false]); - assert.deepEqual(coll.map('a'), [1, 2, 3, 4]); - assert.deepEqual(coll.sortBy('a')[3], model); - assert.deepEqual(coll.sortBy('e')[0], model); - assert.deepEqual(coll.countBy({a: 4}), {'false': 3, 'true': 1}); - assert.deepEqual(coll.countBy('d'), {'undefined': 4}); - assert.equal(coll.findIndex({b: 1}), 0); - assert.equal(coll.findIndex({b: 9}), -1); - assert.equal(coll.findLastIndex({b: 1}), 3); - assert.equal(coll.findLastIndex({b: 9}), -1); - }); - - QUnit.test('reset', function(assert) { - assert.expect(16); - - var resetCount = 0; - var models = col.models; - col.on('reset', function() { resetCount += 1; }); - col.reset([]); - assert.equal(resetCount, 1); - assert.equal(col.length, 0); - assert.equal(col.last(), null); - col.reset(models); - assert.equal(resetCount, 2); - assert.equal(col.length, 4); - assert.equal(col.last(), d); - col.reset(_.map(models, function(m){ return m.attributes; })); - assert.equal(resetCount, 3); - assert.equal(col.length, 4); - assert.ok(col.last() !== d); - assert.ok(_.isEqual(col.last().attributes, d.attributes)); - col.reset(); - assert.equal(col.length, 0); - assert.equal(resetCount, 4); - - var f = new Backbone.Model({id: 20, label: 'f'}); - col.reset([undefined, f]); - assert.equal(col.length, 2); - assert.equal(resetCount, 5); - - col.reset(new Array(4)); - assert.equal(col.length, 4); - assert.equal(resetCount, 6); - }); - - QUnit.test('reset with different values', function(assert) { - var collection = new Backbone.Collection({id: 1}); - collection.reset({id: 1, a: 1}); - assert.equal(collection.get(1).get('a'), 1); - }); - - QUnit.test('same references in reset', function(assert) { - var model = new Backbone.Model({id: 1}); - var collection = new Backbone.Collection({id: 1}); - collection.reset(model); - assert.equal(collection.get(1), model); - }); - - QUnit.test('reset passes caller options', function(assert) { - assert.expect(3); - var Model = Backbone.Model.extend({ - initialize: function(attrs, options) { - this.modelParameter = options.modelParameter; - } - }); - var collection = new (Backbone.Collection.extend({model: Model}))(); - collection.reset([{astring: 'green', anumber: 1}, {astring: 'blue', anumber: 2}], {modelParameter: 'model parameter'}); - assert.equal(collection.length, 2); - collection.each(function(model) { - assert.equal(model.modelParameter, 'model parameter'); - }); - }); - - QUnit.test('reset does not alter options by reference', function(assert) { - assert.expect(2); - var collection = new Backbone.Collection([{id: 1}]); - var origOpts = {}; - collection.on('reset', function(coll, opts){ - assert.equal(origOpts.previousModels, undefined); - assert.equal(opts.previousModels[0].id, 1); - }); - collection.reset([], origOpts); - }); - - QUnit.test('trigger custom events on models', function(assert) { - assert.expect(1); - var fired = null; - a.on('custom', function() { fired = true; }); - a.trigger('custom'); - assert.equal(fired, true); - }); - - QUnit.test('add does not alter arguments', function(assert) { - assert.expect(2); - var attrs = {}; - var models = [attrs]; - new Backbone.Collection().add(models); - assert.equal(models.length, 1); - assert.ok(attrs === models[0]); - }); - - QUnit.test('#714: access `model.collection` in a brand new model.', function(assert) { - assert.expect(2); - var collection = new Backbone.Collection; - collection.url = '/test'; - var Model = Backbone.Model.extend({ - set: function(attrs) { - assert.equal(attrs.prop, 'value'); - assert.equal(this.collection, collection); - return this; - } - }); - collection.model = Model; - collection.create({prop: 'value'}); - }); - - QUnit.test('#574, remove its own reference to the .models array.', function(assert) { - assert.expect(2); - var collection = new Backbone.Collection([ - {id: 1}, {id: 2}, {id: 3}, {id: 4}, {id: 5}, {id: 6} - ]); - assert.equal(collection.length, 6); - collection.remove(collection.models); - assert.equal(collection.length, 0); - }); - - QUnit.test('#861, adding models to a collection which do not pass validation, with validate:true', function(assert) { - assert.expect(2); - var Model = Backbone.Model.extend({ - validate: function(attrs) { - if (attrs.id === 3) return "id can't be 3"; - } - }); - - var Collection = Backbone.Collection.extend({ - model: Model - }); - - var collection = new Collection; - collection.on('invalid', function() { assert.ok(true); }); - - collection.add([{id: 1}, {id: 2}, {id: 3}, {id: 4}, {id: 5}, {id: 6}], {validate: true}); - assert.deepEqual(collection.pluck('id'), [1, 2, 4, 5, 6]); - }); - - QUnit.test('Invalid models are discarded with validate:true.', function(assert) { - assert.expect(5); - var collection = new Backbone.Collection; - collection.on('test', function() { assert.ok(true); }); - collection.model = Backbone.Model.extend({ - validate: function(attrs){ if (!attrs.valid) return 'invalid'; } - }); - var model = new collection.model({id: 1, valid: true}); - collection.add([model, {id: 2}], {validate: true}); - model.trigger('test'); - assert.ok(collection.get(model.cid)); - assert.ok(collection.get(1)); - assert.ok(!collection.get(2)); - assert.equal(collection.length, 1); - }); - - QUnit.test('multiple copies of the same model', function(assert) { - assert.expect(3); - var collection = new Backbone.Collection(); - var model = new Backbone.Model(); - collection.add([model, model]); - assert.equal(collection.length, 1); - collection.add([{id: 1}, {id: 1}]); - assert.equal(collection.length, 2); - assert.equal(collection.last().id, 1); - }); - - QUnit.test('#964 - collection.get return inconsistent', function(assert) { - assert.expect(2); - var collection = new Backbone.Collection(); - assert.ok(collection.get(null) === undefined); - assert.ok(collection.get() === undefined); - }); - - QUnit.test('#1112 - passing options.model sets collection.model', function(assert) { - assert.expect(2); - var Model = Backbone.Model.extend({}); - var collection = new Backbone.Collection([{id: 1}], {model: Model}); - assert.ok(collection.model === Model); - assert.ok(collection.at(0) instanceof Model); - }); - - QUnit.test('null and undefined are invalid ids.', function(assert) { - assert.expect(2); - var model = new Backbone.Model({id: 1}); - var collection = new Backbone.Collection([model]); - model.set({id: null}); - assert.ok(!collection.get('null')); - model.set({id: 1}); - model.set({id: undefined}); - assert.ok(!collection.get('undefined')); - }); - - QUnit.test('falsy comparator', function(assert) { - assert.expect(4); - var Col = Backbone.Collection.extend({ - comparator: function(model){ return model.id; } - }); - var collection = new Col(); - var colFalse = new Col(null, {comparator: false}); - var colNull = new Col(null, {comparator: null}); - var colUndefined = new Col(null, {comparator: undefined}); - assert.ok(collection.comparator); - assert.ok(!colFalse.comparator); - assert.ok(!colNull.comparator); - assert.ok(colUndefined.comparator); - }); - - QUnit.test('#1355 - `options` is passed to success callbacks', function(assert) { - assert.expect(2); - var m = new Backbone.Model({x: 1}); - var collection = new Backbone.Collection(); - var opts = { - opts: true, - success: function(coll, resp, options) { - assert.ok(options.opts); - } - }; - collection.sync = m.sync = function( method, coll, options ){ - options.success({}); - }; - collection.fetch(opts); - collection.create(m, opts); - }); - - QUnit.test("#1412 - Trigger 'request' and 'sync' events.", function(assert) { - assert.expect(4); - var collection = new Backbone.Collection; - collection.url = '/test'; - Backbone.ajax = function(settings){ settings.success(); }; - - collection.on('request', function(obj, xhr, options) { - assert.ok(obj === collection, "collection has correct 'request' event after fetching"); - }); - collection.on('sync', function(obj, response, options) { - assert.ok(obj === collection, "collection has correct 'sync' event after fetching"); - }); - collection.fetch(); - collection.off(); - - collection.on('request', function(obj, xhr, options) { - assert.ok(obj === collection.get(1), "collection has correct 'request' event after one of its models save"); - }); - collection.on('sync', function(obj, response, options) { - assert.ok(obj === collection.get(1), "collection has correct 'sync' event after one of its models save"); - }); - collection.create({id: 1}); - collection.off(); - }); - - QUnit.test('#3283 - fetch, create calls success with context', function(assert) { - assert.expect(2); - var collection = new Backbone.Collection; - collection.url = '/test'; - Backbone.ajax = function(settings) { - settings.success.call(settings.context); - }; - var obj = {}; - var options = { - context: obj, - success: function() { - assert.equal(this, obj); - } - }; - - collection.fetch(options); - collection.create({id: 1}, options); - }); - - QUnit.test('#1447 - create with wait adds model.', function(assert) { - assert.expect(1); - var collection = new Backbone.Collection; - var model = new Backbone.Model; - model.sync = function(method, m, options){ options.success(); }; - collection.on('add', function(){ assert.ok(true); }); - collection.create(model, {wait: true}); - }); - - QUnit.test('#1448 - add sorts collection after merge.', function(assert) { - assert.expect(1); - var collection = new Backbone.Collection([ - {id: 1, x: 1}, - {id: 2, x: 2} - ]); - collection.comparator = function(model){ return model.get('x'); }; - collection.add({id: 1, x: 3}, {merge: true}); - assert.deepEqual(collection.pluck('id'), [2, 1]); - }); - - QUnit.test('#1655 - groupBy can be used with a string argument.', function(assert) { - assert.expect(3); - var collection = new Backbone.Collection([{x: 1}, {x: 2}]); - var grouped = collection.groupBy('x'); - assert.strictEqual(_.keys(grouped).length, 2); - assert.strictEqual(grouped[1][0].get('x'), 1); - assert.strictEqual(grouped[2][0].get('x'), 2); - }); - - QUnit.test('#1655 - sortBy can be used with a string argument.', function(assert) { - assert.expect(1); - var collection = new Backbone.Collection([{x: 3}, {x: 1}, {x: 2}]); - var values = _.map(collection.sortBy('x'), function(model) { - return model.get('x'); - }); - assert.deepEqual(values, [1, 2, 3]); - }); - - QUnit.test('#1604 - Removal during iteration.', function(assert) { - assert.expect(0); - var collection = new Backbone.Collection([{}, {}]); - collection.on('add', function() { - collection.at(0).destroy(); - }); - collection.add({}, {at: 0}); - }); - - QUnit.test('#1638 - `sort` during `add` triggers correctly.', function(assert) { - var collection = new Backbone.Collection; - collection.comparator = function(model) { return model.get('x'); }; - var added = []; - collection.on('add', function(model) { - model.set({x: 3}); - collection.sort(); - added.push(model.id); - }); - collection.add([{id: 1, x: 1}, {id: 2, x: 2}]); - assert.deepEqual(added, [1, 2]); - }); - - QUnit.test('fetch parses models by default', function(assert) { - assert.expect(1); - var model = {}; - var Collection = Backbone.Collection.extend({ - url: 'test', - model: Backbone.Model.extend({ - parse: function(resp) { - assert.strictEqual(resp, model); - } - }) - }); - new Collection().fetch(); - this.ajaxSettings.success([model]); - }); - - QUnit.test("`sort` shouldn't always fire on `add`", function(assert) { - assert.expect(1); - var collection = new Backbone.Collection([{id: 1}, {id: 2}, {id: 3}], { - comparator: 'id' - }); - collection.sort = function(){ assert.ok(true); }; - collection.add([]); - collection.add({id: 1}); - collection.add([{id: 2}, {id: 3}]); - collection.add({id: 4}); - }); - - QUnit.test('#1407 parse option on constructor parses collection and models', function(assert) { - assert.expect(2); - var model = { - namespace: [{id: 1}, {id: 2}] - }; - var Collection = Backbone.Collection.extend({ - model: Backbone.Model.extend({ - parse: function(m) { - m.name = 'test'; - return m; - } - }), - parse: function(m) { - return m.namespace; - } - }); - var collection = new Collection(model, {parse: true}); - - assert.equal(collection.length, 2); - assert.equal(collection.at(0).get('name'), 'test'); - }); - - QUnit.test('#1407 parse option on reset parses collection and models', function(assert) { - assert.expect(2); - var model = { - namespace: [{id: 1}, {id: 2}] - }; - var Collection = Backbone.Collection.extend({ - model: Backbone.Model.extend({ - parse: function(m) { - m.name = 'test'; - return m; - } - }), - parse: function(m) { - return m.namespace; - } - }); - var collection = new Collection(); - collection.reset(model, {parse: true}); - - assert.equal(collection.length, 2); - assert.equal(collection.at(0).get('name'), 'test'); - }); - - - QUnit.test('Reset includes previous models in triggered event.', function(assert) { - assert.expect(1); - var model = new Backbone.Model(); - var collection = new Backbone.Collection([model]); - collection.on('reset', function(coll, options) { - assert.deepEqual(options.previousModels, [model]); - }); - collection.reset([]); - }); - - QUnit.test('set', function(assert) { - var m1 = new Backbone.Model(); - var m2 = new Backbone.Model({id: 2}); - var m3 = new Backbone.Model(); - var collection = new Backbone.Collection([m1, m2]); - - // Test add/change/remove events - collection.on('add', function(model) { - assert.strictEqual(model, m3); - }); - collection.on('change', function(model) { - assert.strictEqual(model, m2); - }); - collection.on('remove', function(model) { - assert.strictEqual(model, m1); - }); - - // remove: false doesn't remove any models - collection.set([], {remove: false}); - assert.strictEqual(collection.length, 2); - - // add: false doesn't add any models - collection.set([m1, m2, m3], {add: false}); - assert.strictEqual(collection.length, 2); - - // merge: false doesn't change any models - collection.set([m1, {id: 2, a: 1}], {merge: false}); - assert.strictEqual(m2.get('a'), void 0); - - // add: false, remove: false only merges existing models - collection.set([m1, {id: 2, a: 0}, m3, {id: 4}], {add: false, remove: false}); - assert.strictEqual(collection.length, 2); - assert.strictEqual(m2.get('a'), 0); - - // default options add/remove/merge as appropriate - collection.set([{id: 2, a: 1}, m3]); - assert.strictEqual(collection.length, 2); - assert.strictEqual(m2.get('a'), 1); - - // Test removing models not passing an argument - collection.off('remove').on('remove', function(model) { - assert.ok(model === m2 || model === m3); - }); - collection.set([]); - assert.strictEqual(collection.length, 0); - - // Test null models on set doesn't clear collection - collection.off(); - collection.set([{id: 1}]); - collection.set(); - assert.strictEqual(collection.length, 1); - }); - - QUnit.test('set with only cids', function(assert) { - assert.expect(3); - var m1 = new Backbone.Model; - var m2 = new Backbone.Model; - var collection = new Backbone.Collection; - collection.set([m1, m2]); - assert.equal(collection.length, 2); - collection.set([m1]); - assert.equal(collection.length, 1); - collection.set([m1, m1, m1, m2, m2], {remove: false}); - assert.equal(collection.length, 2); - }); - - QUnit.test('set with only idAttribute', function(assert) { - assert.expect(3); - var m1 = {_id: 1}; - var m2 = {_id: 2}; - var Col = Backbone.Collection.extend({ - model: Backbone.Model.extend({ - idAttribute: '_id' - }) - }); - var collection = new Col; - collection.set([m1, m2]); - assert.equal(collection.length, 2); - collection.set([m1]); - assert.equal(collection.length, 1); - collection.set([m1, m1, m1, m2, m2], {remove: false}); - assert.equal(collection.length, 2); - }); - - QUnit.test('set + merge with default values defined', function(assert) { - var Model = Backbone.Model.extend({ - defaults: { - key: 'value' - } - }); - var m = new Model({id: 1}); - var collection = new Backbone.Collection([m], {model: Model}); - assert.equal(collection.first().get('key'), 'value'); - - collection.set({id: 1, key: 'other'}); - assert.equal(collection.first().get('key'), 'other'); - - collection.set({id: 1, other: 'value'}); - assert.equal(collection.first().get('key'), 'other'); - assert.equal(collection.length, 1); - }); - - QUnit.test('merge without mutation', function(assert) { - var Model = Backbone.Model.extend({ - initialize: function(attrs, options) { - if (attrs.child) { - this.set('child', new Model(attrs.child, options), options); - } - } - }); - var Collection = Backbone.Collection.extend({model: Model}); - var data = [{id: 1, child: {id: 2}}]; - var collection = new Collection(data); - assert.equal(collection.first().id, 1); - collection.set(data); - assert.equal(collection.first().id, 1); - collection.set([{id: 2, child: {id: 2}}].concat(data)); - assert.deepEqual(collection.pluck('id'), [2, 1]); - }); - - QUnit.test('`set` and model level `parse`', function(assert) { - var Model = Backbone.Model.extend({}); - var Collection = Backbone.Collection.extend({ - model: Model, - parse: function(res) { return _.map(res.models, 'model'); } - }); - var model = new Model({id: 1}); - var collection = new Collection(model); - collection.set({models: [ - {model: {id: 1}}, - {model: {id: 2}} - ]}, {parse: true}); - assert.equal(collection.first(), model); - }); - - QUnit.test('`set` data is only parsed once', function(assert) { - var collection = new Backbone.Collection(); - collection.model = Backbone.Model.extend({ - parse: function(data) { - assert.equal(data.parsed, void 0); - data.parsed = true; - return data; - } - }); - collection.set({}, {parse: true}); - }); - - QUnit.test('`set` matches input order in the absence of a comparator', function(assert) { - var one = new Backbone.Model({id: 1}); - var two = new Backbone.Model({id: 2}); - var three = new Backbone.Model({id: 3}); - var collection = new Backbone.Collection([one, two, three]); - collection.set([{id: 3}, {id: 2}, {id: 1}]); - assert.deepEqual(collection.models, [three, two, one]); - collection.set([{id: 1}, {id: 2}]); - assert.deepEqual(collection.models, [one, two]); - collection.set([two, three, one]); - assert.deepEqual(collection.models, [two, three, one]); - collection.set([{id: 1}, {id: 2}], {remove: false}); - assert.deepEqual(collection.models, [two, three, one]); - collection.set([{id: 1}, {id: 2}, {id: 3}], {merge: false}); - assert.deepEqual(collection.models, [one, two, three]); - collection.set([three, two, one, {id: 4}], {add: false}); - assert.deepEqual(collection.models, [one, two, three]); - }); - - QUnit.test('#1894 - Push should not trigger a sort', function(assert) { - assert.expect(0); - var Collection = Backbone.Collection.extend({ - comparator: 'id', - sort: function() { assert.ok(false); } - }); - new Collection().push({id: 1}); - }); - - QUnit.test('#2428 - push duplicate models, return the correct one', function(assert) { - assert.expect(1); - var collection = new Backbone.Collection; - var model1 = collection.push({id: 101}); - var model2 = collection.push({id: 101}); - assert.ok(model2.cid === model1.cid); - }); - - QUnit.test('`set` with non-normal id', function(assert) { - var Collection = Backbone.Collection.extend({ - model: Backbone.Model.extend({idAttribute: '_id'}) - }); - var collection = new Collection({_id: 1}); - collection.set([{_id: 1, a: 1}], {add: false}); - assert.equal(collection.first().get('a'), 1); - }); - - QUnit.test('#1894 - `sort` can optionally be turned off', function(assert) { - assert.expect(0); - var Collection = Backbone.Collection.extend({ - comparator: 'id', - sort: function() { assert.ok(false); } - }); - new Collection().add({id: 1}, {sort: false}); - }); - - QUnit.test('#1915 - `parse` data in the right order in `set`', function(assert) { - var collection = new (Backbone.Collection.extend({ - parse: function(data) { - assert.strictEqual(data.status, 'ok'); - return data.data; - } - })); - var res = {status: 'ok', data: [{id: 1}]}; - collection.set(res, {parse: true}); - }); - - QUnit.test('#1939 - `parse` is passed `options`', function(assert) { - var done = assert.async(); - assert.expect(1); - var collection = new (Backbone.Collection.extend({ - url: '/', - parse: function(data, options) { - assert.strictEqual(options.xhr.someHeader, 'headerValue'); - return data; - } - })); - var ajax = Backbone.ajax; - Backbone.ajax = function(params) { - _.defer(params.success, []); - return {someHeader: 'headerValue'}; - }; - collection.fetch({ - success: function() { done(); } - }); - Backbone.ajax = ajax; - }); - - QUnit.test('fetch will pass extra options to success callback', function(assert) { - assert.expect(1); - var SpecialSyncCollection = Backbone.Collection.extend({ - url: '/test', - sync: function(method, collection, options) { - _.extend(options, {specialSync: true}); - return Backbone.Collection.prototype.sync.call(this, method, collection, options); - } - }); - - var collection = new SpecialSyncCollection(); - - var onSuccess = function(coll, resp, options) { - assert.ok(options.specialSync, 'Options were passed correctly to callback'); - }; - - collection.fetch({success: onSuccess}); - this.ajaxSettings.success(); - }); - - QUnit.test('`add` only `sort`s when necessary', function(assert) { - assert.expect(2); - var collection = new (Backbone.Collection.extend({ - comparator: 'a' - }))([{id: 1}, {id: 2}, {id: 3}]); - collection.on('sort', function() { assert.ok(true); }); - collection.add({id: 4}); // do sort, new model - collection.add({id: 1, a: 1}, {merge: true}); // do sort, comparator change - collection.add({id: 1, b: 1}, {merge: true}); // don't sort, no comparator change - collection.add({id: 1, a: 1}, {merge: true}); // don't sort, no comparator change - collection.add(collection.models); // don't sort, nothing new - collection.add(collection.models, {merge: true}); // don't sort - }); - - QUnit.test('`add` only `sort`s when necessary with comparator function', function(assert) { - assert.expect(3); - var collection = new (Backbone.Collection.extend({ - comparator: function(m1, m2) { - return m1.get('a') > m2.get('a') ? 1 : (m1.get('a') < m2.get('a') ? -1 : 0); - } - }))([{id: 1}, {id: 2}, {id: 3}]); - collection.on('sort', function() { assert.ok(true); }); - collection.add({id: 4}); // do sort, new model - collection.add({id: 1, a: 1}, {merge: true}); // do sort, model change - collection.add({id: 1, b: 1}, {merge: true}); // do sort, model change - collection.add({id: 1, a: 1}, {merge: true}); // don't sort, no model change - collection.add(collection.models); // don't sort, nothing new - collection.add(collection.models, {merge: true}); // don't sort - }); - - QUnit.test('Attach options to collection.', function(assert) { - assert.expect(2); - var Model = Backbone.Model; - var comparator = function(){}; - - var collection = new Backbone.Collection([], { - model: Model, - comparator: comparator - }); - - assert.ok(collection.model === Model); - assert.ok(collection.comparator === comparator); - }); - - QUnit.test('Pass falsey for `models` for empty Col with `options`', function(assert) { - assert.expect(9); - var opts = {a: 1, b: 2}; - _.forEach([undefined, null, false], function(falsey) { - var Collection = Backbone.Collection.extend({ - initialize: function(models, options) { - assert.strictEqual(models, falsey); - assert.strictEqual(options, opts); - } - }); - - var collection = new Collection(falsey, opts); - assert.strictEqual(collection.length, 0); - }); - }); - - QUnit.test('`add` overrides `set` flags', function(assert) { - var collection = new Backbone.Collection(); - collection.once('add', function(model, coll, options) { - coll.add({id: 2}, options); - }); - collection.set({id: 1}); - assert.equal(collection.length, 2); - }); - - QUnit.test('#2606 - Collection#create, success arguments', function(assert) { - assert.expect(1); - var collection = new Backbone.Collection; - collection.url = 'test'; - collection.create({}, { - success: function(model, resp, options) { - assert.strictEqual(resp, 'response'); - } - }); - this.ajaxSettings.success('response'); - }); - - QUnit.test('#2612 - nested `parse` works with `Collection#set`', function(assert) { - - var Job = Backbone.Model.extend({ - constructor: function() { - this.items = new Items(); - Backbone.Model.apply(this, arguments); - }, - parse: function(attrs) { - this.items.set(attrs.items, {parse: true}); - return _.omit(attrs, 'items'); - } - }); - - var Item = Backbone.Model.extend({ - constructor: function() { - this.subItems = new Backbone.Collection(); - Backbone.Model.apply(this, arguments); - }, - parse: function(attrs) { - this.subItems.set(attrs.subItems, {parse: true}); - return _.omit(attrs, 'subItems'); - } - }); - - var Items = Backbone.Collection.extend({ - model: Item - }); - - var data = { - name: 'JobName', - id: 1, - items: [{ - id: 1, - name: 'Sub1', - subItems: [ - {id: 1, subName: 'One'}, - {id: 2, subName: 'Two'} - ] - }, { - id: 2, - name: 'Sub2', - subItems: [ - {id: 3, subName: 'Three'}, - {id: 4, subName: 'Four'} - ] - }] - }; - - var newData = { - name: 'NewJobName', - id: 1, - items: [{ - id: 1, - name: 'NewSub1', - subItems: [ - {id: 1, subName: 'NewOne'}, - {id: 2, subName: 'NewTwo'} - ] - }, { - id: 2, - name: 'NewSub2', - subItems: [ - {id: 3, subName: 'NewThree'}, - {id: 4, subName: 'NewFour'} - ] - }] - }; - - var job = new Job(data, {parse: true}); - assert.equal(job.get('name'), 'JobName'); - assert.equal(job.items.at(0).get('name'), 'Sub1'); - assert.equal(job.items.length, 2); - assert.equal(job.items.get(1).subItems.get(1).get('subName'), 'One'); - assert.equal(job.items.get(2).subItems.get(3).get('subName'), 'Three'); - job.set(job.parse(newData, {parse: true})); - assert.equal(job.get('name'), 'NewJobName'); - assert.equal(job.items.at(0).get('name'), 'NewSub1'); - assert.equal(job.items.length, 2); - assert.equal(job.items.get(1).subItems.get(1).get('subName'), 'NewOne'); - assert.equal(job.items.get(2).subItems.get(3).get('subName'), 'NewThree'); - }); - - QUnit.test('_addReference binds all collection events & adds to the lookup hashes', function(assert) { - assert.expect(8); - - var calls = {add: 0, remove: 0}; - - var Collection = Backbone.Collection.extend({ - - _addReference: function(model) { - Backbone.Collection.prototype._addReference.apply(this, arguments); - calls.add++; - assert.equal(model, this._byId[model.id]); - assert.equal(model, this._byId[model.cid]); - assert.equal(model._events.all.length, 1); - }, - - _removeReference: function(model) { - Backbone.Collection.prototype._removeReference.apply(this, arguments); - calls.remove++; - assert.equal(this._byId[model.id], void 0); - assert.equal(this._byId[model.cid], void 0); - assert.equal(model.collection, void 0); - } - - }); - - var collection = new Collection(); - var model = collection.add({id: 1}); - collection.remove(model); - - assert.equal(calls.add, 1); - assert.equal(calls.remove, 1); - }); - - QUnit.test('Do not allow duplicate models to be `add`ed or `set`', function(assert) { - var collection = new Backbone.Collection(); - - collection.add([{id: 1}, {id: 1}]); - assert.equal(collection.length, 1); - assert.equal(collection.models.length, 1); - - collection.set([{id: 1}, {id: 1}]); - assert.equal(collection.length, 1); - assert.equal(collection.models.length, 1); - }); - - QUnit.test('#3020: #set with {add: false} should not throw.', function(assert) { - assert.expect(2); - var collection = new Backbone.Collection; - collection.set([{id: 1}], {add: false}); - assert.strictEqual(collection.length, 0); - assert.strictEqual(collection.models.length, 0); - }); - - QUnit.test('create with wait, model instance, #3028', function(assert) { - assert.expect(1); - var collection = new Backbone.Collection(); - var model = new Backbone.Model({id: 1}); - model.sync = function(){ - assert.equal(this.collection, collection); - }; - collection.create(model, {wait: true}); - }); - - QUnit.test('modelId', function(assert) { - var Stooge = Backbone.Model.extend(); - var StoogeCollection = Backbone.Collection.extend({model: Stooge}); - - // Default to using `Collection::model::idAttribute`. - assert.equal(StoogeCollection.prototype.modelId({id: 1}), 1); - Stooge.prototype.idAttribute = '_id'; - assert.equal(StoogeCollection.prototype.modelId({_id: 1}), 1); - }); - - QUnit.test('Polymorphic models work with "simple" constructors', function(assert) { - var A = Backbone.Model.extend(); - var B = Backbone.Model.extend(); - var C = Backbone.Collection.extend({ - model: function(attrs) { - return attrs.type === 'a' ? new A(attrs) : new B(attrs); - } - }); - var collection = new C([{id: 1, type: 'a'}, {id: 2, type: 'b'}]); - assert.equal(collection.length, 2); - assert.ok(collection.at(0) instanceof A); - assert.equal(collection.at(0).id, 1); - assert.ok(collection.at(1) instanceof B); - assert.equal(collection.at(1).id, 2); - }); - - QUnit.test('Polymorphic models work with "advanced" constructors', function(assert) { - var A = Backbone.Model.extend({idAttribute: '_id'}); - var B = Backbone.Model.extend({idAttribute: '_id'}); - var C = Backbone.Collection.extend({ - model: Backbone.Model.extend({ - constructor: function(attrs) { - return attrs.type === 'a' ? new A(attrs) : new B(attrs); - }, - - idAttribute: '_id' - }) - }); - var collection = new C([{_id: 1, type: 'a'}, {_id: 2, type: 'b'}]); - assert.equal(collection.length, 2); - assert.ok(collection.at(0) instanceof A); - assert.equal(collection.at(0), collection.get(1)); - assert.ok(collection.at(1) instanceof B); - assert.equal(collection.at(1), collection.get(2)); - - C = Backbone.Collection.extend({ - model: function(attrs) { - return attrs.type === 'a' ? new A(attrs) : new B(attrs); - }, - - modelId: function(attrs) { - return attrs.type + '-' + attrs.id; - } - }); - collection = new C([{id: 1, type: 'a'}, {id: 1, type: 'b'}]); - assert.equal(collection.length, 2); - assert.ok(collection.at(0) instanceof A); - assert.equal(collection.at(0), collection.get('a-1')); - assert.ok(collection.at(1) instanceof B); - assert.equal(collection.at(1), collection.get('b-1')); - }); - - QUnit.test('Collection with polymorphic models receives default id from modelId', function(assert) { - assert.expect(6); - // When the polymorphic models use 'id' for the idAttribute, all is fine. - var C1 = Backbone.Collection.extend({ - model: function(attrs) { - return new Backbone.Model(attrs); - } - }); - var c1 = new C1({id: 1}); - assert.equal(c1.get(1).id, 1); - assert.equal(c1.modelId({id: 1}), 1); - - // If the polymorphic models define their own idAttribute, - // the modelId method should be overridden, for the reason below. - var M = Backbone.Model.extend({ - idAttribute: '_id' - }); - var C2 = Backbone.Collection.extend({ - model: function(attrs) { - return new M(attrs); - } - }); - var c2 = new C2({'_id': 1}); - assert.equal(c2.get(1), void 0); - assert.equal(c2.modelId(c2.at(0).attributes), void 0); - var m = new M({'_id': 2}); - c2.add(m); - assert.equal(c2.get(2), void 0); - assert.equal(c2.modelId(m.attributes), void 0); - }); - - QUnit.test('#3039 #3951: adding at index fires with correct at', function(assert) { - assert.expect(4); - var collection = new Backbone.Collection([{val: 0}, {val: 4}]); - collection.on('add', function(model, coll, options) { - assert.equal(model.get('val'), options.index); - }); - collection.add([{val: 1}, {val: 2}, {val: 3}], {at: 1}); - collection.add({val: 5}, {at: 10}); - }); - - QUnit.test('#3039: index is not sent when at is not specified', function(assert) { - assert.expect(2); - var collection = new Backbone.Collection([{at: 0}]); - collection.on('add', function(model, coll, options) { - assert.equal(undefined, options.index); - }); - collection.add([{at: 1}, {at: 2}]); - }); - - QUnit.test('#3199 - Order changing should trigger a sort', function(assert) { - assert.expect(1); - var one = new Backbone.Model({id: 1}); - var two = new Backbone.Model({id: 2}); - var three = new Backbone.Model({id: 3}); - var collection = new Backbone.Collection([one, two, three]); - collection.on('sort', function() { - assert.ok(true); - }); - collection.set([{id: 3}, {id: 2}, {id: 1}]); - }); - - QUnit.test('#3199 - Adding a model should trigger a sort', function(assert) { - assert.expect(1); - var one = new Backbone.Model({id: 1}); - var two = new Backbone.Model({id: 2}); - var three = new Backbone.Model({id: 3}); - var collection = new Backbone.Collection([one, two, three]); - collection.on('sort', function() { - assert.ok(true); - }); - collection.set([{id: 1}, {id: 2}, {id: 3}, {id: 0}]); - }); - - QUnit.test('#3199 - Order not changing should not trigger a sort', function(assert) { - assert.expect(0); - var one = new Backbone.Model({id: 1}); - var two = new Backbone.Model({id: 2}); - var three = new Backbone.Model({id: 3}); - var collection = new Backbone.Collection([one, two, three]); - collection.on('sort', function() { - assert.ok(false); - }); - collection.set([{id: 1}, {id: 2}, {id: 3}]); - }); - - QUnit.test('add supports negative indexes', function(assert) { - assert.expect(1); - var collection = new Backbone.Collection([{id: 1}]); - collection.add([{id: 2}, {id: 3}], {at: -1}); - collection.add([{id: 2.5}], {at: -2}); - collection.add([{id: 0.5}], {at: -6}); - assert.equal(collection.pluck('id').join(','), '0.5,1,2,2.5,3'); - }); - - QUnit.test('#set accepts options.at as a string', function(assert) { - assert.expect(1); - var collection = new Backbone.Collection([{id: 1}, {id: 2}]); - collection.add([{id: 3}], {at: '1'}); - assert.deepEqual(collection.pluck('id'), [1, 3, 2]); - }); - - QUnit.test('adding multiple models triggers `update` event once', function(assert) { - assert.expect(1); - var collection = new Backbone.Collection; - collection.on('update', function() { assert.ok(true); }); - collection.add([{id: 1}, {id: 2}, {id: 3}]); - }); - - QUnit.test('removing models triggers `update` event once', function(assert) { - assert.expect(1); - var collection = new Backbone.Collection([{id: 1}, {id: 2}, {id: 3}]); - collection.on('update', function() { assert.ok(true); }); - collection.remove([{id: 1}, {id: 2}]); - }); - - QUnit.test('remove does not trigger `update` when nothing removed', function(assert) { - assert.expect(0); - var collection = new Backbone.Collection([{id: 1}, {id: 2}]); - collection.on('update', function() { assert.ok(false); }); - collection.remove([{id: 3}]); - }); - - QUnit.test('set triggers `set` event once', function(assert) { - assert.expect(1); - var collection = new Backbone.Collection([{id: 1}, {id: 2}]); - collection.on('update', function() { assert.ok(true); }); - collection.set([{id: 1}, {id: 3}]); - }); - - QUnit.test('set does not trigger `update` event when nothing added nor removed', function(assert) { - var collection = new Backbone.Collection([{id: 1}, {id: 2}]); - collection.on('update', function(coll, options) { - assert.equal(options.changes.added.length, 0); - assert.equal(options.changes.removed.length, 0); - assert.equal(options.changes.merged.length, 2); - }); - collection.set([{id: 1}, {id: 2}]); - }); - - QUnit.test('#3610 - invoke collects arguments', function(assert) { - assert.expect(3); - var Model = Backbone.Model.extend({ - method: function(x, y, z) { - assert.equal(x, 1); - assert.equal(y, 2); - assert.equal(z, 3); - } - }); - var Collection = Backbone.Collection.extend({ - model: Model - }); - var collection = new Collection([{id: 1}]); - collection.invoke('method', 1, 2, 3); - }); - - QUnit.test('#3662 - triggering change without model will not error', function(assert) { - assert.expect(1); - var collection = new Backbone.Collection([{id: 1}]); - var model = collection.first(); - collection.on('change', function(m) { - assert.equal(m, undefined); - }); - model.trigger('change'); - }); - - QUnit.test('#3871 - falsy parse result creates empty collection', function(assert) { - var collection = new (Backbone.Collection.extend({ - parse: function(data, options) {} - })); - collection.set('', {parse: true}); - assert.equal(collection.length, 0); - }); - - QUnit.test("#3711 - remove's `update` event returns one removed model", function(assert) { - var model = new Backbone.Model({id: 1, title: 'First Post'}); - var collection = new Backbone.Collection([model]); - collection.on('update', function(context, options) { - var changed = options.changes; - assert.deepEqual(changed.added, []); - assert.deepEqual(changed.merged, []); - assert.strictEqual(changed.removed[0], model); - }); - collection.remove(model); - }); - - QUnit.test("#3711 - remove's `update` event returns multiple removed models", function(assert) { - var model = new Backbone.Model({id: 1, title: 'First Post'}); - var model2 = new Backbone.Model({id: 2, title: 'Second Post'}); - var collection = new Backbone.Collection([model, model2]); - collection.on('update', function(context, options) { - var changed = options.changes; - assert.deepEqual(changed.added, []); - assert.deepEqual(changed.merged, []); - assert.ok(changed.removed.length === 2); - - assert.ok(_.indexOf(changed.removed, model) > -1 && _.indexOf(changed.removed, model2) > -1); - }); - collection.remove([model, model2]); - }); - - QUnit.test("#3711 - set's `update` event returns one added model", function(assert) { - var model = new Backbone.Model({id: 1, title: 'First Post'}); - var collection = new Backbone.Collection(); - collection.on('update', function(context, options) { - var addedModels = options.changes.added; - assert.ok(addedModels.length === 1); - assert.strictEqual(addedModels[0], model); - }); - collection.set(model); - }); - - QUnit.test("#3711 - set's `update` event returns multiple added models", function(assert) { - var model = new Backbone.Model({id: 1, title: 'First Post'}); - var model2 = new Backbone.Model({id: 2, title: 'Second Post'}); - var collection = new Backbone.Collection(); - collection.on('update', function(context, options) { - var addedModels = options.changes.added; - assert.ok(addedModels.length === 2); - assert.strictEqual(addedModels[0], model); - assert.strictEqual(addedModels[1], model2); - }); - collection.set([model, model2]); - }); - - QUnit.test("#3711 - set's `update` event returns one removed model", function(assert) { - var model = new Backbone.Model({id: 1, title: 'First Post'}); - var model2 = new Backbone.Model({id: 2, title: 'Second Post'}); - var model3 = new Backbone.Model({id: 3, title: 'My Last Post'}); - var collection = new Backbone.Collection([model]); - collection.on('update', function(context, options) { - var changed = options.changes; - assert.equal(changed.added.length, 2); - assert.equal(changed.merged.length, 0); - assert.ok(changed.removed.length === 1); - assert.strictEqual(changed.removed[0], model); - }); - collection.set([model2, model3]); - }); - - QUnit.test("#3711 - set's `update` event returns multiple removed models", function(assert) { - var model = new Backbone.Model({id: 1, title: 'First Post'}); - var model2 = new Backbone.Model({id: 2, title: 'Second Post'}); - var model3 = new Backbone.Model({id: 3, title: 'My Last Post'}); - var collection = new Backbone.Collection([model, model2]); - collection.on('update', function(context, options) { - var removedModels = options.changes.removed; - assert.ok(removedModels.length === 2); - assert.strictEqual(removedModels[0], model); - assert.strictEqual(removedModels[1], model2); - }); - collection.set([model3]); - }); - - QUnit.test("#3711 - set's `update` event returns one merged model", function(assert) { - var model = new Backbone.Model({id: 1, title: 'First Post'}); - var model2 = new Backbone.Model({id: 2, title: 'Second Post'}); - var model2Update = new Backbone.Model({id: 2, title: 'Second Post V2'}); - var collection = new Backbone.Collection([model, model2]); - collection.on('update', function(context, options) { - var mergedModels = options.changes.merged; - assert.ok(mergedModels.length === 1); - assert.strictEqual(mergedModels[0].get('title'), model2Update.get('title')); - }); - collection.set([model2Update]); - }); - - QUnit.test("#3711 - set's `update` event returns multiple merged models", function(assert) { - var model = new Backbone.Model({id: 1, title: 'First Post'}); - var modelUpdate = new Backbone.Model({id: 1, title: 'First Post V2'}); - var model2 = new Backbone.Model({id: 2, title: 'Second Post'}); - var model2Update = new Backbone.Model({id: 2, title: 'Second Post V2'}); - var collection = new Backbone.Collection([model, model2]); - collection.on('update', function(context, options) { - var mergedModels = options.changes.merged; - assert.ok(mergedModels.length === 2); - assert.strictEqual(mergedModels[0].get('title'), model2Update.get('title')); - assert.strictEqual(mergedModels[1].get('title'), modelUpdate.get('title')); - }); - collection.set([model2Update, modelUpdate]); - }); - - QUnit.test("#3711 - set's `update` event should not be triggered adding a model which already exists exactly alike", function(assert) { - var fired = false; - var model = new Backbone.Model({id: 1, title: 'First Post'}); - var collection = new Backbone.Collection([model]); - collection.on('update', function(context, options) { - fired = true; - }); - collection.set([model]); - assert.equal(fired, false); - }); - -})(); diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/backbone/test/events.js b/ecomp-portal-FE/client/bower_components/lodash/vendor/backbone/test/events.js deleted file mode 100644 index 544b39a1..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/backbone/test/events.js +++ /dev/null @@ -1,706 +0,0 @@ -(function() { - - QUnit.module('Backbone.Events'); - - QUnit.test('on and trigger', function(assert) { - assert.expect(2); - var obj = {counter: 0}; - _.extend(obj, Backbone.Events); - obj.on('event', function() { obj.counter += 1; }); - obj.trigger('event'); - assert.equal(obj.counter, 1, 'counter should be incremented.'); - obj.trigger('event'); - obj.trigger('event'); - obj.trigger('event'); - obj.trigger('event'); - assert.equal(obj.counter, 5, 'counter should be incremented five times.'); - }); - - QUnit.test('binding and triggering multiple events', function(assert) { - assert.expect(4); - var obj = {counter: 0}; - _.extend(obj, Backbone.Events); - - obj.on('a b c', function() { obj.counter += 1; }); - - obj.trigger('a'); - assert.equal(obj.counter, 1); - - obj.trigger('a b'); - assert.equal(obj.counter, 3); - - obj.trigger('c'); - assert.equal(obj.counter, 4); - - obj.off('a c'); - obj.trigger('a b c'); - assert.equal(obj.counter, 5); - }); - - QUnit.test('binding and triggering with event maps', function(assert) { - var obj = {counter: 0}; - _.extend(obj, Backbone.Events); - - var increment = function() { - this.counter += 1; - }; - - obj.on({ - a: increment, - b: increment, - c: increment - }, obj); - - obj.trigger('a'); - assert.equal(obj.counter, 1); - - obj.trigger('a b'); - assert.equal(obj.counter, 3); - - obj.trigger('c'); - assert.equal(obj.counter, 4); - - obj.off({ - a: increment, - c: increment - }, obj); - obj.trigger('a b c'); - assert.equal(obj.counter, 5); - }); - - QUnit.test('binding and triggering multiple event names with event maps', function(assert) { - var obj = {counter: 0}; - _.extend(obj, Backbone.Events); - - var increment = function() { - this.counter += 1; - }; - - obj.on({ - 'a b c': increment - }); - - obj.trigger('a'); - assert.equal(obj.counter, 1); - - obj.trigger('a b'); - assert.equal(obj.counter, 3); - - obj.trigger('c'); - assert.equal(obj.counter, 4); - - obj.off({ - 'a c': increment - }); - obj.trigger('a b c'); - assert.equal(obj.counter, 5); - }); - - QUnit.test('binding and trigger with event maps context', function(assert) { - assert.expect(2); - var obj = {counter: 0}; - var context = {}; - _.extend(obj, Backbone.Events); - - obj.on({ - a: function() { - assert.strictEqual(this, context, 'defaults `context` to `callback` param'); - } - }, context).trigger('a'); - - obj.off().on({ - a: function() { - assert.strictEqual(this, context, 'will not override explicit `context` param'); - } - }, this, context).trigger('a'); - }); - - QUnit.test('listenTo and stopListening', function(assert) { - assert.expect(1); - var a = _.extend({}, Backbone.Events); - var b = _.extend({}, Backbone.Events); - a.listenTo(b, 'all', function(){ assert.ok(true); }); - b.trigger('anything'); - a.listenTo(b, 'all', function(){ assert.ok(false); }); - a.stopListening(); - b.trigger('anything'); - }); - - QUnit.test('listenTo and stopListening with event maps', function(assert) { - assert.expect(4); - var a = _.extend({}, Backbone.Events); - var b = _.extend({}, Backbone.Events); - var cb = function(){ assert.ok(true); }; - a.listenTo(b, {event: cb}); - b.trigger('event'); - a.listenTo(b, {event2: cb}); - b.on('event2', cb); - a.stopListening(b, {event2: cb}); - b.trigger('event event2'); - a.stopListening(); - b.trigger('event event2'); - }); - - QUnit.test('stopListening with omitted args', function(assert) { - assert.expect(2); - var a = _.extend({}, Backbone.Events); - var b = _.extend({}, Backbone.Events); - var cb = function() { assert.ok(true); }; - a.listenTo(b, 'event', cb); - b.on('event', cb); - a.listenTo(b, 'event2', cb); - a.stopListening(null, {event: cb}); - b.trigger('event event2'); - b.off(); - a.listenTo(b, 'event event2', cb); - a.stopListening(null, 'event'); - a.stopListening(); - b.trigger('event2'); - }); - - QUnit.test('listenToOnce', function(assert) { - assert.expect(2); - // Same as the previous test, but we use once rather than having to explicitly unbind - var obj = {counterA: 0, counterB: 0}; - _.extend(obj, Backbone.Events); - var incrA = function(){ obj.counterA += 1; obj.trigger('event'); }; - var incrB = function(){ obj.counterB += 1; }; - obj.listenToOnce(obj, 'event', incrA); - obj.listenToOnce(obj, 'event', incrB); - obj.trigger('event'); - assert.equal(obj.counterA, 1, 'counterA should have only been incremented once.'); - assert.equal(obj.counterB, 1, 'counterB should have only been incremented once.'); - }); - - QUnit.test('listenToOnce and stopListening', function(assert) { - assert.expect(1); - var a = _.extend({}, Backbone.Events); - var b = _.extend({}, Backbone.Events); - a.listenToOnce(b, 'all', function() { assert.ok(true); }); - b.trigger('anything'); - b.trigger('anything'); - a.listenToOnce(b, 'all', function() { assert.ok(false); }); - a.stopListening(); - b.trigger('anything'); - }); - - QUnit.test('listenTo, listenToOnce and stopListening', function(assert) { - assert.expect(1); - var a = _.extend({}, Backbone.Events); - var b = _.extend({}, Backbone.Events); - a.listenToOnce(b, 'all', function() { assert.ok(true); }); - b.trigger('anything'); - b.trigger('anything'); - a.listenTo(b, 'all', function() { assert.ok(false); }); - a.stopListening(); - b.trigger('anything'); - }); - - QUnit.test('listenTo and stopListening with event maps', function(assert) { - assert.expect(1); - var a = _.extend({}, Backbone.Events); - var b = _.extend({}, Backbone.Events); - a.listenTo(b, {change: function(){ assert.ok(true); }}); - b.trigger('change'); - a.listenTo(b, {change: function(){ assert.ok(false); }}); - a.stopListening(); - b.trigger('change'); - }); - - QUnit.test('listenTo yourself', function(assert) { - assert.expect(1); - var e = _.extend({}, Backbone.Events); - e.listenTo(e, 'foo', function(){ assert.ok(true); }); - e.trigger('foo'); - }); - - QUnit.test('listenTo yourself cleans yourself up with stopListening', function(assert) { - assert.expect(1); - var e = _.extend({}, Backbone.Events); - e.listenTo(e, 'foo', function(){ assert.ok(true); }); - e.trigger('foo'); - e.stopListening(); - e.trigger('foo'); - }); - - QUnit.test('stopListening cleans up references', function(assert) { - assert.expect(12); - var a = _.extend({}, Backbone.Events); - var b = _.extend({}, Backbone.Events); - var fn = function() {}; - b.on('event', fn); - a.listenTo(b, 'event', fn).stopListening(); - assert.equal(_.size(a._listeningTo), 0); - assert.equal(_.size(b._events.event), 1); - assert.equal(_.size(b._listeners), 0); - a.listenTo(b, 'event', fn).stopListening(b); - assert.equal(_.size(a._listeningTo), 0); - assert.equal(_.size(b._events.event), 1); - assert.equal(_.size(b._listeners), 0); - a.listenTo(b, 'event', fn).stopListening(b, 'event'); - assert.equal(_.size(a._listeningTo), 0); - assert.equal(_.size(b._events.event), 1); - assert.equal(_.size(b._listeners), 0); - a.listenTo(b, 'event', fn).stopListening(b, 'event', fn); - assert.equal(_.size(a._listeningTo), 0); - assert.equal(_.size(b._events.event), 1); - assert.equal(_.size(b._listeners), 0); - }); - - QUnit.test('stopListening cleans up references from listenToOnce', function(assert) { - assert.expect(12); - var a = _.extend({}, Backbone.Events); - var b = _.extend({}, Backbone.Events); - var fn = function() {}; - b.on('event', fn); - a.listenToOnce(b, 'event', fn).stopListening(); - assert.equal(_.size(a._listeningTo), 0); - assert.equal(_.size(b._events.event), 1); - assert.equal(_.size(b._listeners), 0); - a.listenToOnce(b, 'event', fn).stopListening(b); - assert.equal(_.size(a._listeningTo), 0); - assert.equal(_.size(b._events.event), 1); - assert.equal(_.size(b._listeners), 0); - a.listenToOnce(b, 'event', fn).stopListening(b, 'event'); - assert.equal(_.size(a._listeningTo), 0); - assert.equal(_.size(b._events.event), 1); - assert.equal(_.size(b._listeners), 0); - a.listenToOnce(b, 'event', fn).stopListening(b, 'event', fn); - assert.equal(_.size(a._listeningTo), 0); - assert.equal(_.size(b._events.event), 1); - assert.equal(_.size(b._listeners), 0); - }); - - QUnit.test('listenTo and off cleaning up references', function(assert) { - assert.expect(8); - var a = _.extend({}, Backbone.Events); - var b = _.extend({}, Backbone.Events); - var fn = function() {}; - a.listenTo(b, 'event', fn); - b.off(); - assert.equal(_.size(a._listeningTo), 0); - assert.equal(_.size(b._listeners), 0); - a.listenTo(b, 'event', fn); - b.off('event'); - assert.equal(_.size(a._listeningTo), 0); - assert.equal(_.size(b._listeners), 0); - a.listenTo(b, 'event', fn); - b.off(null, fn); - assert.equal(_.size(a._listeningTo), 0); - assert.equal(_.size(b._listeners), 0); - a.listenTo(b, 'event', fn); - b.off(null, null, a); - assert.equal(_.size(a._listeningTo), 0); - assert.equal(_.size(b._listeners), 0); - }); - - QUnit.test('listenTo and stopListening cleaning up references', function(assert) { - assert.expect(2); - var a = _.extend({}, Backbone.Events); - var b = _.extend({}, Backbone.Events); - a.listenTo(b, 'all', function(){ assert.ok(true); }); - b.trigger('anything'); - a.listenTo(b, 'other', function(){ assert.ok(false); }); - a.stopListening(b, 'other'); - a.stopListening(b, 'all'); - assert.equal(_.size(a._listeningTo), 0); - }); - - QUnit.test('listenToOnce without context cleans up references after the event has fired', function(assert) { - assert.expect(2); - var a = _.extend({}, Backbone.Events); - var b = _.extend({}, Backbone.Events); - a.listenToOnce(b, 'all', function(){ assert.ok(true); }); - b.trigger('anything'); - assert.equal(_.size(a._listeningTo), 0); - }); - - QUnit.test('listenToOnce with event maps cleans up references', function(assert) { - assert.expect(2); - var a = _.extend({}, Backbone.Events); - var b = _.extend({}, Backbone.Events); - a.listenToOnce(b, { - one: function() { assert.ok(true); }, - two: function() { assert.ok(false); } - }); - b.trigger('one'); - assert.equal(_.size(a._listeningTo), 1); - }); - - QUnit.test('listenToOnce with event maps binds the correct `this`', function(assert) { - assert.expect(1); - var a = _.extend({}, Backbone.Events); - var b = _.extend({}, Backbone.Events); - a.listenToOnce(b, { - one: function() { assert.ok(this === a); }, - two: function() { assert.ok(false); } - }); - b.trigger('one'); - }); - - QUnit.test("listenTo with empty callback doesn't throw an error", function(assert) { - assert.expect(1); - var e = _.extend({}, Backbone.Events); - e.listenTo(e, 'foo', null); - e.trigger('foo'); - assert.ok(true); - }); - - QUnit.test('trigger all for each event', function(assert) { - assert.expect(3); - var a, b, obj = {counter: 0}; - _.extend(obj, Backbone.Events); - obj.on('all', function(event) { - obj.counter++; - if (event === 'a') a = true; - if (event === 'b') b = true; - }) - .trigger('a b'); - assert.ok(a); - assert.ok(b); - assert.equal(obj.counter, 2); - }); - - QUnit.test('on, then unbind all functions', function(assert) { - assert.expect(1); - var obj = {counter: 0}; - _.extend(obj, Backbone.Events); - var callback = function() { obj.counter += 1; }; - obj.on('event', callback); - obj.trigger('event'); - obj.off('event'); - obj.trigger('event'); - assert.equal(obj.counter, 1, 'counter should have only been incremented once.'); - }); - - QUnit.test('bind two callbacks, unbind only one', function(assert) { - assert.expect(2); - var obj = {counterA: 0, counterB: 0}; - _.extend(obj, Backbone.Events); - var callback = function() { obj.counterA += 1; }; - obj.on('event', callback); - obj.on('event', function() { obj.counterB += 1; }); - obj.trigger('event'); - obj.off('event', callback); - obj.trigger('event'); - assert.equal(obj.counterA, 1, 'counterA should have only been incremented once.'); - assert.equal(obj.counterB, 2, 'counterB should have been incremented twice.'); - }); - - QUnit.test('unbind a callback in the midst of it firing', function(assert) { - assert.expect(1); - var obj = {counter: 0}; - _.extend(obj, Backbone.Events); - var callback = function() { - obj.counter += 1; - obj.off('event', callback); - }; - obj.on('event', callback); - obj.trigger('event'); - obj.trigger('event'); - obj.trigger('event'); - assert.equal(obj.counter, 1, 'the callback should have been unbound.'); - }); - - QUnit.test('two binds that unbind themeselves', function(assert) { - assert.expect(2); - var obj = {counterA: 0, counterB: 0}; - _.extend(obj, Backbone.Events); - var incrA = function(){ obj.counterA += 1; obj.off('event', incrA); }; - var incrB = function(){ obj.counterB += 1; obj.off('event', incrB); }; - obj.on('event', incrA); - obj.on('event', incrB); - obj.trigger('event'); - obj.trigger('event'); - obj.trigger('event'); - assert.equal(obj.counterA, 1, 'counterA should have only been incremented once.'); - assert.equal(obj.counterB, 1, 'counterB should have only been incremented once.'); - }); - - QUnit.test('bind a callback with a default context when none supplied', function(assert) { - assert.expect(1); - var obj = _.extend({ - assertTrue: function() { - assert.equal(this, obj, '`this` was bound to the callback'); - } - }, Backbone.Events); - - obj.once('event', obj.assertTrue); - obj.trigger('event'); - }); - - QUnit.test('bind a callback with a supplied context', function(assert) { - assert.expect(1); - var TestClass = function() { - return this; - }; - TestClass.prototype.assertTrue = function() { - assert.ok(true, '`this` was bound to the callback'); - }; - - var obj = _.extend({}, Backbone.Events); - obj.on('event', function() { this.assertTrue(); }, new TestClass); - obj.trigger('event'); - }); - - QUnit.test('nested trigger with unbind', function(assert) { - assert.expect(1); - var obj = {counter: 0}; - _.extend(obj, Backbone.Events); - var incr1 = function(){ obj.counter += 1; obj.off('event', incr1); obj.trigger('event'); }; - var incr2 = function(){ obj.counter += 1; }; - obj.on('event', incr1); - obj.on('event', incr2); - obj.trigger('event'); - assert.equal(obj.counter, 3, 'counter should have been incremented three times'); - }); - - QUnit.test('callback list is not altered during trigger', function(assert) { - assert.expect(2); - var counter = 0, obj = _.extend({}, Backbone.Events); - var incr = function(){ counter++; }; - var incrOn = function(){ obj.on('event all', incr); }; - var incrOff = function(){ obj.off('event all', incr); }; - - obj.on('event all', incrOn).trigger('event'); - assert.equal(counter, 0, 'on does not alter callback list'); - - obj.off().on('event', incrOff).on('event all', incr).trigger('event'); - assert.equal(counter, 2, 'off does not alter callback list'); - }); - - QUnit.test("#1282 - 'all' callback list is retrieved after each event.", function(assert) { - assert.expect(1); - var counter = 0; - var obj = _.extend({}, Backbone.Events); - var incr = function(){ counter++; }; - obj.on('x', function() { - obj.on('y', incr).on('all', incr); - }) - .trigger('x y'); - assert.strictEqual(counter, 2); - }); - - QUnit.test('if no callback is provided, `on` is a noop', function(assert) { - assert.expect(0); - _.extend({}, Backbone.Events).on('test').trigger('test'); - }); - - QUnit.test('if callback is truthy but not a function, `on` should throw an error just like jQuery', function(assert) { - assert.expect(1); - var view = _.extend({}, Backbone.Events).on('test', 'noop'); - assert.raises(function() { - view.trigger('test'); - }); - }); - - QUnit.test('remove all events for a specific context', function(assert) { - assert.expect(4); - var obj = _.extend({}, Backbone.Events); - obj.on('x y all', function() { assert.ok(true); }); - obj.on('x y all', function() { assert.ok(false); }, obj); - obj.off(null, null, obj); - obj.trigger('x y'); - }); - - QUnit.test('remove all events for a specific callback', function(assert) { - assert.expect(4); - var obj = _.extend({}, Backbone.Events); - var success = function() { assert.ok(true); }; - var fail = function() { assert.ok(false); }; - obj.on('x y all', success); - obj.on('x y all', fail); - obj.off(null, fail); - obj.trigger('x y'); - }); - - QUnit.test('#1310 - off does not skip consecutive events', function(assert) { - assert.expect(0); - var obj = _.extend({}, Backbone.Events); - obj.on('event', function() { assert.ok(false); }, obj); - obj.on('event', function() { assert.ok(false); }, obj); - obj.off(null, null, obj); - obj.trigger('event'); - }); - - QUnit.test('once', function(assert) { - assert.expect(2); - // Same as the previous test, but we use once rather than having to explicitly unbind - var obj = {counterA: 0, counterB: 0}; - _.extend(obj, Backbone.Events); - var incrA = function(){ obj.counterA += 1; obj.trigger('event'); }; - var incrB = function(){ obj.counterB += 1; }; - obj.once('event', incrA); - obj.once('event', incrB); - obj.trigger('event'); - assert.equal(obj.counterA, 1, 'counterA should have only been incremented once.'); - assert.equal(obj.counterB, 1, 'counterB should have only been incremented once.'); - }); - - QUnit.test('once variant one', function(assert) { - assert.expect(3); - var f = function(){ assert.ok(true); }; - - var a = _.extend({}, Backbone.Events).once('event', f); - var b = _.extend({}, Backbone.Events).on('event', f); - - a.trigger('event'); - - b.trigger('event'); - b.trigger('event'); - }); - - QUnit.test('once variant two', function(assert) { - assert.expect(3); - var f = function(){ assert.ok(true); }; - var obj = _.extend({}, Backbone.Events); - - obj - .once('event', f) - .on('event', f) - .trigger('event') - .trigger('event'); - }); - - QUnit.test('once with off', function(assert) { - assert.expect(0); - var f = function(){ assert.ok(true); }; - var obj = _.extend({}, Backbone.Events); - - obj.once('event', f); - obj.off('event', f); - obj.trigger('event'); - }); - - QUnit.test('once with event maps', function(assert) { - var obj = {counter: 0}; - _.extend(obj, Backbone.Events); - - var increment = function() { - this.counter += 1; - }; - - obj.once({ - a: increment, - b: increment, - c: increment - }, obj); - - obj.trigger('a'); - assert.equal(obj.counter, 1); - - obj.trigger('a b'); - assert.equal(obj.counter, 2); - - obj.trigger('c'); - assert.equal(obj.counter, 3); - - obj.trigger('a b c'); - assert.equal(obj.counter, 3); - }); - - QUnit.test('bind a callback with a supplied context using once with object notation', function(assert) { - assert.expect(1); - var obj = {counter: 0}; - var context = {}; - _.extend(obj, Backbone.Events); - - obj.once({ - a: function() { - assert.strictEqual(this, context, 'defaults `context` to `callback` param'); - } - }, context).trigger('a'); - }); - - QUnit.test('once with off only by context', function(assert) { - assert.expect(0); - var context = {}; - var obj = _.extend({}, Backbone.Events); - obj.once('event', function(){ assert.ok(false); }, context); - obj.off(null, null, context); - obj.trigger('event'); - }); - - QUnit.test('Backbone object inherits Events', function(assert) { - assert.ok(Backbone.on === Backbone.Events.on); - }); - - QUnit.test('once with asynchronous events', function(assert) { - var done = assert.async(); - assert.expect(1); - var func = _.debounce(function() { assert.ok(true); done(); }, 50); - var obj = _.extend({}, Backbone.Events).once('async', func); - - obj.trigger('async'); - obj.trigger('async'); - }); - - QUnit.test('once with multiple events.', function(assert) { - assert.expect(2); - var obj = _.extend({}, Backbone.Events); - obj.once('x y', function() { assert.ok(true); }); - obj.trigger('x y'); - }); - - QUnit.test('Off during iteration with once.', function(assert) { - assert.expect(2); - var obj = _.extend({}, Backbone.Events); - var f = function(){ this.off('event', f); }; - obj.on('event', f); - obj.once('event', function(){}); - obj.on('event', function(){ assert.ok(true); }); - - obj.trigger('event'); - obj.trigger('event'); - }); - - QUnit.test('`once` on `all` should work as expected', function(assert) { - assert.expect(1); - Backbone.once('all', function() { - assert.ok(true); - Backbone.trigger('all'); - }); - Backbone.trigger('all'); - }); - - QUnit.test('once without a callback is a noop', function(assert) { - assert.expect(0); - _.extend({}, Backbone.Events).once('event').trigger('event'); - }); - - QUnit.test('listenToOnce without a callback is a noop', function(assert) { - assert.expect(0); - var obj = _.extend({}, Backbone.Events); - obj.listenToOnce(obj, 'event').trigger('event'); - }); - - QUnit.test('event functions are chainable', function(assert) { - var obj = _.extend({}, Backbone.Events); - var obj2 = _.extend({}, Backbone.Events); - var fn = function() {}; - assert.equal(obj, obj.trigger('noeventssetyet')); - assert.equal(obj, obj.off('noeventssetyet')); - assert.equal(obj, obj.stopListening('noeventssetyet')); - assert.equal(obj, obj.on('a', fn)); - assert.equal(obj, obj.once('c', fn)); - assert.equal(obj, obj.trigger('a')); - assert.equal(obj, obj.listenTo(obj2, 'a', fn)); - assert.equal(obj, obj.listenToOnce(obj2, 'b', fn)); - assert.equal(obj, obj.off('a c')); - assert.equal(obj, obj.stopListening(obj2, 'a')); - assert.equal(obj, obj.stopListening()); - }); - - QUnit.test('#3448 - listenToOnce with space-separated events', function(assert) { - assert.expect(2); - var one = _.extend({}, Backbone.Events); - var two = _.extend({}, Backbone.Events); - var count = 1; - one.listenToOnce(two, 'x y', function(n) { assert.ok(n === count++); }); - two.trigger('x', 1); - two.trigger('x', 1); - two.trigger('y', 2); - two.trigger('y', 2); - }); - -})(); diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/backbone/test/model.js b/ecomp-portal-FE/client/bower_components/lodash/vendor/backbone/test/model.js deleted file mode 100644 index b73a1c79..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/backbone/test/model.js +++ /dev/null @@ -1,1418 +0,0 @@ -(function() { - - var ProxyModel = Backbone.Model.extend(); - var Klass = Backbone.Collection.extend({ - url: function() { return '/collection'; } - }); - var doc, collection; - - QUnit.module('Backbone.Model', { - - beforeEach: function(assert) { - doc = new ProxyModel({ - id: '1-the-tempest', - title: 'The Tempest', - author: 'Bill Shakespeare', - length: 123 - }); - collection = new Klass(); - collection.add(doc); - } - - }); - - QUnit.test('initialize', function(assert) { - assert.expect(3); - var Model = Backbone.Model.extend({ - initialize: function() { - this.one = 1; - assert.equal(this.collection, collection); - } - }); - var model = new Model({}, {collection: collection}); - assert.equal(model.one, 1); - assert.equal(model.collection, collection); - }); - - QUnit.test('Object.prototype properties are overridden by attributes', function(assert) { - assert.expect(1); - var model = new Backbone.Model({hasOwnProperty: true}); - assert.equal(model.get('hasOwnProperty'), true); - }); - - QUnit.test('initialize with attributes and options', function(assert) { - assert.expect(1); - var Model = Backbone.Model.extend({ - initialize: function(attributes, options) { - this.one = options.one; - } - }); - var model = new Model({}, {one: 1}); - assert.equal(model.one, 1); - }); - - QUnit.test('initialize with parsed attributes', function(assert) { - assert.expect(1); - var Model = Backbone.Model.extend({ - parse: function(attrs) { - attrs.value += 1; - return attrs; - } - }); - var model = new Model({value: 1}, {parse: true}); - assert.equal(model.get('value'), 2); - }); - - QUnit.test('parse can return null', function(assert) { - assert.expect(1); - var Model = Backbone.Model.extend({ - parse: function(attrs) { - attrs.value += 1; - return null; - } - }); - var model = new Model({value: 1}, {parse: true}); - assert.equal(JSON.stringify(model.toJSON()), '{}'); - }); - - QUnit.test('url', function(assert) { - assert.expect(3); - doc.urlRoot = null; - assert.equal(doc.url(), '/collection/1-the-tempest'); - doc.collection.url = '/collection/'; - assert.equal(doc.url(), '/collection/1-the-tempest'); - doc.collection = null; - assert.raises(function() { doc.url(); }); - doc.collection = collection; - }); - - QUnit.test('url when using urlRoot, and uri encoding', function(assert) { - assert.expect(2); - var Model = Backbone.Model.extend({ - urlRoot: '/collection' - }); - var model = new Model(); - assert.equal(model.url(), '/collection'); - model.set({id: '+1+'}); - assert.equal(model.url(), '/collection/%2B1%2B'); - }); - - QUnit.test('url when using urlRoot as a function to determine urlRoot at runtime', function(assert) { - assert.expect(2); - var Model = Backbone.Model.extend({ - urlRoot: function() { - return '/nested/' + this.get('parentId') + '/collection'; - } - }); - - var model = new Model({parentId: 1}); - assert.equal(model.url(), '/nested/1/collection'); - model.set({id: 2}); - assert.equal(model.url(), '/nested/1/collection/2'); - }); - - QUnit.test('underscore methods', function(assert) { - assert.expect(5); - var model = new Backbone.Model({foo: 'a', bar: 'b', baz: 'c'}); - var model2 = model.clone(); - assert.deepEqual(model.keys(), ['foo', 'bar', 'baz']); - assert.deepEqual(model.values(), ['a', 'b', 'c']); - assert.deepEqual(model.invert(), {a: 'foo', b: 'bar', c: 'baz'}); - assert.deepEqual(model.pick('foo', 'baz'), {foo: 'a', baz: 'c'}); - assert.deepEqual(model.omit('foo', 'bar'), {baz: 'c'}); - }); - - QUnit.test('chain', function(assert) { - var model = new Backbone.Model({a: 0, b: 1, c: 2}); - assert.deepEqual(model.chain().pick('a', 'b', 'c').values().compact().value(), [1, 2]); - }); - - QUnit.test('clone', function(assert) { - assert.expect(10); - var a = new Backbone.Model({foo: 1, bar: 2, baz: 3}); - var b = a.clone(); - assert.equal(a.get('foo'), 1); - assert.equal(a.get('bar'), 2); - assert.equal(a.get('baz'), 3); - assert.equal(b.get('foo'), a.get('foo'), 'Foo should be the same on the clone.'); - assert.equal(b.get('bar'), a.get('bar'), 'Bar should be the same on the clone.'); - assert.equal(b.get('baz'), a.get('baz'), 'Baz should be the same on the clone.'); - a.set({foo: 100}); - assert.equal(a.get('foo'), 100); - assert.equal(b.get('foo'), 1, 'Changing a parent attribute does not change the clone.'); - - var foo = new Backbone.Model({p: 1}); - var bar = new Backbone.Model({p: 2}); - bar.set(foo.clone().attributes, {unset: true}); - assert.equal(foo.get('p'), 1); - assert.equal(bar.get('p'), undefined); - }); - - QUnit.test('isNew', function(assert) { - assert.expect(6); - var a = new Backbone.Model({foo: 1, bar: 2, baz: 3}); - assert.ok(a.isNew(), 'it should be new'); - a = new Backbone.Model({foo: 1, bar: 2, baz: 3, id: -5}); - assert.ok(!a.isNew(), 'any defined ID is legal, negative or positive'); - a = new Backbone.Model({foo: 1, bar: 2, baz: 3, id: 0}); - assert.ok(!a.isNew(), 'any defined ID is legal, including zero'); - assert.ok(new Backbone.Model().isNew(), 'is true when there is no id'); - assert.ok(!new Backbone.Model({id: 2}).isNew(), 'is false for a positive integer'); - assert.ok(!new Backbone.Model({id: -5}).isNew(), 'is false for a negative integer'); - }); - - QUnit.test('get', function(assert) { - assert.expect(2); - assert.equal(doc.get('title'), 'The Tempest'); - assert.equal(doc.get('author'), 'Bill Shakespeare'); - }); - - QUnit.test('escape', function(assert) { - assert.expect(5); - assert.equal(doc.escape('title'), 'The Tempest'); - doc.set({audience: 'Bill & Bob'}); - assert.equal(doc.escape('audience'), 'Bill & Bob'); - doc.set({audience: 'Tim > Joan'}); - assert.equal(doc.escape('audience'), 'Tim > Joan'); - doc.set({audience: 10101}); - assert.equal(doc.escape('audience'), '10101'); - doc.unset('audience'); - assert.equal(doc.escape('audience'), ''); - }); - - QUnit.test('has', function(assert) { - assert.expect(10); - var model = new Backbone.Model(); - - assert.strictEqual(model.has('name'), false); - - model.set({ - '0': 0, - '1': 1, - 'true': true, - 'false': false, - 'empty': '', - 'name': 'name', - 'null': null, - 'undefined': undefined - }); - - assert.strictEqual(model.has('0'), true); - assert.strictEqual(model.has('1'), true); - assert.strictEqual(model.has('true'), true); - assert.strictEqual(model.has('false'), true); - assert.strictEqual(model.has('empty'), true); - assert.strictEqual(model.has('name'), true); - - model.unset('name'); - - assert.strictEqual(model.has('name'), false); - assert.strictEqual(model.has('null'), false); - assert.strictEqual(model.has('undefined'), false); - }); - - QUnit.test('matches', function(assert) { - assert.expect(4); - var model = new Backbone.Model(); - - assert.strictEqual(model.matches({name: 'Jonas', cool: true}), false); - - model.set({name: 'Jonas', cool: true}); - - assert.strictEqual(model.matches({name: 'Jonas'}), true); - assert.strictEqual(model.matches({name: 'Jonas', cool: true}), true); - assert.strictEqual(model.matches({name: 'Jonas', cool: false}), false); - }); - - QUnit.test('matches with predicate', function(assert) { - var model = new Backbone.Model({a: 0}); - - assert.strictEqual(model.matches(function(attr) { - return attr.a > 1 && attr.b != null; - }), false); - - model.set({a: 3, b: true}); - - assert.strictEqual(model.matches(function(attr) { - return attr.a > 1 && attr.b != null; - }), true); - }); - - QUnit.test('set and unset', function(assert) { - assert.expect(8); - var a = new Backbone.Model({id: 'id', foo: 1, bar: 2, baz: 3}); - var changeCount = 0; - a.on('change:foo', function() { changeCount += 1; }); - a.set({foo: 2}); - assert.equal(a.get('foo'), 2, 'Foo should have changed.'); - assert.equal(changeCount, 1, 'Change count should have incremented.'); - // set with value that is not new shouldn't fire change event - a.set({foo: 2}); - assert.equal(a.get('foo'), 2, 'Foo should NOT have changed, still 2'); - assert.equal(changeCount, 1, 'Change count should NOT have incremented.'); - - a.validate = function(attrs) { - assert.equal(attrs.foo, void 0, 'validate:true passed while unsetting'); - }; - a.unset('foo', {validate: true}); - assert.equal(a.get('foo'), void 0, 'Foo should have changed'); - delete a.validate; - assert.equal(changeCount, 2, 'Change count should have incremented for unset.'); - - a.unset('id'); - assert.equal(a.id, undefined, 'Unsetting the id should remove the id property.'); - }); - - QUnit.test('#2030 - set with failed validate, followed by another set triggers change', function(assert) { - var attr = 0, main = 0, error = 0; - var Model = Backbone.Model.extend({ - validate: function(attrs) { - if (attrs.x > 1) { - error++; - return 'this is an error'; - } - } - }); - var model = new Model({x: 0}); - model.on('change:x', function() { attr++; }); - model.on('change', function() { main++; }); - model.set({x: 2}, {validate: true}); - model.set({x: 1}, {validate: true}); - assert.deepEqual([attr, main, error], [1, 1, 1]); - }); - - QUnit.test('set triggers changes in the correct order', function(assert) { - var value = null; - var model = new Backbone.Model; - model.on('last', function(){ value = 'last'; }); - model.on('first', function(){ value = 'first'; }); - model.trigger('first'); - model.trigger('last'); - assert.equal(value, 'last'); - }); - - QUnit.test('set falsy values in the correct order', function(assert) { - assert.expect(2); - var model = new Backbone.Model({result: 'result'}); - model.on('change', function() { - assert.equal(model.changed.result, void 0); - assert.equal(model.previous('result'), false); - }); - model.set({result: void 0}, {silent: true}); - model.set({result: null}, {silent: true}); - model.set({result: false}, {silent: true}); - model.set({result: void 0}); - }); - - QUnit.test('nested set triggers with the correct options', function(assert) { - var model = new Backbone.Model(); - var o1 = {}; - var o2 = {}; - var o3 = {}; - model.on('change', function(__, options) { - switch (model.get('a')) { - case 1: - assert.equal(options, o1); - return model.set('a', 2, o2); - case 2: - assert.equal(options, o2); - return model.set('a', 3, o3); - case 3: - assert.equal(options, o3); - } - }); - model.set('a', 1, o1); - }); - - QUnit.test('multiple unsets', function(assert) { - assert.expect(1); - var i = 0; - var counter = function(){ i++; }; - var model = new Backbone.Model({a: 1}); - model.on('change:a', counter); - model.set({a: 2}); - model.unset('a'); - model.unset('a'); - assert.equal(i, 2, 'Unset does not fire an event for missing attributes.'); - }); - - QUnit.test('unset and changedAttributes', function(assert) { - assert.expect(1); - var model = new Backbone.Model({a: 1}); - model.on('change', function() { - assert.ok('a' in model.changedAttributes(), 'changedAttributes should contain unset properties'); - }); - model.unset('a'); - }); - - QUnit.test('using a non-default id attribute.', function(assert) { - assert.expect(5); - var MongoModel = Backbone.Model.extend({idAttribute: '_id'}); - var model = new MongoModel({id: 'eye-dee', _id: 25, title: 'Model'}); - assert.equal(model.get('id'), 'eye-dee'); - assert.equal(model.id, 25); - assert.equal(model.isNew(), false); - model.unset('_id'); - assert.equal(model.id, undefined); - assert.equal(model.isNew(), true); - }); - - QUnit.test('setting an alternative cid prefix', function(assert) { - assert.expect(4); - var Model = Backbone.Model.extend({ - cidPrefix: 'm' - }); - var model = new Model(); - - assert.equal(model.cid.charAt(0), 'm'); - - model = new Backbone.Model(); - assert.equal(model.cid.charAt(0), 'c'); - - var Collection = Backbone.Collection.extend({ - model: Model - }); - var col = new Collection([{id: 'c5'}, {id: 'c6'}, {id: 'c7'}]); - - assert.equal(col.get('c6').cid.charAt(0), 'm'); - col.set([{id: 'c6', value: 'test'}], { - merge: true, - add: true, - remove: false - }); - assert.ok(col.get('c6').has('value')); - }); - - QUnit.test('set an empty string', function(assert) { - assert.expect(1); - var model = new Backbone.Model({name: 'Model'}); - model.set({name: ''}); - assert.equal(model.get('name'), ''); - }); - - QUnit.test('setting an object', function(assert) { - assert.expect(1); - var model = new Backbone.Model({ - custom: {foo: 1} - }); - model.on('change', function() { - assert.ok(1); - }); - model.set({ - custom: {foo: 1} // no change should be fired - }); - model.set({ - custom: {foo: 2} // change event should be fired - }); - }); - - QUnit.test('clear', function(assert) { - assert.expect(3); - var changed; - var model = new Backbone.Model({id: 1, name: 'Model'}); - model.on('change:name', function(){ changed = true; }); - model.on('change', function() { - var changedAttrs = model.changedAttributes(); - assert.ok('name' in changedAttrs); - }); - model.clear(); - assert.equal(changed, true); - assert.equal(model.get('name'), undefined); - }); - - QUnit.test('defaults', function(assert) { - assert.expect(9); - var Defaulted = Backbone.Model.extend({ - defaults: { - one: 1, - two: 2 - } - }); - var model = new Defaulted({two: undefined}); - assert.equal(model.get('one'), 1); - assert.equal(model.get('two'), 2); - model = new Defaulted({two: 3}); - assert.equal(model.get('one'), 1); - assert.equal(model.get('two'), 3); - Defaulted = Backbone.Model.extend({ - defaults: function() { - return { - one: 3, - two: 4 - }; - } - }); - model = new Defaulted({two: undefined}); - assert.equal(model.get('one'), 3); - assert.equal(model.get('two'), 4); - Defaulted = Backbone.Model.extend({ - defaults: {hasOwnProperty: true} - }); - model = new Defaulted(); - assert.equal(model.get('hasOwnProperty'), true); - model = new Defaulted({hasOwnProperty: undefined}); - assert.equal(model.get('hasOwnProperty'), true); - model = new Defaulted({hasOwnProperty: false}); - assert.equal(model.get('hasOwnProperty'), false); - }); - - QUnit.test('change, hasChanged, changedAttributes, previous, previousAttributes', function(assert) { - assert.expect(9); - var model = new Backbone.Model({name: 'Tim', age: 10}); - assert.deepEqual(model.changedAttributes(), false); - model.on('change', function() { - assert.ok(model.hasChanged('name'), 'name changed'); - assert.ok(!model.hasChanged('age'), 'age did not'); - assert.ok(_.isEqual(model.changedAttributes(), {name: 'Rob'}), 'changedAttributes returns the changed attrs'); - assert.equal(model.previous('name'), 'Tim'); - assert.ok(_.isEqual(model.previousAttributes(), {name: 'Tim', age: 10}), 'previousAttributes is correct'); - }); - assert.equal(model.hasChanged(), false); - assert.equal(model.hasChanged(undefined), false); - model.set({name: 'Rob'}); - assert.equal(model.get('name'), 'Rob'); - }); - - QUnit.test('changedAttributes', function(assert) { - assert.expect(3); - var model = new Backbone.Model({a: 'a', b: 'b'}); - assert.deepEqual(model.changedAttributes(), false); - assert.equal(model.changedAttributes({a: 'a'}), false); - assert.equal(model.changedAttributes({a: 'b'}).a, 'b'); - }); - - QUnit.test('change with options', function(assert) { - assert.expect(2); - var value; - var model = new Backbone.Model({name: 'Rob'}); - model.on('change', function(m, options) { - value = options.prefix + m.get('name'); - }); - model.set({name: 'Bob'}, {prefix: 'Mr. '}); - assert.equal(value, 'Mr. Bob'); - model.set({name: 'Sue'}, {prefix: 'Ms. '}); - assert.equal(value, 'Ms. Sue'); - }); - - QUnit.test('change after initialize', function(assert) { - assert.expect(1); - var changed = 0; - var attrs = {id: 1, label: 'c'}; - var obj = new Backbone.Model(attrs); - obj.on('change', function() { changed += 1; }); - obj.set(attrs); - assert.equal(changed, 0); - }); - - QUnit.test('save within change event', function(assert) { - assert.expect(1); - var env = this; - var model = new Backbone.Model({firstName: 'Taylor', lastName: 'Swift'}); - model.url = '/test'; - model.on('change', function() { - model.save(); - assert.ok(_.isEqual(env.syncArgs.model, model)); - }); - model.set({lastName: 'Hicks'}); - }); - - QUnit.test('validate after save', function(assert) { - assert.expect(2); - var lastError, model = new Backbone.Model(); - model.validate = function(attrs) { - if (attrs.admin) return "Can't change admin status."; - }; - model.sync = function(method, m, options) { - options.success.call(this, {admin: true}); - }; - model.on('invalid', function(m, error) { - lastError = error; - }); - model.save(null); - - assert.equal(lastError, "Can't change admin status."); - assert.equal(model.validationError, "Can't change admin status."); - }); - - QUnit.test('save', function(assert) { - assert.expect(2); - doc.save({title: 'Henry V'}); - assert.equal(this.syncArgs.method, 'update'); - assert.ok(_.isEqual(this.syncArgs.model, doc)); - }); - - QUnit.test('save, fetch, destroy triggers error event when an error occurs', function(assert) { - assert.expect(3); - var model = new Backbone.Model(); - model.on('error', function() { - assert.ok(true); - }); - model.sync = function(method, m, options) { - options.error(); - }; - model.save({data: 2, id: 1}); - model.fetch(); - model.destroy(); - }); - - QUnit.test('#3283 - save, fetch, destroy calls success with context', function(assert) { - assert.expect(3); - var model = new Backbone.Model(); - var obj = {}; - var options = { - context: obj, - success: function() { - assert.equal(this, obj); - } - }; - model.sync = function(method, m, opts) { - opts.success.call(opts.context); - }; - model.save({data: 2, id: 1}, options); - model.fetch(options); - model.destroy(options); - }); - - QUnit.test('#3283 - save, fetch, destroy calls error with context', function(assert) { - assert.expect(3); - var model = new Backbone.Model(); - var obj = {}; - var options = { - context: obj, - error: function() { - assert.equal(this, obj); - } - }; - model.sync = function(method, m, opts) { - opts.error.call(opts.context); - }; - model.save({data: 2, id: 1}, options); - model.fetch(options); - model.destroy(options); - }); - - QUnit.test('#3470 - save and fetch with parse false', function(assert) { - assert.expect(2); - var i = 0; - var model = new Backbone.Model(); - model.parse = function() { - assert.ok(false); - }; - model.sync = function(method, m, options) { - options.success({i: ++i}); - }; - model.fetch({parse: false}); - assert.equal(model.get('i'), i); - model.save(null, {parse: false}); - assert.equal(model.get('i'), i); - }); - - QUnit.test('save with PATCH', function(assert) { - doc.clear().set({id: 1, a: 1, b: 2, c: 3, d: 4}); - doc.save(); - assert.equal(this.syncArgs.method, 'update'); - assert.equal(this.syncArgs.options.attrs, undefined); - - doc.save({b: 2, d: 4}, {patch: true}); - assert.equal(this.syncArgs.method, 'patch'); - assert.equal(_.size(this.syncArgs.options.attrs), 2); - assert.equal(this.syncArgs.options.attrs.d, 4); - assert.equal(this.syncArgs.options.attrs.a, undefined); - assert.equal(this.ajaxSettings.data, '{"b":2,"d":4}'); - }); - - QUnit.test('save with PATCH and different attrs', function(assert) { - doc.clear().save({b: 2, d: 4}, {patch: true, attrs: {B: 1, D: 3}}); - assert.equal(this.syncArgs.options.attrs.D, 3); - assert.equal(this.syncArgs.options.attrs.d, undefined); - assert.equal(this.ajaxSettings.data, '{"B":1,"D":3}'); - assert.deepEqual(doc.attributes, {b: 2, d: 4}); - }); - - QUnit.test('save in positional style', function(assert) { - assert.expect(1); - var model = new Backbone.Model(); - model.sync = function(method, m, options) { - options.success(); - }; - model.save('title', 'Twelfth Night'); - assert.equal(model.get('title'), 'Twelfth Night'); - }); - - QUnit.test('save with non-object success response', function(assert) { - assert.expect(2); - var model = new Backbone.Model(); - model.sync = function(method, m, options) { - options.success('', options); - options.success(null, options); - }; - model.save({testing: 'empty'}, { - success: function(m) { - assert.deepEqual(m.attributes, {testing: 'empty'}); - } - }); - }); - - QUnit.test('save with wait and supplied id', function(assert) { - var Model = Backbone.Model.extend({ - urlRoot: '/collection' - }); - var model = new Model(); - model.save({id: 42}, {wait: true}); - assert.equal(this.ajaxSettings.url, '/collection/42'); - }); - - QUnit.test('save will pass extra options to success callback', function(assert) { - assert.expect(1); - var SpecialSyncModel = Backbone.Model.extend({ - sync: function(method, m, options) { - _.extend(options, {specialSync: true}); - return Backbone.Model.prototype.sync.call(this, method, m, options); - }, - urlRoot: '/test' - }); - - var model = new SpecialSyncModel(); - - var onSuccess = function(m, response, options) { - assert.ok(options.specialSync, 'Options were passed correctly to callback'); - }; - - model.save(null, {success: onSuccess}); - this.ajaxSettings.success(); - }); - - QUnit.test('fetch', function(assert) { - assert.expect(2); - doc.fetch(); - assert.equal(this.syncArgs.method, 'read'); - assert.ok(_.isEqual(this.syncArgs.model, doc)); - }); - - QUnit.test('fetch will pass extra options to success callback', function(assert) { - assert.expect(1); - var SpecialSyncModel = Backbone.Model.extend({ - sync: function(method, m, options) { - _.extend(options, {specialSync: true}); - return Backbone.Model.prototype.sync.call(this, method, m, options); - }, - urlRoot: '/test' - }); - - var model = new SpecialSyncModel(); - - var onSuccess = function(m, response, options) { - assert.ok(options.specialSync, 'Options were passed correctly to callback'); - }; - - model.fetch({success: onSuccess}); - this.ajaxSettings.success(); - }); - - QUnit.test('destroy', function(assert) { - assert.expect(3); - doc.destroy(); - assert.equal(this.syncArgs.method, 'delete'); - assert.ok(_.isEqual(this.syncArgs.model, doc)); - - var newModel = new Backbone.Model; - assert.equal(newModel.destroy(), false); - }); - - QUnit.test('destroy will pass extra options to success callback', function(assert) { - assert.expect(1); - var SpecialSyncModel = Backbone.Model.extend({ - sync: function(method, m, options) { - _.extend(options, {specialSync: true}); - return Backbone.Model.prototype.sync.call(this, method, m, options); - }, - urlRoot: '/test' - }); - - var model = new SpecialSyncModel({id: 'id'}); - - var onSuccess = function(m, response, options) { - assert.ok(options.specialSync, 'Options were passed correctly to callback'); - }; - - model.destroy({success: onSuccess}); - this.ajaxSettings.success(); - }); - - QUnit.test('non-persisted destroy', function(assert) { - assert.expect(1); - var a = new Backbone.Model({foo: 1, bar: 2, baz: 3}); - a.sync = function() { throw 'should not be called'; }; - a.destroy(); - assert.ok(true, 'non-persisted model should not call sync'); - }); - - QUnit.test('validate', function(assert) { - var lastError; - var model = new Backbone.Model(); - model.validate = function(attrs) { - if (attrs.admin !== this.get('admin')) return "Can't change admin status."; - }; - model.on('invalid', function(m, error) { - lastError = error; - }); - var result = model.set({a: 100}); - assert.equal(result, model); - assert.equal(model.get('a'), 100); - assert.equal(lastError, undefined); - result = model.set({admin: true}); - assert.equal(model.get('admin'), true); - result = model.set({a: 200, admin: false}, {validate: true}); - assert.equal(lastError, "Can't change admin status."); - assert.equal(result, false); - assert.equal(model.get('a'), 100); - }); - - QUnit.test('validate on unset and clear', function(assert) { - assert.expect(6); - var error; - var model = new Backbone.Model({name: 'One'}); - model.validate = function(attrs) { - if (!attrs.name) { - error = true; - return 'No thanks.'; - } - }; - model.set({name: 'Two'}); - assert.equal(model.get('name'), 'Two'); - assert.equal(error, undefined); - model.unset('name', {validate: true}); - assert.equal(error, true); - assert.equal(model.get('name'), 'Two'); - model.clear({validate: true}); - assert.equal(model.get('name'), 'Two'); - delete model.validate; - model.clear(); - assert.equal(model.get('name'), undefined); - }); - - QUnit.test('validate with error callback', function(assert) { - assert.expect(8); - var lastError, boundError; - var model = new Backbone.Model(); - model.validate = function(attrs) { - if (attrs.admin) return "Can't change admin status."; - }; - model.on('invalid', function(m, error) { - boundError = true; - }); - var result = model.set({a: 100}, {validate: true}); - assert.equal(result, model); - assert.equal(model.get('a'), 100); - assert.equal(model.validationError, null); - assert.equal(boundError, undefined); - result = model.set({a: 200, admin: true}, {validate: true}); - assert.equal(result, false); - assert.equal(model.get('a'), 100); - assert.equal(model.validationError, "Can't change admin status."); - assert.equal(boundError, true); - }); - - QUnit.test('defaults always extend attrs (#459)', function(assert) { - assert.expect(2); - var Defaulted = Backbone.Model.extend({ - defaults: {one: 1}, - initialize: function(attrs, opts) { - assert.equal(this.attributes.one, 1); - } - }); - var providedattrs = new Defaulted({}); - var emptyattrs = new Defaulted(); - }); - - QUnit.test('Inherit class properties', function(assert) { - assert.expect(6); - var Parent = Backbone.Model.extend({ - instancePropSame: function() {}, - instancePropDiff: function() {} - }, { - classProp: function() {} - }); - var Child = Parent.extend({ - instancePropDiff: function() {} - }); - - var adult = new Parent; - var kid = new Child; - - assert.equal(Child.classProp, Parent.classProp); - assert.notEqual(Child.classProp, undefined); - - assert.equal(kid.instancePropSame, adult.instancePropSame); - assert.notEqual(kid.instancePropSame, undefined); - - assert.notEqual(Child.prototype.instancePropDiff, Parent.prototype.instancePropDiff); - assert.notEqual(Child.prototype.instancePropDiff, undefined); - }); - - QUnit.test("Nested change events don't clobber previous attributes", function(assert) { - assert.expect(4); - new Backbone.Model() - .on('change:state', function(m, newState) { - assert.equal(m.previous('state'), undefined); - assert.equal(newState, 'hello'); - // Fire a nested change event. - m.set({other: 'whatever'}); - }) - .on('change:state', function(m, newState) { - assert.equal(m.previous('state'), undefined); - assert.equal(newState, 'hello'); - }) - .set({state: 'hello'}); - }); - - QUnit.test('hasChanged/set should use same comparison', function(assert) { - assert.expect(2); - var changed = 0, model = new Backbone.Model({a: null}); - model.on('change', function() { - assert.ok(this.hasChanged('a')); - }) - .on('change:a', function() { - changed++; - }) - .set({a: undefined}); - assert.equal(changed, 1); - }); - - QUnit.test('#582, #425, change:attribute callbacks should fire after all changes have occurred', function(assert) { - assert.expect(9); - var model = new Backbone.Model; - - var assertion = function() { - assert.equal(model.get('a'), 'a'); - assert.equal(model.get('b'), 'b'); - assert.equal(model.get('c'), 'c'); - }; - - model.on('change:a', assertion); - model.on('change:b', assertion); - model.on('change:c', assertion); - - model.set({a: 'a', b: 'b', c: 'c'}); - }); - - QUnit.test('#871, set with attributes property', function(assert) { - assert.expect(1); - var model = new Backbone.Model(); - model.set({attributes: true}); - assert.ok(model.has('attributes')); - }); - - QUnit.test('set value regardless of equality/change', function(assert) { - assert.expect(1); - var model = new Backbone.Model({x: []}); - var a = []; - model.set({x: a}); - assert.ok(model.get('x') === a); - }); - - QUnit.test('set same value does not trigger change', function(assert) { - assert.expect(0); - var model = new Backbone.Model({x: 1}); - model.on('change change:x', function() { assert.ok(false); }); - model.set({x: 1}); - model.set({x: 1}); - }); - - QUnit.test('unset does not fire a change for undefined attributes', function(assert) { - assert.expect(0); - var model = new Backbone.Model({x: undefined}); - model.on('change:x', function(){ assert.ok(false); }); - model.unset('x'); - }); - - QUnit.test('set: undefined values', function(assert) { - assert.expect(1); - var model = new Backbone.Model({x: undefined}); - assert.ok('x' in model.attributes); - }); - - QUnit.test('hasChanged works outside of change events, and true within', function(assert) { - assert.expect(6); - var model = new Backbone.Model({x: 1}); - model.on('change:x', function() { - assert.ok(model.hasChanged('x')); - assert.equal(model.get('x'), 1); - }); - model.set({x: 2}, {silent: true}); - assert.ok(model.hasChanged()); - assert.equal(model.hasChanged('x'), true); - model.set({x: 1}); - assert.ok(model.hasChanged()); - assert.equal(model.hasChanged('x'), true); - }); - - QUnit.test('hasChanged gets cleared on the following set', function(assert) { - assert.expect(4); - var model = new Backbone.Model; - model.set({x: 1}); - assert.ok(model.hasChanged()); - model.set({x: 1}); - assert.ok(!model.hasChanged()); - model.set({x: 2}); - assert.ok(model.hasChanged()); - model.set({}); - assert.ok(!model.hasChanged()); - }); - - QUnit.test('save with `wait` succeeds without `validate`', function(assert) { - assert.expect(1); - var model = new Backbone.Model(); - model.url = '/test'; - model.save({x: 1}, {wait: true}); - assert.ok(this.syncArgs.model === model); - }); - - QUnit.test("save without `wait` doesn't set invalid attributes", function(assert) { - var model = new Backbone.Model(); - model.validate = function() { return 1; }; - model.save({a: 1}); - assert.equal(model.get('a'), void 0); - }); - - QUnit.test("save doesn't validate twice", function(assert) { - var model = new Backbone.Model(); - var times = 0; - model.sync = function() {}; - model.validate = function() { ++times; }; - model.save({}); - assert.equal(times, 1); - }); - - QUnit.test('`hasChanged` for falsey keys', function(assert) { - assert.expect(2); - var model = new Backbone.Model(); - model.set({x: true}, {silent: true}); - assert.ok(!model.hasChanged(0)); - assert.ok(!model.hasChanged('')); - }); - - QUnit.test('`previous` for falsey keys', function(assert) { - assert.expect(2); - var model = new Backbone.Model({'0': true, '': true}); - model.set({'0': false, '': false}, {silent: true}); - assert.equal(model.previous(0), true); - assert.equal(model.previous(''), true); - }); - - QUnit.test('`save` with `wait` sends correct attributes', function(assert) { - assert.expect(5); - var changed = 0; - var model = new Backbone.Model({x: 1, y: 2}); - model.url = '/test'; - model.on('change:x', function() { changed++; }); - model.save({x: 3}, {wait: true}); - assert.deepEqual(JSON.parse(this.ajaxSettings.data), {x: 3, y: 2}); - assert.equal(model.get('x'), 1); - assert.equal(changed, 0); - this.syncArgs.options.success({}); - assert.equal(model.get('x'), 3); - assert.equal(changed, 1); - }); - - QUnit.test("a failed `save` with `wait` doesn't leave attributes behind", function(assert) { - assert.expect(1); - var model = new Backbone.Model; - model.url = '/test'; - model.save({x: 1}, {wait: true}); - assert.equal(model.get('x'), void 0); - }); - - QUnit.test('#1030 - `save` with `wait` results in correct attributes if success is called during sync', function(assert) { - assert.expect(2); - var model = new Backbone.Model({x: 1, y: 2}); - model.sync = function(method, m, options) { - options.success(); - }; - model.on('change:x', function() { assert.ok(true); }); - model.save({x: 3}, {wait: true}); - assert.equal(model.get('x'), 3); - }); - - QUnit.test('save with wait validates attributes', function(assert) { - var model = new Backbone.Model(); - model.url = '/test'; - model.validate = function() { assert.ok(true); }; - model.save({x: 1}, {wait: true}); - }); - - QUnit.test('save turns on parse flag', function(assert) { - var Model = Backbone.Model.extend({ - sync: function(method, m, options) { assert.ok(options.parse); } - }); - new Model().save(); - }); - - QUnit.test("nested `set` during `'change:attr'`", function(assert) { - assert.expect(2); - var events = []; - var model = new Backbone.Model(); - model.on('all', function(event) { events.push(event); }); - model.on('change', function() { - model.set({z: true}, {silent: true}); - }); - model.on('change:x', function() { - model.set({y: true}); - }); - model.set({x: true}); - assert.deepEqual(events, ['change:y', 'change:x', 'change']); - events = []; - model.set({z: true}); - assert.deepEqual(events, []); - }); - - QUnit.test('nested `change` only fires once', function(assert) { - assert.expect(1); - var model = new Backbone.Model(); - model.on('change', function() { - assert.ok(true); - model.set({x: true}); - }); - model.set({x: true}); - }); - - QUnit.test("nested `set` during `'change'`", function(assert) { - assert.expect(6); - var count = 0; - var model = new Backbone.Model(); - model.on('change', function() { - switch (count++) { - case 0: - assert.deepEqual(this.changedAttributes(), {x: true}); - assert.equal(model.previous('x'), undefined); - model.set({y: true}); - break; - case 1: - assert.deepEqual(this.changedAttributes(), {x: true, y: true}); - assert.equal(model.previous('x'), undefined); - model.set({z: true}); - break; - case 2: - assert.deepEqual(this.changedAttributes(), {x: true, y: true, z: true}); - assert.equal(model.previous('y'), undefined); - break; - default: - assert.ok(false); - } - }); - model.set({x: true}); - }); - - QUnit.test('nested `change` with silent', function(assert) { - assert.expect(3); - var count = 0; - var model = new Backbone.Model(); - model.on('change:y', function() { assert.ok(false); }); - model.on('change', function() { - switch (count++) { - case 0: - assert.deepEqual(this.changedAttributes(), {x: true}); - model.set({y: true}, {silent: true}); - model.set({z: true}); - break; - case 1: - assert.deepEqual(this.changedAttributes(), {x: true, y: true, z: true}); - break; - case 2: - assert.deepEqual(this.changedAttributes(), {z: false}); - break; - default: - assert.ok(false); - } - }); - model.set({x: true}); - model.set({z: false}); - }); - - QUnit.test('nested `change:attr` with silent', function(assert) { - assert.expect(0); - var model = new Backbone.Model(); - model.on('change:y', function(){ assert.ok(false); }); - model.on('change', function() { - model.set({y: true}, {silent: true}); - model.set({z: true}); - }); - model.set({x: true}); - }); - - QUnit.test('multiple nested changes with silent', function(assert) { - assert.expect(1); - var model = new Backbone.Model(); - model.on('change:x', function() { - model.set({y: 1}, {silent: true}); - model.set({y: 2}); - }); - model.on('change:y', function(m, val) { - assert.equal(val, 2); - }); - model.set({x: true}); - }); - - QUnit.test('multiple nested changes with silent', function(assert) { - assert.expect(1); - var changes = []; - var model = new Backbone.Model(); - model.on('change:b', function(m, val) { changes.push(val); }); - model.on('change', function() { - model.set({b: 1}); - }); - model.set({b: 0}); - assert.deepEqual(changes, [0, 1]); - }); - - QUnit.test('basic silent change semantics', function(assert) { - assert.expect(1); - var model = new Backbone.Model; - model.set({x: 1}); - model.on('change', function(){ assert.ok(true); }); - model.set({x: 2}, {silent: true}); - model.set({x: 1}); - }); - - QUnit.test('nested set multiple times', function(assert) { - assert.expect(1); - var model = new Backbone.Model(); - model.on('change:b', function() { - assert.ok(true); - }); - model.on('change:a', function() { - model.set({b: true}); - model.set({b: true}); - }); - model.set({a: true}); - }); - - QUnit.test('#1122 - clear does not alter options.', function(assert) { - assert.expect(1); - var model = new Backbone.Model(); - var options = {}; - model.clear(options); - assert.ok(!options.unset); - }); - - QUnit.test('#1122 - unset does not alter options.', function(assert) { - assert.expect(1); - var model = new Backbone.Model(); - var options = {}; - model.unset('x', options); - assert.ok(!options.unset); - }); - - QUnit.test('#1355 - `options` is passed to success callbacks', function(assert) { - assert.expect(3); - var model = new Backbone.Model(); - var opts = { - success: function( m, resp, options ) { - assert.ok(options); - } - }; - model.sync = function(method, m, options) { - options.success(); - }; - model.save({id: 1}, opts); - model.fetch(opts); - model.destroy(opts); - }); - - QUnit.test("#1412 - Trigger 'sync' event.", function(assert) { - assert.expect(3); - var model = new Backbone.Model({id: 1}); - model.sync = function(method, m, options) { options.success(); }; - model.on('sync', function(){ assert.ok(true); }); - model.fetch(); - model.save(); - model.destroy(); - }); - - QUnit.test('#1365 - Destroy: New models execute success callback.', function(assert) { - var done = assert.async(); - assert.expect(2); - new Backbone.Model() - .on('sync', function() { assert.ok(false); }) - .on('destroy', function(){ assert.ok(true); }) - .destroy({success: function(){ - assert.ok(true); - done(); - }}); - }); - - QUnit.test('#1433 - Save: An invalid model cannot be persisted.', function(assert) { - assert.expect(1); - var model = new Backbone.Model; - model.validate = function(){ return 'invalid'; }; - model.sync = function(){ assert.ok(false); }; - assert.strictEqual(model.save(), false); - }); - - QUnit.test("#1377 - Save without attrs triggers 'error'.", function(assert) { - assert.expect(1); - var Model = Backbone.Model.extend({ - url: '/test/', - sync: function(method, m, options){ options.success(); }, - validate: function(){ return 'invalid'; } - }); - var model = new Model({id: 1}); - model.on('invalid', function(){ assert.ok(true); }); - model.save(); - }); - - QUnit.test('#1545 - `undefined` can be passed to a model constructor without coersion', function(assert) { - var Model = Backbone.Model.extend({ - defaults: {one: 1}, - initialize: function(attrs, opts) { - assert.equal(attrs, undefined); - } - }); - var emptyattrs = new Model(); - var undefinedattrs = new Model(undefined); - }); - - QUnit.test('#1478 - Model `save` does not trigger change on unchanged attributes', function(assert) { - var done = assert.async(); - assert.expect(0); - var Model = Backbone.Model.extend({ - sync: function(method, m, options) { - setTimeout(function(){ - options.success(); - done(); - }, 0); - } - }); - new Model({x: true}) - .on('change:x', function(){ assert.ok(false); }) - .save(null, {wait: true}); - }); - - QUnit.test('#1664 - Changing from one value, silently to another, back to original triggers a change.', function(assert) { - assert.expect(1); - var model = new Backbone.Model({x: 1}); - model.on('change:x', function() { assert.ok(true); }); - model.set({x: 2}, {silent: true}); - model.set({x: 3}, {silent: true}); - model.set({x: 1}); - }); - - QUnit.test('#1664 - multiple silent changes nested inside a change event', function(assert) { - assert.expect(2); - var changes = []; - var model = new Backbone.Model(); - model.on('change', function() { - model.set({a: 'c'}, {silent: true}); - model.set({b: 2}, {silent: true}); - model.unset('c', {silent: true}); - }); - model.on('change:a change:b change:c', function(m, val) { changes.push(val); }); - model.set({a: 'a', b: 1, c: 'item'}); - assert.deepEqual(changes, ['a', 1, 'item']); - assert.deepEqual(model.attributes, {a: 'c', b: 2}); - }); - - QUnit.test('#1791 - `attributes` is available for `parse`', function(assert) { - var Model = Backbone.Model.extend({ - parse: function() { this.has('a'); } // shouldn't throw an error - }); - var model = new Model(null, {parse: true}); - assert.expect(0); - }); - - QUnit.test('silent changes in last `change` event back to original triggers change', function(assert) { - assert.expect(2); - var changes = []; - var model = new Backbone.Model(); - model.on('change:a change:b change:c', function(m, val) { changes.push(val); }); - model.on('change', function() { - model.set({a: 'c'}, {silent: true}); - }); - model.set({a: 'a'}); - assert.deepEqual(changes, ['a']); - model.set({a: 'a'}); - assert.deepEqual(changes, ['a', 'a']); - }); - - QUnit.test('#1943 change calculations should use _.isEqual', function(assert) { - var model = new Backbone.Model({a: {key: 'value'}}); - model.set('a', {key: 'value'}, {silent: true}); - assert.equal(model.changedAttributes(), false); - }); - - QUnit.test('#1964 - final `change` event is always fired, regardless of interim changes', function(assert) { - assert.expect(1); - var model = new Backbone.Model(); - model.on('change:property', function() { - model.set('property', 'bar'); - }); - model.on('change', function() { - assert.ok(true); - }); - model.set('property', 'foo'); - }); - - QUnit.test('isValid', function(assert) { - var model = new Backbone.Model({valid: true}); - model.validate = function(attrs) { - if (!attrs.valid) return 'invalid'; - }; - assert.equal(model.isValid(), true); - assert.equal(model.set({valid: false}, {validate: true}), false); - assert.equal(model.isValid(), true); - model.set({valid: false}); - assert.equal(model.isValid(), false); - assert.ok(!model.set('valid', false, {validate: true})); - }); - - QUnit.test('#1179 - isValid returns true in the absence of validate.', function(assert) { - assert.expect(1); - var model = new Backbone.Model(); - model.validate = null; - assert.ok(model.isValid()); - }); - - QUnit.test('#1961 - Creating a model with {validate:true} will call validate and use the error callback', function(assert) { - var Model = Backbone.Model.extend({ - validate: function(attrs) { - if (attrs.id === 1) return "This shouldn't happen"; - } - }); - var model = new Model({id: 1}, {validate: true}); - assert.equal(model.validationError, "This shouldn't happen"); - }); - - QUnit.test('toJSON receives attrs during save(..., {wait: true})', function(assert) { - assert.expect(1); - var Model = Backbone.Model.extend({ - url: '/test', - toJSON: function() { - assert.strictEqual(this.attributes.x, 1); - return _.clone(this.attributes); - } - }); - var model = new Model; - model.save({x: 1}, {wait: true}); - }); - - QUnit.test('#2034 - nested set with silent only triggers one change', function(assert) { - assert.expect(1); - var model = new Backbone.Model(); - model.on('change', function() { - model.set({b: true}, {silent: true}); - assert.ok(true); - }); - model.set({a: true}); - }); - - QUnit.test('#3778 - id will only be updated if it is set', function(assert) { - assert.expect(2); - var model = new Backbone.Model({id: 1}); - model.id = 2; - model.set({foo: 'bar'}); - assert.equal(model.id, 2); - model.set({id: 3}); - assert.equal(model.id, 3); - }); - -})(); diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/backbone/test/noconflict.js b/ecomp-portal-FE/client/bower_components/lodash/vendor/backbone/test/noconflict.js deleted file mode 100644 index 9968f688..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/backbone/test/noconflict.js +++ /dev/null @@ -1,13 +0,0 @@ -(function() { - - QUnit.module('Backbone.noConflict'); - - QUnit.test('noConflict', function(assert) { - assert.expect(2); - var noconflictBackbone = Backbone.noConflict(); - assert.equal(window.Backbone, undefined, 'Returned window.Backbone'); - window.Backbone = noconflictBackbone; - assert.equal(window.Backbone, noconflictBackbone, 'Backbone is still pointing to the original Backbone'); - }); - -})(); diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/backbone/test/router.js b/ecomp-portal-FE/client/bower_components/lodash/vendor/backbone/test/router.js deleted file mode 100644 index 13110c45..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/backbone/test/router.js +++ /dev/null @@ -1,1062 +0,0 @@ -(function() { - - var router = null; - var location = null; - var lastRoute = null; - var lastArgs = []; - - var onRoute = function(routerParam, route, args) { - lastRoute = route; - lastArgs = args; - }; - - var Location = function(href) { - this.replace(href); - }; - - _.extend(Location.prototype, { - - parser: document.createElement('a'), - - replace: function(href) { - this.parser.href = href; - _.extend(this, _.pick(this.parser, - 'href', - 'hash', - 'host', - 'search', - 'fragment', - 'pathname', - 'protocol' - )); - // In IE, anchor.pathname does not contain a leading slash though - // window.location.pathname does. - if (!/^\//.test(this.pathname)) this.pathname = '/' + this.pathname; - }, - - toString: function() { - return this.href; - } - - }); - - QUnit.module('Backbone.Router', { - - setup: function() { - location = new Location('http://example.com'); - Backbone.history = _.extend(new Backbone.History, {location: location}); - router = new Router({testing: 101}); - Backbone.history.interval = 9; - Backbone.history.start({pushState: false}); - lastRoute = null; - lastArgs = []; - Backbone.history.on('route', onRoute); - }, - - teardown: function() { - Backbone.history.stop(); - Backbone.history.off('route', onRoute); - } - - }); - - var ExternalObject = { - value: 'unset', - - routingFunction: function(value) { - this.value = value; - } - }; - ExternalObject.routingFunction = _.bind(ExternalObject.routingFunction, ExternalObject); - - var Router = Backbone.Router.extend({ - - count: 0, - - routes: { - 'noCallback': 'noCallback', - 'counter': 'counter', - 'search/:query': 'search', - 'search/:query/p:page': 'search', - 'charñ': 'charUTF', - 'char%C3%B1': 'charEscaped', - 'contacts': 'contacts', - 'contacts/new': 'newContact', - 'contacts/:id': 'loadContact', - 'route-event/:arg': 'routeEvent', - 'optional(/:item)': 'optionalItem', - 'named/optional/(y:z)': 'namedOptional', - 'splat/*args/end': 'splat', - ':repo/compare/*from...*to': 'github', - 'decode/:named/*splat': 'decode', - '*first/complex-*part/*rest': 'complex', - 'query/:entity': 'query', - 'function/:value': ExternalObject.routingFunction, - '*anything': 'anything' - }, - - initialize: function(options) { - this.testing = options.testing; - this.route('implicit', 'implicit'); - }, - - counter: function() { - this.count++; - }, - - implicit: function() { - this.count++; - }, - - search: function(query, page) { - this.query = query; - this.page = page; - }, - - charUTF: function() { - this.charType = 'UTF'; - }, - - charEscaped: function() { - this.charType = 'escaped'; - }, - - contacts: function(){ - this.contact = 'index'; - }, - - newContact: function(){ - this.contact = 'new'; - }, - - loadContact: function(){ - this.contact = 'load'; - }, - - optionalItem: function(arg){ - this.arg = arg !== void 0 ? arg : null; - }, - - splat: function(args) { - this.args = args; - }, - - github: function(repo, from, to) { - this.repo = repo; - this.from = from; - this.to = to; - }, - - complex: function(first, part, rest) { - this.first = first; - this.part = part; - this.rest = rest; - }, - - query: function(entity, args) { - this.entity = entity; - this.queryArgs = args; - }, - - anything: function(whatever) { - this.anything = whatever; - }, - - namedOptional: function(z) { - this.z = z; - }, - - decode: function(named, path) { - this.named = named; - this.path = path; - }, - - routeEvent: function(arg) { - } - - }); - - QUnit.test('initialize', function(assert) { - assert.expect(1); - assert.equal(router.testing, 101); - }); - - QUnit.test('routes (simple)', function(assert) { - assert.expect(4); - location.replace('http://example.com#search/news'); - Backbone.history.checkUrl(); - assert.equal(router.query, 'news'); - assert.equal(router.page, void 0); - assert.equal(lastRoute, 'search'); - assert.equal(lastArgs[0], 'news'); - }); - - QUnit.test('routes (simple, but unicode)', function(assert) { - assert.expect(4); - location.replace('http://example.com#search/тест'); - Backbone.history.checkUrl(); - assert.equal(router.query, 'тест'); - assert.equal(router.page, void 0); - assert.equal(lastRoute, 'search'); - assert.equal(lastArgs[0], 'тест'); - }); - - QUnit.test('routes (two part)', function(assert) { - assert.expect(2); - location.replace('http://example.com#search/nyc/p10'); - Backbone.history.checkUrl(); - assert.equal(router.query, 'nyc'); - assert.equal(router.page, '10'); - }); - - QUnit.test('routes via navigate', function(assert) { - assert.expect(2); - Backbone.history.navigate('search/manhattan/p20', {trigger: true}); - assert.equal(router.query, 'manhattan'); - assert.equal(router.page, '20'); - }); - - QUnit.test('routes via navigate with params', function(assert) { - assert.expect(1); - Backbone.history.navigate('query/test?a=b', {trigger: true}); - assert.equal(router.queryArgs, 'a=b'); - }); - - QUnit.test('routes via navigate for backwards-compatibility', function(assert) { - assert.expect(2); - Backbone.history.navigate('search/manhattan/p20', true); - assert.equal(router.query, 'manhattan'); - assert.equal(router.page, '20'); - }); - - QUnit.test('reports matched route via nagivate', function(assert) { - assert.expect(1); - assert.ok(Backbone.history.navigate('search/manhattan/p20', true)); - }); - - QUnit.test('route precedence via navigate', function(assert){ - assert.expect(6); - // check both 0.9.x and backwards-compatibility options - _.each([{trigger: true}, true], function( options ){ - Backbone.history.navigate('contacts', options); - assert.equal(router.contact, 'index'); - Backbone.history.navigate('contacts/new', options); - assert.equal(router.contact, 'new'); - Backbone.history.navigate('contacts/foo', options); - assert.equal(router.contact, 'load'); - }); - }); - - QUnit.test('loadUrl is not called for identical routes.', function(assert) { - assert.expect(0); - Backbone.history.loadUrl = function(){ assert.ok(false); }; - location.replace('http://example.com#route'); - Backbone.history.navigate('route'); - Backbone.history.navigate('/route'); - Backbone.history.navigate('/route'); - }); - - QUnit.test('use implicit callback if none provided', function(assert) { - assert.expect(1); - router.count = 0; - router.navigate('implicit', {trigger: true}); - assert.equal(router.count, 1); - }); - - QUnit.test('routes via navigate with {replace: true}', function(assert) { - assert.expect(1); - location.replace('http://example.com#start_here'); - Backbone.history.checkUrl(); - location.replace = function(href) { - assert.strictEqual(href, new Location('http://example.com#end_here').href); - }; - Backbone.history.navigate('end_here', {replace: true}); - }); - - QUnit.test('routes (splats)', function(assert) { - assert.expect(1); - location.replace('http://example.com#splat/long-list/of/splatted_99args/end'); - Backbone.history.checkUrl(); - assert.equal(router.args, 'long-list/of/splatted_99args'); - }); - - QUnit.test('routes (github)', function(assert) { - assert.expect(3); - location.replace('http://example.com#backbone/compare/1.0...braddunbar:with/slash'); - Backbone.history.checkUrl(); - assert.equal(router.repo, 'backbone'); - assert.equal(router.from, '1.0'); - assert.equal(router.to, 'braddunbar:with/slash'); - }); - - QUnit.test('routes (optional)', function(assert) { - assert.expect(2); - location.replace('http://example.com#optional'); - Backbone.history.checkUrl(); - assert.ok(!router.arg); - location.replace('http://example.com#optional/thing'); - Backbone.history.checkUrl(); - assert.equal(router.arg, 'thing'); - }); - - QUnit.test('routes (complex)', function(assert) { - assert.expect(3); - location.replace('http://example.com#one/two/three/complex-part/four/five/six/seven'); - Backbone.history.checkUrl(); - assert.equal(router.first, 'one/two/three'); - assert.equal(router.part, 'part'); - assert.equal(router.rest, 'four/five/six/seven'); - }); - - QUnit.test('routes (query)', function(assert) { - assert.expect(5); - location.replace('http://example.com#query/mandel?a=b&c=d'); - Backbone.history.checkUrl(); - assert.equal(router.entity, 'mandel'); - assert.equal(router.queryArgs, 'a=b&c=d'); - assert.equal(lastRoute, 'query'); - assert.equal(lastArgs[0], 'mandel'); - assert.equal(lastArgs[1], 'a=b&c=d'); - }); - - QUnit.test('routes (anything)', function(assert) { - assert.expect(1); - location.replace('http://example.com#doesnt-match-a-route'); - Backbone.history.checkUrl(); - assert.equal(router.anything, 'doesnt-match-a-route'); - }); - - QUnit.test('routes (function)', function(assert) { - assert.expect(3); - router.on('route', function(name) { - assert.ok(name === ''); - }); - assert.equal(ExternalObject.value, 'unset'); - location.replace('http://example.com#function/set'); - Backbone.history.checkUrl(); - assert.equal(ExternalObject.value, 'set'); - }); - - QUnit.test('Decode named parameters, not splats.', function(assert) { - assert.expect(2); - location.replace('http://example.com#decode/a%2Fb/c%2Fd/e'); - Backbone.history.checkUrl(); - assert.strictEqual(router.named, 'a/b'); - assert.strictEqual(router.path, 'c/d/e'); - }); - - QUnit.test("fires event when router doesn't have callback on it", function(assert) { - assert.expect(1); - router.on('route:noCallback', function(){ assert.ok(true); }); - location.replace('http://example.com#noCallback'); - Backbone.history.checkUrl(); - }); - - QUnit.test('No events are triggered if #execute returns false.', function(assert) { - assert.expect(1); - var MyRouter = Backbone.Router.extend({ - - routes: { - foo: function() { - assert.ok(true); - } - }, - - execute: function(callback, args) { - callback.apply(this, args); - return false; - } - - }); - - var myRouter = new MyRouter; - - myRouter.on('route route:foo', function() { - assert.ok(false); - }); - - Backbone.history.on('route', function() { - assert.ok(false); - }); - - location.replace('http://example.com#foo'); - Backbone.history.checkUrl(); - }); - - QUnit.test('#933, #908 - leading slash', function(assert) { - assert.expect(2); - location.replace('http://example.com/root/foo'); - - Backbone.history.stop(); - Backbone.history = _.extend(new Backbone.History, {location: location}); - Backbone.history.start({root: '/root', hashChange: false, silent: true}); - assert.strictEqual(Backbone.history.getFragment(), 'foo'); - - Backbone.history.stop(); - Backbone.history = _.extend(new Backbone.History, {location: location}); - Backbone.history.start({root: '/root/', hashChange: false, silent: true}); - assert.strictEqual(Backbone.history.getFragment(), 'foo'); - }); - - QUnit.test('#967 - Route callback gets passed encoded values.', function(assert) { - assert.expect(3); - var route = 'has%2Fslash/complex-has%23hash/has%20space'; - Backbone.history.navigate(route, {trigger: true}); - assert.strictEqual(router.first, 'has/slash'); - assert.strictEqual(router.part, 'has#hash'); - assert.strictEqual(router.rest, 'has space'); - }); - - QUnit.test('correctly handles URLs with % (#868)', function(assert) { - assert.expect(3); - location.replace('http://example.com#search/fat%3A1.5%25'); - Backbone.history.checkUrl(); - location.replace('http://example.com#search/fat'); - Backbone.history.checkUrl(); - assert.equal(router.query, 'fat'); - assert.equal(router.page, void 0); - assert.equal(lastRoute, 'search'); - }); - - QUnit.test('#2666 - Hashes with UTF8 in them.', function(assert) { - assert.expect(2); - Backbone.history.navigate('charñ', {trigger: true}); - assert.equal(router.charType, 'UTF'); - Backbone.history.navigate('char%C3%B1', {trigger: true}); - assert.equal(router.charType, 'UTF'); - }); - - QUnit.test('#1185 - Use pathname when hashChange is not wanted.', function(assert) { - assert.expect(1); - Backbone.history.stop(); - location.replace('http://example.com/path/name#hash'); - Backbone.history = _.extend(new Backbone.History, {location: location}); - Backbone.history.start({hashChange: false}); - var fragment = Backbone.history.getFragment(); - assert.strictEqual(fragment, location.pathname.replace(/^\//, '')); - }); - - QUnit.test('#1206 - Strip leading slash before location.assign.', function(assert) { - assert.expect(1); - Backbone.history.stop(); - location.replace('http://example.com/root/'); - Backbone.history = _.extend(new Backbone.History, {location: location}); - Backbone.history.start({hashChange: false, root: '/root/'}); - location.assign = function(pathname) { - assert.strictEqual(pathname, '/root/fragment'); - }; - Backbone.history.navigate('/fragment'); - }); - - QUnit.test('#1387 - Root fragment without trailing slash.', function(assert) { - assert.expect(1); - Backbone.history.stop(); - location.replace('http://example.com/root'); - Backbone.history = _.extend(new Backbone.History, {location: location}); - Backbone.history.start({hashChange: false, root: '/root/', silent: true}); - assert.strictEqual(Backbone.history.getFragment(), ''); - }); - - QUnit.test('#1366 - History does not prepend root to fragment.', function(assert) { - assert.expect(2); - Backbone.history.stop(); - location.replace('http://example.com/root/'); - Backbone.history = _.extend(new Backbone.History, { - location: location, - history: { - pushState: function(state, title, url) { - assert.strictEqual(url, '/root/x'); - } - } - }); - Backbone.history.start({ - root: '/root/', - pushState: true, - hashChange: false - }); - Backbone.history.navigate('x'); - assert.strictEqual(Backbone.history.fragment, 'x'); - }); - - QUnit.test('Normalize root.', function(assert) { - assert.expect(1); - Backbone.history.stop(); - location.replace('http://example.com/root'); - Backbone.history = _.extend(new Backbone.History, { - location: location, - history: { - pushState: function(state, title, url) { - assert.strictEqual(url, '/root/fragment'); - } - } - }); - Backbone.history.start({ - pushState: true, - root: '/root', - hashChange: false - }); - Backbone.history.navigate('fragment'); - }); - - QUnit.test('Normalize root.', function(assert) { - assert.expect(1); - Backbone.history.stop(); - location.replace('http://example.com/root#fragment'); - Backbone.history = _.extend(new Backbone.History, { - location: location, - history: { - pushState: function(state, title, url) {}, - replaceState: function(state, title, url) { - assert.strictEqual(url, '/root/fragment'); - } - } - }); - Backbone.history.start({ - pushState: true, - root: '/root' - }); - }); - - QUnit.test('Normalize root.', function(assert) { - assert.expect(1); - Backbone.history.stop(); - location.replace('http://example.com/root'); - Backbone.history = _.extend(new Backbone.History, {location: location}); - Backbone.history.loadUrl = function() { assert.ok(true); }; - Backbone.history.start({ - pushState: true, - root: '/root' - }); - }); - - QUnit.test('Normalize root - leading slash.', function(assert) { - assert.expect(1); - Backbone.history.stop(); - location.replace('http://example.com/root'); - Backbone.history = _.extend(new Backbone.History, { - location: location, - history: { - pushState: function(){}, - replaceState: function(){} - } - }); - Backbone.history.start({root: 'root'}); - assert.strictEqual(Backbone.history.root, '/root/'); - }); - - QUnit.test('Transition from hashChange to pushState.', function(assert) { - assert.expect(1); - Backbone.history.stop(); - location.replace('http://example.com/root#x/y'); - Backbone.history = _.extend(new Backbone.History, { - location: location, - history: { - pushState: function(){}, - replaceState: function(state, title, url){ - assert.strictEqual(url, '/root/x/y'); - } - } - }); - Backbone.history.start({ - root: 'root', - pushState: true - }); - }); - - QUnit.test('#1619: Router: Normalize empty root', function(assert) { - assert.expect(1); - Backbone.history.stop(); - location.replace('http://example.com/'); - Backbone.history = _.extend(new Backbone.History, { - location: location, - history: { - pushState: function(){}, - replaceState: function(){} - } - }); - Backbone.history.start({root: ''}); - assert.strictEqual(Backbone.history.root, '/'); - }); - - QUnit.test('#1619: Router: nagivate with empty root', function(assert) { - assert.expect(1); - Backbone.history.stop(); - location.replace('http://example.com/'); - Backbone.history = _.extend(new Backbone.History, { - location: location, - history: { - pushState: function(state, title, url) { - assert.strictEqual(url, '/fragment'); - } - } - }); - Backbone.history.start({ - pushState: true, - root: '', - hashChange: false - }); - Backbone.history.navigate('fragment'); - }); - - QUnit.test('Transition from pushState to hashChange.', function(assert) { - assert.expect(1); - Backbone.history.stop(); - location.replace('http://example.com/root/x/y?a=b'); - location.replace = function(url) { - assert.strictEqual(url, '/root#x/y?a=b'); - }; - Backbone.history = _.extend(new Backbone.History, { - location: location, - history: { - pushState: null, - replaceState: null - } - }); - Backbone.history.start({ - root: 'root', - pushState: true - }); - }); - - QUnit.test('#1695 - hashChange to pushState with search.', function(assert) { - assert.expect(1); - Backbone.history.stop(); - location.replace('http://example.com/root#x/y?a=b'); - Backbone.history = _.extend(new Backbone.History, { - location: location, - history: { - pushState: function(){}, - replaceState: function(state, title, url){ - assert.strictEqual(url, '/root/x/y?a=b'); - } - } - }); - Backbone.history.start({ - root: 'root', - pushState: true - }); - }); - - QUnit.test('#1746 - Router allows empty route.', function(assert) { - assert.expect(1); - var MyRouter = Backbone.Router.extend({ - routes: {'': 'empty'}, - empty: function(){}, - route: function(route){ - assert.strictEqual(route, ''); - } - }); - new MyRouter; - }); - - QUnit.test('#1794 - Trailing space in fragments.', function(assert) { - assert.expect(1); - var history = new Backbone.History; - assert.strictEqual(history.getFragment('fragment '), 'fragment'); - }); - - QUnit.test('#1820 - Leading slash and trailing space.', 1, function(assert) { - var history = new Backbone.History; - assert.strictEqual(history.getFragment('/fragment '), 'fragment'); - }); - - QUnit.test('#1980 - Optional parameters.', function(assert) { - assert.expect(2); - location.replace('http://example.com#named/optional/y'); - Backbone.history.checkUrl(); - assert.strictEqual(router.z, undefined); - location.replace('http://example.com#named/optional/y123'); - Backbone.history.checkUrl(); - assert.strictEqual(router.z, '123'); - }); - - QUnit.test("#2062 - Trigger 'route' event on router instance.", function(assert) { - assert.expect(2); - router.on('route', function(name, args) { - assert.strictEqual(name, 'routeEvent'); - assert.deepEqual(args, ['x', null]); - }); - location.replace('http://example.com#route-event/x'); - Backbone.history.checkUrl(); - }); - - QUnit.test('#2255 - Extend routes by making routes a function.', function(assert) { - assert.expect(1); - var RouterBase = Backbone.Router.extend({ - routes: function() { - return { - home: 'root', - index: 'index.html' - }; - } - }); - - var RouterExtended = RouterBase.extend({ - routes: function() { - var _super = RouterExtended.__super__.routes; - return _.extend(_super(), {show: 'show', search: 'search'}); - } - }); - - var myRouter = new RouterExtended(); - assert.deepEqual({home: 'root', index: 'index.html', show: 'show', search: 'search'}, myRouter.routes); - }); - - QUnit.test('#2538 - hashChange to pushState only if both requested.', function(assert) { - assert.expect(0); - Backbone.history.stop(); - location.replace('http://example.com/root?a=b#x/y'); - Backbone.history = _.extend(new Backbone.History, { - location: location, - history: { - pushState: function(){}, - replaceState: function(){ assert.ok(false); } - } - }); - Backbone.history.start({ - root: 'root', - pushState: true, - hashChange: false - }); - }); - - QUnit.test('No hash fallback.', function(assert) { - assert.expect(0); - Backbone.history.stop(); - Backbone.history = _.extend(new Backbone.History, { - location: location, - history: { - pushState: function(){}, - replaceState: function(){} - } - }); - - var MyRouter = Backbone.Router.extend({ - routes: { - hash: function() { assert.ok(false); } - } - }); - var myRouter = new MyRouter; - - location.replace('http://example.com/'); - Backbone.history.start({ - pushState: true, - hashChange: false - }); - location.replace('http://example.com/nomatch#hash'); - Backbone.history.checkUrl(); - }); - - QUnit.test('#2656 - No trailing slash on root.', function(assert) { - assert.expect(1); - Backbone.history.stop(); - Backbone.history = _.extend(new Backbone.History, { - location: location, - history: { - pushState: function(state, title, url){ - assert.strictEqual(url, '/root'); - } - } - }); - location.replace('http://example.com/root/path'); - Backbone.history.start({pushState: true, hashChange: false, root: 'root'}); - Backbone.history.navigate(''); - }); - - QUnit.test('#2656 - No trailing slash on root.', function(assert) { - assert.expect(1); - Backbone.history.stop(); - Backbone.history = _.extend(new Backbone.History, { - location: location, - history: { - pushState: function(state, title, url) { - assert.strictEqual(url, '/'); - } - } - }); - location.replace('http://example.com/path'); - Backbone.history.start({pushState: true, hashChange: false}); - Backbone.history.navigate(''); - }); - - QUnit.test('#2656 - No trailing slash on root.', function(assert) { - assert.expect(1); - Backbone.history.stop(); - Backbone.history = _.extend(new Backbone.History, { - location: location, - history: { - pushState: function(state, title, url){ - assert.strictEqual(url, '/root?x=1'); - } - } - }); - location.replace('http://example.com/root/path'); - Backbone.history.start({pushState: true, hashChange: false, root: 'root'}); - Backbone.history.navigate('?x=1'); - }); - - QUnit.test('#2765 - Fragment matching sans query/hash.', function(assert) { - assert.expect(2); - Backbone.history.stop(); - Backbone.history = _.extend(new Backbone.History, { - location: location, - history: { - pushState: function(state, title, url) { - assert.strictEqual(url, '/path?query#hash'); - } - } - }); - - var MyRouter = Backbone.Router.extend({ - routes: { - path: function() { assert.ok(true); } - } - }); - var myRouter = new MyRouter; - - location.replace('http://example.com/'); - Backbone.history.start({pushState: true, hashChange: false}); - Backbone.history.navigate('path?query#hash', true); - }); - - QUnit.test('Do not decode the search params.', function(assert) { - assert.expect(1); - var MyRouter = Backbone.Router.extend({ - routes: { - path: function(params){ - assert.strictEqual(params, 'x=y%3Fz'); - } - } - }); - var myRouter = new MyRouter; - Backbone.history.navigate('path?x=y%3Fz', true); - }); - - QUnit.test('Navigate to a hash url.', function(assert) { - assert.expect(1); - Backbone.history.stop(); - Backbone.history = _.extend(new Backbone.History, {location: location}); - Backbone.history.start({pushState: true}); - var MyRouter = Backbone.Router.extend({ - routes: { - path: function(params) { - assert.strictEqual(params, 'x=y'); - } - } - }); - var myRouter = new MyRouter; - location.replace('http://example.com/path?x=y#hash'); - Backbone.history.checkUrl(); - }); - - QUnit.test('#navigate to a hash url.', function(assert) { - assert.expect(1); - Backbone.history.stop(); - Backbone.history = _.extend(new Backbone.History, {location: location}); - Backbone.history.start({pushState: true}); - var MyRouter = Backbone.Router.extend({ - routes: { - path: function(params) { - assert.strictEqual(params, 'x=y'); - } - } - }); - var myRouter = new MyRouter; - Backbone.history.navigate('path?x=y#hash', true); - }); - - QUnit.test('unicode pathname', function(assert) { - assert.expect(1); - location.replace('http://example.com/myyjä'); - Backbone.history.stop(); - Backbone.history = _.extend(new Backbone.History, {location: location}); - var MyRouter = Backbone.Router.extend({ - routes: { - myyjä: function() { - assert.ok(true); - } - } - }); - new MyRouter; - Backbone.history.start({pushState: true}); - }); - - QUnit.test('unicode pathname with % in a parameter', function(assert) { - assert.expect(1); - location.replace('http://example.com/myyjä/foo%20%25%3F%2f%40%25%20bar'); - location.pathname = '/myyj%C3%A4/foo%20%25%3F%2f%40%25%20bar'; - Backbone.history.stop(); - Backbone.history = _.extend(new Backbone.History, {location: location}); - var MyRouter = Backbone.Router.extend({ - routes: { - 'myyjä/:query': function(query) { - assert.strictEqual(query, 'foo %?/@% bar'); - } - } - }); - new MyRouter; - Backbone.history.start({pushState: true}); - }); - - QUnit.test('newline in route', function(assert) { - assert.expect(1); - location.replace('http://example.com/stuff%0Anonsense?param=foo%0Abar'); - Backbone.history.stop(); - Backbone.history = _.extend(new Backbone.History, {location: location}); - var MyRouter = Backbone.Router.extend({ - routes: { - 'stuff\nnonsense': function() { - assert.ok(true); - } - } - }); - new MyRouter; - Backbone.history.start({pushState: true}); - }); - - QUnit.test('Router#execute receives callback, args, name.', function(assert) { - assert.expect(3); - location.replace('http://example.com#foo/123/bar?x=y'); - Backbone.history.stop(); - Backbone.history = _.extend(new Backbone.History, {location: location}); - var MyRouter = Backbone.Router.extend({ - routes: {'foo/:id/bar': 'foo'}, - foo: function(){}, - execute: function(callback, args, name) { - assert.strictEqual(callback, this.foo); - assert.deepEqual(args, ['123', 'x=y']); - assert.strictEqual(name, 'foo'); - } - }); - var myRouter = new MyRouter; - Backbone.history.start(); - }); - - QUnit.test('pushState to hashChange with only search params.', function(assert) { - assert.expect(1); - Backbone.history.stop(); - location.replace('http://example.com?a=b'); - location.replace = function(url) { - assert.strictEqual(url, '/#?a=b'); - }; - Backbone.history = _.extend(new Backbone.History, { - location: location, - history: null - }); - Backbone.history.start({pushState: true}); - }); - - QUnit.test('#3123 - History#navigate decodes before comparison.', function(assert) { - assert.expect(1); - Backbone.history.stop(); - location.replace('http://example.com/shop/search?keyword=short%20dress'); - Backbone.history = _.extend(new Backbone.History, { - location: location, - history: { - pushState: function(){ assert.ok(false); }, - replaceState: function(){ assert.ok(false); } - } - }); - Backbone.history.start({pushState: true}); - Backbone.history.navigate('shop/search?keyword=short%20dress', true); - assert.strictEqual(Backbone.history.fragment, 'shop/search?keyword=short dress'); - }); - - QUnit.test('#3175 - Urls in the params', function(assert) { - assert.expect(1); - Backbone.history.stop(); - location.replace('http://example.com#login?a=value&backUrl=https%3A%2F%2Fwww.msn.com%2Fidp%2Fidpdemo%3Fspid%3Dspdemo%26target%3Db'); - Backbone.history = _.extend(new Backbone.History, {location: location}); - var myRouter = new Backbone.Router; - myRouter.route('login', function(params) { - assert.strictEqual(params, 'a=value&backUrl=https%3A%2F%2Fwww.msn.com%2Fidp%2Fidpdemo%3Fspid%3Dspdemo%26target%3Db'); - }); - Backbone.history.start(); - }); - - QUnit.test('#3358 - pushState to hashChange transition with search params', function(assert) { - assert.expect(1); - Backbone.history.stop(); - location.replace('http://example.com/root?foo=bar'); - location.replace = function(url) { - assert.strictEqual(url, '/root#?foo=bar'); - }; - Backbone.history = _.extend(new Backbone.History, { - location: location, - history: { - pushState: undefined, - replaceState: undefined - } - }); - Backbone.history.start({root: '/root', pushState: true}); - }); - - QUnit.test("Paths that don't match the root should not match no root", function(assert) { - assert.expect(0); - location.replace('http://example.com/foo'); - Backbone.history.stop(); - Backbone.history = _.extend(new Backbone.History, {location: location}); - var MyRouter = Backbone.Router.extend({ - routes: { - foo: function(){ - assert.ok(false, 'should not match unless root matches'); - } - } - }); - var myRouter = new MyRouter; - Backbone.history.start({root: 'root', pushState: true}); - }); - - QUnit.test("Paths that don't match the root should not match roots of the same length", function(assert) { - assert.expect(0); - location.replace('http://example.com/xxxx/foo'); - Backbone.history.stop(); - Backbone.history = _.extend(new Backbone.History, {location: location}); - var MyRouter = Backbone.Router.extend({ - routes: { - foo: function(){ - assert.ok(false, 'should not match unless root matches'); - } - } - }); - var myRouter = new MyRouter; - Backbone.history.start({root: 'root', pushState: true}); - }); - - QUnit.test('roots with regex characters', function(assert) { - assert.expect(1); - location.replace('http://example.com/x+y.z/foo'); - Backbone.history.stop(); - Backbone.history = _.extend(new Backbone.History, {location: location}); - var MyRouter = Backbone.Router.extend({ - routes: {foo: function(){ assert.ok(true); }} - }); - var myRouter = new MyRouter; - Backbone.history.start({root: 'x+y.z', pushState: true}); - }); - - QUnit.test('roots with unicode characters', function(assert) { - assert.expect(1); - location.replace('http://example.com/®ooτ/foo'); - Backbone.history.stop(); - Backbone.history = _.extend(new Backbone.History, {location: location}); - var MyRouter = Backbone.Router.extend({ - routes: {foo: function(){ assert.ok(true); }} - }); - var myRouter = new MyRouter; - Backbone.history.start({root: '®ooτ', pushState: true}); - }); - - QUnit.test('roots without slash', function(assert) { - assert.expect(1); - location.replace('http://example.com/®ooτ'); - Backbone.history.stop(); - Backbone.history = _.extend(new Backbone.History, {location: location}); - var MyRouter = Backbone.Router.extend({ - routes: {'': function(){ assert.ok(true); }} - }); - var myRouter = new MyRouter; - Backbone.history.start({root: '®ooτ', pushState: true}); - }); - -})(); diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/backbone/test/setup/dom-setup.js b/ecomp-portal-FE/client/bower_components/lodash/vendor/backbone/test/setup/dom-setup.js deleted file mode 100644 index f2242282..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/backbone/test/setup/dom-setup.js +++ /dev/null @@ -1,4 +0,0 @@ -$('body').append( - '<div id="qunit"></div>' + - '<div id="qunit-fixture"></div>' -); diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/backbone/test/setup/environment.js b/ecomp-portal-FE/client/bower_components/lodash/vendor/backbone/test/setup/environment.js deleted file mode 100644 index c2441ac7..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/backbone/test/setup/environment.js +++ /dev/null @@ -1,45 +0,0 @@ -(function() { - - var sync = Backbone.sync; - var ajax = Backbone.ajax; - var emulateHTTP = Backbone.emulateHTTP; - var emulateJSON = Backbone.emulateJSON; - var history = window.history; - var pushState = history.pushState; - var replaceState = history.replaceState; - - QUnit.config.noglobals = true; - - QUnit.testStart(function() { - var env = QUnit.config.current.testEnvironment; - - // We never want to actually call these during tests. - history.pushState = history.replaceState = function(){}; - - // Capture ajax settings for comparison. - Backbone.ajax = function(settings) { - env.ajaxSettings = settings; - }; - - // Capture the arguments to Backbone.sync for comparison. - Backbone.sync = function(method, model, options) { - env.syncArgs = { - method: method, - model: model, - options: options - }; - sync.apply(this, arguments); - }; - - }); - - QUnit.testDone(function() { - Backbone.sync = sync; - Backbone.ajax = ajax; - Backbone.emulateHTTP = emulateHTTP; - Backbone.emulateJSON = emulateJSON; - history.pushState = pushState; - history.replaceState = replaceState; - }); - -})(); diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/backbone/test/sync.js b/ecomp-portal-FE/client/bower_components/lodash/vendor/backbone/test/sync.js deleted file mode 100644 index 8813f158..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/backbone/test/sync.js +++ /dev/null @@ -1,239 +0,0 @@ -(function() { - - var Library = Backbone.Collection.extend({ - url: function() { return '/library'; } - }); - var library; - - var attrs = { - title: 'The Tempest', - author: 'Bill Shakespeare', - length: 123 - }; - - QUnit.module('Backbone.sync', { - - beforeEach: function(assert) { - library = new Library; - library.create(attrs, {wait: false}); - }, - - afterEach: function(assert) { - Backbone.emulateHTTP = false; - } - - }); - - QUnit.test('read', function(assert) { - assert.expect(4); - library.fetch(); - assert.equal(this.ajaxSettings.url, '/library'); - assert.equal(this.ajaxSettings.type, 'GET'); - assert.equal(this.ajaxSettings.dataType, 'json'); - assert.ok(_.isEmpty(this.ajaxSettings.data)); - }); - - QUnit.test('passing data', function(assert) { - assert.expect(3); - library.fetch({data: {a: 'a', one: 1}}); - assert.equal(this.ajaxSettings.url, '/library'); - assert.equal(this.ajaxSettings.data.a, 'a'); - assert.equal(this.ajaxSettings.data.one, 1); - }); - - QUnit.test('create', function(assert) { - assert.expect(6); - assert.equal(this.ajaxSettings.url, '/library'); - assert.equal(this.ajaxSettings.type, 'POST'); - assert.equal(this.ajaxSettings.dataType, 'json'); - var data = JSON.parse(this.ajaxSettings.data); - assert.equal(data.title, 'The Tempest'); - assert.equal(data.author, 'Bill Shakespeare'); - assert.equal(data.length, 123); - }); - - QUnit.test('update', function(assert) { - assert.expect(7); - library.first().save({id: '1-the-tempest', author: 'William Shakespeare'}); - assert.equal(this.ajaxSettings.url, '/library/1-the-tempest'); - assert.equal(this.ajaxSettings.type, 'PUT'); - assert.equal(this.ajaxSettings.dataType, 'json'); - var data = JSON.parse(this.ajaxSettings.data); - assert.equal(data.id, '1-the-tempest'); - assert.equal(data.title, 'The Tempest'); - assert.equal(data.author, 'William Shakespeare'); - assert.equal(data.length, 123); - }); - - QUnit.test('update with emulateHTTP and emulateJSON', function(assert) { - assert.expect(7); - library.first().save({id: '2-the-tempest', author: 'Tim Shakespeare'}, { - emulateHTTP: true, - emulateJSON: true - }); - assert.equal(this.ajaxSettings.url, '/library/2-the-tempest'); - assert.equal(this.ajaxSettings.type, 'POST'); - assert.equal(this.ajaxSettings.dataType, 'json'); - assert.equal(this.ajaxSettings.data._method, 'PUT'); - var data = JSON.parse(this.ajaxSettings.data.model); - assert.equal(data.id, '2-the-tempest'); - assert.equal(data.author, 'Tim Shakespeare'); - assert.equal(data.length, 123); - }); - - QUnit.test('update with just emulateHTTP', function(assert) { - assert.expect(6); - library.first().save({id: '2-the-tempest', author: 'Tim Shakespeare'}, { - emulateHTTP: true - }); - assert.equal(this.ajaxSettings.url, '/library/2-the-tempest'); - assert.equal(this.ajaxSettings.type, 'POST'); - assert.equal(this.ajaxSettings.contentType, 'application/json'); - var data = JSON.parse(this.ajaxSettings.data); - assert.equal(data.id, '2-the-tempest'); - assert.equal(data.author, 'Tim Shakespeare'); - assert.equal(data.length, 123); - }); - - QUnit.test('update with just emulateJSON', function(assert) { - assert.expect(6); - library.first().save({id: '2-the-tempest', author: 'Tim Shakespeare'}, { - emulateJSON: true - }); - assert.equal(this.ajaxSettings.url, '/library/2-the-tempest'); - assert.equal(this.ajaxSettings.type, 'PUT'); - assert.equal(this.ajaxSettings.contentType, 'application/x-www-form-urlencoded'); - var data = JSON.parse(this.ajaxSettings.data.model); - assert.equal(data.id, '2-the-tempest'); - assert.equal(data.author, 'Tim Shakespeare'); - assert.equal(data.length, 123); - }); - - QUnit.test('read model', function(assert) { - assert.expect(3); - library.first().save({id: '2-the-tempest', author: 'Tim Shakespeare'}); - library.first().fetch(); - assert.equal(this.ajaxSettings.url, '/library/2-the-tempest'); - assert.equal(this.ajaxSettings.type, 'GET'); - assert.ok(_.isEmpty(this.ajaxSettings.data)); - }); - - QUnit.test('destroy', function(assert) { - assert.expect(3); - library.first().save({id: '2-the-tempest', author: 'Tim Shakespeare'}); - library.first().destroy({wait: true}); - assert.equal(this.ajaxSettings.url, '/library/2-the-tempest'); - assert.equal(this.ajaxSettings.type, 'DELETE'); - assert.equal(this.ajaxSettings.data, null); - }); - - QUnit.test('destroy with emulateHTTP', function(assert) { - assert.expect(3); - library.first().save({id: '2-the-tempest', author: 'Tim Shakespeare'}); - library.first().destroy({ - emulateHTTP: true, - emulateJSON: true - }); - assert.equal(this.ajaxSettings.url, '/library/2-the-tempest'); - assert.equal(this.ajaxSettings.type, 'POST'); - assert.equal(JSON.stringify(this.ajaxSettings.data), '{"_method":"DELETE"}'); - }); - - QUnit.test('urlError', function(assert) { - assert.expect(2); - var model = new Backbone.Model(); - assert.raises(function() { - model.fetch(); - }); - model.fetch({url: '/one/two'}); - assert.equal(this.ajaxSettings.url, '/one/two'); - }); - - QUnit.test('#1052 - `options` is optional.', function(assert) { - assert.expect(0); - var model = new Backbone.Model(); - model.url = '/test'; - Backbone.sync('create', model); - }); - - QUnit.test('Backbone.ajax', function(assert) { - assert.expect(1); - Backbone.ajax = function(settings){ - assert.strictEqual(settings.url, '/test'); - }; - var model = new Backbone.Model(); - model.url = '/test'; - Backbone.sync('create', model); - }); - - QUnit.test('Call provided error callback on error.', function(assert) { - assert.expect(1); - var model = new Backbone.Model; - model.url = '/test'; - Backbone.sync('read', model, { - error: function() { assert.ok(true); } - }); - this.ajaxSettings.error(); - }); - - QUnit.test('Use Backbone.emulateHTTP as default.', function(assert) { - assert.expect(2); - var model = new Backbone.Model; - model.url = '/test'; - - Backbone.emulateHTTP = true; - model.sync('create', model); - assert.strictEqual(this.ajaxSettings.emulateHTTP, true); - - Backbone.emulateHTTP = false; - model.sync('create', model); - assert.strictEqual(this.ajaxSettings.emulateHTTP, false); - }); - - QUnit.test('Use Backbone.emulateJSON as default.', function(assert) { - assert.expect(2); - var model = new Backbone.Model; - model.url = '/test'; - - Backbone.emulateJSON = true; - model.sync('create', model); - assert.strictEqual(this.ajaxSettings.emulateJSON, true); - - Backbone.emulateJSON = false; - model.sync('create', model); - assert.strictEqual(this.ajaxSettings.emulateJSON, false); - }); - - QUnit.test('#1756 - Call user provided beforeSend function.', function(assert) { - assert.expect(4); - Backbone.emulateHTTP = true; - var model = new Backbone.Model; - model.url = '/test'; - var xhr = { - setRequestHeader: function(header, value) { - assert.strictEqual(header, 'X-HTTP-Method-Override'); - assert.strictEqual(value, 'DELETE'); - } - }; - model.sync('delete', model, { - beforeSend: function(_xhr) { - assert.ok(_xhr === xhr); - return false; - } - }); - assert.strictEqual(this.ajaxSettings.beforeSend(xhr), false); - }); - - QUnit.test('#2928 - Pass along `textStatus` and `errorThrown`.', function(assert) { - assert.expect(2); - var model = new Backbone.Model; - model.url = '/test'; - model.on('error', function(m, xhr, options) { - assert.strictEqual(options.textStatus, 'textStatus'); - assert.strictEqual(options.errorThrown, 'errorThrown'); - }); - model.fetch(); - this.ajaxSettings.error({}, 'textStatus', 'errorThrown'); - }); - -})(); diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/backbone/test/view.js b/ecomp-portal-FE/client/bower_components/lodash/vendor/backbone/test/view.js deleted file mode 100644 index faf3445b..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/backbone/test/view.js +++ /dev/null @@ -1,495 +0,0 @@ -(function() { - - var view; - - QUnit.module('Backbone.View', { - - beforeEach: function(assert) { - $('#qunit-fixture').append( - '<div id="testElement"><h1>Test</h1></div>' - ); - - view = new Backbone.View({ - id: 'test-view', - className: 'test-view', - other: 'non-special-option' - }); - }, - - afterEach: function() { - $('#testElement').remove(); - $('#test-view').remove(); - } - - }); - - QUnit.test('constructor', function(assert) { - assert.expect(3); - assert.equal(view.el.id, 'test-view'); - assert.equal(view.el.className, 'test-view'); - assert.equal(view.el.other, void 0); - }); - - QUnit.test('$', function(assert) { - assert.expect(2); - var myView = new Backbone.View; - myView.setElement('<p><a><b>test</b></a></p>'); - var result = myView.$('a b'); - - assert.strictEqual(result[0].innerHTML, 'test'); - assert.ok(result.length === +result.length); - }); - - QUnit.test('$el', function(assert) { - assert.expect(3); - var myView = new Backbone.View; - myView.setElement('<p><a><b>test</b></a></p>'); - assert.strictEqual(myView.el.nodeType, 1); - - assert.ok(myView.$el instanceof Backbone.$); - assert.strictEqual(myView.$el[0], myView.el); - }); - - QUnit.test('initialize', function(assert) { - assert.expect(1); - var View = Backbone.View.extend({ - initialize: function() { - this.one = 1; - } - }); - - assert.strictEqual(new View().one, 1); - }); - - QUnit.test('render', function(assert) { - assert.expect(1); - var myView = new Backbone.View; - assert.equal(myView.render(), myView, '#render returns the view instance'); - }); - - QUnit.test('delegateEvents', function(assert) { - assert.expect(6); - var counter1 = 0, counter2 = 0; - - var myView = new Backbone.View({el: '#testElement'}); - myView.increment = function(){ counter1++; }; - myView.$el.on('click', function(){ counter2++; }); - - var events = {'click h1': 'increment'}; - - myView.delegateEvents(events); - myView.$('h1').trigger('click'); - assert.equal(counter1, 1); - assert.equal(counter2, 1); - - myView.$('h1').trigger('click'); - assert.equal(counter1, 2); - assert.equal(counter2, 2); - - myView.delegateEvents(events); - myView.$('h1').trigger('click'); - assert.equal(counter1, 3); - assert.equal(counter2, 3); - }); - - QUnit.test('delegate', function(assert) { - assert.expect(3); - var myView = new Backbone.View({el: '#testElement'}); - myView.delegate('click', 'h1', function() { - assert.ok(true); - }); - myView.delegate('click', function() { - assert.ok(true); - }); - myView.$('h1').trigger('click'); - - assert.equal(myView.delegate(), myView, '#delegate returns the view instance'); - }); - - QUnit.test('delegateEvents allows functions for callbacks', function(assert) { - assert.expect(3); - var myView = new Backbone.View({el: '<p></p>'}); - myView.counter = 0; - - var events = { - click: function() { - this.counter++; - } - }; - - myView.delegateEvents(events); - myView.$el.trigger('click'); - assert.equal(myView.counter, 1); - - myView.$el.trigger('click'); - assert.equal(myView.counter, 2); - - myView.delegateEvents(events); - myView.$el.trigger('click'); - assert.equal(myView.counter, 3); - }); - - - QUnit.test('delegateEvents ignore undefined methods', function(assert) { - assert.expect(0); - var myView = new Backbone.View({el: '<p></p>'}); - myView.delegateEvents({'click': 'undefinedMethod'}); - myView.$el.trigger('click'); - }); - - QUnit.test('undelegateEvents', function(assert) { - assert.expect(7); - var counter1 = 0, counter2 = 0; - - var myView = new Backbone.View({el: '#testElement'}); - myView.increment = function(){ counter1++; }; - myView.$el.on('click', function(){ counter2++; }); - - var events = {'click h1': 'increment'}; - - myView.delegateEvents(events); - myView.$('h1').trigger('click'); - assert.equal(counter1, 1); - assert.equal(counter2, 1); - - myView.undelegateEvents(); - myView.$('h1').trigger('click'); - assert.equal(counter1, 1); - assert.equal(counter2, 2); - - myView.delegateEvents(events); - myView.$('h1').trigger('click'); - assert.equal(counter1, 2); - assert.equal(counter2, 3); - - assert.equal(myView.undelegateEvents(), myView, '#undelegateEvents returns the view instance'); - }); - - QUnit.test('undelegate', function(assert) { - assert.expect(1); - var myView = new Backbone.View({el: '#testElement'}); - myView.delegate('click', function() { assert.ok(false); }); - myView.delegate('click', 'h1', function() { assert.ok(false); }); - - myView.undelegate('click'); - - myView.$('h1').trigger('click'); - myView.$el.trigger('click'); - - assert.equal(myView.undelegate(), myView, '#undelegate returns the view instance'); - }); - - QUnit.test('undelegate with passed handler', function(assert) { - assert.expect(1); - var myView = new Backbone.View({el: '#testElement'}); - var listener = function() { assert.ok(false); }; - myView.delegate('click', listener); - myView.delegate('click', function() { assert.ok(true); }); - myView.undelegate('click', listener); - myView.$el.trigger('click'); - }); - - QUnit.test('undelegate with selector', function(assert) { - assert.expect(2); - var myView = new Backbone.View({el: '#testElement'}); - myView.delegate('click', function() { assert.ok(true); }); - myView.delegate('click', 'h1', function() { assert.ok(false); }); - myView.undelegate('click', 'h1'); - myView.$('h1').trigger('click'); - myView.$el.trigger('click'); - }); - - QUnit.test('undelegate with handler and selector', function(assert) { - assert.expect(2); - var myView = new Backbone.View({el: '#testElement'}); - myView.delegate('click', function() { assert.ok(true); }); - var handler = function(){ assert.ok(false); }; - myView.delegate('click', 'h1', handler); - myView.undelegate('click', 'h1', handler); - myView.$('h1').trigger('click'); - myView.$el.trigger('click'); - }); - - QUnit.test('tagName can be provided as a string', function(assert) { - assert.expect(1); - var View = Backbone.View.extend({ - tagName: 'span' - }); - - assert.equal(new View().el.tagName, 'SPAN'); - }); - - QUnit.test('tagName can be provided as a function', function(assert) { - assert.expect(1); - var View = Backbone.View.extend({ - tagName: function() { - return 'p'; - } - }); - - assert.ok(new View().$el.is('p')); - }); - - QUnit.test('_ensureElement with DOM node el', function(assert) { - assert.expect(1); - var View = Backbone.View.extend({ - el: document.body - }); - - assert.equal(new View().el, document.body); - }); - - QUnit.test('_ensureElement with string el', function(assert) { - assert.expect(3); - var View = Backbone.View.extend({ - el: 'body' - }); - assert.strictEqual(new View().el, document.body); - - View = Backbone.View.extend({ - el: '#testElement > h1' - }); - assert.strictEqual(new View().el, $('#testElement > h1').get(0)); - - View = Backbone.View.extend({ - el: '#nonexistent' - }); - assert.ok(!new View().el); - }); - - QUnit.test('with className and id functions', function(assert) { - assert.expect(2); - var View = Backbone.View.extend({ - className: function() { - return 'className'; - }, - id: function() { - return 'id'; - } - }); - - assert.strictEqual(new View().el.className, 'className'); - assert.strictEqual(new View().el.id, 'id'); - }); - - QUnit.test('with attributes', function(assert) { - assert.expect(2); - var View = Backbone.View.extend({ - attributes: { - 'id': 'id', - 'class': 'class' - } - }); - - assert.strictEqual(new View().el.className, 'class'); - assert.strictEqual(new View().el.id, 'id'); - }); - - QUnit.test('with attributes as a function', function(assert) { - assert.expect(1); - var View = Backbone.View.extend({ - attributes: function() { - return {'class': 'dynamic'}; - } - }); - - assert.strictEqual(new View().el.className, 'dynamic'); - }); - - QUnit.test('should default to className/id properties', function(assert) { - assert.expect(4); - var View = Backbone.View.extend({ - className: 'backboneClass', - id: 'backboneId', - attributes: { - 'class': 'attributeClass', - 'id': 'attributeId' - } - }); - - var myView = new View; - assert.strictEqual(myView.el.className, 'backboneClass'); - assert.strictEqual(myView.el.id, 'backboneId'); - assert.strictEqual(myView.$el.attr('class'), 'backboneClass'); - assert.strictEqual(myView.$el.attr('id'), 'backboneId'); - }); - - QUnit.test('multiple views per element', function(assert) { - assert.expect(3); - var count = 0; - var $el = $('<p></p>'); - - var View = Backbone.View.extend({ - el: $el, - events: { - click: function() { - count++; - } - } - }); - - var view1 = new View; - $el.trigger('click'); - assert.equal(1, count); - - var view2 = new View; - $el.trigger('click'); - assert.equal(3, count); - - view1.delegateEvents(); - $el.trigger('click'); - assert.equal(5, count); - }); - - QUnit.test('custom events', function(assert) { - assert.expect(2); - var View = Backbone.View.extend({ - el: $('body'), - events: { - fake$event: function() { assert.ok(true); } - } - }); - - var myView = new View; - $('body').trigger('fake$event').trigger('fake$event'); - - $('body').off('fake$event'); - $('body').trigger('fake$event'); - }); - - QUnit.test('#1048 - setElement uses provided object.', function(assert) { - assert.expect(2); - var $el = $('body'); - - var myView = new Backbone.View({el: $el}); - assert.ok(myView.$el === $el); - - myView.setElement($el = $($el)); - assert.ok(myView.$el === $el); - }); - - QUnit.test('#986 - Undelegate before changing element.', function(assert) { - assert.expect(1); - var button1 = $('<button></button>'); - var button2 = $('<button></button>'); - - var View = Backbone.View.extend({ - events: { - click: function(e) { - assert.ok(myView.el === e.target); - } - } - }); - - var myView = new View({el: button1}); - myView.setElement(button2); - - button1.trigger('click'); - button2.trigger('click'); - }); - - QUnit.test('#1172 - Clone attributes object', function(assert) { - assert.expect(2); - var View = Backbone.View.extend({ - attributes: {foo: 'bar'} - }); - - var view1 = new View({id: 'foo'}); - assert.strictEqual(view1.el.id, 'foo'); - - var view2 = new View(); - assert.ok(!view2.el.id); - }); - - QUnit.test('views stopListening', function(assert) { - assert.expect(0); - var View = Backbone.View.extend({ - initialize: function() { - this.listenTo(this.model, 'all x', function(){ assert.ok(false); }); - this.listenTo(this.collection, 'all x', function(){ assert.ok(false); }); - } - }); - - var myView = new View({ - model: new Backbone.Model, - collection: new Backbone.Collection - }); - - myView.stopListening(); - myView.model.trigger('x'); - myView.collection.trigger('x'); - }); - - QUnit.test('Provide function for el.', function(assert) { - assert.expect(2); - var View = Backbone.View.extend({ - el: function() { - return '<p><a></a></p>'; - } - }); - - var myView = new View; - assert.ok(myView.$el.is('p')); - assert.ok(myView.$el.has('a')); - }); - - QUnit.test('events passed in options', function(assert) { - assert.expect(1); - var counter = 0; - - var View = Backbone.View.extend({ - el: '#testElement', - increment: function() { - counter++; - } - }); - - var myView = new View({ - events: { - 'click h1': 'increment' - } - }); - - myView.$('h1').trigger('click').trigger('click'); - assert.equal(counter, 2); - }); - - QUnit.test('remove', function(assert) { - assert.expect(2); - var myView = new Backbone.View; - document.body.appendChild(view.el); - - myView.delegate('click', function() { assert.ok(false); }); - myView.listenTo(myView, 'all x', function() { assert.ok(false); }); - - assert.equal(myView.remove(), myView, '#remove returns the view instance'); - myView.$el.trigger('click'); - myView.trigger('x'); - - // In IE8 and below, parentNode still exists but is not document.body. - assert.notEqual(myView.el.parentNode, document.body); - }); - - QUnit.test('setElement', function(assert) { - assert.expect(3); - var myView = new Backbone.View({ - events: { - click: function() { assert.ok(false); } - } - }); - myView.events = { - click: function() { assert.ok(true); } - }; - var oldEl = myView.el; - var $oldEl = myView.$el; - - myView.setElement(document.createElement('div')); - - $oldEl.click(); - myView.$el.click(); - - assert.notEqual(oldEl, myView.el); - assert.notEqual($oldEl, myView.$el); - }); - -})(); diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/license.txt b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/license.txt deleted file mode 100644 index ba43b751..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/license.txt +++ /dev/null @@ -1,30 +0,0 @@ -Software License Agreement (BSD License) - -Copyright (c) 2007, Parakey Inc. -All rights reserved. - -Redistribution and use of this software 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 Parakey Inc. nor the names of its - contributors may be used to endorse or promote products - derived from this software without specific prior - written permission of Parakey Inc. - -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 THE COPYRIGHT OWNER 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. diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/blank.gif b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/blank.gif Binary files differdeleted file mode 100644 index 6865c960..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/blank.gif +++ /dev/null diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/buttonBg.png b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/buttonBg.png Binary files differdeleted file mode 100644 index f367b427..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/buttonBg.png +++ /dev/null diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/buttonBgHover.png b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/buttonBgHover.png Binary files differdeleted file mode 100644 index cd37a0d5..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/buttonBgHover.png +++ /dev/null diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/debugger.css b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/debugger.css deleted file mode 100644 index ba55c7ea..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/debugger.css +++ /dev/null @@ -1,331 +0,0 @@ -/* See license.txt for terms of usage */ - -.panelNode-script { - overflow: hidden; - font-family: monospace; -} - -/************************************************************************************************/ - -.scriptTooltip { - position: fixed; - z-index: 2147483647; - padding: 2px 3px; - border: 1px solid #CBE087; - background: LightYellow; - font-family: monospace; - color: #000000; -} - -/************************************************************************************************/ - -.sourceBox { - /* TODO: xxxpedro problem with sourceBox and scrolling elements */ - /*overflow: scroll; /* see issue 1479 */ - position: absolute; - left: 0; - top: 0; - width: 100%; - height: 100%; -} - -.sourceRow { - white-space: nowrap; - -moz-user-select: text; -} - -.sourceRow.hovered { - background-color: #EEEEEE; -} - -/************************************************************************************************/ - -.sourceLine { - -moz-user-select: none; - margin-right: 10px; - border-right: 1px solid #CCCCCC; - padding: 0px 4px 0 20px; - background: #EEEEEE no-repeat 2px 0px; - color: #888888; - white-space: pre; - font-family: monospace; /* see issue 2953 */ -} - -.noteInToolTip { /* below sourceLine, so it overrides it */ - background-color: #FFD472; -} - -.useA11y .sourceBox .sourceViewport:focus .sourceLine { - background-color: #FFFFC0; - color: navy; - border-right: 1px solid black; -} - -.useA11y .sourceBox .sourceViewport:focus { - outline: none; -} - -.a11y1emSize { - width: 1em; - height: 1em; - position: absolute; -} - -.useA11y .panelStatusLabel:focus { - outline-offset: -2px !important; - } - -.sourceBox > .sourceRow > .sourceLine { - cursor: pointer; -} - -.sourceLine:hover { - text-decoration: none; -} - -.sourceRowText { - white-space: pre; -} - -.sourceRow[exe_line="true"] { - outline: 1px solid #D9D9B6; - margin-right: 1px; - background-color: lightgoldenrodyellow; -} - -.sourceRow[executable="true"] > .sourceLine { - content: "-"; - color: #4AA02C; /* Spring Green */ - font-weight: bold; -} - -.sourceRow[exe_line="true"] > .sourceLine { - background-image: url(chrome://firebug/skin/exe.png); - color: #000000; -} - -.sourceRow[breakpoint="true"] > .sourceLine { - background-image: url(chrome://firebug/skin/breakpoint.png); -} - -.sourceRow[breakpoint="true"][condition="true"] > .sourceLine { - background-image: url(chrome://firebug/skin/breakpointCondition.png); -} - -.sourceRow[breakpoint="true"][disabledBreakpoint="true"] > .sourceLine { - background-image: url(chrome://firebug/skin/breakpointDisabled.png); -} - -.sourceRow[breakpoint="true"][exe_line="true"] > .sourceLine { - background-image: url(chrome://firebug/skin/breakpointExe.png); -} - -.sourceRow[breakpoint="true"][exe_line="true"][disabledBreakpoint="true"] > .sourceLine { - background-image: url(chrome://firebug/skin/breakpointDisabledExe.png); -} - -.sourceLine.editing { - background-image: url(chrome://firebug/skin/breakpoint.png); -} - -/************************************************************************************************/ - -.conditionEditor { - z-index: 2147483647; - position: absolute; - margin-top: 0; - left: 2px; - width: 90%; -} - -.conditionEditorInner { - position: relative; - top: -26px; - height: 0; -} - -.conditionCaption { - margin-bottom: 2px; - font-family: Lucida Grande, sans-serif; - font-weight: bold; - font-size: 11px; - color: #226679; -} - -.conditionInput { - width: 100%; - border: 1px solid #0096C0; - font-family: monospace; - font-size: inherit; -} - -.conditionEditorInner1 { - padding-left: 37px; - background: url(condBorders.png) repeat-y; -} - -.conditionEditorInner2 { - padding-right: 25px; - background: url(condBorders.png) repeat-y 100% 0; -} - -.conditionEditorTop1 { - background: url(condCorners.png) no-repeat 100% 0; - margin-left: 37px; - height: 35px; -} - -.conditionEditorTop2 { - position: relative; - left: -37px; - width: 37px; - height: 35px; - background: url(condCorners.png) no-repeat; -} - -.conditionEditorBottom1 { - background: url(condCorners.png) no-repeat 100% 100%; - margin-left: 37px; - height: 33px; -} - -.conditionEditorBottom2 { - position: relative; left: -37px; - width: 37px; - height: 33px; - background: url(condCorners.png) no-repeat 0 100%; -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -.upsideDown { - margin-top: 2px; -} - -.upsideDown .conditionEditorInner { - top: -8px; -} - -.upsideDown .conditionEditorInner1 { - padding-left: 33px; - background: url(condBordersUps.png) repeat-y; -} - -.upsideDown .conditionEditorInner2 { - padding-right: 25px; - background: url(condBordersUps.png) repeat-y 100% 0; -} - -.upsideDown .conditionEditorTop1 { - background: url(condCornersUps.png) no-repeat 100% 0; - margin-left: 33px; - height: 25px; -} - -.upsideDown .conditionEditorTop2 { - position: relative; - left: -33px; - width: 33px; - height: 25px; - background: url(condCornersUps.png) no-repeat; -} - -.upsideDown .conditionEditorBottom1 { - background: url(condCornersUps.png) no-repeat 100% 100%; - margin-left: 33px; - height: 43px; -} - -.upsideDown .conditionEditorBottom2 { - position: relative; - left: -33px; - width: 33px; - height: 43px; - background: url(condCornersUps.png) no-repeat 0 100%; -} - -/************************************************************************************************/ - -.breakpointsGroupListBox { - overflow: hidden; -} - -.breakpointBlockHead { - position: relative; - padding-top: 4px; -} - -.breakpointBlockHead > .checkbox { - margin-right: 4px; -} - -.breakpointBlockHead > .objectLink-sourceLink { - top: 4px; - right: 20px; - background-color: #FFFFFF; /* issue 3308 */ -} - -.breakpointBlockHead > .closeButton { - position: absolute; - top: 2px; - right: 2px; -} - -.breakpointCheckbox { - margin-top: 0; - vertical-align: top; -} - -.breakpointName { - margin-left: 4px; - font-weight: bold; -} - -.breakpointRow[aria-checked="false"] > .breakpointBlockHead > *, -.breakpointRow[aria-checked="false"] > .breakpointCode { - opacity: 0.5; -} - -.breakpointRow[aria-checked="false"] .breakpointCheckbox, -.breakpointRow[aria-checked="false"] .objectLink-sourceLink, -.breakpointRow[aria-checked="false"] .closeButton, -.breakpointRow[aria-checked="false"] .breakpointMutationType { - opacity: 1.0 !important; -} - -.breakpointCode { - overflow: hidden; - white-space: nowrap; - padding-left: 24px; - padding-bottom: 2px; - border-bottom: 1px solid #D7D7D7; - font-family: monospace; - color: DarkGreen; -} - -.breakpointCondition { - white-space: nowrap; - padding-left: 24px; - padding-bottom: 2px; - border-bottom: 1px solid #D7D7D7; - font-family: monospace; - color: Gray; -} - -.breakpointBlock-breakpoints > .groupHeader { - display: none; -} - -.breakpointBlock-monitors > .breakpointCode { - padding: 0; -} - -.breakpointBlock-errorBreakpoints .breakpointCheckbox, -.breakpointBlock-monitors .breakpointCheckbox { - display: none; -} - -.breakpointHeader { - margin: 0 !important; - border-top: none !important; -} diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/detach.png b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/detach.png Binary files differdeleted file mode 100644 index 0ddb9a17..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/detach.png +++ /dev/null diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/detachHover.png b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/detachHover.png Binary files differdeleted file mode 100644 index e4192729..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/detachHover.png +++ /dev/null diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/disable.gif b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/disable.gif Binary files differdeleted file mode 100644 index dd9eb0e3..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/disable.gif +++ /dev/null diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/disable.png b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/disable.png Binary files differdeleted file mode 100644 index c28bcdf2..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/disable.png +++ /dev/null diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/disableHover.gif b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/disableHover.gif Binary files differdeleted file mode 100644 index 70565a83..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/disableHover.gif +++ /dev/null diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/disableHover.png b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/disableHover.png Binary files differdeleted file mode 100644 index 26fe3754..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/disableHover.png +++ /dev/null diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/down.png b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/down.png Binary files differdeleted file mode 100644 index acbbd30c..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/down.png +++ /dev/null diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/downActive.png b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/downActive.png Binary files differdeleted file mode 100644 index f4312b2f..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/downActive.png +++ /dev/null diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/downHover.png b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/downHover.png Binary files differdeleted file mode 100644 index 8144e637..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/downHover.png +++ /dev/null diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/errorIcon-sm.png b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/errorIcon-sm.png Binary files differdeleted file mode 100644 index 0c377e30..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/errorIcon-sm.png +++ /dev/null diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/errorIcon.gif b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/errorIcon.gif Binary files differdeleted file mode 100644 index 8ee8116a..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/errorIcon.gif +++ /dev/null diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/errorIcon.png b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/errorIcon.png Binary files differdeleted file mode 100644 index 2d75261b..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/errorIcon.png +++ /dev/null diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/firebug-1.3a2.css b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/firebug-1.3a2.css deleted file mode 100644 index 42f9faf5..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/firebug-1.3a2.css +++ /dev/null @@ -1,817 +0,0 @@ -.fbBtnPressed { - background: #ECEBE3; - padding: 3px 6px 2px 7px !important; - margin: 1px 0 0 1px; - _margin: 1px -1px 0 1px; - border: 1px solid #ACA899 !important; - border-color: #ACA899 #ECEBE3 #ECEBE3 #ACA899 !important; -} - -.fbToolbarButtons { - display: none; -} - -#fbStatusBarBox { - display: none; -} - -/************************************************************************************************ - Error Popup -*************************************************************************************************/ -#fbErrorPopup { - position: absolute; - right: 0; - bottom: 0; - height: 19px; - width: 75px; - background: url(sprite.png) #f1f2ee 0 0; - z-index: 999; -} - -#fbErrorPopupContent { - position: absolute; - right: 0; - top: 1px; - height: 18px; - width: 75px; - _width: 74px; - border-left: 1px solid #aca899; -} - -#fbErrorIndicator { - position: absolute; - top: 2px; - right: 5px; -} - - - - - - - - - - -.fbBtnInspectActive { - background: #aaa; - color: #fff !important; -} - -/************************************************************************************************ - General -*************************************************************************************************/ -html, body { - margin: 0; - padding: 0; - overflow: hidden; -} - -body { - font-family: Lucida Grande, Tahoma, sans-serif; - font-size: 11px; - background: #fff; -} - -.clear { - clear: both; -} - -/************************************************************************************************ - Mini Chrome -*************************************************************************************************/ -#fbMiniChrome { - display: none; - right: 0; - height: 27px; - background: url(sprite.png) #f1f2ee 0 0; - margin-left: 1px; -} - -#fbMiniContent { - display: block; - position: relative; - left: -1px; - right: 0; - top: 1px; - height: 25px; - border-left: 1px solid #aca899; -} - -#fbToolbarSearch { - float: right; - border: 1px solid #ccc; - margin: 0 5px 0 0; - background: #fff url(search.png) no-repeat 4px 2px; - padding-left: 20px; - font-size: 11px; -} - -#fbToolbarErrors { - float: right; - margin: 1px 4px 0 0; - font-size: 11px; -} - -#fbLeftToolbarErrors { - float: left; - margin: 7px 0px 0 5px; - font-size: 11px; -} - -.fbErrors { - padding-left: 20px; - height: 14px; - background: url(errorIcon.png) no-repeat; - color: #f00; - font-weight: bold; -} - -#fbMiniErrors { - display: inline; - display: none; - float: right; - margin: 5px 2px 0 5px; -} - -#fbMiniIcon { - float: right; - margin: 3px 4px 0; - height: 20px; - width: 20px; - float: right; - background: url(sprite.png) 0 -135px; - cursor: pointer; -} - - -/************************************************************************************************ - Master Layout -*************************************************************************************************/ -#fbChrome { - position: fixed; - overflow: hidden; - height: 100%; - width: 100%; - border-collapse: collapse; - background: #fff; -} - -#fbTop { - height: 49px; -} - -#fbToolbar { - position: absolute; - z-index: 5; - width: 100%; - top: 0; - background: url(sprite.png) #f1f2ee 0 0; - height: 27px; - font-size: 11px; - overflow: hidden; -} - -#fbPanelBarBox { - top: 27px; - position: absolute; - z-index: 8; - width: 100%; - background: url(sprite.png) #dbd9c9 0 -27px; - height: 22px; -} - -#fbContent { - height: 100%; - vertical-align: top; -} - -#fbBottom { - height: 18px; - background: #fff; -} - -/************************************************************************************************ - Sub-Layout -*************************************************************************************************/ - -/* fbToolbar -*************************************************************************************************/ -#fbToolbarIcon { - float: left; - padding: 4px 5px 0; -} - -#fbToolbarIcon a { - display: block; - height: 20px; - width: 20px; - background: url(sprite.png) 0 -135px; - text-decoration: none; - cursor: default; -} - -#fbToolbarButtons { - float: left; - padding: 4px 2px 0 5px; -} - -#fbToolbarButtons a { - text-decoration: none; - display: block; - float: left; - color: #000; - padding: 4px 8px 4px; - cursor: default; -} - -#fbToolbarButtons a:hover { - color: #333; - padding: 3px 7px 3px; - border: 1px solid #fff; - border-bottom: 1px solid #bbb; - border-right: 1px solid #bbb; -} - -#fbStatusBarBox { - position: relative; - top: 5px; - line-height: 19px; - cursor: default; -} - -.fbToolbarSeparator{ - overflow: hidden; - border: 1px solid; - border-color: transparent #fff transparent #777; - _border-color: #eee #fff #eee #777; - height: 7px; - margin: 10px 6px 0 0; - float: left; -} - -.fbStatusBar span { - color: #808080; - padding: 0 4px 0 0; -} - -.fbStatusBar span a { - text-decoration: none; - color: black; -} - -.fbStatusBar span a:hover { - color: blue; - cursor: pointer; -} - - -#fbWindowButtons { - position: absolute; - white-space: nowrap; - right: 0; - top: 0; - height: 17px; - _width: 50px; - padding: 5px 0 5px 5px; - z-index: 6; - background: url(sprite.png) #f1f2ee 0 0; -} - -/* fbPanelBarBox -*************************************************************************************************/ - -#fbPanelBar1 { - width: 255px; /* fixed width to avoid tabs breaking line */ - z-index: 8; - left: 0; - white-space: nowrap; - background: url(sprite.png) #dbd9c9 0 -27px; - position: absolute; - left: 4px; -} - -#fbPanelBar2Box { - background: url(sprite.png) #dbd9c9 0 -27px; - position: absolute; - height: 22px; - width: 300px; /* fixed width to avoid tabs breaking line */ - z-index: 9; - right: 0; -} - -#fbPanelBar2 { - position: absolute; - width: 290px; /* fixed width to avoid tabs breaking line */ - height: 22px; - padding-left: 10px; -} - -/* body -*************************************************************************************************/ -.fbPanel { - display: none; -} - -#fbPanelBox1, #fbPanelBox2 { - max-height: inherit; - height: 100%; - font-size: 11px; -} - -#fbPanelBox2 { - background: #fff; -} - -#fbPanelBox2 { - width: 300px; - background: #fff; -} - -#fbPanel2 { - padding-left: 6px; - background: #fff; -} - -.hide { - overflow: hidden !important; - position: fixed !important; - display: none !important; - visibility: hidden !important; -} - -/* fbBottom -*************************************************************************************************/ - -#fbCommand { - height: 18px; -} - -#fbCommandBox { - position: absolute; - width: 100%; - height: 18px; - bottom: 0; - overflow: hidden; - z-index: 9; - background: #fff; - border: 0; - border-top: 1px solid #ccc; -} - -#fbCommandIcon { - position: absolute; - color: #00f; - top: 2px; - left: 7px; - display: inline; - font: 11px Monaco, monospace; - z-index: 10; -} - -#fbCommandLine { - position: absolute; - width: 100%; - top: 0; - left: 0; - border: 0; - margin: 0; - padding: 2px 0 2px 32px; - font: 11px Monaco, monospace; - z-index: 9; -} - -div.fbFitHeight { - overflow: auto; - _position: absolute; -} - - -/************************************************************************************************ - Layout Controls -*************************************************************************************************/ - -/* fbToolbar buttons -*************************************************************************************************/ -#fbWindowButtons a { - font-size: 1px; - width: 16px; - height: 16px; - display: block; - float: right; - margin-right: 4px; - text-decoration: none; - cursor: default; -} - -#fbWindow_btClose { - background: url(sprite.png) 0 -119px; -} - -#fbWindow_btClose:hover { - background: url(sprite.png) -16px -119px; -} - -#fbWindow_btDetach { - background: url(sprite.png) -32px -119px; -} - -#fbWindow_btDetach:hover { - background: url(sprite.png) -48px -119px; -} - -/* fbPanelBarBox tabs -*************************************************************************************************/ -.fbTab { - text-decoration: none; - display: none; - float: left; - width: auto; - float: left; - cursor: default; - font-family: Lucida Grande, Tahoma, sans-serif; - font-size: 11px; - font-weight: bold; - height: 22px; - color: #565656; -} - -.fbPanelBar span { - display: block; - float: left; -} - -.fbPanelBar .fbTabL,.fbPanelBar .fbTabR { - height: 22px; - width: 8px; -} - -.fbPanelBar .fbTabText { - padding: 4px 1px 0; -} - -a.fbTab:hover { - background: url(sprite.png) 0 -73px; -} - -a.fbTab:hover .fbTabL { - background: url(sprite.png) -16px -96px; -} - -a.fbTab:hover .fbTabR { - background: url(sprite.png) -24px -96px; -} - -.fbSelectedTab { - background: url(sprite.png) #f1f2ee 0 -50px !important; - color: #000; -} - -.fbSelectedTab .fbTabL { - background: url(sprite.png) 0 -96px !important; -} - -.fbSelectedTab .fbTabR { - background: url(sprite.png) -8px -96px !important; -} - -/* splitters -*************************************************************************************************/ -#fbHSplitter { - position: absolute; - left: 0; - top: 0; - width: 100%; - height: 5px; - overflow: hidden; - cursor: n-resize !important; - background: url(pixel_transparent.gif); - z-index: 9; -} - -#fbHSplitter.fbOnMovingHSplitter { - height: 100%; - z-index: 100; -} - -.fbVSplitter { - background: #ece9d8; - color: #000; - border: 1px solid #716f64; - border-width: 0 1px; - border-left-color: #aca899; - width: 4px; - cursor: e-resize; - overflow: hidden; - right: 294px; - text-decoration: none; - z-index: 9; - position: absolute; - height: 100%; - top: 27px; - _width: 6px; -} - -/************************************************************************************************/ -div.lineNo { - font: 11px Monaco, monospace; - float: left; - display: inline; - position: relative; - margin: 0; - padding: 0 5px 0 20px; - background: #eee; - color: #888; - border-right: 1px solid #ccc; - text-align: right; -} - -pre.nodeCode { - font: 11px Monaco, monospace; - margin: 0; - padding-left: 10px; - overflow: hidden; - /* - _width: 100%; - /**/ -} - -/************************************************************************************************/ -.nodeControl { - margin-top: 3px; - margin-left: -14px; - float: left; - width: 9px; - height: 9px; - overflow: hidden; - cursor: default; - background: url(tree_open.gif); - _float: none; - _display: inline; - _position: absolute; -} - -div.nodeMaximized { - background: url(tree_close.gif); -} - -div.objectBox-element { - padding: 1px 3px; -} -.objectBox-selector{ - cursor: default; -} - -.selectedElement{ - background: highlight; - /* background: url(roundCorner.svg); Opera */ - color: #fff !important; -} -.selectedElement span{ - color: #fff !important; -} - -/* Webkit CSS Hack - bug in "highlight" named color */ -@media screen and (-webkit-min-device-pixel-ratio:0) { - .selectedElement{ - background: #316AC5; - color: #fff !important; - } -} - -/************************************************************************************************/ -/************************************************************************************************/ -.logRow * { - font-size: 11px; -} - -.logRow { - position: relative; - border-bottom: 1px solid #D7D7D7; - padding: 2px 4px 1px 6px; - background-color: #FFFFFF; -} - -.logRow-command { - font-family: Monaco, monospace; - color: blue; -} - -.objectBox-string, -.objectBox-text, -.objectBox-number, -.objectBox-function, -.objectLink-element, -.objectLink-textNode, -.objectLink-function, -.objectBox-stackTrace, -.objectLink-profile { - font-family: Monaco, monospace; -} - -.objectBox-null { - padding: 0 2px; - border: 1px solid #666666; - background-color: #888888; - color: #FFFFFF; -} - -.objectBox-string { - color: red; - white-space: pre; -} - -.objectBox-number { - color: #000088; -} - -.objectBox-function { - color: DarkGreen; -} - -.objectBox-object { - color: DarkGreen; - font-weight: bold; - font-family: Lucida Grande, sans-serif; -} - -.objectBox-array { - color: #000; -} - -/************************************************************************************************/ -.logRow-info,.logRow-error,.logRow-warning { - background: #fff no-repeat 2px 2px; - padding-left: 20px; - padding-bottom: 3px; -} - -.logRow-info { - background-image: url(infoIcon.png); -} - -.logRow-warning { - background-color: cyan; - background-image: url(warningIcon.png); -} - -.logRow-error { - background-color: LightYellow; - background-image: url(errorIcon.png); - color: #f00; -} - -.errorMessage { - vertical-align: top; - color: #f00; -} - -.objectBox-sourceLink { - position: absolute; - right: 4px; - top: 2px; - padding-left: 8px; - font-family: Lucida Grande, sans-serif; - font-weight: bold; - color: #0000FF; -} - -/************************************************************************************************/ -.logRow-group { - background: #EEEEEE; - border-bottom: none; -} - -.logGroup { - background: #EEEEEE; -} - -.logGroupBox { - margin-left: 24px; - border-top: 1px solid #D7D7D7; - border-left: 1px solid #D7D7D7; -} - -/************************************************************************************************/ -.selectorTag,.selectorId,.selectorClass { - font-family: Monaco, monospace; - font-weight: normal; -} - -.selectorTag { - color: #0000FF; -} - -.selectorId { - color: DarkBlue; -} - -.selectorClass { - color: red; -} - -/************************************************************************************************/ -.objectBox-element { - font-family: Monaco, monospace; - color: #000088; -} - -.nodeChildren { - padding-left: 26px; -} - -.nodeTag { - color: blue; - cursor: pointer; -} - -.nodeValue { - color: #FF0000; - font-weight: normal; -} - -.nodeText,.nodeComment { - margin: 0 2px; - vertical-align: top; -} - -.nodeText { - color: #333333; - font-family: Monaco, monospace; -} - -.nodeComment { - color: DarkGreen; -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -.nodeHidden, .nodeHidden * { - color: #888888; -} - -.nodeHidden .nodeTag { - color: #5F82D9; -} - -.nodeHidden .nodeValue { - color: #D86060; -} - -.selectedElement .nodeHidden, .selectedElement .nodeHidden * { - color: SkyBlue !important; -} - - -/************************************************************************************************/ -.log-object { - /* - _position: relative; - _height: 100%; - /**/ -} - -.property { - position: relative; - clear: both; - height: 15px; -} - -.propertyNameCell { - vertical-align: top; - float: left; - width: 28%; - position: absolute; - left: 0; - z-index: 0; -} - -.propertyValueCell { - float: right; - width: 68%; - background: #fff; - position: absolute; - padding-left: 5px; - display: table-cell; - right: 0; - z-index: 1; - /* - _position: relative; - /**/ -} - -.propertyName { - font-weight: bold; -} - -.FirebugPopup { - height: 100% !important; -} - -.FirebugPopup #fbWindowButtons { - display: none !important; -} - -.FirebugPopup #fbHSplitter { - display: none !important; -} diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/firebug.IE6.css b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/firebug.IE6.css deleted file mode 100644 index 13a41d28..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/firebug.IE6.css +++ /dev/null @@ -1,20 +0,0 @@ -/************************************************************************************************/ -#fbToolbarSearch { - background-image: url(search.gif) !important; -} -/************************************************************************************************/ -.fbErrors { - background-image: url(errorIcon.gif) !important; -} -/************************************************************************************************/ -.logRow-info { - background-image: url(infoIcon.gif) !important; -} - -.logRow-warning { - background-image: url(warningIcon.gif) !important; -} - -.logRow-error { - background-image: url(errorIcon.gif) !important; -} diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/firebug.css b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/firebug.css deleted file mode 100644 index a1465ec5..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/firebug.css +++ /dev/null @@ -1,3147 +0,0 @@ -/*************************************************************************************************/ -/*************************************************************************************************/ -/*************************************************************************************************/ -/*************************************************************************************************/ -/* Loose */ -/*************************************************************************************************/ -/*************************************************************************************************/ -/*************************************************************************************************/ -/* -.netInfoResponseHeadersTitle, netInfoResponseHeadersBody { - display: none; -} -/**/ - -.obscured { - left: -999999px !important; -} - -/* IE6 need a separated rule, otherwise it will not recognize it */ -.collapsed { - display: none; -} - -[collapsed="true"] { - display: none; -} - -#fbCSS { - padding: 0 !important; -} - -.cssPropDisable { - float: left; - display: block; - width: 2em; - cursor: default; -} - -/*************************************************************************************************/ -/*************************************************************************************************/ -/*************************************************************************************************/ -/*************************************************************************************************/ -/* panelBase */ -/*************************************************************************************************/ -/*************************************************************************************************/ -/*************************************************************************************************/ - -/************************************************************************************************/ - -.infoTip { - z-index: 2147483647; - position: fixed; - padding: 2px 3px; - border: 1px solid #CBE087; - background: LightYellow; - font-family: Monaco, monospace; - color: #000000; - display: none; - white-space: nowrap; - pointer-events: none; -} - -.infoTip[active="true"] { - display: block; -} - -.infoTipLoading { - width: 16px; - height: 16px; - background: url(chrome://firebug/skin/loading_16.gif) no-repeat; -} - -.infoTipImageBox { - font-size: 11px; - min-width: 100px; - text-align: center; -} - -.infoTipCaption { - font-size: 11px; - font: Monaco, monospace; -} - -.infoTipLoading > .infoTipImage, -.infoTipLoading > .infoTipCaption { - display: none; -} - -/************************************************************************************************/ - -h1.groupHeader { - padding: 2px 4px; - margin: 0 0 4px 0; - border-top: 1px solid #CCCCCC; - border-bottom: 1px solid #CCCCCC; - background: #eee url(group.gif) repeat-x; - font-size: 11px; - font-weight: bold; - _position: relative; -} - -/************************************************************************************************/ - -.inlineEditor, -.fixedWidthEditor { - z-index: 2147483647; - position: absolute; - display: none; -} - -.inlineEditor { - margin-left: -6px; - margin-top: -3px; - /* - _margin-left: -7px; - _margin-top: -5px; - /**/ -} - -.textEditorInner, -.fixedWidthEditor { - margin: 0 0 0 0 !important; - padding: 0; - border: none !important; - font: inherit; - text-decoration: inherit; - background-color: #FFFFFF; -} - -.fixedWidthEditor { - border-top: 1px solid #888888 !important; - border-bottom: 1px solid #888888 !important; -} - -.textEditorInner { - position: relative; - top: -7px; - left: -5px; - - outline: none; - resize: none; - - /* - _border: 1px solid #999 !important; - _padding: 1px !important; - _filter:progid:DXImageTransform.Microsoft.dropshadow(OffX=2, OffY=2, Color="#55404040"); - /**/ -} - -.textEditorInner1 { - padding-left: 11px; - background: url(textEditorBorders.png) repeat-y; - _background: url(textEditorBorders.gif) repeat-y; - _overflow: hidden; -} - -.textEditorInner2 { - position: relative; - padding-right: 2px; - background: url(textEditorBorders.png) repeat-y 100% 0; - _background: url(textEditorBorders.gif) repeat-y 100% 0; - _position: fixed; -} - -.textEditorTop1 { - background: url(textEditorCorners.png) no-repeat 100% 0; - margin-left: 11px; - height: 10px; - _background: url(textEditorCorners.gif) no-repeat 100% 0; - _overflow: hidden; -} - -.textEditorTop2 { - position: relative; - left: -11px; - width: 11px; - height: 10px; - background: url(textEditorCorners.png) no-repeat; - _background: url(textEditorCorners.gif) no-repeat; -} - -.textEditorBottom1 { - position: relative; - background: url(textEditorCorners.png) no-repeat 100% 100%; - margin-left: 11px; - height: 12px; - _background: url(textEditorCorners.gif) no-repeat 100% 100%; -} - -.textEditorBottom2 { - position: relative; - left: -11px; - width: 11px; - height: 12px; - background: url(textEditorCorners.png) no-repeat 0 100%; - _background: url(textEditorCorners.gif) no-repeat 0 100%; -} - - -/*************************************************************************************************/ -/*************************************************************************************************/ -/*************************************************************************************************/ -/*************************************************************************************************/ -/* CSS */ -/*************************************************************************************************/ -/*************************************************************************************************/ -/*************************************************************************************************/ - -/* See license.txt for terms of usage */ - -.panelNode-css { - overflow-x: hidden; -} - -.cssSheet > .insertBefore { - height: 1.5em; -} - -.cssRule { - position: relative; - margin: 0; - padding: 1em 0 0 6px; - font-family: Monaco, monospace; - color: #000000; -} - -.cssRule:first-child { - padding-top: 6px; -} - -.cssElementRuleContainer { - position: relative; -} - -.cssHead { - padding-right: 150px; -} - -.cssProp { - /*padding-left: 2em;*/ -} - -.cssPropName { - color: DarkGreen; -} - -.cssPropValue { - margin-left: 8px; - color: DarkBlue; -} - -.cssOverridden span { - text-decoration: line-through; -} - -.cssInheritedRule { -} - -.cssInheritLabel { - margin-right: 0.5em; - font-weight: bold; -} - -.cssRule .objectLink-sourceLink { - top: 0; -} - -.cssProp.editGroup:hover { - background: url(disable.png) no-repeat 2px 1px; - _background: url(disable.gif) no-repeat 2px 1px; -} - -.cssProp.editGroup.editing { - background: none; -} - -.cssProp.disabledStyle { - background: url(disableHover.png) no-repeat 2px 1px; - _background: url(disableHover.gif) no-repeat 2px 1px; - opacity: 1; - color: #CCCCCC; -} - -.disabledStyle .cssPropName, -.disabledStyle .cssPropValue { - color: #CCCCCC; -} - -.cssPropValue.editing + .cssSemi, -.inlineExpander + .cssSemi { - display: none; -} - -.cssPropValue.editing { - white-space: nowrap; -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -.stylePropName { - font-weight: bold; - padding: 0 4px 4px 4px; - width: 50%; -} - -.stylePropValue { - width: 50%; -} -/* -.useA11y .a11yCSSView .focusRow:focus { - outline: none; - background-color: transparent - } - - .useA11y .a11yCSSView .focusRow:focus .cssSelector, - .useA11y .a11yCSSView .focusRow:focus .cssPropName, - .useA11y .a11yCSSView .focusRow:focus .cssPropValue, - .useA11y .a11yCSSView .computedStyleRow:focus, - .useA11y .a11yCSSView .groupHeader:focus { - outline: 2px solid #FF9933; - outline-offset: -2px; - background-color: #FFFFD6; - } - - .useA11y .a11yCSSView .groupHeader:focus { - outline-offset: -2px; - } -/**/ - - -/*************************************************************************************************/ -/*************************************************************************************************/ -/*************************************************************************************************/ -/*************************************************************************************************/ -/* Net */ -/*************************************************************************************************/ -/*************************************************************************************************/ -/*************************************************************************************************/ - -/* See license.txt for terms of usage */ - -.panelNode-net { - overflow-x: hidden; -} - -.netTable { - width: 100%; -} - -/************************************************************************************************/ - -.hideCategory-undefined .category-undefined, -.hideCategory-html .category-html, -.hideCategory-css .category-css, -.hideCategory-js .category-js, -.hideCategory-image .category-image, -.hideCategory-xhr .category-xhr, -.hideCategory-flash .category-flash, -.hideCategory-txt .category-txt, -.hideCategory-bin .category-bin { - display: none; -} - -/************************************************************************************************/ - -.netHeadRow { - background: url(chrome://firebug/skin/group.gif) repeat-x #FFFFFF; -} - -.netHeadCol { - border-bottom: 1px solid #CCCCCC; - padding: 2px 4px 2px 18px; - font-weight: bold; -} - -.netHeadLabel { - white-space: nowrap; - overflow: hidden; -} - -/************************************************************************************************/ -/* Header for Net panel table */ - -.netHeaderRow { - height: 16px; -} - -.netHeaderCell { - cursor: pointer; - -moz-user-select: none; - border-bottom: 1px solid #9C9C9C; - padding: 0 !important; - font-weight: bold; - background: #BBBBBB url(chrome://firebug/skin/tableHeader.gif) repeat-x; - white-space: nowrap; -} - -.netHeaderRow > .netHeaderCell:first-child > .netHeaderCellBox { - padding: 2px 14px 2px 18px; -} - -.netHeaderCellBox { - padding: 2px 14px 2px 10px; - border-left: 1px solid #D9D9D9; - border-right: 1px solid #9C9C9C; -} - -.netHeaderCell:hover:active { - background: #959595 url(chrome://firebug/skin/tableHeaderActive.gif) repeat-x; -} - -.netHeaderSorted { - background: #7D93B2 url(chrome://firebug/skin/tableHeaderSorted.gif) repeat-x; -} - -.netHeaderSorted > .netHeaderCellBox { - border-right-color: #6B7C93; - background: url(chrome://firebug/skin/arrowDown.png) no-repeat right; -} - -.netHeaderSorted.sortedAscending > .netHeaderCellBox { - background-image: url(chrome://firebug/skin/arrowUp.png); -} - -.netHeaderSorted:hover:active { - background: #536B90 url(chrome://firebug/skin/tableHeaderSortedActive.gif) repeat-x; -} - -/************************************************************************************************/ -/* Breakpoints */ - -.panelNode-net .netRowHeader { - display: block; -} - -.netRowHeader { - cursor: pointer; - display: none; - height: 15px; - margin-right: 0 !important; -} - -/* Display brekpoint disc */ -.netRow .netRowHeader { - background-position: 5px 1px; -} - -.netRow[breakpoint="true"] .netRowHeader { - background-image: url(chrome://firebug/skin/breakpoint.png); -} - -.netRow[breakpoint="true"][disabledBreakpoint="true"] .netRowHeader { - background-image: url(chrome://firebug/skin/breakpointDisabled.png); -} - -.netRow.category-xhr:hover .netRowHeader { - background-color: #F6F6F6; -} - -#netBreakpointBar { - max-width: 38px; -} - -#netHrefCol > .netHeaderCellBox { - border-left: 0px; -} - -.netRow .netRowHeader { - width: 3px; -} - -.netInfoRow .netRowHeader { - display: table-cell; -} - -/************************************************************************************************/ -/* Column visibility */ - -.netTable[hiddenCols~=netHrefCol] TD[id="netHrefCol"], -.netTable[hiddenCols~=netHrefCol] TD.netHrefCol, -.netTable[hiddenCols~=netStatusCol] TD[id="netStatusCol"], -.netTable[hiddenCols~=netStatusCol] TD.netStatusCol, -.netTable[hiddenCols~=netDomainCol] TD[id="netDomainCol"], -.netTable[hiddenCols~=netDomainCol] TD.netDomainCol, -.netTable[hiddenCols~=netSizeCol] TD[id="netSizeCol"], -.netTable[hiddenCols~=netSizeCol] TD.netSizeCol, -.netTable[hiddenCols~=netTimeCol] TD[id="netTimeCol"], -.netTable[hiddenCols~=netTimeCol] TD.netTimeCol { - display: none; -} - -/************************************************************************************************/ - -.netRow { - background: LightYellow; -} - -.netRow.loaded { - background: #FFFFFF; -} - -.netRow.loaded:hover { - background: #EFEFEF; -} - -.netCol { - padding: 0; - vertical-align: top; - border-bottom: 1px solid #EFEFEF; - white-space: nowrap; - height: 17px; -} - -.netLabel { - width: 100%; -} - -.netStatusCol { - padding-left: 10px; - color: rgb(128, 128, 128); -} - -.responseError > .netStatusCol { - color: red; -} - -.netDomainCol { - padding-left: 5px; -} - -.netSizeCol { - text-align: right; - padding-right: 10px; -} - -.netHrefLabel { - -moz-box-sizing: padding-box; - overflow: hidden; - z-index: 10; - position: absolute; - padding-left: 18px; - padding-top: 1px; - max-width: 15%; - font-weight: bold; -} - -.netFullHrefLabel { - display: none; - -moz-user-select: none; - padding-right: 10px; - padding-bottom: 3px; - max-width: 100%; - background: #FFFFFF; - z-index: 200; -} - -.netHrefCol:hover > .netFullHrefLabel { - display: block; -} - -.netRow.loaded:hover .netCol > .netFullHrefLabel { - background-color: #EFEFEF; -} - -.useA11y .a11yShowFullLabel { - display: block; - background-image: none !important; - border: 1px solid #CBE087; - background-color: LightYellow; - font-family: Monaco, monospace; - color: #000000; - font-size: 10px; - z-index: 2147483647; -} - -.netSizeLabel { - padding-left: 6px; -} - -.netStatusLabel, -.netDomainLabel, -.netSizeLabel, -.netBar { - padding: 1px 0 2px 0 !important; -} - -.responseError { - color: red; -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -.hasHeaders .netHrefLabel:hover { - cursor: pointer; - color: blue; - text-decoration: underline; -} - -/************************************************************************************************/ - -.netLoadingIcon { - position: absolute; - border: 0; - margin-left: 14px; - width: 16px; - height: 16px; - background: transparent no-repeat 0 0; - background-image: url(chrome://firebug/skin/loading_16.gif); - display:inline-block; -} - -.loaded .netLoadingIcon { - display: none; -} - -/************************************************************************************************/ - -.netBar, .netSummaryBar { - position: relative; - border-right: 50px solid transparent; -} - -.netResolvingBar { - position: absolute; - left: 0; - top: 0; - bottom: 0; - background: #FFFFFF url(chrome://firebug/skin/netBarResolving.gif) repeat-x; - z-index:60; -} - -.netConnectingBar { - position: absolute; - left: 0; - top: 0; - bottom: 0; - background: #FFFFFF url(chrome://firebug/skin/netBarConnecting.gif) repeat-x; - z-index:50; -} - -.netBlockingBar { - position: absolute; - left: 0; - top: 0; - bottom: 0; - background: #FFFFFF url(chrome://firebug/skin/netBarWaiting.gif) repeat-x; - z-index:40; -} - -.netSendingBar { - position: absolute; - left: 0; - top: 0; - bottom: 0; - background: #FFFFFF url(chrome://firebug/skin/netBarSending.gif) repeat-x; - z-index:30; -} - -.netWaitingBar { - position: absolute; - left: 0; - top: 0; - bottom: 0; - background: #FFFFFF url(chrome://firebug/skin/netBarResponded.gif) repeat-x; - z-index:20; - min-width: 1px; -} - -.netReceivingBar { - position: absolute; - left: 0; - top: 0; - bottom: 0; - background: #38D63B url(chrome://firebug/skin/netBarLoading.gif) repeat-x; - z-index:10; -} - -.netWindowLoadBar, -.netContentLoadBar { - position: absolute; - left: 0; - top: 0; - bottom: 0; - width: 1px; - background-color: red; - z-index: 70; - opacity: 0.5; - display: none; - margin-bottom:-1px; -} - -.netContentLoadBar { - background-color: Blue; -} - -.netTimeLabel { - -moz-box-sizing: padding-box; - position: absolute; - top: 1px; - left: 100%; - padding-left: 6px; - color: #444444; - min-width: 16px; -} - -/* - * Timing info tip is reusing net timeline styles to display the same - * colors for individual request phases. Notice that the info tip must - * respect also loaded and fromCache styles that also modify the - * actual color. These are used both on the same element in case - * of the tooltip. - */ -.loaded .netReceivingBar, -.loaded.netReceivingBar { - background: #B6B6B6 url(chrome://firebug/skin/netBarLoaded.gif) repeat-x; - border-color: #B6B6B6; -} - -.fromCache .netReceivingBar, -.fromCache.netReceivingBar { - background: #D6D6D6 url(chrome://firebug/skin/netBarCached.gif) repeat-x; - border-color: #D6D6D6; -} - -.netSummaryRow .netTimeLabel, -.loaded .netTimeLabel { - background: transparent; -} - -/************************************************************************************************/ -/* Time Info tip */ - -.timeInfoTip { - width: 150px; - height: 40px -} - -.timeInfoTipBar, -.timeInfoTipEventBar { - position: relative; - display: block; - margin: 0; - opacity: 1; - height: 15px; - width: 4px; -} - -.timeInfoTipEventBar { - width: 1px !important; -} - -.timeInfoTipCell.startTime { - padding-right: 8px; -} - -.timeInfoTipCell.elapsedTime { - text-align: right; - padding-right: 8px; -} - -/************************************************************************************************/ -/* Size Info tip */ - -.sizeInfoLabelCol { - font-weight: bold; - padding-right: 10px; - font-family: Lucida Grande, Tahoma, sans-serif; - font-size: 11px; -} - -.sizeInfoSizeCol { - font-weight: bold; -} - -.sizeInfoDetailCol { - color: gray; - text-align: right; -} - -.sizeInfoDescCol { - font-style: italic; -} - -/************************************************************************************************/ -/* Summary */ - -.netSummaryRow .netReceivingBar { - background: #BBBBBB; - border: none; -} - -.netSummaryLabel { - color: #222222; -} - -.netSummaryRow { - background: #BBBBBB !important; - font-weight: bold; -} - -.netSummaryRow .netBar { - border-right-color: #BBBBBB; -} - -.netSummaryRow > .netCol { - border-top: 1px solid #999999; - border-bottom: 2px solid; - -moz-border-bottom-colors: #EFEFEF #999999; - padding-top: 1px; - padding-bottom: 2px; -} - -.netSummaryRow > .netHrefCol:hover { - background: transparent !important; -} - -.netCountLabel { - padding-left: 18px; -} - -.netTotalSizeCol { - text-align: right; - padding-right: 10px; -} - -.netTotalTimeCol { - text-align: right; -} - -.netCacheSizeLabel { - position: absolute; - z-index: 1000; - left: 0; - top: 0; -} - -/************************************************************************************************/ - -.netLimitRow { - background: rgb(255, 255, 225) !important; - font-weight:normal; - color: black; - font-weight:normal; -} - -.netLimitLabel { - padding-left: 18px; -} - -.netLimitRow > .netCol { - border-bottom: 2px solid; - -moz-border-bottom-colors: #EFEFEF #999999; - vertical-align: middle !important; - padding-top: 2px; - padding-bottom: 2px; -} - -.netLimitButton { - font-size: 11px; - padding-top: 1px; - padding-bottom: 1px; -} - -/************************************************************************************************/ - -.netInfoCol { - border-top: 1px solid #EEEEEE; - background: url(chrome://firebug/skin/group.gif) repeat-x #FFFFFF; -} - -.netInfoBody { - margin: 10px 0 4px 10px; -} - -.netInfoTabs { - position: relative; - padding-left: 17px; -} - -.netInfoTab { - position: relative; - top: -3px; - margin-top: 10px; - padding: 4px 6px; - border: 1px solid transparent; - border-bottom: none; - _border: none; - font-weight: bold; - color: #565656; - cursor: pointer; -} - -/*.netInfoTab:hover { - cursor: pointer; -}*/ - -/* replaced by .netInfoTabSelected for IE6 support -.netInfoTab[selected="true"] { - cursor: default !important; - border: 1px solid #D7D7D7 !important; - border-bottom: none !important; - -moz-border-radius: 4px 4px 0 0; - background-color: #FFFFFF; -} -/**/ -.netInfoTabSelected { - cursor: default !important; - border: 1px solid #D7D7D7 !important; - border-bottom: none !important; - -moz-border-radius: 4px 4px 0 0; - -webkit-border-radius: 4px 4px 0 0; - border-radius: 4px 4px 0 0; - background-color: #FFFFFF; -} - -.logRow-netInfo.error .netInfoTitle { - color: red; -} - -.logRow-netInfo.loading .netInfoResponseText { - font-style: italic; - color: #888888; -} - -.loading .netInfoResponseHeadersTitle { - display: none; -} - -.netInfoResponseSizeLimit { - font-family: Lucida Grande, Tahoma, sans-serif; - padding-top: 10px; - font-size: 11px; -} - -.netInfoText { - display: none; - margin: 0; - border: 1px solid #D7D7D7; - border-right: none; - padding: 8px; - background-color: #FFFFFF; - font-family: Monaco, monospace; - white-space: pre-wrap; - /*overflow-x: auto; HTML is damaged in case of big (2-3MB) responses */ -} - -/* replaced by .netInfoTextSelected for IE6 support -.netInfoText[selected="true"] { - display: block; -} -/**/ -.netInfoTextSelected { - display: block; -} - -.netInfoParamName { - padding-right: 10px; - font-family: Lucida Grande, Tahoma, sans-serif; - font-weight: bold; - vertical-align: top; - text-align: right; - white-space: nowrap; -} - -.netInfoPostText .netInfoParamName { - width: 1px; /* Google Chrome need this otherwise the first column of - the post variables table will be larger than expected */ -} - -.netInfoParamValue { - width: 100%; -} - -.netInfoHeadersText, -.netInfoPostText, -.netInfoPutText { - padding-top: 0; -} - -.netInfoHeadersGroup, -.netInfoPostParams, -.netInfoPostSource { - margin-bottom: 4px; - border-bottom: 1px solid #D7D7D7; - padding-top: 8px; - padding-bottom: 2px; - font-family: Lucida Grande, Tahoma, sans-serif; - font-weight: bold; - color: #565656; -} - -.netInfoPostParamsTable, -.netInfoPostPartsTable, -.netInfoPostJSONTable, -.netInfoPostXMLTable, -.netInfoPostSourceTable { - margin-bottom: 10px; - width: 100%; -} - -.netInfoPostContentType { - color: #bdbdbd; - padding-left: 50px; - font-weight: normal; -} - -.netInfoHtmlPreview { - border: 0; - width: 100%; - height:100%; -} - -/************************************************************************************************/ -/* Request & Response Headers */ - -.netHeadersViewSource { - color: #bdbdbd; - margin-left: 200px; - font-weight: normal; -} - -.netHeadersViewSource:hover { - color: blue; - cursor: pointer; -} - -/************************************************************************************************/ - -.netActivationRow, -.netPageSeparatorRow { - background: rgb(229, 229, 229) !important; - font-weight: normal; - color: black; -} - -.netActivationLabel { - background: url(chrome://firebug/skin/infoIcon.png) no-repeat 3px 2px; - padding-left: 22px; -} - -/************************************************************************************************/ - -.netPageSeparatorRow { - height: 5px !important; -} - -.netPageSeparatorLabel { - padding-left: 22px; - height: 5px !important; -} - -.netPageRow { - background-color: rgb(255, 255, 255); -} - -.netPageRow:hover { - background: #EFEFEF; -} - -.netPageLabel { - padding: 1px 0 2px 18px !important; - font-weight: bold; -} - -/************************************************************************************************/ - -.netActivationRow > .netCol { - border-bottom: 2px solid; - -moz-border-bottom-colors: #EFEFEF #999999; - padding-top: 2px; - padding-bottom: 3px; -} -/* -.useA11y .panelNode-net .a11yFocus:focus, -.useA11y .panelNode-net .focusRow:focus { - outline-offset: -2px; - background-color: #FFFFD6 !important; -} - -.useA11y .panelNode-net .netHeaderCell:focus, -.useA11y .panelNode-net :focus .netHeaderCell, -.useA11y .panelNode-net :focus .netReceivingBar, -.useA11y .netSummaryRow :focus .netBar, -.useA11y .netSummaryRow:focus .netBar { - background-color: #FFFFD6; - background-image: none; - border-color: #FFFFD6; -} -/**/ - -/*************************************************************************************************/ -/*************************************************************************************************/ -/*************************************************************************************************/ -/*************************************************************************************************/ -/* Windows */ -/*************************************************************************************************/ -/*************************************************************************************************/ -/*************************************************************************************************/ - - -/************************************************************************************************/ -/* Twisties */ - -.twisty, -.logRow-errorMessage > .hasTwisty > .errorTitle, -.logRow-log > .objectBox-array.hasTwisty, -.logRow-spy .spyHead .spyTitle, -.logGroup > .logRow, -.memberRow.hasChildren > .memberLabelCell > .memberLabel, -.hasHeaders .netHrefLabel, -.netPageRow > .netCol > .netPageTitle { - background-image: url(tree_open.gif); - background-repeat: no-repeat; - background-position: 2px 2px; - min-height: 12px; -} - -.logRow-errorMessage > .hasTwisty.opened > .errorTitle, -.logRow-log > .objectBox-array.hasTwisty.opened, -.logRow-spy.opened .spyHead .spyTitle, -.logGroup.opened > .logRow, -.memberRow.hasChildren.opened > .memberLabelCell > .memberLabel, -.nodeBox.highlightOpen > .nodeLabel > .twisty, -.nodeBox.open > .nodeLabel > .twisty, -.netRow.opened > .netCol > .netHrefLabel, -.netPageRow.opened > .netCol > .netPageTitle { - background-image: url(tree_close.gif); -} - -.twisty { - background-position: 4px 4px; -} - - - -/************************************************************************************************/ -/* Twisties IE6 */ - -/* IE6 has problems with > operator, and multiple classes */ - -* html .logRow-spy .spyHead .spyTitle, -* html .logGroup .logGroupLabel, -* html .hasChildren .memberLabelCell .memberLabel, -* html .hasHeaders .netHrefLabel { - background-image: url(tree_open.gif); - background-repeat: no-repeat; - background-position: 2px 2px; -} - -* html .opened .spyHead .spyTitle, -* html .opened .logGroupLabel, -* html .opened .memberLabelCell .memberLabel { - background-image: url(tree_close.gif); - background-repeat: no-repeat; - background-position: 2px 2px; -} - - - -/*************************************************************************************************/ -/*************************************************************************************************/ -/*************************************************************************************************/ -/*************************************************************************************************/ -/* Console */ -/*************************************************************************************************/ -/*************************************************************************************************/ -/*************************************************************************************************/ - - -/* See license.txt for terms of usage */ - -.panelNode-console { - overflow-x: hidden; -} - -.objectLink { - text-decoration: none; -} - -.objectLink:hover { - cursor: pointer; - text-decoration: underline; -} - -.logRow { - position: relative; - margin: 0; - border-bottom: 1px solid #D7D7D7; - padding: 2px 4px 1px 6px; - background-color: #FFFFFF; - overflow: hidden !important; /* IE need this to avoid disappearing bug with collapsed logs */ -} - -.useA11y .logRow:focus { - border-bottom: 1px solid #000000 !important; - outline: none !important; - background-color: #FFFFAD !important; -} - -.useA11y .logRow:focus a.objectLink-sourceLink { - background-color: #FFFFAD; -} - -.useA11y .a11yFocus:focus, .useA11y .objectBox:focus { - outline: 2px solid #FF9933; - background-color: #FFFFAD; -} - -.useA11y .objectBox-null:focus, .useA11y .objectBox-undefined:focus{ - background-color: #888888 !important; -} - -.useA11y .logGroup.opened > .logRow { - border-bottom: 1px solid #ffffff; -} - -.logGroup { - background: url(group.gif) repeat-x #FFFFFF; - padding: 0 !important; - border: none !important; -} - -.logGroupBody { - display: none; - margin-left: 16px; - border-left: 1px solid #D7D7D7; - border-top: 1px solid #D7D7D7; - background: #FFFFFF; -} - -.logGroup > .logRow { - background-color: transparent !important; - font-weight: bold; -} - -.logGroup.opened > .logRow { - border-bottom: none; -} - -.logGroup.opened > .logGroupBody { - display: block; -} - -/*****************************************************************************************/ - -.logRow-command > .objectBox-text { - font-family: Monaco, monospace; - color: #0000FF; - white-space: pre-wrap; -} - -.logRow-info, -.logRow-warn, -.logRow-error, -.logRow-assert, -.logRow-warningMessage, -.logRow-errorMessage { - padding-left: 22px; - background-repeat: no-repeat; - background-position: 4px 2px; -} - -.logRow-assert, -.logRow-warningMessage, -.logRow-errorMessage { - padding-top: 0; - padding-bottom: 0; -} - -.logRow-info, -.logRow-info .objectLink-sourceLink { - background-color: #FFFFFF; -} - -.logRow-warn, -.logRow-warningMessage, -.logRow-warn .objectLink-sourceLink, -.logRow-warningMessage .objectLink-sourceLink { - background-color: cyan; -} - -.logRow-error, -.logRow-assert, -.logRow-errorMessage, -.logRow-error .objectLink-sourceLink, -.logRow-errorMessage .objectLink-sourceLink { - background-color: LightYellow; -} - -.logRow-error, -.logRow-assert, -.logRow-errorMessage { - color: #FF0000; -} - -.logRow-info { - /*background-image: url(chrome://firebug/skin/infoIcon.png);*/ -} - -.logRow-warn, -.logRow-warningMessage { - /*background-image: url(chrome://firebug/skin/warningIcon.png);*/ -} - -.logRow-error, -.logRow-assert, -.logRow-errorMessage { - /*background-image: url(chrome://firebug/skin/errorIcon.png);*/ -} - -/*****************************************************************************************/ - -.objectBox-string, -.objectBox-text, -.objectBox-number, -.objectLink-element, -.objectLink-textNode, -.objectLink-function, -.objectBox-stackTrace, -.objectLink-profile { - font-family: Monaco, monospace; -} - -.objectBox-string, -.objectBox-text, -.objectLink-textNode { - white-space: pre-wrap; -} - -.objectBox-number, -.objectLink-styleRule, -.objectLink-element, -.objectLink-textNode { - color: #000088; -} - -.objectBox-string { - color: #FF0000; -} - -.objectLink-function, -.objectBox-stackTrace, -.objectLink-profile { - color: DarkGreen; -} - -.objectBox-null, -.objectBox-undefined { - padding: 0 2px; - border: 1px solid #666666; - background-color: #888888; - color: #FFFFFF; -} - -.objectBox-exception { - padding: 0 2px 0 18px; - /*background: url(chrome://firebug/skin/errorIcon-sm.png) no-repeat 0 0;*/ - color: red; -} - -.objectLink-sourceLink { - position: absolute; - right: 4px; - top: 2px; - padding-left: 8px; - font-family: Lucida Grande, sans-serif; - font-weight: bold; - color: #0000FF; -} - -/************************************************************************************************/ - -.errorTitle { - margin-top: 0px; - margin-bottom: 1px; - padding-top: 2px; - padding-bottom: 2px; -} - -.errorTrace { - margin-left: 17px; -} - -.errorSourceBox { - margin: 2px 0; -} - -.errorSource-none { - display: none; -} - -.errorSource-syntax > .errorBreak { - visibility: hidden; -} - -.errorSource { - cursor: pointer; - font-family: Monaco, monospace; - color: DarkGreen; -} - -.errorSource:hover { - text-decoration: underline; -} - -.errorBreak { - cursor: pointer; - display: none; - margin: 0 6px 0 0; - width: 13px; - height: 14px; - vertical-align: bottom; - /*background: url(chrome://firebug/skin/breakpoint.png) no-repeat;*/ - opacity: 0.1; -} - -.hasBreakSwitch .errorBreak { - display: inline; -} - -.breakForError .errorBreak { - opacity: 1; -} - -.assertDescription { - margin: 0; -} - -/************************************************************************************************/ - -.logRow-profile > .logRow > .objectBox-text { - font-family: Lucida Grande, Tahoma, sans-serif; - color: #000000; -} - -.logRow-profile > .logRow > .objectBox-text:last-child { - color: #555555; - font-style: italic; -} - -.logRow-profile.opened > .logRow { - padding-bottom: 4px; -} - -.profilerRunning > .logRow { - /*background: transparent url(chrome://firebug/skin/loading_16.gif) no-repeat 2px 0 !important;*/ - padding-left: 22px !important; -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -.profileSizer { - width:100%; - overflow-x:auto; - overflow-y: scroll; -} - -.profileTable { - border-bottom: 1px solid #D7D7D7; - padding: 0 0 4px 0; -} - -.profileTable tr[odd="1"] { - background-color: #F5F5F5; - vertical-align:middle; -} - -.profileTable a { - vertical-align:middle; -} - -.profileTable td { - padding: 1px 4px 0 4px; -} - -.headerCell { - cursor: pointer; - -moz-user-select: none; - border-bottom: 1px solid #9C9C9C; - padding: 0 !important; - font-weight: bold; - /*background: #BBBBBB url(chrome://firebug/skin/tableHeader.gif) repeat-x;*/ -} - -.headerCellBox { - padding: 2px 4px; - border-left: 1px solid #D9D9D9; - border-right: 1px solid #9C9C9C; -} - -.headerCell:hover:active { - /*background: #959595 url(chrome://firebug/skin/tableHeaderActive.gif) repeat-x;*/ -} - -.headerSorted { - /*background: #7D93B2 url(chrome://firebug/skin/tableHeaderSorted.gif) repeat-x;*/ -} - -.headerSorted > .headerCellBox { - border-right-color: #6B7C93; - /*background: url(chrome://firebug/skin/arrowDown.png) no-repeat right;*/ -} - -.headerSorted.sortedAscending > .headerCellBox { - /*background-image: url(chrome://firebug/skin/arrowUp.png);*/ -} - -.headerSorted:hover:active { - /*background: #536B90 url(chrome://firebug/skin/tableHeaderSortedActive.gif) repeat-x;*/ -} - -.linkCell { - text-align: right; -} - -.linkCell > .objectLink-sourceLink { - position: static; -} - -/*****************************************************************************************/ - -.logRow-stackTrace { - padding-top: 0; - background: #f8f8f8; -} - -.logRow-stackTrace > .objectBox-stackFrame { - position: relative; - padding-top: 2px; -} - -/************************************************************************************************/ - -.objectLink-object { - font-family: Lucida Grande, sans-serif; - font-weight: bold; - color: DarkGreen; - white-space: pre-wrap; -} - -/* xxxpedro reps object representation .................................... */ -.objectProp-object { - color: DarkGreen; -} - -.objectProps { - color: #000; - font-weight: normal; -} - -.objectPropName { - /*font-style: italic;*/ - color: #777; -} - -/* -.objectProps .objectProp-string, -.objectProps .objectProp-number, -.objectProps .objectProp-object -{ - font-style: italic; -} -/**/ - -.objectProps .objectProp-string -{ - /*font-family: Monaco, monospace;*/ - color: #f55; -} -.objectProps .objectProp-number -{ - /*font-family: Monaco, monospace;*/ - color: #55a; -} -.objectProps .objectProp-object -{ - /*font-family: Lucida Grande,sans-serif;*/ - color: #585; -} -/* xxxpedro reps object representation .................................... */ - -/************************************************************************************************/ - -.selectorTag, -.selectorId, -.selectorClass { - font-family: Monaco, monospace; - font-weight: normal; -} - -.selectorTag { - color: #0000FF; -} - -.selectorId { - color: DarkBlue; -} - -.selectorClass { - color: red; -} - -.selectorHidden > .selectorTag { - color: #5F82D9; -} - -.selectorHidden > .selectorId { - color: #888888; -} - -.selectorHidden > .selectorClass { - color: #D86060; -} - -.selectorValue { - font-family: Lucida Grande, sans-serif; - font-style: italic; - color: #555555; -} - -/*****************************************************************************************/ - -.panelNode.searching .logRow { - display: none; -} - -.logRow.matched { - display: block !important; -} - -.logRow.matching { - position: absolute; - left: -1000px; - top: -1000px; - max-width: 0; - max-height: 0; - overflow: hidden; -} - -/*****************************************************************************************/ - -.objectLeftBrace, -.objectRightBrace, -.objectEqual, -.objectComma, -.arrayLeftBracket, -.arrayRightBracket, -.arrayComma { - font-family: Monaco, monospace; -} - -.objectLeftBrace, -.objectRightBrace, -.arrayLeftBracket, -.arrayRightBracket { - font-weight: bold; -} - -.objectLeftBrace, -.arrayLeftBracket { - margin-right: 4px; -} - -.objectRightBrace, -.arrayRightBracket { - margin-left: 4px; -} - -/*****************************************************************************************/ - -.logRow-dir { - padding: 0; -} - -/************************************************************************************************/ - -/* -.logRow-errorMessage > .hasTwisty > .errorTitle, -.logRow-spy .spyHead .spyTitle, -.logGroup > .logRow -*/ -.logRow-errorMessage .hasTwisty .errorTitle, -.logRow-spy .spyHead .spyTitle, -.logGroup .logRow { - cursor: pointer; - padding-left: 18px; - background-repeat: no-repeat; - background-position: 3px 3px; -} - -.logRow-errorMessage > .hasTwisty > .errorTitle { - background-position: 2px 3px; -} - -.logRow-errorMessage > .hasTwisty > .errorTitle:hover, -.logRow-spy .spyHead .spyTitle:hover, -.logGroup > .logRow:hover { - text-decoration: underline; -} - -/*****************************************************************************************/ - -.logRow-spy { - padding: 0 !important; -} - -.logRow-spy, -.logRow-spy .objectLink-sourceLink { - background: url(group.gif) repeat-x #FFFFFF; - padding-right: 4px; - right: 0; -} - -.logRow-spy.opened { - padding-bottom: 4px; - border-bottom: none; -} - -.spyTitle { - color: #000000; - font-weight: bold; - -moz-box-sizing: padding-box; - overflow: hidden; - z-index: 100; - padding-left: 18px; -} - -.spyCol { - padding: 0; - white-space: nowrap; - height: 16px; -} - -.spyTitleCol:hover > .objectLink-sourceLink, -.spyTitleCol:hover > .spyTime, -.spyTitleCol:hover > .spyStatus, -.spyTitleCol:hover > .spyTitle { - display: none; -} - -.spyFullTitle { - display: none; - -moz-user-select: none; - max-width: 100%; - background-color: Transparent; -} - -.spyTitleCol:hover > .spyFullTitle { - display: block; -} - -.spyStatus { - padding-left: 10px; - color: rgb(128, 128, 128); -} - -.spyTime { - margin-left:4px; - margin-right:4px; - color: rgb(128, 128, 128); -} - -.spyIcon { - margin-right: 4px; - margin-left: 4px; - width: 16px; - height: 16px; - vertical-align: middle; - background: transparent no-repeat 0 0; - display: none; -} - -.loading .spyHead .spyRow .spyIcon { - background-image: url(loading_16.gif); - display: block; -} - -.logRow-spy.loaded:not(.error) .spyHead .spyRow .spyIcon { - width: 0; - margin: 0; -} - -.logRow-spy.error .spyHead .spyRow .spyIcon { - background-image: url(errorIcon-sm.png); - display: block; - background-position: 2px 2px; -} - -.logRow-spy .spyHead .netInfoBody { - display: none; -} - -.logRow-spy.opened .spyHead .netInfoBody { - margin-top: 10px; - display: block; -} - -.logRow-spy.error .spyTitle, -.logRow-spy.error .spyStatus, -.logRow-spy.error .spyTime { - color: red; -} - -.logRow-spy.loading .spyResponseText { - font-style: italic; - color: #888888; -} - -/************************************************************************************************/ - -.caption { - font-family: Lucida Grande, Tahoma, sans-serif; - font-weight: bold; - color: #444444; -} - -.warning { - padding: 10px; - font-family: Lucida Grande, Tahoma, sans-serif; - font-weight: bold; - color: #888888; -} - - - - -/*************************************************************************************************/ -/*************************************************************************************************/ -/*************************************************************************************************/ -/*************************************************************************************************/ -/* DOM */ -/*************************************************************************************************/ -/*************************************************************************************************/ -/*************************************************************************************************/ - - -/* See license.txt for terms of usage */ - -.panelNode-dom { - overflow-x: hidden !important; -} - -.domTable { - font-size: 1em; - width: 100%; - table-layout: fixed; - background: #fff; -} - -.domTableIE { - width: auto; -} - -.memberLabelCell { - padding: 2px 0 2px 0; - vertical-align: top; -} - -.memberValueCell { - padding: 1px 0 1px 5px; - display: block; - overflow: hidden; -} - -.memberLabel { - display: block; - cursor: default; - -moz-user-select: none; - overflow: hidden; - /*position: absolute;*/ - padding-left: 18px; - /*max-width: 30%;*/ - /*white-space: nowrap;*/ - background-color: #FFFFFF; - text-decoration: none; -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -.memberRow.hasChildren .memberLabelCell .memberLabel:hover { - cursor: pointer; - color: blue; - text-decoration: underline; -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -.userLabel { - color: #000000; - font-weight: bold; -} - -.userClassLabel { - color: #E90000; - font-weight: bold; -} - -.userFunctionLabel { - color: #025E2A; - font-weight: bold; -} - -.domLabel { - color: #000000; -} - -.domFunctionLabel { - color: #025E2A; -} - -.ordinalLabel { - color: SlateBlue; - font-weight: bold; -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -.scopesRow { - padding: 2px 18px; - background-color: LightYellow; - border-bottom: 5px solid #BEBEBE; - color: #666666; -} -.scopesLabel { - background-color: LightYellow; -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -.watchEditCell { - padding: 2px 18px; - background-color: LightYellow; - border-bottom: 1px solid #BEBEBE; - color: #666666; -} - -.editor-watchNewRow, -.editor-memberRow { - font-family: Monaco, monospace !important; -} - -.editor-memberRow { - padding: 1px 0 !important; -} - -.editor-watchRow { - padding-bottom: 0 !important; -} - -.watchRow > .memberLabelCell { - font-family: Monaco, monospace; - padding-top: 1px; - padding-bottom: 1px; -} - -.watchRow > .memberLabelCell > .memberLabel { - background-color: transparent; -} - -.watchRow > .memberValueCell { - padding-top: 2px; - padding-bottom: 2px; -} - -.watchRow > .memberLabelCell, -.watchRow > .memberValueCell { - background-color: #F5F5F5; - border-bottom: 1px solid #BEBEBE; -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -.watchToolbox { - z-index: 2147483647; - position: absolute; - right: 0; - padding: 1px 2px; -} - - -/*************************************************************************************************/ -/*************************************************************************************************/ -/*************************************************************************************************/ -/*************************************************************************************************/ -/*************************************************************************************************/ -/*************************************************************************************************/ -/*************************************************************************************************/ -/* FROM ORIGINAL FIREBUG */ - - - - -/************************************************************************************************ - CSS Not organized -*************************************************************************************************/ -#fbConsole { - overflow-x: hidden !important; -} - -#fbCSS { - font: 1em Monaco, monospace; - padding: 0 7px; -} - -#fbstylesheetButtons select, #fbScriptButtons select { - font: 11px Lucida Grande, Tahoma, sans-serif; - margin-top: 1px; - padding-left: 3px; - background: #fafafa; - border: 1px inset #fff; - width: 220px; - outline: none; -} - -.Selector { margin-top:10px } -.CSSItem {margin-left: 4% } -.CSSText { padding-left:20px; } -.CSSProperty { color:#005500; } -.CSSValue { padding-left:5px; color:#000088; } - - -/************************************************************************************************ - Not organized -*************************************************************************************************/ - -#fbHTMLStatusBar { - display: inline; -} - -.fbToolbarButtons { - display: none; -} - -.fbStatusSeparator{ - display: block; - float: left; - padding-top: 4px; -} - -#fbStatusBarBox { - display: none; -} - -#fbToolbarContent { - display: block; - position: absolute; - _position: absolute; - top: 0; - padding-top: 4px; - height: 23px; - clip: rect(0, 2048px, 27px, 0); -} - -.fbTabMenuTarget { - display: none !important; - float: left; - width: 10px; - height: 10px; - margin-top: 6px; - background: url(tabMenuTarget.png); -} - -.fbTabMenuTarget:hover { - background: url(tabMenuTargetHover.png); -} - -.fbShadow { - float: left; - background: url(shadowAlpha.png) no-repeat bottom right !important; - background: url(shadow2.gif) no-repeat bottom right; - margin: 10px 0 0 10px !important; - margin: 10px 0 0 5px; -} - -.fbShadowContent { - display: block; - position: relative; - background-color: #fff; - border: 1px solid #a9a9a9; - top: -6px; - left: -6px; -} - -.fbMenu { - display: none; - position: absolute; - font-size: 11px; - line-height: 13px; - z-index: 2147483647; -} - -.fbMenuContent { - padding: 2px; -} - -.fbMenuSeparator { - display: block; - position: relative; - padding: 1px 18px 0; - text-decoration: none; - color: #000; - cursor: default; - background: #ACA899; - margin: 4px 0; -} - -.fbMenuOption -{ - display: block; - position: relative; - padding: 2px 18px; - text-decoration: none; - color: #000; - cursor: default; -} - -.fbMenuOption:hover -{ - color: #fff; - background: #316AC5; -} - -.fbMenuGroup { - background: transparent url(tabMenuPin.png) no-repeat right 0; -} - -.fbMenuGroup:hover { - background: #316AC5 url(tabMenuPin.png) no-repeat right -17px; -} - -.fbMenuGroupSelected { - color: #fff; - background: #316AC5 url(tabMenuPin.png) no-repeat right -17px; -} - -.fbMenuChecked { - background: transparent url(tabMenuCheckbox.png) no-repeat 4px 0; -} - -.fbMenuChecked:hover { - background: #316AC5 url(tabMenuCheckbox.png) no-repeat 4px -17px; -} - -.fbMenuRadioSelected { - background: transparent url(tabMenuRadio.png) no-repeat 4px 0; -} - -.fbMenuRadioSelected:hover { - background: #316AC5 url(tabMenuRadio.png) no-repeat 4px -17px; -} - -.fbMenuShortcut { - padding-right: 85px; -} - -.fbMenuShortcutKey { - position: absolute; - right: 0; - top: 2px; - width: 77px; -} - -#fbFirebugMenu { - top: 22px; - left: 0; -} - -.fbMenuDisabled { - color: #ACA899 !important; -} - -#fbFirebugSettingsMenu { - left: 245px; - top: 99px; -} - -#fbConsoleMenu { - top: 42px; - left: 48px; -} - -.fbIconButton { - display: block; -} - -.fbIconButton { - display: block; -} - -.fbIconButton { - display: block; - float: left; - height: 20px; - width: 20px; - color: #000; - margin-right: 2px; - text-decoration: none; - cursor: default; -} - -.fbIconButton:hover { - position: relative; - top: -1px; - left: -1px; - margin-right: 0; - _margin-right: 1px; - color: #333; - border: 1px solid #fff; - border-bottom: 1px solid #bbb; - border-right: 1px solid #bbb; -} - -.fbIconPressed { - position: relative; - margin-right: 0; - _margin-right: 1px; - top: 0 !important; - left: 0 !important; - height: 19px; - color: #333 !important; - border: 1px solid #bbb !important; - border-bottom: 1px solid #cfcfcf !important; - border-right: 1px solid #ddd !important; -} - - - -/************************************************************************************************ - Error Popup -*************************************************************************************************/ -#fbErrorPopup { - position: absolute; - right: 0; - bottom: 0; - height: 19px; - width: 75px; - background: url(sprite.png) #f1f2ee 0 0; - z-index: 999; -} - -#fbErrorPopupContent { - position: absolute; - right: 0; - top: 1px; - height: 18px; - width: 75px; - _width: 74px; - border-left: 1px solid #aca899; -} - -#fbErrorIndicator { - position: absolute; - top: 2px; - right: 5px; -} - - - - - - - - - - -.fbBtnInspectActive { - background: #aaa; - color: #fff !important; -} - -/************************************************************************************************ - General -*************************************************************************************************/ -.fbBody { - margin: 0; - padding: 0; - overflow: hidden; - - font-family: Lucida Grande, Tahoma, sans-serif; - font-size: 11px; - background: #fff; -} - -.clear { - clear: both; -} - -/************************************************************************************************ - Mini Chrome -*************************************************************************************************/ -#fbMiniChrome { - display: none; - right: 0; - height: 27px; - background: url(sprite.png) #f1f2ee 0 0; - margin-left: 1px; -} - -#fbMiniContent { - display: block; - position: relative; - left: -1px; - right: 0; - top: 1px; - height: 25px; - border-left: 1px solid #aca899; -} - -#fbToolbarSearch { - float: right; - border: 1px solid #ccc; - margin: 0 5px 0 0; - background: #fff url(search.png) no-repeat 4px 2px !important; - background: #fff url(search.gif) no-repeat 4px 2px; - padding-left: 20px; - font-size: 11px; -} - -#fbToolbarErrors { - float: right; - margin: 1px 4px 0 0; - font-size: 11px; -} - -#fbLeftToolbarErrors { - float: left; - margin: 7px 0px 0 5px; - font-size: 11px; -} - -.fbErrors { - padding-left: 20px; - height: 14px; - background: url(errorIcon.png) no-repeat !important; - background: url(errorIcon.gif) no-repeat; - color: #f00; - font-weight: bold; -} - -#fbMiniErrors { - display: inline; - display: none; - float: right; - margin: 5px 2px 0 5px; -} - -#fbMiniIcon { - float: right; - margin: 3px 4px 0; - height: 20px; - width: 20px; - float: right; - background: url(sprite.png) 0 -135px; - cursor: pointer; -} - - -/************************************************************************************************ - Master Layout -*************************************************************************************************/ -#fbChrome { - font-family: Lucida Grande, Tahoma, sans-serif; - font-size: 11px; - position: absolute; - _position: static; - top: 0; - left: 0; - height: 100%; - width: 100%; - border-collapse: collapse; - border-spacing: 0; - background: #fff; - overflow: hidden; -} - -#fbChrome > tbody > tr > td { - padding: 0; -} - -#fbTop { - height: 49px; -} - -#fbToolbar { - background: url(sprite.png) #f1f2ee 0 0; - height: 27px; - font-size: 11px; - line-height: 13px; -} - -#fbPanelBarBox { - background: url(sprite.png) #dbd9c9 0 -27px; - height: 22px; -} - -#fbContent { - height: 100%; - vertical-align: top; -} - -#fbBottom { - height: 18px; - background: #fff; -} - -/************************************************************************************************ - Sub-Layout -*************************************************************************************************/ - -/* fbToolbar -*************************************************************************************************/ -#fbToolbarIcon { - float: left; - padding: 0 5px 0; -} - -#fbToolbarIcon a { - background: url(sprite.png) 0 -135px; -} - -#fbToolbarButtons { - padding: 0 2px 0 5px; -} - -#fbToolbarButtons { - padding: 0 2px 0 5px; -} -/* -#fbStatusBarBox a { - text-decoration: none; - display: block; - float: left; - color: #000; - padding: 4px 5px; - margin: 0 0 0 1px; - cursor: default; -} - -#fbStatusBarBox a:hover { - color: #333; - padding: 3px 4px; - border: 1px solid #fff; - border-bottom: 1px solid #bbb; - border-right: 1px solid #bbb; -} -/**/ - -.fbButton { - text-decoration: none; - display: block; - float: left; - color: #000; - padding: 4px 6px 4px 7px; - cursor: default; -} - -.fbButton:hover { - color: #333; - background: #f5f5ef url(buttonBg.png); - padding: 3px 5px 3px 6px; - border: 1px solid #fff; - border-bottom: 1px solid #bbb; - border-right: 1px solid #bbb; -} - -.fbBtnPressed { - background: #e3e3db url(buttonBgHover.png) !important; - padding: 3px 4px 2px 6px !important; - margin: 1px 0 0 1px !important; - border: 1px solid #ACA899 !important; - border-color: #ACA899 #ECEBE3 #ECEBE3 #ACA899 !important; -} - -#fbStatusBarBox { - top: 4px; - cursor: default; -} - -.fbToolbarSeparator { - overflow: hidden; - border: 1px solid; - border-color: transparent #fff transparent #777; - _border-color: #eee #fff #eee #777; - height: 7px; - margin: 6px 3px; - float: left; -} - -.fbBtnSelected { - font-weight: bold; -} - -.fbStatusBar { - color: #aca899; -} - -.fbStatusBar a { - text-decoration: none; - color: black; -} - -.fbStatusBar a:hover { - color: blue; - cursor: pointer; -} - - -#fbWindowButtons { - position: absolute; - white-space: nowrap; - right: 0; - top: 0; - height: 17px; - width: 48px; - padding: 5px; - z-index: 6; - background: url(sprite.png) #f1f2ee 0 0; -} - -/* fbPanelBarBox -*************************************************************************************************/ - -#fbPanelBar1 { - width: 1024px; /* fixed width to avoid tabs breaking line */ - z-index: 8; - left: 0; - white-space: nowrap; - background: url(sprite.png) #dbd9c9 0 -27px; - position: absolute; - left: 4px; -} - -#fbPanelBar2Box { - background: url(sprite.png) #dbd9c9 0 -27px; - position: absolute; - height: 22px; - width: 300px; /* fixed width to avoid tabs breaking line */ - z-index: 9; - right: 0; -} - -#fbPanelBar2 { - position: absolute; - width: 290px; /* fixed width to avoid tabs breaking line */ - height: 22px; - padding-left: 4px; -} - -/* body -*************************************************************************************************/ -.fbPanel { - display: none; -} - -#fbPanelBox1, #fbPanelBox2 { - max-height: inherit; - height: 100%; - font-size: 1em; -} - -#fbPanelBox2 { - background: #fff; -} - -#fbPanelBox2 { - width: 300px; - background: #fff; -} - -#fbPanel2 { - margin-left: 6px; - background: #fff; -} - -#fbLargeCommandLine { - display: none; - position: absolute; - z-index: 9; - top: 27px; - right: 0; - width: 294px; - height: 201px; - border-width: 0; - margin: 0; - padding: 2px 0 0 2px; - resize: none; - outline: none; - font-size: 11px; - overflow: auto; - border-top: 1px solid #B9B7AF; - _right: -1px; - _border-left: 1px solid #fff; -} - -#fbLargeCommandButtons { - display: none; - background: #ECE9D8; - bottom: 0; - right: 0; - width: 294px; - height: 21px; - padding-top: 1px; - position: fixed; - border-top: 1px solid #ACA899; - z-index: 9; -} - -#fbSmallCommandLineIcon { - background: url(down.png) no-repeat; - position: absolute; - right: 2px; - bottom: 3px; - - z-index: 99; -} - -#fbSmallCommandLineIcon:hover { - background: url(downHover.png) no-repeat; -} - -.hide { - overflow: hidden !important; - position: fixed !important; - display: none !important; - visibility: hidden !important; -} - -/* fbBottom -*************************************************************************************************/ - -#fbCommand { - height: 18px; -} - -#fbCommandBox { - position: fixed; - _position: absolute; - width: 100%; - height: 18px; - bottom: 0; - overflow: hidden; - z-index: 9; - background: #fff; - border: 0; - border-top: 1px solid #ccc; -} - -#fbCommandIcon { - position: absolute; - color: #00f; - top: 2px; - left: 6px; - display: inline; - font: 11px Monaco, monospace; - z-index: 10; -} - -#fbCommandLine { - position: absolute; - width: 100%; - top: 0; - left: 0; - border: 0; - margin: 0; - padding: 2px 0 2px 32px; - font: 11px Monaco, monospace; - z-index: 9; - outline: none; -} - -#fbLargeCommandLineIcon { - background: url(up.png) no-repeat; - position: absolute; - right: 1px; - bottom: 1px; - z-index: 10; -} - -#fbLargeCommandLineIcon:hover { - background: url(upHover.png) no-repeat; -} - -div.fbFitHeight { - overflow: auto; - position: relative; -} - - -/************************************************************************************************ - Layout Controls -*************************************************************************************************/ - -/* fbToolbar buttons -*************************************************************************************************/ -.fbSmallButton { - overflow: hidden; - width: 16px; - height: 16px; - display: block; - text-decoration: none; - cursor: default; -} - -#fbWindowButtons .fbSmallButton { - float: right; -} - -#fbWindow_btClose { - background: url(min.png); -} - -#fbWindow_btClose:hover { - background: url(minHover.png); -} - -#fbWindow_btDetach { - background: url(detach.png); -} - -#fbWindow_btDetach:hover { - background: url(detachHover.png); -} - -#fbWindow_btDeactivate { - background: url(off.png); -} - -#fbWindow_btDeactivate:hover { - background: url(offHover.png); -} - - -/* fbPanelBarBox tabs -*************************************************************************************************/ -.fbTab { - text-decoration: none; - display: none; - float: left; - width: auto; - float: left; - cursor: default; - font-family: Lucida Grande, Tahoma, sans-serif; - font-size: 11px; - line-height: 13px; - font-weight: bold; - height: 22px; - color: #565656; -} - -.fbPanelBar span { - /*display: block; TODO: safe to remove this? */ - float: left; -} - -.fbPanelBar .fbTabL,.fbPanelBar .fbTabR { - height: 22px; - width: 8px; -} - -.fbPanelBar .fbTabText { - padding: 4px 1px 0; -} - -a.fbTab:hover { - background: url(sprite.png) 0 -73px; -} - -a.fbTab:hover .fbTabL { - background: url(sprite.png) -16px -96px; -} - -a.fbTab:hover .fbTabR { - background: url(sprite.png) -24px -96px; -} - -.fbSelectedTab { - background: url(sprite.png) #f1f2ee 0 -50px !important; - color: #000; -} - -.fbSelectedTab .fbTabL { - background: url(sprite.png) 0 -96px !important; -} - -.fbSelectedTab .fbTabR { - background: url(sprite.png) -8px -96px !important; -} - -/* splitters -*************************************************************************************************/ -#fbHSplitter { - position: fixed; - _position: absolute; - left: 0; - top: 0; - width: 100%; - height: 5px; - overflow: hidden; - cursor: n-resize !important; - background: url(pixel_transparent.gif); - z-index: 9; -} - -#fbHSplitter.fbOnMovingHSplitter { - height: 100%; - z-index: 100; -} - -.fbVSplitter { - background: #ece9d8; - color: #000; - border: 1px solid #716f64; - border-width: 0 1px; - border-left-color: #aca899; - width: 4px; - cursor: e-resize; - overflow: hidden; - right: 294px; - text-decoration: none; - z-index: 10; - position: absolute; - height: 100%; - top: 27px; -} - -/************************************************************************************************/ -div.lineNo { - font: 1em/1.4545em Monaco, monospace; - position: relative; - float: left; - top: 0; - left: 0; - margin: 0 5px 0 0; - padding: 0 5px 0 10px; - background: #eee; - color: #888; - border-right: 1px solid #ccc; - text-align: right; -} - -.sourceBox { - position: absolute; -} - -.sourceCode { - font: 1em Monaco, monospace; - overflow: hidden; - white-space: pre; - display: inline; -} - -/************************************************************************************************/ -.nodeControl { - margin-top: 3px; - margin-left: -14px; - float: left; - width: 9px; - height: 9px; - overflow: hidden; - cursor: default; - background: url(tree_open.gif); - _float: none; - _display: inline; - _position: absolute; -} - -div.nodeMaximized { - background: url(tree_close.gif); -} - -div.objectBox-element { - padding: 1px 3px; -} -.objectBox-selector{ - cursor: default; -} - -.selectedElement{ - background: highlight; - /* background: url(roundCorner.svg); Opera */ - color: #fff !important; -} -.selectedElement span{ - color: #fff !important; -} - -/* IE6 need this hack */ -* html .selectedElement { - position: relative; -} - -/* Webkit CSS Hack - bug in "highlight" named color */ -@media screen and (-webkit-min-device-pixel-ratio:0) { - .selectedElement{ - background: #316AC5; - color: #fff !important; - } -} - -/************************************************************************************************/ -/************************************************************************************************/ -.logRow * { - font-size: 1em; -} - -/* TODO: remove this? */ -/* TODO: xxxpedro - IE need this in windowless mode (cnn.com) check if the issue is related to -position. if so, override it at chrome.js initialization when creating the div */ -.logRow { - position: relative; - border-bottom: 1px solid #D7D7D7; - padding: 2px 4px 1px 6px; - zbackground-color: #FFFFFF; -} -/**/ - -.logRow-command { - font-family: Monaco, monospace; - color: blue; -} - -.objectBox-string, -.objectBox-text, -.objectBox-number, -.objectBox-function, -.objectLink-element, -.objectLink-textNode, -.objectLink-function, -.objectBox-stackTrace, -.objectLink-profile { - font-family: Monaco, monospace; -} - -.objectBox-null { - padding: 0 2px; - border: 1px solid #666666; - background-color: #888888; - color: #FFFFFF; -} - -.objectBox-string { - color: red; - - /* TODO: xxxpedro make long strings break line */ - /*white-space: pre; */ -} - -.objectBox-number { - color: #000088; -} - -.objectBox-function { - color: DarkGreen; -} - -.objectBox-object { - color: DarkGreen; - font-weight: bold; - font-family: Lucida Grande, sans-serif; -} - -.objectBox-array { - color: #000; -} - -/************************************************************************************************/ -.logRow-info,.logRow-error,.logRow-warn { - background: #fff no-repeat 2px 2px; - padding-left: 20px; - padding-bottom: 3px; -} - -.logRow-info { - background-image: url(infoIcon.png) !important; - background-image: url(infoIcon.gif); -} - -.logRow-warn { - background-color: cyan; - background-image: url(warningIcon.png) !important; - background-image: url(warningIcon.gif); -} - -.logRow-error { - background-color: LightYellow; - background-image: url(errorIcon.png) !important; - background-image: url(errorIcon.gif); - color: #f00; -} - -.errorMessage { - vertical-align: top; - color: #f00; -} - -.objectBox-sourceLink { - position: absolute; - right: 4px; - top: 2px; - padding-left: 8px; - font-family: Lucida Grande, sans-serif; - font-weight: bold; - color: #0000FF; -} - -/************************************************************************************************/ -/* -//TODO: remove this when console2 is finished -*/ -/* -.logRow-group { - background: #EEEEEE; - border-bottom: none; -} - -.logGroup { - background: #EEEEEE; -} - -.logGroupBox { - margin-left: 24px; - border-top: 1px solid #D7D7D7; - border-left: 1px solid #D7D7D7; -}/**/ - -/************************************************************************************************/ -.selectorTag,.selectorId,.selectorClass { - font-family: Monaco, monospace; - font-weight: normal; -} - -.selectorTag { - color: #0000FF; -} - -.selectorId { - color: DarkBlue; -} - -.selectorClass { - color: red; -} - -/************************************************************************************************/ -.objectBox-element { - font-family: Monaco, monospace; - color: #000088; -} - -.nodeChildren { - padding-left: 26px; -} - -.nodeTag { - color: blue; - cursor: pointer; -} - -.nodeValue { - color: #FF0000; - font-weight: normal; -} - -.nodeText,.nodeComment { - margin: 0 2px; - vertical-align: top; -} - -.nodeText { - color: #333333; - font-family: Monaco, monospace; -} - -.nodeComment { - color: DarkGreen; -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -.nodeHidden, .nodeHidden * { - color: #888888; -} - -.nodeHidden .nodeTag { - color: #5F82D9; -} - -.nodeHidden .nodeValue { - color: #D86060; -} - -.selectedElement .nodeHidden, .selectedElement .nodeHidden * { - color: SkyBlue !important; -} - - -/************************************************************************************************/ -.log-object { - /* - _position: relative; - _height: 100%; - /**/ -} - -.property { - position: relative; - clear: both; - height: 15px; -} - -.propertyNameCell { - vertical-align: top; - float: left; - width: 28%; - position: absolute; - left: 0; - z-index: 0; -} - -.propertyValueCell { - float: right; - width: 68%; - background: #fff; - position: absolute; - padding-left: 5px; - display: table-cell; - right: 0; - z-index: 1; - /* - _position: relative; - /**/ -} - -.propertyName { - font-weight: bold; -} - -.FirebugPopup { - height: 100% !important; -} - -.FirebugPopup #fbWindowButtons { - display: none !important; -} - -.FirebugPopup #fbHSplitter { - display: none !important; -} diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/firebug.html b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/firebug.html deleted file mode 100644 index aa078099..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/firebug.html +++ /dev/null @@ -1,215 +0,0 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/DTD/strict.dtd"> -<html> -<head> -<meta http-equiv="content-type" content="text/html; charset=utf-8"> -<title>Firebug Lite</title> -<!-- An empty script to avoid FOUC when loading the stylesheet --> -<script type="text/javascript"></script> -<style type="text/css" media="screen">@import "firebug.css";</style> -<style>html,body{margin:0;padding:0;overflow:hidden;}</style> -</head> -<body class="fbBody"> -<table id="fbChrome" cellpadding="0" cellspacing="0" border="0"> - <tbody> - <tr> - <!-- Interface - Top Area --> - <td id="fbTop" colspan="2"> - - <!-- - <div> - --><!-- <span id="fbToolbarErrors" class="fbErrors">2 errors</span> --><!-- - <input type="text" id="fbToolbarSearch" /> - </div> - --> - - <!-- Window Buttons --> - <div id="fbWindowButtons"> - <a id="fbWindow_btDeactivate" class="fbSmallButton fbHover" title="Deactivate Firebug for this web page"> </a> - <a id="fbWindow_btDetach" class="fbSmallButton fbHover" title="Open Firebug in popup window"> </a> - <a id="fbWindow_btClose" class="fbSmallButton fbHover" title="Minimize Firebug"> </a> - </div> - - <!-- Toolbar buttons and Status Bar --> - <div id="fbToolbar"> - <div id="fbToolbarContent"> - - <!-- Firebug Button --> - <span id="fbToolbarIcon"> - <a id="fbFirebugButton" class="fbIconButton" class="fbHover" target="_blank"> </a> - </span> - - <!-- - <span id="fbLeftToolbarErrors" class="fbErrors">2 errors</span> - --> - - <!-- Toolbar Buttons --> - <span id="fbToolbarButtons"> - <!-- Fixed Toolbar Buttons --> - <span id="fbFixedButtons"> - <a id="fbChrome_btInspect" class="fbButton fbHover" title="Click an element in the page to inspect">Inspect</a> - </span> - - <!-- Console Panel Toolbar Buttons --> - <span id="fbConsoleButtons" class="fbToolbarButtons"> - <a id="fbConsole_btClear" class="fbButton fbHover" title="Clear the console">Clear</a> - </span> - - <!-- HTML Panel Toolbar Buttons --> - <!-- - <span id="fbHTMLButtons" class="fbToolbarButtons"> - <a id="fbHTML_btEdit" class="fbHover" title="Edit this HTML">Edit</a> - </span> - --> - </span> - - <!-- Status Bar --> - <span id="fbStatusBarBox"> - <span class="fbToolbarSeparator"></span> - <!-- HTML Panel Status Bar --> - <!-- - <span id="fbHTMLStatusBar" class="fbStatusBar fbToolbarButtons"> - </span> - --> - </span> - - </div> - - </div> - - <!-- PanelBars --> - <div id="fbPanelBarBox"> - - <!-- Main PanelBar --> - <div id="fbPanelBar1" class="fbPanelBar"> - <a id="fbConsoleTab" class="fbTab fbHover"> - <span class="fbTabL"></span> - <span class="fbTabText">Console</span> - <span class="fbTabMenuTarget"></span> - <span class="fbTabR"></span> - </a> - <a id="fbHTMLTab" class="fbTab fbHover"> - <span class="fbTabL"></span> - <span class="fbTabText">HTML</span> - <span class="fbTabR"></span> - </a> - <a class="fbTab fbHover"> - <span class="fbTabL"></span> - <span class="fbTabText">CSS</span> - <span class="fbTabR"></span> - </a> - <a class="fbTab fbHover"> - <span class="fbTabL"></span> - <span class="fbTabText">Script</span> - <span class="fbTabR"></span> - </a> - <a class="fbTab fbHover"> - <span class="fbTabL"></span> - <span class="fbTabText">DOM</span> - <span class="fbTabR"></span> - </a> - </div> - - <!-- Side PanelBars --> - <div id="fbPanelBar2Box" class="hide"> - <div id="fbPanelBar2" class="fbPanelBar"> - <!-- - <a class="fbTab fbHover"> - <span class="fbTabL"></span> - <span class="fbTabText">Style</span> - <span class="fbTabR"></span> - </a> - <a class="fbTab fbHover"> - <span class="fbTabL"></span> - <span class="fbTabText">Layout</span> - <span class="fbTabR"></span> - </a> - <a class="fbTab fbHover"> - <span class="fbTabL"></span> - <span class="fbTabText">DOM</span> - <span class="fbTabR"></span> - </a> - --> - </div> - </div> - - </div> - - <!-- Horizontal Splitter --> - <div id="fbHSplitter"> </div> - - </td> - </tr> - - <!-- Interface - Main Area --> - <tr id="fbContent"> - - <!-- Panels --> - <td id="fbPanelBox1"> - <div id="fbPanel1" class="fbFitHeight"> - <div id="fbConsole" class="fbPanel"></div> - <div id="fbHTML" class="fbPanel"></div> - </div> - </td> - - <!-- Side Panel Box --> - <td id="fbPanelBox2" class="hide"> - - <!-- VerticalSplitter --> - <div id="fbVSplitter" class="fbVSplitter"> </div> - - <!-- Side Panels --> - <div id="fbPanel2" class="fbFitHeight"> - - <!-- HTML Side Panels --> - <div id="fbHTML_Style" class="fbPanel"></div> - <div id="fbHTML_Layout" class="fbPanel"></div> - <div id="fbHTML_DOM" class="fbPanel"></div> - - </div> - - <!-- Large Command Line --> - <textarea id="fbLargeCommandLine" class="fbFitHeight"></textarea> - - <!-- Large Command Line Buttons --> - <div id="fbLargeCommandButtons"> - <a id="fbCommand_btRun" class="fbButton fbHover">Run</a> - <a id="fbCommand_btClear" class="fbButton fbHover">Clear</a> - - <a id="fbSmallCommandLineIcon" class="fbSmallButton fbHover"></a> - </div> - - </td> - - </tr> - - <!-- Interface - Bottom Area --> - <tr id="fbBottom" class="hide"> - - <!-- Command Line --> - <td id="fbCommand" colspan="2"> - <div id="fbCommandBox"> - <div id="fbCommandIcon">>>></div> - <input id="fbCommandLine" name="fbCommandLine" type="text" /> - <a id="fbLargeCommandLineIcon" class="fbSmallButton fbHover"></a> - </div> - </td> - - </tr> - - </tbody> -</table> -<span id="fbMiniChrome"> - <span id="fbMiniContent"> - <span id="fbMiniIcon" title="Open Firebug Lite"></span> - <span id="fbMiniErrors" class="fbErrors"><!-- 2 errors --></span> - </span> -</span> -<!-- -<div id="fbErrorPopup"> - <div id="fbErrorPopupContent"> - <div id="fbErrorIndicator" class="fbErrors">2 errors</div> - </div> -</div> - --> -</body> -</html>
\ No newline at end of file diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/firebug.png b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/firebug.png Binary files differdeleted file mode 100644 index e10affeb..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/firebug.png +++ /dev/null diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/group.gif b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/group.gif Binary files differdeleted file mode 100644 index 8db97c21..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/group.gif +++ /dev/null diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/html.css b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/html.css deleted file mode 100644 index 5b7c5f4b..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/html.css +++ /dev/null @@ -1,272 +0,0 @@ -/* See license.txt for terms of usage */ - -.panelNode-html { - -moz-box-sizing: padding-box; - padding: 4px 0 0 2px; -} - -.nodeBox { - position: relative; - font-family: Monaco, monospace; - padding-left: 13px; - -moz-user-select: -moz-none; -} -.nodeBox.search-selection { - -moz-user-select: text; -} -.twisty { - position: absolute; - left: 0px; - top: 0px; - width: 14px; - height: 14px; -} - -.nodeChildBox { - margin-left: 12px; - display: none; -} - -.nodeLabel, -.nodeCloseLabel { - margin: -2px 2px 0 2px; - border: 2px solid transparent; - -moz-border-radius: 3px; - padding: 0 2px; - color: #000088; -} - -.nodeCloseLabel { - display: none; -} - -.nodeTag { - cursor: pointer; - color: blue; -} - -.nodeValue { - color: #FF0000; - font-weight: normal; -} - -.nodeText, -.nodeComment { - margin: 0 2px; - vertical-align: top; -} - -.nodeText { - color: #333333; -} - -.nodeWhiteSpace { - border: 1px solid LightGray; - white-space: pre; /* otherwise the border will be collapsed around zero pixels */ - margin-left: 1px; - color: gray; -} - - -.nodeWhiteSpace_Space { - border: 1px solid #ddd; -} - -.nodeTextEntity { - border: 1px solid gray; - white-space: pre; /* otherwise the border will be collapsed around zero pixels */ - margin-left: 1px; -} - -.nodeComment { - color: DarkGreen; -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -.nodeBox.highlightOpen > .nodeLabel { - background-color: #EEEEEE; -} - -.nodeBox.highlightOpen > .nodeCloseLabel, -.nodeBox.highlightOpen > .nodeChildBox, -.nodeBox.open > .nodeCloseLabel, -.nodeBox.open > .nodeChildBox { - display: block; -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -.nodeBox.selected > .nodeLabel > .nodeLabelBox, -.nodeBox.selected > .nodeLabel { - border-color: Highlight; - background-color: Highlight; - color: HighlightText !important; -} - -.nodeBox.selected > .nodeLabel > .nodeLabelBox, -.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeTag, -.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue, -.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeText { - color: inherit !important; -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -.nodeBox.highlighted > .nodeLabel { - border-color: Highlight !important; - background-color: cyan !important; - color: #000000 !important; -} - -.nodeBox.highlighted > .nodeLabel > .nodeLabelBox, -.nodeBox.highlighted > .nodeLabel > .nodeLabelBox > .nodeTag, -.nodeBox.highlighted > .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue, -.nodeBox.highlighted > .nodeLabel > .nodeLabelBox > .nodeText { - color: #000000 !important; -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -.nodeBox.nodeHidden .nodeLabel > .nodeLabelBox, -.nodeBox.nodeHidden .nodeCloseLabel, -.nodeBox.nodeHidden .nodeLabel > .nodeLabelBox > .nodeText, -.nodeBox.nodeHidden .nodeText { - color: #888888; -} - -.nodeBox.nodeHidden .nodeLabel > .nodeLabelBox > .nodeTag, -.nodeBox.nodeHidden .nodeCloseLabel > .nodeCloseLabelBox > .nodeTag { - color: #5F82D9; -} - -.nodeBox.nodeHidden .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue { - color: #D86060; -} - -.nodeBox.nodeHidden.selected > .nodeLabel > .nodeLabelBox, -.nodeBox.nodeHidden.selected > .nodeLabel > .nodeLabelBox > .nodeTag, -.nodeBox.nodeHidden.selected > .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue, -.nodeBox.nodeHidden.selected > .nodeLabel > .nodeLabelBox > .nodeText { - color: SkyBlue !important; -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -.nodeBox.mutated > .nodeLabel, -.nodeAttr.mutated, -.nodeValue.mutated, -.nodeText.mutated, -.nodeBox.mutated > .nodeText { - background-color: #EFFF79; - color: #FF0000 !important; -} - -.nodeBox.selected.mutated > .nodeLabel, -.nodeBox.selected.mutated > .nodeLabel > .nodeLabelBox, -.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeAttr.mutated > .nodeValue, -.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue.mutated, -.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeText.mutated { - background-color: #EFFF79; - border-color: #EFFF79; - color: #FF0000 !important; -} - -/************************************************************************************************/ - -.logRow-dirxml { - padding-left: 0; -} - -.soloElement > .nodeBox { - padding-left: 0; -} - -.useA11y .nodeLabel.focused { - outline: 2px solid #FF9933; - -moz-outline-radius: 3px; - outline-offset: -2px; -} - -.useA11y .nodeLabelBox:focus { - outline: none; -} - -/************************************************************************************************/ - -.breakpointCode .twisty { - display: none; -} - -.breakpointCode .nodeBox.containerNodeBox, -.breakpointCode .nodeLabel { - padding-left: 0px; - margin-left: 0px; - font-family: Monaco, monospace !important; -} - -.breakpointCode .nodeTag, -.breakpointCode .nodeAttr, -.breakpointCode .nodeText, -.breakpointCode .nodeValue, -.breakpointCode .nodeLabel { - color: DarkGreen !important; -} - -.breakpointMutationType { - position: absolute; - top: 4px; - right: 20px; - color: gray; -} - - - - - - -/************************************************************************************************/ -/************************************************************************************************/ -/************************************************************************************************/ -/************************************************************************************************/ -/************************************************************************************************/ -/************************************************************************************************/ -/************************************************************************************************/ -/************************************************************************************************/ -/************************************************************************************************/ -/************************************************************************************************/ - - - -/************************************************************************************************/ -/* Twisties */ - -.twisty, -.logRow-errorMessage > .hasTwisty > .errorTitle, -.logRow-log > .objectBox-array.hasTwisty, -.logRow-spy .spyHead .spyTitle, -.logGroup > .logRow, -.memberRow.hasChildren > .memberLabelCell > .memberLabel, -.hasHeaders .netHrefLabel, -.netPageRow > .netCol > .netPageTitle { - background-image: url(twistyClosed.png); - background-repeat: no-repeat; - background-position: 2px 2px; - min-height: 12px; -} - -.logRow-errorMessage > .hasTwisty.opened > .errorTitle, -.logRow-log > .objectBox-array.hasTwisty.opened, -.logRow-spy.opened .spyHead .spyTitle, -.logGroup.opened > .logRow, -.memberRow.hasChildren.opened > .memberLabelCell > .memberLabel, -.nodeBox.highlightOpen > .nodeLabel > .twisty, -.nodeBox.open > .nodeLabel > .twisty, -.netRow.opened > .netCol > .netHrefLabel, -.netPageRow.opened > .netCol > .netPageTitle { - background-image: url(twistyOpen.png); -} - -.twisty { - background-position: 4px 4px; -}
\ No newline at end of file diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/infoIcon.gif b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/infoIcon.gif Binary files differdeleted file mode 100644 index 0618e208..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/infoIcon.gif +++ /dev/null diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/infoIcon.png b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/infoIcon.png Binary files differdeleted file mode 100644 index da1e5334..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/infoIcon.png +++ /dev/null diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/loading_16.gif b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/loading_16.gif Binary files differdeleted file mode 100644 index 085ccaec..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/loading_16.gif +++ /dev/null diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/min.png b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/min.png Binary files differdeleted file mode 100644 index 1034d66f..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/min.png +++ /dev/null diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/minHover.png b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/minHover.png Binary files differdeleted file mode 100644 index b0d1e1af..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/minHover.png +++ /dev/null diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/off.png b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/off.png Binary files differdeleted file mode 100644 index b70b1d24..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/off.png +++ /dev/null diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/offHover.png b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/offHover.png Binary files differdeleted file mode 100644 index f3670f19..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/offHover.png +++ /dev/null diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/pixel_transparent.gif b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/pixel_transparent.gif Binary files differdeleted file mode 100644 index 6865c960..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/pixel_transparent.gif +++ /dev/null diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/roundCorner.svg b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/roundCorner.svg deleted file mode 100644 index 2dfa7280..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/roundCorner.svg +++ /dev/null @@ -1,6 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<svg xmlns="http://www.w3.org/2000/svg"> - <rect fill="white" x="0" y="0" width="100%" height="100%" /> - <rect fill="highlight" x="0" y="0" width="100%" height="100%" rx="2px"/> -</svg> - diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/search.gif b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/search.gif Binary files differdeleted file mode 100644 index 2a620987..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/search.gif +++ /dev/null diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/search.png b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/search.png Binary files differdeleted file mode 100644 index fba33b8a..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/search.png +++ /dev/null diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/shadow.gif b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/shadow.gif Binary files differdeleted file mode 100644 index af7f537e..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/shadow.gif +++ /dev/null diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/shadow2.gif b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/shadow2.gif Binary files differdeleted file mode 100644 index 099cbf35..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/shadow2.gif +++ /dev/null diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/shadowAlpha.png b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/shadowAlpha.png Binary files differdeleted file mode 100644 index a2561df9..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/shadowAlpha.png +++ /dev/null diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/sprite.png b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/sprite.png Binary files differdeleted file mode 100644 index 33d2c4d4..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/sprite.png +++ /dev/null diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/tabHoverLeft.png b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/tabHoverLeft.png Binary files differdeleted file mode 100644 index 0fb24d0c..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/tabHoverLeft.png +++ /dev/null diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/tabHoverMid.png b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/tabHoverMid.png Binary files differdeleted file mode 100644 index fbccab54..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/tabHoverMid.png +++ /dev/null diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/tabHoverRight.png b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/tabHoverRight.png Binary files differdeleted file mode 100644 index 3db0f361..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/tabHoverRight.png +++ /dev/null diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/tabLeft.png b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/tabLeft.png Binary files differdeleted file mode 100644 index a6cc9e94..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/tabLeft.png +++ /dev/null diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/tabMenuCheckbox.png b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/tabMenuCheckbox.png Binary files differdeleted file mode 100644 index 4726e622..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/tabMenuCheckbox.png +++ /dev/null diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/tabMenuPin.png b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/tabMenuPin.png Binary files differdeleted file mode 100644 index eb4b11ef..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/tabMenuPin.png +++ /dev/null diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/tabMenuRadio.png b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/tabMenuRadio.png Binary files differdeleted file mode 100644 index 55b982d7..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/tabMenuRadio.png +++ /dev/null diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/tabMenuTarget.png b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/tabMenuTarget.png Binary files differdeleted file mode 100644 index 957bd9f2..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/tabMenuTarget.png +++ /dev/null diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/tabMenuTargetHover.png b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/tabMenuTargetHover.png Binary files differdeleted file mode 100644 index 200a3708..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/tabMenuTargetHover.png +++ /dev/null diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/tabMid.png b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/tabMid.png Binary files differdeleted file mode 100644 index 68986c3b..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/tabMid.png +++ /dev/null diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/tabRight.png b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/tabRight.png Binary files differdeleted file mode 100644 index 50113079..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/tabRight.png +++ /dev/null diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/textEditorBorders.gif b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/textEditorBorders.gif Binary files differdeleted file mode 100644 index 0ee54978..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/textEditorBorders.gif +++ /dev/null diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/textEditorBorders.png b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/textEditorBorders.png Binary files differdeleted file mode 100644 index 21682c3d..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/textEditorBorders.png +++ /dev/null diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/textEditorCorners.gif b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/textEditorCorners.gif Binary files differdeleted file mode 100644 index 04f84215..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/textEditorCorners.gif +++ /dev/null diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/textEditorCorners.png b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/textEditorCorners.png Binary files differdeleted file mode 100644 index a0f839dc..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/textEditorCorners.png +++ /dev/null diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/titlebarMid.png b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/titlebarMid.png Binary files differdeleted file mode 100644 index 10998ae7..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/titlebarMid.png +++ /dev/null diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/toolbarMid.png b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/toolbarMid.png Binary files differdeleted file mode 100644 index aa21dee6..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/toolbarMid.png +++ /dev/null diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/tree_close.gif b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/tree_close.gif Binary files differdeleted file mode 100644 index e26728ab..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/tree_close.gif +++ /dev/null diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/tree_open.gif b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/tree_open.gif Binary files differdeleted file mode 100644 index edf662f3..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/tree_open.gif +++ /dev/null diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/twistyClosed.png b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/twistyClosed.png Binary files differdeleted file mode 100644 index f80319b0..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/twistyClosed.png +++ /dev/null diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/twistyOpen.png b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/twistyOpen.png Binary files differdeleted file mode 100644 index 86801243..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/twistyOpen.png +++ /dev/null diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/up.png b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/up.png Binary files differdeleted file mode 100644 index 2174d03a..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/up.png +++ /dev/null diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/upActive.png b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/upActive.png Binary files differdeleted file mode 100644 index 236cf676..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/upActive.png +++ /dev/null diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/upHover.png b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/upHover.png Binary files differdeleted file mode 100644 index cd813170..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/upHover.png +++ /dev/null diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/warningIcon.gif b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/warningIcon.gif Binary files differdeleted file mode 100644 index 84972788..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/warningIcon.gif +++ /dev/null diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/warningIcon.png b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/warningIcon.png Binary files differdeleted file mode 100644 index de51084e..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/skin/xp/warningIcon.png +++ /dev/null diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/src/firebug-lite-debug.js b/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/src/firebug-lite-debug.js deleted file mode 100644 index 40b1ae70..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/firebug-lite/src/firebug-lite-debug.js +++ /dev/null @@ -1,31176 +0,0 @@ -(function(){ - -/*!************************************************************* - * - * Firebug Lite 1.4.0 - * - * Copyright (c) 2007, Parakey Inc. - * Released under BSD license. - * More information: http://getfirebug.com/firebuglite - * - **************************************************************/ - -/*! - * CSS selectors powered by: - * - * Sizzle CSS Selector Engine - v1.0 - * Copyright 2009, The Dojo Foundation - * Released under the MIT, BSD, and GPL Licenses. - * More information: http://sizzlejs.com/ - */ - -/** @namespace describe lib */ - -// FIXME: xxxpedro if we use "var FBL = {}" the FBL won't appear in the DOM Panel in IE -var FBL = {}; - -( /** @scope s_lib @this FBL */ function() { -// ************************************************************************************************ - -// ************************************************************************************************ -// Constants - -var productionDir = "http://getfirebug.com/releases/lite/"; -var bookmarkletVersion = 4; - -// ************************************************************************************************ - -var reNotWhitespace = /[^\s]/; -var reSplitFile = /:\/{1,3}(.*?)\/([^\/]*?)\/?($|\?.*)/; - -// Globals -this.reJavascript = /\s*javascript:\s*(.*)/; -this.reChrome = /chrome:\/\/([^\/]*)\//; -this.reFile = /file:\/\/([^\/]*)\//; - - -// ************************************************************************************************ -// properties - -var userAgent = navigator.userAgent.toLowerCase(); -this.isFirefox = /firefox/.test(userAgent); -this.isOpera = /opera/.test(userAgent); -this.isSafari = /webkit/.test(userAgent); -this.isIE = /msie/.test(userAgent) && !/opera/.test(userAgent); -this.isIE6 = /msie 6/i.test(navigator.appVersion); -this.browserVersion = (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [0,'0'])[1]; -this.isIElt8 = this.isIE && (this.browserVersion-0 < 8); - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - -this.NS = null; -this.pixelsPerInch = null; - - -// ************************************************************************************************ -// Namespaces - -var namespaces = []; - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - -this.ns = function(fn) -{ - var ns = {}; - namespaces.push(fn, ns); - return ns; -}; - -var FBTrace = null; - -this.initialize = function() -{ - // Firebug Lite is already running in persistent mode so we just quit - if (window.firebug && firebug.firebuglite || window.console && console.firebuglite) - return; - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // initialize environment - - // point the FBTrace object to the local variable - if (FBL.FBTrace) - FBTrace = FBL.FBTrace; - else - FBTrace = FBL.FBTrace = {}; - - // check if the actual window is a persisted chrome context - var isChromeContext = window.Firebug && typeof window.Firebug.SharedEnv == "object"; - - // chrome context of the persistent application - if (isChromeContext) - { - // TODO: xxxpedro persist - make a better synchronization - sharedEnv = window.Firebug.SharedEnv; - delete window.Firebug.SharedEnv; - - FBL.Env = sharedEnv; - FBL.Env.isChromeContext = true; - FBTrace.messageQueue = FBL.Env.traceMessageQueue; - } - // non-persistent application - else - { - FBL.NS = document.documentElement.namespaceURI; - FBL.Env.browser = window; - FBL.Env.destroy = destroyEnvironment; - - if (document.documentElement.getAttribute("debug") == "true") - FBL.Env.Options.startOpened = true; - - // find the URL location of the loaded application - findLocation(); - - // TODO: get preferences here... - // The problem is that we don't have the Firebug object yet, so we can't use - // Firebug.loadPrefs. We're using the Store module directly instead. - var prefs = FBL.Store.get("FirebugLite") || {}; - FBL.Env.DefaultOptions = FBL.Env.Options; - FBL.Env.Options = FBL.extend(FBL.Env.Options, prefs.options || {}); - - if (FBL.isFirefox && - typeof FBL.Env.browser.console == "object" && - FBL.Env.browser.console.firebug && - FBL.Env.Options.disableWhenFirebugActive) - return; - } - - // exposes the FBL to the global namespace when in debug mode - if (FBL.Env.isDebugMode) - { - FBL.Env.browser.FBL = FBL; - } - - // check browser compatibilities - this.isQuiksMode = FBL.Env.browser.document.compatMode == "BackCompat"; - this.isIEQuiksMode = this.isIE && this.isQuiksMode; - this.isIEStantandMode = this.isIE && !this.isQuiksMode; - - this.noFixedPosition = this.isIE6 || this.isIEQuiksMode; - - // after creating/synchronizing the environment, initialize the FBTrace module - if (FBL.Env.Options.enableTrace) FBTrace.initialize(); - - if (FBTrace.DBG_INITIALIZE && isChromeContext) FBTrace.sysout("FBL.initialize - persistent application", "initialize chrome context"); - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // initialize namespaces - - if (FBTrace.DBG_INITIALIZE) FBTrace.sysout("FBL.initialize", namespaces.length/2+" namespaces BEGIN"); - - for (var i = 0; i < namespaces.length; i += 2) - { - var fn = namespaces[i]; - var ns = namespaces[i+1]; - fn.apply(ns); - } - - if (FBTrace.DBG_INITIALIZE) { - FBTrace.sysout("FBL.initialize", namespaces.length/2+" namespaces END"); - FBTrace.sysout("FBL waitForDocument", "waiting document load"); - } - - FBL.Ajax.initialize(); - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // finish environment initialization - FBL.Firebug.loadPrefs(); - - if (FBL.Env.Options.enablePersistent) - { - // TODO: xxxpedro persist - make a better synchronization - if (isChromeContext) - { - FBL.FirebugChrome.clone(FBL.Env.FirebugChrome); - } - else - { - FBL.Env.FirebugChrome = FBL.FirebugChrome; - FBL.Env.traceMessageQueue = FBTrace.messageQueue; - } - } - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // wait document load - - waitForDocument(); -}; - -var waitForDocument = function waitForDocument() -{ - // document.body not available in XML+XSL documents in Firefox - var doc = FBL.Env.browser.document; - var body = doc.getElementsByTagName("body")[0]; - - if (body) - { - calculatePixelsPerInch(doc, body); - onDocumentLoad(); - } - else - setTimeout(waitForDocument, 50); -}; - -var onDocumentLoad = function onDocumentLoad() -{ - if (FBTrace.DBG_INITIALIZE) FBTrace.sysout("FBL onDocumentLoad", "document loaded"); - - // fix IE6 problem with cache of background images, causing a lot of flickering - if (FBL.isIE6) - fixIE6BackgroundImageCache(); - - // chrome context of the persistent application - if (FBL.Env.Options.enablePersistent && FBL.Env.isChromeContext) - { - // finally, start the application in the chrome context - FBL.Firebug.initialize(); - - // if is not development mode, remove the shared environment cache object - // used to synchronize the both persistent contexts - if (!FBL.Env.isDevelopmentMode) - { - sharedEnv.destroy(); - sharedEnv = null; - } - } - // non-persistent application - else - { - FBL.FirebugChrome.create(); - } -}; - -// ************************************************************************************************ -// Env - -var sharedEnv; - -this.Env = -{ - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // Env Options (will be transported to Firebug options) - Options: - { - saveCookies: true, - - saveWindowPosition: false, - saveCommandLineHistory: false, - - startOpened: false, - startInNewWindow: false, - showIconWhenHidden: true, - - overrideConsole: true, - ignoreFirebugElements: true, - disableWhenFirebugActive: true, - - disableXHRListener: false, - disableResourceFetching: false, - - enableTrace: false, - enablePersistent: false - - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // Library location - Location: - { - sourceDir: null, - baseDir: null, - skinDir: null, - skin: null, - app: null - }, - - skin: "xp", - useLocalSkin: false, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // Env states - isDevelopmentMode: false, - isDebugMode: false, - isChromeContext: false, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // Env references - browser: null, - chrome: null -}; - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - -var destroyEnvironment = function destroyEnvironment() -{ - setTimeout(function() - { - FBL = null; - }, 100); -}; - -// ************************************************************************************************ -// Library location - -var findLocation = function findLocation() -{ - var reFirebugFile = /(firebug-lite(?:-\w+)?(?:\.js|\.jgz))(?:#(.+))?$/; - var reGetFirebugSite = /(?:http|https):\/\/getfirebug.com\//; - var isGetFirebugSite; - - var rePath = /^(.*\/)/; - var reProtocol = /^\w+:\/\//; - var path = null; - var doc = document; - - // Firebug Lite 1.3.0 bookmarklet identification - var script = doc.getElementById("FirebugLite"); - - var scriptSrc; - var hasSrcAttribute = true; - - // If the script was loaded via bookmarklet, we already have the script tag - if (script) - { - scriptSrc = script.src; - file = reFirebugFile.exec(scriptSrc); - - var version = script.getAttribute("FirebugLite"); - var number = version ? parseInt(version) : 0; - - if (!version || !number || number < bookmarkletVersion) - { - FBL.Env.bookmarkletOutdated = true; - } - } - // otherwise we must search for the correct script tag - else - { - for(var i=0, s=doc.getElementsByTagName("script"), si; si=s[i]; i++) - { - var file = null; - if ( si.nodeName.toLowerCase() == "script" ) - { - if (file = reFirebugFile.exec(si.getAttribute("firebugSrc"))) - { - scriptSrc = si.getAttribute("firebugSrc"); - hasSrcAttribute = false; - } - else if (file = reFirebugFile.exec(si.src)) - { - scriptSrc = si.src; - } - else - continue; - - script = si; - break; - } - } - } - - // mark the script tag to be ignored by Firebug Lite - if (script) - script.firebugIgnore = true; - - if (file) - { - var fileName = file[1]; - var fileOptions = file[2]; - - // absolute path - if (reProtocol.test(scriptSrc)) { - path = rePath.exec(scriptSrc)[1]; - - } - // relative path - else - { - var r = rePath.exec(scriptSrc); - var src = r ? r[1] : scriptSrc; - var backDir = /^((?:\.\.\/)+)(.*)/.exec(src); - var reLastDir = /^(.*\/)[^\/]+\/$/; - path = rePath.exec(location.href)[1]; - - // "../some/path" - if (backDir) - { - var j = backDir[1].length/3; - var p; - while (j-- > 0) - path = reLastDir.exec(path)[1]; - - path += backDir[2]; - } - - else if(src.indexOf("/") != -1) - { - // "./some/path" - if(/^\.\/./.test(src)) - { - path += src.substring(2); - } - // "/some/path" - else if(/^\/./.test(src)) - { - var domain = /^(\w+:\/\/[^\/]+)/.exec(path); - path = domain[1] + src; - } - // "some/path" - else - { - path += src; - } - } - } - } - - FBL.Env.isChromeExtension = script && script.getAttribute("extension") == "Chrome"; - if (FBL.Env.isChromeExtension) - { - path = productionDir; - FBL.Env.bookmarkletOutdated = false; - script = {innerHTML: "{showIconWhenHidden:false}"}; - } - - isGetFirebugSite = reGetFirebugSite.test(path); - - if (isGetFirebugSite && path.indexOf("/releases/lite/") == -1) - { - // See Issue 4587 - If we are loading the script from getfirebug.com shortcut, like - // https://getfirebug.com/firebug-lite.js, then we must manually add the full path, - // otherwise the Env.Location will hold the wrong path, which will in turn lead to - // undesirable effects like the problem in Issue 4587 - path += "releases/lite/" + (fileName == "firebug-lite-beta.js" ? "beta/" : "latest/"); - } - - var m = path && path.match(/([^\/]+)\/$/) || null; - - if (path && m) - { - var Env = FBL.Env; - - // Always use the local skin when running in the same domain - // See Issue 3554: Firebug Lite should use local images when loaded locally - Env.useLocalSkin = path.indexOf(location.protocol + "//" + location.host + "/") == 0 && - // but we cannot use the locan skin when loaded from getfirebug.com, otherwise - // the bookmarklet won't work when visiting getfirebug.com - !isGetFirebugSite; - - // detecting development and debug modes via file name - if (fileName == "firebug-lite-dev.js") - { - Env.isDevelopmentMode = true; - Env.isDebugMode = true; - } - else if (fileName == "firebug-lite-debug.js") - { - Env.isDebugMode = true; - } - - // process the <html debug="true"> - if (Env.browser.document.documentElement.getAttribute("debug") == "true") - { - Env.Options.startOpened = true; - } - - // process the Script URL Options - if (fileOptions) - { - var options = fileOptions.split(","); - - for (var i = 0, length = options.length; i < length; i++) - { - var option = options[i]; - var name, value; - - if (option.indexOf("=") != -1) - { - var parts = option.split("="); - name = parts[0]; - value = eval(unescape(parts[1])); - } - else - { - name = option; - value = true; - } - - if (name == "debug") - { - Env.isDebugMode = !!value; - } - else if (name in Env.Options) - { - Env.Options[name] = value; - } - else - { - Env[name] = value; - } - } - } - - // process the Script JSON Options - if (hasSrcAttribute) - { - var innerOptions = FBL.trim(script.innerHTML); - if (innerOptions) - { - var innerOptionsObject = eval("(" + innerOptions + ")"); - - for (var name in innerOptionsObject) - { - var value = innerOptionsObject[name]; - - if (name == "debug") - { - Env.isDebugMode = !!value; - } - else if (name in Env.Options) - { - Env.Options[name] = value; - } - else - { - Env[name] = value; - } - } - } - } - - if (!Env.Options.saveCookies) - FBL.Store.remove("FirebugLite"); - - // process the Debug Mode - if (Env.isDebugMode) - { - Env.Options.startOpened = true; - Env.Options.enableTrace = true; - Env.Options.disableWhenFirebugActive = false; - } - - var loc = Env.Location; - var isProductionRelease = path.indexOf(productionDir) != -1; - - loc.sourceDir = path; - loc.baseDir = path.substr(0, path.length - m[1].length - 1); - loc.skinDir = (isProductionRelease ? path : loc.baseDir) + "skin/" + Env.skin + "/"; - loc.skin = loc.skinDir + "firebug.html"; - loc.app = path + fileName; - } - else - { - throw new Error("Firebug Error: Library path not found"); - } -}; - -// ************************************************************************************************ -// Basics - -this.bind = function() // fn, thisObject, args => thisObject.fn(args, arguments); -{ - var args = cloneArray(arguments), fn = args.shift(), object = args.shift(); - return function() { return fn.apply(object, arrayInsert(cloneArray(args), 0, arguments)); }; -}; - -this.bindFixed = function() // fn, thisObject, args => thisObject.fn(args); -{ - var args = cloneArray(arguments), fn = args.shift(), object = args.shift(); - return function() { return fn.apply(object, args); }; -}; - -this.extend = function(l, r) -{ - var newOb = {}; - for (var n in l) - newOb[n] = l[n]; - for (var n in r) - newOb[n] = r[n]; - return newOb; -}; - -this.descend = function(prototypeParent, childProperties) -{ - function protoSetter() {}; - protoSetter.prototype = prototypeParent; - var newOb = new protoSetter(); - for (var n in childProperties) - newOb[n] = childProperties[n]; - return newOb; -}; - -this.append = function(l, r) -{ - for (var n in r) - l[n] = r[n]; - - return l; -}; - -this.keys = function(map) // At least sometimes the keys will be on user-level window objects -{ - var keys = []; - try - { - for (var name in map) // enumeration is safe - keys.push(name); // name is string, safe - } - catch (exc) - { - // Sometimes we get exceptions trying to iterate properties - } - - return keys; // return is safe -}; - -this.values = function(map) -{ - var values = []; - try - { - for (var name in map) - { - try - { - values.push(map[name]); - } - catch (exc) - { - // Sometimes we get exceptions trying to access properties - if (FBTrace.DBG_ERRORS) - FBTrace.sysout("lib.values FAILED ", exc); - } - - } - } - catch (exc) - { - // Sometimes we get exceptions trying to iterate properties - if (FBTrace.DBG_ERRORS) - FBTrace.sysout("lib.values FAILED ", exc); - } - - return values; -}; - -this.remove = function(list, item) -{ - for (var i = 0; i < list.length; ++i) - { - if (list[i] == item) - { - list.splice(i, 1); - break; - } - } -}; - -this.sliceArray = function(array, index) -{ - var slice = []; - for (var i = index; i < array.length; ++i) - slice.push(array[i]); - - return slice; -}; - -function cloneArray(array, fn) -{ - var newArray = []; - - if (fn) - for (var i = 0; i < array.length; ++i) - newArray.push(fn(array[i])); - else - for (var i = 0; i < array.length; ++i) - newArray.push(array[i]); - - return newArray; -} - -function extendArray(array, array2) -{ - var newArray = []; - newArray.push.apply(newArray, array); - newArray.push.apply(newArray, array2); - return newArray; -} - -this.extendArray = extendArray; -this.cloneArray = cloneArray; - -function arrayInsert(array, index, other) -{ - for (var i = 0; i < other.length; ++i) - array.splice(i+index, 0, other[i]); - - return array; -} - -// ************************************************************************************************ - -this.createStyleSheet = function(doc, url) -{ - //TODO: xxxpedro - //var style = doc.createElementNS("http://www.w3.org/1999/xhtml", "style"); - var style = this.createElement("link"); - style.setAttribute("charset","utf-8"); - style.firebugIgnore = true; - style.setAttribute("rel", "stylesheet"); - style.setAttribute("type", "text/css"); - style.setAttribute("href", url); - - //TODO: xxxpedro - //style.innerHTML = this.getResource(url); - return style; -}; - -this.addStyleSheet = function(doc, style) -{ - var heads = doc.getElementsByTagName("head"); - if (heads.length) - heads[0].appendChild(style); - else - doc.documentElement.appendChild(style); -}; - -this.appendStylesheet = function(doc, uri) -{ - // Make sure the stylesheet is not appended twice. - if (this.$(uri, doc)) - return; - - var styleSheet = this.createStyleSheet(doc, uri); - styleSheet.setAttribute("id", uri); - this.addStyleSheet(doc, styleSheet); -}; - -this.addScript = function(doc, id, src) -{ - var element = doc.createElementNS("http://www.w3.org/1999/xhtml", "html:script"); - element.setAttribute("type", "text/javascript"); - element.setAttribute("id", id); - if (!FBTrace.DBG_CONSOLE) - FBL.unwrapObject(element).firebugIgnore = true; - - element.innerHTML = src; - if (doc.documentElement) - doc.documentElement.appendChild(element); - else - { - // See issue 1079, the svg test case gives this error - if (FBTrace.DBG_ERRORS) - FBTrace.sysout("lib.addScript doc has no documentElement:", doc); - } - return element; -}; - - -// ************************************************************************************************ - -this.getStyle = this.isIE ? - function(el, name) - { - return el.currentStyle[name] || el.style[name] || undefined; - } - : - function(el, name) - { - return el.ownerDocument.defaultView.getComputedStyle(el,null)[name] - || el.style[name] || undefined; - }; - - -// ************************************************************************************************ -// Whitespace and Entity conversions - -var entityConversionLists = this.entityConversionLists = { - normal : { - whitespace : { - '\t' : '\u200c\u2192', - '\n' : '\u200c\u00b6', - '\r' : '\u200c\u00ac', - ' ' : '\u200c\u00b7' - } - }, - reverse : { - whitespace : { - '	' : '\t', - '
' : '\n', - '\u200c\u2192' : '\t', - '\u200c\u00b6' : '\n', - '\u200c\u00ac' : '\r', - '\u200c\u00b7' : ' ' - } - } -}; - -var normal = entityConversionLists.normal, - reverse = entityConversionLists.reverse; - -function addEntityMapToList(ccode, entity) -{ - var lists = Array.prototype.slice.call(arguments, 2), - len = lists.length, - ch = String.fromCharCode(ccode); - for (var i = 0; i < len; i++) - { - var list = lists[i]; - normal[list]=normal[list] || {}; - normal[list][ch] = '&' + entity + ';'; - reverse[list]=reverse[list] || {}; - reverse[list]['&' + entity + ';'] = ch; - } -}; - -var e = addEntityMapToList, - white = 'whitespace', - text = 'text', - attr = 'attributes', - css = 'css', - editor = 'editor'; - -e(0x0022, 'quot', attr, css); -e(0x0026, 'amp', attr, text, css); -e(0x0027, 'apos', css); -e(0x003c, 'lt', attr, text, css); -e(0x003e, 'gt', attr, text, css); -e(0xa9, 'copy', text, editor); -e(0xae, 'reg', text, editor); -e(0x2122, 'trade', text, editor); - -// See http://en.wikipedia.org/wiki/Dash -e(0x2012, '#8210', attr, text, editor); // figure dash -e(0x2013, 'ndash', attr, text, editor); // en dash -e(0x2014, 'mdash', attr, text, editor); // em dash -e(0x2015, '#8213', attr, text, editor); // horizontal bar - -e(0x00a0, 'nbsp', attr, text, white, editor); -e(0x2002, 'ensp', attr, text, white, editor); -e(0x2003, 'emsp', attr, text, white, editor); -e(0x2009, 'thinsp', attr, text, white, editor); -e(0x200c, 'zwnj', attr, text, white, editor); -e(0x200d, 'zwj', attr, text, white, editor); -e(0x200e, 'lrm', attr, text, white, editor); -e(0x200f, 'rlm', attr, text, white, editor); -e(0x200b, '#8203', attr, text, white, editor); // zero-width space (ZWSP) - -//************************************************************************************************ -// Entity escaping - -var entityConversionRegexes = { - normal : {}, - reverse : {} - }; - -var escapeEntitiesRegEx = { - normal : function(list) - { - var chars = []; - for ( var ch in list) - { - chars.push(ch); - } - return new RegExp('([' + chars.join('') + '])', 'gm'); - }, - reverse : function(list) - { - var chars = []; - for ( var ch in list) - { - chars.push(ch); - } - return new RegExp('(' + chars.join('|') + ')', 'gm'); - } -}; - -function getEscapeRegexp(direction, lists) -{ - var name = '', re; - var groups = [].concat(lists); - for (i = 0; i < groups.length; i++) - { - name += groups[i].group; - } - re = entityConversionRegexes[direction][name]; - if (!re) - { - var list = {}; - if (groups.length > 1) - { - for ( var i = 0; i < groups.length; i++) - { - var aList = entityConversionLists[direction][groups[i].group]; - for ( var item in aList) - list[item] = aList[item]; - } - } else if (groups.length==1) - { - list = entityConversionLists[direction][groups[0].group]; // faster for special case - } else { - list = {}; // perhaps should print out an error here? - } - re = entityConversionRegexes[direction][name] = escapeEntitiesRegEx[direction](list); - } - return re; -}; - -function createSimpleEscape(name, direction) -{ - return function(value) - { - var list = entityConversionLists[direction][name]; - return String(value).replace( - getEscapeRegexp(direction, { - group : name, - list : list - }), - function(ch) - { - return list[ch]; - } - ); - }; -}; - -function escapeGroupsForEntities(str, lists) -{ - lists = [].concat(lists); - var re = getEscapeRegexp('normal', lists), - split = String(str).split(re), - len = split.length, - results = [], - cur, r, i, ri = 0, l, list, last = ''; - if (!len) - return [ { - str : String(str), - group : '', - name : '' - } ]; - for (i = 0; i < len; i++) - { - cur = split[i]; - if (cur == '') - continue; - for (l = 0; l < lists.length; l++) - { - list = lists[l]; - r = entityConversionLists.normal[list.group][cur]; - // if (cur == ' ' && list.group == 'whitespace' && last == ' ') // only show for runs of more than one space - // r = ' '; - if (r) - { - results[ri] = { - 'str' : r, - 'class' : list['class'], - 'extra' : list.extra[cur] ? list['class'] - + list.extra[cur] : '' - }; - break; - } - } - // last=cur; - if (!r) - results[ri] = { - 'str' : cur, - 'class' : '', - 'extra' : '' - }; - ri++; - } - return results; -}; - -this.escapeGroupsForEntities = escapeGroupsForEntities; - - -function unescapeEntities(str, lists) -{ - var re = getEscapeRegexp('reverse', lists), - split = String(str).split(re), - len = split.length, - results = [], - cur, r, i, ri = 0, l, list; - if (!len) - return str; - lists = [].concat(lists); - for (i = 0; i < len; i++) - { - cur = split[i]; - if (cur == '') - continue; - for (l = 0; l < lists.length; l++) - { - list = lists[l]; - r = entityConversionLists.reverse[list.group][cur]; - if (r) - { - results[ri] = r; - break; - } - } - if (!r) - results[ri] = cur; - ri++; - } - return results.join('') || ''; -}; - - -// ************************************************************************************************ -// String escaping - -var escapeForTextNode = this.escapeForTextNode = createSimpleEscape('text', 'normal'); -var escapeForHtmlEditor = this.escapeForHtmlEditor = createSimpleEscape('editor', 'normal'); -var escapeForElementAttribute = this.escapeForElementAttribute = createSimpleEscape('attributes', 'normal'); -var escapeForCss = this.escapeForCss = createSimpleEscape('css', 'normal'); - -// deprecated compatibility functions -//this.deprecateEscapeHTML = createSimpleEscape('text', 'normal'); -//this.deprecatedUnescapeHTML = createSimpleEscape('text', 'reverse'); -//this.escapeHTML = deprecated("use appropriate escapeFor... function", this.deprecateEscapeHTML); -//this.unescapeHTML = deprecated("use appropriate unescapeFor... function", this.deprecatedUnescapeHTML); - -var escapeForSourceLine = this.escapeForSourceLine = createSimpleEscape('text', 'normal'); - -var unescapeWhitespace = createSimpleEscape('whitespace', 'reverse'); - -this.unescapeForTextNode = function(str) -{ - if (Firebug.showTextNodesWithWhitespace) - str = unescapeWhitespace(str); - if (!Firebug.showTextNodesWithEntities) - str = escapeForElementAttribute(str); - return str; -}; - -this.escapeNewLines = function(value) -{ - return value.replace(/\r/g, "\\r").replace(/\n/g, "\\n"); -}; - -this.stripNewLines = function(value) -{ - return typeof(value) == "string" ? value.replace(/[\r\n]/g, " ") : value; -}; - -this.escapeJS = function(value) -{ - return value.replace(/\r/g, "\\r").replace(/\n/g, "\\n").replace('"', '\\"', "g"); -}; - -function escapeHTMLAttribute(value) -{ - function replaceChars(ch) - { - switch (ch) - { - case "&": - return "&"; - case "'": - return apos; - case '"': - return quot; - } - return "?"; - }; - var apos = "'", quot = """, around = '"'; - if( value.indexOf('"') == -1 ) { - quot = '"'; - apos = "'"; - } else if( value.indexOf("'") == -1 ) { - quot = '"'; - around = "'"; - } - return around + (String(value).replace(/[&'"]/g, replaceChars)) + around; -} - - -function escapeHTML(value) -{ - function replaceChars(ch) - { - switch (ch) - { - case "<": - return "<"; - case ">": - return ">"; - case "&": - return "&"; - case "'": - return "'"; - case '"': - return """; - } - return "?"; - }; - return String(value).replace(/[<>&"']/g, replaceChars); -} - -this.escapeHTML = escapeHTML; - -this.cropString = function(text, limit) -{ - text = text + ""; - - if (!limit) - var halfLimit = 50; - else - var halfLimit = limit / 2; - - if (text.length > limit) - return this.escapeNewLines(text.substr(0, halfLimit) + "..." + text.substr(text.length-halfLimit)); - else - return this.escapeNewLines(text); -}; - -this.isWhitespace = function(text) -{ - return !reNotWhitespace.exec(text); -}; - -this.splitLines = function(text) -{ - var reSplitLines2 = /.*(:?\r\n|\n|\r)?/mg; - var lines; - if (text.match) - { - lines = text.match(reSplitLines2); - } - else - { - var str = text+""; - lines = str.match(reSplitLines2); - } - lines.pop(); - return lines; -}; - - -// ************************************************************************************************ - -this.safeToString = function(ob) -{ - if (this.isIE) - { - try - { - // FIXME: xxxpedro this is failing in IE for the global "external" object - return ob + ""; - } - catch(E) - { - FBTrace.sysout("Lib.safeToString() failed for ", ob); - return ""; - } - } - - try - { - if (ob && "toString" in ob && typeof ob.toString == "function") - return ob.toString(); - } - catch (exc) - { - // xxxpedro it is not safe to use ob+""? - return ob + ""; - ///return "[an object with no toString() function]"; - } -}; - -// ************************************************************************************************ - -this.hasProperties = function(ob) -{ - try - { - for (var name in ob) - return true; - } catch (exc) {} - return false; -}; - -// ************************************************************************************************ -// String Util - -var reTrim = /^\s+|\s+$/g; -this.trim = function(s) -{ - return s.replace(reTrim, ""); -}; - - -// ************************************************************************************************ -// Empty - -this.emptyFn = function(){}; - - - -// ************************************************************************************************ -// Visibility - -this.isVisible = function(elt) -{ - /* - if (elt instanceof XULElement) - { - //FBTrace.sysout("isVisible elt.offsetWidth: "+elt.offsetWidth+" offsetHeight:"+ elt.offsetHeight+" localName:"+ elt.localName+" nameSpace:"+elt.nameSpaceURI+"\n"); - return (!elt.hidden && !elt.collapsed); - } - /**/ - - return this.getStyle(elt, "visibility") != "hidden" && - ( elt.offsetWidth > 0 || elt.offsetHeight > 0 - || elt.tagName in invisibleTags - || elt.namespaceURI == "http://www.w3.org/2000/svg" - || elt.namespaceURI == "http://www.w3.org/1998/Math/MathML" ); -}; - -this.collapse = function(elt, collapsed) -{ - // IE6 doesn't support the [collapsed] CSS selector. IE7 does support the selector, - // but it is causing a bug (the element disappears when you set the "collapsed" - // attribute, but it doesn't appear when you remove the attribute. So, for those - // cases, we need to use the class attribute. - if (this.isIElt8) - { - if (collapsed) - this.setClass(elt, "collapsed"); - else - this.removeClass(elt, "collapsed"); - } - else - elt.setAttribute("collapsed", collapsed ? "true" : "false"); -}; - -this.obscure = function(elt, obscured) -{ - if (obscured) - this.setClass(elt, "obscured"); - else - this.removeClass(elt, "obscured"); -}; - -this.hide = function(elt, hidden) -{ - elt.style.visibility = hidden ? "hidden" : "visible"; -}; - -this.clearNode = function(node) -{ - var nodeName = " " + node.nodeName.toLowerCase() + " "; - var ignoreTags = " table tbody thead tfoot th tr td "; - - // IE can't use innerHTML of table elements - if (this.isIE && ignoreTags.indexOf(nodeName) != -1) - this.eraseNode(node); - else - node.innerHTML = ""; -}; - -this.eraseNode = function(node) -{ - while (node.lastChild) - node.removeChild(node.lastChild); -}; - -// ************************************************************************************************ -// Window iteration - -this.iterateWindows = function(win, handler) -{ - if (!win || !win.document) - return; - - handler(win); - - if (win == top || !win.frames) return; // XXXjjb hack for chromeBug - - for (var i = 0; i < win.frames.length; ++i) - { - var subWin = win.frames[i]; - if (subWin != win) - this.iterateWindows(subWin, handler); - } -}; - -this.getRootWindow = function(win) -{ - for (; win; win = win.parent) - { - if (!win.parent || win == win.parent || !this.instanceOf(win.parent, "Window")) - return win; - } - return null; -}; - -// ************************************************************************************************ -// Graphics - -this.getClientOffset = function(elt) -{ - var addOffset = function addOffset(elt, coords, view) - { - var p = elt.offsetParent; - - ///var style = isIE ? elt.currentStyle : view.getComputedStyle(elt, ""); - var chrome = Firebug.chrome; - - if (elt.offsetLeft) - ///coords.x += elt.offsetLeft + parseInt(style.borderLeftWidth); - coords.x += elt.offsetLeft + chrome.getMeasurementInPixels(elt, "borderLeft"); - if (elt.offsetTop) - ///coords.y += elt.offsetTop + parseInt(style.borderTopWidth); - coords.y += elt.offsetTop + chrome.getMeasurementInPixels(elt, "borderTop"); - - if (p) - { - if (p.nodeType == 1) - addOffset(p, coords, view); - } - else - { - var otherView = isIE ? elt.ownerDocument.parentWindow : elt.ownerDocument.defaultView; - // IE will fail when reading the frameElement property of a popup window. - // We don't need it anyway once it is outside the (popup) viewport, so we're - // ignoring the frameElement check when the window is a popup - if (!otherView.opener && otherView.frameElement) - addOffset(otherView.frameElement, coords, otherView); - } - }; - - var isIE = this.isIE; - var coords = {x: 0, y: 0}; - if (elt) - { - var view = isIE ? elt.ownerDocument.parentWindow : elt.ownerDocument.defaultView; - addOffset(elt, coords, view); - } - - return coords; -}; - -this.getViewOffset = function(elt, singleFrame) -{ - function addOffset(elt, coords, view) - { - var p = elt.offsetParent; - coords.x += elt.offsetLeft - (p ? p.scrollLeft : 0); - coords.y += elt.offsetTop - (p ? p.scrollTop : 0); - - if (p) - { - if (p.nodeType == 1) - { - var parentStyle = view.getComputedStyle(p, ""); - if (parentStyle.position != "static") - { - coords.x += parseInt(parentStyle.borderLeftWidth); - coords.y += parseInt(parentStyle.borderTopWidth); - - if (p.localName == "TABLE") - { - coords.x += parseInt(parentStyle.paddingLeft); - coords.y += parseInt(parentStyle.paddingTop); - } - else if (p.localName == "BODY") - { - var style = view.getComputedStyle(elt, ""); - coords.x += parseInt(style.marginLeft); - coords.y += parseInt(style.marginTop); - } - } - else if (p.localName == "BODY") - { - coords.x += parseInt(parentStyle.borderLeftWidth); - coords.y += parseInt(parentStyle.borderTopWidth); - } - - var parent = elt.parentNode; - while (p != parent) - { - coords.x -= parent.scrollLeft; - coords.y -= parent.scrollTop; - parent = parent.parentNode; - } - addOffset(p, coords, view); - } - } - else - { - if (elt.localName == "BODY") - { - var style = view.getComputedStyle(elt, ""); - coords.x += parseInt(style.borderLeftWidth); - coords.y += parseInt(style.borderTopWidth); - - var htmlStyle = view.getComputedStyle(elt.parentNode, ""); - coords.x -= parseInt(htmlStyle.paddingLeft); - coords.y -= parseInt(htmlStyle.paddingTop); - } - - if (elt.scrollLeft) - coords.x += elt.scrollLeft; - if (elt.scrollTop) - coords.y += elt.scrollTop; - - var win = elt.ownerDocument.defaultView; - if (win && (!singleFrame && win.frameElement)) - addOffset(win.frameElement, coords, win); - } - - } - - var coords = {x: 0, y: 0}; - if (elt) - addOffset(elt, coords, elt.ownerDocument.defaultView); - - return coords; -}; - -this.getLTRBWH = function(elt) -{ - var bcrect, - dims = {"left": 0, "top": 0, "right": 0, "bottom": 0, "width": 0, "height": 0}; - - if (elt) - { - bcrect = elt.getBoundingClientRect(); - dims.left = bcrect.left; - dims.top = bcrect.top; - dims.right = bcrect.right; - dims.bottom = bcrect.bottom; - - if(bcrect.width) - { - dims.width = bcrect.width; - dims.height = bcrect.height; - } - else - { - dims.width = dims.right - dims.left; - dims.height = dims.bottom - dims.top; - } - } - return dims; -}; - -this.applyBodyOffsets = function(elt, clientRect) -{ - var od = elt.ownerDocument; - if (!od.body) - return clientRect; - - var style = od.defaultView.getComputedStyle(od.body, null); - - var pos = style.getPropertyValue('position'); - if(pos === 'absolute' || pos === 'relative') - { - var borderLeft = parseInt(style.getPropertyValue('border-left-width').replace('px', ''),10) || 0; - var borderTop = parseInt(style.getPropertyValue('border-top-width').replace('px', ''),10) || 0; - var paddingLeft = parseInt(style.getPropertyValue('padding-left').replace('px', ''),10) || 0; - var paddingTop = parseInt(style.getPropertyValue('padding-top').replace('px', ''),10) || 0; - var marginLeft = parseInt(style.getPropertyValue('margin-left').replace('px', ''),10) || 0; - var marginTop = parseInt(style.getPropertyValue('margin-top').replace('px', ''),10) || 0; - - var offsetX = borderLeft + paddingLeft + marginLeft; - var offsetY = borderTop + paddingTop + marginTop; - - clientRect.left -= offsetX; - clientRect.top -= offsetY; - clientRect.right -= offsetX; - clientRect.bottom -= offsetY; - } - - return clientRect; -}; - -this.getOffsetSize = function(elt) -{ - return {width: elt.offsetWidth, height: elt.offsetHeight}; -}; - -this.getOverflowParent = function(element) -{ - for (var scrollParent = element.parentNode; scrollParent; scrollParent = scrollParent.offsetParent) - { - if (scrollParent.scrollHeight > scrollParent.offsetHeight) - return scrollParent; - } -}; - -this.isScrolledToBottom = function(element) -{ - var onBottom = (element.scrollTop + element.offsetHeight) == element.scrollHeight; - if (FBTrace.DBG_CONSOLE) - FBTrace.sysout("isScrolledToBottom offsetHeight: "+element.offsetHeight +" onBottom:"+onBottom); - return onBottom; -}; - -this.scrollToBottom = function(element) -{ - element.scrollTop = element.scrollHeight; - - if (FBTrace.DBG_CONSOLE) - { - FBTrace.sysout("scrollToBottom reset scrollTop "+element.scrollTop+" = "+element.scrollHeight); - if (element.scrollHeight == element.offsetHeight) - FBTrace.sysout("scrollToBottom attempt to scroll non-scrollable element "+element, element); - } - - return (element.scrollTop == element.scrollHeight); -}; - -this.move = function(element, x, y) -{ - element.style.left = x + "px"; - element.style.top = y + "px"; -}; - -this.resize = function(element, w, h) -{ - element.style.width = w + "px"; - element.style.height = h + "px"; -}; - -this.linesIntoCenterView = function(element, scrollBox) // {before: int, after: int} -{ - if (!scrollBox) - scrollBox = this.getOverflowParent(element); - - if (!scrollBox) - return; - - var offset = this.getClientOffset(element); - - var topSpace = offset.y - scrollBox.scrollTop; - var bottomSpace = (scrollBox.scrollTop + scrollBox.clientHeight) - - (offset.y + element.offsetHeight); - - if (topSpace < 0 || bottomSpace < 0) - { - var split = (scrollBox.clientHeight/2); - var centerY = offset.y - split; - scrollBox.scrollTop = centerY; - topSpace = split; - bottomSpace = split - element.offsetHeight; - } - - return {before: Math.round((topSpace/element.offsetHeight) + 0.5), - after: Math.round((bottomSpace/element.offsetHeight) + 0.5) }; -}; - -this.scrollIntoCenterView = function(element, scrollBox, notX, notY) -{ - if (!element) - return; - - if (!scrollBox) - scrollBox = this.getOverflowParent(element); - - if (!scrollBox) - return; - - var offset = this.getClientOffset(element); - - if (!notY) - { - var topSpace = offset.y - scrollBox.scrollTop; - var bottomSpace = (scrollBox.scrollTop + scrollBox.clientHeight) - - (offset.y + element.offsetHeight); - - if (topSpace < 0 || bottomSpace < 0) - { - var centerY = offset.y - (scrollBox.clientHeight/2); - scrollBox.scrollTop = centerY; - } - } - - if (!notX) - { - var leftSpace = offset.x - scrollBox.scrollLeft; - var rightSpace = (scrollBox.scrollLeft + scrollBox.clientWidth) - - (offset.x + element.clientWidth); - - if (leftSpace < 0 || rightSpace < 0) - { - var centerX = offset.x - (scrollBox.clientWidth/2); - scrollBox.scrollLeft = centerX; - } - } - if (FBTrace.DBG_SOURCEFILES) - FBTrace.sysout("lib.scrollIntoCenterView ","Element:"+element.innerHTML); -}; - - -// ************************************************************************************************ -// CSS - -var cssKeywordMap = null; -var cssPropNames = null; -var cssColorNames = null; -var imageRules = null; - -this.getCSSKeywordsByProperty = function(propName) -{ - if (!cssKeywordMap) - { - cssKeywordMap = {}; - - for (var name in this.cssInfo) - { - var list = []; - - var types = this.cssInfo[name]; - for (var i = 0; i < types.length; ++i) - { - var keywords = this.cssKeywords[types[i]]; - if (keywords) - list.push.apply(list, keywords); - } - - cssKeywordMap[name] = list; - } - } - - return propName in cssKeywordMap ? cssKeywordMap[propName] : []; -}; - -this.getCSSPropertyNames = function() -{ - if (!cssPropNames) - { - cssPropNames = []; - - for (var name in this.cssInfo) - cssPropNames.push(name); - } - - return cssPropNames; -}; - -this.isColorKeyword = function(keyword) -{ - if (keyword == "transparent") - return false; - - if (!cssColorNames) - { - cssColorNames = []; - - var colors = this.cssKeywords["color"]; - for (var i = 0; i < colors.length; ++i) - cssColorNames.push(colors[i].toLowerCase()); - - var systemColors = this.cssKeywords["systemColor"]; - for (var i = 0; i < systemColors.length; ++i) - cssColorNames.push(systemColors[i].toLowerCase()); - } - - return cssColorNames.indexOf ? // Array.indexOf is not available in IE - cssColorNames.indexOf(keyword.toLowerCase()) != -1 : - (" " + cssColorNames.join(" ") + " ").indexOf(" " + keyword.toLowerCase() + " ") != -1; -}; - -this.isImageRule = function(rule) -{ - if (!imageRules) - { - imageRules = []; - - for (var i in this.cssInfo) - { - var r = i.toLowerCase(); - var suffix = "image"; - if (r.match(suffix + "$") == suffix || r == "background") - imageRules.push(r); - } - } - - return imageRules.indexOf ? // Array.indexOf is not available in IE - imageRules.indexOf(rule.toLowerCase()) != -1 : - (" " + imageRules.join(" ") + " ").indexOf(" " + rule.toLowerCase() + " ") != -1; -}; - -this.copyTextStyles = function(fromNode, toNode, style) -{ - var view = this.isIE ? - fromNode.ownerDocument.parentWindow : - fromNode.ownerDocument.defaultView; - - if (view) - { - if (!style) - style = this.isIE ? fromNode.currentStyle : view.getComputedStyle(fromNode, ""); - - toNode.style.fontFamily = style.fontFamily; - - // TODO: xxxpedro need to create a FBL.getComputedStyle() because IE - // returns wrong computed styles for inherited properties (like font-*) - // - // Also would be good to create a FBL.getStyle() - toNode.style.fontSize = style.fontSize; - toNode.style.fontWeight = style.fontWeight; - toNode.style.fontStyle = style.fontStyle; - - return style; - } -}; - -this.copyBoxStyles = function(fromNode, toNode, style) -{ - var view = this.isIE ? - fromNode.ownerDocument.parentWindow : - fromNode.ownerDocument.defaultView; - - if (view) - { - if (!style) - style = this.isIE ? fromNode.currentStyle : view.getComputedStyle(fromNode, ""); - - toNode.style.marginTop = style.marginTop; - toNode.style.marginRight = style.marginRight; - toNode.style.marginBottom = style.marginBottom; - toNode.style.marginLeft = style.marginLeft; - toNode.style.borderTopWidth = style.borderTopWidth; - toNode.style.borderRightWidth = style.borderRightWidth; - toNode.style.borderBottomWidth = style.borderBottomWidth; - toNode.style.borderLeftWidth = style.borderLeftWidth; - - return style; - } -}; - -this.readBoxStyles = function(style) -{ - var styleNames = { - "margin-top": "marginTop", "margin-right": "marginRight", - "margin-left": "marginLeft", "margin-bottom": "marginBottom", - "border-top-width": "borderTop", "border-right-width": "borderRight", - "border-left-width": "borderLeft", "border-bottom-width": "borderBottom", - "padding-top": "paddingTop", "padding-right": "paddingRight", - "padding-left": "paddingLeft", "padding-bottom": "paddingBottom", - "z-index": "zIndex" - }; - - var styles = {}; - for (var styleName in styleNames) - styles[styleNames[styleName]] = parseInt(style.getPropertyCSSValue(styleName).cssText) || 0; - if (FBTrace.DBG_INSPECT) - FBTrace.sysout("readBoxStyles ", styles); - return styles; -}; - -this.getBoxFromStyles = function(style, element) -{ - var args = this.readBoxStyles(style); - args.width = element.offsetWidth - - (args.paddingLeft+args.paddingRight+args.borderLeft+args.borderRight); - args.height = element.offsetHeight - - (args.paddingTop+args.paddingBottom+args.borderTop+args.borderBottom); - return args; -}; - -this.getElementCSSSelector = function(element) -{ - var label = element.localName.toLowerCase(); - if (element.id) - label += "#" + element.id; - if (element.hasAttribute("class")) - label += "." + element.getAttribute("class").split(" ")[0]; - - return label; -}; - -this.getURLForStyleSheet= function(styleSheet) -{ - //http://www.w3.org/TR/DOM-Level-2-Style/stylesheets.html#StyleSheets-StyleSheet. For inline style sheets, the value of this attribute is null. - return (styleSheet.href ? styleSheet.href : styleSheet.ownerNode.ownerDocument.URL); -}; - -this.getDocumentForStyleSheet = function(styleSheet) -{ - while (styleSheet.parentStyleSheet && !styleSheet.ownerNode) - { - styleSheet = styleSheet.parentStyleSheet; - } - if (styleSheet.ownerNode) - return styleSheet.ownerNode.ownerDocument; -}; - -/** - * Retrieves the instance number for a given style sheet. The instance number - * is sheet's index within the set of all other sheets whose URL is the same. - */ -this.getInstanceForStyleSheet = function(styleSheet, ownerDocument) -{ - // System URLs are always unique (or at least we are making this assumption) - if (FBL.isSystemStyleSheet(styleSheet)) - return 0; - - // ownerDocument is an optional hint for performance - if (FBTrace.DBG_CSS) FBTrace.sysout("getInstanceForStyleSheet: " + styleSheet.href + " " + styleSheet.media.mediaText + " " + (styleSheet.ownerNode && FBL.getElementXPath(styleSheet.ownerNode)), ownerDocument); - ownerDocument = ownerDocument || FBL.getDocumentForStyleSheet(styleSheet); - - var ret = 0, - styleSheets = ownerDocument.styleSheets, - href = styleSheet.href; - for (var i = 0; i < styleSheets.length; i++) - { - var curSheet = styleSheets[i]; - if (FBTrace.DBG_CSS) FBTrace.sysout("getInstanceForStyleSheet: compare href " + i + " " + curSheet.href + " " + curSheet.media.mediaText + " " + (curSheet.ownerNode && FBL.getElementXPath(curSheet.ownerNode))); - if (curSheet == styleSheet) - break; - if (curSheet.href == href) - ret++; - } - return ret; -}; - -// ************************************************************************************************ -// HTML and XML Serialization - - -var getElementType = this.getElementType = function(node) -{ - if (isElementXUL(node)) - return 'xul'; - else if (isElementSVG(node)) - return 'svg'; - else if (isElementMathML(node)) - return 'mathml'; - else if (isElementXHTML(node)) - return 'xhtml'; - else if (isElementHTML(node)) - return 'html'; -}; - -var getElementSimpleType = this.getElementSimpleType = function(node) -{ - if (isElementSVG(node)) - return 'svg'; - else if (isElementMathML(node)) - return 'mathml'; - else - return 'html'; -}; - -var isElementHTML = this.isElementHTML = function(node) -{ - return node.nodeName == node.nodeName.toUpperCase(); -}; - -var isElementXHTML = this.isElementXHTML = function(node) -{ - return node.nodeName == node.nodeName.toLowerCase(); -}; - -var isElementMathML = this.isElementMathML = function(node) -{ - return node.namespaceURI == 'http://www.w3.org/1998/Math/MathML'; -}; - -var isElementSVG = this.isElementSVG = function(node) -{ - return node.namespaceURI == 'http://www.w3.org/2000/svg'; -}; - -var isElementXUL = this.isElementXUL = function(node) -{ - return node instanceof XULElement; -}; - -this.isSelfClosing = function(element) -{ - if (isElementSVG(element) || isElementMathML(element)) - return true; - var tag = element.localName.toLowerCase(); - return (this.selfClosingTags.hasOwnProperty(tag)); -}; - -this.getElementHTML = function(element) -{ - var self=this; - function toHTML(elt) - { - if (elt.nodeType == Node.ELEMENT_NODE) - { - if (unwrapObject(elt).firebugIgnore) - return; - - html.push('<', elt.nodeName.toLowerCase()); - - for (var i = 0; i < elt.attributes.length; ++i) - { - var attr = elt.attributes[i]; - - // Hide attributes set by Firebug - if (attr.localName.indexOf("firebug-") == 0) - continue; - - // MathML - if (attr.localName.indexOf("-moz-math") == 0) - { - // just hide for now - continue; - } - - html.push(' ', attr.nodeName, '="', escapeForElementAttribute(attr.nodeValue),'"'); - } - - if (elt.firstChild) - { - html.push('>'); - - var pureText=true; - for (var child = element.firstChild; child; child = child.nextSibling) - pureText=pureText && (child.nodeType == Node.TEXT_NODE); - - if (pureText) - html.push(escapeForHtmlEditor(elt.textContent)); - else { - for (var child = elt.firstChild; child; child = child.nextSibling) - toHTML(child); - } - - html.push('</', elt.nodeName.toLowerCase(), '>'); - } - else if (isElementSVG(elt) || isElementMathML(elt)) - { - html.push('/>'); - } - else if (self.isSelfClosing(elt)) - { - html.push((isElementXHTML(elt))?'/>':'>'); - } - else - { - html.push('></', elt.nodeName.toLowerCase(), '>'); - } - } - else if (elt.nodeType == Node.TEXT_NODE) - html.push(escapeForTextNode(elt.textContent)); - else if (elt.nodeType == Node.CDATA_SECTION_NODE) - html.push('<![CDATA[', elt.nodeValue, ']]>'); - else if (elt.nodeType == Node.COMMENT_NODE) - html.push('<!--', elt.nodeValue, '-->'); - } - - var html = []; - toHTML(element); - return html.join(""); -}; - -this.getElementXML = function(element) -{ - function toXML(elt) - { - if (elt.nodeType == Node.ELEMENT_NODE) - { - if (unwrapObject(elt).firebugIgnore) - return; - - xml.push('<', elt.nodeName.toLowerCase()); - - for (var i = 0; i < elt.attributes.length; ++i) - { - var attr = elt.attributes[i]; - - // Hide attributes set by Firebug - if (attr.localName.indexOf("firebug-") == 0) - continue; - - // MathML - if (attr.localName.indexOf("-moz-math") == 0) - { - // just hide for now - continue; - } - - xml.push(' ', attr.nodeName, '="', escapeForElementAttribute(attr.nodeValue),'"'); - } - - if (elt.firstChild) - { - xml.push('>'); - - for (var child = elt.firstChild; child; child = child.nextSibling) - toXML(child); - - xml.push('</', elt.nodeName.toLowerCase(), '>'); - } - else - xml.push('/>'); - } - else if (elt.nodeType == Node.TEXT_NODE) - xml.push(elt.nodeValue); - else if (elt.nodeType == Node.CDATA_SECTION_NODE) - xml.push('<![CDATA[', elt.nodeValue, ']]>'); - else if (elt.nodeType == Node.COMMENT_NODE) - xml.push('<!--', elt.nodeValue, '-->'); - } - - var xml = []; - toXML(element); - return xml.join(""); -}; - - -// ************************************************************************************************ -// CSS classes - -this.hasClass = function(node, name) // className, className, ... -{ - // TODO: xxxpedro when lib.hasClass is called with more than 2 arguments? - // this function can be optimized a lot if assumed 2 arguments only, - // which seems to be what happens 99% of the time - if (arguments.length == 2) - return (' '+node.className+' ').indexOf(' '+name+' ') != -1; - - if (!node || node.nodeType != 1) - return false; - else - { - for (var i=1; i<arguments.length; ++i) - { - var name = arguments[i]; - var re = new RegExp("(^|\\s)"+name+"($|\\s)"); - if (!re.exec(node.className)) - return false; - } - - return true; - } -}; - -this.old_hasClass = function(node, name) // className, className, ... -{ - if (!node || node.nodeType != 1) - return false; - else - { - for (var i=1; i<arguments.length; ++i) - { - var name = arguments[i]; - var re = new RegExp("(^|\\s)"+name+"($|\\s)"); - if (!re.exec(node.className)) - return false; - } - - return true; - } -}; - -this.setClass = function(node, name) -{ - if (node && (' '+node.className+' ').indexOf(' '+name+' ') == -1) - ///if (node && !this.hasClass(node, name)) - node.className += " " + name; -}; - -this.getClassValue = function(node, name) -{ - var re = new RegExp(name+"-([^ ]+)"); - var m = re.exec(node.className); - return m ? m[1] : ""; -}; - -this.removeClass = function(node, name) -{ - if (node && node.className) - { - var index = node.className.indexOf(name); - if (index >= 0) - { - var size = name.length; - node.className = node.className.substr(0,index-1) + node.className.substr(index+size); - } - } -}; - -this.toggleClass = function(elt, name) -{ - if ((' '+elt.className+' ').indexOf(' '+name+' ') != -1) - ///if (this.hasClass(elt, name)) - this.removeClass(elt, name); - else - this.setClass(elt, name); -}; - -this.setClassTimed = function(elt, name, context, timeout) -{ - if (!timeout) - timeout = 1300; - - if (elt.__setClassTimeout) - context.clearTimeout(elt.__setClassTimeout); - else - this.setClass(elt, name); - - elt.__setClassTimeout = context.setTimeout(function() - { - delete elt.__setClassTimeout; - - FBL.removeClass(elt, name); - }, timeout); -}; - -this.cancelClassTimed = function(elt, name, context) -{ - if (elt.__setClassTimeout) - { - FBL.removeClass(elt, name); - context.clearTimeout(elt.__setClassTimeout); - delete elt.__setClassTimeout; - } -}; - - -// ************************************************************************************************ -// DOM queries - -this.$ = function(id, doc) -{ - if (doc) - return doc.getElementById(id); - else - { - return FBL.Firebug.chrome.document.getElementById(id); - } -}; - -this.$$ = function(selector, doc) -{ - if (doc || !FBL.Firebug.chrome) - return FBL.Firebug.Selector(selector, doc); - else - { - return FBL.Firebug.Selector(selector, FBL.Firebug.chrome.document); - } -}; - -this.getChildByClass = function(node) // ,classname, classname, classname... -{ - for (var i = 1; i < arguments.length; ++i) - { - var className = arguments[i]; - var child = node.firstChild; - node = null; - for (; child; child = child.nextSibling) - { - if (this.hasClass(child, className)) - { - node = child; - break; - } - } - } - - return node; -}; - -this.getAncestorByClass = function(node, className) -{ - for (var parent = node; parent; parent = parent.parentNode) - { - if (this.hasClass(parent, className)) - return parent; - } - - return null; -}; - - -this.getElementsByClass = function(node, className) -{ - var result = []; - - for (var child = node.firstChild; child; child = child.nextSibling) - { - if (this.hasClass(child, className)) - result.push(child); - } - - return result; -}; - -this.getElementByClass = function(node, className) // className, className, ... -{ - var args = cloneArray(arguments); args.splice(0, 1); - for (var child = node.firstChild; child; child = child.nextSibling) - { - var args1 = cloneArray(args); args1.unshift(child); - if (FBL.hasClass.apply(null, args1)) - return child; - else - { - var found = FBL.getElementByClass.apply(null, args1); - if (found) - return found; - } - } - - return null; -}; - -this.isAncestor = function(node, potentialAncestor) -{ - for (var parent = node; parent; parent = parent.parentNode) - { - if (parent == potentialAncestor) - return true; - } - - return false; -}; - -this.getNextElement = function(node) -{ - while (node && node.nodeType != 1) - node = node.nextSibling; - - return node; -}; - -this.getPreviousElement = function(node) -{ - while (node && node.nodeType != 1) - node = node.previousSibling; - - return node; -}; - -this.getBody = function(doc) -{ - if (doc.body) - return doc.body; - - var body = doc.getElementsByTagName("body")[0]; - if (body) - return body; - - return doc.firstChild; // For non-HTML docs -}; - -this.findNextDown = function(node, criteria) -{ - if (!node) - return null; - - for (var child = node.firstChild; child; child = child.nextSibling) - { - if (criteria(child)) - return child; - - var next = this.findNextDown(child, criteria); - if (next) - return next; - } -}; - -this.findPreviousUp = function(node, criteria) -{ - if (!node) - return null; - - for (var child = node.lastChild; child; child = child.previousSibling) - { - var next = this.findPreviousUp(child, criteria); - if (next) - return next; - - if (criteria(child)) - return child; - } -}; - -this.findNext = function(node, criteria, upOnly, maxRoot) -{ - if (!node) - return null; - - if (!upOnly) - { - var next = this.findNextDown(node, criteria); - if (next) - return next; - } - - for (var sib = node.nextSibling; sib; sib = sib.nextSibling) - { - if (criteria(sib)) - return sib; - - var next = this.findNextDown(sib, criteria); - if (next) - return next; - } - - if (node.parentNode && node.parentNode != maxRoot) - return this.findNext(node.parentNode, criteria, true); -}; - -this.findPrevious = function(node, criteria, downOnly, maxRoot) -{ - if (!node) - return null; - - for (var sib = node.previousSibling; sib; sib = sib.previousSibling) - { - var prev = this.findPreviousUp(sib, criteria); - if (prev) - return prev; - - if (criteria(sib)) - return sib; - } - - if (!downOnly) - { - var next = this.findPreviousUp(node, criteria); - if (next) - return next; - } - - if (node.parentNode && node.parentNode != maxRoot) - { - if (criteria(node.parentNode)) - return node.parentNode; - - return this.findPrevious(node.parentNode, criteria, true); - } -}; - -this.getNextByClass = function(root, state) -{ - var iter = function iter(node) { return node.nodeType == 1 && FBL.hasClass(node, state); }; - return this.findNext(root, iter); -}; - -this.getPreviousByClass = function(root, state) -{ - var iter = function iter(node) { return node.nodeType == 1 && FBL.hasClass(node, state); }; - return this.findPrevious(root, iter); -}; - -this.isElement = function(o) -{ - try { - return o && this.instanceOf(o, "Element"); - } - catch (ex) { - return false; - } -}; - - -// ************************************************************************************************ -// DOM Modification - -// TODO: xxxpedro use doc fragments in Context API -var appendFragment = null; - -this.appendInnerHTML = function(element, html, referenceElement) -{ - // if undefined, we must convert it to null otherwise it will throw an error in IE - // when executing element.insertBefore(firstChild, referenceElement) - referenceElement = referenceElement || null; - - var doc = element.ownerDocument; - - // doc.createRange not available in IE - if (doc.createRange) - { - var range = doc.createRange(); // a helper object - range.selectNodeContents(element); // the environment to interpret the html - - var fragment = range.createContextualFragment(html); // parse - var firstChild = fragment.firstChild; - element.insertBefore(fragment, referenceElement); - } - else - { - if (!appendFragment || appendFragment.ownerDocument != doc) - appendFragment = doc.createDocumentFragment(); - - var div = doc.createElement("div"); - div.innerHTML = html; - - var firstChild = div.firstChild; - while (div.firstChild) - appendFragment.appendChild(div.firstChild); - - element.insertBefore(appendFragment, referenceElement); - - div = null; - } - - return firstChild; -}; - - -// ************************************************************************************************ -// DOM creation - -this.createElement = function(tagName, properties) -{ - properties = properties || {}; - var doc = properties.document || FBL.Firebug.chrome.document; - - var element = doc.createElement(tagName); - - for(var name in properties) - { - if (name != "document") - { - element[name] = properties[name]; - } - } - - return element; -}; - -this.createGlobalElement = function(tagName, properties) -{ - properties = properties || {}; - var doc = FBL.Env.browser.document; - - var element = this.NS && doc.createElementNS ? - doc.createElementNS(FBL.NS, tagName) : - doc.createElement(tagName); - - for(var name in properties) - { - var propname = name; - if (FBL.isIE && name == "class") propname = "className"; - - if (name != "document") - { - element.setAttribute(propname, properties[name]); - } - } - - return element; -}; - -//************************************************************************************************ - -this.safeGetWindowLocation = function(window) -{ - try - { - if (window) - { - if (window.closed) - return "(window.closed)"; - if ("location" in window) - return window.location+""; - else - return "(no window.location)"; - } - else - return "(no context.window)"; - } - catch(exc) - { - if (FBTrace.DBG_WINDOWS || FBTrace.DBG_ERRORS) - FBTrace.sysout("TabContext.getWindowLocation failed "+exc, exc); - FBTrace.sysout("TabContext.getWindowLocation failed window:", window); - return "(getWindowLocation: "+exc+")"; - } -}; - -// ************************************************************************************************ -// Events - -this.isLeftClick = function(event) -{ - return (this.isIE && event.type != "click" && event.type != "dblclick" ? - event.button == 1 : // IE "click" and "dblclick" button model - event.button == 0) && // others - this.noKeyModifiers(event); -}; - -this.isMiddleClick = function(event) -{ - return (this.isIE && event.type != "click" && event.type != "dblclick" ? - event.button == 4 : // IE "click" and "dblclick" button model - event.button == 1) && - this.noKeyModifiers(event); -}; - -this.isRightClick = function(event) -{ - return (this.isIE && event.type != "click" && event.type != "dblclick" ? - event.button == 2 : // IE "click" and "dblclick" button model - event.button == 2) && - this.noKeyModifiers(event); -}; - -this.noKeyModifiers = function(event) -{ - return !event.ctrlKey && !event.shiftKey && !event.altKey && !event.metaKey; -}; - -this.isControlClick = function(event) -{ - return (this.isIE && event.type != "click" && event.type != "dblclick" ? - event.button == 1 : // IE "click" and "dblclick" button model - event.button == 0) && - this.isControl(event); -}; - -this.isShiftClick = function(event) -{ - return (this.isIE && event.type != "click" && event.type != "dblclick" ? - event.button == 1 : // IE "click" and "dblclick" button model - event.button == 0) && - this.isShift(event); -}; - -this.isControl = function(event) -{ - return (event.metaKey || event.ctrlKey) && !event.shiftKey && !event.altKey; -}; - -this.isAlt = function(event) -{ - return event.altKey && !event.ctrlKey && !event.shiftKey && !event.metaKey; -}; - -this.isAltClick = function(event) -{ - return (this.isIE && event.type != "click" && event.type != "dblclick" ? - event.button == 1 : // IE "click" and "dblclick" button model - event.button == 0) && - this.isAlt(event); -}; - -this.isControlShift = function(event) -{ - return (event.metaKey || event.ctrlKey) && event.shiftKey && !event.altKey; -}; - -this.isShift = function(event) -{ - return event.shiftKey && !event.metaKey && !event.ctrlKey && !event.altKey; -}; - -this.addEvent = function(object, name, handler, useCapture) -{ - if (object.addEventListener) - object.addEventListener(name, handler, useCapture); - else - object.attachEvent("on"+name, handler); -}; - -this.removeEvent = function(object, name, handler, useCapture) -{ - try - { - if (object.removeEventListener) - object.removeEventListener(name, handler, useCapture); - else - object.detachEvent("on"+name, handler); - } - catch(e) - { - if (FBTrace.DBG_ERRORS) - FBTrace.sysout("FBL.removeEvent error: ", object, name); - } -}; - -this.cancelEvent = function(e, preventDefault) -{ - if (!e) return; - - if (preventDefault) - { - if (e.preventDefault) - e.preventDefault(); - else - e.returnValue = false; - } - - if (e.stopPropagation) - e.stopPropagation(); - else - e.cancelBubble = true; -}; - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - -this.addGlobalEvent = function(name, handler) -{ - var doc = this.Firebug.browser.document; - var frames = this.Firebug.browser.window.frames; - - this.addEvent(doc, name, handler); - - if (this.Firebug.chrome.type == "popup") - this.addEvent(this.Firebug.chrome.document, name, handler); - - for (var i = 0, frame; frame = frames[i]; i++) - { - try - { - this.addEvent(frame.document, name, handler); - } - catch(E) - { - // Avoid acess denied - } - } -}; - -this.removeGlobalEvent = function(name, handler) -{ - var doc = this.Firebug.browser.document; - var frames = this.Firebug.browser.window.frames; - - this.removeEvent(doc, name, handler); - - if (this.Firebug.chrome.type == "popup") - this.removeEvent(this.Firebug.chrome.document, name, handler); - - for (var i = 0, frame; frame = frames[i]; i++) - { - try - { - this.removeEvent(frame.document, name, handler); - } - catch(E) - { - // Avoid acess denied - } - } -}; - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - -this.dispatch = function(listeners, name, args) -{ - if (!listeners) return; - - try - {/**/ - if (typeof listeners.length != "undefined") - { - if (FBTrace.DBG_DISPATCH) FBTrace.sysout("FBL.dispatch", name+" to "+listeners.length+" listeners"); - - for (var i = 0; i < listeners.length; ++i) - { - var listener = listeners[i]; - if ( listener[name] ) - listener[name].apply(listener, args); - } - } - else - { - if (FBTrace.DBG_DISPATCH) FBTrace.sysout("FBL.dispatch", name+" to listeners of an object"); - - for (var prop in listeners) - { - var listener = listeners[prop]; - if ( listener[name] ) - listener[name].apply(listener, args); - } - } - } - catch (exc) - { - if (FBTrace.DBG_ERRORS) - { - FBTrace.sysout(" Exception in lib.dispatch "+ name, exc); - //FBTrace.dumpProperties(" Exception in lib.dispatch listener", listener); - } - } - /**/ -}; - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - -var disableTextSelectionHandler = function(event) -{ - FBL.cancelEvent(event, true); - - return false; -}; - -this.disableTextSelection = function(e) -{ - if (typeof e.onselectstart != "undefined") // IE - this.addEvent(e, "selectstart", disableTextSelectionHandler); - - else // others - { - e.style.cssText = "user-select: none; -khtml-user-select: none; -moz-user-select: none;"; - - // canceling the event in FF will prevent the menu popups to close when clicking over - // text-disabled elements - if (!this.isFirefox) - this.addEvent(e, "mousedown", disableTextSelectionHandler); - } - - e.style.cursor = "default"; -}; - -this.restoreTextSelection = function(e) -{ - if (typeof e.onselectstart != "undefined") // IE - this.removeEvent(e, "selectstart", disableTextSelectionHandler); - - else // others - { - e.style.cssText = "cursor: default;"; - - // canceling the event in FF will prevent the menu popups to close when clicking over - // text-disabled elements - if (!this.isFirefox) - this.removeEvent(e, "mousedown", disableTextSelectionHandler); - } -}; - -// ************************************************************************************************ -// DOM Events - -var eventTypes = -{ - composition: [ - "composition", - "compositionstart", - "compositionend" ], - contextmenu: [ - "contextmenu" ], - drag: [ - "dragenter", - "dragover", - "dragexit", - "dragdrop", - "draggesture" ], - focus: [ - "focus", - "blur" ], - form: [ - "submit", - "reset", - "change", - "select", - "input" ], - key: [ - "keydown", - "keyup", - "keypress" ], - load: [ - "load", - "beforeunload", - "unload", - "abort", - "error" ], - mouse: [ - "mousedown", - "mouseup", - "click", - "dblclick", - "mouseover", - "mouseout", - "mousemove" ], - mutation: [ - "DOMSubtreeModified", - "DOMNodeInserted", - "DOMNodeRemoved", - "DOMNodeRemovedFromDocument", - "DOMNodeInsertedIntoDocument", - "DOMAttrModified", - "DOMCharacterDataModified" ], - paint: [ - "paint", - "resize", - "scroll" ], - scroll: [ - "overflow", - "underflow", - "overflowchanged" ], - text: [ - "text" ], - ui: [ - "DOMActivate", - "DOMFocusIn", - "DOMFocusOut" ], - xul: [ - "popupshowing", - "popupshown", - "popuphiding", - "popuphidden", - "close", - "command", - "broadcast", - "commandupdate" ] -}; - -this.getEventFamily = function(eventType) -{ - if (!this.families) - { - this.families = {}; - - for (var family in eventTypes) - { - var types = eventTypes[family]; - for (var i = 0; i < types.length; ++i) - this.families[types[i]] = family; - } - } - - return this.families[eventType]; -}; - - -// ************************************************************************************************ -// URLs - -this.getFileName = function(url) -{ - var split = this.splitURLBase(url); - return split.name; -}; - -this.splitURLBase = function(url) -{ - if (this.isDataURL(url)) - return this.splitDataURL(url); - return this.splitURLTrue(url); -}; - -this.splitDataURL = function(url) -{ - var mark = url.indexOf(':', 3); - if (mark != 4) - return false; // the first 5 chars must be 'data:' - - var point = url.indexOf(',', mark+1); - if (point < mark) - return false; // syntax error - - var props = { encodedContent: url.substr(point+1) }; - - var metadataBuffer = url.substr(mark+1, point); - var metadata = metadataBuffer.split(';'); - for (var i = 0; i < metadata.length; i++) - { - var nv = metadata[i].split('='); - if (nv.length == 2) - props[nv[0]] = nv[1]; - } - - // Additional Firebug-specific properties - if (props.hasOwnProperty('fileName')) - { - var caller_URL = decodeURIComponent(props['fileName']); - var caller_split = this.splitURLTrue(caller_URL); - - if (props.hasOwnProperty('baseLineNumber')) // this means it's probably an eval() - { - props['path'] = caller_split.path; - props['line'] = props['baseLineNumber']; - var hint = decodeURIComponent(props['encodedContent'].substr(0,200)).replace(/\s*$/, ""); - props['name'] = 'eval->'+hint; - } - else - { - props['name'] = caller_split.name; - props['path'] = caller_split.path; - } - } - else - { - if (!props.hasOwnProperty('path')) - props['path'] = "data:"; - if (!props.hasOwnProperty('name')) - props['name'] = decodeURIComponent(props['encodedContent'].substr(0,200)).replace(/\s*$/, ""); - } - - return props; -}; - -this.splitURLTrue = function(url) -{ - var m = reSplitFile.exec(url); - if (!m) - return {name: url, path: url}; - else if (!m[2]) - return {path: m[1], name: m[1]}; - else - return {path: m[1], name: m[2]+m[3]}; -}; - -this.getFileExtension = function(url) -{ - if (!url) - return null; - - // Remove query string from the URL if any. - var queryString = url.indexOf("?"); - if (queryString != -1) - url = url.substr(0, queryString); - - // Now get the file extension. - var lastDot = url.lastIndexOf("."); - return url.substr(lastDot+1); -}; - -this.isSystemURL = function(url) -{ - if (!url) return true; - if (url.length == 0) return true; - if (url[0] == 'h') return false; - if (url.substr(0, 9) == "resource:") - return true; - else if (url.substr(0, 16) == "chrome://firebug") - return true; - else if (url == "XPCSafeJSObjectWrapper.cpp") - return true; - else if (url.substr(0, 6) == "about:") - return true; - else if (url.indexOf("firebug-service.js") != -1) - return true; - else - return false; -}; - -this.isSystemPage = function(win) -{ - try - { - var doc = win.document; - if (!doc) - return false; - - // Detect pages for pretty printed XML - if ((doc.styleSheets.length && doc.styleSheets[0].href - == "chrome://global/content/xml/XMLPrettyPrint.css") - || (doc.styleSheets.length > 1 && doc.styleSheets[1].href - == "chrome://browser/skin/feeds/subscribe.css")) - return true; - - return FBL.isSystemURL(win.location.href); - } - catch (exc) - { - // Sometimes documents just aren't ready to be manipulated here, but don't let that - // gum up the works - ERROR("tabWatcher.isSystemPage document not ready:"+ exc); - return false; - } -}; - -this.isSystemStyleSheet = function(sheet) -{ - var href = sheet && sheet.href; - return href && FBL.isSystemURL(href); -}; - -this.getURIHost = function(uri) -{ - try - { - if (uri) - return uri.host; - else - return ""; - } - catch (exc) - { - return ""; - } -}; - -this.isLocalURL = function(url) -{ - if (url.substr(0, 5) == "file:") - return true; - else if (url.substr(0, 8) == "wyciwyg:") - return true; - else - return false; -}; - -this.isDataURL = function(url) -{ - return (url && url.substr(0,5) == "data:"); -}; - -this.getLocalPath = function(url) -{ - if (this.isLocalURL(url)) - { - var fileHandler = ioService.getProtocolHandler("file").QueryInterface(Ci.nsIFileProtocolHandler); - var file = fileHandler.getFileFromURLSpec(url); - return file.path; - } -}; - -this.getURLFromLocalFile = function(file) -{ - var fileHandler = ioService.getProtocolHandler("file").QueryInterface(Ci.nsIFileProtocolHandler); - var URL = fileHandler.getURLSpecFromFile(file); - return URL; -}; - -this.getDataURLForContent = function(content, url) -{ - // data:text/javascript;fileName=x%2Cy.js;baseLineNumber=10,<the-url-encoded-data> - var uri = "data:text/html;"; - uri += "fileName="+encodeURIComponent(url)+ ","; - uri += encodeURIComponent(content); - return uri; -}, - -this.getDomain = function(url) -{ - var m = /[^:]+:\/{1,3}([^\/]+)/.exec(url); - return m ? m[1] : ""; -}; - -this.getURLPath = function(url) -{ - var m = /[^:]+:\/{1,3}[^\/]+(\/.*?)$/.exec(url); - return m ? m[1] : ""; -}; - -this.getPrettyDomain = function(url) -{ - var m = /[^:]+:\/{1,3}(www\.)?([^\/]+)/.exec(url); - return m ? m[2] : ""; -}; - -this.absoluteURL = function(url, baseURL) -{ - return this.absoluteURLWithDots(url, baseURL).replace("/./", "/", "g"); -}; - -this.absoluteURLWithDots = function(url, baseURL) -{ - if (url[0] == "?") - return baseURL + url; - - var reURL = /(([^:]+:)\/{1,2}[^\/]*)(.*?)$/; - var m = reURL.exec(url); - if (m) - return url; - - var m = reURL.exec(baseURL); - if (!m) - return ""; - - var head = m[1]; - var tail = m[3]; - if (url.substr(0, 2) == "//") - return m[2] + url; - else if (url[0] == "/") - { - return head + url; - } - else if (tail[tail.length-1] == "/") - return baseURL + url; - else - { - var parts = tail.split("/"); - return head + parts.slice(0, parts.length-1).join("/") + "/" + url; - } -}; - -this.normalizeURL = function(url) // this gets called a lot, any performance improvement welcome -{ - if (!url) - return ""; - // Replace one or more characters that are not forward-slash followed by /.., by space. - if (url.length < 255) // guard against monsters. - { - // Replace one or more characters that are not forward-slash followed by /.., by space. - url = url.replace(/[^\/]+\/\.\.\//, "", "g"); - // Issue 1496, avoid # - url = url.replace(/#.*/,""); - // For some reason, JSDS reports file URLs like "file:/" instead of "file:///", so they - // don't match up with the URLs we get back from the DOM - url = url.replace(/file:\/([^\/])/g, "file:///$1"); - if (url.indexOf('chrome:')==0) - { - var m = reChromeCase.exec(url); // 1 is package name, 2 is path - if (m) - { - url = "chrome://"+m[1].toLowerCase()+"/"+m[2]; - } - } - } - return url; -}; - -this.denormalizeURL = function(url) -{ - return url.replace(/file:\/\/\//g, "file:/"); -}; - -this.parseURLParams = function(url) -{ - var q = url ? url.indexOf("?") : -1; - if (q == -1) - return []; - - var search = url.substr(q+1); - var h = search.lastIndexOf("#"); - if (h != -1) - search = search.substr(0, h); - - if (!search) - return []; - - return this.parseURLEncodedText(search); -}; - -this.parseURLEncodedText = function(text) -{ - var maxValueLength = 25000; - - var params = []; - - // Unescape '+' characters that are used to encode a space. - // See section 2.2.in RFC 3986: http://www.ietf.org/rfc/rfc3986.txt - text = text.replace(/\+/g, " "); - - var args = text.split("&"); - for (var i = 0; i < args.length; ++i) - { - try { - var parts = args[i].split("="); - if (parts.length == 2) - { - if (parts[1].length > maxValueLength) - parts[1] = this.$STR("LargeData"); - - params.push({name: decodeURIComponent(parts[0]), value: decodeURIComponent(parts[1])}); - } - else - params.push({name: decodeURIComponent(parts[0]), value: ""}); - } - catch (e) - { - if (FBTrace.DBG_ERRORS) - { - FBTrace.sysout("parseURLEncodedText EXCEPTION ", e); - FBTrace.sysout("parseURLEncodedText EXCEPTION URI", args[i]); - } - } - } - - params.sort(function(a, b) { return a.name <= b.name ? -1 : 1; }); - - return params; -}; - -// TODO: xxxpedro lib. why loops in domplate are requiring array in parameters -// as in response/request headers and get/post parameters in Net module? -this.parseURLParamsArray = function(url) -{ - var q = url ? url.indexOf("?") : -1; - if (q == -1) - return []; - - var search = url.substr(q+1); - var h = search.lastIndexOf("#"); - if (h != -1) - search = search.substr(0, h); - - if (!search) - return []; - - return this.parseURLEncodedTextArray(search); -}; - -this.parseURLEncodedTextArray = function(text) -{ - var maxValueLength = 25000; - - var params = []; - - // Unescape '+' characters that are used to encode a space. - // See section 2.2.in RFC 3986: http://www.ietf.org/rfc/rfc3986.txt - text = text.replace(/\+/g, " "); - - var args = text.split("&"); - for (var i = 0; i < args.length; ++i) - { - try { - var parts = args[i].split("="); - if (parts.length == 2) - { - if (parts[1].length > maxValueLength) - parts[1] = this.$STR("LargeData"); - - params.push({name: decodeURIComponent(parts[0]), value: [decodeURIComponent(parts[1])]}); - } - else - params.push({name: decodeURIComponent(parts[0]), value: [""]}); - } - catch (e) - { - if (FBTrace.DBG_ERRORS) - { - FBTrace.sysout("parseURLEncodedText EXCEPTION ", e); - FBTrace.sysout("parseURLEncodedText EXCEPTION URI", args[i]); - } - } - } - - params.sort(function(a, b) { return a.name <= b.name ? -1 : 1; }); - - return params; -}; - -this.reEncodeURL = function(file, text) -{ - var lines = text.split("\n"); - var params = this.parseURLEncodedText(lines[lines.length-1]); - - var args = []; - for (var i = 0; i < params.length; ++i) - args.push(encodeURIComponent(params[i].name)+"="+encodeURIComponent(params[i].value)); - - var url = file.href; - url += (url.indexOf("?") == -1 ? "?" : "&") + args.join("&"); - - return url; -}; - -this.getResource = function(aURL) -{ - try - { - var channel=ioService.newChannel(aURL,null,null); - var input=channel.open(); - return FBL.readFromStream(input); - } - catch (e) - { - if (FBTrace.DBG_ERRORS) - FBTrace.sysout("lib.getResource FAILS for "+aURL, e); - } -}; - -this.parseJSONString = function(jsonString, originURL) -{ - // See if this is a Prototype style *-secure request. - var regex = new RegExp(/^\/\*-secure-([\s\S]*)\*\/\s*$/); - var matches = regex.exec(jsonString); - - if (matches) - { - jsonString = matches[1]; - - if (jsonString[0] == "\\" && jsonString[1] == "n") - jsonString = jsonString.substr(2); - - if (jsonString[jsonString.length-2] == "\\" && jsonString[jsonString.length-1] == "n") - jsonString = jsonString.substr(0, jsonString.length-2); - } - - if (jsonString.indexOf("&&&START&&&")) - { - regex = new RegExp(/&&&START&&& (.+) &&&END&&&/); - matches = regex.exec(jsonString); - if (matches) - jsonString = matches[1]; - } - - // throw on the extra parentheses - jsonString = "(" + jsonString + ")"; - - ///var s = Components.utils.Sandbox(originURL); - var jsonObject = null; - - try - { - ///jsonObject = Components.utils.evalInSandbox(jsonString, s); - - //jsonObject = Firebug.context.eval(jsonString); - jsonObject = Firebug.context.evaluate(jsonString, null, null, function(){return null;}); - } - catch(e) - { - /*** - if (e.message.indexOf("is not defined")) - { - var parts = e.message.split(" "); - s[parts[0]] = function(str){ return str; }; - try { - jsonObject = Components.utils.evalInSandbox(jsonString, s); - } catch(ex) { - if (FBTrace.DBG_ERRORS || FBTrace.DBG_JSONVIEWER) - FBTrace.sysout("jsonviewer.parseJSON EXCEPTION", e); - return null; - } - } - else - {/**/ - if (FBTrace.DBG_ERRORS || FBTrace.DBG_JSONVIEWER) - FBTrace.sysout("jsonviewer.parseJSON EXCEPTION", e); - return null; - ///} - } - - return jsonObject; -}; - -// ************************************************************************************************ - -this.objectToString = function(object) -{ - try - { - return object+""; - } - catch (exc) - { - return null; - } -}; - -// ************************************************************************************************ -// Input Caret Position - -this.setSelectionRange = function(input, start, length) -{ - if (input.createTextRange) - { - var range = input.createTextRange(); - range.moveStart("character", start); - range.moveEnd("character", length - input.value.length); - range.select(); - } - else if (input.setSelectionRange) - { - input.setSelectionRange(start, length); - input.focus(); - } -}; - -// ************************************************************************************************ -// Input Selection Start / Caret Position - -this.getInputSelectionStart = function(input) -{ - if (document.selection) - { - var range = input.ownerDocument.selection.createRange(); - var text = range.text; - - //console.log("range", range.text); - - // if there is a selection, find the start position - if (text) - { - return input.value.indexOf(text); - } - // if there is no selection, find the caret position - else - { - range.moveStart("character", -input.value.length); - - return range.text.length; - } - } - else if (typeof input.selectionStart != "undefined") - return input.selectionStart; - - return 0; -}; - -// ************************************************************************************************ -// Opera Tab Fix - -function onOperaTabBlur(e) -{ - if (this.lastKey == 9) - this.focus(); -}; - -function onOperaTabKeyDown(e) -{ - this.lastKey = e.keyCode; -}; - -function onOperaTabFocus(e) -{ - this.lastKey = null; -}; - -this.fixOperaTabKey = function(el) -{ - el.onfocus = onOperaTabFocus; - el.onblur = onOperaTabBlur; - el.onkeydown = onOperaTabKeyDown; -}; - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - -this.Property = function(object, name) -{ - this.object = object; - this.name = name; - - this.getObject = function() - { - return object[name]; - }; -}; - -this.ErrorCopy = function(message) -{ - this.message = message; -}; - -function EventCopy(event) -{ - // Because event objects are destroyed arbitrarily by Gecko, we must make a copy of them to - // represent them long term in the inspector. - for (var name in event) - { - try { - this[name] = event[name]; - } catch (exc) { } - } -} - -this.EventCopy = EventCopy; - - -// ************************************************************************************************ -// Type Checking - -var toString = Object.prototype.toString; -var reFunction = /^\s*function(\s+[\w_$][\w\d_$]*)?\s*\(/; - -this.isArray = function(object) { - return toString.call(object) === '[object Array]'; -}; - -this.isFunction = function(object) { - if (!object) return false; - - try - { - // FIXME: xxxpedro this is failing in IE for the global "external" object - return toString.call(object) === "[object Function]" || - this.isIE && typeof object != "string" && reFunction.test(""+object); - } - catch (E) - { - FBTrace.sysout("Lib.isFunction() failed for ", object); - return false; - } -}; - - -// ************************************************************************************************ -// Instance Checking - -this.instanceOf = function(object, className) -{ - if (!object || typeof object != "object") - return false; - - // Try to use the native instanceof operator. We can only use it when we know - // exactly the window where the object is located at - if (object.ownerDocument) - { - // find the correct window of the object - var win = object.ownerDocument.defaultView || object.ownerDocument.parentWindow; - - // if the class is accessible in the window, uses the native instanceof operator - // if the instanceof evaluates to "true" we can assume it is a instance, but if it - // evaluates to "false" we must continue with the duck type detection below because - // the native object may be extended, thus breaking the instanceof result - // See Issue 3524: Firebug Lite Style Panel doesn't work if the native Element is extended - if (className in win && object instanceof win[className]) - return true; - } - // If the object doesn't have the ownerDocument property, we'll try to look at - // the current context's window - else - { - // TODO: xxxpedro context - // Since we're not using yet a Firebug.context, we'll just use the top window - // (browser) as a reference - var win = Firebug.browser.window; - if (className in win) - return object instanceof win[className]; - } - - // get the duck type model from the cache - var cache = instanceCheckMap[className]; - if (!cache) - return false; - - // starts the hacky duck type detection - for(var n in cache) - { - var obj = cache[n]; - var type = typeof obj; - obj = type == "object" ? obj : [obj]; - - for(var name in obj) - { - // avoid problems with extended native objects - // See Issue 3524: Firebug Lite Style Panel doesn't work if the native Element is extended - if (!obj.hasOwnProperty(name)) - continue; - - var value = obj[name]; - - if( n == "property" && !(value in object) || - n == "method" && !this.isFunction(object[value]) || - n == "value" && (""+object[name]).toLowerCase() != (""+value).toLowerCase() ) - return false; - } - } - - return true; -}; - -var instanceCheckMap = -{ - // DuckTypeCheck: - // { - // property: ["window", "document"], - // method: "setTimeout", - // value: {nodeType: 1} - // }, - - Window: - { - property: ["window", "document"], - method: "setTimeout" - }, - - Document: - { - property: ["body", "cookie"], - method: "getElementById" - }, - - Node: - { - property: "ownerDocument", - method: "appendChild" - }, - - Element: - { - property: "tagName", - value: {nodeType: 1} - }, - - Location: - { - property: ["hostname", "protocol"], - method: "assign" - }, - - HTMLImageElement: - { - property: "useMap", - value: - { - nodeType: 1, - tagName: "img" - } - }, - - HTMLAnchorElement: - { - property: "hreflang", - value: - { - nodeType: 1, - tagName: "a" - } - }, - - HTMLInputElement: - { - property: "form", - value: - { - nodeType: 1, - tagName: "input" - } - }, - - HTMLButtonElement: - { - // ? - }, - - HTMLFormElement: - { - method: "submit", - value: - { - nodeType: 1, - tagName: "form" - } - }, - - HTMLBodyElement: - { - - }, - - HTMLHtmlElement: - { - - }, - - CSSStyleRule: - { - property: ["selectorText", "style"] - } - -}; - - -// ************************************************************************************************ -// DOM Constants - -/* - -Problems: - - - IE does not have window.Node, window.Element, etc - - for (var name in Node.prototype) return nothing on FF - -*/ - - -var domMemberMap2 = {}; - -var domMemberMap2Sandbox = null; - -var getDomMemberMap2 = function(name) -{ - if (!domMemberMap2Sandbox) - { - var doc = Firebug.chrome.document; - var frame = doc.createElement("iframe"); - - frame.id = "FirebugSandbox"; - frame.style.display = "none"; - frame.src = "about:blank"; - - doc.body.appendChild(frame); - - domMemberMap2Sandbox = frame.window || frame.contentWindow; - } - - var props = []; - - //var object = domMemberMap2Sandbox[name]; - //object = object.prototype || object; - - var object = null; - - if (name == "Window") - object = domMemberMap2Sandbox.window; - - else if (name == "Document") - object = domMemberMap2Sandbox.document; - - else if (name == "HTMLScriptElement") - object = domMemberMap2Sandbox.document.createElement("script"); - - else if (name == "HTMLAnchorElement") - object = domMemberMap2Sandbox.document.createElement("a"); - - else if (name.indexOf("Element") != -1) - { - object = domMemberMap2Sandbox.document.createElement("div"); - } - - if (object) - { - //object = object.prototype || object; - - //props = 'addEventListener,document,location,navigator,window'.split(','); - - for (var n in object) - props.push(n); - } - /**/ - - return props; - return extendArray(props, domMemberMap[name]); -}; - -// xxxpedro experimental get DOM members -this.getDOMMembers = function(object) -{ - if (!domMemberCache) - { - FBL.domMemberCache = domMemberCache = {}; - - for (var name in domMemberMap) - { - var builtins = getDomMemberMap2(name); - var cache = domMemberCache[name] = {}; - - /* - if (name.indexOf("Element") != -1) - { - this.append(cache, this.getDOMMembers("Node")); - this.append(cache, this.getDOMMembers("Element")); - } - /**/ - - for (var i = 0; i < builtins.length; ++i) - cache[builtins[i]] = i; - } - } - - try - { - if (this.instanceOf(object, "Window")) - { return domMemberCache.Window; } - else if (this.instanceOf(object, "Document") || this.instanceOf(object, "XMLDocument")) - { return domMemberCache.Document; } - else if (this.instanceOf(object, "Location")) - { return domMemberCache.Location; } - else if (this.instanceOf(object, "HTMLImageElement")) - { return domMemberCache.HTMLImageElement; } - else if (this.instanceOf(object, "HTMLAnchorElement")) - { return domMemberCache.HTMLAnchorElement; } - else if (this.instanceOf(object, "HTMLInputElement")) - { return domMemberCache.HTMLInputElement; } - else if (this.instanceOf(object, "HTMLButtonElement")) - { return domMemberCache.HTMLButtonElement; } - else if (this.instanceOf(object, "HTMLFormElement")) - { return domMemberCache.HTMLFormElement; } - else if (this.instanceOf(object, "HTMLBodyElement")) - { return domMemberCache.HTMLBodyElement; } - else if (this.instanceOf(object, "HTMLHtmlElement")) - { return domMemberCache.HTMLHtmlElement; } - else if (this.instanceOf(object, "HTMLScriptElement")) - { return domMemberCache.HTMLScriptElement; } - else if (this.instanceOf(object, "HTMLTableElement")) - { return domMemberCache.HTMLTableElement; } - else if (this.instanceOf(object, "HTMLTableRowElement")) - { return domMemberCache.HTMLTableRowElement; } - else if (this.instanceOf(object, "HTMLTableCellElement")) - { return domMemberCache.HTMLTableCellElement; } - else if (this.instanceOf(object, "HTMLIFrameElement")) - { return domMemberCache.HTMLIFrameElement; } - else if (this.instanceOf(object, "SVGSVGElement")) - { return domMemberCache.SVGSVGElement; } - else if (this.instanceOf(object, "SVGElement")) - { return domMemberCache.SVGElement; } - else if (this.instanceOf(object, "Element")) - { return domMemberCache.Element; } - else if (this.instanceOf(object, "Text") || this.instanceOf(object, "CDATASection")) - { return domMemberCache.Text; } - else if (this.instanceOf(object, "Attr")) - { return domMemberCache.Attr; } - else if (this.instanceOf(object, "Node")) - { return domMemberCache.Node; } - else if (this.instanceOf(object, "Event") || this.instanceOf(object, "EventCopy")) - { return domMemberCache.Event; } - else - return {}; - } - catch(E) - { - if (FBTrace.DBG_ERRORS) - FBTrace.sysout("lib.getDOMMembers FAILED ", E); - - return {}; - } -}; - - -/* -this.getDOMMembers = function(object) -{ - if (!domMemberCache) - { - domMemberCache = {}; - - for (var name in domMemberMap) - { - var builtins = domMemberMap[name]; - var cache = domMemberCache[name] = {}; - - for (var i = 0; i < builtins.length; ++i) - cache[builtins[i]] = i; - } - } - - try - { - if (this.instanceOf(object, "Window")) - { return domMemberCache.Window; } - else if (object instanceof Document || object instanceof XMLDocument) - { return domMemberCache.Document; } - else if (object instanceof Location) - { return domMemberCache.Location; } - else if (object instanceof HTMLImageElement) - { return domMemberCache.HTMLImageElement; } - else if (object instanceof HTMLAnchorElement) - { return domMemberCache.HTMLAnchorElement; } - else if (object instanceof HTMLInputElement) - { return domMemberCache.HTMLInputElement; } - else if (object instanceof HTMLButtonElement) - { return domMemberCache.HTMLButtonElement; } - else if (object instanceof HTMLFormElement) - { return domMemberCache.HTMLFormElement; } - else if (object instanceof HTMLBodyElement) - { return domMemberCache.HTMLBodyElement; } - else if (object instanceof HTMLHtmlElement) - { return domMemberCache.HTMLHtmlElement; } - else if (object instanceof HTMLScriptElement) - { return domMemberCache.HTMLScriptElement; } - else if (object instanceof HTMLTableElement) - { return domMemberCache.HTMLTableElement; } - else if (object instanceof HTMLTableRowElement) - { return domMemberCache.HTMLTableRowElement; } - else if (object instanceof HTMLTableCellElement) - { return domMemberCache.HTMLTableCellElement; } - else if (object instanceof HTMLIFrameElement) - { return domMemberCache.HTMLIFrameElement; } - else if (object instanceof SVGSVGElement) - { return domMemberCache.SVGSVGElement; } - else if (object instanceof SVGElement) - { return domMemberCache.SVGElement; } - else if (object instanceof Element) - { return domMemberCache.Element; } - else if (object instanceof Text || object instanceof CDATASection) - { return domMemberCache.Text; } - else if (object instanceof Attr) - { return domMemberCache.Attr; } - else if (object instanceof Node) - { return domMemberCache.Node; } - else if (object instanceof Event || object instanceof EventCopy) - { return domMemberCache.Event; } - else - return {}; - } - catch(E) - { - return {}; - } -}; -/**/ - -this.isDOMMember = function(object, propName) -{ - var members = this.getDOMMembers(object); - return members && propName in members; -}; - -var domMemberCache = null; -var domMemberMap = {}; - -domMemberMap.Window = -[ - "document", - "frameElement", - - "innerWidth", - "innerHeight", - "outerWidth", - "outerHeight", - "screenX", - "screenY", - "pageXOffset", - "pageYOffset", - "scrollX", - "scrollY", - "scrollMaxX", - "scrollMaxY", - - "status", - "defaultStatus", - - "parent", - "opener", - "top", - "window", - "content", - "self", - - "location", - "history", - "frames", - "navigator", - "screen", - "menubar", - "toolbar", - "locationbar", - "personalbar", - "statusbar", - "directories", - "scrollbars", - "fullScreen", - "netscape", - "java", - "console", - "Components", - "controllers", - "closed", - "crypto", - "pkcs11", - - "name", - "property", - "length", - - "sessionStorage", - "globalStorage", - - "setTimeout", - "setInterval", - "clearTimeout", - "clearInterval", - "addEventListener", - "removeEventListener", - "dispatchEvent", - "getComputedStyle", - "captureEvents", - "releaseEvents", - "routeEvent", - "enableExternalCapture", - "disableExternalCapture", - "moveTo", - "moveBy", - "resizeTo", - "resizeBy", - "scroll", - "scrollTo", - "scrollBy", - "scrollByLines", - "scrollByPages", - "sizeToContent", - "setResizable", - "getSelection", - "open", - "openDialog", - "close", - "alert", - "confirm", - "prompt", - "dump", - "focus", - "blur", - "find", - "back", - "forward", - "home", - "stop", - "print", - "atob", - "btoa", - "updateCommands", - "XPCNativeWrapper", - "GeckoActiveXObject", - "applicationCache" // FF3 -]; - -domMemberMap.Location = -[ - "href", - "protocol", - "host", - "hostname", - "port", - "pathname", - "search", - "hash", - - "assign", - "reload", - "replace" -]; - -domMemberMap.Node = -[ - "id", - "className", - - "nodeType", - "tagName", - "nodeName", - "localName", - "prefix", - "namespaceURI", - "nodeValue", - - "ownerDocument", - "parentNode", - "offsetParent", - "nextSibling", - "previousSibling", - "firstChild", - "lastChild", - "childNodes", - "attributes", - - "dir", - "baseURI", - "textContent", - "innerHTML", - - "addEventListener", - "removeEventListener", - "dispatchEvent", - "cloneNode", - "appendChild", - "insertBefore", - "replaceChild", - "removeChild", - "compareDocumentPosition", - "hasAttributes", - "hasChildNodes", - "lookupNamespaceURI", - "lookupPrefix", - "normalize", - "isDefaultNamespace", - "isEqualNode", - "isSameNode", - "isSupported", - "getFeature", - "getUserData", - "setUserData" -]; - -domMemberMap.Document = extendArray(domMemberMap.Node, -[ - "documentElement", - "body", - "title", - "location", - "referrer", - "cookie", - "contentType", - "lastModified", - "characterSet", - "inputEncoding", - "xmlEncoding", - "xmlStandalone", - "xmlVersion", - "strictErrorChecking", - "documentURI", - "URL", - - "defaultView", - "doctype", - "implementation", - "styleSheets", - "images", - "links", - "forms", - "anchors", - "embeds", - "plugins", - "applets", - - "width", - "height", - - "designMode", - "compatMode", - "async", - "preferredStylesheetSet", - - "alinkColor", - "linkColor", - "vlinkColor", - "bgColor", - "fgColor", - "domain", - - "addEventListener", - "removeEventListener", - "dispatchEvent", - "captureEvents", - "releaseEvents", - "routeEvent", - "clear", - "open", - "close", - "execCommand", - "execCommandShowHelp", - "getElementsByName", - "getSelection", - "queryCommandEnabled", - "queryCommandIndeterm", - "queryCommandState", - "queryCommandSupported", - "queryCommandText", - "queryCommandValue", - "write", - "writeln", - "adoptNode", - "appendChild", - "removeChild", - "renameNode", - "cloneNode", - "compareDocumentPosition", - "createAttribute", - "createAttributeNS", - "createCDATASection", - "createComment", - "createDocumentFragment", - "createElement", - "createElementNS", - "createEntityReference", - "createEvent", - "createExpression", - "createNSResolver", - "createNodeIterator", - "createProcessingInstruction", - "createRange", - "createTextNode", - "createTreeWalker", - "domConfig", - "evaluate", - "evaluateFIXptr", - "evaluateXPointer", - "getAnonymousElementByAttribute", - "getAnonymousNodes", - "addBinding", - "removeBinding", - "getBindingParent", - "getBoxObjectFor", - "setBoxObjectFor", - "getElementById", - "getElementsByTagName", - "getElementsByTagNameNS", - "hasAttributes", - "hasChildNodes", - "importNode", - "insertBefore", - "isDefaultNamespace", - "isEqualNode", - "isSameNode", - "isSupported", - "load", - "loadBindingDocument", - "lookupNamespaceURI", - "lookupPrefix", - "normalize", - "normalizeDocument", - "getFeature", - "getUserData", - "setUserData" -]); - -domMemberMap.Element = extendArray(domMemberMap.Node, -[ - "clientWidth", - "clientHeight", - "offsetLeft", - "offsetTop", - "offsetWidth", - "offsetHeight", - "scrollLeft", - "scrollTop", - "scrollWidth", - "scrollHeight", - - "style", - - "tabIndex", - "title", - "lang", - "align", - "spellcheck", - - "addEventListener", - "removeEventListener", - "dispatchEvent", - "focus", - "blur", - "cloneNode", - "appendChild", - "insertBefore", - "replaceChild", - "removeChild", - "compareDocumentPosition", - "getElementsByTagName", - "getElementsByTagNameNS", - "getAttribute", - "getAttributeNS", - "getAttributeNode", - "getAttributeNodeNS", - "setAttribute", - "setAttributeNS", - "setAttributeNode", - "setAttributeNodeNS", - "removeAttribute", - "removeAttributeNS", - "removeAttributeNode", - "hasAttribute", - "hasAttributeNS", - "hasAttributes", - "hasChildNodes", - "lookupNamespaceURI", - "lookupPrefix", - "normalize", - "isDefaultNamespace", - "isEqualNode", - "isSameNode", - "isSupported", - "getFeature", - "getUserData", - "setUserData" -]); - -domMemberMap.SVGElement = extendArray(domMemberMap.Element, -[ - "x", - "y", - "width", - "height", - "rx", - "ry", - "transform", - "href", - - "ownerSVGElement", - "viewportElement", - "farthestViewportElement", - "nearestViewportElement", - - "getBBox", - "getCTM", - "getScreenCTM", - "getTransformToElement", - "getPresentationAttribute", - "preserveAspectRatio" -]); - -domMemberMap.SVGSVGElement = extendArray(domMemberMap.Element, -[ - "x", - "y", - "width", - "height", - "rx", - "ry", - "transform", - - "viewBox", - "viewport", - "currentView", - "useCurrentView", - "pixelUnitToMillimeterX", - "pixelUnitToMillimeterY", - "screenPixelToMillimeterX", - "screenPixelToMillimeterY", - "currentScale", - "currentTranslate", - "zoomAndPan", - - "ownerSVGElement", - "viewportElement", - "farthestViewportElement", - "nearestViewportElement", - "contentScriptType", - "contentStyleType", - - "getBBox", - "getCTM", - "getScreenCTM", - "getTransformToElement", - "getEnclosureList", - "getIntersectionList", - "getViewboxToViewportTransform", - "getPresentationAttribute", - "getElementById", - "checkEnclosure", - "checkIntersection", - "createSVGAngle", - "createSVGLength", - "createSVGMatrix", - "createSVGNumber", - "createSVGPoint", - "createSVGRect", - "createSVGString", - "createSVGTransform", - "createSVGTransformFromMatrix", - "deSelectAll", - "preserveAspectRatio", - "forceRedraw", - "suspendRedraw", - "unsuspendRedraw", - "unsuspendRedrawAll", - "getCurrentTime", - "setCurrentTime", - "animationsPaused", - "pauseAnimations", - "unpauseAnimations" -]); - -domMemberMap.HTMLImageElement = extendArray(domMemberMap.Element, -[ - "src", - "naturalWidth", - "naturalHeight", - "width", - "height", - "x", - "y", - "name", - "alt", - "longDesc", - "lowsrc", - "border", - "complete", - "hspace", - "vspace", - "isMap", - "useMap" -]); - -domMemberMap.HTMLAnchorElement = extendArray(domMemberMap.Element, -[ - "name", - "target", - "accessKey", - "href", - "protocol", - "host", - "hostname", - "port", - "pathname", - "search", - "hash", - "hreflang", - "coords", - "shape", - "text", - "type", - "rel", - "rev", - "charset" -]); - -domMemberMap.HTMLIFrameElement = extendArray(domMemberMap.Element, -[ - "contentDocument", - "contentWindow", - "frameBorder", - "height", - "longDesc", - "marginHeight", - "marginWidth", - "name", - "scrolling", - "src", - "width" -]); - -domMemberMap.HTMLTableElement = extendArray(domMemberMap.Element, -[ - "bgColor", - "border", - "caption", - "cellPadding", - "cellSpacing", - "frame", - "rows", - "rules", - "summary", - "tBodies", - "tFoot", - "tHead", - "width", - - "createCaption", - "createTFoot", - "createTHead", - "deleteCaption", - "deleteRow", - "deleteTFoot", - "deleteTHead", - "insertRow" -]); - -domMemberMap.HTMLTableRowElement = extendArray(domMemberMap.Element, -[ - "bgColor", - "cells", - "ch", - "chOff", - "rowIndex", - "sectionRowIndex", - "vAlign", - - "deleteCell", - "insertCell" -]); - -domMemberMap.HTMLTableCellElement = extendArray(domMemberMap.Element, -[ - "abbr", - "axis", - "bgColor", - "cellIndex", - "ch", - "chOff", - "colSpan", - "headers", - "height", - "noWrap", - "rowSpan", - "scope", - "vAlign", - "width" - -]); - -domMemberMap.HTMLScriptElement = extendArray(domMemberMap.Element, -[ - "src" -]); - -domMemberMap.HTMLButtonElement = extendArray(domMemberMap.Element, -[ - "accessKey", - "disabled", - "form", - "name", - "type", - "value", - - "click" -]); - -domMemberMap.HTMLInputElement = extendArray(domMemberMap.Element, -[ - "type", - "value", - "checked", - "accept", - "accessKey", - "alt", - "controllers", - "defaultChecked", - "defaultValue", - "disabled", - "form", - "maxLength", - "name", - "readOnly", - "selectionEnd", - "selectionStart", - "size", - "src", - "textLength", - "useMap", - - "click", - "select", - "setSelectionRange" -]); - -domMemberMap.HTMLFormElement = extendArray(domMemberMap.Element, -[ - "acceptCharset", - "action", - "author", - "elements", - "encoding", - "enctype", - "entry_id", - "length", - "method", - "name", - "post", - "target", - "text", - "url", - - "reset", - "submit" -]); - -domMemberMap.HTMLBodyElement = extendArray(domMemberMap.Element, -[ - "aLink", - "background", - "bgColor", - "link", - "text", - "vLink" -]); - -domMemberMap.HTMLHtmlElement = extendArray(domMemberMap.Element, -[ - "version" -]); - -domMemberMap.Text = extendArray(domMemberMap.Node, -[ - "data", - "length", - - "appendData", - "deleteData", - "insertData", - "replaceData", - "splitText", - "substringData" -]); - -domMemberMap.Attr = extendArray(domMemberMap.Node, -[ - "name", - "value", - "specified", - "ownerElement" -]); - -domMemberMap.Event = -[ - "type", - "target", - "currentTarget", - "originalTarget", - "explicitOriginalTarget", - "relatedTarget", - "rangeParent", - "rangeOffset", - "view", - - "keyCode", - "charCode", - "screenX", - "screenY", - "clientX", - "clientY", - "layerX", - "layerY", - "pageX", - "pageY", - - "detail", - "button", - "which", - "ctrlKey", - "shiftKey", - "altKey", - "metaKey", - - "eventPhase", - "timeStamp", - "bubbles", - "cancelable", - "cancelBubble", - - "isTrusted", - "isChar", - - "getPreventDefault", - "initEvent", - "initMouseEvent", - "initKeyEvent", - "initUIEvent", - "preventBubble", - "preventCapture", - "preventDefault", - "stopPropagation" -]; - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - -this.domConstantMap = -{ - "ELEMENT_NODE": 1, - "ATTRIBUTE_NODE": 1, - "TEXT_NODE": 1, - "CDATA_SECTION_NODE": 1, - "ENTITY_REFERENCE_NODE": 1, - "ENTITY_NODE": 1, - "PROCESSING_INSTRUCTION_NODE": 1, - "COMMENT_NODE": 1, - "DOCUMENT_NODE": 1, - "DOCUMENT_TYPE_NODE": 1, - "DOCUMENT_FRAGMENT_NODE": 1, - "NOTATION_NODE": 1, - - "DOCUMENT_POSITION_DISCONNECTED": 1, - "DOCUMENT_POSITION_PRECEDING": 1, - "DOCUMENT_POSITION_FOLLOWING": 1, - "DOCUMENT_POSITION_CONTAINS": 1, - "DOCUMENT_POSITION_CONTAINED_BY": 1, - "DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC": 1, - - "UNKNOWN_RULE": 1, - "STYLE_RULE": 1, - "CHARSET_RULE": 1, - "IMPORT_RULE": 1, - "MEDIA_RULE": 1, - "FONT_FACE_RULE": 1, - "PAGE_RULE": 1, - - "CAPTURING_PHASE": 1, - "AT_TARGET": 1, - "BUBBLING_PHASE": 1, - - "SCROLL_PAGE_UP": 1, - "SCROLL_PAGE_DOWN": 1, - - "MOUSEUP": 1, - "MOUSEDOWN": 1, - "MOUSEOVER": 1, - "MOUSEOUT": 1, - "MOUSEMOVE": 1, - "MOUSEDRAG": 1, - "CLICK": 1, - "DBLCLICK": 1, - "KEYDOWN": 1, - "KEYUP": 1, - "KEYPRESS": 1, - "DRAGDROP": 1, - "FOCUS": 1, - "BLUR": 1, - "SELECT": 1, - "CHANGE": 1, - "RESET": 1, - "SUBMIT": 1, - "SCROLL": 1, - "LOAD": 1, - "UNLOAD": 1, - "XFER_DONE": 1, - "ABORT": 1, - "ERROR": 1, - "LOCATE": 1, - "MOVE": 1, - "RESIZE": 1, - "FORWARD": 1, - "HELP": 1, - "BACK": 1, - "TEXT": 1, - - "ALT_MASK": 1, - "CONTROL_MASK": 1, - "SHIFT_MASK": 1, - "META_MASK": 1, - - "DOM_VK_TAB": 1, - "DOM_VK_PAGE_UP": 1, - "DOM_VK_PAGE_DOWN": 1, - "DOM_VK_UP": 1, - "DOM_VK_DOWN": 1, - "DOM_VK_LEFT": 1, - "DOM_VK_RIGHT": 1, - "DOM_VK_CANCEL": 1, - "DOM_VK_HELP": 1, - "DOM_VK_BACK_SPACE": 1, - "DOM_VK_CLEAR": 1, - "DOM_VK_RETURN": 1, - "DOM_VK_ENTER": 1, - "DOM_VK_SHIFT": 1, - "DOM_VK_CONTROL": 1, - "DOM_VK_ALT": 1, - "DOM_VK_PAUSE": 1, - "DOM_VK_CAPS_LOCK": 1, - "DOM_VK_ESCAPE": 1, - "DOM_VK_SPACE": 1, - "DOM_VK_END": 1, - "DOM_VK_HOME": 1, - "DOM_VK_PRINTSCREEN": 1, - "DOM_VK_INSERT": 1, - "DOM_VK_DELETE": 1, - "DOM_VK_0": 1, - "DOM_VK_1": 1, - "DOM_VK_2": 1, - "DOM_VK_3": 1, - "DOM_VK_4": 1, - "DOM_VK_5": 1, - "DOM_VK_6": 1, - "DOM_VK_7": 1, - "DOM_VK_8": 1, - "DOM_VK_9": 1, - "DOM_VK_SEMICOLON": 1, - "DOM_VK_EQUALS": 1, - "DOM_VK_A": 1, - "DOM_VK_B": 1, - "DOM_VK_C": 1, - "DOM_VK_D": 1, - "DOM_VK_E": 1, - "DOM_VK_F": 1, - "DOM_VK_G": 1, - "DOM_VK_H": 1, - "DOM_VK_I": 1, - "DOM_VK_J": 1, - "DOM_VK_K": 1, - "DOM_VK_L": 1, - "DOM_VK_M": 1, - "DOM_VK_N": 1, - "DOM_VK_O": 1, - "DOM_VK_P": 1, - "DOM_VK_Q": 1, - "DOM_VK_R": 1, - "DOM_VK_S": 1, - "DOM_VK_T": 1, - "DOM_VK_U": 1, - "DOM_VK_V": 1, - "DOM_VK_W": 1, - "DOM_VK_X": 1, - "DOM_VK_Y": 1, - "DOM_VK_Z": 1, - "DOM_VK_CONTEXT_MENU": 1, - "DOM_VK_NUMPAD0": 1, - "DOM_VK_NUMPAD1": 1, - "DOM_VK_NUMPAD2": 1, - "DOM_VK_NUMPAD3": 1, - "DOM_VK_NUMPAD4": 1, - "DOM_VK_NUMPAD5": 1, - "DOM_VK_NUMPAD6": 1, - "DOM_VK_NUMPAD7": 1, - "DOM_VK_NUMPAD8": 1, - "DOM_VK_NUMPAD9": 1, - "DOM_VK_MULTIPLY": 1, - "DOM_VK_ADD": 1, - "DOM_VK_SEPARATOR": 1, - "DOM_VK_SUBTRACT": 1, - "DOM_VK_DECIMAL": 1, - "DOM_VK_DIVIDE": 1, - "DOM_VK_F1": 1, - "DOM_VK_F2": 1, - "DOM_VK_F3": 1, - "DOM_VK_F4": 1, - "DOM_VK_F5": 1, - "DOM_VK_F6": 1, - "DOM_VK_F7": 1, - "DOM_VK_F8": 1, - "DOM_VK_F9": 1, - "DOM_VK_F10": 1, - "DOM_VK_F11": 1, - "DOM_VK_F12": 1, - "DOM_VK_F13": 1, - "DOM_VK_F14": 1, - "DOM_VK_F15": 1, - "DOM_VK_F16": 1, - "DOM_VK_F17": 1, - "DOM_VK_F18": 1, - "DOM_VK_F19": 1, - "DOM_VK_F20": 1, - "DOM_VK_F21": 1, - "DOM_VK_F22": 1, - "DOM_VK_F23": 1, - "DOM_VK_F24": 1, - "DOM_VK_NUM_LOCK": 1, - "DOM_VK_SCROLL_LOCK": 1, - "DOM_VK_COMMA": 1, - "DOM_VK_PERIOD": 1, - "DOM_VK_SLASH": 1, - "DOM_VK_BACK_QUOTE": 1, - "DOM_VK_OPEN_BRACKET": 1, - "DOM_VK_BACK_SLASH": 1, - "DOM_VK_CLOSE_BRACKET": 1, - "DOM_VK_QUOTE": 1, - "DOM_VK_META": 1, - - "SVG_ZOOMANDPAN_DISABLE": 1, - "SVG_ZOOMANDPAN_MAGNIFY": 1, - "SVG_ZOOMANDPAN_UNKNOWN": 1 -}; - -this.cssInfo = -{ - "background": ["bgRepeat", "bgAttachment", "bgPosition", "color", "systemColor", "none"], - "background-attachment": ["bgAttachment"], - "background-color": ["color", "systemColor"], - "background-image": ["none"], - "background-position": ["bgPosition"], - "background-repeat": ["bgRepeat"], - - "border": ["borderStyle", "thickness", "color", "systemColor", "none"], - "border-top": ["borderStyle", "borderCollapse", "color", "systemColor", "none"], - "border-right": ["borderStyle", "borderCollapse", "color", "systemColor", "none"], - "border-bottom": ["borderStyle", "borderCollapse", "color", "systemColor", "none"], - "border-left": ["borderStyle", "borderCollapse", "color", "systemColor", "none"], - "border-collapse": ["borderCollapse"], - "border-color": ["color", "systemColor"], - "border-top-color": ["color", "systemColor"], - "border-right-color": ["color", "systemColor"], - "border-bottom-color": ["color", "systemColor"], - "border-left-color": ["color", "systemColor"], - "border-spacing": [], - "border-style": ["borderStyle"], - "border-top-style": ["borderStyle"], - "border-right-style": ["borderStyle"], - "border-bottom-style": ["borderStyle"], - "border-left-style": ["borderStyle"], - "border-width": ["thickness"], - "border-top-width": ["thickness"], - "border-right-width": ["thickness"], - "border-bottom-width": ["thickness"], - "border-left-width": ["thickness"], - - "bottom": ["auto"], - "caption-side": ["captionSide"], - "clear": ["clear", "none"], - "clip": ["auto"], - "color": ["color", "systemColor"], - "content": ["content"], - "counter-increment": ["none"], - "counter-reset": ["none"], - "cursor": ["cursor", "none"], - "direction": ["direction"], - "display": ["display", "none"], - "empty-cells": [], - "float": ["float", "none"], - "font": ["fontStyle", "fontVariant", "fontWeight", "fontFamily"], - - "font-family": ["fontFamily"], - "font-size": ["fontSize"], - "font-size-adjust": [], - "font-stretch": [], - "font-style": ["fontStyle"], - "font-variant": ["fontVariant"], - "font-weight": ["fontWeight"], - - "height": ["auto"], - "left": ["auto"], - "letter-spacing": [], - "line-height": [], - - "list-style": ["listStyleType", "listStylePosition", "none"], - "list-style-image": ["none"], - "list-style-position": ["listStylePosition"], - "list-style-type": ["listStyleType", "none"], - - "margin": [], - "margin-top": [], - "margin-right": [], - "margin-bottom": [], - "margin-left": [], - - "marker-offset": ["auto"], - "min-height": ["none"], - "max-height": ["none"], - "min-width": ["none"], - "max-width": ["none"], - - "outline": ["borderStyle", "color", "systemColor", "none"], - "outline-color": ["color", "systemColor"], - "outline-style": ["borderStyle"], - "outline-width": [], - - "overflow": ["overflow", "auto"], - "overflow-x": ["overflow", "auto"], - "overflow-y": ["overflow", "auto"], - - "padding": [], - "padding-top": [], - "padding-right": [], - "padding-bottom": [], - "padding-left": [], - - "position": ["position"], - "quotes": ["none"], - "right": ["auto"], - "table-layout": ["tableLayout", "auto"], - "text-align": ["textAlign"], - "text-decoration": ["textDecoration", "none"], - "text-indent": [], - "text-shadow": [], - "text-transform": ["textTransform", "none"], - "top": ["auto"], - "unicode-bidi": [], - "vertical-align": ["verticalAlign"], - "white-space": ["whiteSpace"], - "width": ["auto"], - "word-spacing": [], - "z-index": [], - - "-moz-appearance": ["mozAppearance"], - "-moz-border-radius": [], - "-moz-border-radius-bottomleft": [], - "-moz-border-radius-bottomright": [], - "-moz-border-radius-topleft": [], - "-moz-border-radius-topright": [], - "-moz-border-top-colors": ["color", "systemColor"], - "-moz-border-right-colors": ["color", "systemColor"], - "-moz-border-bottom-colors": ["color", "systemColor"], - "-moz-border-left-colors": ["color", "systemColor"], - "-moz-box-align": ["mozBoxAlign"], - "-moz-box-direction": ["mozBoxDirection"], - "-moz-box-flex": [], - "-moz-box-ordinal-group": [], - "-moz-box-orient": ["mozBoxOrient"], - "-moz-box-pack": ["mozBoxPack"], - "-moz-box-sizing": ["mozBoxSizing"], - "-moz-opacity": [], - "-moz-user-focus": ["userFocus", "none"], - "-moz-user-input": ["userInput"], - "-moz-user-modify": [], - "-moz-user-select": ["userSelect", "none"], - "-moz-background-clip": [], - "-moz-background-inline-policy": [], - "-moz-background-origin": [], - "-moz-binding": [], - "-moz-column-count": [], - "-moz-column-gap": [], - "-moz-column-width": [], - "-moz-image-region": [] -}; - -this.inheritedStyleNames = -{ - "border-collapse": 1, - "border-spacing": 1, - "border-style": 1, - "caption-side": 1, - "color": 1, - "cursor": 1, - "direction": 1, - "empty-cells": 1, - "font": 1, - "font-family": 1, - "font-size-adjust": 1, - "font-size": 1, - "font-style": 1, - "font-variant": 1, - "font-weight": 1, - "letter-spacing": 1, - "line-height": 1, - "list-style": 1, - "list-style-image": 1, - "list-style-position": 1, - "list-style-type": 1, - "quotes": 1, - "text-align": 1, - "text-decoration": 1, - "text-indent": 1, - "text-shadow": 1, - "text-transform": 1, - "white-space": 1, - "word-spacing": 1 -}; - -this.cssKeywords = -{ - "appearance": - [ - "button", - "button-small", - "checkbox", - "checkbox-container", - "checkbox-small", - "dialog", - "listbox", - "menuitem", - "menulist", - "menulist-button", - "menulist-textfield", - "menupopup", - "progressbar", - "radio", - "radio-container", - "radio-small", - "resizer", - "scrollbar", - "scrollbarbutton-down", - "scrollbarbutton-left", - "scrollbarbutton-right", - "scrollbarbutton-up", - "scrollbartrack-horizontal", - "scrollbartrack-vertical", - "separator", - "statusbar", - "tab", - "tab-left-edge", - "tabpanels", - "textfield", - "toolbar", - "toolbarbutton", - "toolbox", - "tooltip", - "treeheadercell", - "treeheadersortarrow", - "treeitem", - "treetwisty", - "treetwistyopen", - "treeview", - "window" - ], - - "systemColor": - [ - "ActiveBorder", - "ActiveCaption", - "AppWorkspace", - "Background", - "ButtonFace", - "ButtonHighlight", - "ButtonShadow", - "ButtonText", - "CaptionText", - "GrayText", - "Highlight", - "HighlightText", - "InactiveBorder", - "InactiveCaption", - "InactiveCaptionText", - "InfoBackground", - "InfoText", - "Menu", - "MenuText", - "Scrollbar", - "ThreeDDarkShadow", - "ThreeDFace", - "ThreeDHighlight", - "ThreeDLightShadow", - "ThreeDShadow", - "Window", - "WindowFrame", - "WindowText", - "-moz-field", - "-moz-fieldtext", - "-moz-workspace", - "-moz-visitedhyperlinktext", - "-moz-use-text-color" - ], - - "color": - [ - "AliceBlue", - "AntiqueWhite", - "Aqua", - "Aquamarine", - "Azure", - "Beige", - "Bisque", - "Black", - "BlanchedAlmond", - "Blue", - "BlueViolet", - "Brown", - "BurlyWood", - "CadetBlue", - "Chartreuse", - "Chocolate", - "Coral", - "CornflowerBlue", - "Cornsilk", - "Crimson", - "Cyan", - "DarkBlue", - "DarkCyan", - "DarkGoldenRod", - "DarkGray", - "DarkGreen", - "DarkKhaki", - "DarkMagenta", - "DarkOliveGreen", - "DarkOrange", - "DarkOrchid", - "DarkRed", - "DarkSalmon", - "DarkSeaGreen", - "DarkSlateBlue", - "DarkSlateGray", - "DarkTurquoise", - "DarkViolet", - "DeepPink", - "DarkSkyBlue", - "DimGray", - "DodgerBlue", - "Feldspar", - "FireBrick", - "FloralWhite", - "ForestGreen", - "Fuchsia", - "Gainsboro", - "GhostWhite", - "Gold", - "GoldenRod", - "Gray", - "Green", - "GreenYellow", - "HoneyDew", - "HotPink", - "IndianRed", - "Indigo", - "Ivory", - "Khaki", - "Lavender", - "LavenderBlush", - "LawnGreen", - "LemonChiffon", - "LightBlue", - "LightCoral", - "LightCyan", - "LightGoldenRodYellow", - "LightGrey", - "LightGreen", - "LightPink", - "LightSalmon", - "LightSeaGreen", - "LightSkyBlue", - "LightSlateBlue", - "LightSlateGray", - "LightSteelBlue", - "LightYellow", - "Lime", - "LimeGreen", - "Linen", - "Magenta", - "Maroon", - "MediumAquaMarine", - "MediumBlue", - "MediumOrchid", - "MediumPurple", - "MediumSeaGreen", - "MediumSlateBlue", - "MediumSpringGreen", - "MediumTurquoise", - "MediumVioletRed", - "MidnightBlue", - "MintCream", - "MistyRose", - "Moccasin", - "NavajoWhite", - "Navy", - "OldLace", - "Olive", - "OliveDrab", - "Orange", - "OrangeRed", - "Orchid", - "PaleGoldenRod", - "PaleGreen", - "PaleTurquoise", - "PaleVioletRed", - "PapayaWhip", - "PeachPuff", - "Peru", - "Pink", - "Plum", - "PowderBlue", - "Purple", - "Red", - "RosyBrown", - "RoyalBlue", - "SaddleBrown", - "Salmon", - "SandyBrown", - "SeaGreen", - "SeaShell", - "Sienna", - "Silver", - "SkyBlue", - "SlateBlue", - "SlateGray", - "Snow", - "SpringGreen", - "SteelBlue", - "Tan", - "Teal", - "Thistle", - "Tomato", - "Turquoise", - "Violet", - "VioletRed", - "Wheat", - "White", - "WhiteSmoke", - "Yellow", - "YellowGreen", - "transparent", - "invert" - ], - - "auto": - [ - "auto" - ], - - "none": - [ - "none" - ], - - "captionSide": - [ - "top", - "bottom", - "left", - "right" - ], - - "clear": - [ - "left", - "right", - "both" - ], - - "cursor": - [ - "auto", - "cell", - "context-menu", - "crosshair", - "default", - "help", - "pointer", - "progress", - "move", - "e-resize", - "all-scroll", - "ne-resize", - "nw-resize", - "n-resize", - "se-resize", - "sw-resize", - "s-resize", - "w-resize", - "ew-resize", - "ns-resize", - "nesw-resize", - "nwse-resize", - "col-resize", - "row-resize", - "text", - "vertical-text", - "wait", - "alias", - "copy", - "move", - "no-drop", - "not-allowed", - "-moz-alias", - "-moz-cell", - "-moz-copy", - "-moz-grab", - "-moz-grabbing", - "-moz-contextmenu", - "-moz-zoom-in", - "-moz-zoom-out", - "-moz-spinning" - ], - - "direction": - [ - "ltr", - "rtl" - ], - - "bgAttachment": - [ - "scroll", - "fixed" - ], - - "bgPosition": - [ - "top", - "center", - "bottom", - "left", - "right" - ], - - "bgRepeat": - [ - "repeat", - "repeat-x", - "repeat-y", - "no-repeat" - ], - - "borderStyle": - [ - "hidden", - "dotted", - "dashed", - "solid", - "double", - "groove", - "ridge", - "inset", - "outset", - "-moz-bg-inset", - "-moz-bg-outset", - "-moz-bg-solid" - ], - - "borderCollapse": - [ - "collapse", - "separate" - ], - - "overflow": - [ - "visible", - "hidden", - "scroll", - "-moz-scrollbars-horizontal", - "-moz-scrollbars-none", - "-moz-scrollbars-vertical" - ], - - "listStyleType": - [ - "disc", - "circle", - "square", - "decimal", - "decimal-leading-zero", - "lower-roman", - "upper-roman", - "lower-greek", - "lower-alpha", - "lower-latin", - "upper-alpha", - "upper-latin", - "hebrew", - "armenian", - "georgian", - "cjk-ideographic", - "hiragana", - "katakana", - "hiragana-iroha", - "katakana-iroha", - "inherit" - ], - - "listStylePosition": - [ - "inside", - "outside" - ], - - "content": - [ - "open-quote", - "close-quote", - "no-open-quote", - "no-close-quote", - "inherit" - ], - - "fontStyle": - [ - "normal", - "italic", - "oblique", - "inherit" - ], - - "fontVariant": - [ - "normal", - "small-caps", - "inherit" - ], - - "fontWeight": - [ - "normal", - "bold", - "bolder", - "lighter", - "inherit" - ], - - "fontSize": - [ - "xx-small", - "x-small", - "small", - "medium", - "large", - "x-large", - "xx-large", - "smaller", - "larger" - ], - - "fontFamily": - [ - "Arial", - "Comic Sans MS", - "Georgia", - "Tahoma", - "Verdana", - "Times New Roman", - "Trebuchet MS", - "Lucida Grande", - "Helvetica", - "serif", - "sans-serif", - "cursive", - "fantasy", - "monospace", - "caption", - "icon", - "menu", - "message-box", - "small-caption", - "status-bar", - "inherit" - ], - - "display": - [ - "block", - "inline", - "inline-block", - "list-item", - "marker", - "run-in", - "compact", - "table", - "inline-table", - "table-row-group", - "table-column", - "table-column-group", - "table-header-group", - "table-footer-group", - "table-row", - "table-cell", - "table-caption", - "-moz-box", - "-moz-compact", - "-moz-deck", - "-moz-grid", - "-moz-grid-group", - "-moz-grid-line", - "-moz-groupbox", - "-moz-inline-block", - "-moz-inline-box", - "-moz-inline-grid", - "-moz-inline-stack", - "-moz-inline-table", - "-moz-marker", - "-moz-popup", - "-moz-runin", - "-moz-stack" - ], - - "position": - [ - "static", - "relative", - "absolute", - "fixed", - "inherit" - ], - - "float": - [ - "left", - "right" - ], - - "textAlign": - [ - "left", - "right", - "center", - "justify" - ], - - "tableLayout": - [ - "fixed" - ], - - "textDecoration": - [ - "underline", - "overline", - "line-through", - "blink" - ], - - "textTransform": - [ - "capitalize", - "lowercase", - "uppercase", - "inherit" - ], - - "unicodeBidi": - [ - "normal", - "embed", - "bidi-override" - ], - - "whiteSpace": - [ - "normal", - "pre", - "nowrap" - ], - - "verticalAlign": - [ - "baseline", - "sub", - "super", - "top", - "text-top", - "middle", - "bottom", - "text-bottom", - "inherit" - ], - - "thickness": - [ - "thin", - "medium", - "thick" - ], - - "userFocus": - [ - "ignore", - "normal" - ], - - "userInput": - [ - "disabled", - "enabled" - ], - - "userSelect": - [ - "normal" - ], - - "mozBoxSizing": - [ - "content-box", - "padding-box", - "border-box" - ], - - "mozBoxAlign": - [ - "start", - "center", - "end", - "baseline", - "stretch" - ], - - "mozBoxDirection": - [ - "normal", - "reverse" - ], - - "mozBoxOrient": - [ - "horizontal", - "vertical" - ], - - "mozBoxPack": - [ - "start", - "center", - "end" - ] -}; - -this.nonEditableTags = -{ - "HTML": 1, - "HEAD": 1, - "html": 1, - "head": 1 -}; - -this.innerEditableTags = -{ - "BODY": 1, - "body": 1 -}; - -this.selfClosingTags = -{ // End tags for void elements are forbidden http://wiki.whatwg.org/wiki/HTML_vs._XHTML - "meta": 1, - "link": 1, - "area": 1, - "base": 1, - "col": 1, - "input": 1, - "img": 1, - "br": 1, - "hr": 1, - "param":1, - "embed":1 -}; - -var invisibleTags = this.invisibleTags = -{ - "HTML": 1, - "HEAD": 1, - "TITLE": 1, - "META": 1, - "LINK": 1, - "STYLE": 1, - "SCRIPT": 1, - "NOSCRIPT": 1, - "BR": 1, - "PARAM": 1, - "COL": 1, - - "html": 1, - "head": 1, - "title": 1, - "meta": 1, - "link": 1, - "style": 1, - "script": 1, - "noscript": 1, - "br": 1, - "param": 1, - "col": 1 - /* - "window": 1, - "browser": 1, - "frame": 1, - "tabbrowser": 1, - "WINDOW": 1, - "BROWSER": 1, - "FRAME": 1, - "TABBROWSER": 1, - */ -}; - - -if (typeof KeyEvent == "undefined") { - this.KeyEvent = { - DOM_VK_CANCEL: 3, - DOM_VK_HELP: 6, - DOM_VK_BACK_SPACE: 8, - DOM_VK_TAB: 9, - DOM_VK_CLEAR: 12, - DOM_VK_RETURN: 13, - DOM_VK_ENTER: 14, - DOM_VK_SHIFT: 16, - DOM_VK_CONTROL: 17, - DOM_VK_ALT: 18, - DOM_VK_PAUSE: 19, - DOM_VK_CAPS_LOCK: 20, - DOM_VK_ESCAPE: 27, - DOM_VK_SPACE: 32, - DOM_VK_PAGE_UP: 33, - DOM_VK_PAGE_DOWN: 34, - DOM_VK_END: 35, - DOM_VK_HOME: 36, - DOM_VK_LEFT: 37, - DOM_VK_UP: 38, - DOM_VK_RIGHT: 39, - DOM_VK_DOWN: 40, - DOM_VK_PRINTSCREEN: 44, - DOM_VK_INSERT: 45, - DOM_VK_DELETE: 46, - DOM_VK_0: 48, - DOM_VK_1: 49, - DOM_VK_2: 50, - DOM_VK_3: 51, - DOM_VK_4: 52, - DOM_VK_5: 53, - DOM_VK_6: 54, - DOM_VK_7: 55, - DOM_VK_8: 56, - DOM_VK_9: 57, - DOM_VK_SEMICOLON: 59, - DOM_VK_EQUALS: 61, - DOM_VK_A: 65, - DOM_VK_B: 66, - DOM_VK_C: 67, - DOM_VK_D: 68, - DOM_VK_E: 69, - DOM_VK_F: 70, - DOM_VK_G: 71, - DOM_VK_H: 72, - DOM_VK_I: 73, - DOM_VK_J: 74, - DOM_VK_K: 75, - DOM_VK_L: 76, - DOM_VK_M: 77, - DOM_VK_N: 78, - DOM_VK_O: 79, - DOM_VK_P: 80, - DOM_VK_Q: 81, - DOM_VK_R: 82, - DOM_VK_S: 83, - DOM_VK_T: 84, - DOM_VK_U: 85, - DOM_VK_V: 86, - DOM_VK_W: 87, - DOM_VK_X: 88, - DOM_VK_Y: 89, - DOM_VK_Z: 90, - DOM_VK_CONTEXT_MENU: 93, - DOM_VK_NUMPAD0: 96, - DOM_VK_NUMPAD1: 97, - DOM_VK_NUMPAD2: 98, - DOM_VK_NUMPAD3: 99, - DOM_VK_NUMPAD4: 100, - DOM_VK_NUMPAD5: 101, - DOM_VK_NUMPAD6: 102, - DOM_VK_NUMPAD7: 103, - DOM_VK_NUMPAD8: 104, - DOM_VK_NUMPAD9: 105, - DOM_VK_MULTIPLY: 106, - DOM_VK_ADD: 107, - DOM_VK_SEPARATOR: 108, - DOM_VK_SUBTRACT: 109, - DOM_VK_DECIMAL: 110, - DOM_VK_DIVIDE: 111, - DOM_VK_F1: 112, - DOM_VK_F2: 113, - DOM_VK_F3: 114, - DOM_VK_F4: 115, - DOM_VK_F5: 116, - DOM_VK_F6: 117, - DOM_VK_F7: 118, - DOM_VK_F8: 119, - DOM_VK_F9: 120, - DOM_VK_F10: 121, - DOM_VK_F11: 122, - DOM_VK_F12: 123, - DOM_VK_F13: 124, - DOM_VK_F14: 125, - DOM_VK_F15: 126, - DOM_VK_F16: 127, - DOM_VK_F17: 128, - DOM_VK_F18: 129, - DOM_VK_F19: 130, - DOM_VK_F20: 131, - DOM_VK_F21: 132, - DOM_VK_F22: 133, - DOM_VK_F23: 134, - DOM_VK_F24: 135, - DOM_VK_NUM_LOCK: 144, - DOM_VK_SCROLL_LOCK: 145, - DOM_VK_COMMA: 188, - DOM_VK_PERIOD: 190, - DOM_VK_SLASH: 191, - DOM_VK_BACK_QUOTE: 192, - DOM_VK_OPEN_BRACKET: 219, - DOM_VK_BACK_SLASH: 220, - DOM_VK_CLOSE_BRACKET: 221, - DOM_VK_QUOTE: 222, - DOM_VK_META: 224 - }; -} - - -// ************************************************************************************************ -// Ajax - -/** - * @namespace - */ -this.Ajax = -{ - - requests: [], - transport: null, - states: ["Uninitialized","Loading","Loaded","Interactive","Complete"], - - initialize: function() - { - this.transport = FBL.getNativeXHRObject(); - }, - - getXHRObject: function() - { - var xhrObj = false; - try - { - xhrObj = new XMLHttpRequest(); - } - catch(e) - { - var progid = [ - "MSXML2.XMLHTTP.5.0", "MSXML2.XMLHTTP.4.0", - "MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP", "Microsoft.XMLHTTP" - ]; - - for ( var i=0; i < progid.length; ++i ) { - try - { - xhrObj = new ActiveXObject(progid[i]); - } - catch(e) - { - continue; - } - break; - } - } - finally - { - return xhrObj; - } - }, - - - /** - * Create a AJAX request. - * - * @name request - * @param {Object} options request options - * @param {String} options.url URL to be requested - * @param {String} options.type Request type ("get" ou "post"). Default is "get". - * @param {Boolean} options.async Asynchronous flag. Default is "true". - * @param {String} options.dataType Data type ("text", "html", "xml" or "json"). Default is "text". - * @param {String} options.contentType Content-type of the data being sent. Default is "application/x-www-form-urlencoded". - * @param {Function} options.onLoading onLoading callback - * @param {Function} options.onLoaded onLoaded callback - * @param {Function} options.onInteractive onInteractive callback - * @param {Function} options.onComplete onComplete callback - * @param {Function} options.onUpdate onUpdate callback - * @param {Function} options.onSuccess onSuccess callback - * @param {Function} options.onFailure onFailure callback - */ - request: function(options) - { - // process options - var o = FBL.extend( - { - // default values - type: "get", - async: true, - dataType: "text", - contentType: "application/x-www-form-urlencoded" - }, - options || {} - ); - - this.requests.push(o); - - var s = this.getState(); - if (s == "Uninitialized" || s == "Complete" || s == "Loaded") - this.sendRequest(); - }, - - serialize: function(data) - { - var r = [""], rl = 0; - if (data) { - if (typeof data == "string") r[rl++] = data; - - else if (data.innerHTML && data.elements) { - for (var i=0,el,l=(el=data.elements).length; i < l; i++) - if (el[i].name) { - r[rl++] = encodeURIComponent(el[i].name); - r[rl++] = "="; - r[rl++] = encodeURIComponent(el[i].value); - r[rl++] = "&"; - } - - } else - for(var param in data) { - r[rl++] = encodeURIComponent(param); - r[rl++] = "="; - r[rl++] = encodeURIComponent(data[param]); - r[rl++] = "&"; - } - } - return r.join("").replace(/&$/, ""); - }, - - sendRequest: function() - { - var t = FBL.Ajax.transport, r = FBL.Ajax.requests.shift(), data; - - // open XHR object - t.open(r.type, r.url, r.async); - - //setRequestHeaders(); - - // indicates that it is a XHR request to the server - t.setRequestHeader("X-Requested-With", "XMLHttpRequest"); - - // if data is being sent, sets the appropriate content-type - if (data = FBL.Ajax.serialize(r.data)) - t.setRequestHeader("Content-Type", r.contentType); - - /** @ignore */ - // onreadystatechange handler - t.onreadystatechange = function() - { - FBL.Ajax.onStateChange(r); - }; - - // send the request - t.send(data); - }, - - /** - * Handles the state change - */ - onStateChange: function(options) - { - var fn, o = options, t = this.transport; - var state = this.getState(t); - - if (fn = o["on" + state]) fn(this.getResponse(o), o); - - if (state == "Complete") - { - var success = t.status == 200, response = this.getResponse(o); - - if (fn = o["onUpdate"]) - fn(response, o); - - if (fn = o["on" + (success ? "Success" : "Failure")]) - fn(response, o); - - t.onreadystatechange = FBL.emptyFn; - - if (this.requests.length > 0) - setTimeout(this.sendRequest, 10); - } - }, - - /** - * gets the appropriate response value according the type - */ - getResponse: function(options) - { - var t = this.transport, type = options.dataType; - - if (t.status != 200) return t.statusText; - else if (type == "text") return t.responseText; - else if (type == "html") return t.responseText; - else if (type == "xml") return t.responseXML; - else if (type == "json") return eval("(" + t.responseText + ")"); - }, - - /** - * returns the current state of the XHR object - */ - getState: function() - { - return this.states[this.transport.readyState]; - } - -}; - - -// ************************************************************************************************ -// Cookie, from http://www.quirksmode.org/js/cookies.html - -this.createCookie = function(name,value,days) -{ - if ('cookie' in document) - { - if (days) - { - var date = new Date(); - date.setTime(date.getTime()+(days*24*60*60*1000)); - var expires = "; expires="+date.toGMTString(); - } - else - var expires = ""; - - document.cookie = name+"="+value+expires+"; path=/"; - } -}; - -this.readCookie = function (name) -{ - if ('cookie' in document) - { - var nameEQ = name + "="; - var ca = document.cookie.split(';'); - - for(var i=0; i < ca.length; i++) - { - var c = ca[i]; - while (c.charAt(0)==' ') c = c.substring(1,c.length); - if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length); - } - } - - return null; -}; - -this.removeCookie = function(name) -{ - this.createCookie(name, "", -1); -}; - - -// ************************************************************************************************ -// http://www.mister-pixel.com/#Content__state=is_that_simple -var fixIE6BackgroundImageCache = function(doc) -{ - doc = doc || document; - try - { - doc.execCommand("BackgroundImageCache", false, true); - } - catch(E) - { - - } -}; - -// ************************************************************************************************ -// calculatePixelsPerInch - -var resetStyle = "margin:0; padding:0; border:0; position:absolute; overflow:hidden; display:block;"; - -var calculatePixelsPerInch = function calculatePixelsPerInch(doc, body) -{ - var inch = FBL.createGlobalElement("div"); - inch.style.cssText = resetStyle + "width:1in; height:1in; position:absolute; top:-1234px; left:-1234px;"; - body.appendChild(inch); - - FBL.pixelsPerInch = { - x: inch.offsetWidth, - y: inch.offsetHeight - }; - - body.removeChild(inch); -}; - - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - -this.SourceLink = function(url, line, type, object, instance) -{ - this.href = url; - this.instance = instance; - this.line = line; - this.type = type; - this.object = object; -}; - -this.SourceLink.prototype = -{ - toString: function() - { - return this.href; - }, - toJSON: function() // until 3.1... - { - return "{\"href\":\""+this.href+"\", "+ - (this.line?("\"line\":"+this.line+","):"")+ - (this.type?(" \"type\":\""+this.type+"\","):"")+ - "}"; - } - -}; - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - -this.SourceText = function(lines, owner) -{ - this.lines = lines; - this.owner = owner; -}; - -this.SourceText.getLineAsHTML = function(lineNo) -{ - return escapeForSourceLine(this.lines[lineNo-1]); -}; - - -// ************************************************************************************************ -}).apply(FBL); - -/* See license.txt for terms of usage */ - -FBL.ns( /** @scope s_i18n */ function() { with (FBL) { -// ************************************************************************************************ - -// TODO: xxxpedro localization -var oSTR = -{ - "NoMembersWarning": "There are no properties to show for this object.", - - "EmptyStyleSheet": "There are no rules in this stylesheet.", - "EmptyElementCSS": "This element has no style rules.", - "AccessRestricted": "Access to restricted URI denied.", - - "net.label.Parameters": "Parameters", - "net.label.Source": "Source", - "URLParameters": "Params", - - "EditStyle": "Edit Element Style...", - "NewRule": "New Rule...", - - "NewProp": "New Property...", - "EditProp": 'Edit "%s"', - "DeleteProp": 'Delete "%s"', - "DisableProp": 'Disable "%s"' -}; - -// ************************************************************************************************ - -FBL.$STR = function(name) -{ - return oSTR.hasOwnProperty(name) ? oSTR[name] : name; -}; - -FBL.$STRF = function(name, args) -{ - if (!oSTR.hasOwnProperty(name)) return name; - - var format = oSTR[name]; - var objIndex = 0; - - var parts = parseFormat(format); - var trialIndex = objIndex; - var objects = args; - - for (var i= 0; i < parts.length; i++) - { - var part = parts[i]; - if (part && typeof(part) == "object") - { - if (++trialIndex > objects.length) // then too few parameters for format, assume unformatted. - { - format = ""; - objIndex = -1; - parts.length = 0; - break; - } - } - - } - - var result = []; - for (var i = 0; i < parts.length; ++i) - { - var part = parts[i]; - if (part && typeof(part) == "object") - { - result.push(""+args.shift()); - } - else - result.push(part); - } - - return result.join(""); -}; - -// ************************************************************************************************ - -var parseFormat = function parseFormat(format) -{ - var parts = []; - if (format.length <= 0) - return parts; - - var reg = /((^%|.%)(\d+)?(\.)([a-zA-Z]))|((^%|.%)([a-zA-Z]))/; - for (var m = reg.exec(format); m; m = reg.exec(format)) - { - if (m[0].substr(0, 2) == "%%") - { - parts.push(format.substr(0, m.index)); - parts.push(m[0].substr(1)); - } - else - { - var type = m[8] ? m[8] : m[5]; - var precision = m[3] ? parseInt(m[3]) : (m[4] == "." ? -1 : 0); - - var rep = null; - switch (type) - { - case "s": - rep = FirebugReps.Text; - break; - case "f": - case "i": - case "d": - rep = FirebugReps.Number; - break; - case "o": - rep = null; - break; - } - - parts.push(format.substr(0, m[0][0] == "%" ? m.index : m.index+1)); - parts.push({rep: rep, precision: precision, type: ("%" + type)}); - } - - format = format.substr(m.index+m[0].length); - } - - parts.push(format); - return parts; -}; - -// ************************************************************************************************ -}}); - -/* See license.txt for terms of usage */ - -FBL.ns( /** @scope s_firebug */ function() { with (FBL) { -// ************************************************************************************************ - -// ************************************************************************************************ -// Globals - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// Internals - -var modules = []; -var panelTypes = []; -var panelTypeMap = {}; -var reps = []; - -var parentPanelMap = {}; - - -// ************************************************************************************************ -// Firebug - -/** - * @namespace describe Firebug - * @exports FBL.Firebug as Firebug - */ -FBL.Firebug = -{ - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - version: "Firebug Lite 1.4.0", - revision: "$Revision$", - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - modules: modules, - panelTypes: panelTypes, - panelTypeMap: panelTypeMap, - reps: reps, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // Initialization - - initialize: function() - { - if (FBTrace.DBG_INITIALIZE) FBTrace.sysout("Firebug.initialize", "initializing application"); - - Firebug.browser = new Context(Env.browser); - Firebug.context = Firebug.browser; - - Firebug.loadPrefs(); - Firebug.context.persistedState.isOpen = false; - - // Document must be cached before chrome initialization - cacheDocument(); - - if (Firebug.Inspector && Firebug.Inspector.create) - Firebug.Inspector.create(); - - if (FBL.CssAnalyzer && FBL.CssAnalyzer.processAllStyleSheets) - FBL.CssAnalyzer.processAllStyleSheets(Firebug.browser.document); - - FirebugChrome.initialize(); - - dispatch(modules, "initialize", []); - - if (Firebug.disableResourceFetching) - Firebug.Console.logFormatted(["Some Firebug Lite features are not working because " + - "resource fetching is disabled. To enabled it set the Firebug Lite option " + - "\"disableResourceFetching\" to \"false\". More info at " + - "http://getfirebug.com/firebuglite#Options"], - Firebug.context, "warn"); - - if (Env.onLoad) - { - var onLoad = Env.onLoad; - delete Env.onLoad; - - setTimeout(onLoad, 200); - } - }, - - shutdown: function() - { - if (Firebug.saveCookies) - Firebug.savePrefs(); - - if (Firebug.Inspector) - Firebug.Inspector.destroy(); - - dispatch(modules, "shutdown", []); - - var chromeMap = FirebugChrome.chromeMap; - - for (var name in chromeMap) - { - if (chromeMap.hasOwnProperty(name)) - { - try - { - chromeMap[name].destroy(); - } - catch(E) - { - if (FBTrace.DBG_ERRORS) FBTrace.sysout("chrome.destroy() failed to: " + name); - } - } - } - - Firebug.Lite.Cache.Element.clear(); - Firebug.Lite.Cache.StyleSheet.clear(); - - Firebug.browser = null; - Firebug.context = null; - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // Registration - - registerModule: function() - { - modules.push.apply(modules, arguments); - - if (FBTrace.DBG_INITIALIZE) FBTrace.sysout("Firebug.registerModule"); - }, - - registerPanel: function() - { - panelTypes.push.apply(panelTypes, arguments); - - for (var i = 0, panelType; panelType = arguments[i]; ++i) - { - panelTypeMap[panelType.prototype.name] = arguments[i]; - - if (panelType.prototype.parentPanel) - parentPanelMap[panelType.prototype.parentPanel] = 1; - } - - if (FBTrace.DBG_INITIALIZE) - for (var i = 0; i < arguments.length; ++i) - FBTrace.sysout("Firebug.registerPanel", arguments[i].prototype.name); - }, - - registerRep: function() - { - reps.push.apply(reps, arguments); - }, - - unregisterRep: function() - { - for (var i = 0; i < arguments.length; ++i) - remove(reps, arguments[i]); - }, - - setDefaultReps: function(funcRep, rep) - { - FBL.defaultRep = rep; - FBL.defaultFuncRep = funcRep; - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // Reps - - getRep: function(object) - { - var type = typeof object; - if (isIE && isFunction(object)) - type = "function"; - - for (var i = 0; i < reps.length; ++i) - { - var rep = reps[i]; - try - { - if (rep.supportsObject(object, type)) - { - if (FBTrace.DBG_DOM) - FBTrace.sysout("getRep type: "+type+" object: "+object, rep); - return rep; - } - } - catch (exc) - { - if (FBTrace.DBG_ERRORS) - { - FBTrace.sysout("firebug.getRep FAILS: ", exc.message || exc); - FBTrace.sysout("firebug.getRep reps["+i+"/"+reps.length+"]: Rep="+reps[i].className); - // TODO: xxxpedro add trace to FBTrace logs like in Firebug - //firebug.trace(); - } - } - } - - return (type == 'function') ? defaultFuncRep : defaultRep; - }, - - getRepObject: function(node) - { - var target = null; - for (var child = node; child; child = child.parentNode) - { - if (hasClass(child, "repTarget")) - target = child; - - if (child.repObject) - { - if (!target && hasClass(child, "repIgnore")) - break; - else - return child.repObject; - } - } - }, - - getRepNode: function(node) - { - for (var child = node; child; child = child.parentNode) - { - if (child.repObject) - return child; - } - }, - - getElementByRepObject: function(element, object) - { - for (var child = element.firstChild; child; child = child.nextSibling) - { - if (child.repObject == object) - return child; - } - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // Preferences - - getPref: function(name) - { - return Firebug[name]; - }, - - setPref: function(name, value) - { - Firebug[name] = value; - - Firebug.savePrefs(); - }, - - setPrefs: function(prefs) - { - for (var name in prefs) - { - if (prefs.hasOwnProperty(name)) - Firebug[name] = prefs[name]; - } - - Firebug.savePrefs(); - }, - - restorePrefs: function() - { - var Options = Env.DefaultOptions; - - for (var name in Options) - { - Firebug[name] = Options[name]; - } - }, - - loadPrefs: function() - { - this.restorePrefs(); - - var prefs = Store.get("FirebugLite") || {}; - var options = prefs.options; - var persistedState = prefs.persistedState || FBL.defaultPersistedState; - - for (var name in options) - { - if (options.hasOwnProperty(name)) - Firebug[name] = options[name]; - } - - if (Firebug.context && persistedState) - Firebug.context.persistedState = persistedState; - }, - - savePrefs: function() - { - var prefs = { - options: {} - }; - - var EnvOptions = Env.Options; - var options = prefs.options; - for (var name in EnvOptions) - { - if (EnvOptions.hasOwnProperty(name)) - { - options[name] = Firebug[name]; - } - } - - var persistedState = Firebug.context.persistedState; - if (!persistedState) - { - persistedState = Firebug.context.persistedState = FBL.defaultPersistedState; - } - - prefs.persistedState = persistedState; - - Store.set("FirebugLite", prefs); - }, - - erasePrefs: function() - { - Store.remove("FirebugLite"); - this.restorePrefs(); - } -}; - -Firebug.restorePrefs(); - -// xxxpedro should we remove this? -window.Firebug = FBL.Firebug; - -if (!Env.Options.enablePersistent || - Env.Options.enablePersistent && Env.isChromeContext || - Env.isDebugMode) - Env.browser.window.Firebug = FBL.Firebug; - - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// Other methods - -FBL.cacheDocument = function cacheDocument() -{ - var ElementCache = Firebug.Lite.Cache.Element; - var els = Firebug.browser.document.getElementsByTagName("*"); - for (var i=0, l=els.length, el; i<l; i++) - { - el = els[i]; - ElementCache(el); - } -}; - -// ************************************************************************************************ - -/** - * @class - * - * Support for listeners registration. This object also extended by Firebug.Module so, - * all modules supports listening automatically. Notice that array of listeners - * is created for each intance of a module within initialize method. Thus all derived - * module classes must ensure that Firebug.Module.initialize method is called for the - * super class. - */ -Firebug.Listener = function() -{ - // The array is created when the first listeners is added. - // It can't be created here since derived objects would share - // the same array. - this.fbListeners = null; -}; - -Firebug.Listener.prototype = -{ - addListener: function(listener) - { - if (!this.fbListeners) - this.fbListeners = []; // delay the creation until the objects are created so 'this' causes new array for each module - - this.fbListeners.push(listener); - }, - - removeListener: function(listener) - { - remove(this.fbListeners, listener); // if this.fbListeners is null, remove is being called with no add - } -}; - -// ************************************************************************************************ - - -// ************************************************************************************************ -// Module - -/** - * @module Base class for all modules. Every derived module object must be registered using - * <code>Firebug.registerModule</code> method. There is always one instance of a module object - * per browser window. - * @extends Firebug.Listener - */ -Firebug.Module = extend(new Firebug.Listener(), -/** @extend Firebug.Module */ -{ - /** - * Called when the window is opened. - */ - initialize: function() - { - }, - - /** - * Called when the window is closed. - */ - shutdown: function() - { - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - /** - * Called when a new context is created but before the page is loaded. - */ - initContext: function(context) - { - }, - - /** - * Called after a context is detached to a separate window; - */ - reattachContext: function(browser, context) - { - }, - - /** - * Called when a context is destroyed. Module may store info on persistedState for reloaded pages. - */ - destroyContext: function(context, persistedState) - { - }, - - // Called when a FF tab is create or activated (user changes FF tab) - // Called after context is created or with context == null (to abort?) - showContext: function(browser, context) - { - }, - - /** - * Called after a context's page gets DOMContentLoaded - */ - loadedContext: function(context) - { - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - showPanel: function(browser, panel) - { - }, - - showSidePanel: function(browser, panel) - { - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - updateOption: function(name, value) - { - }, - - getObjectByURL: function(context, url) - { - } -}); - -// ************************************************************************************************ -// Panel - -/** - * @panel Base class for all panels. Every derived panel must define a constructor and - * register with "Firebug.registerPanel" method. An instance of the panel - * object is created by the framework for each browser tab where Firebug is activated. - */ -Firebug.Panel = -{ - name: "HelloWorld", - title: "Hello World!", - - parentPanel: null, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - options: { - hasCommandLine: false, - hasStatusBar: false, - hasToolButtons: false, - - // Pre-rendered panels are those included in the skin file (firebug.html) - isPreRendered: false, - innerHTMLSync: false - - /* - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // To be used by external extensions - panelHTML: "", - panelCSS: "", - - toolButtonsHTML: "" - /**/ - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - tabNode: null, - panelNode: null, - sidePanelNode: null, - statusBarNode: null, - toolButtonsNode: null, - - panelBarNode: null, - - sidePanelBarBoxNode: null, - sidePanelBarNode: null, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - sidePanelBar: null, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - searchable: false, - editable: true, - order: 2147483647, - statusSeparator: "<", - - create: function(context, doc) - { - this.hasSidePanel = parentPanelMap.hasOwnProperty(this.name); - - this.panelBarNode = $("fbPanelBar1"); - this.sidePanelBarBoxNode = $("fbPanelBar2"); - - if (this.hasSidePanel) - { - this.sidePanelBar = extend({}, PanelBar); - this.sidePanelBar.create(this); - } - - var options = this.options = extend(Firebug.Panel.options, this.options); - var panelId = "fb" + this.name; - - if (options.isPreRendered) - { - this.panelNode = $(panelId); - - this.tabNode = $(panelId + "Tab"); - this.tabNode.style.display = "block"; - - if (options.hasToolButtons) - { - this.toolButtonsNode = $(panelId + "Buttons"); - } - - if (options.hasStatusBar) - { - this.statusBarBox = $("fbStatusBarBox"); - this.statusBarNode = $(panelId + "StatusBar"); - } - } - else - { - var containerSufix = this.parentPanel ? "2" : "1"; - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // Create Panel - var panelNode = this.panelNode = createElement("div", { - id: panelId, - className: "fbPanel" - }); - - $("fbPanel" + containerSufix).appendChild(panelNode); - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // Create Panel Tab - var tabHTML = '<span class="fbTabL"></span><span class="fbTabText">' + - this.title + '</span><span class="fbTabR"></span>'; - - var tabNode = this.tabNode = createElement("a", { - id: panelId + "Tab", - className: "fbTab fbHover", - innerHTML: tabHTML - }); - - if (isIE6) - { - tabNode.href = "javascript:void(0)"; - } - - var panelBarNode = this.parentPanel ? - Firebug.chrome.getPanel(this.parentPanel).sidePanelBarNode : - this.panelBarNode; - - panelBarNode.appendChild(tabNode); - tabNode.style.display = "block"; - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // create ToolButtons - if (options.hasToolButtons) - { - this.toolButtonsNode = createElement("span", { - id: panelId + "Buttons", - className: "fbToolbarButtons" - }); - - $("fbToolbarButtons").appendChild(this.toolButtonsNode); - } - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // create StatusBar - if (options.hasStatusBar) - { - this.statusBarBox = $("fbStatusBarBox"); - - this.statusBarNode = createElement("span", { - id: panelId + "StatusBar", - className: "fbToolbarButtons fbStatusBar" - }); - - this.statusBarBox.appendChild(this.statusBarNode); - } - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // create SidePanel - } - - this.containerNode = this.panelNode.parentNode; - - if (FBTrace.DBG_INITIALIZE) FBTrace.sysout("Firebug.Panel.create", this.name); - - // xxxpedro contextMenu - this.onContextMenu = bind(this.onContextMenu, this); - - /* - this.context = context; - this.document = doc; - - this.panelNode = doc.createElement("div"); - this.panelNode.ownerPanel = this; - - setClass(this.panelNode, "panelNode panelNode-"+this.name+" contextUID="+context.uid); - doc.body.appendChild(this.panelNode); - - if (FBTrace.DBG_INITIALIZE) - FBTrace.sysout("firebug.initialize panelNode for "+this.name+"\n"); - - this.initializeNode(this.panelNode); - /**/ - }, - - destroy: function(state) // Panel may store info on state - { - if (FBTrace.DBG_INITIALIZE) FBTrace.sysout("Firebug.Panel.destroy", this.name); - - if (this.hasSidePanel) - { - this.sidePanelBar.destroy(); - this.sidePanelBar = null; - } - - this.options = null; - this.name = null; - this.parentPanel = null; - - this.tabNode = null; - this.panelNode = null; - this.containerNode = null; - - this.toolButtonsNode = null; - this.statusBarBox = null; - this.statusBarNode = null; - - //if (this.panelNode) - // delete this.panelNode.ownerPanel; - - //this.destroyNode(); - }, - - initialize: function() - { - if (FBTrace.DBG_INITIALIZE) FBTrace.sysout("Firebug.Panel.initialize", this.name); - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - if (this.hasSidePanel) - { - this.sidePanelBar.initialize(); - } - - var options = this.options = extend(Firebug.Panel.options, this.options); - var panelId = "fb" + this.name; - - this.panelNode = $(panelId); - - this.tabNode = $(panelId + "Tab"); - this.tabNode.style.display = "block"; - - if (options.hasStatusBar) - { - this.statusBarBox = $("fbStatusBarBox"); - this.statusBarNode = $(panelId + "StatusBar"); - } - - if (options.hasToolButtons) - { - this.toolButtonsNode = $(panelId + "Buttons"); - } - - this.containerNode = this.panelNode.parentNode; - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // restore persistent state - this.containerNode.scrollTop = this.lastScrollTop; - - // xxxpedro contextMenu - addEvent(this.containerNode, "contextmenu", this.onContextMenu); - - - /// TODO: xxxpedro infoTip Hack - Firebug.chrome.currentPanel = - Firebug.chrome.selectedPanel && Firebug.chrome.selectedPanel.sidePanelBar ? - Firebug.chrome.selectedPanel.sidePanelBar.selectedPanel : - Firebug.chrome.selectedPanel; - - Firebug.showInfoTips = true; - if (Firebug.InfoTip) - Firebug.InfoTip.initializeBrowser(Firebug.chrome); - }, - - shutdown: function() - { - if (FBTrace.DBG_INITIALIZE) FBTrace.sysout("Firebug.Panel.shutdown", this.name); - - /// TODO: xxxpedro infoTip Hack - if (Firebug.InfoTip) - Firebug.InfoTip.uninitializeBrowser(Firebug.chrome); - - if (Firebug.chrome.largeCommandLineVisible) - Firebug.chrome.hideLargeCommandLine(); - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - if (this.hasSidePanel) - { - // TODO: xxxpedro firebug1.3a6 - // new PanelBar mechanism will need to call shutdown to hide the panels (so it - // doesn't appears in other panel's sidePanelBar. Therefore, we need to implement - // a "remember selected panel" feature in the sidePanelBar - //this.sidePanelBar.shutdown(); - } - - // store persistent state - this.lastScrollTop = this.containerNode.scrollTop; - - // xxxpedro contextMenu - removeEvent(this.containerNode, "contextmenu", this.onContextMenu); - }, - - detach: function(oldChrome, newChrome) - { - if (oldChrome && oldChrome.selectedPanel && oldChrome.selectedPanel.name == this.name) - this.lastScrollTop = oldChrome.selectedPanel.containerNode.scrollTop; - }, - - reattach: function(doc) - { - if (this.options.innerHTMLSync) - this.synchronizeUI(); - }, - - synchronizeUI: function() - { - this.containerNode.scrollTop = this.lastScrollTop || 0; - }, - - show: function(state) - { - var options = this.options; - - if (options.hasStatusBar) - { - this.statusBarBox.style.display = "inline"; - this.statusBarNode.style.display = "inline"; - } - - if (options.hasToolButtons) - { - this.toolButtonsNode.style.display = "inline"; - } - - this.panelNode.style.display = "block"; - - this.visible = true; - - if (!this.parentPanel) - Firebug.chrome.layout(this); - }, - - hide: function(state) - { - var options = this.options; - - if (options.hasStatusBar) - { - this.statusBarBox.style.display = "none"; - this.statusBarNode.style.display = "none"; - } - - if (options.hasToolButtons) - { - this.toolButtonsNode.style.display = "none"; - } - - this.panelNode.style.display = "none"; - - this.visible = false; - }, - - watchWindow: function(win) - { - }, - - unwatchWindow: function(win) - { - }, - - updateOption: function(name, value) - { - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - /** - * Toolbar helpers - */ - showToolbarButtons: function(buttonsId, show) - { - try - { - if (!this.context.browser) // XXXjjb this is bug. Somehow the panel context is not FirebugContext. - { - if (FBTrace.DBG_ERRORS) - FBTrace.sysout("firebug.Panel showToolbarButtons this.context has no browser, this:", this); - - return; - } - var buttons = this.context.browser.chrome.$(buttonsId); - if (buttons) - collapse(buttons, show ? "false" : "true"); - } - catch (exc) - { - if (FBTrace.DBG_ERRORS) - { - FBTrace.dumpProperties("firebug.Panel showToolbarButtons FAILS", exc); - if (!this.context.browser)FBTrace.dumpStack("firebug.Panel showToolbarButtons no browser"); - } - } - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - /** - * Returns a number indicating the view's ability to inspect the object. - * - * Zero means not supported, and higher numbers indicate specificity. - */ - supportsObject: function(object) - { - return 0; - }, - - hasObject: function(object) // beyond type testing, is this object selectable? - { - return false; - }, - - select: function(object, forceUpdate) - { - if (!object) - object = this.getDefaultSelection(this.context); - - if(FBTrace.DBG_PANELS) - FBTrace.sysout("firebug.select "+this.name+" forceUpdate: "+forceUpdate+" "+object+((object==this.selection)?"==":"!=")+this.selection); - - if (forceUpdate || object != this.selection) - { - this.selection = object; - this.updateSelection(object); - - // TODO: xxxpedro - // XXXjoe This is kind of cheating, but, feh. - //Firebug.chrome.onPanelSelect(object, this); - //if (uiListeners.length > 0) - // dispatch(uiListeners, "onPanelSelect", [object, this]); // TODO: make Firebug.chrome a uiListener - } - }, - - updateSelection: function(object) - { - }, - - markChange: function(skipSelf) - { - if (this.dependents) - { - if (skipSelf) - { - for (var i = 0; i < this.dependents.length; ++i) - { - var panelName = this.dependents[i]; - if (panelName != this.name) - this.context.invalidatePanels(panelName); - } - } - else - this.context.invalidatePanels.apply(this.context, this.dependents); - } - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - startInspecting: function() - { - }, - - stopInspecting: function(object, cancelled) - { - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - search: function(text, reverse) - { - }, - - /** - * Retrieves the search options that this modules supports. - * This is used by the search UI to present the proper options. - */ - getSearchOptionsMenuItems: function() - { - return [ - Firebug.Search.searchOptionMenu("search.Case Sensitive", "searchCaseSensitive") - ]; - }, - - /** - * Navigates to the next document whose match parameter returns true. - */ - navigateToNextDocument: function(match, reverse) - { - // This is an approximation of the UI that is displayed by the location - // selector. This should be close enough, although it may be better - // to simply generate the sorted list within the module, rather than - // sorting within the UI. - var self = this; - function compare(a, b) { - var locA = self.getObjectDescription(a); - var locB = self.getObjectDescription(b); - if(locA.path > locB.path) - return 1; - if(locA.path < locB.path) - return -1; - if(locA.name > locB.name) - return 1; - if(locA.name < locB.name) - return -1; - return 0; - } - var allLocs = this.getLocationList().sort(compare); - for (var curPos = 0; curPos < allLocs.length && allLocs[curPos] != this.location; curPos++); - - function transformIndex(index) { - if (reverse) { - // For the reverse case we need to implement wrap around. - var intermediate = curPos - index - 1; - return (intermediate < 0 ? allLocs.length : 0) + intermediate; - } else { - return (curPos + index + 1) % allLocs.length; - } - }; - - for (var next = 0; next < allLocs.length - 1; next++) - { - var object = allLocs[transformIndex(next)]; - - if (match(object)) - { - this.navigate(object); - return object; - } - } - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - // Called when "Options" clicked. Return array of - // {label: 'name', nol10n: true, type: "checkbox", checked: <value>, command:function to set <value>} - getOptionsMenuItems: function() - { - return null; - }, - - /* - * Called by chrome.onContextMenu to build the context menu when this panel has focus. - * See also FirebugRep for a similar function also called by onContextMenu - * Extensions may monkey patch and chain off this call - * @param object: the 'realObject', a model value, eg a DOM property - * @param target: the HTML element clicked on. - * @return an array of menu items. - */ - getContextMenuItems: function(object, target) - { - return []; - }, - - getBreakOnMenuItems: function() - { - return []; - }, - - getEditor: function(target, value) - { - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - getDefaultSelection: function() - { - return null; - }, - - browseObject: function(object) - { - }, - - getPopupObject: function(target) - { - return Firebug.getRepObject(target); - }, - - getTooltipObject: function(target) - { - return Firebug.getRepObject(target); - }, - - showInfoTip: function(infoTip, x, y) - { - - }, - - getObjectPath: function(object) - { - return null; - }, - - // An array of objects that can be passed to getObjectLocation. - // The list of things a panel can show, eg sourceFiles. - // Only shown if panel.location defined and supportsObject true - getLocationList: function() - { - return null; - }, - - getDefaultLocation: function() - { - return null; - }, - - getObjectLocation: function(object) - { - return ""; - }, - - // Text for the location list menu eg script panel source file list - // return.path: group/category label, return.name: item label - getObjectDescription: function(object) - { - var url = this.getObjectLocation(object); - return FBL.splitURLBase(url); - }, - - /* - * UI signal that a tab needs attention, eg Script panel is currently stopped on a breakpoint - * @param: show boolean, true turns on. - */ - highlight: function(show) - { - var tab = this.getTab(); - if (!tab) - return; - - if (show) - tab.setAttribute("highlight", "true"); - else - tab.removeAttribute("highlight"); - }, - - getTab: function() - { - var chrome = Firebug.chrome; - - var tab = chrome.$("fbPanelBar2").getTab(this.name); - if (!tab) - tab = chrome.$("fbPanelBar1").getTab(this.name); - return tab; - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // Support for Break On Next - - /** - * Called by the framework when the user clicks on the Break On Next button. - * @param {Boolean} armed Set to true if the Break On Next feature is - * to be armed for action and set to false if the Break On Next should be disarmed. - * If 'armed' is true, then the next call to shouldBreakOnNext should be |true|. - */ - breakOnNext: function(armed) - { - }, - - /** - * Called when a panel is selected/displayed. The method should return true - * if the Break On Next feature is currently armed for this panel. - */ - shouldBreakOnNext: function() - { - return false; - }, - - /** - * Returns labels for Break On Next tooltip (one for enabled and one for disabled state). - * @param {Boolean} enabled Set to true if the Break On Next feature is - * currently activated for this panel. - */ - getBreakOnNextTooltip: function(enabled) - { - return null; - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - // xxxpedro contextMenu - onContextMenu: function(event) - { - if (!this.getContextMenuItems) - return; - - cancelEvent(event, true); - - var target = event.target || event.srcElement; - - var menu = this.getContextMenuItems(this.selection, target); - if (!menu) - return; - - var contextMenu = new Menu( - { - id: "fbPanelContextMenu", - - items: menu - }); - - contextMenu.show(event.clientX, event.clientY); - - return true; - - /* - // TODO: xxxpedro move code to somewhere. code to get cross-browser - // window to screen coordinates - var box = Firebug.browser.getElementPosition(Firebug.chrome.node); - - var screenY = 0; - - // Firefox - if (typeof window.mozInnerScreenY != "undefined") - { - screenY = window.mozInnerScreenY; - } - // Chrome - else if (typeof window.innerHeight != "undefined") - { - screenY = window.outerHeight - window.innerHeight; - } - // IE - else if (typeof window.screenTop != "undefined") - { - screenY = window.screenTop; - } - - contextMenu.show(event.screenX-box.left, event.screenY-screenY-box.top); - /**/ - } - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -}; - - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - -/** - * MeasureBox - * To get pixels size.width and size.height: - * <ul><li> this.startMeasuring(view); </li> - * <li> var size = this.measureText(lineNoCharsSpacer); </li> - * <li> this.stopMeasuring(); </li> - * </ul> - * - * @namespace - */ -Firebug.MeasureBox = -{ - startMeasuring: function(target) - { - if (!this.measureBox) - { - this.measureBox = target.ownerDocument.createElement("span"); - this.measureBox.className = "measureBox"; - } - - copyTextStyles(target, this.measureBox); - target.ownerDocument.body.appendChild(this.measureBox); - }, - - getMeasuringElement: function() - { - return this.measureBox; - }, - - measureText: function(value) - { - this.measureBox.innerHTML = value ? escapeForSourceLine(value) : "m"; - return {width: this.measureBox.offsetWidth, height: this.measureBox.offsetHeight-1}; - }, - - measureInputText: function(value) - { - value = value ? escapeForTextNode(value) : "m"; - if (!Firebug.showTextNodesWithWhitespace) - value = value.replace(/\t/g,'mmmmmm').replace(/\ /g,'m'); - this.measureBox.innerHTML = value; - return {width: this.measureBox.offsetWidth, height: this.measureBox.offsetHeight-1}; - }, - - getBox: function(target) - { - var style = this.measureBox.ownerDocument.defaultView.getComputedStyle(this.measureBox, ""); - var box = getBoxFromStyles(style, this.measureBox); - return box; - }, - - stopMeasuring: function() - { - this.measureBox.parentNode.removeChild(this.measureBox); - } -}; - - -// ************************************************************************************************ -if (FBL.domplate) Firebug.Rep = domplate( -{ - className: "", - inspectable: true, - - supportsObject: function(object, type) - { - return false; - }, - - inspectObject: function(object, context) - { - Firebug.chrome.select(object); - }, - - browseObject: function(object, context) - { - }, - - persistObject: function(object, context) - { - }, - - getRealObject: function(object, context) - { - return object; - }, - - getTitle: function(object) - { - var label = safeToString(object); - - var re = /\[object (.*?)\]/; - var m = re.exec(label); - - ///return m ? m[1] : label; - - // if the label is in the "[object TYPE]" format return its type - if (m) - { - return m[1]; - } - // if it is IE we need to handle some special cases - else if ( - // safeToString() fails to recognize some objects in IE - isIE && - // safeToString() returns "[object]" for some objects like window.Image - (label == "[object]" || - // safeToString() returns undefined for some objects like window.clientInformation - typeof object == "object" && typeof label == "undefined") - ) - { - return "Object"; - } - else - { - return label; - } - }, - - getTooltip: function(object) - { - return null; - }, - - getContextMenuItems: function(object, target, context) - { - return []; - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // Convenience for domplates - - STR: function(name) - { - return $STR(name); - }, - - cropString: function(text) - { - return cropString(text); - }, - - cropMultipleLines: function(text, limit) - { - return cropMultipleLines(text, limit); - }, - - toLowerCase: function(text) - { - return text ? text.toLowerCase() : text; - }, - - plural: function(n) - { - return n == 1 ? "" : "s"; - } -}); - -// ************************************************************************************************ - - -// ************************************************************************************************ -}}); - -/* See license.txt for terms of usage */ - -FBL.ns( /** @scope s_gui */ function() { with (FBL) { -// ************************************************************************************************ - -// ************************************************************************************************ -// Controller - -/**@namespace*/ -FBL.Controller = { - - controllers: null, - controllerContext: null, - - initialize: function(context) - { - this.controllers = []; - this.controllerContext = context || Firebug.chrome; - }, - - shutdown: function() - { - this.removeControllers(); - - //this.controllers = null; - //this.controllerContext = null; - }, - - addController: function() - { - for (var i=0, arg; arg=arguments[i]; i++) - { - // If the first argument is a string, make a selector query - // within the controller node context - if (typeof arg[0] == "string") - { - arg[0] = $$(arg[0], this.controllerContext); - } - - // bind the handler to the proper context - var handler = arg[2]; - arg[2] = bind(handler, this); - // save the original handler as an extra-argument, so we can - // look for it later, when removing a particular controller - arg[3] = handler; - - this.controllers.push(arg); - addEvent.apply(this, arg); - } - }, - - removeController: function() - { - for (var i=0, arg; arg=arguments[i]; i++) - { - for (var j=0, c; c=this.controllers[j]; j++) - { - if (arg[0] == c[0] && arg[1] == c[1] && arg[2] == c[3]) - removeEvent.apply(this, c); - } - } - }, - - removeControllers: function() - { - for (var i=0, c; c=this.controllers[i]; i++) - { - removeEvent.apply(this, c); - } - } -}; - - -// ************************************************************************************************ -// PanelBar - -/**@namespace*/ -FBL.PanelBar = -{ - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - panelMap: null, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - selectedPanel: null, - parentPanelName: null, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - create: function(ownerPanel) - { - this.panelMap = {}; - this.ownerPanel = ownerPanel; - - if (ownerPanel) - { - ownerPanel.sidePanelBarNode = createElement("span"); - ownerPanel.sidePanelBarNode.style.display = "none"; - ownerPanel.sidePanelBarBoxNode.appendChild(ownerPanel.sidePanelBarNode); - } - - var panels = Firebug.panelTypes; - for (var i=0, p; p=panels[i]; i++) - { - if ( // normal Panel of the Chrome's PanelBar - !ownerPanel && !p.prototype.parentPanel || - // Child Panel of the current Panel's SidePanelBar - ownerPanel && p.prototype.parentPanel && - ownerPanel.name == p.prototype.parentPanel) - { - this.addPanel(p.prototype.name); - } - } - }, - - destroy: function() - { - PanelBar.shutdown.call(this); - - for (var name in this.panelMap) - { - this.removePanel(name); - - var panel = this.panelMap[name]; - panel.destroy(); - - this.panelMap[name] = null; - delete this.panelMap[name]; - } - - this.panelMap = null; - this.ownerPanel = null; - }, - - initialize: function() - { - if (this.ownerPanel) - this.ownerPanel.sidePanelBarNode.style.display = "inline"; - - for(var name in this.panelMap) - { - (function(self, name){ - - // tab click handler - var onTabClick = function onTabClick() - { - self.selectPanel(name); - return false; - }; - - Firebug.chrome.addController([self.panelMap[name].tabNode, "mousedown", onTabClick]); - - })(this, name); - } - }, - - shutdown: function() - { - var selectedPanel = this.selectedPanel; - - if (selectedPanel) - { - removeClass(selectedPanel.tabNode, "fbSelectedTab"); - selectedPanel.hide(); - selectedPanel.shutdown(); - } - - if (this.ownerPanel) - this.ownerPanel.sidePanelBarNode.style.display = "none"; - - this.selectedPanel = null; - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - addPanel: function(panelName, parentPanel) - { - var PanelType = Firebug.panelTypeMap[panelName]; - var panel = this.panelMap[panelName] = new PanelType(); - - panel.create(); - }, - - removePanel: function(panelName) - { - var panel = this.panelMap[panelName]; - if (panel.hasOwnProperty(panelName)) - panel.destroy(); - }, - - selectPanel: function(panelName) - { - var selectedPanel = this.selectedPanel; - var panel = this.panelMap[panelName]; - - if (panel && selectedPanel != panel) - { - if (selectedPanel) - { - removeClass(selectedPanel.tabNode, "fbSelectedTab"); - selectedPanel.shutdown(); - selectedPanel.hide(); - } - - if (!panel.parentPanel) - Firebug.context.persistedState.selectedPanelName = panelName; - - this.selectedPanel = panel; - - setClass(panel.tabNode, "fbSelectedTab"); - panel.show(); - panel.initialize(); - } - }, - - getPanel: function(panelName) - { - var panel = this.panelMap[panelName]; - - return panel; - } - -}; - -//************************************************************************************************ -// Button - -/** - * options.element - * options.caption - * options.title - * - * options.owner - * options.className - * options.pressedClassName - * - * options.onPress - * options.onUnpress - * options.onClick - * - * @class - * @extends FBL.Controller - * - */ - -FBL.Button = function(options) -{ - options = options || {}; - - append(this, options); - - this.state = "unpressed"; - this.display = "unpressed"; - - if (this.element) - { - this.container = this.element.parentNode; - } - else - { - this.shouldDestroy = true; - - this.container = this.owner.getPanel().toolButtonsNode; - - this.element = createElement("a", { - className: this.baseClassName + " " + this.className + " fbHover", - innerHTML: this.caption - }); - - if (this.title) - this.element.title = this.title; - - this.container.appendChild(this.element); - } -}; - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - -Button.prototype = extend(Controller, -/**@extend FBL.Button.prototype*/ -{ - type: "normal", - caption: "caption", - title: null, - - className: "", // custom class - baseClassName: "fbButton", // control class - pressedClassName: "fbBtnPressed", // control pressed class - - element: null, - container: null, - owner: null, - - state: null, - display: null, - - destroy: function() - { - this.shutdown(); - - // only remove if it is a dynamically generated button (not pre-rendered) - if (this.shouldDestroy) - this.container.removeChild(this.element); - - this.element = null; - this.container = null; - this.owner = null; - }, - - initialize: function() - { - Controller.initialize.apply(this); - - var element = this.element; - - this.addController([element, "mousedown", this.handlePress]); - - if (this.type == "normal") - this.addController( - [element, "mouseup", this.handleUnpress], - [element, "mouseout", this.handleUnpress], - [element, "click", this.handleClick] - ); - }, - - shutdown: function() - { - Controller.shutdown.apply(this); - }, - - restore: function() - { - this.changeState("unpressed"); - }, - - changeState: function(state) - { - this.state = state; - this.changeDisplay(state); - }, - - changeDisplay: function(display) - { - if (display != this.display) - { - if (display == "pressed") - { - setClass(this.element, this.pressedClassName); - } - else if (display == "unpressed") - { - removeClass(this.element, this.pressedClassName); - } - this.display = display; - } - }, - - handlePress: function(event) - { - cancelEvent(event, true); - - if (this.type == "normal") - { - this.changeDisplay("pressed"); - this.beforeClick = true; - } - else if (this.type == "toggle") - { - if (this.state == "pressed") - { - this.changeState("unpressed"); - - if (this.onUnpress) - this.onUnpress.apply(this.owner, arguments); - } - else - { - this.changeState("pressed"); - - if (this.onPress) - this.onPress.apply(this.owner, arguments); - } - - if (this.onClick) - this.onClick.apply(this.owner, arguments); - } - - return false; - }, - - handleUnpress: function(event) - { - cancelEvent(event, true); - - if (this.beforeClick) - this.changeDisplay("unpressed"); - - return false; - }, - - handleClick: function(event) - { - cancelEvent(event, true); - - if (this.type == "normal") - { - if (this.onClick) - this.onClick.apply(this.owner); - - this.changeState("unpressed"); - } - - this.beforeClick = false; - - return false; - } -}); - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - -/** - * @class - * @extends FBL.Button - */ -FBL.IconButton = function() -{ - Button.apply(this, arguments); -}; - -IconButton.prototype = extend(Button.prototype, -/**@extend FBL.IconButton.prototype*/ -{ - baseClassName: "fbIconButton", - pressedClassName: "fbIconPressed" -}); - - -//************************************************************************************************ -// Menu - -var menuItemProps = {"class": "$item.className", type: "$item.type", value: "$item.value", - _command: "$item.command"}; - -if (isIE6) - menuItemProps.href = "javascript:void(0)"; - -// Allow GUI to be loaded even when Domplate module is not installed. -if (FBL.domplate) -var MenuPlate = domplate(Firebug.Rep, -{ - tag: - DIV({"class": "fbMenu fbShadow"}, - DIV({"class": "fbMenuContent fbShadowContent"}, - FOR("item", "$object.items|memberIterator", - TAG("$item.tag", {item: "$item"}) - ) - ) - ), - - itemTag: - A(menuItemProps, - "$item.label" - ), - - checkBoxTag: - A(extend(menuItemProps, {checked : "$item.checked"}), - - "$item.label" - ), - - radioButtonTag: - A(extend(menuItemProps, {selected : "$item.selected"}), - - "$item.label" - ), - - groupTag: - A(extend(menuItemProps, {child: "$item.child"}), - "$item.label" - ), - - shortcutTag: - A(menuItemProps, - "$item.label", - SPAN({"class": "fbMenuShortcutKey"}, - "$item.key" - ) - ), - - separatorTag: - SPAN({"class": "fbMenuSeparator"}), - - memberIterator: function(items) - { - var result = []; - - for (var i=0, length=items.length; i<length; i++) - { - var item = items[i]; - - // separator representation - if (typeof item == "string" && item.indexOf("-") == 0) - { - result.push({tag: this.separatorTag}); - continue; - } - - item = extend(item, {}); - - item.type = item.type || ""; - item.value = item.value || ""; - - var type = item.type; - - // default item representation - item.tag = this.itemTag; - - var className = item.className || ""; - - className += "fbMenuOption fbHover "; - - // specific representations - if (type == "checkbox") - { - className += "fbMenuCheckBox "; - item.tag = this.checkBoxTag; - } - else if (type == "radiobutton") - { - className += "fbMenuRadioButton "; - item.tag = this.radioButtonTag; - } - else if (type == "group") - { - className += "fbMenuGroup "; - item.tag = this.groupTag; - } - else if (type == "shortcut") - { - className += "fbMenuShortcut "; - item.tag = this.shortcutTag; - } - - if (item.checked) - className += "fbMenuChecked "; - else if (item.selected) - className += "fbMenuRadioSelected "; - - if (item.disabled) - className += "fbMenuDisabled "; - - item.className = className; - - item.label = $STR(item.label); - - result.push(item); - } - - return result; - } -}); - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - -/** - * options - * options.element - * options.id - * options.items - * - * item.label - * item.className - * item.type - * item.value - * item.disabled - * item.checked - * item.selected - * item.command - * item.child - * - * - * @class - * @extends FBL.Controller - * - */ -FBL.Menu = function(options) -{ - // if element is not pre-rendered, we must render it now - if (!options.element) - { - if (options.getItems) - options.items = options.getItems(); - - options.element = MenuPlate.tag.append( - {object: options}, - getElementByClass(Firebug.chrome.document, "fbBody"), - MenuPlate - ); - } - - // extend itself with the provided options - append(this, options); - - if (typeof this.element == "string") - { - this.id = this.element; - this.element = $(this.id); - } - else if (this.id) - { - this.element.id = this.id; - } - - this.element.firebugIgnore = true; - this.elementStyle = this.element.style; - - this.isVisible = false; - - this.handleMouseDown = bind(this.handleMouseDown, this); - this.handleMouseOver = bind(this.handleMouseOver, this); - this.handleMouseOut = bind(this.handleMouseOut, this); - - this.handleWindowMouseDown = bind(this.handleWindowMouseDown, this); -}; - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - -var menuMap = {}; - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - -Menu.prototype = extend(Controller, -/**@extend FBL.Menu.prototype*/ -{ - destroy: function() - { - //if (this.element) console.log("destroy", this.element.id); - - this.hide(); - - // if it is a childMenu, remove its reference from the parentMenu - if (this.parentMenu) - this.parentMenu.childMenu = null; - - // remove the element from the document - this.element.parentNode.removeChild(this.element); - - // clear references - this.element = null; - this.elementStyle = null; - this.parentMenu = null; - this.parentTarget = null; - }, - - initialize: function() - { - Controller.initialize.call(this); - - this.addController( - [this.element, "mousedown", this.handleMouseDown], - [this.element, "mouseover", this.handleMouseOver] - ); - }, - - shutdown: function() - { - Controller.shutdown.call(this); - }, - - show: function(x, y) - { - this.initialize(); - - if (this.isVisible) return; - - //console.log("show", this.element.id); - - x = x || 0; - y = y || 0; - - if (this.parentMenu) - { - var oldChildMenu = this.parentMenu.childMenu; - if (oldChildMenu && oldChildMenu != this) - { - oldChildMenu.destroy(); - } - - this.parentMenu.childMenu = this; - } - else - addEvent(Firebug.chrome.document, "mousedown", this.handleWindowMouseDown); - - this.elementStyle.display = "block"; - this.elementStyle.visibility = "hidden"; - - var size = Firebug.chrome.getSize(); - - x = Math.min(x, size.width - this.element.clientWidth - 10); - x = Math.max(x, 0); - - y = Math.min(y, size.height - this.element.clientHeight - 10); - y = Math.max(y, 0); - - this.elementStyle.left = x + "px"; - this.elementStyle.top = y + "px"; - - this.elementStyle.visibility = "visible"; - - this.isVisible = true; - - if (isFunction(this.onShow)) - this.onShow.apply(this, arguments); - }, - - hide: function() - { - this.clearHideTimeout(); - this.clearShowChildTimeout(); - - if (!this.isVisible) return; - - //console.log("hide", this.element.id); - - this.elementStyle.display = "none"; - - if(this.childMenu) - { - this.childMenu.destroy(); - this.childMenu = null; - } - - if(this.parentTarget) - removeClass(this.parentTarget, "fbMenuGroupSelected"); - - this.isVisible = false; - - this.shutdown(); - - if (isFunction(this.onHide)) - this.onHide.apply(this, arguments); - }, - - showChildMenu: function(target) - { - var id = target.getAttribute("child"); - - var parent = this; - var target = target; - - this.showChildTimeout = Firebug.chrome.window.setTimeout(function(){ - - //if (!parent.isVisible) return; - - var box = Firebug.chrome.getElementBox(target); - - var childMenuObject = menuMap.hasOwnProperty(id) ? - menuMap[id] : {element: $(id)}; - - var childMenu = new Menu(extend(childMenuObject, - { - parentMenu: parent, - parentTarget: target - })); - - var offsetLeft = isIE6 ? -1 : -6; // IE6 problem with fixed position - childMenu.show(box.left + box.width + offsetLeft, box.top -6); - setClass(target, "fbMenuGroupSelected"); - - },350); - }, - - clearHideTimeout: function() - { - if (this.hideTimeout) - { - Firebug.chrome.window.clearTimeout(this.hideTimeout); - delete this.hideTimeout; - } - }, - - clearShowChildTimeout: function() - { - if(this.showChildTimeout) - { - Firebug.chrome.window.clearTimeout(this.showChildTimeout); - this.showChildTimeout = null; - } - }, - - handleMouseDown: function(event) - { - cancelEvent(event, true); - - var topParent = this; - while (topParent.parentMenu) - topParent = topParent.parentMenu; - - var target = event.target || event.srcElement; - - target = getAncestorByClass(target, "fbMenuOption"); - - if(!target || hasClass(target, "fbMenuGroup")) - return false; - - if (target && !hasClass(target, "fbMenuDisabled")) - { - var type = target.getAttribute("type"); - - if (type == "checkbox") - { - var checked = target.getAttribute("checked"); - var value = target.getAttribute("value"); - var wasChecked = hasClass(target, "fbMenuChecked"); - - if (wasChecked) - { - removeClass(target, "fbMenuChecked"); - target.setAttribute("checked", ""); - } - else - { - setClass(target, "fbMenuChecked"); - target.setAttribute("checked", "true"); - } - - if (isFunction(this.onCheck)) - this.onCheck.call(this, target, value, !wasChecked); - } - - if (type == "radiobutton") - { - var selectedRadios = getElementsByClass(target.parentNode, "fbMenuRadioSelected"); - - var group = target.getAttribute("group"); - - for (var i = 0, length = selectedRadios.length; i < length; i++) - { - radio = selectedRadios[i]; - - if (radio.getAttribute("group") == group) - { - removeClass(radio, "fbMenuRadioSelected"); - radio.setAttribute("selected", ""); - } - } - - setClass(target, "fbMenuRadioSelected"); - target.setAttribute("selected", "true"); - } - - var handler = null; - - // target.command can be a function or a string. - var cmd = target.command; - - // If it is a function it will be used as the handler - if (isFunction(cmd)) - handler = cmd; - // If it is a string it the property of the current menu object - // will be used as the handler - else if (typeof cmd == "string") - handler = this[cmd]; - - var closeMenu = true; - - if (handler) - closeMenu = handler.call(this, target) !== false; - - if (closeMenu) - topParent.hide(); - } - - return false; - }, - - handleWindowMouseDown: function(event) - { - //console.log("handleWindowMouseDown"); - - var target = event.target || event.srcElement; - - target = getAncestorByClass(target, "fbMenu"); - - if (!target) - { - removeEvent(Firebug.chrome.document, "mousedown", this.handleWindowMouseDown); - this.hide(); - } - }, - - handleMouseOver: function(event) - { - //console.log("handleMouseOver", this.element.id); - - this.clearHideTimeout(); - this.clearShowChildTimeout(); - - var target = event.target || event.srcElement; - - target = getAncestorByClass(target, "fbMenuOption"); - - if(!target) - return; - - var childMenu = this.childMenu; - if(childMenu) - { - removeClass(childMenu.parentTarget, "fbMenuGroupSelected"); - - if (childMenu.parentTarget != target && childMenu.isVisible) - { - childMenu.clearHideTimeout(); - childMenu.hideTimeout = Firebug.chrome.window.setTimeout(function(){ - childMenu.destroy(); - },300); - } - } - - if(hasClass(target, "fbMenuGroup")) - { - this.showChildMenu(target); - } - } -}); - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - -append(Menu, -/**@extend FBL.Menu*/ -{ - register: function(object) - { - menuMap[object.id] = object; - }, - - check: function(element) - { - setClass(element, "fbMenuChecked"); - element.setAttribute("checked", "true"); - }, - - uncheck: function(element) - { - removeClass(element, "fbMenuChecked"); - element.setAttribute("checked", ""); - }, - - disable: function(element) - { - setClass(element, "fbMenuDisabled"); - }, - - enable: function(element) - { - removeClass(element, "fbMenuDisabled"); - } -}); - - -//************************************************************************************************ -// Status Bar - -/**@class*/ -function StatusBar(){}; - -StatusBar.prototype = extend(Controller, { - -}); - -// ************************************************************************************************ - - -// ************************************************************************************************ -}}); - -/* See license.txt for terms of usage */ - -FBL.ns( /**@scope s_context*/ function() { with (FBL) { -// ************************************************************************************************ - -// ************************************************************************************************ -// Globals - -var refreshDelay = 300; - -// Opera and some versions of webkit returns the wrong value of document.elementFromPoint() -// function, without taking into account the scroll position. Safari 4 (webkit/531.21.8) -// still have this issue. Google Chrome 4 (webkit/532.5) does not. So, we're assuming this -// issue was fixed in the 532 version -var shouldFixElementFromPoint = isOpera || isSafari && browserVersion < "532"; - -var evalError = "___firebug_evaluation_error___"; -var pixelsPerInch; - -var resetStyle = "margin:0; padding:0; border:0; position:absolute; overflow:hidden; display:block;"; -var offscreenStyle = resetStyle + "top:-1234px; left:-1234px;"; - - -// ************************************************************************************************ -// Context - -/** @class */ -FBL.Context = function(win) -{ - this.window = win.window; - this.document = win.document; - - this.browser = Env.browser; - - // Some windows in IE, like iframe, doesn't have the eval() method - if (isIE && !this.window.eval) - { - // But after executing the following line the method magically appears! - this.window.execScript("null"); - // Just to make sure the "magic" really happened - if (!this.window.eval) - throw new Error("Firebug Error: eval() method not found in this window"); - } - - // Create a new "black-box" eval() method that runs in the global namespace - // of the context window, without exposing the local variables declared - // by the function that calls it - this.eval = this.window.eval("new Function('" + - "try{ return window.eval.apply(window,arguments) }catch(E){ E."+evalError+"=true; return E }" + - "')"); -}; - -FBL.Context.prototype = -{ - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // partial-port of Firebug tabContext.js - - browser: null, - loaded: true, - - setTimeout: function(fn, delay) - { - var win = this.window; - - if (win.setTimeout == this.setTimeout) - throw new Error("setTimeout recursion"); - - var timeout = win.setTimeout.apply ? // IE doesn't have apply method on setTimeout - win.setTimeout.apply(win, arguments) : - win.setTimeout(fn, delay); - - if (!this.timeouts) - this.timeouts = {}; - - this.timeouts[timeout] = 1; - - return timeout; - }, - - clearTimeout: function(timeout) - { - clearTimeout(timeout); - - if (this.timeouts) - delete this.timeouts[timeout]; - }, - - setInterval: function(fn, delay) - { - var win = this.window; - - var timeout = win.setInterval.apply ? // IE doesn't have apply method on setTimeout - win.setInterval.apply(win, arguments) : - win.setInterval(fn, delay); - - if (!this.intervals) - this.intervals = {}; - - this.intervals[timeout] = 1; - - return timeout; - }, - - clearInterval: function(timeout) - { - clearInterval(timeout); - - if (this.intervals) - delete this.intervals[timeout]; - }, - - invalidatePanels: function() - { - if (!this.invalidPanels) - this.invalidPanels = {}; - - for (var i = 0; i < arguments.length; ++i) - { - var panelName = arguments[i]; - - // avoid error. need to create a better getPanel() function as explained below - if (!Firebug.chrome || !Firebug.chrome.selectedPanel) - return; - - //var panel = this.getPanel(panelName, true); - //TODO: xxxpedro context how to get all panels using a single function? - // the current workaround to make the invalidation works is invalidating - // only sidePanels. There's also a problem with panel name (LowerCase in Firebug Lite) - var panel = Firebug.chrome.selectedPanel.sidePanelBar ? - Firebug.chrome.selectedPanel.sidePanelBar.getPanel(panelName, true) : - null; - - if (panel && !panel.noRefresh) - this.invalidPanels[panelName] = 1; - } - - if (this.refreshTimeout) - { - this.clearTimeout(this.refreshTimeout); - delete this.refreshTimeout; - } - - this.refreshTimeout = this.setTimeout(bindFixed(function() - { - var invalids = []; - - for (var panelName in this.invalidPanels) - { - //var panel = this.getPanel(panelName, true); - //TODO: xxxpedro context how to get all panels using a single function? - // the current workaround to make the invalidation works is invalidating - // only sidePanels. There's also a problem with panel name (LowerCase in Firebug Lite) - var panel = Firebug.chrome.selectedPanel.sidePanelBar ? - Firebug.chrome.selectedPanel.sidePanelBar.getPanel(panelName, true) : - null; - - if (panel) - { - if (panel.visible && !panel.editing) - panel.refresh(); - else - panel.needsRefresh = true; - - // If the panel is being edited, we'll keep trying to - // refresh it until editing is done - if (panel.editing) - invalids.push(panelName); - } - } - - delete this.invalidPanels; - delete this.refreshTimeout; - - // Keep looping until every tab is valid - if (invalids.length) - this.invalidatePanels.apply(this, invalids); - }, this), refreshDelay); - }, - - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // Evalutation Method - - /** - * Evaluates an expression in the current context window. - * - * @param {String} expr expression to be evaluated - * - * @param {String} context string indicating the global location - * of the object that will be used as the - * context. The context is referred in - * the expression as the "this" keyword. - * If no context is informed, the "window" - * context is used. - * - * @param {String} api string indicating the global location - * of the object that will be used as the - * api of the evaluation. - * - * @param {Function} errorHandler(message) error handler to be called - * if the evaluation fails. - */ - evaluate: function(expr, context, api, errorHandler) - { - // the default context is the "window" object. It can be any string that represents - // a global accessible element as: "my.namespaced.object" - context = context || "window"; - - var isObjectLiteral = trim(expr).indexOf("{") == 0, - cmd, - result; - - // if the context is the "window" object, we don't need a closure - if (context == "window") - { - // If it is an object literal, then wrap the expression with parenthesis so we can - // capture the return value - if (isObjectLiteral) - { - cmd = api ? - "with("+api+"){ ("+expr+") }" : - "(" + expr + ")"; - } - else - { - cmd = api ? - "with("+api+"){ "+expr+" }" : - expr; - } - } - else - { - cmd = api ? - // with API and context, no return value - "(function(arguments){ with(" + api + "){ " + - expr + - " } }).call(" + context + ",undefined)" - : - // with context only, no return value - "(function(arguments){ " + - expr + - " }).call(" + context + ",undefined)"; - } - - result = this.eval(cmd); - - if (result && result[evalError]) - { - var msg = result.name ? (result.name + ": ") : ""; - msg += result.message || result; - - if (errorHandler) - result = errorHandler(msg); - else - result = msg; - } - - return result; - }, - - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // Window Methods - - getWindowSize: function() - { - var width=0, height=0, el; - - if (typeof this.window.innerWidth == "number") - { - width = this.window.innerWidth; - height = this.window.innerHeight; - } - else if ((el=this.document.documentElement) && (el.clientHeight || el.clientWidth)) - { - width = el.clientWidth; - height = el.clientHeight; - } - else if ((el=this.document.body) && (el.clientHeight || el.clientWidth)) - { - width = el.clientWidth; - height = el.clientHeight; - } - - return {width: width, height: height}; - }, - - getWindowScrollSize: function() - { - var width=0, height=0, el; - - // first try the document.documentElement scroll size - if (!isIEQuiksMode && (el=this.document.documentElement) && - (el.scrollHeight || el.scrollWidth)) - { - width = el.scrollWidth; - height = el.scrollHeight; - } - - // then we need to check if document.body has a bigger scroll size value - // because sometimes depending on the browser and the page, the document.body - // scroll size returns a smaller (and wrong) measure - if ((el=this.document.body) && (el.scrollHeight || el.scrollWidth) && - (el.scrollWidth > width || el.scrollHeight > height)) - { - width = el.scrollWidth; - height = el.scrollHeight; - } - - return {width: width, height: height}; - }, - - getWindowScrollPosition: function() - { - var top=0, left=0, el; - - if(typeof this.window.pageYOffset == "number") - { - top = this.window.pageYOffset; - left = this.window.pageXOffset; - } - else if((el=this.document.body) && (el.scrollTop || el.scrollLeft)) - { - top = el.scrollTop; - left = el.scrollLeft; - } - else if((el=this.document.documentElement) && (el.scrollTop || el.scrollLeft)) - { - top = el.scrollTop; - left = el.scrollLeft; - } - - return {top:top, left:left}; - }, - - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // Element Methods - - getElementFromPoint: function(x, y) - { - if (shouldFixElementFromPoint) - { - var scroll = this.getWindowScrollPosition(); - return this.document.elementFromPoint(x + scroll.left, y + scroll.top); - } - else - return this.document.elementFromPoint(x, y); - }, - - getElementPosition: function(el) - { - var left = 0; - var top = 0; - - do - { - left += el.offsetLeft; - top += el.offsetTop; - } - while (el = el.offsetParent); - - return {left:left, top:top}; - }, - - getElementBox: function(el) - { - var result = {}; - - if (el.getBoundingClientRect) - { - var rect = el.getBoundingClientRect(); - - // fix IE problem with offset when not in fullscreen mode - var offset = isIE ? this.document.body.clientTop || this.document.documentElement.clientTop: 0; - - var scroll = this.getWindowScrollPosition(); - - result.top = Math.round(rect.top - offset + scroll.top); - result.left = Math.round(rect.left - offset + scroll.left); - result.height = Math.round(rect.bottom - rect.top); - result.width = Math.round(rect.right - rect.left); - } - else - { - var position = this.getElementPosition(el); - - result.top = position.top; - result.left = position.left; - result.height = el.offsetHeight; - result.width = el.offsetWidth; - } - - return result; - }, - - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // Measurement Methods - - getMeasurement: function(el, name) - { - var result = {value: 0, unit: "px"}; - - var cssValue = this.getStyle(el, name); - - if (!cssValue) return result; - if (cssValue.toLowerCase() == "auto") return result; - - var reMeasure = /(\d+\.?\d*)(.*)/; - var m = cssValue.match(reMeasure); - - if (m) - { - result.value = m[1]-0; - result.unit = m[2].toLowerCase(); - } - - return result; - }, - - getMeasurementInPixels: function(el, name) - { - if (!el) return null; - - var m = this.getMeasurement(el, name); - var value = m.value; - var unit = m.unit; - - if (unit == "px") - return value; - - else if (unit == "pt") - return this.pointsToPixels(name, value); - - else if (unit == "em") - return this.emToPixels(el, value); - - else if (unit == "%") - return this.percentToPixels(el, value); - - else if (unit == "ex") - return this.exToPixels(el, value); - - // TODO: add other units. Maybe create a better general way - // to calculate measurements in different units. - }, - - getMeasurementBox1: function(el, name) - { - var sufixes = ["Top", "Left", "Bottom", "Right"]; - var result = []; - - for(var i=0, sufix; sufix=sufixes[i]; i++) - result[i] = Math.round(this.getMeasurementInPixels(el, name + sufix)); - - return {top:result[0], left:result[1], bottom:result[2], right:result[3]}; - }, - - getMeasurementBox: function(el, name) - { - var result = []; - var sufixes = name == "border" ? - ["TopWidth", "LeftWidth", "BottomWidth", "RightWidth"] : - ["Top", "Left", "Bottom", "Right"]; - - if (isIE) - { - var propName, cssValue; - var autoMargin = null; - - for(var i=0, sufix; sufix=sufixes[i]; i++) - { - propName = name + sufix; - - cssValue = el.currentStyle[propName] || el.style[propName]; - - if (cssValue == "auto") - { - if (!autoMargin) - autoMargin = this.getCSSAutoMarginBox(el); - - result[i] = autoMargin[sufix.toLowerCase()]; - } - else - result[i] = this.getMeasurementInPixels(el, propName); - - } - - } - else - { - for(var i=0, sufix; sufix=sufixes[i]; i++) - result[i] = this.getMeasurementInPixels(el, name + sufix); - } - - return {top:result[0], left:result[1], bottom:result[2], right:result[3]}; - }, - - getCSSAutoMarginBox: function(el) - { - if (isIE && " meta title input script link a ".indexOf(" "+el.nodeName.toLowerCase()+" ") != -1) - return {top:0, left:0, bottom:0, right:0}; - /**/ - - if (isIE && " h1 h2 h3 h4 h5 h6 h7 ul p ".indexOf(" "+el.nodeName.toLowerCase()+" ") == -1) - return {top:0, left:0, bottom:0, right:0}; - /**/ - - var offsetTop = 0; - if (false && isIEStantandMode) - { - var scrollSize = Firebug.browser.getWindowScrollSize(); - offsetTop = scrollSize.height; - } - - var box = this.document.createElement("div"); - //box.style.cssText = "margin:0; padding:1px; border: 0; position:static; overflow:hidden; visibility: hidden;"; - box.style.cssText = "margin:0; padding:1px; border: 0; visibility: hidden;"; - - var clone = el.cloneNode(false); - var text = this.document.createTextNode(" "); - clone.appendChild(text); - - box.appendChild(clone); - - this.document.body.appendChild(box); - - var marginTop = clone.offsetTop - box.offsetTop - 1; - var marginBottom = box.offsetHeight - clone.offsetHeight - 2 - marginTop; - - var marginLeft = clone.offsetLeft - box.offsetLeft - 1; - var marginRight = box.offsetWidth - clone.offsetWidth - 2 - marginLeft; - - this.document.body.removeChild(box); - - return {top:marginTop+offsetTop, left:marginLeft, bottom:marginBottom-offsetTop, right:marginRight}; - }, - - getFontSizeInPixels: function(el) - { - var size = this.getMeasurement(el, "fontSize"); - - if (size.unit == "px") return size.value; - - // get font size, the dirty way - var computeDirtyFontSize = function(el, calibration) - { - var div = this.document.createElement("div"); - var divStyle = offscreenStyle; - - if (calibration) - divStyle += " font-size:"+calibration+"px;"; - - div.style.cssText = divStyle; - div.innerHTML = "A"; - el.appendChild(div); - - var value = div.offsetHeight; - el.removeChild(div); - return value; - }; - - /* - var calibrationBase = 200; - var calibrationValue = computeDirtyFontSize(el, calibrationBase); - var rate = calibrationBase / calibrationValue; - /**/ - - // the "dirty technique" fails in some environments, so we're using a static value - // based in some tests. - var rate = 200 / 225; - - var value = computeDirtyFontSize(el); - - return value * rate; - }, - - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // Unit Funtions - - pointsToPixels: function(name, value, returnFloat) - { - var axis = /Top$|Bottom$/.test(name) ? "y" : "x"; - - var result = value * pixelsPerInch[axis] / 72; - - return returnFloat ? result : Math.round(result); - }, - - emToPixels: function(el, value) - { - if (!el) return null; - - var fontSize = this.getFontSizeInPixels(el); - - return Math.round(value * fontSize); - }, - - exToPixels: function(el, value) - { - if (!el) return null; - - // get ex value, the dirty way - var div = this.document.createElement("div"); - div.style.cssText = offscreenStyle + "width:"+value + "ex;"; - - el.appendChild(div); - var value = div.offsetWidth; - el.removeChild(div); - - return value; - }, - - percentToPixels: function(el, value) - { - if (!el) return null; - - // get % value, the dirty way - var div = this.document.createElement("div"); - div.style.cssText = offscreenStyle + "width:"+value + "%;"; - - el.appendChild(div); - var value = div.offsetWidth; - el.removeChild(div); - - return value; - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - getStyle: isIE ? function(el, name) - { - return el.currentStyle[name] || el.style[name] || undefined; - } - : function(el, name) - { - return this.document.defaultView.getComputedStyle(el,null)[name] - || el.style[name] || undefined; - } - -}; - - -// ************************************************************************************************ -}}); - -/* See license.txt for terms of usage */ - -FBL.ns( /**@scope ns-chrome*/ function() { with (FBL) { -// ************************************************************************************************ - -// ************************************************************************************************ -// Globals - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// Window Options - -var WindowDefaultOptions = - { - type: "frame", - id: "FirebugUI" - //height: 350 // obsolete - }, - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// Instantiated objects - - commandLine, - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// Interface Elements Cache - - fbTop, - fbContent, - fbContentStyle, - fbBottom, - fbBtnInspect, - - fbToolbar, - - fbPanelBox1, - fbPanelBox1Style, - fbPanelBox2, - fbPanelBox2Style, - fbPanelBar2Box, - fbPanelBar2BoxStyle, - - fbHSplitter, - fbVSplitter, - fbVSplitterStyle, - - fbPanel1, - fbPanel1Style, - fbPanel2, - fbPanel2Style, - - fbConsole, - fbConsoleStyle, - fbHTML, - - fbCommandLine, - fbLargeCommandLine, - fbLargeCommandButtons, - -//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// Cached size values - - topHeight, - topPartialHeight, - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - chromeRedrawSkipRate = isIE ? 75 : isOpera ? 80 : 75, - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - lastSelectedPanelName, - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - focusCommandLineState = 0, - lastFocusedPanelName, - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - lastHSplitterMouseMove = 0, - onHSplitterMouseMoveBuffer = null, - onHSplitterMouseMoveTimer = null, - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - lastVSplitterMouseMove = 0; - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - -// ************************************************************************************************ -// FirebugChrome - -FBL.defaultPersistedState = -{ - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - isOpen: false, - height: 300, - sidePanelWidth: 350, - - selectedPanelName: "Console", - selectedHTMLElementId: null, - - htmlSelectionStack: [] - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -}; - -/**@namespace*/ -FBL.FirebugChrome = -{ - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - //isOpen: false, - //height: 300, - //sidePanelWidth: 350, - - //selectedPanelName: "Console", - //selectedHTMLElementId: null, - - chromeMap: {}, - - htmlSelectionStack: [], - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - create: function() - { - if (FBTrace.DBG_INITIALIZE) FBTrace.sysout("FirebugChrome.create", "creating chrome window"); - - createChromeWindow(); - }, - - initialize: function() - { - if (FBTrace.DBG_INITIALIZE) FBTrace.sysout("FirebugChrome.initialize", "initializing chrome window"); - - if (Env.chrome.type == "frame" || Env.chrome.type == "div") - ChromeMini.create(Env.chrome); - - var chrome = Firebug.chrome = new Chrome(Env.chrome); - FirebugChrome.chromeMap[chrome.type] = chrome; - - addGlobalEvent("keydown", onGlobalKeyDown); - - if (Env.Options.enablePersistent && chrome.type == "popup") - { - // TODO: xxxpedro persist - revise chrome synchronization when in persistent mode - var frame = FirebugChrome.chromeMap.frame; - if (frame) - frame.close(); - - //chrome.reattach(frame, chrome); - //TODO: xxxpedro persist synchronize? - chrome.initialize(); - } - }, - - clone: function(FBChrome) - { - for (var name in FBChrome) - { - var prop = FBChrome[name]; - if (FBChrome.hasOwnProperty(name) && !isFunction(prop)) - { - this[name] = prop; - } - } - } -}; - - - -// ************************************************************************************************ -// Chrome Window Creation - -var createChromeWindow = function(options) -{ - options = extend(WindowDefaultOptions, options || {}); - - //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // Locals - - var browserWin = Env.browser.window; - var browserContext = new Context(browserWin); - var prefs = Store.get("FirebugLite"); - var persistedState = prefs && prefs.persistedState || defaultPersistedState; - - var chrome = {}, - - context = options.context || Env.browser, - - type = chrome.type = Env.Options.enablePersistent ? - "popup" : - options.type, - - isChromeFrame = type == "frame", - - useLocalSkin = Env.useLocalSkin, - - url = useLocalSkin ? - Env.Location.skin : - "about:blank", - - // document.body not available in XML+XSL documents in Firefox - body = context.document.getElementsByTagName("body")[0], - - formatNode = function(node) - { - if (!Env.isDebugMode) - { - node.firebugIgnore = true; - } - - var browserWinSize = browserContext.getWindowSize(); - var height = persistedState.height || 300; - - height = Math.min(browserWinSize.height, height); - height = Math.max(200, height); - - node.style.border = "0"; - node.style.visibility = "hidden"; - node.style.zIndex = "2147483647"; // MAX z-index = 2147483647 - node.style.position = noFixedPosition ? "absolute" : "fixed"; - node.style.width = "100%"; // "102%"; IE auto margin bug - node.style.left = "0"; - node.style.bottom = noFixedPosition ? "-1px" : "0"; - node.style.height = height + "px"; - - // avoid flickering during chrome rendering - //if (isFirefox) - // node.style.display = "none"; - }, - - createChromeDiv = function() - { - //Firebug.Console.warn("Firebug Lite GUI is working in 'windowless mode'. It may behave slower and receive interferences from the page in which it is installed."); - - var node = chrome.node = createGlobalElement("div"), - style = createGlobalElement("style"), - - css = FirebugChrome.Skin.CSS - /* - .replace(/;/g, " !important;") - .replace(/!important\s!important/g, "!important") - .replace(/display\s*:\s*(\w+)\s*!important;/g, "display:$1;")*/, - - // reset some styles to minimize interference from the main page's style - rules = ".fbBody *{margin:0;padding:0;font-size:11px;line-height:13px;color:inherit;}" + - // load the chrome styles - css + - // adjust some remaining styles - ".fbBody #fbHSplitter{position:absolute !important;} .fbBody #fbHTML span{line-height:14px;} .fbBody .lineNo div{line-height:inherit !important;}"; - /* - if (isIE) - { - // IE7 CSS bug (FbChrome table bigger than its parent div) - rules += ".fbBody table.fbChrome{position: static !important;}"; - }/**/ - - style.type = "text/css"; - - if (style.styleSheet) - style.styleSheet.cssText = rules; - else - style.appendChild(context.document.createTextNode(rules)); - - document.getElementsByTagName("head")[0].appendChild(style); - - node.className = "fbBody"; - node.style.overflow = "hidden"; - node.innerHTML = getChromeDivTemplate(); - - if (isIE) - { - // IE7 CSS bug (FbChrome table bigger than its parent div) - setTimeout(function(){ - node.firstChild.style.height = "1px"; - node.firstChild.style.position = "static"; - },0); - /**/ - } - - formatNode(node); - - body.appendChild(node); - - chrome.window = window; - chrome.document = document; - onChromeLoad(chrome); - }; - - //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - try - { - //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // create the Chrome as a "div" (windowless mode) - if (type == "div") - { - createChromeDiv(); - return; - } - - //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // cretate the Chrome as an "iframe" - else if (isChromeFrame) - { - // Create the Chrome Frame - var node = chrome.node = createGlobalElement("iframe"); - node.setAttribute("src", url); - node.setAttribute("frameBorder", "0"); - - formatNode(node); - - body.appendChild(node); - - // must set the id after appending to the document, otherwise will cause an - // strange error in IE, making the iframe load the page in which the bookmarklet - // was created (like getfirebug.com), before loading the injected UI HTML, - // generating an "Access Denied" error. - node.id = options.id; - } - - //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // create the Chrome as a "popup" - else - { - var height = persistedState.popupHeight || 300; - var browserWinSize = browserContext.getWindowSize(); - - var browserWinLeft = typeof browserWin.screenX == "number" ? - browserWin.screenX : browserWin.screenLeft; - - var popupLeft = typeof persistedState.popupLeft == "number" ? - persistedState.popupLeft : browserWinLeft; - - var browserWinTop = typeof browserWin.screenY == "number" ? - browserWin.screenY : browserWin.screenTop; - - var popupTop = typeof persistedState.popupTop == "number" ? - persistedState.popupTop : - Math.max( - 0, - Math.min( - browserWinTop + browserWinSize.height - height, - // Google Chrome bug - screen.availHeight - height - 61 - ) - ); - - var popupWidth = typeof persistedState.popupWidth == "number" ? - persistedState.popupWidth : - Math.max( - 0, - Math.min( - browserWinSize.width, - // Opera opens popup in a new tab if it's too big! - screen.availWidth-10 - ) - ); - - var popupHeight = typeof persistedState.popupHeight == "number" ? - persistedState.popupHeight : 300; - - var options = [ - "true,top=", popupTop, - ",left=", popupLeft, - ",height=", popupHeight, - ",width=", popupWidth, - ",resizable" - ].join(""), - - node = chrome.node = context.window.open( - url, - "popup", - options - ); - - if (node) - { - try - { - node.focus(); - } - catch(E) - { - alert("Firebug Error: Firebug popup was blocked."); - return; - } - } - else - { - alert("Firebug Error: Firebug popup was blocked."); - return; - } - } - - //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // Inject the interface HTML if it is not using the local skin - - if (!useLocalSkin) - { - var tpl = getChromeTemplate(!isChromeFrame), - doc = isChromeFrame ? node.contentWindow.document : node.document; - - doc.write(tpl); - doc.close(); - } - - //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // Wait the Window to be loaded - - var win, - - waitDelay = useLocalSkin ? isChromeFrame ? 200 : 300 : 100, - - waitForWindow = function() - { - if ( // Frame loaded... OR - isChromeFrame && (win=node.contentWindow) && - node.contentWindow.document.getElementById("fbCommandLine") || - - // Popup loaded - !isChromeFrame && (win=node.window) && node.document && - node.document.getElementById("fbCommandLine") ) - { - chrome.window = win.window; - chrome.document = win.document; - - // Prevent getting the wrong chrome height in FF when opening a popup - setTimeout(function(){ - onChromeLoad(chrome); - }, useLocalSkin ? 200 : 0); - } - else - setTimeout(waitForWindow, waitDelay); - }; - - waitForWindow(); - } - catch(e) - { - var msg = e.message || e; - - if (/access/i.test(msg)) - { - // Firebug Lite could not create a window for its Graphical User Interface due to - // a access restriction. This happens in some pages, when loading via bookmarklet. - // In such cases, the only way is to load the GUI in a "windowless mode". - - if (isChromeFrame) - body.removeChild(node); - else if(type == "popup") - node.close(); - - // Load the GUI in a "windowless mode" - createChromeDiv(); - } - else - { - alert("Firebug Error: Firebug GUI could not be created."); - } - } -}; - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - -var onChromeLoad = function onChromeLoad(chrome) -{ - Env.chrome = chrome; - - if (FBTrace.DBG_INITIALIZE) FBTrace.sysout("Chrome onChromeLoad", "chrome window loaded"); - - if (Env.Options.enablePersistent) - { - // TODO: xxxpedro persist - make better chrome synchronization when in persistent mode - Env.FirebugChrome = FirebugChrome; - - chrome.window.Firebug = chrome.window.Firebug || {}; - chrome.window.Firebug.SharedEnv = Env; - - if (Env.isDevelopmentMode) - { - Env.browser.window.FBDev.loadChromeApplication(chrome); - } - else - { - var doc = chrome.document; - var script = doc.createElement("script"); - script.src = Env.Location.app + "#remote,persist"; - doc.getElementsByTagName("head")[0].appendChild(script); - } - } - else - { - if (chrome.type == "frame" || chrome.type == "div") - { - // initialize the chrome application - setTimeout(function(){ - FBL.Firebug.initialize(); - },0); - } - else if (chrome.type == "popup") - { - var oldChrome = FirebugChrome.chromeMap.frame; - - var newChrome = new Chrome(chrome); - - // TODO: xxxpedro sync detach reattach attach - dispatch(newChrome.panelMap, "detach", [oldChrome, newChrome]); - - newChrome.reattach(oldChrome, newChrome); - } - } -}; - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - -var getChromeDivTemplate = function() -{ - return FirebugChrome.Skin.HTML; -}; - -var getChromeTemplate = function(isPopup) -{ - var tpl = FirebugChrome.Skin; - var r = [], i = -1; - - r[++i] = '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/DTD/strict.dtd">'; - r[++i] = '<html><head><title>'; - r[++i] = Firebug.version; - - /* - r[++i] = '</title><link href="'; - r[++i] = Env.Location.skinDir + 'firebug.css'; - r[++i] = '" rel="stylesheet" type="text/css" />'; - /**/ - - r[++i] = '</title><style>html,body{margin:0;padding:0;overflow:hidden;}'; - r[++i] = tpl.CSS; - r[++i] = '</style>'; - /**/ - - r[++i] = '</head><body class="fbBody' + (isPopup ? ' FirebugPopup' : '') + '">'; - r[++i] = tpl.HTML; - r[++i] = '</body></html>'; - - return r.join(""); -}; - - -// ************************************************************************************************ -// Chrome Class - -/**@class*/ -var Chrome = function Chrome(chrome) -{ - var type = chrome.type; - var Base = type == "frame" || type == "div" ? ChromeFrameBase : ChromePopupBase; - - append(this, Base); // inherit from base class (ChromeFrameBase or ChromePopupBase) - append(this, chrome); // inherit chrome window properties - append(this, new Context(chrome.window)); // inherit from Context class - - FirebugChrome.chromeMap[type] = this; - Firebug.chrome = this; - Env.chrome = chrome.window; - - this.commandLineVisible = false; - this.sidePanelVisible = false; - - this.create(); - - return this; -}; - -// ************************************************************************************************ -// ChromeBase - -/** - * @namespace - * @extends FBL.Controller - * @extends FBL.PanelBar - **/ -var ChromeBase = {}; -append(ChromeBase, Controller); -append(ChromeBase, PanelBar); -append(ChromeBase, -/**@extend ns-chrome-ChromeBase*/ -{ - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // inherited properties - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // inherited from createChrome function - - node: null, - type: null, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // inherited from Context.prototype - - document: null, - window: null, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // value properties - - sidePanelVisible: false, - commandLineVisible: false, - largeCommandLineVisible: false, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // object properties - - inspectButton: null, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - create: function() - { - PanelBar.create.call(this); - - if (Firebug.Inspector) - this.inspectButton = new Button({ - type: "toggle", - element: $("fbChrome_btInspect"), - owner: Firebug.Inspector, - - onPress: Firebug.Inspector.startInspecting, - onUnpress: Firebug.Inspector.stopInspecting - }); - }, - - destroy: function() - { - if(Firebug.Inspector) - this.inspectButton.destroy(); - - PanelBar.destroy.call(this); - - this.shutdown(); - }, - - testMenu: function() - { - var firebugMenu = new Menu( - { - id: "fbFirebugMenu", - - items: - [ - { - label: "Open Firebug", - type: "shortcut", - key: isFirefox ? "Shift+F12" : "F12", - checked: true, - command: "toggleChrome" - }, - { - label: "Open Firebug in New Window", - type: "shortcut", - key: isFirefox ? "Ctrl+Shift+F12" : "Ctrl+F12", - command: "openPopup" - }, - { - label: "Inspect Element", - type: "shortcut", - key: "Ctrl+Shift+C", - command: "toggleInspect" - }, - { - label: "Command Line", - type: "shortcut", - key: "Ctrl+Shift+L", - command: "focusCommandLine" - }, - "-", - { - label: "Options", - type: "group", - child: "fbFirebugOptionsMenu" - }, - "-", - { - label: "Firebug Lite Website...", - command: "visitWebsite" - }, - { - label: "Discussion Group...", - command: "visitDiscussionGroup" - }, - { - label: "Issue Tracker...", - command: "visitIssueTracker" - } - ], - - onHide: function() - { - iconButton.restore(); - }, - - toggleChrome: function() - { - Firebug.chrome.toggle(); - }, - - openPopup: function() - { - Firebug.chrome.toggle(true, true); - }, - - toggleInspect: function() - { - Firebug.Inspector.toggleInspect(); - }, - - focusCommandLine: function() - { - Firebug.chrome.focusCommandLine(); - }, - - visitWebsite: function() - { - this.visit("http://getfirebug.com/lite.html"); - }, - - visitDiscussionGroup: function() - { - this.visit("http://groups.google.com/group/firebug"); - }, - - visitIssueTracker: function() - { - this.visit("http://code.google.com/p/fbug/issues/list"); - }, - - visit: function(url) - { - window.open(url); - } - - }); - - /**@private*/ - var firebugOptionsMenu = - { - id: "fbFirebugOptionsMenu", - - getItems: function() - { - var cookiesDisabled = !Firebug.saveCookies; - - return [ - { - label: "Start Opened", - type: "checkbox", - value: "startOpened", - checked: Firebug.startOpened, - disabled: cookiesDisabled - }, - { - label: "Start in New Window", - type: "checkbox", - value: "startInNewWindow", - checked: Firebug.startInNewWindow, - disabled: cookiesDisabled - }, - { - label: "Show Icon When Hidden", - type: "checkbox", - value: "showIconWhenHidden", - checked: Firebug.showIconWhenHidden, - disabled: cookiesDisabled - }, - { - label: "Override Console Object", - type: "checkbox", - value: "overrideConsole", - checked: Firebug.overrideConsole, - disabled: cookiesDisabled - }, - { - label: "Ignore Firebug Elements", - type: "checkbox", - value: "ignoreFirebugElements", - checked: Firebug.ignoreFirebugElements, - disabled: cookiesDisabled - }, - { - label: "Disable When Firebug Active", - type: "checkbox", - value: "disableWhenFirebugActive", - checked: Firebug.disableWhenFirebugActive, - disabled: cookiesDisabled - }, - { - label: "Disable XHR Listener", - type: "checkbox", - value: "disableXHRListener", - checked: Firebug.disableXHRListener, - disabled: cookiesDisabled - }, - { - label: "Disable Resource Fetching", - type: "checkbox", - value: "disableResourceFetching", - checked: Firebug.disableResourceFetching, - disabled: cookiesDisabled - }, - { - label: "Enable Trace Mode", - type: "checkbox", - value: "enableTrace", - checked: Firebug.enableTrace, - disabled: cookiesDisabled - }, - { - label: "Enable Persistent Mode (experimental)", - type: "checkbox", - value: "enablePersistent", - checked: Firebug.enablePersistent, - disabled: cookiesDisabled - }, - "-", - { - label: "Reset All Firebug Options", - command: "restorePrefs", - disabled: cookiesDisabled - } - ]; - }, - - onCheck: function(target, value, checked) - { - Firebug.setPref(value, checked); - }, - - restorePrefs: function(target) - { - Firebug.erasePrefs(); - - if (target) - this.updateMenu(target); - }, - - updateMenu: function(target) - { - var options = getElementsByClass(target.parentNode, "fbMenuOption"); - - var firstOption = options[0]; - var enabled = Firebug.saveCookies; - if (enabled) - Menu.check(firstOption); - else - Menu.uncheck(firstOption); - - if (enabled) - Menu.check(options[0]); - else - Menu.uncheck(options[0]); - - for (var i = 1, length = options.length; i < length; i++) - { - var option = options[i]; - - var value = option.getAttribute("value"); - var pref = Firebug[value]; - - if (pref) - Menu.check(option); - else - Menu.uncheck(option); - - if (enabled) - Menu.enable(option); - else - Menu.disable(option); - } - } - }; - - Menu.register(firebugOptionsMenu); - - var menu = firebugMenu; - - var testMenuClick = function(event) - { - //console.log("testMenuClick"); - cancelEvent(event, true); - - var target = event.target || event.srcElement; - - if (menu.isVisible) - menu.hide(); - else - { - var offsetLeft = isIE6 ? 1 : -4, // IE6 problem with fixed position - - chrome = Firebug.chrome, - - box = chrome.getElementBox(target), - - offset = chrome.type == "div" ? - chrome.getElementPosition(chrome.node) : - {top: 0, left: 0}; - - menu.show( - box.left + offsetLeft - offset.left, - box.top + box.height -5 - offset.top - ); - } - - return false; - }; - - var iconButton = new IconButton({ - type: "toggle", - element: $("fbFirebugButton"), - - onClick: testMenuClick - }); - - iconButton.initialize(); - - //addEvent($("fbToolbarIcon"), "click", testMenuClick); - }, - - initialize: function() - { - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - if (Env.bookmarkletOutdated) - Firebug.Console.logFormatted([ - "A new bookmarklet version is available. " + - "Please visit http://getfirebug.com/firebuglite#Install and update it." - ], Firebug.context, "warn"); - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - if (Firebug.Console) - Firebug.Console.flush(); - - if (Firebug.Trace) - FBTrace.flush(Firebug.Trace); - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - if (FBTrace.DBG_INITIALIZE) FBTrace.sysout("Firebug.chrome.initialize", "initializing chrome application"); - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // initialize inherited classes - Controller.initialize.call(this); - PanelBar.initialize.call(this); - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // create the interface elements cache - - fbTop = $("fbTop"); - fbContent = $("fbContent"); - fbContentStyle = fbContent.style; - fbBottom = $("fbBottom"); - fbBtnInspect = $("fbBtnInspect"); - - fbToolbar = $("fbToolbar"); - - fbPanelBox1 = $("fbPanelBox1"); - fbPanelBox1Style = fbPanelBox1.style; - fbPanelBox2 = $("fbPanelBox2"); - fbPanelBox2Style = fbPanelBox2.style; - fbPanelBar2Box = $("fbPanelBar2Box"); - fbPanelBar2BoxStyle = fbPanelBar2Box.style; - - fbHSplitter = $("fbHSplitter"); - fbVSplitter = $("fbVSplitter"); - fbVSplitterStyle = fbVSplitter.style; - - fbPanel1 = $("fbPanel1"); - fbPanel1Style = fbPanel1.style; - fbPanel2 = $("fbPanel2"); - fbPanel2Style = fbPanel2.style; - - fbConsole = $("fbConsole"); - fbConsoleStyle = fbConsole.style; - fbHTML = $("fbHTML"); - - fbCommandLine = $("fbCommandLine"); - fbLargeCommandLine = $("fbLargeCommandLine"); - fbLargeCommandButtons = $("fbLargeCommandButtons"); - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // static values cache - topHeight = fbTop.offsetHeight; - topPartialHeight = fbToolbar.offsetHeight; - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - disableTextSelection($("fbToolbar")); - disableTextSelection($("fbPanelBarBox")); - disableTextSelection($("fbPanelBar1")); - disableTextSelection($("fbPanelBar2")); - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // Add the "javascript:void(0)" href attributes used to make the hover effect in IE6 - if (isIE6 && Firebug.Selector) - { - // TODO: xxxpedro change to getElementsByClass - var as = $$(".fbHover"); - for (var i=0, a; a=as[i]; i++) - { - a.setAttribute("href", "javascript:void(0)"); - } - } - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // initialize all panels - /* - var panelMap = Firebug.panelTypes; - for (var i=0, p; p=panelMap[i]; i++) - { - if (!p.parentPanel) - { - this.addPanel(p.prototype.name); - } - } - /**/ - - // ************************************************************************************************ - // ************************************************************************************************ - // ************************************************************************************************ - // ************************************************************************************************ - - if(Firebug.Inspector) - this.inspectButton.initialize(); - - // ************************************************************************************************ - // ************************************************************************************************ - // ************************************************************************************************ - // ************************************************************************************************ - - this.addController( - [$("fbLargeCommandLineIcon"), "click", this.showLargeCommandLine] - ); - - // ************************************************************************************************ - - // Select the first registered panel - // TODO: BUG IE7 - var self = this; - setTimeout(function(){ - self.selectPanel(Firebug.context.persistedState.selectedPanelName); - - if (Firebug.context.persistedState.selectedPanelName == "Console" && Firebug.CommandLine) - Firebug.chrome.focusCommandLine(); - },0); - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - //this.draw(); - - - - - - - - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - var onPanelMouseDown = function onPanelMouseDown(event) - { - //console.log("onPanelMouseDown", event.target || event.srcElement, event); - - var target = event.target || event.srcElement; - - if (FBL.isLeftClick(event)) - { - var editable = FBL.getAncestorByClass(target, "editable"); - - // if an editable element has been clicked then start editing - if (editable) - { - Firebug.Editor.startEditing(editable); - FBL.cancelEvent(event); - } - // if any other element has been clicked then stop editing - else - { - if (!hasClass(target, "textEditorInner")) - Firebug.Editor.stopEditing(); - } - } - else if (FBL.isMiddleClick(event) && Firebug.getRepNode(target)) - { - // Prevent auto-scroll when middle-clicking a rep object - FBL.cancelEvent(event); - } - }; - - Firebug.getElementPanel = function(element) - { - var panelNode = getAncestorByClass(element, "fbPanel"); - var id = panelNode.id.substr(2); - - var panel = Firebug.chrome.panelMap[id]; - - if (!panel) - { - if (Firebug.chrome.selectedPanel.sidePanelBar) - panel = Firebug.chrome.selectedPanel.sidePanelBar.panelMap[id]; - } - - return panel; - }; - - - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - // TODO: xxxpedro port to Firebug - - // Improved window key code event listener. Only one "keydown" event will be attached - // to the window, and the onKeyCodeListen() function will delegate which listeners - // should be called according to the event.keyCode fired. - var onKeyCodeListenersMap = []; - var onKeyCodeListen = function(event) - { - for (var keyCode in onKeyCodeListenersMap) - { - var listeners = onKeyCodeListenersMap[keyCode]; - - for (var i = 0, listener; listener = listeners[i]; i++) - { - var filter = listener.filter || FBL.noKeyModifiers; - - if (event.keyCode == keyCode && (!filter || filter(event))) - { - listener.listener(); - FBL.cancelEvent(event, true); - return false; - } - } - } - }; - - addEvent(Firebug.chrome.document, "keydown", onKeyCodeListen); - - /** - * @name keyCodeListen - * @memberOf FBL.FirebugChrome - */ - Firebug.chrome.keyCodeListen = function(key, filter, listener, capture) - { - var keyCode = KeyEvent["DOM_VK_"+key]; - - if (!onKeyCodeListenersMap[keyCode]) - onKeyCodeListenersMap[keyCode] = []; - - onKeyCodeListenersMap[keyCode].push({ - filter: filter, - listener: listener - }); - - return keyCode; - }; - - /** - * @name keyIgnore - * @memberOf FBL.FirebugChrome - */ - Firebug.chrome.keyIgnore = function(keyCode) - { - onKeyCodeListenersMap[keyCode] = null; - delete onKeyCodeListenersMap[keyCode]; - }; - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - /**/ - // move to shutdown - //removeEvent(Firebug.chrome.document, "keydown", listener[0]); - - - /* - Firebug.chrome.keyCodeListen = function(key, filter, listener, capture) - { - if (!filter) - filter = FBL.noKeyModifiers; - - var keyCode = KeyEvent["DOM_VK_"+key]; - - var fn = function fn(event) - { - if (event.keyCode == keyCode && (!filter || filter(event))) - { - listener(); - FBL.cancelEvent(event, true); - return false; - } - } - - addEvent(Firebug.chrome.document, "keydown", fn); - - return [fn, capture]; - }; - - Firebug.chrome.keyIgnore = function(listener) - { - removeEvent(Firebug.chrome.document, "keydown", listener[0]); - }; - /**/ - - - this.addController( - [fbPanel1, "mousedown", onPanelMouseDown], - [fbPanel2, "mousedown", onPanelMouseDown] - ); -/**/ - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - - // menus can be used without domplate - if (FBL.domplate) - this.testMenu(); - /**/ - - //test XHR - /* - setTimeout(function(){ - - FBL.Ajax.request({url: "../content/firebug/boot.js"}); - FBL.Ajax.request({url: "../content/firebug/boot.js.invalid"}); - - },1000); - /**/ - }, - - shutdown: function() - { - // ************************************************************************************************ - // ************************************************************************************************ - // ************************************************************************************************ - // ************************************************************************************************ - - if(Firebug.Inspector) - this.inspectButton.shutdown(); - - // ************************************************************************************************ - // ************************************************************************************************ - // ************************************************************************************************ - // ************************************************************************************************ - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - // remove disableTextSelection event handlers - restoreTextSelection($("fbToolbar")); - restoreTextSelection($("fbPanelBarBox")); - restoreTextSelection($("fbPanelBar1")); - restoreTextSelection($("fbPanelBar2")); - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // shutdown inherited classes - Controller.shutdown.call(this); - PanelBar.shutdown.call(this); - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // Remove the interface elements cache (this must happen after calling - // the shutdown method of all dependent components to avoid errors) - - fbTop = null; - fbContent = null; - fbContentStyle = null; - fbBottom = null; - fbBtnInspect = null; - - fbToolbar = null; - - fbPanelBox1 = null; - fbPanelBox1Style = null; - fbPanelBox2 = null; - fbPanelBox2Style = null; - fbPanelBar2Box = null; - fbPanelBar2BoxStyle = null; - - fbHSplitter = null; - fbVSplitter = null; - fbVSplitterStyle = null; - - fbPanel1 = null; - fbPanel1Style = null; - fbPanel2 = null; - - fbConsole = null; - fbConsoleStyle = null; - fbHTML = null; - - fbCommandLine = null; - fbLargeCommandLine = null; - fbLargeCommandButtons = null; - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // static values cache - - topHeight = null; - topPartialHeight = null; - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - toggle: function(forceOpen, popup) - { - if(popup) - { - this.detach(); - } - else - { - if (isOpera && Firebug.chrome.type == "popup" && Firebug.chrome.node.closed) - { - var frame = FirebugChrome.chromeMap.frame; - frame.reattach(); - - FirebugChrome.chromeMap.popup = null; - - frame.open(); - - return; - } - - // If the context is a popup, ignores the toggle process - if (Firebug.chrome.type == "popup") return; - - var shouldOpen = forceOpen || !Firebug.context.persistedState.isOpen; - - if(shouldOpen) - this.open(); - else - this.close(); - } - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - detach: function() - { - if(!FirebugChrome.chromeMap.popup) - { - this.close(); - createChromeWindow({type: "popup"}); - } - }, - - reattach: function(oldChrome, newChrome) - { - Firebug.browser.window.Firebug = Firebug; - - // chrome synchronization - var newPanelMap = newChrome.panelMap; - var oldPanelMap = oldChrome.panelMap; - - var panel; - for(var name in newPanelMap) - { - // TODO: xxxpedro innerHTML - panel = newPanelMap[name]; - if (panel.options.innerHTMLSync) - panel.panelNode.innerHTML = oldPanelMap[name].panelNode.innerHTML; - } - - Firebug.chrome = newChrome; - - // TODO: xxxpedro sync detach reattach attach - //dispatch(Firebug.chrome.panelMap, "detach", [oldChrome, newChrome]); - - if (newChrome.type == "popup") - { - newChrome.initialize(); - //dispatch(Firebug.modules, "initialize", []); - } - else - { - // TODO: xxxpedro only needed in persistent - // should use FirebugChrome.clone, but popup FBChrome - // isn't acessible - Firebug.context.persistedState.selectedPanelName = oldChrome.selectedPanel.name; - } - - dispatch(newPanelMap, "reattach", [oldChrome, newChrome]); - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - draw: function() - { - var size = this.getSize(); - - // Height related values - var commandLineHeight = Firebug.chrome.commandLineVisible ? fbCommandLine.offsetHeight : 0, - - y = Math.max(size.height /* chrome height */, topHeight), - - heightValue = Math.max(y - topHeight - commandLineHeight /* fixed height */, 0), - - height = heightValue + "px", - - // Width related values - sideWidthValue = Firebug.chrome.sidePanelVisible ? Firebug.context.persistedState.sidePanelWidth : 0, - - width = Math.max(size.width /* chrome width */ - sideWidthValue, 0) + "px"; - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // Height related rendering - fbPanelBox1Style.height = height; - fbPanel1Style.height = height; - - if (isIE || isOpera) - { - // Fix IE and Opera problems with auto resizing the verticall splitter - fbVSplitterStyle.height = Math.max(y - topPartialHeight - commandLineHeight, 0) + "px"; - } - //xxxpedro FF2 only? - /* - else if (isFirefox) - { - // Fix Firefox problem with table rows with 100% height (fit height) - fbContentStyle.maxHeight = Math.max(y - fixedHeight, 0)+ "px"; - }/**/ - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // Width related rendering - fbPanelBox1Style.width = width; - fbPanel1Style.width = width; - - // SidePanel rendering - if (Firebug.chrome.sidePanelVisible) - { - sideWidthValue = Math.max(sideWidthValue - 6, 0); - - var sideWidth = sideWidthValue + "px"; - - fbPanelBox2Style.width = sideWidth; - - fbVSplitterStyle.right = sideWidth; - - if (Firebug.chrome.largeCommandLineVisible) - { - fbLargeCommandLine = $("fbLargeCommandLine"); - - fbLargeCommandLine.style.height = heightValue - 4 + "px"; - fbLargeCommandLine.style.width = sideWidthValue - 2 + "px"; - - fbLargeCommandButtons = $("fbLargeCommandButtons"); - fbLargeCommandButtons.style.width = sideWidth; - } - else - { - fbPanel2Style.height = height; - fbPanel2Style.width = sideWidth; - - fbPanelBar2BoxStyle.width = sideWidth; - } - } - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - getSize: function() - { - return this.type == "div" ? - { - height: this.node.offsetHeight, - width: this.node.offsetWidth - } - : - this.getWindowSize(); - }, - - resize: function() - { - var self = this; - - // avoid partial resize when maximizing window - setTimeout(function(){ - self.draw(); - - if (noFixedPosition && (self.type == "frame" || self.type == "div")) - self.fixIEPosition(); - }, 0); - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - layout: function(panel) - { - if (FBTrace.DBG_CHROME) FBTrace.sysout("Chrome.layout", ""); - - var options = panel.options; - - changeCommandLineVisibility(options.hasCommandLine); - changeSidePanelVisibility(panel.hasSidePanel); - - Firebug.chrome.draw(); - }, - - showLargeCommandLine: function(hideToggleIcon) - { - var chrome = Firebug.chrome; - - if (!chrome.largeCommandLineVisible) - { - chrome.largeCommandLineVisible = true; - - if (chrome.selectedPanel.options.hasCommandLine) - { - if (Firebug.CommandLine) - Firebug.CommandLine.blur(); - - changeCommandLineVisibility(false); - } - - changeSidePanelVisibility(true); - - fbLargeCommandLine.style.display = "block"; - fbLargeCommandButtons.style.display = "block"; - - fbPanel2Style.display = "none"; - fbPanelBar2BoxStyle.display = "none"; - - chrome.draw(); - - fbLargeCommandLine.focus(); - - if (Firebug.CommandLine) - Firebug.CommandLine.setMultiLine(true); - } - }, - - hideLargeCommandLine: function() - { - if (Firebug.chrome.largeCommandLineVisible) - { - Firebug.chrome.largeCommandLineVisible = false; - - if (Firebug.CommandLine) - Firebug.CommandLine.setMultiLine(false); - - fbLargeCommandLine.blur(); - - fbPanel2Style.display = "block"; - fbPanelBar2BoxStyle.display = "block"; - - fbLargeCommandLine.style.display = "none"; - fbLargeCommandButtons.style.display = "none"; - - changeSidePanelVisibility(false); - - if (Firebug.chrome.selectedPanel.options.hasCommandLine) - changeCommandLineVisibility(true); - - Firebug.chrome.draw(); - - } - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - focusCommandLine: function() - { - var selectedPanelName = this.selectedPanel.name, panelToSelect; - - if (focusCommandLineState == 0 || selectedPanelName != "Console") - { - focusCommandLineState = 0; - lastFocusedPanelName = selectedPanelName; - - panelToSelect = "Console"; - } - if (focusCommandLineState == 1) - { - panelToSelect = lastFocusedPanelName; - } - - this.selectPanel(panelToSelect); - - try - { - if (Firebug.CommandLine) - { - if (panelToSelect == "Console") - Firebug.CommandLine.focus(); - else - Firebug.CommandLine.blur(); - } - } - catch(e) - { - //TODO: xxxpedro trace error - } - - focusCommandLineState = ++focusCommandLineState % 2; - } - -}); - -// ************************************************************************************************ -// ChromeFrameBase - -/** - * @namespace - * @extends ns-chrome-ChromeBase - */ -var ChromeFrameBase = extend(ChromeBase, -/**@extend ns-chrome-ChromeFrameBase*/ -{ - create: function() - { - ChromeBase.create.call(this); - - // restore display for the anti-flicker trick - if (isFirefox) - this.node.style.display = "block"; - - if (Env.Options.startInNewWindow) - { - this.close(); - this.toggle(true, true); - return; - } - - if (Env.Options.startOpened) - this.open(); - else - this.close(); - }, - - destroy: function() - { - var size = Firebug.chrome.getWindowSize(); - - Firebug.context.persistedState.height = size.height; - - if (Firebug.saveCookies) - Firebug.savePrefs(); - - removeGlobalEvent("keydown", onGlobalKeyDown); - - ChromeBase.destroy.call(this); - - this.document = null; - delete this.document; - - this.window = null; - delete this.window; - - this.node.parentNode.removeChild(this.node); - this.node = null; - delete this.node; - }, - - initialize: function() - { - //FBTrace.sysout("Frame", "initialize();") - ChromeBase.initialize.call(this); - - this.addController( - [Firebug.browser.window, "resize", this.resize], - [$("fbWindow_btClose"), "click", this.close], - [$("fbWindow_btDetach"), "click", this.detach], - [$("fbWindow_btDeactivate"), "click", this.deactivate] - ); - - if (!Env.Options.enablePersistent) - this.addController([Firebug.browser.window, "unload", Firebug.shutdown]); - - if (noFixedPosition) - { - this.addController( - [Firebug.browser.window, "scroll", this.fixIEPosition] - ); - } - - fbVSplitter.onmousedown = onVSplitterMouseDown; - fbHSplitter.onmousedown = onHSplitterMouseDown; - - this.isInitialized = true; - }, - - shutdown: function() - { - fbVSplitter.onmousedown = null; - fbHSplitter.onmousedown = null; - - ChromeBase.shutdown.apply(this); - - this.isInitialized = false; - }, - - reattach: function() - { - var frame = FirebugChrome.chromeMap.frame; - - ChromeBase.reattach(FirebugChrome.chromeMap.popup, this); - }, - - open: function() - { - if (!Firebug.context.persistedState.isOpen) - { - Firebug.context.persistedState.isOpen = true; - - if (Env.isChromeExtension) - localStorage.setItem("Firebug", "1,1"); - - var node = this.node; - - node.style.visibility = "hidden"; // Avoid flickering - - if (Firebug.showIconWhenHidden) - { - if (ChromeMini.isInitialized) - { - ChromeMini.shutdown(); - } - - } - else - node.style.display = "block"; - - var main = $("fbChrome"); - - // IE6 throws an error when setting this property! why? - //main.style.display = "table"; - main.style.display = ""; - - var self = this; - /// TODO: xxxpedro FOUC - node.style.visibility = "visible"; - setTimeout(function(){ - ///node.style.visibility = "visible"; - - //dispatch(Firebug.modules, "initialize", []); - self.initialize(); - - if (noFixedPosition) - self.fixIEPosition(); - - self.draw(); - - }, 10); - } - }, - - close: function() - { - if (Firebug.context.persistedState.isOpen) - { - if (this.isInitialized) - { - //dispatch(Firebug.modules, "shutdown", []); - this.shutdown(); - } - - Firebug.context.persistedState.isOpen = false; - - if (Env.isChromeExtension) - localStorage.setItem("Firebug", "1,0"); - - var node = this.node; - - if (Firebug.showIconWhenHidden) - { - node.style.visibility = "hidden"; // Avoid flickering - - // TODO: xxxpedro - persist IE fixed? - var main = $("fbChrome", FirebugChrome.chromeMap.frame.document); - main.style.display = "none"; - - ChromeMini.initialize(); - - node.style.visibility = "visible"; - } - else - node.style.display = "none"; - } - }, - - deactivate: function() - { - // if it is running as a Chrome extension, dispatch a message to the extension signaling - // that Firebug should be deactivated for the current tab - if (Env.isChromeExtension) - { - localStorage.removeItem("Firebug"); - Firebug.GoogleChrome.dispatch("FB_deactivate"); - - // xxxpedro problem here regarding Chrome extension. We can't deactivate the whole - // app, otherwise it won't be able to be reactivated without reloading the page. - // but we need to stop listening global keys, otherwise the key activation won't work. - Firebug.chrome.close(); - } - else - { - Firebug.shutdown(); - } - }, - - fixIEPosition: function() - { - // fix IE problem with offset when not in fullscreen mode - var doc = this.document; - var offset = isIE ? doc.body.clientTop || doc.documentElement.clientTop: 0; - - var size = Firebug.browser.getWindowSize(); - var scroll = Firebug.browser.getWindowScrollPosition(); - var maxHeight = size.height; - var height = this.node.offsetHeight; - - var bodyStyle = doc.body.currentStyle; - - this.node.style.top = maxHeight - height + scroll.top + "px"; - - if ((this.type == "frame" || this.type == "div") && - (bodyStyle.marginLeft || bodyStyle.marginRight)) - { - this.node.style.width = size.width + "px"; - } - - if (fbVSplitterStyle) - fbVSplitterStyle.right = Firebug.context.persistedState.sidePanelWidth + "px"; - - this.draw(); - } - -}); - - -// ************************************************************************************************ -// ChromeMini - -/** - * @namespace - * @extends FBL.Controller - */ -var ChromeMini = extend(Controller, -/**@extend ns-chrome-ChromeMini*/ -{ - create: function(chrome) - { - append(this, chrome); - this.type = "mini"; - }, - - initialize: function() - { - Controller.initialize.apply(this); - - var doc = FirebugChrome.chromeMap.frame.document; - - var mini = $("fbMiniChrome", doc); - mini.style.display = "block"; - - var miniIcon = $("fbMiniIcon", doc); - var width = miniIcon.offsetWidth + 10; - miniIcon.title = "Open " + Firebug.version; - - var errors = $("fbMiniErrors", doc); - if (errors.offsetWidth) - width += errors.offsetWidth + 10; - - var node = this.node; - node.style.height = "27px"; - node.style.width = width + "px"; - node.style.left = ""; - node.style.right = 0; - - if (this.node.nodeName.toLowerCase() == "iframe") - { - node.setAttribute("allowTransparency", "true"); - this.document.body.style.backgroundColor = "transparent"; - } - else - node.style.background = "transparent"; - - if (noFixedPosition) - this.fixIEPosition(); - - this.addController( - [$("fbMiniIcon", doc), "click", onMiniIconClick] - ); - - if (noFixedPosition) - { - this.addController( - [Firebug.browser.window, "scroll", this.fixIEPosition] - ); - } - - this.isInitialized = true; - }, - - shutdown: function() - { - var node = this.node; - node.style.height = Firebug.context.persistedState.height + "px"; - node.style.width = "100%"; - node.style.left = 0; - node.style.right = ""; - - if (this.node.nodeName.toLowerCase() == "iframe") - { - node.setAttribute("allowTransparency", "false"); - this.document.body.style.backgroundColor = "#fff"; - } - else - node.style.background = "#fff"; - - if (noFixedPosition) - this.fixIEPosition(); - - var doc = FirebugChrome.chromeMap.frame.document; - - var mini = $("fbMiniChrome", doc); - mini.style.display = "none"; - - Controller.shutdown.apply(this); - - this.isInitialized = false; - }, - - draw: function() - { - - }, - - fixIEPosition: ChromeFrameBase.fixIEPosition - -}); - - -// ************************************************************************************************ -// ChromePopupBase - -/** - * @namespace - * @extends ns-chrome-ChromeBase - */ -var ChromePopupBase = extend(ChromeBase, -/**@extend ns-chrome-ChromePopupBase*/ -{ - - initialize: function() - { - setClass(this.document.body, "FirebugPopup"); - - ChromeBase.initialize.call(this); - - this.addController( - [Firebug.chrome.window, "resize", this.resize], - [Firebug.chrome.window, "unload", this.destroy] - //[Firebug.chrome.window, "beforeunload", this.destroy] - ); - - if (Env.Options.enablePersistent) - { - this.persist = bind(this.persist, this); - addEvent(Firebug.browser.window, "unload", this.persist); - } - else - this.addController( - [Firebug.browser.window, "unload", this.close] - ); - - fbVSplitter.onmousedown = onVSplitterMouseDown; - }, - - destroy: function() - { - var chromeWin = Firebug.chrome.window; - var left = chromeWin.screenX || chromeWin.screenLeft; - var top = chromeWin.screenY || chromeWin.screenTop; - var size = Firebug.chrome.getWindowSize(); - - Firebug.context.persistedState.popupTop = top; - Firebug.context.persistedState.popupLeft = left; - Firebug.context.persistedState.popupWidth = size.width; - Firebug.context.persistedState.popupHeight = size.height; - - if (Firebug.saveCookies) - Firebug.savePrefs(); - - // TODO: xxxpedro sync detach reattach attach - var frame = FirebugChrome.chromeMap.frame; - - if(frame) - { - dispatch(frame.panelMap, "detach", [this, frame]); - - frame.reattach(this, frame); - } - - if (Env.Options.enablePersistent) - { - removeEvent(Firebug.browser.window, "unload", this.persist); - } - - ChromeBase.destroy.apply(this); - - FirebugChrome.chromeMap.popup = null; - - this.node.close(); - }, - - persist: function() - { - persistTimeStart = new Date().getTime(); - - removeEvent(Firebug.browser.window, "unload", this.persist); - - Firebug.Inspector.destroy(); - Firebug.browser.window.FirebugOldBrowser = true; - - var persistTimeStart = new Date().getTime(); - - var waitMainWindow = function() - { - var doc, head; - - try - { - if (window.opener && !window.opener.FirebugOldBrowser && (doc = window.opener.document)/* && - doc.documentElement && (head = doc.documentElement.firstChild)*/) - { - - try - { - // exposes the FBL to the global namespace when in debug mode - if (Env.isDebugMode) - { - window.FBL = FBL; - } - - window.Firebug = Firebug; - window.opener.Firebug = Firebug; - - Env.browser = window.opener; - Firebug.browser = Firebug.context = new Context(Env.browser); - Firebug.loadPrefs(); - - registerConsole(); - - // the delay time should be calculated right after registering the - // console, once right after the console registration, call log messages - // will be properly handled - var persistDelay = new Date().getTime() - persistTimeStart; - - var chrome = Firebug.chrome; - addEvent(Firebug.browser.window, "unload", chrome.persist); - - FBL.cacheDocument(); - Firebug.Inspector.create(); - - Firebug.Console.logFormatted( - ["Firebug could not capture console calls during " + - persistDelay + "ms"], - Firebug.context, - "info" - ); - - setTimeout(function(){ - var htmlPanel = chrome.getPanel("HTML"); - htmlPanel.createUI(); - },50); - - } - catch(pE) - { - alert("persist error: " + (pE.message || pE)); - } - - } - else - { - window.setTimeout(waitMainWindow, 0); - } - - } catch (E) { - window.close(); - } - }; - - waitMainWindow(); - }, - - close: function() - { - this.destroy(); - } - -}); - - -//************************************************************************************************ -// UI helpers - -var changeCommandLineVisibility = function changeCommandLineVisibility(visibility) -{ - var last = Firebug.chrome.commandLineVisible; - var visible = Firebug.chrome.commandLineVisible = - typeof visibility == "boolean" ? visibility : !Firebug.chrome.commandLineVisible; - - if (visible != last) - { - if (visible) - { - fbBottom.className = ""; - - if (Firebug.CommandLine) - Firebug.CommandLine.activate(); - } - else - { - if (Firebug.CommandLine) - Firebug.CommandLine.deactivate(); - - fbBottom.className = "hide"; - } - } -}; - -var changeSidePanelVisibility = function changeSidePanelVisibility(visibility) -{ - var last = Firebug.chrome.sidePanelVisible; - Firebug.chrome.sidePanelVisible = - typeof visibility == "boolean" ? visibility : !Firebug.chrome.sidePanelVisible; - - if (Firebug.chrome.sidePanelVisible != last) - { - fbPanelBox2.className = Firebug.chrome.sidePanelVisible ? "" : "hide"; - fbPanelBar2Box.className = Firebug.chrome.sidePanelVisible ? "" : "hide"; - } -}; - - -// ************************************************************************************************ -// F12 Handler - -var onGlobalKeyDown = function onGlobalKeyDown(event) -{ - var keyCode = event.keyCode; - var shiftKey = event.shiftKey; - var ctrlKey = event.ctrlKey; - - if (keyCode == 123 /* F12 */ && (!isFirefox && !shiftKey || shiftKey && isFirefox)) - { - Firebug.chrome.toggle(false, ctrlKey); - cancelEvent(event, true); - - // TODO: xxxpedro replace with a better solution. we're doing this - // to allow reactivating with the F12 key after being deactivated - if (Env.isChromeExtension) - { - Firebug.GoogleChrome.dispatch("FB_enableIcon"); - } - } - else if (keyCode == 67 /* C */ && ctrlKey && shiftKey) - { - Firebug.Inspector.toggleInspect(); - cancelEvent(event, true); - } - else if (keyCode == 76 /* L */ && ctrlKey && shiftKey) - { - Firebug.chrome.focusCommandLine(); - cancelEvent(event, true); - } -}; - -var onMiniIconClick = function onMiniIconClick(event) -{ - Firebug.chrome.toggle(false, event.ctrlKey); - cancelEvent(event, true); -}; - - -// ************************************************************************************************ -// Horizontal Splitter Handling - -var onHSplitterMouseDown = function onHSplitterMouseDown(event) -{ - addGlobalEvent("mousemove", onHSplitterMouseMove); - addGlobalEvent("mouseup", onHSplitterMouseUp); - - if (isIE) - addEvent(Firebug.browser.document.documentElement, "mouseleave", onHSplitterMouseUp); - - fbHSplitter.className = "fbOnMovingHSplitter"; - - return false; -}; - -var onHSplitterMouseMove = function onHSplitterMouseMove(event) -{ - cancelEvent(event, true); - - var clientY = event.clientY; - var win = isIE - ? event.srcElement.ownerDocument.parentWindow - : event.target.defaultView || event.target.ownerDocument && event.target.ownerDocument.defaultView; - - if (!win) - return; - - if (win != win.parent) - { - var frameElement = win.frameElement; - if (frameElement) - { - var framePos = Firebug.browser.getElementPosition(frameElement).top; - clientY += framePos; - - if (frameElement.style.position != "fixed") - clientY -= Firebug.browser.getWindowScrollPosition().top; - } - } - - if (isOpera && isQuiksMode && win.frameElement.id == "FirebugUI") - { - clientY = Firebug.browser.getWindowSize().height - win.frameElement.offsetHeight + clientY; - } - - /* - console.log( - typeof win.FBL != "undefined" ? "no-Chrome" : "Chrome", - //win.frameElement.id, - event.target, - clientY - );/**/ - - onHSplitterMouseMoveBuffer = clientY; // buffer - - if (new Date().getTime() - lastHSplitterMouseMove > chromeRedrawSkipRate) // frame skipping - { - lastHSplitterMouseMove = new Date().getTime(); - handleHSplitterMouseMove(); - } - else - if (!onHSplitterMouseMoveTimer) - onHSplitterMouseMoveTimer = setTimeout(handleHSplitterMouseMove, chromeRedrawSkipRate); - - // improving the resizing performance by canceling the mouse event. - // canceling events will prevent the page to receive such events, which would imply - // in more processing being expended. - cancelEvent(event, true); - return false; -}; - -var handleHSplitterMouseMove = function() -{ - if (onHSplitterMouseMoveTimer) - { - clearTimeout(onHSplitterMouseMoveTimer); - onHSplitterMouseMoveTimer = null; - } - - var clientY = onHSplitterMouseMoveBuffer; - - var windowSize = Firebug.browser.getWindowSize(); - var scrollSize = Firebug.browser.getWindowScrollSize(); - - // compute chrome fixed size (top bar and command line) - var commandLineHeight = Firebug.chrome.commandLineVisible ? fbCommandLine.offsetHeight : 0; - var fixedHeight = topHeight + commandLineHeight; - var chromeNode = Firebug.chrome.node; - - var scrollbarSize = !isIE && (scrollSize.width > windowSize.width) ? 17 : 0; - - //var height = !isOpera ? chromeNode.offsetTop + chromeNode.clientHeight : windowSize.height; - var height = windowSize.height; - - // compute the min and max size of the chrome - var chromeHeight = Math.max(height - clientY + 5 - scrollbarSize, fixedHeight); - chromeHeight = Math.min(chromeHeight, windowSize.height - scrollbarSize); - - Firebug.context.persistedState.height = chromeHeight; - chromeNode.style.height = chromeHeight + "px"; - - if (noFixedPosition) - Firebug.chrome.fixIEPosition(); - - Firebug.chrome.draw(); -}; - -var onHSplitterMouseUp = function onHSplitterMouseUp(event) -{ - removeGlobalEvent("mousemove", onHSplitterMouseMove); - removeGlobalEvent("mouseup", onHSplitterMouseUp); - - if (isIE) - removeEvent(Firebug.browser.document.documentElement, "mouseleave", onHSplitterMouseUp); - - fbHSplitter.className = ""; - - Firebug.chrome.draw(); - - // avoid text selection in IE when returning to the document - // after the mouse leaves the document during the resizing - return false; -}; - - -// ************************************************************************************************ -// Vertical Splitter Handling - -var onVSplitterMouseDown = function onVSplitterMouseDown(event) -{ - addGlobalEvent("mousemove", onVSplitterMouseMove); - addGlobalEvent("mouseup", onVSplitterMouseUp); - - return false; -}; - -var onVSplitterMouseMove = function onVSplitterMouseMove(event) -{ - if (new Date().getTime() - lastVSplitterMouseMove > chromeRedrawSkipRate) // frame skipping - { - var target = event.target || event.srcElement; - if (target && target.ownerDocument) // avoid error when cursor reaches out of the chrome - { - var clientX = event.clientX; - var win = document.all - ? event.srcElement.ownerDocument.parentWindow - : event.target.ownerDocument.defaultView; - - if (win != win.parent) - clientX += win.frameElement ? win.frameElement.offsetLeft : 0; - - var size = Firebug.chrome.getSize(); - var x = Math.max(size.width - clientX + 3, 6); - - Firebug.context.persistedState.sidePanelWidth = x; - Firebug.chrome.draw(); - } - - lastVSplitterMouseMove = new Date().getTime(); - } - - cancelEvent(event, true); - return false; -}; - -var onVSplitterMouseUp = function onVSplitterMouseUp(event) -{ - removeGlobalEvent("mousemove", onVSplitterMouseMove); - removeGlobalEvent("mouseup", onVSplitterMouseUp); - - Firebug.chrome.draw(); -}; - - -// ************************************************************************************************ -}}); - -/* See license.txt for terms of usage */ - -FBL.ns(function() { with (FBL) { -// ************************************************************************************************ - -Firebug.Lite = -{ -}; - -// ************************************************************************************************ -}}); - - -/* See license.txt for terms of usage */ - -FBL.ns(function() { with (FBL) { -// ************************************************************************************************ - -Firebug.Lite.Cache = -{ - ID: "firebug-" + new Date().getTime() -}; - -// ************************************************************************************************ - -/** - * TODO: if a cached element is cloned, the expando property will be cloned too in IE - * which will result in a bug. Firebug Lite will think the new cloned node is the old - * one. - * - * TODO: Investigate a possibility of cache validation, to be customized by each - * kind of cache. For ElementCache it should validate if the element still is - * inserted at the DOM. - */ -var cacheUID = 0; -var createCache = function() -{ - var map = {}; - var data = {}; - - var CID = Firebug.Lite.Cache.ID; - - // better detection - var supportsDeleteExpando = !document.all; - - var cacheFunction = function(element) - { - return cacheAPI.set(element); - }; - - var cacheAPI = - { - get: function(key) - { - return map.hasOwnProperty(key) ? - map[key] : - null; - }, - - set: function(element) - { - var id = getValidatedKey(element); - - if (!id) - { - id = ++cacheUID; - element[CID] = id; - } - - if (!map.hasOwnProperty(id)) - { - map[id] = element; - data[id] = {}; - } - - return id; - }, - - unset: function(element) - { - var id = getValidatedKey(element); - - if (!id) return; - - if (supportsDeleteExpando) - { - delete element[CID]; - } - else if (element.removeAttribute) - { - element.removeAttribute(CID); - } - - delete map[id]; - delete data[id]; - - }, - - key: function(element) - { - return getValidatedKey(element); - }, - - has: function(element) - { - var id = getValidatedKey(element); - return id && map.hasOwnProperty(id); - }, - - each: function(callback) - { - for (var key in map) - { - if (map.hasOwnProperty(key)) - { - callback(key, map[key]); - } - } - }, - - data: function(element, name, value) - { - // set data - if (value) - { - if (!name) return null; - - var id = cacheAPI.set(element); - - return data[id][name] = value; - } - // get data - else - { - var id = cacheAPI.key(element); - - return data.hasOwnProperty(id) && data[id].hasOwnProperty(name) ? - data[id][name] : - null; - } - }, - - clear: function() - { - for (var id in map) - { - var element = map[id]; - cacheAPI.unset(element); - } - } - }; - - var getValidatedKey = function(element) - { - var id = element[CID]; - - // If a cached element is cloned in IE, the expando property CID will be also - // cloned (differently than other browsers) resulting in a bug: Firebug Lite - // will think the new cloned node is the old one. To prevent this problem we're - // checking if the cached element matches the given element. - if ( - !supportsDeleteExpando && // the problem happens when supportsDeleteExpando is false - id && // the element has the expando property - map.hasOwnProperty(id) && // there is a cached element with the same id - map[id] != element // but it is a different element than the current one - ) - { - // remove the problematic property - element.removeAttribute(CID); - - id = null; - } - - return id; - }; - - FBL.append(cacheFunction, cacheAPI); - - return cacheFunction; -}; - -// ************************************************************************************************ - -// TODO: xxxpedro : check if we need really this on FBL scope -Firebug.Lite.Cache.StyleSheet = createCache(); -Firebug.Lite.Cache.Element = createCache(); - -// TODO: xxxpedro -Firebug.Lite.Cache.Event = createCache(); - - -// ************************************************************************************************ -}}); - - -/* See license.txt for terms of usage */ - -FBL.ns(function() { with (FBL) { -// ************************************************************************************************ - -// ************************************************************************************************ -var sourceMap = {}; - -// ************************************************************************************************ -Firebug.Lite.Proxy = -{ - // jsonp callbacks - _callbacks: {}, - - /** - * Load a resource, either locally (directly) or externally (via proxy) using - * synchronous XHR calls. Loading external resources requires the proxy plugin to - * be installed and configured (see /plugin/proxy/proxy.php). - */ - load: function(url) - { - var resourceDomain = getDomain(url); - var isLocalResource = - // empty domain means local URL - !resourceDomain || - // same domain means local too - resourceDomain == Firebug.context.window.location.host; // TODO: xxxpedro context - - return isLocalResource ? fetchResource(url) : fetchProxyResource(url); - }, - - /** - * Load a resource using JSONP technique. - */ - loadJSONP: function(url, callback) - { - var script = createGlobalElement("script"), - doc = Firebug.context.document, - - uid = "" + new Date().getTime(), - callbackName = "callback=Firebug.Lite.Proxy._callbacks." + uid, - - jsonpURL = url.indexOf("?") != -1 ? - url + "&" + callbackName : - url + "?" + callbackName; - - Firebug.Lite.Proxy._callbacks[uid] = function(data) - { - if (callback) - callback(data); - - script.parentNode.removeChild(script); - delete Firebug.Lite.Proxy._callbacks[uid]; - }; - - script.src = jsonpURL; - - if (doc.documentElement) - doc.documentElement.appendChild(script); - }, - - /** - * Load a resource using YQL (not reliable). - */ - YQL: function(url, callback) - { - var yql = "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20html%20where%20url%3D%22" + - encodeURIComponent(url) + "%22&format=xml"; - - this.loadJSONP(yql, function(data) - { - var source = data.results[0]; - - // clean up YQL bogus elements - var match = /<body>\s+<p>([\s\S]+)<\/p>\s+<\/body>$/.exec(source); - if (match) - source = match[1]; - - console.log(source); - }); - } -}; - -// ************************************************************************************************ - -Firebug.Lite.Proxy.fetchResourceDisabledMessage = - "/* Firebug Lite resource fetching is disabled.\n" + - "To enabled it set the Firebug Lite option \"disableResourceFetching\" to \"false\".\n" + - "More info at http://getfirebug.com/firebuglite#Options */"; - -var fetchResource = function(url) -{ - if (Firebug.disableResourceFetching) - { - var source = sourceMap[url] = Firebug.Lite.Proxy.fetchResourceDisabledMessage; - return source; - } - - if (sourceMap.hasOwnProperty(url)) - return sourceMap[url]; - - // Getting the native XHR object so our calls won't be logged in the Console Panel - var xhr = FBL.getNativeXHRObject(); - xhr.open("get", url, false); - xhr.send(); - - var source = sourceMap[url] = xhr.responseText; - return source; -}; - -var fetchProxyResource = function(url) -{ - if (sourceMap.hasOwnProperty(url)) - return sourceMap[url]; - - var proxyURL = Env.Location.baseDir + "plugin/proxy/proxy.php?url=" + encodeURIComponent(url); - var response = fetchResource(proxyURL); - - try - { - var data = eval("(" + response + ")"); - } - catch(E) - { - return "ERROR: Firebug Lite Proxy plugin returned an invalid response."; - } - - var source = data ? data.contents : ""; - return source; -}; - - -// ************************************************************************************************ -}}); - - -/* See license.txt for terms of usage */ - -FBL.ns(function() { with (FBL) { -// ************************************************************************************************ - -Firebug.Lite.Style = -{ -}; - -// ************************************************************************************************ -}}); - - -/* See license.txt for terms of usage */ - -FBL.ns(function() { with (FBL) { -// ************************************************************************************************ - -Firebug.Lite.Script = function(window) -{ - this.fileName = null; - this.isValid = null; - this.baseLineNumber = null; - this.lineExtent = null; - this.tag = null; - - this.functionName = null; - this.functionSource = null; -}; - -Firebug.Lite.Script.prototype = -{ - isLineExecutable: function(){}, - pcToLine: function(){}, - lineToPc: function(){}, - - toString: function() - { - return "Firebug.Lite.Script"; - } -}; - -// ************************************************************************************************ -}}); - - -/* See license.txt for terms of usage */ - -FBL.ns(function() { with (FBL) { -// ************************************************************************************************ - - -Firebug.Lite.Browser = function(window) -{ - this.contentWindow = window; - this.contentDocument = window.document; - this.currentURI = - { - spec: window.location.href - }; -}; - -Firebug.Lite.Browser.prototype = -{ - toString: function() - { - return "Firebug.Lite.Browser"; - } -}; - - -// ************************************************************************************************ -}}); - - -/* See license.txt for terms of usage */ - -/* - http://www.JSON.org/json2.js - 2010-03-20 - - Public Domain. - - NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. - - See http://www.JSON.org/js.html - - - This code should be minified before deployment. - See http://javascript.crockford.com/jsmin.html - - USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO - NOT CONTROL. - - - This file creates a global JSON object containing two methods: stringify - and parse. - - JSON.stringify(value, replacer, space) - value any JavaScript value, usually an object or array. - - replacer an optional parameter that determines how object - values are stringified for objects. It can be a - function or an array of strings. - - space an optional parameter that specifies the indentation - of nested structures. If it is omitted, the text will - be packed without extra whitespace. If it is a number, - it will specify the number of spaces to indent at each - level. If it is a string (such as '\t' or ' '), - it contains the characters used to indent at each level. - - This method produces a JSON text from a JavaScript value. - - When an object value is found, if the object contains a toJSON - method, its toJSON method will be called and the result will be - stringified. A toJSON method does not serialize: it returns the - value represented by the name/value pair that should be serialized, - or undefined if nothing should be serialized. The toJSON method - will be passed the key associated with the value, and this will be - bound to the value - - For example, this would serialize Dates as ISO strings. - - Date.prototype.toJSON = function (key) { - function f(n) { - // Format integers to have at least two digits. - return n < 10 ? '0' + n : n; - } - - return this.getUTCFullYear() + '-' + - f(this.getUTCMonth() + 1) + '-' + - f(this.getUTCDate()) + 'T' + - f(this.getUTCHours()) + ':' + - f(this.getUTCMinutes()) + ':' + - f(this.getUTCSeconds()) + 'Z'; - }; - - You can provide an optional replacer method. It will be passed the - key and value of each member, with this bound to the containing - object. The value that is returned from your method will be - serialized. If your method returns undefined, then the member will - be excluded from the serialization. - - If the replacer parameter is an array of strings, then it will be - used to select the members to be serialized. It filters the results - such that only members with keys listed in the replacer array are - stringified. - - Values that do not have JSON representations, such as undefined or - functions, will not be serialized. Such values in objects will be - dropped; in arrays they will be replaced with null. You can use - a replacer function to replace those with JSON values. - JSON.stringify(undefined) returns undefined. - - The optional space parameter produces a stringification of the - value that is filled with line breaks and indentation to make it - easier to read. - - If the space parameter is a non-empty string, then that string will - be used for indentation. If the space parameter is a number, then - the indentation will be that many spaces. - - Example: - - text = JSON.stringify(['e', {pluribus: 'unum'}]); - // text is '["e",{"pluribus":"unum"}]' - - - text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t'); - // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]' - - text = JSON.stringify([new Date()], function (key, value) { - return this[key] instanceof Date ? - 'Date(' + this[key] + ')' : value; - }); - // text is '["Date(---current time---)"]' - - - JSON.parse(text, reviver) - This method parses a JSON text to produce an object or array. - It can throw a SyntaxError exception. - - The optional reviver parameter is a function that can filter and - transform the results. It receives each of the keys and values, - and its return value is used instead of the original value. - If it returns what it received, then the structure is not modified. - If it returns undefined then the member is deleted. - - Example: - - // Parse the text. Values that look like ISO date strings will - // be converted to Date objects. - - myData = JSON.parse(text, function (key, value) { - var a; - if (typeof value === 'string') { - a = -/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value); - if (a) { - return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], - +a[5], +a[6])); - } - } - return value; - }); - - myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) { - var d; - if (typeof value === 'string' && - value.slice(0, 5) === 'Date(' && - value.slice(-1) === ')') { - d = new Date(value.slice(5, -1)); - if (d) { - return d; - } - } - return value; - }); - - - This is a reference implementation. You are free to copy, modify, or - redistribute. -*/ - -/*jslint evil: true, strict: false */ - -/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply, - call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours, - getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join, - lastIndex, length, parse, prototype, push, replace, slice, stringify, - test, toJSON, toString, valueOf -*/ - - -// Create a JSON object only if one does not already exist. We create the -// methods in a closure to avoid creating global variables. - -// ************************************************************************************************ - -var JSON = window.JSON || {}; - -// ************************************************************************************************ - -(function () { - - function f(n) { - // Format integers to have at least two digits. - return n < 10 ? '0' + n : n; - } - - if (typeof Date.prototype.toJSON !== 'function') { - - Date.prototype.toJSON = function (key) { - - return isFinite(this.valueOf()) ? - this.getUTCFullYear() + '-' + - f(this.getUTCMonth() + 1) + '-' + - f(this.getUTCDate()) + 'T' + - f(this.getUTCHours()) + ':' + - f(this.getUTCMinutes()) + ':' + - f(this.getUTCSeconds()) + 'Z' : null; - }; - - String.prototype.toJSON = - Number.prototype.toJSON = - Boolean.prototype.toJSON = function (key) { - return this.valueOf(); - }; - } - - var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, - escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, - gap, - indent, - meta = { // table of character substitutions - '\b': '\\b', - '\t': '\\t', - '\n': '\\n', - '\f': '\\f', - '\r': '\\r', - '"' : '\\"', - '\\': '\\\\' - }, - rep; - - - function quote(string) { - -// If the string contains no control characters, no quote characters, and no -// backslash characters, then we can safely slap some quotes around it. -// Otherwise we must also replace the offending characters with safe escape -// sequences. - - escapable.lastIndex = 0; - return escapable.test(string) ? - '"' + string.replace(escapable, function (a) { - var c = meta[a]; - return typeof c === 'string' ? c : - '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); - }) + '"' : - '"' + string + '"'; - } - - - function str(key, holder) { - -// Produce a string from holder[key]. - - var i, // The loop counter. - k, // The member key. - v, // The member value. - length, - mind = gap, - partial, - value = holder[key]; - -// If the value has a toJSON method, call it to obtain a replacement value. - - if (value && typeof value === 'object' && - typeof value.toJSON === 'function') { - value = value.toJSON(key); - } - -// If we were called with a replacer function, then call the replacer to -// obtain a replacement value. - - if (typeof rep === 'function') { - value = rep.call(holder, key, value); - } - -// What happens next depends on the value's type. - - switch (typeof value) { - case 'string': - return quote(value); - - case 'number': - -// JSON numbers must be finite. Encode non-finite numbers as null. - - return isFinite(value) ? String(value) : 'null'; - - case 'boolean': - case 'null': - -// If the value is a boolean or null, convert it to a string. Note: -// typeof null does not produce 'null'. The case is included here in -// the remote chance that this gets fixed someday. - - return String(value); - -// If the type is 'object', we might be dealing with an object or an array or -// null. - - case 'object': - -// Due to a specification blunder in ECMAScript, typeof null is 'object', -// so watch out for that case. - - if (!value) { - return 'null'; - } - -// Make an array to hold the partial results of stringifying this object value. - - gap += indent; - partial = []; - -// Is the value an array? - - if (Object.prototype.toString.apply(value) === '[object Array]') { - -// The value is an array. Stringify every element. Use null as a placeholder -// for non-JSON values. - - length = value.length; - for (i = 0; i < length; i += 1) { - partial[i] = str(i, value) || 'null'; - } - -// Join all of the elements together, separated with commas, and wrap them in -// brackets. - - v = partial.length === 0 ? '[]' : - gap ? '[\n' + gap + - partial.join(',\n' + gap) + '\n' + - mind + ']' : - '[' + partial.join(',') + ']'; - gap = mind; - return v; - } - -// If the replacer is an array, use it to select the members to be stringified. - - if (rep && typeof rep === 'object') { - length = rep.length; - for (i = 0; i < length; i += 1) { - k = rep[i]; - if (typeof k === 'string') { - v = str(k, value); - if (v) { - partial.push(quote(k) + (gap ? ': ' : ':') + v); - } - } - } - } else { - -// Otherwise, iterate through all of the keys in the object. - - for (k in value) { - if (Object.hasOwnProperty.call(value, k)) { - v = str(k, value); - if (v) { - partial.push(quote(k) + (gap ? ': ' : ':') + v); - } - } - } - } - -// Join all of the member texts together, separated with commas, -// and wrap them in braces. - - v = partial.length === 0 ? '{}' : - gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + - mind + '}' : '{' + partial.join(',') + '}'; - gap = mind; - return v; - } - } - -// If the JSON object does not yet have a stringify method, give it one. - - if (typeof JSON.stringify !== 'function') { - JSON.stringify = function (value, replacer, space) { - -// The stringify method takes a value and an optional replacer, and an optional -// space parameter, and returns a JSON text. The replacer can be a function -// that can replace values, or an array of strings that will select the keys. -// A default replacer method can be provided. Use of the space parameter can -// produce text that is more easily readable. - - var i; - gap = ''; - indent = ''; - -// If the space parameter is a number, make an indent string containing that -// many spaces. - - if (typeof space === 'number') { - for (i = 0; i < space; i += 1) { - indent += ' '; - } - -// If the space parameter is a string, it will be used as the indent string. - - } else if (typeof space === 'string') { - indent = space; - } - -// If there is a replacer, it must be a function or an array. -// Otherwise, throw an error. - - rep = replacer; - if (replacer && typeof replacer !== 'function' && - (typeof replacer !== 'object' || - typeof replacer.length !== 'number')) { - throw new Error('JSON.stringify'); - } - -// Make a fake root object containing our value under the key of ''. -// Return the result of stringifying the value. - - return str('', {'': value}); - }; - } - - -// If the JSON object does not yet have a parse method, give it one. - - if (typeof JSON.parse !== 'function') { - JSON.parse = function (text, reviver) { - -// The parse method takes a text and an optional reviver function, and returns -// a JavaScript value if the text is a valid JSON text. - - var j; - - function walk(holder, key) { - -// The walk method is used to recursively walk the resulting structure so -// that modifications can be made. - - var k, v, value = holder[key]; - if (value && typeof value === 'object') { - for (k in value) { - if (Object.hasOwnProperty.call(value, k)) { - v = walk(value, k); - if (v !== undefined) { - value[k] = v; - } else { - delete value[k]; - } - } - } - } - return reviver.call(holder, key, value); - } - - -// Parsing happens in four stages. In the first stage, we replace certain -// Unicode characters with escape sequences. JavaScript handles many characters -// incorrectly, either silently deleting them, or treating them as line endings. - - text = String(text); - cx.lastIndex = 0; - if (cx.test(text)) { - text = text.replace(cx, function (a) { - return '\\u' + - ('0000' + a.charCodeAt(0).toString(16)).slice(-4); - }); - } - -// In the second stage, we run the text against regular expressions that look -// for non-JSON patterns. We are especially concerned with '()' and 'new' -// because they can cause invocation, and '=' because it can cause mutation. -// But just to be safe, we want to reject all unexpected forms. - -// We split the second stage into 4 regexp operations in order to work around -// crippling inefficiencies in IE's and Safari's regexp engines. First we -// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we -// replace all simple value tokens with ']' characters. Third, we delete all -// open brackets that follow a colon or comma or that begin the text. Finally, -// we look to see that the remaining characters are only whitespace or ']' or -// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval. - - if (/^[\],:{}\s]*$/. -test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@'). -replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']'). -replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { - -// In the third stage we use the eval function to compile the text into a -// JavaScript structure. The '{' operator is subject to a syntactic ambiguity -// in JavaScript: it can begin a block or an object literal. We wrap the text -// in parens to eliminate the ambiguity. - - j = eval('(' + text + ')'); - -// In the optional fourth stage, we recursively walk the new structure, passing -// each name/value pair to a reviver function for possible transformation. - - return typeof reviver === 'function' ? - walk({'': j}, '') : j; - } - -// If the text is not JSON parseable, then a SyntaxError is thrown. - - throw new SyntaxError('JSON.parse'); - }; - } - -// ************************************************************************************************ -// registration - -FBL.JSON = JSON; - -// ************************************************************************************************ -}()); - -/* See license.txt for terms of usage */ - -(function(){ -// ************************************************************************************************ - -/* Copyright (c) 2010-2011 Marcus Westin - * - * 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. - */ - -var store = (function(){ - var api = {}, - win = window, - doc = win.document, - localStorageName = 'localStorage', - globalStorageName = 'globalStorage', - namespace = '__firebug__storejs__', - storage - - api.disabled = false - api.set = function(key, value) {} - api.get = function(key) {} - api.remove = function(key) {} - api.clear = function() {} - api.transact = function(key, transactionFn) { - var val = api.get(key) - if (typeof val == 'undefined') { val = {} } - transactionFn(val) - api.set(key, val) - } - - api.serialize = function(value) { - return JSON.stringify(value) - } - api.deserialize = function(value) { - if (typeof value != 'string') { return undefined } - return JSON.parse(value) - } - - // Functions to encapsulate questionable FireFox 3.6.13 behavior - // when about.config::dom.storage.enabled === false - // See https://github.com/marcuswestin/store.js/issues#issue/13 - function isLocalStorageNameSupported() { - try { return (localStorageName in win && win[localStorageName]) } - catch(err) { return false } - } - - function isGlobalStorageNameSupported() { - try { return (globalStorageName in win && win[globalStorageName] && win[globalStorageName][win.location.hostname]) } - catch(err) { return false } - } - - if (isLocalStorageNameSupported()) { - storage = win[localStorageName] - api.set = function(key, val) { storage.setItem(key, api.serialize(val)) } - api.get = function(key) { return api.deserialize(storage.getItem(key)) } - api.remove = function(key) { storage.removeItem(key) } - api.clear = function() { storage.clear() } - - } else if (isGlobalStorageNameSupported()) { - storage = win[globalStorageName][win.location.hostname] - api.set = function(key, val) { storage[key] = api.serialize(val) } - api.get = function(key) { return api.deserialize(storage[key] && storage[key].value) } - api.remove = function(key) { delete storage[key] } - api.clear = function() { for (var key in storage ) { delete storage[key] } } - - } else if (doc.documentElement.addBehavior) { - var storage = doc.createElement('div') - function withIEStorage(storeFunction) { - return function() { - var args = Array.prototype.slice.call(arguments, 0) - args.unshift(storage) - // See http://msdn.microsoft.com/en-us/library/ms531081(v=VS.85).aspx - // and http://msdn.microsoft.com/en-us/library/ms531424(v=VS.85).aspx - // TODO: xxxpedro doc.body is not always available so we must use doc.documentElement. - // We need to make sure this change won't affect the behavior of this library. - doc.documentElement.appendChild(storage) - storage.addBehavior('#default#userData') - storage.load(localStorageName) - var result = storeFunction.apply(api, args) - doc.documentElement.removeChild(storage) - return result - } - } - api.set = withIEStorage(function(storage, key, val) { - storage.setAttribute(key, api.serialize(val)) - storage.save(localStorageName) - }) - api.get = withIEStorage(function(storage, key) { - return api.deserialize(storage.getAttribute(key)) - }) - api.remove = withIEStorage(function(storage, key) { - storage.removeAttribute(key) - storage.save(localStorageName) - }) - api.clear = withIEStorage(function(storage) { - var attributes = storage.XMLDocument.documentElement.attributes - storage.load(localStorageName) - for (var i=0, attr; attr = attributes[i]; i++) { - storage.removeAttribute(attr.name) - } - storage.save(localStorageName) - }) - } - - try { - api.set(namespace, namespace) - if (api.get(namespace) != namespace) { api.disabled = true } - api.remove(namespace) - } catch(e) { - api.disabled = true - } - - return api -})(); - -if (typeof module != 'undefined') { module.exports = store } - - -// ************************************************************************************************ -// registration - -FBL.Store = store; - -// ************************************************************************************************ -})(); - -/* See license.txt for terms of usage */ - -FBL.ns( /**@scope s_selector*/ function() { with (FBL) { -// ************************************************************************************************ - -/* - * Sizzle CSS Selector Engine - v1.0 - * Copyright 2009, The Dojo Foundation - * Released under the MIT, BSD, and GPL Licenses. - * More information: http://sizzlejs.com/ - */ - -var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, - done = 0, - toString = Object.prototype.toString, - hasDuplicate = false, - baseHasDuplicate = true; - -// Here we check if the JavaScript engine is using some sort of -// optimization where it does not always call our comparision -// function. If that is the case, discard the hasDuplicate value. -// Thus far that includes Google Chrome. -[0, 0].sort(function(){ - baseHasDuplicate = false; - return 0; -}); - -/** - * @name Firebug.Selector - * @namespace - */ - -/** - * @exports Sizzle as Firebug.Selector - */ -var Sizzle = function(selector, context, results, seed) { - results = results || []; - var origContext = context = context || document; - - if ( context.nodeType !== 1 && context.nodeType !== 9 ) { - return []; - } - - if ( !selector || typeof selector !== "string" ) { - return results; - } - - var parts = [], m, set, checkSet, check, mode, extra, prune = true, contextXML = isXML(context), - soFar = selector; - - // Reset the position of the chunker regexp (start from head) - while ( (chunker.exec(""), m = chunker.exec(soFar)) !== null ) { - soFar = m[3]; - - parts.push( m[1] ); - - if ( m[2] ) { - extra = m[3]; - break; - } - } - - if ( parts.length > 1 && origPOS.exec( selector ) ) { - if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { - set = posProcess( parts[0] + parts[1], context ); - } else { - set = Expr.relative[ parts[0] ] ? - [ context ] : - Sizzle( parts.shift(), context ); - - while ( parts.length ) { - selector = parts.shift(); - - if ( Expr.relative[ selector ] ) - selector += parts.shift(); - - set = posProcess( selector, set ); - } - } - } else { - // Take a shortcut and set the context if the root selector is an ID - // (but not if it'll be faster if the inner selector is an ID) - if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && - Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { - var ret = Sizzle.find( parts.shift(), context, contextXML ); - context = ret.expr ? Sizzle.filter( ret.expr, ret.set )[0] : ret.set[0]; - } - - if ( context ) { - var ret = seed ? - { expr: parts.pop(), set: makeArray(seed) } : - Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); - set = ret.expr ? Sizzle.filter( ret.expr, ret.set ) : ret.set; - - if ( parts.length > 0 ) { - checkSet = makeArray(set); - } else { - prune = false; - } - - while ( parts.length ) { - var cur = parts.pop(), pop = cur; - - if ( !Expr.relative[ cur ] ) { - cur = ""; - } else { - pop = parts.pop(); - } - - if ( pop == null ) { - pop = context; - } - - Expr.relative[ cur ]( checkSet, pop, contextXML ); - } - } else { - checkSet = parts = []; - } - } - - if ( !checkSet ) { - checkSet = set; - } - - if ( !checkSet ) { - throw "Syntax error, unrecognized expression: " + (cur || selector); - } - - if ( toString.call(checkSet) === "[object Array]" ) { - if ( !prune ) { - results.push.apply( results, checkSet ); - } else if ( context && context.nodeType === 1 ) { - for ( var i = 0; checkSet[i] != null; i++ ) { - if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) { - results.push( set[i] ); - } - } - } else { - for ( var i = 0; checkSet[i] != null; i++ ) { - if ( checkSet[i] && checkSet[i].nodeType === 1 ) { - results.push( set[i] ); - } - } - } - } else { - makeArray( checkSet, results ); - } - - if ( extra ) { - Sizzle( extra, origContext, results, seed ); - Sizzle.uniqueSort( results ); - } - - return results; -}; - -Sizzle.uniqueSort = function(results){ - if ( sortOrder ) { - hasDuplicate = baseHasDuplicate; - results.sort(sortOrder); - - if ( hasDuplicate ) { - for ( var i = 1; i < results.length; i++ ) { - if ( results[i] === results[i-1] ) { - results.splice(i--, 1); - } - } - } - } - - return results; -}; - -Sizzle.matches = function(expr, set){ - return Sizzle(expr, null, null, set); -}; - -Sizzle.find = function(expr, context, isXML){ - var set, match; - - if ( !expr ) { - return []; - } - - for ( var i = 0, l = Expr.order.length; i < l; i++ ) { - var type = Expr.order[i], match; - - if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { - var left = match[1]; - match.splice(1,1); - - if ( left.substr( left.length - 1 ) !== "\\" ) { - match[1] = (match[1] || "").replace(/\\/g, ""); - set = Expr.find[ type ]( match, context, isXML ); - if ( set != null ) { - expr = expr.replace( Expr.match[ type ], "" ); - break; - } - } - } - } - - if ( !set ) { - set = context.getElementsByTagName("*"); - } - - return {set: set, expr: expr}; -}; - -Sizzle.filter = function(expr, set, inplace, not){ - var old = expr, result = [], curLoop = set, match, anyFound, - isXMLFilter = set && set[0] && isXML(set[0]); - - while ( expr && set.length ) { - for ( var type in Expr.filter ) { - if ( (match = Expr.match[ type ].exec( expr )) != null ) { - var filter = Expr.filter[ type ], found, item; - anyFound = false; - - if ( curLoop == result ) { - result = []; - } - - if ( Expr.preFilter[ type ] ) { - match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); - - if ( !match ) { - anyFound = found = true; - } else if ( match === true ) { - continue; - } - } - - if ( match ) { - for ( var i = 0; (item = curLoop[i]) != null; i++ ) { - if ( item ) { - found = filter( item, match, i, curLoop ); - var pass = not ^ !!found; - - if ( inplace && found != null ) { - if ( pass ) { - anyFound = true; - } else { - curLoop[i] = false; - } - } else if ( pass ) { - result.push( item ); - anyFound = true; - } - } - } - } - - if ( found !== undefined ) { - if ( !inplace ) { - curLoop = result; - } - - expr = expr.replace( Expr.match[ type ], "" ); - - if ( !anyFound ) { - return []; - } - - break; - } - } - } - - // Improper expression - if ( expr == old ) { - if ( anyFound == null ) { - throw "Syntax error, unrecognized expression: " + expr; - } else { - break; - } - } - - old = expr; - } - - return curLoop; -}; - -/**#@+ @ignore */ -var Expr = Sizzle.selectors = { - order: [ "ID", "NAME", "TAG" ], - match: { - ID: /#((?:[\w\u00c0-\uFFFF-]|\\.)+)/, - CLASS: /\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/, - NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/, - ATTR: /\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/, - TAG: /^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/, - CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/, - POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/, - PSEUDO: /:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/ - }, - leftMatch: {}, - attrMap: { - "class": "className", - "for": "htmlFor" - }, - attrHandle: { - href: function(elem){ - return elem.getAttribute("href"); - } - }, - relative: { - "+": function(checkSet, part, isXML){ - var isPartStr = typeof part === "string", - isTag = isPartStr && !/\W/.test(part), - isPartStrNotTag = isPartStr && !isTag; - - if ( isTag && !isXML ) { - part = part.toUpperCase(); - } - - for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { - if ( (elem = checkSet[i]) ) { - while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} - - checkSet[i] = isPartStrNotTag || elem && elem.nodeName === part ? - elem || false : - elem === part; - } - } - - if ( isPartStrNotTag ) { - Sizzle.filter( part, checkSet, true ); - } - }, - ">": function(checkSet, part, isXML){ - var isPartStr = typeof part === "string"; - - if ( isPartStr && !/\W/.test(part) ) { - part = isXML ? part : part.toUpperCase(); - - for ( var i = 0, l = checkSet.length; i < l; i++ ) { - var elem = checkSet[i]; - if ( elem ) { - var parent = elem.parentNode; - checkSet[i] = parent.nodeName === part ? parent : false; - } - } - } else { - for ( var i = 0, l = checkSet.length; i < l; i++ ) { - var elem = checkSet[i]; - if ( elem ) { - checkSet[i] = isPartStr ? - elem.parentNode : - elem.parentNode === part; - } - } - - if ( isPartStr ) { - Sizzle.filter( part, checkSet, true ); - } - } - }, - "": function(checkSet, part, isXML){ - var doneName = done++, checkFn = dirCheck; - - if ( !/\W/.test(part) ) { - var nodeCheck = part = isXML ? part : part.toUpperCase(); - checkFn = dirNodeCheck; - } - - checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML); - }, - "~": function(checkSet, part, isXML){ - var doneName = done++, checkFn = dirCheck; - - if ( typeof part === "string" && !/\W/.test(part) ) { - var nodeCheck = part = isXML ? part : part.toUpperCase(); - checkFn = dirNodeCheck; - } - - checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML); - } - }, - find: { - ID: function(match, context, isXML){ - if ( typeof context.getElementById !== "undefined" && !isXML ) { - var m = context.getElementById(match[1]); - return m ? [m] : []; - } - }, - NAME: function(match, context, isXML){ - if ( typeof context.getElementsByName !== "undefined" ) { - var ret = [], results = context.getElementsByName(match[1]); - - for ( var i = 0, l = results.length; i < l; i++ ) { - if ( results[i].getAttribute("name") === match[1] ) { - ret.push( results[i] ); - } - } - - return ret.length === 0 ? null : ret; - } - }, - TAG: function(match, context){ - return context.getElementsByTagName(match[1]); - } - }, - preFilter: { - CLASS: function(match, curLoop, inplace, result, not, isXML){ - match = " " + match[1].replace(/\\/g, "") + " "; - - if ( isXML ) { - return match; - } - - for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { - if ( elem ) { - if ( not ^ (elem.className && (" " + elem.className + " ").indexOf(match) >= 0) ) { - if ( !inplace ) - result.push( elem ); - } else if ( inplace ) { - curLoop[i] = false; - } - } - } - - return false; - }, - ID: function(match){ - return match[1].replace(/\\/g, ""); - }, - TAG: function(match, curLoop){ - for ( var i = 0; curLoop[i] === false; i++ ){} - return curLoop[i] && isXML(curLoop[i]) ? match[1] : match[1].toUpperCase(); - }, - CHILD: function(match){ - if ( match[1] == "nth" ) { - // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' - var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec( - match[2] == "even" && "2n" || match[2] == "odd" && "2n+1" || - !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); - - // calculate the numbers (first)n+(last) including if they are negative - match[2] = (test[1] + (test[2] || 1)) - 0; - match[3] = test[3] - 0; - } - - // TODO: Move to normal caching system - match[0] = done++; - - return match; - }, - ATTR: function(match, curLoop, inplace, result, not, isXML){ - var name = match[1].replace(/\\/g, ""); - - if ( !isXML && Expr.attrMap[name] ) { - match[1] = Expr.attrMap[name]; - } - - if ( match[2] === "~=" ) { - match[4] = " " + match[4] + " "; - } - - return match; - }, - PSEUDO: function(match, curLoop, inplace, result, not){ - if ( match[1] === "not" ) { - // If we're dealing with a complex expression, or a simple one - if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) { - match[3] = Sizzle(match[3], null, null, curLoop); - } else { - var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); - if ( !inplace ) { - result.push.apply( result, ret ); - } - return false; - } - } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { - return true; - } - - return match; - }, - POS: function(match){ - match.unshift( true ); - return match; - } - }, - filters: { - enabled: function(elem){ - return elem.disabled === false && elem.type !== "hidden"; - }, - disabled: function(elem){ - return elem.disabled === true; - }, - checked: function(elem){ - return elem.checked === true; - }, - selected: function(elem){ - // Accessing this property makes selected-by-default - // options in Safari work properly - elem.parentNode.selectedIndex; - return elem.selected === true; - }, - parent: function(elem){ - return !!elem.firstChild; - }, - empty: function(elem){ - return !elem.firstChild; - }, - has: function(elem, i, match){ - return !!Sizzle( match[3], elem ).length; - }, - header: function(elem){ - return /h\d/i.test( elem.nodeName ); - }, - text: function(elem){ - return "text" === elem.type; - }, - radio: function(elem){ - return "radio" === elem.type; - }, - checkbox: function(elem){ - return "checkbox" === elem.type; - }, - file: function(elem){ - return "file" === elem.type; - }, - password: function(elem){ - return "password" === elem.type; - }, - submit: function(elem){ - return "submit" === elem.type; - }, - image: function(elem){ - return "image" === elem.type; - }, - reset: function(elem){ - return "reset" === elem.type; - }, - button: function(elem){ - return "button" === elem.type || elem.nodeName.toUpperCase() === "BUTTON"; - }, - input: function(elem){ - return /input|select|textarea|button/i.test(elem.nodeName); - } - }, - setFilters: { - first: function(elem, i){ - return i === 0; - }, - last: function(elem, i, match, array){ - return i === array.length - 1; - }, - even: function(elem, i){ - return i % 2 === 0; - }, - odd: function(elem, i){ - return i % 2 === 1; - }, - lt: function(elem, i, match){ - return i < match[3] - 0; - }, - gt: function(elem, i, match){ - return i > match[3] - 0; - }, - nth: function(elem, i, match){ - return match[3] - 0 == i; - }, - eq: function(elem, i, match){ - return match[3] - 0 == i; - } - }, - filter: { - PSEUDO: function(elem, match, i, array){ - var name = match[1], filter = Expr.filters[ name ]; - - if ( filter ) { - return filter( elem, i, match, array ); - } else if ( name === "contains" ) { - return (elem.textContent || elem.innerText || "").indexOf(match[3]) >= 0; - } else if ( name === "not" ) { - var not = match[3]; - - for ( var i = 0, l = not.length; i < l; i++ ) { - if ( not[i] === elem ) { - return false; - } - } - - return true; - } - }, - CHILD: function(elem, match){ - var type = match[1], node = elem; - switch (type) { - case 'only': - case 'first': - while ( (node = node.previousSibling) ) { - if ( node.nodeType === 1 ) return false; - } - if ( type == 'first') return true; - node = elem; - case 'last': - while ( (node = node.nextSibling) ) { - if ( node.nodeType === 1 ) return false; - } - return true; - case 'nth': - var first = match[2], last = match[3]; - - if ( first == 1 && last == 0 ) { - return true; - } - - var doneName = match[0], - parent = elem.parentNode; - - if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) { - var count = 0; - for ( node = parent.firstChild; node; node = node.nextSibling ) { - if ( node.nodeType === 1 ) { - node.nodeIndex = ++count; - } - } - parent.sizcache = doneName; - } - - var diff = elem.nodeIndex - last; - if ( first == 0 ) { - return diff == 0; - } else { - return ( diff % first == 0 && diff / first >= 0 ); - } - } - }, - ID: function(elem, match){ - return elem.nodeType === 1 && elem.getAttribute("id") === match; - }, - TAG: function(elem, match){ - return (match === "*" && elem.nodeType === 1) || elem.nodeName === match; - }, - CLASS: function(elem, match){ - return (" " + (elem.className || elem.getAttribute("class")) + " ") - .indexOf( match ) > -1; - }, - ATTR: function(elem, match){ - var name = match[1], - result = Expr.attrHandle[ name ] ? - Expr.attrHandle[ name ]( elem ) : - elem[ name ] != null ? - elem[ name ] : - elem.getAttribute( name ), - value = result + "", - type = match[2], - check = match[4]; - - return result == null ? - type === "!=" : - type === "=" ? - value === check : - type === "*=" ? - value.indexOf(check) >= 0 : - type === "~=" ? - (" " + value + " ").indexOf(check) >= 0 : - !check ? - value && result !== false : - type === "!=" ? - value != check : - type === "^=" ? - value.indexOf(check) === 0 : - type === "$=" ? - value.substr(value.length - check.length) === check : - type === "|=" ? - value === check || value.substr(0, check.length + 1) === check + "-" : - false; - }, - POS: function(elem, match, i, array){ - var name = match[2], filter = Expr.setFilters[ name ]; - - if ( filter ) { - return filter( elem, i, match, array ); - } - } - } -}; - -var origPOS = Expr.match.POS; - -for ( var type in Expr.match ) { - Expr.match[ type ] = new RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source ); - Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source ); -} - -var makeArray = function(array, results) { - array = Array.prototype.slice.call( array, 0 ); - - if ( results ) { - results.push.apply( results, array ); - return results; - } - - return array; -}; - -// Perform a simple check to determine if the browser is capable of -// converting a NodeList to an array using builtin methods. -try { - Array.prototype.slice.call( document.documentElement.childNodes, 0 ); - -// Provide a fallback method if it does not work -} catch(e){ - makeArray = function(array, results) { - var ret = results || []; - - if ( toString.call(array) === "[object Array]" ) { - Array.prototype.push.apply( ret, array ); - } else { - if ( typeof array.length === "number" ) { - for ( var i = 0, l = array.length; i < l; i++ ) { - ret.push( array[i] ); - } - } else { - for ( var i = 0; array[i]; i++ ) { - ret.push( array[i] ); - } - } - } - - return ret; - }; -} - -var sortOrder; - -if ( document.documentElement.compareDocumentPosition ) { - sortOrder = function( a, b ) { - if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { - if ( a == b ) { - hasDuplicate = true; - } - return 0; - } - - var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1; - if ( ret === 0 ) { - hasDuplicate = true; - } - return ret; - }; -} else if ( "sourceIndex" in document.documentElement ) { - sortOrder = function( a, b ) { - if ( !a.sourceIndex || !b.sourceIndex ) { - if ( a == b ) { - hasDuplicate = true; - } - return 0; - } - - var ret = a.sourceIndex - b.sourceIndex; - if ( ret === 0 ) { - hasDuplicate = true; - } - return ret; - }; -} else if ( document.createRange ) { - sortOrder = function( a, b ) { - if ( !a.ownerDocument || !b.ownerDocument ) { - if ( a == b ) { - hasDuplicate = true; - } - return 0; - } - - var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange(); - aRange.setStart(a, 0); - aRange.setEnd(a, 0); - bRange.setStart(b, 0); - bRange.setEnd(b, 0); - var ret = aRange.compareBoundaryPoints(Range.START_TO_END, bRange); - if ( ret === 0 ) { - hasDuplicate = true; - } - return ret; - }; -} - -// Check to see if the browser returns elements by name when -// querying by getElementById (and provide a workaround) -(function(){ - // We're going to inject a fake input element with a specified name - var form = document.createElement("div"), - id = "script" + (new Date).getTime(); - form.innerHTML = "<a name='" + id + "'/>"; - - // Inject it into the root element, check its status, and remove it quickly - var root = document.documentElement; - root.insertBefore( form, root.firstChild ); - - // The workaround has to do additional checks after a getElementById - // Which slows things down for other browsers (hence the branching) - if ( !!document.getElementById( id ) ) { - Expr.find.ID = function(match, context, isXML){ - if ( typeof context.getElementById !== "undefined" && !isXML ) { - var m = context.getElementById(match[1]); - return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : []; - } - }; - - Expr.filter.ID = function(elem, match){ - var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); - return elem.nodeType === 1 && node && node.nodeValue === match; - }; - } - - root.removeChild( form ); - root = form = null; // release memory in IE -})(); - -(function(){ - // Check to see if the browser returns only elements - // when doing getElementsByTagName("*") - - // Create a fake element - var div = document.createElement("div"); - div.appendChild( document.createComment("") ); - - // Make sure no comments are found - if ( div.getElementsByTagName("*").length > 0 ) { - Expr.find.TAG = function(match, context){ - var results = context.getElementsByTagName(match[1]); - - // Filter out possible comments - if ( match[1] === "*" ) { - var tmp = []; - - for ( var i = 0; results[i]; i++ ) { - if ( results[i].nodeType === 1 ) { - tmp.push( results[i] ); - } - } - - results = tmp; - } - - return results; - }; - } - - // Check to see if an attribute returns normalized href attributes - div.innerHTML = "<a href='#'></a>"; - if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && - div.firstChild.getAttribute("href") !== "#" ) { - Expr.attrHandle.href = function(elem){ - return elem.getAttribute("href", 2); - }; - } - - div = null; // release memory in IE -})(); - -if ( document.querySelectorAll ) (function(){ - var oldSizzle = Sizzle, div = document.createElement("div"); - div.innerHTML = "<p class='TEST'></p>"; - - // Safari can't handle uppercase or unicode characters when - // in quirks mode. - if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { - return; - } - - Sizzle = function(query, context, extra, seed){ - context = context || document; - - // Only use querySelectorAll on non-XML documents - // (ID selectors don't work in non-HTML documents) - if ( !seed && context.nodeType === 9 && !isXML(context) ) { - try { - return makeArray( context.querySelectorAll(query), extra ); - } catch(e){} - } - - return oldSizzle(query, context, extra, seed); - }; - - for ( var prop in oldSizzle ) { - Sizzle[ prop ] = oldSizzle[ prop ]; - } - - div = null; // release memory in IE -})(); - -if ( document.getElementsByClassName && document.documentElement.getElementsByClassName ) (function(){ - var div = document.createElement("div"); - div.innerHTML = "<div class='test e'></div><div class='test'></div>"; - - // Opera can't find a second classname (in 9.6) - if ( div.getElementsByClassName("e").length === 0 ) - return; - - // Safari caches class attributes, doesn't catch changes (in 3.2) - div.lastChild.className = "e"; - - if ( div.getElementsByClassName("e").length === 1 ) - return; - - Expr.order.splice(1, 0, "CLASS"); - Expr.find.CLASS = function(match, context, isXML) { - if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { - return context.getElementsByClassName(match[1]); - } - }; - - div = null; // release memory in IE -})(); - -function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { - var sibDir = dir == "previousSibling" && !isXML; - for ( var i = 0, l = checkSet.length; i < l; i++ ) { - var elem = checkSet[i]; - if ( elem ) { - if ( sibDir && elem.nodeType === 1 ){ - elem.sizcache = doneName; - elem.sizset = i; - } - elem = elem[dir]; - var match = false; - - while ( elem ) { - if ( elem.sizcache === doneName ) { - match = checkSet[elem.sizset]; - break; - } - - if ( elem.nodeType === 1 && !isXML ){ - elem.sizcache = doneName; - elem.sizset = i; - } - - if ( elem.nodeName === cur ) { - match = elem; - break; - } - - elem = elem[dir]; - } - - checkSet[i] = match; - } - } -} - -function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { - var sibDir = dir == "previousSibling" && !isXML; - for ( var i = 0, l = checkSet.length; i < l; i++ ) { - var elem = checkSet[i]; - if ( elem ) { - if ( sibDir && elem.nodeType === 1 ) { - elem.sizcache = doneName; - elem.sizset = i; - } - elem = elem[dir]; - var match = false; - - while ( elem ) { - if ( elem.sizcache === doneName ) { - match = checkSet[elem.sizset]; - break; - } - - if ( elem.nodeType === 1 ) { - if ( !isXML ) { - elem.sizcache = doneName; - elem.sizset = i; - } - if ( typeof cur !== "string" ) { - if ( elem === cur ) { - match = true; - break; - } - - } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { - match = elem; - break; - } - } - - elem = elem[dir]; - } - - checkSet[i] = match; - } - } -} - -var contains = document.compareDocumentPosition ? function(a, b){ - return a.compareDocumentPosition(b) & 16; -} : function(a, b){ - return a !== b && (a.contains ? a.contains(b) : true); -}; - -var isXML = function(elem){ - return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" || - !!elem.ownerDocument && elem.ownerDocument.documentElement.nodeName !== "HTML"; -}; - -var posProcess = function(selector, context){ - var tmpSet = [], later = "", match, - root = context.nodeType ? [context] : context; - - // Position selectors must be done after the filter - // And so must :not(positional) so we move all PSEUDOs to the end - while ( (match = Expr.match.PSEUDO.exec( selector )) ) { - later += match[0]; - selector = selector.replace( Expr.match.PSEUDO, "" ); - } - - selector = Expr.relative[selector] ? selector + "*" : selector; - - for ( var i = 0, l = root.length; i < l; i++ ) { - Sizzle( selector, root[i], tmpSet ); - } - - return Sizzle.filter( later, tmpSet ); -}; - -// EXPOSE - -Firebug.Selector = Sizzle; - -/**#@-*/ - -// ************************************************************************************************ -}}); - -/* See license.txt for terms of usage */ - -FBL.ns(function() { with (FBL) { -// ************************************************************************************************ - -// ************************************************************************************************ -// Inspector Module - -var ElementCache = Firebug.Lite.Cache.Element; - -var inspectorTS, inspectorTimer, isInspecting; - -Firebug.Inspector = -{ - create: function() - { - offlineFragment = Env.browser.document.createDocumentFragment(); - - createBoxModelInspector(); - createOutlineInspector(); - }, - - destroy: function() - { - destroyBoxModelInspector(); - destroyOutlineInspector(); - - offlineFragment = null; - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // Inspect functions - - toggleInspect: function() - { - if (isInspecting) - { - this.stopInspecting(); - } - else - { - Firebug.chrome.inspectButton.changeState("pressed"); - this.startInspecting(); - } - }, - - startInspecting: function() - { - isInspecting = true; - - Firebug.chrome.selectPanel("HTML"); - - createInspectorFrame(); - - var size = Firebug.browser.getWindowScrollSize(); - - fbInspectFrame.style.width = size.width + "px"; - fbInspectFrame.style.height = size.height + "px"; - - //addEvent(Firebug.browser.document.documentElement, "mousemove", Firebug.Inspector.onInspectingBody); - - addEvent(fbInspectFrame, "mousemove", Firebug.Inspector.onInspecting); - addEvent(fbInspectFrame, "mousedown", Firebug.Inspector.onInspectingClick); - }, - - stopInspecting: function() - { - isInspecting = false; - - if (outlineVisible) this.hideOutline(); - removeEvent(fbInspectFrame, "mousemove", Firebug.Inspector.onInspecting); - removeEvent(fbInspectFrame, "mousedown", Firebug.Inspector.onInspectingClick); - - destroyInspectorFrame(); - - Firebug.chrome.inspectButton.restore(); - - if (Firebug.chrome.type == "popup") - Firebug.chrome.node.focus(); - }, - - onInspectingClick: function(e) - { - fbInspectFrame.style.display = "none"; - var targ = Firebug.browser.getElementFromPoint(e.clientX, e.clientY); - fbInspectFrame.style.display = "block"; - - // Avoid inspecting the outline, and the FirebugUI - var id = targ.id; - if (id && /^fbOutline\w$/.test(id)) return; - if (id == "FirebugUI") return; - - // Avoid looking at text nodes in Opera - while (targ.nodeType != 1) targ = targ.parentNode; - - //Firebug.Console.log(targ); - Firebug.Inspector.stopInspecting(); - }, - - onInspecting: function(e) - { - if (new Date().getTime() - lastInspecting > 30) - { - fbInspectFrame.style.display = "none"; - var targ = Firebug.browser.getElementFromPoint(e.clientX, e.clientY); - fbInspectFrame.style.display = "block"; - - // Avoid inspecting the outline, and the FirebugUI - var id = targ.id; - if (id && /^fbOutline\w$/.test(id)) return; - if (id == "FirebugUI") return; - - // Avoid looking at text nodes in Opera - while (targ.nodeType != 1) targ = targ.parentNode; - - if (targ.nodeName.toLowerCase() == "body") return; - - //Firebug.Console.log(e.clientX, e.clientY, targ); - Firebug.Inspector.drawOutline(targ); - - if (ElementCache(targ)) - { - var target = ""+ElementCache.key(targ); - var lazySelect = function() - { - inspectorTS = new Date().getTime(); - - if (Firebug.HTML) - Firebug.HTML.selectTreeNode(""+ElementCache.key(targ)); - }; - - if (inspectorTimer) - { - clearTimeout(inspectorTimer); - inspectorTimer = null; - } - - if (new Date().getTime() - inspectorTS > 200) - setTimeout(lazySelect, 0); - else - inspectorTimer = setTimeout(lazySelect, 300); - } - - lastInspecting = new Date().getTime(); - } - }, - - // TODO: xxxpedro remove this? - onInspectingBody: function(e) - { - if (new Date().getTime() - lastInspecting > 30) - { - var targ = e.target; - - // Avoid inspecting the outline, and the FirebugUI - var id = targ.id; - if (id && /^fbOutline\w$/.test(id)) return; - if (id == "FirebugUI") return; - - // Avoid looking at text nodes in Opera - while (targ.nodeType != 1) targ = targ.parentNode; - - if (targ.nodeName.toLowerCase() == "body") return; - - //Firebug.Console.log(e.clientX, e.clientY, targ); - Firebug.Inspector.drawOutline(targ); - - if (ElementCache.has(targ)) - FBL.Firebug.HTML.selectTreeNode(""+ElementCache.key(targ)); - - lastInspecting = new Date().getTime(); - } - }, - - /** - * - * llttttttrr - * llttttttrr - * ll rr - * ll rr - * llbbbbbbrr - * llbbbbbbrr - */ - drawOutline: function(el) - { - var border = 2; - var scrollbarSize = 17; - - var windowSize = Firebug.browser.getWindowSize(); - var scrollSize = Firebug.browser.getWindowScrollSize(); - var scrollPosition = Firebug.browser.getWindowScrollPosition(); - - var box = Firebug.browser.getElementBox(el); - - var top = box.top; - var left = box.left; - var height = box.height; - var width = box.width; - - var freeHorizontalSpace = scrollPosition.left + windowSize.width - left - width - - (!isIE && scrollSize.height > windowSize.height ? // is *vertical* scrollbar visible - scrollbarSize : 0); - - var freeVerticalSpace = scrollPosition.top + windowSize.height - top - height - - (!isIE && scrollSize.width > windowSize.width ? // is *horizontal* scrollbar visible - scrollbarSize : 0); - - var numVerticalBorders = freeVerticalSpace > 0 ? 2 : 1; - - var o = outlineElements; - var style; - - style = o.fbOutlineT.style; - style.top = top-border + "px"; - style.left = left + "px"; - style.height = border + "px"; // TODO: on initialize() - style.width = width + "px"; - - style = o.fbOutlineL.style; - style.top = top-border + "px"; - style.left = left-border + "px"; - style.height = height+ numVerticalBorders*border + "px"; - style.width = border + "px"; // TODO: on initialize() - - style = o.fbOutlineB.style; - if (freeVerticalSpace > 0) - { - style.top = top+height + "px"; - style.left = left + "px"; - style.width = width + "px"; - //style.height = border + "px"; // TODO: on initialize() or worst case? - } - else - { - style.top = -2*border + "px"; - style.left = -2*border + "px"; - style.width = border + "px"; - //style.height = border + "px"; - } - - style = o.fbOutlineR.style; - if (freeHorizontalSpace > 0) - { - style.top = top-border + "px"; - style.left = left+width + "px"; - style.height = height + numVerticalBorders*border + "px"; - style.width = (freeHorizontalSpace < border ? freeHorizontalSpace : border) + "px"; - } - else - { - style.top = -2*border + "px"; - style.left = -2*border + "px"; - style.height = border + "px"; - style.width = border + "px"; - } - - if (!outlineVisible) this.showOutline(); - }, - - hideOutline: function() - { - if (!outlineVisible) return; - - for (var name in outline) - offlineFragment.appendChild(outlineElements[name]); - - outlineVisible = false; - }, - - showOutline: function() - { - if (outlineVisible) return; - - if (boxModelVisible) this.hideBoxModel(); - - for (var name in outline) - Firebug.browser.document.getElementsByTagName("body")[0].appendChild(outlineElements[name]); - - outlineVisible = true; - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // Box Model - - drawBoxModel: function(el) - { - // avoid error when the element is not attached a document - if (!el || !el.parentNode) - return; - - var box = Firebug.browser.getElementBox(el); - - var windowSize = Firebug.browser.getWindowSize(); - var scrollPosition = Firebug.browser.getWindowScrollPosition(); - - // element may be occluded by the chrome, when in frame mode - var offsetHeight = Firebug.chrome.type == "frame" ? Firebug.context.persistedState.height : 0; - - // if element box is not inside the viewport, don't draw the box model - if (box.top > scrollPosition.top + windowSize.height - offsetHeight || - box.left > scrollPosition.left + windowSize.width || - scrollPosition.top > box.top + box.height || - scrollPosition.left > box.left + box.width ) - return; - - var top = box.top; - var left = box.left; - var height = box.height; - var width = box.width; - - var margin = Firebug.browser.getMeasurementBox(el, "margin"); - var padding = Firebug.browser.getMeasurementBox(el, "padding"); - var border = Firebug.browser.getMeasurementBox(el, "border"); - - boxModelStyle.top = top - margin.top + "px"; - boxModelStyle.left = left - margin.left + "px"; - boxModelStyle.height = height + margin.top + margin.bottom + "px"; - boxModelStyle.width = width + margin.left + margin.right + "px"; - - boxBorderStyle.top = margin.top + "px"; - boxBorderStyle.left = margin.left + "px"; - boxBorderStyle.height = height + "px"; - boxBorderStyle.width = width + "px"; - - boxPaddingStyle.top = margin.top + border.top + "px"; - boxPaddingStyle.left = margin.left + border.left + "px"; - boxPaddingStyle.height = height - border.top - border.bottom + "px"; - boxPaddingStyle.width = width - border.left - border.right + "px"; - - boxContentStyle.top = margin.top + border.top + padding.top + "px"; - boxContentStyle.left = margin.left + border.left + padding.left + "px"; - boxContentStyle.height = height - border.top - padding.top - padding.bottom - border.bottom + "px"; - boxContentStyle.width = width - border.left - padding.left - padding.right - border.right + "px"; - - if (!boxModelVisible) this.showBoxModel(); - }, - - hideBoxModel: function() - { - if (!boxModelVisible) return; - - offlineFragment.appendChild(boxModel); - boxModelVisible = false; - }, - - showBoxModel: function() - { - if (boxModelVisible) return; - - if (outlineVisible) this.hideOutline(); - - Firebug.browser.document.getElementsByTagName("body")[0].appendChild(boxModel); - boxModelVisible = true; - } - -}; - -// ************************************************************************************************ -// Inspector Internals - - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// Shared variables - - - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// Internal variables - -var offlineFragment = null; - -var boxModelVisible = false; - -var boxModel, boxModelStyle, - boxMargin, boxMarginStyle, - boxBorder, boxBorderStyle, - boxPadding, boxPaddingStyle, - boxContent, boxContentStyle; - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - -var resetStyle = "margin:0; padding:0; border:0; position:absolute; overflow:hidden; display:block;"; -var offscreenStyle = resetStyle + "top:-1234px; left:-1234px;"; - -var inspectStyle = resetStyle + "z-index: 2147483500;"; -var inspectFrameStyle = resetStyle + "z-index: 2147483550; top:0; left:0; background:url(" + - Env.Location.skinDir + "pixel_transparent.gif);"; - -//if (Env.Options.enableTrace) inspectFrameStyle = resetStyle + "z-index: 2147483550; top: 0; left: 0; background: #ff0; opacity: 0.05; _filter: alpha(opacity=5);"; - -var inspectModelOpacity = isIE ? "filter:alpha(opacity=80);" : "opacity:0.8;"; -var inspectModelStyle = inspectStyle + inspectModelOpacity; -var inspectMarginStyle = inspectStyle + "background: #EDFF64; height:100%; width:100%;"; -var inspectBorderStyle = inspectStyle + "background: #666;"; -var inspectPaddingStyle = inspectStyle + "background: SlateBlue;"; -var inspectContentStyle = inspectStyle + "background: SkyBlue;"; - - -var outlineStyle = { - fbHorizontalLine: "background: #3875D7;height: 2px;", - fbVerticalLine: "background: #3875D7;width: 2px;" -}; - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - -var lastInspecting = 0; -var fbInspectFrame = null; - - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - -var outlineVisible = false; -var outlineElements = {}; -var outline = { - "fbOutlineT": "fbHorizontalLine", - "fbOutlineL": "fbVerticalLine", - "fbOutlineB": "fbHorizontalLine", - "fbOutlineR": "fbVerticalLine" -}; - - -var getInspectingTarget = function() -{ - -}; - -// ************************************************************************************************ -// Section - -var createInspectorFrame = function createInspectorFrame() -{ - fbInspectFrame = createGlobalElement("div"); - fbInspectFrame.id = "fbInspectFrame"; - fbInspectFrame.firebugIgnore = true; - fbInspectFrame.style.cssText = inspectFrameStyle; - Firebug.browser.document.getElementsByTagName("body")[0].appendChild(fbInspectFrame); -}; - -var destroyInspectorFrame = function destroyInspectorFrame() -{ - if (fbInspectFrame) - { - Firebug.browser.document.getElementsByTagName("body")[0].removeChild(fbInspectFrame); - fbInspectFrame = null; - } -}; - -var createOutlineInspector = function createOutlineInspector() -{ - for (var name in outline) - { - var el = outlineElements[name] = createGlobalElement("div"); - el.id = name; - el.firebugIgnore = true; - el.style.cssText = inspectStyle + outlineStyle[outline[name]]; - offlineFragment.appendChild(el); - } -}; - -var destroyOutlineInspector = function destroyOutlineInspector() -{ - for (var name in outline) - { - var el = outlineElements[name]; - el.parentNode.removeChild(el); - } -}; - -var createBoxModelInspector = function createBoxModelInspector() -{ - boxModel = createGlobalElement("div"); - boxModel.id = "fbBoxModel"; - boxModel.firebugIgnore = true; - boxModelStyle = boxModel.style; - boxModelStyle.cssText = inspectModelStyle; - - boxMargin = createGlobalElement("div"); - boxMargin.id = "fbBoxMargin"; - boxMarginStyle = boxMargin.style; - boxMarginStyle.cssText = inspectMarginStyle; - boxModel.appendChild(boxMargin); - - boxBorder = createGlobalElement("div"); - boxBorder.id = "fbBoxBorder"; - boxBorderStyle = boxBorder.style; - boxBorderStyle.cssText = inspectBorderStyle; - boxModel.appendChild(boxBorder); - - boxPadding = createGlobalElement("div"); - boxPadding.id = "fbBoxPadding"; - boxPaddingStyle = boxPadding.style; - boxPaddingStyle.cssText = inspectPaddingStyle; - boxModel.appendChild(boxPadding); - - boxContent = createGlobalElement("div"); - boxContent.id = "fbBoxContent"; - boxContentStyle = boxContent.style; - boxContentStyle.cssText = inspectContentStyle; - boxModel.appendChild(boxContent); - - offlineFragment.appendChild(boxModel); -}; - -var destroyBoxModelInspector = function destroyBoxModelInspector() -{ - boxModel.parentNode.removeChild(boxModel); -}; - -// ************************************************************************************************ -// Section - - - - -// ************************************************************************************************ -}}); - -// Problems in IE -// FIXED - eval return -// FIXED - addEventListener problem in IE -// FIXED doc.createRange? -// -// class reserved word -// test all honza examples in IE6 and IE7 - - -/* See license.txt for terms of usage */ - -( /** @scope s_domplate */ function() { - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - -/** @class */ -FBL.DomplateTag = function DomplateTag(tagName) -{ - this.tagName = tagName; -}; - -/** - * @class - * @extends FBL.DomplateTag - */ -FBL.DomplateEmbed = function DomplateEmbed() -{ -}; - -/** - * @class - * @extends FBL.DomplateTag - */ -FBL.DomplateLoop = function DomplateLoop() -{ -}; - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - -var DomplateTag = FBL.DomplateTag; -var DomplateEmbed = FBL.DomplateEmbed; -var DomplateLoop = FBL.DomplateLoop; - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - -var womb = null; - -FBL.domplate = function() -{ - var lastSubject; - for (var i = 0; i < arguments.length; ++i) - lastSubject = lastSubject ? copyObject(lastSubject, arguments[i]) : arguments[i]; - - for (var name in lastSubject) - { - var val = lastSubject[name]; - if (isTag(val)) - val.tag.subject = lastSubject; - } - - return lastSubject; -}; - -var domplate = FBL.domplate; - -FBL.domplate.context = function(context, fn) -{ - var lastContext = domplate.lastContext; - domplate.topContext = context; - fn.apply(context); - domplate.topContext = lastContext; -}; - -FBL.TAG = function() -{ - var embed = new DomplateEmbed(); - return embed.merge(arguments); -}; - -FBL.FOR = function() -{ - var loop = new DomplateLoop(); - return loop.merge(arguments); -}; - -FBL.DomplateTag.prototype = -{ - merge: function(args, oldTag) - { - if (oldTag) - this.tagName = oldTag.tagName; - - this.context = oldTag ? oldTag.context : null; - this.subject = oldTag ? oldTag.subject : null; - this.attrs = oldTag ? copyObject(oldTag.attrs) : {}; - this.classes = oldTag ? copyObject(oldTag.classes) : {}; - this.props = oldTag ? copyObject(oldTag.props) : null; - this.listeners = oldTag ? copyArray(oldTag.listeners) : null; - this.children = oldTag ? copyArray(oldTag.children) : []; - this.vars = oldTag ? copyArray(oldTag.vars) : []; - - var attrs = args.length ? args[0] : null; - var hasAttrs = typeof(attrs) == "object" && !isTag(attrs); - - this.children = []; - - if (domplate.topContext) - this.context = domplate.topContext; - - if (args.length) - parseChildren(args, hasAttrs ? 1 : 0, this.vars, this.children); - - if (hasAttrs) - this.parseAttrs(attrs); - - return creator(this, DomplateTag); - }, - - parseAttrs: function(args) - { - for (var name in args) - { - var val = parseValue(args[name]); - readPartNames(val, this.vars); - - if (name.indexOf("on") == 0) - { - var eventName = name.substr(2); - if (!this.listeners) - this.listeners = []; - this.listeners.push(eventName, val); - } - else if (name.indexOf("_") == 0) - { - var propName = name.substr(1); - if (!this.props) - this.props = {}; - this.props[propName] = val; - } - else if (name.indexOf("$") == 0) - { - var className = name.substr(1); - if (!this.classes) - this.classes = {}; - this.classes[className] = val; - } - else - { - if (name == "class" && this.attrs.hasOwnProperty(name) ) - this.attrs[name] += " " + val; - else - this.attrs[name] = val; - } - } - }, - - compile: function() - { - if (this.renderMarkup) - return; - - this.compileMarkup(); - this.compileDOM(); - - //if (FBTrace.DBG_DOM) FBTrace.sysout("domplate renderMarkup: ", this.renderMarkup); - //if (FBTrace.DBG_DOM) FBTrace.sysout("domplate renderDOM:", this.renderDOM); - //if (FBTrace.DBG_DOM) FBTrace.sysout("domplate domArgs:", this.domArgs); - }, - - compileMarkup: function() - { - this.markupArgs = []; - var topBlock = [], topOuts = [], blocks = [], info = {args: this.markupArgs, argIndex: 0}; - - this.generateMarkup(topBlock, topOuts, blocks, info); - this.addCode(topBlock, topOuts, blocks); - - var fnBlock = ['r=(function (__code__, __context__, __in__, __out__']; - for (var i = 0; i < info.argIndex; ++i) - fnBlock.push(', s', i); - fnBlock.push(') {'); - - if (this.subject) - fnBlock.push('with (this) {'); - if (this.context) - fnBlock.push('with (__context__) {'); - fnBlock.push('with (__in__) {'); - - fnBlock.push.apply(fnBlock, blocks); - - if (this.subject) - fnBlock.push('}'); - if (this.context) - fnBlock.push('}'); - - fnBlock.push('}})'); - - function __link__(tag, code, outputs, args) - { - if (!tag || !tag.tag) - return; - - tag.tag.compile(); - - var tagOutputs = []; - var markupArgs = [code, tag.tag.context, args, tagOutputs]; - markupArgs.push.apply(markupArgs, tag.tag.markupArgs); - tag.tag.renderMarkup.apply(tag.tag.subject, markupArgs); - - outputs.push(tag); - outputs.push(tagOutputs); - } - - function __escape__(value) - { - function replaceChars(ch) - { - switch (ch) - { - case "<": - return "<"; - case ">": - return ">"; - case "&": - return "&"; - case "'": - return "'"; - case '"': - return """; - } - return "?"; - }; - return String(value).replace(/[<>&"']/g, replaceChars); - } - - function __loop__(iter, outputs, fn) - { - var iterOuts = []; - outputs.push(iterOuts); - - if (iter instanceof Array) - iter = new ArrayIterator(iter); - - try - { - while (1) - { - var value = iter.next(); - var itemOuts = [0,0]; - iterOuts.push(itemOuts); - fn.apply(this, [value, itemOuts]); - } - } - catch (exc) - { - if (exc != StopIteration) - throw exc; - } - } - - var js = fnBlock.join(""); - var r = null; - eval(js); - this.renderMarkup = r; - }, - - getVarNames: function(args) - { - if (this.vars) - args.push.apply(args, this.vars); - - for (var i = 0; i < this.children.length; ++i) - { - var child = this.children[i]; - if (isTag(child)) - child.tag.getVarNames(args); - else if (child instanceof Parts) - { - for (var i = 0; i < child.parts.length; ++i) - { - if (child.parts[i] instanceof Variable) - { - var name = child.parts[i].name; - var names = name.split("."); - args.push(names[0]); - } - } - } - } - }, - - generateMarkup: function(topBlock, topOuts, blocks, info) - { - topBlock.push(',"<', this.tagName, '"'); - - for (var name in this.attrs) - { - if (name != "class") - { - var val = this.attrs[name]; - topBlock.push(', " ', name, '=\\""'); - addParts(val, ',', topBlock, info, true); - topBlock.push(', "\\""'); - } - } - - if (this.listeners) - { - for (var i = 0; i < this.listeners.length; i += 2) - readPartNames(this.listeners[i+1], topOuts); - } - - if (this.props) - { - for (var name in this.props) - readPartNames(this.props[name], topOuts); - } - - if ( this.attrs.hasOwnProperty("class") || this.classes) - { - topBlock.push(', " class=\\""'); - if (this.attrs.hasOwnProperty("class")) - addParts(this.attrs["class"], ',', topBlock, info, true); - topBlock.push(', " "'); - for (var name in this.classes) - { - topBlock.push(', ('); - addParts(this.classes[name], '', topBlock, info); - topBlock.push(' ? "', name, '" + " " : "")'); - } - topBlock.push(', "\\""'); - } - topBlock.push(',">"'); - - this.generateChildMarkup(topBlock, topOuts, blocks, info); - topBlock.push(',"</', this.tagName, '>"'); - }, - - generateChildMarkup: function(topBlock, topOuts, blocks, info) - { - for (var i = 0; i < this.children.length; ++i) - { - var child = this.children[i]; - if (isTag(child)) - child.tag.generateMarkup(topBlock, topOuts, blocks, info); - else - addParts(child, ',', topBlock, info, true); - } - }, - - addCode: function(topBlock, topOuts, blocks) - { - if (topBlock.length) - blocks.push('__code__.push(""', topBlock.join(""), ');'); - if (topOuts.length) - blocks.push('__out__.push(', topOuts.join(","), ');'); - topBlock.splice(0, topBlock.length); - topOuts.splice(0, topOuts.length); - }, - - addLocals: function(blocks) - { - var varNames = []; - this.getVarNames(varNames); - - var map = {}; - for (var i = 0; i < varNames.length; ++i) - { - var name = varNames[i]; - if ( map.hasOwnProperty(name) ) - continue; - - map[name] = 1; - var names = name.split("."); - blocks.push('var ', names[0] + ' = ' + '__in__.' + names[0] + ';'); - } - }, - - compileDOM: function() - { - var path = []; - var blocks = []; - this.domArgs = []; - path.embedIndex = 0; - path.loopIndex = 0; - path.staticIndex = 0; - path.renderIndex = 0; - var nodeCount = this.generateDOM(path, blocks, this.domArgs); - - var fnBlock = ['r=(function (root, context, o']; - - for (var i = 0; i < path.staticIndex; ++i) - fnBlock.push(', ', 's'+i); - - for (var i = 0; i < path.renderIndex; ++i) - fnBlock.push(', ', 'd'+i); - - fnBlock.push(') {'); - for (var i = 0; i < path.loopIndex; ++i) - fnBlock.push('var l', i, ' = 0;'); - for (var i = 0; i < path.embedIndex; ++i) - fnBlock.push('var e', i, ' = 0;'); - - if (this.subject) - fnBlock.push('with (this) {'); - if (this.context) - fnBlock.push('with (context) {'); - - fnBlock.push(blocks.join("")); - - if (this.subject) - fnBlock.push('}'); - if (this.context) - fnBlock.push('}'); - - fnBlock.push('return ', nodeCount, ';'); - fnBlock.push('})'); - - function __bind__(object, fn) - { - return function(event) { return fn.apply(object, [event]); }; - } - - function __link__(node, tag, args) - { - if (!tag || !tag.tag) - return; - - tag.tag.compile(); - - var domArgs = [node, tag.tag.context, 0]; - domArgs.push.apply(domArgs, tag.tag.domArgs); - domArgs.push.apply(domArgs, args); - //if (FBTrace.DBG_DOM) FBTrace.dumpProperties("domplate__link__ domArgs:", domArgs); - return tag.tag.renderDOM.apply(tag.tag.subject, domArgs); - } - - var self = this; - function __loop__(iter, fn) - { - var nodeCount = 0; - for (var i = 0; i < iter.length; ++i) - { - iter[i][0] = i; - iter[i][1] = nodeCount; - nodeCount += fn.apply(this, iter[i]); - //if (FBTrace.DBG_DOM) FBTrace.sysout("nodeCount", nodeCount); - } - return nodeCount; - } - - function __path__(parent, offset) - { - //if (FBTrace.DBG_DOM) FBTrace.sysout("domplate __path__ offset: "+ offset+"\n"); - var root = parent; - - for (var i = 2; i < arguments.length; ++i) - { - var index = arguments[i]; - if (i == 3) - index += offset; - - if (index == -1) - parent = parent.parentNode; - else - parent = parent.childNodes[index]; - } - - //if (FBTrace.DBG_DOM) FBTrace.sysout("domplate: "+arguments[2]+", root: "+ root+", parent: "+ parent+"\n"); - return parent; - } - - var js = fnBlock.join(""); - //if (FBTrace.DBG_DOM) FBTrace.sysout(js.replace(/(\;|\{)/g, "$1\n")); - var r = null; - eval(js); - this.renderDOM = r; - }, - - generateDOM: function(path, blocks, args) - { - if (this.listeners || this.props) - this.generateNodePath(path, blocks); - - if (this.listeners) - { - for (var i = 0; i < this.listeners.length; i += 2) - { - var val = this.listeners[i+1]; - var arg = generateArg(val, path, args); - //blocks.push('node.addEventListener("', this.listeners[i], '", __bind__(this, ', arg, '), false);'); - blocks.push('addEvent(node, "', this.listeners[i], '", __bind__(this, ', arg, '), false);'); - } - } - - if (this.props) - { - for (var name in this.props) - { - var val = this.props[name]; - var arg = generateArg(val, path, args); - blocks.push('node.', name, ' = ', arg, ';'); - } - } - - this.generateChildDOM(path, blocks, args); - return 1; - }, - - generateNodePath: function(path, blocks) - { - blocks.push("var node = __path__(root, o"); - for (var i = 0; i < path.length; ++i) - blocks.push(",", path[i]); - blocks.push(");"); - }, - - generateChildDOM: function(path, blocks, args) - { - path.push(0); - for (var i = 0; i < this.children.length; ++i) - { - var child = this.children[i]; - if (isTag(child)) - path[path.length-1] += '+' + child.tag.generateDOM(path, blocks, args); - else - path[path.length-1] += '+1'; - } - path.pop(); - } -}; - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - -FBL.DomplateEmbed.prototype = copyObject(FBL.DomplateTag.prototype, -/** @lends FBL.DomplateEmbed.prototype */ -{ - merge: function(args, oldTag) - { - this.value = oldTag ? oldTag.value : parseValue(args[0]); - this.attrs = oldTag ? oldTag.attrs : {}; - this.vars = oldTag ? copyArray(oldTag.vars) : []; - - var attrs = args[1]; - for (var name in attrs) - { - var val = parseValue(attrs[name]); - this.attrs[name] = val; - readPartNames(val, this.vars); - } - - return creator(this, DomplateEmbed); - }, - - getVarNames: function(names) - { - if (this.value instanceof Parts) - names.push(this.value.parts[0].name); - - if (this.vars) - names.push.apply(names, this.vars); - }, - - generateMarkup: function(topBlock, topOuts, blocks, info) - { - this.addCode(topBlock, topOuts, blocks); - - blocks.push('__link__('); - addParts(this.value, '', blocks, info); - blocks.push(', __code__, __out__, {'); - - var lastName = null; - for (var name in this.attrs) - { - if (lastName) - blocks.push(','); - lastName = name; - - var val = this.attrs[name]; - blocks.push('"', name, '":'); - addParts(val, '', blocks, info); - } - - blocks.push('});'); - //this.generateChildMarkup(topBlock, topOuts, blocks, info); - }, - - generateDOM: function(path, blocks, args) - { - var embedName = 'e'+path.embedIndex++; - - this.generateNodePath(path, blocks); - - var valueName = 'd' + path.renderIndex++; - var argsName = 'd' + path.renderIndex++; - blocks.push(embedName + ' = __link__(node, ', valueName, ', ', argsName, ');'); - - return embedName; - } -}); - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - -FBL.DomplateLoop.prototype = copyObject(FBL.DomplateTag.prototype, -/** @lends FBL.DomplateLoop.prototype */ -{ - merge: function(args, oldTag) - { - this.varName = oldTag ? oldTag.varName : args[0]; - this.iter = oldTag ? oldTag.iter : parseValue(args[1]); - this.vars = []; - - this.children = oldTag ? copyArray(oldTag.children) : []; - - var offset = Math.min(args.length, 2); - parseChildren(args, offset, this.vars, this.children); - - return creator(this, DomplateLoop); - }, - - getVarNames: function(names) - { - if (this.iter instanceof Parts) - names.push(this.iter.parts[0].name); - - DomplateTag.prototype.getVarNames.apply(this, [names]); - }, - - generateMarkup: function(topBlock, topOuts, blocks, info) - { - this.addCode(topBlock, topOuts, blocks); - - var iterName; - if (this.iter instanceof Parts) - { - var part = this.iter.parts[0]; - iterName = part.name; - - if (part.format) - { - for (var i = 0; i < part.format.length; ++i) - iterName = part.format[i] + "(" + iterName + ")"; - } - } - else - iterName = this.iter; - - blocks.push('__loop__.apply(this, [', iterName, ', __out__, function(', this.varName, ', __out__) {'); - this.generateChildMarkup(topBlock, topOuts, blocks, info); - this.addCode(topBlock, topOuts, blocks); - blocks.push('}]);'); - }, - - generateDOM: function(path, blocks, args) - { - var iterName = 'd'+path.renderIndex++; - var counterName = 'i'+path.loopIndex; - var loopName = 'l'+path.loopIndex++; - - if (!path.length) - path.push(-1, 0); - - var preIndex = path.renderIndex; - path.renderIndex = 0; - - var nodeCount = 0; - - var subBlocks = []; - var basePath = path[path.length-1]; - for (var i = 0; i < this.children.length; ++i) - { - path[path.length-1] = basePath+'+'+loopName+'+'+nodeCount; - - var child = this.children[i]; - if (isTag(child)) - nodeCount += '+' + child.tag.generateDOM(path, subBlocks, args); - else - nodeCount += '+1'; - } - - path[path.length-1] = basePath+'+'+loopName; - - blocks.push(loopName,' = __loop__.apply(this, [', iterName, ', function(', counterName,',',loopName); - for (var i = 0; i < path.renderIndex; ++i) - blocks.push(',d'+i); - blocks.push(') {'); - blocks.push(subBlocks.join("")); - blocks.push('return ', nodeCount, ';'); - blocks.push('}]);'); - - path.renderIndex = preIndex; - - return loopName; - } -}); - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - -/** @class */ -function Variable(name, format) -{ - this.name = name; - this.format = format; -} - -/** @class */ -function Parts(parts) -{ - this.parts = parts; -} - -// ************************************************************************************************ - -function parseParts(str) -{ - var re = /\$([_A-Za-z][_A-Za-z0-9.|]*)/g; - var index = 0; - var parts = []; - - var m; - while (m = re.exec(str)) - { - var pre = str.substr(index, (re.lastIndex-m[0].length)-index); - if (pre) - parts.push(pre); - - var expr = m[1].split("|"); - parts.push(new Variable(expr[0], expr.slice(1))); - index = re.lastIndex; - } - - if (!index) - return str; - - var post = str.substr(index); - if (post) - parts.push(post); - - return new Parts(parts); -} - -function parseValue(val) -{ - return typeof(val) == 'string' ? parseParts(val) : val; -} - -function parseChildren(args, offset, vars, children) -{ - for (var i = offset; i < args.length; ++i) - { - var val = parseValue(args[i]); - children.push(val); - readPartNames(val, vars); - } -} - -function readPartNames(val, vars) -{ - if (val instanceof Parts) - { - for (var i = 0; i < val.parts.length; ++i) - { - var part = val.parts[i]; - if (part instanceof Variable) - vars.push(part.name); - } - } -} - -function generateArg(val, path, args) -{ - if (val instanceof Parts) - { - var vals = []; - for (var i = 0; i < val.parts.length; ++i) - { - var part = val.parts[i]; - if (part instanceof Variable) - { - var varName = 'd'+path.renderIndex++; - if (part.format) - { - for (var j = 0; j < part.format.length; ++j) - varName = part.format[j] + '(' + varName + ')'; - } - - vals.push(varName); - } - else - vals.push('"'+part.replace(/"/g, '\\"')+'"'); - } - - return vals.join('+'); - } - else - { - args.push(val); - return 's' + path.staticIndex++; - } -} - -function addParts(val, delim, block, info, escapeIt) -{ - var vals = []; - if (val instanceof Parts) - { - for (var i = 0; i < val.parts.length; ++i) - { - var part = val.parts[i]; - if (part instanceof Variable) - { - var partName = part.name; - if (part.format) - { - for (var j = 0; j < part.format.length; ++j) - partName = part.format[j] + "(" + partName + ")"; - } - - if (escapeIt) - vals.push("__escape__(" + partName + ")"); - else - vals.push(partName); - } - else - vals.push('"'+ part + '"'); - } - } - else if (isTag(val)) - { - info.args.push(val); - vals.push('s'+info.argIndex++); - } - else - vals.push('"'+ val + '"'); - - var parts = vals.join(delim); - if (parts) - block.push(delim, parts); -} - -function isTag(obj) -{ - return (typeof(obj) == "function" || obj instanceof Function) && !!obj.tag; -} - -function creator(tag, cons) -{ - var fn = new Function( - "var tag = arguments.callee.tag;" + - "var cons = arguments.callee.cons;" + - "var newTag = new cons();" + - "return newTag.merge(arguments, tag);"); - - fn.tag = tag; - fn.cons = cons; - extend(fn, Renderer); - - return fn; -} - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - -function copyArray(oldArray) -{ - var ary = []; - if (oldArray) - for (var i = 0; i < oldArray.length; ++i) - ary.push(oldArray[i]); - return ary; -} - -function copyObject(l, r) -{ - var m = {}; - extend(m, l); - extend(m, r); - return m; -} - -function extend(l, r) -{ - for (var n in r) - l[n] = r[n]; -} - -function addEvent(object, name, handler) -{ - if (document.all) - object.attachEvent("on"+name, handler); - else - object.addEventListener(name, handler, false); -} - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - -/** @class */ -function ArrayIterator(array) -{ - var index = -1; - - this.next = function() - { - if (++index >= array.length) - throw StopIteration; - - return array[index]; - }; -} - -/** @class */ -function StopIteration() {} - -FBL.$break = function() -{ - throw StopIteration; -}; - -// ************************************************************************************************ - -/** @namespace */ -var Renderer = -{ - renderHTML: function(args, outputs, self) - { - var code = []; - var markupArgs = [code, this.tag.context, args, outputs]; - markupArgs.push.apply(markupArgs, this.tag.markupArgs); - this.tag.renderMarkup.apply(self ? self : this.tag.subject, markupArgs); - return code.join(""); - }, - - insertRows: function(args, before, self) - { - this.tag.compile(); - - var outputs = []; - var html = this.renderHTML(args, outputs, self); - - var doc = before.ownerDocument; - var div = doc.createElement("div"); - div.innerHTML = "<table><tbody>"+html+"</tbody></table>"; - - var tbody = div.firstChild.firstChild; - var parent = before.tagName == "TR" ? before.parentNode : before; - var after = before.tagName == "TR" ? before.nextSibling : null; - - var firstRow = tbody.firstChild, lastRow; - while (tbody.firstChild) - { - lastRow = tbody.firstChild; - if (after) - parent.insertBefore(lastRow, after); - else - parent.appendChild(lastRow); - } - - var offset = 0; - if (before.tagName == "TR") - { - var node = firstRow.parentNode.firstChild; - for (; node && node != firstRow; node = node.nextSibling) - ++offset; - } - - var domArgs = [firstRow, this.tag.context, offset]; - domArgs.push.apply(domArgs, this.tag.domArgs); - domArgs.push.apply(domArgs, outputs); - - this.tag.renderDOM.apply(self ? self : this.tag.subject, domArgs); - return [firstRow, lastRow]; - }, - - insertBefore: function(args, before, self) - { - return this.insertNode(args, before.ownerDocument, before, false, self); - }, - - insertAfter: function(args, after, self) - { - return this.insertNode(args, after.ownerDocument, after, true, self); - }, - - insertNode: function(args, doc, element, isAfter, self) - { - if (!args) - args = {}; - - this.tag.compile(); - - var outputs = []; - var html = this.renderHTML(args, outputs, self); - - //if (FBTrace.DBG_DOM) - // FBTrace.sysout("domplate.insertNode html: "+html+"\n"); - - var doc = element.ownerDocument; - if (!womb || womb.ownerDocument != doc) - womb = doc.createElement("div"); - - womb.innerHTML = html; - - var root = womb.firstChild; - if (isAfter) - { - while (womb.firstChild) - if (element.nextSibling) - element.parentNode.insertBefore(womb.firstChild, element.nextSibling); - else - element.parentNode.appendChild(womb.firstChild); - } - else - { - while (womb.lastChild) - element.parentNode.insertBefore(womb.lastChild, element); - } - - var domArgs = [root, this.tag.context, 0]; - domArgs.push.apply(domArgs, this.tag.domArgs); - domArgs.push.apply(domArgs, outputs); - - //if (FBTrace.DBG_DOM) - // FBTrace.sysout("domplate.insertNode domArgs:", domArgs); - this.tag.renderDOM.apply(self ? self : this.tag.subject, domArgs); - - return root; - }, - /**/ - - /* - insertAfter: function(args, before, self) - { - this.tag.compile(); - - var outputs = []; - var html = this.renderHTML(args, outputs, self); - - var doc = before.ownerDocument; - if (!womb || womb.ownerDocument != doc) - womb = doc.createElement("div"); - - womb.innerHTML = html; - - var root = womb.firstChild; - while (womb.firstChild) - if (before.nextSibling) - before.parentNode.insertBefore(womb.firstChild, before.nextSibling); - else - before.parentNode.appendChild(womb.firstChild); - - var domArgs = [root, this.tag.context, 0]; - domArgs.push.apply(domArgs, this.tag.domArgs); - domArgs.push.apply(domArgs, outputs); - - this.tag.renderDOM.apply(self ? self : (this.tag.subject ? this.tag.subject : null), - domArgs); - - return root; - }, - /**/ - - replace: function(args, parent, self) - { - this.tag.compile(); - - var outputs = []; - var html = this.renderHTML(args, outputs, self); - - var root; - if (parent.nodeType == 1) - { - parent.innerHTML = html; - root = parent.firstChild; - } - else - { - if (!parent || parent.nodeType != 9) - parent = document; - - if (!womb || womb.ownerDocument != parent) - womb = parent.createElement("div"); - womb.innerHTML = html; - - root = womb.firstChild; - //womb.removeChild(root); - } - - var domArgs = [root, this.tag.context, 0]; - domArgs.push.apply(domArgs, this.tag.domArgs); - domArgs.push.apply(domArgs, outputs); - this.tag.renderDOM.apply(self ? self : this.tag.subject, domArgs); - - return root; - }, - - append: function(args, parent, self) - { - this.tag.compile(); - - var outputs = []; - var html = this.renderHTML(args, outputs, self); - //if (FBTrace.DBG_DOM) FBTrace.sysout("domplate.append html: "+html+"\n"); - - if (!womb || womb.ownerDocument != parent.ownerDocument) - womb = parent.ownerDocument.createElement("div"); - womb.innerHTML = html; - - // TODO: xxxpedro domplate port to Firebug - var root = womb.firstChild; - while (womb.firstChild) - parent.appendChild(womb.firstChild); - - // clearing element reference to avoid reference error in IE8 when switching contexts - womb = null; - - var domArgs = [root, this.tag.context, 0]; - domArgs.push.apply(domArgs, this.tag.domArgs); - domArgs.push.apply(domArgs, outputs); - - //if (FBTrace.DBG_DOM) FBTrace.dumpProperties("domplate append domArgs:", domArgs); - this.tag.renderDOM.apply(self ? self : this.tag.subject, domArgs); - - return root; - } -}; - -// ************************************************************************************************ - -function defineTags() -{ - for (var i = 0; i < arguments.length; ++i) - { - var tagName = arguments[i]; - var fn = new Function("var newTag = new arguments.callee.DomplateTag('"+tagName+"'); return newTag.merge(arguments);"); - fn.DomplateTag = DomplateTag; - - var fnName = tagName.toUpperCase(); - FBL[fnName] = fn; - } -} - -defineTags( - "a", "button", "br", "canvas", "code", "col", "colgroup", "div", "fieldset", "form", "h1", "h2", "h3", "hr", - "img", "input", "label", "legend", "li", "ol", "optgroup", "option", "p", "pre", "select", - "span", "strong", "table", "tbody", "td", "textarea", "tfoot", "th", "thead", "tr", "tt", "ul", "iframe" -); - -})(); - - -/* See license.txt for terms of usage */ - -var FirebugReps = FBL.ns(function() { with (FBL) { - - -// ************************************************************************************************ -// Common Tags - -var OBJECTBOX = this.OBJECTBOX = - SPAN({"class": "objectBox objectBox-$className"}); - -var OBJECTBLOCK = this.OBJECTBLOCK = - DIV({"class": "objectBox objectBox-$className"}); - -var OBJECTLINK = this.OBJECTLINK = isIE6 ? // IE6 object link representation - A({ - "class": "objectLink objectLink-$className a11yFocus", - href: "javascript:void(0)", - // workaround to show XPath (a better approach would use the tooltip on mouseover, - // so the XPath information would be calculated dynamically, but we need to create - // a tooltip class/wrapper around Menu or InfoTip) - title: "$object|FBL.getElementXPath", - _repObject: "$object" - }) - : // Other browsers - A({ - "class": "objectLink objectLink-$className a11yFocus", - // workaround to show XPath (a better approach would use the tooltip on mouseover, - // so the XPath information would be calculated dynamically, but we need to create - // a tooltip class/wrapper around Menu or InfoTip) - title: "$object|FBL.getElementXPath", - _repObject: "$object" - }); - - -// ************************************************************************************************ - -this.Undefined = domplate(Firebug.Rep, -{ - tag: OBJECTBOX("undefined"), - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - className: "undefined", - - supportsObject: function(object, type) - { - return type == "undefined"; - } -}); - -// ************************************************************************************************ - -this.Null = domplate(Firebug.Rep, -{ - tag: OBJECTBOX("null"), - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - className: "null", - - supportsObject: function(object, type) - { - return object == null; - } -}); - -// ************************************************************************************************ - -this.Nada = domplate(Firebug.Rep, -{ - tag: SPAN(""), - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - className: "nada" -}); - -// ************************************************************************************************ - -this.Number = domplate(Firebug.Rep, -{ - tag: OBJECTBOX("$object"), - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - className: "number", - - supportsObject: function(object, type) - { - return type == "boolean" || type == "number"; - } -}); - -// ************************************************************************************************ - -this.String = domplate(Firebug.Rep, -{ - tag: OBJECTBOX(""$object""), - - shortTag: OBJECTBOX(""$object|cropString""), - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - className: "string", - - supportsObject: function(object, type) - { - return type == "string"; - } -}); - -// ************************************************************************************************ - -this.Text = domplate(Firebug.Rep, -{ - tag: OBJECTBOX("$object"), - - shortTag: OBJECTBOX("$object|cropString"), - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - className: "text" -}); - -// ************************************************************************************************ - -this.Caption = domplate(Firebug.Rep, -{ - tag: SPAN({"class": "caption"}, "$object") -}); - -// ************************************************************************************************ - -this.Warning = domplate(Firebug.Rep, -{ - tag: DIV({"class": "warning focusRow", role : 'listitem'}, "$object|STR") -}); - -// ************************************************************************************************ - -this.Func = domplate(Firebug.Rep, -{ - tag: - OBJECTLINK("$object|summarizeFunction"), - - summarizeFunction: function(fn) - { - var fnRegex = /function ([^(]+\([^)]*\)) \{/; - var fnText = safeToString(fn); - - var m = fnRegex.exec(fnText); - return m ? m[1] : "function()"; - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - copySource: function(fn) - { - copyToClipboard(safeToString(fn)); - }, - - monitor: function(fn, script, monitored) - { - if (monitored) - Firebug.Debugger.unmonitorScript(fn, script, "monitor"); - else - Firebug.Debugger.monitorScript(fn, script, "monitor"); - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - className: "function", - - supportsObject: function(object, type) - { - return isFunction(object); - }, - - inspectObject: function(fn, context) - { - var sourceLink = findSourceForFunction(fn, context); - if (sourceLink) - Firebug.chrome.select(sourceLink); - if (FBTrace.DBG_FUNCTION_NAME) - FBTrace.sysout("reps.function.inspectObject selected sourceLink is ", sourceLink); - }, - - getTooltip: function(fn, context) - { - var script = findScriptForFunctionInContext(context, fn); - if (script) - return $STRF("Line", [normalizeURL(script.fileName), script.baseLineNumber]); - else - if (fn.toString) - return fn.toString(); - }, - - getTitle: function(fn, context) - { - var name = fn.name ? fn.name : "function"; - return name + "()"; - }, - - getContextMenuItems: function(fn, target, context, script) - { - if (!script) - script = findScriptForFunctionInContext(context, fn); - if (!script) - return; - - var scriptInfo = getSourceFileAndLineByScript(context, script); - var monitored = scriptInfo ? fbs.isMonitored(scriptInfo.sourceFile.href, scriptInfo.lineNo) : false; - - var name = script ? getFunctionName(script, context) : fn.name; - return [ - {label: "CopySource", command: bindFixed(this.copySource, this, fn) }, - "-", - {label: $STRF("ShowCallsInConsole", [name]), nol10n: true, - type: "checkbox", checked: monitored, - command: bindFixed(this.monitor, this, fn, script, monitored) } - ]; - } -}); - -// ************************************************************************************************ -/* -this.jsdScript = domplate(Firebug.Rep, -{ - copySource: function(script) - { - var fn = script.functionObject.getWrappedValue(); - return FirebugReps.Func.copySource(fn); - }, - - monitor: function(fn, script, monitored) - { - fn = script.functionObject.getWrappedValue(); - return FirebugReps.Func.monitor(fn, script, monitored); - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - className: "jsdScript", - inspectable: false, - - supportsObject: function(object, type) - { - return object instanceof jsdIScript; - }, - - inspectObject: function(script, context) - { - var sourceLink = getSourceLinkForScript(script, context); - if (sourceLink) - Firebug.chrome.select(sourceLink); - }, - - getRealObject: function(script, context) - { - return script; - }, - - getTooltip: function(script) - { - return $STRF("jsdIScript", [script.tag]); - }, - - getTitle: function(script, context) - { - var fn = script.functionObject.getWrappedValue(); - return FirebugReps.Func.getTitle(fn, context); - }, - - getContextMenuItems: function(script, target, context) - { - var fn = script.functionObject.getWrappedValue(); - - var scriptInfo = getSourceFileAndLineByScript(context, script); - var monitored = scriptInfo ? fbs.isMonitored(scriptInfo.sourceFile.href, scriptInfo.lineNo) : false; - - var name = getFunctionName(script, context); - - return [ - {label: "CopySource", command: bindFixed(this.copySource, this, script) }, - "-", - {label: $STRF("ShowCallsInConsole", [name]), nol10n: true, - type: "checkbox", checked: monitored, - command: bindFixed(this.monitor, this, fn, script, monitored) } - ]; - } -}); -/**/ -//************************************************************************************************ - -this.Obj = domplate(Firebug.Rep, -{ - tag: - OBJECTLINK( - SPAN({"class": "objectTitle"}, "$object|getTitle "), - - SPAN({"class": "objectProps"}, - SPAN({"class": "objectLeftBrace", role: "presentation"}, "{"), - FOR("prop", "$object|propIterator", - SPAN({"class": "objectPropName", role: "presentation"}, "$prop.name"), - SPAN({"class": "objectEqual", role: "presentation"}, "$prop.equal"), - TAG("$prop.tag", {object: "$prop.object"}), - SPAN({"class": "objectComma", role: "presentation"}, "$prop.delim") - ), - SPAN({"class": "objectRightBrace"}, "}") - ) - ), - - propNumberTag: - SPAN({"class": "objectProp-number"}, "$object"), - - propStringTag: - SPAN({"class": "objectProp-string"}, ""$object""), - - propObjectTag: - SPAN({"class": "objectProp-object"}, "$object"), - - propIterator: function (object) - { - ///Firebug.ObjectShortIteratorMax; - var maxLength = 55; // default max length for long representation - - if (!object) - return []; - - var props = []; - var length = 0; - - var numProperties = 0; - var numPropertiesShown = 0; - var maxLengthReached = false; - - var lib = this; - - var propRepsMap = - { - "boolean": this.propNumberTag, - "number": this.propNumberTag, - "string": this.propStringTag, - "object": this.propObjectTag - }; - - try - { - var title = Firebug.Rep.getTitle(object); - length += title.length; - - for (var name in object) - { - var value; - try - { - value = object[name]; - } - catch (exc) - { - continue; - } - - var type = typeof(value); - if (type == "boolean" || - type == "number" || - (type == "string" && value) || - (type == "object" && value && value.toString)) - { - var tag = propRepsMap[type]; - - var value = (type == "object") ? - Firebug.getRep(value).getTitle(value) : - value + ""; - - length += name.length + value.length + 4; - - if (length <= maxLength) - { - props.push({ - tag: tag, - name: name, - object: value, - equal: "=", - delim: ", " - }); - - numPropertiesShown++; - } - else - maxLengthReached = true; - - } - - numProperties++; - - if (maxLengthReached && numProperties > numPropertiesShown) - break; - } - - if (numProperties > numPropertiesShown) - { - props.push({ - object: "...", //xxxHonza localization - tag: FirebugReps.Caption.tag, - name: "", - equal:"", - delim:"" - }); - } - else if (props.length > 0) - { - props[props.length-1].delim = ''; - } - } - catch (exc) - { - // Sometimes we get exceptions when trying to read from certain objects, like - // StorageList, but don't let that gum up the works - // XXXjjb also History.previous fails because object is a web-page object which does not have - // permission to read the history - } - return props; - }, - - fb_1_6_propIterator: function (object, max) - { - max = max || 3; - if (!object) - return []; - - var props = []; - var len = 0, count = 0; - - try - { - for (var name in object) - { - var value; - try - { - value = object[name]; - } - catch (exc) - { - continue; - } - - var t = typeof(value); - if (t == "boolean" || t == "number" || (t == "string" && value) - || (t == "object" && value && value.toString)) - { - var rep = Firebug.getRep(value); - var tag = rep.shortTag || rep.tag; - if (t == "object") - { - value = rep.getTitle(value); - tag = rep.titleTag; - } - count++; - if (count <= max) - props.push({tag: tag, name: name, object: value, equal: "=", delim: ", "}); - else - break; - } - } - if (count > max) - { - props[Math.max(1,max-1)] = { - object: "more...", //xxxHonza localization - tag: FirebugReps.Caption.tag, - name: "", - equal:"", - delim:"" - }; - } - else if (props.length > 0) - { - props[props.length-1].delim = ''; - } - } - catch (exc) - { - // Sometimes we get exceptions when trying to read from certain objects, like - // StorageList, but don't let that gum up the works - // XXXjjb also History.previous fails because object is a web-page object which does not have - // permission to read the history - } - return props; - }, - - /* - propIterator: function (object) - { - if (!object) - return []; - - var props = []; - var len = 0; - - try - { - for (var name in object) - { - var val; - try - { - val = object[name]; - } - catch (exc) - { - continue; - } - - var t = typeof val; - if (t == "boolean" || t == "number" || (t == "string" && val) - || (t == "object" && !isFunction(val) && val && val.toString)) - { - var title = (t == "object") - ? Firebug.getRep(val).getTitle(val) - : val+""; - - len += name.length + title.length + 1; - if (len < 50) - props.push({name: name, value: title}); - else - break; - } - } - } - catch (exc) - { - // Sometimes we get exceptions when trying to read from certain objects, like - // StorageList, but don't let that gum up the works - // XXXjjb also History.previous fails because object is a web-page object which does not have - // permission to read the history - } - - return props; - }, - /**/ - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - className: "object", - - supportsObject: function(object, type) - { - return true; - } -}); - - -// ************************************************************************************************ - -this.Arr = domplate(Firebug.Rep, -{ - tag: - OBJECTBOX({_repObject: "$object"}, - SPAN({"class": "arrayLeftBracket", role : "presentation"}, "["), - FOR("item", "$object|arrayIterator", - TAG("$item.tag", {object: "$item.object"}), - SPAN({"class": "arrayComma", role : "presentation"}, "$item.delim") - ), - SPAN({"class": "arrayRightBracket", role : "presentation"}, "]") - ), - - shortTag: - OBJECTBOX({_repObject: "$object"}, - SPAN({"class": "arrayLeftBracket", role : "presentation"}, "["), - FOR("item", "$object|shortArrayIterator", - TAG("$item.tag", {object: "$item.object"}), - SPAN({"class": "arrayComma", role : "presentation"}, "$item.delim") - ), - // TODO: xxxpedro - confirm this on Firebug - //FOR("prop", "$object|shortPropIterator", - // " $prop.name=", - // SPAN({"class": "objectPropValue"}, "$prop.value|cropString") - //), - SPAN({"class": "arrayRightBracket"}, "]") - ), - - arrayIterator: function(array) - { - var items = []; - for (var i = 0; i < array.length; ++i) - { - var value = array[i]; - var rep = Firebug.getRep(value); - var tag = rep.shortTag ? rep.shortTag : rep.tag; - var delim = (i == array.length-1 ? "" : ", "); - - items.push({object: value, tag: tag, delim: delim}); - } - - return items; - }, - - shortArrayIterator: function(array) - { - var items = []; - for (var i = 0; i < array.length && i < 3; ++i) - { - var value = array[i]; - var rep = Firebug.getRep(value); - var tag = rep.shortTag ? rep.shortTag : rep.tag; - var delim = (i == array.length-1 ? "" : ", "); - - items.push({object: value, tag: tag, delim: delim}); - } - - if (array.length > 3) - items.push({object: (array.length-3) + " more...", tag: FirebugReps.Caption.tag, delim: ""}); - - return items; - }, - - shortPropIterator: this.Obj.propIterator, - - getItemIndex: function(child) - { - var arrayIndex = 0; - for (child = child.previousSibling; child; child = child.previousSibling) - { - if (child.repObject) - ++arrayIndex; - } - return arrayIndex; - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - className: "array", - - supportsObject: function(object) - { - return this.isArray(object); - }, - - // http://code.google.com/p/fbug/issues/detail?id=874 - // BEGIN Yahoo BSD Source (modified here) YAHOO.lang.isArray, YUI 2.2.2 June 2007 - isArray: function(obj) { - try { - if (!obj) - return false; - else if (isIE && !isFunction(obj) && typeof obj == "object" && isFinite(obj.length) && obj.nodeType != 8) - return true; - else if (isFinite(obj.length) && isFunction(obj.splice)) - return true; - else if (isFinite(obj.length) && isFunction(obj.callee)) // arguments - return true; - else if (instanceOf(obj, "HTMLCollection")) - return true; - else if (instanceOf(obj, "NodeList")) - return true; - else - return false; - } - catch(exc) - { - if (FBTrace.DBG_ERRORS) - { - FBTrace.sysout("isArray FAILS:", exc); /* Something weird: without the try/catch, OOM, with no exception?? */ - FBTrace.sysout("isArray Fails on obj", obj); - } - } - - return false; - }, - // END Yahoo BSD SOURCE See license below. - - getTitle: function(object, context) - { - return "[" + object.length + "]"; - } -}); - -// ************************************************************************************************ - -this.Property = domplate(Firebug.Rep, -{ - supportsObject: function(object) - { - return object instanceof Property; - }, - - getRealObject: function(prop, context) - { - return prop.object[prop.name]; - }, - - getTitle: function(prop, context) - { - return prop.name; - } -}); - -// ************************************************************************************************ - -this.NetFile = domplate(this.Obj, -{ - supportsObject: function(object) - { - return object instanceof Firebug.NetFile; - }, - - browseObject: function(file, context) - { - openNewTab(file.href); - return true; - }, - - getRealObject: function(file, context) - { - return null; - } -}); - -// ************************************************************************************************ - -this.Except = domplate(Firebug.Rep, -{ - tag: - OBJECTBOX({_repObject: "$object"}, "$object.message"), - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - className: "exception", - - supportsObject: function(object) - { - return object instanceof ErrorCopy; - } -}); - - -// ************************************************************************************************ - -this.Element = domplate(Firebug.Rep, -{ - tag: - OBJECTLINK( - "<", - SPAN({"class": "nodeTag"}, "$object.nodeName|toLowerCase"), - FOR("attr", "$object|attrIterator", - " $attr.nodeName="", SPAN({"class": "nodeValue"}, "$attr.nodeValue"), """ - ), - ">" - ), - - shortTag: - OBJECTLINK( - SPAN({"class": "$object|getVisible"}, - SPAN({"class": "selectorTag"}, "$object|getSelectorTag"), - SPAN({"class": "selectorId"}, "$object|getSelectorId"), - SPAN({"class": "selectorClass"}, "$object|getSelectorClass"), - SPAN({"class": "selectorValue"}, "$object|getValue") - ) - ), - - getVisible: function(elt) - { - return isVisible(elt) ? "" : "selectorHidden"; - }, - - getSelectorTag: function(elt) - { - return elt.nodeName.toLowerCase(); - }, - - getSelectorId: function(elt) - { - return elt.id ? "#" + elt.id : ""; - }, - - getSelectorClass: function(elt) - { - return elt.className ? "." + elt.className.split(" ")[0] : ""; - }, - - getValue: function(elt) - { - // TODO: xxxpedro - return ""; - var value; - if (elt instanceof HTMLImageElement) - value = getFileName(elt.src); - else if (elt instanceof HTMLAnchorElement) - value = getFileName(elt.href); - else if (elt instanceof HTMLInputElement) - value = elt.value; - else if (elt instanceof HTMLFormElement) - value = getFileName(elt.action); - else if (elt instanceof HTMLScriptElement) - value = getFileName(elt.src); - - return value ? " " + cropString(value, 20) : ""; - }, - - attrIterator: function(elt) - { - var attrs = []; - var idAttr, classAttr; - if (elt.attributes) - { - for (var i = 0; i < elt.attributes.length; ++i) - { - var attr = elt.attributes[i]; - - // we must check if the attribute is specified otherwise IE will show them - if (!attr.specified || attr.nodeName && attr.nodeName.indexOf("firebug-") != -1) - continue; - else if (attr.nodeName == "id") - idAttr = attr; - else if (attr.nodeName == "class") - classAttr = attr; - else if (attr.nodeName == "style") - attrs.push({ - nodeName: attr.nodeName, - nodeValue: attr.nodeValue || - // IE won't recognize the attr.nodeValue of <style> nodes ... - // and will return CSS property names in upper case, so we need to convert them - elt.style.cssText.replace(/([^\s]+)\s*:/g, - function(m,g){return g.toLowerCase()+":"}) - }); - else - attrs.push(attr); - } - } - if (classAttr) - attrs.splice(0, 0, classAttr); - if (idAttr) - attrs.splice(0, 0, idAttr); - - return attrs; - }, - - shortAttrIterator: function(elt) - { - var attrs = []; - if (elt.attributes) - { - for (var i = 0; i < elt.attributes.length; ++i) - { - var attr = elt.attributes[i]; - if (attr.nodeName == "id" || attr.nodeName == "class") - attrs.push(attr); - } - } - - return attrs; - }, - - getHidden: function(elt) - { - return isVisible(elt) ? "" : "nodeHidden"; - }, - - getXPath: function(elt) - { - return getElementTreeXPath(elt); - }, - - // TODO: xxxpedro remove this? - getNodeText: function(element) - { - var text = element.textContent; - if (Firebug.showFullTextNodes) - return text; - else - return cropString(text, 50); - }, - /**/ - - getNodeTextGroups: function(element) - { - var text = element.textContent; - if (!Firebug.showFullTextNodes) - { - text=cropString(text,50); - } - - var escapeGroups=[]; - - if (Firebug.showTextNodesWithWhitespace) - escapeGroups.push({ - 'group': 'whitespace', - 'class': 'nodeWhiteSpace', - 'extra': { - '\t': '_Tab', - '\n': '_Para', - ' ' : '_Space' - } - }); - if (Firebug.showTextNodesWithEntities) - escapeGroups.push({ - 'group':'text', - 'class':'nodeTextEntity', - 'extra':{} - }); - - if (escapeGroups.length) - return escapeGroupsForEntities(text, escapeGroups); - else - return [{str:text,'class':'',extra:''}]; - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - copyHTML: function(elt) - { - var html = getElementXML(elt); - copyToClipboard(html); - }, - - copyInnerHTML: function(elt) - { - copyToClipboard(elt.innerHTML); - }, - - copyXPath: function(elt) - { - var xpath = getElementXPath(elt); - copyToClipboard(xpath); - }, - - persistor: function(context, xpath) - { - var elts = xpath - ? getElementsByXPath(context.window.document, xpath) - : null; - - return elts && elts.length ? elts[0] : null; - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - className: "element", - - supportsObject: function(object) - { - //return object instanceof Element || object.nodeType == 1 && typeof object.nodeName == "string"; - return instanceOf(object, "Element"); - }, - - browseObject: function(elt, context) - { - var tag = elt.nodeName.toLowerCase(); - if (tag == "script") - openNewTab(elt.src); - else if (tag == "link") - openNewTab(elt.href); - else if (tag == "a") - openNewTab(elt.href); - else if (tag == "img") - openNewTab(elt.src); - - return true; - }, - - persistObject: function(elt, context) - { - var xpath = getElementXPath(elt); - - return bind(this.persistor, top, xpath); - }, - - getTitle: function(element, context) - { - return getElementCSSSelector(element); - }, - - getTooltip: function(elt) - { - return this.getXPath(elt); - }, - - getContextMenuItems: function(elt, target, context) - { - var monitored = areEventsMonitored(elt, null, context); - - return [ - {label: "CopyHTML", command: bindFixed(this.copyHTML, this, elt) }, - {label: "CopyInnerHTML", command: bindFixed(this.copyInnerHTML, this, elt) }, - {label: "CopyXPath", command: bindFixed(this.copyXPath, this, elt) }, - "-", - {label: "ShowEventsInConsole", type: "checkbox", checked: monitored, - command: bindFixed(toggleMonitorEvents, FBL, elt, null, monitored, context) }, - "-", - {label: "ScrollIntoView", command: bindFixed(elt.scrollIntoView, elt) } - ]; - } -}); - -// ************************************************************************************************ - -this.TextNode = domplate(Firebug.Rep, -{ - tag: - OBJECTLINK( - "<", - SPAN({"class": "nodeTag"}, "TextNode"), - " textContent="", SPAN({"class": "nodeValue"}, "$object.textContent|cropString"), """, - ">" - ), - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - className: "textNode", - - supportsObject: function(object) - { - return object instanceof Text; - } -}); - -// ************************************************************************************************ - -this.Document = domplate(Firebug.Rep, -{ - tag: - OBJECTLINK("Document ", SPAN({"class": "objectPropValue"}, "$object|getLocation")), - - getLocation: function(doc) - { - return doc.location ? getFileName(doc.location.href) : ""; - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - className: "object", - - supportsObject: function(object) - { - //return object instanceof Document || object instanceof XMLDocument; - return instanceOf(object, "Document"); - }, - - browseObject: function(doc, context) - { - openNewTab(doc.location.href); - return true; - }, - - persistObject: function(doc, context) - { - return this.persistor; - }, - - persistor: function(context) - { - return context.window.document; - }, - - getTitle: function(win, context) - { - return "document"; - }, - - getTooltip: function(doc) - { - return doc.location.href; - } -}); - -// ************************************************************************************************ - -this.StyleSheet = domplate(Firebug.Rep, -{ - tag: - OBJECTLINK("StyleSheet ", SPAN({"class": "objectPropValue"}, "$object|getLocation")), - - getLocation: function(styleSheet) - { - return getFileName(styleSheet.href); - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - copyURL: function(styleSheet) - { - copyToClipboard(styleSheet.href); - }, - - openInTab: function(styleSheet) - { - openNewTab(styleSheet.href); - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - className: "object", - - supportsObject: function(object) - { - //return object instanceof CSSStyleSheet; - return instanceOf(object, "CSSStyleSheet"); - }, - - browseObject: function(styleSheet, context) - { - openNewTab(styleSheet.href); - return true; - }, - - persistObject: function(styleSheet, context) - { - return bind(this.persistor, top, styleSheet.href); - }, - - getTooltip: function(styleSheet) - { - return styleSheet.href; - }, - - getContextMenuItems: function(styleSheet, target, context) - { - return [ - {label: "CopyLocation", command: bindFixed(this.copyURL, this, styleSheet) }, - "-", - {label: "OpenInTab", command: bindFixed(this.openInTab, this, styleSheet) } - ]; - }, - - persistor: function(context, href) - { - return getStyleSheetByHref(href, context); - } -}); - -// ************************************************************************************************ - -this.Window = domplate(Firebug.Rep, -{ - tag: - OBJECTLINK("Window ", SPAN({"class": "objectPropValue"}, "$object|getLocation")), - - getLocation: function(win) - { - try - { - return (win && win.location && !win.closed) ? getFileName(win.location.href) : ""; - } - catch (exc) - { - if (FBTrace.DBG_ERRORS) - FBTrace.sysout("reps.Window window closed?"); - } - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - className: "object", - - supportsObject: function(object) - { - return instanceOf(object, "Window"); - }, - - browseObject: function(win, context) - { - openNewTab(win.location.href); - return true; - }, - - persistObject: function(win, context) - { - return this.persistor; - }, - - persistor: function(context) - { - return context.window; - }, - - getTitle: function(win, context) - { - return "window"; - }, - - getTooltip: function(win) - { - if (win && !win.closed) - return win.location.href; - } -}); - -// ************************************************************************************************ - -this.Event = domplate(Firebug.Rep, -{ - tag: TAG("$copyEventTag", {object: "$object|copyEvent"}), - - copyEventTag: - OBJECTLINK("$object|summarizeEvent"), - - summarizeEvent: function(event) - { - var info = [event.type, ' ']; - - var eventFamily = getEventFamily(event.type); - if (eventFamily == "mouse") - info.push("clientX=", event.clientX, ", clientY=", event.clientY); - else if (eventFamily == "key") - info.push("charCode=", event.charCode, ", keyCode=", event.keyCode); - - return info.join(""); - }, - - copyEvent: function(event) - { - return new EventCopy(event); - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - className: "object", - - supportsObject: function(object) - { - //return object instanceof Event || object instanceof EventCopy; - return instanceOf(object, "Event") || instanceOf(object, "EventCopy"); - }, - - getTitle: function(event, context) - { - return "Event " + event.type; - } -}); - -// ************************************************************************************************ - -this.SourceLink = domplate(Firebug.Rep, -{ - tag: - OBJECTLINK({$collapsed: "$object|hideSourceLink"}, "$object|getSourceLinkTitle"), - - hideSourceLink: function(sourceLink) - { - return sourceLink ? sourceLink.href.indexOf("XPCSafeJSObjectWrapper") != -1 : true; - }, - - getSourceLinkTitle: function(sourceLink) - { - if (!sourceLink) - return ""; - - try - { - var fileName = getFileName(sourceLink.href); - fileName = decodeURIComponent(fileName); - fileName = cropString(fileName, 17); - } - catch(exc) - { - if (FBTrace.DBG_ERRORS) - FBTrace.sysout("reps.getSourceLinkTitle decodeURIComponent fails for \'"+fileName+"\': "+exc, exc); - } - - return typeof sourceLink.line == "number" ? - fileName + " (line " + sourceLink.line + ")" : - fileName; - - // TODO: xxxpedro - //return $STRF("Line", [fileName, sourceLink.line]); - }, - - copyLink: function(sourceLink) - { - copyToClipboard(sourceLink.href); - }, - - openInTab: function(sourceLink) - { - openNewTab(sourceLink.href); - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - className: "sourceLink", - - supportsObject: function(object) - { - return object instanceof SourceLink; - }, - - getTooltip: function(sourceLink) - { - return decodeURI(sourceLink.href); - }, - - inspectObject: function(sourceLink, context) - { - if (sourceLink.type == "js") - { - var scriptFile = getSourceFileByHref(sourceLink.href, context); - if (scriptFile) - return Firebug.chrome.select(sourceLink); - } - else if (sourceLink.type == "css") - { - // If an object is defined, treat it as the highest priority for - // inspect actions - if (sourceLink.object) { - Firebug.chrome.select(sourceLink.object); - return; - } - - var stylesheet = getStyleSheetByHref(sourceLink.href, context); - if (stylesheet) - { - var ownerNode = stylesheet.ownerNode; - if (ownerNode) - { - Firebug.chrome.select(sourceLink, "html"); - return; - } - - var panel = context.getPanel("stylesheet"); - if (panel && panel.getRuleByLine(stylesheet, sourceLink.line)) - return Firebug.chrome.select(sourceLink); - } - } - - // Fallback is to just open the view-source window on the file - viewSource(sourceLink.href, sourceLink.line); - }, - - browseObject: function(sourceLink, context) - { - openNewTab(sourceLink.href); - return true; - }, - - getContextMenuItems: function(sourceLink, target, context) - { - return [ - {label: "CopyLocation", command: bindFixed(this.copyLink, this, sourceLink) }, - "-", - {label: "OpenInTab", command: bindFixed(this.openInTab, this, sourceLink) } - ]; - } -}); - -// ************************************************************************************************ - -this.SourceFile = domplate(this.SourceLink, -{ - tag: - OBJECTLINK({$collapsed: "$object|hideSourceLink"}, "$object|getSourceLinkTitle"), - - persistor: function(context, href) - { - return getSourceFileByHref(href, context); - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - className: "sourceFile", - - supportsObject: function(object) - { - return object instanceof SourceFile; - }, - - persistObject: function(sourceFile) - { - return bind(this.persistor, top, sourceFile.href); - }, - - browseObject: function(sourceLink, context) - { - }, - - getTooltip: function(sourceFile) - { - return sourceFile.href; - } -}); - -// ************************************************************************************************ - -this.StackFrame = domplate(Firebug.Rep, // XXXjjb Since the repObject is fn the stack does not have correct line numbers -{ - tag: - OBJECTBLOCK( - A({"class": "objectLink objectLink-function focusRow a11yFocus", _repObject: "$object.fn"}, "$object|getCallName"), - " ( ", - FOR("arg", "$object|argIterator", - TAG("$arg.tag", {object: "$arg.value"}), - SPAN({"class": "arrayComma"}, "$arg.delim") - ), - " )", - SPAN({"class": "objectLink-sourceLink objectLink"}, "$object|getSourceLinkTitle") - ), - - getCallName: function(frame) - { - //TODO: xxxpedro reps StackFrame - return frame.name || "anonymous"; - - //return getFunctionName(frame.script, frame.context); - }, - - getSourceLinkTitle: function(frame) - { - //TODO: xxxpedro reps StackFrame - var fileName = cropString(getFileName(frame.href), 20); - return fileName + (frame.lineNo ? " (line " + frame.lineNo + ")" : ""); - - var fileName = cropString(getFileName(frame.href), 17); - return $STRF("Line", [fileName, frame.lineNo]); - }, - - argIterator: function(frame) - { - if (!frame.args) - return []; - - var items = []; - - for (var i = 0; i < frame.args.length; ++i) - { - var arg = frame.args[i]; - - if (!arg) - break; - - var rep = Firebug.getRep(arg.value); - var tag = rep.shortTag ? rep.shortTag : rep.tag; - - var delim = (i == frame.args.length-1 ? "" : ", "); - - items.push({name: arg.name, value: arg.value, tag: tag, delim: delim}); - } - - return items; - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - className: "stackFrame", - - supportsObject: function(object) - { - return object instanceof StackFrame; - }, - - inspectObject: function(stackFrame, context) - { - var sourceLink = new SourceLink(stackFrame.href, stackFrame.lineNo, "js"); - Firebug.chrome.select(sourceLink); - }, - - getTooltip: function(stackFrame, context) - { - return $STRF("Line", [stackFrame.href, stackFrame.lineNo]); - } - -}); - -// ************************************************************************************************ - -this.StackTrace = domplate(Firebug.Rep, -{ - tag: - FOR("frame", "$object.frames focusRow", - TAG(this.StackFrame.tag, {object: "$frame"}) - ), - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - className: "stackTrace", - - supportsObject: function(object) - { - return object instanceof StackTrace; - } -}); - -// ************************************************************************************************ - -this.jsdStackFrame = domplate(Firebug.Rep, -{ - inspectable: false, - - supportsObject: function(object) - { - return (object instanceof jsdIStackFrame) && (object.isValid); - }, - - getTitle: function(frame, context) - { - if (!frame.isValid) return "(invalid frame)"; // XXXjjb avoid frame.script == null - return getFunctionName(frame.script, context); - }, - - getTooltip: function(frame, context) - { - if (!frame.isValid) return "(invalid frame)"; // XXXjjb avoid frame.script == null - var sourceInfo = FBL.getSourceFileAndLineByScript(context, frame.script, frame); - if (sourceInfo) - return $STRF("Line", [sourceInfo.sourceFile.href, sourceInfo.lineNo]); - else - return $STRF("Line", [frame.script.fileName, frame.line]); - }, - - getContextMenuItems: function(frame, target, context) - { - var fn = frame.script.functionObject.getWrappedValue(); - return FirebugReps.Func.getContextMenuItems(fn, target, context, frame.script); - } -}); - -// ************************************************************************************************ - -this.ErrorMessage = domplate(Firebug.Rep, -{ - tag: - OBJECTBOX({ - $hasTwisty: "$object|hasStackTrace", - $hasBreakSwitch: "$object|hasBreakSwitch", - $breakForError: "$object|hasErrorBreak", - _repObject: "$object", - _stackTrace: "$object|getLastErrorStackTrace", - onclick: "$onToggleError"}, - - DIV({"class": "errorTitle a11yFocus", role : 'checkbox', 'aria-checked' : 'false'}, - "$object.message|getMessage" - ), - DIV({"class": "errorTrace"}), - DIV({"class": "errorSourceBox errorSource-$object|getSourceType"}, - IMG({"class": "errorBreak a11yFocus", src:"blank.gif", role : 'checkbox', 'aria-checked':'false', title: "Break on this error"}), - A({"class": "errorSource a11yFocus"}, "$object|getLine") - ), - TAG(this.SourceLink.tag, {object: "$object|getSourceLink"}) - ), - - getLastErrorStackTrace: function(error) - { - return error.trace; - }, - - hasStackTrace: function(error) - { - var url = error.href.toString(); - var fromCommandLine = (url.indexOf("XPCSafeJSObjectWrapper") != -1); - return !fromCommandLine && error.trace; - }, - - hasBreakSwitch: function(error) - { - return error.href && error.lineNo > 0; - }, - - hasErrorBreak: function(error) - { - return fbs.hasErrorBreakpoint(error.href, error.lineNo); - }, - - getMessage: function(message) - { - var re = /\[Exception... "(.*?)" nsresult:/; - var m = re.exec(message); - return m ? m[1] : message; - }, - - getLine: function(error) - { - if (error.category == "js") - { - if (error.source) - return cropString(error.source, 80); - else if (error.href && error.href.indexOf("XPCSafeJSObjectWrapper") == -1) - return cropString(error.getSourceLine(), 80); - } - }, - - getSourceLink: function(error) - { - var ext = error.category == "css" ? "css" : "js"; - return error.lineNo ? new SourceLink(error.href, error.lineNo, ext) : null; - }, - - getSourceType: function(error) - { - // Errors occurring inside of HTML event handlers look like "foo.html (line 1)" - // so let's try to skip those - if (error.source) - return "syntax"; - else if (error.lineNo == 1 && getFileExtension(error.href) != "js") - return "none"; - else if (error.category == "css") - return "none"; - else if (!error.href || !error.lineNo) - return "none"; - else - return "exec"; - }, - - onToggleError: function(event) - { - var target = event.currentTarget; - if (hasClass(event.target, "errorBreak")) - { - this.breakOnThisError(target.repObject); - } - else if (hasClass(event.target, "errorSource")) - { - var panel = Firebug.getElementPanel(event.target); - this.inspectObject(target.repObject, panel.context); - } - else if (hasClass(event.target, "errorTitle")) - { - var traceBox = target.childNodes[1]; - toggleClass(target, "opened"); - event.target.setAttribute('aria-checked', hasClass(target, "opened")); - if (hasClass(target, "opened")) - { - if (target.stackTrace) - var node = FirebugReps.StackTrace.tag.append({object: target.stackTrace}, traceBox); - if (Firebug.A11yModel.enabled) - { - var panel = Firebug.getElementPanel(event.target); - dispatch([Firebug.A11yModel], "onLogRowContentCreated", [panel , traceBox]); - } - } - else - clearNode(traceBox); - } - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - copyError: function(error) - { - var message = [ - this.getMessage(error.message), - error.href, - "Line " + error.lineNo - ]; - copyToClipboard(message.join("\n")); - }, - - breakOnThisError: function(error) - { - if (this.hasErrorBreak(error)) - Firebug.Debugger.clearErrorBreakpoint(error.href, error.lineNo); - else - Firebug.Debugger.setErrorBreakpoint(error.href, error.lineNo); - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - className: "errorMessage", - inspectable: false, - - supportsObject: function(object) - { - return object instanceof ErrorMessage; - }, - - inspectObject: function(error, context) - { - var sourceLink = this.getSourceLink(error); - FirebugReps.SourceLink.inspectObject(sourceLink, context); - }, - - getContextMenuItems: function(error, target, context) - { - var breakOnThisError = this.hasErrorBreak(error); - - var items = [ - {label: "CopyError", command: bindFixed(this.copyError, this, error) } - ]; - - if (error.category == "css") - { - items.push( - "-", - {label: "BreakOnThisError", type: "checkbox", checked: breakOnThisError, - command: bindFixed(this.breakOnThisError, this, error) }, - - optionMenu("BreakOnAllErrors", "breakOnErrors") - ); - } - - return items; - } -}); - -// ************************************************************************************************ - -this.Assert = domplate(Firebug.Rep, -{ - tag: - DIV( - DIV({"class": "errorTitle"}), - DIV({"class": "assertDescription"}) - ), - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - className: "assert", - - inspectObject: function(error, context) - { - var sourceLink = this.getSourceLink(error); - Firebug.chrome.select(sourceLink); - }, - - getContextMenuItems: function(error, target, context) - { - var breakOnThisError = this.hasErrorBreak(error); - - return [ - {label: "CopyError", command: bindFixed(this.copyError, this, error) }, - "-", - {label: "BreakOnThisError", type: "checkbox", checked: breakOnThisError, - command: bindFixed(this.breakOnThisError, this, error) }, - {label: "BreakOnAllErrors", type: "checkbox", checked: Firebug.breakOnErrors, - command: bindFixed(this.breakOnAllErrors, this, error) } - ]; - } -}); - -// ************************************************************************************************ - -this.SourceText = domplate(Firebug.Rep, -{ - tag: - DIV( - FOR("line", "$object|lineIterator", - DIV({"class": "sourceRow", role : "presentation"}, - SPAN({"class": "sourceLine", role : "presentation"}, "$line.lineNo"), - SPAN({"class": "sourceRowText", role : "presentation"}, "$line.text") - ) - ) - ), - - lineIterator: function(sourceText) - { - var maxLineNoChars = (sourceText.lines.length + "").length; - var list = []; - - for (var i = 0; i < sourceText.lines.length; ++i) - { - // Make sure all line numbers are the same width (with a fixed-width font) - var lineNo = (i+1) + ""; - while (lineNo.length < maxLineNoChars) - lineNo = " " + lineNo; - - list.push({lineNo: lineNo, text: sourceText.lines[i]}); - } - - return list; - }, - - getHTML: function(sourceText) - { - return getSourceLineRange(sourceText, 1, sourceText.lines.length); - } -}); - -//************************************************************************************************ -this.nsIDOMHistory = domplate(Firebug.Rep, -{ - tag:OBJECTBOX({onclick: "$showHistory"}, - OBJECTLINK("$object|summarizeHistory") - ), - - className: "nsIDOMHistory", - - summarizeHistory: function(history) - { - try - { - var items = history.length; - return items + " history entries"; - } - catch(exc) - { - return "object does not support history (nsIDOMHistory)"; - } - }, - - showHistory: function(history) - { - try - { - var items = history.length; // if this throws, then unsupported - Firebug.chrome.select(history); - } - catch (exc) - { - } - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - supportsObject: function(object, type) - { - return (object instanceof Ci.nsIDOMHistory); - } -}); - -// ************************************************************************************************ -this.ApplicationCache = domplate(Firebug.Rep, -{ - tag:OBJECTBOX({onclick: "$showApplicationCache"}, - OBJECTLINK("$object|summarizeCache") - ), - - summarizeCache: function(applicationCache) - { - try - { - return applicationCache.length + " items in offline cache"; - } - catch(exc) - { - return "https://bugzilla.mozilla.org/show_bug.cgi?id=422264"; - } - }, - - showApplicationCache: function(event) - { - openNewTab("https://bugzilla.mozilla.org/show_bug.cgi?id=422264"); - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - className: "applicationCache", - - supportsObject: function(object, type) - { - if (Ci.nsIDOMOfflineResourceList) - return (object instanceof Ci.nsIDOMOfflineResourceList); - } - -}); - -this.Storage = domplate(Firebug.Rep, -{ - tag: OBJECTBOX({onclick: "$show"}, OBJECTLINK("$object|summarize")), - - summarize: function(storage) - { - return storage.length +" items in Storage"; - }, - show: function(storage) - { - openNewTab("http://dev.w3.org/html5/webstorage/#storage-0"); - }, - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - className: "Storage", - - supportsObject: function(object, type) - { - return (object instanceof Storage); - } - -}); - -// ************************************************************************************************ -Firebug.registerRep( - //this.nsIDOMHistory, // make this early to avoid exceptions - this.Undefined, - this.Null, - this.Number, - this.String, - this.Window, - //this.ApplicationCache, // must come before Arr (array) else exceptions. - //this.ErrorMessage, - this.Element, - //this.TextNode, - this.Document, - this.StyleSheet, - this.Event, - //this.SourceLink, - //this.SourceFile, - //this.StackTrace, - //this.StackFrame, - //this.jsdStackFrame, - //this.jsdScript, - //this.NetFile, - this.Property, - this.Except, - this.Arr -); - -Firebug.setDefaultReps(this.Func, this.Obj); - -}}); - -// ************************************************************************************************ -/* - * The following is http://developer.yahoo.com/yui/license.txt and applies to only code labeled "Yahoo BSD Source" - * in only this file reps.js. John J. Barton June 2007. - * -Software License Agreement (BSD License) - -Copyright (c) 2006, Yahoo! Inc. -All rights reserved. - -Redistribution and use of this software 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 Yahoo! Inc. nor the names of its - contributors may be used to endorse or promote products - derived from this software without specific prior - written permission of Yahoo! Inc. - -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 THE COPYRIGHT OWNER 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. - * / - */ - - -/* See license.txt for terms of usage */ - -FBL.ns(function() { with (FBL) { - -// ************************************************************************************************ -// Constants - -var saveTimeout = 400; -var pageAmount = 10; - -// ************************************************************************************************ -// Globals - -var currentTarget = null; -var currentGroup = null; -var currentPanel = null; -var currentEditor = null; - -var defaultEditor = null; - -var originalClassName = null; - -var originalValue = null; -var defaultValue = null; -var previousValue = null; - -var invalidEditor = false; -var ignoreNextInput = false; - -// ************************************************************************************************ - -Firebug.Editor = extend(Firebug.Module, -{ - supportsStopEvent: true, - - dispatchName: "editor", - tabCharacter: " ", - - startEditing: function(target, value, editor) - { - this.stopEditing(); - - if (hasClass(target, "insertBefore") || hasClass(target, "insertAfter")) - return; - - var panel = Firebug.getElementPanel(target); - if (!panel.editable) - return; - - if (FBTrace.DBG_EDITOR) - FBTrace.sysout("editor.startEditing " + value, target); - - defaultValue = target.getAttribute("defaultValue"); - if (value == undefined) - { - var textContent = isIE ? "innerText" : "textContent"; - value = target[textContent]; - if (value == defaultValue) - value = ""; - } - - originalValue = previousValue = value; - - invalidEditor = false; - currentTarget = target; - currentPanel = panel; - currentGroup = getAncestorByClass(target, "editGroup"); - - currentPanel.editing = true; - - var panelEditor = currentPanel.getEditor(target, value); - currentEditor = editor ? editor : panelEditor; - if (!currentEditor) - currentEditor = getDefaultEditor(currentPanel); - - var inlineParent = getInlineParent(target); - var targetSize = getOffsetSize(inlineParent); - - setClass(panel.panelNode, "editing"); - setClass(target, "editing"); - if (currentGroup) - setClass(currentGroup, "editing"); - - currentEditor.show(target, currentPanel, value, targetSize); - //dispatch(this.fbListeners, "onBeginEditing", [currentPanel, currentEditor, target, value]); - currentEditor.beginEditing(target, value); - if (FBTrace.DBG_EDITOR) - FBTrace.sysout("Editor start panel "+currentPanel.name); - this.attachListeners(currentEditor, panel.context); - }, - - stopEditing: function(cancel) - { - if (!currentTarget) - return; - - if (FBTrace.DBG_EDITOR) - FBTrace.sysout("editor.stopEditing cancel:" + cancel+" saveTimeout: "+this.saveTimeout); - - clearTimeout(this.saveTimeout); - delete this.saveTimeout; - - this.detachListeners(currentEditor, currentPanel.context); - - removeClass(currentPanel.panelNode, "editing"); - removeClass(currentTarget, "editing"); - if (currentGroup) - removeClass(currentGroup, "editing"); - - var value = currentEditor.getValue(); - if (value == defaultValue) - value = ""; - - var removeGroup = currentEditor.endEditing(currentTarget, value, cancel); - - try - { - if (cancel) - { - //dispatch([Firebug.A11yModel], 'onInlineEditorClose', [currentPanel, currentTarget, removeGroup && !originalValue]); - if (value != originalValue) - this.saveEditAndNotifyListeners(currentTarget, originalValue, previousValue); - - if (removeGroup && !originalValue && currentGroup) - currentGroup.parentNode.removeChild(currentGroup); - } - else if (!value) - { - this.saveEditAndNotifyListeners(currentTarget, null, previousValue); - - if (removeGroup && currentGroup) - currentGroup.parentNode.removeChild(currentGroup); - } - else - this.save(value); - } - catch (exc) - { - //throw exc.message; - //ERROR(exc); - } - - currentEditor.hide(); - currentPanel.editing = false; - - //dispatch(this.fbListeners, "onStopEdit", [currentPanel, currentEditor, currentTarget]); - //if (FBTrace.DBG_EDITOR) - // FBTrace.sysout("Editor stop panel "+currentPanel.name); - - currentTarget = null; - currentGroup = null; - currentPanel = null; - currentEditor = null; - originalValue = null; - invalidEditor = false; - - return value; - }, - - cancelEditing: function() - { - return this.stopEditing(true); - }, - - update: function(saveNow) - { - if (this.saveTimeout) - clearTimeout(this.saveTimeout); - - invalidEditor = true; - - currentEditor.layout(); - - if (saveNow) - this.save(); - else - { - var context = currentPanel.context; - this.saveTimeout = context.setTimeout(bindFixed(this.save, this), saveTimeout); - if (FBTrace.DBG_EDITOR) - FBTrace.sysout("editor.update saveTimeout: "+this.saveTimeout); - } - }, - - save: function(value) - { - if (!invalidEditor) - return; - - if (value == undefined) - value = currentEditor.getValue(); - if (FBTrace.DBG_EDITOR) - FBTrace.sysout("editor.save saveTimeout: "+this.saveTimeout+" currentPanel: "+(currentPanel?currentPanel.name:"null")); - try - { - this.saveEditAndNotifyListeners(currentTarget, value, previousValue); - - previousValue = value; - invalidEditor = false; - } - catch (exc) - { - if (FBTrace.DBG_ERRORS) - FBTrace.sysout("editor.save FAILS "+exc, exc); - } - }, - - saveEditAndNotifyListeners: function(currentTarget, value, previousValue) - { - currentEditor.saveEdit(currentTarget, value, previousValue); - //dispatch(this.fbListeners, "onSaveEdit", [currentPanel, currentEditor, currentTarget, value, previousValue]); - }, - - setEditTarget: function(element) - { - if (!element) - { - dispatch([Firebug.A11yModel], 'onInlineEditorClose', [currentPanel, currentTarget, true]); - this.stopEditing(); - } - else if (hasClass(element, "insertBefore")) - this.insertRow(element, "before"); - else if (hasClass(element, "insertAfter")) - this.insertRow(element, "after"); - else - this.startEditing(element); - }, - - tabNextEditor: function() - { - if (!currentTarget) - return; - - var value = currentEditor.getValue(); - var nextEditable = currentTarget; - do - { - nextEditable = !value && currentGroup - ? getNextOutsider(nextEditable, currentGroup) - : getNextByClass(nextEditable, "editable"); - } - while (nextEditable && !nextEditable.offsetHeight); - - this.setEditTarget(nextEditable); - }, - - tabPreviousEditor: function() - { - if (!currentTarget) - return; - - var value = currentEditor.getValue(); - var prevEditable = currentTarget; - do - { - prevEditable = !value && currentGroup - ? getPreviousOutsider(prevEditable, currentGroup) - : getPreviousByClass(prevEditable, "editable"); - } - while (prevEditable && !prevEditable.offsetHeight); - - this.setEditTarget(prevEditable); - }, - - insertRow: function(relative, insertWhere) - { - var group = - relative || getAncestorByClass(currentTarget, "editGroup") || currentTarget; - var value = this.stopEditing(); - - currentPanel = Firebug.getElementPanel(group); - - currentEditor = currentPanel.getEditor(group, value); - if (!currentEditor) - currentEditor = getDefaultEditor(currentPanel); - - currentGroup = currentEditor.insertNewRow(group, insertWhere); - if (!currentGroup) - return; - - var editable = hasClass(currentGroup, "editable") - ? currentGroup - : getNextByClass(currentGroup, "editable"); - - if (editable) - this.setEditTarget(editable); - }, - - insertRowForObject: function(relative) - { - var container = getAncestorByClass(relative, "insertInto"); - if (container) - { - relative = getChildByClass(container, "insertBefore"); - if (relative) - this.insertRow(relative, "before"); - } - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - attachListeners: function(editor, context) - { - var win = isIE ? - currentTarget.ownerDocument.parentWindow : - currentTarget.ownerDocument.defaultView; - - addEvent(win, "resize", this.onResize); - addEvent(win, "blur", this.onBlur); - - var chrome = Firebug.chrome; - - this.listeners = [ - chrome.keyCodeListen("ESCAPE", null, bind(this.cancelEditing, this)) - ]; - - if (editor.arrowCompletion) - { - this.listeners.push( - chrome.keyCodeListen("UP", null, bindFixed(editor.completeValue, editor, -1)), - chrome.keyCodeListen("DOWN", null, bindFixed(editor.completeValue, editor, 1)), - chrome.keyCodeListen("PAGE_UP", null, bindFixed(editor.completeValue, editor, -pageAmount)), - chrome.keyCodeListen("PAGE_DOWN", null, bindFixed(editor.completeValue, editor, pageAmount)) - ); - } - - if (currentEditor.tabNavigation) - { - this.listeners.push( - chrome.keyCodeListen("RETURN", null, bind(this.tabNextEditor, this)), - chrome.keyCodeListen("RETURN", isControl, bind(this.insertRow, this, null, "after")), - chrome.keyCodeListen("TAB", null, bind(this.tabNextEditor, this)), - chrome.keyCodeListen("TAB", isShift, bind(this.tabPreviousEditor, this)) - ); - } - else if (currentEditor.multiLine) - { - this.listeners.push( - chrome.keyCodeListen("TAB", null, insertTab) - ); - } - else - { - this.listeners.push( - chrome.keyCodeListen("RETURN", null, bindFixed(this.stopEditing, this)) - ); - - if (currentEditor.tabCompletion) - { - this.listeners.push( - chrome.keyCodeListen("TAB", null, bind(editor.completeValue, editor, 1)), - chrome.keyCodeListen("TAB", isShift, bind(editor.completeValue, editor, -1)) - ); - } - } - }, - - detachListeners: function(editor, context) - { - if (!this.listeners) - return; - - var win = isIE ? - currentTarget.ownerDocument.parentWindow : - currentTarget.ownerDocument.defaultView; - - removeEvent(win, "resize", this.onResize); - removeEvent(win, "blur", this.onBlur); - - var chrome = Firebug.chrome; - if (chrome) - { - for (var i = 0; i < this.listeners.length; ++i) - chrome.keyIgnore(this.listeners[i]); - } - - delete this.listeners; - }, - - onResize: function(event) - { - currentEditor.layout(true); - }, - - onBlur: function(event) - { - if (currentEditor.enterOnBlur && isAncestor(event.target, currentEditor.box)) - this.stopEditing(); - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // extends Module - - initialize: function() - { - Firebug.Module.initialize.apply(this, arguments); - - this.onResize = bindFixed(this.onResize, this); - this.onBlur = bind(this.onBlur, this); - }, - - disable: function() - { - this.stopEditing(); - }, - - showContext: function(browser, context) - { - this.stopEditing(); - }, - - showPanel: function(browser, panel) - { - this.stopEditing(); - } -}); - -// ************************************************************************************************ -// BaseEditor - -Firebug.BaseEditor = extend(Firebug.MeasureBox, -{ - getValue: function() - { - }, - - setValue: function(value) - { - }, - - show: function(target, panel, value, textSize, targetSize) - { - }, - - hide: function() - { - }, - - layout: function(forceAll) - { - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // Support for context menus within inline editors. - - getContextMenuItems: function(target) - { - var items = []; - items.push({label: "Cut", commandID: "cmd_cut"}); - items.push({label: "Copy", commandID: "cmd_copy"}); - items.push({label: "Paste", commandID: "cmd_paste"}); - return items; - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // Editor Module listeners will get "onBeginEditing" just before this call - - beginEditing: function(target, value) - { - }, - - // Editor Module listeners will get "onSaveEdit" just after this call - saveEdit: function(target, value, previousValue) - { - }, - - endEditing: function(target, value, cancel) - { - // Remove empty groups by default - return true; - }, - - insertNewRow: function(target, insertWhere) - { - } -}); - -// ************************************************************************************************ -// InlineEditor - -// basic inline editor attributes -var inlineEditorAttributes = { - "class": "textEditorInner", - - type: "text", - spellcheck: "false", - - onkeypress: "$onKeyPress", - - onoverflow: "$onOverflow", - oncontextmenu: "$onContextMenu" -}; - -// IE does not support the oninput event, so we're using the onkeydown to signalize -// the relevant keyboard events, and the onpropertychange to actually handle the -// input event, which should happen after the onkeydown event is fired and after the -// value of the input is updated, but before the onkeyup and before the input (with the -// new value) is rendered -if (isIE) -{ - inlineEditorAttributes.onpropertychange = "$onInput"; - inlineEditorAttributes.onkeydown = "$onKeyDown"; -} -// for other browsers we use the oninput event -else -{ - inlineEditorAttributes.oninput = "$onInput"; -} - -Firebug.InlineEditor = function(doc) -{ - this.initializeInline(doc); -}; - -Firebug.InlineEditor.prototype = domplate(Firebug.BaseEditor, -{ - enterOnBlur: true, - outerMargin: 8, - shadowExpand: 7, - - tag: - DIV({"class": "inlineEditor"}, - DIV({"class": "textEditorTop1"}, - DIV({"class": "textEditorTop2"}) - ), - DIV({"class": "textEditorInner1"}, - DIV({"class": "textEditorInner2"}, - INPUT( - inlineEditorAttributes - ) - ) - ), - DIV({"class": "textEditorBottom1"}, - DIV({"class": "textEditorBottom2"}) - ) - ), - - inputTag : - INPUT({"class": "textEditorInner", type: "text", - /*oninput: "$onInput",*/ onkeypress: "$onKeyPress", onoverflow: "$onOverflow"} - ), - - expanderTag: - IMG({"class": "inlineExpander", src: "blank.gif"}), - - initialize: function() - { - this.fixedWidth = false; - this.completeAsYouType = true; - this.tabNavigation = true; - this.multiLine = false; - this.tabCompletion = false; - this.arrowCompletion = true; - this.noWrap = true; - this.numeric = false; - }, - - destroy: function() - { - this.destroyInput(); - }, - - initializeInline: function(doc) - { - if (FBTrace.DBG_EDITOR) - FBTrace.sysout("Firebug.InlineEditor initializeInline()"); - - //this.box = this.tag.replace({}, doc, this); - this.box = this.tag.append({}, doc.body, this); - - //this.input = this.box.childNodes[1].firstChild.firstChild; // XXXjjb childNode[1] required - this.input = this.box.getElementsByTagName("input")[0]; - - if (isIElt8) - { - this.input.style.top = "-8px"; - } - - this.expander = this.expanderTag.replace({}, doc, this); - this.initialize(); - }, - - destroyInput: function() - { - // XXXjoe Need to remove input/keypress handlers to avoid leaks - }, - - getValue: function() - { - return this.input.value; - }, - - setValue: function(value) - { - // It's only a one-line editor, so new lines shouldn't be allowed - return this.input.value = stripNewLines(value); - }, - - show: function(target, panel, value, targetSize) - { - //dispatch([Firebug.A11yModel], "onInlineEditorShow", [panel, this]); - this.target = target; - this.panel = panel; - - this.targetSize = targetSize; - - // TODO: xxxpedro editor - //this.targetOffset = getClientOffset(target); - - // Some browsers (IE, Google Chrome and Safari) will have problem trying to get the - // offset values of invisible elements, or empty elements. So, in order to get the - // correct values, we temporary inject a character in the innerHTML of the empty element, - // then we get the offset values, and next, we restore the original innerHTML value. - var innerHTML = target.innerHTML; - var isEmptyElement = !innerHTML; - if (isEmptyElement) - target.innerHTML = "."; - - // Get the position of the target element (that is about to be edited) - this.targetOffset = - { - x: target.offsetLeft, - y: target.offsetTop - }; - - // Restore the original innerHTML value of the empty element - if (isEmptyElement) - target.innerHTML = innerHTML; - - this.originalClassName = this.box.className; - - var classNames = target.className.split(" "); - for (var i = 0; i < classNames.length; ++i) - setClass(this.box, "editor-" + classNames[i]); - - // Make the editor match the target's font style - copyTextStyles(target, this.box); - - this.setValue(value); - - if (this.fixedWidth) - this.updateLayout(true); - else - { - this.startMeasuring(target); - this.textSize = this.measureInputText(value); - - // Correct the height of the box to make the funky CSS drop-shadow line up - var parent = this.input.parentNode; - if (hasClass(parent, "textEditorInner2")) - { - var yDiff = this.textSize.height - this.shadowExpand; - - // IE6 height offset - if (isIE6) - yDiff -= 2; - - parent.style.height = yDiff + "px"; - parent.parentNode.style.height = yDiff + "px"; - } - - this.updateLayout(true); - } - - this.getAutoCompleter().reset(); - - if (isIElt8) - panel.panelNode.appendChild(this.box); - else - target.offsetParent.appendChild(this.box); - - //console.log(target); - //this.input.select(); // it's called bellow, with setTimeout - - if (isIE) - { - // reset input style - this.input.style.fontFamily = "Monospace"; - this.input.style.fontSize = "11px"; - } - - // Insert the "expander" to cover the target element with white space - if (!this.fixedWidth) - { - copyBoxStyles(target, this.expander); - - target.parentNode.replaceChild(this.expander, target); - collapse(target, true); - this.expander.parentNode.insertBefore(target, this.expander); - } - - //TODO: xxxpedro - //scrollIntoCenterView(this.box, null, true); - - // Display the editor after change its size and position to avoid flickering - this.box.style.display = "block"; - - // we need to call input.focus() and input.select() with a timeout, - // otherwise it won't work on all browsers due to timing issues - var self = this; - setTimeout(function(){ - self.input.focus(); - self.input.select(); - },0); - }, - - hide: function() - { - this.box.className = this.originalClassName; - - if (!this.fixedWidth) - { - this.stopMeasuring(); - - collapse(this.target, false); - - if (this.expander.parentNode) - this.expander.parentNode.removeChild(this.expander); - } - - if (this.box.parentNode) - { - ///setSelectionRange(this.input, 0, 0); - this.input.blur(); - - this.box.parentNode.removeChild(this.box); - } - - delete this.target; - delete this.panel; - }, - - layout: function(forceAll) - { - if (!this.fixedWidth) - this.textSize = this.measureInputText(this.input.value); - - if (forceAll) - this.targetOffset = getClientOffset(this.expander); - - this.updateLayout(false, forceAll); - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - beginEditing: function(target, value) - { - }, - - saveEdit: function(target, value, previousValue) - { - }, - - endEditing: function(target, value, cancel) - { - // Remove empty groups by default - return true; - }, - - insertNewRow: function(target, insertWhere) - { - }, - - advanceToNext: function(target, charCode) - { - return false; - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - getAutoCompleteRange: function(value, offset) - { - }, - - getAutoCompleteList: function(preExpr, expr, postExpr) - { - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - getAutoCompleter: function() - { - if (!this.autoCompleter) - { - this.autoCompleter = new Firebug.AutoCompleter(null, - bind(this.getAutoCompleteRange, this), bind(this.getAutoCompleteList, this), - true, false); - } - - return this.autoCompleter; - }, - - completeValue: function(amt) - { - //console.log("completeValue"); - - var selectRangeCallback = this.getAutoCompleter().complete(currentPanel.context, this.input, true, amt < 0); - - if (selectRangeCallback) - { - Firebug.Editor.update(true); - - // We need to select the editor text after calling update in Safari/Chrome, - // otherwise the text won't be selected - if (isSafari) - setTimeout(selectRangeCallback,0); - else - selectRangeCallback(); - } - else - this.incrementValue(amt); - }, - - incrementValue: function(amt) - { - var value = this.input.value; - - // TODO: xxxpedro editor - if (isIE) - var start = getInputSelectionStart(this.input), end = start; - else - var start = this.input.selectionStart, end = this.input.selectionEnd; - - //debugger; - var range = this.getAutoCompleteRange(value, start); - if (!range || range.type != "int") - range = {start: 0, end: value.length-1}; - - var expr = value.substr(range.start, range.end-range.start+1); - preExpr = value.substr(0, range.start); - postExpr = value.substr(range.end+1); - - // See if the value is an integer, and if so increment it - var intValue = parseInt(expr); - if (!!intValue || intValue == 0) - { - var m = /\d+/.exec(expr); - var digitPost = expr.substr(m.index+m[0].length); - - var completion = intValue-amt; - this.input.value = preExpr + completion + digitPost + postExpr; - - setSelectionRange(this.input, start, end); - - Firebug.Editor.update(true); - - return true; - } - else - return false; - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - onKeyPress: function(event) - { - //console.log("onKeyPress", event); - if (event.keyCode == 27 && !this.completeAsYouType) - { - var reverted = this.getAutoCompleter().revert(this.input); - if (reverted) - cancelEvent(event); - } - else if (event.charCode && this.advanceToNext(this.target, event.charCode)) - { - Firebug.Editor.tabNextEditor(); - cancelEvent(event); - } - else - { - if (this.numeric && event.charCode && (event.charCode < 48 || event.charCode > 57) - && event.charCode != 45 && event.charCode != 46) - FBL.cancelEvent(event); - else - { - // If the user backspaces, don't autocomplete after the upcoming input event - this.ignoreNextInput = event.keyCode == 8; - } - } - }, - - onOverflow: function() - { - this.updateLayout(false, false, 3); - }, - - onKeyDown: function(event) - { - //console.log("onKeyDown", event.keyCode); - if (event.keyCode > 46 || event.keyCode == 32 || event.keyCode == 8) - { - this.keyDownPressed = true; - } - }, - - onInput: function(event) - { - //debugger; - - // skip not relevant onpropertychange calls on IE - if (isIE) - { - if (event.propertyName != "value" || !isVisible(this.input) || !this.keyDownPressed) - return; - - this.keyDownPressed = false; - } - - //console.log("onInput", event); - //console.trace(); - - var selectRangeCallback; - - if (this.ignoreNextInput) - { - this.ignoreNextInput = false; - this.getAutoCompleter().reset(); - } - else if (this.completeAsYouType) - selectRangeCallback = this.getAutoCompleter().complete(currentPanel.context, this.input, false); - else - this.getAutoCompleter().reset(); - - Firebug.Editor.update(); - - if (selectRangeCallback) - { - // We need to select the editor text after calling update in Safari/Chrome, - // otherwise the text won't be selected - if (isSafari) - setTimeout(selectRangeCallback,0); - else - selectRangeCallback(); - } - }, - - onContextMenu: function(event) - { - cancelEvent(event); - - var popup = $("fbInlineEditorPopup"); - FBL.eraseNode(popup); - - var target = event.target || event.srcElement; - var menu = this.getContextMenuItems(target); - if (menu) - { - for (var i = 0; i < menu.length; ++i) - FBL.createMenuItem(popup, menu[i]); - } - - if (!popup.firstChild) - return false; - - popup.openPopupAtScreen(event.screenX, event.screenY, true); - return true; - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - updateLayout: function(initial, forceAll, extraWidth) - { - if (this.fixedWidth) - { - this.box.style.left = (this.targetOffset.x) + "px"; - this.box.style.top = (this.targetOffset.y) + "px"; - - var w = this.target.offsetWidth; - var h = this.target.offsetHeight; - this.input.style.width = w + "px"; - this.input.style.height = (h-3) + "px"; - } - else - { - if (initial || forceAll) - { - this.box.style.left = this.targetOffset.x + "px"; - this.box.style.top = this.targetOffset.y + "px"; - } - - var approxTextWidth = this.textSize.width; - var maxWidth = (currentPanel.panelNode.scrollWidth - this.targetOffset.x) - - this.outerMargin; - - var wrapped = initial - ? this.noWrap && this.targetSize.height > this.textSize.height+3 - : this.noWrap && approxTextWidth > maxWidth; - - if (wrapped) - { - var style = isIE ? - this.target.currentStyle : - this.target.ownerDocument.defaultView.getComputedStyle(this.target, ""); - - targetMargin = parseInt(style.marginLeft) + parseInt(style.marginRight); - - // Make the width fit the remaining x-space from the offset to the far right - approxTextWidth = maxWidth - targetMargin; - - this.input.style.width = "100%"; - this.box.style.width = approxTextWidth + "px"; - } - else - { - // Make the input one character wider than the text value so that - // typing does not ever cause the textbox to scroll - var charWidth = this.measureInputText('m').width; - - // Sometimes we need to make the editor a little wider, specifically when - // an overflow happens, otherwise it will scroll off some text on the left - if (extraWidth) - charWidth *= extraWidth; - - var inputWidth = approxTextWidth + charWidth; - - if (initial) - { - if (isIE) - { - // TODO: xxxpedro - var xDiff = 13; - this.box.style.width = (inputWidth + xDiff) + "px"; - } - else - this.box.style.width = "auto"; - } - else - { - // TODO: xxxpedro - var xDiff = isIE ? 13: this.box.scrollWidth - this.input.offsetWidth; - this.box.style.width = (inputWidth + xDiff) + "px"; - } - - this.input.style.width = inputWidth + "px"; - } - - this.expander.style.width = approxTextWidth + "px"; - this.expander.style.height = Math.max(this.textSize.height-3,0) + "px"; - } - - if (forceAll) - scrollIntoCenterView(this.box, null, true); - } -}); - -// ************************************************************************************************ -// Autocompletion - -Firebug.AutoCompleter = function(getExprOffset, getRange, evaluator, selectMode, caseSensitive) -{ - var candidates = null; - var originalValue = null; - var originalOffset = -1; - var lastExpr = null; - var lastOffset = -1; - var exprOffset = 0; - var lastIndex = 0; - var preParsed = null; - var preExpr = null; - var postExpr = null; - - this.revert = function(textBox) - { - if (originalOffset != -1) - { - textBox.value = originalValue; - - setSelectionRange(textBox, originalOffset, originalOffset); - - this.reset(); - return true; - } - else - { - this.reset(); - return false; - } - }; - - this.reset = function() - { - candidates = null; - originalValue = null; - originalOffset = -1; - lastExpr = null; - lastOffset = 0; - exprOffset = 0; - }; - - this.complete = function(context, textBox, cycle, reverse) - { - //console.log("complete", context, textBox, cycle, reverse); - // TODO: xxxpedro important port to firebug (variable leak) - //var value = lastValue = textBox.value; - var value = textBox.value; - - //var offset = textBox.selectionStart; - var offset = getInputSelectionStart(textBox); - - // The result of selectionStart() in Safari/Chrome is 1 unit less than the result - // in Firefox. Therefore, we need to manually adjust the value here. - if (isSafari && !cycle && offset >= 0) offset++; - - if (!selectMode && originalOffset != -1) - offset = originalOffset; - - if (!candidates || !cycle || offset != lastOffset) - { - originalOffset = offset; - originalValue = value; - - // Find the part of the string that will be parsed - var parseStart = getExprOffset ? getExprOffset(value, offset, context) : 0; - preParsed = value.substr(0, parseStart); - var parsed = value.substr(parseStart); - - // Find the part of the string that is being completed - var range = getRange ? getRange(parsed, offset-parseStart, context) : null; - if (!range) - range = {start: 0, end: parsed.length-1 }; - - var expr = parsed.substr(range.start, range.end-range.start+1); - preExpr = parsed.substr(0, range.start); - postExpr = parsed.substr(range.end+1); - exprOffset = parseStart + range.start; - - if (!cycle) - { - if (!expr) - return; - else if (lastExpr && lastExpr.indexOf(expr) != 0) - { - candidates = null; - } - else if (lastExpr && lastExpr.length >= expr.length) - { - candidates = null; - lastExpr = expr; - return; - } - } - - lastExpr = expr; - lastOffset = offset; - - var searchExpr; - - // Check if the cursor is at the very right edge of the expression, or - // somewhere in the middle of it - if (expr && offset != parseStart+range.end+1) - { - if (cycle) - { - // We are in the middle of the expression, but we can - // complete by cycling to the next item in the values - // list after the expression - offset = range.start; - searchExpr = expr; - expr = ""; - } - else - { - // We can't complete unless we are at the ridge edge - return; - } - } - - var values = evaluator(preExpr, expr, postExpr, context); - if (!values) - return; - - if (expr) - { - // Filter the list of values to those which begin with expr. We - // will then go on to complete the first value in the resulting list - candidates = []; - - if (caseSensitive) - { - for (var i = 0; i < values.length; ++i) - { - var name = values[i]; - if (name.indexOf && name.indexOf(expr) == 0) - candidates.push(name); - } - } - else - { - var lowerExpr = caseSensitive ? expr : expr.toLowerCase(); - for (var i = 0; i < values.length; ++i) - { - var name = values[i]; - if (name.indexOf && name.toLowerCase().indexOf(lowerExpr) == 0) - candidates.push(name); - } - } - - lastIndex = reverse ? candidates.length-1 : 0; - } - else if (searchExpr) - { - var searchIndex = -1; - - // Find the first instance of searchExpr in the values list. We - // will then complete the string that is found - if (caseSensitive) - { - searchIndex = values.indexOf(expr); - } - else - { - var lowerExpr = searchExpr.toLowerCase(); - for (var i = 0; i < values.length; ++i) - { - var name = values[i]; - if (name && name.toLowerCase().indexOf(lowerExpr) == 0) - { - searchIndex = i; - break; - } - } - } - - // Nothing found, so there's nothing to complete to - if (searchIndex == -1) - return this.reset(); - - expr = searchExpr; - candidates = cloneArray(values); - lastIndex = searchIndex; - } - else - { - expr = ""; - candidates = []; - for (var i = 0; i < values.length; ++i) - { - if (values[i].substr) - candidates.push(values[i]); - } - lastIndex = -1; - } - } - - if (cycle) - { - expr = lastExpr; - lastIndex += reverse ? -1 : 1; - } - - if (!candidates.length) - return; - - if (lastIndex >= candidates.length) - lastIndex = 0; - else if (lastIndex < 0) - lastIndex = candidates.length-1; - - var completion = candidates[lastIndex]; - var preCompletion = expr.substr(0, offset-exprOffset); - var postCompletion = completion.substr(offset-exprOffset); - - textBox.value = preParsed + preExpr + preCompletion + postCompletion + postExpr; - var offsetEnd = preParsed.length + preExpr.length + completion.length; - - // TODO: xxxpedro remove the following commented code, if the lib.setSelectionRange() - // is working well. - /* - if (textBox.setSelectionRange) - { - // we must select the range with a timeout, otherwise the text won't - // be properly selected (because after this function executes, the editor's - // input will be resized to fit the whole text) - setTimeout(function(){ - if (selectMode) - textBox.setSelectionRange(offset, offsetEnd); - else - textBox.setSelectionRange(offsetEnd, offsetEnd); - },0); - } - /**/ - - // we must select the range with a timeout, otherwise the text won't - // be properly selected (because after this function executes, the editor's - // input will be resized to fit the whole text) - /* - setTimeout(function(){ - if (selectMode) - setSelectionRange(textBox, offset, offsetEnd); - else - setSelectionRange(textBox, offsetEnd, offsetEnd); - },0); - - return true; - /**/ - - // The editor text should be selected only after calling the editor.update() - // in Safari/Chrome, otherwise the text won't be selected. So, we're returning - // a function to be called later (in the proper time for all browsers). - // - // TODO: xxxpedro see if we can move the editor.update() calls to here, and avoid - // returning a closure. the complete() function seems to be called only twice in - // editor.js. See if this function is called anywhere else (like css.js for example). - return function(){ - //console.log("autocomplete ", textBox, offset, offsetEnd); - - if (selectMode) - setSelectionRange(textBox, offset, offsetEnd); - else - setSelectionRange(textBox, offsetEnd, offsetEnd); - }; - /**/ - }; -}; - -// ************************************************************************************************ -// Local Helpers - -var getDefaultEditor = function getDefaultEditor(panel) -{ - if (!defaultEditor) - { - var doc = panel.document; - defaultEditor = new Firebug.InlineEditor(doc); - } - - return defaultEditor; -} - -/** - * An outsider is the first element matching the stepper element that - * is not an child of group. Elements tagged with insertBefore or insertAfter - * classes are also excluded from these results unless they are the sibling - * of group, relative to group's parent editGroup. This allows for the proper insertion - * rows when groups are nested. - */ -var getOutsider = function getOutsider(element, group, stepper) -{ - var parentGroup = getAncestorByClass(group.parentNode, "editGroup"); - var next; - do - { - next = stepper(next || element); - } - while (isAncestor(next, group) || isGroupInsert(next, parentGroup)); - - return next; -} - -var isGroupInsert = function isGroupInsert(next, group) -{ - return (!group || isAncestor(next, group)) - && (hasClass(next, "insertBefore") || hasClass(next, "insertAfter")); -} - -var getNextOutsider = function getNextOutsider(element, group) -{ - return getOutsider(element, group, bind(getNextByClass, FBL, "editable")); -} - -var getPreviousOutsider = function getPreviousOutsider(element, group) -{ - return getOutsider(element, group, bind(getPreviousByClass, FBL, "editable")); -} - -var getInlineParent = function getInlineParent(element) -{ - var lastInline = element; - for (; element; element = element.parentNode) - { - //var s = element.ownerDocument.defaultView.getComputedStyle(element, ""); - var s = isIE ? - element.currentStyle : - element.ownerDocument.defaultView.getComputedStyle(element, ""); - - if (s.display != "inline") - return lastInline; - else - lastInline = element; - } - return null; -} - -var insertTab = function insertTab() -{ - insertTextIntoElement(currentEditor.input, Firebug.Editor.tabCharacter); -} - -// ************************************************************************************************ - -Firebug.registerModule(Firebug.Editor); - -// ************************************************************************************************ - -}}); - - -/* See license.txt for terms of usage */ - -FBL.ns(function() { with (FBL) { -// ************************************************************************************************ - -if (Env.Options.disableXHRListener) - return; - -// ************************************************************************************************ -// XHRSpy - -var XHRSpy = function() -{ - this.requestHeaders = []; - this.responseHeaders = []; -}; - -XHRSpy.prototype = -{ - method: null, - url: null, - async: null, - - xhrRequest: null, - - href: null, - - loaded: false, - - logRow: null, - - responseText: null, - - requestHeaders: null, - responseHeaders: null, - - sourceLink: null, // {href:"file.html", line: 22} - - getURL: function() - { - return this.href; - } -}; - -// ************************************************************************************************ -// XMLHttpRequestWrapper - -var XMLHttpRequestWrapper = function(activeXObject) -{ - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // XMLHttpRequestWrapper internal variables - - var xhrRequest = typeof activeXObject != "undefined" ? - activeXObject : - new _XMLHttpRequest(), - - spy = new XHRSpy(), - - self = this, - - reqType, - reqUrl, - reqStartTS; - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // XMLHttpRequestWrapper internal methods - - var updateSelfPropertiesIgnore = { - abort: 1, - channel: 1, - getAllResponseHeaders: 1, - getInterface: 1, - getResponseHeader: 1, - mozBackgroundRequest: 1, - multipart: 1, - onreadystatechange: 1, - open: 1, - send: 1, - setRequestHeader: 1 - }; - - var updateSelfProperties = function() - { - if (supportsXHRIterator) - { - for (var propName in xhrRequest) - { - if (propName in updateSelfPropertiesIgnore) - continue; - - try - { - var propValue = xhrRequest[propName]; - - if (propValue && !isFunction(propValue)) - self[propName] = propValue; - } - catch(E) - { - //console.log(propName, E.message); - } - } - } - else - { - // will fail to read these xhrRequest properties if the request is not completed - if (xhrRequest.readyState == 4) - { - self.status = xhrRequest.status; - self.statusText = xhrRequest.statusText; - self.responseText = xhrRequest.responseText; - self.responseXML = xhrRequest.responseXML; - } - } - }; - - var updateXHRPropertiesIgnore = { - channel: 1, - onreadystatechange: 1, - readyState: 1, - responseBody: 1, - responseText: 1, - responseXML: 1, - status: 1, - statusText: 1, - upload: 1 - }; - - var updateXHRProperties = function() - { - for (var propName in self) - { - if (propName in updateXHRPropertiesIgnore) - continue; - - try - { - var propValue = self[propName]; - - if (propValue && !xhrRequest[propName]) - { - xhrRequest[propName] = propValue; - } - } - catch(E) - { - //console.log(propName, E.message); - } - } - }; - - var logXHR = function() - { - var row = Firebug.Console.log(spy, null, "spy", Firebug.Spy.XHR); - - if (row) - { - setClass(row, "loading"); - spy.logRow = row; - } - }; - - var finishXHR = function() - { - var duration = new Date().getTime() - reqStartTS; - var success = xhrRequest.status == 200; - - var responseHeadersText = xhrRequest.getAllResponseHeaders(); - var responses = responseHeadersText ? responseHeadersText.split(/[\n\r]/) : []; - var reHeader = /^(\S+):\s*(.*)/; - - for (var i=0, l=responses.length; i<l; i++) - { - var text = responses[i]; - var match = text.match(reHeader); - - if (match) - { - var name = match[1]; - var value = match[2]; - - // update the spy mimeType property so we can detect when to show - // custom response viewers (such as HTML, XML or JSON viewer) - if (name == "Content-Type") - spy.mimeType = value; - - /* - if (name == "Last Modified") - { - if (!spy.cacheEntry) - spy.cacheEntry = []; - - spy.cacheEntry.push({ - name: [name], - value: [value] - }); - } - /**/ - - spy.responseHeaders.push({ - name: [name], - value: [value] - }); - } - } - - with({ - row: spy.logRow, - status: xhrRequest.status == 0 ? - // if xhrRequest.status == 0 then accessing xhrRequest.statusText - // will cause an error, so we must handle this case (Issue 3504) - "" : xhrRequest.status + " " + xhrRequest.statusText, - time: duration, - success: success - }) - { - setTimeout(function(){ - - spy.responseText = xhrRequest.responseText; - - // update row information to avoid "ethernal spinning gif" bug in IE - row = row || spy.logRow; - - // if chrome document is not loaded, there will be no row yet, so just ignore - if (!row) return; - - // update the XHR representation data - handleRequestStatus(success, status, time); - - },200); - } - - spy.loaded = true; - /* - // commented because they are being updated by the updateSelfProperties() function - self.status = xhrRequest.status; - self.statusText = xhrRequest.statusText; - self.responseText = xhrRequest.responseText; - self.responseXML = xhrRequest.responseXML; - /**/ - updateSelfProperties(); - }; - - var handleStateChange = function() - { - //Firebug.Console.log(["onreadystatechange", xhrRequest.readyState, xhrRequest.readyState == 4 && xhrRequest.status]); - - self.readyState = xhrRequest.readyState; - - if (xhrRequest.readyState == 4) - { - finishXHR(); - - xhrRequest.onreadystatechange = function(){}; - } - - //Firebug.Console.log(spy.url + ": " + xhrRequest.readyState); - - self.onreadystatechange(); - }; - - // update the XHR representation data - var handleRequestStatus = function(success, status, time) - { - var row = spy.logRow; - FBL.removeClass(row, "loading"); - - if (!success) - FBL.setClass(row, "error"); - - var item = FBL.$$(".spyStatus", row)[0]; - item.innerHTML = status; - - if (time) - { - var item = FBL.$$(".spyTime", row)[0]; - item.innerHTML = time + "ms"; - } - }; - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // XMLHttpRequestWrapper public properties and handlers - - this.readyState = 0; - - this.onreadystatechange = function(){}; - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // XMLHttpRequestWrapper public methods - - this.open = function(method, url, async, user, password) - { - //Firebug.Console.log("xhrRequest open"); - - updateSelfProperties(); - - if (spy.loaded) - spy = new XHRSpy(); - - spy.method = method; - spy.url = url; - spy.async = async; - spy.href = url; - spy.xhrRequest = xhrRequest; - spy.urlParams = parseURLParamsArray(url); - - try - { - // xhrRequest.open.apply may not be available in IE - if (supportsApply) - xhrRequest.open.apply(xhrRequest, arguments); - else - xhrRequest.open(method, url, async, user, password); - } - catch(e) - { - } - - xhrRequest.onreadystatechange = handleStateChange; - - }; - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - this.send = function(data) - { - //Firebug.Console.log("xhrRequest send"); - spy.data = data; - - reqStartTS = new Date().getTime(); - - updateXHRProperties(); - - try - { - xhrRequest.send(data); - } - catch(e) - { - // TODO: xxxpedro XHR throws or not? - //throw e; - } - finally - { - logXHR(); - - if (!spy.async) - { - self.readyState = xhrRequest.readyState; - - // sometimes an error happens when calling finishXHR() - // Issue 3422: Firebug Lite breaks Google Instant Search - try - { - finishXHR(); - } - catch(E) - { - } - } - } - }; - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - this.setRequestHeader = function(header, value) - { - spy.requestHeaders.push({name: [header], value: [value]}); - return xhrRequest.setRequestHeader(header, value); - }; - - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - this.abort = function() - { - xhrRequest.abort(); - updateSelfProperties(); - handleRequestStatus(false, "Aborted"); - }; - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - this.getResponseHeader = function(header) - { - return xhrRequest.getResponseHeader(header); - }; - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - this.getAllResponseHeaders = function() - { - return xhrRequest.getAllResponseHeaders(); - }; - - /**/ - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // Clone XHR object - - // xhrRequest.open.apply not available in IE and will throw an error in - // IE6 by simply reading xhrRequest.open so we must sniff it - var supportsApply = !isIE6 && - xhrRequest && - xhrRequest.open && - typeof xhrRequest.open.apply != "undefined"; - - var numberOfXHRProperties = 0; - for (var propName in xhrRequest) - { - numberOfXHRProperties++; - - if (propName in updateSelfPropertiesIgnore) - continue; - - try - { - var propValue = xhrRequest[propName]; - - if (isFunction(propValue)) - { - if (typeof self[propName] == "undefined") - { - this[propName] = (function(name, xhr){ - - return supportsApply ? - // if the browser supports apply - function() - { - return xhr[name].apply(xhr, arguments); - } - : - function(a,b,c,d,e) - { - return xhr[name](a,b,c,d,e); - }; - - })(propName, xhrRequest); - } - } - else - this[propName] = propValue; - } - catch(E) - { - //console.log(propName, E.message); - } - } - - // IE6 does not support for (var prop in XHR) - var supportsXHRIterator = numberOfXHRProperties > 0; - - /**/ - - return this; -}; - -// ************************************************************************************************ -// ActiveXObject Wrapper (IE6 only) - -var _ActiveXObject; -var isIE6 = /msie 6/i.test(navigator.appVersion); - -if (isIE6) -{ - _ActiveXObject = window.ActiveXObject; - - var xhrObjects = " MSXML2.XMLHTTP.5.0 MSXML2.XMLHTTP.4.0 MSXML2.XMLHTTP.3.0 MSXML2.XMLHTTP Microsoft.XMLHTTP "; - - window.ActiveXObject = function(name) - { - var error = null; - - try - { - var activeXObject = new _ActiveXObject(name); - } - catch(e) - { - error = e; - } - finally - { - if (!error) - { - if (xhrObjects.indexOf(" " + name + " ") != -1) - return new XMLHttpRequestWrapper(activeXObject); - else - return activeXObject; - } - else - throw error.message; - } - }; -} - -// ************************************************************************************************ - -// Register the XMLHttpRequestWrapper for non-IE6 browsers -if (!isIE6) -{ - var _XMLHttpRequest = XMLHttpRequest; - window.XMLHttpRequest = function() - { - return new XMLHttpRequestWrapper(); - }; -} - -//************************************************************************************************ - -FBL.getNativeXHRObject = function() -{ - var xhrObj = false; - try - { - xhrObj = new _XMLHttpRequest(); - } - catch(e) - { - var progid = [ - "MSXML2.XMLHTTP.5.0", "MSXML2.XMLHTTP.4.0", - "MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP", "Microsoft.XMLHTTP" - ]; - - for ( var i=0; i < progid.length; ++i ) { - try - { - xhrObj = new _ActiveXObject(progid[i]); - } - catch(e) - { - continue; - } - break; - } - } - finally - { - return xhrObj; - } -}; - -// ************************************************************************************************ -}}); - - -/* See license.txt for terms of usage */ - -FBL.ns(function() { with (FBL) { -// ************************************************************************************************ - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - -var reIgnore = /about:|javascript:|resource:|chrome:|jar:/; -var layoutInterval = 300; -var indentWidth = 18; - -var cacheSession = null; -var contexts = new Array(); -var panelName = "net"; -var maxQueueRequests = 500; -//var panelBar1 = $("fbPanelBar1"); // chrome not available at startup -var activeRequests = []; - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - -var mimeExtensionMap = -{ - "txt": "text/plain", - "html": "text/html", - "htm": "text/html", - "xhtml": "text/html", - "xml": "text/xml", - "css": "text/css", - "js": "application/x-javascript", - "jss": "application/x-javascript", - "jpg": "image/jpg", - "jpeg": "image/jpeg", - "gif": "image/gif", - "png": "image/png", - "bmp": "image/bmp", - "swf": "application/x-shockwave-flash", - "flv": "video/x-flv" -}; - -var fileCategories = -{ - "undefined": 1, - "html": 1, - "css": 1, - "js": 1, - "xhr": 1, - "image": 1, - "flash": 1, - "txt": 1, - "bin": 1 -}; - -var textFileCategories = -{ - "txt": 1, - "html": 1, - "xhr": 1, - "css": 1, - "js": 1 -}; - -var binaryFileCategories = -{ - "bin": 1, - "flash": 1 -}; - -var mimeCategoryMap = -{ - "text/plain": "txt", - "application/octet-stream": "bin", - "text/html": "html", - "text/xml": "html", - "text/css": "css", - "application/x-javascript": "js", - "text/javascript": "js", - "application/javascript" : "js", - "image/jpeg": "image", - "image/jpg": "image", - "image/gif": "image", - "image/png": "image", - "image/bmp": "image", - "application/x-shockwave-flash": "flash", - "video/x-flv": "flash" -}; - -var binaryCategoryMap = -{ - "image": 1, - "flash" : 1 -}; - -// ************************************************************************************************ - -/** - * @module Represents a module object for the Net panel. This object is derived - * from <code>Firebug.ActivableModule</code> in order to support activation (enable/disable). - * This allows to avoid (performance) expensive features if the functionality is not necessary - * for the user. - */ -Firebug.NetMonitor = extend(Firebug.ActivableModule, -{ - dispatchName: "netMonitor", - - clear: function(context) - { - // The user pressed a Clear button so, remove content of the panel... - var panel = context.getPanel(panelName, true); - if (panel) - panel.clear(); - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // extends Module - - initialize: function() - { - return; - - this.panelName = panelName; - - Firebug.ActivableModule.initialize.apply(this, arguments); - - if (Firebug.TraceModule) - Firebug.TraceModule.addListener(this.TraceListener); - - // HTTP observer must be registered now (and not in monitorContext, since if a - // page is opened in a new tab the top document request would be missed otherwise. - NetHttpObserver.registerObserver(); - NetHttpActivityObserver.registerObserver(); - - Firebug.Debugger.addListener(this.DebuggerListener); - }, - - shutdown: function() - { - return; - - prefs.removeObserver(Firebug.prefDomain, this, false); - if (Firebug.TraceModule) - Firebug.TraceModule.removeListener(this.TraceListener); - - NetHttpObserver.unregisterObserver(); - NetHttpActivityObserver.unregisterObserver(); - - Firebug.Debugger.removeListener(this.DebuggerListener); - } -}); - - -/** - * @domplate Represents a template that is used to reneder detailed info about a request. - * This template is rendered when a request is expanded. - */ -Firebug.NetMonitor.NetInfoBody = domplate(Firebug.Rep, new Firebug.Listener(), -{ - tag: - DIV({"class": "netInfoBody", _repObject: "$file"}, - TAG("$infoTabs", {file: "$file"}), - TAG("$infoBodies", {file: "$file"}) - ), - - infoTabs: - DIV({"class": "netInfoTabs focusRow subFocusRow", "role": "tablist"}, - A({"class": "netInfoParamsTab netInfoTab a11yFocus", onclick: "$onClickTab", "role": "tab", - view: "Params", - $collapsed: "$file|hideParams"}, - $STR("URLParameters") - ), - A({"class": "netInfoHeadersTab netInfoTab a11yFocus", onclick: "$onClickTab", "role": "tab", - view: "Headers"}, - $STR("Headers") - ), - A({"class": "netInfoPostTab netInfoTab a11yFocus", onclick: "$onClickTab", "role": "tab", - view: "Post", - $collapsed: "$file|hidePost"}, - $STR("Post") - ), - A({"class": "netInfoPutTab netInfoTab a11yFocus", onclick: "$onClickTab", "role": "tab", - view: "Put", - $collapsed: "$file|hidePut"}, - $STR("Put") - ), - A({"class": "netInfoResponseTab netInfoTab a11yFocus", onclick: "$onClickTab", "role": "tab", - view: "Response", - $collapsed: "$file|hideResponse"}, - $STR("Response") - ), - A({"class": "netInfoCacheTab netInfoTab a11yFocus", onclick: "$onClickTab", "role": "tab", - view: "Cache", - $collapsed: "$file|hideCache"}, - $STR("Cache") - ), - A({"class": "netInfoHtmlTab netInfoTab a11yFocus", onclick: "$onClickTab", "role": "tab", - view: "Html", - $collapsed: "$file|hideHtml"}, - $STR("HTML") - ) - ), - - infoBodies: - DIV({"class": "netInfoBodies outerFocusRow"}, - TABLE({"class": "netInfoParamsText netInfoText netInfoParamsTable", "role": "tabpanel", - cellpadding: 0, cellspacing: 0}, TBODY()), - DIV({"class": "netInfoHeadersText netInfoText", "role": "tabpanel"}), - DIV({"class": "netInfoPostText netInfoText", "role": "tabpanel"}), - DIV({"class": "netInfoPutText netInfoText", "role": "tabpanel"}), - PRE({"class": "netInfoResponseText netInfoText", "role": "tabpanel"}), - DIV({"class": "netInfoCacheText netInfoText", "role": "tabpanel"}, - TABLE({"class": "netInfoCacheTable", cellpadding: 0, cellspacing: 0, "role": "presentation"}, - TBODY({"role": "list", "aria-label": $STR("Cache")}) - ) - ), - DIV({"class": "netInfoHtmlText netInfoText", "role": "tabpanel"}, - IFRAME({"class": "netInfoHtmlPreview", "role": "document"}) - ) - ), - - headerDataTag: - FOR("param", "$headers", - TR({"role": "listitem"}, - TD({"class": "netInfoParamName", "role": "presentation"}, - TAG("$param|getNameTag", {param: "$param"}) - ), - TD({"class": "netInfoParamValue", "role": "list", "aria-label": "$param.name"}, - FOR("line", "$param|getParamValueIterator", - CODE({"class": "focusRow subFocusRow", "role": "listitem"}, "$line") - ) - ) - ) - ), - - customTab: - A({"class": "netInfo$tabId\\Tab netInfoTab", onclick: "$onClickTab", view: "$tabId", "role": "tab"}, - "$tabTitle" - ), - - customBody: - DIV({"class": "netInfo$tabId\\Text netInfoText", "role": "tabpanel"}), - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - nameTag: - SPAN("$param|getParamName"), - - nameWithTooltipTag: - SPAN({title: "$param.name"}, "$param|getParamName"), - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - getNameTag: function(param) - { - return (this.getParamName(param) == param.name) ? this.nameTag : this.nameWithTooltipTag; - }, - - getParamName: function(param) - { - var limit = 25; - var name = param.name; - if (name.length > limit) - name = name.substr(0, limit) + "..."; - return name; - }, - - getParamTitle: function(param) - { - var limit = 25; - var name = param.name; - if (name.length > limit) - return name; - return ""; - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - hideParams: function(file) - { - return !file.urlParams || !file.urlParams.length; - }, - - hidePost: function(file) - { - return file.method.toUpperCase() != "POST"; - }, - - hidePut: function(file) - { - return file.method.toUpperCase() != "PUT"; - }, - - hideResponse: function(file) - { - return false; - //return file.category in binaryFileCategories; - }, - - hideCache: function(file) - { - return true; - //xxxHonza: I don't see any reason why not to display the cache also info for images. - return !file.cacheEntry; // || file.category=="image"; - }, - - hideHtml: function(file) - { - return (file.mimeType != "text/html") && (file.mimeType != "application/xhtml+xml"); - }, - - onClickTab: function(event) - { - this.selectTab(event.currentTarget || event.srcElement); - }, - - getParamValueIterator: function(param) - { - // TODO: xxxpedro console2 - return param.value; - - // This value is inserted into CODE element and so, make sure the HTML isn't escaped (1210). - // This is why the second parameter is true. - // The CODE (with style white-space:pre) element preserves whitespaces so they are - // displayed the same, as they come from the server (1194). - // In case of a long header values of post parameters the value must be wrapped (2105). - return wrapText(param.value, true); - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - appendTab: function(netInfoBox, tabId, tabTitle) - { - // Create new tab and body. - var args = {tabId: tabId, tabTitle: tabTitle}; - ///this.customTab.append(args, netInfoBox.getElementsByClassName("netInfoTabs").item(0)); - ///this.customBody.append(args, netInfoBox.getElementsByClassName("netInfoBodies").item(0)); - this.customTab.append(args, $$(".netInfoTabs", netInfoBox)[0]); - this.customBody.append(args, $$(".netInfoBodies", netInfoBox)[0]); - }, - - selectTabByName: function(netInfoBox, tabName) - { - var tab = getChildByClass(netInfoBox, "netInfoTabs", "netInfo"+tabName+"Tab"); - if (tab) - this.selectTab(tab); - }, - - selectTab: function(tab) - { - var view = tab.getAttribute("view"); - - var netInfoBox = getAncestorByClass(tab, "netInfoBody"); - - var selectedTab = netInfoBox.selectedTab; - - if (selectedTab) - { - //netInfoBox.selectedText.removeAttribute("selected"); - removeClass(netInfoBox.selectedText, "netInfoTextSelected"); - - removeClass(selectedTab, "netInfoTabSelected"); - //selectedTab.removeAttribute("selected"); - selectedTab.setAttribute("aria-selected", "false"); - } - - var textBodyName = "netInfo" + view + "Text"; - - selectedTab = netInfoBox.selectedTab = tab; - - netInfoBox.selectedText = $$("."+textBodyName, netInfoBox)[0]; - //netInfoBox.selectedText = netInfoBox.getElementsByClassName(textBodyName).item(0); - - //netInfoBox.selectedText.setAttribute("selected", "true"); - setClass(netInfoBox.selectedText, "netInfoTextSelected"); - - setClass(selectedTab, "netInfoTabSelected"); - selectedTab.setAttribute("selected", "true"); - selectedTab.setAttribute("aria-selected", "true"); - - var file = Firebug.getRepObject(netInfoBox); - - //var context = Firebug.getElementPanel(netInfoBox).context; - var context = Firebug.chrome; - - this.updateInfo(netInfoBox, file, context); - }, - - updateInfo: function(netInfoBox, file, context) - { - if (FBTrace.DBG_NET) - FBTrace.sysout("net.updateInfo; file", file); - - if (!netInfoBox) - { - if (FBTrace.DBG_NET || FBTrace.DBG_ERRORS) - FBTrace.sysout("net.updateInfo; ERROR netInfo == null " + file.href, file); - return; - } - - var tab = netInfoBox.selectedTab; - - if (hasClass(tab, "netInfoParamsTab")) - { - if (file.urlParams && !netInfoBox.urlParamsPresented) - { - netInfoBox.urlParamsPresented = true; - this.insertHeaderRows(netInfoBox, file.urlParams, "Params"); - } - } - - else if (hasClass(tab, "netInfoHeadersTab")) - { - var headersText = $$(".netInfoHeadersText", netInfoBox)[0]; - //var headersText = netInfoBox.getElementsByClassName("netInfoHeadersText").item(0); - - if (file.responseHeaders && !netInfoBox.responseHeadersPresented) - { - netInfoBox.responseHeadersPresented = true; - NetInfoHeaders.renderHeaders(headersText, file.responseHeaders, "ResponseHeaders"); - } - - if (file.requestHeaders && !netInfoBox.requestHeadersPresented) - { - netInfoBox.requestHeadersPresented = true; - NetInfoHeaders.renderHeaders(headersText, file.requestHeaders, "RequestHeaders"); - } - } - - else if (hasClass(tab, "netInfoPostTab")) - { - if (!netInfoBox.postPresented) - { - netInfoBox.postPresented = true; - //var postText = netInfoBox.getElementsByClassName("netInfoPostText").item(0); - var postText = $$(".netInfoPostText", netInfoBox)[0]; - NetInfoPostData.render(context, postText, file); - } - } - - else if (hasClass(tab, "netInfoPutTab")) - { - if (!netInfoBox.putPresented) - { - netInfoBox.putPresented = true; - //var putText = netInfoBox.getElementsByClassName("netInfoPutText").item(0); - var putText = $$(".netInfoPutText", netInfoBox)[0]; - NetInfoPostData.render(context, putText, file); - } - } - - else if (hasClass(tab, "netInfoResponseTab") && file.loaded && !netInfoBox.responsePresented) - { - ///var responseTextBox = netInfoBox.getElementsByClassName("netInfoResponseText").item(0); - var responseTextBox = $$(".netInfoResponseText", netInfoBox)[0]; - if (file.category == "image") - { - netInfoBox.responsePresented = true; - - var responseImage = netInfoBox.ownerDocument.createElement("img"); - responseImage.src = file.href; - - clearNode(responseTextBox); - responseTextBox.appendChild(responseImage, responseTextBox); - } - else ///if (!(binaryCategoryMap.hasOwnProperty(file.category))) - { - this.setResponseText(file, netInfoBox, responseTextBox, context); - } - } - - else if (hasClass(tab, "netInfoCacheTab") && file.loaded && !netInfoBox.cachePresented) - { - var responseTextBox = netInfoBox.getElementsByClassName("netInfoCacheText").item(0); - if (file.cacheEntry) { - netInfoBox.cachePresented = true; - this.insertHeaderRows(netInfoBox, file.cacheEntry, "Cache"); - } - } - - else if (hasClass(tab, "netInfoHtmlTab") && file.loaded && !netInfoBox.htmlPresented) - { - netInfoBox.htmlPresented = true; - - var text = Utils.getResponseText(file, context); - - ///var iframe = netInfoBox.getElementsByClassName("netInfoHtmlPreview").item(0); - var iframe = $$(".netInfoHtmlPreview", netInfoBox)[0]; - - ///iframe.contentWindow.document.body.innerHTML = text; - - // TODO: xxxpedro net - remove scripts - var reScript = /<script(.|\s)*?\/script>/gi; - - text = text.replace(reScript, ""); - - iframe.contentWindow.document.write(text); - iframe.contentWindow.document.close(); - } - - // Notify listeners about update so, content of custom tabs can be updated. - dispatch(NetInfoBody.fbListeners, "updateTabBody", [netInfoBox, file, context]); - }, - - setResponseText: function(file, netInfoBox, responseTextBox, context) - { - //********************************************** - //********************************************** - //********************************************** - netInfoBox.responsePresented = true; - // line breaks somehow are different in IE - // make this only once in the initialization? we don't have net panels and modules yet. - if (isIE) - responseTextBox.style.whiteSpace = "nowrap"; - - responseTextBox[ - typeof responseTextBox.textContent != "undefined" ? - "textContent" : - "innerText" - ] = file.responseText; - - return; - //********************************************** - //********************************************** - //********************************************** - - // Get response text and make sure it doesn't exceed the max limit. - var text = Utils.getResponseText(file, context); - var limit = Firebug.netDisplayedResponseLimit + 15; - var limitReached = text ? (text.length > limit) : false; - if (limitReached) - text = text.substr(0, limit) + "..."; - - // Insert the response into the UI. - if (text) - insertWrappedText(text, responseTextBox); - else - insertWrappedText("", responseTextBox); - - // Append a message informing the user that the response isn't fully displayed. - if (limitReached) - { - var object = { - text: $STR("net.responseSizeLimitMessage"), - onClickLink: function() { - var panel = context.getPanel("net", true); - panel.openResponseInTab(file); - } - }; - Firebug.NetMonitor.ResponseSizeLimit.append(object, responseTextBox); - } - - netInfoBox.responsePresented = true; - - if (FBTrace.DBG_NET) - FBTrace.sysout("net.setResponseText; response text updated"); - }, - - insertHeaderRows: function(netInfoBox, headers, tableName, rowName) - { - if (!headers.length) - return; - - var headersTable = $$(".netInfo"+tableName+"Table", netInfoBox)[0]; - //var headersTable = netInfoBox.getElementsByClassName("netInfo"+tableName+"Table").item(0); - var tbody = getChildByClass(headersTable, "netInfo" + rowName + "Body"); - if (!tbody) - tbody = headersTable.firstChild; - var titleRow = getChildByClass(tbody, "netInfo" + rowName + "Title"); - - this.headerDataTag.insertRows({headers: headers}, titleRow ? titleRow : tbody); - removeClass(titleRow, "collapsed"); - } -}); - -var NetInfoBody = Firebug.NetMonitor.NetInfoBody; - -// ************************************************************************************************ - -/** - * @domplate Used within the Net panel to display raw source of request and response headers - * as well as pretty-formatted summary of these headers. - */ -Firebug.NetMonitor.NetInfoHeaders = domplate(Firebug.Rep, //new Firebug.Listener(), -{ - tag: - DIV({"class": "netInfoHeadersTable", "role": "tabpanel"}, - DIV({"class": "netInfoHeadersGroup netInfoResponseHeadersTitle"}, - SPAN($STR("ResponseHeaders")), - SPAN({"class": "netHeadersViewSource response collapsed", onclick: "$onViewSource", - _sourceDisplayed: false, _rowName: "ResponseHeaders"}, - $STR("net.headers.view source") - ) - ), - TABLE({cellpadding: 0, cellspacing: 0}, - TBODY({"class": "netInfoResponseHeadersBody", "role": "list", - "aria-label": $STR("ResponseHeaders")}) - ), - DIV({"class": "netInfoHeadersGroup netInfoRequestHeadersTitle"}, - SPAN($STR("RequestHeaders")), - SPAN({"class": "netHeadersViewSource request collapsed", onclick: "$onViewSource", - _sourceDisplayed: false, _rowName: "RequestHeaders"}, - $STR("net.headers.view source") - ) - ), - TABLE({cellpadding: 0, cellspacing: 0}, - TBODY({"class": "netInfoRequestHeadersBody", "role": "list", - "aria-label": $STR("RequestHeaders")}) - ) - ), - - sourceTag: - TR({"role": "presentation"}, - TD({colspan: 2, "role": "presentation"}, - PRE({"class": "source"}) - ) - ), - - onViewSource: function(event) - { - var target = event.target; - var requestHeaders = (target.rowName == "RequestHeaders"); - - var netInfoBox = getAncestorByClass(target, "netInfoBody"); - var file = netInfoBox.repObject; - - if (target.sourceDisplayed) - { - var headers = requestHeaders ? file.requestHeaders : file.responseHeaders; - this.insertHeaderRows(netInfoBox, headers, target.rowName); - target.innerHTML = $STR("net.headers.view source"); - } - else - { - var source = requestHeaders ? file.requestHeadersText : file.responseHeadersText; - this.insertSource(netInfoBox, source, target.rowName); - target.innerHTML = $STR("net.headers.pretty print"); - } - - target.sourceDisplayed = !target.sourceDisplayed; - - cancelEvent(event); - }, - - insertSource: function(netInfoBox, source, rowName) - { - // This breaks copy to clipboard. - //if (source) - // source = source.replace(/\r\n/gm, "<span style='color:lightgray'>\\r\\n</span>\r\n"); - - ///var tbody = netInfoBox.getElementsByClassName("netInfo" + rowName + "Body").item(0); - var tbody = $$(".netInfo" + rowName + "Body", netInfoBox)[0]; - var node = this.sourceTag.replace({}, tbody); - ///var sourceNode = node.getElementsByClassName("source").item(0); - var sourceNode = $$(".source", node)[0]; - sourceNode.innerHTML = source; - }, - - insertHeaderRows: function(netInfoBox, headers, rowName) - { - var headersTable = $$(".netInfoHeadersTable", netInfoBox)[0]; - var tbody = $$(".netInfo" + rowName + "Body", headersTable)[0]; - - //var headersTable = netInfoBox.getElementsByClassName("netInfoHeadersTable").item(0); - //var tbody = headersTable.getElementsByClassName("netInfo" + rowName + "Body").item(0); - - clearNode(tbody); - - if (!headers.length) - return; - - NetInfoBody.headerDataTag.insertRows({headers: headers}, tbody); - - var titleRow = getChildByClass(headersTable, "netInfo" + rowName + "Title"); - removeClass(titleRow, "collapsed"); - }, - - init: function(parent) - { - var rootNode = this.tag.append({}, parent); - - var netInfoBox = getAncestorByClass(parent, "netInfoBody"); - var file = netInfoBox.repObject; - - var viewSource; - - viewSource = $$(".request", rootNode)[0]; - //viewSource = rootNode.getElementsByClassName("netHeadersViewSource request").item(0); - if (file.requestHeadersText) - removeClass(viewSource, "collapsed"); - - viewSource = $$(".response", rootNode)[0]; - //viewSource = rootNode.getElementsByClassName("netHeadersViewSource response").item(0); - if (file.responseHeadersText) - removeClass(viewSource, "collapsed"); - }, - - renderHeaders: function(parent, headers, rowName) - { - if (!parent.firstChild) - this.init(parent); - - this.insertHeaderRows(parent, headers, rowName); - } -}); - -var NetInfoHeaders = Firebug.NetMonitor.NetInfoHeaders; - -// ************************************************************************************************ - -/** - * @domplate Represents posted data within request info (the info, which is visible when - * a request entry is expanded. This template renders content of the Post tab. - */ -Firebug.NetMonitor.NetInfoPostData = domplate(Firebug.Rep, /*new Firebug.Listener(),*/ -{ - // application/x-www-form-urlencoded - paramsTable: - TABLE({"class": "netInfoPostParamsTable", cellpadding: 0, cellspacing: 0, "role": "presentation"}, - TBODY({"role": "list", "aria-label": $STR("net.label.Parameters")}, - TR({"class": "netInfoPostParamsTitle", "role": "presentation"}, - TD({colspan: 3, "role": "presentation"}, - DIV({"class": "netInfoPostParams"}, - $STR("net.label.Parameters"), - SPAN({"class": "netInfoPostContentType"}, - "application/x-www-form-urlencoded" - ) - ) - ) - ) - ) - ), - - // multipart/form-data - partsTable: - TABLE({"class": "netInfoPostPartsTable", cellpadding: 0, cellspacing: 0, "role": "presentation"}, - TBODY({"role": "list", "aria-label": $STR("net.label.Parts")}, - TR({"class": "netInfoPostPartsTitle", "role": "presentation"}, - TD({colspan: 2, "role":"presentation" }, - DIV({"class": "netInfoPostParams"}, - $STR("net.label.Parts"), - SPAN({"class": "netInfoPostContentType"}, - "multipart/form-data" - ) - ) - ) - ) - ) - ), - - // application/json - jsonTable: - TABLE({"class": "netInfoPostJSONTable", cellpadding: 0, cellspacing: 0, "role": "presentation"}, - ///TBODY({"role": "list", "aria-label": $STR("jsonviewer.tab.JSON")}, - TBODY({"role": "list", "aria-label": $STR("JSON")}, - TR({"class": "netInfoPostJSONTitle", "role": "presentation"}, - TD({"role": "presentation" }, - DIV({"class": "netInfoPostParams"}, - ///$STR("jsonviewer.tab.JSON") - $STR("JSON") - ) - ) - ), - TR( - TD({"class": "netInfoPostJSONBody"}) - ) - ) - ), - - // application/xml - xmlTable: - TABLE({"class": "netInfoPostXMLTable", cellpadding: 0, cellspacing: 0, "role": "presentation"}, - TBODY({"role": "list", "aria-label": $STR("xmlviewer.tab.XML")}, - TR({"class": "netInfoPostXMLTitle", "role": "presentation"}, - TD({"role": "presentation" }, - DIV({"class": "netInfoPostParams"}, - $STR("xmlviewer.tab.XML") - ) - ) - ), - TR( - TD({"class": "netInfoPostXMLBody"}) - ) - ) - ), - - sourceTable: - TABLE({"class": "netInfoPostSourceTable", cellpadding: 0, cellspacing: 0, "role": "presentation"}, - TBODY({"role": "list", "aria-label": $STR("net.label.Source")}, - TR({"class": "netInfoPostSourceTitle", "role": "presentation"}, - TD({colspan: 2, "role": "presentation"}, - DIV({"class": "netInfoPostSource"}, - $STR("net.label.Source") - ) - ) - ) - ) - ), - - sourceBodyTag: - TR({"role": "presentation"}, - TD({colspan: 2, "role": "presentation"}, - FOR("line", "$param|getParamValueIterator", - CODE({"class":"focusRow subFocusRow" , "role": "listitem"},"$line") - ) - ) - ), - - getParamValueIterator: function(param) - { - return NetInfoBody.getParamValueIterator(param); - }, - - render: function(context, parentNode, file) - { - //debugger; - var spy = getAncestorByClass(parentNode, "spyHead"); - var spyObject = spy.repObject; - var data = spyObject.data; - - ///var contentType = Utils.findHeader(file.requestHeaders, "content-type"); - var contentType = file.mimeType; - - ///var text = Utils.getPostText(file, context, true); - ///if (text == undefined) - /// return; - - ///if (Utils.isURLEncodedRequest(file, context)) - // fake Utils.isURLEncodedRequest identification - if (contentType && contentType == "application/x-www-form-urlencoded" || - data && data.indexOf("=") != -1) - { - ///var lines = text.split("\n"); - ///var params = parseURLEncodedText(lines[lines.length-1]); - var params = parseURLEncodedTextArray(data); - if (params) - this.insertParameters(parentNode, params); - } - - ///if (Utils.isMultiPartRequest(file, context)) - ///{ - /// var data = this.parseMultiPartText(file, context); - /// if (data) - /// this.insertParts(parentNode, data); - ///} - - // moved to the top - ///var contentType = Utils.findHeader(file.requestHeaders, "content-type"); - - ///if (Firebug.JSONViewerModel.isJSON(contentType)) - var jsonData = { - responseText: data - }; - - if (Firebug.JSONViewerModel.isJSON(contentType, data)) - ///this.insertJSON(parentNode, file, context); - this.insertJSON(parentNode, jsonData, context); - - ///if (Firebug.XMLViewerModel.isXML(contentType)) - /// this.insertXML(parentNode, file, context); - - ///var postText = Utils.getPostText(file, context); - ///postText = Utils.formatPostText(postText); - var postText = data; - if (postText) - this.insertSource(parentNode, postText); - }, - - insertParameters: function(parentNode, params) - { - if (!params || !params.length) - return; - - var paramTable = this.paramsTable.append({object:{}}, parentNode); - var row = $$(".netInfoPostParamsTitle", paramTable)[0]; - //var paramTable = this.paramsTable.append(null, parentNode); - //var row = paramTable.getElementsByClassName("netInfoPostParamsTitle").item(0); - - var tbody = paramTable.getElementsByTagName("tbody")[0]; - - NetInfoBody.headerDataTag.insertRows({headers: params}, row); - }, - - insertParts: function(parentNode, data) - { - if (!data.params || !data.params.length) - return; - - var partsTable = this.partsTable.append({object:{}}, parentNode); - var row = $$(".netInfoPostPartsTitle", paramTable)[0]; - //var partsTable = this.partsTable.append(null, parentNode); - //var row = partsTable.getElementsByClassName("netInfoPostPartsTitle").item(0); - - NetInfoBody.headerDataTag.insertRows({headers: data.params}, row); - }, - - insertJSON: function(parentNode, file, context) - { - ///var text = Utils.getPostText(file, context); - var text = file.responseText; - ///var data = parseJSONString(text, "http://" + file.request.originalURI.host); - var data = parseJSONString(text); - if (!data) - return; - - ///var jsonTable = this.jsonTable.append(null, parentNode); - var jsonTable = this.jsonTable.append({}, parentNode); - ///var jsonBody = jsonTable.getElementsByClassName("netInfoPostJSONBody").item(0); - var jsonBody = $$(".netInfoPostJSONBody", jsonTable)[0]; - - if (!this.toggles) - this.toggles = {}; - - Firebug.DOMPanel.DirTable.tag.replace( - {object: data, toggles: this.toggles}, jsonBody); - }, - - insertXML: function(parentNode, file, context) - { - var text = Utils.getPostText(file, context); - - var jsonTable = this.xmlTable.append(null, parentNode); - ///var jsonBody = jsonTable.getElementsByClassName("netInfoPostXMLBody").item(0); - var jsonBody = $$(".netInfoPostXMLBody", jsonTable)[0]; - - Firebug.XMLViewerModel.insertXML(jsonBody, text); - }, - - insertSource: function(parentNode, text) - { - var sourceTable = this.sourceTable.append({object:{}}, parentNode); - var row = $$(".netInfoPostSourceTitle", sourceTable)[0]; - //var sourceTable = this.sourceTable.append(null, parentNode); - //var row = sourceTable.getElementsByClassName("netInfoPostSourceTitle").item(0); - - var param = {value: [text]}; - this.sourceBodyTag.insertRows({param: param}, row); - }, - - parseMultiPartText: function(file, context) - { - var text = Utils.getPostText(file, context); - if (text == undefined) - return null; - - FBTrace.sysout("net.parseMultiPartText; boundary: ", text); - - var boundary = text.match(/\s*boundary=\s*(.*)/)[1]; - - var divider = "\r\n\r\n"; - var bodyStart = text.indexOf(divider); - var body = text.substr(bodyStart + divider.length); - - var postData = {}; - postData.mimeType = "multipart/form-data"; - postData.params = []; - - var parts = body.split("--" + boundary); - for (var i=0; i<parts.length; i++) - { - var part = parts[i].split(divider); - if (part.length != 2) - continue; - - var m = part[0].match(/\s*name=\"(.*)\"(;|$)/); - postData.params.push({ - name: (m && m.length > 1) ? m[1] : "", - value: trim(part[1]) - }); - } - - return postData; - } -}); - -var NetInfoPostData = Firebug.NetMonitor.NetInfoPostData; - -// ************************************************************************************************ - - -// TODO: xxxpedro net i18n -var $STRP = function(a){return a;}; - -Firebug.NetMonitor.NetLimit = domplate(Firebug.Rep, -{ - collapsed: true, - - tableTag: - DIV( - TABLE({width: "100%", cellpadding: 0, cellspacing: 0}, - TBODY() - ) - ), - - limitTag: - TR({"class": "netRow netLimitRow", $collapsed: "$isCollapsed"}, - TD({"class": "netCol netLimitCol", colspan: 6}, - TABLE({cellpadding: 0, cellspacing: 0}, - TBODY( - TR( - TD( - SPAN({"class": "netLimitLabel"}, - $STRP("plural.Limit_Exceeded", [0]) - ) - ), - TD({style: "width:100%"}), - TD( - BUTTON({"class": "netLimitButton", title: "$limitPrefsTitle", - onclick: "$onPreferences"}, - $STR("LimitPrefs") - ) - ), - TD(" ") - ) - ) - ) - ) - ), - - isCollapsed: function() - { - return this.collapsed; - }, - - onPreferences: function(event) - { - openNewTab("about:config"); - }, - - updateCounter: function(row) - { - removeClass(row, "collapsed"); - - // Update info within the limit row. - var limitLabel = row.getElementsByClassName("netLimitLabel").item(0); - limitLabel.firstChild.nodeValue = $STRP("plural.Limit_Exceeded", [row.limitInfo.totalCount]); - }, - - createTable: function(parent, limitInfo) - { - var table = this.tableTag.replace({}, parent); - var row = this.createRow(table.firstChild.firstChild, limitInfo); - return [table, row]; - }, - - createRow: function(parent, limitInfo) - { - var row = this.limitTag.insertRows(limitInfo, parent, this)[0]; - row.limitInfo = limitInfo; - return row; - }, - - // nsIPrefObserver - observe: function(subject, topic, data) - { - // We're observing preferences only. - if (topic != "nsPref:changed") - return; - - if (data.indexOf("net.logLimit") != -1) - this.updateMaxLimit(); - }, - - updateMaxLimit: function() - { - var value = Firebug.getPref(Firebug.prefDomain, "net.logLimit"); - maxQueueRequests = value ? value : maxQueueRequests; - } -}); - -var NetLimit = Firebug.NetMonitor.NetLimit; - -// ************************************************************************************************ - -Firebug.NetMonitor.ResponseSizeLimit = domplate(Firebug.Rep, -{ - tag: - DIV({"class": "netInfoResponseSizeLimit"}, - SPAN("$object.beforeLink"), - A({"class": "objectLink", onclick: "$onClickLink"}, - "$object.linkText" - ), - SPAN("$object.afterLink") - ), - - reLink: /^(.*)<a>(.*)<\/a>(.*$)/, - append: function(obj, parent) - { - var m = obj.text.match(this.reLink); - return this.tag.append({onClickLink: obj.onClickLink, - object: { - beforeLink: m[1], - linkText: m[2], - afterLink: m[3] - }}, parent, this); - } -}); - -// ************************************************************************************************ -// ************************************************************************************************ - -Firebug.NetMonitor.Utils = -{ - findHeader: function(headers, name) - { - if (!headers) - return null; - - name = name.toLowerCase(); - for (var i = 0; i < headers.length; ++i) - { - var headerName = headers[i].name.toLowerCase(); - if (headerName == name) - return headers[i].value; - } - }, - - formatPostText: function(text) - { - if (text instanceof XMLDocument) - return getElementXML(text.documentElement); - else - return text; - }, - - getPostText: function(file, context, noLimit) - { - if (!file.postText) - { - file.postText = readPostTextFromRequest(file.request, context); - - if (!file.postText && context) - file.postText = readPostTextFromPage(file.href, context); - } - - if (!file.postText) - return file.postText; - - var limit = Firebug.netDisplayedPostBodyLimit; - if (file.postText.length > limit && !noLimit) - { - return cropString(file.postText, limit, - "\n\n... " + $STR("net.postDataSizeLimitMessage") + " ...\n\n"); - } - - return file.postText; - }, - - getResponseText: function(file, context) - { - // The response can be also empty string so, check agains "undefined". - return (typeof(file.responseText) != "undefined")? file.responseText : - context.sourceCache.loadText(file.href, file.method, file); - }, - - isURLEncodedRequest: function(file, context) - { - var text = Utils.getPostText(file, context); - if (text && text.toLowerCase().indexOf("content-type: application/x-www-form-urlencoded") == 0) - return true; - - // The header value doesn't have to be always exactly "application/x-www-form-urlencoded", - // there can be even charset specified. So, use indexOf rather than just "==". - var headerValue = Utils.findHeader(file.requestHeaders, "content-type"); - if (headerValue && headerValue.indexOf("application/x-www-form-urlencoded") == 0) - return true; - - return false; - }, - - isMultiPartRequest: function(file, context) - { - var text = Utils.getPostText(file, context); - if (text && text.toLowerCase().indexOf("content-type: multipart/form-data") == 0) - return true; - return false; - }, - - getMimeType: function(mimeType, uri) - { - if (!mimeType || !(mimeCategoryMap.hasOwnProperty(mimeType))) - { - var ext = getFileExtension(uri); - if (!ext) - return mimeType; - else - { - var extMimeType = mimeExtensionMap[ext.toLowerCase()]; - return extMimeType ? extMimeType : mimeType; - } - } - else - return mimeType; - }, - - getDateFromSeconds: function(s) - { - var d = new Date(); - d.setTime(s*1000); - return d; - }, - - getHttpHeaders: function(request, file) - { - try - { - var http = QI(request, Ci.nsIHttpChannel); - file.status = request.responseStatus; - - // xxxHonza: is there any problem to do this in requestedFile method? - file.method = http.requestMethod; - file.urlParams = parseURLParams(file.href); - file.mimeType = Utils.getMimeType(request.contentType, request.name); - - if (!file.responseHeaders && Firebug.collectHttpHeaders) - { - var requestHeaders = [], responseHeaders = []; - - http.visitRequestHeaders({ - visitHeader: function(name, value) - { - requestHeaders.push({name: name, value: value}); - } - }); - http.visitResponseHeaders({ - visitHeader: function(name, value) - { - responseHeaders.push({name: name, value: value}); - } - }); - - file.requestHeaders = requestHeaders; - file.responseHeaders = responseHeaders; - } - } - catch (exc) - { - // An exception can be throwed e.g. when the request is aborted and - // request.responseStatus is accessed. - if (FBTrace.DBG_ERRORS) - FBTrace.sysout("net.getHttpHeaders FAILS " + file.href, exc); - } - }, - - isXHR: function(request) - { - try - { - var callbacks = request.notificationCallbacks; - var xhrRequest = callbacks ? callbacks.getInterface(Ci.nsIXMLHttpRequest) : null; - if (FBTrace.DBG_NET) - FBTrace.sysout("net.isXHR; " + (xhrRequest != null) + ", " + safeGetName(request)); - - return (xhrRequest != null); - } - catch (exc) - { - } - - return false; - }, - - getFileCategory: function(file) - { - if (file.category) - { - if (FBTrace.DBG_NET) - FBTrace.sysout("net.getFileCategory; current: " + file.category + " for: " + file.href, file); - return file.category; - } - - if (file.isXHR) - { - if (FBTrace.DBG_NET) - FBTrace.sysout("net.getFileCategory; XHR for: " + file.href, file); - return file.category = "xhr"; - } - - if (!file.mimeType) - { - var ext = getFileExtension(file.href); - if (ext) - file.mimeType = mimeExtensionMap[ext.toLowerCase()]; - } - - /*if (FBTrace.DBG_NET) - FBTrace.sysout("net.getFileCategory; " + mimeCategoryMap[file.mimeType] + - ", mimeType: " + file.mimeType + " for: " + file.href, file);*/ - - if (!file.mimeType) - return ""; - - // Solve cases when charset is also specified, eg "text/html; charset=UTF-8". - var mimeType = file.mimeType; - if (mimeType) - mimeType = mimeType.split(";")[0]; - - return (file.category = mimeCategoryMap[mimeType]); - } -}; - -var Utils = Firebug.NetMonitor.Utils; - -// ************************************************************************************************ - -//Firebug.registerRep(Firebug.NetMonitor.NetRequestTable); -//Firebug.registerActivableModule(Firebug.NetMonitor); -//Firebug.registerPanel(NetPanel); - -Firebug.registerModule(Firebug.NetMonitor); -//Firebug.registerRep(Firebug.NetMonitor.BreakpointRep); - -// ************************************************************************************************ -}}); - - -/* See license.txt for terms of usage */ - -FBL.ns(function() { with (FBL) { - -// ************************************************************************************************ -// Constants - -//const Cc = Components.classes; -//const Ci = Components.interfaces; - -// List of contexts with XHR spy attached. -var contexts = []; - -// ************************************************************************************************ -// Spy Module - -/** - * @module Represents a XHR Spy module. The main purpose of the XHR Spy feature is to monitor - * XHR activity of the current page and create appropriate log into the Console panel. - * This feature can be controlled by an option <i>Show XMLHttpRequests</i> (from within the - * console panel). - * - * The module is responsible for attaching/detaching a HTTP Observers when Firebug is - * activated/deactivated for a site. - */ -Firebug.Spy = extend(Firebug.Module, -/** @lends Firebug.Spy */ -{ - dispatchName: "spy", - - initialize: function() - { - if (Firebug.TraceModule) - Firebug.TraceModule.addListener(this.TraceListener); - - Firebug.Module.initialize.apply(this, arguments); - }, - - shutdown: function() - { - Firebug.Module.shutdown.apply(this, arguments); - - if (Firebug.TraceModule) - Firebug.TraceModule.removeListener(this.TraceListener); - }, - - initContext: function(context) - { - context.spies = []; - - if (Firebug.showXMLHttpRequests && Firebug.Console.isAlwaysEnabled()) - this.attachObserver(context, context.window); - - if (FBTrace.DBG_SPY) - FBTrace.sysout("spy.initContext " + contexts.length + " ", context.getName()); - }, - - destroyContext: function(context) - { - // For any spies that are in progress, remove our listeners so that they don't leak - this.detachObserver(context, null); - - if (FBTrace.DBG_SPY && context.spies.length) - FBTrace.sysout("spy.destroyContext; ERROR There are leaking Spies (" - + context.spies.length + ") " + context.getName()); - - delete context.spies; - - if (FBTrace.DBG_SPY) - FBTrace.sysout("spy.destroyContext " + contexts.length + " ", context.getName()); - }, - - watchWindow: function(context, win) - { - if (Firebug.showXMLHttpRequests && Firebug.Console.isAlwaysEnabled()) - this.attachObserver(context, win); - }, - - unwatchWindow: function(context, win) - { - try - { - // This make sure that the existing context is properly removed from "contexts" array. - this.detachObserver(context, win); - } - catch (ex) - { - // Get exceptions here sometimes, so let's just ignore them - // since the window is going away anyhow - ERROR(ex); - } - }, - - updateOption: function(name, value) - { - // XXXjjb Honza, if Console.isEnabled(context) false, then this can't be called, - // but somehow seems not correct - if (name == "showXMLHttpRequests") - { - var tach = value ? this.attachObserver : this.detachObserver; - for (var i = 0; i < TabWatcher.contexts.length; ++i) - { - var context = TabWatcher.contexts[i]; - iterateWindows(context.window, function(win) - { - tach.apply(this, [context, win]); - }); - } - } - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // Attaching Spy to XHR requests. - - /** - * Returns false if Spy should not be attached to XHRs executed by the specified window. - */ - skipSpy: function(win) - { - if (!win) - return true; - - // Don't attach spy to chrome. - var uri = safeGetWindowLocation(win); - if (uri && (uri.indexOf("about:") == 0 || uri.indexOf("chrome:") == 0)) - return true; - }, - - attachObserver: function(context, win) - { - if (Firebug.Spy.skipSpy(win)) - return; - - for (var i=0; i<contexts.length; ++i) - { - if ((contexts[i].context == context) && (contexts[i].win == win)) - return; - } - - // Register HTTP observers only once. - if (contexts.length == 0) - { - httpObserver.addObserver(SpyHttpObserver, "firebug-http-event", false); - SpyHttpActivityObserver.registerObserver(); - } - - contexts.push({context: context, win: win}); - - if (FBTrace.DBG_SPY) - FBTrace.sysout("spy.attachObserver (HTTP) " + contexts.length + " ", context.getName()); - }, - - detachObserver: function(context, win) - { - for (var i=0; i<contexts.length; ++i) - { - if (contexts[i].context == context) - { - if (win && (contexts[i].win != win)) - continue; - - contexts.splice(i, 1); - - // If no context is using spy, remvove the (only one) HTTP observer. - if (contexts.length == 0) - { - httpObserver.removeObserver(SpyHttpObserver, "firebug-http-event"); - SpyHttpActivityObserver.unregisterObserver(); - } - - if (FBTrace.DBG_SPY) - FBTrace.sysout("spy.detachObserver (HTTP) " + contexts.length + " ", - context.getName()); - return; - } - } - }, - - /** - * Return XHR object that is associated with specified request <i>nsIHttpChannel</i>. - * Returns null if the request doesn't represent XHR. - */ - getXHR: function(request) - { - // Does also query-interface for nsIHttpChannel. - if (!(request instanceof Ci.nsIHttpChannel)) - return null; - - try - { - var callbacks = request.notificationCallbacks; - return (callbacks ? callbacks.getInterface(Ci.nsIXMLHttpRequest) : null); - } - catch (exc) - { - if (exc.name == "NS_NOINTERFACE") - { - if (FBTrace.DBG_SPY) - FBTrace.sysout("spy.getXHR; Request is not nsIXMLHttpRequest: " + - safeGetRequestName(request)); - } - } - - return null; - } -}); - - - - - -// ************************************************************************************************ - -/* -function getSpyForXHR(request, xhrRequest, context, noCreate) -{ - var spy = null; - - // Iterate all existing spy objects in this context and look for one that is - // already created for this request. - var length = context.spies.length; - for (var i=0; i<length; i++) - { - spy = context.spies[i]; - if (spy.request == request) - return spy; - } - - if (noCreate) - return null; - - spy = new Firebug.Spy.XMLHttpRequestSpy(request, xhrRequest, context); - context.spies.push(spy); - - var name = request.URI.asciiSpec; - var origName = request.originalURI.asciiSpec; - - // Attach spy only to the original request. Notice that there can be more network requests - // made by the same XHR if redirects are involved. - if (name == origName) - spy.attach(); - - if (FBTrace.DBG_SPY) - FBTrace.sysout("spy.getSpyForXHR; New spy object created (" + - (name == origName ? "new XHR" : "redirected XHR") + ") for: " + name, spy); - - return spy; -} -/**/ - -// ************************************************************************************************ - -/** - * @class This class represents a Spy object that is attached to XHR. This object - * registers various listeners into the XHR in order to monitor various events fired - * during the request process (onLoad, onAbort, etc.) - */ -/* -Firebug.Spy.XMLHttpRequestSpy = function(request, xhrRequest, context) -{ - this.request = request; - this.xhrRequest = xhrRequest; - this.context = context; - this.responseText = ""; - - // For compatibility with the Net templates. - this.isXHR = true; - - // Support for activity-observer - this.transactionStarted = false; - this.transactionClosed = false; -}; -/**/ - -//Firebug.Spy.XMLHttpRequestSpy.prototype = -/** @lends Firebug.Spy.XMLHttpRequestSpy */ -/* -{ - attach: function() - { - var spy = this; - this.onReadyStateChange = function(event) { onHTTPSpyReadyStateChange(spy, event); }; - this.onLoad = function() { onHTTPSpyLoad(spy); }; - this.onError = function() { onHTTPSpyError(spy); }; - this.onAbort = function() { onHTTPSpyAbort(spy); }; - - // xxxHonza: #502959 is still failing on Fx 3.5 - // Use activity distributor to identify 3.6 - if (SpyHttpActivityObserver.getActivityDistributor()) - { - this.onreadystatechange = this.xhrRequest.onreadystatechange; - this.xhrRequest.onreadystatechange = this.onReadyStateChange; - } - - this.xhrRequest.addEventListener("load", this.onLoad, false); - this.xhrRequest.addEventListener("error", this.onError, false); - this.xhrRequest.addEventListener("abort", this.onAbort, false); - - // xxxHonza: should be removed from FB 3.6 - if (!SpyHttpActivityObserver.getActivityDistributor()) - this.context.sourceCache.addListener(this); - }, - - detach: function() - { - // Bubble out if already detached. - if (!this.onLoad) - return; - - // If the activity distributor is available, let's detach it when the XHR - // transaction is closed. Since, in case of multipart XHRs the onLoad method - // (readyState == 4) can be called mutliple times. - // Keep in mind: - // 1) It can happen that that the TRANSACTION_CLOSE event comes before - // the onLoad (if the XHR is made as part of the page load) so, detach if - // it's already closed. - // 2) In case of immediate cache responses, the transaction doesn't have to - // be started at all (or the activity observer is no available in Firefox 3.5). - // So, also detach in this case. - if (this.transactionStarted && !this.transactionClosed) - return; - - if (FBTrace.DBG_SPY) - FBTrace.sysout("spy.detach; " + this.href); - - // Remove itself from the list of active spies. - remove(this.context.spies, this); - - if (this.onreadystatechange) - this.xhrRequest.onreadystatechange = this.onreadystatechange; - - try { this.xhrRequest.removeEventListener("load", this.onLoad, false); } catch (e) {} - try { this.xhrRequest.removeEventListener("error", this.onError, false); } catch (e) {} - try { this.xhrRequest.removeEventListener("abort", this.onAbort, false); } catch (e) {} - - this.onreadystatechange = null; - this.onLoad = null; - this.onError = null; - this.onAbort = null; - - // xxxHonza: shouuld be removed from FB 1.6 - if (!SpyHttpActivityObserver.getActivityDistributor()) - this.context.sourceCache.removeListener(this); - }, - - getURL: function() - { - return this.xhrRequest.channel ? this.xhrRequest.channel.name : this.href; - }, - - // Cache listener - onStopRequest: function(context, request, responseText) - { - if (!responseText) - return; - - if (request == this.request) - this.responseText = responseText; - }, -}; -/**/ -// ************************************************************************************************ -/* -function onHTTPSpyReadyStateChange(spy, event) -{ - if (FBTrace.DBG_SPY) - FBTrace.sysout("spy.onHTTPSpyReadyStateChange " + spy.xhrRequest.readyState + - " (multipart: " + spy.xhrRequest.multipart + ")"); - - // Remember just in case spy is detached (readyState == 4). - var originalHandler = spy.onreadystatechange; - - // Force response text to be updated in the UI (in case the console entry - // has been already expanded and the response tab selected). - if (spy.logRow && spy.xhrRequest.readyState >= 3) - { - var netInfoBox = getChildByClass(spy.logRow, "spyHead", "netInfoBody"); - if (netInfoBox) - { - netInfoBox.htmlPresented = false; - netInfoBox.responsePresented = false; - } - } - - // If the request is loading update the end time. - if (spy.xhrRequest.readyState == 3) - { - spy.responseTime = spy.endTime - spy.sendTime; - updateTime(spy); - } - - // Request loaded. Get all the info from the request now, just in case the - // XHR would be aborted in the original onReadyStateChange handler. - if (spy.xhrRequest.readyState == 4) - { - // Cumulate response so, multipart response content is properly displayed. - if (SpyHttpActivityObserver.getActivityDistributor()) - spy.responseText += spy.xhrRequest.responseText; - else - { - // xxxHonza: remove from FB 1.6 - if (!spy.responseText) - spy.responseText = spy.xhrRequest.responseText; - } - - // The XHR is loaded now (used also by the activity observer). - spy.loaded = true; - - // Update UI. - updateHttpSpyInfo(spy); - - // Notify Net pane about a request beeing loaded. - // xxxHonza: I don't think this is necessary. - var netProgress = spy.context.netProgress; - if (netProgress) - netProgress.post(netProgress.stopFile, [spy.request, spy.endTime, spy.postText, spy.responseText]); - - // Notify registered listeners about finish of the XHR. - dispatch(Firebug.Spy.fbListeners, "onLoad", [spy.context, spy]); - } - - // Pass the event to the original page handler. - callPageHandler(spy, event, originalHandler); -} - -function onHTTPSpyLoad(spy) -{ - if (FBTrace.DBG_SPY) - FBTrace.sysout("spy.onHTTPSpyLoad: " + spy.href, spy); - - // Detach must be done in onLoad (not in onreadystatechange) otherwise - // onAbort would not be handled. - spy.detach(); - - // xxxHonza: Still needed for Fx 3.5 (#502959) - if (!SpyHttpActivityObserver.getActivityDistributor()) - onHTTPSpyReadyStateChange(spy, null); -} - -function onHTTPSpyError(spy) -{ - if (FBTrace.DBG_SPY) - FBTrace.sysout("spy.onHTTPSpyError; " + spy.href, spy); - - spy.detach(); - spy.loaded = true; - - if (spy.logRow) - { - removeClass(spy.logRow, "loading"); - setClass(spy.logRow, "error"); - } -} - -function onHTTPSpyAbort(spy) -{ - if (FBTrace.DBG_SPY) - FBTrace.sysout("spy.onHTTPSpyAbort: " + spy.href, spy); - - spy.detach(); - spy.loaded = true; - - if (spy.logRow) - { - removeClass(spy.logRow, "loading"); - setClass(spy.logRow, "error"); - } - - spy.statusText = "Aborted"; - updateLogRow(spy); - - // Notify Net pane about a request beeing aborted. - // xxxHonza: the net panel shoud find out this itself. - var netProgress = spy.context.netProgress; - if (netProgress) - netProgress.post(netProgress.abortFile, [spy.request, spy.endTime, spy.postText, spy.responseText]); -} -/**/ - -// ************************************************************************************************ - -/** - * @domplate Represents a template for XHRs logged in the Console panel. The body of the - * log (displayed when expanded) is rendered using {@link Firebug.NetMonitor.NetInfoBody}. - */ - -Firebug.Spy.XHR = domplate(Firebug.Rep, -/** @lends Firebug.Spy.XHR */ - -{ - tag: - DIV({"class": "spyHead", _repObject: "$object"}, - TABLE({"class": "spyHeadTable focusRow outerFocusRow", cellpadding: 0, cellspacing: 0, - "role": "listitem", "aria-expanded": "false"}, - TBODY({"role": "presentation"}, - TR({"class": "spyRow"}, - TD({"class": "spyTitleCol spyCol", onclick: "$onToggleBody"}, - DIV({"class": "spyTitle"}, - "$object|getCaption" - ), - DIV({"class": "spyFullTitle spyTitle"}, - "$object|getFullUri" - ) - ), - TD({"class": "spyCol"}, - DIV({"class": "spyStatus"}, "$object|getStatus") - ), - TD({"class": "spyCol"}, - SPAN({"class": "spyIcon"}) - ), - TD({"class": "spyCol"}, - SPAN({"class": "spyTime"}) - ), - TD({"class": "spyCol"}, - TAG(FirebugReps.SourceLink.tag, {object: "$object.sourceLink"}) - ) - ) - ) - ) - ), - - getCaption: function(spy) - { - return spy.method.toUpperCase() + " " + cropString(spy.getURL(), 100); - }, - - getFullUri: function(spy) - { - return spy.method.toUpperCase() + " " + spy.getURL(); - }, - - getStatus: function(spy) - { - var text = ""; - if (spy.statusCode) - text += spy.statusCode + " "; - - if (spy.statusText) - return text += spy.statusText; - - return text; - }, - - onToggleBody: function(event) - { - var target = event.currentTarget || event.srcElement; - var logRow = getAncestorByClass(target, "logRow-spy"); - - if (isLeftClick(event)) - { - toggleClass(logRow, "opened"); - - var spy = getChildByClass(logRow, "spyHead").repObject; - var spyHeadTable = getAncestorByClass(target, "spyHeadTable"); - - if (hasClass(logRow, "opened")) - { - updateHttpSpyInfo(spy, logRow); - if (spyHeadTable) - spyHeadTable.setAttribute('aria-expanded', 'true'); - } - else - { - //var netInfoBox = getChildByClass(spy.logRow, "spyHead", "netInfoBody"); - //dispatch(Firebug.NetMonitor.NetInfoBody.fbListeners, "destroyTabBody", [netInfoBox, spy]); - //if (spyHeadTable) - // spyHeadTable.setAttribute('aria-expanded', 'false'); - } - } - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - copyURL: function(spy) - { - copyToClipboard(spy.getURL()); - }, - - copyParams: function(spy) - { - var text = spy.postText; - if (!text) - return; - - var url = reEncodeURL(spy, text, true); - copyToClipboard(url); - }, - - copyResponse: function(spy) - { - copyToClipboard(spy.responseText); - }, - - openInTab: function(spy) - { - openNewTab(spy.getURL(), spy.postText); - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - supportsObject: function(object) - { - // TODO: xxxpedro spy xhr - return false; - - return object instanceof Firebug.Spy.XMLHttpRequestSpy; - }, - - browseObject: function(spy, context) - { - var url = spy.getURL(); - openNewTab(url); - return true; - }, - - getRealObject: function(spy, context) - { - return spy.xhrRequest; - }, - - getContextMenuItems: function(spy) - { - var items = [ - {label: "CopyLocation", command: bindFixed(this.copyURL, this, spy) } - ]; - - if (spy.postText) - { - items.push( - {label: "CopyLocationParameters", command: bindFixed(this.copyParams, this, spy) } - ); - } - - items.push( - {label: "CopyResponse", command: bindFixed(this.copyResponse, this, spy) }, - "-", - {label: "OpenInTab", command: bindFixed(this.openInTab, this, spy) } - ); - - return items; - } -}); - -// ************************************************************************************************ - -function updateTime(spy) -{ - var timeBox = spy.logRow.getElementsByClassName("spyTime").item(0); - if (spy.responseTime) - timeBox.textContent = " " + formatTime(spy.responseTime); -} - -function updateLogRow(spy) -{ - updateTime(spy); - - var statusBox = spy.logRow.getElementsByClassName("spyStatus").item(0); - statusBox.textContent = Firebug.Spy.XHR.getStatus(spy); - - removeClass(spy.logRow, "loading"); - setClass(spy.logRow, "loaded"); - - try - { - var errorRange = Math.floor(spy.xhrRequest.status/100); - if (errorRange == 4 || errorRange == 5) - setClass(spy.logRow, "error"); - } - catch (exc) - { - } -} - -var updateHttpSpyInfo = function updateHttpSpyInfo(spy, logRow) -{ - if (!spy.logRow && logRow) - spy.logRow = logRow; - - if (!spy.logRow || !hasClass(spy.logRow, "opened")) - return; - - if (!spy.params) - //spy.params = parseURLParams(spy.href+""); - spy.params = parseURLParams(spy.href+""); - - if (!spy.requestHeaders) - spy.requestHeaders = getRequestHeaders(spy); - - if (!spy.responseHeaders && spy.loaded) - spy.responseHeaders = getResponseHeaders(spy); - - var template = Firebug.NetMonitor.NetInfoBody; - var netInfoBox = getChildByClass(spy.logRow, "spyHead", "netInfoBody"); - if (!netInfoBox) - { - var head = getChildByClass(spy.logRow, "spyHead"); - netInfoBox = template.tag.append({"file": spy}, head); - dispatch(template.fbListeners, "initTabBody", [netInfoBox, spy]); - template.selectTabByName(netInfoBox, "Response"); - } - else - { - template.updateInfo(netInfoBox, spy, spy.context); - } -}; - - - -// ************************************************************************************************ - -function getRequestHeaders(spy) -{ - var headers = []; - - var channel = spy.xhrRequest.channel; - if (channel instanceof Ci.nsIHttpChannel) - { - channel.visitRequestHeaders({ - visitHeader: function(name, value) - { - headers.push({name: name, value: value}); - } - }); - } - - return headers; -} - -function getResponseHeaders(spy) -{ - var headers = []; - - try - { - var channel = spy.xhrRequest.channel; - if (channel instanceof Ci.nsIHttpChannel) - { - channel.visitResponseHeaders({ - visitHeader: function(name, value) - { - headers.push({name: name, value: value}); - } - }); - } - } - catch (exc) - { - if (FBTrace.DBG_SPY || FBTrace.DBG_ERRORS) - FBTrace.sysout("spy.getResponseHeaders; EXCEPTION " + - safeGetRequestName(spy.request), exc); - } - - return headers; -} - -// ************************************************************************************************ -// Registration - -Firebug.registerModule(Firebug.Spy); -//Firebug.registerRep(Firebug.Spy.XHR); - -// ************************************************************************************************ -}}); - - -/* See license.txt for terms of usage */ - -FBL.ns(function() { with (FBL) { - -// ************************************************************************************************ - -// List of JSON content types. -var contentTypes = -{ - // TODO: create issue: jsonViewer will not try to evaluate the contents of the requested file - // if the content-type is set to "text/plain" - //"text/plain": 1, - "text/javascript": 1, - "text/x-javascript": 1, - "text/json": 1, - "text/x-json": 1, - "application/json": 1, - "application/x-json": 1, - "application/javascript": 1, - "application/x-javascript": 1, - "application/json-rpc": 1 -}; - -// ************************************************************************************************ -// Model implementation - -Firebug.JSONViewerModel = extend(Firebug.Module, -{ - dispatchName: "jsonViewer", - initialize: function() - { - Firebug.NetMonitor.NetInfoBody.addListener(this); - - // Used by Firebug.DOMPanel.DirTable domplate. - this.toggles = {}; - }, - - shutdown: function() - { - Firebug.NetMonitor.NetInfoBody.removeListener(this); - }, - - initTabBody: function(infoBox, file) - { - if (FBTrace.DBG_JSONVIEWER) - FBTrace.sysout("jsonviewer.initTabBody", infoBox); - - // Let listeners to parse the JSON. - dispatch(this.fbListeners, "onParseJSON", [file]); - - // The JSON is still no there, try to parse most common cases. - if (!file.jsonObject) - { - ///if (this.isJSON(safeGetContentType(file.request), file.responseText)) - if (this.isJSON(file.mimeType, file.responseText)) - file.jsonObject = this.parseJSON(file); - } - - // The jsonObject is created so, the JSON tab can be displayed. - if (file.jsonObject && hasProperties(file.jsonObject)) - { - Firebug.NetMonitor.NetInfoBody.appendTab(infoBox, "JSON", - ///$STR("jsonviewer.tab.JSON")); - $STR("JSON")); - - if (FBTrace.DBG_JSONVIEWER) - FBTrace.sysout("jsonviewer.initTabBody; JSON object available " + - (typeof(file.jsonObject) != "undefined"), file.jsonObject); - } - }, - - isJSON: function(contentType, data) - { - // Workaround for JSON responses without proper content type - // Let's consider all responses starting with "{" as JSON. In the worst - // case there will be an exception when parsing. This means that no-JSON - // responses (and post data) (with "{") can be parsed unnecessarily, - // which represents a little overhead, but this happens only if the request - // is actually expanded by the user in the UI (Net & Console panels). - - ///var responseText = data ? trimLeft(data) : null; - ///if (responseText && responseText.indexOf("{") == 0) - /// return true; - var responseText = data ? trim(data) : null; - if (responseText && responseText.indexOf("{") == 0) - return true; - - if (!contentType) - return false; - - contentType = contentType.split(";")[0]; - contentType = trim(contentType); - return contentTypes[contentType]; - }, - - // Update listener for TabView - updateTabBody: function(infoBox, file, context) - { - var tab = infoBox.selectedTab; - ///var tabBody = infoBox.getElementsByClassName("netInfoJSONText").item(0); - var tabBody = $$(".netInfoJSONText", infoBox)[0]; - if (!hasClass(tab, "netInfoJSONTab") || tabBody.updated) - return; - - tabBody.updated = true; - - if (file.jsonObject) { - Firebug.DOMPanel.DirTable.tag.replace( - {object: file.jsonObject, toggles: this.toggles}, tabBody); - } - }, - - parseJSON: function(file) - { - var jsonString = new String(file.responseText); - ///return parseJSONString(jsonString, "http://" + file.request.originalURI.host); - return parseJSONString(jsonString); - } -}); - -// ************************************************************************************************ -// Registration - -Firebug.registerModule(Firebug.JSONViewerModel); - -// ************************************************************************************************ -}}); - - -/* See license.txt for terms of usage */ - -FBL.ns(function() { with (FBL) { - -// ************************************************************************************************ -// Constants - -// List of XML related content types. -var xmlContentTypes = -[ - "text/xml", - "application/xml", - "application/xhtml+xml", - "application/rss+xml", - "application/atom+xml",, - "application/vnd.mozilla.maybe.feed", - "application/rdf+xml", - "application/vnd.mozilla.xul+xml" -]; - -// ************************************************************************************************ -// Model implementation - -/** - * @module Implements viewer for XML based network responses. In order to create a new - * tab wihin network request detail, a listener is registered into - * <code>Firebug.NetMonitor.NetInfoBody</code> object. - */ -Firebug.XMLViewerModel = extend(Firebug.Module, -{ - dispatchName: "xmlViewer", - - initialize: function() - { - ///Firebug.ActivableModule.initialize.apply(this, arguments); - Firebug.Module.initialize.apply(this, arguments); - Firebug.NetMonitor.NetInfoBody.addListener(this); - }, - - shutdown: function() - { - ///Firebug.ActivableModule.shutdown.apply(this, arguments); - Firebug.Module.shutdown.apply(this, arguments); - Firebug.NetMonitor.NetInfoBody.removeListener(this); - }, - - /** - * Check response's content-type and if it's a XML, create a new tab with XML preview. - */ - initTabBody: function(infoBox, file) - { - if (FBTrace.DBG_XMLVIEWER) - FBTrace.sysout("xmlviewer.initTabBody", infoBox); - - // If the response is XML let's display a pretty preview. - ///if (this.isXML(safeGetContentType(file.request))) - if (this.isXML(file.mimeType, file.responseText)) - { - Firebug.NetMonitor.NetInfoBody.appendTab(infoBox, "XML", - ///$STR("xmlviewer.tab.XML")); - $STR("XML")); - - if (FBTrace.DBG_XMLVIEWER) - FBTrace.sysout("xmlviewer.initTabBody; XML response available"); - } - }, - - isXML: function(contentType) - { - if (!contentType) - return false; - - // Look if the response is XML based. - for (var i=0; i<xmlContentTypes.length; i++) - { - if (contentType.indexOf(xmlContentTypes[i]) == 0) - return true; - } - - return false; - }, - - /** - * Parse XML response and render pretty printed preview. - */ - updateTabBody: function(infoBox, file, context) - { - var tab = infoBox.selectedTab; - ///var tabBody = infoBox.getElementsByClassName("netInfoXMLText").item(0); - var tabBody = $$(".netInfoXMLText", infoBox)[0]; - if (!hasClass(tab, "netInfoXMLTab") || tabBody.updated) - return; - - tabBody.updated = true; - - this.insertXML(tabBody, Firebug.NetMonitor.Utils.getResponseText(file, context)); - }, - - insertXML: function(parentNode, text) - { - var xmlText = text.replace(/^\s*<?.+?>\s*/, ""); - - var div = parentNode.ownerDocument.createElement("div"); - div.innerHTML = xmlText; - - var root = div.getElementsByTagName("*")[0]; - - /*** - var parser = CCIN("@mozilla.org/xmlextras/domparser;1", "nsIDOMParser"); - var doc = parser.parseFromString(text, "text/xml"); - var root = doc.documentElement; - - // Error handling - var nsURI = "http://www.mozilla.org/newlayout/xml/parsererror.xml"; - if (root.namespaceURI == nsURI && root.nodeName == "parsererror") - { - this.ParseError.tag.replace({error: { - message: root.firstChild.nodeValue, - source: root.lastChild.textContent - }}, parentNode); - return; - } - /**/ - - if (FBTrace.DBG_XMLVIEWER) - FBTrace.sysout("xmlviewer.updateTabBody; XML response parsed", doc); - - // Override getHidden in these templates. The parsed XML documen is - // hidden, but we want to display it using 'visible' styling. - /* - var templates = [ - Firebug.HTMLPanel.CompleteElement, - Firebug.HTMLPanel.Element, - Firebug.HTMLPanel.TextElement, - Firebug.HTMLPanel.EmptyElement, - Firebug.HTMLPanel.XEmptyElement, - ]; - - var originals = []; - for (var i=0; i<templates.length; i++) - { - originals[i] = templates[i].getHidden; - templates[i].getHidden = function() { - return ""; - } - } - /**/ - - // Generate XML preview. - ///Firebug.HTMLPanel.CompleteElement.tag.replace({object: doc.documentElement}, parentNode); - - // TODO: xxxpedro html3 - ///Firebug.HTMLPanel.CompleteElement.tag.replace({object: root}, parentNode); - var html = []; - Firebug.Reps.appendNode(root, html); - parentNode.innerHTML = html.join(""); - - - /* - for (var i=0; i<originals.length; i++) - templates[i].getHidden = originals[i];/**/ - } -}); - -// ************************************************************************************************ -// Domplate - -/** - * @domplate Represents a template for displaying XML parser errors. Used by - * <code>Firebug.XMLViewerModel</code>. - */ -Firebug.XMLViewerModel.ParseError = domplate(Firebug.Rep, -{ - tag: - DIV({"class": "xmlInfoError"}, - DIV({"class": "xmlInfoErrorMsg"}, "$error.message"), - PRE({"class": "xmlInfoErrorSource"}, "$error|getSource") - ), - - getSource: function(error) - { - var parts = error.source.split("\n"); - if (parts.length != 2) - return error.source; - - var limit = 50; - var column = parts[1].length; - if (column >= limit) { - parts[0] = "..." + parts[0].substr(column - limit); - parts[1] = "..." + parts[1].substr(column - limit); - } - - if (parts[0].length > 80) - parts[0] = parts[0].substr(0, 80) + "..."; - - return parts.join("\n"); - } -}); - -// ************************************************************************************************ -// Registration - -Firebug.registerModule(Firebug.XMLViewerModel); - -}}); - - -/* See license.txt for terms of usage */ - -// next-generation Console Panel (will override consoje.js) -FBL.ns(function() { with (FBL) { -// ************************************************************************************************ - -// ************************************************************************************************ -// Constants - -/* -const Cc = Components.classes; -const Ci = Components.interfaces; -const nsIPrefBranch2 = Ci.nsIPrefBranch2; -const PrefService = Cc["@mozilla.org/preferences-service;1"]; -const prefs = PrefService.getService(nsIPrefBranch2); -/**/ -/* - -// new offline message handler -o = {x:1,y:2}; - -r = Firebug.getRep(o); - -r.tag.tag.compile(); - -outputs = []; -html = r.tag.renderHTML({object:o}, outputs); - - -// finish rendering the template (the DOM part) -target = $("build"); -target.innerHTML = html; -root = target.firstChild; - -domArgs = [root, r.tag.context, 0]; -domArgs.push.apply(domArgs, r.tag.domArgs); -domArgs.push.apply(domArgs, outputs); -r.tag.tag.renderDOM.apply(self ? self : r.tag.subject, domArgs); - - - */ -var consoleQueue = []; -var lastHighlightedObject; -var FirebugContext = Env.browser; - -// ************************************************************************************************ - -var maxQueueRequests = 500; - -// ************************************************************************************************ - -Firebug.ConsoleBase = -{ - log: function(object, context, className, rep, noThrottle, sourceLink) - { - //dispatch(this.fbListeners,"log",[context, object, className, sourceLink]); - return this.logRow(appendObject, object, context, className, rep, sourceLink, noThrottle); - }, - - logFormatted: function(objects, context, className, noThrottle, sourceLink) - { - //dispatch(this.fbListeners,"logFormatted",[context, objects, className, sourceLink]); - return this.logRow(appendFormatted, objects, context, className, null, sourceLink, noThrottle); - }, - - openGroup: function(objects, context, className, rep, noThrottle, sourceLink, noPush) - { - return this.logRow(appendOpenGroup, objects, context, className, rep, sourceLink, noThrottle); - }, - - closeGroup: function(context, noThrottle) - { - return this.logRow(appendCloseGroup, null, context, null, null, null, noThrottle, true); - }, - - logRow: function(appender, objects, context, className, rep, sourceLink, noThrottle, noRow) - { - // TODO: xxxpedro console console2 - noThrottle = true; // xxxpedro forced because there is no TabContext yet - - if (!context) - context = FirebugContext; - - if (FBTrace.DBG_ERRORS && !context) - FBTrace.sysout("Console.logRow has no context, skipping objects", objects); - - if (!context) - return; - - if (noThrottle || !context) - { - var panel = this.getPanel(context); - if (panel) - { - var row = panel.append(appender, objects, className, rep, sourceLink, noRow); - var container = panel.panelNode; - - // TODO: xxxpedro what is this? console console2 - /* - var template = Firebug.NetMonitor.NetLimit; - - while (container.childNodes.length > maxQueueRequests + 1) - { - clearDomplate(container.firstChild.nextSibling); - container.removeChild(container.firstChild.nextSibling); - panel.limit.limitInfo.totalCount++; - template.updateCounter(panel.limit); - } - dispatch([Firebug.A11yModel], "onLogRowCreated", [panel , row]); - /**/ - return row; - } - else - { - consoleQueue.push([appender, objects, context, className, rep, sourceLink, noThrottle, noRow]); - } - } - else - { - if (!context.throttle) - { - //FBTrace.sysout("console.logRow has not context.throttle! "); - return; - } - var args = [appender, objects, context, className, rep, sourceLink, true, noRow]; - context.throttle(this.logRow, this, args); - } - }, - - appendFormatted: function(args, row, context) - { - if (!context) - context = FirebugContext; - - var panel = this.getPanel(context); - panel.appendFormatted(args, row); - }, - - clear: function(context) - { - if (!context) - //context = FirebugContext; - context = Firebug.context; - - /* - if (context) - Firebug.Errors.clear(context); - /**/ - - var panel = this.getPanel(context, true); - if (panel) - { - panel.clear(); - } - }, - - // Override to direct output to your panel - getPanel: function(context, noCreate) - { - //return context.getPanel("console", noCreate); - // TODO: xxxpedro console console2 - return Firebug.chrome ? Firebug.chrome.getPanel("Console") : null; - } - -}; - -// ************************************************************************************************ - -//TODO: xxxpedro -//var ActivableConsole = extend(Firebug.ActivableModule, Firebug.ConsoleBase); -var ActivableConsole = extend(Firebug.ConsoleBase, -{ - isAlwaysEnabled: function() - { - return true; - } -}); - -Firebug.Console = Firebug.Console = extend(ActivableConsole, -//Firebug.Console = extend(ActivableConsole, -{ - dispatchName: "console", - - error: function() - { - Firebug.Console.logFormatted(arguments, Firebug.browser, "error"); - }, - - flush: function() - { - dispatch(this.fbListeners,"flush",[]); - - for (var i=0, length=consoleQueue.length; i<length; i++) - { - var args = consoleQueue[i]; - this.logRow.apply(this, args); - } - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // extends Module - - showPanel: function(browser, panel) - { - }, - - getFirebugConsoleElement: function(context, win) - { - var element = win.document.getElementById("_firebugConsole"); - if (!element) - { - if (FBTrace.DBG_CONSOLE) - FBTrace.sysout("getFirebugConsoleElement forcing element"); - var elementForcer = "(function(){var r=null; try { r = window._getFirebugConsoleElement();}catch(exc){r=exc;} return r;})();"; // we could just add the elements here - - if (context.stopped) - Firebug.Console.injector.evaluateConsoleScript(context); // todo evaluate consoleForcer on stack - else - var r = Firebug.CommandLine.evaluateInWebPage(elementForcer, context, win); - - if (FBTrace.DBG_CONSOLE) - FBTrace.sysout("getFirebugConsoleElement forcing element result "+r, r); - - var element = win.document.getElementById("_firebugConsole"); - if (!element) // elementForce fails - { - if (FBTrace.DBG_ERRORS) FBTrace.sysout("console.getFirebugConsoleElement: no _firebugConsole in win:", win); - Firebug.Console.logFormatted(["Firebug cannot find _firebugConsole element", r, win], context, "error", true); - } - } - - return element; - }, - - isReadyElsePreparing: function(context, win) // this is the only code that should call injector.attachIfNeeded - { - if (FBTrace.DBG_CONSOLE) - FBTrace.sysout("console.isReadyElsePreparing, win is " + - (win?"an argument: ":"null, context.window: ") + - (win?win.location:context.window.location), (win?win:context.window)); - - if (win) - return this.injector.attachIfNeeded(context, win); - else - { - var attached = true; - for (var i = 0; i < context.windows.length; i++) - attached = attached && this.injector.attachIfNeeded(context, context.windows[i]); - // already in the list above attached = attached && this.injector.attachIfNeeded(context, context.window); - if (context.windows.indexOf(context.window) == -1) - FBTrace.sysout("isReadyElsePreparing ***************** context.window not in context.windows"); - if (FBTrace.DBG_CONSOLE) - FBTrace.sysout("console.isReadyElsePreparing attached to "+context.windows.length+" and returns "+attached); - return attached; - } - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // extends ActivableModule - - initialize: function() - { - this.panelName = "console"; - - //TODO: xxxpedro - //Firebug.ActivableModule.initialize.apply(this, arguments); - //Firebug.Debugger.addListener(this); - }, - - enable: function() - { - if (Firebug.Console.isAlwaysEnabled()) - this.watchForErrors(); - }, - - disable: function() - { - if (Firebug.Console.isAlwaysEnabled()) - this.unwatchForErrors(); - }, - - initContext: function(context, persistedState) - { - Firebug.ActivableModule.initContext.apply(this, arguments); - context.consoleReloadWarning = true; // mark as need to warn. - }, - - loadedContext: function(context) - { - for (var url in context.sourceFileMap) - return; // if there are any sourceFiles, then do nothing - - // else we saw no JS, so the reload warning it not needed. - this.clearReloadWarning(context); - }, - - clearReloadWarning: function(context) // remove the warning about reloading. - { - if (context.consoleReloadWarning) - { - var panel = context.getPanel(this.panelName); - panel.clearReloadWarning(); - delete context.consoleReloadWarning; - } - }, - - togglePersist: function(context) - { - var panel = context.getPanel(this.panelName); - panel.persistContent = panel.persistContent ? false : true; - Firebug.chrome.setGlobalAttribute("cmd_togglePersistConsole", "checked", panel.persistContent); - }, - - showContext: function(browser, context) - { - Firebug.chrome.setGlobalAttribute("cmd_clearConsole", "disabled", !context); - - Firebug.ActivableModule.showContext.apply(this, arguments); - }, - - destroyContext: function(context, persistedState) - { - Firebug.Console.injector.detachConsole(context, context.window); // TODO iterate windows? - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - onPanelEnable: function(panelName) - { - if (panelName != this.panelName) // we don't care about other panels - return; - - if (FBTrace.DBG_CONSOLE) - FBTrace.sysout("console.onPanelEnable**************"); - - this.watchForErrors(); - Firebug.Debugger.addDependentModule(this); // we inject the console during JS compiles so we need jsd - }, - - onPanelDisable: function(panelName) - { - if (panelName != this.panelName) // we don't care about other panels - return; - - if (FBTrace.DBG_CONSOLE) - FBTrace.sysout("console.onPanelDisable**************"); - - Firebug.Debugger.removeDependentModule(this); // we inject the console during JS compiles so we need jsd - this.unwatchForErrors(); - - // Make sure possible errors coming from the page and displayed in the Firefox - // status bar are removed. - this.clear(); - }, - - onSuspendFirebug: function() - { - if (FBTrace.DBG_CONSOLE) - FBTrace.sysout("console.onSuspendFirebug\n"); - if (Firebug.Console.isAlwaysEnabled()) - this.unwatchForErrors(); - }, - - onResumeFirebug: function() - { - if (FBTrace.DBG_CONSOLE) - FBTrace.sysout("console.onResumeFirebug\n"); - if (Firebug.Console.isAlwaysEnabled()) - this.watchForErrors(); - }, - - watchForErrors: function() - { - Firebug.Errors.checkEnabled(); - $('fbStatusIcon').setAttribute("console", "on"); - }, - - unwatchForErrors: function() - { - Firebug.Errors.checkEnabled(); - $('fbStatusIcon').removeAttribute("console"); - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // Firebug.Debugger listener - - onMonitorScript: function(context, frame) - { - Firebug.Console.log(frame, context); - }, - - onFunctionCall: function(context, frame, depth, calling) - { - if (calling) - Firebug.Console.openGroup([frame, "depth:"+depth], context); - else - Firebug.Console.closeGroup(context); - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - logRow: function(appender, objects, context, className, rep, sourceLink, noThrottle, noRow) - { - if (!context) - context = FirebugContext; - - if (FBTrace.DBG_WINDOWS && !context) FBTrace.sysout("Console.logRow: no context \n"); - - if (this.isAlwaysEnabled()) - return Firebug.ConsoleBase.logRow.apply(this, arguments); - } -}); - -Firebug.ConsoleListener = -{ - log: function(context, object, className, sourceLink) - { - }, - - logFormatted: function(context, objects, className, sourceLink) - { - } -}; - -// ************************************************************************************************ - -Firebug.ConsolePanel = function () {} // XXjjb attach Firebug so this panel can be extended. - -//TODO: xxxpedro -//Firebug.ConsolePanel.prototype = extend(Firebug.ActivablePanel, -Firebug.ConsolePanel.prototype = extend(Firebug.Panel, -{ - wasScrolledToBottom: false, - messageCount: 0, - lastLogTime: 0, - groups: null, - limit: null, - - append: function(appender, objects, className, rep, sourceLink, noRow) - { - var container = this.getTopContainer(); - - if (noRow) - { - appender.apply(this, [objects]); - } - else - { - // xxxHonza: Don't update the this.wasScrolledToBottom flag now. - // At the beginning (when the first log is created) the isScrolledToBottom - // always returns true. - //if (this.panelNode.offsetHeight) - // this.wasScrolledToBottom = isScrolledToBottom(this.panelNode); - - var row = this.createRow("logRow", className); - appender.apply(this, [objects, row, rep]); - - if (sourceLink) - FirebugReps.SourceLink.tag.append({object: sourceLink}, row); - - container.appendChild(row); - - this.filterLogRow(row, this.wasScrolledToBottom); - - if (this.wasScrolledToBottom) - scrollToBottom(this.panelNode); - - return row; - } - }, - - clear: function() - { - if (this.panelNode) - { - if (FBTrace.DBG_CONSOLE) - FBTrace.sysout("ConsolePanel.clear"); - clearNode(this.panelNode); - this.insertLogLimit(this.context); - } - }, - - insertLogLimit: function() - { - // Create limit row. This row is the first in the list of entries - // and initially hidden. It's displayed as soon as the number of - // entries reaches the limit. - var row = this.createRow("limitRow"); - - var limitInfo = { - totalCount: 0, - limitPrefsTitle: $STRF("LimitPrefsTitle", [Firebug.prefDomain+".console.logLimit"]) - }; - - //TODO: xxxpedro console net limit!? - return; - var netLimitRep = Firebug.NetMonitor.NetLimit; - var nodes = netLimitRep.createTable(row, limitInfo); - - this.limit = nodes[1]; - - var container = this.panelNode; - container.insertBefore(nodes[0], container.firstChild); - }, - - insertReloadWarning: function() - { - // put the message in, we will clear if the window console is injected. - this.warningRow = this.append(appendObject, $STR("message.Reload to activate window console"), "info"); - }, - - clearReloadWarning: function() - { - if (this.warningRow) - { - this.warningRow.parentNode.removeChild(this.warningRow); - delete this.warningRow; - } - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - appendObject: function(object, row, rep) - { - if (!rep) - rep = Firebug.getRep(object); - return rep.tag.append({object: object}, row); - }, - - appendFormatted: function(objects, row, rep) - { - if (!objects || !objects.length) - return; - - function logText(text, row) - { - var node = row.ownerDocument.createTextNode(text); - row.appendChild(node); - } - - var format = objects[0]; - var objIndex = 0; - - if (typeof(format) != "string") - { - format = ""; - objIndex = -1; - } - else // a string - { - if (objects.length === 1) // then we have only a string... - { - if (format.length < 1) { // ...and it has no characters. - logText("(an empty string)", row); - return; - } - } - } - - var parts = parseFormat(format); - var trialIndex = objIndex; - for (var i= 0; i < parts.length; i++) - { - var part = parts[i]; - if (part && typeof(part) == "object") - { - if (++trialIndex > objects.length) // then too few parameters for format, assume unformatted. - { - format = ""; - objIndex = -1; - parts.length = 0; - break; - } - } - - } - for (var i = 0; i < parts.length; ++i) - { - var part = parts[i]; - if (part && typeof(part) == "object") - { - var object = objects[++objIndex]; - if (typeof(object) != "undefined") - this.appendObject(object, row, part.rep); - else - this.appendObject(part.type, row, FirebugReps.Text); - } - else - FirebugReps.Text.tag.append({object: part}, row); - } - - for (var i = objIndex+1; i < objects.length; ++i) - { - logText(" ", row); - var object = objects[i]; - if (typeof(object) == "string") - FirebugReps.Text.tag.append({object: object}, row); - else - this.appendObject(object, row); - } - }, - - appendOpenGroup: function(objects, row, rep) - { - if (!this.groups) - this.groups = []; - - setClass(row, "logGroup"); - setClass(row, "opened"); - - var innerRow = this.createRow("logRow"); - setClass(innerRow, "logGroupLabel"); - if (rep) - rep.tag.replace({"objects": objects}, innerRow); - else - this.appendFormatted(objects, innerRow, rep); - row.appendChild(innerRow); - //dispatch([Firebug.A11yModel], 'onLogRowCreated', [this, innerRow]); - var groupBody = this.createRow("logGroupBody"); - row.appendChild(groupBody); - groupBody.setAttribute('role', 'group'); - this.groups.push(groupBody); - - addEvent(innerRow, "mousedown", function(event) - { - if (isLeftClick(event)) - { - //console.log(event.currentTarget == event.target); - - var target = event.target || event.srcElement; - - target = getAncestorByClass(target, "logGroupLabel"); - - var groupRow = target.parentNode; - - if (hasClass(groupRow, "opened")) - { - removeClass(groupRow, "opened"); - target.setAttribute('aria-expanded', 'false'); - } - else - { - setClass(groupRow, "opened"); - target.setAttribute('aria-expanded', 'true'); - } - } - }); - }, - - appendCloseGroup: function(object, row, rep) - { - if (this.groups) - this.groups.pop(); - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // TODO: xxxpedro console2 - onMouseMove: function(event) - { - if (!Firebug.Inspector) return; - - var target = event.srcElement || event.target; - - var object = getAncestorByClass(target, "objectLink-element"); - object = object ? object.repObject : null; - - if(object && instanceOf(object, "Element") && object.nodeType == 1) - { - if(object != lastHighlightedObject) - { - Firebug.Inspector.drawBoxModel(object); - object = lastHighlightedObject; - } - } - else - Firebug.Inspector.hideBoxModel(); - - }, - - onMouseDown: function(event) - { - var target = event.srcElement || event.target; - - var object = getAncestorByClass(target, "objectLink"); - var repObject = object ? object.repObject : null; - - if (!repObject) - { - return; - } - - if (hasClass(object, "objectLink-object")) - { - Firebug.chrome.selectPanel("DOM"); - Firebug.chrome.getPanel("DOM").select(repObject, true); - } - else if (hasClass(object, "objectLink-element")) - { - Firebug.chrome.selectPanel("HTML"); - Firebug.chrome.getPanel("HTML").select(repObject, true); - } - - /* - if(object && instanceOf(object, "Element") && object.nodeType == 1) - { - if(object != lastHighlightedObject) - { - Firebug.Inspector.drawBoxModel(object); - object = lastHighlightedObject; - } - } - else - Firebug.Inspector.hideBoxModel(); - /**/ - - }, - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // extends Panel - - name: "Console", - title: "Console", - //searchable: true, - //breakable: true, - //editable: false, - - options: - { - hasCommandLine: true, - hasToolButtons: true, - isPreRendered: true - }, - - create: function() - { - Firebug.Panel.create.apply(this, arguments); - - this.context = Firebug.browser.window; - this.document = Firebug.chrome.document; - this.onMouseMove = bind(this.onMouseMove, this); - this.onMouseDown = bind(this.onMouseDown, this); - - this.clearButton = new Button({ - element: $("fbConsole_btClear"), - owner: Firebug.Console, - onClick: Firebug.Console.clear - }); - }, - - initialize: function() - { - Firebug.Panel.initialize.apply(this, arguments); // loads persisted content - //Firebug.ActivablePanel.initialize.apply(this, arguments); // loads persisted content - - if (!this.persistedContent && Firebug.Console.isAlwaysEnabled()) - { - this.insertLogLimit(this.context); - - // Initialize log limit and listen for changes. - this.updateMaxLimit(); - - if (this.context.consoleReloadWarning) // we have not yet injected the console - this.insertReloadWarning(); - } - - //Firebug.Console.injector.install(Firebug.browser.window); - - addEvent(this.panelNode, "mouseover", this.onMouseMove); - addEvent(this.panelNode, "mousedown", this.onMouseDown); - - this.clearButton.initialize(); - - //consolex.trace(); - //TODO: xxxpedro remove this - /* - Firebug.Console.openGroup(["asd"], null, "group", null, false); - Firebug.Console.log("asd"); - Firebug.Console.log("asd"); - Firebug.Console.log("asd"); - /**/ - - //TODO: xxxpedro preferences prefs - //prefs.addObserver(Firebug.prefDomain, this, false); - }, - - initializeNode : function() - { - //dispatch([Firebug.A11yModel], 'onInitializeNode', [this]); - if (FBTrace.DBG_CONSOLE) - { - this.onScroller = bind(this.onScroll, this); - addEvent(this.panelNode, "scroll", this.onScroller); - } - - this.onResizer = bind(this.onResize, this); - this.resizeEventTarget = Firebug.chrome.$('fbContentBox'); - addEvent(this.resizeEventTarget, "resize", this.onResizer); - }, - - destroyNode : function() - { - //dispatch([Firebug.A11yModel], 'onDestroyNode', [this]); - if (this.onScroller) - removeEvent(this.panelNode, "scroll", this.onScroller); - - //removeEvent(this.resizeEventTarget, "resize", this.onResizer); - }, - - shutdown: function() - { - //TODO: xxxpedro console console2 - this.clearButton.shutdown(); - - removeEvent(this.panelNode, "mousemove", this.onMouseMove); - removeEvent(this.panelNode, "mousedown", this.onMouseDown); - - this.destroyNode(); - - Firebug.Panel.shutdown.apply(this, arguments); - - //TODO: xxxpedro preferences prefs - //prefs.removeObserver(Firebug.prefDomain, this, false); - }, - - ishow: function(state) - { - if (FBTrace.DBG_CONSOLE) - FBTrace.sysout("Console.panel show; " + this.context.getName(), state); - - var enabled = Firebug.Console.isAlwaysEnabled(); - if (enabled) - { - Firebug.Console.disabledPanelPage.hide(this); - this.showCommandLine(true); - this.showToolbarButtons("fbConsoleButtons", true); - Firebug.chrome.setGlobalAttribute("cmd_togglePersistConsole", "checked", this.persistContent); - - if (state && state.wasScrolledToBottom) - { - this.wasScrolledToBottom = state.wasScrolledToBottom; - delete state.wasScrolledToBottom; - } - - if (this.wasScrolledToBottom) - scrollToBottom(this.panelNode); - - if (FBTrace.DBG_CONSOLE) - FBTrace.sysout("console.show ------------------ wasScrolledToBottom: " + - this.wasScrolledToBottom + ", " + this.context.getName()); - } - else - { - this.hide(state); - Firebug.Console.disabledPanelPage.show(this); - } - }, - - ihide: function(state) - { - if (FBTrace.DBG_CONSOLE) - FBTrace.sysout("Console.panel hide; " + this.context.getName(), state); - - this.showToolbarButtons("fbConsoleButtons", false); - this.showCommandLine(false); - - if (FBTrace.DBG_CONSOLE) - FBTrace.sysout("console.hide ------------------ wasScrolledToBottom: " + - this.wasScrolledToBottom + ", " + this.context.getName()); - }, - - destroy: function(state) - { - if (this.panelNode.offsetHeight) - this.wasScrolledToBottom = isScrolledToBottom(this.panelNode); - - if (state) - state.wasScrolledToBottom = this.wasScrolledToBottom; - - if (FBTrace.DBG_CONSOLE) - FBTrace.sysout("console.destroy ------------------ wasScrolledToBottom: " + - this.wasScrolledToBottom + ", " + this.context.getName()); - }, - - shouldBreakOnNext: function() - { - // xxxHonza: shouldn't the breakOnErrors be context related? - // xxxJJB, yes, but we can't support it because we can't yet tell - // which window the error is on. - return Firebug.getPref(Firebug.servicePrefDomain, "breakOnErrors"); - }, - - getBreakOnNextTooltip: function(enabled) - { - return (enabled ? $STR("console.Disable Break On All Errors") : - $STR("console.Break On All Errors")); - }, - - enablePanel: function(module) - { - if (FBTrace.DBG_CONSOLE) - FBTrace.sysout("console.ConsolePanel.enablePanel; " + this.context.getName()); - - Firebug.ActivablePanel.enablePanel.apply(this, arguments); - - this.showCommandLine(true); - - if (this.wasScrolledToBottom) - scrollToBottom(this.panelNode); - }, - - disablePanel: function(module) - { - if (FBTrace.DBG_CONSOLE) - FBTrace.sysout("console.ConsolePanel.disablePanel; " + this.context.getName()); - - Firebug.ActivablePanel.disablePanel.apply(this, arguments); - - this.showCommandLine(false); - }, - - getOptionsMenuItems: function() - { - return [ - optionMenu("ShowJavaScriptErrors", "showJSErrors"), - optionMenu("ShowJavaScriptWarnings", "showJSWarnings"), - optionMenu("ShowCSSErrors", "showCSSErrors"), - optionMenu("ShowXMLErrors", "showXMLErrors"), - optionMenu("ShowXMLHttpRequests", "showXMLHttpRequests"), - optionMenu("ShowChromeErrors", "showChromeErrors"), - optionMenu("ShowChromeMessages", "showChromeMessages"), - optionMenu("ShowExternalErrors", "showExternalErrors"), - optionMenu("ShowNetworkErrors", "showNetworkErrors"), - this.getShowStackTraceMenuItem(), - this.getStrictOptionMenuItem(), - "-", - optionMenu("LargeCommandLine", "largeCommandLine") - ]; - }, - - getShowStackTraceMenuItem: function() - { - var menuItem = serviceOptionMenu("ShowStackTrace", "showStackTrace"); - if (FirebugContext && !Firebug.Debugger.isAlwaysEnabled()) - menuItem.disabled = true; - return menuItem; - }, - - getStrictOptionMenuItem: function() - { - var strictDomain = "javascript.options"; - var strictName = "strict"; - var strictValue = prefs.getBoolPref(strictDomain+"."+strictName); - return {label: "JavascriptOptionsStrict", type: "checkbox", checked: strictValue, - command: bindFixed(Firebug.setPref, Firebug, strictDomain, strictName, !strictValue) }; - }, - - getBreakOnMenuItems: function() - { - //xxxHonza: no BON options for now. - /*return [ - optionMenu("console.option.Persist Break On Error", "persistBreakOnError") - ];*/ - return []; - }, - - search: function(text) - { - if (!text) - return; - - // Make previously visible nodes invisible again - if (this.matchSet) - { - for (var i in this.matchSet) - removeClass(this.matchSet[i], "matched"); - } - - this.matchSet = []; - - function findRow(node) { return getAncestorByClass(node, "logRow"); } - var search = new TextSearch(this.panelNode, findRow); - - var logRow = search.find(text); - if (!logRow) - { - dispatch([Firebug.A11yModel], 'onConsoleSearchMatchFound', [this, text, []]); - return false; - } - for (; logRow; logRow = search.findNext()) - { - setClass(logRow, "matched"); - this.matchSet.push(logRow); - } - dispatch([Firebug.A11yModel], 'onConsoleSearchMatchFound', [this, text, this.matchSet]); - return true; - }, - - breakOnNext: function(breaking) - { - Firebug.setPref(Firebug.servicePrefDomain, "breakOnErrors", breaking); - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // private - - createRow: function(rowName, className) - { - var elt = this.document.createElement("div"); - elt.className = rowName + (className ? " " + rowName + "-" + className : ""); - return elt; - }, - - getTopContainer: function() - { - if (this.groups && this.groups.length) - return this.groups[this.groups.length-1]; - else - return this.panelNode; - }, - - filterLogRow: function(logRow, scrolledToBottom) - { - if (this.searchText) - { - setClass(logRow, "matching"); - setClass(logRow, "matched"); - - // Search after a delay because we must wait for a frame to be created for - // the new logRow so that the finder will be able to locate it - setTimeout(bindFixed(function() - { - if (this.searchFilter(this.searchText, logRow)) - this.matchSet.push(logRow); - else - removeClass(logRow, "matched"); - - removeClass(logRow, "matching"); - - if (scrolledToBottom) - scrollToBottom(this.panelNode); - }, this), 100); - } - }, - - searchFilter: function(text, logRow) - { - var count = this.panelNode.childNodes.length; - var searchRange = this.document.createRange(); - searchRange.setStart(this.panelNode, 0); - searchRange.setEnd(this.panelNode, count); - - var startPt = this.document.createRange(); - startPt.setStartBefore(logRow); - - var endPt = this.document.createRange(); - endPt.setStartAfter(logRow); - - return finder.Find(text, searchRange, startPt, endPt) != null; - }, - - // nsIPrefObserver - observe: function(subject, topic, data) - { - // We're observing preferences only. - if (topic != "nsPref:changed") - return; - - // xxxHonza check this out. - var prefDomain = "Firebug.extension."; - var prefName = data.substr(prefDomain.length); - if (prefName == "console.logLimit") - this.updateMaxLimit(); - }, - - updateMaxLimit: function() - { - var value = 1000; - //TODO: xxxpedro preferences log limit? - //var value = Firebug.getPref(Firebug.prefDomain, "console.logLimit"); - maxQueueRequests = value ? value : maxQueueRequests; - }, - - showCommandLine: function(shouldShow) - { - //TODO: xxxpedro show command line important - return; - - if (shouldShow) - { - collapse(Firebug.chrome.$("fbCommandBox"), false); - Firebug.CommandLine.setMultiLine(Firebug.largeCommandLine, Firebug.chrome); - } - else - { - // Make sure that entire content of the Console panel is hidden when - // the panel is disabled. - Firebug.CommandLine.setMultiLine(false, Firebug.chrome, Firebug.largeCommandLine); - collapse(Firebug.chrome.$("fbCommandBox"), true); - } - }, - - onScroll: function(event) - { - // Update the scroll position flag if the position changes. - this.wasScrolledToBottom = FBL.isScrolledToBottom(this.panelNode); - - if (FBTrace.DBG_CONSOLE) - FBTrace.sysout("console.onScroll ------------------ wasScrolledToBottom: " + - this.wasScrolledToBottom + ", wasScrolledToBottom: " + - this.context.getName(), event); - }, - - onResize: function(event) - { - if (FBTrace.DBG_CONSOLE) - FBTrace.sysout("console.onResize ------------------ wasScrolledToBottom: " + - this.wasScrolledToBottom + ", offsetHeight: " + this.panelNode.offsetHeight + - ", scrollTop: " + this.panelNode.scrollTop + ", scrollHeight: " + - this.panelNode.scrollHeight + ", " + this.context.getName(), event); - - if (this.wasScrolledToBottom) - scrollToBottom(this.panelNode); - } -}); - -// ************************************************************************************************ - -function parseFormat(format) -{ - var parts = []; - if (format.length <= 0) - return parts; - - var reg = /((^%|.%)(\d+)?(\.)([a-zA-Z]))|((^%|.%)([a-zA-Z]))/; - for (var m = reg.exec(format); m; m = reg.exec(format)) - { - if (m[0].substr(0, 2) == "%%") - { - parts.push(format.substr(0, m.index)); - parts.push(m[0].substr(1)); - } - else - { - var type = m[8] ? m[8] : m[5]; - var precision = m[3] ? parseInt(m[3]) : (m[4] == "." ? -1 : 0); - - var rep = null; - switch (type) - { - case "s": - rep = FirebugReps.Text; - break; - case "f": - case "i": - case "d": - rep = FirebugReps.Number; - break; - case "o": - rep = null; - break; - } - - parts.push(format.substr(0, m[0][0] == "%" ? m.index : m.index+1)); - parts.push({rep: rep, precision: precision, type: ("%" + type)}); - } - - format = format.substr(m.index+m[0].length); - } - - parts.push(format); - return parts; -} - -// ************************************************************************************************ - -var appendObject = Firebug.ConsolePanel.prototype.appendObject; -var appendFormatted = Firebug.ConsolePanel.prototype.appendFormatted; -var appendOpenGroup = Firebug.ConsolePanel.prototype.appendOpenGroup; -var appendCloseGroup = Firebug.ConsolePanel.prototype.appendCloseGroup; - -// ************************************************************************************************ - -//Firebug.registerActivableModule(Firebug.Console); -Firebug.registerModule(Firebug.Console); -Firebug.registerPanel(Firebug.ConsolePanel); - -// ************************************************************************************************ -}}); - - -/* See license.txt for terms of usage */ - -FBL.ns(function() { with (FBL) { - -// ************************************************************************************************ -// Constants - -//const Cc = Components.classes; -//const Ci = Components.interfaces; - -var frameCounters = {}; -var traceRecursion = 0; - -Firebug.Console.injector = -{ - install: function(context) - { - var win = context.window; - - var consoleHandler = new FirebugConsoleHandler(context, win); - - var properties = - [ - "log", - "debug", - "info", - "warn", - "error", - "assert", - "dir", - "dirxml", - "group", - "groupCollapsed", - "groupEnd", - "time", - "timeEnd", - "count", - "trace", - "profile", - "profileEnd", - "clear", - "open", - "close" - ]; - - var Handler = function(name) - { - var c = consoleHandler; - var f = consoleHandler[name]; - return function(){return f.apply(c,arguments);}; - }; - - var installer = function(c) - { - for (var i=0, l=properties.length; i<l; i++) - { - var name = properties[i]; - c[name] = new Handler(name); - c.firebuglite = Firebug.version; - } - }; - - var sandbox; - - if (win.console) - { - if (Env.Options.overrideConsole) - sandbox = new win.Function("arguments.callee.install(window.console={})"); - else - // if there's a console object and overrideConsole is false we should just quit - return; - } - else - { - try - { - // try overriding the console object - sandbox = new win.Function("arguments.callee.install(window.console={})"); - } - catch(E) - { - // if something goes wrong create the firebug object instead - sandbox = new win.Function("arguments.callee.install(window.firebug={})"); - } - } - - sandbox.install = installer; - sandbox(); - }, - - isAttached: function(context, win) - { - if (win.wrappedJSObject) - { - var attached = (win.wrappedJSObject._getFirebugConsoleElement ? true : false); - if (FBTrace.DBG_CONSOLE) - FBTrace.sysout("Console.isAttached:"+attached+" to win.wrappedJSObject "+safeGetWindowLocation(win.wrappedJSObject)); - - return attached; - } - else - { - if (FBTrace.DBG_CONSOLE) - FBTrace.sysout("Console.isAttached? to win "+win.location+" fnc:"+win._getFirebugConsoleElement); - return (win._getFirebugConsoleElement ? true : false); - } - }, - - attachIfNeeded: function(context, win) - { - if (FBTrace.DBG_CONSOLE) - FBTrace.sysout("Console.attachIfNeeded has win "+(win? ((win.wrappedJSObject?"YES":"NO")+" wrappedJSObject"):"null") ); - - if (this.isAttached(context, win)) - return true; - - if (FBTrace.DBG_CONSOLE) - FBTrace.sysout("Console.attachIfNeeded found isAttached false "); - - this.attachConsoleInjector(context, win); - this.addConsoleListener(context, win); - - Firebug.Console.clearReloadWarning(context); - - var attached = this.isAttached(context, win); - if (attached) - dispatch(Firebug.Console.fbListeners, "onConsoleInjected", [context, win]); - - return attached; - }, - - attachConsoleInjector: function(context, win) - { - var consoleInjection = this.getConsoleInjectionScript(); // Do it all here. - - if (FBTrace.DBG_CONSOLE) - FBTrace.sysout("attachConsoleInjector evaluating in "+win.location, consoleInjection); - - Firebug.CommandLine.evaluateInWebPage(consoleInjection, context, win); - - if (FBTrace.DBG_CONSOLE) - FBTrace.sysout("attachConsoleInjector evaluation completed for "+win.location); - }, - - getConsoleInjectionScript: function() { - if (!this.consoleInjectionScript) - { - var script = ""; - script += "window.__defineGetter__('console', function() {\n"; - script += " return (window._firebug ? window._firebug : window.loadFirebugConsole()); })\n\n"; - - script += "window.loadFirebugConsole = function() {\n"; - script += "window._firebug = new _FirebugConsole();"; - - if (FBTrace.DBG_CONSOLE) - script += " window.dump('loadFirebugConsole '+window.location+'\\n');\n"; - - script += " return window._firebug };\n"; - - var theFirebugConsoleScript = getResource("chrome://firebug/content/consoleInjected.js"); - script += theFirebugConsoleScript; - - - this.consoleInjectionScript = script; - } - return this.consoleInjectionScript; - }, - - forceConsoleCompilationInPage: function(context, win) - { - if (!win) - { - if (FBTrace.DBG_CONSOLE) - FBTrace.sysout("no win in forceConsoleCompilationInPage!"); - return; - } - - var consoleForcer = "window.loadFirebugConsole();"; - - if (context.stopped) - Firebug.Console.injector.evaluateConsoleScript(context); // todo evaluate consoleForcer on stack - else - Firebug.CommandLine.evaluateInWebPage(consoleForcer, context, win); - - if (FBTrace.DBG_CONSOLE) - FBTrace.sysout("forceConsoleCompilationInPage "+win.location, consoleForcer); - }, - - evaluateConsoleScript: function(context) - { - var scriptSource = this.getConsoleInjectionScript(); // TODO XXXjjb this should be getConsoleInjectionScript - Firebug.Debugger.evaluate(scriptSource, context); - }, - - addConsoleListener: function(context, win) - { - if (!context.activeConsoleHandlers) // then we have not been this way before - context.activeConsoleHandlers = []; - else - { // we've been this way before... - for (var i=0; i<context.activeConsoleHandlers.length; i++) - { - if (context.activeConsoleHandlers[i].window == win) - { - context.activeConsoleHandlers[i].detach(); - if (FBTrace.DBG_CONSOLE) - FBTrace.sysout("consoleInjector addConsoleListener removed handler("+context.activeConsoleHandlers[i].handler_name+") from _firebugConsole in : "+win.location+"\n"); - context.activeConsoleHandlers.splice(i,1); - } - } - } - - // We need the element to attach our event listener. - var element = Firebug.Console.getFirebugConsoleElement(context, win); - if (element) - element.setAttribute("FirebugVersion", Firebug.version); // Initialize Firebug version. - else - return false; - - var handler = new FirebugConsoleHandler(context, win); - handler.attachTo(element); - - context.activeConsoleHandlers.push(handler); - - if (FBTrace.DBG_CONSOLE) - FBTrace.sysout("consoleInjector addConsoleListener attached handler("+handler.handler_name+") to _firebugConsole in : "+win.location+"\n"); - return true; - }, - - detachConsole: function(context, win) - { - if (win && win.document) - { - var element = win.document.getElementById("_firebugConsole"); - if (element) - element.parentNode.removeChild(element); - } - } -}; - -var total_handlers = 0; -var FirebugConsoleHandler = function FirebugConsoleHandler(context, win) -{ - this.window = win; - - this.attachTo = function(element) - { - this.element = element; - // When raised on our injected element, callback to Firebug and append to console - this.boundHandler = bind(this.handleEvent, this); - this.element.addEventListener('firebugAppendConsole', this.boundHandler, true); // capturing - }; - - this.detach = function() - { - this.element.removeEventListener('firebugAppendConsole', this.boundHandler, true); - }; - - this.handler_name = ++total_handlers; - this.handleEvent = function(event) - { - if (FBTrace.DBG_CONSOLE) - FBTrace.sysout("FirebugConsoleHandler("+this.handler_name+") "+event.target.getAttribute("methodName")+", event", event); - if (!Firebug.CommandLine.CommandHandler.handle(event, this, win)) - { - if (FBTrace.DBG_CONSOLE) - FBTrace.sysout("FirebugConsoleHandler", this); - - var methodName = event.target.getAttribute("methodName"); - Firebug.Console.log($STRF("console.MethodNotSupported", [methodName])); - } - }; - - this.firebuglite = Firebug.version; - - this.init = function() - { - var consoleElement = win.document.getElementById('_firebugConsole'); - consoleElement.setAttribute("FirebugVersion", Firebug.version); - }; - - this.log = function() - { - logFormatted(arguments, "log"); - }; - - this.debug = function() - { - logFormatted(arguments, "debug", true); - }; - - this.info = function() - { - logFormatted(arguments, "info", true); - }; - - this.warn = function() - { - logFormatted(arguments, "warn", true); - }; - - this.error = function() - { - //TODO: xxxpedro console error - //if (arguments.length == 1) - //{ - // logAssert("error", arguments); // add more info based on stack trace - //} - //else - //{ - //Firebug.Errors.increaseCount(context); - logFormatted(arguments, "error", true); // user already added info - //} - }; - - this.exception = function() - { - logAssert("error", arguments); - }; - - this.assert = function(x) - { - if (!x) - { - var rest = []; - for (var i = 1; i < arguments.length; i++) - rest.push(arguments[i]); - logAssert("assert", rest); - } - }; - - this.dir = function(o) - { - Firebug.Console.log(o, context, "dir", Firebug.DOMPanel.DirTable); - }; - - this.dirxml = function(o) - { - ///if (o instanceof Window) - if (instanceOf(o, "Window")) - o = o.document.documentElement; - ///else if (o instanceof Document) - else if (instanceOf(o, "Document")) - o = o.documentElement; - - Firebug.Console.log(o, context, "dirxml", Firebug.HTMLPanel.SoloElement); - }; - - this.group = function() - { - //TODO: xxxpedro; - //var sourceLink = getStackLink(); - var sourceLink = null; - Firebug.Console.openGroup(arguments, null, "group", null, false, sourceLink); - }; - - this.groupEnd = function() - { - Firebug.Console.closeGroup(context); - }; - - this.groupCollapsed = function() - { - var sourceLink = getStackLink(); - // noThrottle true is probably ok, openGroups will likely be short strings. - var row = Firebug.Console.openGroup(arguments, null, "group", null, true, sourceLink); - removeClass(row, "opened"); - }; - - this.profile = function(title) - { - logFormatted(["console.profile() not supported."], "warn", true); - - //Firebug.Profiler.startProfiling(context, title); - }; - - this.profileEnd = function() - { - logFormatted(["console.profile() not supported."], "warn", true); - - //Firebug.Profiler.stopProfiling(context); - }; - - this.count = function(key) - { - // TODO: xxxpedro console2: is there a better way to find a unique ID for the coun() call? - var frameId = "0"; - //var frameId = FBL.getStackFrameId(); - if (frameId) - { - if (!frameCounters) - frameCounters = {}; - - if (key != undefined) - frameId += key; - - var frameCounter = frameCounters[frameId]; - if (!frameCounter) - { - var logRow = logFormatted(["0"], null, true, true); - - frameCounter = {logRow: logRow, count: 1}; - frameCounters[frameId] = frameCounter; - } - else - ++frameCounter.count; - - var label = key == undefined - ? frameCounter.count - : key + " " + frameCounter.count; - - frameCounter.logRow.firstChild.firstChild.nodeValue = label; - } - }; - - this.trace = function() - { - var getFuncName = function getFuncName (f) - { - if (f.getName instanceof Function) - { - return f.getName(); - } - if (f.name) // in FireFox, Function objects have a name property... - { - return f.name; - } - - var name = f.toString().match(/function\s*([_$\w\d]*)/)[1]; - return name || "anonymous"; - }; - - var wasVisited = function(fn) - { - for (var i=0, l=frames.length; i<l; i++) - { - if (frames[i].fn == fn) - { - return true; - } - } - - return false; - }; - - traceRecursion++; - - if (traceRecursion > 1) - { - traceRecursion--; - return; - } - - var frames = []; - - for (var fn = arguments.callee.caller.caller; fn; fn = fn.caller) - { - if (wasVisited(fn)) break; - - var args = []; - - for (var i = 0, l = fn.arguments.length; i < l; ++i) - { - args.push({value: fn.arguments[i]}); - } - - frames.push({fn: fn, name: getFuncName(fn), args: args}); - } - - - // **************************************************************************************** - - try - { - (0)(); - } - catch(e) - { - var result = e; - - var stack = - result.stack || // Firefox / Google Chrome - result.stacktrace || // Opera - ""; - - stack = stack.replace(/\n\r|\r\n/g, "\n"); // normalize line breaks - var items = stack.split(/[\n\r]/); - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // Google Chrome - if (FBL.isSafari) - { - //var reChromeStackItem = /^\s+at\s+([^\(]+)\s\((.*)\)$/; - //var reChromeStackItem = /^\s+at\s+(.*)((?:http|https|ftp|file):\/\/.*)$/; - var reChromeStackItem = /^\s+at\s+(.*)((?:http|https|ftp|file):\/\/.*)$/; - - var reChromeStackItemName = /\s*\($/; - var reChromeStackItemValue = /^(.+)\:(\d+\:\d+)\)?$/; - - var framePos = 0; - for (var i=4, length=items.length; i<length; i++, framePos++) - { - var frame = frames[framePos]; - var item = items[i]; - var match = item.match(reChromeStackItem); - - //Firebug.Console.log("["+ framePos +"]--------------------------"); - //Firebug.Console.log(item); - //Firebug.Console.log("................"); - - if (match) - { - var name = match[1]; - if (name) - { - name = name.replace(reChromeStackItemName, ""); - frame.name = name; - } - - //Firebug.Console.log("name: "+name); - - var value = match[2].match(reChromeStackItemValue); - if (value) - { - frame.href = value[1]; - frame.lineNo = value[2]; - - //Firebug.Console.log("url: "+value[1]); - //Firebug.Console.log("line: "+value[2]); - } - //else - // Firebug.Console.log(match[2]); - - } - } - } - /**/ - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - else if (FBL.isFirefox) - { - // Firefox - var reFirefoxStackItem = /^(.*)@(.*)$/; - var reFirefoxStackItemValue = /^(.+)\:(\d+)$/; - - var framePos = 0; - for (var i=2, length=items.length; i<length; i++, framePos++) - { - var frame = frames[framePos] || {}; - var item = items[i]; - var match = item.match(reFirefoxStackItem); - - if (match) - { - var name = match[1]; - - //Firebug.Console.logFormatted("name: "+name); - - var value = match[2].match(reFirefoxStackItemValue); - if (value) - { - frame.href = value[1]; - frame.lineNo = value[2]; - - //Firebug.Console.log("href: "+ value[1]); - //Firebug.Console.log("line: " + value[2]); - } - //else - // Firebug.Console.logFormatted([match[2]]); - } - } - } - /**/ - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - /* - else if (FBL.isOpera) - { - // Opera - var reOperaStackItem = /^\s\s(?:\.\.\.\s\s)?Line\s(\d+)\sof\s(.+)$/; - var reOperaStackItemValue = /^linked\sscript\s(.+)$/; - - for (var i=0, length=items.length; i<length; i+=2) - { - var item = items[i]; - - var match = item.match(reOperaStackItem); - - if (match) - { - //Firebug.Console.log(match[1]); - - var value = match[2].match(reOperaStackItemValue); - - if (value) - { - //Firebug.Console.log(value[1]); - } - //else - // Firebug.Console.log(match[2]); - - //Firebug.Console.log("--------------------------"); - } - } - } - /**/ - } - - //console.log(stack); - //console.dir(frames); - Firebug.Console.log({frames: frames}, context, "stackTrace", FirebugReps.StackTrace); - - traceRecursion--; - }; - - this.trace_ok = function() - { - var getFuncName = function getFuncName (f) - { - if (f.getName instanceof Function) - return f.getName(); - if (f.name) // in FireFox, Function objects have a name property... - return f.name; - - var name = f.toString().match(/function\s*([_$\w\d]*)/)[1]; - return name || "anonymous"; - }; - - var wasVisited = function(fn) - { - for (var i=0, l=frames.length; i<l; i++) - { - if (frames[i].fn == fn) - return true; - } - - return false; - }; - - var frames = []; - - for (var fn = arguments.callee.caller; fn; fn = fn.caller) - { - if (wasVisited(fn)) break; - - var args = []; - - for (var i = 0, l = fn.arguments.length; i < l; ++i) - { - args.push({value: fn.arguments[i]}); - } - - frames.push({fn: fn, name: getFuncName(fn), args: args}); - } - - Firebug.Console.log({frames: frames}, context, "stackTrace", FirebugReps.StackTrace); - }; - - this.clear = function() - { - Firebug.Console.clear(context); - }; - - this.time = function(name, reset) - { - if (!name) - return; - - var time = new Date().getTime(); - - if (!this.timeCounters) - this.timeCounters = {}; - - var key = "KEY"+name.toString(); - - if (!reset && this.timeCounters[key]) - return; - - this.timeCounters[key] = time; - }; - - this.timeEnd = function(name) - { - var time = new Date().getTime(); - - if (!this.timeCounters) - return; - - var key = "KEY"+name.toString(); - - var timeCounter = this.timeCounters[key]; - if (timeCounter) - { - var diff = time - timeCounter; - var label = name + ": " + diff + "ms"; - - this.info(label); - - delete this.timeCounters[key]; - } - return diff; - }; - - // These functions are over-ridden by commandLine - this.evaluated = function(result, context) - { - if (FBTrace.DBG_CONSOLE) - FBTrace.sysout("consoleInjector.FirebugConsoleHandler evalutated default called", result); - - Firebug.Console.log(result, context); - }; - this.evaluateError = function(result, context) - { - Firebug.Console.log(result, context, "errorMessage"); - }; - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - function logFormatted(args, className, linkToSource, noThrottle) - { - var sourceLink = linkToSource ? getStackLink() : null; - return Firebug.Console.logFormatted(args, context, className, noThrottle, sourceLink); - } - - function logAssert(category, args) - { - Firebug.Errors.increaseCount(context); - - if (!args || !args.length || args.length == 0) - var msg = [FBL.$STR("Assertion")]; - else - var msg = args[0]; - - if (Firebug.errorStackTrace) - { - var trace = Firebug.errorStackTrace; - delete Firebug.errorStackTrace; - if (FBTrace.DBG_CONSOLE) - FBTrace.sysout("logAssert trace from errorStackTrace", trace); - } - else if (msg.stack) - { - var trace = parseToStackTrace(msg.stack); - if (FBTrace.DBG_CONSOLE) - FBTrace.sysout("logAssert trace from msg.stack", trace); - } - else - { - var trace = getJSDUserStack(); - if (FBTrace.DBG_CONSOLE) - FBTrace.sysout("logAssert trace from getJSDUserStack", trace); - } - - var errorObject = new FBL.ErrorMessage(msg, (msg.fileName?msg.fileName:win.location), (msg.lineNumber?msg.lineNumber:0), "", category, context, trace); - - - if (trace && trace.frames && trace.frames[0]) - errorObject.correctWithStackTrace(trace); - - errorObject.resetSource(); - - var objects = errorObject; - if (args.length > 1) - { - objects = [errorObject]; - for (var i = 1; i < args.length; i++) - objects.push(args[i]); - } - - var row = Firebug.Console.log(objects, context, "errorMessage", null, true); // noThrottle - row.scrollIntoView(); - } - - function getComponentsStackDump() - { - // Starting with our stack, walk back to the user-level code - var frame = Components.stack; - var userURL = win.location.href.toString(); - - if (FBTrace.DBG_CONSOLE) - FBTrace.sysout("consoleInjector.getComponentsStackDump initial stack for userURL "+userURL, frame); - - // Drop frames until we get into user code. - while (frame && FBL.isSystemURL(frame.filename) ) - frame = frame.caller; - - // Drop two more frames, the injected console function and firebugAppendConsole() - if (frame) - frame = frame.caller; - if (frame) - frame = frame.caller; - - if (FBTrace.DBG_CONSOLE) - FBTrace.sysout("consoleInjector.getComponentsStackDump final stack for userURL "+userURL, frame); - - return frame; - } - - function getStackLink() - { - // TODO: xxxpedro console2 - return; - //return FBL.getFrameSourceLink(getComponentsStackDump()); - } - - function getJSDUserStack() - { - var trace = FBL.getCurrentStackTrace(context); - - var frames = trace ? trace.frames : null; - if (frames && (frames.length > 0) ) - { - var oldest = frames.length - 1; // 6 - 1 = 5 - for (var i = 0; i < frames.length; i++) - { - if (frames[oldest - i].href.indexOf("chrome:") == 0) break; - var fn = frames[oldest - i].fn + ""; - if (fn && (fn.indexOf("_firebugEvalEvent") != -1) ) break; // command line - } - FBTrace.sysout("consoleInjector getJSDUserStack: "+frames.length+" oldest: "+oldest+" i: "+i+" i - oldest + 2: "+(i - oldest + 2), trace); - trace.frames = trace.frames.slice(2 - i); // take the oldest frames, leave 2 behind they are injection code - - return trace; - } - else - return "Firebug failed to get stack trace with any frames"; - } -}; - -// ************************************************************************************************ -// Register console namespace - -FBL.registerConsole = function() -{ - var win = Env.browser.window; - Firebug.Console.injector.install(win); -}; - -registerConsole(); - -}}); - - -/* See license.txt for terms of usage */ - -FBL.ns(function() { with (FBL) { -// ************************************************************************************************ - - -// ************************************************************************************************ -// Globals - -var commandPrefix = ">>>"; -var reOpenBracket = /[\[\(\{]/; -var reCloseBracket = /[\]\)\}]/; - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - -var commandHistory = []; -var commandPointer = -1; - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - -var isAutoCompleting = null; -var autoCompletePrefix = null; -var autoCompleteExpr = null; -var autoCompleteBuffer = null; -var autoCompletePosition = null; - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - -var fbCommandLine = null; -var fbLargeCommandLine = null; -var fbLargeCommandButtons = null; - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - -var _completion = -{ - window: - [ - "console" - ], - - document: - [ - "getElementById", - "getElementsByTagName" - ] -}; - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - -var _stack = function(command) -{ - Firebug.context.persistedState.commandHistory.push(command); - Firebug.context.persistedState.commandPointer = - Firebug.context.persistedState.commandHistory.length; -}; - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - -// ************************************************************************************************ -// CommandLine - -Firebug.CommandLine = extend(Firebug.Module, -{ - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - element: null, - isMultiLine: false, - isActive: false, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - initialize: function(doc) - { - this.clear = bind(this.clear, this); - this.enter = bind(this.enter, this); - - this.onError = bind(this.onError, this); - this.onKeyDown = bind(this.onKeyDown, this); - this.onMultiLineKeyDown = bind(this.onMultiLineKeyDown, this); - - addEvent(Firebug.browser.window, "error", this.onError); - addEvent(Firebug.chrome.window, "error", this.onError); - }, - - shutdown: function(doc) - { - this.deactivate(); - - removeEvent(Firebug.browser.window, "error", this.onError); - removeEvent(Firebug.chrome.window, "error", this.onError); - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - activate: function(multiLine, hideToggleIcon, onRun) - { - defineCommandLineAPI(); - - Firebug.context.persistedState.commandHistory = - Firebug.context.persistedState.commandHistory || []; - - Firebug.context.persistedState.commandPointer = - Firebug.context.persistedState.commandPointer || -1; - - if (this.isActive) - { - if (this.isMultiLine == multiLine) return; - - this.deactivate(); - } - - fbCommandLine = $("fbCommandLine"); - fbLargeCommandLine = $("fbLargeCommandLine"); - fbLargeCommandButtons = $("fbLargeCommandButtons"); - - if (multiLine) - { - onRun = onRun || this.enter; - - this.isMultiLine = true; - - this.element = fbLargeCommandLine; - - addEvent(this.element, "keydown", this.onMultiLineKeyDown); - - addEvent($("fbSmallCommandLineIcon"), "click", Firebug.chrome.hideLargeCommandLine); - - this.runButton = new Button({ - element: $("fbCommand_btRun"), - owner: Firebug.CommandLine, - onClick: onRun - }); - - this.runButton.initialize(); - - this.clearButton = new Button({ - element: $("fbCommand_btClear"), - owner: Firebug.CommandLine, - onClick: this.clear - }); - - this.clearButton.initialize(); - } - else - { - this.isMultiLine = false; - this.element = fbCommandLine; - - if (!fbCommandLine) - return; - - addEvent(this.element, "keydown", this.onKeyDown); - } - - //Firebug.Console.log("activate", this.element); - - if (isOpera) - fixOperaTabKey(this.element); - - if(this.lastValue) - this.element.value = this.lastValue; - - this.isActive = true; - }, - - deactivate: function() - { - if (!this.isActive) return; - - //Firebug.Console.log("deactivate", this.element); - - this.isActive = false; - - this.lastValue = this.element.value; - - if (this.isMultiLine) - { - removeEvent(this.element, "keydown", this.onMultiLineKeyDown); - - removeEvent($("fbSmallCommandLineIcon"), "click", Firebug.chrome.hideLargeCommandLine); - - this.runButton.destroy(); - this.clearButton.destroy(); - } - else - { - removeEvent(this.element, "keydown", this.onKeyDown); - } - - this.element = null; - delete this.element; - - fbCommandLine = null; - fbLargeCommandLine = null; - fbLargeCommandButtons = null; - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - focus: function() - { - this.element.focus(); - }, - - blur: function() - { - this.element.blur(); - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - clear: function() - { - this.element.value = ""; - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - evaluate: function(expr) - { - // TODO: need to register the API in console.firebug.commandLineAPI - var api = "Firebug.CommandLine.API"; - - var result = Firebug.context.evaluate(expr, "window", api, Firebug.Console.error); - - return result; - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - enter: function() - { - var command = this.element.value; - - if (!command) return; - - _stack(command); - - Firebug.Console.log(commandPrefix + " " + stripNewLines(command), - Firebug.browser, "command", FirebugReps.Text); - - var result = this.evaluate(command); - - Firebug.Console.log(result); - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - prevCommand: function() - { - if (Firebug.context.persistedState.commandPointer > 0 && - Firebug.context.persistedState.commandHistory.length > 0) - { - this.element.value = Firebug.context.persistedState.commandHistory - [--Firebug.context.persistedState.commandPointer]; - } - }, - - nextCommand: function() - { - var element = this.element; - - var limit = Firebug.context.persistedState.commandHistory.length -1; - var i = Firebug.context.persistedState.commandPointer; - - if (i < limit) - element.value = Firebug.context.persistedState.commandHistory - [++Firebug.context.persistedState.commandPointer]; - - else if (i == limit) - { - ++Firebug.context.persistedState.commandPointer; - element.value = ""; - } - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - autocomplete: function(reverse) - { - var element = this.element; - - var command = element.value; - var offset = getExpressionOffset(command); - - var valBegin = offset ? command.substr(0, offset) : ""; - var val = command.substr(offset); - - var buffer, obj, objName, commandBegin, result, prefix; - - // if it is the beginning of the completion - if(!isAutoCompleting) - { - - // group1 - command begin - // group2 - base object - // group3 - property prefix - var reObj = /(.*[^_$\w\d\.])?((?:[_$\w][_$\w\d]*\.)*)([_$\w][_$\w\d]*)?$/; - var r = reObj.exec(val); - - // parse command - if (r[1] || r[2] || r[3]) - { - commandBegin = r[1] || ""; - objName = r[2] || ""; - prefix = r[3] || ""; - } - else if (val == "") - { - commandBegin = objName = prefix = ""; - } else - return; - - isAutoCompleting = true; - - // find base object - if(objName == "") - obj = window; - - else - { - objName = objName.replace(/\.$/, ""); - - var n = objName.split("."); - var target = window, o; - - for (var i=0, ni; ni = n[i]; i++) - { - if (o = target[ni]) - target = o; - - else - { - target = null; - break; - } - } - obj = target; - } - - // map base object - if(obj) - { - autoCompletePrefix = prefix; - autoCompleteExpr = valBegin + commandBegin + (objName ? objName + "." : ""); - autoCompletePosition = -1; - - buffer = autoCompleteBuffer = isIE ? - _completion[objName || "window"] || [] : []; - - for(var p in obj) - buffer.push(p); - } - - // if it is the continuation of the last completion - } else - buffer = autoCompleteBuffer; - - if (buffer) - { - prefix = autoCompletePrefix; - - var diff = reverse ? -1 : 1; - - for(var i=autoCompletePosition+diff, l=buffer.length, bi; i>=0 && i<l; i+=diff) - { - bi = buffer[i]; - - if (bi.indexOf(prefix) == 0) - { - autoCompletePosition = i; - result = bi; - break; - } - } - } - - if (result) - element.value = autoCompleteExpr + result; - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - setMultiLine: function(multiLine) - { - if (multiLine == this.isMultiLine) return; - - this.activate(multiLine); - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - onError: function(msg, href, lineNo) - { - href = href || ""; - - var lastSlash = href.lastIndexOf("/"); - var fileName = lastSlash == -1 ? href : href.substr(lastSlash+1); - var html = [ - '<span class="errorMessage">', msg, '</span>', - '<div class="objectBox-sourceLink">', fileName, ' (line ', lineNo, ')</div>' - ]; - - // TODO: xxxpedro ajust to Console2 - //Firebug.Console.writeRow(html, "error"); - }, - - onKeyDown: function(e) - { - e = e || event; - - var code = e.keyCode; - - /*tab, shift, control, alt*/ - if (code != 9 && code != 16 && code != 17 && code != 18) - { - isAutoCompleting = false; - } - - if (code == 13 /* enter */) - { - this.enter(); - this.clear(); - } - else if (code == 27 /* ESC */) - { - setTimeout(this.clear, 0); - } - else if (code == 38 /* up */) - { - this.prevCommand(); - } - else if (code == 40 /* down */) - { - this.nextCommand(); - } - else if (code == 9 /* tab */) - { - this.autocomplete(e.shiftKey); - } - else - return; - - cancelEvent(e, true); - return false; - }, - - onMultiLineKeyDown: function(e) - { - e = e || event; - - var code = e.keyCode; - - if (code == 13 /* enter */ && e.ctrlKey) - { - this.enter(); - } - } -}); - -Firebug.registerModule(Firebug.CommandLine); - - -// ************************************************************************************************ -// - -function getExpressionOffset(command) -{ - // XXXjoe This is kind of a poor-man's JavaScript parser - trying - // to find the start of the expression that the cursor is inside. - // Not 100% fool proof, but hey... - - var bracketCount = 0; - - var start = command.length-1; - for (; start >= 0; --start) - { - var c = command[start]; - if ((c == "," || c == ";" || c == " ") && !bracketCount) - break; - if (reOpenBracket.test(c)) - { - if (bracketCount) - --bracketCount; - else - break; - } - else if (reCloseBracket.test(c)) - ++bracketCount; - } - - return start + 1; -} - -// ************************************************************************************************ -// CommandLine API - -var CommandLineAPI = -{ - $: function(id) - { - return Firebug.browser.document.getElementById(id); - }, - - $$: function(selector, context) - { - context = context || Firebug.browser.document; - return Firebug.Selector ? - Firebug.Selector(selector, context) : - Firebug.Console.error("Firebug.Selector module not loaded."); - }, - - $0: null, - - $1: null, - - dir: function(o) - { - Firebug.Console.log(o, Firebug.context, "dir", Firebug.DOMPanel.DirTable); - }, - - dirxml: function(o) - { - ///if (o instanceof Window) - if (instanceOf(o, "Window")) - o = o.document.documentElement; - ///else if (o instanceof Document) - else if (instanceOf(o, "Document")) - o = o.documentElement; - - Firebug.Console.log(o, Firebug.context, "dirxml", Firebug.HTMLPanel.SoloElement); - } -}; - -// ************************************************************************************************ - -var defineCommandLineAPI = function defineCommandLineAPI() -{ - Firebug.CommandLine.API = {}; - for (var m in CommandLineAPI) - if (!Env.browser.window[m]) - Firebug.CommandLine.API[m] = CommandLineAPI[m]; - - var stack = FirebugChrome.htmlSelectionStack; - if (stack) - { - Firebug.CommandLine.API.$0 = stack[0]; - Firebug.CommandLine.API.$1 = stack[1]; - } -}; - -// ************************************************************************************************ -}}); - -/* See license.txt for terms of usage */ - -FBL.ns(function() { with (FBL) { -// ************************************************************************************************ - -// ************************************************************************************************ -// Globals - -var ElementCache = Firebug.Lite.Cache.Element; -var cacheID = Firebug.Lite.Cache.ID; - -var ignoreHTMLProps = -{ - // ignores the attributes injected by Sizzle, otherwise it will - // be visible on IE (when enumerating element.attributes) - sizcache: 1, - sizset: 1 -}; - -if (Firebug.ignoreFirebugElements) - // ignores also the cache property injected by firebug - ignoreHTMLProps[cacheID] = 1; - - -// ************************************************************************************************ -// HTML Module - -Firebug.HTML = extend(Firebug.Module, -{ - appendTreeNode: function(nodeArray, html) - { - var reTrim = /^\s+|\s+$/g; - - if (!nodeArray.length) nodeArray = [nodeArray]; - - for (var n=0, node; node=nodeArray[n]; n++) - { - if (node.nodeType == 1) - { - if (Firebug.ignoreFirebugElements && node.firebugIgnore) continue; - - var uid = ElementCache(node); - var child = node.childNodes; - var childLength = child.length; - - var nodeName = node.nodeName.toLowerCase(); - - var nodeVisible = isVisible(node); - - var hasSingleTextChild = childLength == 1 && node.firstChild.nodeType == 3 && - nodeName != "script" && nodeName != "style"; - - var nodeControl = !hasSingleTextChild && childLength > 0 ? - ('<div class="nodeControl"></div>') : ''; - - // FIXME xxxpedro remove this - //var isIE = false; - - if(isIE && nodeControl) - html.push(nodeControl); - - if (typeof uid != 'undefined') - html.push( - '<div class="objectBox-element" ', - 'id="', uid, - '">', - !isIE && nodeControl ? nodeControl: "", - '<span ', - cacheID, - '="', uid, - '" class="nodeBox', - nodeVisible ? "" : " nodeHidden", - '"><<span class="nodeTag">', nodeName, '</span>' - ); - else - html.push( - '<div class="objectBox-element"><span class="nodeBox', - nodeVisible ? "" : " nodeHidden", - '"><<span class="nodeTag">', - nodeName, '</span>' - ); - - for (var i = 0; i < node.attributes.length; ++i) - { - var attr = node.attributes[i]; - if (!attr.specified || - // Issue 4432: Firebug Lite: HTML is mixed-up with functions - // The problem here is that expando properties added to DOM elements in - // IE < 9 will behave like DOM attributes and so they'll show up when - // looking at element.attributes list. - isIE && (browserVersion-0<9) && typeof attr.nodeValue != "string" || - Firebug.ignoreFirebugElements && ignoreHTMLProps.hasOwnProperty(attr.nodeName)) - continue; - - var name = attr.nodeName.toLowerCase(); - var value = name == "style" ? formatStyles(node.style.cssText) : attr.nodeValue; - - html.push(' <span class="nodeName">', name, - '</span>="<span class="nodeValue">', escapeHTML(value), - '</span>"'); - } - - /* - // source code nodes - if (nodeName == 'script' || nodeName == 'style') - { - - if(document.all){ - var src = node.innerHTML+'\n'; - - }else { - var src = '\n'+node.innerHTML+'\n'; - } - - var match = src.match(/\n/g); - var num = match ? match.length : 0; - var s = [], sl = 0; - - for(var c=1; c<num; c++){ - s[sl++] = '<div line="'+c+'">' + c + '</div>'; - } - - html.push('></div><div class="nodeGroup"><div class="nodeChildren"><div class="lineNo">', - s.join(''), - '</div><pre class="nodeCode">', - escapeHTML(src), - '</pre>', - '</div><div class="objectBox-element"></<span class="nodeTag">', - nodeName, - '</span>></div>', - '</div>' - ); - - - }/**/ - - // Just a single text node child - if (hasSingleTextChild) - { - var value = child[0].nodeValue.replace(reTrim, ''); - if(value) - { - html.push( - '><span class="nodeText">', - escapeHTML(value), - '</span></<span class="nodeTag">', - nodeName, - '</span>></span></div>' - ); - } - else - html.push('/></span></div>'); // blank text, print as childless node - - } - else if (childLength > 0) - { - html.push('></span></div>'); - } - else - html.push('/></span></div>'); - - } - else if (node.nodeType == 3) - { - if ( node.parentNode && ( node.parentNode.nodeName.toLowerCase() == "script" || - node.parentNode.nodeName.toLowerCase() == "style" ) ) - { - var value = node.nodeValue.replace(reTrim, ''); - - if(isIE){ - var src = value+'\n'; - - }else { - var src = '\n'+value+'\n'; - } - - var match = src.match(/\n/g); - var num = match ? match.length : 0; - var s = [], sl = 0; - - for(var c=1; c<num; c++){ - s[sl++] = '<div line="'+c+'">' + c + '</div>'; - } - - html.push('<div class="lineNo">', - s.join(''), - '</div><pre class="sourceCode">', - escapeHTML(src), - '</pre>' - ); - - } - else - { - var value = node.nodeValue.replace(reTrim, ''); - if (value) - html.push('<div class="nodeText">', escapeHTML(value),'</div>'); - } - } - } - }, - - appendTreeChildren: function(treeNode) - { - var doc = Firebug.chrome.document; - var uid = treeNode.id; - var parentNode = ElementCache.get(uid); - - if (parentNode.childNodes.length == 0) return; - - var treeNext = treeNode.nextSibling; - var treeParent = treeNode.parentNode; - - // FIXME xxxpedro remove this - //var isIE = false; - var control = isIE ? treeNode.previousSibling : treeNode.firstChild; - control.className = 'nodeControl nodeMaximized'; - - var html = []; - var children = doc.createElement("div"); - children.className = "nodeChildren"; - this.appendTreeNode(parentNode.childNodes, html); - children.innerHTML = html.join(""); - - treeParent.insertBefore(children, treeNext); - - var closeElement = doc.createElement("div"); - closeElement.className = "objectBox-element"; - closeElement.innerHTML = '</<span class="nodeTag">' + - parentNode.nodeName.toLowerCase() + '></span>'; - - treeParent.insertBefore(closeElement, treeNext); - - }, - - removeTreeChildren: function(treeNode) - { - var children = treeNode.nextSibling; - var closeTag = children.nextSibling; - - // FIXME xxxpedro remove this - //var isIE = false; - var control = isIE ? treeNode.previousSibling : treeNode.firstChild; - control.className = 'nodeControl'; - - children.parentNode.removeChild(children); - closeTag.parentNode.removeChild(closeTag); - }, - - isTreeNodeVisible: function(id) - { - return $(id); - }, - - select: function(el) - { - var id = el && ElementCache(el); - if (id) - this.selectTreeNode(id); - }, - - selectTreeNode: function(id) - { - id = ""+id; - var node, stack = []; - while(id && !this.isTreeNodeVisible(id)) - { - stack.push(id); - - var node = ElementCache.get(id).parentNode; - - if (node) - id = ElementCache(node); - else - break; - } - - stack.push(id); - - while(stack.length > 0) - { - id = stack.pop(); - node = $(id); - - if (stack.length > 0 && ElementCache.get(id).childNodes.length > 0) - this.appendTreeChildren(node); - } - - selectElement(node); - - // TODO: xxxpedro - if (fbPanel1) - fbPanel1.scrollTop = Math.round(node.offsetTop - fbPanel1.clientHeight/2); - } - -}); - -Firebug.registerModule(Firebug.HTML); - -// ************************************************************************************************ -// HTML Panel - -function HTMLPanel(){}; - -HTMLPanel.prototype = extend(Firebug.Panel, -{ - name: "HTML", - title: "HTML", - - options: { - hasSidePanel: true, - //hasToolButtons: true, - isPreRendered: !Firebug.flexChromeEnabled /* FIXME xxxpedro chromenew */, - innerHTMLSync: true - }, - - create: function(){ - Firebug.Panel.create.apply(this, arguments); - - this.panelNode.style.padding = "4px 3px 1px 15px"; - this.panelNode.style.minWidth = "500px"; - - if (Env.Options.enablePersistent || Firebug.chrome.type != "popup") - this.createUI(); - - if(this.sidePanelBar && !this.sidePanelBar.selectedPanel) - { - this.sidePanelBar.selectPanel("css"); - } - }, - - destroy: function() - { - selectedElement = null; - fbPanel1 = null; - - selectedSidePanelTS = null; - selectedSidePanelTimer = null; - - Firebug.Panel.destroy.apply(this, arguments); - }, - - createUI: function() - { - var rootNode = Firebug.browser.document.documentElement; - var html = []; - Firebug.HTML.appendTreeNode(rootNode, html); - - this.panelNode.innerHTML = html.join(""); - }, - - initialize: function() - { - Firebug.Panel.initialize.apply(this, arguments); - addEvent(this.panelNode, 'click', Firebug.HTML.onTreeClick); - - fbPanel1 = $("fbPanel1"); - - if(!selectedElement) - { - Firebug.context.persistedState.selectedHTMLElementId = - Firebug.context.persistedState.selectedHTMLElementId && - ElementCache.get(Firebug.context.persistedState.selectedHTMLElementId) ? - Firebug.context.persistedState.selectedHTMLElementId : - ElementCache(Firebug.browser.document.body); - - Firebug.HTML.selectTreeNode(Firebug.context.persistedState.selectedHTMLElementId); - } - - // TODO: xxxpedro - addEvent(fbPanel1, 'mousemove', Firebug.HTML.onListMouseMove); - addEvent($("fbContent"), 'mouseout', Firebug.HTML.onListMouseMove); - addEvent(Firebug.chrome.node, 'mouseout', Firebug.HTML.onListMouseMove); - }, - - shutdown: function() - { - // TODO: xxxpedro - removeEvent(fbPanel1, 'mousemove', Firebug.HTML.onListMouseMove); - removeEvent($("fbContent"), 'mouseout', Firebug.HTML.onListMouseMove); - removeEvent(Firebug.chrome.node, 'mouseout', Firebug.HTML.onListMouseMove); - - removeEvent(this.panelNode, 'click', Firebug.HTML.onTreeClick); - - fbPanel1 = null; - - Firebug.Panel.shutdown.apply(this, arguments); - }, - - reattach: function() - { - // TODO: panel reattach - if(Firebug.context.persistedState.selectedHTMLElementId) - Firebug.HTML.selectTreeNode(Firebug.context.persistedState.selectedHTMLElementId); - }, - - updateSelection: function(object) - { - var id = ElementCache(object); - - if (id) - { - Firebug.HTML.selectTreeNode(id); - } - } -}); - -Firebug.registerPanel(HTMLPanel); - -// ************************************************************************************************ - -var formatStyles = function(styles) -{ - return isIE ? - // IE return CSS property names in upper case, so we need to convert them - styles.replace(/([^\s]+)\s*:/g, function(m,g){return g.toLowerCase()+":";}) : - // other browsers are just fine - styles; -}; - -// ************************************************************************************************ - -var selectedElement = null; -var fbPanel1 = null; - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -var selectedSidePanelTS, selectedSidePanelTimer; - -var selectElement= function selectElement(e) -{ - if (e != selectedElement) - { - if (selectedElement) - selectedElement.className = "objectBox-element"; - - e.className = e.className + " selectedElement"; - - if (FBL.isFirefox) - e.style.MozBorderRadius = "2px"; - - else if (FBL.isSafari) - e.style.WebkitBorderRadius = "2px"; - - e.style.borderRadius = "2px"; - - selectedElement = e; - - Firebug.context.persistedState.selectedHTMLElementId = e.id; - - var target = ElementCache.get(e.id); - var sidePanelBar = Firebug.chrome.getPanel("HTML").sidePanelBar; - var selectedSidePanel = sidePanelBar ? sidePanelBar.selectedPanel : null; - - var stack = FirebugChrome.htmlSelectionStack; - - stack.unshift(target); - - if (stack.length > 2) - stack.pop(); - - var lazySelect = function() - { - selectedSidePanelTS = new Date().getTime(); - - if (selectedSidePanel) - selectedSidePanel.select(target, true); - }; - - if (selectedSidePanelTimer) - { - clearTimeout(selectedSidePanelTimer); - selectedSidePanelTimer = null; - } - - if (new Date().getTime() - selectedSidePanelTS > 100) - setTimeout(lazySelect, 0); - else - selectedSidePanelTimer = setTimeout(lazySelect, 150); - } -}; - - -// ************************************************************************************************ -// *** TODO: REFACTOR ************************************************************************** -// ************************************************************************************************ -Firebug.HTML.onTreeClick = function (e) -{ - e = e || event; - var targ; - - if (e.target) targ = e.target; - else if (e.srcElement) targ = e.srcElement; - if (targ.nodeType == 3) // defeat Safari bug - targ = targ.parentNode; - - - if (targ.className.indexOf('nodeControl') != -1 || targ.className == 'nodeTag') - { - // FIXME xxxpedro remove this - //var isIE = false; - - if(targ.className == 'nodeTag') - { - var control = isIE ? (targ.parentNode.previousSibling || targ) : - (targ.parentNode.previousSibling || targ); - - selectElement(targ.parentNode.parentNode); - - if (control.className.indexOf('nodeControl') == -1) - return; - - } else - control = targ; - - FBL.cancelEvent(e); - - var treeNode = isIE ? control.nextSibling : control.parentNode; - - //FBL.Firebug.Console.log(treeNode); - - if (control.className.indexOf(' nodeMaximized') != -1) { - FBL.Firebug.HTML.removeTreeChildren(treeNode); - } else { - FBL.Firebug.HTML.appendTreeChildren(treeNode); - } - } - else if (targ.className == 'nodeValue' || targ.className == 'nodeName') - { - /* - var input = FBL.Firebug.chrome.document.getElementById('treeInput'); - - input.style.display = "block"; - input.style.left = targ.offsetLeft + 'px'; - input.style.top = FBL.topHeight + targ.offsetTop - FBL.fbPanel1.scrollTop + 'px'; - input.style.width = targ.offsetWidth + 6 + 'px'; - input.value = targ.textContent || targ.innerText; - input.focus(); - /**/ - } -}; - -function onListMouseOut(e) -{ - e = e || event || window; - var targ; - - if (e.target) targ = e.target; - else if (e.srcElement) targ = e.srcElement; - if (targ.nodeType == 3) // defeat Safari bug - targ = targ.parentNode; - - if (hasClass(targ, "fbPanel")) { - FBL.Firebug.Inspector.hideBoxModel(); - hoverElement = null; - } -}; - -var hoverElement = null; -var hoverElementTS = 0; - -Firebug.HTML.onListMouseMove = function onListMouseMove(e) -{ - try - { - e = e || event || window; - var targ; - - if (e.target) targ = e.target; - else if (e.srcElement) targ = e.srcElement; - if (targ.nodeType == 3) // defeat Safari bug - targ = targ.parentNode; - - var found = false; - while (targ && !found) { - if (!/\snodeBox\s|\sobjectBox-selector\s/.test(" " + targ.className + " ")) - targ = targ.parentNode; - else - found = true; - } - - if (!targ) - { - FBL.Firebug.Inspector.hideBoxModel(); - hoverElement = null; - return; - } - - /* - if (typeof targ.attributes[cacheID] == 'undefined') return; - - var uid = targ.attributes[cacheID]; - if (!uid) return; - /**/ - - if (typeof targ.attributes[cacheID] == 'undefined') return; - - var uid = targ.attributes[cacheID]; - if (!uid) return; - - var el = ElementCache.get(uid.value); - - var nodeName = el.nodeName.toLowerCase(); - - if (FBL.isIE && " meta title script link ".indexOf(" "+nodeName+" ") != -1) - return; - - if (!/\snodeBox\s|\sobjectBox-selector\s/.test(" " + targ.className + " ")) return; - - if (el.id == "FirebugUI" || " html head body br script link iframe ".indexOf(" "+nodeName+" ") != -1) { - FBL.Firebug.Inspector.hideBoxModel(); - hoverElement = null; - return; - } - - if ((new Date().getTime() - hoverElementTS > 40) && hoverElement != el) { - hoverElementTS = new Date().getTime(); - hoverElement = el; - FBL.Firebug.Inspector.drawBoxModel(el); - } - } - catch(E) - { - } -}; - - -// ************************************************************************************************ - -Firebug.Reps = { - - appendText: function(object, html) - { - html.push(escapeHTML(objectToString(object))); - }, - - appendNull: function(object, html) - { - html.push('<span class="objectBox-null">', escapeHTML(objectToString(object)), '</span>'); - }, - - appendString: function(object, html) - { - html.push('<span class="objectBox-string">"', escapeHTML(objectToString(object)), - '"</span>'); - }, - - appendInteger: function(object, html) - { - html.push('<span class="objectBox-number">', escapeHTML(objectToString(object)), '</span>'); - }, - - appendFloat: function(object, html) - { - html.push('<span class="objectBox-number">', escapeHTML(objectToString(object)), '</span>'); - }, - - appendFunction: function(object, html) - { - var reName = /function ?(.*?)\(/; - var m = reName.exec(objectToString(object)); - var name = m && m[1] ? m[1] : "function"; - html.push('<span class="objectBox-function">', escapeHTML(name), '()</span>'); - }, - - appendObject: function(object, html) - { - /* - var rep = Firebug.getRep(object); - var outputs = []; - - rep.tag.tag.compile(); - - var str = rep.tag.renderHTML({object: object}, outputs); - html.push(str); - /**/ - - try - { - if (object == undefined) - this.appendNull("undefined", html); - else if (object == null) - this.appendNull("null", html); - else if (typeof object == "string") - this.appendString(object, html); - else if (typeof object == "number") - this.appendInteger(object, html); - else if (typeof object == "boolean") - this.appendInteger(object, html); - else if (typeof object == "function") - this.appendFunction(object, html); - else if (object.nodeType == 1) - this.appendSelector(object, html); - else if (typeof object == "object") - { - if (typeof object.length != "undefined") - this.appendArray(object, html); - else - this.appendObjectFormatted(object, html); - } - else - this.appendText(object, html); - } - catch (exc) - { - } - /**/ - }, - - appendObjectFormatted: function(object, html) - { - var text = objectToString(object); - var reObject = /\[object (.*?)\]/; - - var m = reObject.exec(text); - html.push('<span class="objectBox-object">', m ? m[1] : text, '</span>'); - }, - - appendSelector: function(object, html) - { - var uid = ElementCache(object); - var uidString = uid ? [cacheID, '="', uid, '"'].join("") : ""; - - html.push('<span class="objectBox-selector"', uidString, '>'); - - html.push('<span class="selectorTag">', escapeHTML(object.nodeName.toLowerCase()), '</span>'); - if (object.id) - html.push('<span class="selectorId">#', escapeHTML(object.id), '</span>'); - if (object.className) - html.push('<span class="selectorClass">.', escapeHTML(object.className), '</span>'); - - html.push('</span>'); - }, - - appendNode: function(node, html) - { - if (node.nodeType == 1) - { - var uid = ElementCache(node); - var uidString = uid ? [cacheID, '="', uid, '"'].join("") : ""; - - html.push( - '<div class="objectBox-element"', uidString, '">', - '<span ', cacheID, '="', uid, '" class="nodeBox">', - '<<span class="nodeTag">', node.nodeName.toLowerCase(), '</span>'); - - for (var i = 0; i < node.attributes.length; ++i) - { - var attr = node.attributes[i]; - if (!attr.specified || attr.nodeName == cacheID) - continue; - - var name = attr.nodeName.toLowerCase(); - var value = name == "style" ? node.style.cssText : attr.nodeValue; - - html.push(' <span class="nodeName">', name, - '</span>="<span class="nodeValue">', escapeHTML(value), - '</span>"'); - } - - if (node.firstChild) - { - html.push('></div><div class="nodeChildren">'); - - for (var child = node.firstChild; child; child = child.nextSibling) - this.appendNode(child, html); - - html.push('</div><div class="objectBox-element"></<span class="nodeTag">', - node.nodeName.toLowerCase(), '></span></span></div>'); - } - else - html.push('/></span></div>'); - } - else if (node.nodeType == 3) - { - var value = trim(node.nodeValue); - if (value) - html.push('<div class="nodeText">', escapeHTML(value),'</div>'); - } - }, - - appendArray: function(object, html) - { - html.push('<span class="objectBox-array"><b>[</b> '); - - for (var i = 0, l = object.length, obj; i < l; ++i) - { - this.appendObject(object[i], html); - - if (i < l-1) - html.push(', '); - } - - html.push(' <b>]</b></span>'); - } - -}; - - - -// ************************************************************************************************ -}}); - -/* See license.txt for terms of usage */ - -/* - -Hack: -Firebug.chrome.currentPanel = Firebug.chrome.selectedPanel; -Firebug.showInfoTips = true; -Firebug.InfoTip.initializeBrowser(Firebug.chrome); - -/**/ - -FBL.ns(function() { with (FBL) { - -// ************************************************************************************************ -// Constants - -var maxWidth = 100, maxHeight = 80; -var infoTipMargin = 10; -var infoTipWindowPadding = 25; - -// ************************************************************************************************ - -Firebug.InfoTip = extend(Firebug.Module, -{ - dispatchName: "infoTip", - tags: domplate( - { - infoTipTag: DIV({"class": "infoTip"}), - - colorTag: - DIV({style: "background: $rgbValue; width: 100px; height: 40px"}, " "), - - imgTag: - DIV({"class": "infoTipImageBox infoTipLoading"}, - IMG({"class": "infoTipImage", src: "$urlValue", repeat: "$repeat", - onload: "$onLoadImage"}), - IMG({"class": "infoTipBgImage", collapsed: true, src: "blank.gif"}), - DIV({"class": "infoTipCaption"}) - ), - - onLoadImage: function(event) - { - var img = event.currentTarget || event.srcElement; - ///var bgImg = img.nextSibling; - ///if (!bgImg) - /// return; // Sometimes gets called after element is dead - - ///var caption = bgImg.nextSibling; - var innerBox = img.parentNode; - - /// TODO: xxxpedro infoTip hack - var caption = getElementByClass(innerBox, "infoTipCaption"); - var bgImg = getElementByClass(innerBox, "infoTipBgImage"); - if (!bgImg) - return; // Sometimes gets called after element is dead - - // TODO: xxxpedro infoTip IE and timing issue - // TODO: use offline document to avoid flickering - if (isIE) - removeClass(innerBox, "infoTipLoading"); - - var updateInfoTip = function(){ - - var w = img.naturalWidth || img.width || 10, - h = img.naturalHeight || img.height || 10; - - var repeat = img.getAttribute("repeat"); - - if (repeat == "repeat-x" || (w == 1 && h > 1)) - { - collapse(img, true); - collapse(bgImg, false); - bgImg.style.background = "url(" + img.src + ") repeat-x"; - bgImg.style.width = maxWidth + "px"; - if (h > maxHeight) - bgImg.style.height = maxHeight + "px"; - else - bgImg.style.height = h + "px"; - } - else if (repeat == "repeat-y" || (h == 1 && w > 1)) - { - collapse(img, true); - collapse(bgImg, false); - bgImg.style.background = "url(" + img.src + ") repeat-y"; - bgImg.style.height = maxHeight + "px"; - if (w > maxWidth) - bgImg.style.width = maxWidth + "px"; - else - bgImg.style.width = w + "px"; - } - else if (repeat == "repeat" || (w == 1 && h == 1)) - { - collapse(img, true); - collapse(bgImg, false); - bgImg.style.background = "url(" + img.src + ") repeat"; - bgImg.style.width = maxWidth + "px"; - bgImg.style.height = maxHeight + "px"; - } - else - { - if (w > maxWidth || h > maxHeight) - { - if (w > h) - { - img.style.width = maxWidth + "px"; - img.style.height = Math.round((h / w) * maxWidth) + "px"; - } - else - { - img.style.width = Math.round((w / h) * maxHeight) + "px"; - img.style.height = maxHeight + "px"; - } - } - } - - //caption.innerHTML = $STRF("Dimensions", [w, h]); - caption.innerHTML = $STRF(w + " x " + h); - - - }; - - if (isIE) - setTimeout(updateInfoTip, 0); - else - { - updateInfoTip(); - removeClass(innerBox, "infoTipLoading"); - } - - /// - } - - /* - /// onLoadImage original - onLoadImage: function(event) - { - var img = event.currentTarget; - var bgImg = img.nextSibling; - if (!bgImg) - return; // Sometimes gets called after element is dead - - var caption = bgImg.nextSibling; - var innerBox = img.parentNode; - - var w = img.naturalWidth, h = img.naturalHeight; - var repeat = img.getAttribute("repeat"); - - if (repeat == "repeat-x" || (w == 1 && h > 1)) - { - collapse(img, true); - collapse(bgImg, false); - bgImg.style.background = "url(" + img.src + ") repeat-x"; - bgImg.style.width = maxWidth + "px"; - if (h > maxHeight) - bgImg.style.height = maxHeight + "px"; - else - bgImg.style.height = h + "px"; - } - else if (repeat == "repeat-y" || (h == 1 && w > 1)) - { - collapse(img, true); - collapse(bgImg, false); - bgImg.style.background = "url(" + img.src + ") repeat-y"; - bgImg.style.height = maxHeight + "px"; - if (w > maxWidth) - bgImg.style.width = maxWidth + "px"; - else - bgImg.style.width = w + "px"; - } - else if (repeat == "repeat" || (w == 1 && h == 1)) - { - collapse(img, true); - collapse(bgImg, false); - bgImg.style.background = "url(" + img.src + ") repeat"; - bgImg.style.width = maxWidth + "px"; - bgImg.style.height = maxHeight + "px"; - } - else - { - if (w > maxWidth || h > maxHeight) - { - if (w > h) - { - img.style.width = maxWidth + "px"; - img.style.height = Math.round((h / w) * maxWidth) + "px"; - } - else - { - img.style.width = Math.round((w / h) * maxHeight) + "px"; - img.style.height = maxHeight + "px"; - } - } - } - - caption.innerHTML = $STRF("Dimensions", [w, h]); - - removeClass(innerBox, "infoTipLoading"); - } - /**/ - - }), - - initializeBrowser: function(browser) - { - browser.onInfoTipMouseOut = bind(this.onMouseOut, this, browser); - browser.onInfoTipMouseMove = bind(this.onMouseMove, this, browser); - - ///var doc = browser.contentDocument; - var doc = browser.document; - if (!doc) - return; - - ///doc.addEventListener("mouseover", browser.onInfoTipMouseMove, true); - ///doc.addEventListener("mouseout", browser.onInfoTipMouseOut, true); - ///doc.addEventListener("mousemove", browser.onInfoTipMouseMove, true); - addEvent(doc, "mouseover", browser.onInfoTipMouseMove); - addEvent(doc, "mouseout", browser.onInfoTipMouseOut); - addEvent(doc, "mousemove", browser.onInfoTipMouseMove); - - return browser.infoTip = this.tags.infoTipTag.append({}, getBody(doc)); - }, - - uninitializeBrowser: function(browser) - { - if (browser.infoTip) - { - ///var doc = browser.contentDocument; - var doc = browser.document; - ///doc.removeEventListener("mouseover", browser.onInfoTipMouseMove, true); - ///doc.removeEventListener("mouseout", browser.onInfoTipMouseOut, true); - ///doc.removeEventListener("mousemove", browser.onInfoTipMouseMove, true); - removeEvent(doc, "mouseover", browser.onInfoTipMouseMove); - removeEvent(doc, "mouseout", browser.onInfoTipMouseOut); - removeEvent(doc, "mousemove", browser.onInfoTipMouseMove); - - browser.infoTip.parentNode.removeChild(browser.infoTip); - delete browser.infoTip; - delete browser.onInfoTipMouseMove; - } - }, - - showInfoTip: function(infoTip, panel, target, x, y, rangeParent, rangeOffset) - { - if (!Firebug.showInfoTips) - return; - - var scrollParent = getOverflowParent(target); - var scrollX = x + (scrollParent ? scrollParent.scrollLeft : 0); - - if (panel.showInfoTip(infoTip, target, scrollX, y, rangeParent, rangeOffset)) - { - var htmlElt = infoTip.ownerDocument.documentElement; - var panelWidth = htmlElt.clientWidth; - var panelHeight = htmlElt.clientHeight; - - if (x+infoTip.offsetWidth+infoTipMargin > panelWidth) - { - infoTip.style.left = Math.max(0, panelWidth-(infoTip.offsetWidth+infoTipMargin)) + "px"; - infoTip.style.right = "auto"; - } - else - { - infoTip.style.left = (x+infoTipMargin) + "px"; - infoTip.style.right = "auto"; - } - - if (y+infoTip.offsetHeight+infoTipMargin > panelHeight) - { - infoTip.style.top = Math.max(0, panelHeight-(infoTip.offsetHeight+infoTipMargin)) + "px"; - infoTip.style.bottom = "auto"; - } - else - { - infoTip.style.top = (y+infoTipMargin) + "px"; - infoTip.style.bottom = "auto"; - } - - if (FBTrace.DBG_INFOTIP) - FBTrace.sysout("infotip.showInfoTip; top: " + infoTip.style.top + - ", left: " + infoTip.style.left + ", bottom: " + infoTip.style.bottom + - ", right:" + infoTip.style.right + ", offsetHeight: " + infoTip.offsetHeight + - ", offsetWidth: " + infoTip.offsetWidth + - ", x: " + x + ", panelWidth: " + panelWidth + - ", y: " + y + ", panelHeight: " + panelHeight); - - infoTip.setAttribute("active", "true"); - } - else - this.hideInfoTip(infoTip); - }, - - hideInfoTip: function(infoTip) - { - if (infoTip) - infoTip.removeAttribute("active"); - }, - - onMouseOut: function(event, browser) - { - if (!event.relatedTarget) - this.hideInfoTip(browser.infoTip); - }, - - onMouseMove: function(event, browser) - { - // Ignore if the mouse is moving over the existing info tip. - if (getAncestorByClass(event.target, "infoTip")) - return; - - if (browser.currentPanel) - { - var x = event.clientX, y = event.clientY, target = event.target || event.srcElement; - this.showInfoTip(browser.infoTip, browser.currentPanel, target, x, y, event.rangeParent, event.rangeOffset); - } - else - this.hideInfoTip(browser.infoTip); - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - populateColorInfoTip: function(infoTip, color) - { - this.tags.colorTag.replace({rgbValue: color}, infoTip); - return true; - }, - - populateImageInfoTip: function(infoTip, url, repeat) - { - if (!repeat) - repeat = "no-repeat"; - - this.tags.imgTag.replace({urlValue: url, repeat: repeat}, infoTip); - - return true; - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // extends Module - - disable: function() - { - // XXXjoe For each browser, call uninitializeBrowser - }, - - showPanel: function(browser, panel) - { - if (panel) - { - var infoTip = panel.panelBrowser.infoTip; - if (!infoTip) - infoTip = this.initializeBrowser(panel.panelBrowser); - this.hideInfoTip(infoTip); - } - - }, - - showSidePanel: function(browser, panel) - { - this.showPanel(browser, panel); - } -}); - -// ************************************************************************************************ - -Firebug.registerModule(Firebug.InfoTip); - -// ************************************************************************************************ - -}}); - - -/* See license.txt for terms of usage */ - -FBL.ns(function() { with (FBL) { -// ************************************************************************************************ - -var CssParser = null; - -// ************************************************************************************************ - -// Simple CSS stylesheet parser from: -// https://github.com/sergeche/webkit-css - -/** - * Simple CSS stylesheet parser that remembers rule's lines in file - * @author Sergey Chikuyonok (serge.che@gmail.com) - * @link http://chikuyonok.ru - */ -CssParser = (function(){ - /** - * Returns rule object - * @param {Number} start Character index where CSS rule definition starts - * @param {Number} body_start Character index where CSS rule's body starts - * @param {Number} end Character index where CSS rule definition ends - */ - function rule(start, body_start, end) { - return { - start: start || 0, - body_start: body_start || 0, - end: end || 0, - line: -1, - selector: null, - parent: null, - - /** @type {rule[]} */ - children: [], - - addChild: function(start, body_start, end) { - var r = rule(start, body_start, end); - r.parent = this; - this.children.push(r); - return r; - }, - /** - * Returns last child element - * @return {rule} - */ - lastChild: function() { - return this.children[this.children.length - 1]; - } - }; - } - - /** - * Replaces all occurances of substring defined by regexp - * @param {String} str - * @return {RegExp} re - * @return {String} - */ - function removeAll(str, re) { - var m; - while (m = str.match(re)) { - str = str.substring(m[0].length); - } - - return str; - } - - /** - * Trims whitespace from the beginning and the end of string - * @param {String} str - * @return {String} - */ - function trim(str) { - return str.replace(/^\s+|\s+$/g, ''); - } - - /** - * Normalizes CSS rules selector - * @param {String} selector - */ - function normalizeSelector(selector) { - // remove newlines - selector = selector.replace(/[\n\r]/g, ' '); - - selector = trim(selector); - - // remove spaces after commas - selector = selector.replace(/\s*,\s*/g, ','); - - return selector; - } - - /** - * Preprocesses parsed rules: adjusts char indexes, skipping whitespace and - * newlines, saves rule selector, removes comments, etc. - * @param {String} text CSS stylesheet - * @param {rule} rule_node CSS rule node - * @return {rule[]} - */ - function preprocessRules(text, rule_node) { - for (var i = 0, il = rule_node.children.length; i < il; i++) { - var r = rule_node.children[i], - rule_start = text.substring(r.start, r.body_start), - cur_len = rule_start.length; - - // remove newlines for better regexp matching - rule_start = rule_start.replace(/[\n\r]/g, ' '); - - // remove @import rules -// rule_start = removeAll(rule_start, /^\s*@import\s*url\((['"])?.+?\1?\)\;?/g); - - // remove comments - rule_start = removeAll(rule_start, /^\s*\/\*.*?\*\/[\s\t]*/); - - // remove whitespace - rule_start = rule_start.replace(/^[\s\t]+/, ''); - - r.start += (cur_len - rule_start.length); - r.selector = normalizeSelector(rule_start); - } - - return rule_node; - } - - /** - * Saves all lise starting indexes for faster search - * @param {String} text CSS stylesheet - * @return {Number[]} - */ - function saveLineIndexes(text) { - var result = [0], - i = 0, - il = text.length, - ch, ch2; - - while (i < il) { - ch = text.charAt(i); - - if (ch == '\n' || ch == '\r') { - if (ch == '\r' && i < il - 1 && text.charAt(i + 1) == '\n') { - // windows line ending: CRLF. Skip next character - i++; - } - - result.push(i + 1); - } - - i++; - } - - return result; - } - - /** - * Saves line number for parsed rules - * @param {String} text CSS stylesheet - * @param {rule} rule_node Rule node - * @return {rule[]} - */ - function saveLineNumbers(text, rule_node, line_indexes, startLine) { - preprocessRules(text, rule_node); - - startLine = startLine || 0; - - // remember lines start indexes, preserving line ending characters - if (!line_indexes) - var line_indexes = saveLineIndexes(text); - - // now find each rule's line - for (var i = 0, il = rule_node.children.length; i < il; i++) { - var r = rule_node.children[i]; - r.line = line_indexes.length + startLine; - for (var j = 0, jl = line_indexes.length - 1; j < jl; j++) { - var line_ix = line_indexes[j]; - if (r.start >= line_indexes[j] && r.start < line_indexes[j + 1]) { - r.line = j + 1 + startLine; - break; - } - } - - saveLineNumbers(text, r, line_indexes); - } - - return rule_node; - } - - return { - /** - * Parses text as CSS stylesheet, remembring each rule position inside - * text - * @param {String} text CSS stylesheet to parse - */ - read: function(text, startLine) { - var rule_start = [], - rule_body_start = [], - rules = [], - in_comment = 0, - root = rule(), - cur_parent = root, - last_rule = null, - stack = [], - ch, ch2; - - stack.last = function() { - return this[this.length - 1]; - }; - - function hasStr(pos, substr) { - return text.substr(pos, substr.length) == substr; - } - - for (var i = 0, il = text.length; i < il; i++) { - ch = text.charAt(i); - ch2 = i < il - 1 ? text.charAt(i + 1) : ''; - - if (!rule_start.length) - rule_start.push(i); - - switch (ch) { - case '@': - if (!in_comment) { - if (hasStr(i, '@import')) { - var m = text.substr(i).match(/^@import\s*url\((['"])?.+?\1?\)\;?/); - if (m) { - cur_parent.addChild(i, i + 7, i + m[0].length); - i += m[0].length; - rule_start.pop(); - } - break; - } - } - case '/': - // xxxpedro allowing comment inside comment - if (!in_comment && ch2 == '*') { // comment start - in_comment++; - } - break; - - case '*': - if (ch2 == '/') { // comment end - in_comment--; - } - break; - - case '{': - if (!in_comment) { - rule_body_start.push(i); - - cur_parent = cur_parent.addChild(rule_start.pop()); - stack.push(cur_parent); - } - break; - - case '}': - // found the end of the rule - if (!in_comment) { - /** @type {rule} */ - var last_rule = stack.pop(); - rule_start.pop(); - last_rule.body_start = rule_body_start.pop(); - last_rule.end = i; - cur_parent = last_rule.parent || root; - } - break; - } - - } - - return saveLineNumbers(text, root, null, startLine); - }, - - normalizeSelector: normalizeSelector, - - /** - * Find matched rule by selector. - * @param {rule} rule_node Parsed rule node - * @param {String} selector CSS selector - * @param {String} source CSS stylesheet source code - * - * @return {rule[]|null} Array of matched rules, sorted by priority (most - * recent on top) - */ - findBySelector: function(rule_node, selector, source) { - var selector = normalizeSelector(selector), - result = []; - - if (rule_node) { - for (var i = 0, il = rule_node.children.length; i < il; i++) { - /** @type {rule} */ - var r = rule_node.children[i]; - if (r.selector == selector) { - result.push(r); - } - } - } - - if (result.length) { - return result; - } else { - return null; - } - } - }; -})(); - - -// ************************************************************************************************ - -FBL.CssParser = CssParser; - -// ************************************************************************************************ -}}); - -/* See license.txt for terms of usage */ - -FBL.ns(function() { with (FBL) { - -// ************************************************************************************************ -// StyleSheet Parser - -var CssAnalyzer = {}; - -// ************************************************************************************************ -// Locals - -var CSSRuleMap = {}; -var ElementCSSRulesMap = {}; - -var internalStyleSheetIndex = -1; - -var reSelectorTag = /(^|\s)(?:\w+)/g; -var reSelectorClass = /\.[\w\d_-]+/g; -var reSelectorId = /#[\w\d_-]+/g; - -var globalCSSRuleIndex; - -var processAllStyleSheetsTimeout = null; - -var externalStyleSheetURLs = []; - -var ElementCache = Firebug.Lite.Cache.Element; -var StyleSheetCache = Firebug.Lite.Cache.StyleSheet; - -//************************************************************************************************ -// CSS Analyzer templates - -CssAnalyzer.externalStyleSheetWarning = domplate(Firebug.Rep, -{ - tag: - DIV({"class": "warning focusRow", style: "font-weight:normal;", role: 'listitem'}, - SPAN("$object|STR"), - A({"href": "$href", target:"_blank"}, "$link|STR") - ) -}); - -// ************************************************************************************************ -// CSS Analyzer methods - -CssAnalyzer.processAllStyleSheets = function(doc, styleSheetIterator) -{ - try - { - processAllStyleSheets(doc, styleSheetIterator); - } - catch(e) - { - // TODO: FBTrace condition - FBTrace.sysout("CssAnalyzer.processAllStyleSheets fails: ", e); - } -}; - -/** - * - * @param element - * @returns {String[]} Array of IDs of CSS Rules - */ -CssAnalyzer.getElementCSSRules = function(element) -{ - try - { - return getElementCSSRules(element); - } - catch(e) - { - // TODO: FBTrace condition - FBTrace.sysout("CssAnalyzer.getElementCSSRules fails: ", e); - } -}; - -CssAnalyzer.getRuleData = function(ruleId) -{ - return CSSRuleMap[ruleId]; -}; - -// TODO: do we need this? -CssAnalyzer.getRuleLine = function() -{ -}; - -CssAnalyzer.hasExternalStyleSheet = function() -{ - return externalStyleSheetURLs.length > 0; -}; - -CssAnalyzer.parseStyleSheet = function(href) -{ - var sourceData = extractSourceData(href); - var parsedObj = CssParser.read(sourceData.source, sourceData.startLine); - var parsedRules = parsedObj.children; - - // See: Issue 4776: [Firebug lite] CSS Media Types - // - // Ignore all special selectors like @media and @page - for(var i=0; i < parsedRules.length; ) - { - if (parsedRules[i].selector.indexOf("@") != -1) - { - parsedRules.splice(i, 1); - } - else - i++; - } - - return parsedRules; -}; - -//************************************************************************************************ -// Internals -//************************************************************************************************ - -// ************************************************************************************************ -// StyleSheet processing - -var processAllStyleSheets = function(doc, styleSheetIterator) -{ - styleSheetIterator = styleSheetIterator || processStyleSheet; - - globalCSSRuleIndex = -1; - - var styleSheets = doc.styleSheets; - var importedStyleSheets = []; - - if (FBTrace.DBG_CSS) - var start = new Date().getTime(); - - for(var i=0, length=styleSheets.length; i<length; i++) - { - try - { - var styleSheet = styleSheets[i]; - - if ("firebugIgnore" in styleSheet) continue; - - // we must read the length to make sure we have permission to read - // the stylesheet's content. If an error occurs here, we cannot - // read the stylesheet due to access restriction policy - var rules = isIE ? styleSheet.rules : styleSheet.cssRules; - rules.length; - } - catch(e) - { - externalStyleSheetURLs.push(styleSheet.href); - styleSheet.restricted = true; - var ssid = StyleSheetCache(styleSheet); - - /// TODO: xxxpedro external css - //loadExternalStylesheet(doc, styleSheetIterator, styleSheet); - } - - // process internal and external styleSheets - styleSheetIterator(doc, styleSheet); - - var importedStyleSheet, importedRules; - - // process imported styleSheets in IE - if (isIE) - { - var imports = styleSheet.imports; - - for(var j=0, importsLength=imports.length; j<importsLength; j++) - { - try - { - importedStyleSheet = imports[j]; - // we must read the length to make sure we have permission - // to read the imported stylesheet's content. - importedRules = importedStyleSheet.rules; - importedRules.length; - } - catch(e) - { - externalStyleSheetURLs.push(styleSheet.href); - importedStyleSheet.restricted = true; - var ssid = StyleSheetCache(importedStyleSheet); - } - - styleSheetIterator(doc, importedStyleSheet); - } - } - // process imported styleSheets in other browsers - else if (rules) - { - for(var j=0, rulesLength=rules.length; j<rulesLength; j++) - { - try - { - var rule = rules[j]; - - importedStyleSheet = rule.styleSheet; - - if (importedStyleSheet) - { - // we must read the length to make sure we have permission - // to read the imported stylesheet's content. - importedRules = importedStyleSheet.cssRules; - importedRules.length; - } - else - break; - } - catch(e) - { - externalStyleSheetURLs.push(styleSheet.href); - importedStyleSheet.restricted = true; - var ssid = StyleSheetCache(importedStyleSheet); - } - - styleSheetIterator(doc, importedStyleSheet); - } - } - }; - - if (FBTrace.DBG_CSS) - { - FBTrace.sysout("FBL.processAllStyleSheets", "all stylesheet rules processed in " + (new Date().getTime() - start) + "ms"); - } -}; - -// ************************************************************************************************ - -var processStyleSheet = function(doc, styleSheet) -{ - if (styleSheet.restricted) - return; - - var rules = isIE ? styleSheet.rules : styleSheet.cssRules; - - var ssid = StyleSheetCache(styleSheet); - - var href = styleSheet.href; - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // CSS Parser - var shouldParseCSS = typeof CssParser != "undefined" && !Firebug.disableResourceFetching; - if (shouldParseCSS) - { - try - { - var parsedRules = CssAnalyzer.parseStyleSheet(href); - } - catch(e) - { - if (FBTrace.DBG_ERRORS) FBTrace.sysout("processStyleSheet FAILS", e.message || e); - shouldParseCSS = false; - } - finally - { - var parsedRulesIndex = 0; - - var dontSupportGroupedRules = isIE && browserVersion < 9; - var group = []; - var groupItem; - } - } - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - for (var i=0, length=rules.length; i<length; i++) - { - // TODO: xxxpedro is there a better way to cache CSS Rules? The problem is that - // we cannot add expando properties in the rule object in IE - var rid = ssid + ":" + i; - var rule = rules[i]; - var selector = rule.selectorText || ""; - var lineNo = null; - - // See: Issue 4776: [Firebug lite] CSS Media Types - // - // Ignore all special selectors like @media and @page - if (!selector || selector.indexOf("@") != -1) - continue; - - if (isIE) - selector = selector.replace(reSelectorTag, function(s){return s.toLowerCase();}); - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // CSS Parser - if (shouldParseCSS) - { - var parsedRule = parsedRules[parsedRulesIndex]; - var parsedSelector = parsedRule.selector; - - if (dontSupportGroupedRules && parsedSelector.indexOf(",") != -1 && group.length == 0) - group = parsedSelector.split(","); - - if (dontSupportGroupedRules && group.length > 0) - { - groupItem = group.shift(); - - if (CssParser.normalizeSelector(selector) == groupItem) - lineNo = parsedRule.line; - - if (group.length == 0) - parsedRulesIndex++; - } - else if (CssParser.normalizeSelector(selector) == parsedRule.selector) - { - lineNo = parsedRule.line; - parsedRulesIndex++; - } - } - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - CSSRuleMap[rid] = - { - styleSheetId: ssid, - styleSheetIndex: i, - order: ++globalCSSRuleIndex, - specificity: - // See: Issue 4777: [Firebug lite] Specificity of CSS Rules - // - // if it is a normal selector then calculate the specificity - selector && selector.indexOf(",") == -1 ? - getCSSRuleSpecificity(selector) : - // See: Issue 3262: [Firebug lite] Specificity of grouped CSS Rules - // - // if it is a grouped selector, do not calculate the specificity - // because the correct value will depend of the matched element. - // The proper specificity value for grouped selectors are calculated - // via getElementCSSRules(element) - 0, - - rule: rule, - lineNo: lineNo, - selector: selector, - cssText: rule.style ? rule.style.cssText : rule.cssText ? rule.cssText : "" - }; - - // TODO: what happens with elements added after this? Need to create a test case. - // Maybe we should place this at getElementCSSRules() but it will make the function - // a lot more expensive. - // - // Maybe add a "refresh" button? - var elements = Firebug.Selector(selector, doc); - - for (var j=0, elementsLength=elements.length; j<elementsLength; j++) - { - var element = elements[j]; - var eid = ElementCache(element); - - if (!ElementCSSRulesMap[eid]) - ElementCSSRulesMap[eid] = []; - - ElementCSSRulesMap[eid].push(rid); - } - - //console.log(selector, elements); - } -}; - -// ************************************************************************************************ -// External StyleSheet Loader - -var loadExternalStylesheet = function(doc, styleSheetIterator, styleSheet) -{ - var url = styleSheet.href; - styleSheet.firebugIgnore = true; - - var source = Firebug.Lite.Proxy.load(url); - - // TODO: check for null and error responses - - // remove comments - //var reMultiComment = /(\/\*([^\*]|\*(?!\/))*\*\/)/g; - //source = source.replace(reMultiComment, ""); - - // convert relative addresses to absolute ones - source = source.replace(/url\(([^\)]+)\)/g, function(a,name){ - - var hasDomain = /\w+:\/\/./.test(name); - - if (!hasDomain) - { - name = name.replace(/^(["'])(.+)\1$/, "$2"); - var first = name.charAt(0); - - // relative path, based on root - if (first == "/") - { - // TODO: xxxpedro move to lib or Firebug.Lite.something - // getURLRoot - var m = /^([^:]+:\/{1,3}[^\/]+)/.exec(url); - - return m ? - "url(" + m[1] + name + ")" : - "url(" + name + ")"; - } - // relative path, based on current location - else - { - // TODO: xxxpedro move to lib or Firebug.Lite.something - // getURLPath - var path = url.replace(/[^\/]+\.[\w\d]+(\?.+|#.+)?$/g, ""); - - path = path + name; - - var reBack = /[^\/]+\/\.\.\//; - while(reBack.test(path)) - { - path = path.replace(reBack, ""); - } - - //console.log("url(" + path + ")"); - - return "url(" + path + ")"; - } - } - - // if it is an absolute path, there is nothing to do - return a; - }); - - var oldStyle = styleSheet.ownerNode; - - if (!oldStyle) return; - - if (!oldStyle.parentNode) return; - - var style = createGlobalElement("style"); - style.setAttribute("charset","utf-8"); - style.setAttribute("type", "text/css"); - style.innerHTML = source; - - //debugger; - oldStyle.parentNode.insertBefore(style, oldStyle.nextSibling); - oldStyle.parentNode.removeChild(oldStyle); - - doc.styleSheets[doc.styleSheets.length-1].externalURL = url; - - console.log(url, "call " + externalStyleSheetURLs.length, source); - - externalStyleSheetURLs.pop(); - - if (processAllStyleSheetsTimeout) - { - clearTimeout(processAllStyleSheetsTimeout); - } - - processAllStyleSheetsTimeout = setTimeout(function(){ - console.log("processing"); - FBL.processAllStyleSheets(doc, styleSheetIterator); - processAllStyleSheetsTimeout = null; - },200); - -}; - -//************************************************************************************************ -// getElementCSSRules - -var getElementCSSRules = function(element) -{ - var eid = ElementCache(element); - var rules = ElementCSSRulesMap[eid]; - - if (!rules) return; - - var arr = [element]; - var Selector = Firebug.Selector; - var ruleId, rule; - - // for the case of grouped selectors, we need to calculate the highest - // specificity within the selectors of the group that matches the element, - // so we can sort the rules properly without over estimating the specificity - // of grouped selectors - for (var i = 0, length = rules.length; i < length; i++) - { - ruleId = rules[i]; - rule = CSSRuleMap[ruleId]; - - // check if it is a grouped selector - if (rule.selector.indexOf(",") != -1) - { - var selectors = rule.selector.split(","); - var maxSpecificity = -1; - var sel, spec, mostSpecificSelector; - - // loop over all selectors in the group - for (var j, len = selectors.length; j < len; j++) - { - sel = selectors[j]; - - // find if the selector matches the element - if (Selector.matches(sel, arr).length == 1) - { - spec = getCSSRuleSpecificity(sel); - - // find the most specific selector that macthes the element - if (spec > maxSpecificity) - { - maxSpecificity = spec; - mostSpecificSelector = sel; - } - } - } - - rule.specificity = maxSpecificity; - } - } - - rules.sort(sortElementRules); - //rules.sort(solveRulesTied); - - return rules; -}; - -// ************************************************************************************************ -// Rule Specificity - -var sortElementRules = function(a, b) -{ - var ruleA = CSSRuleMap[a]; - var ruleB = CSSRuleMap[b]; - - var specificityA = ruleA.specificity; - var specificityB = ruleB.specificity; - - if (specificityA > specificityB) - return 1; - - else if (specificityA < specificityB) - return -1; - - else - return ruleA.order > ruleB.order ? 1 : -1; -}; - -var solveRulesTied = function(a, b) -{ - var ruleA = CSSRuleMap[a]; - var ruleB = CSSRuleMap[b]; - - if (ruleA.specificity == ruleB.specificity) - return ruleA.order > ruleB.order ? 1 : -1; - - return null; -}; - -var getCSSRuleSpecificity = function(selector) -{ - var match = selector.match(reSelectorTag); - var tagCount = match ? match.length : 0; - - match = selector.match(reSelectorClass); - var classCount = match ? match.length : 0; - - match = selector.match(reSelectorId); - var idCount = match ? match.length : 0; - - return tagCount + 10*classCount + 100*idCount; -}; - -// ************************************************************************************************ -// StyleSheet data - -var extractSourceData = function(href) -{ - var sourceData = - { - source: null, - startLine: 0 - }; - - if (href) - { - sourceData.source = Firebug.Lite.Proxy.load(href); - } - else - { - // TODO: create extractInternalSourceData(index) - // TODO: pre process the position of the inline styles so this will happen only once - // in case of having multiple inline styles - var index = 0; - var ssIndex = ++internalStyleSheetIndex; - var reStyleTag = /\<\s*style.*\>/gi; - var reEndStyleTag = /\<\/\s*style.*\>/gi; - - var source = Firebug.Lite.Proxy.load(Env.browser.location.href); - source = source.replace(/\n\r|\r\n/g, "\n"); // normalize line breaks - - var startLine = 0; - - do - { - var matchStyleTag = source.match(reStyleTag); - var i0 = source.indexOf(matchStyleTag[0]) + matchStyleTag[0].length; - - for (var i=0; i < i0; i++) - { - if (source.charAt(i) == "\n") - startLine++; - } - - source = source.substr(i0); - - index++; - } - while (index <= ssIndex); - - var matchEndStyleTag = source.match(reEndStyleTag); - var i1 = source.indexOf(matchEndStyleTag[0]); - - var extractedSource = source.substr(0, i1); - - sourceData.source = extractedSource; - sourceData.startLine = startLine; - } - - return sourceData; -}; - -// ************************************************************************************************ -// Registration - -FBL.CssAnalyzer = CssAnalyzer; - -// ************************************************************************************************ -}}); - - -/* See license.txt for terms of usage */ - -// move to FBL -(function() { - -// ************************************************************************************************ -// XPath - -/** - * Gets an XPath for an element which describes its hierarchical location. - */ -this.getElementXPath = function(element) -{ - try - { - if (element && element.id) - return '//*[@id="' + element.id + '"]'; - else - return this.getElementTreeXPath(element); - } - catch(E) - { - // xxxpedro: trying to detect the mysterious error: - // Security error" code: "1000 - //debugger; - } -}; - -this.getElementTreeXPath = function(element) -{ - var paths = []; - - for (; element && element.nodeType == 1; element = element.parentNode) - { - var index = 0; - var nodeName = element.nodeName; - - for (var sibling = element.previousSibling; sibling; sibling = sibling.previousSibling) - { - if (sibling.nodeType != 1) continue; - - if (sibling.nodeName == nodeName) - ++index; - } - - var tagName = element.nodeName.toLowerCase(); - var pathIndex = (index ? "[" + (index+1) + "]" : ""); - paths.splice(0, 0, tagName + pathIndex); - } - - return paths.length ? "/" + paths.join("/") : null; -}; - -this.getElementsByXPath = function(doc, xpath) -{ - var nodes = []; - - try { - var result = doc.evaluate(xpath, doc, null, XPathResult.ANY_TYPE, null); - for (var item = result.iterateNext(); item; item = result.iterateNext()) - nodes.push(item); - } - catch (exc) - { - // Invalid xpath expressions make their way here sometimes. If that happens, - // we still want to return an empty set without an exception. - } - - return nodes; -}; - -this.getRuleMatchingElements = function(rule, doc) -{ - var css = rule.selectorText; - var xpath = this.cssToXPath(css); - return this.getElementsByXPath(doc, xpath); -}; - - -}).call(FBL); - - - - -FBL.ns(function() { with (FBL) { - -// ************************************************************************************************ -// ************************************************************************************************ -// ************************************************************************************************ -// ************************************************************************************************ -// ************************************************************************************************ - -var toCamelCase = function toCamelCase(s) -{ - return s.replace(reSelectorCase, toCamelCaseReplaceFn); -}; - -var toSelectorCase = function toSelectorCase(s) -{ - return s.replace(reCamelCase, "-$1").toLowerCase(); - -}; - -var reCamelCase = /([A-Z])/g; -var reSelectorCase = /\-(.)/g; -var toCamelCaseReplaceFn = function toCamelCaseReplaceFn(m,g) -{ - return g.toUpperCase(); -}; - -// ************************************************************************************************ - -var ElementCache = Firebug.Lite.Cache.Element; -var StyleSheetCache = Firebug.Lite.Cache.StyleSheet; - -// ************************************************************************************************ -// ************************************************************************************************ -// ************************************************************************************************ -// ************************************************************************************************ -// ************************************************************************************************ -// ************************************************************************************************ - - -// ************************************************************************************************ -// Constants - -//const Cc = Components.classes; -//const Ci = Components.interfaces; -//const nsIDOMCSSStyleRule = Ci.nsIDOMCSSStyleRule; -//const nsIInterfaceRequestor = Ci.nsIInterfaceRequestor; -//const nsISelectionDisplay = Ci.nsISelectionDisplay; -//const nsISelectionController = Ci.nsISelectionController; - -// See: http://mxr.mozilla.org/mozilla1.9.2/source/content/events/public/nsIEventStateManager.h#153 -//const STATE_ACTIVE = 0x01; -//const STATE_FOCUS = 0x02; -//const STATE_HOVER = 0x04; - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -Firebug.SourceBoxPanel = Firebug.Panel; - -var reSelectorTag = /(^|\s)(?:\w+)/g; - -var domUtils = null; - -var textContent = isIE ? "innerText" : "textContent"; -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - -var CSSDomplateBase = { - isEditable: function(rule) - { - return !rule.isSystemSheet; - }, - isSelectorEditable: function(rule) - { - return rule.isSelectorEditable && this.isEditable(rule); - } -}; - -var CSSPropTag = domplate(CSSDomplateBase, { - tag: DIV({"class": "cssProp focusRow", $disabledStyle: "$prop.disabled", - $editGroup: "$rule|isEditable", - $cssOverridden: "$prop.overridden", role : "option"}, - A({"class": "cssPropDisable"}, " "), - SPAN({"class": "cssPropName", $editable: "$rule|isEditable"}, "$prop.name"), - SPAN({"class": "cssColon"}, ":"), - SPAN({"class": "cssPropValue", $editable: "$rule|isEditable"}, "$prop.value$prop.important"), - SPAN({"class": "cssSemi"}, ";") - ) -}); - -var CSSRuleTag = - TAG("$rule.tag", {rule: "$rule"}); - -var CSSImportRuleTag = domplate({ - tag: DIV({"class": "cssRule insertInto focusRow importRule", _repObject: "$rule.rule"}, - "@import "", - A({"class": "objectLink", _repObject: "$rule.rule.styleSheet"}, "$rule.rule.href"), - "";" - ) -}); - -var CSSStyleRuleTag = domplate(CSSDomplateBase, { - tag: DIV({"class": "cssRule insertInto", - $cssEditableRule: "$rule|isEditable", - $editGroup: "$rule|isSelectorEditable", - _repObject: "$rule.rule", - "ruleId": "$rule.id", role : 'presentation'}, - DIV({"class": "cssHead focusRow", role : 'listitem'}, - SPAN({"class": "cssSelector", $editable: "$rule|isSelectorEditable"}, "$rule.selector"), " {" - ), - DIV({role : 'group'}, - DIV({"class": "cssPropertyListBox", role : 'listbox'}, - FOR("prop", "$rule.props", - TAG(CSSPropTag.tag, {rule: "$rule", prop: "$prop"}) - ) - ) - ), - DIV({"class": "editable insertBefore", role:"presentation"}, "}") - ) -}); - -var reSplitCSS = /(url\("?[^"\)]+?"?\))|(rgb\(.*?\))|(#[\dA-Fa-f]+)|(-?\d+(\.\d+)?(%|[a-z]{1,2})?)|([^,\s]+)|"(.*?)"/; - -var reURL = /url\("?([^"\)]+)?"?\)/; - -var reRepeat = /no-repeat|repeat-x|repeat-y|repeat/; - -//const sothinkInstalled = !!$("swfcatcherKey_sidebar"); -var sothinkInstalled = false; -var styleGroups = -{ - text: [ - "font-family", - "font-size", - "font-weight", - "font-style", - "color", - "text-transform", - "text-decoration", - "letter-spacing", - "word-spacing", - "line-height", - "text-align", - "vertical-align", - "direction", - "column-count", - "column-gap", - "column-width" - ], - - background: [ - "background-color", - "background-image", - "background-repeat", - "background-position", - "background-attachment", - "opacity" - ], - - box: [ - "width", - "height", - "top", - "right", - "bottom", - "left", - "margin-top", - "margin-right", - "margin-bottom", - "margin-left", - "padding-top", - "padding-right", - "padding-bottom", - "padding-left", - "border-top-width", - "border-right-width", - "border-bottom-width", - "border-left-width", - "border-top-color", - "border-right-color", - "border-bottom-color", - "border-left-color", - "border-top-style", - "border-right-style", - "border-bottom-style", - "border-left-style", - "-moz-border-top-radius", - "-moz-border-right-radius", - "-moz-border-bottom-radius", - "-moz-border-left-radius", - "outline-top-width", - "outline-right-width", - "outline-bottom-width", - "outline-left-width", - "outline-top-color", - "outline-right-color", - "outline-bottom-color", - "outline-left-color", - "outline-top-style", - "outline-right-style", - "outline-bottom-style", - "outline-left-style" - ], - - layout: [ - "position", - "display", - "visibility", - "z-index", - "overflow-x", // http://www.w3.org/TR/2002/WD-css3-box-20021024/#overflow - "overflow-y", - "overflow-clip", - "white-space", - "clip", - "float", - "clear", - "-moz-box-sizing" - ], - - other: [ - "cursor", - "list-style-image", - "list-style-position", - "list-style-type", - "marker-offset", - "user-focus", - "user-select", - "user-modify", - "user-input" - ] -}; - -var styleGroupTitles = -{ - text: "Text", - background: "Background", - box: "Box Model", - layout: "Layout", - other: "Other" -}; - -Firebug.CSSModule = extend(Firebug.Module, -{ - freeEdit: function(styleSheet, value) - { - if (!styleSheet.editStyleSheet) - { - var ownerNode = getStyleSheetOwnerNode(styleSheet); - styleSheet.disabled = true; - - var url = CCSV("@mozilla.org/network/standard-url;1", Components.interfaces.nsIURL); - url.spec = styleSheet.href; - - var editStyleSheet = ownerNode.ownerDocument.createElementNS( - "http://www.w3.org/1999/xhtml", - "style"); - unwrapObject(editStyleSheet).firebugIgnore = true; - editStyleSheet.setAttribute("type", "text/css"); - editStyleSheet.setAttributeNS( - "http://www.w3.org/XML/1998/namespace", - "base", - url.directory); - if (ownerNode.hasAttribute("media")) - { - editStyleSheet.setAttribute("media", ownerNode.getAttribute("media")); - } - - // Insert the edited stylesheet directly after the old one to ensure the styles - // cascade properly. - ownerNode.parentNode.insertBefore(editStyleSheet, ownerNode.nextSibling); - - styleSheet.editStyleSheet = editStyleSheet; - } - - styleSheet.editStyleSheet.innerHTML = value; - if (FBTrace.DBG_CSS) - FBTrace.sysout("css.saveEdit styleSheet.href:"+styleSheet.href+" got innerHTML:"+value+"\n"); - - dispatch(this.fbListeners, "onCSSFreeEdit", [styleSheet, value]); - }, - - insertRule: function(styleSheet, cssText, ruleIndex) - { - if (FBTrace.DBG_CSS) FBTrace.sysout("Insert: " + ruleIndex + " " + cssText); - var insertIndex = styleSheet.insertRule(cssText, ruleIndex); - - dispatch(this.fbListeners, "onCSSInsertRule", [styleSheet, cssText, ruleIndex]); - - return insertIndex; - }, - - deleteRule: function(styleSheet, ruleIndex) - { - if (FBTrace.DBG_CSS) FBTrace.sysout("deleteRule: " + ruleIndex + " " + styleSheet.cssRules.length, styleSheet.cssRules); - dispatch(this.fbListeners, "onCSSDeleteRule", [styleSheet, ruleIndex]); - - styleSheet.deleteRule(ruleIndex); - }, - - setProperty: function(rule, propName, propValue, propPriority) - { - var style = rule.style || rule; - - // Record the original CSS text for the inline case so we can reconstruct at a later - // point for diffing purposes - var baseText = style.cssText; - - // good browsers - if (style.getPropertyValue) - { - var prevValue = style.getPropertyValue(propName); - var prevPriority = style.getPropertyPriority(propName); - - // XXXjoe Gecko bug workaround: Just changing priority doesn't have any effect - // unless we remove the property first - style.removeProperty(propName); - - style.setProperty(propName, propValue, propPriority); - } - // sad browsers - else - { - // TODO: xxxpedro parse CSS rule to find property priority in IE? - //console.log(propName, propValue); - style[toCamelCase(propName)] = propValue; - } - - if (propName) { - dispatch(this.fbListeners, "onCSSSetProperty", [style, propName, propValue, propPriority, prevValue, prevPriority, rule, baseText]); - } - }, - - removeProperty: function(rule, propName, parent) - { - var style = rule.style || rule; - - // Record the original CSS text for the inline case so we can reconstruct at a later - // point for diffing purposes - var baseText = style.cssText; - - if (style.getPropertyValue) - { - - var prevValue = style.getPropertyValue(propName); - var prevPriority = style.getPropertyPriority(propName); - - style.removeProperty(propName); - } - else - { - style[toCamelCase(propName)] = ""; - } - - if (propName) { - dispatch(this.fbListeners, "onCSSRemoveProperty", [style, propName, prevValue, prevPriority, rule, baseText]); - } - }/*, - - cleanupSheets: function(doc, context) - { - // Due to the manner in which the layout engine handles multiple - // references to the same sheet we need to kick it a little bit. - // The injecting a simple stylesheet then removing it will force - // Firefox to regenerate it's CSS hierarchy. - // - // WARN: This behavior was determined anecdotally. - // See http://code.google.com/p/fbug/issues/detail?id=2440 - var style = doc.createElementNS("http://www.w3.org/1999/xhtml", "style"); - style.setAttribute("charset","utf-8"); - unwrapObject(style).firebugIgnore = true; - style.setAttribute("type", "text/css"); - style.innerHTML = "#fbIgnoreStyleDO_NOT_USE {}"; - addStyleSheet(doc, style); - style.parentNode.removeChild(style); - - // https://bugzilla.mozilla.org/show_bug.cgi?id=500365 - // This voodoo touches each style sheet to force some Firefox internal change to allow edits. - var styleSheets = getAllStyleSheets(context); - for(var i = 0; i < styleSheets.length; i++) - { - try - { - var rules = styleSheets[i].cssRules; - if (rules.length > 0) - var touch = rules[0]; - if (FBTrace.DBG_CSS && touch) - FBTrace.sysout("css.show() touch "+typeof(touch)+" in "+(styleSheets[i].href?styleSheets[i].href:context.getName())); - } - catch(e) - { - if (FBTrace.DBG_ERRORS) - FBTrace.sysout("css.show: sheet.cssRules FAILS for "+(styleSheets[i]?styleSheets[i].href:"null sheet")+e, e); - } - } - }, - cleanupSheetHandler: function(event, context) - { - var target = event.target || event.srcElement, - tagName = (target.tagName || "").toLowerCase(); - if (tagName == "link") - { - this.cleanupSheets(target.ownerDocument, context); - } - }, - watchWindow: function(context, win) - { - var cleanupSheets = bind(this.cleanupSheets, this), - cleanupSheetHandler = bind(this.cleanupSheetHandler, this, context), - doc = win.document; - - //doc.addEventListener("DOMAttrModified", cleanupSheetHandler, false); - //doc.addEventListener("DOMNodeInserted", cleanupSheetHandler, false); - }, - loadedContext: function(context) - { - var self = this; - iterateWindows(context.browser.contentWindow, function(subwin) - { - self.cleanupSheets(subwin.document, context); - }); - } - /**/ -}); - -// ************************************************************************************************ - -Firebug.CSSStyleSheetPanel = function() {}; - -Firebug.CSSStyleSheetPanel.prototype = extend(Firebug.SourceBoxPanel, -{ - template: domplate( - { - tag: - DIV({"class": "cssSheet insertInto a11yCSSView"}, - FOR("rule", "$rules", - CSSRuleTag - ), - DIV({"class": "cssSheet editable insertBefore"}, "") - ) - }), - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - refresh: function() - { - if (this.location) - this.updateLocation(this.location); - else if (this.selection) - this.updateSelection(this.selection); - }, - - toggleEditing: function() - { - if (!this.stylesheetEditor) - this.stylesheetEditor = new StyleSheetEditor(this.document); - - if (this.editing) - Firebug.Editor.stopEditing(); - else - { - if (!this.location) - return; - - var styleSheet = this.location.editStyleSheet - ? this.location.editStyleSheet.sheet - : this.location; - - var css = getStyleSheetCSS(styleSheet, this.context); - //var topmost = getTopmostRuleLine(this.panelNode); - - this.stylesheetEditor.styleSheet = this.location; - Firebug.Editor.startEditing(this.panelNode, css, this.stylesheetEditor); - //this.stylesheetEditor.scrollToLine(topmost.line, topmost.offset); - } - }, - - getStylesheetURL: function(rule) - { - if (this.location.href) - return this.location.href; - else - return this.context.window.location.href; - }, - - getRuleByLine: function(styleSheet, line) - { - if (!domUtils) - return null; - - var cssRules = styleSheet.cssRules; - for (var i = 0; i < cssRules.length; ++i) - { - var rule = cssRules[i]; - if (rule instanceof CSSStyleRule) - { - var ruleLine = domUtils.getRuleLine(rule); - if (ruleLine >= line) - return rule; - } - } - }, - - highlightRule: function(rule) - { - var ruleElement = Firebug.getElementByRepObject(this.panelNode.firstChild, rule); - if (ruleElement) - { - scrollIntoCenterView(ruleElement, this.panelNode); - setClassTimed(ruleElement, "jumpHighlight", this.context); - } - }, - - getStyleSheetRules: function(context, styleSheet) - { - var isSystemSheet = isSystemStyleSheet(styleSheet); - - function appendRules(cssRules) - { - for (var i = 0; i < cssRules.length; ++i) - { - var rule = cssRules[i]; - - // TODO: xxxpedro opera instanceof stylesheet remove the following comments when - // the issue with opera and style sheet Classes has been solved. - - //if (rule instanceof CSSStyleRule) - if (instanceOf(rule, "CSSStyleRule")) - { - var props = this.getRuleProperties(context, rule); - //var line = domUtils.getRuleLine(rule); - var line = null; - - var selector = rule.selectorText; - - if (isIE) - { - selector = selector.replace(reSelectorTag, - function(s){return s.toLowerCase();}); - } - - var ruleId = rule.selectorText+"/"+line; - rules.push({tag: CSSStyleRuleTag.tag, rule: rule, id: ruleId, - selector: selector, props: props, - isSystemSheet: isSystemSheet, - isSelectorEditable: true}); - } - //else if (rule instanceof CSSImportRule) - else if (instanceOf(rule, "CSSImportRule")) - rules.push({tag: CSSImportRuleTag.tag, rule: rule}); - //else if (rule instanceof CSSMediaRule) - else if (instanceOf(rule, "CSSMediaRule")) - appendRules.apply(this, [rule.cssRules]); - else - { - if (FBTrace.DBG_ERRORS || FBTrace.DBG_CSS) - FBTrace.sysout("css getStyleSheetRules failed to classify a rule ", rule); - } - } - } - - var rules = []; - appendRules.apply(this, [styleSheet.cssRules || styleSheet.rules]); - return rules; - }, - - parseCSSProps: function(style, inheritMode) - { - var props = []; - - if (Firebug.expandShorthandProps) - { - var count = style.length-1, - index = style.length; - while (index--) - { - var propName = style.item(count - index); - this.addProperty(propName, style.getPropertyValue(propName), !!style.getPropertyPriority(propName), false, inheritMode, props); - } - } - else - { - var lines = style.cssText.match(/(?:[^;\(]*(?:\([^\)]*?\))?[^;\(]*)*;?/g); - var propRE = /\s*([^:\s]*)\s*:\s*(.*?)\s*(! important)?;?$/; - var line,i=0; - // TODO: xxxpedro port to firebug: variable leaked into global namespace - var m; - - while(line=lines[i++]){ - m = propRE.exec(line); - if(!m) - continue; - //var name = m[1], value = m[2], important = !!m[3]; - if (m[2]) - this.addProperty(m[1], m[2], !!m[3], false, inheritMode, props); - }; - } - - return props; - }, - - getRuleProperties: function(context, rule, inheritMode) - { - var props = this.parseCSSProps(rule.style, inheritMode); - - // TODO: xxxpedro port to firebug: variable leaked into global namespace - //var line = domUtils.getRuleLine(rule); - var line; - var ruleId = rule.selectorText+"/"+line; - this.addOldProperties(context, ruleId, inheritMode, props); - sortProperties(props); - - return props; - }, - - addOldProperties: function(context, ruleId, inheritMode, props) - { - if (context.selectorMap && context.selectorMap.hasOwnProperty(ruleId) ) - { - var moreProps = context.selectorMap[ruleId]; - for (var i = 0; i < moreProps.length; ++i) - { - var prop = moreProps[i]; - this.addProperty(prop.name, prop.value, prop.important, true, inheritMode, props); - } - } - }, - - addProperty: function(name, value, important, disabled, inheritMode, props) - { - name = name.toLowerCase(); - - if (inheritMode && !inheritedStyleNames[name]) - return; - - name = this.translateName(name, value); - if (name) - { - value = stripUnits(rgbToHex(value)); - important = important ? " !important" : ""; - - var prop = {name: name, value: value, important: important, disabled: disabled}; - props.push(prop); - } - }, - - translateName: function(name, value) - { - // Don't show these proprietary Mozilla properties - if ((value == "-moz-initial" - && (name == "-moz-background-clip" || name == "-moz-background-origin" - || name == "-moz-background-inline-policy")) - || (value == "physical" - && (name == "margin-left-ltr-source" || name == "margin-left-rtl-source" - || name == "margin-right-ltr-source" || name == "margin-right-rtl-source")) - || (value == "physical" - && (name == "padding-left-ltr-source" || name == "padding-left-rtl-source" - || name == "padding-right-ltr-source" || name == "padding-right-rtl-source"))) - return null; - - // Translate these back to the form the user probably expects - if (name == "margin-left-value") - return "margin-left"; - else if (name == "margin-right-value") - return "margin-right"; - else if (name == "margin-top-value") - return "margin-top"; - else if (name == "margin-bottom-value") - return "margin-bottom"; - else if (name == "padding-left-value") - return "padding-left"; - else if (name == "padding-right-value") - return "padding-right"; - else if (name == "padding-top-value") - return "padding-top"; - else if (name == "padding-bottom-value") - return "padding-bottom"; - // XXXjoe What about border! - else - return name; - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - editElementStyle: function() - { - ///var rulesBox = this.panelNode.getElementsByClassName("cssElementRuleContainer")[0]; - var rulesBox = $$(".cssElementRuleContainer", this.panelNode)[0]; - var styleRuleBox = rulesBox && Firebug.getElementByRepObject(rulesBox, this.selection); - if (!styleRuleBox) - { - var rule = {rule: this.selection, inherited: false, selector: "element.style", props: []}; - if (!rulesBox) - { - // The element did not have any displayed styles. We need to create the whole tree and remove - // the no styles message - styleRuleBox = this.template.cascadedTag.replace({ - rules: [rule], inherited: [], inheritLabel: "Inherited from" // $STR("InheritedFrom") - }, this.panelNode); - - ///styleRuleBox = styleRuleBox.getElementsByClassName("cssElementRuleContainer")[0]; - styleRuleBox = $$(".cssElementRuleContainer", styleRuleBox)[0]; - } - else - styleRuleBox = this.template.ruleTag.insertBefore({rule: rule}, rulesBox); - - ///styleRuleBox = styleRuleBox.getElementsByClassName("insertInto")[0]; - styleRuleBox = $$(".insertInto", styleRuleBox)[0]; - } - - Firebug.Editor.insertRowForObject(styleRuleBox); - }, - - insertPropertyRow: function(row) - { - Firebug.Editor.insertRowForObject(row); - }, - - insertRule: function(row) - { - var location = getAncestorByClass(row, "cssRule"); - if (!location) - { - location = getChildByClass(this.panelNode, "cssSheet"); - Firebug.Editor.insertRowForObject(location); - } - else - { - Firebug.Editor.insertRow(location, "before"); - } - }, - - editPropertyRow: function(row) - { - var propValueBox = getChildByClass(row, "cssPropValue"); - Firebug.Editor.startEditing(propValueBox); - }, - - deletePropertyRow: function(row) - { - var rule = Firebug.getRepObject(row); - var propName = getChildByClass(row, "cssPropName")[textContent]; - Firebug.CSSModule.removeProperty(rule, propName); - - // Remove the property from the selector map, if it was disabled - var ruleId = Firebug.getRepNode(row).getAttribute("ruleId"); - if ( this.context.selectorMap && this.context.selectorMap.hasOwnProperty(ruleId) ) - { - var map = this.context.selectorMap[ruleId]; - for (var i = 0; i < map.length; ++i) - { - if (map[i].name == propName) - { - map.splice(i, 1); - break; - } - } - } - if (this.name == "stylesheet") - dispatch([Firebug.A11yModel], 'onInlineEditorClose', [this, row.firstChild, true]); - row.parentNode.removeChild(row); - - this.markChange(this.name == "stylesheet"); - }, - - disablePropertyRow: function(row) - { - toggleClass(row, "disabledStyle"); - - var rule = Firebug.getRepObject(row); - var propName = getChildByClass(row, "cssPropName")[textContent]; - - if (!this.context.selectorMap) - this.context.selectorMap = {}; - - // XXXjoe Generate unique key for elements too - var ruleId = Firebug.getRepNode(row).getAttribute("ruleId"); - if (!(this.context.selectorMap.hasOwnProperty(ruleId))) - this.context.selectorMap[ruleId] = []; - - var map = this.context.selectorMap[ruleId]; - var propValue = getChildByClass(row, "cssPropValue")[textContent]; - var parsedValue = parsePriority(propValue); - if (hasClass(row, "disabledStyle")) - { - Firebug.CSSModule.removeProperty(rule, propName); - - map.push({"name": propName, "value": parsedValue.value, - "important": parsedValue.priority}); - } - else - { - Firebug.CSSModule.setProperty(rule, propName, parsedValue.value, parsedValue.priority); - - var index = findPropByName(map, propName); - map.splice(index, 1); - } - - this.markChange(this.name == "stylesheet"); - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - onMouseDown: function(event) - { - //console.log("onMouseDown", event.target || event.srcElement, event); - - // xxxpedro adjusting coordinates because the panel isn't a window yet - var offset = event.clientX - this.panelNode.parentNode.offsetLeft; - - // XXjoe Hack to only allow clicking on the checkbox - if (!isLeftClick(event) || offset > 20) - return; - - var target = event.target || event.srcElement; - if (hasClass(target, "textEditor")) - return; - - var row = getAncestorByClass(target, "cssProp"); - if (row && hasClass(row, "editGroup")) - { - this.disablePropertyRow(row); - cancelEvent(event); - } - }, - - onDoubleClick: function(event) - { - //console.log("onDoubleClick", event.target || event.srcElement, event); - - // xxxpedro adjusting coordinates because the panel isn't a window yet - var offset = event.clientX - this.panelNode.parentNode.offsetLeft; - - if (!isLeftClick(event) || offset <= 20) - return; - - var target = event.target || event.srcElement; - - //console.log("ok", target, hasClass(target, "textEditorInner"), !isLeftClick(event), offset <= 20); - - // if the inline editor was clicked, don't insert a new rule - if (hasClass(target, "textEditorInner")) - return; - - var row = getAncestorByClass(target, "cssRule"); - if (row && !getAncestorByClass(target, "cssPropName") - && !getAncestorByClass(target, "cssPropValue")) - { - this.insertPropertyRow(row); - cancelEvent(event); - } - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // extends Panel - - name: "stylesheet", - title: "CSS", - parentPanel: null, - searchable: true, - dependents: ["css", "stylesheet", "dom", "domSide", "layout"], - - options: - { - hasToolButtons: true - }, - - create: function() - { - Firebug.Panel.create.apply(this, arguments); - - this.onMouseDown = bind(this.onMouseDown, this); - this.onDoubleClick = bind(this.onDoubleClick, this); - - if (this.name == "stylesheet") - { - this.onChangeSelect = bind(this.onChangeSelect, this); - - var doc = Firebug.browser.document; - var selectNode = this.selectNode = createElement("select"); - - CssAnalyzer.processAllStyleSheets(doc, function(doc, styleSheet) - { - var key = StyleSheetCache.key(styleSheet); - var fileName = getFileName(styleSheet.href) || getFileName(doc.location.href); - var option = createElement("option", {value: key}); - - option.appendChild(Firebug.chrome.document.createTextNode(fileName)); - selectNode.appendChild(option); - }); - - this.toolButtonsNode.appendChild(selectNode); - } - /**/ - }, - - onChangeSelect: function(event) - { - event = event || window.event; - var target = event.srcElement || event.currentTarget; - var key = target.value; - var styleSheet = StyleSheetCache.get(key); - - this.updateLocation(styleSheet); - }, - - initialize: function() - { - Firebug.Panel.initialize.apply(this, arguments); - - //if (!domUtils) - //{ - // try { - // domUtils = CCSV("@mozilla.org/inspector/dom-utils;1", "inIDOMUtils"); - // } catch (exc) { - // if (FBTrace.DBG_ERRORS) - // FBTrace.sysout("@mozilla.org/inspector/dom-utils;1 FAILED to load: "+exc, exc); - // } - //} - - //TODO: xxxpedro - this.context = Firebug.chrome; // TODO: xxxpedro css2 - this.document = Firebug.chrome.document; // TODO: xxxpedro css2 - - this.initializeNode(); - - if (this.name == "stylesheet") - { - var styleSheets = Firebug.browser.document.styleSheets; - - if (styleSheets.length > 0) - { - addEvent(this.selectNode, "change", this.onChangeSelect); - - this.updateLocation(styleSheets[0]); - } - } - - //Firebug.SourceBoxPanel.initialize.apply(this, arguments); - }, - - shutdown: function() - { - // must destroy the editor when we leave the panel to avoid problems (Issue 2981) - Firebug.Editor.stopEditing(); - - if (this.name == "stylesheet") - { - removeEvent(this.selectNode, "change", this.onChangeSelect); - } - - this.destroyNode(); - - Firebug.Panel.shutdown.apply(this, arguments); - }, - - destroy: function(state) - { - //state.scrollTop = this.panelNode.scrollTop ? this.panelNode.scrollTop : this.lastScrollTop; - - //persistObjects(this, state); - - // xxxpedro we are stopping the editor in the shutdown method already - //Firebug.Editor.stopEditing(); - Firebug.Panel.destroy.apply(this, arguments); - }, - - initializeNode: function(oldPanelNode) - { - addEvent(this.panelNode, "mousedown", this.onMouseDown); - addEvent(this.panelNode, "dblclick", this.onDoubleClick); - //Firebug.SourceBoxPanel.initializeNode.apply(this, arguments); - //dispatch([Firebug.A11yModel], 'onInitializeNode', [this, 'css']); - }, - - destroyNode: function() - { - removeEvent(this.panelNode, "mousedown", this.onMouseDown); - removeEvent(this.panelNode, "dblclick", this.onDoubleClick); - //Firebug.SourceBoxPanel.destroyNode.apply(this, arguments); - //dispatch([Firebug.A11yModel], 'onDestroyNode', [this, 'css']); - }, - - ishow: function(state) - { - Firebug.Inspector.stopInspecting(true); - - this.showToolbarButtons("fbCSSButtons", true); - - if (this.context.loaded && !this.location) // wait for loadedContext to restore the panel - { - restoreObjects(this, state); - - if (!this.location) - this.location = this.getDefaultLocation(); - - if (state && state.scrollTop) - this.panelNode.scrollTop = state.scrollTop; - } - }, - - ihide: function() - { - this.showToolbarButtons("fbCSSButtons", false); - - this.lastScrollTop = this.panelNode.scrollTop; - }, - - supportsObject: function(object) - { - if (object instanceof CSSStyleSheet) - return 1; - else if (object instanceof CSSStyleRule) - return 2; - else if (object instanceof CSSStyleDeclaration) - return 2; - else if (object instanceof SourceLink && object.type == "css" && reCSS.test(object.href)) - return 2; - else - return 0; - }, - - updateLocation: function(styleSheet) - { - if (!styleSheet) - return; - if (styleSheet.editStyleSheet) - styleSheet = styleSheet.editStyleSheet.sheet; - - // if it is a restricted stylesheet, show the warning message and abort the update process - if (styleSheet.restricted) - { - FirebugReps.Warning.tag.replace({object: "AccessRestricted"}, this.panelNode); - - // TODO: xxxpedro remove when there the external resource problem is fixed - CssAnalyzer.externalStyleSheetWarning.tag.append({ - object: "The stylesheet could not be loaded due to access restrictions. ", - link: "more...", - href: "http://getfirebug.com/wiki/index.php/Firebug_Lite_FAQ#I_keep_seeing_.22Access_to_restricted_URI_denied.22" - }, this.panelNode); - - return; - } - - var rules = this.getStyleSheetRules(this.context, styleSheet); - - var result; - if (rules.length) - // FIXME xxxpedro chromenew this is making iPad's Safari to crash - result = this.template.tag.replace({rules: rules}, this.panelNode); - else - result = FirebugReps.Warning.tag.replace({object: "EmptyStyleSheet"}, this.panelNode); - - // TODO: xxxpedro need to fix showToolbarButtons function - //this.showToolbarButtons("fbCSSButtons", !isSystemStyleSheet(this.location)); - - //dispatch([Firebug.A11yModel], 'onCSSRulesAdded', [this, this.panelNode]); - }, - - updateSelection: function(object) - { - this.selection = null; - - if (object instanceof CSSStyleDeclaration) { - object = object.parentRule; - } - - if (object instanceof CSSStyleRule) - { - this.navigate(object.parentStyleSheet); - this.highlightRule(object); - } - else if (object instanceof CSSStyleSheet) - { - this.navigate(object); - } - else if (object instanceof SourceLink) - { - try - { - var sourceLink = object; - - var sourceFile = getSourceFileByHref(sourceLink.href, this.context); - if (sourceFile) - { - clearNode(this.panelNode); // replace rendered stylesheets - this.showSourceFile(sourceFile); - - var lineNo = object.line; - if (lineNo) - this.scrollToLine(lineNo, this.jumpHighlightFactory(lineNo, this.context)); - } - else // XXXjjb we should not be taking this path - { - var stylesheet = getStyleSheetByHref(sourceLink.href, this.context); - if (stylesheet) - this.navigate(stylesheet); - else - { - if (FBTrace.DBG_CSS) - FBTrace.sysout("css.updateSelection no sourceFile for "+sourceLink.href, sourceLink); - } - } - } - catch(exc) { - if (FBTrace.DBG_CSS) - FBTrace.sysout("css.upDateSelection FAILS "+exc, exc); - } - } - }, - - updateOption: function(name, value) - { - if (name == "expandShorthandProps") - this.refresh(); - }, - - getLocationList: function() - { - var styleSheets = getAllStyleSheets(this.context); - return styleSheets; - }, - - getOptionsMenuItems: function() - { - return [ - {label: "Expand Shorthand Properties", type: "checkbox", checked: Firebug.expandShorthandProps, - command: bindFixed(Firebug.togglePref, Firebug, "expandShorthandProps") }, - "-", - {label: "Refresh", command: bind(this.refresh, this) } - ]; - }, - - getContextMenuItems: function(style, target) - { - var items = []; - - if (this.infoTipType == "color") - { - items.push( - {label: "CopyColor", - command: bindFixed(copyToClipboard, FBL, this.infoTipObject) } - ); - } - else if (this.infoTipType == "image") - { - items.push( - {label: "CopyImageLocation", - command: bindFixed(copyToClipboard, FBL, this.infoTipObject) }, - {label: "OpenImageInNewTab", - command: bindFixed(openNewTab, FBL, this.infoTipObject) } - ); - } - - ///if (this.selection instanceof Element) - if (isElement(this.selection)) - { - items.push( - //"-", - {label: "EditStyle", - command: bindFixed(this.editElementStyle, this) } - ); - } - else if (!isSystemStyleSheet(this.selection)) - { - items.push( - //"-", - {label: "NewRule", - command: bindFixed(this.insertRule, this, target) } - ); - } - - var cssRule = getAncestorByClass(target, "cssRule"); - if (cssRule && hasClass(cssRule, "cssEditableRule")) - { - items.push( - "-", - {label: "NewProp", - command: bindFixed(this.insertPropertyRow, this, target) } - ); - - var propRow = getAncestorByClass(target, "cssProp"); - if (propRow) - { - var propName = getChildByClass(propRow, "cssPropName")[textContent]; - var isDisabled = hasClass(propRow, "disabledStyle"); - - items.push( - {label: $STRF("EditProp", [propName]), nol10n: true, - command: bindFixed(this.editPropertyRow, this, propRow) }, - {label: $STRF("DeleteProp", [propName]), nol10n: true, - command: bindFixed(this.deletePropertyRow, this, propRow) }, - {label: $STRF("DisableProp", [propName]), nol10n: true, - type: "checkbox", checked: isDisabled, - command: bindFixed(this.disablePropertyRow, this, propRow) } - ); - } - } - - items.push( - "-", - {label: "Refresh", command: bind(this.refresh, this) } - ); - - return items; - }, - - browseObject: function(object) - { - if (this.infoTipType == "image") - { - openNewTab(this.infoTipObject); - return true; - } - }, - - showInfoTip: function(infoTip, target, x, y) - { - var propValue = getAncestorByClass(target, "cssPropValue"); - if (propValue) - { - var offset = getClientOffset(propValue); - var offsetX = x-offset.x; - - var text = propValue[textContent]; - var charWidth = propValue.offsetWidth/text.length; - var charOffset = Math.floor(offsetX/charWidth); - - var cssValue = parseCSSValue(text, charOffset); - if (cssValue) - { - if (cssValue.value == this.infoTipValue) - return true; - - this.infoTipValue = cssValue.value; - - if (cssValue.type == "rgb" || (!cssValue.type && isColorKeyword(cssValue.value))) - { - this.infoTipType = "color"; - this.infoTipObject = cssValue.value; - - return Firebug.InfoTip.populateColorInfoTip(infoTip, cssValue.value); - } - else if (cssValue.type == "url") - { - ///var propNameNode = target.parentNode.getElementsByClassName("cssPropName").item(0); - var propNameNode = getElementByClass(target.parentNode, "cssPropName"); - if (propNameNode && isImageRule(propNameNode[textContent])) - { - var rule = Firebug.getRepObject(target); - var baseURL = this.getStylesheetURL(rule); - var relURL = parseURLValue(cssValue.value); - var absURL = isDataURL(relURL) ? relURL:absoluteURL(relURL, baseURL); - var repeat = parseRepeatValue(text); - - this.infoTipType = "image"; - this.infoTipObject = absURL; - - return Firebug.InfoTip.populateImageInfoTip(infoTip, absURL, repeat); - } - } - } - } - - delete this.infoTipType; - delete this.infoTipValue; - delete this.infoTipObject; - }, - - getEditor: function(target, value) - { - if (target == this.panelNode - || hasClass(target, "cssSelector") || hasClass(target, "cssRule") - || hasClass(target, "cssSheet")) - { - if (!this.ruleEditor) - this.ruleEditor = new CSSRuleEditor(this.document); - - return this.ruleEditor; - } - else - { - if (!this.editor) - this.editor = new CSSEditor(this.document); - - return this.editor; - } - }, - - getDefaultLocation: function() - { - try - { - var styleSheets = this.context.window.document.styleSheets; - if (styleSheets.length) - { - var sheet = styleSheets[0]; - return (Firebug.filterSystemURLs && isSystemURL(getURLForStyleSheet(sheet))) ? null : sheet; - } - } - catch (exc) - { - if (FBTrace.DBG_LOCATIONS) - FBTrace.sysout("css.getDefaultLocation FAILS "+exc, exc); - } - }, - - getObjectDescription: function(styleSheet) - { - var url = getURLForStyleSheet(styleSheet); - var instance = getInstanceForStyleSheet(styleSheet); - - var baseDescription = splitURLBase(url); - if (instance) { - baseDescription.name = baseDescription.name + " #" + (instance + 1); - } - return baseDescription; - }, - - search: function(text, reverse) - { - var curDoc = this.searchCurrentDoc(!Firebug.searchGlobal, text, reverse); - if (!curDoc && Firebug.searchGlobal) - { - return this.searchOtherDocs(text, reverse); - } - return curDoc; - }, - - searchOtherDocs: function(text, reverse) - { - var scanRE = Firebug.Search.getTestingRegex(text); - function scanDoc(styleSheet) { - // we don't care about reverse here as we are just looking for existence, - // if we do have a result we will handle the reverse logic on display - for (var i = 0; i < styleSheet.cssRules.length; i++) - { - if (scanRE.test(styleSheet.cssRules[i].cssText)) - { - return true; - } - } - } - - if (this.navigateToNextDocument(scanDoc, reverse)) - { - return this.searchCurrentDoc(true, text, reverse); - } - }, - - searchCurrentDoc: function(wrapSearch, text, reverse) - { - if (!text) - { - delete this.currentSearch; - return false; - } - - var row; - if (this.currentSearch && text == this.currentSearch.text) - { - row = this.currentSearch.findNext(wrapSearch, false, reverse, Firebug.Search.isCaseSensitive(text)); - } - else - { - if (this.editing) - { - this.currentSearch = new TextSearch(this.stylesheetEditor.box); - row = this.currentSearch.find(text, reverse, Firebug.Search.isCaseSensitive(text)); - - if (row) - { - var sel = this.document.defaultView.getSelection(); - sel.removeAllRanges(); - sel.addRange(this.currentSearch.range); - scrollSelectionIntoView(this); - return true; - } - else - return false; - } - else - { - function findRow(node) { return node.nodeType == 1 ? node : node.parentNode; } - this.currentSearch = new TextSearch(this.panelNode, findRow); - row = this.currentSearch.find(text, reverse, Firebug.Search.isCaseSensitive(text)); - } - } - - if (row) - { - this.document.defaultView.getSelection().selectAllChildren(row); - scrollIntoCenterView(row, this.panelNode); - dispatch([Firebug.A11yModel], 'onCSSSearchMatchFound', [this, text, row]); - return true; - } - else - { - dispatch([Firebug.A11yModel], 'onCSSSearchMatchFound', [this, text, null]); - return false; - } - }, - - getSearchOptionsMenuItems: function() - { - return [ - Firebug.Search.searchOptionMenu("search.Case_Sensitive", "searchCaseSensitive"), - Firebug.Search.searchOptionMenu("search.Multiple_Files", "searchGlobal") - ]; - } -}); -/**/ -// ************************************************************************************************ - -function CSSElementPanel() {} - -CSSElementPanel.prototype = extend(Firebug.CSSStyleSheetPanel.prototype, -{ - template: domplate( - { - cascadedTag: - DIV({"class": "a11yCSSView", role : 'presentation'}, - DIV({role : 'list', 'aria-label' : $STR('aria.labels.style rules') }, - FOR("rule", "$rules", - TAG("$ruleTag", {rule: "$rule"}) - ) - ), - DIV({role : "list", 'aria-label' :$STR('aria.labels.inherited style rules')}, - FOR("section", "$inherited", - H1({"class": "cssInheritHeader groupHeader focusRow", role : 'listitem' }, - SPAN({"class": "cssInheritLabel"}, "$inheritLabel"), - TAG(FirebugReps.Element.shortTag, {object: "$section.element"}) - ), - DIV({role : 'group'}, - FOR("rule", "$section.rules", - TAG("$ruleTag", {rule: "$rule"}) - ) - ) - ) - ) - ), - - ruleTag: - isIE ? - // IE needs the sourceLink first, otherwise it will be rendered outside the panel - DIV({"class": "cssElementRuleContainer"}, - TAG(FirebugReps.SourceLink.tag, {object: "$rule.sourceLink"}), - TAG(CSSStyleRuleTag.tag, {rule: "$rule"}) - ) - : - // other browsers need the sourceLink last, otherwise it will cause an extra space - // before the rule representation - DIV({"class": "cssElementRuleContainer"}, - TAG(CSSStyleRuleTag.tag, {rule: "$rule"}), - TAG(FirebugReps.SourceLink.tag, {object: "$rule.sourceLink"}) - ) - }), - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - updateCascadeView: function(element) - { - //dispatch([Firebug.A11yModel], 'onBeforeCSSRulesAdded', [this]); - var rules = [], sections = [], usedProps = {}; - this.getInheritedRules(element, sections, usedProps); - this.getElementRules(element, rules, usedProps); - - if (rules.length || sections.length) - { - var inheritLabel = "Inherited from"; // $STR("InheritedFrom"); - var result = this.template.cascadedTag.replace({rules: rules, inherited: sections, - inheritLabel: inheritLabel}, this.panelNode); - //dispatch([Firebug.A11yModel], 'onCSSRulesAdded', [this, result]); - } - else - { - var result = FirebugReps.Warning.tag.replace({object: "EmptyElementCSS"}, this.panelNode); - //dispatch([Firebug.A11yModel], 'onCSSRulesAdded', [this, result]); - } - - // TODO: xxxpedro remove when there the external resource problem is fixed - if (CssAnalyzer.hasExternalStyleSheet()) - CssAnalyzer.externalStyleSheetWarning.tag.append({ - object: "The results here may be inaccurate because some " + - "stylesheets could not be loaded due to access restrictions. ", - link: "more...", - href: "http://getfirebug.com/wiki/index.php/Firebug_Lite_FAQ#I_keep_seeing_.22This_element_has_no_style_rules.22" - }, this.panelNode); - }, - - getStylesheetURL: function(rule) - { - // if the parentStyleSheet.href is null, CSS std says its inline style. - // TODO: xxxpedro IE doesn't have rule.parentStyleSheet so we must fall back to the doc.location - if (rule && rule.parentStyleSheet && rule.parentStyleSheet.href) - return rule.parentStyleSheet.href; - else - return this.selection.ownerDocument.location.href; - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - getInheritedRules: function(element, sections, usedProps) - { - var parent = element.parentNode; - if (parent && parent.nodeType == 1) - { - this.getInheritedRules(parent, sections, usedProps); - - var rules = []; - this.getElementRules(parent, rules, usedProps, true); - - if (rules.length) - sections.splice(0, 0, {element: parent, rules: rules}); - } - }, - - getElementRules: function(element, rules, usedProps, inheritMode) - { - var inspectedRules, displayedRules = {}; - - inspectedRules = CssAnalyzer.getElementCSSRules(element); - - if (inspectedRules) - { - for (var i = 0, length=inspectedRules.length; i < length; ++i) - { - var ruleId = inspectedRules[i]; - var ruleData = CssAnalyzer.getRuleData(ruleId); - var rule = ruleData.rule; - - var ssid = ruleData.styleSheetId; - var parentStyleSheet = StyleSheetCache.get(ssid); - - var href = parentStyleSheet.externalURL ? parentStyleSheet.externalURL : parentStyleSheet.href; // Null means inline - - var instance = null; - //var instance = getInstanceForStyleSheet(rule.parentStyleSheet, element.ownerDocument); - - var isSystemSheet = false; - //var isSystemSheet = isSystemStyleSheet(rule.parentStyleSheet); - - if (!Firebug.showUserAgentCSS && isSystemSheet) // This removes user agent rules - continue; - - if (!href) - href = element.ownerDocument.location.href; // http://code.google.com/p/fbug/issues/detail?id=452 - - var props = this.getRuleProperties(this.context, rule, inheritMode); - if (inheritMode && !props.length) - continue; - - // - //var line = domUtils.getRuleLine(rule); - // TODO: xxxpedro CSS line number - var line = ruleData.lineNo; - - var ruleId = rule.selectorText+"/"+line; - var sourceLink = new SourceLink(href, line, "css", rule, instance); - - this.markOverridenProps(props, usedProps, inheritMode); - - rules.splice(0, 0, {rule: rule, id: ruleId, - selector: ruleData.selector, sourceLink: sourceLink, - props: props, inherited: inheritMode, - isSystemSheet: isSystemSheet}); - } - } - - if (element.style) - this.getStyleProperties(element, rules, usedProps, inheritMode); - - if (FBTrace.DBG_CSS) - FBTrace.sysout("getElementRules "+rules.length+" rules for "+getElementXPath(element), rules); - }, - /* - getElementRules: function(element, rules, usedProps, inheritMode) - { - var inspectedRules, displayedRules = {}; - try - { - inspectedRules = domUtils ? domUtils.getCSSStyleRules(element) : null; - } catch (exc) {} - - if (inspectedRules) - { - for (var i = 0; i < inspectedRules.Count(); ++i) - { - var rule = QI(inspectedRules.GetElementAt(i), nsIDOMCSSStyleRule); - - var href = rule.parentStyleSheet.href; // Null means inline - - var instance = getInstanceForStyleSheet(rule.parentStyleSheet, element.ownerDocument); - - var isSystemSheet = isSystemStyleSheet(rule.parentStyleSheet); - if (!Firebug.showUserAgentCSS && isSystemSheet) // This removes user agent rules - continue; - if (!href) - href = element.ownerDocument.location.href; // http://code.google.com/p/fbug/issues/detail?id=452 - - var props = this.getRuleProperties(this.context, rule, inheritMode); - if (inheritMode && !props.length) - continue; - - var line = domUtils.getRuleLine(rule); - var ruleId = rule.selectorText+"/"+line; - var sourceLink = new SourceLink(href, line, "css", rule, instance); - - this.markOverridenProps(props, usedProps, inheritMode); - - rules.splice(0, 0, {rule: rule, id: ruleId, - selector: rule.selectorText, sourceLink: sourceLink, - props: props, inherited: inheritMode, - isSystemSheet: isSystemSheet}); - } - } - - if (element.style) - this.getStyleProperties(element, rules, usedProps, inheritMode); - - if (FBTrace.DBG_CSS) - FBTrace.sysout("getElementRules "+rules.length+" rules for "+getElementXPath(element), rules); - }, - /**/ - markOverridenProps: function(props, usedProps, inheritMode) - { - for (var i = 0; i < props.length; ++i) - { - var prop = props[i]; - if ( usedProps.hasOwnProperty(prop.name) ) - { - var deadProps = usedProps[prop.name]; // all previous occurrences of this property - for (var j = 0; j < deadProps.length; ++j) - { - var deadProp = deadProps[j]; - if (!deadProp.disabled && !deadProp.wasInherited && deadProp.important && !prop.important) - prop.overridden = true; // new occurrence overridden - else if (!prop.disabled) - deadProp.overridden = true; // previous occurrences overridden - } - } - else - usedProps[prop.name] = []; - - prop.wasInherited = inheritMode ? true : false; - usedProps[prop.name].push(prop); // all occurrences of a property seen so far, by name - } - }, - - getStyleProperties: function(element, rules, usedProps, inheritMode) - { - var props = this.parseCSSProps(element.style, inheritMode); - this.addOldProperties(this.context, getElementXPath(element), inheritMode, props); - - sortProperties(props); - this.markOverridenProps(props, usedProps, inheritMode); - - if (props.length) - rules.splice(0, 0, - {rule: element, id: getElementXPath(element), - selector: "element.style", props: props, inherited: inheritMode}); - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // extends Panel - - name: "css", - title: "Style", - parentPanel: "HTML", - order: 0, - - initialize: function() - { - this.context = Firebug.chrome; // TODO: xxxpedro css2 - this.document = Firebug.chrome.document; // TODO: xxxpedro css2 - - Firebug.CSSStyleSheetPanel.prototype.initialize.apply(this, arguments); - - // TODO: xxxpedro css2 - var selection = ElementCache.get(Firebug.context.persistedState.selectedHTMLElementId); - if (selection) - this.select(selection, true); - - //this.updateCascadeView(document.getElementsByTagName("h1")[0]); - //this.updateCascadeView(document.getElementById("build")); - - /* - this.onStateChange = bindFixed(this.contentStateCheck, this); - this.onHoverChange = bindFixed(this.contentStateCheck, this, STATE_HOVER); - this.onActiveChange = bindFixed(this.contentStateCheck, this, STATE_ACTIVE); - /**/ - }, - - ishow: function(state) - { - }, - - watchWindow: function(win) - { - if (domUtils) - { - // Normally these would not be required, but in order to update after the state is set - // using the options menu we need to monitor these global events as well - var doc = win.document; - ///addEvent(doc, "mouseover", this.onHoverChange); - ///addEvent(doc, "mousedown", this.onActiveChange); - } - }, - unwatchWindow: function(win) - { - var doc = win.document; - ///removeEvent(doc, "mouseover", this.onHoverChange); - ///removeEvent(doc, "mousedown", this.onActiveChange); - - if (isAncestor(this.stateChangeEl, doc)) - { - this.removeStateChangeHandlers(); - } - }, - - supportsObject: function(object) - { - return object instanceof Element ? 1 : 0; - }, - - updateView: function(element) - { - this.updateCascadeView(element); - if (domUtils) - { - this.contentState = safeGetContentState(element); - this.addStateChangeHandlers(element); - } - }, - - updateSelection: function(element) - { - if ( !instanceOf(element , "Element") ) // html supports SourceLink - return; - - if (sothinkInstalled) - { - FirebugReps.Warning.tag.replace({object: "SothinkWarning"}, this.panelNode); - return; - } - - /* - if (!domUtils) - { - FirebugReps.Warning.tag.replace({object: "DOMInspectorWarning"}, this.panelNode); - return; - } - /**/ - - if (!element) - return; - - this.updateView(element); - }, - - updateOption: function(name, value) - { - if (name == "showUserAgentCSS" || name == "expandShorthandProps") - this.refresh(); - }, - - getOptionsMenuItems: function() - { - var ret = [ - {label: "Show User Agent CSS", type: "checkbox", checked: Firebug.showUserAgentCSS, - command: bindFixed(Firebug.togglePref, Firebug, "showUserAgentCSS") }, - {label: "Expand Shorthand Properties", type: "checkbox", checked: Firebug.expandShorthandProps, - command: bindFixed(Firebug.togglePref, Firebug, "expandShorthandProps") } - ]; - if (domUtils && this.selection) - { - var state = safeGetContentState(this.selection); - - ret.push("-"); - ret.push({label: ":active", type: "checkbox", checked: state & STATE_ACTIVE, - command: bindFixed(this.updateContentState, this, STATE_ACTIVE, state & STATE_ACTIVE)}); - ret.push({label: ":hover", type: "checkbox", checked: state & STATE_HOVER, - command: bindFixed(this.updateContentState, this, STATE_HOVER, state & STATE_HOVER)}); - } - return ret; - }, - - updateContentState: function(state, remove) - { - domUtils.setContentState(remove ? this.selection.ownerDocument.documentElement : this.selection, state); - this.refresh(); - }, - - addStateChangeHandlers: function(el) - { - this.removeStateChangeHandlers(); - - /* - addEvent(el, "focus", this.onStateChange); - addEvent(el, "blur", this.onStateChange); - addEvent(el, "mouseup", this.onStateChange); - addEvent(el, "mousedown", this.onStateChange); - addEvent(el, "mouseover", this.onStateChange); - addEvent(el, "mouseout", this.onStateChange); - /**/ - - this.stateChangeEl = el; - }, - - removeStateChangeHandlers: function() - { - var sel = this.stateChangeEl; - if (sel) - { - /* - removeEvent(sel, "focus", this.onStateChange); - removeEvent(sel, "blur", this.onStateChange); - removeEvent(sel, "mouseup", this.onStateChange); - removeEvent(sel, "mousedown", this.onStateChange); - removeEvent(sel, "mouseover", this.onStateChange); - removeEvent(sel, "mouseout", this.onStateChange); - /**/ - } - }, - - contentStateCheck: function(state) - { - if (!state || this.contentState & state) - { - var timeoutRunner = bindFixed(function() - { - var newState = safeGetContentState(this.selection); - if (newState != this.contentState) - { - this.context.invalidatePanels(this.name); - } - }, this); - - // Delay exec until after the event has processed and the state has been updated - setTimeout(timeoutRunner, 0); - } - } -}); - -function safeGetContentState(selection) -{ - try - { - return domUtils.getContentState(selection); - } - catch (e) - { - if (FBTrace.DBG_ERRORS) - FBTrace.sysout("css.safeGetContentState; EXCEPTION", e); - } -} - -// ************************************************************************************************ - -function CSSComputedElementPanel() {} - -CSSComputedElementPanel.prototype = extend(CSSElementPanel.prototype, -{ - template: domplate( - { - computedTag: - DIV({"class": "a11yCSSView", role : "list", "aria-label" : $STR('aria.labels.computed styles')}, - FOR("group", "$groups", - H1({"class": "cssInheritHeader groupHeader focusRow", role : "listitem"}, - SPAN({"class": "cssInheritLabel"}, "$group.title") - ), - TABLE({width: "100%", role : 'group'}, - TBODY({role : 'presentation'}, - FOR("prop", "$group.props", - TR({"class": 'focusRow computedStyleRow', role : 'listitem'}, - TD({"class": "stylePropName", role : 'presentation'}, "$prop.name"), - TD({"class": "stylePropValue", role : 'presentation'}, "$prop.value") - ) - ) - ) - ) - ) - ) - }), - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - updateComputedView: function(element) - { - var win = isIE ? - element.ownerDocument.parentWindow : - element.ownerDocument.defaultView; - - var style = isIE ? - element.currentStyle : - win.getComputedStyle(element, ""); - - var groups = []; - - for (var groupName in styleGroups) - { - // TODO: xxxpedro i18n $STR - //var title = $STR("StyleGroup-" + groupName); - var title = styleGroupTitles[groupName]; - var group = {title: title, props: []}; - groups.push(group); - - var props = styleGroups[groupName]; - for (var i = 0; i < props.length; ++i) - { - var propName = props[i]; - var propValue = style.getPropertyValue ? - style.getPropertyValue(propName) : - ""+style[toCamelCase(propName)]; - - if (propValue === undefined || propValue === null) - continue; - - propValue = stripUnits(rgbToHex(propValue)); - if (propValue) - group.props.push({name: propName, value: propValue}); - } - } - - var result = this.template.computedTag.replace({groups: groups}, this.panelNode); - //dispatch([Firebug.A11yModel], 'onCSSRulesAdded', [this, result]); - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // extends Panel - - name: "computed", - title: "Computed", - parentPanel: "HTML", - order: 1, - - updateView: function(element) - { - this.updateComputedView(element); - }, - - getOptionsMenuItems: function() - { - return [ - {label: "Refresh", command: bind(this.refresh, this) } - ]; - } -}); - -// ************************************************************************************************ -// CSSEditor - -function CSSEditor(doc) -{ - this.initializeInline(doc); -} - -CSSEditor.prototype = domplate(Firebug.InlineEditor.prototype, -{ - insertNewRow: function(target, insertWhere) - { - var rule = Firebug.getRepObject(target); - var emptyProp = - { - // TODO: xxxpedro - uses charCode(255) to force the element being rendered, - // allowing webkit to get the correct position of the property name "span", - // when inserting a new CSS rule? - name: "", - value: "", - important: "" - }; - - if (insertWhere == "before") - return CSSPropTag.tag.insertBefore({prop: emptyProp, rule: rule}, target); - else - return CSSPropTag.tag.insertAfter({prop: emptyProp, rule: rule}, target); - }, - - saveEdit: function(target, value, previousValue) - { - // We need to check the value first in order to avoid a problem in IE8 - // See Issue 3038: Empty (null) styles when adding CSS styles in Firebug Lite - if (!value) return; - - target.innerHTML = escapeForCss(value); - - var row = getAncestorByClass(target, "cssProp"); - if (hasClass(row, "disabledStyle")) - toggleClass(row, "disabledStyle"); - - var rule = Firebug.getRepObject(target); - - if (hasClass(target, "cssPropName")) - { - if (value && previousValue != value) // name of property has changed. - { - var propValue = getChildByClass(row, "cssPropValue")[textContent]; - var parsedValue = parsePriority(propValue); - - if (propValue && propValue != "undefined") { - if (FBTrace.DBG_CSS) - FBTrace.sysout("CSSEditor.saveEdit : "+previousValue+"->"+value+" = "+propValue+"\n"); - if (previousValue) - Firebug.CSSModule.removeProperty(rule, previousValue); - Firebug.CSSModule.setProperty(rule, value, parsedValue.value, parsedValue.priority); - } - } - else if (!value) // name of the property has been deleted, so remove the property. - Firebug.CSSModule.removeProperty(rule, previousValue); - } - else if (getAncestorByClass(target, "cssPropValue")) - { - var propName = getChildByClass(row, "cssPropName")[textContent]; - var propValue = getChildByClass(row, "cssPropValue")[textContent]; - - if (FBTrace.DBG_CSS) - { - FBTrace.sysout("CSSEditor.saveEdit propName=propValue: "+propName +" = "+propValue+"\n"); - // FBTrace.sysout("CSSEditor.saveEdit BEFORE style:",style); - } - - if (value && value != "null") - { - var parsedValue = parsePriority(value); - Firebug.CSSModule.setProperty(rule, propName, parsedValue.value, parsedValue.priority); - } - else if (previousValue && previousValue != "null") - Firebug.CSSModule.removeProperty(rule, propName); - } - - this.panel.markChange(this.panel.name == "stylesheet"); - }, - - advanceToNext: function(target, charCode) - { - if (charCode == 58 /*":"*/ && hasClass(target, "cssPropName")) - return true; - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - getAutoCompleteRange: function(value, offset) - { - if (hasClass(this.target, "cssPropName")) - return {start: 0, end: value.length-1}; - else - return parseCSSValue(value, offset); - }, - - getAutoCompleteList: function(preExpr, expr, postExpr) - { - if (hasClass(this.target, "cssPropName")) - { - return getCSSPropertyNames(); - } - else - { - var row = getAncestorByClass(this.target, "cssProp"); - var propName = getChildByClass(row, "cssPropName")[textContent]; - return getCSSKeywordsByProperty(propName); - } - } -}); - -//************************************************************************************************ -//CSSRuleEditor - -function CSSRuleEditor(doc) -{ - this.initializeInline(doc); - this.completeAsYouType = false; -} -CSSRuleEditor.uniquifier = 0; -CSSRuleEditor.prototype = domplate(Firebug.InlineEditor.prototype, -{ - insertNewRow: function(target, insertWhere) - { - var emptyRule = { - selector: "", - id: "", - props: [], - isSelectorEditable: true - }; - - if (insertWhere == "before") - return CSSStyleRuleTag.tag.insertBefore({rule: emptyRule}, target); - else - return CSSStyleRuleTag.tag.insertAfter({rule: emptyRule}, target); - }, - - saveEdit: function(target, value, previousValue) - { - if (FBTrace.DBG_CSS) - FBTrace.sysout("CSSRuleEditor.saveEdit: '" + value + "' '" + previousValue + "'", target); - - target.innerHTML = escapeForCss(value); - - if (value === previousValue) return; - - var row = getAncestorByClass(target, "cssRule"); - var styleSheet = this.panel.location; - styleSheet = styleSheet.editStyleSheet ? styleSheet.editStyleSheet.sheet : styleSheet; - - var cssRules = styleSheet.cssRules; - var rule = Firebug.getRepObject(target), oldRule = rule; - var ruleIndex = cssRules.length; - if (rule || Firebug.getRepObject(row.nextSibling)) - { - var searchRule = rule || Firebug.getRepObject(row.nextSibling); - for (ruleIndex=0; ruleIndex<cssRules.length && searchRule!=cssRules[ruleIndex]; ruleIndex++) {} - } - - // Delete in all cases except for new add - // We want to do this before the insert to ease change tracking - if (oldRule) - { - Firebug.CSSModule.deleteRule(styleSheet, ruleIndex); - } - - // Firefox does not follow the spec for the update selector text case. - // When attempting to update the value, firefox will silently fail. - // See https://bugzilla.mozilla.org/show_bug.cgi?id=37468 for the quite - // old discussion of this bug. - // As a result we need to recreate the style every time the selector - // changes. - if (value) - { - var cssText = [ value, "{" ]; - var props = row.getElementsByClassName("cssProp"); - for (var i = 0; i < props.length; i++) { - var propEl = props[i]; - if (!hasClass(propEl, "disabledStyle")) { - cssText.push(getChildByClass(propEl, "cssPropName")[textContent]); - cssText.push(":"); - cssText.push(getChildByClass(propEl, "cssPropValue")[textContent]); - cssText.push(";"); - } - } - cssText.push("}"); - cssText = cssText.join(""); - - try - { - var insertLoc = Firebug.CSSModule.insertRule(styleSheet, cssText, ruleIndex); - rule = cssRules[insertLoc]; - ruleIndex++; - } - catch (err) - { - if (FBTrace.DBG_CSS || FBTrace.DBG_ERRORS) - FBTrace.sysout("CSS Insert Error: "+err, err); - - target.innerHTML = escapeForCss(previousValue); - row.repObject = undefined; - return; - } - } else { - rule = undefined; - } - - // Update the rep object - row.repObject = rule; - if (!oldRule) - { - // Who knows what the domutils will return for rule line - // for a recently created rule. To be safe we just generate - // a unique value as this is only used as an internal key. - var ruleId = "new/"+value+"/"+(++CSSRuleEditor.uniquifier); - row.setAttribute("ruleId", ruleId); - } - - this.panel.markChange(this.panel.name == "stylesheet"); - } -}); - -// ************************************************************************************************ -// StyleSheetEditor - -function StyleSheetEditor(doc) -{ - this.box = this.tag.replace({}, doc, this); - this.input = this.box.firstChild; -} - -StyleSheetEditor.prototype = domplate(Firebug.BaseEditor, -{ - multiLine: true, - - tag: DIV( - TEXTAREA({"class": "styleSheetEditor fullPanelEditor", oninput: "$onInput"}) - ), - - getValue: function() - { - return this.input.value; - }, - - setValue: function(value) - { - return this.input.value = value; - }, - - show: function(target, panel, value, textSize, targetSize) - { - this.target = target; - this.panel = panel; - - this.panel.panelNode.appendChild(this.box); - - this.input.value = value; - this.input.focus(); - - var command = Firebug.chrome.$("cmd_toggleCSSEditing"); - command.setAttribute("checked", true); - }, - - hide: function() - { - var command = Firebug.chrome.$("cmd_toggleCSSEditing"); - command.setAttribute("checked", false); - - if (this.box.parentNode == this.panel.panelNode) - this.panel.panelNode.removeChild(this.box); - - delete this.target; - delete this.panel; - delete this.styleSheet; - }, - - saveEdit: function(target, value, previousValue) - { - Firebug.CSSModule.freeEdit(this.styleSheet, value); - }, - - endEditing: function() - { - this.panel.refresh(); - return true; - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - onInput: function() - { - Firebug.Editor.update(); - }, - - scrollToLine: function(line, offset) - { - this.startMeasuring(this.input); - var lineHeight = this.measureText().height; - this.stopMeasuring(); - - this.input.scrollTop = (line * lineHeight) + offset; - } -}); - -// ************************************************************************************************ -// Local Helpers - -var rgbToHex = function rgbToHex(value) -{ - return value.replace(/\brgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)/gi, rgbToHexReplacer); -}; - -var rgbToHexReplacer = function(_, r, g, b) { - return '#' + ((1 << 24) + (r << 16) + (g << 8) + (b << 0)).toString(16).substr(-6).toUpperCase(); -}; - -var stripUnits = function stripUnits(value) -{ - // remove units from '0px', '0em' etc. leave non-zero units in-tact. - return value.replace(/(url\(.*?\)|[^0]\S*\s*)|0(%|em|ex|px|in|cm|mm|pt|pc)(\s|$)/gi, stripUnitsReplacer); -}; - -var stripUnitsReplacer = function(_, skip, remove, whitespace) { - return skip || ('0' + whitespace); -}; - -function parsePriority(value) -{ - var rePriority = /(.*?)\s*(!important)?$/; - var m = rePriority.exec(value); - var propValue = m ? m[1] : ""; - var priority = m && m[2] ? "important" : ""; - return {value: propValue, priority: priority}; -} - -function parseURLValue(value) -{ - var m = reURL.exec(value); - return m ? m[1] : ""; -} - -function parseRepeatValue(value) -{ - var m = reRepeat.exec(value); - return m ? m[0] : ""; -} - -function parseCSSValue(value, offset) -{ - var start = 0; - var m; - while (1) - { - m = reSplitCSS.exec(value); - if (m && m.index+m[0].length < offset) - { - value = value.substr(m.index+m[0].length); - start += m.index+m[0].length; - offset -= m.index+m[0].length; - } - else - break; - } - - if (m) - { - var type; - if (m[1]) - type = "url"; - else if (m[2] || m[3]) - type = "rgb"; - else if (m[4]) - type = "int"; - - return {value: m[0], start: start+m.index, end: start+m.index+(m[0].length-1), type: type}; - } -} - -function findPropByName(props, name) -{ - for (var i = 0; i < props.length; ++i) - { - if (props[i].name == name) - return i; - } -} - -function sortProperties(props) -{ - props.sort(function(a, b) - { - return a.name > b.name ? 1 : -1; - }); -} - -function getTopmostRuleLine(panelNode) -{ - for (var child = panelNode.firstChild; child; child = child.nextSibling) - { - if (child.offsetTop+child.offsetHeight > panelNode.scrollTop) - { - var rule = child.repObject; - if (rule) - return { - line: domUtils.getRuleLine(rule), - offset: panelNode.scrollTop-child.offsetTop - }; - } - } - return 0; -} - -function getStyleSheetCSS(sheet, context) -{ - if (sheet.ownerNode instanceof HTMLStyleElement) - return sheet.ownerNode.innerHTML; - else - return context.sourceCache.load(sheet.href).join(""); -} - -function getStyleSheetOwnerNode(sheet) { - for (; sheet && !sheet.ownerNode; sheet = sheet.parentStyleSheet); - - return sheet.ownerNode; -} - -function scrollSelectionIntoView(panel) -{ - var selCon = getSelectionController(panel); - selCon.scrollSelectionIntoView( - nsISelectionController.SELECTION_NORMAL, - nsISelectionController.SELECTION_FOCUS_REGION, true); -} - -function getSelectionController(panel) -{ - var browser = Firebug.chrome.getPanelBrowser(panel); - return browser.docShell.QueryInterface(nsIInterfaceRequestor) - .getInterface(nsISelectionDisplay) - .QueryInterface(nsISelectionController); -} - -// ************************************************************************************************ - -Firebug.registerModule(Firebug.CSSModule); -Firebug.registerPanel(Firebug.CSSStyleSheetPanel); -Firebug.registerPanel(CSSElementPanel); -Firebug.registerPanel(CSSComputedElementPanel); - -// ************************************************************************************************ - -}}); - - -/* See license.txt for terms of usage */ - -FBL.ns(function() { with (FBL) { -// ************************************************************************************************ - -// ************************************************************************************************ -// Script Module - -Firebug.Script = extend(Firebug.Module, -{ - getPanel: function() - { - return Firebug.chrome ? Firebug.chrome.getPanel("Script") : null; - }, - - selectSourceCode: function(index) - { - this.getPanel().selectSourceCode(index); - } -}); - -Firebug.registerModule(Firebug.Script); - - -// ************************************************************************************************ -// Script Panel - -function ScriptPanel(){}; - -ScriptPanel.prototype = extend(Firebug.Panel, -{ - name: "Script", - title: "Script", - - selectIndex: 0, // index of the current selectNode's option - sourceIndex: -1, // index of the script node, based in doc.getElementsByTagName("script") - - options: { - hasToolButtons: true - }, - - create: function() - { - Firebug.Panel.create.apply(this, arguments); - - this.onChangeSelect = bind(this.onChangeSelect, this); - - var doc = Firebug.browser.document; - var scripts = doc.getElementsByTagName("script"); - var selectNode = this.selectNode = createElement("select"); - - for(var i=0, script; script=scripts[i]; i++) - { - // Don't show Firebug Lite source code in the list of options - if (Firebug.ignoreFirebugElements && script.getAttribute("firebugIgnore")) - continue; - - var fileName = getFileName(script.src) || getFileName(doc.location.href); - var option = createElement("option", {value:i}); - - option.appendChild(Firebug.chrome.document.createTextNode(fileName)); - selectNode.appendChild(option); - }; - - this.toolButtonsNode.appendChild(selectNode); - }, - - initialize: function() - { - // we must render the code first, so the persistent state can be restore - this.selectSourceCode(this.selectIndex); - - Firebug.Panel.initialize.apply(this, arguments); - - addEvent(this.selectNode, "change", this.onChangeSelect); - }, - - shutdown: function() - { - removeEvent(this.selectNode, "change", this.onChangeSelect); - - Firebug.Panel.shutdown.apply(this, arguments); - }, - - detach: function(oldChrome, newChrome) - { - Firebug.Panel.detach.apply(this, arguments); - - var oldPanel = oldChrome.getPanel("Script"); - var index = oldPanel.selectIndex; - - this.selectNode.selectedIndex = index; - this.selectIndex = index; - this.sourceIndex = -1; - }, - - onChangeSelect: function(event) - { - var select = this.selectNode; - - this.selectIndex = select.selectedIndex; - - var option = select.options[select.selectedIndex]; - if (!option) - return; - - var selectedSourceIndex = parseInt(option.value); - - this.renderSourceCode(selectedSourceIndex); - }, - - selectSourceCode: function(index) - { - var select = this.selectNode; - select.selectedIndex = index; - - var option = select.options[index]; - if (!option) - return; - - var selectedSourceIndex = parseInt(option.value); - - this.renderSourceCode(selectedSourceIndex); - }, - - renderSourceCode: function(index) - { - if (this.sourceIndex != index) - { - var renderProcess = function renderProcess(src) - { - var html = [], - hl = 0; - - src = isIE && !isExternal ? - src+'\n' : // IE put an extra line when reading source of local resources - '\n'+src; - - // find the number of lines of code - src = src.replace(/\n\r|\r\n/g, "\n"); - var match = src.match(/[\n]/g); - var lines=match ? match.length : 0; - - // render the full source code + line numbers html - html[hl++] = '<div><div class="sourceBox" style="left:'; - html[hl++] = 35 + 7*(lines+'').length; - html[hl++] = 'px;"><pre class="sourceCode">'; - html[hl++] = escapeHTML(src); - html[hl++] = '</pre></div><div class="lineNo">'; - - // render the line number divs - for(var l=1, lines; l<=lines; l++) - { - html[hl++] = '<div line="'; - html[hl++] = l; - html[hl++] = '">'; - html[hl++] = l; - html[hl++] = '</div>'; - } - - html[hl++] = '</div></div>'; - - updatePanel(html); - }; - - var updatePanel = function(html) - { - self.panelNode.innerHTML = html.join(""); - - // IE needs this timeout, otherwise the panel won't scroll - setTimeout(function(){ - self.synchronizeUI(); - },0); - }; - - var onFailure = function() - { - FirebugReps.Warning.tag.replace({object: "AccessRestricted"}, self.panelNode); - }; - - var self = this; - - var doc = Firebug.browser.document; - var script = doc.getElementsByTagName("script")[index]; - var url = getScriptURL(script); - var isExternal = url && url != doc.location.href; - - try - { - if (Firebug.disableResourceFetching) - { - renderProcess(Firebug.Lite.Proxy.fetchResourceDisabledMessage); - } - else if (isExternal) - { - Ajax.request({url: url, onSuccess: renderProcess, onFailure: onFailure}); - } - else - { - var src = script.innerHTML; - renderProcess(src); - } - } - catch(e) - { - onFailure(); - } - - this.sourceIndex = index; - } - } -}); - -Firebug.registerPanel(ScriptPanel); - - -// ************************************************************************************************ - - -var getScriptURL = function getScriptURL(script) -{ - var reFile = /([^\/\?#]+)(#.+)?$/; - var rePath = /^(.*\/)/; - var reProtocol = /^\w+:\/\//; - var path = null; - var doc = Firebug.browser.document; - - var file = reFile.exec(script.src); - - if (file) - { - var fileName = file[1]; - var fileOptions = file[2]; - - // absolute path - if (reProtocol.test(script.src)) { - path = rePath.exec(script.src)[1]; - - } - // relative path - else - { - var r = rePath.exec(script.src); - var src = r ? r[1] : script.src; - var backDir = /^((?:\.\.\/)+)(.*)/.exec(src); - var reLastDir = /^(.*\/)[^\/]+\/$/; - path = rePath.exec(doc.location.href)[1]; - - // "../some/path" - if (backDir) - { - var j = backDir[1].length/3; - var p; - while (j-- > 0) - path = reLastDir.exec(path)[1]; - - path += backDir[2]; - } - - else if(src.indexOf("/") != -1) - { - // "./some/path" - if(/^\.\/./.test(src)) - { - path += src.substring(2); - } - // "/some/path" - else if(/^\/./.test(src)) - { - var domain = /^(\w+:\/\/[^\/]+)/.exec(path); - path = domain[1] + src; - } - // "some/path" - else - { - path += src; - } - } - } - } - - var m = path && path.match(/([^\/]+)\/$/) || null; - - if (path && m) - { - return path + fileName; - } -}; - -var getFileName = function getFileName(path) -{ - if (!path) return ""; - - var match = path && path.match(/[^\/]+(\?.*)?(#.*)?$/); - - return match && match[0] || path; -}; - - -// ************************************************************************************************ -}}); - -/* See license.txt for terms of usage */ - -FBL.ns(function() { with (FBL) { -// ************************************************************************************************ - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - -var ElementCache = Firebug.Lite.Cache.Element; - -var insertSliceSize = 18; -var insertInterval = 40; - -var ignoreVars = -{ - "__firebug__": 1, - "eval": 1, - - // We are forced to ignore Java-related variables, because - // trying to access them causes browser freeze - "java": 1, - "sun": 1, - "Packages": 1, - "JavaArray": 1, - "JavaMember": 1, - "JavaObject": 1, - "JavaClass": 1, - "JavaPackage": 1, - "_firebug": 1, - "_FirebugConsole": 1, - "_FirebugCommandLine": 1 -}; - -if (Firebug.ignoreFirebugElements) - ignoreVars[Firebug.Lite.Cache.ID] = 1; - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - -var memberPanelRep = - isIE6 ? - {"class": "memberLabel $member.type\\Label", href: "javacript:void(0)"} - : - {"class": "memberLabel $member.type\\Label"}; - -var RowTag = - TR({"class": "memberRow $member.open $member.type\\Row", $hasChildren: "$member.hasChildren", role : 'presentation', - level: "$member.level"}, - TD({"class": "memberLabelCell", style: "padding-left: $member.indent\\px", role : 'presentation'}, - A(memberPanelRep, - SPAN({}, "$member.name") - ) - ), - TD({"class": "memberValueCell", role : 'presentation'}, - TAG("$member.tag", {object: "$member.value"}) - ) - ); - -var WatchRowTag = - TR({"class": "watchNewRow", level: 0}, - TD({"class": "watchEditCell", colspan: 2}, - DIV({"class": "watchEditBox a11yFocusNoTab", role: "button", 'tabindex' : '0', - 'aria-label' : $STR('press enter to add new watch expression')}, - $STR("NewWatch") - ) - ) - ); - -var SizerRow = - TR({role : 'presentation'}, - TD({width: "30%"}), - TD({width: "70%"}) - ); - -var domTableClass = isIElt8 ? "domTable domTableIE" : "domTable"; -var DirTablePlate = domplate(Firebug.Rep, -{ - tag: - TABLE({"class": domTableClass, cellpadding: 0, cellspacing: 0, onclick: "$onClick", role :"tree"}, - TBODY({role: 'presentation'}, - SizerRow, - FOR("member", "$object|memberIterator", RowTag) - ) - ), - - watchTag: - TABLE({"class": domTableClass, cellpadding: 0, cellspacing: 0, - _toggles: "$toggles", _domPanel: "$domPanel", onclick: "$onClick", role : 'tree'}, - TBODY({role : 'presentation'}, - SizerRow, - WatchRowTag - ) - ), - - tableTag: - TABLE({"class": domTableClass, cellpadding: 0, cellspacing: 0, - _toggles: "$toggles", _domPanel: "$domPanel", onclick: "$onClick", role : 'tree'}, - TBODY({role : 'presentation'}, - SizerRow - ) - ), - - rowTag: - FOR("member", "$members", RowTag), - - memberIterator: function(object, level) - { - return getMembers(object, level); - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - onClick: function(event) - { - if (!isLeftClick(event)) - return; - - var target = event.target || event.srcElement; - - var row = getAncestorByClass(target, "memberRow"); - var label = getAncestorByClass(target, "memberLabel"); - if (label && hasClass(row, "hasChildren")) - { - var row = label.parentNode.parentNode; - this.toggleRow(row); - } - else - { - var object = Firebug.getRepObject(target); - if (typeof(object) == "function") - { - Firebug.chrome.select(object, "script"); - cancelEvent(event); - } - else if (event.detail == 2 && !object) - { - var panel = row.parentNode.parentNode.domPanel; - if (panel) - { - var rowValue = panel.getRowPropertyValue(row); - if (typeof(rowValue) == "boolean") - panel.setPropertyValue(row, !rowValue); - else - panel.editProperty(row); - - cancelEvent(event); - } - } - } - - return false; - }, - - toggleRow: function(row) - { - var level = parseInt(row.getAttribute("level")); - var toggles = row.parentNode.parentNode.toggles; - - if (hasClass(row, "opened")) - { - removeClass(row, "opened"); - - if (toggles) - { - var path = getPath(row); - - // Remove the path from the toggle tree - for (var i = 0; i < path.length; ++i) - { - if (i == path.length-1) - delete toggles[path[i]]; - else - toggles = toggles[path[i]]; - } - } - - var rowTag = this.rowTag; - var tbody = row.parentNode; - - setTimeout(function() - { - for (var firstRow = row.nextSibling; firstRow; firstRow = row.nextSibling) - { - if (parseInt(firstRow.getAttribute("level")) <= level) - break; - - tbody.removeChild(firstRow); - } - }, row.insertTimeout ? row.insertTimeout : 0); - } - else - { - setClass(row, "opened"); - - if (toggles) - { - var path = getPath(row); - - // Mark the path in the toggle tree - for (var i = 0; i < path.length; ++i) - { - var name = path[i]; - if (toggles.hasOwnProperty(name)) - toggles = toggles[name]; - else - toggles = toggles[name] = {}; - } - } - - var value = row.lastChild.firstChild.repObject; - var members = getMembers(value, level+1); - - var rowTag = this.rowTag; - var lastRow = row; - - var delay = 0; - //var setSize = members.length; - //var rowCount = 1; - while (members.length) - { - with({slice: members.splice(0, insertSliceSize), isLast: !members.length}) - { - setTimeout(function() - { - if (lastRow.parentNode) - { - var result = rowTag.insertRows({members: slice}, lastRow); - lastRow = result[1]; - //dispatch([Firebug.A11yModel], 'onMemberRowSliceAdded', [null, result, rowCount, setSize]); - //rowCount += insertSliceSize; - } - if (isLast) - row.removeAttribute("insertTimeout"); - }, delay); - } - - delay += insertInterval; - } - - row.insertTimeout = delay; - } - } -}); - - - -// ************************************************************************************************ - -Firebug.DOMBasePanel = function() {}; - -Firebug.DOMBasePanel.prototype = extend(Firebug.Panel, -{ - tag: DirTablePlate.tableTag, - - getRealObject: function(object) - { - // TODO: Move this to some global location - // TODO: Unwrapping should be centralized rather than sprinkling it around ad hoc. - // TODO: We might be able to make this check more authoritative with QueryInterface. - if (!object) return object; - if (object.wrappedJSObject) return object.wrappedJSObject; - return object; - }, - - rebuild: function(update, scrollTop) - { - //dispatch([Firebug.A11yModel], 'onBeforeDomUpdateSelection', [this]); - var members = getMembers(this.selection); - expandMembers(members, this.toggles, 0, 0); - - this.showMembers(members, update, scrollTop); - - //TODO: xxxpedro statusbar - if (!this.parentPanel) - updateStatusBar(this); - }, - - showMembers: function(members, update, scrollTop) - { - // If we are still in the midst of inserting rows, cancel all pending - // insertions here - this is a big speedup when stepping in the debugger - if (this.timeouts) - { - for (var i = 0; i < this.timeouts.length; ++i) - this.context.clearTimeout(this.timeouts[i]); - delete this.timeouts; - } - - if (!members.length) - return this.showEmptyMembers(); - - var panelNode = this.panelNode; - var priorScrollTop = scrollTop == undefined ? panelNode.scrollTop : scrollTop; - - // If we are asked to "update" the current view, then build the new table - // offscreen and swap it in when it's done - var offscreen = update && panelNode.firstChild; - var dest = offscreen ? panelNode.ownerDocument : panelNode; - - var table = this.tag.replace({domPanel: this, toggles: this.toggles}, dest); - var tbody = table.lastChild; - var rowTag = DirTablePlate.rowTag; - - // Insert the first slice immediately - //var slice = members.splice(0, insertSliceSize); - //var result = rowTag.insertRows({members: slice}, tbody.lastChild); - - //var setSize = members.length; - //var rowCount = 1; - - var panel = this; - var result; - - //dispatch([Firebug.A11yModel], 'onMemberRowSliceAdded', [panel, result, rowCount, setSize]); - var timeouts = []; - - var delay = 0; - - // enable to measure rendering performance - var renderStart = new Date().getTime(); - while (members.length) - { - with({slice: members.splice(0, insertSliceSize), isLast: !members.length}) - { - timeouts.push(this.context.setTimeout(function() - { - // TODO: xxxpedro can this be a timing error related to the - // "iteration number" approach insted of "duration time"? - // avoid error in IE8 - if (!tbody.lastChild) return; - - result = rowTag.insertRows({members: slice}, tbody.lastChild); - - //rowCount += insertSliceSize; - //dispatch([Firebug.A11yModel], 'onMemberRowSliceAdded', [panel, result, rowCount, setSize]); - - if ((panelNode.scrollHeight+panelNode.offsetHeight) >= priorScrollTop) - panelNode.scrollTop = priorScrollTop; - - - // enable to measure rendering performance - //if (isLast) alert(new Date().getTime() - renderStart + "ms"); - - - }, delay)); - - delay += insertInterval; - } - } - - if (offscreen) - { - timeouts.push(this.context.setTimeout(function() - { - if (panelNode.firstChild) - panelNode.replaceChild(table, panelNode.firstChild); - else - panelNode.appendChild(table); - - // Scroll back to where we were before - panelNode.scrollTop = priorScrollTop; - }, delay)); - } - else - { - timeouts.push(this.context.setTimeout(function() - { - panelNode.scrollTop = scrollTop == undefined ? 0 : scrollTop; - }, delay)); - } - this.timeouts = timeouts; - }, - - /* - // new - showMembers: function(members, update, scrollTop) - { - // If we are still in the midst of inserting rows, cancel all pending - // insertions here - this is a big speedup when stepping in the debugger - if (this.timeouts) - { - for (var i = 0; i < this.timeouts.length; ++i) - this.context.clearTimeout(this.timeouts[i]); - delete this.timeouts; - } - - if (!members.length) - return this.showEmptyMembers(); - - var panelNode = this.panelNode; - var priorScrollTop = scrollTop == undefined ? panelNode.scrollTop : scrollTop; - - // If we are asked to "update" the current view, then build the new table - // offscreen and swap it in when it's done - var offscreen = update && panelNode.firstChild; - var dest = offscreen ? panelNode.ownerDocument : panelNode; - - var table = this.tag.replace({domPanel: this, toggles: this.toggles}, dest); - var tbody = table.lastChild; - var rowTag = DirTablePlate.rowTag; - - // Insert the first slice immediately - //var slice = members.splice(0, insertSliceSize); - //var result = rowTag.insertRows({members: slice}, tbody.lastChild); - - //var setSize = members.length; - //var rowCount = 1; - - var panel = this; - var result; - - //dispatch([Firebug.A11yModel], 'onMemberRowSliceAdded', [panel, result, rowCount, setSize]); - var timeouts = []; - - var delay = 0; - var _insertSliceSize = insertSliceSize; - var _insertInterval = insertInterval; - - // enable to measure rendering performance - var renderStart = new Date().getTime(); - var lastSkip = renderStart, now; - - while (members.length) - { - with({slice: members.splice(0, _insertSliceSize), isLast: !members.length}) - { - var _tbody = tbody; - var _rowTag = rowTag; - var _panelNode = panelNode; - var _priorScrollTop = priorScrollTop; - - timeouts.push(this.context.setTimeout(function() - { - // TODO: xxxpedro can this be a timing error related to the - // "iteration number" approach insted of "duration time"? - // avoid error in IE8 - if (!_tbody.lastChild) return; - - result = _rowTag.insertRows({members: slice}, _tbody.lastChild); - - //rowCount += _insertSliceSize; - //dispatch([Firebug.A11yModel], 'onMemberRowSliceAdded', [panel, result, rowCount, setSize]); - - if ((_panelNode.scrollHeight + _panelNode.offsetHeight) >= _priorScrollTop) - _panelNode.scrollTop = _priorScrollTop; - - - // enable to measure rendering performance - //alert("gap: " + (new Date().getTime() - lastSkip)); - //lastSkip = new Date().getTime(); - - //if (isLast) alert("new: " + (new Date().getTime() - renderStart) + "ms"); - - }, delay)); - - delay += _insertInterval; - } - } - - if (offscreen) - { - timeouts.push(this.context.setTimeout(function() - { - if (panelNode.firstChild) - panelNode.replaceChild(table, panelNode.firstChild); - else - panelNode.appendChild(table); - - // Scroll back to where we were before - panelNode.scrollTop = priorScrollTop; - }, delay)); - } - else - { - timeouts.push(this.context.setTimeout(function() - { - panelNode.scrollTop = scrollTop == undefined ? 0 : scrollTop; - }, delay)); - } - this.timeouts = timeouts; - }, - /**/ - - showEmptyMembers: function() - { - FirebugReps.Warning.tag.replace({object: "NoMembersWarning"}, this.panelNode); - }, - - findPathObject: function(object) - { - var pathIndex = -1; - for (var i = 0; i < this.objectPath.length; ++i) - { - // IE needs === instead of == or otherwise some objects will - // be considered equal to different objects, returning the - // wrong index of the objectPath array - if (this.getPathObject(i) === object) - return i; - } - - return -1; - }, - - getPathObject: function(index) - { - var object = this.objectPath[index]; - - if (object instanceof Property) - return object.getObject(); - else - return object; - }, - - getRowObject: function(row) - { - var object = getRowOwnerObject(row); - return object ? object : this.selection; - }, - - getRowPropertyValue: function(row) - { - var object = this.getRowObject(row); - object = this.getRealObject(object); - if (object) - { - var propName = getRowName(row); - - if (object instanceof jsdIStackFrame) - return Firebug.Debugger.evaluate(propName, this.context); - else - return object[propName]; - } - }, - /* - copyProperty: function(row) - { - var value = this.getRowPropertyValue(row); - copyToClipboard(value); - }, - - editProperty: function(row, editValue) - { - if (hasClass(row, "watchNewRow")) - { - if (this.context.stopped) - Firebug.Editor.startEditing(row, ""); - else if (Firebug.Console.isAlwaysEnabled()) // not stopped in debugger, need command line - { - if (Firebug.CommandLine.onCommandLineFocus()) - Firebug.Editor.startEditing(row, ""); - else - row.innerHTML = $STR("warning.Command line blocked?"); - } - else - row.innerHTML = $STR("warning.Console must be enabled"); - } - else if (hasClass(row, "watchRow")) - Firebug.Editor.startEditing(row, getRowName(row)); - else - { - var object = this.getRowObject(row); - this.context.thisValue = object; - - if (!editValue) - { - var propValue = this.getRowPropertyValue(row); - - var type = typeof(propValue); - if (type == "undefined" || type == "number" || type == "boolean") - editValue = propValue; - else if (type == "string") - editValue = "\"" + escapeJS(propValue) + "\""; - else if (propValue == null) - editValue = "null"; - else if (object instanceof Window || object instanceof jsdIStackFrame) - editValue = getRowName(row); - else - editValue = "this." + getRowName(row); - } - - - Firebug.Editor.startEditing(row, editValue); - } - }, - - deleteProperty: function(row) - { - if (hasClass(row, "watchRow")) - this.deleteWatch(row); - else - { - var object = getRowOwnerObject(row); - if (!object) - object = this.selection; - object = this.getRealObject(object); - - if (object) - { - var name = getRowName(row); - try - { - delete object[name]; - } - catch (exc) - { - return; - } - - this.rebuild(true); - this.markChange(); - } - } - }, - - setPropertyValue: function(row, value) // value must be string - { - if(FBTrace.DBG_DOM) - { - FBTrace.sysout("row: "+row); - FBTrace.sysout("value: "+value+" type "+typeof(value), value); - } - - var name = getRowName(row); - if (name == "this") - return; - - var object = this.getRowObject(row); - object = this.getRealObject(object); - if (object && !(object instanceof jsdIStackFrame)) - { - // unwrappedJSObject.property = unwrappedJSObject - Firebug.CommandLine.evaluate(value, this.context, object, this.context.getGlobalScope(), - function success(result, context) - { - if (FBTrace.DBG_DOM) - FBTrace.sysout("setPropertyValue evaluate success object["+name+"]="+result+" type "+typeof(result), result); - object[name] = result; - }, - function failed(exc, context) - { - try - { - if (FBTrace.DBG_DOM) - FBTrace.sysout("setPropertyValue evaluate failed with exc:"+exc+" object["+name+"]="+value+" type "+typeof(value), exc); - // If the value doesn't parse, then just store it as a string. Some users will - // not realize they're supposed to enter a JavaScript expression and just type - // literal text - object[name] = String(value); // unwrappedJSobject.property = string - } - catch (exc) - { - return; - } - } - ); - } - else if (this.context.stopped) - { - try - { - Firebug.CommandLine.evaluate(name+"="+value, this.context); - } - catch (exc) - { - try - { - // See catch block above... - object[name] = String(value); // unwrappedJSobject.property = string - } - catch (exc) - { - return; - } - } - } - - this.rebuild(true); - this.markChange(); - }, - - highlightRow: function(row) - { - if (this.highlightedRow) - cancelClassTimed(this.highlightedRow, "jumpHighlight", this.context); - - this.highlightedRow = row; - - if (row) - setClassTimed(row, "jumpHighlight", this.context); - },/**/ - - onMouseMove: function(event) - { - var target = event.srcElement || event.target; - - var object = getAncestorByClass(target, "objectLink-element"); - object = object ? object.repObject : null; - - if(object && instanceOf(object, "Element") && object.nodeType == 1) - { - if(object != lastHighlightedObject) - { - Firebug.Inspector.drawBoxModel(object); - object = lastHighlightedObject; - } - } - else - Firebug.Inspector.hideBoxModel(); - - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // extends Panel - - create: function() - { - // TODO: xxxpedro - this.context = Firebug.browser; - - this.objectPath = []; - this.propertyPath = []; - this.viewPath = []; - this.pathIndex = -1; - this.toggles = {}; - - Firebug.Panel.create.apply(this, arguments); - - this.panelNode.style.padding = "0 1px"; - }, - - initialize: function(){ - Firebug.Panel.initialize.apply(this, arguments); - - addEvent(this.panelNode, "mousemove", this.onMouseMove); - }, - - shutdown: function() - { - removeEvent(this.panelNode, "mousemove", this.onMouseMove); - - Firebug.Panel.shutdown.apply(this, arguments); - }, - - /* - destroy: function(state) - { - var view = this.viewPath[this.pathIndex]; - if (view && this.panelNode.scrollTop) - view.scrollTop = this.panelNode.scrollTop; - - if (this.pathIndex) - state.pathIndex = this.pathIndex; - if (this.viewPath) - state.viewPath = this.viewPath; - if (this.propertyPath) - state.propertyPath = this.propertyPath; - - if (this.propertyPath.length > 0 && !this.propertyPath[1]) - state.firstSelection = persistObject(this.getPathObject(1), this.context); - - Firebug.Panel.destroy.apply(this, arguments); - }, - /**/ - - ishow: function(state) - { - if (this.context.loaded && !this.selection) - { - if (!state) - { - this.select(null); - return; - } - if (state.viewPath) - this.viewPath = state.viewPath; - if (state.propertyPath) - this.propertyPath = state.propertyPath; - - var defaultObject = this.getDefaultSelection(this.context); - var selectObject = defaultObject; - - if (state.firstSelection) - { - var restored = state.firstSelection(this.context); - if (restored) - { - selectObject = restored; - this.objectPath = [defaultObject, restored]; - } - else - this.objectPath = [defaultObject]; - } - else - this.objectPath = [defaultObject]; - - if (this.propertyPath.length > 1) - { - for (var i = 1; i < this.propertyPath.length; ++i) - { - var name = this.propertyPath[i]; - if (!name) - continue; - - var object = selectObject; - try - { - selectObject = object[name]; - } - catch (exc) - { - selectObject = null; - } - - if (selectObject) - { - this.objectPath.push(new Property(object, name)); - } - else - { - // If we can't access a property, just stop - this.viewPath.splice(i); - this.propertyPath.splice(i); - this.objectPath.splice(i); - selectObject = this.getPathObject(this.objectPath.length-1); - break; - } - } - } - - var selection = state.pathIndex <= this.objectPath.length-1 - ? this.getPathObject(state.pathIndex) - : this.getPathObject(this.objectPath.length-1); - - this.select(selection); - } - }, - /* - hide: function() - { - var view = this.viewPath[this.pathIndex]; - if (view && this.panelNode.scrollTop) - view.scrollTop = this.panelNode.scrollTop; - }, - /**/ - - supportsObject: function(object) - { - if (object == null) - return 1000; - - if (typeof(object) == "undefined") - return 1000; - else if (object instanceof SourceLink) - return 0; - else - return 1; // just agree to support everything but not agressively. - }, - - refresh: function() - { - this.rebuild(true); - }, - - updateSelection: function(object) - { - var previousIndex = this.pathIndex; - var previousView = previousIndex == -1 ? null : this.viewPath[previousIndex]; - - var newPath = this.pathToAppend; - delete this.pathToAppend; - - var pathIndex = this.findPathObject(object); - if (newPath || pathIndex == -1) - { - this.toggles = {}; - - if (newPath) - { - // Remove everything after the point where we are inserting, so we - // essentially replace it with the new path - if (previousView) - { - if (this.panelNode.scrollTop) - previousView.scrollTop = this.panelNode.scrollTop; - - var start = previousIndex + 1, - // Opera needs the length argument in splice(), otherwise - // it will consider that only one element should be removed - length = this.objectPath.length - start; - - this.objectPath.splice(start, length); - this.propertyPath.splice(start, length); - this.viewPath.splice(start, length); - } - - var value = this.getPathObject(previousIndex); - if (!value) - { - if (FBTrace.DBG_ERRORS) - FBTrace.sysout("dom.updateSelection no pathObject for "+previousIndex+"\n"); - return; - } - - for (var i = 0, length = newPath.length; i < length; ++i) - { - var name = newPath[i]; - var object = value; - try - { - value = value[name]; - } - catch(exc) - { - if (FBTrace.DBG_ERRORS) - FBTrace.sysout("dom.updateSelection FAILS at path_i="+i+" for name:"+name+"\n"); - return; - } - - ++this.pathIndex; - this.objectPath.push(new Property(object, name)); - this.propertyPath.push(name); - this.viewPath.push({toggles: this.toggles, scrollTop: 0}); - } - } - else - { - this.toggles = {}; - - var win = Firebug.browser.window; - //var win = this.context.getGlobalScope(); - if (object === win) - { - this.pathIndex = 0; - this.objectPath = [win]; - this.propertyPath = [null]; - this.viewPath = [{toggles: this.toggles, scrollTop: 0}]; - } - else - { - this.pathIndex = 1; - this.objectPath = [win, object]; - this.propertyPath = [null, null]; - this.viewPath = [ - {toggles: {}, scrollTop: 0}, - {toggles: this.toggles, scrollTop: 0} - ]; - } - } - - this.panelNode.scrollTop = 0; - this.rebuild(); - } - else - { - this.pathIndex = pathIndex; - - var view = this.viewPath[pathIndex]; - this.toggles = view.toggles; - - // Persist the current scroll location - if (previousView && this.panelNode.scrollTop) - previousView.scrollTop = this.panelNode.scrollTop; - - this.rebuild(false, view.scrollTop); - } - }, - - getObjectPath: function(object) - { - return this.objectPath; - }, - - getDefaultSelection: function() - { - return Firebug.browser.window; - //return this.context.getGlobalScope(); - }/*, - - updateOption: function(name, value) - { - const optionMap = {showUserProps: 1, showUserFuncs: 1, showDOMProps: 1, - showDOMFuncs: 1, showDOMConstants: 1}; - if ( optionMap.hasOwnProperty(name) ) - this.rebuild(true); - }, - - getOptionsMenuItems: function() - { - return [ - optionMenu("ShowUserProps", "showUserProps"), - optionMenu("ShowUserFuncs", "showUserFuncs"), - optionMenu("ShowDOMProps", "showDOMProps"), - optionMenu("ShowDOMFuncs", "showDOMFuncs"), - optionMenu("ShowDOMConstants", "showDOMConstants"), - "-", - {label: "Refresh", command: bindFixed(this.rebuild, this, true) } - ]; - }, - - getContextMenuItems: function(object, target) - { - var row = getAncestorByClass(target, "memberRow"); - - var items = []; - - if (row) - { - var rowName = getRowName(row); - var rowObject = this.getRowObject(row); - var rowValue = this.getRowPropertyValue(row); - - var isWatch = hasClass(row, "watchRow"); - var isStackFrame = rowObject instanceof jsdIStackFrame; - - if (typeof(rowValue) == "string" || typeof(rowValue) == "number") - { - // Functions already have a copy item in their context menu - items.push( - "-", - {label: "CopyValue", - command: bindFixed(this.copyProperty, this, row) } - ); - } - - items.push( - "-", - {label: isWatch ? "EditWatch" : (isStackFrame ? "EditVariable" : "EditProperty"), - command: bindFixed(this.editProperty, this, row) } - ); - - if (isWatch || (!isStackFrame && !isDOMMember(rowObject, rowName))) - { - items.push( - {label: isWatch ? "DeleteWatch" : "DeleteProperty", - command: bindFixed(this.deleteProperty, this, row) } - ); - } - } - - items.push( - "-", - {label: "Refresh", command: bindFixed(this.rebuild, this, true) } - ); - - return items; - }, - - getEditor: function(target, value) - { - if (!this.editor) - this.editor = new DOMEditor(this.document); - - return this.editor; - }/**/ -}); - -// ************************************************************************************************ - -// TODO: xxxpedro statusbar -var updateStatusBar = function(panel) -{ - var path = panel.propertyPath; - var index = panel.pathIndex; - - var r = []; - - for (var i=0, l=path.length; i<l; i++) - { - r.push(i==index ? '<a class="fbHover fbButton fbBtnSelected" ' : '<a class="fbHover fbButton" '); - r.push('pathIndex='); - r.push(i); - - if(isIE6) - r.push(' href="javascript:void(0)"'); - - r.push('>'); - r.push(i==0 ? "window" : path[i] || "Object"); - r.push('</a>'); - - if(i < l-1) - r.push('<span class="fbStatusSeparator">></span>'); - } - panel.statusBarNode.innerHTML = r.join(""); -}; - - -var DOMMainPanel = Firebug.DOMPanel = function () {}; - -Firebug.DOMPanel.DirTable = DirTablePlate; - -DOMMainPanel.prototype = extend(Firebug.DOMBasePanel.prototype, -{ - onClickStatusBar: function(event) - { - var target = event.srcElement || event.target; - var element = getAncestorByClass(target, "fbHover"); - - if(element) - { - var pathIndex = element.getAttribute("pathIndex"); - - if(pathIndex) - { - this.select(this.getPathObject(pathIndex)); - } - } - }, - - selectRow: function(row, target) - { - if (!target) - target = row.lastChild.firstChild; - - if (!target || !target.repObject) - return; - - this.pathToAppend = getPath(row); - - // If the object is inside an array, look up its index - var valueBox = row.lastChild.firstChild; - if (hasClass(valueBox, "objectBox-array")) - { - var arrayIndex = FirebugReps.Arr.getItemIndex(target); - this.pathToAppend.push(arrayIndex); - } - - // Make sure we get a fresh status path for the object, since otherwise - // it might find the object in the existing path and not refresh it - //Firebug.chrome.clearStatusPath(); - - this.select(target.repObject, true); - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - onClick: function(event) - { - var target = event.srcElement || event.target; - var repNode = Firebug.getRepNode(target); - if (repNode) - { - var row = getAncestorByClass(target, "memberRow"); - if (row) - { - this.selectRow(row, repNode); - cancelEvent(event); - } - } - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // extends Panel - - name: "DOM", - title: "DOM", - searchable: true, - statusSeparator: ">", - - options: { - hasToolButtons: true, - hasStatusBar: true - }, - - create: function() - { - Firebug.DOMBasePanel.prototype.create.apply(this, arguments); - - this.onClick = bind(this.onClick, this); - - //TODO: xxxpedro - this.onClickStatusBar = bind(this.onClickStatusBar, this); - - this.panelNode.style.padding = "0 1px"; - }, - - initialize: function(oldPanelNode) - { - //this.panelNode.addEventListener("click", this.onClick, false); - //dispatch([Firebug.A11yModel], 'onInitializeNode', [this, 'console']); - - Firebug.DOMBasePanel.prototype.initialize.apply(this, arguments); - - addEvent(this.panelNode, "click", this.onClick); - - // TODO: xxxpedro dom - this.ishow(); - - //TODO: xxxpedro - addEvent(this.statusBarNode, "click", this.onClickStatusBar); - }, - - shutdown: function() - { - //this.panelNode.removeEventListener("click", this.onClick, false); - //dispatch([Firebug.A11yModel], 'onDestroyNode', [this, 'console']); - - removeEvent(this.panelNode, "click", this.onClick); - - Firebug.DOMBasePanel.prototype.shutdown.apply(this, arguments); - }/*, - - search: function(text, reverse) - { - if (!text) - { - delete this.currentSearch; - this.highlightRow(null); - return false; - } - - var row; - if (this.currentSearch && text == this.currentSearch.text) - row = this.currentSearch.findNext(true, undefined, reverse, Firebug.searchCaseSensitive); - else - { - function findRow(node) { return getAncestorByClass(node, "memberRow"); } - this.currentSearch = new TextSearch(this.panelNode, findRow); - row = this.currentSearch.find(text, reverse, Firebug.searchCaseSensitive); - } - - if (row) - { - var sel = this.document.defaultView.getSelection(); - sel.removeAllRanges(); - sel.addRange(this.currentSearch.range); - - scrollIntoCenterView(row, this.panelNode); - - this.highlightRow(row); - dispatch([Firebug.A11yModel], 'onDomSearchMatchFound', [this, text, row]); - return true; - } - else - { - dispatch([Firebug.A11yModel], 'onDomSearchMatchFound', [this, text, null]); - return false; - } - }/**/ -}); - -Firebug.registerPanel(DOMMainPanel); - - -// ************************************************************************************************ - - - -// ************************************************************************************************ -// Local Helpers - -var getMembers = function getMembers(object, level) // we expect object to be user-level object wrapped in security blanket -{ - if (!level) - level = 0; - - var ordinals = [], userProps = [], userClasses = [], userFuncs = [], - domProps = [], domFuncs = [], domConstants = []; - - try - { - var domMembers = getDOMMembers(object); - //var domMembers = {}; // TODO: xxxpedro - //var domConstantMap = {}; // TODO: xxxpedro - - if (object.wrappedJSObject) - var insecureObject = object.wrappedJSObject; - else - var insecureObject = object; - - // IE function prototype is not listed in (for..in) - if (isIE && isFunction(object)) - addMember("user", userProps, "prototype", object.prototype, level); - - for (var name in insecureObject) // enumeration is safe - { - if (ignoreVars[name] == 1) // javascript.options.strict says ignoreVars is undefined. - continue; - - var val; - try - { - val = insecureObject[name]; // getter is safe - } - catch (exc) - { - // Sometimes we get exceptions trying to access certain members - if (FBTrace.DBG_ERRORS && FBTrace.DBG_DOM) - FBTrace.sysout("dom.getMembers cannot access "+name, exc); - } - - var ordinal = parseInt(name); - if (ordinal || ordinal == 0) - { - addMember("ordinal", ordinals, name, val, level); - } - else if (isFunction(val)) - { - if (isClassFunction(val) && !(name in domMembers)) - addMember("userClass", userClasses, name, val, level); - else if (name in domMembers) - addMember("domFunction", domFuncs, name, val, level, domMembers[name]); - else - addMember("userFunction", userFuncs, name, val, level); - } - else - { - //TODO: xxxpedro - /* - var getterFunction = insecureObject.__lookupGetter__(name), - setterFunction = insecureObject.__lookupSetter__(name), - prefix = ""; - - if(getterFunction && !setterFunction) - prefix = "get "; - /**/ - - var prefix = ""; - - if (name in domMembers && !(name in domConstantMap)) - addMember("dom", domProps, (prefix+name), val, level, domMembers[name]); - else if (name in domConstantMap) - addMember("dom", domConstants, (prefix+name), val, level); - else - addMember("user", userProps, (prefix+name), val, level); - } - } - } - catch (exc) - { - // Sometimes we get exceptions just from trying to iterate the members - // of certain objects, like StorageList, but don't let that gum up the works - throw exc; - if (FBTrace.DBG_ERRORS && FBTrace.DBG_DOM) - FBTrace.sysout("dom.getMembers FAILS: ", exc); - //throw exc; - } - - function sortName(a, b) { return a.name > b.name ? 1 : -1; } - function sortOrder(a, b) { return a.order > b.order ? 1 : -1; } - - var members = []; - - members.push.apply(members, ordinals); - - Firebug.showUserProps = true; // TODO: xxxpedro - Firebug.showUserFuncs = true; // TODO: xxxpedro - Firebug.showDOMProps = true; - Firebug.showDOMFuncs = true; - Firebug.showDOMConstants = true; - - if (Firebug.showUserProps) - { - userProps.sort(sortName); - members.push.apply(members, userProps); - } - - if (Firebug.showUserFuncs) - { - userClasses.sort(sortName); - members.push.apply(members, userClasses); - - userFuncs.sort(sortName); - members.push.apply(members, userFuncs); - } - - if (Firebug.showDOMProps) - { - domProps.sort(sortName); - members.push.apply(members, domProps); - } - - if (Firebug.showDOMFuncs) - { - domFuncs.sort(sortName); - members.push.apply(members, domFuncs); - } - - if (Firebug.showDOMConstants) - members.push.apply(members, domConstants); - - return members; -}; - -function expandMembers(members, toggles, offset, level) // recursion starts with offset=0, level=0 -{ - var expanded = 0; - for (var i = offset; i < members.length; ++i) - { - var member = members[i]; - if (member.level > level) - break; - - if ( toggles.hasOwnProperty(member.name) ) - { - member.open = "opened"; // member.level <= level && member.name in toggles. - - var newMembers = getMembers(member.value, level+1); // sets newMembers.level to level+1 - - var args = [i+1, 0]; - args.push.apply(args, newMembers); - members.splice.apply(members, args); - - /* - if (FBTrace.DBG_DOM) - { - FBTrace.sysout("expandMembers member.name", member.name); - FBTrace.sysout("expandMembers toggles", toggles); - FBTrace.sysout("expandMembers toggles[member.name]", toggles[member.name]); - FBTrace.sysout("dom.expandedMembers level: "+level+" member", member); - } - /**/ - - expanded += newMembers.length; - i += newMembers.length + expandMembers(members, toggles[member.name], i+1, level+1); - } - } - - return expanded; -} - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - -function isClassFunction(fn) -{ - try - { - for (var name in fn.prototype) - return true; - } catch (exc) {} - return false; -} - -// FIXME: xxxpedro This function is already defined in Lib. If we keep this definition here, it -// will crash IE9 when not running the IE Developer Tool with JavaScript Debugging enabled!!! -// Check if this function is in fact defined in Firebug for Firefox. If so, we should remove -// this from here. The only difference of this function is the IE hack to show up the prototype -// of functions, but Firebug no longer shows the prototype for simple functions. -//var hasProperties = function hasProperties(ob) -//{ -// try -// { -// for (var name in ob) -// return true; -// } catch (exc) {} -// -// // IE function prototype is not listed in (for..in) -// if (isFunction(ob)) return true; -// -// return false; -//}; - -FBL.ErrorCopy = function(message) -{ - this.message = message; -}; - -var addMember = function addMember(type, props, name, value, level, order) -{ - var rep = Firebug.getRep(value); // do this first in case a call to instanceof reveals contents - var tag = rep.shortTag ? rep.shortTag : rep.tag; - - var ErrorCopy = function(){}; //TODO: xxxpedro - - var valueType = typeof(value); - var hasChildren = hasProperties(value) && !(value instanceof ErrorCopy) && - (isFunction(value) || (valueType == "object" && value != null) - || (valueType == "string" && value.length > Firebug.stringCropLength)); - - props.push({ - name: name, - value: value, - type: type, - rowClass: "memberRow-"+type, - open: "", - order: order, - level: level, - indent: level*16, - hasChildren: hasChildren, - tag: tag - }); -}; - -var getWatchRowIndex = function getWatchRowIndex(row) -{ - var index = -1; - for (; row && hasClass(row, "watchRow"); row = row.previousSibling) - ++index; - return index; -}; - -var getRowName = function getRowName(row) -{ - var node = row.firstChild; - return node.textContent ? node.textContent : node.innerText; -}; - -var getRowValue = function getRowValue(row) -{ - return row.lastChild.firstChild.repObject; -}; - -var getRowOwnerObject = function getRowOwnerObject(row) -{ - var parentRow = getParentRow(row); - if (parentRow) - return getRowValue(parentRow); -}; - -var getParentRow = function getParentRow(row) -{ - var level = parseInt(row.getAttribute("level"))-1; - for (row = row.previousSibling; row; row = row.previousSibling) - { - if (parseInt(row.getAttribute("level")) == level) - return row; - } -}; - -var getPath = function getPath(row) -{ - var name = getRowName(row); - var path = [name]; - - var level = parseInt(row.getAttribute("level"))-1; - for (row = row.previousSibling; row; row = row.previousSibling) - { - if (parseInt(row.getAttribute("level")) == level) - { - var name = getRowName(row); - path.splice(0, 0, name); - - --level; - } - } - - return path; -}; - -// ************************************************************************************************ - - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - -// ************************************************************************************************ -// DOM Module - -Firebug.DOM = extend(Firebug.Module, -{ - getPanel: function() - { - return Firebug.chrome ? Firebug.chrome.getPanel("DOM") : null; - } -}); - -Firebug.registerModule(Firebug.DOM); - - -// ************************************************************************************************ -// DOM Panel - -var lastHighlightedObject; - -function DOMSidePanel(){}; - -DOMSidePanel.prototype = extend(Firebug.DOMBasePanel.prototype, -{ - selectRow: function(row, target) - { - if (!target) - target = row.lastChild.firstChild; - - if (!target || !target.repObject) - return; - - this.pathToAppend = getPath(row); - - // If the object is inside an array, look up its index - var valueBox = row.lastChild.firstChild; - if (hasClass(valueBox, "objectBox-array")) - { - var arrayIndex = FirebugReps.Arr.getItemIndex(target); - this.pathToAppend.push(arrayIndex); - } - - // Make sure we get a fresh status path for the object, since otherwise - // it might find the object in the existing path and not refresh it - //Firebug.chrome.clearStatusPath(); - - var object = target.repObject; - - if (instanceOf(object, "Element")) - { - Firebug.HTML.selectTreeNode(ElementCache(object)); - } - else - { - Firebug.chrome.selectPanel("DOM"); - Firebug.chrome.getPanel("DOM").select(object, true); - } - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - - onClick: function(event) - { - /* - var target = event.srcElement || event.target; - - var object = getAncestorByClass(target, "objectLink"); - object = object ? object.repObject : null; - - if(!object) return; - - if (instanceOf(object, "Element")) - { - Firebug.HTML.selectTreeNode(ElementCache(object)); - } - else - { - Firebug.chrome.selectPanel("DOM"); - Firebug.chrome.getPanel("DOM").select(object, true); - } - /**/ - - - var target = event.srcElement || event.target; - var repNode = Firebug.getRepNode(target); - if (repNode) - { - var row = getAncestorByClass(target, "memberRow"); - if (row) - { - this.selectRow(row, repNode); - cancelEvent(event); - } - } - /**/ - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // extends Panel - - name: "DOMSidePanel", - parentPanel: "HTML", - title: "DOM", - - options: { - hasToolButtons: true - }, - - isInitialized: false, - - create: function() - { - Firebug.DOMBasePanel.prototype.create.apply(this, arguments); - - this.onClick = bind(this.onClick, this); - }, - - initialize: function(){ - Firebug.DOMBasePanel.prototype.initialize.apply(this, arguments); - - addEvent(this.panelNode, "click", this.onClick); - - // TODO: xxxpedro css2 - var selection = ElementCache.get(Firebug.context.persistedState.selectedHTMLElementId); - if (selection) - this.select(selection, true); - }, - - shutdown: function() - { - removeEvent(this.panelNode, "click", this.onClick); - - Firebug.DOMBasePanel.prototype.shutdown.apply(this, arguments); - }, - - reattach: function(oldChrome) - { - //this.isInitialized = oldChrome.getPanel("DOM").isInitialized; - this.toggles = oldChrome.getPanel("DOMSidePanel").toggles; - } - -}); - -Firebug.registerPanel(DOMSidePanel); - - -// ************************************************************************************************ -}}); - -/* See license.txt for terms of usage */ - -FBL.FBTrace = {}; - -(function() { -// ************************************************************************************************ - -var traceOptions = { - DBG_TIMESTAMP: 1, - DBG_INITIALIZE: 1, - DBG_CHROME: 1, - DBG_ERRORS: 1, - DBG_DISPATCH: 1, - DBG_CSS: 1 -}; - -this.module = null; - -this.initialize = function() -{ - if (!this.messageQueue) - this.messageQueue = []; - - for (var name in traceOptions) - this[name] = traceOptions[name]; -}; - -// ************************************************************************************************ -// FBTrace API - -this.sysout = function() -{ - return this.logFormatted(arguments, ""); -}; - -this.dumpProperties = function(title, object) -{ - return this.logFormatted("dumpProperties() not supported.", "warning"); -}; - -this.dumpStack = function() -{ - return this.logFormatted("dumpStack() not supported.", "warning"); -}; - -this.flush = function(module) -{ - this.module = module; - - var queue = this.messageQueue; - this.messageQueue = []; - - for (var i = 0; i < queue.length; ++i) - this.writeMessage(queue[i][0], queue[i][1], queue[i][2]); -}; - -this.getPanel = function() -{ - return this.module ? this.module.getPanel() : null; -}; - -//************************************************************************************************* - -this.logFormatted = function(objects, className) -{ - var html = this.DBG_TIMESTAMP ? [getTimestamp(), " | "] : []; - var length = objects.length; - - for (var i = 0; i < length; ++i) - { - appendText(" ", html); - - var object = objects[i]; - - if (i == 0) - { - html.push("<b>"); - appendText(object, html); - html.push("</b>"); - } - else - appendText(object, html); - } - - return this.logRow(html, className); -}; - -this.logRow = function(message, className) -{ - var panel = this.getPanel(); - - if (panel && panel.panelNode) - this.writeMessage(message, className); - else - { - this.messageQueue.push([message, className]); - } - - return this.LOG_COMMAND; -}; - -this.writeMessage = function(message, className) -{ - var container = this.getPanel().containerNode; - var isScrolledToBottom = - container.scrollTop + container.offsetHeight >= container.scrollHeight; - - this.writeRow.call(this, message, className); - - if (isScrolledToBottom) - container.scrollTop = container.scrollHeight - container.offsetHeight; -}; - -this.appendRow = function(row) -{ - var container = this.getPanel().panelNode; - container.appendChild(row); -}; - -this.writeRow = function(message, className) -{ - var row = this.getPanel().panelNode.ownerDocument.createElement("div"); - row.className = "logRow" + (className ? " logRow-"+className : ""); - row.innerHTML = message.join(""); - this.appendRow(row); -}; - -//************************************************************************************************* - -function appendText(object, html) -{ - html.push(escapeHTML(objectToString(object))); -}; - -function getTimestamp() -{ - var now = new Date(); - var ms = "" + (now.getMilliseconds() / 1000).toFixed(3); - ms = ms.substr(2); - - return now.toLocaleTimeString() + "." + ms; -}; - -//************************************************************************************************* - -var HTMLtoEntity = -{ - "<": "<", - ">": ">", - "&": "&", - "'": "'", - '"': """ -}; - -function replaceChars(ch) -{ - return HTMLtoEntity[ch]; -}; - -function escapeHTML(value) -{ - return (value+"").replace(/[<>&"']/g, replaceChars); -}; - -//************************************************************************************************* - -function objectToString(object) -{ - try - { - return object+""; - } - catch (exc) - { - return null; - } -}; - -// ************************************************************************************************ -}).apply(FBL.FBTrace); - -/* See license.txt for terms of usage */ - -FBL.ns(function() { with (FBL) { -// ************************************************************************************************ - -// If application isn't in trace mode, the FBTrace panel won't be loaded -if (!Env.Options.enableTrace) return; - -// ************************************************************************************************ -// FBTrace Module - -Firebug.Trace = extend(Firebug.Module, -{ - getPanel: function() - { - return Firebug.chrome ? Firebug.chrome.getPanel("Trace") : null; - }, - - clear: function() - { - this.getPanel().panelNode.innerHTML = ""; - } -}); - -Firebug.registerModule(Firebug.Trace); - - -// ************************************************************************************************ -// FBTrace Panel - -function TracePanel(){}; - -TracePanel.prototype = extend(Firebug.Panel, -{ - name: "Trace", - title: "Trace", - - options: { - hasToolButtons: true, - innerHTMLSync: true - }, - - create: function(){ - Firebug.Panel.create.apply(this, arguments); - - this.clearButton = new Button({ - caption: "Clear", - title: "Clear FBTrace logs", - owner: Firebug.Trace, - onClick: Firebug.Trace.clear - }); - }, - - initialize: function(){ - Firebug.Panel.initialize.apply(this, arguments); - - this.clearButton.initialize(); - }, - - shutdown: function() - { - this.clearButton.shutdown(); - - Firebug.Panel.shutdown.apply(this, arguments); - } - -}); - -Firebug.registerPanel(TracePanel); - -// ************************************************************************************************ -}}); - -/* See license.txt for terms of usage */ - -FBL.ns(function() { with (FBL) { -// ************************************************************************************************ - -// ************************************************************************************************ -// Globals - -var modules = []; -var panelTypes = []; -var panelTypeMap = {}; - -var parentPanelMap = {}; - - -var registerModule = Firebug.registerModule; -var registerPanel = Firebug.registerPanel; - -// ************************************************************************************************ -append(Firebug, -{ - extend: function(fn) - { - if (Firebug.chrome && Firebug.chrome.addPanel) - { - var namespace = ns(fn); - fn.call(namespace, FBL); - } - else - { - setTimeout(function(){Firebug.extend(fn);},100); - } - }, - - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - // Registration - - registerModule: function() - { - registerModule.apply(Firebug, arguments); - - modules.push.apply(modules, arguments); - - dispatch(modules, "initialize", []); - - if (FBTrace.DBG_INITIALIZE) FBTrace.sysout("Firebug.registerModule"); - }, - - registerPanel: function() - { - registerPanel.apply(Firebug, arguments); - - panelTypes.push.apply(panelTypes, arguments); - - for (var i = 0, panelType; panelType = arguments[i]; ++i) - { - // TODO: xxxpedro investigate why Dev Panel throws an error - if (panelType.prototype.name == "Dev") continue; - - panelTypeMap[panelType.prototype.name] = arguments[i]; - - var parentPanelName = panelType.prototype.parentPanel; - if (parentPanelName) - { - parentPanelMap[parentPanelName] = 1; - } - else - { - var panelName = panelType.prototype.name; - var chrome = Firebug.chrome; - chrome.addPanel(panelName); - - // tab click handler - var onTabClick = function onTabClick() - { - chrome.selectPanel(panelName); - return false; - }; - - chrome.addController([chrome.panelMap[panelName].tabNode, "mousedown", onTabClick]); - } - } - - if (FBTrace.DBG_INITIALIZE) - for (var i = 0; i < arguments.length; ++i) - FBTrace.sysout("Firebug.registerPanel", arguments[i].prototype.name); - } - -}); - - - - -// ************************************************************************************************ -}}); - -FBL.ns(function() { with (FBL) { -// ************************************************************************************************ - -FirebugChrome.Skin = -{ - CSS: '.obscured{left:-999999px !important;}.collapsed{display:none;}[collapsed="true"]{display:none;}#fbCSS{padding:0 !important;}.cssPropDisable{float:left;display:block;width:2em;cursor:default;}.infoTip{z-index:2147483647;position:fixed;padding:2px 3px;border:1px solid #CBE087;background:LightYellow;font-family:Monaco,monospace;color:#000000;display:none;white-space:nowrap;pointer-events:none;}.infoTip[active="true"]{display:block;}.infoTipLoading{width:16px;height:16px;background:url(https://getfirebug.com/releases/lite/latest/skin/xp/chrome://firebug/skin/loading_16.gif) no-repeat;}.infoTipImageBox{font-size:11px;min-width:100px;text-align:center;}.infoTipCaption{font-size:11px;font:Monaco,monospace;}.infoTipLoading > .infoTipImage,.infoTipLoading > .infoTipCaption{display:none;}h1.groupHeader{padding:2px 4px;margin:0 0 4px 0;border-top:1px solid #CCCCCC;border-bottom:1px solid #CCCCCC;background:#eee url(https://getfirebug.com/releases/lite/latest/skin/xp/group.gif) repeat-x;font-size:11px;font-weight:bold;_position:relative;}.inlineEditor,.fixedWidthEditor{z-index:2147483647;position:absolute;display:none;}.inlineEditor{margin-left:-6px;margin-top:-3px;}.textEditorInner,.fixedWidthEditor{margin:0 0 0 0 !important;padding:0;border:none !important;font:inherit;text-decoration:inherit;background-color:#FFFFFF;}.fixedWidthEditor{border-top:1px solid #888888 !important;border-bottom:1px solid #888888 !important;}.textEditorInner{position:relative;top:-7px;left:-5px;outline:none;resize:none;}.textEditorInner1{padding-left:11px;background:url(https://getfirebug.com/releases/lite/latest/skin/xp/textEditorBorders.png) repeat-y;_background:url(https://getfirebug.com/releases/lite/latest/skin/xp/textEditorBorders.gif) repeat-y;_overflow:hidden;}.textEditorInner2{position:relative;padding-right:2px;background:url(https://getfirebug.com/releases/lite/latest/skin/xp/textEditorBorders.png) repeat-y 100% 0;_background:url(https://getfirebug.com/releases/lite/latest/skin/xp/textEditorBorders.gif) repeat-y 100% 0;_position:fixed;}.textEditorTop1{background:url(https://getfirebug.com/releases/lite/latest/skin/xp/textEditorCorners.png) no-repeat 100% 0;margin-left:11px;height:10px;_background:url(https://getfirebug.com/releases/lite/latest/skin/xp/textEditorCorners.gif) no-repeat 100% 0;_overflow:hidden;}.textEditorTop2{position:relative;left:-11px;width:11px;height:10px;background:url(https://getfirebug.com/releases/lite/latest/skin/xp/textEditorCorners.png) no-repeat;_background:url(https://getfirebug.com/releases/lite/latest/skin/xp/textEditorCorners.gif) no-repeat;}.textEditorBottom1{position:relative;background:url(https://getfirebug.com/releases/lite/latest/skin/xp/textEditorCorners.png) no-repeat 100% 100%;margin-left:11px;height:12px;_background:url(https://getfirebug.com/releases/lite/latest/skin/xp/textEditorCorners.gif) no-repeat 100% 100%;}.textEditorBottom2{position:relative;left:-11px;width:11px;height:12px;background:url(https://getfirebug.com/releases/lite/latest/skin/xp/textEditorCorners.png) no-repeat 0 100%;_background:url(https://getfirebug.com/releases/lite/latest/skin/xp/textEditorCorners.gif) no-repeat 0 100%;}.panelNode-css{overflow-x:hidden;}.cssSheet > .insertBefore{height:1.5em;}.cssRule{position:relative;margin:0;padding:1em 0 0 6px;font-family:Monaco,monospace;color:#000000;}.cssRule:first-child{padding-top:6px;}.cssElementRuleContainer{position:relative;}.cssHead{padding-right:150px;}.cssProp{}.cssPropName{color:DarkGreen;}.cssPropValue{margin-left:8px;color:DarkBlue;}.cssOverridden span{text-decoration:line-through;}.cssInheritedRule{}.cssInheritLabel{margin-right:0.5em;font-weight:bold;}.cssRule .objectLink-sourceLink{top:0;}.cssProp.editGroup:hover{background:url(https://getfirebug.com/releases/lite/latest/skin/xp/disable.png) no-repeat 2px 1px;_background:url(https://getfirebug.com/releases/lite/latest/skin/xp/disable.gif) no-repeat 2px 1px;}.cssProp.editGroup.editing{background:none;}.cssProp.disabledStyle{background:url(https://getfirebug.com/releases/lite/latest/skin/xp/disableHover.png) no-repeat 2px 1px;_background:url(https://getfirebug.com/releases/lite/latest/skin/xp/disableHover.gif) no-repeat 2px 1px;opacity:1;color:#CCCCCC;}.disabledStyle .cssPropName,.disabledStyle .cssPropValue{color:#CCCCCC;}.cssPropValue.editing + .cssSemi,.inlineExpander + .cssSemi{display:none;}.cssPropValue.editing{white-space:nowrap;}.stylePropName{font-weight:bold;padding:0 4px 4px 4px;width:50%;}.stylePropValue{width:50%;}.panelNode-net{overflow-x:hidden;}.netTable{width:100%;}.hideCategory-undefined .category-undefined,.hideCategory-html .category-html,.hideCategory-css .category-css,.hideCategory-js .category-js,.hideCategory-image .category-image,.hideCategory-xhr .category-xhr,.hideCategory-flash .category-flash,.hideCategory-txt .category-txt,.hideCategory-bin .category-bin{display:none;}.netHeadRow{background:url(https://getfirebug.com/releases/lite/latest/skin/xp/chrome://firebug/skin/group.gif) repeat-x #FFFFFF;}.netHeadCol{border-bottom:1px solid #CCCCCC;padding:2px 4px 2px 18px;font-weight:bold;}.netHeadLabel{white-space:nowrap;overflow:hidden;}.netHeaderRow{height:16px;}.netHeaderCell{cursor:pointer;-moz-user-select:none;border-bottom:1px solid #9C9C9C;padding:0 !important;font-weight:bold;background:#BBBBBB url(https://getfirebug.com/releases/lite/latest/skin/xp/chrome://firebug/skin/tableHeader.gif) repeat-x;white-space:nowrap;}.netHeaderRow > .netHeaderCell:first-child > .netHeaderCellBox{padding:2px 14px 2px 18px;}.netHeaderCellBox{padding:2px 14px 2px 10px;border-left:1px solid #D9D9D9;border-right:1px solid #9C9C9C;}.netHeaderCell:hover:active{background:#959595 url(https://getfirebug.com/releases/lite/latest/skin/xp/chrome://firebug/skin/tableHeaderActive.gif) repeat-x;}.netHeaderSorted{background:#7D93B2 url(https://getfirebug.com/releases/lite/latest/skin/xp/chrome://firebug/skin/tableHeaderSorted.gif) repeat-x;}.netHeaderSorted > .netHeaderCellBox{border-right-color:#6B7C93;background:url(https://getfirebug.com/releases/lite/latest/skin/xp/chrome://firebug/skin/arrowDown.png) no-repeat right;}.netHeaderSorted.sortedAscending > .netHeaderCellBox{background-image:url(https://getfirebug.com/releases/lite/latest/skin/xp/chrome://firebug/skin/arrowUp.png);}.netHeaderSorted:hover:active{background:#536B90 url(https://getfirebug.com/releases/lite/latest/skin/xp/chrome://firebug/skin/tableHeaderSortedActive.gif) repeat-x;}.panelNode-net .netRowHeader{display:block;}.netRowHeader{cursor:pointer;display:none;height:15px;margin-right:0 !important;}.netRow .netRowHeader{background-position:5px 1px;}.netRow[breakpoint="true"] .netRowHeader{background-image:url(https://getfirebug.com/releases/lite/latest/skin/xp/chrome://firebug/skin/breakpoint.png);}.netRow[breakpoint="true"][disabledBreakpoint="true"] .netRowHeader{background-image:url(https://getfirebug.com/releases/lite/latest/skin/xp/chrome://firebug/skin/breakpointDisabled.png);}.netRow.category-xhr:hover .netRowHeader{background-color:#F6F6F6;}#netBreakpointBar{max-width:38px;}#netHrefCol > .netHeaderCellBox{border-left:0px;}.netRow .netRowHeader{width:3px;}.netInfoRow .netRowHeader{display:table-cell;}.netTable[hiddenCols~=netHrefCol] TD[id="netHrefCol"],.netTable[hiddenCols~=netHrefCol] TD.netHrefCol,.netTable[hiddenCols~=netStatusCol] TD[id="netStatusCol"],.netTable[hiddenCols~=netStatusCol] TD.netStatusCol,.netTable[hiddenCols~=netDomainCol] TD[id="netDomainCol"],.netTable[hiddenCols~=netDomainCol] TD.netDomainCol,.netTable[hiddenCols~=netSizeCol] TD[id="netSizeCol"],.netTable[hiddenCols~=netSizeCol] TD.netSizeCol,.netTable[hiddenCols~=netTimeCol] TD[id="netTimeCol"],.netTable[hiddenCols~=netTimeCol] TD.netTimeCol{display:none;}.netRow{background:LightYellow;}.netRow.loaded{background:#FFFFFF;}.netRow.loaded:hover{background:#EFEFEF;}.netCol{padding:0;vertical-align:top;border-bottom:1px solid #EFEFEF;white-space:nowrap;height:17px;}.netLabel{width:100%;}.netStatusCol{padding-left:10px;color:rgb(128,128,128);}.responseError > .netStatusCol{color:red;}.netDomainCol{padding-left:5px;}.netSizeCol{text-align:right;padding-right:10px;}.netHrefLabel{-moz-box-sizing:padding-box;overflow:hidden;z-index:10;position:absolute;padding-left:18px;padding-top:1px;max-width:15%;font-weight:bold;}.netFullHrefLabel{display:none;-moz-user-select:none;padding-right:10px;padding-bottom:3px;max-width:100%;background:#FFFFFF;z-index:200;}.netHrefCol:hover > .netFullHrefLabel{display:block;}.netRow.loaded:hover .netCol > .netFullHrefLabel{background-color:#EFEFEF;}.useA11y .a11yShowFullLabel{display:block;background-image:none !important;border:1px solid #CBE087;background-color:LightYellow;font-family:Monaco,monospace;color:#000000;font-size:10px;z-index:2147483647;}.netSizeLabel{padding-left:6px;}.netStatusLabel,.netDomainLabel,.netSizeLabel,.netBar{padding:1px 0 2px 0 !important;}.responseError{color:red;}.hasHeaders .netHrefLabel:hover{cursor:pointer;color:blue;text-decoration:underline;}.netLoadingIcon{position:absolute;border:0;margin-left:14px;width:16px;height:16px;background:transparent no-repeat 0 0;background-image:url(https://getfirebug.com/releases/lite/latest/skin/xp/chrome://firebug/skin/loading_16.gif);display:inline-block;}.loaded .netLoadingIcon{display:none;}.netBar,.netSummaryBar{position:relative;border-right:50px solid transparent;}.netResolvingBar{position:absolute;left:0;top:0;bottom:0;background:#FFFFFF url(https://getfirebug.com/releases/lite/latest/skin/xp/chrome://firebug/skin/netBarResolving.gif) repeat-x;z-index:60;}.netConnectingBar{position:absolute;left:0;top:0;bottom:0;background:#FFFFFF url(https://getfirebug.com/releases/lite/latest/skin/xp/chrome://firebug/skin/netBarConnecting.gif) repeat-x;z-index:50;}.netBlockingBar{position:absolute;left:0;top:0;bottom:0;background:#FFFFFF url(https://getfirebug.com/releases/lite/latest/skin/xp/chrome://firebug/skin/netBarWaiting.gif) repeat-x;z-index:40;}.netSendingBar{position:absolute;left:0;top:0;bottom:0;background:#FFFFFF url(https://getfirebug.com/releases/lite/latest/skin/xp/chrome://firebug/skin/netBarSending.gif) repeat-x;z-index:30;}.netWaitingBar{position:absolute;left:0;top:0;bottom:0;background:#FFFFFF url(https://getfirebug.com/releases/lite/latest/skin/xp/chrome://firebug/skin/netBarResponded.gif) repeat-x;z-index:20;min-width:1px;}.netReceivingBar{position:absolute;left:0;top:0;bottom:0;background:#38D63B url(https://getfirebug.com/releases/lite/latest/skin/xp/chrome://firebug/skin/netBarLoading.gif) repeat-x;z-index:10;}.netWindowLoadBar,.netContentLoadBar{position:absolute;left:0;top:0;bottom:0;width:1px;background-color:red;z-index:70;opacity:0.5;display:none;margin-bottom:-1px;}.netContentLoadBar{background-color:Blue;}.netTimeLabel{-moz-box-sizing:padding-box;position:absolute;top:1px;left:100%;padding-left:6px;color:#444444;min-width:16px;}.loaded .netReceivingBar,.loaded.netReceivingBar{background:#B6B6B6 url(https://getfirebug.com/releases/lite/latest/skin/xp/chrome://firebug/skin/netBarLoaded.gif) repeat-x;border-color:#B6B6B6;}.fromCache .netReceivingBar,.fromCache.netReceivingBar{background:#D6D6D6 url(https://getfirebug.com/releases/lite/latest/skin/xp/chrome://firebug/skin/netBarCached.gif) repeat-x;border-color:#D6D6D6;}.netSummaryRow .netTimeLabel,.loaded .netTimeLabel{background:transparent;}.timeInfoTip{width:150px; height:40px}.timeInfoTipBar,.timeInfoTipEventBar{position:relative;display:block;margin:0;opacity:1;height:15px;width:4px;}.timeInfoTipEventBar{width:1px !important;}.timeInfoTipCell.startTime{padding-right:8px;}.timeInfoTipCell.elapsedTime{text-align:right;padding-right:8px;}.sizeInfoLabelCol{font-weight:bold;padding-right:10px;font-family:Lucida Grande,Tahoma,sans-serif;font-size:11px;}.sizeInfoSizeCol{font-weight:bold;}.sizeInfoDetailCol{color:gray;text-align:right;}.sizeInfoDescCol{font-style:italic;}.netSummaryRow .netReceivingBar{background:#BBBBBB;border:none;}.netSummaryLabel{color:#222222;}.netSummaryRow{background:#BBBBBB !important;font-weight:bold;}.netSummaryRow .netBar{border-right-color:#BBBBBB;}.netSummaryRow > .netCol{border-top:1px solid #999999;border-bottom:2px solid;-moz-border-bottom-colors:#EFEFEF #999999;padding-top:1px;padding-bottom:2px;}.netSummaryRow > .netHrefCol:hover{background:transparent !important;}.netCountLabel{padding-left:18px;}.netTotalSizeCol{text-align:right;padding-right:10px;}.netTotalTimeCol{text-align:right;}.netCacheSizeLabel{position:absolute;z-index:1000;left:0;top:0;}.netLimitRow{background:rgb(255,255,225) !important;font-weight:normal;color:black;font-weight:normal;}.netLimitLabel{padding-left:18px;}.netLimitRow > .netCol{border-bottom:2px solid;-moz-border-bottom-colors:#EFEFEF #999999;vertical-align:middle !important;padding-top:2px;padding-bottom:2px;}.netLimitButton{font-size:11px;padding-top:1px;padding-bottom:1px;}.netInfoCol{border-top:1px solid #EEEEEE;background:url(https://getfirebug.com/releases/lite/latest/skin/xp/chrome://firebug/skin/group.gif) repeat-x #FFFFFF;}.netInfoBody{margin:10px 0 4px 10px;}.netInfoTabs{position:relative;padding-left:17px;}.netInfoTab{position:relative;top:-3px;margin-top:10px;padding:4px 6px;border:1px solid transparent;border-bottom:none;_border:none;font-weight:bold;color:#565656;cursor:pointer;}.netInfoTabSelected{cursor:default !important;border:1px solid #D7D7D7 !important;border-bottom:none !important;-moz-border-radius:4px 4px 0 0;-webkit-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0;background-color:#FFFFFF;}.logRow-netInfo.error .netInfoTitle{color:red;}.logRow-netInfo.loading .netInfoResponseText{font-style:italic;color:#888888;}.loading .netInfoResponseHeadersTitle{display:none;}.netInfoResponseSizeLimit{font-family:Lucida Grande,Tahoma,sans-serif;padding-top:10px;font-size:11px;}.netInfoText{display:none;margin:0;border:1px solid #D7D7D7;border-right:none;padding:8px;background-color:#FFFFFF;font-family:Monaco,monospace;white-space:pre-wrap;}.netInfoTextSelected{display:block;}.netInfoParamName{padding-right:10px;font-family:Lucida Grande,Tahoma,sans-serif;font-weight:bold;vertical-align:top;text-align:right;white-space:nowrap;}.netInfoPostText .netInfoParamName{width:1px;}.netInfoParamValue{width:100%;}.netInfoHeadersText,.netInfoPostText,.netInfoPutText{padding-top:0;}.netInfoHeadersGroup,.netInfoPostParams,.netInfoPostSource{margin-bottom:4px;border-bottom:1px solid #D7D7D7;padding-top:8px;padding-bottom:2px;font-family:Lucida Grande,Tahoma,sans-serif;font-weight:bold;color:#565656;}.netInfoPostParamsTable,.netInfoPostPartsTable,.netInfoPostJSONTable,.netInfoPostXMLTable,.netInfoPostSourceTable{margin-bottom:10px;width:100%;}.netInfoPostContentType{color:#bdbdbd;padding-left:50px;font-weight:normal;}.netInfoHtmlPreview{border:0;width:100%;height:100%;}.netHeadersViewSource{color:#bdbdbd;margin-left:200px;font-weight:normal;}.netHeadersViewSource:hover{color:blue;cursor:pointer;}.netActivationRow,.netPageSeparatorRow{background:rgb(229,229,229) !important;font-weight:normal;color:black;}.netActivationLabel{background:url(https://getfirebug.com/releases/lite/latest/skin/xp/chrome://firebug/skin/infoIcon.png) no-repeat 3px 2px;padding-left:22px;}.netPageSeparatorRow{height:5px !important;}.netPageSeparatorLabel{padding-left:22px;height:5px !important;}.netPageRow{background-color:rgb(255,255,255);}.netPageRow:hover{background:#EFEFEF;}.netPageLabel{padding:1px 0 2px 18px !important;font-weight:bold;}.netActivationRow > .netCol{border-bottom:2px solid;-moz-border-bottom-colors:#EFEFEF #999999;padding-top:2px;padding-bottom:3px;}.twisty,.logRow-errorMessage > .hasTwisty > .errorTitle,.logRow-log > .objectBox-array.hasTwisty,.logRow-spy .spyHead .spyTitle,.logGroup > .logRow,.memberRow.hasChildren > .memberLabelCell > .memberLabel,.hasHeaders .netHrefLabel,.netPageRow > .netCol > .netPageTitle{background-image:url(https://getfirebug.com/releases/lite/latest/skin/xp/tree_open.gif);background-repeat:no-repeat;background-position:2px 2px;min-height:12px;}.logRow-errorMessage > .hasTwisty.opened > .errorTitle,.logRow-log > .objectBox-array.hasTwisty.opened,.logRow-spy.opened .spyHead .spyTitle,.logGroup.opened > .logRow,.memberRow.hasChildren.opened > .memberLabelCell > .memberLabel,.nodeBox.highlightOpen > .nodeLabel > .twisty,.nodeBox.open > .nodeLabel > .twisty,.netRow.opened > .netCol > .netHrefLabel,.netPageRow.opened > .netCol > .netPageTitle{background-image:url(https://getfirebug.com/releases/lite/latest/skin/xp/tree_close.gif);}.twisty{background-position:4px 4px;}* html .logRow-spy .spyHead .spyTitle,* html .logGroup .logGroupLabel,* html .hasChildren .memberLabelCell .memberLabel,* html .hasHeaders .netHrefLabel{background-image:url(https://getfirebug.com/releases/lite/latest/skin/xp/tree_open.gif);background-repeat:no-repeat;background-position:2px 2px;}* html .opened .spyHead .spyTitle,* html .opened .logGroupLabel,* html .opened .memberLabelCell .memberLabel{background-image:url(https://getfirebug.com/releases/lite/latest/skin/xp/tree_close.gif);background-repeat:no-repeat;background-position:2px 2px;}.panelNode-console{overflow-x:hidden;}.objectLink{text-decoration:none;}.objectLink:hover{cursor:pointer;text-decoration:underline;}.logRow{position:relative;margin:0;border-bottom:1px solid #D7D7D7;padding:2px 4px 1px 6px;background-color:#FFFFFF;overflow:hidden !important;}.useA11y .logRow:focus{border-bottom:1px solid #000000 !important;outline:none !important;background-color:#FFFFAD !important;}.useA11y .logRow:focus a.objectLink-sourceLink{background-color:#FFFFAD;}.useA11y .a11yFocus:focus,.useA11y .objectBox:focus{outline:2px solid #FF9933;background-color:#FFFFAD;}.useA11y .objectBox-null:focus,.useA11y .objectBox-undefined:focus{background-color:#888888 !important;}.useA11y .logGroup.opened > .logRow{border-bottom:1px solid #ffffff;}.logGroup{background:url(https://getfirebug.com/releases/lite/latest/skin/xp/group.gif) repeat-x #FFFFFF;padding:0 !important;border:none !important;}.logGroupBody{display:none;margin-left:16px;border-left:1px solid #D7D7D7;border-top:1px solid #D7D7D7;background:#FFFFFF;}.logGroup > .logRow{background-color:transparent !important;font-weight:bold;}.logGroup.opened > .logRow{border-bottom:none;}.logGroup.opened > .logGroupBody{display:block;}.logRow-command > .objectBox-text{font-family:Monaco,monospace;color:#0000FF;white-space:pre-wrap;}.logRow-info,.logRow-warn,.logRow-error,.logRow-assert,.logRow-warningMessage,.logRow-errorMessage{padding-left:22px;background-repeat:no-repeat;background-position:4px 2px;}.logRow-assert,.logRow-warningMessage,.logRow-errorMessage{padding-top:0;padding-bottom:0;}.logRow-info,.logRow-info .objectLink-sourceLink{background-color:#FFFFFF;}.logRow-warn,.logRow-warningMessage,.logRow-warn .objectLink-sourceLink,.logRow-warningMessage .objectLink-sourceLink{background-color:cyan;}.logRow-error,.logRow-assert,.logRow-errorMessage,.logRow-error .objectLink-sourceLink,.logRow-errorMessage .objectLink-sourceLink{background-color:LightYellow;}.logRow-error,.logRow-assert,.logRow-errorMessage{color:#FF0000;}.logRow-info{}.logRow-warn,.logRow-warningMessage{}.logRow-error,.logRow-assert,.logRow-errorMessage{}.objectBox-string,.objectBox-text,.objectBox-number,.objectLink-element,.objectLink-textNode,.objectLink-function,.objectBox-stackTrace,.objectLink-profile{font-family:Monaco,monospace;}.objectBox-string,.objectBox-text,.objectLink-textNode{white-space:pre-wrap;}.objectBox-number,.objectLink-styleRule,.objectLink-element,.objectLink-textNode{color:#000088;}.objectBox-string{color:#FF0000;}.objectLink-function,.objectBox-stackTrace,.objectLink-profile{color:DarkGreen;}.objectBox-null,.objectBox-undefined{padding:0 2px;border:1px solid #666666;background-color:#888888;color:#FFFFFF;}.objectBox-exception{padding:0 2px 0 18px;color:red;}.objectLink-sourceLink{position:absolute;right:4px;top:2px;padding-left:8px;font-family:Lucida Grande,sans-serif;font-weight:bold;color:#0000FF;}.errorTitle{margin-top:0px;margin-bottom:1px;padding-top:2px;padding-bottom:2px;}.errorTrace{margin-left:17px;}.errorSourceBox{margin:2px 0;}.errorSource-none{display:none;}.errorSource-syntax > .errorBreak{visibility:hidden;}.errorSource{cursor:pointer;font-family:Monaco,monospace;color:DarkGreen;}.errorSource:hover{text-decoration:underline;}.errorBreak{cursor:pointer;display:none;margin:0 6px 0 0;width:13px;height:14px;vertical-align:bottom;opacity:0.1;}.hasBreakSwitch .errorBreak{display:inline;}.breakForError .errorBreak{opacity:1;}.assertDescription{margin:0;}.logRow-profile > .logRow > .objectBox-text{font-family:Lucida Grande,Tahoma,sans-serif;color:#000000;}.logRow-profile > .logRow > .objectBox-text:last-child{color:#555555;font-style:italic;}.logRow-profile.opened > .logRow{padding-bottom:4px;}.profilerRunning > .logRow{padding-left:22px !important;}.profileSizer{width:100%;overflow-x:auto;overflow-y:scroll;}.profileTable{border-bottom:1px solid #D7D7D7;padding:0 0 4px 0;}.profileTable tr[odd="1"]{background-color:#F5F5F5;vertical-align:middle;}.profileTable a{vertical-align:middle;}.profileTable td{padding:1px 4px 0 4px;}.headerCell{cursor:pointer;-moz-user-select:none;border-bottom:1px solid #9C9C9C;padding:0 !important;font-weight:bold;}.headerCellBox{padding:2px 4px;border-left:1px solid #D9D9D9;border-right:1px solid #9C9C9C;}.headerCell:hover:active{}.headerSorted{}.headerSorted > .headerCellBox{border-right-color:#6B7C93;}.headerSorted.sortedAscending > .headerCellBox{}.headerSorted:hover:active{}.linkCell{text-align:right;}.linkCell > .objectLink-sourceLink{position:static;}.logRow-stackTrace{padding-top:0;background:#f8f8f8;}.logRow-stackTrace > .objectBox-stackFrame{position:relative;padding-top:2px;}.objectLink-object{font-family:Lucida Grande,sans-serif;font-weight:bold;color:DarkGreen;white-space:pre-wrap;}.objectProp-object{color:DarkGreen;}.objectProps{color:#000;font-weight:normal;}.objectPropName{color:#777;}.objectProps .objectProp-string{color:#f55;}.objectProps .objectProp-number{color:#55a;}.objectProps .objectProp-object{color:#585;}.selectorTag,.selectorId,.selectorClass{font-family:Monaco,monospace;font-weight:normal;}.selectorTag{color:#0000FF;}.selectorId{color:DarkBlue;}.selectorClass{color:red;}.selectorHidden > .selectorTag{color:#5F82D9;}.selectorHidden > .selectorId{color:#888888;}.selectorHidden > .selectorClass{color:#D86060;}.selectorValue{font-family:Lucida Grande,sans-serif;font-style:italic;color:#555555;}.panelNode.searching .logRow{display:none;}.logRow.matched{display:block !important;}.logRow.matching{position:absolute;left:-1000px;top:-1000px;max-width:0;max-height:0;overflow:hidden;}.objectLeftBrace,.objectRightBrace,.objectEqual,.objectComma,.arrayLeftBracket,.arrayRightBracket,.arrayComma{font-family:Monaco,monospace;}.objectLeftBrace,.objectRightBrace,.arrayLeftBracket,.arrayRightBracket{font-weight:bold;}.objectLeftBrace,.arrayLeftBracket{margin-right:4px;}.objectRightBrace,.arrayRightBracket{margin-left:4px;}.logRow-dir{padding:0;}.logRow-errorMessage .hasTwisty .errorTitle,.logRow-spy .spyHead .spyTitle,.logGroup .logRow{cursor:pointer;padding-left:18px;background-repeat:no-repeat;background-position:3px 3px;}.logRow-errorMessage > .hasTwisty > .errorTitle{background-position:2px 3px;}.logRow-errorMessage > .hasTwisty > .errorTitle:hover,.logRow-spy .spyHead .spyTitle:hover,.logGroup > .logRow:hover{text-decoration:underline;}.logRow-spy{padding:0 !important;}.logRow-spy,.logRow-spy .objectLink-sourceLink{background:url(https://getfirebug.com/releases/lite/latest/skin/xp/group.gif) repeat-x #FFFFFF;padding-right:4px;right:0;}.logRow-spy.opened{padding-bottom:4px;border-bottom:none;}.spyTitle{color:#000000;font-weight:bold;-moz-box-sizing:padding-box;overflow:hidden;z-index:100;padding-left:18px;}.spyCol{padding:0;white-space:nowrap;height:16px;}.spyTitleCol:hover > .objectLink-sourceLink,.spyTitleCol:hover > .spyTime,.spyTitleCol:hover > .spyStatus,.spyTitleCol:hover > .spyTitle{display:none;}.spyFullTitle{display:none;-moz-user-select:none;max-width:100%;background-color:Transparent;}.spyTitleCol:hover > .spyFullTitle{display:block;}.spyStatus{padding-left:10px;color:rgb(128,128,128);}.spyTime{margin-left:4px;margin-right:4px;color:rgb(128,128,128);}.spyIcon{margin-right:4px;margin-left:4px;width:16px;height:16px;vertical-align:middle;background:transparent no-repeat 0 0;display:none;}.loading .spyHead .spyRow .spyIcon{background-image:url(https://getfirebug.com/releases/lite/latest/skin/xp/loading_16.gif);display:block;}.logRow-spy.loaded:not(.error) .spyHead .spyRow .spyIcon{width:0;margin:0;}.logRow-spy.error .spyHead .spyRow .spyIcon{background-image:url(https://getfirebug.com/releases/lite/latest/skin/xp/errorIcon-sm.png);display:block;background-position:2px 2px;}.logRow-spy .spyHead .netInfoBody{display:none;}.logRow-spy.opened .spyHead .netInfoBody{margin-top:10px;display:block;}.logRow-spy.error .spyTitle,.logRow-spy.error .spyStatus,.logRow-spy.error .spyTime{color:red;}.logRow-spy.loading .spyResponseText{font-style:italic;color:#888888;}.caption{font-family:Lucida Grande,Tahoma,sans-serif;font-weight:bold;color:#444444;}.warning{padding:10px;font-family:Lucida Grande,Tahoma,sans-serif;font-weight:bold;color:#888888;}.panelNode-dom{overflow-x:hidden !important;}.domTable{font-size:1em;width:100%;table-layout:fixed;background:#fff;}.domTableIE{width:auto;}.memberLabelCell{padding:2px 0 2px 0;vertical-align:top;}.memberValueCell{padding:1px 0 1px 5px;display:block;overflow:hidden;}.memberLabel{display:block;cursor:default;-moz-user-select:none;overflow:hidden;padding-left:18px;background-color:#FFFFFF;text-decoration:none;}.memberRow.hasChildren .memberLabelCell .memberLabel:hover{cursor:pointer;color:blue;text-decoration:underline;}.userLabel{color:#000000;font-weight:bold;}.userClassLabel{color:#E90000;font-weight:bold;}.userFunctionLabel{color:#025E2A;font-weight:bold;}.domLabel{color:#000000;}.domFunctionLabel{color:#025E2A;}.ordinalLabel{color:SlateBlue;font-weight:bold;}.scopesRow{padding:2px 18px;background-color:LightYellow;border-bottom:5px solid #BEBEBE;color:#666666;}.scopesLabel{background-color:LightYellow;}.watchEditCell{padding:2px 18px;background-color:LightYellow;border-bottom:1px solid #BEBEBE;color:#666666;}.editor-watchNewRow,.editor-memberRow{font-family:Monaco,monospace !important;}.editor-memberRow{padding:1px 0 !important;}.editor-watchRow{padding-bottom:0 !important;}.watchRow > .memberLabelCell{font-family:Monaco,monospace;padding-top:1px;padding-bottom:1px;}.watchRow > .memberLabelCell > .memberLabel{background-color:transparent;}.watchRow > .memberValueCell{padding-top:2px;padding-bottom:2px;}.watchRow > .memberLabelCell,.watchRow > .memberValueCell{background-color:#F5F5F5;border-bottom:1px solid #BEBEBE;}.watchToolbox{z-index:2147483647;position:absolute;right:0;padding:1px 2px;}#fbConsole{overflow-x:hidden !important;}#fbCSS{font:1em Monaco,monospace;padding:0 7px;}#fbstylesheetButtons select,#fbScriptButtons select{font:11px Lucida Grande,Tahoma,sans-serif;margin-top:1px;padding-left:3px;background:#fafafa;border:1px inset #fff;width:220px;outline:none;}.Selector{margin-top:10px}.CSSItem{margin-left:4%}.CSSText{padding-left:20px;}.CSSProperty{color:#005500;}.CSSValue{padding-left:5px; color:#000088;}#fbHTMLStatusBar{display:inline;}.fbToolbarButtons{display:none;}.fbStatusSeparator{display:block;float:left;padding-top:4px;}#fbStatusBarBox{display:none;}#fbToolbarContent{display:block;position:absolute;_position:absolute;top:0;padding-top:4px;height:23px;clip:rect(0,2048px,27px,0);}.fbTabMenuTarget{display:none !important;float:left;width:10px;height:10px;margin-top:6px;background:url(https://getfirebug.com/releases/lite/latest/skin/xp/tabMenuTarget.png);}.fbTabMenuTarget:hover{background:url(https://getfirebug.com/releases/lite/latest/skin/xp/tabMenuTargetHover.png);}.fbShadow{float:left;background:url(https://getfirebug.com/releases/lite/latest/skin/xp/shadowAlpha.png) no-repeat bottom right !important;background:url(https://getfirebug.com/releases/lite/latest/skin/xp/shadow2.gif) no-repeat bottom right;margin:10px 0 0 10px !important;margin:10px 0 0 5px;}.fbShadowContent{display:block;position:relative;background-color:#fff;border:1px solid #a9a9a9;top:-6px;left:-6px;}.fbMenu{display:none;position:absolute;font-size:11px;line-height:13px;z-index:2147483647;}.fbMenuContent{padding:2px;}.fbMenuSeparator{display:block;position:relative;padding:1px 18px 0;text-decoration:none;color:#000;cursor:default;background:#ACA899;margin:4px 0;}.fbMenuOption{display:block;position:relative;padding:2px 18px;text-decoration:none;color:#000;cursor:default;}.fbMenuOption:hover{color:#fff;background:#316AC5;}.fbMenuGroup{background:transparent url(https://getfirebug.com/releases/lite/latest/skin/xp/tabMenuPin.png) no-repeat right 0;}.fbMenuGroup:hover{background:#316AC5 url(https://getfirebug.com/releases/lite/latest/skin/xp/tabMenuPin.png) no-repeat right -17px;}.fbMenuGroupSelected{color:#fff;background:#316AC5 url(https://getfirebug.com/releases/lite/latest/skin/xp/tabMenuPin.png) no-repeat right -17px;}.fbMenuChecked{background:transparent url(https://getfirebug.com/releases/lite/latest/skin/xp/tabMenuCheckbox.png) no-repeat 4px 0;}.fbMenuChecked:hover{background:#316AC5 url(https://getfirebug.com/releases/lite/latest/skin/xp/tabMenuCheckbox.png) no-repeat 4px -17px;}.fbMenuRadioSelected{background:transparent url(https://getfirebug.com/releases/lite/latest/skin/xp/tabMenuRadio.png) no-repeat 4px 0;}.fbMenuRadioSelected:hover{background:#316AC5 url(https://getfirebug.com/releases/lite/latest/skin/xp/tabMenuRadio.png) no-repeat 4px -17px;}.fbMenuShortcut{padding-right:85px;}.fbMenuShortcutKey{position:absolute;right:0;top:2px;width:77px;}#fbFirebugMenu{top:22px;left:0;}.fbMenuDisabled{color:#ACA899 !important;}#fbFirebugSettingsMenu{left:245px;top:99px;}#fbConsoleMenu{top:42px;left:48px;}.fbIconButton{display:block;}.fbIconButton{display:block;}.fbIconButton{display:block;float:left;height:20px;width:20px;color:#000;margin-right:2px;text-decoration:none;cursor:default;}.fbIconButton:hover{position:relative;top:-1px;left:-1px;margin-right:0;_margin-right:1px;color:#333;border:1px solid #fff;border-bottom:1px solid #bbb;border-right:1px solid #bbb;}.fbIconPressed{position:relative;margin-right:0;_margin-right:1px;top:0 !important;left:0 !important;height:19px;color:#333 !important;border:1px solid #bbb !important;border-bottom:1px solid #cfcfcf !important;border-right:1px solid #ddd !important;}#fbErrorPopup{position:absolute;right:0;bottom:0;height:19px;width:75px;background:url(https://getfirebug.com/releases/lite/latest/skin/xp/sprite.png) #f1f2ee 0 0;z-index:999;}#fbErrorPopupContent{position:absolute;right:0;top:1px;height:18px;width:75px;_width:74px;border-left:1px solid #aca899;}#fbErrorIndicator{position:absolute;top:2px;right:5px;}.fbBtnInspectActive{background:#aaa;color:#fff !important;}.fbBody{margin:0;padding:0;overflow:hidden;font-family:Lucida Grande,Tahoma,sans-serif;font-size:11px;background:#fff;}.clear{clear:both;}#fbMiniChrome{display:none;right:0;height:27px;background:url(https://getfirebug.com/releases/lite/latest/skin/xp/sprite.png) #f1f2ee 0 0;margin-left:1px;}#fbMiniContent{display:block;position:relative;left:-1px;right:0;top:1px;height:25px;border-left:1px solid #aca899;}#fbToolbarSearch{float:right;border:1px solid #ccc;margin:0 5px 0 0;background:#fff url(https://getfirebug.com/releases/lite/latest/skin/xp/search.png) no-repeat 4px 2px !important;background:#fff url(https://getfirebug.com/releases/lite/latest/skin/xp/search.gif) no-repeat 4px 2px;padding-left:20px;font-size:11px;}#fbToolbarErrors{float:right;margin:1px 4px 0 0;font-size:11px;}#fbLeftToolbarErrors{float:left;margin:7px 0px 0 5px;font-size:11px;}.fbErrors{padding-left:20px;height:14px;background:url(https://getfirebug.com/releases/lite/latest/skin/xp/errorIcon.png) no-repeat !important;background:url(https://getfirebug.com/releases/lite/latest/skin/xp/errorIcon.gif) no-repeat;color:#f00;font-weight:bold;}#fbMiniErrors{display:inline;display:none;float:right;margin:5px 2px 0 5px;}#fbMiniIcon{float:right;margin:3px 4px 0;height:20px;width:20px;float:right;background:url(https://getfirebug.com/releases/lite/latest/skin/xp/sprite.png) 0 -135px;cursor:pointer;}#fbChrome{font-family:Lucida Grande,Tahoma,sans-serif;font-size:11px;position:absolute;_position:static;top:0;left:0;height:100%;width:100%;border-collapse:collapse;border-spacing:0;background:#fff;overflow:hidden;}#fbChrome > tbody > tr > td{padding:0;}#fbTop{height:49px;}#fbToolbar{background:url(https://getfirebug.com/releases/lite/latest/skin/xp/sprite.png) #f1f2ee 0 0;height:27px;font-size:11px;line-height:13px;}#fbPanelBarBox{background:url(https://getfirebug.com/releases/lite/latest/skin/xp/sprite.png) #dbd9c9 0 -27px;height:22px;}#fbContent{height:100%;vertical-align:top;}#fbBottom{height:18px;background:#fff;}#fbToolbarIcon{float:left;padding:0 5px 0;}#fbToolbarIcon a{background:url(https://getfirebug.com/releases/lite/latest/skin/xp/sprite.png) 0 -135px;}#fbToolbarButtons{padding:0 2px 0 5px;}#fbToolbarButtons{padding:0 2px 0 5px;}.fbButton{text-decoration:none;display:block;float:left;color:#000;padding:4px 6px 4px 7px;cursor:default;}.fbButton:hover{color:#333;background:#f5f5ef url(https://getfirebug.com/releases/lite/latest/skin/xp/buttonBg.png);padding:3px 5px 3px 6px;border:1px solid #fff;border-bottom:1px solid #bbb;border-right:1px solid #bbb;}.fbBtnPressed{background:#e3e3db url(https://getfirebug.com/releases/lite/latest/skin/xp/buttonBgHover.png) !important;padding:3px 4px 2px 6px !important;margin:1px 0 0 1px !important;border:1px solid #ACA899 !important;border-color:#ACA899 #ECEBE3 #ECEBE3 #ACA899 !important;}#fbStatusBarBox{top:4px;cursor:default;}.fbToolbarSeparator{overflow:hidden;border:1px solid;border-color:transparent #fff transparent #777;_border-color:#eee #fff #eee #777;height:7px;margin:6px 3px;float:left;}.fbBtnSelected{font-weight:bold;}.fbStatusBar{color:#aca899;}.fbStatusBar a{text-decoration:none;color:black;}.fbStatusBar a:hover{color:blue;cursor:pointer;}#fbWindowButtons{position:absolute;white-space:nowrap;right:0;top:0;height:17px;width:48px;padding:5px;z-index:6;background:url(https://getfirebug.com/releases/lite/latest/skin/xp/sprite.png) #f1f2ee 0 0;}#fbPanelBar1{width:1024px; z-index:8;left:0;white-space:nowrap;background:url(https://getfirebug.com/releases/lite/latest/skin/xp/sprite.png) #dbd9c9 0 -27px;position:absolute;left:4px;}#fbPanelBar2Box{background:url(https://getfirebug.com/releases/lite/latest/skin/xp/sprite.png) #dbd9c9 0 -27px;position:absolute;height:22px;width:300px; z-index:9;right:0;}#fbPanelBar2{position:absolute;width:290px; height:22px;padding-left:4px;}.fbPanel{display:none;}#fbPanelBox1,#fbPanelBox2{max-height:inherit;height:100%;font-size:1em;}#fbPanelBox2{background:#fff;}#fbPanelBox2{width:300px;background:#fff;}#fbPanel2{margin-left:6px;background:#fff;}#fbLargeCommandLine{display:none;position:absolute;z-index:9;top:27px;right:0;width:294px;height:201px;border-width:0;margin:0;padding:2px 0 0 2px;resize:none;outline:none;font-size:11px;overflow:auto;border-top:1px solid #B9B7AF;_right:-1px;_border-left:1px solid #fff;}#fbLargeCommandButtons{display:none;background:#ECE9D8;bottom:0;right:0;width:294px;height:21px;padding-top:1px;position:fixed;border-top:1px solid #ACA899;z-index:9;}#fbSmallCommandLineIcon{background:url(https://getfirebug.com/releases/lite/latest/skin/xp/down.png) no-repeat;position:absolute;right:2px;bottom:3px;z-index:99;}#fbSmallCommandLineIcon:hover{background:url(https://getfirebug.com/releases/lite/latest/skin/xp/downHover.png) no-repeat;}.hide{overflow:hidden !important;position:fixed !important;display:none !important;visibility:hidden !important;}#fbCommand{height:18px;}#fbCommandBox{position:fixed;_position:absolute;width:100%;height:18px;bottom:0;overflow:hidden;z-index:9;background:#fff;border:0;border-top:1px solid #ccc;}#fbCommandIcon{position:absolute;color:#00f;top:2px;left:6px;display:inline;font:11px Monaco,monospace;z-index:10;}#fbCommandLine{position:absolute;width:100%;top:0;left:0;border:0;margin:0;padding:2px 0 2px 32px;font:11px Monaco,monospace;z-index:9;outline:none;}#fbLargeCommandLineIcon{background:url(https://getfirebug.com/releases/lite/latest/skin/xp/up.png) no-repeat;position:absolute;right:1px;bottom:1px;z-index:10;}#fbLargeCommandLineIcon:hover{background:url(https://getfirebug.com/releases/lite/latest/skin/xp/upHover.png) no-repeat;}div.fbFitHeight{overflow:auto;position:relative;}.fbSmallButton{overflow:hidden;width:16px;height:16px;display:block;text-decoration:none;cursor:default;}#fbWindowButtons .fbSmallButton{float:right;}#fbWindow_btClose{background:url(https://getfirebug.com/releases/lite/latest/skin/xp/min.png);}#fbWindow_btClose:hover{background:url(https://getfirebug.com/releases/lite/latest/skin/xp/minHover.png);}#fbWindow_btDetach{background:url(https://getfirebug.com/releases/lite/latest/skin/xp/detach.png);}#fbWindow_btDetach:hover{background:url(https://getfirebug.com/releases/lite/latest/skin/xp/detachHover.png);}#fbWindow_btDeactivate{background:url(https://getfirebug.com/releases/lite/latest/skin/xp/off.png);}#fbWindow_btDeactivate:hover{background:url(https://getfirebug.com/releases/lite/latest/skin/xp/offHover.png);}.fbTab{text-decoration:none;display:none;float:left;width:auto;float:left;cursor:default;font-family:Lucida Grande,Tahoma,sans-serif;font-size:11px;line-height:13px;font-weight:bold;height:22px;color:#565656;}.fbPanelBar span{float:left;}.fbPanelBar .fbTabL,.fbPanelBar .fbTabR{height:22px;width:8px;}.fbPanelBar .fbTabText{padding:4px 1px 0;}a.fbTab:hover{background:url(https://getfirebug.com/releases/lite/latest/skin/xp/sprite.png) 0 -73px;}a.fbTab:hover .fbTabL{background:url(https://getfirebug.com/releases/lite/latest/skin/xp/sprite.png) -16px -96px;}a.fbTab:hover .fbTabR{background:url(https://getfirebug.com/releases/lite/latest/skin/xp/sprite.png) -24px -96px;}.fbSelectedTab{background:url(https://getfirebug.com/releases/lite/latest/skin/xp/sprite.png) #f1f2ee 0 -50px !important;color:#000;}.fbSelectedTab .fbTabL{background:url(https://getfirebug.com/releases/lite/latest/skin/xp/sprite.png) 0 -96px !important;}.fbSelectedTab .fbTabR{background:url(https://getfirebug.com/releases/lite/latest/skin/xp/sprite.png) -8px -96px !important;}#fbHSplitter{position:fixed;_position:absolute;left:0;top:0;width:100%;height:5px;overflow:hidden;cursor:n-resize !important;background:url(https://getfirebug.com/releases/lite/latest/skin/xp/pixel_transparent.gif);z-index:9;}#fbHSplitter.fbOnMovingHSplitter{height:100%;z-index:100;}.fbVSplitter{background:#ece9d8;color:#000;border:1px solid #716f64;border-width:0 1px;border-left-color:#aca899;width:4px;cursor:e-resize;overflow:hidden;right:294px;text-decoration:none;z-index:10;position:absolute;height:100%;top:27px;}div.lineNo{font:1em/1.4545em Monaco,monospace;position:relative;float:left;top:0;left:0;margin:0 5px 0 0;padding:0 5px 0 10px;background:#eee;color:#888;border-right:1px solid #ccc;text-align:right;}.sourceBox{position:absolute;}.sourceCode{font:1em Monaco,monospace;overflow:hidden;white-space:pre;display:inline;}.nodeControl{margin-top:3px;margin-left:-14px;float:left;width:9px;height:9px;overflow:hidden;cursor:default;background:url(https://getfirebug.com/releases/lite/latest/skin/xp/tree_open.gif);_float:none;_display:inline;_position:absolute;}div.nodeMaximized{background:url(https://getfirebug.com/releases/lite/latest/skin/xp/tree_close.gif);}div.objectBox-element{padding:1px 3px;}.objectBox-selector{cursor:default;}.selectedElement{background:highlight;color:#fff !important;}.selectedElement span{color:#fff !important;}* html .selectedElement{position:relative;}@media screen and (-webkit-min-device-pixel-ratio:0){.selectedElement{background:#316AC5;color:#fff !important;}}.logRow *{font-size:1em;}.logRow{position:relative;border-bottom:1px solid #D7D7D7;padding:2px 4px 1px 6px;zbackground-color:#FFFFFF;}.logRow-command{font-family:Monaco,monospace;color:blue;}.objectBox-string,.objectBox-text,.objectBox-number,.objectBox-function,.objectLink-element,.objectLink-textNode,.objectLink-function,.objectBox-stackTrace,.objectLink-profile{font-family:Monaco,monospace;}.objectBox-null{padding:0 2px;border:1px solid #666666;background-color:#888888;color:#FFFFFF;}.objectBox-string{color:red;}.objectBox-number{color:#000088;}.objectBox-function{color:DarkGreen;}.objectBox-object{color:DarkGreen;font-weight:bold;font-family:Lucida Grande,sans-serif;}.objectBox-array{color:#000;}.logRow-info,.logRow-error,.logRow-warn{background:#fff no-repeat 2px 2px;padding-left:20px;padding-bottom:3px;}.logRow-info{background-image:url(https://getfirebug.com/releases/lite/latest/skin/xp/infoIcon.png) !important;background-image:url(https://getfirebug.com/releases/lite/latest/skin/xp/infoIcon.gif);}.logRow-warn{background-color:cyan;background-image:url(https://getfirebug.com/releases/lite/latest/skin/xp/warningIcon.png) !important;background-image:url(https://getfirebug.com/releases/lite/latest/skin/xp/warningIcon.gif);}.logRow-error{background-color:LightYellow;background-image:url(https://getfirebug.com/releases/lite/latest/skin/xp/errorIcon.png) !important;background-image:url(https://getfirebug.com/releases/lite/latest/skin/xp/errorIcon.gif);color:#f00;}.errorMessage{vertical-align:top;color:#f00;}.objectBox-sourceLink{position:absolute;right:4px;top:2px;padding-left:8px;font-family:Lucida Grande,sans-serif;font-weight:bold;color:#0000FF;}.selectorTag,.selectorId,.selectorClass{font-family:Monaco,monospace;font-weight:normal;}.selectorTag{color:#0000FF;}.selectorId{color:DarkBlue;}.selectorClass{color:red;}.objectBox-element{font-family:Monaco,monospace;color:#000088;}.nodeChildren{padding-left:26px;}.nodeTag{color:blue;cursor:pointer;}.nodeValue{color:#FF0000;font-weight:normal;}.nodeText,.nodeComment{margin:0 2px;vertical-align:top;}.nodeText{color:#333333;font-family:Monaco,monospace;}.nodeComment{color:DarkGreen;}.nodeHidden,.nodeHidden *{color:#888888;}.nodeHidden .nodeTag{color:#5F82D9;}.nodeHidden .nodeValue{color:#D86060;}.selectedElement .nodeHidden,.selectedElement .nodeHidden *{color:SkyBlue !important;}.log-object{}.property{position:relative;clear:both;height:15px;}.propertyNameCell{vertical-align:top;float:left;width:28%;position:absolute;left:0;z-index:0;}.propertyValueCell{float:right;width:68%;background:#fff;position:absolute;padding-left:5px;display:table-cell;right:0;z-index:1;}.propertyName{font-weight:bold;}.FirebugPopup{height:100% !important;}.FirebugPopup #fbWindowButtons{display:none !important;}.FirebugPopup #fbHSplitter{display:none !important;}', - HTML: '<table id="fbChrome" cellpadding="0" cellspacing="0" border="0"><tbody><tr><td id="fbTop" colspan="2"><div id="fbWindowButtons"><a id="fbWindow_btDeactivate" class="fbSmallButton fbHover" title="Deactivate Firebug for this web page"> </a><a id="fbWindow_btDetach" class="fbSmallButton fbHover" title="Open Firebug in popup window"> </a><a id="fbWindow_btClose" class="fbSmallButton fbHover" title="Minimize Firebug"> </a></div><div id="fbToolbar"><div id="fbToolbarContent"><span id="fbToolbarIcon"><a id="fbFirebugButton" class="fbIconButton" class="fbHover" target="_blank"> </a></span><span id="fbToolbarButtons"><span id="fbFixedButtons"><a id="fbChrome_btInspect" class="fbButton fbHover" title="Click an element in the page to inspect">Inspect</a></span><span id="fbConsoleButtons" class="fbToolbarButtons"><a id="fbConsole_btClear" class="fbButton fbHover" title="Clear the console">Clear</a></span></span><span id="fbStatusBarBox"><span class="fbToolbarSeparator"></span></span></div></div><div id="fbPanelBarBox"><div id="fbPanelBar1" class="fbPanelBar"><a id="fbConsoleTab" class="fbTab fbHover"><span class="fbTabL"></span><span class="fbTabText">Console</span><span class="fbTabMenuTarget"></span><span class="fbTabR"></span></a><a id="fbHTMLTab" class="fbTab fbHover"><span class="fbTabL"></span><span class="fbTabText">HTML</span><span class="fbTabR"></span></a><a class="fbTab fbHover"><span class="fbTabL"></span><span class="fbTabText">CSS</span><span class="fbTabR"></span></a><a class="fbTab fbHover"><span class="fbTabL"></span><span class="fbTabText">Script</span><span class="fbTabR"></span></a><a class="fbTab fbHover"><span class="fbTabL"></span><span class="fbTabText">DOM</span><span class="fbTabR"></span></a></div><div id="fbPanelBar2Box" class="hide"><div id="fbPanelBar2" class="fbPanelBar"></div></div></div><div id="fbHSplitter"> </div></td></tr><tr id="fbContent"><td id="fbPanelBox1"><div id="fbPanel1" class="fbFitHeight"><div id="fbConsole" class="fbPanel"></div><div id="fbHTML" class="fbPanel"></div></div></td><td id="fbPanelBox2" class="hide"><div id="fbVSplitter" class="fbVSplitter"> </div><div id="fbPanel2" class="fbFitHeight"><div id="fbHTML_Style" class="fbPanel"></div><div id="fbHTML_Layout" class="fbPanel"></div><div id="fbHTML_DOM" class="fbPanel"></div></div><textarea id="fbLargeCommandLine" class="fbFitHeight"></textarea><div id="fbLargeCommandButtons"><a id="fbCommand_btRun" class="fbButton fbHover">Run</a><a id="fbCommand_btClear" class="fbButton fbHover">Clear</a><a id="fbSmallCommandLineIcon" class="fbSmallButton fbHover"></a></div></td></tr><tr id="fbBottom" class="hide"><td id="fbCommand" colspan="2"><div id="fbCommandBox"><div id="fbCommandIcon">>>></div><input id="fbCommandLine" name="fbCommandLine" type="text"/><a id="fbLargeCommandLineIcon" class="fbSmallButton fbHover"></a></div></td></tr></tbody></table><span id="fbMiniChrome"><span id="fbMiniContent"><span id="fbMiniIcon" title="Open Firebug Lite"></span><span id="fbMiniErrors" class="fbErrors"></span></span></span>' -}; - -// ************************************************************************************************ -}}); - -// ************************************************************************************************ -FBL.initialize(); -// ************************************************************************************************ - -})();
\ No newline at end of file diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/json-js/json2.js b/ecomp-portal-FE/client/bower_components/lodash/vendor/json-js/json2.js deleted file mode 100644 index 58384577..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/json-js/json2.js +++ /dev/null @@ -1,519 +0,0 @@ -/* - json2.js - 2015-05-03 - - Public Domain. - - NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. - - See http://www.JSON.org/js.html - - - This code should be minified before deployment. - See http://javascript.crockford.com/jsmin.html - - USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO - NOT CONTROL. - - - This file creates a global JSON object containing two methods: stringify - and parse. This file is provides the ES5 JSON capability to ES3 systems. - If a project might run on IE8 or earlier, then this file should be included. - This file does nothing on ES5 systems. - - JSON.stringify(value, replacer, space) - value any JavaScript value, usually an object or array. - - replacer an optional parameter that determines how object - values are stringified for objects. It can be a - function or an array of strings. - - space an optional parameter that specifies the indentation - of nested structures. If it is omitted, the text will - be packed without extra whitespace. If it is a number, - it will specify the number of spaces to indent at each - level. If it is a string (such as '\t' or ' '), - it contains the characters used to indent at each level. - - This method produces a JSON text from a JavaScript value. - - When an object value is found, if the object contains a toJSON - method, its toJSON method will be called and the result will be - stringified. A toJSON method does not serialize: it returns the - value represented by the name/value pair that should be serialized, - or undefined if nothing should be serialized. The toJSON method - will be passed the key associated with the value, and this will be - bound to the value - - For example, this would serialize Dates as ISO strings. - - Date.prototype.toJSON = function (key) { - function f(n) { - // Format integers to have at least two digits. - return n < 10 - ? '0' + n - : n; - } - - return this.getUTCFullYear() + '-' + - f(this.getUTCMonth() + 1) + '-' + - f(this.getUTCDate()) + 'T' + - f(this.getUTCHours()) + ':' + - f(this.getUTCMinutes()) + ':' + - f(this.getUTCSeconds()) + 'Z'; - }; - - You can provide an optional replacer method. It will be passed the - key and value of each member, with this bound to the containing - object. The value that is returned from your method will be - serialized. If your method returns undefined, then the member will - be excluded from the serialization. - - If the replacer parameter is an array of strings, then it will be - used to select the members to be serialized. It filters the results - such that only members with keys listed in the replacer array are - stringified. - - Values that do not have JSON representations, such as undefined or - functions, will not be serialized. Such values in objects will be - dropped; in arrays they will be replaced with null. You can use - a replacer function to replace those with JSON values. - JSON.stringify(undefined) returns undefined. - - The optional space parameter produces a stringification of the - value that is filled with line breaks and indentation to make it - easier to read. - - If the space parameter is a non-empty string, then that string will - be used for indentation. If the space parameter is a number, then - the indentation will be that many spaces. - - Example: - - text = JSON.stringify(['e', {pluribus: 'unum'}]); - // text is '["e",{"pluribus":"unum"}]' - - - text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t'); - // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]' - - text = JSON.stringify([new Date()], function (key, value) { - return this[key] instanceof Date - ? 'Date(' + this[key] + ')' - : value; - }); - // text is '["Date(---current time---)"]' - - - JSON.parse(text, reviver) - This method parses a JSON text to produce an object or array. - It can throw a SyntaxError exception. - - The optional reviver parameter is a function that can filter and - transform the results. It receives each of the keys and values, - and its return value is used instead of the original value. - If it returns what it received, then the structure is not modified. - If it returns undefined then the member is deleted. - - Example: - - // Parse the text. Values that look like ISO date strings will - // be converted to Date objects. - - myData = JSON.parse(text, function (key, value) { - var a; - if (typeof value === 'string') { - a = -/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value); - if (a) { - return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], - +a[5], +a[6])); - } - } - return value; - }); - - myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) { - var d; - if (typeof value === 'string' && - value.slice(0, 5) === 'Date(' && - value.slice(-1) === ')') { - d = new Date(value.slice(5, -1)); - if (d) { - return d; - } - } - return value; - }); - - - This is a reference implementation. You are free to copy, modify, or - redistribute. -*/ - -/*jslint - eval, for, this -*/ - -/*property - JSON, apply, call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours, - getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join, - lastIndex, length, parse, prototype, push, replace, slice, stringify, - test, toJSON, toString, valueOf -*/ - - -// Create a JSON object only if one does not already exist. We create the -// methods in a closure to avoid creating global variables. - -if (typeof JSON !== 'object') { - JSON = {}; -} - -(function () { - 'use strict'; - - var rx_one = /^[\],:{}\s]*$/, - rx_two = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, - rx_three = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, - rx_four = /(?:^|:|,)(?:\s*\[)+/g, - rx_escapable = /[\\\"\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, - rx_dangerous = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g; - - function f(n) { - // Format integers to have at least two digits. - return n < 10 - ? '0' + n - : n; - } - - function this_value() { - return this.valueOf(); - } - - if (typeof Date.prototype.toJSON !== 'function') { - - Date.prototype.toJSON = function () { - - return isFinite(this.valueOf()) - ? this.getUTCFullYear() + '-' + - f(this.getUTCMonth() + 1) + '-' + - f(this.getUTCDate()) + 'T' + - f(this.getUTCHours()) + ':' + - f(this.getUTCMinutes()) + ':' + - f(this.getUTCSeconds()) + 'Z' - : null; - }; - - Boolean.prototype.toJSON = this_value; - Number.prototype.toJSON = this_value; - String.prototype.toJSON = this_value; - } - - var gap, - indent, - meta, - rep; - - - function quote(string) { - -// If the string contains no control characters, no quote characters, and no -// backslash characters, then we can safely slap some quotes around it. -// Otherwise we must also replace the offending characters with safe escape -// sequences. - - rx_escapable.lastIndex = 0; - return rx_escapable.test(string) - ? '"' + string.replace(rx_escapable, function (a) { - var c = meta[a]; - return typeof c === 'string' - ? c - : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); - }) + '"' - : '"' + string + '"'; - } - - - function str(key, holder) { - -// Produce a string from holder[key]. - - var i, // The loop counter. - k, // The member key. - v, // The member value. - length, - mind = gap, - partial, - value = holder[key]; - -// If the value has a toJSON method, call it to obtain a replacement value. - - if (value && typeof value === 'object' && - typeof value.toJSON === 'function') { - value = value.toJSON(key); - } - -// If we were called with a replacer function, then call the replacer to -// obtain a replacement value. - - if (typeof rep === 'function') { - value = rep.call(holder, key, value); - } - -// What happens next depends on the value's type. - - switch (typeof value) { - case 'string': - return quote(value); - - case 'number': - -// JSON numbers must be finite. Encode non-finite numbers as null. - - return isFinite(value) - ? String(value) - : 'null'; - - case 'boolean': - case 'null': - -// If the value is a boolean or null, convert it to a string. Note: -// typeof null does not produce 'null'. The case is included here in -// the remote chance that this gets fixed someday. - - return String(value); - -// If the type is 'object', we might be dealing with an object or an array or -// null. - - case 'object': - -// Due to a specification blunder in ECMAScript, typeof null is 'object', -// so watch out for that case. - - if (!value) { - return 'null'; - } - -// Make an array to hold the partial results of stringifying this object value. - - gap += indent; - partial = []; - -// Is the value an array? - - if (Object.prototype.toString.apply(value) === '[object Array]') { - -// The value is an array. Stringify every element. Use null as a placeholder -// for non-JSON values. - - length = value.length; - for (i = 0; i < length; i += 1) { - partial[i] = str(i, value) || 'null'; - } - -// Join all of the elements together, separated with commas, and wrap them in -// brackets. - - v = partial.length === 0 - ? '[]' - : gap - ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' - : '[' + partial.join(',') + ']'; - gap = mind; - return v; - } - -// If the replacer is an array, use it to select the members to be stringified. - - if (rep && typeof rep === 'object') { - length = rep.length; - for (i = 0; i < length; i += 1) { - if (typeof rep[i] === 'string') { - k = rep[i]; - v = str(k, value); - if (v) { - partial.push(quote(k) + ( - gap - ? ': ' - : ':' - ) + v); - } - } - } - } else { - -// Otherwise, iterate through all of the keys in the object. - - for (k in value) { - if (Object.prototype.hasOwnProperty.call(value, k)) { - v = str(k, value); - if (v) { - partial.push(quote(k) + ( - gap - ? ': ' - : ':' - ) + v); - } - } - } - } - -// Join all of the member texts together, separated with commas, -// and wrap them in braces. - - v = partial.length === 0 - ? '{}' - : gap - ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' - : '{' + partial.join(',') + '}'; - gap = mind; - return v; - } - } - -// If the JSON object does not yet have a stringify method, give it one. - - if (typeof JSON.stringify !== 'function') { - meta = { // table of character substitutions - '\b': '\\b', - '\t': '\\t', - '\n': '\\n', - '\f': '\\f', - '\r': '\\r', - '"': '\\"', - '\\': '\\\\' - }; - JSON.stringify = function (value, replacer, space) { - -// The stringify method takes a value and an optional replacer, and an optional -// space parameter, and returns a JSON text. The replacer can be a function -// that can replace values, or an array of strings that will select the keys. -// A default replacer method can be provided. Use of the space parameter can -// produce text that is more easily readable. - - var i; - gap = ''; - indent = ''; - -// If the space parameter is a number, make an indent string containing that -// many spaces. - - if (typeof space === 'number') { - for (i = 0; i < space; i += 1) { - indent += ' '; - } - -// If the space parameter is a string, it will be used as the indent string. - - } else if (typeof space === 'string') { - indent = space; - } - -// If there is a replacer, it must be a function or an array. -// Otherwise, throw an error. - - rep = replacer; - if (replacer && typeof replacer !== 'function' && - (typeof replacer !== 'object' || - typeof replacer.length !== 'number')) { - throw new Error('JSON.stringify'); - } - -// Make a fake root object containing our value under the key of ''. -// Return the result of stringifying the value. - - return str('', {'': value}); - }; - } - - -// If the JSON object does not yet have a parse method, give it one. - - if (typeof JSON.parse !== 'function') { - JSON.parse = function (text, reviver) { - -// The parse method takes a text and an optional reviver function, and returns -// a JavaScript value if the text is a valid JSON text. - - var j; - - function walk(holder, key) { - -// The walk method is used to recursively walk the resulting structure so -// that modifications can be made. - - var k, v, value = holder[key]; - if (value && typeof value === 'object') { - for (k in value) { - if (Object.prototype.hasOwnProperty.call(value, k)) { - v = walk(value, k); - if (v !== undefined) { - value[k] = v; - } else { - delete value[k]; - } - } - } - } - return reviver.call(holder, key, value); - } - - -// Parsing happens in four stages. In the first stage, we replace certain -// Unicode characters with escape sequences. JavaScript handles many characters -// incorrectly, either silently deleting them, or treating them as line endings. - - text = String(text); - rx_dangerous.lastIndex = 0; - if (rx_dangerous.test(text)) { - text = text.replace(rx_dangerous, function (a) { - return '\\u' + - ('0000' + a.charCodeAt(0).toString(16)).slice(-4); - }); - } - -// In the second stage, we run the text against regular expressions that look -// for non-JSON patterns. We are especially concerned with '()' and 'new' -// because they can cause invocation, and '=' because it can cause mutation. -// But just to be safe, we want to reject all unexpected forms. - -// We split the second stage into 4 regexp operations in order to work around -// crippling inefficiencies in IE's and Safari's regexp engines. First we -// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we -// replace all simple value tokens with ']' characters. Third, we delete all -// open brackets that follow a colon or comma or that begin the text. Finally, -// we look to see that the remaining characters are only whitespace or ']' or -// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval. - - if ( - rx_one.test( - text - .replace(rx_two, '@') - .replace(rx_three, ']') - .replace(rx_four, '') - ) - ) { - -// In the third stage we use the eval function to compile the text into a -// JavaScript structure. The '{' operator is subject to a syntactic ambiguity -// in JavaScript: it can begin a block or an object literal. We wrap the text -// in parens to eliminate the ambiguity. - - j = eval('(' + text + ')'); - -// In the optional fourth stage, we recursively walk the new structure, passing -// each name/value pair to a reviver function for possible transformation. - - return typeof reviver === 'function' - ? walk({'': j}, '') - : j; - } - -// If the text is not JSON parseable, then a SyntaxError is thrown. - - throw new SyntaxError('JSON.parse'); - }; - } -}()); diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/underscore/LICENSE b/ecomp-portal-FE/client/bower_components/lodash/vendor/underscore/LICENSE deleted file mode 100644 index 447239f3..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/underscore/LICENSE +++ /dev/null @@ -1,23 +0,0 @@ -Copyright (c) 2009-2016 Jeremy Ashkenas, DocumentCloud and Investigative -Reporters & Editors - -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. diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/underscore/test/arrays.js b/ecomp-portal-FE/client/bower_components/lodash/vendor/underscore/test/arrays.js deleted file mode 100644 index 748edea4..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/underscore/test/arrays.js +++ /dev/null @@ -1,555 +0,0 @@ -(function() { - var _ = typeof require == 'function' ? require('..') : window._; - - QUnit.module('Arrays'); - - QUnit.test('first', function(assert) { - assert.equal(_.first([1, 2, 3]), 1, 'can pull out the first element of an array'); - assert.equal(_([1, 2, 3]).first(), 1, 'can perform OO-style "first()"'); - assert.deepEqual(_.first([1, 2, 3], 0), [], 'returns an empty array when n <= 0 (0 case)'); - assert.deepEqual(_.first([1, 2, 3], -1), [], 'returns an empty array when n <= 0 (negative case)'); - assert.deepEqual(_.first([1, 2, 3], 2), [1, 2], 'can fetch the first n elements'); - assert.deepEqual(_.first([1, 2, 3], 5), [1, 2, 3], 'returns the whole array if n > length'); - var result = (function(){ return _.first(arguments); }(4, 3, 2, 1)); - assert.equal(result, 4, 'works on an arguments object'); - result = _.map([[1, 2, 3], [1, 2, 3]], _.first); - assert.deepEqual(result, [1, 1], 'works well with _.map'); - assert.equal(_.first(null), void 0, 'returns undefined when called on null'); - }); - - QUnit.test('head', function(assert) { - assert.strictEqual(_.head, _.first, 'is an alias for first'); - }); - - QUnit.test('take', function(assert) { - assert.strictEqual(_.take, _.first, 'is an alias for first'); - }); - - QUnit.test('rest', function(assert) { - var numbers = [1, 2, 3, 4]; - assert.deepEqual(_.rest(numbers), [2, 3, 4], 'fetches all but the first element'); - assert.deepEqual(_.rest(numbers, 0), [1, 2, 3, 4], 'returns the whole array when index is 0'); - assert.deepEqual(_.rest(numbers, 2), [3, 4], 'returns elements starting at the given index'); - var result = (function(){ return _(arguments).rest(); }(1, 2, 3, 4)); - assert.deepEqual(result, [2, 3, 4], 'works on an arguments object'); - result = _.map([[1, 2, 3], [1, 2, 3]], _.rest); - assert.deepEqual(_.flatten(result), [2, 3, 2, 3], 'works well with _.map'); - }); - - QUnit.test('tail', function(assert) { - assert.strictEqual(_.tail, _.rest, 'is an alias for rest'); - }); - - QUnit.test('drop', function(assert) { - assert.strictEqual(_.drop, _.rest, 'is an alias for rest'); - }); - - QUnit.test('initial', function(assert) { - assert.deepEqual(_.initial([1, 2, 3, 4, 5]), [1, 2, 3, 4], 'returns all but the last element'); - assert.deepEqual(_.initial([1, 2, 3, 4], 2), [1, 2], 'returns all but the last n elements'); - assert.deepEqual(_.initial([1, 2, 3, 4], 6), [], 'returns an empty array when n > length'); - var result = (function(){ return _(arguments).initial(); }(1, 2, 3, 4)); - assert.deepEqual(result, [1, 2, 3], 'works on an arguments object'); - result = _.map([[1, 2, 3], [1, 2, 3]], _.initial); - assert.deepEqual(_.flatten(result), [1, 2, 1, 2], 'works well with _.map'); - }); - - QUnit.test('last', function(assert) { - assert.equal(_.last([1, 2, 3]), 3, 'can pull out the last element of an array'); - assert.equal(_([1, 2, 3]).last(), 3, 'can perform OO-style "last()"'); - assert.deepEqual(_.last([1, 2, 3], 0), [], 'returns an empty array when n <= 0 (0 case)'); - assert.deepEqual(_.last([1, 2, 3], -1), [], 'returns an empty array when n <= 0 (negative case)'); - assert.deepEqual(_.last([1, 2, 3], 2), [2, 3], 'can fetch the last n elements'); - assert.deepEqual(_.last([1, 2, 3], 5), [1, 2, 3], 'returns the whole array if n > length'); - var result = (function(){ return _(arguments).last(); }(1, 2, 3, 4)); - assert.equal(result, 4, 'works on an arguments object'); - result = _.map([[1, 2, 3], [1, 2, 3]], _.last); - assert.deepEqual(result, [3, 3], 'works well with _.map'); - assert.equal(_.last(null), void 0, 'returns undefined when called on null'); - }); - - QUnit.test('compact', function(assert) { - assert.deepEqual(_.compact([1, false, null, 0, '', void 0, NaN, 2]), [1, 2], 'removes all falsy values'); - var result = (function(){ return _.compact(arguments); }(0, 1, false, 2, false, 3)); - assert.deepEqual(result, [1, 2, 3], 'works on an arguments object'); - result = _.map([[1, false, false], [false, false, 3]], _.compact); - assert.deepEqual(result, [[1], [3]], 'works well with _.map'); - }); - - QUnit.test('flatten', function(assert) { - assert.deepEqual(_.flatten(null), [], 'supports null'); - assert.deepEqual(_.flatten(void 0), [], 'supports undefined'); - - assert.deepEqual(_.flatten([[], [[]], []]), [], 'supports empty arrays'); - assert.deepEqual(_.flatten([[], [[]], []], true), [[]], 'can shallowly flatten empty arrays'); - - var list = [1, [2], [3, [[[4]]]]]; - assert.deepEqual(_.flatten(list), [1, 2, 3, 4], 'can flatten nested arrays'); - assert.deepEqual(_.flatten(list, true), [1, 2, 3, [[[4]]]], 'can shallowly flatten nested arrays'); - var result = (function(){ return _.flatten(arguments); }(1, [2], [3, [[[4]]]])); - assert.deepEqual(result, [1, 2, 3, 4], 'works on an arguments object'); - list = [[1], [2], [3], [[4]]]; - assert.deepEqual(_.flatten(list, true), [1, 2, 3, [4]], 'can shallowly flatten arrays containing only other arrays'); - - assert.equal(_.flatten([_.range(10), _.range(10), 5, 1, 3], true).length, 23, 'can flatten medium length arrays'); - assert.equal(_.flatten([_.range(10), _.range(10), 5, 1, 3]).length, 23, 'can shallowly flatten medium length arrays'); - assert.equal(_.flatten([new Array(1000000), _.range(56000), 5, 1, 3]).length, 1056003, 'can handle massive arrays'); - assert.equal(_.flatten([new Array(1000000), _.range(56000), 5, 1, 3], true).length, 1056003, 'can handle massive arrays in shallow mode'); - - var x = _.range(100000); - for (var i = 0; i < 1000; i++) x = [x]; - assert.deepEqual(_.flatten(x), _.range(100000), 'can handle very deep arrays'); - assert.deepEqual(_.flatten(x, true), x[0], 'can handle very deep arrays in shallow mode'); - }); - - QUnit.test('without', function(assert) { - var list = [1, 2, 1, 0, 3, 1, 4]; - assert.deepEqual(_.without(list, 0, 1), [2, 3, 4], 'removes all instances of the given values'); - var result = (function(){ return _.without(arguments, 0, 1); }(1, 2, 1, 0, 3, 1, 4)); - assert.deepEqual(result, [2, 3, 4], 'works on an arguments object'); - - list = [{one: 1}, {two: 2}]; - assert.deepEqual(_.without(list, {one: 1}), list, 'compares objects by reference (value case)'); - assert.deepEqual(_.without(list, list[0]), [{two: 2}], 'compares objects by reference (reference case)'); - }); - - QUnit.test('sortedIndex', function(assert) { - var numbers = [10, 20, 30, 40, 50]; - var indexFor35 = _.sortedIndex(numbers, 35); - assert.equal(indexFor35, 3, 'finds the index at which a value should be inserted to retain order'); - var indexFor30 = _.sortedIndex(numbers, 30); - assert.equal(indexFor30, 2, 'finds the smallest index at which a value could be inserted to retain order'); - - var objects = [{x: 10}, {x: 20}, {x: 30}, {x: 40}]; - var iterator = function(obj){ return obj.x; }; - assert.strictEqual(_.sortedIndex(objects, {x: 25}, iterator), 2, 'uses the result of `iterator` for order comparisons'); - assert.strictEqual(_.sortedIndex(objects, {x: 35}, 'x'), 3, 'when `iterator` is a string, uses that key for order comparisons'); - - var context = {1: 2, 2: 3, 3: 4}; - iterator = function(obj){ return this[obj]; }; - assert.strictEqual(_.sortedIndex([1, 3], 2, iterator, context), 1, 'can execute its iterator in the given context'); - - var values = [0, 1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191, 16383, 32767, 65535, 131071, 262143, 524287, - 1048575, 2097151, 4194303, 8388607, 16777215, 33554431, 67108863, 134217727, 268435455, 536870911, 1073741823, 2147483647]; - var largeArray = Array(Math.pow(2, 32) - 1); - var length = values.length; - // Sparsely populate `array` - while (length--) { - largeArray[values[length]] = values[length]; - } - assert.equal(_.sortedIndex(largeArray, 2147483648), 2147483648, 'works with large indexes'); - }); - - QUnit.test('uniq', function(assert) { - var list = [1, 2, 1, 3, 1, 4]; - assert.deepEqual(_.uniq(list), [1, 2, 3, 4], 'can find the unique values of an unsorted array'); - list = [1, 1, 1, 2, 2, 3]; - assert.deepEqual(_.uniq(list, true), [1, 2, 3], 'can find the unique values of a sorted array faster'); - - list = [{name: 'Moe'}, {name: 'Curly'}, {name: 'Larry'}, {name: 'Curly'}]; - var expected = [{name: 'Moe'}, {name: 'Curly'}, {name: 'Larry'}]; - var iterator = function(stooge) { return stooge.name; }; - assert.deepEqual(_.uniq(list, false, iterator), expected, 'uses the result of `iterator` for uniqueness comparisons (unsorted case)'); - assert.deepEqual(_.uniq(list, iterator), expected, '`sorted` argument defaults to false when omitted'); - assert.deepEqual(_.uniq(list, 'name'), expected, 'when `iterator` is a string, uses that key for comparisons (unsorted case)'); - - list = [{score: 8}, {score: 10}, {score: 10}]; - expected = [{score: 8}, {score: 10}]; - iterator = function(item) { return item.score; }; - assert.deepEqual(_.uniq(list, true, iterator), expected, 'uses the result of `iterator` for uniqueness comparisons (sorted case)'); - assert.deepEqual(_.uniq(list, true, 'score'), expected, 'when `iterator` is a string, uses that key for comparisons (sorted case)'); - - assert.deepEqual(_.uniq([{0: 1}, {0: 1}, {0: 1}, {0: 2}], 0), [{0: 1}, {0: 2}], 'can use falsey pluck like iterator'); - - var result = (function(){ return _.uniq(arguments); }(1, 2, 1, 3, 1, 4)); - assert.deepEqual(result, [1, 2, 3, 4], 'works on an arguments object'); - - var a = {}, b = {}, c = {}; - assert.deepEqual(_.uniq([a, b, a, b, c]), [a, b, c], 'works on values that can be tested for equivalency but not ordered'); - - assert.deepEqual(_.uniq(null), [], 'returns an empty array when `array` is not iterable'); - - var context = {}; - list = [3]; - _.uniq(list, function(value, index, array) { - assert.strictEqual(this, context, 'executes its iterator in the given context'); - assert.strictEqual(value, 3, 'passes its iterator the value'); - assert.strictEqual(index, 0, 'passes its iterator the index'); - assert.strictEqual(array, list, 'passes its iterator the entire array'); - }, context); - - }); - - QUnit.test('unique', function(assert) { - assert.strictEqual(_.unique, _.uniq, 'is an alias for uniq'); - }); - - QUnit.test('intersection', function(assert) { - var stooges = ['moe', 'curly', 'larry'], leaders = ['moe', 'groucho']; - assert.deepEqual(_.intersection(stooges, leaders), ['moe'], 'can find the set intersection of two arrays'); - assert.deepEqual(_(stooges).intersection(leaders), ['moe'], 'can perform an OO-style intersection'); - var result = (function(){ return _.intersection(arguments, leaders); }('moe', 'curly', 'larry')); - assert.deepEqual(result, ['moe'], 'works on an arguments object'); - var theSixStooges = ['moe', 'moe', 'curly', 'curly', 'larry', 'larry']; - assert.deepEqual(_.intersection(theSixStooges, leaders), ['moe'], 'returns a duplicate-free array'); - result = _.intersection([2, 4, 3, 1], [1, 2, 3]); - assert.deepEqual(result, [2, 3, 1], 'preserves the order of the first array'); - result = _.intersection(null, [1, 2, 3]); - assert.deepEqual(result, [], 'returns an empty array when passed null as the first argument'); - result = _.intersection([1, 2, 3], null); - assert.deepEqual(result, [], 'returns an empty array when passed null as an argument beyond the first'); - }); - - QUnit.test('union', function(assert) { - var result = _.union([1, 2, 3], [2, 30, 1], [1, 40]); - assert.deepEqual(result, [1, 2, 3, 30, 40], 'can find the union of a list of arrays'); - - result = _([1, 2, 3]).union([2, 30, 1], [1, 40]); - assert.deepEqual(result, [1, 2, 3, 30, 40], 'can perform an OO-style union'); - - result = _.union([1, 2, 3], [2, 30, 1], [1, 40, [1]]); - assert.deepEqual(result, [1, 2, 3, 30, 40, [1]], 'can find the union of a list of nested arrays'); - - result = _.union([10, 20], [1, 30, 10], [0, 40]); - assert.deepEqual(result, [10, 20, 1, 30, 0, 40], 'orders values by their first encounter'); - - result = (function(){ return _.union(arguments, [2, 30, 1], [1, 40]); }(1, 2, 3)); - assert.deepEqual(result, [1, 2, 3, 30, 40], 'works on an arguments object'); - - assert.deepEqual(_.union([1, 2, 3], 4), [1, 2, 3], 'restricts the union to arrays only'); - }); - - QUnit.test('difference', function(assert) { - var result = _.difference([1, 2, 3], [2, 30, 40]); - assert.deepEqual(result, [1, 3], 'can find the difference of two arrays'); - - result = _([1, 2, 3]).difference([2, 30, 40]); - assert.deepEqual(result, [1, 3], 'can perform an OO-style difference'); - - result = _.difference([1, 2, 3, 4], [2, 30, 40], [1, 11, 111]); - assert.deepEqual(result, [3, 4], 'can find the difference of three arrays'); - - result = _.difference([8, 9, 3, 1], [3, 8]); - assert.deepEqual(result, [9, 1], 'preserves the order of the first array'); - - result = (function(){ return _.difference(arguments, [2, 30, 40]); }(1, 2, 3)); - assert.deepEqual(result, [1, 3], 'works on an arguments object'); - - result = _.difference([1, 2, 3], 1); - assert.deepEqual(result, [1, 2, 3], 'restrict the difference to arrays only'); - }); - - QUnit.test('zip', function(assert) { - var names = ['moe', 'larry', 'curly'], ages = [30, 40, 50], leaders = [true]; - assert.deepEqual(_.zip(names, ages, leaders), [ - ['moe', 30, true], - ['larry', 40, void 0], - ['curly', 50, void 0] - ], 'zipped together arrays of different lengths'); - - var stooges = _.zip(['moe', 30, 'stooge 1'], ['larry', 40, 'stooge 2'], ['curly', 50, 'stooge 3']); - assert.deepEqual(stooges, [['moe', 'larry', 'curly'], [30, 40, 50], ['stooge 1', 'stooge 2', 'stooge 3']], 'zipped pairs'); - - // In the case of different lengths of the tuples, undefined values - // should be used as placeholder - stooges = _.zip(['moe', 30], ['larry', 40], ['curly', 50, 'extra data']); - assert.deepEqual(stooges, [['moe', 'larry', 'curly'], [30, 40, 50], [void 0, void 0, 'extra data']], 'zipped pairs with empties'); - - var empty = _.zip([]); - assert.deepEqual(empty, [], 'unzipped empty'); - - assert.deepEqual(_.zip(null), [], 'handles null'); - assert.deepEqual(_.zip(), [], '_.zip() returns []'); - }); - - QUnit.test('unzip', function(assert) { - assert.deepEqual(_.unzip(null), [], 'handles null'); - - assert.deepEqual(_.unzip([['a', 'b'], [1, 2]]), [['a', 1], ['b', 2]]); - - // complements zip - var zipped = _.zip(['fred', 'barney'], [30, 40], [true, false]); - assert.deepEqual(_.unzip(zipped), [['fred', 'barney'], [30, 40], [true, false]]); - - zipped = _.zip(['moe', 30], ['larry', 40], ['curly', 50, 'extra data']); - assert.deepEqual(_.unzip(zipped), [['moe', 30, void 0], ['larry', 40, void 0], ['curly', 50, 'extra data']], 'Uses length of largest array'); - }); - - QUnit.test('object', function(assert) { - var result = _.object(['moe', 'larry', 'curly'], [30, 40, 50]); - var shouldBe = {moe: 30, larry: 40, curly: 50}; - assert.deepEqual(result, shouldBe, 'two arrays zipped together into an object'); - - result = _.object([['one', 1], ['two', 2], ['three', 3]]); - shouldBe = {one: 1, two: 2, three: 3}; - assert.deepEqual(result, shouldBe, 'an array of pairs zipped together into an object'); - - var stooges = {moe: 30, larry: 40, curly: 50}; - assert.deepEqual(_.object(_.pairs(stooges)), stooges, 'an object converted to pairs and back to an object'); - - assert.deepEqual(_.object(null), {}, 'handles nulls'); - }); - - QUnit.test('indexOf', function(assert) { - var numbers = [1, 2, 3]; - assert.equal(_.indexOf(numbers, 2), 1, 'can compute indexOf'); - var result = (function(){ return _.indexOf(arguments, 2); }(1, 2, 3)); - assert.equal(result, 1, 'works on an arguments object'); - - _.each([null, void 0, [], false], function(val) { - var msg = 'Handles: ' + (_.isArray(val) ? '[]' : val); - assert.equal(_.indexOf(val, 2), -1, msg); - assert.equal(_.indexOf(val, 2, -1), -1, msg); - assert.equal(_.indexOf(val, 2, -20), -1, msg); - assert.equal(_.indexOf(val, 2, 15), -1, msg); - }); - - var num = 35; - numbers = [10, 20, 30, 40, 50]; - var index = _.indexOf(numbers, num, true); - assert.equal(index, -1, '35 is not in the list'); - - numbers = [10, 20, 30, 40, 50]; num = 40; - index = _.indexOf(numbers, num, true); - assert.equal(index, 3, '40 is in the list'); - - numbers = [1, 40, 40, 40, 40, 40, 40, 40, 50, 60, 70]; num = 40; - assert.equal(_.indexOf(numbers, num, true), 1, '40 is in the list'); - assert.equal(_.indexOf(numbers, 6, true), -1, '6 isnt in the list'); - assert.equal(_.indexOf([1, 2, 5, 4, 6, 7], 5, true), -1, 'sorted indexOf doesn\'t uses binary search'); - assert.ok(_.every(['1', [], {}, null], function() { - return _.indexOf(numbers, num, {}) === 1; - }), 'non-nums as fromIndex make indexOf assume sorted'); - - numbers = [1, 2, 3, 1, 2, 3, 1, 2, 3]; - index = _.indexOf(numbers, 2, 5); - assert.equal(index, 7, 'supports the fromIndex argument'); - - index = _.indexOf([,,, 0], void 0); - assert.equal(index, 0, 'treats sparse arrays as if they were dense'); - - var array = [1, 2, 3, 1, 2, 3]; - assert.strictEqual(_.indexOf(array, 1, -3), 3, 'neg `fromIndex` starts at the right index'); - assert.strictEqual(_.indexOf(array, 1, -2), -1, 'neg `fromIndex` starts at the right index'); - assert.strictEqual(_.indexOf(array, 2, -3), 4); - _.each([-6, -8, -Infinity], function(fromIndex) { - assert.strictEqual(_.indexOf(array, 1, fromIndex), 0); - }); - assert.strictEqual(_.indexOf([1, 2, 3], 1, true), 0); - - index = _.indexOf([], void 0, true); - assert.equal(index, -1, 'empty array with truthy `isSorted` returns -1'); - }); - - QUnit.test('indexOf with NaN', function(assert) { - assert.strictEqual(_.indexOf([1, 2, NaN, NaN], NaN), 2, 'Expected [1, 2, NaN] to contain NaN'); - assert.strictEqual(_.indexOf([1, 2, Infinity], NaN), -1, 'Expected [1, 2, NaN] to contain NaN'); - - assert.strictEqual(_.indexOf([1, 2, NaN, NaN], NaN, 1), 2, 'startIndex does not affect result'); - assert.strictEqual(_.indexOf([1, 2, NaN, NaN], NaN, -2), 2, 'startIndex does not affect result'); - - (function() { - assert.strictEqual(_.indexOf(arguments, NaN), 2, 'Expected arguments [1, 2, NaN] to contain NaN'); - }(1, 2, NaN, NaN)); - }); - - QUnit.test('indexOf with +- 0', function(assert) { - _.each([-0, +0], function(val) { - assert.strictEqual(_.indexOf([1, 2, val, val], val), 2); - assert.strictEqual(_.indexOf([1, 2, val, val], -val), 2); - }); - }); - - QUnit.test('lastIndexOf', function(assert) { - var numbers = [1, 0, 1]; - var falsey = [void 0, '', 0, false, NaN, null, void 0]; - assert.equal(_.lastIndexOf(numbers, 1), 2); - - numbers = [1, 0, 1, 0, 0, 1, 0, 0, 0]; - numbers.lastIndexOf = null; - assert.equal(_.lastIndexOf(numbers, 1), 5, 'can compute lastIndexOf, even without the native function'); - assert.equal(_.lastIndexOf(numbers, 0), 8, 'lastIndexOf the other element'); - var result = (function(){ return _.lastIndexOf(arguments, 1); }(1, 0, 1, 0, 0, 1, 0, 0, 0)); - assert.equal(result, 5, 'works on an arguments object'); - - _.each([null, void 0, [], false], function(val) { - var msg = 'Handles: ' + (_.isArray(val) ? '[]' : val); - assert.equal(_.lastIndexOf(val, 2), -1, msg); - assert.equal(_.lastIndexOf(val, 2, -1), -1, msg); - assert.equal(_.lastIndexOf(val, 2, -20), -1, msg); - assert.equal(_.lastIndexOf(val, 2, 15), -1, msg); - }); - - numbers = [1, 2, 3, 1, 2, 3, 1, 2, 3]; - var index = _.lastIndexOf(numbers, 2, 2); - assert.equal(index, 1, 'supports the fromIndex argument'); - - var array = [1, 2, 3, 1, 2, 3]; - - assert.strictEqual(_.lastIndexOf(array, 1, 0), 0, 'starts at the correct from idx'); - assert.strictEqual(_.lastIndexOf(array, 3), 5, 'should return the index of the last matched value'); - assert.strictEqual(_.lastIndexOf(array, 4), -1, 'should return `-1` for an unmatched value'); - - assert.strictEqual(_.lastIndexOf(array, 1, 2), 0, 'should work with a positive `fromIndex`'); - - _.each([6, 8, Math.pow(2, 32), Infinity], function(fromIndex) { - assert.strictEqual(_.lastIndexOf(array, void 0, fromIndex), -1); - assert.strictEqual(_.lastIndexOf(array, 1, fromIndex), 3); - assert.strictEqual(_.lastIndexOf(array, '', fromIndex), -1); - }); - - var expected = _.map(falsey, function(value) { - return typeof value == 'number' ? -1 : 5; - }); - - var actual = _.map(falsey, function(fromIndex) { - return _.lastIndexOf(array, 3, fromIndex); - }); - - assert.deepEqual(actual, expected, 'should treat falsey `fromIndex` values, except `0` and `NaN`, as `array.length`'); - assert.strictEqual(_.lastIndexOf(array, 3, '1'), 5, 'should treat non-number `fromIndex` values as `array.length`'); - assert.strictEqual(_.lastIndexOf(array, 3, true), 5, 'should treat non-number `fromIndex` values as `array.length`'); - - assert.strictEqual(_.lastIndexOf(array, 2, -3), 1, 'should work with a negative `fromIndex`'); - assert.strictEqual(_.lastIndexOf(array, 1, -3), 3, 'neg `fromIndex` starts at the right index'); - - assert.deepEqual(_.map([-6, -8, -Infinity], function(fromIndex) { - return _.lastIndexOf(array, 1, fromIndex); - }), [0, -1, -1]); - }); - - QUnit.test('lastIndexOf with NaN', function(assert) { - assert.strictEqual(_.lastIndexOf([1, 2, NaN, NaN], NaN), 3, 'Expected [1, 2, NaN] to contain NaN'); - assert.strictEqual(_.lastIndexOf([1, 2, Infinity], NaN), -1, 'Expected [1, 2, NaN] to contain NaN'); - - assert.strictEqual(_.lastIndexOf([1, 2, NaN, NaN], NaN, 2), 2, 'fromIndex does not affect result'); - assert.strictEqual(_.lastIndexOf([1, 2, NaN, NaN], NaN, -2), 2, 'fromIndex does not affect result'); - - (function() { - assert.strictEqual(_.lastIndexOf(arguments, NaN), 3, 'Expected arguments [1, 2, NaN] to contain NaN'); - }(1, 2, NaN, NaN)); - }); - - QUnit.test('lastIndexOf with +- 0', function(assert) { - _.each([-0, +0], function(val) { - assert.strictEqual(_.lastIndexOf([1, 2, val, val], val), 3); - assert.strictEqual(_.lastIndexOf([1, 2, val, val], -val), 3); - assert.strictEqual(_.lastIndexOf([-1, 1, 2], -val), -1); - }); - }); - - QUnit.test('findIndex', function(assert) { - var objects = [ - {a: 0, b: 0}, - {a: 1, b: 1}, - {a: 2, b: 2}, - {a: 0, b: 0} - ]; - - assert.equal(_.findIndex(objects, function(obj) { - return obj.a === 0; - }), 0); - - assert.equal(_.findIndex(objects, function(obj) { - return obj.b * obj.a === 4; - }), 2); - - assert.equal(_.findIndex(objects, 'a'), 1, 'Uses lookupIterator'); - - assert.equal(_.findIndex(objects, function(obj) { - return obj.b * obj.a === 5; - }), -1); - - assert.equal(_.findIndex(null, _.noop), -1); - assert.strictEqual(_.findIndex(objects, function(a) { - return a.foo === null; - }), -1); - _.findIndex([{a: 1}], function(a, key, obj) { - assert.equal(key, 0); - assert.deepEqual(obj, [{a: 1}]); - assert.strictEqual(this, objects, 'called with context'); - }, objects); - - var sparse = []; - sparse[20] = {a: 2, b: 2}; - assert.equal(_.findIndex(sparse, function(obj) { - return obj && obj.b * obj.a === 4; - }), 20, 'Works with sparse arrays'); - - var array = [1, 2, 3, 4]; - array.match = 55; - assert.strictEqual(_.findIndex(array, function(x) { return x === 55; }), -1, 'doesn\'t match array-likes keys'); - }); - - QUnit.test('findLastIndex', function(assert) { - var objects = [ - {a: 0, b: 0}, - {a: 1, b: 1}, - {a: 2, b: 2}, - {a: 0, b: 0} - ]; - - assert.equal(_.findLastIndex(objects, function(obj) { - return obj.a === 0; - }), 3); - - assert.equal(_.findLastIndex(objects, function(obj) { - return obj.b * obj.a === 4; - }), 2); - - assert.equal(_.findLastIndex(objects, 'a'), 2, 'Uses lookupIterator'); - - assert.equal(_.findLastIndex(objects, function(obj) { - return obj.b * obj.a === 5; - }), -1); - - assert.equal(_.findLastIndex(null, _.noop), -1); - assert.strictEqual(_.findLastIndex(objects, function(a) { - return a.foo === null; - }), -1); - _.findLastIndex([{a: 1}], function(a, key, obj) { - assert.equal(key, 0); - assert.deepEqual(obj, [{a: 1}]); - assert.strictEqual(this, objects, 'called with context'); - }, objects); - - var sparse = []; - sparse[20] = {a: 2, b: 2}; - assert.equal(_.findLastIndex(sparse, function(obj) { - return obj && obj.b * obj.a === 4; - }), 20, 'Works with sparse arrays'); - - var array = [1, 2, 3, 4]; - array.match = 55; - assert.strictEqual(_.findLastIndex(array, function(x) { return x === 55; }), -1, 'doesn\'t match array-likes keys'); - }); - - QUnit.test('range', function(assert) { - assert.deepEqual(_.range(0), [], 'range with 0 as a first argument generates an empty array'); - assert.deepEqual(_.range(4), [0, 1, 2, 3], 'range with a single positive argument generates an array of elements 0,1,2,...,n-1'); - assert.deepEqual(_.range(5, 8), [5, 6, 7], 'range with two arguments a & b, a<b generates an array of elements a,a+1,a+2,...,b-2,b-1'); - assert.deepEqual(_.range(3, 10, 3), [3, 6, 9], 'range with three arguments a & b & c, c < b-a, a < b generates an array of elements a,a+c,a+2c,...,b - (multiplier of a) < c'); - assert.deepEqual(_.range(3, 10, 15), [3], 'range with three arguments a & b & c, c > b-a, a < b generates an array with a single element, equal to a'); - assert.deepEqual(_.range(12, 7, -2), [12, 10, 8], 'range with three arguments a & b & c, a > b, c < 0 generates an array of elements a,a-c,a-2c and ends with the number not less than b'); - assert.deepEqual(_.range(0, -10, -1), [0, -1, -2, -3, -4, -5, -6, -7, -8, -9], 'final example in the Python docs'); - assert.strictEqual(1 / _.range(-0, 1)[0], -Infinity, 'should preserve -0'); - assert.deepEqual(_.range(8, 5), [8, 7, 6], 'negative range generates descending array'); - assert.deepEqual(_.range(-3), [0, -1, -2], 'negative range generates descending array'); - }); - - QUnit.test('chunk', function(assert) { - assert.deepEqual(_.chunk([], 2), [], 'chunk for empty array returns an empty array'); - - assert.deepEqual(_.chunk([1, 2, 3], 0), [], 'chunk into parts of 0 elements returns empty array'); - assert.deepEqual(_.chunk([1, 2, 3], -1), [], 'chunk into parts of negative amount of elements returns an empty array'); - assert.deepEqual(_.chunk([1, 2, 3]), [], 'defaults to empty array (chunk size 0)'); - - assert.deepEqual(_.chunk([1, 2, 3], 1), [[1], [2], [3]], 'chunk into parts of 1 elements returns original array'); - - assert.deepEqual(_.chunk([1, 2, 3], 3), [[1, 2, 3]], 'chunk into parts of current array length elements returns the original array'); - assert.deepEqual(_.chunk([1, 2, 3], 5), [[1, 2, 3]], 'chunk into parts of more then current array length elements returns the original array'); - - assert.deepEqual(_.chunk([10, 20, 30, 40, 50, 60, 70], 2), [[10, 20], [30, 40], [50, 60], [70]], 'chunk into parts of less then current array length elements'); - assert.deepEqual(_.chunk([10, 20, 30, 40, 50, 60, 70], 3), [[10, 20, 30], [40, 50, 60], [70]], 'chunk into parts of less then current array length elements'); - }); -}()); diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/underscore/test/chaining.js b/ecomp-portal-FE/client/bower_components/lodash/vendor/underscore/test/chaining.js deleted file mode 100644 index 6ad21dcf..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/underscore/test/chaining.js +++ /dev/null @@ -1,99 +0,0 @@ -(function() { - var _ = typeof require == 'function' ? require('..') : window._; - - QUnit.module('Chaining'); - - QUnit.test('map/flatten/reduce', function(assert) { - var lyrics = [ - 'I\'m a lumberjack and I\'m okay', - 'I sleep all night and I work all day', - 'He\'s a lumberjack and he\'s okay', - 'He sleeps all night and he works all day' - ]; - var counts = _(lyrics).chain() - .map(function(line) { return line.split(''); }) - .flatten() - .reduce(function(hash, l) { - hash[l] = hash[l] || 0; - hash[l]++; - return hash; - }, {}) - .value(); - assert.equal(counts.a, 16, 'counted all the letters in the song'); - assert.equal(counts.e, 10, 'counted all the letters in the song'); - }); - - QUnit.test('select/reject/sortBy', function(assert) { - var numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; - numbers = _(numbers).chain().select(function(n) { - return n % 2 === 0; - }).reject(function(n) { - return n % 4 === 0; - }).sortBy(function(n) { - return -n; - }).value(); - assert.deepEqual(numbers, [10, 6, 2], 'filtered and reversed the numbers'); - }); - - QUnit.test('select/reject/sortBy in functional style', function(assert) { - var numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; - numbers = _.chain(numbers).select(function(n) { - return n % 2 === 0; - }).reject(function(n) { - return n % 4 === 0; - }).sortBy(function(n) { - return -n; - }).value(); - assert.deepEqual(numbers, [10, 6, 2], 'filtered and reversed the numbers'); - }); - - QUnit.test('reverse/concat/unshift/pop/map', function(assert) { - var numbers = [1, 2, 3, 4, 5]; - numbers = _(numbers).chain() - .reverse() - .concat([5, 5, 5]) - .unshift(17) - .pop() - .map(function(n){ return n * 2; }) - .value(); - assert.deepEqual(numbers, [34, 10, 8, 6, 4, 2, 10, 10], 'can chain together array functions.'); - }); - - QUnit.test('splice', function(assert) { - var instance = _([1, 2, 3, 4, 5]).chain(); - assert.deepEqual(instance.splice(1, 3).value(), [1, 5]); - assert.deepEqual(instance.splice(1, 0).value(), [1, 5]); - assert.deepEqual(instance.splice(1, 1).value(), [1]); - assert.deepEqual(instance.splice(0, 1).value(), [], '#397 Can create empty array'); - }); - - QUnit.test('shift', function(assert) { - var instance = _([1, 2, 3]).chain(); - assert.deepEqual(instance.shift().value(), [2, 3]); - assert.deepEqual(instance.shift().value(), [3]); - assert.deepEqual(instance.shift().value(), [], '#397 Can create empty array'); - }); - - QUnit.test('pop', function(assert) { - var instance = _([1, 2, 3]).chain(); - assert.deepEqual(instance.pop().value(), [1, 2]); - assert.deepEqual(instance.pop().value(), [1]); - assert.deepEqual(instance.pop().value(), [], '#397 Can create empty array'); - }); - - QUnit.test('chaining works in small stages', function(assert) { - var o = _([1, 2, 3, 4]).chain(); - assert.deepEqual(o.filter(function(i) { return i < 3; }).value(), [1, 2]); - assert.deepEqual(o.filter(function(i) { return i > 2; }).value(), [3, 4]); - }); - - QUnit.test('#1562: Engine proxies for chained functions', function(assert) { - var wrapped = _(512); - assert.strictEqual(wrapped.toJSON(), 512); - assert.strictEqual(wrapped.valueOf(), 512); - assert.strictEqual(+wrapped, 512); - assert.strictEqual(wrapped.toString(), '512'); - assert.strictEqual('' + wrapped, '512'); - }); - -}()); diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/underscore/test/collections.js b/ecomp-portal-FE/client/bower_components/lodash/vendor/underscore/test/collections.js deleted file mode 100644 index 182f7a21..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/underscore/test/collections.js +++ /dev/null @@ -1,896 +0,0 @@ -(function() { - var _ = typeof require == 'function' ? require('..') : window._; - - QUnit.module('Collections'); - - QUnit.test('each', function(assert) { - _.each([1, 2, 3], function(num, i) { - assert.equal(num, i + 1, 'each iterators provide value and iteration count'); - }); - - var answers = []; - _.each([1, 2, 3], function(num){ answers.push(num * this.multiplier); }, {multiplier: 5}); - assert.deepEqual(answers, [5, 10, 15], 'context object property accessed'); - - answers = []; - _.each([1, 2, 3], function(num){ answers.push(num); }); - assert.deepEqual(answers, [1, 2, 3], 'can iterate a simple array'); - - answers = []; - var obj = {one: 1, two: 2, three: 3}; - obj.constructor.prototype.four = 4; - _.each(obj, function(value, key){ answers.push(key); }); - assert.deepEqual(answers, ['one', 'two', 'three'], 'iterating over objects works, and ignores the object prototype.'); - delete obj.constructor.prototype.four; - - // ensure the each function is JITed - _(1000).times(function() { _.each([], function(){}); }); - var count = 0; - obj = {1: 'foo', 2: 'bar', 3: 'baz'}; - _.each(obj, function(){ count++; }); - assert.equal(count, 3, 'the fun should be called only 3 times'); - - var answer = null; - _.each([1, 2, 3], function(num, index, arr){ if (_.include(arr, num)) answer = true; }); - assert.ok(answer, 'can reference the original collection from inside the iterator'); - - answers = 0; - _.each(null, function(){ ++answers; }); - assert.equal(answers, 0, 'handles a null properly'); - - _.each(false, function(){}); - - var a = [1, 2, 3]; - assert.strictEqual(_.each(a, function(){}), a); - assert.strictEqual(_.each(null, function(){}), null); - }); - - QUnit.test('forEach', function(assert) { - assert.strictEqual(_.forEach, _.each, 'is an alias for each'); - }); - - QUnit.test('lookupIterator with contexts', function(assert) { - _.each([true, false, 'yes', '', 0, 1, {}], function(context) { - _.each([1], function() { - assert.equal(this, context); - }, context); - }); - }); - - QUnit.test('Iterating objects with sketchy length properties', function(assert) { - var functions = [ - 'each', 'map', 'filter', 'find', - 'some', 'every', 'max', 'min', - 'groupBy', 'countBy', 'partition', 'indexBy' - ]; - var reducers = ['reduce', 'reduceRight']; - - var tricks = [ - {length: '5'}, - {length: {valueOf: _.constant(5)}}, - {length: Math.pow(2, 53) + 1}, - {length: Math.pow(2, 53)}, - {length: null}, - {length: -2}, - {length: new Number(15)} - ]; - - assert.expect(tricks.length * (functions.length + reducers.length + 4)); - - _.each(tricks, function(trick) { - var length = trick.length; - assert.strictEqual(_.size(trick), 1, 'size on obj with length: ' + length); - assert.deepEqual(_.toArray(trick), [length], 'toArray on obj with length: ' + length); - assert.deepEqual(_.shuffle(trick), [length], 'shuffle on obj with length: ' + length); - assert.deepEqual(_.sample(trick), length, 'sample on obj with length: ' + length); - - - _.each(functions, function(method) { - _[method](trick, function(val, key) { - assert.strictEqual(key, 'length', method + ': ran with length = ' + val); - }); - }); - - _.each(reducers, function(method) { - assert.strictEqual(_[method](trick), trick.length, method); - }); - }); - }); - - QUnit.test('Resistant to collection length and properties changing while iterating', function(assert) { - - var collection = [ - 'each', 'map', 'filter', 'find', - 'some', 'every', 'max', 'min', 'reject', - 'groupBy', 'countBy', 'partition', 'indexBy', - 'reduce', 'reduceRight' - ]; - var array = [ - 'findIndex', 'findLastIndex' - ]; - var object = [ - 'mapObject', 'findKey', 'pick', 'omit' - ]; - - _.each(collection.concat(array), function(method) { - var sparseArray = [1, 2, 3]; - sparseArray.length = 100; - var answers = 0; - _[method](sparseArray, function(){ - ++answers; - return method === 'every' ? true : null; - }, {}); - assert.equal(answers, 100, method + ' enumerates [0, length)'); - - var growingCollection = [1, 2, 3], count = 0; - _[method](growingCollection, function() { - if (count < 10) growingCollection.push(count++); - return method === 'every' ? true : null; - }, {}); - assert.equal(count, 3, method + ' is resistant to length changes'); - }); - - _.each(collection.concat(object), function(method) { - var changingObject = {0: 0, 1: 1}, count = 0; - _[method](changingObject, function(val) { - if (count < 10) changingObject[++count] = val + 1; - return method === 'every' ? true : null; - }, {}); - - assert.equal(count, 2, method + ' is resistant to property changes'); - }); - }); - - QUnit.test('map', function(assert) { - var doubled = _.map([1, 2, 3], function(num){ return num * 2; }); - assert.deepEqual(doubled, [2, 4, 6], 'doubled numbers'); - - var tripled = _.map([1, 2, 3], function(num){ return num * this.multiplier; }, {multiplier: 3}); - assert.deepEqual(tripled, [3, 6, 9], 'tripled numbers with context'); - - doubled = _([1, 2, 3]).map(function(num){ return num * 2; }); - assert.deepEqual(doubled, [2, 4, 6], 'OO-style doubled numbers'); - - var ids = _.map({length: 2, 0: {id: '1'}, 1: {id: '2'}}, function(n){ - return n.id; - }); - assert.deepEqual(ids, ['1', '2'], 'Can use collection methods on Array-likes.'); - - assert.deepEqual(_.map(null, _.noop), [], 'handles a null properly'); - - assert.deepEqual(_.map([1], function() { - return this.length; - }, [5]), [1], 'called with context'); - - // Passing a property name like _.pluck. - var people = [{name: 'moe', age: 30}, {name: 'curly', age: 50}]; - assert.deepEqual(_.map(people, 'name'), ['moe', 'curly'], 'predicate string map to object properties'); - }); - - QUnit.test('collect', function(assert) { - assert.strictEqual(_.collect, _.map, 'is an alias for map'); - }); - - QUnit.test('reduce', function(assert) { - var sum = _.reduce([1, 2, 3], function(memo, num){ return memo + num; }, 0); - assert.equal(sum, 6, 'can sum up an array'); - - var context = {multiplier: 3}; - sum = _.reduce([1, 2, 3], function(memo, num){ return memo + num * this.multiplier; }, 0, context); - assert.equal(sum, 18, 'can reduce with a context object'); - - sum = _([1, 2, 3]).reduce(function(memo, num){ return memo + num; }, 0); - assert.equal(sum, 6, 'OO-style reduce'); - - sum = _.reduce([1, 2, 3], function(memo, num){ return memo + num; }); - assert.equal(sum, 6, 'default initial value'); - - var prod = _.reduce([1, 2, 3, 4], function(memo, num){ return memo * num; }); - assert.equal(prod, 24, 'can reduce via multiplication'); - - assert.ok(_.reduce(null, _.noop, 138) === 138, 'handles a null (with initial value) properly'); - assert.equal(_.reduce([], _.noop, void 0), void 0, 'undefined can be passed as a special case'); - assert.equal(_.reduce([_], _.noop), _, 'collection of length one with no initial value returns the first item'); - assert.equal(_.reduce([], _.noop), void 0, 'returns undefined when collection is empty and no initial value'); - }); - - QUnit.test('foldl', function(assert) { - assert.strictEqual(_.foldl, _.reduce, 'is an alias for reduce'); - }); - - QUnit.test('inject', function(assert) { - assert.strictEqual(_.inject, _.reduce, 'is an alias for reduce'); - }); - - QUnit.test('reduceRight', function(assert) { - var list = _.reduceRight(['foo', 'bar', 'baz'], function(memo, str){ return memo + str; }, ''); - assert.equal(list, 'bazbarfoo', 'can perform right folds'); - - list = _.reduceRight(['foo', 'bar', 'baz'], function(memo, str){ return memo + str; }); - assert.equal(list, 'bazbarfoo', 'default initial value'); - - var sum = _.reduceRight({a: 1, b: 2, c: 3}, function(memo, num){ return memo + num; }); - assert.equal(sum, 6, 'default initial value on object'); - - assert.ok(_.reduceRight(null, _.noop, 138) === 138, 'handles a null (with initial value) properly'); - assert.equal(_.reduceRight([_], _.noop), _, 'collection of length one with no initial value returns the first item'); - - assert.equal(_.reduceRight([], _.noop, void 0), void 0, 'undefined can be passed as a special case'); - assert.equal(_.reduceRight([], _.noop), void 0, 'returns undefined when collection is empty and no initial value'); - - // Assert that the correct arguments are being passed. - - var args, - init = {}, - object = {a: 1, b: 2}, - lastKey = _.keys(object).pop(); - - var expected = lastKey === 'a' - ? [init, 1, 'a', object] - : [init, 2, 'b', object]; - - _.reduceRight(object, function() { - if (!args) args = _.toArray(arguments); - }, init); - - assert.deepEqual(args, expected); - - // And again, with numeric keys. - - object = {2: 'a', 1: 'b'}; - lastKey = _.keys(object).pop(); - args = null; - - expected = lastKey === '2' - ? [init, 'a', '2', object] - : [init, 'b', '1', object]; - - _.reduceRight(object, function() { - if (!args) args = _.toArray(arguments); - }, init); - - assert.deepEqual(args, expected); - }); - - QUnit.test('foldr', function(assert) { - assert.strictEqual(_.foldr, _.reduceRight, 'is an alias for reduceRight'); - }); - - QUnit.test('find', function(assert) { - var array = [1, 2, 3, 4]; - assert.strictEqual(_.find(array, function(n) { return n > 2; }), 3, 'should return first found `value`'); - assert.strictEqual(_.find(array, function() { return false; }), void 0, 'should return `undefined` if `value` is not found'); - - array.dontmatch = 55; - assert.strictEqual(_.find(array, function(x) { return x === 55; }), void 0, 'iterates array-likes correctly'); - - // Matching an object like _.findWhere. - var list = [{a: 1, b: 2}, {a: 2, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}, {a: 2, b: 4}]; - assert.deepEqual(_.find(list, {a: 1}), {a: 1, b: 2}, 'can be used as findWhere'); - assert.deepEqual(_.find(list, {b: 4}), {a: 1, b: 4}); - assert.ok(!_.find(list, {c: 1}), 'undefined when not found'); - assert.ok(!_.find([], {c: 1}), 'undefined when searching empty list'); - - var result = _.find([1, 2, 3], function(num){ return num * 2 === 4; }); - assert.equal(result, 2, 'found the first "2" and broke the loop'); - - var obj = { - a: {x: 1, z: 3}, - b: {x: 2, z: 2}, - c: {x: 3, z: 4}, - d: {x: 4, z: 1} - }; - - assert.deepEqual(_.find(obj, {x: 2}), {x: 2, z: 2}, 'works on objects'); - assert.deepEqual(_.find(obj, {x: 2, z: 1}), void 0); - assert.deepEqual(_.find(obj, function(x) { - return x.x === 4; - }), {x: 4, z: 1}); - - _.findIndex([{a: 1}], function(a, key, o) { - assert.equal(key, 0); - assert.deepEqual(o, [{a: 1}]); - assert.strictEqual(this, _, 'called with context'); - }, _); - }); - - QUnit.test('detect', function(assert) { - assert.strictEqual(_.detect, _.find, 'is an alias for find'); - }); - - QUnit.test('filter', function(assert) { - var evenArray = [1, 2, 3, 4, 5, 6]; - var evenObject = {one: 1, two: 2, three: 3}; - var isEven = function(num){ return num % 2 === 0; }; - - assert.deepEqual(_.filter(evenArray, isEven), [2, 4, 6]); - assert.deepEqual(_.filter(evenObject, isEven), [2], 'can filter objects'); - assert.deepEqual(_.filter([{}, evenObject, []], 'two'), [evenObject], 'predicate string map to object properties'); - - _.filter([1], function() { - assert.equal(this, evenObject, 'given context'); - }, evenObject); - - // Can be used like _.where. - var list = [{a: 1, b: 2}, {a: 2, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}]; - assert.deepEqual(_.filter(list, {a: 1}), [{a: 1, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}]); - assert.deepEqual(_.filter(list, {b: 2}), [{a: 1, b: 2}, {a: 2, b: 2}]); - assert.deepEqual(_.filter(list, {}), list, 'Empty object accepts all items'); - assert.deepEqual(_(list).filter({}), list, 'OO-filter'); - }); - - QUnit.test('select', function(assert) { - assert.strictEqual(_.select, _.filter, 'is an alias for filter'); - }); - - QUnit.test('reject', function(assert) { - var odds = _.reject([1, 2, 3, 4, 5, 6], function(num){ return num % 2 === 0; }); - assert.deepEqual(odds, [1, 3, 5], 'rejected each even number'); - - var context = 'obj'; - - var evens = _.reject([1, 2, 3, 4, 5, 6], function(num){ - assert.equal(context, 'obj'); - return num % 2 !== 0; - }, context); - assert.deepEqual(evens, [2, 4, 6], 'rejected each odd number'); - - assert.deepEqual(_.reject([odds, {one: 1, two: 2, three: 3}], 'two'), [odds], 'predicate string map to object properties'); - - // Can be used like _.where. - var list = [{a: 1, b: 2}, {a: 2, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}]; - assert.deepEqual(_.reject(list, {a: 1}), [{a: 2, b: 2}]); - assert.deepEqual(_.reject(list, {b: 2}), [{a: 1, b: 3}, {a: 1, b: 4}]); - assert.deepEqual(_.reject(list, {}), [], 'Returns empty list given empty object'); - assert.deepEqual(_.reject(list, []), [], 'Returns empty list given empty array'); - }); - - QUnit.test('every', function(assert) { - assert.ok(_.every([], _.identity), 'the empty set'); - assert.ok(_.every([true, true, true], _.identity), 'every true values'); - assert.ok(!_.every([true, false, true], _.identity), 'one false value'); - assert.ok(_.every([0, 10, 28], function(num){ return num % 2 === 0; }), 'even numbers'); - assert.ok(!_.every([0, 11, 28], function(num){ return num % 2 === 0; }), 'an odd number'); - assert.ok(_.every([1], _.identity) === true, 'cast to boolean - true'); - assert.ok(_.every([0], _.identity) === false, 'cast to boolean - false'); - assert.ok(!_.every([void 0, void 0, void 0], _.identity), 'works with arrays of undefined'); - - var list = [{a: 1, b: 2}, {a: 2, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}]; - assert.ok(!_.every(list, {a: 1, b: 2}), 'Can be called with object'); - assert.ok(_.every(list, 'a'), 'String mapped to object property'); - - list = [{a: 1, b: 2}, {a: 2, b: 2, c: true}]; - assert.ok(_.every(list, {b: 2}), 'Can be called with object'); - assert.ok(!_.every(list, 'c'), 'String mapped to object property'); - - assert.ok(_.every({a: 1, b: 2, c: 3, d: 4}, _.isNumber), 'takes objects'); - assert.ok(!_.every({a: 1, b: 2, c: 3, d: 4}, _.isObject), 'takes objects'); - assert.ok(_.every(['a', 'b', 'c', 'd'], _.hasOwnProperty, {a: 1, b: 2, c: 3, d: 4}), 'context works'); - assert.ok(!_.every(['a', 'b', 'c', 'd', 'f'], _.hasOwnProperty, {a: 1, b: 2, c: 3, d: 4}), 'context works'); - }); - - QUnit.test('all', function(assert) { - assert.strictEqual(_.all, _.every, 'is an alias for every'); - }); - - QUnit.test('some', function(assert) { - assert.ok(!_.some([]), 'the empty set'); - assert.ok(!_.some([false, false, false]), 'all false values'); - assert.ok(_.some([false, false, true]), 'one true value'); - assert.ok(_.some([null, 0, 'yes', false]), 'a string'); - assert.ok(!_.some([null, 0, '', false]), 'falsy values'); - assert.ok(!_.some([1, 11, 29], function(num){ return num % 2 === 0; }), 'all odd numbers'); - assert.ok(_.some([1, 10, 29], function(num){ return num % 2 === 0; }), 'an even number'); - assert.ok(_.some([1], _.identity) === true, 'cast to boolean - true'); - assert.ok(_.some([0], _.identity) === false, 'cast to boolean - false'); - assert.ok(_.some([false, false, true])); - - var list = [{a: 1, b: 2}, {a: 2, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}]; - assert.ok(!_.some(list, {a: 5, b: 2}), 'Can be called with object'); - assert.ok(_.some(list, 'a'), 'String mapped to object property'); - - list = [{a: 1, b: 2}, {a: 2, b: 2, c: true}]; - assert.ok(_.some(list, {b: 2}), 'Can be called with object'); - assert.ok(!_.some(list, 'd'), 'String mapped to object property'); - - assert.ok(_.some({a: '1', b: '2', c: '3', d: '4', e: 6}, _.isNumber), 'takes objects'); - assert.ok(!_.some({a: 1, b: 2, c: 3, d: 4}, _.isObject), 'takes objects'); - assert.ok(_.some(['a', 'b', 'c', 'd'], _.hasOwnProperty, {a: 1, b: 2, c: 3, d: 4}), 'context works'); - assert.ok(!_.some(['x', 'y', 'z'], _.hasOwnProperty, {a: 1, b: 2, c: 3, d: 4}), 'context works'); - }); - - QUnit.test('any', function(assert) { - assert.strictEqual(_.any, _.some, 'is an alias for some'); - }); - - QUnit.test('includes', function(assert) { - _.each([null, void 0, 0, 1, NaN, {}, []], function(val) { - assert.strictEqual(_.includes(val, 'hasOwnProperty'), false); - }); - assert.strictEqual(_.includes([1, 2, 3], 2), true, 'two is in the array'); - assert.ok(!_.includes([1, 3, 9], 2), 'two is not in the array'); - - assert.strictEqual(_.includes([5, 4, 3, 2, 1], 5, true), true, 'doesn\'t delegate to binary search'); - - assert.ok(_.includes({moe: 1, larry: 3, curly: 9}, 3) === true, '_.includes on objects checks their values'); - assert.ok(_([1, 2, 3]).includes(2), 'OO-style includes'); - - var numbers = [1, 2, 3, 1, 2, 3, 1, 2, 3]; - assert.strictEqual(_.includes(numbers, 1, 1), true, 'takes a fromIndex'); - assert.strictEqual(_.includes(numbers, 1, -1), false, 'takes a fromIndex'); - assert.strictEqual(_.includes(numbers, 1, -2), false, 'takes a fromIndex'); - assert.strictEqual(_.includes(numbers, 1, -3), true, 'takes a fromIndex'); - assert.strictEqual(_.includes(numbers, 1, 6), true, 'takes a fromIndex'); - assert.strictEqual(_.includes(numbers, 1, 7), false, 'takes a fromIndex'); - - assert.ok(_.every([1, 2, 3], _.partial(_.includes, numbers)), 'fromIndex is guarded'); - }); - - QUnit.test('include', function(assert) { - assert.strictEqual(_.include, _.includes, 'is an alias for includes'); - }); - - QUnit.test('contains', function(assert) { - assert.strictEqual(_.contains, _.includes, 'is an alias for includes'); - - }); - - QUnit.test('includes with NaN', function(assert) { - assert.strictEqual(_.includes([1, 2, NaN, NaN], NaN), true, 'Expected [1, 2, NaN] to contain NaN'); - assert.strictEqual(_.includes([1, 2, Infinity], NaN), false, 'Expected [1, 2, NaN] to contain NaN'); - }); - - QUnit.test('includes with +- 0', function(assert) { - _.each([-0, +0], function(val) { - assert.strictEqual(_.includes([1, 2, val, val], val), true); - assert.strictEqual(_.includes([1, 2, val, val], -val), true); - assert.strictEqual(_.includes([-1, 1, 2], -val), false); - }); - }); - - - QUnit.test('invoke', function(assert) { - assert.expect(5); - var list = [[5, 1, 7], [3, 2, 1]]; - var result = _.invoke(list, 'sort'); - assert.deepEqual(result[0], [1, 5, 7], 'first array sorted'); - assert.deepEqual(result[1], [1, 2, 3], 'second array sorted'); - - _.invoke([{ - method: function() { - assert.deepEqual(_.toArray(arguments), [1, 2, 3], 'called with arguments'); - } - }], 'method', 1, 2, 3); - - assert.deepEqual(_.invoke([{a: null}, {}, {a: _.constant(1)}], 'a'), [null, void 0, 1], 'handles null & undefined'); - - assert.raises(function() { - _.invoke([{a: 1}], 'a'); - }, TypeError, 'throws for non-functions'); - }); - - QUnit.test('invoke w/ function reference', function(assert) { - var list = [[5, 1, 7], [3, 2, 1]]; - var result = _.invoke(list, Array.prototype.sort); - assert.deepEqual(result[0], [1, 5, 7], 'first array sorted'); - assert.deepEqual(result[1], [1, 2, 3], 'second array sorted'); - - assert.deepEqual(_.invoke([1, 2, 3], function(a) { - return a + this; - }, 5), [6, 7, 8], 'receives params from invoke'); - }); - - // Relevant when using ClojureScript - QUnit.test('invoke when strings have a call method', function(assert) { - String.prototype.call = function() { - return 42; - }; - var list = [[5, 1, 7], [3, 2, 1]]; - var s = 'foo'; - assert.equal(s.call(), 42, 'call function exists'); - var result = _.invoke(list, 'sort'); - assert.deepEqual(result[0], [1, 5, 7], 'first array sorted'); - assert.deepEqual(result[1], [1, 2, 3], 'second array sorted'); - delete String.prototype.call; - assert.equal(s.call, void 0, 'call function removed'); - }); - - QUnit.test('pluck', function(assert) { - var people = [{name: 'moe', age: 30}, {name: 'curly', age: 50}]; - assert.deepEqual(_.pluck(people, 'name'), ['moe', 'curly'], 'pulls names out of objects'); - assert.deepEqual(_.pluck(people, 'address'), [void 0, void 0], 'missing properties are returned as undefined'); - //compat: most flexible handling of edge cases - assert.deepEqual(_.pluck([{'[object Object]': 1}], {}), [1]); - }); - - QUnit.test('where', function(assert) { - var list = [{a: 1, b: 2}, {a: 2, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}]; - var result = _.where(list, {a: 1}); - assert.equal(result.length, 3); - assert.equal(result[result.length - 1].b, 4); - result = _.where(list, {b: 2}); - assert.equal(result.length, 2); - assert.equal(result[0].a, 1); - result = _.where(list, {}); - assert.equal(result.length, list.length); - - function test() {} - test.map = _.map; - assert.deepEqual(_.where([_, {a: 1, b: 2}, _], test), [_, _], 'checks properties given function'); - }); - - QUnit.test('findWhere', function(assert) { - var list = [{a: 1, b: 2}, {a: 2, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}, {a: 2, b: 4}]; - var result = _.findWhere(list, {a: 1}); - assert.deepEqual(result, {a: 1, b: 2}); - result = _.findWhere(list, {b: 4}); - assert.deepEqual(result, {a: 1, b: 4}); - - result = _.findWhere(list, {c: 1}); - assert.ok(_.isUndefined(result), 'undefined when not found'); - - result = _.findWhere([], {c: 1}); - assert.ok(_.isUndefined(result), 'undefined when searching empty list'); - - function test() {} - test.map = _.map; - assert.equal(_.findWhere([_, {a: 1, b: 2}, _], test), _, 'checks properties given function'); - - function TestClass() { - this.y = 5; - this.x = 'foo'; - } - var expect = {c: 1, x: 'foo', y: 5}; - assert.deepEqual(_.findWhere([{y: 5, b: 6}, expect], new TestClass()), expect, 'uses class instance properties'); - }); - - QUnit.test('max', function(assert) { - assert.equal(-Infinity, _.max(null), 'can handle null/undefined'); - assert.equal(-Infinity, _.max(void 0), 'can handle null/undefined'); - assert.equal(-Infinity, _.max(null, _.identity), 'can handle null/undefined'); - - assert.equal(3, _.max([1, 2, 3]), 'can perform a regular Math.max'); - - var neg = _.max([1, 2, 3], function(num){ return -num; }); - assert.equal(neg, 1, 'can perform a computation-based max'); - - assert.equal(-Infinity, _.max({}), 'Maximum value of an empty object'); - assert.equal(-Infinity, _.max([]), 'Maximum value of an empty array'); - assert.equal(_.max({a: 'a'}), -Infinity, 'Maximum value of a non-numeric collection'); - - assert.equal(299999, _.max(_.range(1, 300000)), 'Maximum value of a too-big array'); - - assert.equal(3, _.max([1, 2, 3, 'test']), 'Finds correct max in array starting with num and containing a NaN'); - assert.equal(3, _.max(['test', 1, 2, 3]), 'Finds correct max in array starting with NaN'); - - assert.equal(3, _.max([1, 2, 3, null]), 'Finds correct max in array starting with num and containing a `null`'); - assert.equal(3, _.max([null, 1, 2, 3]), 'Finds correct max in array starting with a `null`'); - - assert.equal(3, _.max([1, 2, 3, '']), 'Finds correct max in array starting with num and containing an empty string'); - assert.equal(3, _.max(['', 1, 2, 3]), 'Finds correct max in array starting with an empty string'); - - assert.equal(3, _.max([1, 2, 3, false]), 'Finds correct max in array starting with num and containing a false'); - assert.equal(3, _.max([false, 1, 2, 3]), 'Finds correct max in array starting with a false'); - - assert.equal(4, _.max([0, 1, 2, 3, 4]), 'Finds correct max in array containing a zero'); - assert.equal(0, _.max([-3, -2, -1, 0]), 'Finds correct max in array containing negative numbers'); - - assert.deepEqual([3, 6], _.map([[1, 2, 3], [4, 5, 6]], _.max), 'Finds correct max in array when mapping through multiple arrays'); - - var a = {x: -Infinity}; - var b = {x: -Infinity}; - var iterator = function(o){ return o.x; }; - assert.equal(_.max([a, b], iterator), a, 'Respects iterator return value of -Infinity'); - - assert.deepEqual(_.max([{a: 1}, {a: 0, b: 3}, {a: 4}, {a: 2}], 'a'), {a: 4}, 'String keys use property iterator'); - - assert.deepEqual(_.max([0, 2], function(c){ return c * this.x; }, {x: 1}), 2, 'Iterator context'); - assert.deepEqual(_.max([[1], [2, 3], [-1, 4], [5]], 0), [5], 'Lookup falsy iterator'); - assert.deepEqual(_.max([{0: 1}, {0: 2}, {0: -1}, {a: 1}], 0), {0: 2}, 'Lookup falsy iterator'); - }); - - QUnit.test('min', function(assert) { - assert.equal(Infinity, _.min(null), 'can handle null/undefined'); - assert.equal(Infinity, _.min(void 0), 'can handle null/undefined'); - assert.equal(Infinity, _.min(null, _.identity), 'can handle null/undefined'); - - assert.equal(1, _.min([1, 2, 3]), 'can perform a regular Math.min'); - - var neg = _.min([1, 2, 3], function(num){ return -num; }); - assert.equal(neg, 3, 'can perform a computation-based min'); - - assert.equal(Infinity, _.min({}), 'Minimum value of an empty object'); - assert.equal(Infinity, _.min([]), 'Minimum value of an empty array'); - assert.equal(_.min({a: 'a'}), Infinity, 'Minimum value of a non-numeric collection'); - - assert.deepEqual([1, 4], _.map([[1, 2, 3], [4, 5, 6]], _.min), 'Finds correct min in array when mapping through multiple arrays'); - - var now = new Date(9999999999); - var then = new Date(0); - assert.equal(_.min([now, then]), then); - - assert.equal(1, _.min(_.range(1, 300000)), 'Minimum value of a too-big array'); - - assert.equal(1, _.min([1, 2, 3, 'test']), 'Finds correct min in array starting with num and containing a NaN'); - assert.equal(1, _.min(['test', 1, 2, 3]), 'Finds correct min in array starting with NaN'); - - assert.equal(1, _.min([1, 2, 3, null]), 'Finds correct min in array starting with num and containing a `null`'); - assert.equal(1, _.min([null, 1, 2, 3]), 'Finds correct min in array starting with a `null`'); - - assert.equal(0, _.min([0, 1, 2, 3, 4]), 'Finds correct min in array containing a zero'); - assert.equal(-3, _.min([-3, -2, -1, 0]), 'Finds correct min in array containing negative numbers'); - - var a = {x: Infinity}; - var b = {x: Infinity}; - var iterator = function(o){ return o.x; }; - assert.equal(_.min([a, b], iterator), a, 'Respects iterator return value of Infinity'); - - assert.deepEqual(_.min([{a: 1}, {a: 0, b: 3}, {a: 4}, {a: 2}], 'a'), {a: 0, b: 3}, 'String keys use property iterator'); - - assert.deepEqual(_.min([0, 2], function(c){ return c * this.x; }, {x: -1}), 2, 'Iterator context'); - assert.deepEqual(_.min([[1], [2, 3], [-1, 4], [5]], 0), [-1, 4], 'Lookup falsy iterator'); - assert.deepEqual(_.min([{0: 1}, {0: 2}, {0: -1}, {a: 1}], 0), {0: -1}, 'Lookup falsy iterator'); - }); - - QUnit.test('sortBy', function(assert) { - var people = [{name: 'curly', age: 50}, {name: 'moe', age: 30}]; - people = _.sortBy(people, function(person){ return person.age; }); - assert.deepEqual(_.pluck(people, 'name'), ['moe', 'curly'], 'stooges sorted by age'); - - var list = [void 0, 4, 1, void 0, 3, 2]; - assert.deepEqual(_.sortBy(list, _.identity), [1, 2, 3, 4, void 0, void 0], 'sortBy with undefined values'); - - list = ['one', 'two', 'three', 'four', 'five']; - var sorted = _.sortBy(list, 'length'); - assert.deepEqual(sorted, ['one', 'two', 'four', 'five', 'three'], 'sorted by length'); - - function Pair(x, y) { - this.x = x; - this.y = y; - } - - var stableArray = [ - new Pair(1, 1), new Pair(1, 2), - new Pair(1, 3), new Pair(1, 4), - new Pair(1, 5), new Pair(1, 6), - new Pair(2, 1), new Pair(2, 2), - new Pair(2, 3), new Pair(2, 4), - new Pair(2, 5), new Pair(2, 6), - new Pair(void 0, 1), new Pair(void 0, 2), - new Pair(void 0, 3), new Pair(void 0, 4), - new Pair(void 0, 5), new Pair(void 0, 6) - ]; - - var stableObject = _.object('abcdefghijklmnopqr'.split(''), stableArray); - - var actual = _.sortBy(stableArray, function(pair) { - return pair.x; - }); - - assert.deepEqual(actual, stableArray, 'sortBy should be stable for arrays'); - assert.deepEqual(_.sortBy(stableArray, 'x'), stableArray, 'sortBy accepts property string'); - - actual = _.sortBy(stableObject, function(pair) { - return pair.x; - }); - - assert.deepEqual(actual, stableArray, 'sortBy should be stable for objects'); - - list = ['q', 'w', 'e', 'r', 't', 'y']; - assert.deepEqual(_.sortBy(list), ['e', 'q', 'r', 't', 'w', 'y'], 'uses _.identity if iterator is not specified'); - }); - - QUnit.test('groupBy', function(assert) { - var parity = _.groupBy([1, 2, 3, 4, 5, 6], function(num){ return num % 2; }); - assert.ok('0' in parity && '1' in parity, 'created a group for each value'); - assert.deepEqual(parity[0], [2, 4, 6], 'put each even number in the right group'); - - var list = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten']; - var grouped = _.groupBy(list, 'length'); - assert.deepEqual(grouped['3'], ['one', 'two', 'six', 'ten']); - assert.deepEqual(grouped['4'], ['four', 'five', 'nine']); - assert.deepEqual(grouped['5'], ['three', 'seven', 'eight']); - - var context = {}; - _.groupBy([{}], function(){ assert.ok(this === context); }, context); - - grouped = _.groupBy([4.2, 6.1, 6.4], function(num) { - return Math.floor(num) > 4 ? 'hasOwnProperty' : 'constructor'; - }); - assert.equal(grouped.constructor.length, 1); - assert.equal(grouped.hasOwnProperty.length, 2); - - var array = [{}]; - _.groupBy(array, function(value, index, obj){ assert.ok(obj === array); }); - - array = [1, 2, 1, 2, 3]; - grouped = _.groupBy(array); - assert.equal(grouped['1'].length, 2); - assert.equal(grouped['3'].length, 1); - - var matrix = [ - [1, 2], - [1, 3], - [2, 3] - ]; - assert.deepEqual(_.groupBy(matrix, 0), {1: [[1, 2], [1, 3]], 2: [[2, 3]]}); - assert.deepEqual(_.groupBy(matrix, 1), {2: [[1, 2]], 3: [[1, 3], [2, 3]]}); - }); - - QUnit.test('indexBy', function(assert) { - var parity = _.indexBy([1, 2, 3, 4, 5], function(num){ return num % 2 === 0; }); - assert.equal(parity['true'], 4); - assert.equal(parity['false'], 5); - - var list = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten']; - var grouped = _.indexBy(list, 'length'); - assert.equal(grouped['3'], 'ten'); - assert.equal(grouped['4'], 'nine'); - assert.equal(grouped['5'], 'eight'); - - var array = [1, 2, 1, 2, 3]; - grouped = _.indexBy(array); - assert.equal(grouped['1'], 1); - assert.equal(grouped['2'], 2); - assert.equal(grouped['3'], 3); - }); - - QUnit.test('countBy', function(assert) { - var parity = _.countBy([1, 2, 3, 4, 5], function(num){ return num % 2 === 0; }); - assert.equal(parity['true'], 2); - assert.equal(parity['false'], 3); - - var list = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten']; - var grouped = _.countBy(list, 'length'); - assert.equal(grouped['3'], 4); - assert.equal(grouped['4'], 3); - assert.equal(grouped['5'], 3); - - var context = {}; - _.countBy([{}], function(){ assert.ok(this === context); }, context); - - grouped = _.countBy([4.2, 6.1, 6.4], function(num) { - return Math.floor(num) > 4 ? 'hasOwnProperty' : 'constructor'; - }); - assert.equal(grouped.constructor, 1); - assert.equal(grouped.hasOwnProperty, 2); - - var array = [{}]; - _.countBy(array, function(value, index, obj){ assert.ok(obj === array); }); - - array = [1, 2, 1, 2, 3]; - grouped = _.countBy(array); - assert.equal(grouped['1'], 2); - assert.equal(grouped['3'], 1); - }); - - QUnit.test('shuffle', function(assert) { - assert.deepEqual(_.shuffle([1]), [1], 'behaves correctly on size 1 arrays'); - var numbers = _.range(20); - var shuffled = _.shuffle(numbers); - assert.notDeepEqual(numbers, shuffled, 'does change the order'); // Chance of false negative: 1 in ~2.4*10^18 - assert.notStrictEqual(numbers, shuffled, 'original object is unmodified'); - assert.deepEqual(numbers, _.sortBy(shuffled), 'contains the same members before and after shuffle'); - - shuffled = _.shuffle({a: 1, b: 2, c: 3, d: 4}); - assert.equal(shuffled.length, 4); - assert.deepEqual(shuffled.sort(), [1, 2, 3, 4], 'works on objects'); - }); - - QUnit.test('sample', function(assert) { - assert.strictEqual(_.sample([1]), 1, 'behaves correctly when no second parameter is given'); - assert.deepEqual(_.sample([1, 2, 3], -2), [], 'behaves correctly on negative n'); - var numbers = _.range(10); - var allSampled = _.sample(numbers, 10).sort(); - assert.deepEqual(allSampled, numbers, 'contains the same members before and after sample'); - allSampled = _.sample(numbers, 20).sort(); - assert.deepEqual(allSampled, numbers, 'also works when sampling more objects than are present'); - assert.ok(_.contains(numbers, _.sample(numbers)), 'sampling a single element returns something from the array'); - assert.strictEqual(_.sample([]), void 0, 'sampling empty array with no number returns undefined'); - assert.notStrictEqual(_.sample([], 5), [], 'sampling empty array with a number returns an empty array'); - assert.notStrictEqual(_.sample([1, 2, 3], 0), [], 'sampling an array with 0 picks returns an empty array'); - assert.deepEqual(_.sample([1, 2], -1), [], 'sampling a negative number of picks returns an empty array'); - assert.ok(_.contains([1, 2, 3], _.sample({a: 1, b: 2, c: 3})), 'sample one value from an object'); - var partialSample = _.sample(_.range(1000), 10); - var partialSampleSorted = partialSample.sort(); - assert.notDeepEqual(partialSampleSorted, _.range(10), 'samples from the whole array, not just the beginning'); - }); - - QUnit.test('toArray', function(assert) { - assert.ok(!_.isArray(arguments), 'arguments object is not an array'); - assert.ok(_.isArray(_.toArray(arguments)), 'arguments object converted into array'); - var a = [1, 2, 3]; - assert.ok(_.toArray(a) !== a, 'array is cloned'); - assert.deepEqual(_.toArray(a), [1, 2, 3], 'cloned array contains same elements'); - - var numbers = _.toArray({one: 1, two: 2, three: 3}); - assert.deepEqual(numbers, [1, 2, 3], 'object flattened into array'); - - var hearts = '\uD83D\uDC95'; - var pair = hearts.split(''); - var expected = [pair[0], hearts, '&', hearts, pair[1]]; - assert.deepEqual(_.toArray(expected.join('')), expected, 'maintains astral characters'); - assert.deepEqual(_.toArray(''), [], 'empty string into empty array'); - - if (typeof document != 'undefined') { - // test in IE < 9 - var actual; - try { - actual = _.toArray(document.childNodes); - } catch (e) { /* ignored */ } - assert.deepEqual(actual, _.map(document.childNodes, _.identity), 'works on NodeList'); - } - }); - - QUnit.test('size', function(assert) { - assert.equal(_.size({one: 1, two: 2, three: 3}), 3, 'can compute the size of an object'); - assert.equal(_.size([1, 2, 3]), 3, 'can compute the size of an array'); - assert.equal(_.size({length: 3, 0: 0, 1: 0, 2: 0}), 3, 'can compute the size of Array-likes'); - - var func = function() { - return _.size(arguments); - }; - - assert.equal(func(1, 2, 3, 4), 4, 'can test the size of the arguments object'); - - assert.equal(_.size('hello'), 5, 'can compute the size of a string literal'); - assert.equal(_.size(new String('hello')), 5, 'can compute the size of string object'); - - assert.equal(_.size(null), 0, 'handles nulls'); - assert.equal(_.size(0), 0, 'handles numbers'); - }); - - QUnit.test('partition', function(assert) { - var list = [0, 1, 2, 3, 4, 5]; - assert.deepEqual(_.partition(list, function(x) { return x < 4; }), [[0, 1, 2, 3], [4, 5]], 'handles bool return values'); - assert.deepEqual(_.partition(list, function(x) { return x & 1; }), [[1, 3, 5], [0, 2, 4]], 'handles 0 and 1 return values'); - assert.deepEqual(_.partition(list, function(x) { return x - 3; }), [[0, 1, 2, 4, 5], [3]], 'handles other numeric return values'); - assert.deepEqual(_.partition(list, function(x) { return x > 1 ? null : true; }), [[0, 1], [2, 3, 4, 5]], 'handles null return values'); - assert.deepEqual(_.partition(list, function(x) { if (x < 2) return true; }), [[0, 1], [2, 3, 4, 5]], 'handles undefined return values'); - assert.deepEqual(_.partition({a: 1, b: 2, c: 3}, function(x) { return x > 1; }), [[2, 3], [1]], 'handles objects'); - - assert.deepEqual(_.partition(list, function(x, index) { return index % 2; }), [[1, 3, 5], [0, 2, 4]], 'can reference the array index'); - assert.deepEqual(_.partition(list, function(x, index, arr) { return x === arr.length - 1; }), [[5], [0, 1, 2, 3, 4]], 'can reference the collection'); - - // Default iterator - assert.deepEqual(_.partition([1, false, true, '']), [[1, true], [false, '']], 'Default iterator'); - assert.deepEqual(_.partition([{x: 1}, {x: 0}, {x: 1}], 'x'), [[{x: 1}, {x: 1}], [{x: 0}]], 'Takes a string'); - - // Context - var predicate = function(x){ return x === this.x; }; - assert.deepEqual(_.partition([1, 2, 3], predicate, {x: 2}), [[2], [1, 3]], 'partition takes a context argument'); - - assert.deepEqual(_.partition([{a: 1}, {b: 2}, {a: 1, b: 2}], {a: 1}), [[{a: 1}, {a: 1, b: 2}], [{b: 2}]], 'predicate can be object'); - - var object = {a: 1}; - _.partition(object, function(val, key, obj) { - assert.equal(val, 1); - assert.equal(key, 'a'); - assert.equal(obj, object); - assert.equal(this, predicate); - }, predicate); - }); - - if (typeof document != 'undefined') { - QUnit.test('Can use various collection methods on NodeLists', function(assert) { - var parent = document.createElement('div'); - parent.innerHTML = '<span id=id1></span>textnode<span id=id2></span>'; - - var elementChildren = _.filter(parent.childNodes, _.isElement); - assert.equal(elementChildren.length, 2); - - assert.deepEqual(_.map(elementChildren, 'id'), ['id1', 'id2']); - assert.deepEqual(_.map(parent.childNodes, 'nodeType'), [1, 3, 1]); - - assert.ok(!_.every(parent.childNodes, _.isElement)); - assert.ok(_.some(parent.childNodes, _.isElement)); - - function compareNode(node) { - return _.isElement(node) ? node.id.charAt(2) : void 0; - } - assert.equal(_.max(parent.childNodes, compareNode), _.last(parent.childNodes)); - assert.equal(_.min(parent.childNodes, compareNode), _.first(parent.childNodes)); - }); - } - -}()); diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/underscore/test/cross-document.js b/ecomp-portal-FE/client/bower_components/lodash/vendor/underscore/test/cross-document.js deleted file mode 100644 index cb68a3d9..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/underscore/test/cross-document.js +++ /dev/null @@ -1,141 +0,0 @@ -(function() { - if (typeof document == 'undefined') return; - - var _ = typeof require == 'function' ? require('..') : window._; - - QUnit.module('Cross Document'); - /* global iObject, iElement, iArguments, iFunction, iArray, iError, iString, iNumber, iBoolean, iDate, iRegExp, iNaN, iNull, iUndefined, ActiveXObject */ - - // Setup remote variables for iFrame tests. - var iframe = document.createElement('iframe'); - iframe.frameBorder = iframe.height = iframe.width = 0; - document.body.appendChild(iframe); - var iDoc = (iDoc = iframe.contentDocument || iframe.contentWindow).document || iDoc; - iDoc.write( - [ - '<script>', - 'parent.iElement = document.createElement("div");', - 'parent.iArguments = (function(){ return arguments; })(1, 2, 3);', - 'parent.iArray = [1, 2, 3];', - 'parent.iString = new String("hello");', - 'parent.iNumber = new Number(100);', - 'parent.iFunction = (function(){});', - 'parent.iDate = new Date();', - 'parent.iRegExp = /hi/;', - 'parent.iNaN = NaN;', - 'parent.iNull = null;', - 'parent.iBoolean = new Boolean(false);', - 'parent.iUndefined = undefined;', - 'parent.iObject = {};', - 'parent.iError = new Error();', - '</script>' - ].join('\n') - ); - iDoc.close(); - - QUnit.test('isEqual', function(assert) { - - assert.ok(!_.isEqual(iNumber, 101)); - assert.ok(_.isEqual(iNumber, 100)); - - // Objects from another frame. - assert.ok(_.isEqual({}, iObject), 'Objects with equivalent members created in different documents are equal'); - - // Array from another frame. - assert.ok(_.isEqual([1, 2, 3], iArray), 'Arrays with equivalent elements created in different documents are equal'); - }); - - QUnit.test('isEmpty', function(assert) { - assert.ok(!_([iNumber]).isEmpty(), '[1] is not empty'); - assert.ok(!_.isEmpty(iArray), '[] is empty'); - assert.ok(_.isEmpty(iObject), '{} is empty'); - }); - - QUnit.test('isElement', function(assert) { - assert.ok(!_.isElement('div'), 'strings are not dom elements'); - assert.ok(_.isElement(document.body), 'the body tag is a DOM element'); - assert.ok(_.isElement(iElement), 'even from another frame'); - }); - - QUnit.test('isArguments', function(assert) { - assert.ok(_.isArguments(iArguments), 'even from another frame'); - }); - - QUnit.test('isObject', function(assert) { - assert.ok(_.isObject(iElement), 'even from another frame'); - assert.ok(_.isObject(iFunction), 'even from another frame'); - }); - - QUnit.test('isArray', function(assert) { - assert.ok(_.isArray(iArray), 'even from another frame'); - }); - - QUnit.test('isString', function(assert) { - assert.ok(_.isString(iString), 'even from another frame'); - }); - - QUnit.test('isNumber', function(assert) { - assert.ok(_.isNumber(iNumber), 'even from another frame'); - }); - - QUnit.test('isBoolean', function(assert) { - assert.ok(_.isBoolean(iBoolean), 'even from another frame'); - }); - - QUnit.test('isFunction', function(assert) { - assert.ok(_.isFunction(iFunction), 'even from another frame'); - }); - - QUnit.test('isDate', function(assert) { - assert.ok(_.isDate(iDate), 'even from another frame'); - }); - - QUnit.test('isRegExp', function(assert) { - assert.ok(_.isRegExp(iRegExp), 'even from another frame'); - }); - - QUnit.test('isNaN', function(assert) { - assert.ok(_.isNaN(iNaN), 'even from another frame'); - }); - - QUnit.test('isNull', function(assert) { - assert.ok(_.isNull(iNull), 'even from another frame'); - }); - - QUnit.test('isUndefined', function(assert) { - assert.ok(_.isUndefined(iUndefined), 'even from another frame'); - }); - - QUnit.test('isError', function(assert) { - assert.ok(_.isError(iError), 'even from another frame'); - }); - - if (typeof ActiveXObject != 'undefined') { - QUnit.test('IE host objects', function(assert) { - var xml = new ActiveXObject('Msxml2.DOMDocument.3.0'); - assert.ok(!_.isNumber(xml)); - assert.ok(!_.isBoolean(xml)); - assert.ok(!_.isNaN(xml)); - assert.ok(!_.isFunction(xml)); - assert.ok(!_.isNull(xml)); - assert.ok(!_.isUndefined(xml)); - }); - - QUnit.test('#1621 IE 11 compat mode DOM elements are not functions', function(assert) { - var fn = function() {}; - var xml = new ActiveXObject('Msxml2.DOMDocument.3.0'); - var div = document.createElement('div'); - - // JIT the function - var count = 200; - while (count--) { - _.isFunction(fn); - } - - assert.equal(_.isFunction(xml), false); - assert.equal(_.isFunction(div), false); - assert.equal(_.isFunction(fn), true); - }); - } - -}()); diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/underscore/test/functions.js b/ecomp-portal-FE/client/bower_components/lodash/vendor/underscore/test/functions.js deleted file mode 100644 index f696bd64..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/underscore/test/functions.js +++ /dev/null @@ -1,728 +0,0 @@ -(function() { - var _ = typeof require == 'function' ? require('..') : window._; - - QUnit.module('Functions'); - QUnit.config.asyncRetries = 3; - - QUnit.test('bind', function(assert) { - var context = {name: 'moe'}; - var func = function(arg) { return 'name: ' + (this.name || arg); }; - var bound = _.bind(func, context); - assert.equal(bound(), 'name: moe', 'can bind a function to a context'); - - bound = _(func).bind(context); - assert.equal(bound(), 'name: moe', 'can do OO-style binding'); - - bound = _.bind(func, null, 'curly'); - var result = bound(); - // Work around a PhantomJS bug when applying a function with null|undefined. - assert.ok(result === 'name: curly' || result === 'name: ' + window.name, 'can bind without specifying a context'); - - func = function(salutation, name) { return salutation + ': ' + name; }; - func = _.bind(func, this, 'hello'); - assert.equal(func('moe'), 'hello: moe', 'the function was partially applied in advance'); - - func = _.bind(func, this, 'curly'); - assert.equal(func(), 'hello: curly', 'the function was completely applied in advance'); - - func = function(salutation, firstname, lastname) { return salutation + ': ' + firstname + ' ' + lastname; }; - func = _.bind(func, this, 'hello', 'moe', 'curly'); - assert.equal(func(), 'hello: moe curly', 'the function was partially applied in advance and can accept multiple arguments'); - - func = function(ctx, message) { assert.equal(this, ctx, message); }; - _.bind(func, 0, 0, 'can bind a function to `0`')(); - _.bind(func, '', '', 'can bind a function to an empty string')(); - _.bind(func, false, false, 'can bind a function to `false`')(); - - // These tests are only meaningful when using a browser without a native bind function - // To test this with a modern browser, set underscore's nativeBind to undefined - var F = function() { return this; }; - var boundf = _.bind(F, {hello: 'moe curly'}); - var Boundf = boundf; // make eslint happy. - var newBoundf = new Boundf(); - assert.equal(newBoundf.hello, void 0, 'function should not be bound to the context, to comply with ECMAScript 5'); - assert.equal(boundf().hello, 'moe curly', "When called without the new operator, it's OK to be bound to the context"); - assert.ok(newBoundf instanceof F, 'a bound instance is an instance of the original function'); - - assert.raises(function() { _.bind('notafunction'); }, TypeError, 'throws an error when binding to a non-function'); - }); - - QUnit.test('partial', function(assert) { - var obj = {name: 'moe'}; - var func = function() { return this.name + ' ' + _.toArray(arguments).join(' '); }; - - obj.func = _.partial(func, 'a', 'b'); - assert.equal(obj.func('c', 'd'), 'moe a b c d', 'can partially apply'); - - obj.func = _.partial(func, _, 'b', _, 'd'); - assert.equal(obj.func('a', 'c'), 'moe a b c d', 'can partially apply with placeholders'); - - func = _.partial(function() { return arguments.length; }, _, 'b', _, 'd'); - assert.equal(func('a', 'c', 'e'), 5, 'accepts more arguments than the number of placeholders'); - assert.equal(func('a'), 4, 'accepts fewer arguments than the number of placeholders'); - - func = _.partial(function() { return typeof arguments[2]; }, _, 'b', _, 'd'); - assert.equal(func('a'), 'undefined', 'unfilled placeholders are undefined'); - - // passes context - function MyWidget(name, options) { - this.name = name; - this.options = options; - } - MyWidget.prototype.get = function() { - return this.name; - }; - var MyWidgetWithCoolOpts = _.partial(MyWidget, _, {a: 1}); - var widget = new MyWidgetWithCoolOpts('foo'); - assert.ok(widget instanceof MyWidget, 'Can partially bind a constructor'); - assert.equal(widget.get(), 'foo', 'keeps prototype'); - assert.deepEqual(widget.options, {a: 1}); - - _.partial.placeholder = obj; - func = _.partial(function() { return arguments.length; }, obj, 'b', obj, 'd'); - assert.equal(func('a'), 4, 'allows the placeholder to be swapped out'); - - _.partial.placeholder = {}; - func = _.partial(function() { return arguments.length; }, obj, 'b', obj, 'd'); - assert.equal(func('a'), 5, 'swapping the placeholder preserves previously bound arguments'); - - _.partial.placeholder = _; - }); - - QUnit.test('bindAll', function(assert) { - var curly = {name: 'curly'}; - var moe = { - name: 'moe', - getName: function() { return 'name: ' + this.name; }, - sayHi: function() { return 'hi: ' + this.name; } - }; - curly.getName = moe.getName; - _.bindAll(moe, 'getName', 'sayHi'); - curly.sayHi = moe.sayHi; - assert.equal(curly.getName(), 'name: curly', 'unbound function is bound to current object'); - assert.equal(curly.sayHi(), 'hi: moe', 'bound function is still bound to original object'); - - curly = {name: 'curly'}; - moe = { - name: 'moe', - getName: function() { return 'name: ' + this.name; }, - sayHi: function() { return 'hi: ' + this.name; }, - sayLast: function() { return this.sayHi(_.last(arguments)); } - }; - - assert.raises(function() { _.bindAll(moe); }, Error, 'throws an error for bindAll with no functions named'); - assert.raises(function() { _.bindAll(moe, 'sayBye'); }, TypeError, 'throws an error for bindAll if the given key is undefined'); - assert.raises(function() { _.bindAll(moe, 'name'); }, TypeError, 'throws an error for bindAll if the given key is not a function'); - - _.bindAll(moe, 'sayHi', 'sayLast'); - curly.sayHi = moe.sayHi; - assert.equal(curly.sayHi(), 'hi: moe'); - - var sayLast = moe.sayLast; - assert.equal(sayLast(1, 2, 3, 4, 5, 6, 7, 'Tom'), 'hi: moe', 'createCallback works with any number of arguments'); - - _.bindAll(moe, ['getName']); - var getName = moe.getName; - assert.equal(getName(), 'name: moe', 'flattens arguments into a single list'); - }); - - QUnit.test('memoize', function(assert) { - var fib = function(n) { - return n < 2 ? n : fib(n - 1) + fib(n - 2); - }; - assert.equal(fib(10), 55, 'a memoized version of fibonacci produces identical results'); - fib = _.memoize(fib); // Redefine `fib` for memoization - assert.equal(fib(10), 55, 'a memoized version of fibonacci produces identical results'); - - var o = function(str) { - return str; - }; - var fastO = _.memoize(o); - assert.equal(o('toString'), 'toString', 'checks hasOwnProperty'); - assert.equal(fastO('toString'), 'toString', 'checks hasOwnProperty'); - - // Expose the cache. - var upper = _.memoize(function(s) { - return s.toUpperCase(); - }); - assert.equal(upper('foo'), 'FOO'); - assert.equal(upper('bar'), 'BAR'); - assert.deepEqual(upper.cache, {foo: 'FOO', bar: 'BAR'}); - upper.cache = {foo: 'BAR', bar: 'FOO'}; - assert.equal(upper('foo'), 'BAR'); - assert.equal(upper('bar'), 'FOO'); - - var hashed = _.memoize(function(key) { - //https://github.com/jashkenas/underscore/pull/1679#discussion_r13736209 - assert.ok(/[a-z]+/.test(key), 'hasher doesn\'t change keys'); - return key; - }, function(key) { - return key.toUpperCase(); - }); - hashed('yep'); - assert.deepEqual(hashed.cache, {YEP: 'yep'}, 'takes a hasher'); - - // Test that the hash function can be used to swizzle the key. - var objCacher = _.memoize(function(value, key) { - return {key: key, value: value}; - }, function(value, key) { - return key; - }); - var myObj = objCacher('a', 'alpha'); - var myObjAlias = objCacher('b', 'alpha'); - assert.notStrictEqual(myObj, void 0, 'object is created if second argument used as key'); - assert.strictEqual(myObj, myObjAlias, 'object is cached if second argument used as key'); - assert.strictEqual(myObj.value, 'a', 'object is not modified if second argument used as key'); - }); - - QUnit.test('delay', function(assert) { - assert.expect(2); - var done = assert.async(); - var delayed = false; - _.delay(function(){ delayed = true; }, 100); - setTimeout(function(){ assert.ok(!delayed, "didn't delay the function quite yet"); }, 50); - setTimeout(function(){ assert.ok(delayed, 'delayed the function'); done(); }, 150); - }); - - QUnit.test('defer', function(assert) { - assert.expect(1); - var done = assert.async(); - var deferred = false; - _.defer(function(bool){ deferred = bool; }, true); - _.delay(function(){ assert.ok(deferred, 'deferred the function'); done(); }, 50); - }); - - QUnit.test('throttle', function(assert) { - assert.expect(2); - var done = assert.async(); - var counter = 0; - var incr = function(){ counter++; }; - var throttledIncr = _.throttle(incr, 32); - throttledIncr(); throttledIncr(); - - assert.equal(counter, 1, 'incr was called immediately'); - _.delay(function(){ assert.equal(counter, 2, 'incr was throttled'); done(); }, 64); - }); - - QUnit.test('throttle arguments', function(assert) { - assert.expect(2); - var done = assert.async(); - var value = 0; - var update = function(val){ value = val; }; - var throttledUpdate = _.throttle(update, 32); - throttledUpdate(1); throttledUpdate(2); - _.delay(function(){ throttledUpdate(3); }, 64); - assert.equal(value, 1, 'updated to latest value'); - _.delay(function(){ assert.equal(value, 3, 'updated to latest value'); done(); }, 96); - }); - - QUnit.test('throttle once', function(assert) { - assert.expect(2); - var done = assert.async(); - var counter = 0; - var incr = function(){ return ++counter; }; - var throttledIncr = _.throttle(incr, 32); - var result = throttledIncr(); - _.delay(function(){ - assert.equal(result, 1, 'throttled functions return their value'); - assert.equal(counter, 1, 'incr was called once'); done(); - }, 64); - }); - - QUnit.test('throttle twice', function(assert) { - assert.expect(1); - var done = assert.async(); - var counter = 0; - var incr = function(){ counter++; }; - var throttledIncr = _.throttle(incr, 32); - throttledIncr(); throttledIncr(); - _.delay(function(){ assert.equal(counter, 2, 'incr was called twice'); done(); }, 64); - }); - - QUnit.test('more throttling', function(assert) { - assert.expect(3); - var done = assert.async(); - var counter = 0; - var incr = function(){ counter++; }; - var throttledIncr = _.throttle(incr, 30); - throttledIncr(); throttledIncr(); - assert.equal(counter, 1); - _.delay(function(){ - assert.equal(counter, 2); - throttledIncr(); - assert.equal(counter, 3); - done(); - }, 85); - }); - - QUnit.test('throttle repeatedly with results', function(assert) { - assert.expect(6); - var done = assert.async(); - var counter = 0; - var incr = function(){ return ++counter; }; - var throttledIncr = _.throttle(incr, 100); - var results = []; - var saveResult = function() { results.push(throttledIncr()); }; - saveResult(); saveResult(); - _.delay(saveResult, 50); - _.delay(saveResult, 150); - _.delay(saveResult, 160); - _.delay(saveResult, 230); - _.delay(function() { - assert.equal(results[0], 1, 'incr was called once'); - assert.equal(results[1], 1, 'incr was throttled'); - assert.equal(results[2], 1, 'incr was throttled'); - assert.equal(results[3], 2, 'incr was called twice'); - assert.equal(results[4], 2, 'incr was throttled'); - assert.equal(results[5], 3, 'incr was called trailing'); - done(); - }, 300); - }); - - QUnit.test('throttle triggers trailing call when invoked repeatedly', function(assert) { - assert.expect(2); - var done = assert.async(); - var counter = 0; - var limit = 48; - var incr = function(){ counter++; }; - var throttledIncr = _.throttle(incr, 32); - - var stamp = new Date; - while (new Date - stamp < limit) { - throttledIncr(); - } - var lastCount = counter; - assert.ok(counter > 1); - - _.delay(function() { - assert.ok(counter > lastCount); - done(); - }, 96); - }); - - QUnit.test('throttle does not trigger leading call when leading is set to false', function(assert) { - assert.expect(2); - var done = assert.async(); - var counter = 0; - var incr = function(){ counter++; }; - var throttledIncr = _.throttle(incr, 60, {leading: false}); - - throttledIncr(); throttledIncr(); - assert.equal(counter, 0); - - _.delay(function() { - assert.equal(counter, 1); - done(); - }, 96); - }); - - QUnit.test('more throttle does not trigger leading call when leading is set to false', function(assert) { - assert.expect(3); - var done = assert.async(); - var counter = 0; - var incr = function(){ counter++; }; - var throttledIncr = _.throttle(incr, 100, {leading: false}); - - throttledIncr(); - _.delay(throttledIncr, 50); - _.delay(throttledIncr, 60); - _.delay(throttledIncr, 200); - assert.equal(counter, 0); - - _.delay(function() { - assert.equal(counter, 1); - }, 250); - - _.delay(function() { - assert.equal(counter, 2); - done(); - }, 350); - }); - - QUnit.test('one more throttle with leading: false test', function(assert) { - assert.expect(2); - var done = assert.async(); - var counter = 0; - var incr = function(){ counter++; }; - var throttledIncr = _.throttle(incr, 100, {leading: false}); - - var time = new Date; - while (new Date - time < 350) throttledIncr(); - assert.ok(counter <= 3); - - _.delay(function() { - assert.ok(counter <= 4); - done(); - }, 200); - }); - - QUnit.test('throttle does not trigger trailing call when trailing is set to false', function(assert) { - assert.expect(4); - var done = assert.async(); - var counter = 0; - var incr = function(){ counter++; }; - var throttledIncr = _.throttle(incr, 60, {trailing: false}); - - throttledIncr(); throttledIncr(); throttledIncr(); - assert.equal(counter, 1); - - _.delay(function() { - assert.equal(counter, 1); - - throttledIncr(); throttledIncr(); - assert.equal(counter, 2); - - _.delay(function() { - assert.equal(counter, 2); - done(); - }, 96); - }, 96); - }); - - QUnit.test('throttle continues to function after system time is set backwards', function(assert) { - assert.expect(2); - var done = assert.async(); - var counter = 0; - var incr = function(){ counter++; }; - var throttledIncr = _.throttle(incr, 100); - var origNowFunc = _.now; - - throttledIncr(); - assert.equal(counter, 1); - _.now = function() { - return new Date(2013, 0, 1, 1, 1, 1); - }; - - _.delay(function() { - throttledIncr(); - assert.equal(counter, 2); - done(); - _.now = origNowFunc; - }, 200); - }); - - QUnit.test('throttle re-entrant', function(assert) { - assert.expect(2); - var done = assert.async(); - var sequence = [ - ['b1', 'b2'], - ['c1', 'c2'] - ]; - var value = ''; - var throttledAppend; - var append = function(arg){ - value += this + arg; - var args = sequence.pop(); - if (args) { - throttledAppend.call(args[0], args[1]); - } - }; - throttledAppend = _.throttle(append, 32); - throttledAppend.call('a1', 'a2'); - assert.equal(value, 'a1a2'); - _.delay(function(){ - assert.equal(value, 'a1a2c1c2b1b2', 'append was throttled successfully'); - done(); - }, 100); - }); - - QUnit.test('throttle cancel', function(assert) { - var done = assert.async(); - var counter = 0; - var incr = function(){ counter++; }; - var throttledIncr = _.throttle(incr, 32); - throttledIncr(); - throttledIncr.cancel(); - throttledIncr(); - throttledIncr(); - - assert.equal(counter, 2, 'incr was called immediately'); - _.delay(function(){ assert.equal(counter, 3, 'incr was throttled'); done(); }, 64); - }); - - QUnit.test('throttle cancel with leading: false', function(assert) { - var done = assert.async(); - var counter = 0; - var incr = function(){ counter++; }; - var throttledIncr = _.throttle(incr, 32, {leading: false}); - throttledIncr(); - throttledIncr.cancel(); - - assert.equal(counter, 0, 'incr was throttled'); - _.delay(function(){ assert.equal(counter, 0, 'incr was throttled'); done(); }, 64); - }); - - QUnit.test('debounce', function(assert) { - assert.expect(1); - var done = assert.async(); - var counter = 0; - var incr = function(){ counter++; }; - var debouncedIncr = _.debounce(incr, 32); - debouncedIncr(); debouncedIncr(); - _.delay(debouncedIncr, 16); - _.delay(function(){ assert.equal(counter, 1, 'incr was debounced'); done(); }, 96); - }); - - QUnit.test('debounce cancel', function(assert) { - assert.expect(1); - var done = assert.async(); - var counter = 0; - var incr = function(){ counter++; }; - var debouncedIncr = _.debounce(incr, 32); - debouncedIncr(); - debouncedIncr.cancel(); - _.delay(function(){ assert.equal(counter, 0, 'incr was not called'); done(); }, 96); - }); - - QUnit.test('debounce asap', function(assert) { - assert.expect(6); - var done = assert.async(); - var a, b, c; - var counter = 0; - var incr = function(){ return ++counter; }; - var debouncedIncr = _.debounce(incr, 64, true); - a = debouncedIncr(); - b = debouncedIncr(); - assert.equal(a, 1); - assert.equal(b, 1); - assert.equal(counter, 1, 'incr was called immediately'); - _.delay(debouncedIncr, 16); - _.delay(debouncedIncr, 32); - _.delay(debouncedIncr, 48); - _.delay(function(){ - assert.equal(counter, 1, 'incr was debounced'); - c = debouncedIncr(); - assert.equal(c, 2); - assert.equal(counter, 2, 'incr was called again'); - done(); - }, 128); - }); - - QUnit.test('debounce asap cancel', function(assert) { - assert.expect(4); - var done = assert.async(); - var a, b; - var counter = 0; - var incr = function(){ return ++counter; }; - var debouncedIncr = _.debounce(incr, 64, true); - a = debouncedIncr(); - debouncedIncr.cancel(); - b = debouncedIncr(); - assert.equal(a, 1); - assert.equal(b, 2); - assert.equal(counter, 2, 'incr was called immediately'); - _.delay(debouncedIncr, 16); - _.delay(debouncedIncr, 32); - _.delay(debouncedIncr, 48); - _.delay(function(){ assert.equal(counter, 2, 'incr was debounced'); done(); }, 128); - }); - - QUnit.test('debounce asap recursively', function(assert) { - assert.expect(2); - var done = assert.async(); - var counter = 0; - var debouncedIncr = _.debounce(function(){ - counter++; - if (counter < 10) debouncedIncr(); - }, 32, true); - debouncedIncr(); - assert.equal(counter, 1, 'incr was called immediately'); - _.delay(function(){ assert.equal(counter, 1, 'incr was debounced'); done(); }, 96); - }); - - QUnit.test('debounce after system time is set backwards', function(assert) { - assert.expect(2); - var done = assert.async(); - var counter = 0; - var origNowFunc = _.now; - var debouncedIncr = _.debounce(function(){ - counter++; - }, 100, true); - - debouncedIncr(); - assert.equal(counter, 1, 'incr was called immediately'); - - _.now = function() { - return new Date(2013, 0, 1, 1, 1, 1); - }; - - _.delay(function() { - debouncedIncr(); - assert.equal(counter, 2, 'incr was debounced successfully'); - done(); - _.now = origNowFunc; - }, 200); - }); - - QUnit.test('debounce re-entrant', function(assert) { - assert.expect(2); - var done = assert.async(); - var sequence = [ - ['b1', 'b2'] - ]; - var value = ''; - var debouncedAppend; - var append = function(arg){ - value += this + arg; - var args = sequence.pop(); - if (args) { - debouncedAppend.call(args[0], args[1]); - } - }; - debouncedAppend = _.debounce(append, 32); - debouncedAppend.call('a1', 'a2'); - assert.equal(value, ''); - _.delay(function(){ - assert.equal(value, 'a1a2b1b2', 'append was debounced successfully'); - done(); - }, 100); - }); - - QUnit.test('once', function(assert) { - var num = 0; - var increment = _.once(function(){ return ++num; }); - increment(); - increment(); - assert.equal(num, 1); - - assert.equal(increment(), 1, 'stores a memo to the last value'); - }); - - QUnit.test('Recursive onced function.', function(assert) { - assert.expect(1); - var f = _.once(function(){ - assert.ok(true); - f(); - }); - f(); - }); - - QUnit.test('wrap', function(assert) { - var greet = function(name){ return 'hi: ' + name; }; - var backwards = _.wrap(greet, function(func, name){ return func(name) + ' ' + name.split('').reverse().join(''); }); - assert.equal(backwards('moe'), 'hi: moe eom', 'wrapped the salutation function'); - - var inner = function(){ return 'Hello '; }; - var obj = {name: 'Moe'}; - obj.hi = _.wrap(inner, function(fn){ return fn() + this.name; }); - assert.equal(obj.hi(), 'Hello Moe'); - - var noop = function(){}; - var wrapped = _.wrap(noop, function(){ return Array.prototype.slice.call(arguments, 0); }); - var ret = wrapped(['whats', 'your'], 'vector', 'victor'); - assert.deepEqual(ret, [noop, ['whats', 'your'], 'vector', 'victor']); - }); - - QUnit.test('negate', function(assert) { - var isOdd = function(n){ return n & 1; }; - assert.equal(_.negate(isOdd)(2), true, 'should return the complement of the given function'); - assert.equal(_.negate(isOdd)(3), false, 'should return the complement of the given function'); - }); - - QUnit.test('compose', function(assert) { - var greet = function(name){ return 'hi: ' + name; }; - var exclaim = function(sentence){ return sentence + '!'; }; - var composed = _.compose(exclaim, greet); - assert.equal(composed('moe'), 'hi: moe!', 'can compose a function that takes another'); - - composed = _.compose(greet, exclaim); - assert.equal(composed('moe'), 'hi: moe!', 'in this case, the functions are also commutative'); - - // f(g(h(x, y, z))) - function h(x, y, z) { - assert.equal(arguments.length, 3, 'First function called with multiple args'); - return z * y; - } - function g(x) { - assert.equal(arguments.length, 1, 'Composed function is called with 1 argument'); - return x; - } - function f(x) { - assert.equal(arguments.length, 1, 'Composed function is called with 1 argument'); - return x * 2; - } - composed = _.compose(f, g, h); - assert.equal(composed(1, 2, 3), 12); - }); - - QUnit.test('after', function(assert) { - var testAfter = function(afterAmount, timesCalled) { - var afterCalled = 0; - var after = _.after(afterAmount, function() { - afterCalled++; - }); - while (timesCalled--) after(); - return afterCalled; - }; - - assert.equal(testAfter(5, 5), 1, 'after(N) should fire after being called N times'); - assert.equal(testAfter(5, 4), 0, 'after(N) should not fire unless called N times'); - assert.equal(testAfter(0, 0), 0, 'after(0) should not fire immediately'); - assert.equal(testAfter(0, 1), 1, 'after(0) should fire when first invoked'); - }); - - QUnit.test('before', function(assert) { - var testBefore = function(beforeAmount, timesCalled) { - var beforeCalled = 0; - var before = _.before(beforeAmount, function() { beforeCalled++; }); - while (timesCalled--) before(); - return beforeCalled; - }; - - assert.equal(testBefore(5, 5), 4, 'before(N) should not fire after being called N times'); - assert.equal(testBefore(5, 4), 4, 'before(N) should fire before being called N times'); - assert.equal(testBefore(0, 0), 0, 'before(0) should not fire immediately'); - assert.equal(testBefore(0, 1), 0, 'before(0) should not fire when first invoked'); - - var context = {num: 0}; - var increment = _.before(3, function(){ return ++this.num; }); - _.times(10, increment, context); - assert.equal(increment(), 2, 'stores a memo to the last value'); - assert.equal(context.num, 2, 'provides context'); - }); - - QUnit.test('iteratee', function(assert) { - var identity = _.iteratee(); - assert.equal(identity, _.identity, '_.iteratee is exposed as an external function.'); - - function fn() { - return arguments; - } - _.each([_.iteratee(fn), _.iteratee(fn, {})], function(cb) { - assert.equal(cb().length, 0); - assert.deepEqual(_.toArray(cb(1, 2, 3)), _.range(1, 4)); - assert.deepEqual(_.toArray(cb(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)), _.range(1, 11)); - }); - - }); - - QUnit.test('restArgs', function(assert) { - assert.expect(10); - _.restArgs(function(a, args) { - assert.strictEqual(a, 1); - assert.deepEqual(args, [2, 3], 'collects rest arguments into an array'); - })(1, 2, 3); - - _.restArgs(function(a, args) { - assert.strictEqual(a, void 0); - assert.deepEqual(args, [], 'passes empty array if there are not enough arguments'); - })(); - - _.restArgs(function(a, b, c, args) { - assert.strictEqual(arguments.length, 4); - assert.deepEqual(args, [4, 5], 'works on functions with many named parameters'); - })(1, 2, 3, 4, 5); - - var obj = {}; - _.restArgs(function() { - assert.strictEqual(this, obj, 'invokes function with this context'); - }).call(obj); - - _.restArgs(function(array, iteratee, context) { - assert.deepEqual(array, [1, 2, 3, 4], 'startIndex can be used manually specify index of rest parameter'); - assert.strictEqual(iteratee, void 0); - assert.strictEqual(context, void 0); - }, 0)(1, 2, 3, 4); - }); - -}()); diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/underscore/test/objects.js b/ecomp-portal-FE/client/bower_components/lodash/vendor/underscore/test/objects.js deleted file mode 100644 index fa1d9e3e..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/underscore/test/objects.js +++ /dev/null @@ -1,1102 +0,0 @@ -(function() { - var _ = typeof require == 'function' ? require('..') : window._; - - QUnit.module('Objects'); - - var testElement = typeof document === 'object' ? document.createElement('div') : void 0; - - QUnit.test('keys', function(assert) { - assert.deepEqual(_.keys({one: 1, two: 2}), ['one', 'two'], 'can extract the keys from an object'); - // the test above is not safe because it relies on for-in enumeration order - var a = []; a[1] = 0; - assert.deepEqual(_.keys(a), ['1'], 'is not fooled by sparse arrays; see issue #95'); - assert.deepEqual(_.keys(null), []); - assert.deepEqual(_.keys(void 0), []); - assert.deepEqual(_.keys(1), []); - assert.deepEqual(_.keys('a'), []); - assert.deepEqual(_.keys(true), []); - - // keys that may be missed if the implementation isn't careful - var trouble = { - constructor: Object, - valueOf: _.noop, - hasOwnProperty: null, - toString: 5, - toLocaleString: void 0, - propertyIsEnumerable: /a/, - isPrototypeOf: this, - __defineGetter__: Boolean, - __defineSetter__: {}, - __lookupSetter__: false, - __lookupGetter__: [] - }; - var troubleKeys = ['constructor', 'valueOf', 'hasOwnProperty', 'toString', 'toLocaleString', 'propertyIsEnumerable', - 'isPrototypeOf', '__defineGetter__', '__defineSetter__', '__lookupSetter__', '__lookupGetter__'].sort(); - assert.deepEqual(_.keys(trouble).sort(), troubleKeys, 'matches non-enumerable properties'); - }); - - QUnit.test('allKeys', function(assert) { - assert.deepEqual(_.allKeys({one: 1, two: 2}), ['one', 'two'], 'can extract the allKeys from an object'); - // the test above is not safe because it relies on for-in enumeration order - var a = []; a[1] = 0; - assert.deepEqual(_.allKeys(a), ['1'], 'is not fooled by sparse arrays; see issue #95'); - - a.a = a; - assert.deepEqual(_.allKeys(a), ['1', 'a'], 'is not fooled by sparse arrays with additional properties'); - - _.each([null, void 0, 1, 'a', true, NaN, {}, [], new Number(5), new Date(0)], function(val) { - assert.deepEqual(_.allKeys(val), []); - }); - - // allKeys that may be missed if the implementation isn't careful - var trouble = { - constructor: Object, - valueOf: _.noop, - hasOwnProperty: null, - toString: 5, - toLocaleString: void 0, - propertyIsEnumerable: /a/, - isPrototypeOf: this - }; - var troubleKeys = ['constructor', 'valueOf', 'hasOwnProperty', 'toString', 'toLocaleString', 'propertyIsEnumerable', - 'isPrototypeOf'].sort(); - assert.deepEqual(_.allKeys(trouble).sort(), troubleKeys, 'matches non-enumerable properties'); - - function A() {} - A.prototype.foo = 'foo'; - var b = new A(); - b.bar = 'bar'; - assert.deepEqual(_.allKeys(b).sort(), ['bar', 'foo'], 'should include inherited keys'); - - function y() {} - y.x = 'z'; - assert.deepEqual(_.allKeys(y), ['x'], 'should get keys from constructor'); - }); - - QUnit.test('values', function(assert) { - assert.deepEqual(_.values({one: 1, two: 2}), [1, 2], 'can extract the values from an object'); - assert.deepEqual(_.values({one: 1, two: 2, length: 3}), [1, 2, 3], '... even when one of them is "length"'); - }); - - QUnit.test('pairs', function(assert) { - assert.deepEqual(_.pairs({one: 1, two: 2}), [['one', 1], ['two', 2]], 'can convert an object into pairs'); - assert.deepEqual(_.pairs({one: 1, two: 2, length: 3}), [['one', 1], ['two', 2], ['length', 3]], '... even when one of them is "length"'); - }); - - QUnit.test('invert', function(assert) { - var obj = {first: 'Moe', second: 'Larry', third: 'Curly'}; - assert.deepEqual(_.keys(_.invert(obj)), ['Moe', 'Larry', 'Curly'], 'can invert an object'); - assert.deepEqual(_.invert(_.invert(obj)), obj, 'two inverts gets you back where you started'); - - obj = {length: 3}; - assert.equal(_.invert(obj)['3'], 'length', 'can invert an object with "length"'); - }); - - QUnit.test('functions', function(assert) { - var obj = {a: 'dash', b: _.map, c: /yo/, d: _.reduce}; - assert.deepEqual(['b', 'd'], _.functions(obj), 'can grab the function names of any passed-in object'); - - var Animal = function(){}; - Animal.prototype.run = function(){}; - assert.deepEqual(_.functions(new Animal), ['run'], 'also looks up functions on the prototype'); - }); - - QUnit.test('methods', function(assert) { - assert.strictEqual(_.methods, _.functions, 'is an alias for functions'); - }); - - QUnit.test('extend', function(assert) { - var result; - assert.equal(_.extend({}, {a: 'b'}).a, 'b', 'can extend an object with the attributes of another'); - assert.equal(_.extend({a: 'x'}, {a: 'b'}).a, 'b', 'properties in source override destination'); - assert.equal(_.extend({x: 'x'}, {a: 'b'}).x, 'x', "properties not in source don't get overriden"); - result = _.extend({x: 'x'}, {a: 'a'}, {b: 'b'}); - assert.deepEqual(result, {x: 'x', a: 'a', b: 'b'}, 'can extend from multiple source objects'); - result = _.extend({x: 'x'}, {a: 'a', x: 2}, {a: 'b'}); - assert.deepEqual(result, {x: 2, a: 'b'}, 'extending from multiple source objects last property trumps'); - result = _.extend({}, {a: void 0, b: null}); - assert.deepEqual(_.keys(result), ['a', 'b'], 'extend copies undefined values'); - - var F = function() {}; - F.prototype = {a: 'b'}; - var subObj = new F(); - subObj.c = 'd'; - assert.deepEqual(_.extend({}, subObj), {a: 'b', c: 'd'}, 'extend copies all properties from source'); - _.extend(subObj, {}); - assert.ok(!subObj.hasOwnProperty('a'), "extend does not convert destination object's 'in' properties to 'own' properties"); - - try { - result = {}; - _.extend(result, null, void 0, {a: 1}); - } catch (e) { /* ignored */ } - - assert.equal(result.a, 1, 'should not error on `null` or `undefined` sources'); - - assert.strictEqual(_.extend(null, {a: 1}), null, 'extending null results in null'); - assert.strictEqual(_.extend(void 0, {a: 1}), void 0, 'extending undefined results in undefined'); - }); - - QUnit.test('extendOwn', function(assert) { - var result; - assert.equal(_.extendOwn({}, {a: 'b'}).a, 'b', 'can extend an object with the attributes of another'); - assert.equal(_.extendOwn({a: 'x'}, {a: 'b'}).a, 'b', 'properties in source override destination'); - assert.equal(_.extendOwn({x: 'x'}, {a: 'b'}).x, 'x', "properties not in source don't get overriden"); - result = _.extendOwn({x: 'x'}, {a: 'a'}, {b: 'b'}); - assert.deepEqual(result, {x: 'x', a: 'a', b: 'b'}, 'can extend from multiple source objects'); - result = _.extendOwn({x: 'x'}, {a: 'a', x: 2}, {a: 'b'}); - assert.deepEqual(result, {x: 2, a: 'b'}, 'extending from multiple source objects last property trumps'); - assert.deepEqual(_.extendOwn({}, {a: void 0, b: null}), {a: void 0, b: null}, 'copies undefined values'); - - var F = function() {}; - F.prototype = {a: 'b'}; - var subObj = new F(); - subObj.c = 'd'; - assert.deepEqual(_.extendOwn({}, subObj), {c: 'd'}, 'copies own properties from source'); - - result = {}; - assert.deepEqual(_.extendOwn(result, null, void 0, {a: 1}), {a: 1}, 'should not error on `null` or `undefined` sources'); - - _.each(['a', 5, null, false], function(val) { - assert.strictEqual(_.extendOwn(val, {a: 1}), val, 'extending non-objects results in returning the non-object value'); - }); - - assert.strictEqual(_.extendOwn(void 0, {a: 1}), void 0, 'extending undefined results in undefined'); - - result = _.extendOwn({a: 1, 0: 2, 1: '5', length: 6}, {0: 1, 1: 2, length: 2}); - assert.deepEqual(result, {a: 1, 0: 1, 1: 2, length: 2}, 'should treat array-like objects like normal objects'); - }); - - QUnit.test('assign', function(assert) { - assert.strictEqual(_.assign, _.extendOwn, 'is an alias for extendOwn'); - }); - - QUnit.test('pick', function(assert) { - var result; - result = _.pick({a: 1, b: 2, c: 3}, 'a', 'c'); - assert.deepEqual(result, {a: 1, c: 3}, 'can restrict properties to those named'); - result = _.pick({a: 1, b: 2, c: 3}, ['b', 'c']); - assert.deepEqual(result, {b: 2, c: 3}, 'can restrict properties to those named in an array'); - result = _.pick({a: 1, b: 2, c: 3}, ['a'], 'b'); - assert.deepEqual(result, {a: 1, b: 2}, 'can restrict properties to those named in mixed args'); - result = _.pick(['a', 'b'], 1); - assert.deepEqual(result, {1: 'b'}, 'can pick numeric properties'); - - _.each([null, void 0], function(val) { - assert.deepEqual(_.pick(val, 'hasOwnProperty'), {}, 'Called with null/undefined'); - assert.deepEqual(_.pick(val, _.constant(true)), {}); - }); - assert.deepEqual(_.pick(5, 'toString', 'b'), {toString: Number.prototype.toString}, 'can iterate primitives'); - - var data = {a: 1, b: 2, c: 3}; - var callback = function(value, key, object) { - assert.strictEqual(key, {1: 'a', 2: 'b', 3: 'c'}[value]); - assert.strictEqual(object, data); - return value !== this.value; - }; - result = _.pick(data, callback, {value: 2}); - assert.deepEqual(result, {a: 1, c: 3}, 'can accept a predicate and context'); - - var Obj = function(){}; - Obj.prototype = {a: 1, b: 2, c: 3}; - var instance = new Obj(); - assert.deepEqual(_.pick(instance, 'a', 'c'), {a: 1, c: 3}, 'include prototype props'); - - assert.deepEqual(_.pick(data, function(val, key) { - return this[key] === 3 && this === instance; - }, instance), {c: 3}, 'function is given context'); - - assert.ok(!_.has(_.pick({}, 'foo'), 'foo'), 'does not set own property if property not in object'); - _.pick(data, function(value, key, obj) { - assert.equal(obj, data, 'passes same object as third parameter of iteratee'); - }); - }); - - QUnit.test('omit', function(assert) { - var result; - result = _.omit({a: 1, b: 2, c: 3}, 'b'); - assert.deepEqual(result, {a: 1, c: 3}, 'can omit a single named property'); - result = _.omit({a: 1, b: 2, c: 3}, 'a', 'c'); - assert.deepEqual(result, {b: 2}, 'can omit several named properties'); - result = _.omit({a: 1, b: 2, c: 3}, ['b', 'c']); - assert.deepEqual(result, {a: 1}, 'can omit properties named in an array'); - result = _.omit(['a', 'b'], 0); - assert.deepEqual(result, {1: 'b'}, 'can omit numeric properties'); - - assert.deepEqual(_.omit(null, 'a', 'b'), {}, 'non objects return empty object'); - assert.deepEqual(_.omit(void 0, 'toString'), {}, 'null/undefined return empty object'); - assert.deepEqual(_.omit(5, 'toString', 'b'), {}, 'returns empty object for primitives'); - - var data = {a: 1, b: 2, c: 3}; - var callback = function(value, key, object) { - assert.strictEqual(key, {1: 'a', 2: 'b', 3: 'c'}[value]); - assert.strictEqual(object, data); - return value !== this.value; - }; - result = _.omit(data, callback, {value: 2}); - assert.deepEqual(result, {b: 2}, 'can accept a predicate'); - - var Obj = function(){}; - Obj.prototype = {a: 1, b: 2, c: 3}; - var instance = new Obj(); - assert.deepEqual(_.omit(instance, 'b'), {a: 1, c: 3}, 'include prototype props'); - - assert.deepEqual(_.omit(data, function(val, key) { - return this[key] === 3 && this === instance; - }, instance), {a: 1, b: 2}, 'function is given context'); - }); - - QUnit.test('defaults', function(assert) { - var options = {zero: 0, one: 1, empty: '', nan: NaN, nothing: null}; - - _.defaults(options, {zero: 1, one: 10, twenty: 20, nothing: 'str'}); - assert.equal(options.zero, 0, 'value exists'); - assert.equal(options.one, 1, 'value exists'); - assert.equal(options.twenty, 20, 'default applied'); - assert.equal(options.nothing, null, "null isn't overridden"); - - _.defaults(options, {empty: 'full'}, {nan: 'nan'}, {word: 'word'}, {word: 'dog'}); - assert.equal(options.empty, '', 'value exists'); - assert.ok(_.isNaN(options.nan), "NaN isn't overridden"); - assert.equal(options.word, 'word', 'new value is added, first one wins'); - - try { - options = {}; - _.defaults(options, null, void 0, {a: 1}); - } catch (e) { /* ignored */ } - - assert.equal(options.a, 1, 'should not error on `null` or `undefined` sources'); - - assert.deepEqual(_.defaults(null, {a: 1}), {a: 1}, 'defaults skips nulls'); - assert.deepEqual(_.defaults(void 0, {a: 1}), {a: 1}, 'defaults skips undefined'); - }); - - QUnit.test('clone', function(assert) { - var moe = {name: 'moe', lucky: [13, 27, 34]}; - var clone = _.clone(moe); - assert.equal(clone.name, 'moe', 'the clone as the attributes of the original'); - - clone.name = 'curly'; - assert.ok(clone.name === 'curly' && moe.name === 'moe', 'clones can change shallow attributes without affecting the original'); - - clone.lucky.push(101); - assert.equal(_.last(moe.lucky), 101, 'changes to deep attributes are shared with the original'); - - assert.equal(_.clone(void 0), void 0, 'non objects should not be changed by clone'); - assert.equal(_.clone(1), 1, 'non objects should not be changed by clone'); - assert.equal(_.clone(null), null, 'non objects should not be changed by clone'); - }); - - QUnit.test('create', function(assert) { - var Parent = function() {}; - Parent.prototype = {foo: function() {}, bar: 2}; - - _.each(['foo', null, void 0, 1], function(val) { - assert.deepEqual(_.create(val), {}, 'should return empty object when a non-object is provided'); - }); - - assert.ok(_.create([]) instanceof Array, 'should return new instance of array when array is provided'); - - var Child = function() {}; - Child.prototype = _.create(Parent.prototype); - assert.ok(new Child instanceof Parent, 'object should inherit prototype'); - - var func = function() {}; - Child.prototype = _.create(Parent.prototype, {func: func}); - assert.strictEqual(Child.prototype.func, func, 'properties should be added to object'); - - Child.prototype = _.create(Parent.prototype, {constructor: Child}); - assert.strictEqual(Child.prototype.constructor, Child); - - Child.prototype.foo = 'foo'; - var created = _.create(Child.prototype, new Child); - assert.ok(!created.hasOwnProperty('foo'), 'should only add own properties'); - }); - - QUnit.test('isEqual', function(assert) { - function First() { - this.value = 1; - } - First.prototype.value = 1; - function Second() { - this.value = 1; - } - Second.prototype.value = 2; - - // Basic equality and identity comparisons. - assert.ok(_.isEqual(null, null), '`null` is equal to `null`'); - assert.ok(_.isEqual(), '`undefined` is equal to `undefined`'); - - assert.ok(!_.isEqual(0, -0), '`0` is not equal to `-0`'); - assert.ok(!_.isEqual(-0, 0), 'Commutative equality is implemented for `0` and `-0`'); - assert.ok(!_.isEqual(null, void 0), '`null` is not equal to `undefined`'); - assert.ok(!_.isEqual(void 0, null), 'Commutative equality is implemented for `null` and `undefined`'); - - // String object and primitive comparisons. - assert.ok(_.isEqual('Curly', 'Curly'), 'Identical string primitives are equal'); - assert.ok(_.isEqual(new String('Curly'), new String('Curly')), 'String objects with identical primitive values are equal'); - assert.ok(_.isEqual(new String('Curly'), 'Curly'), 'String primitives and their corresponding object wrappers are equal'); - assert.ok(_.isEqual('Curly', new String('Curly')), 'Commutative equality is implemented for string objects and primitives'); - - assert.ok(!_.isEqual('Curly', 'Larry'), 'String primitives with different values are not equal'); - assert.ok(!_.isEqual(new String('Curly'), new String('Larry')), 'String objects with different primitive values are not equal'); - assert.ok(!_.isEqual(new String('Curly'), {toString: function(){ return 'Curly'; }}), 'String objects and objects with a custom `toString` method are not equal'); - - // Number object and primitive comparisons. - assert.ok(_.isEqual(75, 75), 'Identical number primitives are equal'); - assert.ok(_.isEqual(new Number(75), new Number(75)), 'Number objects with identical primitive values are equal'); - assert.ok(_.isEqual(75, new Number(75)), 'Number primitives and their corresponding object wrappers are equal'); - assert.ok(_.isEqual(new Number(75), 75), 'Commutative equality is implemented for number objects and primitives'); - assert.ok(!_.isEqual(new Number(0), -0), '`new Number(0)` and `-0` are not equal'); - assert.ok(!_.isEqual(0, new Number(-0)), 'Commutative equality is implemented for `new Number(0)` and `-0`'); - - assert.ok(!_.isEqual(new Number(75), new Number(63)), 'Number objects with different primitive values are not equal'); - assert.ok(!_.isEqual(new Number(63), {valueOf: function(){ return 63; }}), 'Number objects and objects with a `valueOf` method are not equal'); - - // Comparisons involving `NaN`. - assert.ok(_.isEqual(NaN, NaN), '`NaN` is equal to `NaN`'); - assert.ok(_.isEqual(new Number(NaN), NaN), 'Object(`NaN`) is equal to `NaN`'); - assert.ok(!_.isEqual(61, NaN), 'A number primitive is not equal to `NaN`'); - assert.ok(!_.isEqual(new Number(79), NaN), 'A number object is not equal to `NaN`'); - assert.ok(!_.isEqual(Infinity, NaN), '`Infinity` is not equal to `NaN`'); - - // Boolean object and primitive comparisons. - assert.ok(_.isEqual(true, true), 'Identical boolean primitives are equal'); - assert.ok(_.isEqual(new Boolean, new Boolean), 'Boolean objects with identical primitive values are equal'); - assert.ok(_.isEqual(true, new Boolean(true)), 'Boolean primitives and their corresponding object wrappers are equal'); - assert.ok(_.isEqual(new Boolean(true), true), 'Commutative equality is implemented for booleans'); - assert.ok(!_.isEqual(new Boolean(true), new Boolean), 'Boolean objects with different primitive values are not equal'); - - // Common type coercions. - assert.ok(!_.isEqual(new Boolean(false), true), '`new Boolean(false)` is not equal to `true`'); - assert.ok(!_.isEqual('75', 75), 'String and number primitives with like values are not equal'); - assert.ok(!_.isEqual(new Number(63), new String(63)), 'String and number objects with like values are not equal'); - assert.ok(!_.isEqual(75, '75'), 'Commutative equality is implemented for like string and number values'); - assert.ok(!_.isEqual(0, ''), 'Number and string primitives with like values are not equal'); - assert.ok(!_.isEqual(1, true), 'Number and boolean primitives with like values are not equal'); - assert.ok(!_.isEqual(new Boolean(false), new Number(0)), 'Boolean and number objects with like values are not equal'); - assert.ok(!_.isEqual(false, new String('')), 'Boolean primitives and string objects with like values are not equal'); - assert.ok(!_.isEqual(12564504e5, new Date(2009, 9, 25)), 'Dates and their corresponding numeric primitive values are not equal'); - - // Dates. - assert.ok(_.isEqual(new Date(2009, 9, 25), new Date(2009, 9, 25)), 'Date objects referencing identical times are equal'); - assert.ok(!_.isEqual(new Date(2009, 9, 25), new Date(2009, 11, 13)), 'Date objects referencing different times are not equal'); - assert.ok(!_.isEqual(new Date(2009, 11, 13), { - getTime: function(){ - return 12606876e5; - } - }), 'Date objects and objects with a `getTime` method are not equal'); - assert.ok(!_.isEqual(new Date('Curly'), new Date('Curly')), 'Invalid dates are not equal'); - - // Functions. - assert.ok(!_.isEqual(First, Second), 'Different functions with identical bodies and source code representations are not equal'); - - // RegExps. - assert.ok(_.isEqual(/(?:)/gim, /(?:)/gim), 'RegExps with equivalent patterns and flags are equal'); - assert.ok(_.isEqual(/(?:)/gi, /(?:)/ig), 'Flag order is not significant'); - assert.ok(!_.isEqual(/(?:)/g, /(?:)/gi), 'RegExps with equivalent patterns and different flags are not equal'); - assert.ok(!_.isEqual(/Moe/gim, /Curly/gim), 'RegExps with different patterns and equivalent flags are not equal'); - assert.ok(!_.isEqual(/(?:)/gi, /(?:)/g), 'Commutative equality is implemented for RegExps'); - assert.ok(!_.isEqual(/Curly/g, {source: 'Larry', global: true, ignoreCase: false, multiline: false}), 'RegExps and RegExp-like objects are not equal'); - - // Empty arrays, array-like objects, and object literals. - assert.ok(_.isEqual({}, {}), 'Empty object literals are equal'); - assert.ok(_.isEqual([], []), 'Empty array literals are equal'); - assert.ok(_.isEqual([{}], [{}]), 'Empty nested arrays and objects are equal'); - assert.ok(!_.isEqual({length: 0}, []), 'Array-like objects and arrays are not equal.'); - assert.ok(!_.isEqual([], {length: 0}), 'Commutative equality is implemented for array-like objects'); - - assert.ok(!_.isEqual({}, []), 'Object literals and array literals are not equal'); - assert.ok(!_.isEqual([], {}), 'Commutative equality is implemented for objects and arrays'); - - // Arrays with primitive and object values. - assert.ok(_.isEqual([1, 'Larry', true], [1, 'Larry', true]), 'Arrays containing identical primitives are equal'); - assert.ok(_.isEqual([/Moe/g, new Date(2009, 9, 25)], [/Moe/g, new Date(2009, 9, 25)]), 'Arrays containing equivalent elements are equal'); - - // Multi-dimensional arrays. - var a = [new Number(47), false, 'Larry', /Moe/, new Date(2009, 11, 13), ['running', 'biking', new String('programming')], {a: 47}]; - var b = [new Number(47), false, 'Larry', /Moe/, new Date(2009, 11, 13), ['running', 'biking', new String('programming')], {a: 47}]; - assert.ok(_.isEqual(a, b), 'Arrays containing nested arrays and objects are recursively compared'); - - // Overwrite the methods defined in ES 5.1 section 15.4.4. - a.forEach = a.map = a.filter = a.every = a.indexOf = a.lastIndexOf = a.some = a.reduce = a.reduceRight = null; - b.join = b.pop = b.reverse = b.shift = b.slice = b.splice = b.concat = b.sort = b.unshift = null; - - // Array elements and properties. - assert.ok(_.isEqual(a, b), 'Arrays containing equivalent elements and different non-numeric properties are equal'); - a.push('White Rocks'); - assert.ok(!_.isEqual(a, b), 'Arrays of different lengths are not equal'); - a.push('East Boulder'); - b.push('Gunbarrel Ranch', 'Teller Farm'); - assert.ok(!_.isEqual(a, b), 'Arrays of identical lengths containing different elements are not equal'); - - // Sparse arrays. - assert.ok(_.isEqual(Array(3), Array(3)), 'Sparse arrays of identical lengths are equal'); - assert.ok(!_.isEqual(Array(3), Array(6)), 'Sparse arrays of different lengths are not equal when both are empty'); - - var sparse = []; - sparse[1] = 5; - assert.ok(_.isEqual(sparse, [void 0, 5]), 'Handles sparse arrays as dense'); - - // Simple objects. - assert.ok(_.isEqual({a: 'Curly', b: 1, c: true}, {a: 'Curly', b: 1, c: true}), 'Objects containing identical primitives are equal'); - assert.ok(_.isEqual({a: /Curly/g, b: new Date(2009, 11, 13)}, {a: /Curly/g, b: new Date(2009, 11, 13)}), 'Objects containing equivalent members are equal'); - assert.ok(!_.isEqual({a: 63, b: 75}, {a: 61, b: 55}), 'Objects of identical sizes with different values are not equal'); - assert.ok(!_.isEqual({a: 63, b: 75}, {a: 61, c: 55}), 'Objects of identical sizes with different property names are not equal'); - assert.ok(!_.isEqual({a: 1, b: 2}, {a: 1}), 'Objects of different sizes are not equal'); - assert.ok(!_.isEqual({a: 1}, {a: 1, b: 2}), 'Commutative equality is implemented for objects'); - assert.ok(!_.isEqual({x: 1, y: void 0}, {x: 1, z: 2}), 'Objects with identical keys and different values are not equivalent'); - - // `A` contains nested objects and arrays. - a = { - name: new String('Moe Howard'), - age: new Number(77), - stooge: true, - hobbies: ['acting'], - film: { - name: 'Sing a Song of Six Pants', - release: new Date(1947, 9, 30), - stars: [new String('Larry Fine'), 'Shemp Howard'], - minutes: new Number(16), - seconds: 54 - } - }; - - // `B` contains equivalent nested objects and arrays. - b = { - name: new String('Moe Howard'), - age: new Number(77), - stooge: true, - hobbies: ['acting'], - film: { - name: 'Sing a Song of Six Pants', - release: new Date(1947, 9, 30), - stars: [new String('Larry Fine'), 'Shemp Howard'], - minutes: new Number(16), - seconds: 54 - } - }; - assert.ok(_.isEqual(a, b), 'Objects with nested equivalent members are recursively compared'); - - // Instances. - assert.ok(_.isEqual(new First, new First), 'Object instances are equal'); - assert.ok(!_.isEqual(new First, new Second), 'Objects with different constructors and identical own properties are not equal'); - assert.ok(!_.isEqual({value: 1}, new First), 'Object instances and objects sharing equivalent properties are not equal'); - assert.ok(!_.isEqual({value: 2}, new Second), 'The prototype chain of objects should not be examined'); - - // Circular Arrays. - (a = []).push(a); - (b = []).push(b); - assert.ok(_.isEqual(a, b), 'Arrays containing circular references are equal'); - a.push(new String('Larry')); - b.push(new String('Larry')); - assert.ok(_.isEqual(a, b), 'Arrays containing circular references and equivalent properties are equal'); - a.push('Shemp'); - b.push('Curly'); - assert.ok(!_.isEqual(a, b), 'Arrays containing circular references and different properties are not equal'); - - // More circular arrays #767. - a = ['everything is checked but', 'this', 'is not']; - a[1] = a; - b = ['everything is checked but', ['this', 'array'], 'is not']; - assert.ok(!_.isEqual(a, b), 'Comparison of circular references with non-circular references are not equal'); - - // Circular Objects. - a = {abc: null}; - b = {abc: null}; - a.abc = a; - b.abc = b; - assert.ok(_.isEqual(a, b), 'Objects containing circular references are equal'); - a.def = 75; - b.def = 75; - assert.ok(_.isEqual(a, b), 'Objects containing circular references and equivalent properties are equal'); - a.def = new Number(75); - b.def = new Number(63); - assert.ok(!_.isEqual(a, b), 'Objects containing circular references and different properties are not equal'); - - // More circular objects #767. - a = {everything: 'is checked', but: 'this', is: 'not'}; - a.but = a; - b = {everything: 'is checked', but: {that: 'object'}, is: 'not'}; - assert.ok(!_.isEqual(a, b), 'Comparison of circular references with non-circular object references are not equal'); - - // Cyclic Structures. - a = [{abc: null}]; - b = [{abc: null}]; - (a[0].abc = a).push(a); - (b[0].abc = b).push(b); - assert.ok(_.isEqual(a, b), 'Cyclic structures are equal'); - a[0].def = 'Larry'; - b[0].def = 'Larry'; - assert.ok(_.isEqual(a, b), 'Cyclic structures containing equivalent properties are equal'); - a[0].def = new String('Larry'); - b[0].def = new String('Curly'); - assert.ok(!_.isEqual(a, b), 'Cyclic structures containing different properties are not equal'); - - // Complex Circular References. - a = {foo: {b: {foo: {c: {foo: null}}}}}; - b = {foo: {b: {foo: {c: {foo: null}}}}}; - a.foo.b.foo.c.foo = a; - b.foo.b.foo.c.foo = b; - assert.ok(_.isEqual(a, b), 'Cyclic structures with nested and identically-named properties are equal'); - - // Chaining. - assert.ok(!_.isEqual(_({x: 1, y: void 0}).chain(), _({x: 1, z: 2}).chain()), 'Chained objects containing different values are not equal'); - - a = _({x: 1, y: 2}).chain(); - b = _({x: 1, y: 2}).chain(); - assert.equal(_.isEqual(a.isEqual(b), _(true)), true, '`isEqual` can be chained'); - - // Objects without a `constructor` property - if (Object.create) { - a = Object.create(null, {x: {value: 1, enumerable: true}}); - b = {x: 1}; - assert.ok(_.isEqual(a, b), 'Handles objects without a constructor (e.g. from Object.create'); - } - - function Foo() { this.a = 1; } - Foo.prototype.constructor = null; - - var other = {a: 1}; - assert.strictEqual(_.isEqual(new Foo, other), false, 'Objects from different constructors are not equal'); - - - // Tricky object cases val comparisions - assert.equal(_.isEqual([0], [-0]), false); - assert.equal(_.isEqual({a: 0}, {a: -0}), false); - assert.equal(_.isEqual([NaN], [NaN]), true); - assert.equal(_.isEqual({a: NaN}, {a: NaN}), true); - - if (typeof Symbol !== 'undefined') { - var symbol = Symbol('x'); - assert.strictEqual(_.isEqual(symbol, symbol), true, 'A symbol is equal to itself'); - assert.strictEqual(_.isEqual(symbol, Object(symbol)), true, 'Even when wrapped in Object()'); - assert.strictEqual(_.isEqual(symbol, null), false, 'Different types are not equal'); - } - - }); - - QUnit.test('isEmpty', function(assert) { - assert.ok(!_([1]).isEmpty(), '[1] is not empty'); - assert.ok(_.isEmpty([]), '[] is empty'); - assert.ok(!_.isEmpty({one: 1}), '{one: 1} is not empty'); - assert.ok(_.isEmpty({}), '{} is empty'); - assert.ok(_.isEmpty(new RegExp('')), 'objects with prototype properties are empty'); - assert.ok(_.isEmpty(null), 'null is empty'); - assert.ok(_.isEmpty(), 'undefined is empty'); - assert.ok(_.isEmpty(''), 'the empty string is empty'); - assert.ok(!_.isEmpty('moe'), 'but other strings are not'); - - var obj = {one: 1}; - delete obj.one; - assert.ok(_.isEmpty(obj), 'deleting all the keys from an object empties it'); - - var args = function(){ return arguments; }; - assert.ok(_.isEmpty(args()), 'empty arguments object is empty'); - assert.ok(!_.isEmpty(args('')), 'non-empty arguments object is not empty'); - - // covers collecting non-enumerable properties in IE < 9 - var nonEnumProp = {toString: 5}; - assert.ok(!_.isEmpty(nonEnumProp), 'non-enumerable property is not empty'); - }); - - if (typeof document === 'object') { - QUnit.test('isElement', function(assert) { - assert.ok(!_.isElement('div'), 'strings are not dom elements'); - assert.ok(_.isElement(testElement), 'an element is a DOM element'); - }); - } - - QUnit.test('isArguments', function(assert) { - var args = (function(){ return arguments; }(1, 2, 3)); - assert.ok(!_.isArguments('string'), 'a string is not an arguments object'); - assert.ok(!_.isArguments(_.isArguments), 'a function is not an arguments object'); - assert.ok(_.isArguments(args), 'but the arguments object is an arguments object'); - assert.ok(!_.isArguments(_.toArray(args)), 'but not when it\'s converted into an array'); - assert.ok(!_.isArguments([1, 2, 3]), 'and not vanilla arrays.'); - }); - - QUnit.test('isObject', function(assert) { - assert.ok(_.isObject(arguments), 'the arguments object is object'); - assert.ok(_.isObject([1, 2, 3]), 'and arrays'); - if (testElement) { - assert.ok(_.isObject(testElement), 'and DOM element'); - } - assert.ok(_.isObject(function() {}), 'and functions'); - assert.ok(!_.isObject(null), 'but not null'); - assert.ok(!_.isObject(void 0), 'and not undefined'); - assert.ok(!_.isObject('string'), 'and not string'); - assert.ok(!_.isObject(12), 'and not number'); - assert.ok(!_.isObject(true), 'and not boolean'); - assert.ok(_.isObject(new String('string')), 'but new String()'); - }); - - QUnit.test('isArray', function(assert) { - assert.ok(!_.isArray(void 0), 'undefined vars are not arrays'); - assert.ok(!_.isArray(arguments), 'the arguments object is not an array'); - assert.ok(_.isArray([1, 2, 3]), 'but arrays are'); - }); - - QUnit.test('isString', function(assert) { - var obj = new String('I am a string object'); - if (testElement) { - assert.ok(!_.isString(testElement), 'an element is not a string'); - } - assert.ok(_.isString([1, 2, 3].join(', ')), 'but strings are'); - assert.strictEqual(_.isString('I am a string literal'), true, 'string literals are'); - assert.ok(_.isString(obj), 'so are String objects'); - assert.strictEqual(_.isString(1), false); - }); - - QUnit.test('isSymbol', function(assert) { - assert.ok(!_.isSymbol(0), 'numbers are not symbols'); - assert.ok(!_.isSymbol(''), 'strings are not symbols'); - assert.ok(!_.isSymbol(_.isSymbol), 'functions are not symbols'); - if (typeof Symbol === 'function') { - assert.ok(_.isSymbol(Symbol()), 'symbols are symbols'); - assert.ok(_.isSymbol(Symbol('description')), 'described symbols are symbols'); - assert.ok(_.isSymbol(Object(Symbol())), 'boxed symbols are symbols'); - } - }); - - QUnit.test('isNumber', function(assert) { - assert.ok(!_.isNumber('string'), 'a string is not a number'); - assert.ok(!_.isNumber(arguments), 'the arguments object is not a number'); - assert.ok(!_.isNumber(void 0), 'undefined is not a number'); - assert.ok(_.isNumber(3 * 4 - 7 / 10), 'but numbers are'); - assert.ok(_.isNumber(NaN), 'NaN *is* a number'); - assert.ok(_.isNumber(Infinity), 'Infinity is a number'); - assert.ok(!_.isNumber('1'), 'numeric strings are not numbers'); - }); - - QUnit.test('isBoolean', function(assert) { - assert.ok(!_.isBoolean(2), 'a number is not a boolean'); - assert.ok(!_.isBoolean('string'), 'a string is not a boolean'); - assert.ok(!_.isBoolean('false'), 'the string "false" is not a boolean'); - assert.ok(!_.isBoolean('true'), 'the string "true" is not a boolean'); - assert.ok(!_.isBoolean(arguments), 'the arguments object is not a boolean'); - assert.ok(!_.isBoolean(void 0), 'undefined is not a boolean'); - assert.ok(!_.isBoolean(NaN), 'NaN is not a boolean'); - assert.ok(!_.isBoolean(null), 'null is not a boolean'); - assert.ok(_.isBoolean(true), 'but true is'); - assert.ok(_.isBoolean(false), 'and so is false'); - }); - - QUnit.test('isMap', function(assert) { - assert.ok(!_.isMap('string'), 'a string is not a map'); - assert.ok(!_.isMap(2), 'a number is not a map'); - assert.ok(!_.isMap({}), 'an object is not a map'); - assert.ok(!_.isMap(false), 'a boolean is not a map'); - assert.ok(!_.isMap(void 0), 'undefined is not a map'); - assert.ok(!_.isMap([1, 2, 3]), 'an array is not a map'); - if (typeof Set === 'function') { - assert.ok(!_.isMap(new Set()), 'a set is not a map'); - } - if (typeof WeakSet === 'function') { - assert.ok(!_.isMap(new WeakSet()), 'a weakset is not a map'); - } - if (typeof WeakMap === 'function') { - assert.ok(!_.isMap(new WeakMap()), 'a weakmap is not a map'); - } - if (typeof Map === 'function') { - var keyString = 'a string'; - var obj = new Map(); - obj.set(keyString, 'value'); - assert.ok(_.isMap(obj), 'but a map is'); - } - }); - - QUnit.test('isWeakMap', function(assert) { - assert.ok(!_.isWeakMap('string'), 'a string is not a weakmap'); - assert.ok(!_.isWeakMap(2), 'a number is not a weakmap'); - assert.ok(!_.isWeakMap({}), 'an object is not a weakmap'); - assert.ok(!_.isWeakMap(false), 'a boolean is not a weakmap'); - assert.ok(!_.isWeakMap(void 0), 'undefined is not a weakmap'); - assert.ok(!_.isWeakMap([1, 2, 3]), 'an array is not a weakmap'); - if (typeof Set === 'function') { - assert.ok(!_.isWeakMap(new Set()), 'a set is not a weakmap'); - } - if (typeof WeakSet === 'function') { - assert.ok(!_.isWeakMap(new WeakSet()), 'a weakset is not a weakmap'); - } - if (typeof Map === 'function') { - assert.ok(!_.isWeakMap(new Map()), 'a map is not a weakmap'); - } - if (typeof WeakMap === 'function') { - var keyObj = {}, obj = new WeakMap(); - obj.set(keyObj, 'value'); - assert.ok(_.isWeakMap(obj), 'but a weakmap is'); - } - }); - - QUnit.test('isSet', function(assert) { - assert.ok(!_.isSet('string'), 'a string is not a set'); - assert.ok(!_.isSet(2), 'a number is not a set'); - assert.ok(!_.isSet({}), 'an object is not a set'); - assert.ok(!_.isSet(false), 'a boolean is not a set'); - assert.ok(!_.isSet(void 0), 'undefined is not a set'); - assert.ok(!_.isSet([1, 2, 3]), 'an array is not a set'); - if (typeof Map === 'function') { - assert.ok(!_.isSet(new Map()), 'a map is not a set'); - } - if (typeof WeakMap === 'function') { - assert.ok(!_.isSet(new WeakMap()), 'a weakmap is not a set'); - } - if (typeof WeakSet === 'function') { - assert.ok(!_.isSet(new WeakSet()), 'a weakset is not a set'); - } - if (typeof Set === 'function') { - var obj = new Set(); - obj.add(1).add('string').add(false).add({}); - assert.ok(_.isSet(obj), 'but a set is'); - } - }); - - QUnit.test('isWeakSet', function(assert) { - - assert.ok(!_.isWeakSet('string'), 'a string is not a weakset'); - assert.ok(!_.isWeakSet(2), 'a number is not a weakset'); - assert.ok(!_.isWeakSet({}), 'an object is not a weakset'); - assert.ok(!_.isWeakSet(false), 'a boolean is not a weakset'); - assert.ok(!_.isWeakSet(void 0), 'undefined is not a weakset'); - assert.ok(!_.isWeakSet([1, 2, 3]), 'an array is not a weakset'); - if (typeof Map === 'function') { - assert.ok(!_.isWeakSet(new Map()), 'a map is not a weakset'); - } - if (typeof WeakMap === 'function') { - assert.ok(!_.isWeakSet(new WeakMap()), 'a weakmap is not a weakset'); - } - if (typeof Set === 'function') { - assert.ok(!_.isWeakSet(new Set()), 'a set is not a weakset'); - } - if (typeof WeakSet === 'function') { - var obj = new WeakSet(); - obj.add({x: 1}, {y: 'string'}).add({y: 'string'}).add({z: [1, 2, 3]}); - assert.ok(_.isWeakSet(obj), 'but a weakset is'); - } - }); - - QUnit.test('isFunction', function(assert) { - assert.ok(!_.isFunction(void 0), 'undefined vars are not functions'); - assert.ok(!_.isFunction([1, 2, 3]), 'arrays are not functions'); - assert.ok(!_.isFunction('moe'), 'strings are not functions'); - assert.ok(_.isFunction(_.isFunction), 'but functions are'); - assert.ok(_.isFunction(function(){}), 'even anonymous ones'); - - if (testElement) { - assert.ok(!_.isFunction(testElement), 'elements are not functions'); - } - - var nodelist = typeof document != 'undefined' && document.childNodes; - if (nodelist) { - assert.ok(!_.isFunction(nodelist)); - } - }); - - if (typeof Int8Array !== 'undefined') { - QUnit.test('#1929 Typed Array constructors are functions', function(assert) { - _.chain(['Float32Array', 'Float64Array', 'Int8Array', 'Int16Array', 'Int32Array', 'Uint8Array', 'Uint8ClampedArray', 'Uint16Array', 'Uint32Array']) - .map(_.propertyOf(typeof GLOBAL != 'undefined' ? GLOBAL : window)) - .compact() - .each(function(TypedArray) { - // PhantomJS reports `typeof UInt8Array == 'object'` and doesn't report toString TypeArray - // as a function - assert.strictEqual(_.isFunction(TypedArray), Object.prototype.toString.call(TypedArray) === '[object Function]'); - }); - }); - } - - QUnit.test('isDate', function(assert) { - assert.ok(!_.isDate(100), 'numbers are not dates'); - assert.ok(!_.isDate({}), 'objects are not dates'); - assert.ok(_.isDate(new Date()), 'but dates are'); - }); - - QUnit.test('isRegExp', function(assert) { - assert.ok(!_.isRegExp(_.identity), 'functions are not RegExps'); - assert.ok(_.isRegExp(/identity/), 'but RegExps are'); - }); - - QUnit.test('isFinite', function(assert) { - assert.ok(!_.isFinite(void 0), 'undefined is not finite'); - assert.ok(!_.isFinite(null), 'null is not finite'); - assert.ok(!_.isFinite(NaN), 'NaN is not finite'); - assert.ok(!_.isFinite(Infinity), 'Infinity is not finite'); - assert.ok(!_.isFinite(-Infinity), '-Infinity is not finite'); - assert.ok(_.isFinite('12'), 'Numeric strings are numbers'); - assert.ok(!_.isFinite('1a'), 'Non numeric strings are not numbers'); - assert.ok(!_.isFinite(''), 'Empty strings are not numbers'); - var obj = new Number(5); - assert.ok(_.isFinite(obj), 'Number instances can be finite'); - assert.ok(_.isFinite(0), '0 is finite'); - assert.ok(_.isFinite(123), 'Ints are finite'); - assert.ok(_.isFinite(-12.44), 'Floats are finite'); - if (typeof Symbol === 'function') { - assert.ok(!_.isFinite(Symbol()), 'symbols are not numbers'); - assert.ok(!_.isFinite(Symbol('description')), 'described symbols are not numbers'); - assert.ok(!_.isFinite(Object(Symbol())), 'boxed symbols are not numbers'); - } - }); - - QUnit.test('isNaN', function(assert) { - assert.ok(!_.isNaN(void 0), 'undefined is not NaN'); - assert.ok(!_.isNaN(null), 'null is not NaN'); - assert.ok(!_.isNaN(0), '0 is not NaN'); - assert.ok(!_.isNaN(new Number(0)), 'wrapped 0 is not NaN'); - assert.ok(_.isNaN(NaN), 'but NaN is'); - assert.ok(_.isNaN(new Number(NaN)), 'wrapped NaN is still NaN'); - }); - - QUnit.test('isNull', function(assert) { - assert.ok(!_.isNull(void 0), 'undefined is not null'); - assert.ok(!_.isNull(NaN), 'NaN is not null'); - assert.ok(_.isNull(null), 'but null is'); - }); - - QUnit.test('isUndefined', function(assert) { - assert.ok(!_.isUndefined(1), 'numbers are defined'); - assert.ok(!_.isUndefined(null), 'null is defined'); - assert.ok(!_.isUndefined(false), 'false is defined'); - assert.ok(!_.isUndefined(NaN), 'NaN is defined'); - assert.ok(_.isUndefined(), 'nothing is undefined'); - assert.ok(_.isUndefined(void 0), 'undefined is undefined'); - }); - - QUnit.test('isError', function(assert) { - assert.ok(!_.isError(1), 'numbers are not Errors'); - assert.ok(!_.isError(null), 'null is not an Error'); - assert.ok(!_.isError(Error), 'functions are not Errors'); - assert.ok(_.isError(new Error()), 'Errors are Errors'); - assert.ok(_.isError(new EvalError()), 'EvalErrors are Errors'); - assert.ok(_.isError(new RangeError()), 'RangeErrors are Errors'); - assert.ok(_.isError(new ReferenceError()), 'ReferenceErrors are Errors'); - assert.ok(_.isError(new SyntaxError()), 'SyntaxErrors are Errors'); - assert.ok(_.isError(new TypeError()), 'TypeErrors are Errors'); - assert.ok(_.isError(new URIError()), 'URIErrors are Errors'); - }); - - QUnit.test('tap', function(assert) { - var intercepted = null; - var interceptor = function(obj) { intercepted = obj; }; - var returned = _.tap(1, interceptor); - assert.equal(intercepted, 1, 'passes tapped object to interceptor'); - assert.equal(returned, 1, 'returns tapped object'); - - returned = _([1, 2, 3]).chain(). - map(function(n){ return n * 2; }). - max(). - tap(interceptor). - value(); - assert.equal(returned, 6, 'can use tapped objects in a chain'); - assert.equal(intercepted, returned, 'can use tapped objects in a chain'); - }); - - QUnit.test('has', function(assert) { - var obj = {foo: 'bar', func: function(){}}; - assert.ok(_.has(obj, 'foo'), 'has() checks that the object has a property.'); - assert.ok(!_.has(obj, 'baz'), "has() returns false if the object doesn't have the property."); - assert.ok(_.has(obj, 'func'), 'has() works for functions too.'); - obj.hasOwnProperty = null; - assert.ok(_.has(obj, 'foo'), 'has() works even when the hasOwnProperty method is deleted.'); - var child = {}; - child.prototype = obj; - assert.ok(!_.has(child, 'foo'), 'has() does not check the prototype chain for a property.'); - assert.strictEqual(_.has(null, 'foo'), false, 'has() returns false for null'); - assert.strictEqual(_.has(void 0, 'foo'), false, 'has() returns false for undefined'); - }); - - QUnit.test('isMatch', function(assert) { - var moe = {name: 'Moe Howard', hair: true}; - var curly = {name: 'Curly Howard', hair: false}; - - assert.equal(_.isMatch(moe, {hair: true}), true, 'Returns a boolean'); - assert.equal(_.isMatch(curly, {hair: true}), false, 'Returns a boolean'); - - assert.equal(_.isMatch(5, {__x__: void 0}), false, 'can match undefined props on primitives'); - assert.equal(_.isMatch({__x__: void 0}, {__x__: void 0}), true, 'can match undefined props'); - - assert.equal(_.isMatch(null, {}), true, 'Empty spec called with null object returns true'); - assert.equal(_.isMatch(null, {a: 1}), false, 'Non-empty spec called with null object returns false'); - - _.each([null, void 0], function(item) { assert.strictEqual(_.isMatch(item, null), true, 'null matches null'); }); - _.each([null, void 0], function(item) { assert.strictEqual(_.isMatch(item, null), true, 'null matches {}'); }); - assert.strictEqual(_.isMatch({b: 1}, {a: void 0}), false, 'handles undefined values (1683)'); - - _.each([true, 5, NaN, null, void 0], function(item) { - assert.strictEqual(_.isMatch({a: 1}, item), true, 'treats primitives as empty'); - }); - - function Prototest() {} - Prototest.prototype.x = 1; - var specObj = new Prototest; - assert.equal(_.isMatch({x: 2}, specObj), true, 'spec is restricted to own properties'); - - specObj.y = 5; - assert.equal(_.isMatch({x: 1, y: 5}, specObj), true); - assert.equal(_.isMatch({x: 1, y: 4}, specObj), false); - - assert.ok(_.isMatch(specObj, {x: 1, y: 5}), 'inherited and own properties are checked on the test object'); - - Prototest.x = 5; - assert.ok(_.isMatch({x: 5, y: 1}, Prototest), 'spec can be a function'); - - //null edge cases - var oCon = {constructor: Object}; - assert.deepEqual(_.map([null, void 0, 5, {}], _.partial(_.isMatch, _, oCon)), [false, false, false, true], 'doesnt falsey match constructor on undefined/null'); - }); - - QUnit.test('matcher', function(assert) { - var moe = {name: 'Moe Howard', hair: true}; - var curly = {name: 'Curly Howard', hair: false}; - var stooges = [moe, curly]; - - assert.equal(_.matcher({hair: true})(moe), true, 'Returns a boolean'); - assert.equal(_.matcher({hair: true})(curly), false, 'Returns a boolean'); - - assert.equal(_.matcher({__x__: void 0})(5), false, 'can match undefined props on primitives'); - assert.equal(_.matcher({__x__: void 0})({__x__: void 0}), true, 'can match undefined props'); - - assert.equal(_.matcher({})(null), true, 'Empty spec called with null object returns true'); - assert.equal(_.matcher({a: 1})(null), false, 'Non-empty spec called with null object returns false'); - - assert.ok(_.find(stooges, _.matcher({hair: false})) === curly, 'returns a predicate that can be used by finding functions.'); - assert.ok(_.find(stooges, _.matcher(moe)) === moe, 'can be used to locate an object exists in a collection.'); - assert.deepEqual(_.filter([null, void 0], _.matcher({a: 1})), [], 'Do not throw on null values.'); - - assert.deepEqual(_.filter([null, void 0], _.matcher(null)), [null, void 0], 'null matches null'); - assert.deepEqual(_.filter([null, void 0], _.matcher({})), [null, void 0], 'null matches {}'); - assert.deepEqual(_.filter([{b: 1}], _.matcher({a: void 0})), [], 'handles undefined values (1683)'); - - _.each([true, 5, NaN, null, void 0], function(item) { - assert.equal(_.matcher(item)({a: 1}), true, 'treats primitives as empty'); - }); - - function Prototest() {} - Prototest.prototype.x = 1; - var specObj = new Prototest; - var protospec = _.matcher(specObj); - assert.equal(protospec({x: 2}), true, 'spec is restricted to own properties'); - - specObj.y = 5; - protospec = _.matcher(specObj); - assert.equal(protospec({x: 1, y: 5}), true); - assert.equal(protospec({x: 1, y: 4}), false); - - assert.ok(_.matcher({x: 1, y: 5})(specObj), 'inherited and own properties are checked on the test object'); - - Prototest.x = 5; - assert.ok(_.matcher(Prototest)({x: 5, y: 1}), 'spec can be a function'); - - // #1729 - var o = {b: 1}; - var m = _.matcher(o); - - assert.equal(m({b: 1}), true); - o.b = 2; - o.a = 1; - assert.equal(m({b: 1}), true, 'changing spec object doesnt change matches result'); - - - //null edge cases - var oCon = _.matcher({constructor: Object}); - assert.deepEqual(_.map([null, void 0, 5, {}], oCon), [false, false, false, true], 'doesnt falsey match constructor on undefined/null'); - }); - - QUnit.test('matches', function(assert) { - assert.strictEqual(_.matches, _.matcher, 'is an alias for matcher'); - }); - - QUnit.test('findKey', function(assert) { - var objects = { - a: {a: 0, b: 0}, - b: {a: 1, b: 1}, - c: {a: 2, b: 2} - }; - - assert.equal(_.findKey(objects, function(obj) { - return obj.a === 0; - }), 'a'); - - assert.equal(_.findKey(objects, function(obj) { - return obj.b * obj.a === 4; - }), 'c'); - - assert.equal(_.findKey(objects, 'a'), 'b', 'Uses lookupIterator'); - - assert.equal(_.findKey(objects, function(obj) { - return obj.b * obj.a === 5; - }), void 0); - - assert.strictEqual(_.findKey([1, 2, 3, 4, 5, 6], function(obj) { - return obj === 3; - }), '2', 'Keys are strings'); - - assert.strictEqual(_.findKey(objects, function(a) { - return a.foo === null; - }), void 0); - - _.findKey({a: {a: 1}}, function(a, key, obj) { - assert.equal(key, 'a'); - assert.deepEqual(obj, {a: {a: 1}}); - assert.strictEqual(this, objects, 'called with context'); - }, objects); - - var array = [1, 2, 3, 4]; - array.match = 55; - assert.strictEqual(_.findKey(array, function(x) { return x === 55; }), 'match', 'matches array-likes keys'); - }); - - - QUnit.test('mapObject', function(assert) { - var obj = {a: 1, b: 2}; - var objects = { - a: {a: 0, b: 0}, - b: {a: 1, b: 1}, - c: {a: 2, b: 2} - }; - - assert.deepEqual(_.mapObject(obj, function(val) { - return val * 2; - }), {a: 2, b: 4}, 'simple objects'); - - assert.deepEqual(_.mapObject(objects, function(val) { - return _.reduce(val, function(memo, v){ - return memo + v; - }, 0); - }), {a: 0, b: 2, c: 4}, 'nested objects'); - - assert.deepEqual(_.mapObject(obj, function(val, key, o) { - return o[key] * 2; - }), {a: 2, b: 4}, 'correct keys'); - - assert.deepEqual(_.mapObject([1, 2], function(val) { - return val * 2; - }), {0: 2, 1: 4}, 'check behavior for arrays'); - - assert.deepEqual(_.mapObject(obj, function(val) { - return val * this.multiplier; - }, {multiplier: 3}), {a: 3, b: 6}, 'keep context'); - - assert.deepEqual(_.mapObject({a: 1}, function() { - return this.length; - }, [1, 2]), {a: 2}, 'called with context'); - - var ids = _.mapObject({length: 2, 0: {id: '1'}, 1: {id: '2'}}, function(n){ - return n.id; - }); - assert.deepEqual(ids, {length: void 0, 0: '1', 1: '2'}, 'Check with array-like objects'); - - // Passing a property name like _.pluck. - var people = {a: {name: 'moe', age: 30}, b: {name: 'curly', age: 50}}; - assert.deepEqual(_.mapObject(people, 'name'), {a: 'moe', b: 'curly'}, 'predicate string map to object properties'); - - _.each([null, void 0, 1, 'abc', [], {}, void 0], function(val){ - assert.deepEqual(_.mapObject(val, _.identity), {}, 'mapValue identity'); - }); - - var Proto = function(){ this.a = 1; }; - Proto.prototype.b = 1; - var protoObj = new Proto(); - assert.deepEqual(_.mapObject(protoObj, _.identity), {a: 1}, 'ignore inherited values from prototypes'); - - }); -}()); diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/underscore/test/utility.js b/ecomp-portal-FE/client/bower_components/lodash/vendor/underscore/test/utility.js deleted file mode 100644 index fbd54df3..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/underscore/test/utility.js +++ /dev/null @@ -1,420 +0,0 @@ -(function() { - var _ = typeof require == 'function' ? require('..') : window._; - var templateSettings; - - QUnit.module('Utility', { - - beforeEach: function() { - templateSettings = _.clone(_.templateSettings); - }, - - afterEach: function() { - _.templateSettings = templateSettings; - } - - }); - - if (typeof this == 'object') { - QUnit.test('noConflict', function(assert) { - var underscore = _.noConflict(); - assert.equal(underscore.identity(1), 1); - if (typeof require != 'function') { - assert.equal(this._, void 0, 'global underscore is removed'); - this._ = underscore; - } else if (typeof global !== 'undefined') { - delete global._; - } - }); - } - - if (typeof require == 'function') { - QUnit.test('noConflict (node vm)', function(assert) { - assert.expect(2); - var done = assert.async(); - var fs = require('fs'); - var vm = require('vm'); - var filename = __dirname + '/../underscore.js'; - fs.readFile(filename, function(err, content){ - var sandbox = vm.createScript( - content + 'this.underscore = this._.noConflict();', - filename - ); - var context = {_: 'oldvalue'}; - sandbox.runInNewContext(context); - assert.equal(context._, 'oldvalue'); - assert.equal(context.underscore.VERSION, _.VERSION); - - done(); - }); - }); - } - - QUnit.test('#750 - Return _ instance.', function(assert) { - assert.expect(2); - var instance = _([]); - assert.ok(_(instance) === instance); - assert.ok(new _(instance) === instance); - }); - - QUnit.test('identity', function(assert) { - var stooge = {name: 'moe'}; - assert.equal(_.identity(stooge), stooge, 'stooge is the same as his identity'); - }); - - QUnit.test('constant', function(assert) { - var stooge = {name: 'moe'}; - assert.equal(_.constant(stooge)(), stooge, 'should create a function that returns stooge'); - }); - - QUnit.test('noop', function(assert) { - assert.strictEqual(_.noop('curly', 'larry', 'moe'), void 0, 'should always return undefined'); - }); - - QUnit.test('property', function(assert) { - var stooge = {name: 'moe'}; - assert.equal(_.property('name')(stooge), 'moe', 'should return the property with the given name'); - assert.equal(_.property('name')(null), void 0, 'should return undefined for null values'); - assert.equal(_.property('name')(void 0), void 0, 'should return undefined for undefined values'); - }); - - QUnit.test('propertyOf', function(assert) { - var stoogeRanks = _.propertyOf({curly: 2, moe: 1, larry: 3}); - assert.equal(stoogeRanks('curly'), 2, 'should return the property with the given name'); - assert.equal(stoogeRanks(null), void 0, 'should return undefined for null values'); - assert.equal(stoogeRanks(void 0), void 0, 'should return undefined for undefined values'); - - function MoreStooges() { this.shemp = 87; } - MoreStooges.prototype = {curly: 2, moe: 1, larry: 3}; - var moreStoogeRanks = _.propertyOf(new MoreStooges()); - assert.equal(moreStoogeRanks('curly'), 2, 'should return properties from further up the prototype chain'); - - var nullPropertyOf = _.propertyOf(null); - assert.equal(nullPropertyOf('curly'), void 0, 'should return undefined when obj is null'); - - var undefPropertyOf = _.propertyOf(void 0); - assert.equal(undefPropertyOf('curly'), void 0, 'should return undefined when obj is undefined'); - }); - - QUnit.test('random', function(assert) { - var array = _.range(1000); - var min = Math.pow(2, 31); - var max = Math.pow(2, 62); - - assert.ok(_.every(array, function() { - return _.random(min, max) >= min; - }), 'should produce a random number greater than or equal to the minimum number'); - - assert.ok(_.some(array, function() { - return _.random(Number.MAX_VALUE) > 0; - }), 'should produce a random number when passed `Number.MAX_VALUE`'); - }); - - QUnit.test('now', function(assert) { - var diff = _.now() - new Date().getTime(); - assert.ok(diff <= 0 && diff > -5, 'Produces the correct time in milliseconds');//within 5ms - }); - - QUnit.test('uniqueId', function(assert) { - var ids = [], i = 0; - while (i++ < 100) ids.push(_.uniqueId()); - assert.equal(_.uniq(ids).length, ids.length, 'can generate a globally-unique stream of ids'); - }); - - QUnit.test('times', function(assert) { - var vals = []; - _.times(3, function(i) { vals.push(i); }); - assert.deepEqual(vals, [0, 1, 2], 'is 0 indexed'); - // - vals = []; - _(3).times(function(i) { vals.push(i); }); - assert.deepEqual(vals, [0, 1, 2], 'works as a wrapper'); - // collects return values - assert.deepEqual([0, 1, 2], _.times(3, function(i) { return i; }), 'collects return values'); - - assert.deepEqual(_.times(0, _.identity), []); - assert.deepEqual(_.times(-1, _.identity), []); - assert.deepEqual(_.times(parseFloat('-Infinity'), _.identity), []); - }); - - QUnit.test('mixin', function(assert) { - _.mixin({ - myReverse: function(string) { - return string.split('').reverse().join(''); - } - }); - assert.equal(_.myReverse('panacea'), 'aecanap', 'mixed in a function to _'); - assert.equal(_('champ').myReverse(), 'pmahc', 'mixed in a function to the OOP wrapper'); - }); - - QUnit.test('_.escape', function(assert) { - assert.equal(_.escape(null), ''); - }); - - QUnit.test('_.unescape', function(assert) { - var string = 'Curly & Moe'; - assert.equal(_.unescape(null), ''); - assert.equal(_.unescape(_.escape(string)), string); - assert.equal(_.unescape(string), string, 'don\'t unescape unnecessarily'); - }); - - // Don't care what they escape them to just that they're escaped and can be unescaped - QUnit.test('_.escape & unescape', function(assert) { - // test & (&) seperately obviously - var escapeCharacters = ['<', '>', '"', '\'', '`']; - - _.each(escapeCharacters, function(escapeChar) { - var s = 'a ' + escapeChar + ' string escaped'; - var e = _.escape(s); - assert.notEqual(s, e, escapeChar + ' is escaped'); - assert.equal(s, _.unescape(e), escapeChar + ' can be unescaped'); - - s = 'a ' + escapeChar + escapeChar + escapeChar + 'some more string' + escapeChar; - e = _.escape(s); - - assert.equal(e.indexOf(escapeChar), -1, 'can escape multiple occurances of ' + escapeChar); - assert.equal(_.unescape(e), s, 'multiple occurrences of ' + escapeChar + ' can be unescaped'); - }); - - // handles multiple escape characters at once - var joiner = ' other stuff '; - var allEscaped = escapeCharacters.join(joiner); - allEscaped += allEscaped; - assert.ok(_.every(escapeCharacters, function(escapeChar) { - return allEscaped.indexOf(escapeChar) !== -1; - }), 'handles multiple characters'); - assert.ok(allEscaped.indexOf(joiner) >= 0, 'can escape multiple escape characters at the same time'); - - // test & -> & - var str = 'some string & another string & yet another'; - var escaped = _.escape(str); - - assert.ok(escaped.indexOf('&') !== -1, 'handles & aka &'); - assert.equal(_.unescape(str), str, 'can unescape &'); - }); - - QUnit.test('template', function(assert) { - var basicTemplate = _.template("<%= thing %> is gettin' on my noives!"); - var result = basicTemplate({thing: 'This'}); - assert.equal(result, "This is gettin' on my noives!", 'can do basic attribute interpolation'); - - var sansSemicolonTemplate = _.template('A <% this %> B'); - assert.equal(sansSemicolonTemplate(), 'A B'); - - var backslashTemplate = _.template('<%= thing %> is \\ridanculous'); - assert.equal(backslashTemplate({thing: 'This'}), 'This is \\ridanculous'); - - var escapeTemplate = _.template('<%= a ? "checked=\\"checked\\"" : "" %>'); - assert.equal(escapeTemplate({a: true}), 'checked="checked"', 'can handle slash escapes in interpolations.'); - - var fancyTemplate = _.template('<ul><% ' + - ' for (var key in people) { ' + - '%><li><%= people[key] %></li><% } %></ul>'); - result = fancyTemplate({people: {moe: 'Moe', larry: 'Larry', curly: 'Curly'}}); - assert.equal(result, '<ul><li>Moe</li><li>Larry</li><li>Curly</li></ul>', 'can run arbitrary javascript in templates'); - - var escapedCharsInJavascriptTemplate = _.template('<ul><% _.each(numbers.split("\\n"), function(item) { %><li><%= item %></li><% }) %></ul>'); - result = escapedCharsInJavascriptTemplate({numbers: 'one\ntwo\nthree\nfour'}); - assert.equal(result, '<ul><li>one</li><li>two</li><li>three</li><li>four</li></ul>', 'Can use escaped characters (e.g. \\n) in JavaScript'); - - var namespaceCollisionTemplate = _.template('<%= pageCount %> <%= thumbnails[pageCount] %> <% _.each(thumbnails, function(p) { %><div class="thumbnail" rel="<%= p %>"></div><% }); %>'); - result = namespaceCollisionTemplate({ - pageCount: 3, - thumbnails: { - 1: 'p1-thumbnail.gif', - 2: 'p2-thumbnail.gif', - 3: 'p3-thumbnail.gif' - } - }); - assert.equal(result, '3 p3-thumbnail.gif <div class="thumbnail" rel="p1-thumbnail.gif"></div><div class="thumbnail" rel="p2-thumbnail.gif"></div><div class="thumbnail" rel="p3-thumbnail.gif"></div>'); - - var noInterpolateTemplate = _.template('<div><p>Just some text. Hey, I know this is silly but it aids consistency.</p></div>'); - result = noInterpolateTemplate(); - assert.equal(result, '<div><p>Just some text. Hey, I know this is silly but it aids consistency.</p></div>'); - - var quoteTemplate = _.template("It's its, not it's"); - assert.equal(quoteTemplate({}), "It's its, not it's"); - - var quoteInStatementAndBody = _.template('<% ' + - " if(foo == 'bar'){ " + - "%>Statement quotes and 'quotes'.<% } %>"); - assert.equal(quoteInStatementAndBody({foo: 'bar'}), "Statement quotes and 'quotes'."); - - var withNewlinesAndTabs = _.template('This\n\t\tis: <%= x %>.\n\tok.\nend.'); - assert.equal(withNewlinesAndTabs({x: 'that'}), 'This\n\t\tis: that.\n\tok.\nend.'); - - var template = _.template('<i><%- value %></i>'); - result = template({value: '<script>'}); - assert.equal(result, '<i><script></i>'); - - var stooge = { - name: 'Moe', - template: _.template("I'm <%= this.name %>") - }; - assert.equal(stooge.template(), "I'm Moe"); - - template = _.template('\n ' + - ' <%\n ' + - ' // a comment\n ' + - ' if (data) { data += 12345; }; %>\n ' + - ' <li><%= data %></li>\n ' - ); - assert.equal(template({data: 12345}).replace(/\s/g, ''), '<li>24690</li>'); - - _.templateSettings = { - evaluate: /\{\{([\s\S]+?)\}\}/g, - interpolate: /\{\{=([\s\S]+?)\}\}/g - }; - - var custom = _.template('<ul>{{ for (var key in people) { }}<li>{{= people[key] }}</li>{{ } }}</ul>'); - result = custom({people: {moe: 'Moe', larry: 'Larry', curly: 'Curly'}}); - assert.equal(result, '<ul><li>Moe</li><li>Larry</li><li>Curly</li></ul>', 'can run arbitrary javascript in templates'); - - var customQuote = _.template("It's its, not it's"); - assert.equal(customQuote({}), "It's its, not it's"); - - quoteInStatementAndBody = _.template("{{ if(foo == 'bar'){ }}Statement quotes and 'quotes'.{{ } }}"); - assert.equal(quoteInStatementAndBody({foo: 'bar'}), "Statement quotes and 'quotes'."); - - _.templateSettings = { - evaluate: /<\?([\s\S]+?)\?>/g, - interpolate: /<\?=([\s\S]+?)\?>/g - }; - - var customWithSpecialChars = _.template('<ul><? for (var key in people) { ?><li><?= people[key] ?></li><? } ?></ul>'); - result = customWithSpecialChars({people: {moe: 'Moe', larry: 'Larry', curly: 'Curly'}}); - assert.equal(result, '<ul><li>Moe</li><li>Larry</li><li>Curly</li></ul>', 'can run arbitrary javascript in templates'); - - var customWithSpecialCharsQuote = _.template("It's its, not it's"); - assert.equal(customWithSpecialCharsQuote({}), "It's its, not it's"); - - quoteInStatementAndBody = _.template("<? if(foo == 'bar'){ ?>Statement quotes and 'quotes'.<? } ?>"); - assert.equal(quoteInStatementAndBody({foo: 'bar'}), "Statement quotes and 'quotes'."); - - _.templateSettings = { - interpolate: /\{\{(.+?)\}\}/g - }; - - var mustache = _.template('Hello {{planet}}!'); - assert.equal(mustache({planet: 'World'}), 'Hello World!', 'can mimic mustache.js'); - - var templateWithNull = _.template('a null undefined {{planet}}'); - assert.equal(templateWithNull({planet: 'world'}), 'a null undefined world', 'can handle missing escape and evaluate settings'); - }); - - QUnit.test('_.template provides the generated function source, when a SyntaxError occurs', function(assert) { - var source; - try { - _.template('<b><%= if x %></b>'); - } catch (ex) { - source = ex.source; - } - assert.ok(/__p/.test(source)); - }); - - QUnit.test('_.template handles \\u2028 & \\u2029', function(assert) { - var tmpl = _.template('<p>\u2028<%= "\\u2028\\u2029" %>\u2029</p>'); - assert.strictEqual(tmpl(), '<p>\u2028\u2028\u2029\u2029</p>'); - }); - - QUnit.test('result calls functions and returns primitives', function(assert) { - var obj = {w: '', x: 'x', y: function(){ return this.x; }}; - assert.strictEqual(_.result(obj, 'w'), ''); - assert.strictEqual(_.result(obj, 'x'), 'x'); - assert.strictEqual(_.result(obj, 'y'), 'x'); - assert.strictEqual(_.result(obj, 'z'), void 0); - assert.strictEqual(_.result(null, 'x'), void 0); - }); - - QUnit.test('result returns a default value if object is null or undefined', function(assert) { - assert.strictEqual(_.result(null, 'b', 'default'), 'default'); - assert.strictEqual(_.result(void 0, 'c', 'default'), 'default'); - assert.strictEqual(_.result(''.match('missing'), 1, 'default'), 'default'); - }); - - QUnit.test('result returns a default value if property of object is missing', function(assert) { - assert.strictEqual(_.result({d: null}, 'd', 'default'), null); - assert.strictEqual(_.result({e: false}, 'e', 'default'), false); - }); - - QUnit.test('result only returns the default value if the object does not have the property or is undefined', function(assert) { - assert.strictEqual(_.result({}, 'b', 'default'), 'default'); - assert.strictEqual(_.result({d: void 0}, 'd', 'default'), 'default'); - }); - - QUnit.test('result does not return the default if the property of an object is found in the prototype', function(assert) { - var Foo = function(){}; - Foo.prototype.bar = 1; - assert.strictEqual(_.result(new Foo, 'bar', 2), 1); - }); - - QUnit.test('result does use the fallback when the result of invoking the property is undefined', function(assert) { - var obj = {a: function() {}}; - assert.strictEqual(_.result(obj, 'a', 'failed'), void 0); - }); - - QUnit.test('result fallback can use a function', function(assert) { - var obj = {a: [1, 2, 3]}; - assert.strictEqual(_.result(obj, 'b', _.constant(5)), 5); - assert.strictEqual(_.result(obj, 'b', function() { - return this.a; - }), obj.a, 'called with context'); - }); - - QUnit.test('_.templateSettings.variable', function(assert) { - var s = '<%=data.x%>'; - var data = {x: 'x'}; - var tmp = _.template(s, {variable: 'data'}); - assert.strictEqual(tmp(data), 'x'); - _.templateSettings.variable = 'data'; - assert.strictEqual(_.template(s)(data), 'x'); - }); - - QUnit.test('#547 - _.templateSettings is unchanged by custom settings.', function(assert) { - assert.ok(!_.templateSettings.variable); - _.template('', {}, {variable: 'x'}); - assert.ok(!_.templateSettings.variable); - }); - - QUnit.test('#556 - undefined template variables.', function(assert) { - var template = _.template('<%=x%>'); - assert.strictEqual(template({x: null}), ''); - assert.strictEqual(template({x: void 0}), ''); - - var templateEscaped = _.template('<%-x%>'); - assert.strictEqual(templateEscaped({x: null}), ''); - assert.strictEqual(templateEscaped({x: void 0}), ''); - - var templateWithProperty = _.template('<%=x.foo%>'); - assert.strictEqual(templateWithProperty({x: {}}), ''); - assert.strictEqual(templateWithProperty({x: {}}), ''); - - var templateWithPropertyEscaped = _.template('<%-x.foo%>'); - assert.strictEqual(templateWithPropertyEscaped({x: {}}), ''); - assert.strictEqual(templateWithPropertyEscaped({x: {}}), ''); - }); - - QUnit.test('interpolate evaluates code only once.', function(assert) { - assert.expect(2); - var count = 0; - var template = _.template('<%= f() %>'); - template({f: function(){ assert.ok(!count++); }}); - - var countEscaped = 0; - var templateEscaped = _.template('<%- f() %>'); - templateEscaped({f: function(){ assert.ok(!countEscaped++); }}); - }); - - QUnit.test('#746 - _.template settings are not modified.', function(assert) { - assert.expect(1); - var settings = {}; - _.template('', null, settings); - assert.deepEqual(settings, {}); - }); - - QUnit.test('#779 - delimeters are applied to unescaped text.', function(assert) { - assert.expect(1); - var template = _.template('<<\nx\n>>', null, {evaluate: /<<(.*?)>>/g}); - assert.strictEqual(template(), '<<\nx\n>>'); - }); - -}()); diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/underscore/underscore-min.js b/ecomp-portal-FE/client/bower_components/lodash/vendor/underscore/underscore-min.js deleted file mode 100644 index f01025b7..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/underscore/underscore-min.js +++ /dev/null @@ -1,6 +0,0 @@ -// Underscore.js 1.8.3 -// http://underscorejs.org -// (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors -// Underscore may be freely distributed under the MIT license. -(function(){function n(n){function t(t,r,e,u,i,o){for(;i>=0&&o>i;i+=n){var a=u?u[i]:i;e=r(e,t[a],a,t)}return e}return function(r,e,u,i){e=b(e,i,4);var o=!k(r)&&m.keys(r),a=(o||r).length,c=n>0?0:a-1;return arguments.length<3&&(u=r[o?o[c]:c],c+=n),t(r,e,u,o,c,a)}}function t(n){return function(t,r,e){r=x(r,e);for(var u=O(t),i=n>0?0:u-1;i>=0&&u>i;i+=n)if(r(t[i],i,t))return i;return-1}}function r(n,t,r){return function(e,u,i){var o=0,a=O(e);if("number"==typeof i)n>0?o=i>=0?i:Math.max(i+a,o):a=i>=0?Math.min(i+1,a):i+a+1;else if(r&&i&&a)return i=r(e,u),e[i]===u?i:-1;if(u!==u)return i=t(l.call(e,o,a),m.isNaN),i>=0?i+o:-1;for(i=n>0?o:a-1;i>=0&&a>i;i+=n)if(e[i]===u)return i;return-1}}function e(n,t){var r=I.length,e=n.constructor,u=m.isFunction(e)&&e.prototype||a,i="constructor";for(m.has(n,i)&&!m.contains(t,i)&&t.push(i);r--;)i=I[r],i in n&&n[i]!==u[i]&&!m.contains(t,i)&&t.push(i)}var u=this,i=u._,o=Array.prototype,a=Object.prototype,c=Function.prototype,f=o.push,l=o.slice,s=a.toString,p=a.hasOwnProperty,h=Array.isArray,v=Object.keys,g=c.bind,y=Object.create,d=function(){},m=function(n){return n instanceof m?n:this instanceof m?void(this._wrapped=n):new m(n)};"undefined"!=typeof exports?("undefined"!=typeof module&&module.exports&&(exports=module.exports=m),exports._=m):u._=m,m.VERSION="1.8.3";var b=function(n,t,r){if(t===void 0)return n;switch(null==r?3:r){case 1:return function(r){return n.call(t,r)};case 2:return function(r,e){return n.call(t,r,e)};case 3:return function(r,e,u){return n.call(t,r,e,u)};case 4:return function(r,e,u,i){return n.call(t,r,e,u,i)}}return function(){return n.apply(t,arguments)}},x=function(n,t,r){return null==n?m.identity:m.isFunction(n)?b(n,t,r):m.isObject(n)?m.matcher(n):m.property(n)};m.iteratee=function(n,t){return x(n,t,1/0)};var _=function(n,t){return function(r){var e=arguments.length;if(2>e||null==r)return r;for(var u=1;e>u;u++)for(var i=arguments[u],o=n(i),a=o.length,c=0;a>c;c++){var f=o[c];t&&r[f]!==void 0||(r[f]=i[f])}return r}},j=function(n){if(!m.isObject(n))return{};if(y)return y(n);d.prototype=n;var t=new d;return d.prototype=null,t},w=function(n){return function(t){return null==t?void 0:t[n]}},A=Math.pow(2,53)-1,O=w("length"),k=function(n){var t=O(n);return"number"==typeof t&&t>=0&&A>=t};m.each=m.forEach=function(n,t,r){t=b(t,r);var e,u;if(k(n))for(e=0,u=n.length;u>e;e++)t(n[e],e,n);else{var i=m.keys(n);for(e=0,u=i.length;u>e;e++)t(n[i[e]],i[e],n)}return n},m.map=m.collect=function(n,t,r){t=x(t,r);for(var e=!k(n)&&m.keys(n),u=(e||n).length,i=Array(u),o=0;u>o;o++){var a=e?e[o]:o;i[o]=t(n[a],a,n)}return i},m.reduce=m.foldl=m.inject=n(1),m.reduceRight=m.foldr=n(-1),m.find=m.detect=function(n,t,r){var e;return e=k(n)?m.findIndex(n,t,r):m.findKey(n,t,r),e!==void 0&&e!==-1?n[e]:void 0},m.filter=m.select=function(n,t,r){var e=[];return t=x(t,r),m.each(n,function(n,r,u){t(n,r,u)&&e.push(n)}),e},m.reject=function(n,t,r){return m.filter(n,m.negate(x(t)),r)},m.every=m.all=function(n,t,r){t=x(t,r);for(var e=!k(n)&&m.keys(n),u=(e||n).length,i=0;u>i;i++){var o=e?e[i]:i;if(!t(n[o],o,n))return!1}return!0},m.some=m.any=function(n,t,r){t=x(t,r);for(var e=!k(n)&&m.keys(n),u=(e||n).length,i=0;u>i;i++){var o=e?e[i]:i;if(t(n[o],o,n))return!0}return!1},m.contains=m.includes=m.include=function(n,t,r,e){return k(n)||(n=m.values(n)),("number"!=typeof r||e)&&(r=0),m.indexOf(n,t,r)>=0},m.invoke=function(n,t){var r=l.call(arguments,2),e=m.isFunction(t);return m.map(n,function(n){var u=e?t:n[t];return null==u?u:u.apply(n,r)})},m.pluck=function(n,t){return m.map(n,m.property(t))},m.where=function(n,t){return m.filter(n,m.matcher(t))},m.findWhere=function(n,t){return m.find(n,m.matcher(t))},m.max=function(n,t,r){var e,u,i=-1/0,o=-1/0;if(null==t&&null!=n){n=k(n)?n:m.values(n);for(var a=0,c=n.length;c>a;a++)e=n[a],e>i&&(i=e)}else t=x(t,r),m.each(n,function(n,r,e){u=t(n,r,e),(u>o||u===-1/0&&i===-1/0)&&(i=n,o=u)});return i},m.min=function(n,t,r){var e,u,i=1/0,o=1/0;if(null==t&&null!=n){n=k(n)?n:m.values(n);for(var a=0,c=n.length;c>a;a++)e=n[a],i>e&&(i=e)}else t=x(t,r),m.each(n,function(n,r,e){u=t(n,r,e),(o>u||1/0===u&&1/0===i)&&(i=n,o=u)});return i},m.shuffle=function(n){for(var t,r=k(n)?n:m.values(n),e=r.length,u=Array(e),i=0;e>i;i++)t=m.random(0,i),t!==i&&(u[i]=u[t]),u[t]=r[i];return u},m.sample=function(n,t,r){return null==t||r?(k(n)||(n=m.values(n)),n[m.random(n.length-1)]):m.shuffle(n).slice(0,Math.max(0,t))},m.sortBy=function(n,t,r){return t=x(t,r),m.pluck(m.map(n,function(n,r,e){return{value:n,index:r,criteria:t(n,r,e)}}).sort(function(n,t){var r=n.criteria,e=t.criteria;if(r!==e){if(r>e||r===void 0)return 1;if(e>r||e===void 0)return-1}return n.index-t.index}),"value")};var F=function(n){return function(t,r,e){var u={};return r=x(r,e),m.each(t,function(e,i){var o=r(e,i,t);n(u,e,o)}),u}};m.groupBy=F(function(n,t,r){m.has(n,r)?n[r].push(t):n[r]=[t]}),m.indexBy=F(function(n,t,r){n[r]=t}),m.countBy=F(function(n,t,r){m.has(n,r)?n[r]++:n[r]=1}),m.toArray=function(n){return n?m.isArray(n)?l.call(n):k(n)?m.map(n,m.identity):m.values(n):[]},m.size=function(n){return null==n?0:k(n)?n.length:m.keys(n).length},m.partition=function(n,t,r){t=x(t,r);var e=[],u=[];return m.each(n,function(n,r,i){(t(n,r,i)?e:u).push(n)}),[e,u]},m.first=m.head=m.take=function(n,t,r){return null==n?void 0:null==t||r?n[0]:m.initial(n,n.length-t)},m.initial=function(n,t,r){return l.call(n,0,Math.max(0,n.length-(null==t||r?1:t)))},m.last=function(n,t,r){return null==n?void 0:null==t||r?n[n.length-1]:m.rest(n,Math.max(0,n.length-t))},m.rest=m.tail=m.drop=function(n,t,r){return l.call(n,null==t||r?1:t)},m.compact=function(n){return m.filter(n,m.identity)};var S=function(n,t,r,e){for(var u=[],i=0,o=e||0,a=O(n);a>o;o++){var c=n[o];if(k(c)&&(m.isArray(c)||m.isArguments(c))){t||(c=S(c,t,r));var f=0,l=c.length;for(u.length+=l;l>f;)u[i++]=c[f++]}else r||(u[i++]=c)}return u};m.flatten=function(n,t){return S(n,t,!1)},m.without=function(n){return m.difference(n,l.call(arguments,1))},m.uniq=m.unique=function(n,t,r,e){m.isBoolean(t)||(e=r,r=t,t=!1),null!=r&&(r=x(r,e));for(var u=[],i=[],o=0,a=O(n);a>o;o++){var c=n[o],f=r?r(c,o,n):c;t?(o&&i===f||u.push(c),i=f):r?m.contains(i,f)||(i.push(f),u.push(c)):m.contains(u,c)||u.push(c)}return u},m.union=function(){return m.uniq(S(arguments,!0,!0))},m.intersection=function(n){for(var t=[],r=arguments.length,e=0,u=O(n);u>e;e++){var i=n[e];if(!m.contains(t,i)){for(var o=1;r>o&&m.contains(arguments[o],i);o++);o===r&&t.push(i)}}return t},m.difference=function(n){var t=S(arguments,!0,!0,1);return m.filter(n,function(n){return!m.contains(t,n)})},m.zip=function(){return m.unzip(arguments)},m.unzip=function(n){for(var t=n&&m.max(n,O).length||0,r=Array(t),e=0;t>e;e++)r[e]=m.pluck(n,e);return r},m.object=function(n,t){for(var r={},e=0,u=O(n);u>e;e++)t?r[n[e]]=t[e]:r[n[e][0]]=n[e][1];return r},m.findIndex=t(1),m.findLastIndex=t(-1),m.sortedIndex=function(n,t,r,e){r=x(r,e,1);for(var u=r(t),i=0,o=O(n);o>i;){var a=Math.floor((i+o)/2);r(n[a])<u?i=a+1:o=a}return i},m.indexOf=r(1,m.findIndex,m.sortedIndex),m.lastIndexOf=r(-1,m.findLastIndex),m.range=function(n,t,r){null==t&&(t=n||0,n=0),r=r||1;for(var e=Math.max(Math.ceil((t-n)/r),0),u=Array(e),i=0;e>i;i++,n+=r)u[i]=n;return u};var E=function(n,t,r,e,u){if(!(e instanceof t))return n.apply(r,u);var i=j(n.prototype),o=n.apply(i,u);return m.isObject(o)?o:i};m.bind=function(n,t){if(g&&n.bind===g)return g.apply(n,l.call(arguments,1));if(!m.isFunction(n))throw new TypeError("Bind must be called on a function");var r=l.call(arguments,2),e=function(){return E(n,e,t,this,r.concat(l.call(arguments)))};return e},m.partial=function(n){var t=l.call(arguments,1),r=function(){for(var e=0,u=t.length,i=Array(u),o=0;u>o;o++)i[o]=t[o]===m?arguments[e++]:t[o];for(;e<arguments.length;)i.push(arguments[e++]);return E(n,r,this,this,i)};return r},m.bindAll=function(n){var t,r,e=arguments.length;if(1>=e)throw new Error("bindAll must be passed function names");for(t=1;e>t;t++)r=arguments[t],n[r]=m.bind(n[r],n);return n},m.memoize=function(n,t){var r=function(e){var u=r.cache,i=""+(t?t.apply(this,arguments):e);return m.has(u,i)||(u[i]=n.apply(this,arguments)),u[i]};return r.cache={},r},m.delay=function(n,t){var r=l.call(arguments,2);return setTimeout(function(){return n.apply(null,r)},t)},m.defer=m.partial(m.delay,m,1),m.throttle=function(n,t,r){var e,u,i,o=null,a=0;r||(r={});var c=function(){a=r.leading===!1?0:m.now(),o=null,i=n.apply(e,u),o||(e=u=null)};return function(){var f=m.now();a||r.leading!==!1||(a=f);var l=t-(f-a);return e=this,u=arguments,0>=l||l>t?(o&&(clearTimeout(o),o=null),a=f,i=n.apply(e,u),o||(e=u=null)):o||r.trailing===!1||(o=setTimeout(c,l)),i}},m.debounce=function(n,t,r){var e,u,i,o,a,c=function(){var f=m.now()-o;t>f&&f>=0?e=setTimeout(c,t-f):(e=null,r||(a=n.apply(i,u),e||(i=u=null)))};return function(){i=this,u=arguments,o=m.now();var f=r&&!e;return e||(e=setTimeout(c,t)),f&&(a=n.apply(i,u),i=u=null),a}},m.wrap=function(n,t){return m.partial(t,n)},m.negate=function(n){return function(){return!n.apply(this,arguments)}},m.compose=function(){var n=arguments,t=n.length-1;return function(){for(var r=t,e=n[t].apply(this,arguments);r--;)e=n[r].call(this,e);return e}},m.after=function(n,t){return function(){return--n<1?t.apply(this,arguments):void 0}},m.before=function(n,t){var r;return function(){return--n>0&&(r=t.apply(this,arguments)),1>=n&&(t=null),r}},m.once=m.partial(m.before,2);var M=!{toString:null}.propertyIsEnumerable("toString"),I=["valueOf","isPrototypeOf","toString","propertyIsEnumerable","hasOwnProperty","toLocaleString"];m.keys=function(n){if(!m.isObject(n))return[];if(v)return v(n);var t=[];for(var r in n)m.has(n,r)&&t.push(r);return M&&e(n,t),t},m.allKeys=function(n){if(!m.isObject(n))return[];var t=[];for(var r in n)t.push(r);return M&&e(n,t),t},m.values=function(n){for(var t=m.keys(n),r=t.length,e=Array(r),u=0;r>u;u++)e[u]=n[t[u]];return e},m.mapObject=function(n,t,r){t=x(t,r);for(var e,u=m.keys(n),i=u.length,o={},a=0;i>a;a++)e=u[a],o[e]=t(n[e],e,n);return o},m.pairs=function(n){for(var t=m.keys(n),r=t.length,e=Array(r),u=0;r>u;u++)e[u]=[t[u],n[t[u]]];return e},m.invert=function(n){for(var t={},r=m.keys(n),e=0,u=r.length;u>e;e++)t[n[r[e]]]=r[e];return t},m.functions=m.methods=function(n){var t=[];for(var r in n)m.isFunction(n[r])&&t.push(r);return t.sort()},m.extend=_(m.allKeys),m.extendOwn=m.assign=_(m.keys),m.findKey=function(n,t,r){t=x(t,r);for(var e,u=m.keys(n),i=0,o=u.length;o>i;i++)if(e=u[i],t(n[e],e,n))return e},m.pick=function(n,t,r){var e,u,i={},o=n;if(null==o)return i;m.isFunction(t)?(u=m.allKeys(o),e=b(t,r)):(u=S(arguments,!1,!1,1),e=function(n,t,r){return t in r},o=Object(o));for(var a=0,c=u.length;c>a;a++){var f=u[a],l=o[f];e(l,f,o)&&(i[f]=l)}return i},m.omit=function(n,t,r){if(m.isFunction(t))t=m.negate(t);else{var e=m.map(S(arguments,!1,!1,1),String);t=function(n,t){return!m.contains(e,t)}}return m.pick(n,t,r)},m.defaults=_(m.allKeys,!0),m.create=function(n,t){var r=j(n);return t&&m.extendOwn(r,t),r},m.clone=function(n){return m.isObject(n)?m.isArray(n)?n.slice():m.extend({},n):n},m.tap=function(n,t){return t(n),n},m.isMatch=function(n,t){var r=m.keys(t),e=r.length;if(null==n)return!e;for(var u=Object(n),i=0;e>i;i++){var o=r[i];if(t[o]!==u[o]||!(o in u))return!1}return!0};var N=function(n,t,r,e){if(n===t)return 0!==n||1/n===1/t;if(null==n||null==t)return n===t;n instanceof m&&(n=n._wrapped),t instanceof m&&(t=t._wrapped);var u=s.call(n);if(u!==s.call(t))return!1;switch(u){case"[object RegExp]":case"[object String]":return""+n==""+t;case"[object Number]":return+n!==+n?+t!==+t:0===+n?1/+n===1/t:+n===+t;case"[object Date]":case"[object Boolean]":return+n===+t}var i="[object Array]"===u;if(!i){if("object"!=typeof n||"object"!=typeof t)return!1;var o=n.constructor,a=t.constructor;if(o!==a&&!(m.isFunction(o)&&o instanceof o&&m.isFunction(a)&&a instanceof a)&&"constructor"in n&&"constructor"in t)return!1}r=r||[],e=e||[];for(var c=r.length;c--;)if(r[c]===n)return e[c]===t;if(r.push(n),e.push(t),i){if(c=n.length,c!==t.length)return!1;for(;c--;)if(!N(n[c],t[c],r,e))return!1}else{var f,l=m.keys(n);if(c=l.length,m.keys(t).length!==c)return!1;for(;c--;)if(f=l[c],!m.has(t,f)||!N(n[f],t[f],r,e))return!1}return r.pop(),e.pop(),!0};m.isEqual=function(n,t){return N(n,t)},m.isEmpty=function(n){return null==n?!0:k(n)&&(m.isArray(n)||m.isString(n)||m.isArguments(n))?0===n.length:0===m.keys(n).length},m.isElement=function(n){return!(!n||1!==n.nodeType)},m.isArray=h||function(n){return"[object Array]"===s.call(n)},m.isObject=function(n){var t=typeof n;return"function"===t||"object"===t&&!!n},m.each(["Arguments","Function","String","Number","Date","RegExp","Error"],function(n){m["is"+n]=function(t){return s.call(t)==="[object "+n+"]"}}),m.isArguments(arguments)||(m.isArguments=function(n){return m.has(n,"callee")}),"function"!=typeof/./&&"object"!=typeof Int8Array&&(m.isFunction=function(n){return"function"==typeof n||!1}),m.isFinite=function(n){return isFinite(n)&&!isNaN(parseFloat(n))},m.isNaN=function(n){return m.isNumber(n)&&n!==+n},m.isBoolean=function(n){return n===!0||n===!1||"[object Boolean]"===s.call(n)},m.isNull=function(n){return null===n},m.isUndefined=function(n){return n===void 0},m.has=function(n,t){return null!=n&&p.call(n,t)},m.noConflict=function(){return u._=i,this},m.identity=function(n){return n},m.constant=function(n){return function(){return n}},m.noop=function(){},m.property=w,m.propertyOf=function(n){return null==n?function(){}:function(t){return n[t]}},m.matcher=m.matches=function(n){return n=m.extendOwn({},n),function(t){return m.isMatch(t,n)}},m.times=function(n,t,r){var e=Array(Math.max(0,n));t=b(t,r,1);for(var u=0;n>u;u++)e[u]=t(u);return e},m.random=function(n,t){return null==t&&(t=n,n=0),n+Math.floor(Math.random()*(t-n+1))},m.now=Date.now||function(){return(new Date).getTime()};var B={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},T=m.invert(B),R=function(n){var t=function(t){return n[t]},r="(?:"+m.keys(n).join("|")+")",e=RegExp(r),u=RegExp(r,"g");return function(n){return n=null==n?"":""+n,e.test(n)?n.replace(u,t):n}};m.escape=R(B),m.unescape=R(T),m.result=function(n,t,r){var e=null==n?void 0:n[t];return e===void 0&&(e=r),m.isFunction(e)?e.call(n):e};var q=0;m.uniqueId=function(n){var t=++q+"";return n?n+t:t},m.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var K=/(.)^/,z={"'":"'","\\":"\\","\r":"r","\n":"n","\u2028":"u2028","\u2029":"u2029"},D=/\\|'|\r|\n|\u2028|\u2029/g,L=function(n){return"\\"+z[n]};m.template=function(n,t,r){!t&&r&&(t=r),t=m.defaults({},t,m.templateSettings);var e=RegExp([(t.escape||K).source,(t.interpolate||K).source,(t.evaluate||K).source].join("|")+"|$","g"),u=0,i="__p+='";n.replace(e,function(t,r,e,o,a){return i+=n.slice(u,a).replace(D,L),u=a+t.length,r?i+="'+\n((__t=("+r+"))==null?'':_.escape(__t))+\n'":e?i+="'+\n((__t=("+e+"))==null?'':__t)+\n'":o&&(i+="';\n"+o+"\n__p+='"),t}),i+="';\n",t.variable||(i="with(obj||{}){\n"+i+"}\n"),i="var __t,__p='',__j=Array.prototype.join,"+"print=function(){__p+=__j.call(arguments,'');};\n"+i+"return __p;\n";try{var o=new Function(t.variable||"obj","_",i)}catch(a){throw a.source=i,a}var c=function(n){return o.call(this,n,m)},f=t.variable||"obj";return c.source="function("+f+"){\n"+i+"}",c},m.chain=function(n){var t=m(n);return t._chain=!0,t};var P=function(n,t){return n._chain?m(t).chain():t};m.mixin=function(n){m.each(m.functions(n),function(t){var r=m[t]=n[t];m.prototype[t]=function(){var n=[this._wrapped];return f.apply(n,arguments),P(this,r.apply(m,n))}})},m.mixin(m),m.each(["pop","push","reverse","shift","sort","splice","unshift"],function(n){var t=o[n];m.prototype[n]=function(){var r=this._wrapped;return t.apply(r,arguments),"shift"!==n&&"splice"!==n||0!==r.length||delete r[0],P(this,r)}}),m.each(["concat","join","slice"],function(n){var t=o[n];m.prototype[n]=function(){return P(this,t.apply(this._wrapped,arguments))}}),m.prototype.value=function(){return this._wrapped},m.prototype.valueOf=m.prototype.toJSON=m.prototype.value,m.prototype.toString=function(){return""+this._wrapped},"function"==typeof define&&define.amd&&define("underscore",[],function(){return m})}).call(this); -//# sourceMappingURL=underscore-min.map
\ No newline at end of file diff --git a/ecomp-portal-FE/client/bower_components/lodash/vendor/underscore/underscore.js b/ecomp-portal-FE/client/bower_components/lodash/vendor/underscore/underscore.js deleted file mode 100644 index bddfdc9f..00000000 --- a/ecomp-portal-FE/client/bower_components/lodash/vendor/underscore/underscore.js +++ /dev/null @@ -1,1620 +0,0 @@ -// Underscore.js 1.8.3 -// http://underscorejs.org -// (c) 2009-2016 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors -// Underscore may be freely distributed under the MIT license. - -(function() { - - // Baseline setup - // -------------- - - // Establish the root object, `window` (`self`) in the browser, `global` - // on the server, or `this` in some virtual machines. We use `self` - // instead of `window` for `WebWorker` support. - var root = typeof self == 'object' && self.self === self && self || - typeof global == 'object' && global.global === global && global || - this; - - // Save the previous value of the `_` variable. - var previousUnderscore = root._; - - // Save bytes in the minified (but not gzipped) version: - var ArrayProto = Array.prototype, ObjProto = Object.prototype; - var SymbolProto = typeof Symbol !== 'undefined' ? Symbol.prototype : null; - - // Create quick reference variables for speed access to core prototypes. - var push = ArrayProto.push, - slice = ArrayProto.slice, - toString = ObjProto.toString, - hasOwnProperty = ObjProto.hasOwnProperty; - - // All **ECMAScript 5** native function implementations that we hope to use - // are declared here. - var nativeIsArray = Array.isArray, - nativeKeys = Object.keys, - nativeCreate = Object.create; - - // Naked function reference for surrogate-prototype-swapping. - var Ctor = function(){}; - - // Create a safe reference to the Underscore object for use below. - var _ = function(obj) { - if (obj instanceof _) return obj; - if (!(this instanceof _)) return new _(obj); - this._wrapped = obj; - }; - - // Export the Underscore object for **Node.js**, with - // backwards-compatibility for their old module API. If we're in - // the browser, add `_` as a global object. - // (`nodeType` is checked to ensure that `module` - // and `exports` are not HTML elements.) - if (typeof exports != 'undefined' && !exports.nodeType) { - if (typeof module != 'undefined' && !module.nodeType && module.exports) { - exports = module.exports = _; - } - exports._ = _; - } else { - root._ = _; - } - - // Current version. - _.VERSION = '1.8.3'; - - // Internal function that returns an efficient (for current engines) version - // of the passed-in callback, to be repeatedly applied in other Underscore - // functions. - var optimizeCb = function(func, context, argCount) { - if (context === void 0) return func; - switch (argCount == null ? 3 : argCount) { - case 1: return function(value) { - return func.call(context, value); - }; - // The 2-parameter case has been omitted only because no current consumers - // made use of it. - case 3: return function(value, index, collection) { - return func.call(context, value, index, collection); - }; - case 4: return function(accumulator, value, index, collection) { - return func.call(context, accumulator, value, index, collection); - }; - } - return function() { - return func.apply(context, arguments); - }; - }; - - // An internal function to generate callbacks that can be applied to each - // element in a collection, returning the desired result — either `identity`, - // an arbitrary callback, a property matcher, or a property accessor. - var cb = function(value, context, argCount) { - if (value == null) return _.identity; - if (_.isFunction(value)) return optimizeCb(value, context, argCount); - if (_.isObject(value)) return _.matcher(value); - return _.property(value); - }; - - // An external wrapper for the internal callback generator. - _.iteratee = function(value, context) { - return cb(value, context, Infinity); - }; - - // Similar to ES6's rest param (http://ariya.ofilabs.com/2013/03/es6-and-rest-parameter.html) - // This accumulates the arguments passed into an array, after a given index. - var restArgs = function(func, startIndex) { - startIndex = startIndex == null ? func.length - 1 : +startIndex; - return function() { - var length = Math.max(arguments.length - startIndex, 0); - var rest = Array(length); - for (var index = 0; index < length; index++) { - rest[index] = arguments[index + startIndex]; - } - switch (startIndex) { - case 0: return func.call(this, rest); - case 1: return func.call(this, arguments[0], rest); - case 2: return func.call(this, arguments[0], arguments[1], rest); - } - var args = Array(startIndex + 1); - for (index = 0; index < startIndex; index++) { - args[index] = arguments[index]; - } - args[startIndex] = rest; - return func.apply(this, args); - }; - }; - - // An internal function for creating a new object that inherits from another. - var baseCreate = function(prototype) { - if (!_.isObject(prototype)) return {}; - if (nativeCreate) return nativeCreate(prototype); - Ctor.prototype = prototype; - var result = new Ctor; - Ctor.prototype = null; - return result; - }; - - var property = function(key) { - return function(obj) { - return obj == null ? void 0 : obj[key]; - }; - }; - - // Helper for collection methods to determine whether a collection - // should be iterated as an array or as an object. - // Related: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength - // Avoids a very nasty iOS 8 JIT bug on ARM-64. #2094 - var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1; - var getLength = property('length'); - var isArrayLike = function(collection) { - var length = getLength(collection); - return typeof length == 'number' && length >= 0 && length <= MAX_ARRAY_INDEX; - }; - - // Collection Functions - // -------------------- - - // The cornerstone, an `each` implementation, aka `forEach`. - // Handles raw objects in addition to array-likes. Treats all - // sparse array-likes as if they were dense. - _.each = _.forEach = function(obj, iteratee, context) { - iteratee = optimizeCb(iteratee, context); - var i, length; - if (isArrayLike(obj)) { - for (i = 0, length = obj.length; i < length; i++) { - iteratee(obj[i], i, obj); - } - } else { - var keys = _.keys(obj); - for (i = 0, length = keys.length; i < length; i++) { - iteratee(obj[keys[i]], keys[i], obj); - } - } - return obj; - }; - - // Return the results of applying the iteratee to each element. - _.map = _.collect = function(obj, iteratee, context) { - iteratee = cb(iteratee, context); - var keys = !isArrayLike(obj) && _.keys(obj), - length = (keys || obj).length, - results = Array(length); - for (var index = 0; index < length; index++) { - var currentKey = keys ? keys[index] : index; - results[index] = iteratee(obj[currentKey], currentKey, obj); - } - return results; - }; - - // Create a reducing function iterating left or right. - var createReduce = function(dir) { - // Wrap code that reassigns argument variables in a separate function than - // the one that accesses `arguments.length` to avoid a perf hit. (#1991) - var reducer = function(obj, iteratee, memo, initial) { - var keys = !isArrayLike(obj) && _.keys(obj), - length = (keys || obj).length, - index = dir > 0 ? 0 : length - 1; - if (!initial) { - memo = obj[keys ? keys[index] : index]; - index += dir; - } - for (; index >= 0 && index < length; index += dir) { - var currentKey = keys ? keys[index] : index; - memo = iteratee(memo, obj[currentKey], currentKey, obj); - } - return memo; - }; - - return function(obj, iteratee, memo, context) { - var initial = arguments.length >= 3; - return reducer(obj, optimizeCb(iteratee, context, 4), memo, initial); - }; - }; - - // **Reduce** builds up a single result from a list of values, aka `inject`, - // or `foldl`. - _.reduce = _.foldl = _.inject = createReduce(1); - - // The right-associative version of reduce, also known as `foldr`. - _.reduceRight = _.foldr = createReduce(-1); - - // Return the first value which passes a truth test. Aliased as `detect`. - _.find = _.detect = function(obj, predicate, context) { - var keyFinder = isArrayLike(obj) ? _.findIndex : _.findKey; - var key = keyFinder(obj, predicate, context); - if (key !== void 0 && key !== -1) return obj[key]; - }; - - // Return all the elements that pass a truth test. - // Aliased as `select`. - _.filter = _.select = function(obj, predicate, context) { - var results = []; - predicate = cb(predicate, context); - _.each(obj, function(value, index, list) { - if (predicate(value, index, list)) results.push(value); - }); - return results; - }; - - // Return all the elements for which a truth test fails. - _.reject = function(obj, predicate, context) { - return _.filter(obj, _.negate(cb(predicate)), context); - }; - - // Determine whether all of the elements match a truth test. - // Aliased as `all`. - _.every = _.all = function(obj, predicate, context) { - predicate = cb(predicate, context); - var keys = !isArrayLike(obj) && _.keys(obj), - length = (keys || obj).length; - for (var index = 0; index < length; index++) { - var currentKey = keys ? keys[index] : index; - if (!predicate(obj[currentKey], currentKey, obj)) return false; - } - return true; - }; - - // Determine if at least one element in the object matches a truth test. - // Aliased as `any`. - _.some = _.any = function(obj, predicate, context) { - predicate = cb(predicate, context); - var keys = !isArrayLike(obj) && _.keys(obj), - length = (keys || obj).length; - for (var index = 0; index < length; index++) { - var currentKey = keys ? keys[index] : index; - if (predicate(obj[currentKey], currentKey, obj)) return true; - } - return false; - }; - - // Determine if the array or object contains a given item (using `===`). - // Aliased as `includes` and `include`. - _.contains = _.includes = _.include = function(obj, item, fromIndex, guard) { - if (!isArrayLike(obj)) obj = _.values(obj); - if (typeof fromIndex != 'number' || guard) fromIndex = 0; - return _.indexOf(obj, item, fromIndex) >= 0; - }; - - // Invoke a method (with arguments) on every item in a collection. - _.invoke = restArgs(function(obj, method, args) { - var isFunc = _.isFunction(method); - return _.map(obj, function(value) { - var func = isFunc ? method : value[method]; - return func == null ? func : func.apply(value, args); - }); - }); - - // Convenience version of a common use case of `map`: fetching a property. - _.pluck = function(obj, key) { - return _.map(obj, _.property(key)); - }; - - // Convenience version of a common use case of `filter`: selecting only objects - // containing specific `key:value` pairs. - _.where = function(obj, attrs) { - return _.filter(obj, _.matcher(attrs)); - }; - - // Convenience version of a common use case of `find`: getting the first object - // containing specific `key:value` pairs. - _.findWhere = function(obj, attrs) { - return _.find(obj, _.matcher(attrs)); - }; - - // Return the maximum element (or element-based computation). - _.max = function(obj, iteratee, context) { - var result = -Infinity, lastComputed = -Infinity, - value, computed; - if (iteratee == null || (typeof iteratee == 'number' && typeof obj[0] != 'object') && obj != null) { - obj = isArrayLike(obj) ? obj : _.values(obj); - for (var i = 0, length = obj.length; i < length; i++) { - value = obj[i]; - if (value != null && value > result) { - result = value; - } - } - } else { - iteratee = cb(iteratee, context); - _.each(obj, function(v, index, list) { - computed = iteratee(v, index, list); - if (computed > lastComputed || computed === -Infinity && result === -Infinity) { - result = v; - lastComputed = computed; - } - }); - } - return result; - }; - - // Return the minimum element (or element-based computation). - _.min = function(obj, iteratee, context) { - var result = Infinity, lastComputed = Infinity, - value, computed; - if (iteratee == null || (typeof iteratee == 'number' && typeof obj[0] != 'object') && obj != null) { - obj = isArrayLike(obj) ? obj : _.values(obj); - for (var i = 0, length = obj.length; i < length; i++) { - value = obj[i]; - if (value != null && value < result) { - result = value; - } - } - } else { - iteratee = cb(iteratee, context); - _.each(obj, function(v, index, list) { - computed = iteratee(v, index, list); - if (computed < lastComputed || computed === Infinity && result === Infinity) { - result = v; - lastComputed = computed; - } - }); - } - return result; - }; - - // Shuffle a collection. - _.shuffle = function(obj) { - return _.sample(obj, Infinity); - }; - - // Sample **n** random values from a collection using the modern version of the - // [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle). - // If **n** is not specified, returns a single random element. - // The internal `guard` argument allows it to work with `map`. - _.sample = function(obj, n, guard) { - if (n == null || guard) { - if (!isArrayLike(obj)) obj = _.values(obj); - return obj[_.random(obj.length - 1)]; - } - var sample = isArrayLike(obj) ? _.clone(obj) : _.values(obj); - var length = getLength(sample); - n = Math.max(Math.min(n, length), 0); - var last = length - 1; - for (var index = 0; index < n; index++) { - var rand = _.random(index, last); - var temp = sample[index]; - sample[index] = sample[rand]; - sample[rand] = temp; - } - return sample.slice(0, n); - }; - - // Sort the object's values by a criterion produced by an iteratee. - _.sortBy = function(obj, iteratee, context) { - var index = 0; - iteratee = cb(iteratee, context); - return _.pluck(_.map(obj, function(value, key, list) { - return { - value: value, - index: index++, - criteria: iteratee(value, key, list) - }; - }).sort(function(left, right) { - var a = left.criteria; - var b = right.criteria; - if (a !== b) { - if (a > b || a === void 0) return 1; - if (a < b || b === void 0) return -1; - } - return left.index - right.index; - }), 'value'); - }; - - // An internal function used for aggregate "group by" operations. - var group = function(behavior, partition) { - return function(obj, iteratee, context) { - var result = partition ? [[], []] : {}; - iteratee = cb(iteratee, context); - _.each(obj, function(value, index) { - var key = iteratee(value, index, obj); - behavior(result, value, key); - }); - return result; - }; - }; - - // Groups the object's values by a criterion. Pass either a string attribute - // to group by, or a function that returns the criterion. - _.groupBy = group(function(result, value, key) { - if (_.has(result, key)) result[key].push(value); else result[key] = [value]; - }); - - // Indexes the object's values by a criterion, similar to `groupBy`, but for - // when you know that your index values will be unique. - _.indexBy = group(function(result, value, key) { - result[key] = value; - }); - - // Counts instances of an object that group by a certain criterion. Pass - // either a string attribute to count by, or a function that returns the - // criterion. - _.countBy = group(function(result, value, key) { - if (_.has(result, key)) result[key]++; else result[key] = 1; - }); - - var reStrSymbol = /[^\ud800-\udfff]|[\ud800-\udbff][\udc00-\udfff]|[\ud800-\udfff]/g; - // Safely create a real, live array from anything iterable. - _.toArray = function(obj) { - if (!obj) return []; - if (_.isArray(obj)) return slice.call(obj); - if (_.isString(obj)) { - // Keep surrogate pair characters together - return obj.match(reStrSymbol); - } - if (isArrayLike(obj)) return _.map(obj); - return _.values(obj); - }; - - // Return the number of elements in an object. - _.size = function(obj) { - if (obj == null) return 0; - return isArrayLike(obj) ? obj.length : _.keys(obj).length; - }; - - // Split a collection into two arrays: one whose elements all satisfy the given - // predicate, and one whose elements all do not satisfy the predicate. - _.partition = group(function(result, value, pass) { - result[pass ? 0 : 1].push(value); - }, true); - - // Array Functions - // --------------- - - // Get the first element of an array. Passing **n** will return the first N - // values in the array. Aliased as `head` and `take`. The **guard** check - // allows it to work with `_.map`. - _.first = _.head = _.take = function(array, n, guard) { - if (array == null) return void 0; - if (n == null || guard) return array[0]; - return _.initial(array, array.length - n); - }; - - // Returns everything but the last entry of the array. Especially useful on - // the arguments object. Passing **n** will return all the values in - // the array, excluding the last N. - _.initial = function(array, n, guard) { - return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n))); - }; - - // Get the last element of an array. Passing **n** will return the last N - // values in the array. - _.last = function(array, n, guard) { - if (array == null) return void 0; - if (n == null || guard) return array[array.length - 1]; - return _.rest(array, Math.max(0, array.length - n)); - }; - - // Returns everything but the first entry of the array. Aliased as `tail` and `drop`. - // Especially useful on the arguments object. Passing an **n** will return - // the rest N values in the array. - _.rest = _.tail = _.drop = function(array, n, guard) { - return slice.call(array, n == null || guard ? 1 : n); - }; - - // Trim out all falsy values from an array. - _.compact = function(array) { - return _.filter(array); - }; - - // Internal implementation of a recursive `flatten` function. - var flatten = function(input, shallow, strict, output) { - output = output || []; - var idx = output.length; - for (var i = 0, length = getLength(input); i < length; i++) { - var value = input[i]; - if (isArrayLike(value) && (_.isArray(value) || _.isArguments(value))) { - // Flatten current level of array or arguments object. - if (shallow) { - var j = 0, len = value.length; - while (j < len) output[idx++] = value[j++]; - } else { - flatten(value, shallow, strict, output); - idx = output.length; - } - } else if (!strict) { - output[idx++] = value; - } - } - return output; - }; - - // Flatten out an array, either recursively (by default), or just one level. - _.flatten = function(array, shallow) { - return flatten(array, shallow, false); - }; - - // Return a version of the array that does not contain the specified value(s). - _.without = restArgs(function(array, otherArrays) { - return _.difference(array, otherArrays); - }); - - // Produce a duplicate-free version of the array. If the array has already - // been sorted, you have the option of using a faster algorithm. - // Aliased as `unique`. - _.uniq = _.unique = function(array, isSorted, iteratee, context) { - if (!_.isBoolean(isSorted)) { - context = iteratee; - iteratee = isSorted; - isSorted = false; - } - if (iteratee != null) iteratee = cb(iteratee, context); - var result = []; - var seen = []; - for (var i = 0, length = getLength(array); i < length; i++) { - var value = array[i], - computed = iteratee ? iteratee(value, i, array) : value; - if (isSorted) { - if (!i || seen !== computed) result.push(value); - seen = computed; - } else if (iteratee) { - if (!_.contains(seen, computed)) { - seen.push(computed); - result.push(value); - } - } else if (!_.contains(result, value)) { - result.push(value); - } - } - return result; - }; - - // Produce an array that contains the union: each distinct element from all of - // the passed-in arrays. - _.union = restArgs(function(arrays) { - return _.uniq(flatten(arrays, true, true)); - }); - - // Produce an array that contains every item shared between all the - // passed-in arrays. - _.intersection = function(array) { - var result = []; - var argsLength = arguments.length; - for (var i = 0, length = getLength(array); i < length; i++) { - var item = array[i]; - if (_.contains(result, item)) continue; - var j; - for (j = 1; j < argsLength; j++) { - if (!_.contains(arguments[j], item)) break; - } - if (j === argsLength) result.push(item); - } - return result; - }; - - // Take the difference between one array and a number of other arrays. - // Only the elements present in just the first array will remain. - _.difference = restArgs(function(array, rest) { - rest = flatten(rest, true, true); - return _.filter(array, function(value){ - return !_.contains(rest, value); - }); - }); - - // Complement of _.zip. Unzip accepts an array of arrays and groups - // each array's elements on shared indices. - _.unzip = function(array) { - var length = array && _.max(array, getLength).length || 0; - var result = Array(length); - - for (var index = 0; index < length; index++) { - result[index] = _.pluck(array, index); - } - return result; - }; - - // Zip together multiple lists into a single array -- elements that share - // an index go together. - _.zip = restArgs(_.unzip); - - // Converts lists into objects. Pass either a single array of `[key, value]` - // pairs, or two parallel arrays of the same length -- one of keys, and one of - // the corresponding values. - _.object = function(list, values) { - var result = {}; - for (var i = 0, length = getLength(list); i < length; i++) { - if (values) { - result[list[i]] = values[i]; - } else { - result[list[i][0]] = list[i][1]; - } - } - return result; - }; - - // Generator function to create the findIndex and findLastIndex functions. - var createPredicateIndexFinder = function(dir) { - return function(array, predicate, context) { - predicate = cb(predicate, context); - var length = getLength(array); - var index = dir > 0 ? 0 : length - 1; - for (; index >= 0 && index < length; index += dir) { - if (predicate(array[index], index, array)) return index; - } - return -1; - }; - }; - - // Returns the first index on an array-like that passes a predicate test. - _.findIndex = createPredicateIndexFinder(1); - _.findLastIndex = createPredicateIndexFinder(-1); - - // Use a comparator function to figure out the smallest index at which - // an object should be inserted so as to maintain order. Uses binary search. - _.sortedIndex = function(array, obj, iteratee, context) { - iteratee = cb(iteratee, context, 1); - var value = iteratee(obj); - var low = 0, high = getLength(array); - while (low < high) { - var mid = Math.floor((low + high) / 2); - if (iteratee(array[mid]) < value) low = mid + 1; else high = mid; - } - return low; - }; - - // Generator function to create the indexOf and lastIndexOf functions. - var createIndexFinder = function(dir, predicateFind, sortedIndex) { - return function(array, item, idx) { - var i = 0, length = getLength(array); - if (typeof idx == 'number') { - if (dir > 0) { - i = idx >= 0 ? idx : Math.max(idx + length, i); - } else { - length = idx >= 0 ? Math.min(idx + 1, length) : idx + length + 1; - } - } else if (sortedIndex && idx && length) { - idx = sortedIndex(array, item); - return array[idx] === item ? idx : -1; - } - if (item !== item) { - idx = predicateFind(slice.call(array, i, length), _.isNaN); - return idx >= 0 ? idx + i : -1; - } - for (idx = dir > 0 ? i : length - 1; idx >= 0 && idx < length; idx += dir) { - if (array[idx] === item) return idx; - } - return -1; - }; - }; - - // Return the position of the first occurrence of an item in an array, - // or -1 if the item is not included in the array. - // If the array is large and already in sort order, pass `true` - // for **isSorted** to use binary search. - _.indexOf = createIndexFinder(1, _.findIndex, _.sortedIndex); - _.lastIndexOf = createIndexFinder(-1, _.findLastIndex); - - // Generate an integer Array containing an arithmetic progression. A port of - // the native Python `range()` function. See - // [the Python documentation](http://docs.python.org/library/functions.html#range). - _.range = function(start, stop, step) { - if (stop == null) { - stop = start || 0; - start = 0; - } - if (!step) { - step = stop < start ? -1 : 1; - } - - var length = Math.max(Math.ceil((stop - start) / step), 0); - var range = Array(length); - - for (var idx = 0; idx < length; idx++, start += step) { - range[idx] = start; - } - - return range; - }; - - // Split an **array** into several arrays containing **count** or less elements - // of initial array. - _.chunk = function(array, count) { - if (count == null || count < 1) return []; - - var result = []; - var i = 0, length = array.length; - while (i < length) { - result.push(slice.call(array, i, i += count)); - } - return result; - }; - - // Function (ahem) Functions - // ------------------ - - // Determines whether to execute a function as a constructor - // or a normal function with the provided arguments. - var executeBound = function(sourceFunc, boundFunc, context, callingContext, args) { - if (!(callingContext instanceof boundFunc)) return sourceFunc.apply(context, args); - var self = baseCreate(sourceFunc.prototype); - var result = sourceFunc.apply(self, args); - if (_.isObject(result)) return result; - return self; - }; - - // Create a function bound to a given object (assigning `this`, and arguments, - // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if - // available. - _.bind = restArgs(function(func, context, args) { - if (!_.isFunction(func)) throw new TypeError('Bind must be called on a function'); - var bound = restArgs(function(callArgs) { - return executeBound(func, bound, context, this, args.concat(callArgs)); - }); - return bound; - }); - - // Partially apply a function by creating a version that has had some of its - // arguments pre-filled, without changing its dynamic `this` context. _ acts - // as a placeholder by default, allowing any combination of arguments to be - // pre-filled. Set `_.partial.placeholder` for a custom placeholder argument. - _.partial = restArgs(function(func, boundArgs) { - var placeholder = _.partial.placeholder; - var bound = function() { - var position = 0, length = boundArgs.length; - var args = Array(length); - for (var i = 0; i < length; i++) { - args[i] = boundArgs[i] === placeholder ? arguments[position++] : boundArgs[i]; - } - while (position < arguments.length) args.push(arguments[position++]); - return executeBound(func, bound, this, this, args); - }; - return bound; - }); - - _.partial.placeholder = _; - - // Bind a number of an object's methods to that object. Remaining arguments - // are the method names to be bound. Useful for ensuring that all callbacks - // defined on an object belong to it. - _.bindAll = restArgs(function(obj, keys) { - keys = flatten(keys, false, false); - var index = keys.length; - if (index < 1) throw new Error('bindAll must be passed function names'); - while (index--) { - var key = keys[index]; - obj[key] = _.bind(obj[key], obj); - } - }); - - // Memoize an expensive function by storing its results. - _.memoize = function(func, hasher) { - var memoize = function(key) { - var cache = memoize.cache; - var address = '' + (hasher ? hasher.apply(this, arguments) : key); - if (!_.has(cache, address)) cache[address] = func.apply(this, arguments); - return cache[address]; - }; - memoize.cache = {}; - return memoize; - }; - - // Delays a function for the given number of milliseconds, and then calls - // it with the arguments supplied. - _.delay = restArgs(function(func, wait, args) { - return setTimeout(function() { - return func.apply(null, args); - }, wait); - }); - - // Defers a function, scheduling it to run after the current call stack has - // cleared. - _.defer = _.partial(_.delay, _, 1); - - // Returns a function, that, when invoked, will only be triggered at most once - // during a given window of time. Normally, the throttled function will run - // as much as it can, without ever going more than once per `wait` duration; - // but if you'd like to disable the execution on the leading edge, pass - // `{leading: false}`. To disable execution on the trailing edge, ditto. - _.throttle = function(func, wait, options) { - var timeout, context, args, result; - var previous = 0; - if (!options) options = {}; - - var later = function() { - previous = options.leading === false ? 0 : _.now(); - timeout = null; - result = func.apply(context, args); - if (!timeout) context = args = null; - }; - - var throttled = function() { - var now = _.now(); - if (!previous && options.leading === false) previous = now; - var remaining = wait - (now - previous); - context = this; - args = arguments; - if (remaining <= 0 || remaining > wait) { - if (timeout) { - clearTimeout(timeout); - timeout = null; - } - previous = now; - result = func.apply(context, args); - if (!timeout) context = args = null; - } else if (!timeout && options.trailing !== false) { - timeout = setTimeout(later, remaining); - } - return result; - }; - - throttled.cancel = function() { - clearTimeout(timeout); - previous = 0; - timeout = context = args = null; - }; - - return throttled; - }; - - // Returns a function, that, as long as it continues to be invoked, will not - // be triggered. The function will be called after it stops being called for - // N milliseconds. If `immediate` is passed, trigger the function on the - // leading edge, instead of the trailing. - _.debounce = function(func, wait, immediate) { - var timeout, result; - - var later = function(context, args) { - timeout = null; - if (args) result = func.apply(context, args); - }; - - var debounced = restArgs(function(args) { - if (timeout) clearTimeout(timeout); - if (immediate) { - var callNow = !timeout; - timeout = setTimeout(later, wait); - if (callNow) result = func.apply(this, args); - } else { - timeout = _.delay(later, wait, this, args); - } - - return result; - }); - - debounced.cancel = function() { - clearTimeout(timeout); - timeout = null; - }; - - return debounced; - }; - - // Returns the first function passed as an argument to the second, - // allowing you to adjust arguments, run code before and after, and - // conditionally execute the original function. - _.wrap = function(func, wrapper) { - return _.partial(wrapper, func); - }; - - // Returns a negated version of the passed-in predicate. - _.negate = function(predicate) { - return function() { - return !predicate.apply(this, arguments); - }; - }; - - // Returns a function that is the composition of a list of functions, each - // consuming the return value of the function that follows. - _.compose = function() { - var args = arguments; - var start = args.length - 1; - return function() { - var i = start; - var result = args[start].apply(this, arguments); - while (i--) result = args[i].call(this, result); - return result; - }; - }; - - // Returns a function that will only be executed on and after the Nth call. - _.after = function(times, func) { - return function() { - if (--times < 1) { - return func.apply(this, arguments); - } - }; - }; - - // Returns a function that will only be executed up to (but not including) the Nth call. - _.before = function(times, func) { - var memo; - return function() { - if (--times > 0) { - memo = func.apply(this, arguments); - } - if (times <= 1) func = null; - return memo; - }; - }; - - // Returns a function that will be executed at most one time, no matter how - // often you call it. Useful for lazy initialization. - _.once = _.partial(_.before, 2); - - _.restArgs = restArgs; - - // Object Functions - // ---------------- - - // Keys in IE < 9 that won't be iterated by `for key in ...` and thus missed. - var hasEnumBug = !{toString: null}.propertyIsEnumerable('toString'); - var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString', - 'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString']; - - var collectNonEnumProps = function(obj, keys) { - var nonEnumIdx = nonEnumerableProps.length; - var constructor = obj.constructor; - var proto = _.isFunction(constructor) && constructor.prototype || ObjProto; - - // Constructor is a special case. - var prop = 'constructor'; - if (_.has(obj, prop) && !_.contains(keys, prop)) keys.push(prop); - - while (nonEnumIdx--) { - prop = nonEnumerableProps[nonEnumIdx]; - if (prop in obj && obj[prop] !== proto[prop] && !_.contains(keys, prop)) { - keys.push(prop); - } - } - }; - - // Retrieve the names of an object's own properties. - // Delegates to **ECMAScript 5**'s native `Object.keys`. - _.keys = function(obj) { - if (!_.isObject(obj)) return []; - if (nativeKeys) return nativeKeys(obj); - var keys = []; - for (var key in obj) if (_.has(obj, key)) keys.push(key); - // Ahem, IE < 9. - if (hasEnumBug) collectNonEnumProps(obj, keys); - return keys; - }; - - // Retrieve all the property names of an object. - _.allKeys = function(obj) { - if (!_.isObject(obj)) return []; - var keys = []; - for (var key in obj) keys.push(key); - // Ahem, IE < 9. - if (hasEnumBug) collectNonEnumProps(obj, keys); - return keys; - }; - - // Retrieve the values of an object's properties. - _.values = function(obj) { - var keys = _.keys(obj); - var length = keys.length; - var values = Array(length); - for (var i = 0; i < length; i++) { - values[i] = obj[keys[i]]; - } - return values; - }; - - // Returns the results of applying the iteratee to each element of the object. - // In contrast to _.map it returns an object. - _.mapObject = function(obj, iteratee, context) { - iteratee = cb(iteratee, context); - var keys = _.keys(obj), - length = keys.length, - results = {}; - for (var index = 0; index < length; index++) { - var currentKey = keys[index]; - results[currentKey] = iteratee(obj[currentKey], currentKey, obj); - } - return results; - }; - - // Convert an object into a list of `[key, value]` pairs. - _.pairs = function(obj) { - var keys = _.keys(obj); - var length = keys.length; - var pairs = Array(length); - for (var i = 0; i < length; i++) { - pairs[i] = [keys[i], obj[keys[i]]]; - } - return pairs; - }; - - // Invert the keys and values of an object. The values must be serializable. - _.invert = function(obj) { - var result = {}; - var keys = _.keys(obj); - for (var i = 0, length = keys.length; i < length; i++) { - result[obj[keys[i]]] = keys[i]; - } - return result; - }; - - // Return a sorted list of the function names available on the object. - // Aliased as `methods`. - _.functions = _.methods = function(obj) { - var names = []; - for (var key in obj) { - if (_.isFunction(obj[key])) names.push(key); - } - return names.sort(); - }; - - // An internal function for creating assigner functions. - var createAssigner = function(keysFunc, defaults) { - return function(obj) { - var length = arguments.length; - if (defaults) obj = Object(obj); - if (length < 2 || obj == null) return obj; - for (var index = 1; index < length; index++) { - var source = arguments[index], - keys = keysFunc(source), - l = keys.length; - for (var i = 0; i < l; i++) { - var key = keys[i]; - if (!defaults || obj[key] === void 0) obj[key] = source[key]; - } - } - return obj; - }; - }; - - // Extend a given object with all the properties in passed-in object(s). - _.extend = createAssigner(_.allKeys); - - // Assigns a given object with all the own properties in the passed-in object(s). - // (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign) - _.extendOwn = _.assign = createAssigner(_.keys); - - // Returns the first key on an object that passes a predicate test. - _.findKey = function(obj, predicate, context) { - predicate = cb(predicate, context); - var keys = _.keys(obj), key; - for (var i = 0, length = keys.length; i < length; i++) { - key = keys[i]; - if (predicate(obj[key], key, obj)) return key; - } - }; - - // Internal pick helper function to determine if `obj` has key `key`. - var keyInObj = function(value, key, obj) { - return key in obj; - }; - - // Return a copy of the object only containing the whitelisted properties. - _.pick = restArgs(function(obj, keys) { - var result = {}, iteratee = keys[0]; - if (obj == null) return result; - if (_.isFunction(iteratee)) { - if (keys.length > 1) iteratee = optimizeCb(iteratee, keys[1]); - keys = _.allKeys(obj); - } else { - iteratee = keyInObj; - keys = flatten(keys, false, false); - obj = Object(obj); - } - for (var i = 0, length = keys.length; i < length; i++) { - var key = keys[i]; - var value = obj[key]; - if (iteratee(value, key, obj)) result[key] = value; - } - return result; - }); - - // Return a copy of the object without the blacklisted properties. - _.omit = restArgs(function(obj, keys) { - var iteratee = keys[0], context; - if (_.isFunction(iteratee)) { - iteratee = _.negate(iteratee); - if (keys.length > 1) context = keys[1]; - } else { - keys = _.map(flatten(keys, false, false), String); - iteratee = function(value, key) { - return !_.contains(keys, key); - }; - } - return _.pick(obj, iteratee, context); - }); - - // Fill in a given object with default properties. - _.defaults = createAssigner(_.allKeys, true); - - // Creates an object that inherits from the given prototype object. - // If additional properties are provided then they will be added to the - // created object. - _.create = function(prototype, props) { - var result = baseCreate(prototype); - if (props) _.extendOwn(result, props); - return result; - }; - - // Create a (shallow-cloned) duplicate of an object. - _.clone = function(obj) { - if (!_.isObject(obj)) return obj; - return _.isArray(obj) ? obj.slice() : _.extend({}, obj); - }; - - // Invokes interceptor with the obj, and then returns obj. - // The primary purpose of this method is to "tap into" a method chain, in - // order to perform operations on intermediate results within the chain. - _.tap = function(obj, interceptor) { - interceptor(obj); - return obj; - }; - - // Returns whether an object has a given set of `key:value` pairs. - _.isMatch = function(object, attrs) { - var keys = _.keys(attrs), length = keys.length; - if (object == null) return !length; - var obj = Object(object); - for (var i = 0; i < length; i++) { - var key = keys[i]; - if (attrs[key] !== obj[key] || !(key in obj)) return false; - } - return true; - }; - - - // Internal recursive comparison function for `isEqual`. - var eq, deepEq; - eq = function(a, b, aStack, bStack) { - // Identical objects are equal. `0 === -0`, but they aren't identical. - // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal). - if (a === b) return a !== 0 || 1 / a === 1 / b; - // A strict comparison is necessary because `null == undefined`. - if (a == null || b == null) return a === b; - // `NaN`s are equivalent, but non-reflexive. - if (a !== a) return b !== b; - // Exhaust primitive checks - var type = typeof a; - if (type !== 'function' && type !== 'object' && typeof b != 'object') return false; - return deepEq(a, b, aStack, bStack); - }; - - // Internal recursive comparison function for `isEqual`. - deepEq = function(a, b, aStack, bStack) { - // Unwrap any wrapped objects. - if (a instanceof _) a = a._wrapped; - if (b instanceof _) b = b._wrapped; - // Compare `[[Class]]` names. - var className = toString.call(a); - if (className !== toString.call(b)) return false; - switch (className) { - // Strings, numbers, regular expressions, dates, and booleans are compared by value. - case '[object RegExp]': - // RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i') - case '[object String]': - // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is - // equivalent to `new String("5")`. - return '' + a === '' + b; - case '[object Number]': - // `NaN`s are equivalent, but non-reflexive. - // Object(NaN) is equivalent to NaN. - if (+a !== +a) return +b !== +b; - // An `egal` comparison is performed for other numeric values. - return +a === 0 ? 1 / +a === 1 / b : +a === +b; - case '[object Date]': - case '[object Boolean]': - // Coerce dates and booleans to numeric primitive values. Dates are compared by their - // millisecond representations. Note that invalid dates with millisecond representations - // of `NaN` are not equivalent. - return +a === +b; - case '[object Symbol]': - return SymbolProto.valueOf.call(a) === SymbolProto.valueOf.call(b); - } - - var areArrays = className === '[object Array]'; - if (!areArrays) { - if (typeof a != 'object' || typeof b != 'object') return false; - - // Objects with different constructors are not equivalent, but `Object`s or `Array`s - // from different frames are. - var aCtor = a.constructor, bCtor = b.constructor; - if (aCtor !== bCtor && !(_.isFunction(aCtor) && aCtor instanceof aCtor && - _.isFunction(bCtor) && bCtor instanceof bCtor) - && ('constructor' in a && 'constructor' in b)) { - return false; - } - } - // Assume equality for cyclic structures. The algorithm for detecting cyclic - // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. - - // Initializing stack of traversed objects. - // It's done here since we only need them for objects and arrays comparison. - aStack = aStack || []; - bStack = bStack || []; - var length = aStack.length; - while (length--) { - // Linear search. Performance is inversely proportional to the number of - // unique nested structures. - if (aStack[length] === a) return bStack[length] === b; - } - - // Add the first object to the stack of traversed objects. - aStack.push(a); - bStack.push(b); - - // Recursively compare objects and arrays. - if (areArrays) { - // Compare array lengths to determine if a deep comparison is necessary. - length = a.length; - if (length !== b.length) return false; - // Deep compare the contents, ignoring non-numeric properties. - while (length--) { - if (!eq(a[length], b[length], aStack, bStack)) return false; - } - } else { - // Deep compare objects. - var keys = _.keys(a), key; - length = keys.length; - // Ensure that both objects contain the same number of properties before comparing deep equality. - if (_.keys(b).length !== length) return false; - while (length--) { - // Deep compare each member - key = keys[length]; - if (!(_.has(b, key) && eq(a[key], b[key], aStack, bStack))) return false; - } - } - // Remove the first object from the stack of traversed objects. - aStack.pop(); - bStack.pop(); - return true; - }; - - // Perform a deep comparison to check if two objects are equal. - _.isEqual = function(a, b) { - return eq(a, b); - }; - - // Is a given array, string, or object empty? - // An "empty" object has no enumerable own-properties. - _.isEmpty = function(obj) { - if (obj == null) return true; - if (isArrayLike(obj) && (_.isArray(obj) || _.isString(obj) || _.isArguments(obj))) return obj.length === 0; - return _.keys(obj).length === 0; - }; - - // Is a given value a DOM element? - _.isElement = function(obj) { - return !!(obj && obj.nodeType === 1); - }; - - // Is a given value an array? - // Delegates to ECMA5's native Array.isArray - _.isArray = nativeIsArray || function(obj) { - return toString.call(obj) === '[object Array]'; - }; - - // Is a given variable an object? - _.isObject = function(obj) { - var type = typeof obj; - return type === 'function' || type === 'object' && !!obj; - }; - - // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp, isError, isMap, isWeakMap, isSet, isWeakSet. - _.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Error', 'Symbol', 'Map', 'WeakMap', 'Set', 'WeakSet'], function(name) { - _['is' + name] = function(obj) { - return toString.call(obj) === '[object ' + name + ']'; - }; - }); - - // Define a fallback version of the method in browsers (ahem, IE < 9), where - // there isn't any inspectable "Arguments" type. - if (!_.isArguments(arguments)) { - _.isArguments = function(obj) { - return _.has(obj, 'callee'); - }; - } - - // Optimize `isFunction` if appropriate. Work around some typeof bugs in old v8, - // IE 11 (#1621), Safari 8 (#1929), and PhantomJS (#2236). - var nodelist = root.document && root.document.childNodes; - if (typeof /./ != 'function' && typeof Int8Array != 'object' && typeof nodelist != 'function') { - _.isFunction = function(obj) { - return typeof obj == 'function' || false; - }; - } - - // Is a given object a finite number? - _.isFinite = function(obj) { - return !_.isSymbol(obj) && isFinite(obj) && !isNaN(parseFloat(obj)); - }; - - // Is the given value `NaN`? - _.isNaN = function(obj) { - return _.isNumber(obj) && isNaN(obj); - }; - - // Is a given value a boolean? - _.isBoolean = function(obj) { - return obj === true || obj === false || toString.call(obj) === '[object Boolean]'; - }; - - // Is a given value equal to null? - _.isNull = function(obj) { - return obj === null; - }; - - // Is a given variable undefined? - _.isUndefined = function(obj) { - return obj === void 0; - }; - - // Shortcut function for checking if an object has a given property directly - // on itself (in other words, not on a prototype). - _.has = function(obj, key) { - return obj != null && hasOwnProperty.call(obj, key); - }; - - // Utility Functions - // ----------------- - - // Run Underscore.js in *noConflict* mode, returning the `_` variable to its - // previous owner. Returns a reference to the Underscore object. - _.noConflict = function() { - root._ = previousUnderscore; - return this; - }; - - // Keep the identity function around for default iteratees. - _.identity = function(value) { - return value; - }; - - // Predicate-generating functions. Often useful outside of Underscore. - _.constant = function(value) { - return function() { - return value; - }; - }; - - _.noop = function(){}; - - _.property = property; - - // Generates a function for a given object that returns a given property. - _.propertyOf = function(obj) { - return obj == null ? function(){} : function(key) { - return obj[key]; - }; - }; - - // Returns a predicate for checking whether an object has a given set of - // `key:value` pairs. - _.matcher = _.matches = function(attrs) { - attrs = _.extendOwn({}, attrs); - return function(obj) { - return _.isMatch(obj, attrs); - }; - }; - - // Run a function **n** times. - _.times = function(n, iteratee, context) { - var accum = Array(Math.max(0, n)); - iteratee = optimizeCb(iteratee, context, 1); - for (var i = 0; i < n; i++) accum[i] = iteratee(i); - return accum; - }; - - // Return a random integer between min and max (inclusive). - _.random = function(min, max) { - if (max == null) { - max = min; - min = 0; - } - return min + Math.floor(Math.random() * (max - min + 1)); - }; - - // A (possibly faster) way to get the current timestamp as an integer. - _.now = Date.now || function() { - return new Date().getTime(); - }; - - // List of HTML entities for escaping. - var escapeMap = { - '&': '&', - '<': '<', - '>': '>', - '"': '"', - "'": ''', - '`': '`' - }; - var unescapeMap = _.invert(escapeMap); - - // Functions for escaping and unescaping strings to/from HTML interpolation. - var createEscaper = function(map) { - var escaper = function(match) { - return map[match]; - }; - // Regexes for identifying a key that needs to be escaped. - var source = '(?:' + _.keys(map).join('|') + ')'; - var testRegexp = RegExp(source); - var replaceRegexp = RegExp(source, 'g'); - return function(string) { - string = string == null ? '' : '' + string; - return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string; - }; - }; - _.escape = createEscaper(escapeMap); - _.unescape = createEscaper(unescapeMap); - - // If the value of the named `property` is a function then invoke it with the - // `object` as context; otherwise, return it. - _.result = function(object, prop, fallback) { - var value = object == null ? void 0 : object[prop]; - if (value === void 0) { - value = fallback; - } - return _.isFunction(value) ? value.call(object) : value; - }; - - // Generate a unique integer id (unique within the entire client session). - // Useful for temporary DOM ids. - var idCounter = 0; - _.uniqueId = function(prefix) { - var id = ++idCounter + ''; - return prefix ? prefix + id : id; - }; - - // By default, Underscore uses ERB-style template delimiters, change the - // following template settings to use alternative delimiters. - _.templateSettings = { - evaluate: /<%([\s\S]+?)%>/g, - interpolate: /<%=([\s\S]+?)%>/g, - escape: /<%-([\s\S]+?)%>/g - }; - - // When customizing `templateSettings`, if you don't want to define an - // interpolation, evaluation or escaping regex, we need one that is - // guaranteed not to match. - var noMatch = /(.)^/; - - // Certain characters need to be escaped so that they can be put into a - // string literal. - var escapes = { - "'": "'", - '\\': '\\', - '\r': 'r', - '\n': 'n', - '\u2028': 'u2028', - '\u2029': 'u2029' - }; - - var escapeRegExp = /\\|'|\r|\n|\u2028|\u2029/g; - - var escapeChar = function(match) { - return '\\' + escapes[match]; - }; - - // JavaScript micro-templating, similar to John Resig's implementation. - // Underscore templating handles arbitrary delimiters, preserves whitespace, - // and correctly escapes quotes within interpolated code. - // NB: `oldSettings` only exists for backwards compatibility. - _.template = function(text, settings, oldSettings) { - if (!settings && oldSettings) settings = oldSettings; - settings = _.defaults({}, settings, _.templateSettings); - - // Combine delimiters into one regular expression via alternation. - var matcher = RegExp([ - (settings.escape || noMatch).source, - (settings.interpolate || noMatch).source, - (settings.evaluate || noMatch).source - ].join('|') + '|$', 'g'); - - // Compile the template source, escaping string literals appropriately. - var index = 0; - var source = "__p+='"; - text.replace(matcher, function(match, escape, interpolate, evaluate, offset) { - source += text.slice(index, offset).replace(escapeRegExp, escapeChar); - index = offset + match.length; - - if (escape) { - source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'"; - } else if (interpolate) { - source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'"; - } else if (evaluate) { - source += "';\n" + evaluate + "\n__p+='"; - } - - // Adobe VMs need the match returned to produce the correct offset. - return match; - }); - source += "';\n"; - - // If a variable is not specified, place data values in local scope. - if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n'; - - source = "var __t,__p='',__j=Array.prototype.join," + - "print=function(){__p+=__j.call(arguments,'');};\n" + - source + 'return __p;\n'; - - var render; - try { - render = new Function(settings.variable || 'obj', '_', source); - } catch (e) { - e.source = source; - throw e; - } - - var template = function(data) { - return render.call(this, data, _); - }; - - // Provide the compiled source as a convenience for precompilation. - var argument = settings.variable || 'obj'; - template.source = 'function(' + argument + '){\n' + source + '}'; - - return template; - }; - - // Add a "chain" function. Start chaining a wrapped Underscore object. - _.chain = function(obj) { - var instance = _(obj); - instance._chain = true; - return instance; - }; - - // OOP - // --------------- - // If Underscore is called as a function, it returns a wrapped object that - // can be used OO-style. This wrapper holds altered versions of all the - // underscore functions. Wrapped objects may be chained. - - // Helper function to continue chaining intermediate results. - var chainResult = function(instance, obj) { - return instance._chain ? _(obj).chain() : obj; - }; - - // Add your own custom functions to the Underscore object. - _.mixin = function(obj) { - _.each(_.functions(obj), function(name) { - var func = _[name] = obj[name]; - _.prototype[name] = function() { - var args = [this._wrapped]; - push.apply(args, arguments); - return chainResult(this, func.apply(_, args)); - }; - }); - }; - - // Add all of the Underscore functions to the wrapper object. - _.mixin(_); - - // Add all mutator Array functions to the wrapper. - _.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) { - var method = ArrayProto[name]; - _.prototype[name] = function() { - var obj = this._wrapped; - method.apply(obj, arguments); - if ((name === 'shift' || name === 'splice') && obj.length === 0) delete obj[0]; - return chainResult(this, obj); - }; - }); - - // Add all accessor Array functions to the wrapper. - _.each(['concat', 'join', 'slice'], function(name) { - var method = ArrayProto[name]; - _.prototype[name] = function() { - return chainResult(this, method.apply(this._wrapped, arguments)); - }; - }); - - // Extracts the result from a wrapped and chained object. - _.prototype.value = function() { - return this._wrapped; - }; - - // Provide unwrapping proxy for some methods used in engine operations - // such as arithmetic and JSON stringification. - _.prototype.valueOf = _.prototype.toJSON = _.prototype.value; - - _.prototype.toString = function() { - return '' + this._wrapped; - }; - - // AMD registration happens at the end for compatibility with AMD loaders - // that may not enforce next-turn semantics on modules. Even though general - // practice for AMD registration is to be anonymous, underscore registers - // as a named module because, like jQuery, it is a base library that is - // popular enough to be bundled in a third party lib, but not be part of - // an AMD load request. Those cases could generate an error when an - // anonymous define() is called outside of a loader request. - if (typeof define == 'function' && define.amd) { - define('underscore', [], function() { - return _; - }); - } -}()); |