diff --git a/CHANGELOG b/CHANGELOG index b5faa02..08dc3d7 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,7 @@ *SVN* +* Add Object.isString, Object.isNumber, and Object.isUndefined, and clean up the source to make use of Object.isXXX where possible. [sam] + * Add the document.viewport object for querying dimensions and scroll offsets of the browser viewport. [Andrew Dupont, Thomas Fuchs, sam] Example: document.viewport.getDimensions() // { width: 1149, height: 923 } diff --git a/src/ajax.js b/src/ajax.js index 84974c4..1234768 100644 --- a/src/ajax.js +++ b/src/ajax.js @@ -28,10 +28,10 @@ Ajax.Responders = { dispatch: function(callback, request, transport, json) { this.each(function(responder) { - if (typeof responder[callback] == 'function') { + if (Object.isFunction(responder[callback])) { try { responder[callback].apply(responder, [request, transport, json]); - } catch (e) {} + } catch (e) { } } }); } @@ -48,7 +48,7 @@ Ajax.Responders.register({ } }); -Ajax.Base = function() {}; +Ajax.Base = function() { }; Ajax.Base.prototype = { setOptions: function(options) { this.options = { @@ -60,10 +60,10 @@ Ajax.Base.prototype = { evalJSON: true, evalJS: true }; - Object.extend(this.options, options || {}); + Object.extend(this.options, options || { }); this.options.method = this.options.method.toLowerCase(); - if (typeof this.options.parameters == 'string') + if (Object.isString(this.options.parameters)) this.options.parameters = this.options.parameters.toQueryParams(); } }; @@ -158,7 +158,7 @@ Ajax.Request.prototype = Object.extend(new Ajax.Base(), { if (typeof this.options.requestHeaders == 'object') { var extras = this.options.requestHeaders; - if (typeof extras.push == 'function') + if (Object.isFunction(extras.push)) for (var i = 0, length = extras.length; i < length; i += 2) headers[extras[i]] = extras[i+1]; else @@ -332,8 +332,8 @@ Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), { if (receiver = $(receiver)) { if (options.insertion) { - if (typeof options.insertion == 'string') { - var insertion = {}; insertion[options.insertion] = responseText; + if (Object.isString(options.insertion)) { + var insertion = { }; insertion[options.insertion] = responseText; receiver.insert(insertion); } else options.insertion(receiver, responseText); @@ -356,7 +356,7 @@ Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), { this.frequency = (this.options.frequency || 2); this.decay = (this.options.decay || 1); - this.updater = {}; + this.updater = { }; this.container = container; this.url = url; diff --git a/src/array.js b/src/array.js index b38abee..89b6831 100644 --- a/src/array.js +++ b/src/array.js @@ -12,8 +12,8 @@ function $A(iterable) { if (Prototype.Browser.WebKit) { function $A(iterable) { if (!iterable) return []; - if (!(typeof iterable == 'function' && iterable == '[object NodeList]') && - iterable.toArray) { + if (!(Object.isFunction(iterable) && iterable == '[object NodeList]') && + iterable.toArray) { return iterable.toArray(); } else { var results = []; @@ -114,7 +114,7 @@ Object.extend(Array.prototype, { }); // use native browser JS 1.6 implementation if available -if (typeof Array.prototype.forEach == 'function') +if (Object.isFunction(Array.prototype.forEach)) Array.prototype._each = Array.prototype.forEach; if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) { diff --git a/src/base.js b/src/base.js index e3a37c9..07ac8d9 100644 --- a/src/base.js +++ b/src/base.js @@ -1,7 +1,7 @@ /* Based on Alex Arnell's inheritance implementation. */ var Class = { create: function(parent, methods) { - if (arguments.length == 1 && typeof parent !== 'function') + if (arguments.length == 1 && !Object.isFunction(parent)) methods = parent, parent = null; var method = function() { @@ -137,6 +137,18 @@ Object.extend(Object, { isFunction: function(object) { return typeof object == "function"; + }, + + isString: function(object) { + return typeof object == "string"; + }, + + isNumber: function(object) { + return typeof object == "number"; + }, + + isUndefined: function(object) { + return typeof object == "undefined"; } }); @@ -212,7 +224,7 @@ var Try = { try { returnValue = lambda(); break; - } catch (e) {} + } catch (e) { } } return returnValue; diff --git a/src/deprecated.js b/src/deprecated.js index e284025..b669303 100644 --- a/src/deprecated.js +++ b/src/deprecated.js @@ -106,7 +106,7 @@ var Position = { page: Element.Methods.viewportOffset, clone: function(source, target, options) { - options = options || {}; + options = options || { }; return Element.clonePosition(target, source, options); } }; diff --git a/src/dom.js b/src/dom.js index 0ab6b7a..deeab3b 100644 --- a/src/dom.js +++ b/src/dom.js @@ -4,7 +4,7 @@ function $(element) { elements.push($(arguments[i])); return elements; } - if (typeof element == 'string') + if (Object.isString(element)) element = document.getElementById(element); return Element.extend(element); } @@ -113,7 +113,7 @@ Element.Methods = { insert: function(element, insertions) { element = $(element); - if (typeof insertions == 'string' || typeof insertions == 'number' || + if (Object.isString(insertions) || Object.isNumber(insertions) || Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML))) insertions = {bottom:insertions}; @@ -146,7 +146,7 @@ Element.Methods = { element = $(element); if (Object.isElement(wrapper)) $(wrapper).writeAttribute(attributes || { }); - else if (typeof wrapper == 'string') wrapper = new Element(wrapper, attributes); + else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes); else wrapper = new Element('div', wrapper); if (element.parentNode) element.parentNode.replaceChild(wrapper, element); @@ -209,7 +209,7 @@ Element.Methods = { }, match: function(element, selector) { - if (typeof selector == 'string') + if (Object.isString(selector)) selector = new Selector(selector); return selector.match($(element)); }, @@ -383,7 +383,7 @@ Element.Methods = { setStyle: function(element, styles) { element = $(element); var elementStyle = element.style, match; - if (typeof styles === 'string') { + if (Object.isString(styles)) { element.style.cssText += ';' + styles; return styles.include('opacity') ? element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element; @@ -680,9 +680,9 @@ if (!document.createRange || Prototype.Browser.Opera) { Element.Methods.insert = function(element, insertions) { element = $(element); - if (typeof insertions == 'string' || typeof insertions == 'number' || + if (Object.isString(insertions) || Object.isNumber(insertions) || Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML))) - insertions = {bottom:insertions}; + insertions = { bottom: insertions }; var t = Element._insertionTranslations, content, position, pos, tagName; @@ -1056,7 +1056,7 @@ Element.extend = (function() { for (property in methods) { value = methods[property]; - if (typeof value == 'function' && !(property in element)) + if (Object.isFunction(value) && !(property in element)) element[property] = value.methodize(); } @@ -1118,7 +1118,7 @@ Element.addMethods = function(methods) { onlyIfAbsent = onlyIfAbsent || false; for (var property in methods) { var value = methods[property]; - if (typeof value != 'function') continue; + if (!Object.isFunction(value)) continue; if (!onlyIfAbsent || !(property in destination)) destination[property] = value.methodize(); } @@ -1157,7 +1157,7 @@ Element.addMethods = function(methods) { if (F.SpecificElementExtensions) { for (var tag in Element.Methods.ByTag) { var klass = findDOMClass(tag); - if (typeof klass == "undefined") continue; + if (Object.isUndefined(klass)) continue; copy(T[tag], klass.prototype); } } @@ -1171,8 +1171,8 @@ Element.addMethods = function(methods) { document.viewport = { getDimensions: function() { - var dimensions = {}; - $w('width height').each( function(d) { + var dimensions = { }; + $w('width height').each(function(d) { var D = d.capitalize(); dimensions[d] = self['inner' + D] || (document.documentElement['client' + D] || document.body['client' + D]); diff --git a/src/enumerable.js b/src/enumerable.js index e4e9936..2b2ae06 100644 --- a/src/enumerable.js +++ b/src/enumerable.js @@ -1,4 +1,4 @@ -var $break = {}; +var $break = { }; var Enumerable = { each: function(iterator, context) { @@ -77,7 +77,7 @@ var Enumerable = { iterator = iterator ? iterator.bind(context) : Prototype.K; var results = []; - if (typeof filter == "string") + if (Object.isString(filter)) filter = new RegExp(filter); this.each(function(value, index) { @@ -88,7 +88,7 @@ var Enumerable = { }, include: function(object) { - if (typeof this.indexOf == 'function') + if (Object.isFunction(this.indexOf)) return this.indexOf(object) != -1; var found = false; @@ -190,7 +190,7 @@ var Enumerable = { zip: function() { var iterator = Prototype.K, args = $A(arguments); - if (typeof args.last() == 'function') + if (Object.isFunction(args.last())) iterator = args.pop(); var collections = [this].concat(args).map($A); diff --git a/src/event.js b/src/event.js index 22fdbc6..cb13b3d 100644 --- a/src/event.js +++ b/src/event.js @@ -220,7 +220,7 @@ Object.extend(Event, (function() { } event.eventName = eventName; - event.memo = memo || {}; + event.memo = memo || { }; if (document.createEvent) { element.dispatchEvent(event); diff --git a/src/form.js b/src/form.js index 6040e34..6083548 100644 --- a/src/form.js +++ b/src/form.js @@ -9,7 +9,7 @@ var Form = { else if (options.hash === undefined) options.hash = true; var key, value, submitted = false, submit = options.submit; - var data = elements.inject({}, function(result, element) { + var data = elements.inject({ }, function(result, element) { if (!element.disabled && element.name) { key = element.name; value = $(element).getValue(); if (value != null && (element.type != 'submit' || (!submitted && @@ -92,14 +92,14 @@ Form.Methods = { }, request: function(form, options) { - form = $(form), options = Object.clone(options || {}); + form = $(form), options = Object.clone(options || { }); var params = options.parameters, action = form.readAttribute('action') || ''; if (action.blank()) action = window.location.href; options.parameters = form.serialize(true); if (params) { - if (typeof params == 'string') params = params.toQueryParams(); + if (Object.isString(params)) params = params.toQueryParams(); Object.extend(options.parameters, params); } @@ -130,7 +130,7 @@ Form.Element.Methods = { if (!element.disabled && element.name) { var value = element.getValue(); if (value != undefined) { - var pair = {}; + var pair = { }; pair[element.name] = value; return Hash.toQueryString(pair); } @@ -167,7 +167,7 @@ Form.Element.Methods = { if (element.select && (element.tagName.toLowerCase() != 'input' || !['button', 'reset', 'submit'].include(element.type))) element.select(); - } catch (e) {} + } catch (e) { } return element; }, @@ -257,7 +257,7 @@ Form.Element.Serializers = { /*--------------------------------------------------------------------------*/ -Abstract.TimedObserver = function() {}; +Abstract.TimedObserver = function() { }; Abstract.TimedObserver.prototype = { initialize: function(element, frequency, callback) { this.frequency = frequency; @@ -274,7 +274,7 @@ Abstract.TimedObserver.prototype = { onTimerEvent: function() { var value = this.getValue(); - var changed = ('string' == typeof this.lastValue && 'string' == typeof value + var changed = (Object.isString(this.lastValue) && Object.isString(value) ? this.lastValue != value : String(this.lastValue) != String(value)); if (changed) { this.callback(this.element, value); @@ -299,7 +299,7 @@ Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { /*--------------------------------------------------------------------------*/ -Abstract.EventObserver = function() {}; +Abstract.EventObserver = function() { }; Abstract.EventObserver.prototype = { initialize: function(element, callback) { this.element = $(element); diff --git a/src/hash.js b/src/hash.js index 963c3f6..2046a89 100644 --- a/src/hash.js +++ b/src/hash.js @@ -1,6 +1,6 @@ var Hash = function(object) { if (object instanceof Hash) this.merge(object); - else Object.extend(this, object || {}); + else Object.extend(this, object || { }); }; Object.extend(Hash, { diff --git a/src/selector.js b/src/selector.js index f5ca759..cdd922f 100644 --- a/src/selector.js +++ b/src/selector.js @@ -19,8 +19,10 @@ Selector.prototype = { c = Selector.criteria, le, p, m; if (Selector._cache[e]) { - this.matcher = Selector._cache[e]; return; + this.matcher = Selector._cache[e]; + return; } + this.matcher = ["this.matcher = function(root) {", "var r = root, h = Selector.handlers, c = false, n;"]; @@ -29,7 +31,7 @@ Selector.prototype = { for (var i in ps) { p = ps[i]; if (m = e.match(p)) { - this.matcher.push(typeof c[i] == 'function' ? c[i](m) : + this.matcher.push(Object.isFunction(c[i]) ? c[i](m) : new Template(c[i]).evaluate(m)); e = e.replace(m[0], ''); break; @@ -55,7 +57,7 @@ Selector.prototype = { le = e; for (var i in ps) { if (m = e.match(ps[i])) { - this.matcher.push(typeof x[i] == 'function' ? x[i](m) : + this.matcher.push(Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m)); e = e.replace(m[0], ''); break; @@ -119,7 +121,7 @@ Selector.prototype = { }; Object.extend(Selector, { - _cache: {}, + _cache: { }, xpath: { descendant: "//*", @@ -141,7 +143,7 @@ Object.extend(Selector, { pseudo: function(m) { var h = Selector.xpath.pseudos[m[1]]; if (!h) return ''; - if (typeof h === 'function') return h(m); + if (Object.isFunction(h)) return h(m); return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m); }, operators: { @@ -170,7 +172,7 @@ Object.extend(Selector, { le = e; for (var i in p) { if (m = e.match(p[i])) { - v = typeof x[i] == 'function' ? x[i](m) : new Template(x[i]).evaluate(m); + v = Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m); exclusion.push("(" + v.substring(1, v.length - 1) + ")"); e = e.replace(m[0], ''); break; @@ -604,7 +606,7 @@ Object.extend(Selector, { }, findElement: function(elements, expression, index) { - if (typeof expression == 'number') { + if (Object.isNumber(expression)) { index = expression; expression = false; } return Selector.matchElements(elements, expression || '*')[index || 0]; diff --git a/src/string.js b/src/string.js index a1f6607..4dfb583 100644 --- a/src/string.js +++ b/src/string.js @@ -91,9 +91,9 @@ Object.extend(String.prototype, { toQueryParams: function(separator) { var match = this.strip().match(/([^?#]*)(#.*)?$/); - if (!match) return {}; + if (!match) return { }; - return match[1].split(separator || '&').inject({}, function(hash, pair) { + return match[1].split(separator || '&').inject({ }, function(hash, pair) { if ((pair = pair.split('='))[0]) { var key = decodeURIComponent(pair.shift()); var value = pair.length > 1 ? pair.join('=') : pair[0]; @@ -216,7 +216,7 @@ if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.proto }); String.prototype.gsub.prepareReplacement = function(replacement) { - if (typeof replacement == 'function') return replacement; + if (Object.isFunction(replacement)) return replacement; var template = new Template(replacement); return function(match) { return template.evaluate(match) }; }; @@ -239,7 +239,7 @@ Template.prototype = { }, evaluate: function(object) { - if (typeof object.toTemplateReplacements == 'function') + if (Object.isFunction(object.toTemplateReplacements)) object = object.toTemplateReplacements(); return this.template.gsub(this.pattern, function(match) { diff --git a/test/unit/base.html b/test/unit/base.html index a0b13c8..49123ff 100644 --- a/test/unit/base.html +++ b/test/unit/base.html @@ -241,6 +241,38 @@ assert(!Object.isFunction(undefined)); }}, + testObjectIsString: function() { with(this) { + assert(!Object.isString(function() { })); + assert(Object.isString("a string")); + assert(!Object.isString(0)); + assert(!Object.isString([])); + assert(!Object.isString({})); + assert(!Object.isString(false)); + assert(!Object.isString(undefined)); + }}, + + testObjectIsNumber: function() { with(this) { + assert(Object.isNumber(0)); + assert(Object.isNumber(1.0)); + assert(!Object.isNumber(function() { })); + assert(!Object.isNumber("a string")); + assert(!Object.isNumber([])); + assert(!Object.isNumber({})); + assert(!Object.isNumber(false)); + assert(!Object.isNumber(undefined)); + }}, + + testObjectIsUndefined: function() { with(this) { + assert(Object.isUndefined(undefined)); + assert(!Object.isUndefined(null)); + assert(!Object.isUndefined(false)); + assert(!Object.isUndefined(0)); + assert(!Object.isUndefined("")); + assert(!Object.isUndefined(function() { })); + assert(!Object.isUndefined([])); + assert(!Object.isUndefined({})); + }}, + // sanity check testDoesntExtendObjectPrototype: function() {with(this) { // for-in is supported with objects