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.

689 lines
18 KiB

10 years ago
11 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. transition: 'reveal'
  562. })
  563. .sidebar('attach events', '.launch.button, .view-ui.button, .launch.item')
  564. .sidebar('attach events', $hideMenu, 'hide')
  565. ;
  566. handler.createIcon();
  567. $example
  568. .each(function() {
  569. $.proxy(handler.generateCode, this)();
  570. })
  571. .find('i.code')
  572. .on('click', handler.createCode)
  573. ;
  574. $themeDropdown
  575. .dropdown({
  576. action: 'select',
  577. onChange: handler.less.changeTheme
  578. })
  579. ;
  580. $shownExample
  581. .each(handler.createCode)
  582. ;
  583. $helpPopup
  584. .popup()
  585. ;
  586. $swap
  587. .on('click', handler.swapStyle)
  588. ;
  589. $developer
  590. .on('click', handler.developerMode)
  591. ;
  592. $designer
  593. .on('click', handler.designerMode)
  594. ;
  595. $overview
  596. .on('click', handler.overviewMode)
  597. ;
  598. $menuPopup
  599. .popup({
  600. position : 'bottom center',
  601. className: {
  602. popup: 'ui popup'
  603. }
  604. })
  605. ;
  606. $sortableTables
  607. .tablesort()
  608. ;
  609. $menuDropdown
  610. .dropdown({
  611. on : 'hover',
  612. action : 'nothing'
  613. })
  614. ;
  615. $sticky
  616. .sticky({
  617. context : '.main.container',
  618. pushing : true
  619. })
  620. ;
  621. };
  622. // attach ready event
  623. $(document)
  624. .ready(semantic.ready)
  625. ;