site.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487
  1. /*!
  2. * # Semantic UI 2.3.3 - Site
  3. * http://github.com/semantic-org/semantic-ui/
  4. *
  5. *
  6. * Released under the MIT license
  7. * http://opensource.org/licenses/MIT
  8. *
  9. */
  10. ;(function ($, window, document, undefined) {
  11. $.site = $.fn.site = function(parameters) {
  12. var
  13. time = new Date().getTime(),
  14. performance = [],
  15. query = arguments[0],
  16. methodInvoked = (typeof query == 'string'),
  17. queryArguments = [].slice.call(arguments, 1),
  18. settings = ( $.isPlainObject(parameters) )
  19. ? $.extend(true, {}, $.site.settings, parameters)
  20. : $.extend({}, $.site.settings),
  21. namespace = settings.namespace,
  22. error = settings.error,
  23. eventNamespace = '.' + namespace,
  24. moduleNamespace = 'module-' + namespace,
  25. $document = $(document),
  26. $module = $document,
  27. element = this,
  28. instance = $module.data(moduleNamespace),
  29. module,
  30. returnedValue
  31. ;
  32. module = {
  33. initialize: function() {
  34. module.instantiate();
  35. },
  36. instantiate: function() {
  37. module.verbose('Storing instance of site', module);
  38. instance = module;
  39. $module
  40. .data(moduleNamespace, module)
  41. ;
  42. },
  43. normalize: function() {
  44. module.fix.console();
  45. module.fix.requestAnimationFrame();
  46. },
  47. fix: {
  48. console: function() {
  49. module.debug('Normalizing window.console');
  50. if (console === undefined || console.log === undefined) {
  51. module.verbose('Console not available, normalizing events');
  52. module.disable.console();
  53. }
  54. if (typeof console.group == 'undefined' || typeof console.groupEnd == 'undefined' || typeof console.groupCollapsed == 'undefined') {
  55. module.verbose('Console group not available, normalizing events');
  56. window.console.group = function() {};
  57. window.console.groupEnd = function() {};
  58. window.console.groupCollapsed = function() {};
  59. }
  60. if (typeof console.markTimeline == 'undefined') {
  61. module.verbose('Mark timeline not available, normalizing events');
  62. window.console.markTimeline = function() {};
  63. }
  64. },
  65. consoleClear: function() {
  66. module.debug('Disabling programmatic console clearing');
  67. window.console.clear = function() {};
  68. },
  69. requestAnimationFrame: function() {
  70. module.debug('Normalizing requestAnimationFrame');
  71. if(window.requestAnimationFrame === undefined) {
  72. module.debug('RequestAnimationFrame not available, normalizing event');
  73. window.requestAnimationFrame = window.requestAnimationFrame
  74. || window.mozRequestAnimationFrame
  75. || window.webkitRequestAnimationFrame
  76. || window.msRequestAnimationFrame
  77. || function(callback) { setTimeout(callback, 0); }
  78. ;
  79. }
  80. }
  81. },
  82. moduleExists: function(name) {
  83. return ($.fn[name] !== undefined && $.fn[name].settings !== undefined);
  84. },
  85. enabled: {
  86. modules: function(modules) {
  87. var
  88. enabledModules = []
  89. ;
  90. modules = modules || settings.modules;
  91. $.each(modules, function(index, name) {
  92. if(module.moduleExists(name)) {
  93. enabledModules.push(name);
  94. }
  95. });
  96. return enabledModules;
  97. }
  98. },
  99. disabled: {
  100. modules: function(modules) {
  101. var
  102. disabledModules = []
  103. ;
  104. modules = modules || settings.modules;
  105. $.each(modules, function(index, name) {
  106. if(!module.moduleExists(name)) {
  107. disabledModules.push(name);
  108. }
  109. });
  110. return disabledModules;
  111. }
  112. },
  113. change: {
  114. setting: function(setting, value, modules, modifyExisting) {
  115. modules = (typeof modules === 'string')
  116. ? (modules === 'all')
  117. ? settings.modules
  118. : [modules]
  119. : modules || settings.modules
  120. ;
  121. modifyExisting = (modifyExisting !== undefined)
  122. ? modifyExisting
  123. : true
  124. ;
  125. $.each(modules, function(index, name) {
  126. var
  127. namespace = (module.moduleExists(name))
  128. ? $.fn[name].settings.namespace || false
  129. : true,
  130. $existingModules
  131. ;
  132. if(module.moduleExists(name)) {
  133. module.verbose('Changing default setting', setting, value, name);
  134. $.fn[name].settings[setting] = value;
  135. if(modifyExisting && namespace) {
  136. $existingModules = $(':data(module-' + namespace + ')');
  137. if($existingModules.length > 0) {
  138. module.verbose('Modifying existing settings', $existingModules);
  139. $existingModules[name]('setting', setting, value);
  140. }
  141. }
  142. }
  143. });
  144. },
  145. settings: function(newSettings, modules, modifyExisting) {
  146. modules = (typeof modules === 'string')
  147. ? [modules]
  148. : modules || settings.modules
  149. ;
  150. modifyExisting = (modifyExisting !== undefined)
  151. ? modifyExisting
  152. : true
  153. ;
  154. $.each(modules, function(index, name) {
  155. var
  156. $existingModules
  157. ;
  158. if(module.moduleExists(name)) {
  159. module.verbose('Changing default setting', newSettings, name);
  160. $.extend(true, $.fn[name].settings, newSettings);
  161. if(modifyExisting && namespace) {
  162. $existingModules = $(':data(module-' + namespace + ')');
  163. if($existingModules.length > 0) {
  164. module.verbose('Modifying existing settings', $existingModules);
  165. $existingModules[name]('setting', newSettings);
  166. }
  167. }
  168. }
  169. });
  170. }
  171. },
  172. enable: {
  173. console: function() {
  174. module.console(true);
  175. },
  176. debug: function(modules, modifyExisting) {
  177. modules = modules || settings.modules;
  178. module.debug('Enabling debug for modules', modules);
  179. module.change.setting('debug', true, modules, modifyExisting);
  180. },
  181. verbose: function(modules, modifyExisting) {
  182. modules = modules || settings.modules;
  183. module.debug('Enabling verbose debug for modules', modules);
  184. module.change.setting('verbose', true, modules, modifyExisting);
  185. }
  186. },
  187. disable: {
  188. console: function() {
  189. module.console(false);
  190. },
  191. debug: function(modules, modifyExisting) {
  192. modules = modules || settings.modules;
  193. module.debug('Disabling debug for modules', modules);
  194. module.change.setting('debug', false, modules, modifyExisting);
  195. },
  196. verbose: function(modules, modifyExisting) {
  197. modules = modules || settings.modules;
  198. module.debug('Disabling verbose debug for modules', modules);
  199. module.change.setting('verbose', false, modules, modifyExisting);
  200. }
  201. },
  202. console: function(enable) {
  203. if(enable) {
  204. if(instance.cache.console === undefined) {
  205. module.error(error.console);
  206. return;
  207. }
  208. module.debug('Restoring console function');
  209. window.console = instance.cache.console;
  210. }
  211. else {
  212. module.debug('Disabling console function');
  213. instance.cache.console = window.console;
  214. window.console = {
  215. clear : function(){},
  216. error : function(){},
  217. group : function(){},
  218. groupCollapsed : function(){},
  219. groupEnd : function(){},
  220. info : function(){},
  221. log : function(){},
  222. markTimeline : function(){},
  223. warn : function(){}
  224. };
  225. }
  226. },
  227. destroy: function() {
  228. module.verbose('Destroying previous site for', $module);
  229. $module
  230. .removeData(moduleNamespace)
  231. ;
  232. },
  233. cache: {},
  234. setting: function(name, value) {
  235. if( $.isPlainObject(name) ) {
  236. $.extend(true, settings, name);
  237. }
  238. else if(value !== undefined) {
  239. settings[name] = value;
  240. }
  241. else {
  242. return settings[name];
  243. }
  244. },
  245. internal: function(name, value) {
  246. if( $.isPlainObject(name) ) {
  247. $.extend(true, module, name);
  248. }
  249. else if(value !== undefined) {
  250. module[name] = value;
  251. }
  252. else {
  253. return module[name];
  254. }
  255. },
  256. debug: function() {
  257. if(settings.debug) {
  258. if(settings.performance) {
  259. module.performance.log(arguments);
  260. }
  261. else {
  262. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  263. module.debug.apply(console, arguments);
  264. }
  265. }
  266. },
  267. verbose: function() {
  268. if(settings.verbose && settings.debug) {
  269. if(settings.performance) {
  270. module.performance.log(arguments);
  271. }
  272. else {
  273. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  274. module.verbose.apply(console, arguments);
  275. }
  276. }
  277. },
  278. error: function() {
  279. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  280. module.error.apply(console, arguments);
  281. },
  282. performance: {
  283. log: function(message) {
  284. var
  285. currentTime,
  286. executionTime,
  287. previousTime
  288. ;
  289. if(settings.performance) {
  290. currentTime = new Date().getTime();
  291. previousTime = time || currentTime;
  292. executionTime = currentTime - previousTime;
  293. time = currentTime;
  294. performance.push({
  295. 'Element' : element,
  296. 'Name' : message[0],
  297. 'Arguments' : [].slice.call(message, 1) || '',
  298. 'Execution Time' : executionTime
  299. });
  300. }
  301. clearTimeout(module.performance.timer);
  302. module.performance.timer = setTimeout(module.performance.display, 500);
  303. },
  304. display: function() {
  305. var
  306. title = settings.name + ':',
  307. totalTime = 0
  308. ;
  309. time = false;
  310. clearTimeout(module.performance.timer);
  311. $.each(performance, function(index, data) {
  312. totalTime += data['Execution Time'];
  313. });
  314. title += ' ' + totalTime + 'ms';
  315. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  316. console.groupCollapsed(title);
  317. if(console.table) {
  318. console.table(performance);
  319. }
  320. else {
  321. $.each(performance, function(index, data) {
  322. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  323. });
  324. }
  325. console.groupEnd();
  326. }
  327. performance = [];
  328. }
  329. },
  330. invoke: function(query, passedArguments, context) {
  331. var
  332. object = instance,
  333. maxDepth,
  334. found,
  335. response
  336. ;
  337. passedArguments = passedArguments || queryArguments;
  338. context = element || context;
  339. if(typeof query == 'string' && object !== undefined) {
  340. query = query.split(/[\. ]/);
  341. maxDepth = query.length - 1;
  342. $.each(query, function(depth, value) {
  343. var camelCaseValue = (depth != maxDepth)
  344. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  345. : query
  346. ;
  347. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  348. object = object[camelCaseValue];
  349. }
  350. else if( object[camelCaseValue] !== undefined ) {
  351. found = object[camelCaseValue];
  352. return false;
  353. }
  354. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  355. object = object[value];
  356. }
  357. else if( object[value] !== undefined ) {
  358. found = object[value];
  359. return false;
  360. }
  361. else {
  362. module.error(error.method, query);
  363. return false;
  364. }
  365. });
  366. }
  367. if ( $.isFunction( found ) ) {
  368. response = found.apply(context, passedArguments);
  369. }
  370. else if(found !== undefined) {
  371. response = found;
  372. }
  373. if($.isArray(returnedValue)) {
  374. returnedValue.push(response);
  375. }
  376. else if(returnedValue !== undefined) {
  377. returnedValue = [returnedValue, response];
  378. }
  379. else if(response !== undefined) {
  380. returnedValue = response;
  381. }
  382. return found;
  383. }
  384. };
  385. if(methodInvoked) {
  386. if(instance === undefined) {
  387. module.initialize();
  388. }
  389. module.invoke(query);
  390. }
  391. else {
  392. if(instance !== undefined) {
  393. module.destroy();
  394. }
  395. module.initialize();
  396. }
  397. return (returnedValue !== undefined)
  398. ? returnedValue
  399. : this
  400. ;
  401. };
  402. $.site.settings = {
  403. name : 'Site',
  404. namespace : 'site',
  405. error : {
  406. console : 'Console cannot be restored, most likely it was overwritten outside of module',
  407. method : 'The method you called is not defined.'
  408. },
  409. debug : false,
  410. verbose : false,
  411. performance : true,
  412. modules: [
  413. 'accordion',
  414. 'api',
  415. 'checkbox',
  416. 'dimmer',
  417. 'dropdown',
  418. 'embed',
  419. 'form',
  420. 'modal',
  421. 'nag',
  422. 'popup',
  423. 'rating',
  424. 'shape',
  425. 'sidebar',
  426. 'state',
  427. 'sticky',
  428. 'tab',
  429. 'transition',
  430. 'visit',
  431. 'visibility'
  432. ],
  433. siteNamespace : 'site',
  434. namespaceStub : {
  435. cache : {},
  436. config : {},
  437. sections : {},
  438. section : {},
  439. utilities : {}
  440. }
  441. };
  442. // allows for selection of elements with data attributes
  443. $.extend($.expr[ ":" ], {
  444. data: ($.expr.createPseudo)
  445. ? $.expr.createPseudo(function(dataName) {
  446. return function(elem) {
  447. return !!$.data(elem, dataName);
  448. };
  449. })
  450. : function(elem, i, match) {
  451. // support: jQuery < 1.8
  452. return !!$.data(elem, match[ 3 ]);
  453. }
  454. });
  455. })( jQuery, window, document );