1 var 2 WINDOW_APP = WINDOW_APP || {}; 3 4 WINDOW_APP.util = {}; 5 6 /** 7 * location hashの変更を通知 8 * 9 * @class 10 */ 11 WINDOW_APP.util.hashchange = (function () { 12 var 13 _DELAY = 50, //監視のタイミング 14 15 _doc = document, 16 17 _isPlaying = false, //動作中か 18 _listeners = [], //リスナー 19 _numListener = 0, //追加された要素の数 20 _timer, //タイマー 21 _prevHash; //前回のハッシュ 22 23 24 /** 25 * イベントの登録 26 * 27 * @param func {Function} リスナー 28 */ 29 function on (func) { 30 var 31 isAdded = false; //すでに追加されているか 32 33 if(typeof func === "function") { 34 //同じものがあれば上書き 35 for(var i = 0; i < _numListener; i++) { 36 if(_listeners[i] === func) { 37 _listeners[i] = func; 38 isAdded = true; 39 break; 40 } 41 } 42 43 if(!isAdded) { 44 _listeners.push(func); 45 _numListener++; 46 } 47 } 48 } 49 50 /** 51 * イベントの登録 52 * 53 * @param func {Function} リスナー 54 */ 55 function bind(func) { 56 on(func); 57 } 58 59 /** 60 * イベントの削除 61 * 62 * @param func {Function} リスナー 63 * @return {Boolean} 削除されたか 64 */ 65 function off (func) { 66 var result = false; 67 for(var i = 0; i < _numListener; i++) { 68 //一致したリスナーを削除 69 if(_listeners[i] === func) { 70 delete _listeners[i]; 71 _numListener--; 72 result = true; 73 break; 74 } 75 } 76 77 return result; 78 } 79 80 /** 81 * イベントの削除 82 * 83 * @param func {Function} リスナー 84 * @return {Boolean} 削除されたか 85 */ 86 function unbind(func) { 87 return off(func); 88 } 89 90 /** 91 * モニターの開始 92 * 93 */ 94 function start () { 95 stop(); 96 97 //開始時のハッシュを保持 98 _prevHash = _doc.location.hash; 99 100 _monitor(); 101 _timer = setInterval(_monitor, _DELAY); 102 _isPlaying = true; 103 } 104 105 /** 106 * モニターの停止 107 * 108 */ 109 function stop () { 110 if(_timer) { 111 clearInterval(_timer); 112 } 113 _isPlaying = false; 114 } 115 116 /** 117 * 通知 118 * 119 */ 120 function trigger() { 121 _monitor(true); 122 } 123 124 /** 125 * 監視&通知 126 * 127 * @param [isForce] {Boolean} 強制的に通知するか 128 */ 129 function _monitor(isForce) { 130 var 131 currentHash = _doc.location.hash, 132 isChange = false; //変更されたか 133 134 if(currentHash !== _prevHash) { 135 isChange = true; 136 } 137 138 //通知 139 if(isChange || isForce) { 140 for(var i = 0; i < _numListener; i++) { 141 _listeners[i].apply(_listeners[i], [currentHash]); 142 } 143 } 144 145 _prevHash = currentHash; //保持 146 } 147 148 //public 149 return { 150 on: on, 151 off: off, 152 bind: bind, 153 unbind: unbind, 154 start: start, 155 stop: stop, 156 trigger: trigger 157 }; 158 }());