github.com/fanux/shipyard@v0.0.0-20161009071005-6515ce223235/controller/static/semantic/src/definitions/behaviors/visit.js (about) 1 /*! 2 * # Semantic UI - Visit 3 * http://github.com/semantic-org/semantic-ui/ 4 * 5 * 6 * Copyright 2014 Contributors 7 * Released under the MIT license 8 * http://opensource.org/licenses/MIT 9 * 10 */ 11 12 ;(function ($, window, document, undefined) { 13 14 "use strict"; 15 16 $.visit = $.fn.visit = function(parameters) { 17 var 18 $allModules = $.isFunction(this) 19 ? $(window) 20 : $(this), 21 moduleSelector = $allModules.selector || '', 22 23 time = new Date().getTime(), 24 performance = [], 25 26 query = arguments[0], 27 methodInvoked = (typeof query == 'string'), 28 queryArguments = [].slice.call(arguments, 1), 29 returnedValue 30 ; 31 $allModules 32 .each(function() { 33 var 34 settings = $.extend(true, {}, $.fn.visit.settings, parameters), 35 36 error = settings.error, 37 namespace = settings.namespace, 38 39 eventNamespace = '.' + namespace, 40 moduleNamespace = namespace + '-module', 41 42 $module = $(this), 43 $displays = $(), 44 45 element = this, 46 instance = $module.data(moduleNamespace), 47 module 48 ; 49 module = { 50 51 initialize: function() { 52 if(settings.count) { 53 module.store(settings.key.count, settings.count); 54 } 55 else if(settings.id) { 56 module.add.id(settings.id); 57 } 58 else if(settings.increment && methodInvoked !== 'increment') { 59 module.increment(); 60 } 61 module.add.display($module); 62 module.instantiate(); 63 }, 64 65 instantiate: function() { 66 module.verbose('Storing instance of visit module', module); 67 instance = module; 68 $module 69 .data(moduleNamespace, module) 70 ; 71 }, 72 73 destroy: function() { 74 module.verbose('Destroying instance'); 75 $module 76 .removeData(moduleNamespace) 77 ; 78 }, 79 80 increment: function(id) { 81 var 82 currentValue = module.get.count(), 83 newValue = +(currentValue) + 1 84 ; 85 if(id) { 86 module.add.id(id); 87 } 88 else { 89 if(newValue > settings.limit && !settings.surpass) { 90 newValue = settings.limit; 91 } 92 module.debug('Incrementing visits', newValue); 93 module.store(settings.key.count, newValue); 94 } 95 }, 96 97 decrement: function(id) { 98 var 99 currentValue = module.get.count(), 100 newValue = +(currentValue) - 1 101 ; 102 if(id) { 103 module.remove.id(id); 104 } 105 else { 106 module.debug('Removing visit'); 107 module.store(settings.key.count, newValue); 108 } 109 }, 110 111 get: { 112 count: function() { 113 return +(module.retrieve(settings.key.count)) || 0; 114 }, 115 idCount: function(ids) { 116 ids = ids || module.get.ids(); 117 return ids.length; 118 }, 119 ids: function(delimitedIDs) { 120 var 121 idArray = [] 122 ; 123 delimitedIDs = delimitedIDs || module.retrieve(settings.key.ids); 124 if(typeof delimitedIDs === 'string') { 125 idArray = delimitedIDs.split(settings.delimiter); 126 } 127 module.verbose('Found visited ID list', idArray); 128 return idArray; 129 }, 130 storageOptions: function(data) { 131 var 132 options = {} 133 ; 134 if(settings.expires) { 135 options.expires = settings.expires; 136 } 137 if(settings.domain) { 138 options.domain = settings.domain; 139 } 140 if(settings.path) { 141 options.path = settings.path; 142 } 143 return options; 144 } 145 }, 146 147 has: { 148 visited: function(id, ids) { 149 var 150 visited = false 151 ; 152 ids = ids || module.get.ids(); 153 if(id !== undefined && ids) { 154 $.each(ids, function(index, value){ 155 if(value == id) { 156 visited = true; 157 } 158 }); 159 } 160 return visited; 161 } 162 }, 163 164 set: { 165 count: function(value) { 166 module.store(settings.key.count, value); 167 }, 168 ids: function(value) { 169 module.store(settings.key.ids, value); 170 } 171 }, 172 173 reset: function() { 174 module.store(settings.key.count, 0); 175 module.store(settings.key.ids, null); 176 }, 177 178 add: { 179 id: function(id) { 180 var 181 currentIDs = module.retrieve(settings.key.ids), 182 newIDs = (currentIDs === undefined || currentIDs === '') 183 ? id 184 : currentIDs + settings.delimiter + id 185 ; 186 if( module.has.visited(id) ) { 187 module.debug('Unique content already visited, not adding visit', id, currentIDs); 188 } 189 else if(id === undefined) { 190 module.debug('ID is not defined'); 191 } 192 else { 193 module.debug('Adding visit to unique content', id); 194 module.store(settings.key.ids, newIDs); 195 } 196 module.set.count( module.get.idCount() ); 197 }, 198 display: function(selector) { 199 var 200 $element = $(selector) 201 ; 202 if($element.length > 0 && !$.isWindow($element[0])) { 203 module.debug('Updating visit count for element', $element); 204 $displays = ($displays.length > 0) 205 ? $displays.add($element) 206 : $element 207 ; 208 } 209 } 210 }, 211 212 remove: { 213 id: function(id) { 214 var 215 currentIDs = module.get.ids(), 216 newIDs = [] 217 ; 218 if(id !== undefined && currentIDs !== undefined) { 219 module.debug('Removing visit to unique content', id, currentIDs); 220 $.each(currentIDs, function(index, value){ 221 if(value !== id) { 222 newIDs.push(value); 223 } 224 }); 225 newIDs = newIDs.join(settings.delimiter); 226 module.store(settings.key.ids, newIDs ); 227 } 228 module.set.count( module.get.idCount() ); 229 } 230 }, 231 232 check: { 233 limit: function(value) { 234 value = value || module.get.count(); 235 if(settings.limit) { 236 if(value >= settings.limit) { 237 module.debug('Pages viewed exceeded limit, firing callback', value, settings.limit); 238 settings.onLimit.call(element, value); 239 } 240 module.debug('Limit not reached', value, settings.limit); 241 settings.onChange.call(element, value); 242 } 243 module.update.display(value); 244 } 245 }, 246 247 update: { 248 display: function(value) { 249 value = value || module.get.count(); 250 if($displays.length > 0) { 251 module.debug('Updating displayed view count', $displays); 252 $displays.html(value); 253 } 254 } 255 }, 256 257 store: function(key, value) { 258 var 259 options = module.get.storageOptions(value) 260 ; 261 if(settings.storageMethod == 'localstorage' && window.localStorage !== undefined) { 262 window.localStorage.setItem(key, value); 263 module.debug('Value stored using local storage', key, value); 264 } 265 else if($.cookie !== undefined) { 266 $.cookie(key, value, options); 267 module.debug('Value stored using cookie', key, value, options); 268 } 269 else { 270 module.error(error.noCookieStorage); 271 return; 272 } 273 if(key == settings.key.count) { 274 module.check.limit(value); 275 } 276 }, 277 retrieve: function(key, value) { 278 var 279 storedValue 280 ; 281 if(settings.storageMethod == 'localstorage' && window.localStorage !== undefined) { 282 storedValue = window.localStorage.getItem(key); 283 } 284 // get by cookie 285 else if($.cookie !== undefined) { 286 storedValue = $.cookie(key); 287 } 288 else { 289 module.error(error.noCookieStorage); 290 } 291 if(storedValue == 'undefined' || storedValue == 'null' || storedValue === undefined || storedValue === null) { 292 storedValue = undefined; 293 } 294 return storedValue; 295 }, 296 297 setting: function(name, value) { 298 if( $.isPlainObject(name) ) { 299 $.extend(true, settings, name); 300 } 301 else if(value !== undefined) { 302 settings[name] = value; 303 } 304 else { 305 return settings[name]; 306 } 307 }, 308 internal: function(name, value) { 309 module.debug('Changing internal', name, value); 310 if(value !== undefined) { 311 if( $.isPlainObject(name) ) { 312 $.extend(true, module, name); 313 } 314 else { 315 module[name] = value; 316 } 317 } 318 else { 319 return module[name]; 320 } 321 }, 322 debug: function() { 323 if(settings.debug) { 324 if(settings.performance) { 325 module.performance.log(arguments); 326 } 327 else { 328 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); 329 module.debug.apply(console, arguments); 330 } 331 } 332 }, 333 verbose: function() { 334 if(settings.verbose && settings.debug) { 335 if(settings.performance) { 336 module.performance.log(arguments); 337 } 338 else { 339 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); 340 module.verbose.apply(console, arguments); 341 } 342 } 343 }, 344 error: function() { 345 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); 346 module.error.apply(console, arguments); 347 }, 348 performance: { 349 log: function(message) { 350 var 351 currentTime, 352 executionTime, 353 previousTime 354 ; 355 if(settings.performance) { 356 currentTime = new Date().getTime(); 357 previousTime = time || currentTime; 358 executionTime = currentTime - previousTime; 359 time = currentTime; 360 performance.push({ 361 'Name' : message[0], 362 'Arguments' : [].slice.call(message, 1) || '', 363 'Element' : element, 364 'Execution Time' : executionTime 365 }); 366 } 367 clearTimeout(module.performance.timer); 368 module.performance.timer = setTimeout(module.performance.display, 100); 369 }, 370 display: function() { 371 var 372 title = settings.name + ':', 373 totalTime = 0 374 ; 375 time = false; 376 clearTimeout(module.performance.timer); 377 $.each(performance, function(index, data) { 378 totalTime += data['Execution Time']; 379 }); 380 title += ' ' + totalTime + 'ms'; 381 if(moduleSelector) { 382 title += ' \'' + moduleSelector + '\''; 383 } 384 if($allModules.length > 1) { 385 title += ' ' + '(' + $allModules.length + ')'; 386 } 387 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { 388 console.groupCollapsed(title); 389 if(console.table) { 390 console.table(performance); 391 } 392 else { 393 $.each(performance, function(index, data) { 394 console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); 395 }); 396 } 397 console.groupEnd(); 398 } 399 performance = []; 400 } 401 }, 402 invoke: function(query, passedArguments, context) { 403 var 404 object = instance, 405 maxDepth, 406 found, 407 response 408 ; 409 passedArguments = passedArguments || queryArguments; 410 context = element || context; 411 if(typeof query == 'string' && object !== undefined) { 412 query = query.split(/[\. ]/); 413 maxDepth = query.length - 1; 414 $.each(query, function(depth, value) { 415 var camelCaseValue = (depth != maxDepth) 416 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) 417 : query 418 ; 419 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) { 420 object = object[camelCaseValue]; 421 } 422 else if( object[camelCaseValue] !== undefined ) { 423 found = object[camelCaseValue]; 424 return false; 425 } 426 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) { 427 object = object[value]; 428 } 429 else if( object[value] !== undefined ) { 430 found = object[value]; 431 return false; 432 } 433 else { 434 return false; 435 } 436 }); 437 } 438 if ( $.isFunction( found ) ) { 439 response = found.apply(context, passedArguments); 440 } 441 else if(found !== undefined) { 442 response = found; 443 } 444 if($.isArray(returnedValue)) { 445 returnedValue.push(response); 446 } 447 else if(returnedValue !== undefined) { 448 returnedValue = [returnedValue, response]; 449 } 450 else if(response !== undefined) { 451 returnedValue = response; 452 } 453 return found; 454 } 455 }; 456 if(methodInvoked) { 457 if(instance === undefined) { 458 module.initialize(); 459 } 460 module.invoke(query); 461 } 462 else { 463 if(instance !== undefined) { 464 instance.invoke('destroy'); 465 } 466 module.initialize(); 467 } 468 469 }) 470 ; 471 return (returnedValue !== undefined) 472 ? returnedValue 473 : this 474 ; 475 }; 476 477 $.fn.visit.settings = { 478 479 name : 'Visit', 480 481 debug : false, 482 verbose : true, 483 performance : true, 484 485 namespace : 'visit', 486 487 increment : false, 488 surpass : false, 489 count : false, 490 limit : false, 491 492 delimiter : '&', 493 storageMethod : 'localstorage', 494 495 key : { 496 count : 'visit-count', 497 ids : 'visit-ids' 498 }, 499 500 expires : 30, 501 domain : false, 502 path : '/', 503 504 onLimit : function() {}, 505 onChange : function() {}, 506 507 error : { 508 method : 'The method you called is not defined', 509 missingPersist : 'Using the persist setting requires the inclusion of PersistJS', 510 noCookieStorage : 'The default storage cookie requires $.cookie to be included.' 511 } 512 513 }; 514 515 })( jQuery, window , document );