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.

748 lines
18 KiB

  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. $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. $waypoints = $peek.closest('.tab, .container').find('h2').first().siblings('h2').addBack(),
  36. $menuPopup = $('.ui.main.menu .popup.item'),
  37. $menuDropdown = $('.ui.main.menu .dropdown'),
  38. $pageTabs = $('.tab.segment .tabular.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 = $('.attached.launch.button'),
  47. $increaseFont = $('.font .increase'),
  48. $decreaseFont = $('.font .decrease'),
  49. $code = $('div.code').not('.existing'),
  50. $existingCode = $('.existing.code'),
  51. // alias
  52. handler
  53. ;
  54. // event handlers
  55. handler = {
  56. createIcon: function() {
  57. $example
  58. .each(function(){
  59. $('<i/>')
  60. .addClass('icon code')
  61. .prependTo( $(this) )
  62. ;
  63. })
  64. ;
  65. },
  66. getSpecification: function(callback) {
  67. var
  68. url = $(this).data('url') || false
  69. ;
  70. callback = callback || function(){};
  71. if(url) {
  72. $.ajax({
  73. method: 'get',
  74. url: url,
  75. type: 'json',
  76. complete: callback
  77. });
  78. }
  79. },
  80. create: {
  81. tick: function() {
  82. },
  83. examples: function(json) {
  84. var
  85. types = json['Types'],
  86. text = json['Text'],
  87. states = json['States'],
  88. variations = json['Variations'],
  89. $element,
  90. html
  91. ;
  92. $.each(types, function(name, type){
  93. html += '<h2 class="ui dividing header">' + name + '</h2';
  94. if($.isPlainObject(type)) {
  95. $.each(type, function(name, subType) {
  96. $element = $.zc(subType);
  97. $element = handler.create.text($element, text);
  98. html += '<h3 class="ui header">' + name + '</h3';
  99. html += handler.create.variations($element, variations);
  100. });
  101. }
  102. else {
  103. $element = $.zc(type);
  104. $element = handler.create.text($element);
  105. html += handler.create.variations($element, variations);
  106. }
  107. });
  108. // Each TYPE
  109. // show type name
  110. // html = koan (html)
  111. // each text
  112. // find label
  113. // if(obj)
  114. // replace random text
  115. // else
  116. // replace text
  117. // end
  118. // Each variation
  119. // (if obj)
  120. // each
  121. // add class
  122. // (else)
  123. // add class
  124. // label = property
  125. // class = class
  126. // show html
  127. // end
  128. // end
  129. },
  130. element: function(koan, type, text, variation) {
  131. },
  132. variations: function($element, variations) {
  133. $.each(variations, function(name, variation){
  134. });
  135. },
  136. text: function($element, text) {
  137. $.each(text, function(selector, text) {
  138. $element.find(selector).text(text);
  139. });
  140. return $element;
  141. }
  142. },
  143. font: {
  144. increase: function() {
  145. var
  146. $container = $(this).parent().prev('.ui.segment'),
  147. fontSize = parseInt( $container.css('font-size'), 10)
  148. ;
  149. $container
  150. .css('font-size', fontSize + 1)
  151. ;
  152. },
  153. decrease: function() {
  154. var
  155. $container = $(this).parent().prev('.ui.segment'),
  156. fontSize = parseInt( $container.css('font-size'), 10)
  157. ;
  158. $container
  159. .css('font-size', fontSize - 1)
  160. ;
  161. }
  162. },
  163. overviewMode: function() {
  164. var
  165. $button = $(this),
  166. $body = $('body'),
  167. $example = $('.example')
  168. ;
  169. $body.toggleClass('overview');
  170. $button.toggleClass('active');
  171. if($body.hasClass('overview')) {
  172. $developer.addClass('disabled').popup('destroy');
  173. $designer.addClass('disabled').popup('destroy');
  174. $example.each(function() {
  175. $(this).children().not('.ui.header:eq(0), .example p:eq(0), .annotation').hide();
  176. });
  177. $example.filter('.another').hide();
  178. }
  179. else {
  180. $developer.removeClass('disabled').popup();
  181. $designer.removeClass('disabled').popup();
  182. $example.each(function() {
  183. $(this).children().not('.ui.header:eq(0), .example p:eq(0), .annotation').show();
  184. });
  185. $example.filter('.another').show();
  186. }
  187. },
  188. developerMode: function() {
  189. var
  190. $example = $('.example').not('.no')
  191. ;
  192. $developer.addClass('active');
  193. $designer.removeClass('active');
  194. $example
  195. .each(function() {
  196. $.proxy(handler.createCode, $(this))('developer');
  197. })
  198. ;
  199. },
  200. designerMode: function() {
  201. var
  202. $example = $('.example').not('.no')
  203. ;
  204. $designer.addClass('active');
  205. $developer.removeClass('active');
  206. $example
  207. .each(function() {
  208. $.proxy(handler.createCode, $(this))('designer');
  209. })
  210. ;
  211. },
  212. generateCode: function() {
  213. var
  214. $example = $(this).closest('.example'),
  215. $annotation = $example.find('.annotation'),
  216. $code = $annotation.find('.code'),
  217. $header = $example.children('.ui.header:first-of-type').eq(0).add('p:first-of-type'),
  218. $demo = $example.children().not($header).not('i.code:first-child, .code, .instructive, .language.label, .annotation, br, .ignore, .ignored'),
  219. whiteSpace = new RegExp('\\n\\s{4}', 'g'),
  220. code = ''
  221. ;
  222. if( $code.size() === 0) {
  223. $demo
  224. .each(function(){
  225. var $this = $(this).clone(false);
  226. if($this.not('br')) {
  227. code += $this.removeAttr('style').get(0).outerHTML + "\n";
  228. }
  229. })
  230. ;
  231. }
  232. $example.data('code', code);
  233. return code;
  234. },
  235. createCode: function(type) {
  236. var
  237. $example = $(this).closest('.example'),
  238. $header = $example.children('.ui.header:first-of-type').eq(0).add('p:first-of-type'),
  239. $annotation = $example.find('.annotation'),
  240. $code = $annotation.find('.code'),
  241. $demo = $example.children().not($header).not('i.code:first-child, .code, .instructive, .language.label, .annotation, br, .ignore, .ignored'),
  242. code = $example.data('code') || $.proxy(handler.generateCode, this)()
  243. ;
  244. if( $code.hasClass('existing') ) {
  245. $annotation.show();
  246. $code.removeClass('existing');
  247. $.proxy(handler.initializeCode, $code)();
  248. }
  249. if($annotation.size() === 0) {
  250. $annotation = $('<div/>')
  251. .addClass('annotation')
  252. .appendTo($example)
  253. ;
  254. }
  255. if( $example.find('.ace_editor').size() === 0) {
  256. $code = $('<div/>')
  257. .data('type', 'html')
  258. .addClass('code')
  259. .html(code)
  260. .hide()
  261. .appendTo($annotation)
  262. ;
  263. $.proxy(handler.initializeCode, $code)();
  264. }
  265. if( ($demo.first().is(':visible') || type == 'developer') && type != 'designer' ) {
  266. $demo.hide();
  267. $header.show();
  268. $annotation.fadeIn(500);
  269. }
  270. else {
  271. $annotation.hide();
  272. if($demo.size() > 1) {
  273. $demo.show();
  274. }
  275. else {
  276. $demo.fadeIn(500);
  277. }
  278. }
  279. },
  280. createAnnotation: function() {
  281. if(!$(this).data('type')) {
  282. $(this).data('type', 'html');
  283. }
  284. $(this)
  285. .wrap('<div class="annotation">')
  286. .parent()
  287. .hide()
  288. ;
  289. },
  290. resizeCode: function() {
  291. $('.ace_editor')
  292. .each(function() {
  293. var
  294. $code = $(this),
  295. padding = 20,
  296. editor,
  297. editorSession,
  298. codeHeight
  299. ;
  300. $code.css('height', 'auto');
  301. editor = ace.edit($code[0]);
  302. editorSession = editor.getSession();
  303. codeHeight = editorSession.getScreenLength() * editor.renderer.lineHeight + padding;
  304. $code.css('height', codeHeight);
  305. editor.resize();
  306. })
  307. ;
  308. },
  309. makeCode: function() {
  310. if(window.ace !== undefined) {
  311. $code
  312. .filter(':visible')
  313. .each(handler.initializeCode)
  314. ;
  315. $existingCode
  316. .filter(':visible')
  317. .each(handler.createAnnotation)
  318. ;
  319. }
  320. },
  321. initializeCode: function() {
  322. var
  323. $code = $(this).show(),
  324. code = $code.html(),
  325. existingCode = $code.hasClass('existing'),
  326. contentType = $code.data('type') || 'javascript',
  327. title = $code.data('title') || false,
  328. demo = $code.data('demo') || false,
  329. preview = $code.data('preview') || false,
  330. label = $code.data('label') || false,
  331. displayType = {
  332. html : 'HTML',
  333. javascript : 'Javascript',
  334. css : 'CSS',
  335. text : 'Command Line',
  336. sh : 'Command Line'
  337. },
  338. whiteSpace = new RegExp('\\n\\s{4}', 'g'),
  339. $label,
  340. padding = 20,
  341. editor,
  342. editorSession,
  343. codeHeight
  344. ;
  345. // trim whitespace
  346. code = $.trim(code.replace(whiteSpace, '\n'));
  347. if(contentType == 'html') {
  348. $code.text(code);
  349. }
  350. else {
  351. $code.html(code);
  352. }
  353. // evaluate if specified
  354. if($code.hasClass('evaluated')) {
  355. eval(code);
  356. }
  357. // initialize
  358. editor = ace.edit($code[0]);
  359. editorSession = editor.getSession();
  360. editor.setTheme('ace/theme/github');
  361. editor.setShowPrintMargin(false);
  362. editor.setReadOnly(true);
  363. editor.renderer.setShowGutter(false);
  364. editor.setHighlightActiveLine(false);
  365. editorSession.setMode('ace/mode/'+ contentType);
  366. editorSession.setUseWrapMode(true);
  367. editorSession.setTabSize(2);
  368. editorSession.setUseSoftTabs(true);
  369. codeHeight = editorSession.getScreenLength() * editor.renderer.lineHeight + padding;
  370. $(this)
  371. .height(codeHeight + 'px')
  372. .wrap('<div class="ui instructive segment">')
  373. ;
  374. // add label
  375. if(title) {
  376. $('<div>')
  377. .addClass('ui attached top label')
  378. .html('<span class="title">' + title + '</span>' + '<em>' + (displayType[contentType] || contentType) + '</em>')
  379. .prependTo( $(this).parent() )
  380. ;
  381. }
  382. if(label) {
  383. $('<div>')
  384. .addClass('ui pointing below label')
  385. .html(displayType[contentType] || contentType)
  386. .insertBefore ( $(this).parent() )
  387. ;
  388. }
  389. // add run code button
  390. if(demo) {
  391. $('<a>')
  392. .addClass('ui pointing below black label')
  393. .html('Run Code')
  394. .on('click', function() {
  395. eval(code);
  396. })
  397. .insertBefore ( $(this).parent() )
  398. ;
  399. }
  400. // add preview if specified
  401. if(preview) {
  402. $(code)
  403. .insertAfter( $(this).parent() )
  404. ;
  405. }
  406. editor.resize();
  407. },
  408. movePeek: function() {
  409. if( $('.stuck .peek').size() > 0 ) {
  410. $('.peek')
  411. .toggleClass('pushed')
  412. ;
  413. }
  414. else {
  415. $('.peek')
  416. .removeClass('pushed')
  417. ;
  418. }
  419. },
  420. menu: {
  421. mouseenter: function() {
  422. $(this)
  423. .stop()
  424. .animate({
  425. width: '155px'
  426. }, 300, function() {
  427. $(this).find('.text').show();
  428. })
  429. ;
  430. },
  431. mouseleave: function(event) {
  432. $(this).find('.text').hide();
  433. $(this)
  434. .stop()
  435. .animate({
  436. width: '70px'
  437. }, 300)
  438. ;
  439. }
  440. },
  441. peek: function() {
  442. var
  443. $body = $('html, body'),
  444. $header = $(this),
  445. $menu = $header.parent(),
  446. $group = $menu.children(),
  447. $headers = $group.add( $group.find('.menu .item') ),
  448. $waypoint = $waypoints.eq( $group.index( $header ) ),
  449. offset
  450. ;
  451. offset = $waypoint.offset().top - 70;
  452. if(!$header.hasClass('active') ) {
  453. $menu
  454. .addClass('animating')
  455. ;
  456. $headers
  457. .removeClass('active')
  458. ;
  459. $body
  460. .stop()
  461. .one('scroll', function() {
  462. $body.stop();
  463. })
  464. .animate({
  465. scrollTop: offset
  466. }, 500)
  467. .promise()
  468. .done(function() {
  469. $menu
  470. .removeClass('animating')
  471. ;
  472. $headers
  473. .removeClass('active')
  474. ;
  475. $header
  476. .addClass('active')
  477. ;
  478. $waypoint
  479. .css('color', $header.css('border-right-color'))
  480. ;
  481. $waypoints
  482. .removeAttr('style')
  483. ;
  484. })
  485. ;
  486. }
  487. },
  488. peekSub: function() {
  489. var
  490. $body = $('html, body'),
  491. $subHeader = $(this),
  492. $header = $subHeader.parents('.item'),
  493. $menu = $header.parent(),
  494. $subHeaderGroup = $header.find('.item'),
  495. $headerGroup = $menu.children(),
  496. $waypoint = $('h2').eq( $headerGroup.index( $header ) ),
  497. $subWaypoint = $waypoint.nextAll('h3').eq( $subHeaderGroup.index($subHeader) ),
  498. offset = $subWaypoint.offset().top - 80
  499. ;
  500. $menu
  501. .addClass('animating')
  502. ;
  503. $headerGroup
  504. .removeClass('active')
  505. ;
  506. $subHeaderGroup
  507. .removeClass('active')
  508. ;
  509. $body
  510. .stop()
  511. .animate({
  512. scrollTop: offset
  513. }, 500, function() {
  514. $menu
  515. .removeClass('animating')
  516. ;
  517. $subHeader
  518. .addClass('active')
  519. ;
  520. })
  521. .one('scroll', function() {
  522. $body.stop();
  523. })
  524. ;
  525. },
  526. swapStyle: function() {
  527. var
  528. theme = $(this).data('theme')
  529. ;
  530. $(this)
  531. .addClass('active')
  532. .siblings()
  533. .removeClass('active')
  534. ;
  535. $('head link.ui')
  536. .each(function() {
  537. var
  538. href = $(this).attr('href'),
  539. subDirectory = href.split('/')[3],
  540. newLink = href.replace(subDirectory, theme)
  541. ;
  542. $(this)
  543. .attr('href', newLink)
  544. ;
  545. })
  546. ;
  547. }
  548. };
  549. $(window)
  550. .on('resize', function() {
  551. clearTimeout(handler.timer);
  552. handler.timer = setTimeout(handler.resizeCode, 100);
  553. })
  554. ;
  555. $downloadDropdown
  556. .dropdown({
  557. on : 'click',
  558. transition : 'scale'
  559. })
  560. ;
  561. // attach events
  562. if($.fn.tablesort !== undefined) {
  563. $sortTable
  564. .tablesort()
  565. ;
  566. }
  567. if( $pageTabs.size() > 0 ) {
  568. $pageTabs
  569. .tab({
  570. history: false,
  571. onTabInit: handler.makeCode
  572. })
  573. ;
  574. }
  575. else {
  576. handler.makeCode();
  577. }
  578. handler.createIcon();
  579. $example
  580. .one('mousemove', handler.generateCode)
  581. .find('i.code')
  582. .on('click', handler.createCode)
  583. ;
  584. $shownExample
  585. .each(handler.createCode)
  586. ;
  587. $helpPopup
  588. .popup()
  589. ;
  590. $swap
  591. .on('click', handler.swapStyle)
  592. ;
  593. $increaseFont
  594. .on('click', handler.font.increase)
  595. ;
  596. $decreaseFont
  597. .on('click', handler.font.decrease)
  598. ;
  599. $developer
  600. .on('click', handler.developerMode)
  601. ;
  602. $designer
  603. .on('click', handler.designerMode)
  604. ;
  605. $overview
  606. .on('click', handler.overviewMode)
  607. ;
  608. $menuPopup
  609. .popup({
  610. position : 'bottom center',
  611. className: {
  612. popup: 'ui popup'
  613. }
  614. })
  615. ;
  616. $menuDropdown
  617. .dropdown({
  618. on : 'hover',
  619. action : 'nothing'
  620. })
  621. ;
  622. $sidebarButton
  623. .on('mouseenter', handler.menu.mouseenter)
  624. .on('mouseleave', handler.menu.mouseleave)
  625. ;
  626. $menu
  627. .sidebar('attach events', '.launch.button, .launch.item')
  628. .sidebar('attach events', $hideMenu, 'hide')
  629. ;
  630. $waypoints
  631. .waypoint({
  632. continuous : false,
  633. offset : 100,
  634. handler : function(direction) {
  635. var
  636. index = (direction == 'down')
  637. ? $waypoints.index(this)
  638. : ($waypoints.index(this) - 1 >= 0)
  639. ? ($waypoints.index(this) - 1)
  640. : 0
  641. ;
  642. $peekItem
  643. .removeClass('active')
  644. .eq( index )
  645. .addClass('active')
  646. ;
  647. }
  648. })
  649. ;
  650. $('body')
  651. .waypoint({
  652. handler: function(direction) {
  653. if(direction == 'down') {
  654. if( !$('body').is(':animated') ) {
  655. $peekItem
  656. .removeClass('active')
  657. .eq( $peekItem.size() - 1 )
  658. .addClass('active')
  659. ;
  660. }
  661. }
  662. },
  663. offset: 'bottom-in-view'
  664. })
  665. ;
  666. $peek
  667. .waypoint('sticky', {
  668. offset : 85,
  669. stuckClass : 'stuck'
  670. })
  671. ;
  672. $peekItem
  673. .on('click', handler.peek)
  674. ;
  675. $peekSubItem
  676. .on('click', handler.peekSub)
  677. ;
  678. };
  679. // attach ready event
  680. $(document)
  681. .ready(semantic.ready)
  682. ;