You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

688 lines
18 KiB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
  1. // namespace
  2. window.semantic = {
  3. handler: {}
  4. };
  5. // Allow for console.log to not break IE
  6. if (typeof window.console == "undefined" || typeof window.console.log == "undefined") {
  7. window.console = {
  8. log : function() {},
  9. info : function(){},
  10. warn : function(){}
  11. };
  12. }
  13. if(typeof window.console.group == 'undefined' || typeof window.console.groupEnd == 'undefined' || typeof window.console.groupCollapsed == 'undefined') {
  14. window.console.group = function(){};
  15. window.console.groupEnd = function(){};
  16. window.console.groupCollapsed = function(){};
  17. }
  18. if(typeof window.console.markTimeline == 'undefined') {
  19. window.console.markTimeline = function(){};
  20. }
  21. window.console.clear = function(){};
  22. // ready event
  23. semantic.ready = function() {
  24. // selector cache
  25. var
  26. $sortableTables = $('.sortable.table'),
  27. $sticky = $('.ui.sticky'),
  28. $themeDropdown = $('.theme.dropdown'),
  29. $ui = $('.ui').not('.hover, .down'),
  30. $swap = $('.theme.menu .item'),
  31. $menu = $('#menu'),
  32. $hideMenu = $('#menu .hide.item'),
  33. $sortTable = $('.sortable.table'),
  34. $demo = $('.demo'),
  35. $menuPopup = $('.ui.main.menu .popup.item'),
  36. $menuDropdown = $('.ui.main.menu .dropdown'),
  37. $pageTabMenu = $('.tab.header.segment .tabular.menu'),
  38. $pageTabs = $('.tab.header.segment .menu .item'),
  39. $downloadDropdown = $('.download.buttons .dropdown'),
  40. $helpPopup = $('.header .help.icon'),
  41. $example = $('.example'),
  42. $shownExample = $example.filter('.shown'),
  43. $developer = $('.developer.item'),
  44. $overview = $('.overview.item, .overview.button'),
  45. $designer = $('.designer.item'),
  46. $sidebarButton = $('.fixed.launch.button'),
  47. $code = $('div.code').not('.existing'),
  48. $existingCode = $('.existing.code'),
  49. // alias
  50. handler
  51. ;
  52. // event handlers
  53. handler = {
  54. createIcon: function() {
  55. $example
  56. .each(function(){
  57. $('<i/>')
  58. .addClass('icon code')
  59. .prependTo( $(this) )
  60. ;
  61. })
  62. ;
  63. },
  64. getSpecification: function(callback) {
  65. var
  66. url = $(this).data('url') || false
  67. ;
  68. callback = callback || function(){};
  69. if(url) {
  70. $.ajax({
  71. method: 'get',
  72. url: url,
  73. type: 'json',
  74. complete: callback
  75. });
  76. }
  77. },
  78. less: {
  79. parseFile: function(content) {
  80. var
  81. variables = {},
  82. lines = content.match(/^(@[\s|\S]+?;)/gm),
  83. name,
  84. value
  85. ;
  86. $.each(lines, function(index, line) {
  87. // clear whitespace
  88. line = $.trim(line);
  89. // match variables only
  90. if(line[0] == '@') {
  91. name = line.match(/^@(.+):/);
  92. value = line.match(/:\s*([\s|\S]+?;)/);
  93. if( ($.isArray(name) && name.length >= 2) && ($.isArray(value) && value.length >= 2) ) {
  94. name = name[1];
  95. value = value[1];
  96. variables[name] = value;
  97. }
  98. }
  99. });
  100. console.log(variables);
  101. return variables;
  102. },
  103. changeTheme: function(theme) {
  104. var
  105. variableURL = '/build/less/themes/packages/{$theme}/{$type}s/{$element}.variables',
  106. overrideURL = '/build/less/themes/packages/{$theme}/{$type}s/{$element}.overrides',
  107. urlData = {
  108. theme : typeof(theme === 'string')
  109. ? theme.toLowerCase()
  110. : theme,
  111. type : $themeDropdown.data('type'),
  112. element : $themeDropdown.data('element')
  113. }
  114. ;
  115. $themeDropdown
  116. .api({
  117. on : 'now',
  118. url : variableURL,
  119. dataType : 'text',
  120. urlData : urlData,
  121. success: function(content) {
  122. less.modifyVars( handler.less.parseFile(content) );
  123. $themeDropdown
  124. .api({
  125. on : 'now',
  126. url : overrideURL,
  127. dataType : 'text',
  128. urlData : urlData,
  129. success: function(content) {
  130. if( $('style.override').size() > 0 ) {
  131. $('style.override').remove();
  132. }
  133. console.log(content);
  134. $('<style>' + content + '</style>')
  135. .addClass('override')
  136. .appendTo('body')
  137. ;
  138. }
  139. })
  140. ;
  141. }
  142. })
  143. ;
  144. }
  145. },
  146. create: {
  147. examples: function(json) {
  148. var
  149. types = json['Types'],
  150. text = json['Text'],
  151. states = json['States'],
  152. variations = json['Variations'],
  153. $element,
  154. html
  155. ;
  156. $.each(types, function(name, type){
  157. html += '<h2 class="ui dividing header">' + name + '</h2';
  158. if($.isPlainObject(type)) {
  159. $.each(type, function(name, subType) {
  160. $element = $.zc(subType);
  161. $element = handler.create.text($element, text);
  162. html += '<h3 class="ui header">' + name + '</h3';
  163. html += handler.create.variations($element, variations);
  164. });
  165. }
  166. else {
  167. $element = $.zc(type);
  168. $element = handler.create.text($element);
  169. html += handler.create.variations($element, variations);
  170. }
  171. });
  172. // Each TYPE
  173. // show type name
  174. // html = koan (html)
  175. // each text
  176. // find label
  177. // if(obj)
  178. // replace random text
  179. // else
  180. // replace text
  181. // end
  182. // Each variation
  183. // (if obj)
  184. // each
  185. // add class
  186. // (else)
  187. // add class
  188. // label = property
  189. // class = class
  190. // show html
  191. // end
  192. // end
  193. },
  194. element: function(koan, type, text, variation) {
  195. },
  196. variations: function($element, variations) {
  197. $.each(variations, function(name, variation){
  198. });
  199. },
  200. text: function($element, text) {
  201. $.each(text, function(selector, text) {
  202. $element.find(selector).text(text);
  203. });
  204. return $element;
  205. }
  206. },
  207. overviewMode: function() {
  208. var
  209. $button = $(this),
  210. $body = $('body'),
  211. $example = $('.example')
  212. ;
  213. $body.toggleClass('overview');
  214. $button.toggleClass('active');
  215. if($body.hasClass('overview')) {
  216. $developer.addClass('disabled').popup('destroy');
  217. $designer.addClass('disabled').popup('destroy');
  218. $example.each(function() {
  219. $(this).children().not('.ui.header:eq(0), .example p:eq(0), .annotation').hide();
  220. });
  221. $example.filter('.another').hide();
  222. }
  223. else {
  224. $developer.removeClass('disabled').popup();
  225. $designer.removeClass('disabled').popup();
  226. $example.each(function() {
  227. $(this).children().not('.ui.header:eq(0), .example p:eq(0), .annotation').show();
  228. });
  229. $example.filter('.another').show();
  230. }
  231. },
  232. developerMode: function() {
  233. var
  234. $example = $('.example').not('.no')
  235. ;
  236. $developer.addClass('active');
  237. $designer.removeClass('active');
  238. $example
  239. .each(function() {
  240. $.proxy(handler.createCode, $(this))('developer');
  241. })
  242. ;
  243. },
  244. designerMode: function() {
  245. var
  246. $example = $('.example').not('.no')
  247. ;
  248. $designer.addClass('active');
  249. $developer.removeClass('active');
  250. $example
  251. .each(function() {
  252. $.proxy(handler.createCode, $(this))('designer');
  253. })
  254. ;
  255. },
  256. getIndent: function(text) {
  257. var
  258. lines = text.split("\n"),
  259. firstLine = (lines[0] === '')
  260. ? lines[1]
  261. : lines[0],
  262. spacesPerIndent = 2,
  263. leadingSpaces = firstLine.length - firstLine.replace(/^\s*/g, '').length,
  264. indent
  265. ;
  266. if(leadingSpaces !== 0) {
  267. indent = leadingSpaces;
  268. }
  269. else {
  270. // string has already been trimmed, get first indented line and subtract 2
  271. $.each(lines, function(index, line) {
  272. leadingSpaces = line.length - line.replace(/^\s*/g, '').length;
  273. if(leadingSpaces !== 0) {
  274. indent = leadingSpaces - spacesPerIndent;
  275. return false;
  276. }
  277. });
  278. }
  279. return indent || 4;
  280. },
  281. generateCode: function() {
  282. var
  283. $example = $(this).closest('.example'),
  284. $annotation = $example.find('.annotation'),
  285. $code = $annotation.find('.code'),
  286. $header = $example.not('.another').children('.ui.header:first-of-type').eq(0).add('p:first-of-type'),
  287. $ignored = $('i.code:first-child, .code, .existing, .pointing.below.label, .instructive, .language.label, .annotation, br, .ignore, .ignored'),
  288. $demo = $example.children().not($header).not($ignored),
  289. code = ''
  290. ;
  291. if( $code.size() === 0) {
  292. $demo
  293. .each(function(){
  294. var $this = $(this).clone(false);
  295. if($this.not('br')) {
  296. code += $this.removeAttr('style').get(0).outerHTML + "\n";
  297. }
  298. })
  299. ;
  300. }
  301. $example.data('code', code);
  302. return code;
  303. },
  304. createCode: function(type) {
  305. var
  306. $example = $(this).closest('.example'),
  307. $header = $example.children('.ui.header:first-of-type').eq(0).add('p:first-of-type'),
  308. $annotation = $example.find('.annotation'),
  309. $code = $annotation.find('.code'),
  310. $ignoredContent = $('.ui.popup, i.code:first-child, .code, .existing.segment, .instructive, .language.label, .annotation, br, .ignore, .ignored'),
  311. $demo = $example.children().not($header).not($ignoredContent),
  312. code = $example.data('code') || $.proxy(handler.generateCode, this)()
  313. ;
  314. if( $code.hasClass('existing') ) {
  315. $annotation.show();
  316. $code.removeClass('existing');
  317. $.proxy(handler.initializeCode, $code)();
  318. }
  319. if($annotation.size() === 0) {
  320. $annotation = $('<div/>')
  321. .addClass('annotation')
  322. .appendTo($example)
  323. ;
  324. }
  325. if( $example.find('.instructive').size() === 0) {
  326. $code = $('<div/>')
  327. .data('type', 'html')
  328. .addClass('code')
  329. .html(code)
  330. .hide()
  331. .appendTo($annotation)
  332. ;
  333. $.proxy(handler.initializeCode, $code)();
  334. }
  335. if( ($demo.first().is(':visible') || type == 'developer') && type != 'designer' ) {
  336. $demo.hide();
  337. $header.show();
  338. $annotation.fadeIn(500);
  339. }
  340. else {
  341. $annotation.hide();
  342. if($demo.size() > 1) {
  343. $demo.show();
  344. }
  345. else {
  346. $demo.fadeIn(500);
  347. }
  348. }
  349. },
  350. createAnnotation: function() {
  351. if(!$(this).data('type')) {
  352. $(this).data('type', 'html');
  353. }
  354. $(this)
  355. .wrap('<div class="annotation">')
  356. .parent()
  357. .hide()
  358. ;
  359. },
  360. resizeCode: function() {
  361. $('.ace_editor')
  362. .each(function() {
  363. var
  364. $code = $(this),
  365. padding = 50,
  366. editor,
  367. editorSession,
  368. codeHeight
  369. ;
  370. $code.css('height', 'auto');
  371. editor = ace.edit($code[0]);
  372. editorSession = editor.getSession();
  373. codeHeight = editorSession.getScreenLength() * editor.renderer.lineHeight + padding;
  374. $code.css('height', codeHeight);
  375. editor.resize();
  376. })
  377. ;
  378. },
  379. makeCode: function() {
  380. if(window.ace !== undefined) {
  381. $code
  382. .filter(':visible')
  383. .each(handler.initializeCode)
  384. ;
  385. $existingCode
  386. .each(handler.createAnnotation)
  387. ;
  388. }
  389. },
  390. initializeCode: function() {
  391. var
  392. $code = $(this).show(),
  393. code = $code.html(),
  394. existingCode = $code.hasClass('existing'),
  395. evaluatedCode = $code.hasClass('evaluated'),
  396. contentType = $code.data('type') || 'javascript',
  397. title = $code.data('title') || false,
  398. demo = $code.data('demo') || false,
  399. preview = $code.data('preview') || false,
  400. label = $code.data('label') || false,
  401. displayType = {
  402. html : 'HTML',
  403. javascript : 'Javascript',
  404. css : 'CSS',
  405. text : 'Command Line',
  406. sh : 'Command Line'
  407. },
  408. indent = handler.getIndent(code) || 2,
  409. padding = 20,
  410. name = (evaluatedCode)
  411. ? 'existing'
  412. : 'instructive',
  413. whiteSpace,
  414. $label,
  415. editor,
  416. editorSession,
  417. codeHeight
  418. ;
  419. // trim whitespace
  420. whiteSpace = new RegExp('\\n\\s{' + indent + '}', 'g');
  421. code = $.trim(code).replace(whiteSpace, '\n');
  422. if(contentType == 'html') {
  423. $code.text(code);
  424. }
  425. else {
  426. $code.html(code);
  427. }
  428. // evaluate if specified
  429. if(evaluatedCode) {
  430. eval(code);
  431. }
  432. // initialize
  433. editor = ace.edit($code[0]);
  434. editorSession = editor.getSession();
  435. //editor.setTheme('ace/theme/tomorrow');
  436. editor.setTheme('ace/theme/github');
  437. editor.setShowPrintMargin(false);
  438. editor.setReadOnly(true);
  439. editor.renderer.setShowGutter(false);
  440. editor.setHighlightActiveLine(false);
  441. editorSession.setMode('ace/mode/'+ contentType);
  442. editorSession.setUseWrapMode(true);
  443. editorSession.setTabSize(2);
  444. editorSession.setUseSoftTabs(true);
  445. codeHeight = editorSession.getScreenLength() * editor.renderer.lineHeight + padding;
  446. $(this)
  447. .height(codeHeight + 'px')
  448. .wrap('<div class="ui ' + name + ' segment">')
  449. ;
  450. // add label
  451. if(title) {
  452. $('<div>')
  453. .addClass('ui attached top label')
  454. .html('<span class="title">' + title + '</span>' + '<em>' + (displayType[contentType] || contentType) + '</em>')
  455. .prependTo( $(this).parent() )
  456. ;
  457. }
  458. if(label) {
  459. $('<div>')
  460. .addClass('ui pointing below label')
  461. .html(displayType[contentType] || contentType)
  462. .insertBefore ( $(this).parent() )
  463. ;
  464. }
  465. // add run code button
  466. if(demo) {
  467. $('<a>')
  468. .addClass('ui pointing below label')
  469. .html('Run Code')
  470. .on('click', function() {
  471. eval(code);
  472. })
  473. .insertBefore ( $(this).parent() )
  474. ;
  475. }
  476. // add preview if specified
  477. if(preview) {
  478. $(code)
  479. .insertAfter( $(this).parent() )
  480. ;
  481. }
  482. editor.resize();
  483. },
  484. swapStyle: function() {
  485. var
  486. theme = $(this).data('theme')
  487. ;
  488. $(this)
  489. .addClass('active')
  490. .siblings()
  491. .removeClass('active')
  492. ;
  493. $('head link.ui')
  494. .each(function() {
  495. var
  496. href = $(this).attr('href'),
  497. subDirectory = href.split('/')[3],
  498. newLink = href.replace(subDirectory, theme)
  499. ;
  500. $(this)
  501. .attr('href', newLink)
  502. ;
  503. })
  504. ;
  505. }
  506. };
  507. $('.masthead')
  508. .visibility({
  509. once: false
  510. })
  511. .visibility('bottom visible', function(){
  512. $('.main.menu').removeClass('filled');
  513. })
  514. .visibility('bottom passed', function(){
  515. $('.main.menu').addClass('filled');
  516. })
  517. .find('.button')
  518. .popup({
  519. position : 'top center',
  520. variation : 'inverted'
  521. })
  522. ;
  523. $(window)
  524. .on('resize', function() {
  525. clearTimeout(handler.timer);
  526. handler.timer = setTimeout(handler.resizeCode, 500);
  527. })
  528. ;
  529. $downloadDropdown
  530. .dropdown({
  531. on : 'click',
  532. transition : 'scale'
  533. })
  534. ;
  535. // attach events
  536. if($.fn.tablesort !== undefined) {
  537. $sortTable
  538. .tablesort()
  539. ;
  540. }
  541. if( $pageTabs.size() > 0 ) {
  542. $pageTabs
  543. .tab({
  544. context : '.main.container',
  545. childrenOnly : true,
  546. history : true,
  547. onTabInit : function() {
  548. handler.makeCode();
  549. },
  550. onTabLoad : function() {
  551. $sticky.filter(':visible').sticky('refresh');
  552. }
  553. })
  554. ;
  555. }
  556. else {
  557. handler.makeCode();
  558. }
  559. $menu
  560. .sidebar()
  561. .sidebar('attach events', '.launch.button, .view-ui.button, .launch.item')
  562. .sidebar('attach events', $hideMenu, 'hide')
  563. ;
  564. handler.createIcon();
  565. $example
  566. .each(function() {
  567. $.proxy(handler.generateCode, this)();
  568. })
  569. .find('i.code')
  570. .on('click', handler.createCode)
  571. ;
  572. $themeDropdown
  573. .dropdown({
  574. action: 'select',
  575. onChange: handler.less.changeTheme
  576. })
  577. ;
  578. $shownExample
  579. .each(handler.createCode)
  580. ;
  581. $helpPopup
  582. .popup()
  583. ;
  584. $swap
  585. .on('click', handler.swapStyle)
  586. ;
  587. $developer
  588. .on('click', handler.developerMode)
  589. ;
  590. $designer
  591. .on('click', handler.designerMode)
  592. ;
  593. $overview
  594. .on('click', handler.overviewMode)
  595. ;
  596. $menuPopup
  597. .popup({
  598. position : 'bottom center',
  599. className: {
  600. popup: 'ui popup'
  601. }
  602. })
  603. ;
  604. $sortableTables
  605. .tablesort()
  606. ;
  607. $menuDropdown
  608. .dropdown({
  609. on : 'hover',
  610. action : 'nothing',
  611. allowTab : false
  612. })
  613. ;
  614. $sticky
  615. .sticky({
  616. context : '.main.container',
  617. pushing : true
  618. })
  619. ;
  620. };
  621. // attach ready event
  622. $(document)
  623. .ready(semantic.ready)
  624. ;