var VnDate = require ('./date'); var Lot = require ('./lot'); /** * Class to handle the hash part of the URL as a key-value javascript object. * It also handles dates and objects as a value. */ module.exports = new Class ({ Extends: Lot ,Properties: { /** * The main window object. */ window: { type: Window ,set: function (x) { this._window = x; x.addEventListener ('hashchange', this._hashChangedHandler); this._hashChanged (); } ,get: function () { return this._window; } } } ,initialize: function (props) { Object.assign (this, { _hash: null ,_hashLock: false ,_window: null ,_hashChangedHandler: this._hashChanged.bind (this) }); this.parent (props); } ,_paramsChanged: function () { this.updateHash (); } /** * Creates a URL with the given hash data. * * @param {Object} params A key-value object * @param {boolean} add %true to combine with the current params, %false otherwise * @return {string} The URL */ ,make: function (params, add) { if (add) { params = Object.assign ({}, params); for (var key in this._params) if (!params[key]) params[key] = this._params[key]; } return this.renderHash (params); } /** * Updates the window hash with current params. */ ,updateHash: function () { if (this._hashLock) return; this._hash = this.renderHash (this._params); this._hashLock = true; location.hash = this._hash; this._hashLock = false; } /* * Called when window hash changes. */ ,_hashChanged: function () { var newHash = location.hash; if (this._hashLock || this._hash === newHash) return; this._hash = newHash; this._hashLock = true; this.params = this.parseHash (newHash); this._hashLock = false; } /** * Creates a URL with the given hash data. * * @param {Object} params The key-value object * @return {string} The URL */ ,renderHash: function (params) { var hash = '#!'; for (var key in params) if (params[key] !== undefined) { if (hash.length > 2) hash += '&'; hash += encodeURIComponent (key) +'='+ this.renderValue (params[key]); } return hash; } /** * Parses a hash string to a key-value object. * * @param {string} hashString The hash string * @return {Object} The key-value object */ ,parseHash: function (hashString) { var newMap = hashMap = {}; var kvPairs = hashString.substr(2).split ('&'); for (var i = 0; i < kvPairs.length; i++) { var kvPair = kvPairs[i].split ('=', 2); if (kvPair[0]) newMap[decodeURIComponent (kvPair[0])] = this.parseValue (kvPair[1]); } return newMap; } ,renderValue: function (v) { if (v == null) return ''; switch (typeof v) { case 'object': if (v instanceof Date) return VnDate.strftime (v, '%Y-%m-%d'); else return JSON.stringify (v) } return v; } ,parseValue: function (v) { if (v == null) return v; v = decodeURIComponent (v); if (v === '') return null; return v; } ,_destroy: function () { this._window.removeEventListener ('hashchange', this._hashChangedHandler); this._window = null; this.parent (); } });