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.

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