JAVASCRIPT   22

urvanov syntax highlighter

Guest on 12th August 2022 12:31:34 AM

  1. // Urvanov Syntax Highlighter JavaScript
  2.  
  3. (function ($) {
  4.  
  5.  
  6.        
  7.     // BEGIN AUXILIARY FUNCTIONS
  8.  
  9.     $.fn.exists = function () {
  10.         return this.length !== 0;
  11.     };
  12.  
  13.     $.fn.style = function (styleName, value, priority) {
  14.         // DOM node
  15.         var node = this.get(0);
  16.         // Ensure we have a DOM node
  17.         if (typeof node == 'undefined') {
  18.             return;
  19.         }
  20.         // CSSStyleDeclaration
  21.         var style = node.style;
  22.         // Getter/Setter
  23.         if (typeof styleName != 'undefined') {
  24.             if (typeof value != 'undefined') {
  25.                 // Set style property
  26.                 priority = typeof priority != 'undefined' ? priority : '';
  27.                 if (typeof style.setProperty != 'undefined') {
  28.                     style.setProperty(styleName, value, priority);
  29.                 } else {
  30.                     // XXX Using priority breaks on IE 7 & 8
  31. //                    if (priority) {
  32. //                        value = value + ' !' + priority;
  33. //                    }
  34.                     style[styleName] = value;
  35.                 }
  36.             } else {
  37.                 // Get style property
  38.                 return style[styleName];
  39.             }
  40.         } else {
  41.             // Get CSSStyleDeclaration
  42.             return style;
  43.         }
  44.     };
  45.  
  46.     // END AUXILIARY FUNCTIONS
  47.  
  48.     var PRESSED = 'crayon-pressed';
  49.     var UNPRESSED = '';
  50.  
  51.     var URVANOV_SYNTAX_HIGHLIGHTER_SYNTAX = 'div.urvanov-syntax-highlighter-syntax';
  52.     var URVANOV_SYNTAX_HIGHLIGHTER_TOOLBAR = '.crayon-toolbar';
  53.     var URVANOV_SYNTAX_HIGHLIGHTER_INFO = '.crayon-info';
  54.     var URVANOV_SYNTAX_HIGHLIGHTER_PLAIN = '.urvanov-syntax-highlighter-plain';
  55.     var URVANOV_SYNTAX_HIGHLIGHTER_MAIN = '.urvanov-syntax-highlighter-main';
  56.     var URVANOV_SYNTAX_HIGHLIGHTER_TABLE = '.crayon-table';
  57.     var URVANOV_SYNTAX_HIGHLIGHTER_LOADING = '.urvanov-syntax-highlighter-loading';
  58.     var URVANOV_SYNTAX_HIGHLIGHTER_CODE = '.urvanov-syntax-highlighter-code';
  59.     var URVANOV_SYNTAX_HIGHLIGHTER_TITLE = '.crayon-title';
  60.     var URVANOV_SYNTAX_HIGHLIGHTER_TOOLS = '.crayon-tools';
  61.     var URVANOV_SYNTAX_HIGHLIGHTER_NUMS = '.crayon-nums';
  62.     var URVANOV_SYNTAX_HIGHLIGHTER_NUM = '.crayon-num';
  63.     var URVANOV_SYNTAX_HIGHLIGHTER_LINE = '.crayon-line';
  64.     var URVANOV_SYNTAX_HIGHLIGHTER_WRAPPED = 'urvanov-syntax-highlighter-wrapped';
  65.     var URVANOV_SYNTAX_HIGHLIGHTER_NUMS_CONTENT = '.urvanov-syntax-highlighter-nums-content';
  66.     var URVANOV_SYNTAX_HIGHLIGHTER_NUMS_BUTTON = '.urvanov-syntax-highlighter-nums-button';
  67.     var URVANOV_SYNTAX_HIGHLIGHTER_WRAP_BUTTON = '.urvanov-syntax-highlighter-wrap-button';
  68.     var URVANOV_SYNTAX_HIGHLIGHTER_EXPAND_BUTTON = '.urvanov-syntax-highlighter-expand-button';
  69.     var URVANOV_SYNTAX_HIGHLIGHTER_EXPANDED = 'urvanov-syntax-highlighter-expanded urvanov-syntax-highlighter-toolbar-visible';
  70.     var URVANOV_SYNTAX_HIGHLIGHTER_PLACEHOLDER = 'urvanov-syntax-highlighter-placeholder';
  71.     var URVANOV_SYNTAX_HIGHLIGHTER_POPUP_BUTTON = '.urvanov-syntax-highlighter-popup-button';
  72.     var URVANOV_SYNTAX_HIGHLIGHTER_COPY_BUTTON = '.urvanov-syntax-highlighter-copy-button';
  73.     var URVANOV_SYNTAX_HIGHLIGHTER_PLAIN_BUTTON = '.urvanov-syntax-highlighter-plain-button';
  74.  
  75.     UrvanovSyntaxHighlighterSyntax = new function () {
  76.         var base = this;
  77.         var urvanov_syntax_highlighters = new Object();
  78.         var settings;
  79.         var strings;
  80.         var currUID = 0;
  81.         var touchscreen;
  82.  
  83.         base.init = function () {
  84.             if (typeof urvanov_syntax_highlighters == 'undefined') {
  85.                 urvanov_syntax_highlighters = new Object();
  86.             }
  87.             settings = UrvanovSyntaxHighlighterSyntaxSettings;
  88.             strings = UrvanovSyntaxHighlighterSyntaxStrings;
  89.             $(URVANOV_SYNTAX_HIGHLIGHTER_SYNTAX).each(function () {
  90.                 base.process(this);
  91.             });
  92.         };
  93.  
  94.         base.process = function (c, replace) {
  95.             c = $(c);
  96.             var uid = c.attr('id');
  97.             if (uid == 'urvanov-syntax-highlighter-') {
  98.                 // No ID, generate one
  99.                 uid += getUID();
  100.             }
  101.             c.attr('id', uid);
  102.             UrvanovSyntaxHighlighterUtil.log(uid);
  103.  
  104.             if (typeof replace == 'undefined') {
  105.                 replace = false;
  106.             }
  107.  
  108.             if (!replace && !makeUID(uid)) {
  109.                 // Already a UrvanovSyntaxHighlighter
  110.                 return;
  111.             }
  112.  
  113.             var toolbar = c.find(URVANOV_SYNTAX_HIGHLIGHTER_TOOLBAR);
  114.             var info = c.find(URVANOV_SYNTAX_HIGHLIGHTER_INFO);
  115.             var plain = c.find(URVANOV_SYNTAX_HIGHLIGHTER_PLAIN);
  116.             var main = c.find(URVANOV_SYNTAX_HIGHLIGHTER_MAIN);
  117.             var table = c.find(URVANOV_SYNTAX_HIGHLIGHTER_TABLE);
  118.             var code = c.find(URVANOV_SYNTAX_HIGHLIGHTER_CODE);
  119.             var title = c.find(URVANOV_SYNTAX_HIGHLIGHTER_TITLE);
  120.             var tools = c.find(URVANOV_SYNTAX_HIGHLIGHTER_TOOLS);
  121.             var nums = c.find(URVANOV_SYNTAX_HIGHLIGHTER_NUMS);
  122.             var numsContent = c.find(URVANOV_SYNTAX_HIGHLIGHTER_NUMS_CONTENT);
  123.             var numsButton = c.find(URVANOV_SYNTAX_HIGHLIGHTER_NUMS_BUTTON);
  124.             var wrapButton = c.find(URVANOV_SYNTAX_HIGHLIGHTER_WRAP_BUTTON);
  125.             var expandButton = c.find(URVANOV_SYNTAX_HIGHLIGHTER_EXPAND_BUTTON);
  126.             var popupButton = c.find(URVANOV_SYNTAX_HIGHLIGHTER_POPUP_BUTTON);
  127.             var copyButton = c.find(URVANOV_SYNTAX_HIGHLIGHTER_COPY_BUTTON);
  128.             var plainButton = c.find(URVANOV_SYNTAX_HIGHLIGHTER_PLAIN_BUTTON);
  129.  
  130.             urvanov_syntax_highlighters[uid] = c;
  131.             urvanov_syntax_highlighters[uid].toolbar = toolbar;
  132.             urvanov_syntax_highlighters[uid].plain = plain;
  133.             urvanov_syntax_highlighters[uid].info = info;
  134.             urvanov_syntax_highlighters[uid].main = main;
  135.             urvanov_syntax_highlighters[uid].table = table;
  136.             urvanov_syntax_highlighters[uid].code = code;
  137.             urvanov_syntax_highlighters[uid].title = title;
  138.             urvanov_syntax_highlighters[uid].tools = tools;
  139.             urvanov_syntax_highlighters[uid].nums = nums;
  140.             urvanov_syntax_highlighters[uid].nums_content = numsContent;
  141.             urvanov_syntax_highlighters[uid].numsButton = numsButton;
  142.             urvanov_syntax_highlighters[uid].wrapButton = wrapButton;
  143.             urvanov_syntax_highlighters[uid].expandButton = expandButton;
  144.             urvanov_syntax_highlighters[uid].popup_button = popupButton;
  145.             urvanov_syntax_highlighters[uid].copy_button = copyButton;
  146.             urvanov_syntax_highlighters[uid].plainButton = plainButton;
  147.             urvanov_syntax_highlighters[uid].numsVisible = true;
  148.             urvanov_syntax_highlighters[uid].wrapped = false;
  149.             urvanov_syntax_highlighters[uid].plainVisible = false;
  150.  
  151.             urvanov_syntax_highlighters[uid].toolbar_delay = 0;
  152.             urvanov_syntax_highlighters[uid].time = 1;
  153.  
  154.             // Set plain
  155.             $(URVANOV_SYNTAX_HIGHLIGHTER_PLAIN).css('z-index', 0);
  156.  
  157.             // XXX Remember CSS dimensions
  158.             var mainStyle = main.style();
  159.             urvanov_syntax_highlighters[uid].mainStyle = {
  160.                 'height': mainStyle && mainStyle.height || '',
  161.                 'max-height': mainStyle && mainStyle.maxHeight || '',
  162.                 'min-height': mainStyle && mainStyle.minHeight || '',
  163.                 'width': mainStyle && mainStyle.width || '',
  164.                 'max-width': mainStyle && mainStyle.maxWidth || '',
  165.                 'min-width': mainStyle && mainStyle.minWidth || ''
  166.             };
  167.             urvanov_syntax_highlighters[uid].mainHeightAuto = urvanov_syntax_highlighters[uid].mainStyle.height == '' && urvanov_syntax_highlighters[uid].mainStyle['max-height'] == '';
  168.  
  169.             var load_timer;
  170.             var i = 0;
  171.             urvanov_syntax_highlighters[uid].loading = true;
  172.             urvanov_syntax_highlighters[uid].scrollBlockFix = false;
  173.  
  174.             // Register click events
  175.             numsButton.click(function () {
  176.                 UrvanovSyntaxHighlighterSyntax.toggleNums(uid);
  177.             });
  178.             wrapButton.click(function () {
  179.                 UrvanovSyntaxHighlighterSyntax.toggleWrap(uid);
  180.             });
  181.             expandButton.click(function () {
  182.                 UrvanovSyntaxHighlighterSyntax.toggleExpand(uid);
  183.             });
  184.             plainButton.click(function () {
  185.                 UrvanovSyntaxHighlighterSyntax.togglePlain(uid);
  186.             });
  187.             copyButton.click(function () {
  188.                 UrvanovSyntaxHighlighterSyntax.copyPlain(uid);
  189.             });
  190.  
  191.             // Enable retina if supported
  192.             retina(uid);
  193.  
  194.             var load_func = function () {
  195.                 // If nums hidden by default
  196.                 if (nums.filter('[data-settings~="hide"]').length != 0) {
  197.                     numsContent.ready(function () {
  198.                         UrvanovSyntaxHighlighterUtil.log('function' + uid);
  199.                         UrvanovSyntaxHighlighterSyntax.toggleNums(uid, true, true);
  200.                     });
  201.                 } else {
  202.                     updateNumsButton(uid);
  203.                 }
  204.  
  205.                 if (typeof urvanov_syntax_highlighters[uid].expanded == 'undefined') {
  206.                     // Determine if we should enable code expanding toggling
  207.                     if (Math.abs(urvanov_syntax_highlighters[uid].main.outerWidth() - urvanov_syntax_highlighters[uid].table.outerWidth()) < 10) {
  208.                         urvanov_syntax_highlighters[uid].expandButton.hide();
  209.                     } else {
  210.                         urvanov_syntax_highlighters[uid].expandButton.show();
  211.                     }
  212.                 }
  213.  
  214.                 // TODO If width has changed or timeout, stop timer
  215.                 if (/*last_num_width != nums.outerWidth() ||*/ i == 5) {
  216.                     clearInterval(load_timer);
  217.                     //urvanov_syntax_highlighters[uid].removeClass(URVANOV_SYNTAX_HIGHLIGHTER_LOADING);
  218.                     urvanov_syntax_highlighters[uid].loading = false;
  219.                 }
  220.                 i++;
  221.             };
  222.             load_timer = setInterval(load_func, 300);
  223.             fixScrollBlank(uid);
  224.  
  225.             // Add ref to num for each line
  226.             $(URVANOV_SYNTAX_HIGHLIGHTER_NUM, urvanov_syntax_highlighters[uid]).each(function () {
  227.                 var lineID = $(this).attr('data-line');
  228.                 var line = $('#' + lineID);
  229.                 var height = line.style('height');
  230.                 if (height) {
  231.                     line.attr('data-height', height);
  232.                 }
  233.             });
  234.  
  235.             // Used for toggling
  236.             main.css('position', 'relative');
  237.             main.css('z-index', 1);
  238.  
  239.             // Disable certain features for touchscreen devices
  240.             touchscreen = (c.filter('[data-settings~="touchscreen"]').length != 0);
  241.  
  242.             // Used to hide info
  243.             if (!touchscreen) {
  244.                 main.click(function () {
  245.                     urvanovSyntaxHighlighterInfo(uid, '', false);
  246.                 });
  247.                 plain.click(function () {
  248.                     urvanovSyntaxHighlighterInfo(uid, '', false);
  249.                 });
  250.                 info.click(function () {
  251.                     urvanovSyntaxHighlighterInfo(uid, '', false);
  252.                 });
  253.             }
  254.  
  255.             // Used for code popup
  256.             if (c.filter('[data-settings~="no-popup"]').length == 0) {
  257.                 urvanov_syntax_highlighters[uid].popup_settings = popupWindow(popupButton, {
  258.                     height: screen.height - 200,
  259.                     width: screen.width - 100,
  260.                     top: 75,
  261.                     left: 50,
  262.                     scrollbars: 1,
  263.                     windowURL: '',
  264.                     data: '' // Data overrides URL
  265.                 }, function () {
  266.                     codePopup(uid);
  267.                 }, function () {
  268.                     //UrvanovSyntaxHighlighterUtil.log('after');
  269.                 });
  270.             }
  271.  
  272.             plain.css('opacity', 0);
  273.  
  274.             urvanov_syntax_highlighters[uid].toolbarVisible = true;
  275.             urvanov_syntax_highlighters[uid].hasOneLine = table.outerHeight() < toolbar.outerHeight() * 2;
  276.             urvanov_syntax_highlighters[uid].toolbarMouseover = false;
  277.             // If a toolbar with mouseover was found
  278.             if (toolbar.filter('[data-settings~="mouseover"]').length != 0 && !touchscreen) {
  279.                 urvanov_syntax_highlighters[uid].toolbarMouseover = true;
  280.                 urvanov_syntax_highlighters[uid].toolbarVisible = false;
  281.  
  282.                 toolbar.css('margin-top', '-' + toolbar.outerHeight() + 'px');
  283.                 toolbar.hide();
  284.                 // Overlay the toolbar if needed, only if doing so will not hide the
  285.                 // whole code!
  286.                 if (toolbar.filter('[data-settings~="overlay"]').length != 0
  287.                     && !urvanov_syntax_highlighters[uid].hasOneLine) {
  288.                     toolbar.css('position', 'absolute');
  289.                     toolbar.css('z-index', 2);
  290.                     // Hide on single click when overlayed
  291.                     if (toolbar.filter('[data-settings~="hide"]').length != 0) {
  292.                         main.click(function () {
  293.                             toggleToolbar(uid, undefined, undefined, 0);
  294.                         });
  295.                         plain.click(function () {
  296.                             toggleToolbar(uid, false, undefined, 0);
  297.                         });
  298.                     }
  299.                 } else {
  300.                     toolbar.css('z-index', 4);
  301.                 }
  302.                 // Enable delay on mouseout
  303.                 if (toolbar.filter('[data-settings~="delay"]').length != 0) {
  304.                     urvanov_syntax_highlighters[uid].toolbar_delay = 500;
  305.                 }
  306.                 // Use .hover() for chrome, but in firefox mouseover/mouseout worked best
  307.                 c.mouseenter(function () {
  308.                     toggleToolbar(uid, true);
  309.                 })
  310.                     .mouseleave(function () {
  311.                         toggleToolbar(uid, false);
  312.                     });
  313.             } else if (touchscreen) {
  314.                 toolbar.show();
  315.             }
  316.  
  317.             // Minimize
  318.             if (c.filter('[data-settings~="minimize"]').length == 0) {
  319.                 base.minimize(uid);
  320.             }
  321.  
  322.             // Plain show events
  323.             if (plain.length != 0 && !touchscreen) {
  324.                 if (plain.filter('[data-settings~="dblclick"]').length != 0) {
  325.                     main.dblclick(function () {
  326.                         UrvanovSyntaxHighlighterSyntax.togglePlain(uid);
  327.                     });
  328.                 } else if (plain.filter('[data-settings~="click"]').length != 0) {
  329.                     main.click(function () {
  330.                         UrvanovSyntaxHighlighterSyntax.togglePlain(uid);
  331.                     });
  332.                 } else if (plain.filter('[data-settings~="mouseover"]').length != 0) {
  333.                     c.mouseenter(function () {
  334.                         UrvanovSyntaxHighlighterSyntax.togglePlain(uid, true);
  335.                     })
  336.                         .mouseleave(function () {
  337.                             UrvanovSyntaxHighlighterSyntax.togglePlain(uid, false);
  338.                         });
  339.                     numsButton.hide();
  340.                 }
  341.                 if (plain.filter('[data-settings~="show-plain-default"]').length != 0) {
  342.                     // XXX
  343.                     UrvanovSyntaxHighlighterSyntax.togglePlain(uid, true);
  344.                 }
  345.             }
  346.  
  347.             // Scrollbar show events
  348.             var expand = c.filter('[data-settings~="expand"]').length != 0;
  349. //            urvanov_syntax_highlighters[uid].mouse_expand = expand;
  350.             if (!touchscreen && c.filter('[data-settings~="scroll-mouseover"]').length != 0) {
  351.                 // Disable on touchscreen devices and when set to mouseover
  352.                 main.css('overflow', 'hidden');
  353.                 plain.css('overflow', 'hidden');
  354.                 c.mouseenter(function () {
  355.                     toggle_scroll(uid, true, expand);
  356.                 })
  357.                 .mouseleave(function () {
  358.                     toggle_scroll(uid, false, expand);
  359.                 });
  360.             }
  361.  
  362.             if (expand) {
  363.                 c.mouseenter(function () {
  364.                     toggleExpand(uid, true);
  365.                 })
  366.                     .mouseleave(function () {
  367.                         toggleExpand(uid, false);
  368.                     });
  369.             }
  370.  
  371.             // Disable animations
  372.             if (c.filter('[data-settings~="disable-anim"]').length != 0) {
  373.                 urvanov_syntax_highlighters[uid].time = 0;
  374.             }
  375.  
  376.             // Wrap
  377.             if (c.filter('[data-settings~="wrap"]').length != 0) {
  378.                 urvanov_syntax_highlighters[uid].wrapped = true;
  379.             }
  380.  
  381.             // Determine if Mac
  382.             urvanov_syntax_highlighters[uid].mac = c.hasClass('urvanov-syntax-highlighter-os-mac');
  383.  
  384.             // Update clickable buttons
  385.             updateNumsButton(uid);
  386.             updatePlainButton(uid);
  387.             updateWrap(uid);
  388.         };
  389.  
  390.         var makeUID = function (uid) {
  391.             UrvanovSyntaxHighlighterUtil.log(urvanov_syntax_highlighters);
  392.             if (typeof urvanov_syntax_highlighters[uid] == 'undefined') {
  393.                 urvanov_syntax_highlighters[uid] = $('#' + uid);
  394.                 UrvanovSyntaxHighlighterUtil.log('make ' + uid);
  395.                 return true;
  396.             }
  397.  
  398.             UrvanovSyntaxHighlighterUtil.log('no make ' + uid);
  399.             return false;
  400.         };
  401.  
  402.         var getUID = function () {
  403.             return currUID++;
  404.         };
  405.  
  406.         var codePopup = function (uid) {
  407.             if (typeof urvanov_syntax_highlighters[uid] == 'undefined') {
  408.                 return makeUID(uid);
  409.             }
  410.             var settings = urvanov_syntax_highlighters[uid].popup_settings;
  411.             if (settings && settings.data) {
  412.                 // Already done
  413.                 return;
  414.             }
  415.  
  416.             var clone = urvanov_syntax_highlighters[uid].clone(true);
  417.             clone.removeClass('urvanov-syntax-highlighter-wrapped');
  418.  
  419.             // Unwrap
  420.             if (urvanov_syntax_highlighters[uid].wrapped) {
  421.                 $(URVANOV_SYNTAX_HIGHLIGHTER_NUM, clone).each(function () {
  422.                     var line_id = $(this).attr('data-line');
  423.                     var line = $('#' + line_id);
  424.                     var height = line.attr('data-height');
  425.                     height = height ? height : '';
  426.                     if (typeof height != 'undefined') {
  427.                         line.css('height', height);
  428.                         $(this).css('height', height);
  429.                     }
  430.                 });
  431.             }
  432.             clone.find(URVANOV_SYNTAX_HIGHLIGHTER_MAIN).css('height', '');
  433.  
  434.             var code = '';
  435.             if (urvanov_syntax_highlighters[uid].plainVisible) {
  436.                 code = clone.find(URVANOV_SYNTAX_HIGHLIGHTER_PLAIN);
  437.             } else {
  438.                 code = clone.find(URVANOV_SYNTAX_HIGHLIGHTER_MAIN);
  439.             }
  440.  
  441.             settings.data = base.getAllCSS() + '<body class="urvanov-syntax-highlighter-popup-window" style="padding:0; margin:0;"><div class="' + clone.attr('class') +
  442.                 ' urvanov-syntax-highlighter-popup">' + base.removeCssInline(base.getHtmlString(code)) + '</div></body>';
  443.         };
  444.  
  445.         base.minimize = function (uid) {
  446.             var button = $('<div class="urvanov-syntax-highlighter-minimize urvanov-syntax-highlighter-button"><div>');
  447.             urvanov_syntax_highlighters[uid].tools.append(button);
  448.             // TODO translate
  449.             urvanov_syntax_highlighters[uid].origTitle = urvanov_syntax_highlighters[uid].title.html();
  450.             if (!urvanov_syntax_highlighters[uid].origTitle) {
  451.                 urvanov_syntax_highlighters[uid].title.html(strings.minimize);
  452.             };
  453.             var cls = 'urvanov-syntax-highlighter-minimized';
  454.             var show = function () {
  455.                 urvanov_syntax_highlighters[uid].toolbarPreventHide = false;
  456.                 button.remove();
  457.                 urvanov_syntax_highlighters[uid].removeClass(cls);
  458.                 urvanov_syntax_highlighters[uid].title.html(urvanov_syntax_highlighters[uid].origTitle);
  459.                 var toolbar = urvanov_syntax_highlighters[uid].toolbar;
  460.                 if (toolbar.filter('[data-settings~="never-show"]').length != 0) {
  461.                     toolbar.remove();
  462.                 }
  463.             };
  464.             urvanov_syntax_highlighters[uid].toolbar.click(show);
  465.             button.click(show);
  466.             urvanov_syntax_highlighters[uid].addClass(cls);
  467.             urvanov_syntax_highlighters[uid].toolbarPreventHide = true;
  468.             toggleToolbar(uid, undefined, undefined, 0);
  469.         }
  470.  
  471.         base.getHtmlString = function (object) {
  472.             return $('<div>').append(object.clone()).remove().html();
  473.         };
  474.  
  475.         base.removeCssInline = function (string) {
  476.             var reStyle = /style\s*=\s*"([^"]+)"/gmi;
  477.             var match = null;
  478.             while ((match = reStyle.exec(string)) != null) {
  479.                 var repl = match[1];
  480.                 repl = repl.replace(/\b(?:width|height)\s*:[^;]+;/gmi, '');
  481.                 string = string.sliceReplace(match.index, match.index + match[0].length, 'style="' + repl + '"');
  482.             }
  483.             return string;
  484.         };
  485.  
  486.         // Get all CSS on the page as a string
  487.         base.getAllCSS = function () {
  488.             var css_str = '';
  489.             var css = $('link[rel="stylesheet"]');
  490.             var filtered = [];
  491.             if (css.length == 1) {
  492.                 // For minified CSS, only allow a single file
  493.                 filtered = css;
  494.             } else {
  495.                 // Filter all others for UrvanovSyntaxHighlighter CSS
  496.                 filtered = css.filter('[href*="urvanov-syntax-highlighter"], [href*="min/"]');
  497.             }
  498.             filtered.each(function () {
  499.                 var string = base.getHtmlString($(this));
  500.                 css_str += string;
  501.             });
  502.             return css_str;
  503.         };
  504.  
  505.         base.copyPlain = function (uid, hover) {
  506.             if (typeof urvanov_syntax_highlighters[uid] == 'undefined') {
  507.                 return makeUID(uid);
  508.             }
  509.  
  510.             var plain = urvanov_syntax_highlighters[uid].plain;
  511.            
  512.             var plainTextCode = plain[0].innerHTML;
  513.  
  514.             navigator.clipboard.writeText(plainTextCode)
  515.                 .then(value => urvanovSyntaxHighlighterInfo(uid, strings.copy));
  516.             return false;
  517.         };
  518.  
  519.         var urvanovSyntaxHighlighterInfo = function (uid, text, show) {
  520.             if (typeof urvanov_syntax_highlighters[uid] == 'undefined') {
  521.                 return makeUID(uid);
  522.             }
  523.  
  524.             var info = urvanov_syntax_highlighters[uid].info;
  525.  
  526.             if (typeof text == 'undefined') {
  527.                 text = '';
  528.             }
  529.             if (typeof show == 'undefined') {
  530.                 show = true;
  531.             }
  532.  
  533.             if (isSlideHidden(info) && show) {
  534.                 info.html('<div>' + text + '</div>');
  535.                 info.css('margin-top', -info.outerHeight());
  536.                 info.show();
  537.                 urvanovSyntaxHighlighterSlide(uid, info, true);
  538.                 setTimeout(function () {
  539.                     urvanovSyntaxHighlighterSlide(uid, info, false);
  540.                 }, 5000);
  541.             }
  542.  
  543.             if (!show) {
  544.                 urvanovSyntaxHighlighterSlide(uid, info, false);
  545.             }
  546.  
  547.         };
  548.  
  549.         var retina = function (uid) {
  550.             if (window.devicePixelRatio > 1) {
  551.                 var buttons = $('.urvanov-syntax-highlighter-button-icon', urvanov_syntax_highlighters[uid].toolbar);
  552.                 buttons.each(function () {
  553.                     var lowres = $(this).css('background-image');
  554.                     var highres = lowres.replace(/\.(?=[^\.]+$)/g, '@2x.');
  555.                     $(this).css('background-size', '48px 128px');
  556.                     $(this).css('background-image', highres);
  557.                 });
  558.             }
  559.         };
  560.  
  561.         var isSlideHidden = function (object) {
  562.             var object_neg_height = '-' + object.outerHeight() + 'px';
  563.             if (object.css('margin-top') == object_neg_height || object.css('display') == 'none') {
  564.                 return true;
  565.             } else {
  566.                 return false;
  567.             }
  568.         };
  569.  
  570.         var urvanovSyntaxHighlighterSlide = function (uid, object, show, animTime, hideDelay, callback) {
  571.             var complete = function () {
  572.                 if (callback) {
  573.                     callback(uid, object);
  574.                 }
  575.             }
  576.             var objectNegHeight = '-' + object.outerHeight() + 'px';
  577.  
  578.             if (typeof show == 'undefined') {
  579.                 if (isSlideHidden(object)) {
  580.                     show = true;
  581.                 } else {
  582.                     show = false;
  583.                 }
  584.             }
  585.             // Instant means no time delay for showing/hiding
  586.             if (typeof animTime == 'undefined') {
  587.                 animTime = 100;
  588.             }
  589.             if (animTime == false) {
  590.                 animTime = false;
  591.             }
  592.             if (typeof hideDelay == 'undefined') {
  593.                 hideDelay = 0;
  594.             }
  595.             object.stop(true);
  596.             if (show == true) {
  597.                 object.show();
  598.                 object.animate({
  599.                     marginTop: 0
  600.                 }, animt(animTime, uid), complete);
  601.             } else if (show == false) {
  602.                 // Delay if fully visible
  603.                 if (/*instant == false && */object.css('margin-top') == '0px' && hideDelay) {
  604.                     object.delay(hideDelay);
  605.                 }
  606.                 object.animate({
  607.                     marginTop: objectNegHeight
  608.                 }, animt(animTime, uid), function () {
  609.                     object.hide();
  610.                     complete();
  611.                 });
  612.             }
  613.         };
  614.  
  615.         base.togglePlain = function (uid, hover, select) {
  616.             if (typeof urvanov_syntax_highlighters[uid] == 'undefined') {
  617.                 return makeUID(uid);
  618.             }
  619.  
  620.             var main = urvanov_syntax_highlighters[uid].main;
  621.             var plain = urvanov_syntax_highlighters[uid].plain;
  622.  
  623.             if ((main.is(':animated') || plain.is(':animated')) && typeof hover == 'undefined') {
  624.                 return;
  625.             }
  626.  
  627.             reconsileDimensions(uid);
  628.  
  629.             var visible, hidden;
  630.             if (typeof hover != 'undefined') {
  631.                 if (hover) {
  632.                     visible = main;
  633.                     hidden = plain;
  634.                 } else {
  635.                     visible = plain;
  636.                     hidden = main;
  637.                 }
  638.             } else {
  639.                 if (main.css('z-index') == 1) {
  640.                     visible = main;
  641.                     hidden = plain;
  642.                 } else {
  643.                     visible = plain;
  644.                     hidden = main;
  645.                 }
  646.             }
  647.  
  648.             urvanov_syntax_highlighters[uid].plainVisible = (hidden == plain);
  649.  
  650.             // Remember scroll positions of visible
  651.             urvanov_syntax_highlighters[uid].top = visible.scrollTop();
  652.             urvanov_syntax_highlighters[uid].left = visible.scrollLeft();
  653.  
  654.             /* Used to detect a change in overflow when the mouse moves out
  655.              * of the UrvanovSyntaxHighlighter. If it does, then overflow has already been changed,
  656.              * no need to revert it after toggling plain. */
  657.             urvanov_syntax_highlighters[uid].scrollChanged = false;
  658.  
  659.             // Hide scrollbars during toggle to avoid Chrome weird draw error
  660.             // visible.css('overflow', 'hidden');
  661.             // hidden.css('overflow', 'hidden');
  662.  
  663.             fixScrollBlank(uid);
  664.  
  665.             // Show hidden, hide visible
  666.             visible.stop(true);
  667.             visible.fadeTo(animt(500, uid), 0,
  668.                 function () {
  669.                     visible.css('z-index', 0);
  670.                 });
  671.             hidden.stop(true);
  672.             hidden.fadeTo(animt(500, uid), 1,
  673.                 function () {
  674.                     hidden.css('z-index', 1);
  675.                     // Give focus to plain code
  676.                     if (hidden == plain) {
  677.                         if (select) {
  678.                             plain.select();
  679.                         } else {
  680.                             // XXX not needed
  681.                             // plain.focus();
  682.                         }
  683.                     }
  684.  
  685.                     // Refresh scrollbar draw
  686.                     hidden.scrollTop(urvanov_syntax_highlighters[uid].top + 1);
  687.                     hidden.scrollTop(urvanov_syntax_highlighters[uid].top);
  688.                     hidden.scrollLeft(urvanov_syntax_highlighters[uid].left + 1);
  689.                     hidden.scrollLeft(urvanov_syntax_highlighters[uid].left);
  690.                 });
  691.  
  692.             // Restore scroll positions to hidden
  693.             hidden.scrollTop(urvanov_syntax_highlighters[uid].top);
  694.             hidden.scrollLeft(urvanov_syntax_highlighters[uid].left);
  695.  
  696.             updatePlainButton(uid);
  697.  
  698.             // Hide toolbar if possible
  699.             toggleToolbar(uid, false);
  700.             return false;
  701.         };
  702.  
  703.         base.toggleNums = function (uid, hide, instant) {
  704.             if (typeof urvanov_syntax_highlighters[uid] == 'undefined') {
  705.                 makeUID(uid);
  706.                 return false;
  707.             }
  708.  
  709.             if (urvanov_syntax_highlighters[uid].table.is(':animated')) {
  710.                 return false;
  711.             }
  712.             var numsWidth = Math.round(urvanov_syntax_highlighters[uid].nums_content.outerWidth() + 1);
  713.             var negWidth = '-' + numsWidth + 'px';
  714.  
  715.             // Force hiding
  716.             var numHidden;
  717.             if (typeof hide != 'undefined') {
  718.                 numHidden = false;
  719.             } else {
  720.                 // Check hiding
  721.                 numHidden = (urvanov_syntax_highlighters[uid].table.css('margin-left') == negWidth);
  722.             }
  723.  
  724.             var numMargin;
  725.             if (numHidden) {
  726.                 // Show
  727.                 numMargin = '0px';
  728.                 urvanov_syntax_highlighters[uid].numsVisible = true;
  729.             } else {
  730.                 // Hide
  731.                 urvanov_syntax_highlighters[uid].table.css('margin-left', '0px');
  732.                 urvanov_syntax_highlighters[uid].numsVisible = false;
  733.                 numMargin = negWidth;
  734.             }
  735.  
  736.             if (typeof instant != 'undefined') {
  737.                 urvanov_syntax_highlighters[uid].table.css('margin-left', numMargin);
  738.                 updateNumsButton(uid);
  739.                 return false;
  740.             }
  741.  
  742.             // Stop jerking animation from scrollbar appearing for a split second due to
  743.             // change in width. Prevents scrollbar disappearing if already visible.
  744.             var h_scroll_visible = (urvanov_syntax_highlighters[uid].table.outerWidth() + pxToInt(urvanov_syntax_highlighters[uid].table.css('margin-left')) > urvanov_syntax_highlighters[uid].main.outerWidth());
  745.             var v_scroll_visible = (urvanov_syntax_highlighters[uid].table.outerHeight() > urvanov_syntax_highlighters[uid].main.outerHeight());
  746.             if (!h_scroll_visible && !v_scroll_visible) {
  747.                 urvanov_syntax_highlighters[uid].main.css('overflow', 'hidden');
  748.             }
  749.             urvanov_syntax_highlighters[uid].table.animate({
  750.                 marginLeft: numMargin
  751.             }, animt(200, uid), function () {
  752.                 if (typeof urvanov_syntax_highlighters[uid] != 'undefined') {
  753.                     updateNumsButton(uid);
  754.                     if (!h_scroll_visible && !v_scroll_visible) {
  755.                         urvanov_syntax_highlighters[uid].main.css('overflow', 'auto');
  756.                     }
  757.                 }
  758.             });
  759.             return false;
  760.         };
  761.  
  762.         base.toggleWrap = function (uid) {
  763.             urvanov_syntax_highlighters[uid].wrapped = !urvanov_syntax_highlighters[uid].wrapped;
  764.             updateWrap(uid);
  765.         };
  766.  
  767.         base.toggleExpand = function (uid) {
  768.             var expand = !UrvanovSyntaxHighlighterUtil.setDefault(urvanov_syntax_highlighters[uid].expanded, false);
  769.             toggleExpand(uid, expand);
  770.         };
  771.  
  772.         var updateWrap = function (uid, restore) {
  773.             restore = UrvanovSyntaxHighlighterUtil.setDefault(restore, true);
  774.             if (urvanov_syntax_highlighters[uid].wrapped) {
  775.                 urvanov_syntax_highlighters[uid].addClass(URVANOV_SYNTAX_HIGHLIGHTER_WRAPPED);
  776.             } else {
  777.                 urvanov_syntax_highlighters[uid].removeClass(URVANOV_SYNTAX_HIGHLIGHTER_WRAPPED);
  778.             }
  779.             updateWrapButton(uid);
  780.             if (!urvanov_syntax_highlighters[uid].expanded && restore) {
  781.                 restoreDimensions(uid);
  782.             }
  783.             urvanov_syntax_highlighters[uid].wrapTimes = 0;
  784.             clearInterval(urvanov_syntax_highlighters[uid].wrapTimer);
  785.             urvanov_syntax_highlighters[uid].wrapTimer = setInterval(function () {
  786.                 if (urvanov_syntax_highlighters[uid].is(':visible')) {
  787.                     // XXX if hidden the height can't be determined
  788.                     reconsileLines(uid);
  789.                     urvanov_syntax_highlighters[uid].wrapTimes++;
  790.                     if (urvanov_syntax_highlighters[uid].wrapTimes == 5) {
  791.                         clearInterval(urvanov_syntax_highlighters[uid].wrapTimer);
  792.                     }
  793.                 }
  794.             }, 200);
  795.         };
  796.  
  797.         var fixTableWidth = function (uid) {
  798.             if (typeof urvanov_syntax_highlighters[uid] == 'undefined') {
  799.                 makeUID(uid);
  800.                 return false;
  801.             }
  802.         };
  803.  
  804.         // Convert '-10px' to -10
  805.         var pxToInt = function (pixels) {
  806.             if (typeof pixels != 'string') {
  807.                 return 0;
  808.             }
  809.             var result = pixels.replace(/[^-0-9]/g, '');
  810.             if (result.length == 0) {
  811.                 return 0;
  812.             } else {
  813.                 return parseInt(result);
  814.             }
  815.         };
  816.  
  817.         var updateNumsButton = function (uid) {
  818.             if (typeof urvanov_syntax_highlighters[uid] == 'undefined' || typeof urvanov_syntax_highlighters[uid].numsVisible == 'undefined') {
  819.                 return;
  820.             }
  821.             if (urvanov_syntax_highlighters[uid].numsVisible) {
  822.                 urvanov_syntax_highlighters[uid].numsButton.removeClass(UNPRESSED);
  823.                 urvanov_syntax_highlighters[uid].numsButton.addClass(PRESSED);
  824.             } else {
  825.                 // TODO doesn't work on iPhone
  826.                 urvanov_syntax_highlighters[uid].numsButton.removeClass(PRESSED);
  827.                 urvanov_syntax_highlighters[uid].numsButton.addClass(UNPRESSED);
  828.             }
  829.         };
  830.  
  831.         var updateWrapButton = function (uid) {
  832.             if (typeof urvanov_syntax_highlighters[uid] == 'undefined' || typeof urvanov_syntax_highlighters[uid].wrapped == 'undefined') {
  833.                 return;
  834.             }
  835.             if (urvanov_syntax_highlighters[uid].wrapped) {
  836.                 urvanov_syntax_highlighters[uid].wrapButton.removeClass(UNPRESSED);
  837.                 urvanov_syntax_highlighters[uid].wrapButton.addClass(PRESSED);
  838.             } else {
  839.                 // TODO doesn't work on iPhone
  840.                 urvanov_syntax_highlighters[uid].wrapButton.removeClass(PRESSED);
  841.                 urvanov_syntax_highlighters[uid].wrapButton.addClass(UNPRESSED);
  842.             }
  843.         };
  844.  
  845.         var updateExpandButton = function (uid) {
  846.             if (typeof urvanov_syntax_highlighters[uid] == 'undefined' || typeof urvanov_syntax_highlighters[uid].expanded == 'undefined') {
  847.                 return;
  848.             }
  849.  
  850.             if (urvanov_syntax_highlighters[uid].expanded) {
  851.                 urvanov_syntax_highlighters[uid].expandButton.removeClass(UNPRESSED);
  852.                 urvanov_syntax_highlighters[uid].expandButton.addClass(PRESSED);
  853.             } else {
  854.                 // TODO doesn't work on iPhone
  855.                 urvanov_syntax_highlighters[uid].expandButton.removeClass(PRESSED);
  856.                 urvanov_syntax_highlighters[uid].expandButton.addClass(UNPRESSED);
  857.             }
  858.         };
  859.  
  860.         var updatePlainButton = function (uid) {
  861.             if (typeof urvanov_syntax_highlighters[uid] == 'undefined' || typeof urvanov_syntax_highlighters[uid].plainVisible == 'undefined') {
  862.                 return;
  863.             }
  864.  
  865.             if (urvanov_syntax_highlighters[uid].plainVisible) {
  866.                 urvanov_syntax_highlighters[uid].plainButton.removeClass(UNPRESSED);
  867.                 urvanov_syntax_highlighters[uid].plainButton.addClass(PRESSED);
  868.             } else {
  869.                 // TODO doesn't work on iPhone
  870.                 urvanov_syntax_highlighters[uid].plainButton.removeClass(PRESSED);
  871.                 urvanov_syntax_highlighters[uid].plainButton.addClass(UNPRESSED);
  872.             }
  873.         };
  874.  
  875.         var toggleToolbar = function (uid, show, animTime, hideDelay) {
  876.             if (typeof urvanov_syntax_highlighters[uid] == 'undefined') {
  877.                 return makeUID(uid);
  878.             } else if (!urvanov_syntax_highlighters[uid].toolbarMouseover) {
  879.                 return;
  880.             } else if (show == false && urvanov_syntax_highlighters[uid].toolbarPreventHide) {
  881.                 return;
  882.             } else if (touchscreen) {
  883.                 return;
  884.             }
  885.             var toolbar = urvanov_syntax_highlighters[uid].toolbar;
  886.  
  887.             if (typeof hideDelay == 'undefined') {
  888.                 hideDelay = urvanov_syntax_highlighters[uid].toolbar_delay;
  889.             }
  890.  
  891.             urvanovSyntaxHighlighterSlide(uid, toolbar, show, animTime, hideDelay, function () {
  892.                 urvanov_syntax_highlighters[uid].toolbarVisible = show;
  893.             });
  894.         };
  895.  
  896.         var addSize = function (orig, add) {
  897.             var copy = $.extend({}, orig);
  898.             copy.width += add.width;
  899.             copy.height += add.height;
  900.             return copy;
  901.         };
  902.  
  903.         var minusSize = function (orig, minus) {
  904.             var copy = $.extend({}, orig);
  905.             copy.width -= minus.width;
  906.             copy.height -= minus.height;
  907.             return copy;
  908.         };
  909.  
  910.         var initSize = function (uid) {
  911.             if (typeof urvanov_syntax_highlighters[uid].initialSize == 'undefined') {
  912.                 // Shared for scrollbars and expanding
  913.                 urvanov_syntax_highlighters[uid].toolbarHeight = urvanov_syntax_highlighters[uid].toolbar.outerHeight();
  914.                 urvanov_syntax_highlighters[uid].innerSize = {width: urvanov_syntax_highlighters[uid].width(), height: urvanov_syntax_highlighters[uid].height()};
  915.                 urvanov_syntax_highlighters[uid].outerSize = {width: urvanov_syntax_highlighters[uid].outerWidth(), height: urvanov_syntax_highlighters[uid].outerHeight()};
  916.                 urvanov_syntax_highlighters[uid].borderSize = minusSize(urvanov_syntax_highlighters[uid].outerSize, urvanov_syntax_highlighters[uid].innerSize);
  917.                 urvanov_syntax_highlighters[uid].initialSize = {width: urvanov_syntax_highlighters[uid].main.outerWidth(), height: urvanov_syntax_highlighters[uid].main.outerHeight()};
  918.                 urvanov_syntax_highlighters[uid].initialSize.height += urvanov_syntax_highlighters[uid].toolbarHeight;
  919.                 urvanov_syntax_highlighters[uid].initialOuterSize = addSize(urvanov_syntax_highlighters[uid].initialSize, urvanov_syntax_highlighters[uid].borderSize);
  920.                 urvanov_syntax_highlighters[uid].finalSize = {width: urvanov_syntax_highlighters[uid].table.outerWidth(), height: urvanov_syntax_highlighters[uid].table.outerHeight()};
  921.                 urvanov_syntax_highlighters[uid].finalSize.height += urvanov_syntax_highlighters[uid].toolbarHeight;
  922.                 // Ensure we don't shrink
  923.                 urvanov_syntax_highlighters[uid].finalSize.width = UrvanovSyntaxHighlighterUtil.setMin(urvanov_syntax_highlighters[uid].finalSize.width, urvanov_syntax_highlighters[uid].initialSize.width);
  924.                 urvanov_syntax_highlighters[uid].finalSize.height = UrvanovSyntaxHighlighterUtil.setMin(urvanov_syntax_highlighters[uid].finalSize.height, urvanov_syntax_highlighters[uid].initialSize.height);
  925.                 urvanov_syntax_highlighters[uid].diffSize = minusSize(urvanov_syntax_highlighters[uid].finalSize, urvanov_syntax_highlighters[uid].initialSize);
  926.                 urvanov_syntax_highlighters[uid].finalOuterSize = addSize(urvanov_syntax_highlighters[uid].finalSize, urvanov_syntax_highlighters[uid].borderSize);
  927.                 urvanov_syntax_highlighters[uid].initialSize.height += urvanov_syntax_highlighters[uid].toolbar.outerHeight();
  928.             }
  929.         };
  930.  
  931.         var toggleExpand = function (uid, expand) {
  932.             if (typeof urvanov_syntax_highlighters[uid] == 'undefined') {
  933.                 return makeUID(uid);
  934.             }
  935.             if (typeof expand == 'undefined') {
  936.                 return;
  937.             }
  938.  
  939.             var main = urvanov_syntax_highlighters[uid].main;
  940.             var plain = urvanov_syntax_highlighters[uid].plain;
  941.  
  942.             if (expand) {
  943.                 if (typeof urvanov_syntax_highlighters[uid].expanded == 'undefined') {
  944.                     initSize(uid);
  945.                     urvanov_syntax_highlighters[uid].expandTime = UrvanovSyntaxHighlighterUtil.setRange(urvanov_syntax_highlighters[uid].diffSize.width / 3, 300, 800);
  946.                     urvanov_syntax_highlighters[uid].expanded = false;
  947.                     var placeHolderSize = urvanov_syntax_highlighters[uid].finalOuterSize;
  948.                     urvanov_syntax_highlighters[uid].placeholder = $('<div></div>');
  949.                     urvanov_syntax_highlighters[uid].placeholder.addClass(URVANOV_SYNTAX_HIGHLIGHTER_PLACEHOLDER);
  950.                     urvanov_syntax_highlighters[uid].placeholder.css(placeHolderSize);
  951.                     urvanov_syntax_highlighters[uid].before(urvanov_syntax_highlighters[uid].placeholder);
  952.                     urvanov_syntax_highlighters[uid].placeholder.css('margin', urvanov_syntax_highlighters[uid].css('margin'));
  953.                     $(window).bind('resize', placeholderResize);
  954.                 }
  955.  
  956.                 var expandHeight = {
  957.                     'height': 'auto',
  958.                     'min-height': 'none',
  959.                     'max-height': 'none'
  960.                 };
  961.                 var expandWidth = {
  962.                     'width': 'auto',
  963.                     'min-width': 'none',
  964.                     'max-width': 'none'
  965.                 };
  966.  
  967.                 urvanov_syntax_highlighters[uid].outerWidth(urvanov_syntax_highlighters[uid].outerWidth());
  968.                 urvanov_syntax_highlighters[uid].css({
  969.                     'min-width': 'none',
  970.                     'max-width': 'none'
  971.                 });
  972.                 var newSize = {
  973.                     width: urvanov_syntax_highlighters[uid].finalOuterSize.width
  974.                 };
  975.                 if (!urvanov_syntax_highlighters[uid].mainHeightAuto && !urvanov_syntax_highlighters[uid].hasOneLine) {
  976.                     newSize.height = urvanov_syntax_highlighters[uid].finalOuterSize.height;
  977.                     urvanov_syntax_highlighters[uid].outerHeight(urvanov_syntax_highlighters[uid].outerHeight());
  978.                 }
  979.  
  980.                 main.css(expandHeight);
  981.                 main.css(expandWidth);
  982.                 urvanov_syntax_highlighters[uid].stop(true);
  983.  
  984.                 urvanov_syntax_highlighters[uid].animate(newSize, animt(urvanov_syntax_highlighters[uid].expandTime, uid), function () {
  985.                     urvanov_syntax_highlighters[uid].expanded = true;
  986.                     updateExpandButton(uid);
  987.                 });
  988.  
  989.                 urvanov_syntax_highlighters[uid].placeholder.show();
  990.                 $('body').prepend(urvanov_syntax_highlighters[uid]);
  991.                 urvanov_syntax_highlighters[uid].addClass(URVANOV_SYNTAX_HIGHLIGHTER_EXPANDED);
  992.                 placeholderResize();
  993.             } else {
  994.                 var initialSize = urvanov_syntax_highlighters[uid].initialOuterSize;
  995.                 var delay = urvanov_syntax_highlighters[uid].toolbar_delay;
  996.                 if (initialSize) {
  997.                     urvanov_syntax_highlighters[uid].stop(true);
  998.                     if (!urvanov_syntax_highlighters[uid].expanded) {
  999.                         urvanov_syntax_highlighters[uid].delay(delay);
  1000.                     }
  1001.                     var newSize = {
  1002.                         width: initialSize.width
  1003.                     };
  1004.                     if (!urvanov_syntax_highlighters[uid].mainHeightAuto && !urvanov_syntax_highlighters[uid].hasOneLine) {
  1005.                         newSize.height = initialSize.height;
  1006.                     }
  1007.                     urvanov_syntax_highlighters[uid].animate(newSize, animt(urvanov_syntax_highlighters[uid].expandTime, uid), function () {
  1008.                         expandFinish(uid);
  1009.                     });
  1010.                 } else {
  1011.                     setTimeout(function () {
  1012.                        expandFinish(uid);
  1013.                     }, delay);
  1014.                 }
  1015.                 urvanov_syntax_highlighters[uid].placeholder.hide();
  1016.                 urvanov_syntax_highlighters[uid].placeholder.before(urvanov_syntax_highlighters[uid]);
  1017.                 urvanov_syntax_highlighters[uid].css({left: 'auto', top: 'auto'});
  1018.                 urvanov_syntax_highlighters[uid].removeClass(URVANOV_SYNTAX_HIGHLIGHTER_EXPANDED);
  1019.             }
  1020.  
  1021.             reconsileDimensions(uid);
  1022.             if (expand) {
  1023.                 updateWrap(uid, false);
  1024.             }
  1025.         };
  1026.  
  1027.         var placeholderResize = function () {
  1028.             for (uid in urvanov_syntax_highlighters) {
  1029.                 if (urvanov_syntax_highlighters[uid].hasClass(URVANOV_SYNTAX_HIGHLIGHTER_EXPANDED)) {
  1030.                     urvanov_syntax_highlighters[uid].css(urvanov_syntax_highlighters[uid].placeholder.offset());
  1031.                 }
  1032.             }
  1033.         };
  1034.  
  1035.         var expandFinish = function(uid) {
  1036.             urvanov_syntax_highlighters[uid].expanded = false;
  1037.             restoreDimensions(uid);
  1038.             updateExpandButton(uid);
  1039.             if (urvanov_syntax_highlighters[uid].wrapped) {
  1040.                 updateWrap(uid);
  1041.             }
  1042.         };
  1043.  
  1044.         var toggle_scroll = function (uid, show, expand) {
  1045.             if (typeof urvanov_syntax_highlighters[uid] == 'undefined') {
  1046.                 return makeUID(uid);
  1047.             }
  1048.             if (typeof show == 'undefined' || expand || urvanov_syntax_highlighters[uid].expanded) {
  1049.                 return;
  1050.             }
  1051.  
  1052.             var main = urvanov_syntax_highlighters[uid].main;
  1053.             var plain = urvanov_syntax_highlighters[uid].plain;
  1054.  
  1055.             if (show) {
  1056.                 // Show scrollbars
  1057.                 main.css('overflow', 'auto');
  1058.                 plain.css('overflow', 'auto');
  1059.                 if (typeof urvanov_syntax_highlighters[uid].top != 'undefined') {
  1060.                     visible = (main.css('z-index') == 1 ? main : plain);
  1061.                     // Browser will not render until scrollbar moves, move it manually
  1062.                     visible.scrollTop(urvanov_syntax_highlighters[uid].top - 1);
  1063.                     visible.scrollTop(urvanov_syntax_highlighters[uid].top);
  1064.                     visible.scrollLeft(urvanov_syntax_highlighters[uid].left - 1);
  1065.                     visible.scrollLeft(urvanov_syntax_highlighters[uid].left);
  1066.                 }
  1067.             } else {
  1068.                 // Hide scrollbars
  1069.                 visible = (main.css('z-index') == 1 ? main : plain);
  1070.                 urvanov_syntax_highlighters[uid].top = visible.scrollTop();
  1071.                 urvanov_syntax_highlighters[uid].left = visible.scrollLeft();
  1072.                 main.css('overflow', 'hidden');
  1073.                 plain.css('overflow', 'hidden');
  1074.             }
  1075.             // Register that overflow has changed
  1076.             urvanov_syntax_highlighters[uid].scrollChanged = true;
  1077.             fixScrollBlank(uid);
  1078.         };
  1079.  
  1080.         /* Fix weird draw error, causes blank area to appear where scrollbar once was. */
  1081.         var fixScrollBlank = function (uid) {
  1082.             // Scrollbar draw error in Chrome
  1083.             urvanov_syntax_highlighters[uid].table.style('width', '100%', 'important');
  1084.             var redraw = setTimeout(function () {
  1085.                 urvanov_syntax_highlighters[uid].table.style('width', '');
  1086.                 clearInterval(redraw);
  1087.             }, 10);
  1088.         };
  1089.  
  1090.         var restoreDimensions = function (uid) {
  1091.             // Restore dimensions
  1092.             var main = urvanov_syntax_highlighters[uid].main;
  1093.             var mainStyle = urvanov_syntax_highlighters[uid].mainStyle;
  1094.             main.css(mainStyle);
  1095.             // Width styles also apply to urvanovSyntaxHighlighter
  1096.             urvanov_syntax_highlighters[uid].css('height', 'auto');
  1097.             urvanov_syntax_highlighters[uid].css('width', mainStyle['width']);
  1098.             urvanov_syntax_highlighters[uid].css('max-width', mainStyle['max-width']);
  1099.             urvanov_syntax_highlighters[uid].css('min-width', mainStyle['min-width']);
  1100.         };
  1101.  
  1102.         var reconsileDimensions = function (uid) {
  1103.             // Reconsile dimensions
  1104.             urvanov_syntax_highlighters[uid].plain.outerHeight(urvanov_syntax_highlighters[uid].main.outerHeight());
  1105.         };
  1106.  
  1107.         var reconsileLines = function (uid) {
  1108.             $(URVANOV_SYNTAX_HIGHLIGHTER_NUM, urvanov_syntax_highlighters[uid]).each(function () {
  1109.                 var lineID = $(this).attr('data-line');
  1110.                 var line = $('#' + lineID);
  1111.                 var height = null;
  1112.                 if (urvanov_syntax_highlighters[uid].wrapped) {
  1113.                     line.css('height', '');
  1114.                     height = line.outerHeight();
  1115.                     height = height ? height : '';
  1116.                     // TODO toolbar should overlay title if needed
  1117.                 } else {
  1118.                     height = line.attr('data-height');
  1119.                     height = height ? height : '';
  1120.                     line.css('height', height);
  1121.                     //line.css('height', line.css('line-height'));
  1122.                 }
  1123.                 $(this).css('height', height);
  1124.             });
  1125.         };
  1126.  
  1127.         var animt = function (x, uid) {
  1128.             if (x == 'fast') {
  1129.                 x = 200;
  1130.             } else if (x == 'slow') {
  1131.                 x = 600;
  1132.             } else if (!isNumber(x)) {
  1133.                 x = parseInt(x);
  1134.                 if (isNaN(x)) {
  1135.                     return 0;
  1136.                 }
  1137.             }
  1138.             return x * urvanov_syntax_highlighters[uid].time;
  1139.         };
  1140.  
  1141.         var isNumber = function (x) {
  1142.             return typeof x == 'number';
  1143.         };
  1144.  
  1145.     };
  1146.  
  1147.     $(document).ready(function () {
  1148.         UrvanovSyntaxHighlighterSyntax.init();
  1149.     });
  1150. })(jQueryUrvanovSyntaxHighlighter);

Raw Paste


Login or Register to edit or fork this paste. It's free.