Today we wanted to feature the hashtable object used internally by the core components and/or widgets in Swell.
At first don ‘t get me wrong, objects used as hash-tables is to date the most convenient way of storing static properties associated to a key, I just complain that it’s sometimes (not always) missing features you would find in other languages such as PHP.
Here’s the code :
Swell.Core.Class({ name : 'Hashtable', namespace : 'Swell.Core', inherits : [Swell.Core.Enumerable, Swell.Core.CustomEventModel], functions : function() { var _hash = {}; var _updateLength = function() { var _l = 0, _n; if(_hash.__count__) { this.length = _hash.__count__; } else { for(_n in _hash) { _l++; } this.length = _l; } } var _initEvents = function() { /** * @event onChange fires when an item is added/updated in the hashtable */ this.createEvent('change'); this.subscribe('change', _updateLength); } return { length : 0, /** * Constructor, initialize enumerable * * @function construct * @constructor */ construct : function() { this.setEnumerable(_hash); _initEvents.call(this); }, /** * Resets the hashtable * * @function dispose */ empty : function() { _hash = {}; }, /** * Add/Update an entry in the hashtable * * @function set * @param {String} key Key name * @return {Swell.Core.Hashtable} */ set : function(key, value) { if(arguments.length === 1) { _hash[Swell.uniqueId()] = key; } else { _hash[key] = value; } this.fireEvent('change', this); return this; }, /** * Add an entry in the hashtable if the key does not exist * * @function set * @param {String} key Key name * @return {Swell.Core.Hashtable} */ add : function(key, value) { if(!this.exists(key)) { this.set(key, value); return this; } return false; }, /** * Update an entry in the hashtable if the key exists * * @function set * @param {String} key Key name * @return {Swell.Core.Hashtable} */ update : function(key, value) { if(this.exists(key)) { this.set(key, value); return this; } return false; }, /** * Get the value of the corresponding key in the hashtable * * @function get * @param {String} key Key name * @return {Mixed/Boolean} value */ get : function(key) { if(_hash.hasOwnProperty(key)) { return _hash[key]; } return false; }, /** * Exchanges all keys with their associated values in the hashtable * * @function flip * @return {Swell.Core.Hashtable} */ flip : function() { var _k, _tmp = {}; for( _k in _hash ) { _tmp[_hash[_k]] = _k; } _hash = _tmp; return this; }, /** * Returns the first item of the hashtable * * @function first * @param {Boolean} [extended] Returns an array with the first item as key and second one as val (optional) * @return {Mixed} */ first : function(extended) { for(var _p in _hash) { if(!Swell.Core.isUndefined(extended)) { return [_p, _hash[_p]]; } return _hash[_p]; } return false; }, /** * Returns the last item of the hashtable * * @function last * @param {Boolean} [extended] Returns an array with the last item as key and second one as val (optional) * @return {Mixed} */ last : function(extended) { var _lastitem = false; for(var _p in _hash) { _lastitem = _hash[_p]; } if(!Swell.Core.isUndefined(extended)) { return [_p, _lastitem]; } return _lastitem; }, /** * Unsets an item from the hashtable * * @function remove * @return {Swell.Core.Hashtable} */ remove : function(key) { if(_hash.hasOwnProperty(key)) { delete _hash[key]; this.fireEvent('change', this); } return this; }, /** * Applies the callback to the elements of the hashtable * * @function map * @return {Swell.Core.Hashtable} */ map : function(fn) { var _p, _tmp = {}; if(Swell.Core.isFunction(fn)) { for(_p in _hash) { _tmp[_p] = fn.call(null, _hash[_p]); } } return _tmp; }, /** * Test if a property exists in the hash table * * @function exists * @return {Boolean} */ exists : function(key) { return _hash.hasOwnProperty(key); }, /** * Applies an user function on every member of the hashtable * * @function walk * @return {Swell.Core.Hashtable} */ walk : function(fn) { var _p; if(Swell.Core.isFunction(fn)) { for(_p in _hash) { _hash[_p] = fn.call(null, _hash[_p]); } } return this; }, /** * Returns an array of keys * * @function keys * @return {Mixed[]} keys */ keys : function() { var _k, _tmp = []; for(_k in _hash) { _tmp.push(_k); } return _tmp; }, /** * Pop the element off the end of array * * @function pop * @return {Mixed} value of the popped item */ pop : function() { var _item = this.last(true); delete _item[0]; return _item[1]; }, /** * Returns an array of values * * @function values * @return {Mixed[]} values */ values : function() { var _k, _tmp = []; for(_k in _hash) { _tmp.push(_hash[_k]); } return _tmp; }, /** * Returns the wrapped native object * * @function toObject * @return {Object} */ toObject : function() { return _hash; }, /** * Returns a string representation of the wrapped native object * * @function toSource * @return {String} */ toSource : function() { if(_hash.toSource) { return _hash.toSource(); } else { var _stack = []; for(var _n in _hash) { _stack.push('"' + _n + '" : "' + _hash[_n] + '"'); } return '({' + _stack.join(',') + '})'; } } } }() });
But how to use it ?
A Swell class can be instantiated just like you would do with a classic object.
var ht = new Swell.Core.Hashtable(); // Put some stuff into the hashtable ht.set('foo', 'bar'); ht.set('baz','bleh'); //Then walk every member of the hashtable to turn the value into uppercase h.walk(function(member) { return member.toUpperCase(); }); // Output the hash, this will give us an object like : {foo : "BAR", baz : "BLEH"} h.toObject();
Tags: class, hashtable, Javascript, objects as hashtable, Swell








March 18th, 2009 at 10:45 pm
Hashtable now supports custom getters when retrieving a key.
Please refer to the blog post on getStyle for more information…
My two cents