1 /*! 2 * mindmaps - a HTML5 powered mind mapping application 3 * Copyright (C) 2011 David Richard 4 * 5 * This program is free software: you can redistribute it and/or modify 6 * it under the terms of the GNU Affero General Public License as 7 * published by the Free Software Foundation, either version 3 of the 8 * License, or (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU Affero General Public License for more details. 14 * 15 * You should have received a copy of the GNU Affero General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 */ 18 19 /* 20 * Make sure this is the first file to be referenced in index.hml. 21 */ 22 23 // Use ECMA5 strict mode. see: 24 // http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/ 25 "use strict"; 26 27 /** 28 * @namespace Application wide namespace for mindmaps. 29 */ 30 var mindmaps = mindmaps || {}; 31 32 /** 33 * Start up. This function is executed when the DOM is loaded. 34 */ 35 $(function() { 36 // take car of old browsers 37 createECMA5Shims(); 38 createHTML5Shims(); 39 40 setupConsole(); 41 trackErrors(); 42 43 // create a new app controller and go 44 var appController = new mindmaps.ApplicationController(); 45 appController.go(); 46 }); 47 48 function trackErrors() { 49 window.onerror = function(msg, url, line) { 50 if (!window._gaq) { 51 return; 52 } 53 54 // Track JS errors in GA. 55 _gaq.push([ '_trackEvent', 'Error Log', msg, url + '_' + line ]); 56 57 return false; // false prevents default error handling. 58 }; 59 } 60 61 // TODO make non global 62 /** 63 * Initialize the console object. 64 */ 65 function setupConsole() { 66 var noOp = function() { 67 }; 68 69 // provide console object and dummy functions if not built-in 70 var console = window.console || {}; 71 console.log = console.log || noOp; 72 console.info = console.info || noOp; 73 console.debug = console.debug || noOp; 74 console.warn = console.warn || noOp; 75 console.error = console.error || noOp; 76 77 // turn all console.xx calls into no-ops when in production mode except 78 // for errors, do an alert. 79 if (!mindmaps.DEBUG) { 80 console.debug = noOp; 81 console.info = noOp; 82 console.log = noOp; 83 console.warn = noOp; 84 console.error = function(s) { 85 window.alert("Error: " + s); 86 }; 87 } 88 } 89 90 /** 91 * Creates ECMA5 shims if the browser does not implement them. 92 */ 93 function createECMA5Shims() { 94 // from: https://github.com/kriskowal/es5-shim/blob/master/es5-shim.js 95 96 // ES-5 15.3.4.5 97 // http://www.ecma-international.org/publications/files/drafts/tc39-2009-025.pdf 98 if (!Function.prototype.bind) { 99 var slice = Array.prototype.slice; 100 Function.prototype.bind = function bind(that) { // .length is 1 101 var target = this; 102 if (typeof target.apply !== "function" 103 || typeof target.call !== "function") 104 return new TypeError(); 105 var args = slice.call(arguments); 106 107 function bound() { 108 109 if (this instanceof bound) { 110 111 var self = Object.create(target.prototype); 112 target.apply(self, args.concat(slice.call(arguments))); 113 return self; 114 } else { 115 return target.call.apply(target, args.concat(slice 116 .call(arguments))); 117 } 118 119 } 120 bound.length = (typeof target === "function" ? Math.max( 121 target.length - args.length, 0) : 0); 122 return bound; 123 }; 124 } 125 126 // ES5 15.4.3.2 127 if (!Array.isArray) { 128 Array.isArray = function isArray(obj) { 129 return Object.prototype.toString.call(obj) === "[object Array]"; 130 }; 131 } 132 133 // ES5 15.4.4.18 134 if (!Array.prototype.forEach) { 135 Array.prototype.forEach = function forEach(block, thisObject) { 136 var len = +this.length; 137 for ( var i = 0; i < len; i++) { 138 if (i in this) { 139 block.call(thisObject, this[i], i, this); 140 } 141 } 142 }; 143 } 144 145 // ES5 15.4.4.19 146 // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/map 147 if (!Array.prototype.map) { 148 Array.prototype.map = function map(fun /* , thisp */) { 149 var len = +this.length; 150 if (typeof fun !== "function") 151 throw new TypeError(); 152 153 var res = new Array(len); 154 var thisp = arguments[1]; 155 for ( var i = 0; i < len; i++) { 156 if (i in this) 157 res[i] = fun.call(thisp, this[i], i, this); 158 } 159 160 return res; 161 }; 162 } 163 164 // ES5 15.4.4.20 165 if (!Array.prototype.filter) { 166 Array.prototype.filter = function filter(block /* , thisp */) { 167 var values = []; 168 var thisp = arguments[1]; 169 for ( var i = 0; i < this.length; i++) 170 if (block.call(thisp, this[i])) 171 values.push(this[i]); 172 return values; 173 }; 174 } 175 176 // ES5 15.4.4.16 177 if (!Array.prototype.every) { 178 Array.prototype.every = function every(block /* , thisp */) { 179 var thisp = arguments[1]; 180 for ( var i = 0; i < this.length; i++) 181 if (!block.call(thisp, this[i])) 182 return false; 183 return true; 184 }; 185 } 186 187 // ES5 15.4.4.17 188 if (!Array.prototype.some) { 189 Array.prototype.some = function some(block /* , thisp */) { 190 var thisp = arguments[1]; 191 for ( var i = 0; i < this.length; i++) 192 if (block.call(thisp, this[i])) 193 return true; 194 return false; 195 }; 196 } 197 198 // ES5 15.4.4.21 199 // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduce 200 if (!Array.prototype.reduce) { 201 Array.prototype.reduce = function reduce(fun /* , initial */) { 202 var len = +this.length; 203 if (typeof fun !== "function") 204 throw new TypeError(); 205 206 // no value to return if no initial value and an empty array 207 if (len === 0 && arguments.length === 1) 208 throw new TypeError(); 209 210 var i = 0; 211 if (arguments.length >= 2) { 212 var rv = arguments[1]; 213 } else { 214 do { 215 if (i in this) { 216 rv = this[i++]; 217 break; 218 } 219 220 // if array contains no values, no initial value to return 221 if (++i >= len) 222 throw new TypeError(); 223 } while (true); 224 } 225 226 for (; i < len; i++) { 227 if (i in this) 228 rv = fun.call(null, rv, this[i], i, this); 229 } 230 231 return rv; 232 }; 233 } 234 235 // ES5 15.4.4.22 236 // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduceRight 237 if (!Array.prototype.reduceRight) { 238 Array.prototype.reduceRight = function reduceRight(fun /* , initial */) { 239 var len = +this.length; 240 if (typeof fun !== "function") 241 throw new TypeError(); 242 243 // no value to return if no initial value, empty array 244 if (len === 0 && arguments.length === 1) 245 throw new TypeError(); 246 247 var rv, i = len - 1; 248 if (arguments.length >= 2) { 249 rv = arguments[1]; 250 } else { 251 do { 252 if (i in this) { 253 rv = this[i--]; 254 break; 255 } 256 257 // if array contains no values, no initial value to return 258 if (--i < 0) 259 throw new TypeError(); 260 } while (true); 261 } 262 263 for (; i >= 0; i--) { 264 if (i in this) 265 rv = fun.call(null, rv, this[i], i, this); 266 } 267 268 return rv; 269 }; 270 } 271 272 // ES5 15.4.4.14 273 if (!Array.prototype.indexOf) { 274 Array.prototype.indexOf = function indexOf(value /* , fromIndex */) { 275 var length = this.length; 276 if (!length) 277 return -1; 278 var i = arguments[1] || 0; 279 if (i >= length) 280 return -1; 281 if (i < 0) 282 i += length; 283 for (; i < length; i++) { 284 if (!(i in this)) 285 continue; 286 if (value === this[i]) 287 return i; 288 } 289 return -1; 290 }; 291 } 292 293 // ES5 15.4.4.15 294 if (!Array.prototype.lastIndexOf) { 295 Array.prototype.lastIndexOf = function lastIndexOf(value) { 296 var length = this.length; 297 if (!length) 298 return -1; 299 var i = arguments[1] || length; 300 if (i < 0) 301 i += length; 302 i = Math.min(i, length - 1); 303 for (; i >= 0; i--) { 304 if (!(i in this)) 305 continue; 306 if (value === this[i]) 307 return i; 308 } 309 return -1; 310 }; 311 } 312 313 // ES5 15.9.4.4 314 if (!Date.now) { 315 Date.now = function now() { 316 return new Date().getTime(); 317 }; 318 } 319 } 320 321 /** 322 * Create shims for HTML5 functionality if not supported by browser. 323 */ 324 function createHTML5Shims() { 325 // localstorage dummy (does nothing) 326 if (typeof window.localStorage == 'undefined') { 327 window.localStorage = { 328 getItem : function() { 329 return null; 330 }, 331 setItem : function() { 332 }, 333 clear : function() { 334 }, 335 removeItem : function() { 336 }, 337 length : 0, 338 key : function() { 339 return null; 340 } 341 }; 342 } 343 }