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.

901 lines
23 KiB

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. $peek = $('.peek'),
  27. $peekItem = $peek.children('.menu').children('a.item'),
  28. $peekSubItem = $peek.find('.item .menu .item'),
  29. $sortableTables = $('.sortable.table'),
  30. $stuckColumn = $('.fixed.column > .image, .fixed.column > .content'),
  31. $themeDropdown = $('.theme.dropdown'),
  32. $ui = $('.ui').not('.hover, .down'),
  33. $swap = $('.theme.menu .item'),
  34. $menu = $('#menu'),
  35. $hideMenu = $('#menu .hide.item'),
  36. $sortTable = $('.sortable.table'),
  37. $demo = $('.demo'),
  38. $waypoints = $peek.closest('.tab, .container').find('h2').first().siblings('h2').addBack(),
  39. $menuPopup = $('.ui.main.menu .popup.item'),
  40. $menuDropdown = $('.ui.main.menu .dropdown'),
  41. $pageTabMenu = $('body > .tab.segment .tabular.menu'),
  42. $pageTabs = $('body > .tab.segment .menu .item'),
  43. $downloadDropdown = $('.download.buttons .dropdown'),
  44. $helpPopup = $('.header .help.icon'),
  45. $example = $('.example'),
  46. $shownExample = $example.filter('.shown'),
  47. $developer = $('.developer.item'),
  48. $overview = $('.overview.item, .overview.button'),
  49. $designer = $('.designer.item'),
  50. $sidebarButton = $('.attached.launch.button'),
  51. $increaseFont = $('.font .increase'),
  52. $decreaseFont = $('.font .decrease'),
  53. $code = $('div.code').not('.existing'),
  54. $existingCode = $('.existing.code'),
  55. // alias
  56. handler
  57. ;
  58. // event handlers
  59. handler = {
  60. createIcon: function() {
  61. $example
  62. .each(function(){
  63. $('<i/>')
  64. .addClass('icon code')
  65. .prependTo( $(this) )
  66. ;
  67. })
  68. ;
  69. },
  70. getSpecification: function(callback) {
  71. var
  72. url = $(this).data('url') || false
  73. ;
  74. callback = callback || function(){};
  75. if(url) {
  76. $.ajax({
  77. method: 'get',
  78. url: url,
  79. type: 'json',
  80. complete: callback
  81. });
  82. }
  83. },
  84. less: {
  85. parseFile: function(content) {
  86. var
  87. variables = {},
  88. lines = content.match(/^(@[\s|\S]+?;)/gm),
  89. name,
  90. value
  91. ;
  92. $.each(lines, function(index, line) {
  93. // clear whitespace
  94. line = $.trim(line);
  95. // match variables only
  96. if(line[0] == '@') {
  97. name = line.match(/^@(.+):/);
  98. value = line.match(/:\s*([\s|\S]+?;)/);
  99. if( ($.isArray(name) && name.length >= 2) && ($.isArray(value) && value.length >= 2) ) {
  100. name = name[1];
  101. value = value[1];
  102. variables[name] = value;
  103. }
  104. }
  105. });
  106. console.log(variables);
  107. return variables;
  108. },
  109. changeTheme: function(theme) {
  110. var
  111. variableURL = '/build/less/themes/packages/{$theme}/{$type}s/{$element}.variables',
  112. overrideURL = '/build/less/themes/packages/{$theme}/{$type}s/{$element}.overrides',
  113. urlData = {
  114. theme : typeof(theme === 'string')
  115. ? theme.toLowerCase()
  116. : theme,
  117. type : $themeDropdown.data('type'),
  118. element : $themeDropdown.data('element')
  119. }
  120. ;
  121. $themeDropdown
  122. .api({
  123. on : 'now',
  124. url : variableURL,
  125. dataType : 'text',
  126. urlData : urlData,
  127. success: function(content) {
  128. less.modifyVars( handler.less.parseFile(content) );
  129. $themeDropdown
  130. .api({
  131. on : 'now',
  132. url : overrideURL,
  133. dataType : 'text',
  134. urlData : urlData,
  135. success: function(content) {
  136. if( $('style.override').size() > 0 ) {
  137. $('style.override').remove();
  138. }
  139. console.log(content);
  140. $('<style>' + content + '</style>')
  141. .addClass('override')
  142. .appendTo('body')
  143. ;
  144. }
  145. })
  146. ;
  147. }
  148. })
  149. ;
  150. }
  151. },
  152. create: {
  153. examples: function(json) {
  154. var
  155. types = json['Types'],
  156. text = json['Text'],
  157. states = json['States'],
  158. variations = json['Variations'],
  159. $element,
  160. html
  161. ;
  162. $.each(types, function(name, type){
  163. html += '<h2 class="ui dividing header">' + name + '</h2';
  164. if($.isPlainObject(type)) {
  165. $.each(type, function(name, subType) {
  166. $element = $.zc(subType);
  167. $element = handler.create.text($element, text);
  168. html += '<h3 class="ui header">' + name + '</h3';
  169. html += handler.create.variations($element, variations);
  170. });
  171. }
  172. else {
  173. $element = $.zc(type);
  174. $element = handler.create.text($element);
  175. html += handler.create.variations($element, variations);
  176. }
  177. });
  178. // Each TYPE
  179. // show type name
  180. // html = koan (html)
  181. // each text
  182. // find label
  183. // if(obj)
  184. // replace random text
  185. // else
  186. // replace text
  187. // end
  188. // Each variation
  189. // (if obj)
  190. // each
  191. // add class
  192. // (else)
  193. // add class
  194. // label = property
  195. // class = class
  196. // show html
  197. // end
  198. // end
  199. },
  200. element: function(koan, type, text, variation) {
  201. },
  202. variations: function($element, variations) {
  203. $.each(variations, function(name, variation){
  204. });
  205. },
  206. text: function($element, text) {
  207. $.each(text, function(selector, text) {
  208. $element.find(selector).text(text);
  209. });
  210. return $element;
  211. }
  212. },
  213. font: {
  214. increase: function() {
  215. var
  216. $container = $(this).parent().prev('.ui.segment'),
  217. fontSize = parseInt( $container.css('font-size'), 10)
  218. ;
  219. $container
  220. .css('font-size', fontSize + 1)
  221. ;
  222. },
  223. decrease: function() {
  224. var
  225. $container = $(this).parent().prev('.ui.segment'),
  226. fontSize = parseInt( $container.css('font-size'), 10)
  227. ;
  228. $container
  229. .css('font-size', fontSize - 1)
  230. ;
  231. }
  232. },
  233. overviewMode: function() {
  234. var
  235. $button = $(this),
  236. $body = $('body'),
  237. $example = $('.example')
  238. ;
  239. $body.toggleClass('overview');
  240. $button.toggleClass('active');
  241. if($body.hasClass('overview')) {
  242. $developer.addClass('disabled').popup('destroy');
  243. $designer.addClass('disabled').popup('destroy');
  244. $example.each(function() {
  245. $(this).children().not('.ui.header:eq(0), .example p:eq(0), .annotation').hide();
  246. });
  247. $example.filter('.another').hide();
  248. }
  249. else {
  250. $developer.removeClass('disabled').popup();
  251. $designer.removeClass('disabled').popup();
  252. $example.each(function() {
  253. $(this).children().not('.ui.header:eq(0), .example p:eq(0), .annotation').show();
  254. });
  255. $example.filter('.another').show();
  256. }
  257. },
  258. developerMode: function() {
  259. var
  260. $example = $('.example').not('.no')
  261. ;
  262. $developer.addClass('active');
  263. $designer.removeClass('active');
  264. $example
  265. .each(function() {
  266. $.proxy(handler.createCode, $(this))('developer');
  267. })
  268. ;
  269. },
  270. designerMode: function() {
  271. var
  272. $example = $('.example').not('.no')
  273. ;
  274. $designer.addClass('active');
  275. $developer.removeClass('active');
  276. $example
  277. .each(function() {
  278. $.proxy(handler.createCode, $(this))('designer');
  279. })
  280. ;
  281. },
  282. getIndent: function(text) {
  283. var
  284. lines = text.split("\n"),
  285. firstLine = (lines[0] === '')
  286. ? lines[1]
  287. : lines[0],
  288. spacesPerIndent = 2,
  289. leadingSpaces = firstLine.length - firstLine.replace(/^\s*/g, '').length,
  290. indent
  291. ;
  292. if(leadingSpaces !== 0) {
  293. indent = leadingSpaces;
  294. }
  295. else {
  296. // string has already been trimmed, get first indented line and subtract 2
  297. $.each(lines, function(index, line) {
  298. leadingSpaces = line.length - line.replace(/^\s*/g, '').length;
  299. if(leadingSpaces !== 0) {
  300. indent = leadingSpaces - spacesPerIndent;
  301. return false;
  302. }
  303. });
  304. }
  305. return indent || 4;
  306. },
  307. generateCode: function() {
  308. var
  309. $example = $(this).closest('.example'),
  310. $annotation = $example.find('.annotation'),
  311. $code = $annotation.find('.code'),
  312. $header = $example.not('.another').children('.ui.header:first-of-type').eq(0).add('p:first-of-type'),
  313. $demo = $example.children().not($header).not('i.code:first-child, .code, .instructive, .language.label, .annotation, br, .ignore, .ignored'),
  314. code = ''
  315. ;
  316. if( $code.size() === 0) {
  317. $demo
  318. .each(function(){
  319. var $this = $(this).clone(false);
  320. if($this.not('br')) {
  321. code += $this.removeAttr('style').get(0).outerHTML + "\n";
  322. }
  323. })
  324. ;
  325. }
  326. $example.data('code', code);
  327. return code;
  328. },
  329. createCode: function(type) {
  330. var
  331. $example = $(this).closest('.example'),
  332. $header = $example.children('.ui.header:first-of-type').eq(0).add('p:first-of-type'),
  333. $annotation = $example.find('.annotation'),
  334. $code = $annotation.find('.code'),
  335. $demo = $example.children().not($header).not('.ui.popup, i.code:first-child, .code, .instructive, .language.label, .annotation, br, .ignore, .ignored'),
  336. code = $example.data('code') || $.proxy(handler.generateCode, this)()
  337. ;
  338. if( $code.hasClass('existing') ) {
  339. $annotation.show();
  340. $code.removeClass('existing');
  341. $.proxy(handler.initializeCode, $code)();
  342. }
  343. if($annotation.size() === 0) {
  344. $annotation = $('<div/>')
  345. .addClass('annotation')
  346. .appendTo($example)
  347. ;
  348. }
  349. if( $example.find('.ace_editor').size() === 0) {
  350. $code = $('<div/>')
  351. .data('type', 'html')
  352. .addClass('code')
  353. .html(code)
  354. .hide()
  355. .appendTo($annotation)
  356. ;
  357. $.proxy(handler.initializeCode, $code)();
  358. }
  359. if( ($demo.first().is(':visible') || type == 'developer') && type != 'designer' ) {
  360. $demo.hide();
  361. $header.show();
  362. $annotation.fadeIn(500);
  363. }
  364. else {
  365. $annotation.hide();
  366. if($demo.size() > 1) {
  367. $demo.show();
  368. }
  369. else {
  370. $demo.fadeIn(500);
  371. }
  372. }
  373. },
  374. createAnnotation: function() {
  375. if(!$(this).data('type')) {
  376. $(this).data('type', 'html');
  377. }
  378. $(this)
  379. .wrap('<div class="annotation">')
  380. .parent()
  381. .hide()
  382. ;
  383. },
  384. resizeCode: function() {
  385. $('.ace_editor')
  386. .each(function() {
  387. var
  388. $code = $(this),
  389. padding = 20,
  390. editor,
  391. editorSession,
  392. codeHeight
  393. ;
  394. $code.css('height', 'auto');
  395. editor = ace.edit($code[0]);
  396. editorSession = editor.getSession();
  397. codeHeight = editorSession.getScreenLength() * editor.renderer.lineHeight + padding;
  398. $code.css('height', codeHeight);
  399. editor.resize();
  400. })
  401. ;
  402. },
  403. makeCode: function() {
  404. if(window.ace !== undefined) {
  405. $code
  406. .filter(':visible')
  407. .each(handler.initializeCode)
  408. ;
  409. $existingCode
  410. .each(handler.createAnnotation)
  411. ;
  412. }
  413. },
  414. makeStickyColumns: function() {
  415. var
  416. $visibleStuck = $(this).find('.fixed.column > .image, .fixed.column > .content'),
  417. isInitialized = ($visibleStuck.parent('.sticky-wrapper').size() !== 0)
  418. ;
  419. if(!isInitialized) {
  420. $visibleStuck
  421. .waypoint('sticky', {
  422. offset : 65,
  423. stuckClass : 'fixed'
  424. })
  425. ;
  426. }
  427. // apparently this doesnt refresh on first hit
  428. $.waypoints('refresh');
  429. $.waypoints('refresh');
  430. },
  431. initializeCode: function() {
  432. var
  433. $code = $(this).show(),
  434. code = $code.html(),
  435. existingCode = $code.hasClass('existing'),
  436. contentType = $code.data('type') || 'javascript',
  437. title = $code.data('title') || false,
  438. demo = $code.data('demo') || false,
  439. preview = $code.data('preview') || false,
  440. label = $code.data('label') || false,
  441. displayType = {
  442. html : 'HTML',
  443. javascript : 'Javascript',
  444. css : 'CSS',
  445. text : 'Command Line',
  446. sh : 'Command Line'
  447. },
  448. indent = handler.getIndent(code) || 4,
  449. padding = 20,
  450. whiteSpace,
  451. $label,
  452. editor,
  453. editorSession,
  454. codeHeight
  455. ;
  456. // trim whitespace
  457. whiteSpace = new RegExp('\\n\\s{' + indent + '}', 'g');
  458. code = $.trim(code).replace(whiteSpace, '\n');
  459. if(contentType == 'html') {
  460. $code.text(code);
  461. }
  462. else {
  463. $code.html(code);
  464. }
  465. // evaluate if specified
  466. if($code.hasClass('evaluated')) {
  467. eval(code);
  468. }
  469. // initialize
  470. editor = ace.edit($code[0]);
  471. editorSession = editor.getSession();
  472. editor.setTheme('ace/theme/github');
  473. editor.setShowPrintMargin(false);
  474. editor.setReadOnly(true);
  475. editor.renderer.setShowGutter(false);
  476. editor.setHighlightActiveLine(false);
  477. editorSession.setMode('ace/mode/'+ contentType);
  478. editorSession.setUseWrapMode(true);
  479. editorSession.setTabSize(2);
  480. editorSession.setUseSoftTabs(true);
  481. codeHeight = editorSession.getScreenLength() * editor.renderer.lineHeight + padding;
  482. $(this)
  483. .height(codeHeight + 'px')
  484. .wrap('<div class="ui instructive segment">')
  485. ;
  486. // add label
  487. if(title) {
  488. $('<div>')
  489. .addClass('ui attached top label')
  490. .html('<span class="title">' + title + '</span>' + '<em>' + (displayType[contentType] || contentType) + '</em>')
  491. .prependTo( $(this).parent() )
  492. ;
  493. }
  494. if(label) {
  495. $('<div>')
  496. .addClass('ui pointing below label')
  497. .html(displayType[contentType] || contentType)
  498. .insertBefore ( $(this).parent() )
  499. ;
  500. }
  501. // add run code button
  502. if(demo) {
  503. $('<a>')
  504. .addClass('ui pointing below black label')
  505. .html('Run Code')
  506. .on('click', function() {
  507. eval(code);
  508. })
  509. .insertBefore ( $(this).parent() )
  510. ;
  511. }
  512. // add preview if specified
  513. if(preview) {
  514. $(code)
  515. .insertAfter( $(this).parent() )
  516. ;
  517. }
  518. editor.resize();
  519. },
  520. movePeek: function() {
  521. if( $('.stuck .peek').size() > 0 ) {
  522. $('.peek')
  523. .toggleClass('pushed')
  524. ;
  525. }
  526. else {
  527. $('.peek')
  528. .removeClass('pushed')
  529. ;
  530. }
  531. },
  532. menu: {
  533. mouseenter: function() {
  534. $(this)
  535. .stop()
  536. .animate({
  537. width: '135px'
  538. }, 300, function() {
  539. $(this).find('.text').show();
  540. })
  541. ;
  542. },
  543. mouseleave: function(event) {
  544. $(this).find('.text').hide();
  545. $(this)
  546. .stop()
  547. .animate({
  548. width: '60px'
  549. }, 300)
  550. ;
  551. }
  552. },
  553. peek: function() {
  554. var
  555. $body = $('html, body'),
  556. $header = $(this),
  557. $menu = $header.parent(),
  558. $group = $menu.children(),
  559. $headers = $group.add( $group.find('.menu .item') ),
  560. $waypoint = $waypoints.eq( $group.index( $header ) ),
  561. offset
  562. ;
  563. offset = $waypoint.offset().top - 70;
  564. if(!$header.hasClass('active') ) {
  565. $menu
  566. .addClass('animating')
  567. ;
  568. $headers
  569. .removeClass('active')
  570. ;
  571. $body
  572. .stop()
  573. .one('scroll', function() {
  574. $body.stop();
  575. })
  576. .animate({
  577. scrollTop: offset
  578. }, 500)
  579. .promise()
  580. .done(function() {
  581. $menu
  582. .removeClass('animating')
  583. ;
  584. $headers
  585. .removeClass('active')
  586. ;
  587. $header
  588. .addClass('active')
  589. ;
  590. $waypoint
  591. .css('color', $header.css('border-right-color'))
  592. ;
  593. $waypoints
  594. .removeAttr('style')
  595. ;
  596. })
  597. ;
  598. }
  599. },
  600. peekSub: function() {
  601. var
  602. $body = $('html, body'),
  603. $subHeader = $(this),
  604. $header = $subHeader.parents('.item'),
  605. $menu = $header.parent(),
  606. $subHeaderGroup = $header.find('.item'),
  607. $headerGroup = $menu.children(),
  608. $waypoint = $('h2').eq( $headerGroup.index( $header ) ),
  609. $subWaypoint = $waypoint.nextAll('h3').eq( $subHeaderGroup.index($subHeader) ),
  610. offset = $subWaypoint.offset().top - 80
  611. ;
  612. $menu
  613. .addClass('animating')
  614. ;
  615. $headerGroup
  616. .removeClass('active')
  617. ;
  618. $subHeaderGroup
  619. .removeClass('active')
  620. ;
  621. $body
  622. .stop()
  623. .animate({
  624. scrollTop: offset
  625. }, 500, function() {
  626. $menu
  627. .removeClass('animating')
  628. ;
  629. $subHeader
  630. .addClass('active')
  631. ;
  632. })
  633. .one('scroll', function() {
  634. $body.stop();
  635. })
  636. ;
  637. },
  638. swapStyle: function() {
  639. var
  640. theme = $(this).data('theme')
  641. ;
  642. $(this)
  643. .addClass('active')
  644. .siblings()
  645. .removeClass('active')
  646. ;
  647. $('head link.ui')
  648. .each(function() {
  649. var
  650. href = $(this).attr('href'),
  651. subDirectory = href.split('/')[3],
  652. newLink = href.replace(subDirectory, theme)
  653. ;
  654. $(this)
  655. .attr('href', newLink)
  656. ;
  657. })
  658. ;
  659. }
  660. };
  661. $('.masthead')
  662. .visibility({
  663. once: false
  664. })
  665. .visibility('bottom visible', function(){
  666. $('.main.menu').removeClass('filled');
  667. })
  668. .visibility('bottom passed', function(){
  669. $('.main.menu').addClass('filled');
  670. })
  671. .find('.button')
  672. .popup({
  673. position : 'top center',
  674. variation : 'inverted'
  675. })
  676. ;
  677. $(window)
  678. .on('resize', function() {
  679. clearTimeout(handler.timer);
  680. handler.timer = setTimeout(handler.resizeCode, 100);
  681. })
  682. ;
  683. $downloadDropdown
  684. .dropdown({
  685. on : 'click',
  686. transition : 'scale'
  687. })
  688. ;
  689. // attach events
  690. if($.fn.tablesort !== undefined) {
  691. $sortTable
  692. .tablesort()
  693. ;
  694. }
  695. if( $pageTabs.size() > 0 ) {
  696. $pageTabs
  697. .tab({
  698. context : '.main.container',
  699. childrenOnly : true,
  700. history : true,
  701. onTabInit : handler.makeCode,
  702. onTabLoad : function() {
  703. $.proxy(handler.makeStickyColumns, this)();
  704. $peekItem.removeClass('active').first().addClass('active');
  705. }
  706. })
  707. ;
  708. }
  709. else {
  710. handler.makeCode();
  711. }
  712. handler.createIcon();
  713. $example
  714. .one('mousemove', handler.generateCode)
  715. .find('i.code')
  716. .on('click', handler.createCode)
  717. ;
  718. $themeDropdown
  719. .dropdown({
  720. action: 'select',
  721. onChange: handler.less.changeTheme
  722. })
  723. ;
  724. $shownExample
  725. .each(handler.createCode)
  726. ;
  727. $helpPopup
  728. .popup()
  729. ;
  730. $swap
  731. .on('click', handler.swapStyle)
  732. ;
  733. $increaseFont
  734. .on('click', handler.font.increase)
  735. ;
  736. $decreaseFont
  737. .on('click', handler.font.decrease)
  738. ;
  739. $developer
  740. .on('click', handler.developerMode)
  741. ;
  742. $designer
  743. .on('click', handler.designerMode)
  744. ;
  745. $overview
  746. .on('click', handler.overviewMode)
  747. ;
  748. $menuPopup
  749. .popup({
  750. position : 'bottom center',
  751. className: {
  752. popup: 'ui popup'
  753. }
  754. })
  755. ;
  756. $sortableTables
  757. .tablesort()
  758. ;
  759. $menuDropdown
  760. .dropdown({
  761. on : 'hover',
  762. action : 'nothing'
  763. })
  764. ;
  765. $sidebarButton
  766. .on('mouseenter', handler.menu.mouseenter)
  767. .on('mouseleave', handler.menu.mouseleave)
  768. ;
  769. $menu
  770. .sidebar({
  771. animation: 'scale down'
  772. })
  773. .sidebar('attach events', '.launch.button, .view-ui.button, .launch.item')
  774. .sidebar('attach events', $hideMenu, 'hide')
  775. ;
  776. $waypoints
  777. .waypoint({
  778. continuous : false,
  779. offset : 100,
  780. handler : function(direction) {
  781. var
  782. index = (direction == 'down')
  783. ? $waypoints.index(this)
  784. : ($waypoints.index(this) - 1 >= 0)
  785. ? ($waypoints.index(this) - 1)
  786. : 0
  787. ;
  788. $peekItem
  789. .removeClass('active')
  790. .eq( index )
  791. .addClass('active')
  792. ;
  793. }
  794. })
  795. ;
  796. /* $('body')
  797. .waypoint({
  798. handler: function(direction) {
  799. if(direction == 'down') {
  800. if( !$('body').is(':animated') ) {
  801. $peekItem
  802. .removeClass('active')
  803. .eq( $peekItem.size() - 1 )
  804. .addClass('active')
  805. ;
  806. }
  807. }
  808. },
  809. offset: 'bottom-in-view'
  810. })
  811. ;*/
  812. $peek
  813. .waypoint('sticky', {
  814. offset : 85,
  815. stuckClass : 'stuck'
  816. })
  817. ;
  818. $peekItem
  819. .on('click', handler.peek)
  820. ;
  821. $peekSubItem
  822. .on('click', handler.peekSub)
  823. ;
  824. };
  825. // attach ready event
  826. $(document)
  827. .ready(semantic.ready)
  828. ;