crayon.js 39 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054
  1. // Crayon Syntax Highlighter JavaScript
  2. (function ($) {
  3. // BEGIN AUXILIARY FUNCTIONS
  4. $.fn.exists = function () {
  5. return this.length !== 0;
  6. };
  7. $.fn.style = function (styleName, value, priority) {
  8. // DOM node
  9. var node = this.get(0);
  10. // Ensure we have a DOM node
  11. if (typeof node == 'undefined') {
  12. return;
  13. }
  14. // CSSStyleDeclaration
  15. var style = node.style;
  16. // Getter/Setter
  17. if (typeof styleName != 'undefined') {
  18. if (typeof value != 'undefined') {
  19. // Set style property
  20. var priority = typeof priority != 'undefined' ? priority : '';
  21. if (typeof style.setProperty != 'undefined') {
  22. style.setProperty(styleName, value, priority);
  23. } else {
  24. style.styleName = value + ' ' + priority;
  25. }
  26. } else {
  27. // Get style property
  28. return style.styleName;
  29. }
  30. } else {
  31. // Get CSSStyleDeclaration
  32. return style;
  33. }
  34. };
  35. // END AUXILIARY FUNCTIONS
  36. var PRESSED = 'crayon-pressed';
  37. var UNPRESSED = '';
  38. var CRAYON_SYNTAX = 'div.crayon-syntax';
  39. var CRAYON_TOOLBAR = '.crayon-toolbar';
  40. var CRAYON_INFO = '.crayon-info';
  41. var CRAYON_PLAIN = '.crayon-plain';
  42. var CRAYON_MAIN = '.crayon-main';
  43. var CRAYON_TABLE = '.crayon-table';
  44. var CRAYON_LOADING = '.crayon-loading';
  45. var CRAYON_CODE = '.crayon-code';
  46. var CRAYON_NUMS = '.crayon-nums';
  47. var CRAYON_NUM = '.crayon-num';
  48. var CRAYON_LINE = '.crayon-line';
  49. var CRAYON_WRAPPED = 'crayon-wrapped';
  50. var CRAYON_NUMS_CONTENT = '.crayon-nums-content';
  51. var CRAYON_NUMS_BUTTON = '.crayon-nums-button';
  52. var CRAYON_WRAP_BUTTON = '.crayon-wrap-button';
  53. var CRAYON_EXPAND_BUTTON = '.crayon-expand-button';
  54. var CRAYON_POPUP_BUTTON = '.crayon-popup-button';
  55. var CRAYON_COPY_BUTTON = '.crayon-copy-button';
  56. var CRAYON_PLAIN_BUTTON = '.crayon-plain-button';
  57. $(document).ready(function () {
  58. CrayonSyntax.init();
  59. });
  60. CrayonSyntax = new function () {
  61. var base = this;
  62. var crayon = new Object();
  63. var currUID = 0;
  64. base.init = function () {
  65. if (typeof crayon == 'undefined') {
  66. crayon = new Object();
  67. }
  68. $(CRAYON_SYNTAX).each(function () {
  69. base.process(this);
  70. });
  71. };
  72. base.process = function (c, replace) {
  73. c = $(c);
  74. var uid = c.attr('id');
  75. if (uid == 'crayon-') {
  76. // No ID, generate one
  77. uid += getUID();
  78. }
  79. c.attr('id', uid);
  80. console_log(uid);
  81. if (typeof replace == 'undefined') {
  82. replace = false;
  83. }
  84. if (!replace && !make_uid(uid)) {
  85. // Already a Crayon
  86. return;
  87. }
  88. var toolbar = c.find(CRAYON_TOOLBAR);
  89. var info = c.find(CRAYON_INFO);
  90. var plain = c.find(CRAYON_PLAIN);
  91. var main = c.find(CRAYON_MAIN);
  92. var table = c.find(CRAYON_TABLE);
  93. var code = c.find(CRAYON_CODE);
  94. var nums = c.find(CRAYON_NUMS);
  95. var nums_content = c.find(CRAYON_NUMS_CONTENT);
  96. var nums_button = c.find(CRAYON_NUMS_BUTTON);
  97. var wrap_button = c.find(CRAYON_WRAP_BUTTON);
  98. var expand_button = c.find(CRAYON_EXPAND_BUTTON);
  99. var popup_button = c.find(CRAYON_POPUP_BUTTON);
  100. var copy_button = c.find(CRAYON_COPY_BUTTON);
  101. var plain_button = c.find(CRAYON_PLAIN_BUTTON);
  102. crayon[uid] = c;
  103. crayon[uid].toolbar = toolbar;
  104. crayon[uid].plain = plain;
  105. crayon[uid].info = info;
  106. crayon[uid].main = main;
  107. crayon[uid].table = table;
  108. crayon[uid].code = code;
  109. crayon[uid].nums = nums;
  110. crayon[uid].nums_content = nums_content;
  111. crayon[uid].nums_button = nums_button;
  112. crayon[uid].wrap_button = wrap_button;
  113. crayon[uid].expand_button = expand_button;
  114. crayon[uid].popup_button = popup_button;
  115. crayon[uid].copy_button = copy_button;
  116. crayon[uid].plain_button = plain_button;
  117. crayon[uid].nums_visible = true;
  118. crayon[uid].wrapped = false;
  119. crayon[uid].plain_visible = false;
  120. crayon[uid].toolbar_delay = 0;
  121. crayon[uid].time = 1;
  122. // Set plain
  123. $(CRAYON_PLAIN).css('z-index', 0);
  124. // XXX Remember CSS dimensions
  125. var main_style = main.style();
  126. crayon[uid].main_style = {
  127. 'height': main_style && main_style.height || '',
  128. 'max-height': main_style && main_style.maxHeight || '',
  129. 'min-height': main_style && main_style.minHeight || '',
  130. 'width': main_style && main_style.width || '',
  131. 'max-width': main_style && main_style.maxWidth || '',
  132. 'min-width': main_style && main_style.minWidth || ''
  133. };
  134. var load_timer;
  135. var i = 0;
  136. crayon[uid].loading = true;
  137. crayon[uid].scroll_block_fix = false;
  138. // Register click events
  139. nums_button.click(function () {
  140. CrayonSyntax.toggle_nums(uid);
  141. });
  142. wrap_button.click(function () {
  143. CrayonSyntax.toggle_wrap(uid);
  144. });
  145. expand_button.click(function () {
  146. CrayonSyntax.toggle_expand(uid);
  147. });
  148. plain_button.click(function () {
  149. CrayonSyntax.toggle_plain(uid);
  150. });
  151. copy_button.click(function () {
  152. CrayonSyntax.copy_plain(uid);
  153. });
  154. // Enable retina if supported
  155. retina(uid);
  156. var load_func = function () {
  157. if (main.height() < 30) {
  158. crayon[uid].scroll_block_fix = true;
  159. }
  160. // If nums hidden by default
  161. if (nums.filter('[data-settings~="hide"]').length != 0) {
  162. nums_content.ready(function () {
  163. console_log('function' + uid);
  164. CrayonSyntax.toggle_nums(uid, true, true);
  165. });
  166. } else {
  167. update_nums_button(uid);
  168. }
  169. if (typeof crayon[uid].expanded == 'undefined') {
  170. // Determine if we should enable code expanding toggling
  171. if (Math.abs(crayon[uid].main.width() - crayon[uid].table.width()) < 10) {
  172. crayon[uid].expand_button.hide();
  173. } else {
  174. crayon[uid].expand_button.show();
  175. }
  176. }
  177. // TODO If width has changed or timeout, stop timer
  178. if (/*last_num_width != nums.width() ||*/ i == 5) {
  179. clearInterval(load_timer);
  180. //crayon[uid].removeClass(CRAYON_LOADING);
  181. crayon[uid].loading = false;
  182. }
  183. i++;
  184. };
  185. load_timer = setInterval(load_func, 300);
  186. fix_scroll_blank(uid);
  187. // Add ref to num for each line
  188. $(CRAYON_NUM, crayon[uid]).each(function () {
  189. var line_id = $(this).attr('data-line');
  190. var line = $('#' + line_id);
  191. var height = line.style('height');
  192. if (height) {
  193. line.attr('data-height', height);
  194. }
  195. });
  196. // Used for toggling
  197. main.css('position', 'relative');
  198. main.css('z-index', 1);
  199. // Disable certain features for touchscreen devices
  200. touchscreen = (c.filter('[data-settings~="touchscreen"]').length != 0);
  201. // Used to hide info
  202. if (!touchscreen) {
  203. main.click(function () {
  204. crayon_info(uid, '', false);
  205. });
  206. plain.click(function () {
  207. crayon_info(uid, '', false);
  208. });
  209. info.click(function () {
  210. crayon_info(uid, '', false);
  211. });
  212. }
  213. // Used for code popup
  214. if (c.filter('[data-settings~="no-popup"]').length == 0) {
  215. crayon[uid].popup_settings = popupWindow(popup_button, {
  216. height: screen.height - 200,
  217. width: screen.width - 100,
  218. top: 75,
  219. left: 50,
  220. scrollbars: 1,
  221. windowURL: '',
  222. data: '' // Data overrides URL
  223. }, function () {
  224. code_popup(uid);
  225. }, function () {
  226. //console_log('after');
  227. });
  228. }
  229. plain.css('opacity', 0);
  230. // If a toolbar with mouseover was found
  231. if (toolbar.filter('[data-settings~="mouseover"]').length != 0 && !touchscreen) {
  232. crayon[uid].toolbar_mouseover = true;
  233. toolbar.css('margin-top', '-' + toolbar.height() + 'px');
  234. toolbar.hide();
  235. // Overlay the toolbar if needed, only if doing so will not hide the
  236. // whole code!
  237. if (toolbar.filter('[data-settings~="overlay"]').length != 0
  238. && main.height() > toolbar.height() * 2) {
  239. toolbar.css('position', 'absolute');
  240. toolbar.css('z-index', 2);
  241. // Hide on single click when overlayed
  242. if (toolbar.filter('[data-settings~="hide"]').length != 0) {
  243. main.click(function () {
  244. toolbar_toggle(uid, undefined, undefined, 0);
  245. });
  246. plain.click(function () {
  247. toolbar_toggle(uid, false, undefined, 0);
  248. });
  249. }
  250. } else {
  251. toolbar.css('z-index', 4);
  252. }
  253. // Enable delay on mouseout
  254. if (toolbar.filter('[data-settings~="delay"]').length != 0) {
  255. crayon[uid].toolbar_delay = 500;
  256. }
  257. // Use .hover() for chrome, but in firefox mouseover/mouseout worked best
  258. c.mouseenter(function () {
  259. toolbar_toggle(uid, true);
  260. })
  261. .mouseleave(function () {
  262. toolbar_toggle(uid, false);
  263. });
  264. } else if (touchscreen) {
  265. toolbar.show();
  266. }
  267. // Plain show events
  268. if (plain.length != 0 && !touchscreen) {
  269. if (plain.filter('[data-settings~="dblclick"]').length != 0) {
  270. main.dblclick(function () {
  271. CrayonSyntax.toggle_plain(uid);
  272. });
  273. } else if (plain.filter('[data-settings~="click"]').length != 0) {
  274. main.click(function () {
  275. CrayonSyntax.toggle_plain(uid);
  276. });
  277. } else if (plain.filter('[data-settings~="mouseover"]').length != 0) {
  278. c.mouseenter(function () {
  279. CrayonSyntax.toggle_plain(uid, true);
  280. })
  281. .mouseleave(function () {
  282. CrayonSyntax.toggle_plain(uid, false);
  283. });
  284. nums_button.hide();
  285. }
  286. if (plain.filter('[data-settings~="show-plain-default"]').length != 0) {
  287. // XXX
  288. CrayonSyntax.toggle_plain(uid, true);
  289. }
  290. }
  291. // Scrollbar show events
  292. var expand = c.filter('[data-settings~="expand"]').length != 0;
  293. // crayon[uid].mouse_expand = expand;
  294. if (!touchscreen && c.filter('[data-settings~="scroll-mouseover"]').length != 0) {
  295. // Disable on touchscreen devices and when set to mouseover
  296. main.css('overflow', 'hidden');
  297. plain.css('overflow', 'hidden');
  298. if (!expand) {
  299. c.mouseenter(function () {
  300. toggle_scroll(uid, true, expand);
  301. })
  302. .mouseleave(function () {
  303. toggle_scroll(uid, false, expand);
  304. });
  305. }
  306. }
  307. if (expand) {
  308. c.mouseenter(function () {
  309. toggle_expand(uid, true);
  310. })
  311. .mouseleave(function () {
  312. toggle_expand(uid, false);
  313. });
  314. }
  315. // Disable animations
  316. if (c.filter('[data-settings~="disable-anim"]').length != 0) {
  317. crayon[uid].time = 0;
  318. }
  319. // Wrap
  320. if (c.filter('[data-settings~="wrap"]').length != 0) {
  321. crayon[uid].wrapped = true;
  322. }
  323. // Determine if Mac
  324. crayon[uid].mac = c.hasClass('crayon-os-mac');
  325. // Update clickable buttons
  326. update_nums_button(uid);
  327. update_plain_button(uid);
  328. update_wrap(uid);
  329. };
  330. var make_uid = function (uid) {
  331. console_log(crayon);
  332. if (typeof crayon[uid] == 'undefined') {
  333. crayon[uid] = $('#' + uid);
  334. console_log('make ' + uid);
  335. return true;
  336. }
  337. console_log('no make ' + uid);
  338. return false;
  339. };
  340. var getUID = function () {
  341. return currUID++;
  342. };
  343. var code_popup = function (uid) {
  344. if (typeof crayon[uid] == 'undefined') {
  345. return make_uid(uid);
  346. }
  347. var settings = crayon[uid].popup_settings;
  348. if (settings.data) {
  349. // Already done
  350. return;
  351. }
  352. var clone = crayon[uid].clone(true);
  353. clone.removeClass('crayon-wrapped');
  354. // Unwrap
  355. if (crayon[uid].wrapped) {
  356. $(CRAYON_NUM, clone).each(function () {
  357. var line_id = $(this).attr('data-line');
  358. var line = $('#' + line_id);
  359. var height = line.attr('data-height');
  360. height = height ? height : '';
  361. if (typeof height != 'undefined') {
  362. line.css('height', height);
  363. $(this).css('height', height);
  364. }
  365. });
  366. }
  367. clone.find(CRAYON_MAIN).css('height', '');
  368. var code = '';
  369. if (crayon[uid].plain_visible) {
  370. code = clone.find(CRAYON_PLAIN);
  371. } else {
  372. code = clone.find(CRAYON_MAIN);
  373. }
  374. settings.data = base.get_all_css() + '<body class="crayon-popup-window" style="padding:0; margin:0;"><div class="' + clone.attr('class') +
  375. ' crayon-popup">' + remove_css_inline(get_jquery_str(code)) + '</div></body>';
  376. };
  377. var get_jquery_str = function (object) {
  378. return $('<div>').append(object.clone()).remove().html();
  379. };
  380. var remove_css_inline = function (string) {
  381. var reStyle = /style\s*=\s*"([^"]+)"/gmi;
  382. var match = null;
  383. while ((match = reStyle.exec(string)) != null) {
  384. var repl = match[1];
  385. repl = repl.replace(/\b(?:width|height)\s*:[^;]+;/gmi, '');
  386. string = string.sliceReplace(match.index, match.index + match[0].length, 'style="' + repl + '"');
  387. }
  388. return string;
  389. };
  390. // Get all CSS on the page as a string
  391. base.get_all_css = function () {
  392. var css_str = '';
  393. var css = $('link[rel="stylesheet"]');
  394. var filtered = [];
  395. if (css.length == 1) {
  396. // For minified CSS, only allow a single file
  397. filtered = css;
  398. } else {
  399. // Filter all others for Crayon CSS
  400. filtered = css.filter('[href*="crayon-syntax-highlighter"]');
  401. }
  402. filtered.each(function () {
  403. var string = get_jquery_str($(this));
  404. css_str += string;
  405. });
  406. return css_str;
  407. };
  408. base.copy_plain = function (uid, hover) {
  409. if (typeof crayon[uid] == 'undefined') {
  410. return make_uid(uid);
  411. }
  412. var plain = crayon[uid].plain;
  413. base.toggle_plain(uid, true, true);
  414. toolbar_toggle(uid, true);
  415. key = crayon[uid].mac ? '\u2318' : 'CTRL';
  416. var text = crayon[uid].copy_button.attr('data-text');
  417. text = text.replace(/%s/, key + '+C');
  418. text = text.replace(/%s/, key + '+V');
  419. crayon_info(uid, text);
  420. return false;
  421. };
  422. var crayon_info = function (uid, text, show) {
  423. if (typeof crayon[uid] == 'undefined') {
  424. return make_uid(uid);
  425. }
  426. var info = crayon[uid].info;
  427. if (typeof text == 'undefined') {
  428. text = '';
  429. }
  430. if (typeof show == 'undefined') {
  431. show = true;
  432. }
  433. if (crayon_is_slide_hidden(info) && show) {
  434. info.html('<div>' + text + '</div>');
  435. info.css('margin-top', -info.height());
  436. info.show();
  437. crayon_slide(uid, info, true);
  438. setTimeout(function () {
  439. crayon_slide(uid, info, false);
  440. }, 5000);
  441. }
  442. if (!show) {
  443. crayon_slide(uid, info, false);
  444. }
  445. };
  446. var retina = function (uid) {
  447. if (window.devicePixelRatio > 1) {
  448. var buttons = $('.crayon-button', crayon[uid].toolbar);
  449. buttons.each(function () {
  450. var lowres = $(this).css('background-image');
  451. var highres = lowres.replace(/\.(?=[^\.]+$)/g, '@2x.');
  452. $(this).css('background-size', '48px 16px');
  453. $(this).css('background-image', highres);
  454. });
  455. }
  456. };
  457. var crayon_is_slide_hidden = function (object) {
  458. var object_neg_height = '-' + object.height() + 'px';
  459. if (object.css('margin-top') == object_neg_height || object.css('display') == 'none') {
  460. return true;
  461. } else {
  462. return false;
  463. }
  464. };
  465. var crayon_slide = function (uid, object, show, anim_time, hide_delay) {
  466. var object_neg_height = '-' + object.height() + 'px';
  467. if (typeof show == 'undefined') {
  468. if (crayon_is_slide_hidden(object)) {
  469. show = true;
  470. } else {
  471. show = false;
  472. }
  473. }
  474. // Instant means no time delay for showing/hiding
  475. if (typeof anim_time == 'undefined') {
  476. anim_time = 100;
  477. }
  478. if (anim_time == false) {
  479. anim_time = false;
  480. }
  481. if (typeof hide_delay == 'undefined') {
  482. hide_delay = 0;
  483. }
  484. object.stop(true);
  485. if (show == true) {
  486. object.show();
  487. object.animate({
  488. marginTop: 0
  489. }, animt(anim_time, uid));
  490. } else if (show == false) {
  491. // Delay if fully visible
  492. if (/*instant == false && */object.css('margin-top') == '0px' && hide_delay) {
  493. object.delay(hide_delay);
  494. }
  495. object.animate({
  496. marginTop: object_neg_height
  497. }, animt(anim_time, uid), function () {
  498. object.hide();
  499. });
  500. }
  501. };
  502. base.toggle_plain = function (uid, hover, select) {
  503. if (typeof crayon[uid] == 'undefined') {
  504. return make_uid(uid);
  505. }
  506. var main = crayon[uid].main;
  507. var plain = crayon[uid].plain;
  508. if ((main.is(':animated') || plain.is(':animated')) && typeof hover == 'undefined') {
  509. return;
  510. }
  511. reconsile_dimensions(uid);
  512. var visible, hidden;
  513. if (typeof hover != 'undefined') {
  514. if (hover) {
  515. visible = main;
  516. hidden = plain;
  517. } else {
  518. visible = plain;
  519. hidden = main;
  520. }
  521. } else {
  522. if (main.css('z-index') == 1) {
  523. visible = main;
  524. hidden = plain;
  525. } else {
  526. visible = plain;
  527. hidden = main;
  528. }
  529. }
  530. crayon[uid].plain_visible = (hidden == plain);
  531. // Remember scroll positions of visible
  532. crayon[uid].top = visible.scrollTop();
  533. crayon[uid].left = visible.scrollLeft();
  534. /* Used to detect a change in overflow when the mouse moves out
  535. * of the Crayon. If it does, then overflow has already been changed,
  536. * no need to revert it after toggling plain. */
  537. crayon[uid].scroll_changed = false;
  538. // Hide scrollbars during toggle to avoid Chrome weird draw error
  539. // visible.css('overflow', 'hidden');
  540. // hidden.css('overflow', 'hidden');
  541. fix_scroll_blank(uid);
  542. // Show hidden, hide visible
  543. visible.stop(true);
  544. visible.fadeTo(animt(500, uid), 0,
  545. function () {
  546. visible.css('z-index', 0);
  547. });
  548. hidden.stop(true);
  549. hidden.fadeTo(animt(500, uid), 1,
  550. function () {
  551. hidden.css('z-index', 1);
  552. // Give focus to plain code
  553. if (hidden == plain) {
  554. if (select) {
  555. plain.select();
  556. } else {
  557. // XXX not needed
  558. // plain.focus();
  559. }
  560. }
  561. // Refresh scrollbar draw
  562. hidden.scrollTop(crayon[uid].top + 1);
  563. hidden.scrollTop(crayon[uid].top);
  564. hidden.scrollLeft(crayon[uid].left + 1);
  565. hidden.scrollLeft(crayon[uid].left);
  566. });
  567. // Restore scroll positions to hidden
  568. hidden.scrollTop(crayon[uid].top);
  569. hidden.scrollLeft(crayon[uid].left);
  570. update_plain_button(uid);
  571. // Hide toolbar if possible
  572. toolbar_toggle(uid, false);
  573. return false;
  574. };
  575. base.toggle_nums = function (uid, hide, instant) {
  576. if (typeof crayon[uid] == 'undefined') {
  577. make_uid(uid);
  578. return false;
  579. }
  580. if (crayon[uid].table.is(':animated')) {
  581. return false;
  582. }
  583. var nums_width = Math.round(crayon[uid].nums_content.width() + 1);
  584. var neg_width = '-' + nums_width + 'px';
  585. // Force hiding
  586. var num_hidden;
  587. if (typeof hide != 'undefined') {
  588. num_hidden = false;
  589. } else {
  590. // Check hiding
  591. num_hidden = (crayon[uid].table.css('margin-left') == neg_width);
  592. }
  593. var num_margin;
  594. if (num_hidden) {
  595. // Show
  596. num_margin = '0px';
  597. crayon[uid].nums_visible = true;
  598. } else {
  599. // Hide
  600. crayon[uid].table.css('margin-left', '0px');
  601. crayon[uid].nums_visible = false;
  602. num_margin = neg_width;
  603. }
  604. if (typeof instant != 'undefined') {
  605. crayon[uid].table.css('margin-left', num_margin);
  606. update_nums_button(uid);
  607. return false;
  608. }
  609. // Stop jerking animation from scrollbar appearing for a split second due to
  610. // change in width. Prevents scrollbar disappearing if already visible.
  611. h_scroll_visible = (crayon[uid].table.width() + px_to_int(crayon[uid].table.css('margin-left')) > crayon[uid].main.width());
  612. v_scroll_visible = (crayon[uid].table.height() > crayon[uid].main.height());
  613. if (!h_scroll_visible && !v_scroll_visible) {
  614. crayon[uid].main.css('overflow', 'hidden');
  615. }
  616. crayon[uid].table.animate({
  617. marginLeft: num_margin
  618. }, animt(200, uid), function () {
  619. if (typeof crayon[uid] != 'undefined') {
  620. update_nums_button(uid);
  621. if (!h_scroll_visible && !v_scroll_visible) {
  622. crayon[uid].main.css('overflow', 'auto');
  623. }
  624. }
  625. });
  626. return false;
  627. };
  628. base.toggle_wrap = function (uid) {
  629. crayon[uid].wrapped = !crayon[uid].wrapped;
  630. update_wrap(uid);
  631. };
  632. base.toggle_expand = function (uid) {
  633. var expand = !CrayonUtil.setDefault(crayon[uid].expanded, false);
  634. toggle_expand(uid, expand);
  635. };
  636. var update_wrap = function (uid) {
  637. if (crayon[uid].wrapped) {
  638. crayon[uid].addClass(CRAYON_WRAPPED);
  639. } else {
  640. crayon[uid].removeClass(CRAYON_WRAPPED);
  641. }
  642. update_wrap_button(uid);
  643. if (!crayon[uid].expanded) {
  644. restore_dimensions(uid);
  645. }
  646. crayon[uid].wrap_times = 0;
  647. crayon[uid].wrap_timer = setInterval(function () {
  648. reconsile_lines(uid);
  649. crayon[uid].wrap_times++;
  650. if (crayon[uid].wrap_times == 5) {
  651. clearInterval(crayon[uid].wrap_timer);
  652. }
  653. }, 200);
  654. };
  655. var fix_table_width = function (uid) {
  656. if (typeof crayon[uid] == 'undefined') {
  657. make_uid(uid);
  658. return false;
  659. }
  660. };
  661. // Convert '-10px' to -10
  662. var px_to_int = function (pixels) {
  663. if (typeof pixels != 'string') {
  664. return 0;
  665. }
  666. var result = pixels.replace(/[^-0-9]/g, '');
  667. if (result.length == 0) {
  668. return 0;
  669. } else {
  670. return parseInt(result);
  671. }
  672. };
  673. var update_nums_button = function (uid) {
  674. if (typeof crayon[uid] == 'undefined' || typeof crayon[uid].nums_visible == 'undefined') {
  675. return;
  676. }
  677. if (crayon[uid].nums_visible) {
  678. crayon[uid].nums_button.removeClass(UNPRESSED);
  679. crayon[uid].nums_button.addClass(PRESSED);
  680. } else {
  681. // TODO doesn't work on iPhone
  682. crayon[uid].nums_button.removeClass(PRESSED);
  683. crayon[uid].nums_button.addClass(UNPRESSED);
  684. }
  685. };
  686. var update_wrap_button = function (uid) {
  687. if (typeof crayon[uid] == 'undefined' || typeof crayon[uid].wrapped == 'undefined') {
  688. return;
  689. }
  690. if (crayon[uid].wrapped) {
  691. crayon[uid].wrap_button.removeClass(UNPRESSED);
  692. crayon[uid].wrap_button.addClass(PRESSED);
  693. } else {
  694. // TODO doesn't work on iPhone
  695. crayon[uid].wrap_button.removeClass(PRESSED);
  696. crayon[uid].wrap_button.addClass(UNPRESSED);
  697. }
  698. };
  699. var update_expand_button = function (uid) {
  700. if (typeof crayon[uid] == 'undefined' || typeof crayon[uid].expanded == 'undefined') {
  701. return;
  702. }
  703. if (crayon[uid].expanded) {
  704. crayon[uid].expand_button.removeClass(UNPRESSED);
  705. crayon[uid].expand_button.addClass(PRESSED);
  706. } else {
  707. // TODO doesn't work on iPhone
  708. crayon[uid].expand_button.removeClass(PRESSED);
  709. crayon[uid].expand_button.addClass(UNPRESSED);
  710. }
  711. };
  712. var update_plain_button = function (uid) {
  713. if (typeof crayon[uid] == 'undefined' || typeof crayon[uid].plain_visible == 'undefined') {
  714. return;
  715. }
  716. if (crayon[uid].plain_visible) {
  717. crayon[uid].plain_button.removeClass(UNPRESSED);
  718. crayon[uid].plain_button.addClass(PRESSED);
  719. } else {
  720. // TODO doesn't work on iPhone
  721. crayon[uid].plain_button.removeClass(PRESSED);
  722. crayon[uid].plain_button.addClass(UNPRESSED);
  723. }
  724. };
  725. var toolbar_toggle = function (uid, show, anim_time, hide_delay) {
  726. if (typeof crayon[uid] == 'undefined') {
  727. return make_uid(uid);
  728. } else if (!crayon[uid].toolbar_mouseover) {
  729. return;
  730. }
  731. var toolbar = crayon[uid].toolbar;
  732. if (typeof hide_delay == 'undefined') {
  733. hide_delay = crayon[uid].toolbar_delay;
  734. }
  735. crayon_slide(uid, toolbar, show, anim_time, hide_delay);
  736. };
  737. var initSize = function (uid) {
  738. // Shared for scrollbars and expanding
  739. crayon[uid].initialSize = {width: crayon[uid].width(), height: crayon[uid].height()};
  740. };
  741. var toggle_expand = function (uid, expand) {
  742. if (typeof crayon[uid] == 'undefined') {
  743. return make_uid(uid);
  744. }
  745. if (typeof expand == 'undefined') {
  746. return;
  747. }
  748. var main = crayon[uid].main;
  749. var plain = crayon[uid].plain;
  750. if (expand) {
  751. if (typeof crayon[uid].expanded == 'undefined') {
  752. initSize(uid);
  753. crayon[uid].finalSize = {width: crayon[uid].table.width(), height: crayon[uid].table.height()};
  754. // Ensure we don't shrink
  755. crayon[uid].finalSize.width = CrayonUtil.setMin(crayon[uid].finalSize.width, crayon[uid].initialSize.width);
  756. crayon[uid].finalSize.height = CrayonUtil.setMin(crayon[uid].finalSize.height, crayon[uid].initialSize.height);
  757. crayon[uid].diffSize = {
  758. width: crayon[uid].finalSize.width - crayon[uid].initialSize.width,
  759. height: crayon[uid].finalSize.height - crayon[uid].initialSize.height
  760. };
  761. crayon[uid].expandTime = CrayonUtil.setRange(crayon[uid].diffSize.width / 3, 300, 800);
  762. crayon[uid].expanded = false;
  763. }
  764. var initialSize = crayon[uid].initialSize;
  765. var diffSize = crayon[uid].diffSize;
  766. var finalSize = crayon[uid].finalSize;
  767. var expandHeight = {
  768. 'height': 'auto',
  769. 'min-height': 'none',
  770. 'max-height': 'none'
  771. };
  772. var expandWidth = {
  773. 'width': 'auto',
  774. 'min-width': 'none',
  775. 'max-width': 'none'
  776. };
  777. crayon[uid].height(crayon[uid].height());
  778. crayon[uid].width(crayon[uid].width());
  779. crayon[uid].css({
  780. 'min-width': 'none',
  781. 'max-width': 'none'
  782. });
  783. main.css(expandHeight);
  784. main.css(expandWidth);
  785. crayon[uid].stop(true);
  786. crayon[uid].animate({
  787. width: finalSize.width,
  788. height: finalSize.height
  789. }, animt(crayon[uid].expandTime, uid), function () {
  790. crayon[uid].expanded = true;
  791. update_expand_button(uid);
  792. });
  793. } else {
  794. var initialSize = crayon[uid].initialSize;
  795. var delay = crayon[uid].toolbar_delay;
  796. if (initialSize) {
  797. crayon[uid].stop(true);
  798. if (!crayon[uid].expanded) {
  799. crayon[uid].delay(delay);
  800. }
  801. crayon[uid].animate({
  802. width: initialSize.width,
  803. height: initialSize.height
  804. }, animt(crayon[uid].expandTime, uid), function () {
  805. expand_finish(uid);
  806. });
  807. } else {
  808. setTimeout(function () {
  809. expand_finish(uid);
  810. }, delay);
  811. }
  812. }
  813. reconsile_dimensions(uid);
  814. if (expand) {
  815. update_wrap(uid);
  816. }
  817. };
  818. var expand_finish = function(uid) {
  819. crayon[uid].expanded = false;
  820. restore_dimensions(uid);
  821. update_expand_button(uid);
  822. if (crayon[uid].wrapped) {
  823. update_wrap(uid);
  824. }
  825. };
  826. var toggle_scroll = function (uid, show, expand) {
  827. if (typeof crayon[uid] == 'undefined') {
  828. return make_uid(uid);
  829. }
  830. if (typeof show == 'undefined') {
  831. return;
  832. }
  833. var main = crayon[uid].main;
  834. var plain = crayon[uid].plain;
  835. if (typeof crayon[uid].initialSize == 'undefined') {
  836. initSize(uid);
  837. }
  838. if (show) {
  839. main.height(main.height());
  840. plain.height(plain.height());
  841. // Show scrollbars
  842. main.css('overflow', 'auto');
  843. plain.css('overflow', 'auto');
  844. if (typeof crayon[uid].top != 'undefined') {
  845. visible = (main.css('z-index') == 1 ? main : plain);
  846. // Browser will not render until scrollbar moves, move it manually
  847. visible.scrollTop(crayon[uid].top - 1);
  848. visible.scrollTop(crayon[uid].top);
  849. visible.scrollLeft(crayon[uid].left - 1);
  850. visible.scrollLeft(crayon[uid].left);
  851. }
  852. } else {
  853. // Hide scrollbars
  854. visible = (main.css('z-index') == 1 ? main : plain);
  855. crayon[uid].top = visible.scrollTop();
  856. crayon[uid].left = visible.scrollLeft();
  857. main.css('overflow', 'hidden');
  858. plain.css('overflow', 'hidden');
  859. // main.height(crayon[uid].initialSize.height);
  860. // plain.height(crayon[uid].initialSize.height);
  861. if (!crayon[uid].expanded) {
  862. restore_dimensions(uid);
  863. }
  864. //restore_dimensions(uid);
  865. }
  866. // Register that overflow has changed
  867. crayon[uid].scroll_changed = true;
  868. fix_scroll_blank(uid);
  869. };
  870. /* Fix weird draw error, causes blank area to appear where scrollbar once was. */
  871. var fix_scroll_blank = function (uid) {
  872. // Scrollbar draw error in Chrome
  873. crayon[uid].table.style('width', '100%', 'important');
  874. var redraw = setTimeout(function () {
  875. crayon[uid].table.style('width', '');
  876. clearInterval(redraw);
  877. }, 10);
  878. };
  879. var restore_dimensions = function (uid) {
  880. // Restore dimensions
  881. var main = crayon[uid].main;
  882. var main_style = crayon[uid].main_style;
  883. main.css(main_style);
  884. // Width styles also apply to crayon
  885. crayon[uid].css('height', 'auto');
  886. crayon[uid].css('width', main_style['width']);
  887. crayon[uid].css('max-width', main_style['max-width']);
  888. crayon[uid].css('min-width', main_style['min-width']);
  889. };
  890. var reconsile_dimensions = function (uid) {
  891. // Reconsile dimensions
  892. crayon[uid].plain.height(crayon[uid].main.height());
  893. };
  894. var reconsile_lines = function (uid) {
  895. $(CRAYON_NUM, crayon[uid]).each(function () {
  896. var line_id = $(this).attr('data-line');
  897. var line = $('#' + line_id);
  898. if (crayon[uid].wrapped) {
  899. line.css('height', '');
  900. $(this).css('height', line.height());
  901. // TODO toolbar should overlay title if needed
  902. } else {
  903. var height = line.attr('data-height');
  904. height = height ? height : '';
  905. if (typeof height != 'undefined') {
  906. line.css('height', height);
  907. $(this).css('height', height);
  908. }
  909. //line.css('height', line.css('line-height'));
  910. //console.log(line.css('line-height'));
  911. }
  912. });
  913. };
  914. var animt = function (x, uid) {
  915. if (x == 'fast') {
  916. x = 200;
  917. } else if (x == 'slow') {
  918. x = 600;
  919. } else if (!isNumber(x)) {
  920. x = parseInt(x);
  921. if (isNaN(x)) {
  922. return 0;
  923. }
  924. }
  925. return x * crayon[uid].time;
  926. };
  927. var isNumber = function (x) {
  928. return typeof x == 'number';
  929. };
  930. };
  931. })(jQueryCrayon);