Advertisement
Romul81

GoldenDict Enhancer src v2.3

Aug 6th, 2017
403
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // ver. 2.3
  2. 'use strict';
  3.  
  4. if ('undefined' == typeof GDEnhancer) {
  5.     var GDEnhancer = (function() {
  6.         function run(md5Id) {
  7.             function getSum(num) {
  8.                 var strNum = num.toString();
  9.                 var strLen = strNum.length;
  10.                 var sum = 0;
  11.                 for (var i = 0; i < strLen; i++) {
  12.                     sum += parseInt(strNum[i]);
  13.                 }
  14.                 return sum < 10 ? sum : getSum(sum);
  15.             }
  16.  
  17.             function hashCode(s) {
  18.                 return s.split('').reduce(function(a, b) {
  19.                     a = (a << 5) - a + b.charCodeAt(0);
  20.                     return a & a;
  21.                 }, 0);
  22.             }
  23.  
  24.             function getSiblings(node) {
  25.                 while ((node = node.nextElementSibling)) {
  26.                     node.classList.add('gde-content');
  27.                 }
  28.             }
  29.  
  30.             function processOptContent(defCol, optTag) {
  31.                 var contentWithOptArr = [];
  32.                 for (var i = 0; i < defCol.length; i++) {
  33.                     var dicHeadword,
  34.                         defElem = defCol[i];
  35.                     if (defElem.querySelector('.' + optTag)) {
  36.                         defElem.classList.add('gde-opt');
  37.                         dicHeadword = getElement(
  38.                             getElement(
  39.                                 defElem,
  40.                                 'gddefinition',
  41.                                 'parentElement'
  42.                             ),
  43.                             'gdheadword',
  44.                             'previousElementSibling'
  45.                         );
  46.                         contentWithOptArr.push(new Array(dicHeadword, defElem));
  47.                     }
  48.                 }
  49.                 contentWithOptArr.forEach(function(item) {
  50.                     var optToggler = document.createElement('span');
  51.                     optToggler.className = 'gde-hwbtn gde-btnmin gde-btnplus';
  52.                     item[0].appendChild(optToggler);
  53.                     optToggler.addEventListener('click', function(event) {
  54.                         event.stopPropagation();
  55.                         toggleOpt.call(item[1], optToggler);
  56.                     });
  57.                 });
  58.             }
  59.  
  60.             function toggleOpt(headword) {
  61.                 headword.classList.toggle('gde-btnplus');
  62.                 this.classList.toggle('gde-opt');
  63.                 updatePage();
  64.             }
  65.  
  66.             function toggleContent(event) {
  67.                 event.stopPropagation();
  68.                 this.classList.toggle('gde-artexp');
  69.                 this.classList.toggle('gde-artcol');
  70.                 updatePage();
  71.             }
  72.  
  73.             function fitImg(evt) {
  74.                 if (evt.target.nodeName === 'IMG') {
  75.                     evt.target.classList.toggle('gde-img');
  76.                     updatePage();
  77.                 }
  78.             }
  79.             var gdArticle = document.getElementById('gdarticle-' + md5Id),
  80.                 gdDictname = gdArticle.getElementsByClassName('gddictname')[0],
  81.                 dicRef = document.getElementById('gdarticleref-' + md5Id),
  82.                 dicFooter = document.createElement('div'),
  83.                 dicFooterCross = document.createElement('span'),
  84.                 dicToggler = document.createElement('span'),
  85.                 colorArr = [
  86.                     'purple',
  87.                     'deeppurple',
  88.                     'indigo',
  89.                     'blue',
  90.                     'green',
  91.                     'lightgreen',
  92.                     'lime',
  93.                     'yellow',
  94.                     'amber'
  95.                 ];
  96.             gdDictname.classList.add('gde-artexp');
  97.             dicFooter.className = 'gde-footer';
  98.             dicFooterCross.className = 'gde-cross';
  99.             dicToggler.className = 'gde-dicname';
  100.             gdDictname.appendChild(dicToggler);
  101.             dicFooter.appendChild(dicFooterCross);
  102.             gdArticle.appendChild(dicFooter);
  103.             gdArticle.classList.add(
  104.                 'gde-' + colorArr[getSum(Math.abs(hashCode(md5Id))) - 1]
  105.             );
  106.             getSiblings(gdDictname);
  107.             gdDictname.addEventListener('click', toggleContent);
  108.             dicFooter.addEventListener('click', function(event) {
  109.                 toggleContent.call(gdDictname, event);
  110.                 GDE.jump(Math.ceil(dicRef.getBoundingClientRect().top), {
  111.                     duration: _duration,
  112.                     callback: afterScrollTimeOut
  113.                 });
  114.             });
  115.             var dslDef = gdArticle.getElementsByClassName('dsl_definition');
  116.             if (dslDef.length) {
  117.                 processOptContent(dslDef, 'dsl_opt');
  118.             }
  119.             var sdctX = gdArticle.getElementsByClassName('sdct_x');
  120.             if (sdctX.length) {
  121.                 processOptContent(sdctX, 'xdxf_ex');
  122.             }
  123.             gdArticle.addEventListener(
  124.                 'click',
  125.                 function() {
  126.                     gdMakeArticleActive(md5Id);
  127.                     isClicked = true;
  128.                 },
  129.                 true
  130.             );
  131.             if (gdArticle.getElementsByTagName('img').length) {
  132.                 gdArticle.addEventListener('click', fitImg);
  133.             }
  134.             requestAnimationFrame(function() {
  135.                 updatePage(gdArticle);
  136.             });
  137.         }
  138.  
  139.         function getElement(elem, cls, method) {
  140.             while ((elem = elem[method]) && !elem.classList.contains(cls));
  141.             return elem;
  142.         }
  143.  
  144.         function ready() {
  145.             function check(mutationRecords) {
  146.                 var addedNode, currentDicId, artTempl, cachedContent;
  147.                 for (var i = 0; i < mutationRecords.length; i++) {
  148.                     for (
  149.                         var j = 0;
  150.                         j < mutationRecords[i].addedNodes.length;
  151.                         j++
  152.                     ) {
  153.                         addedNode = mutationRecords[i].addedNodes[j];
  154.                         if (addedNode.nodeType === 1) {
  155.                             switch (addedNode.localName) {
  156.                                 case 'script':
  157.                                     if (
  158.                                         !!(currentDicId = addedNode.innerHTML.split(
  159.                                             /['"]/
  160.                                         )[1]) &&
  161.                                         currentDicId.length === 32
  162.                                     ) {
  163.                                         if (
  164.                                             !selfDeleted &&
  165.                                             selfDictId === currentDicId
  166.                                         ) {
  167.                                             selfDeleted = true;
  168.                                             addedNode.remove();
  169.                                             selfDict.remove();
  170.                                             selfDict = null;
  171.                                             selfDictRef.remove();
  172.                                             selfDictRef = null;
  173.                                         } else if (
  174.                                             microcache.contains(currentDicId) &&
  175.                                             (cachedContent = microcache.get(
  176.                                                 currentDicId
  177.                                             ))
  178.                                         ) {
  179.                                             //typeof cachedContent == 'number' ? console.log('cachedContent: ' + cachedContent) : void 0;
  180.                                             if (
  181.                                                 cachedContent !== null &&
  182.                                                 typeof cachedContent != 'number'
  183.                                             ) {
  184.                                                 cachedContent.content.appendChild(
  185.                                                     addedNode
  186.                                                 );
  187.                                                 delayDicArr.push(currentDicId);
  188.                                                 delayDicHistArr.push(
  189.                                                     currentDicId
  190.                                                 );
  191.                                                 if (
  192.                                                     delayDicHistArr.length <=
  193.                                                         dicCountToLoad ||
  194.                                                     !hasScrollbar
  195.                                                 ) {
  196.                                                     //console.time('appendTempl');
  197.                                                     appendTempl(
  198.                                                         delayDicArr.shift()
  199.                                                     );
  200.                                                     //console.timeEnd('appendTempl');
  201.                                                 }
  202.                                             }
  203.                                         }
  204.                                     }
  205.                                     break;
  206.  
  207.                                 case 'span':
  208.                                     if (
  209.                                         /^gdarticle(?:ref)?/i.test(
  210.                                             addedNode.className
  211.                                         ) &&
  212.                                         (currentDicId = addedNode.id
  213.                                             .split('-')
  214.                                             .pop()) &&
  215.                                         !~delayDicHistArr.indexOf(currentDicId)
  216.                                     ) {
  217.                                         if (
  218.                                             addedNode.className ===
  219.                                             'gdarticleref'
  220.                                         ) {
  221.                                             artTempl = document.createElement(
  222.                                                 'template'
  223.                                             );
  224.                                             artTempl.id =
  225.                                                 'template-' + currentDicId;
  226.                                             artTempl.content.appendChild(
  227.                                                 addedNode
  228.                                             );
  229.                                             microcache.set(
  230.                                                 currentDicId,
  231.                                                 artTempl
  232.                                             );
  233.                                         } else if (
  234.                                             microcache.contains(currentDicId)
  235.                                         ) {
  236.                                             microcache
  237.                                                 .get(currentDicId)
  238.                                                 .content.appendChild(addedNode);
  239.                                         }
  240.                                     }
  241.                             }
  242.                         }
  243.                     }
  244.                 }
  245.             }
  246.             var MutationObserver =
  247.                 window.MutationObserver || window.WebKitMutationObserver;
  248.             if (!observer) {
  249.                 observer = new MutationObserver(check);
  250.                 observer.observe(document.body, {
  251.                     childList: true
  252.                 });
  253.             }
  254.         }
  255.  
  256.         function observerDisconnect() {
  257.             observer.disconnect();
  258.             isLoaded = true;
  259.         }
  260.  
  261.         function appendTempl(dicId) {
  262.             function unwrap(wrapper) {
  263.                 var parent = wrapper.parentNode;
  264.                 while (wrapper.firstChild) {
  265.                     parent.insertBefore(wrapper.firstChild, wrapper);
  266.                 }
  267.                 parent.removeChild(wrapper);
  268.             }
  269.  
  270.             function processDslDef(elem) {
  271.                 function isBlank(el) {
  272.                     return (
  273.                         el.nodeType === 3 && el.nodeValue.trim().length === 0
  274.                     );
  275.                 }
  276.  
  277.                 function isPureChild(elem) {
  278.                     if (
  279.                         !!elem.previousElementSibling ||
  280.                         !!elem.nextElementSibling
  281.                     )
  282.                         return false;
  283.                     var prevSibling = elem.previousSibling,
  284.                         nextSibling = elem.nextSibling;
  285.                     if (!prevSibling && !nextSibling) return true;
  286.                     if (!prevSibling && nextSibling) {
  287.                         return isBlank(nextSibling);
  288.                     } else if (prevSibling && !nextSibling) {
  289.                         return isBlank(prevSibling);
  290.                     } else return isBlank(prevSibling) && isBlank(nextSibling);
  291.                 }
  292.  
  293.                 function getMaxBlank(emptyTag) {
  294.                     for (var parent; emptyTag; ) {
  295.                         parent = emptyTag.parentNode;
  296.                         if (
  297.                             ~blockTags.indexOf(parent.nodeName) ||
  298.                             parent.classList.contains('dsl_definition') ||
  299.                             parent.textContent.trim().length !== 0
  300.                         )
  301.                             return emptyTag;
  302.                         emptyTag = parent;
  303.                     }
  304.                 }
  305.  
  306.                 function isBreak(el) {
  307.                     switch (el.nodeType) {
  308.                         case 1:
  309.                             return !!~blockTags.indexOf(el.nodeName);
  310.  
  311.                         case 3:
  312.                             return !/\S/.test(el.nodeValue)
  313.                                 ? (
  314.                                       (el = el.nextSibling),
  315.                                       el ? isBreak(el) : true
  316.                                   )
  317.                                 : false;
  318.                     }
  319.                 }
  320.  
  321.                 function merge(pureChild) {
  322.                     var parent;
  323.                     do {
  324.                         parent = pureChild.parentNode;
  325.                         if (!~tagArr.indexOf(pureChild.nodeName)) continue;
  326.                         if (pureChild.className.length !== 0) {
  327.                             parent.className +=
  328.                                 (parent.className.length !== 0 ? ' ' : '') +
  329.                                 pureChild.className;
  330.                         }
  331.                         unwrap(pureChild);
  332.                     } while ((pureChild = parent) && isPureChild(pureChild));
  333.                 }
  334.                 var elems = elem.getElementsByTagName('p'),
  335.                     elemsLen = elems.length,
  336.                     tagArr = ['B', 'DIV', 'I', 'P', 'SPAN'],
  337.                     toDelArr = [],
  338.                     blockTags = ['DIV', 'P'],
  339.                     toMergeArr = [],
  340.                     toDelEl,
  341.                     pBlank,
  342.                     toDelNextEl;
  343.                 for (var i = 0; i < elemsLen; i++) {
  344.                     pBlank = elems[i];
  345.                     if (
  346.                         !pBlank.firstElementChild &&
  347.                         (!pBlank.hasChildNodes() || isBlank(pBlank.firstChild))
  348.                     ) {
  349.                         toDelEl = getMaxBlank(pBlank);
  350.                         toDelNextEl = toDelEl.nextSibling;
  351.                         if (!toDelNextEl || isBreak(toDelNextEl))
  352.                             toDelArr.push(toDelEl);
  353.                     }
  354.                 }
  355.                 while (toDelArr.length) {
  356.                     toDelArr.pop().remove();
  357.                 }
  358.                 var allElems = elem.getElementsByTagName('*'),
  359.                     allElemsLen = allElems.length,
  360.                     currentElem;
  361.                 for (i = 0; i < allElemsLen; i++) {
  362.                     currentElem = allElems[i];
  363.                     if (
  364.                         currentElem.nextElementSibling ||
  365.                         currentElem.previousElementSibling ||
  366.                         !~tagArr.indexOf(currentElem.nodeName)
  367.                     )
  368.                         continue;
  369.                     if (
  370.                         (!currentElem.firstElementChild ||
  371.                             !isPureChild(currentElem.firstElementChild)) &&
  372.                         isPureChild(currentElem)
  373.                     ) {
  374.                         toMergeArr.push(currentElem);
  375.                     }
  376.                 }
  377.                 while (toMergeArr.length) {
  378.                     merge(toMergeArr.pop());
  379.                 }
  380.             }
  381.             var templ = microcache.get(dicId);
  382.             if (templ) {
  383.                 var gdArt = templ.content.querySelector('#gdarticle-' + dicId),
  384.                     gde = gdArt.getElementsByClassName('gde'),
  385.                     toMergeDef = gdArt.getElementsByClassName('dsl_definition'),
  386.                     lsaPlay = gdArt.getElementsByClassName('lsa_play');
  387.                 for (var i = gde.length - 1; i >= 0; i--) {
  388.                     var gdeParent = gde[i].parentNode;
  389.                     var gdeAdj = gdeParent.getElementsByClassName('gde');
  390.                     for (var j = gdeAdj.length - 1; j >= 0; j--) {
  391.                         if (j !== 0) i--;
  392.                         unwrap(gdeAdj[j]);
  393.                     }
  394.                     gdeParent.normalize();
  395.                 }
  396.                 if (toMergeDef.length) {
  397.                     //console.time('processDslDef');
  398.                     for (i = 0; i < toMergeDef.length; i++) {
  399.                         processDslDef(toMergeDef[i]);
  400.                     }
  401.                     var wavElems = gdArt.getElementsByClassName('dsl_s_wav'),
  402.                         wavElemsLen = wavElems.length,
  403.                         audioScript;
  404.                     if (wavElemsLen) {
  405.                         for (i = wavElemsLen - 1; i >= 0; i--) {
  406.                             if (i === 0) {
  407.                                 wavElems[0]
  408.                                     .getElementsByTagName('a')[0]
  409.                                     .classList.add('gde-fstwav');
  410.                                 continue;
  411.                             } else {
  412.                                 audioScript =
  413.                                     wavElems[i].previousElementSibling;
  414.                                 if (audioScript.localName === 'script')
  415.                                     audioScript.remove();
  416.                             }
  417.                         }
  418.                     }
  419.                     //console.timeEnd('processDslDef');
  420.                 }
  421.                 if (lsaPlay.length) {
  422.                     lsaPlay[0]
  423.                         .getElementsByTagName('a')[0]
  424.                         .classList.add('gde-fstwav');
  425.                 }
  426.                 var clone = document.importNode(templ.content, true);
  427.                 document.body.appendChild(clone);
  428.                 microcache.set(dicId, null);
  429.                 run(dicId);
  430.             }
  431.         }
  432.  
  433.         function updatePage(art) {
  434.             if ('undefined' != typeof art) {
  435.                 art.style.display = 'block';
  436.             }
  437.             requestAnimationFrame(measure);
  438.         }
  439.  
  440.         function debounce(func, wait) {
  441.             var timeout, args, context, timestamp;
  442.             var later = function() {
  443.                 var last = Date.now() - timestamp;
  444.                 if (!isScrolling) {
  445.                     //console.log('Scroll Start!')
  446.                     document.body.classList.add('gde-scroll');
  447.                     isScrolling = true;
  448.                 }
  449.                 if (last < wait) {
  450.                     timeout = setTimeout(later, wait - last);
  451.                 } else {
  452.                     timeout = null;
  453.                     func.apply(context, args);
  454.                     return;
  455.                 }
  456.             };
  457.             return function onScrollFn() {
  458.                 context = this;
  459.                 args = arguments;
  460.                 timestamp = Date.now();
  461.                 if (!timeout) {
  462.                     timeout = setTimeout(later, wait);
  463.                 }
  464.             };
  465.         }
  466.  
  467.         function inView(articleId) {
  468.             var currentOffset = Math.round(currentYOffset);
  469.             var dicIdx = gdToc.indexOf(articleId);
  470.             var dicOffset = microcache.get(gdToc[dicIdx]);
  471.             return (
  472.                 currentOffset <= dicOffset && currentOffset + winH > dicOffset
  473.             );
  474.         }
  475.         /*function onResize() {
  476.             if (delayDicArr.length) {
  477.                 currentYOffset = window.pageYOffset;
  478.                 winH = document.documentElement.clientHeight;
  479.                 lastYOffset = 0;
  480.                 measure();
  481.             }
  482.         }*/
  483.         // Start
  484.         var GDE = {},
  485.             currentYOffset = 0,
  486.             delay = 1e3 / 15,
  487.             delayDicArr = [],
  488.             delayDicHistArr = [],
  489.             dicCountToLoad = 5,
  490.             isClicked = false,
  491.             isLoaded = false,
  492.             isScrolling = false,
  493.             lastAfterScrollTime = 0,
  494.             lastMeasureTime = 0,
  495.             lastYOffset = 0,
  496.             selfDeleted = false,
  497.             winH = document.documentElement.clientHeight,
  498.             _duration,
  499.             hasScrollbar,
  500.             lineH,
  501.             observer,
  502.             scrollHeight,
  503.             selfDict,
  504.             selfDictId,
  505.             selfDictRef,
  506.             MicroCache = function() {
  507.                 var _values = {};
  508.                 return {
  509.                     get: function(key) {
  510.                         return _values[key];
  511.                     },
  512.                     contains: function(key) {
  513.                         return key in _values;
  514.                     },
  515.                     set: function(key, value) {
  516.                         _values[key] = value;
  517.                     }
  518.                 };
  519.             },
  520.             microcache = new MicroCache(),
  521.             measure = function(time) {
  522.                 if (time) {
  523.                     var last = time - lastMeasureTime;
  524.                     if (last < 1e3 / 60) return;
  525.                     lastMeasureTime = time;
  526.                 }
  527.                 var dicsToc = gdToc,
  528.                     currentDicOffsetTop,
  529.                     currentKeyVal,
  530.                     currentId;
  531.                 for (var i = dicsToc.length - 1; i >= 0; i--) {
  532.                     currentId = dicsToc[i];
  533.                     currentDicOffsetTop = document.getElementById(
  534.                         'gdarticleref-' + currentId
  535.                     ).offsetTop;
  536.                     //console.log(currentId + ': ' + currentDicOffsetTop);
  537.                     currentKeyVal = microcache.get(currentId);
  538.                     if (currentDicOffsetTop !== currentKeyVal) {
  539.                         microcache.set(currentId, currentDicOffsetTop);
  540.                     } else break;
  541.                 }
  542.                 scrollHeight = document.body.scrollHeight;
  543.                 hasScrollbar = scrollHeight > winH;
  544.                 //console.log('measured!');
  545.                 //console.log('delayDicArr.length: ' + delayDicArr.length);
  546.                 if (delayDicArr.length && !hasScrollbar)
  547.                     requestAnimationFrame(afterScroll);
  548.             },
  549.             afterScroll = function(time) {
  550.                 if (time) {
  551.                     var last = time - lastAfterScrollTime;
  552.                     if (last < 1e3 / 30) return;
  553.                     lastAfterScrollTime = time;
  554.                 }
  555.                 currentYOffset = window.pageYOffset;
  556.                 if (currentYOffset >= lastYOffset && delayDicArr.length) {
  557.                     var lastDicTop;
  558.                     if (
  559.                         (lastDicTop = document.getElementById(
  560.                             'gdarticleref-' + gdToc[gdToc.length - 1]
  561.                         ).offsetTop) &&
  562.                         winH + currentYOffset > lastDicTop - winH /* / 2*/
  563.                     ) {
  564.                         //console.time('appendTempl');
  565.                         appendTempl(delayDicArr.shift());
  566.                         //console.timeEnd('appendTempl');
  567.                         requestAnimationFrame(afterScrollTimeOut);
  568.                     }
  569.                 }
  570.                 if (gdToc.length > 0) {
  571.                     var currentIdx = _gdFindNextArticleToScrollTo();
  572.                     if (currentIdx > 0) {
  573.                         --currentIdx;
  574.                         if (isClicked) {
  575.                             if (!inView(gdCurrentArticle)) {
  576.                                 gdMakeArticleActive(gdToc[currentIdx]);
  577.                                 isClicked = false;
  578.                             }
  579.                         } else {
  580.                             gdMakeArticleActive(gdToc[currentIdx]);
  581.                         }
  582.                     }
  583.                 }
  584.                 document.body.classList.remove('gde-scroll');
  585.                 isScrolling = false;
  586.                 lastYOffset = currentYOffset;
  587.             },
  588.             afterScrollTimeOut = function() {
  589.                 setTimeout(afterScroll, delay);
  590.             },
  591.             onScroll = debounce(function() {
  592.                 requestAnimationFrame(afterScroll);
  593.             }, delay);
  594.  
  595.         /******* init Function *******/
  596.         GDE.init = function() {
  597.             var achtungStyle =
  598.                 'font-size:2em;position:fixed;z-index:999;top:0;left:0;box-sizing:border-box;padding:1em;text-align:center;color:#fff;background-color:#8b0000';
  599.             if (gdToc.length) {
  600.                 var achtung = document.createElement('div');
  601.                 achtung.className = 'gde-achtung';
  602.                 achtung.style = achtungStyle;
  603.                 achtung.innerHTML =
  604.                     'Put <b style="color:#ffff00">GoldenDict Enhancer</b> at the <b style="color:#ff00ff">TOP</b> of the dictionary list!<br> And try again ;-)';
  605.                 document.body.insertBefore(achtung, document.body.firstChild);
  606.                 return;
  607.             }
  608.             var cssCheck = document.createElement('div');
  609.             cssCheck.id = 'gde-csscheck';
  610.             cssCheck.style = achtungStyle;
  611.             cssCheck.innerHTML =
  612.                 'It seems there is some <b style="color:#ff00ff">problem</b> with the custom <b style="color:#ffff00">article-style.css</b>!';
  613.             document.body.insertBefore(cssCheck, document.body.firstChild);
  614.             var isAchtungHidden = (function() {
  615.                 var style = window.getComputedStyle(cssCheck);
  616.                 return style.display === 'none';
  617.             })();
  618.             if (!isAchtungHidden) return;
  619.             lineH = (function() {
  620.                 var temp = document.createElement('div');
  621.                 temp.innerText = 'test';
  622.                 temp = document.body.appendChild(temp);
  623.                 var ret = temp.clientHeight;
  624.                 temp.remove();
  625.                 return ret;
  626.             })();
  627.             //console.log(lineH);
  628.             var gdeCss = document.createElement('style');
  629.             gdeCss.innerHTML = '.gdarticle {display: none;}';
  630.             document.head.appendChild(gdeCss);
  631.             window.removeEventListener('click', _gdHandleWordClick, false);
  632.             window.addEventListener('scroll', onScroll);
  633.             //window.addEventListener('resize', onResize);
  634.             var scr = document.currentScript;
  635.             selfDict = getElement(scr, 'gdarticle', 'parentElement');
  636.             selfDictId = selfDict.id.split('-').pop();
  637.             selfDictRef = document.getElementById('gdarticleref-' + selfDictId);
  638.             selfDictRef.style.display = 'none';
  639.             ready();
  640.             var ifLoaded = function(fn) {
  641.                 if (document.readyState === 'complete') {
  642.                     return fn();
  643.                 }
  644.                 document.addEventListener('DOMContentLoaded', fn);
  645.             };
  646.             ifLoaded(observerDisconnect);
  647.             _duration = function(distance) {
  648.                 //console.log(distance);
  649.                 var duration = Math.sqrt(1e4 * Math.abs(distance) / winH);
  650.                 return duration > 350 ? duration : 350;
  651.             };
  652.             /****** patching article-script.js ******/
  653.             _gdGetWordAtPoint = function(elem, x, y) {
  654.                 if (
  655.                     1 === elem.nodeType &&
  656.                     ('A' === elem.nodeName ||
  657.                         elem.classList.contains('gddictname'))
  658.                 )
  659.                     return null;
  660.                 if (3 === elem.nodeType) {
  661.                     var range = elem.ownerDocument.createRange();
  662.                     range.selectNodeContents(elem);
  663.                     for (
  664.                         var currentPos = 0,
  665.                             endPos = range.endOffset,
  666.                             wordStartPos = 0,
  667.                             start = false;
  668.                         currentPos < endPos;
  669.                         currentPos++
  670.                     ) {
  671.                         range.setStart(elem, currentPos);
  672.                         range.setEnd(elem, currentPos + 1);
  673.                         if (
  674.                             /[\s!-#%-\x29,-/:-@\x5B-\x5D^_\x7B-\x7E¡§«¶·»¿;]/.test(
  675.                                 range.toString()
  676.                             )
  677.                         ) {
  678.                             if (start) {
  679.                                 range.setStart(elem, wordStartPos);
  680.                                 range.setEnd(elem, currentPos);
  681.                                 start = false;
  682.                                 var ret = _gdCheckRange(range, x, y);
  683.                                 if (null !== ret) return ret;
  684.                             }
  685.                         } else
  686.                             start ||
  687.                                 ((wordStartPos = currentPos), (start = true));
  688.                     }
  689.                     if (start) {
  690.                         range.setStart(elem, wordStartPos);
  691.                         range.setEnd(elem, currentPos);
  692.                         var ret = _gdCheckRange(range, x, y);
  693.                         if (null !== ret) return ret;
  694.                     }
  695.                 } else
  696.                     for (var i = 0; i < elem.childNodes.length; i++) {
  697.                         var range = elem.childNodes[
  698.                             i
  699.                         ].ownerDocument.createRange();
  700.                         range.selectNodeContents(elem.childNodes[i]);
  701.                         var rect = range.getBoundingClientRect();
  702.                         range.detach();
  703.                         if (
  704.                             null !== rect &&
  705.                             rect.left <= x &&
  706.                             rect.right >= x &&
  707.                             rect.top <= y &&
  708.                             rect.bottom >= y
  709.                         ) {
  710.                             var result = _gdGetWordAtPoint(
  711.                                 elem.childNodes[i],
  712.                                 x,
  713.                                 y
  714.                             );
  715.                             if (null !== result) return result;
  716.                         }
  717.                     }
  718.                 return null;
  719.             };
  720.  
  721.             var _gdeHandleWordClick = function(event) {
  722.                 for (
  723.                     var elem = event.target;
  724.                     elem && !elem.classList.contains('gdarticle');
  725.                     elem = elem.parentNode
  726.                 ) {
  727.                     if (
  728.                         /^(?:A|IMG|BODY|HTML)$/i.test(elem.nodeName) ||
  729.                         elem.classList.contains('gddictname')
  730.                     )
  731.                         return;
  732.                 }
  733.                 var word = _gdGetWordAtPoint(event.target, event.x, event.y);
  734.                 if (word !== null) {
  735.                     var charset =
  736.                         '[\u2000-\u206F\u2E00-\u2E7F\u2329\u232A\u27E6-\u27EF\u3008-\u301B\x00-#%-/:-@\x5B-\x60\x7B-~¡§«¶·»¿;]';
  737.                     var regex = new RegExp(
  738.                         '^' + charset + '+|' + charset + '+$',
  739.                         'g'
  740.                     );
  741.                     word = word.replace(regex, '');
  742.                     if (word) alert('handleWordClick://' + word);
  743.                 }
  744.             };
  745.             window.addEventListener('click', _gdeHandleWordClick);
  746.             _gdFindNextArticleToScrollTo = function() {
  747.                 var currentOffset = Math.ceil(currentYOffset);
  748.                 var len = gdToc.length;
  749.                 for (var i = 0; i < len; i++) {
  750.                     if (currentOffset < microcache.get(gdToc[i])) return i;
  751.                 }
  752.                 return -1;
  753.             };
  754.             _gdFindNextOrCurrentArticleToScrollTo = function() {
  755.                 var currentOffset = Math.floor(currentYOffset);
  756.                 var len = gdToc.length;
  757.                 for (var i = 0; i < len; i++) {
  758.                     if (currentOffset <= microcache.get(gdToc[i])) {
  759.                         return i;
  760.                     }
  761.                 }
  762.                 return -1;
  763.             };
  764.             gdMakeArticleActive = function(newId) {
  765.                 if (gdCurrentArticle !== newId) {
  766.                     if (gdCurrentArticle) {
  767.                         var currentActiveArticle = document.getElementById(
  768.                             'gdarticle-' + gdCurrentArticle
  769.                         );
  770.                         currentActiveArticle.classList.remove(
  771.                             'gdactivearticle'
  772.                         );
  773.                     }
  774.                     var newActiveArticle = document.getElementById(
  775.                         'gdarticle-' + newId
  776.                     );
  777.                     newActiveArticle.classList.add('gdactivearticle');
  778.                     gdCurrentArticle = newId;
  779.                     if (newId in gdAudioLinks) {
  780.                         var activeAudio = document.getElementById(
  781.                             'gde-activeaudio'
  782.                         );
  783.                         if (activeAudio) activeAudio.id = '';
  784.                         gdAudioLink = gdAudioLinks[newId];
  785.                         if (
  786.                             (activeAudio = newActiveArticle.getElementsByClassName(
  787.                                 'gde-fstwav'
  788.                             )) &&
  789.                             activeAudio.length
  790.                         ) {
  791.                             activeAudio[0].id = 'gde-activeaudio';
  792.                         }
  793.                     }
  794.                 }
  795.             };
  796.             gdNextArticle = function() {
  797.                 if (gdCurrentArticle) {
  798.                     var currentOffset = Math.floor(currentYOffset);
  799.                     if (winH + currentOffset + 3 >= scrollHeight) {
  800.                         if (
  801.                             gdToc.indexOf(gdCurrentArticle) ===
  802.                             gdToc.length - 1
  803.                         ) {
  804.                             if (hasScrollbar) {
  805.                                 requestAnimationFrame(function() {
  806.                                     GDE.jump(
  807.                                         microcache.get(gdToc[0]) -
  808.                                             currentOffset,
  809.                                         {
  810.                                             duration: _duration,
  811.                                             callback: afterScrollTimeOut
  812.                                         }
  813.                                     );
  814.                                 });
  815.                             } else {
  816.                                 gdMakeArticleActive(gdToc[0]);
  817.                             }
  818.                         } else {
  819.                             for (
  820.                                 var i = gdToc.indexOf(gdCurrentArticle);
  821.                                 i < gdToc.length;
  822.                                 i++
  823.                             ) {
  824.                                 if (
  825.                                     i !== gdToc.length - 1 &&
  826.                                     inView(gdToc[i + 1])
  827.                                 ) {
  828.                                     gdMakeArticleActive(gdToc[i + 1]);
  829.                                     break;
  830.                                 }
  831.                             }
  832.                         }
  833.                     } else {
  834.                         var idx = _gdFindNextArticleToScrollTo();
  835.                         if (idx === 0) ++idx;
  836.                         if (idx > 0) {
  837.                             requestAnimationFrame(function() {
  838.                                 var distance;
  839.                                 if (inView(gdToc[idx])) {
  840.                                     distance =
  841.                                         microcache.get(gdToc[idx]) -
  842.                                         currentOffset;
  843.                                 } else {
  844.                                     distance = winH - lineH;
  845.                                 }
  846.                                 if (
  847.                                     currentOffset + distance >
  848.                                     scrollHeight - winH
  849.                                 ) {
  850.                                     distance =
  851.                                         scrollHeight - winH - currentOffset;
  852.                                     isClicked = true;
  853.                                     GDE.jump(distance, {
  854.                                         duration: _duration,
  855.                                         callback: afterScrollTimeOut
  856.                                     });
  857.                                     gdMakeArticleActive(gdToc[idx]);
  858.                                 } else {
  859.                                     GDE.jump(distance, {
  860.                                         duration: _duration,
  861.                                         callback: afterScrollTimeOut
  862.                                     });
  863.                                 }
  864.                             });
  865.                         } else {
  866.                             //gdMakeArticleActive(gdToc[gdToc.length - 1]);
  867.                             requestAnimationFrame(function() {
  868.                                 GDE.jump(winH - lineH, {
  869.                                     duration: _duration,
  870.                                     callback: afterScrollTimeOut
  871.                                 });
  872.                             });
  873.                         }
  874.                     }
  875.                 }
  876.             };
  877.             gdPreviousArticle = function() {
  878.                 if (gdCurrentArticle) {
  879.                     var currentOffset = Math.floor(currentYOffset);
  880.                     if (winH + currentOffset + 3 >= scrollHeight) {
  881.                         for (
  882.                             var i = gdToc.indexOf(gdCurrentArticle);
  883.                             i >= 0;
  884.                             i--
  885.                         ) {
  886.                             if (i !== 0) {
  887.                                 if (inView(gdToc[i - 1])) {
  888.                                     gdMakeArticleActive(gdToc[i - 1]);
  889.                                 } else {
  890.                                     requestAnimationFrame(function() {
  891.                                         GDE.jump(
  892.                                             microcache.get(gdToc[i - 1]) -
  893.                                                 currentOffset,
  894.                                             {
  895.                                                 duration: _duration,
  896.                                                 callback: afterScrollTimeOut
  897.                                             }
  898.                                         );
  899.                                     });
  900.                                 }
  901.                                 break;
  902.                             }
  903.                         }
  904.                     } else {
  905.                         var idx = _gdFindNextOrCurrentArticleToScrollTo();
  906.                         if (idx > 0) {
  907.                             //gdMakeArticleActive(gdToc[idx - 1]);
  908.                             requestAnimationFrame(function() {
  909.                                 GDE.jump(
  910.                                     microcache.get(gdToc[idx - 1]) -
  911.                                         currentOffset,
  912.                                     {
  913.                                         duration: _duration,
  914.                                         callback: afterScrollTimeOut
  915.                                     }
  916.                                 );
  917.                             });
  918.                         }
  919.                     }
  920.                 }
  921.             };
  922.             gdShowToc = function() {
  923.                 if (gdToc.length && gdCurrentArticle) {
  924.                     var currentIdx = gdToc.indexOf(gdCurrentArticle);
  925.  
  926.                     if (currentIdx >= 0) {
  927.                         var tocData = currentIdx + ' ' + gdToc.join(' ');
  928.                         alert('showTableOfContents://' + tocData);
  929.                     }
  930.                 }
  931.             };
  932.             gdJumpTo = function(id) {
  933.                 gdMakeArticleActive(id);
  934.                 requestAnimationFrame(function() {
  935.                     GDE.jump(microcache.get(id) - Math.floor(currentYOffset), {
  936.                         duration: _duration,
  937.                         callback: afterScrollTimeOut
  938.                     });
  939.                 });
  940.             };
  941.         };
  942.         GDE.jump = function(target, options) {
  943.             var start = lastYOffset || window.pageYOffset;
  944.             var opt = {
  945.                 duration: options.duration,
  946.                 offset: options.offset || 0,
  947.                 callback: options.callback,
  948.                 easing: options.easing || easeOutQuad
  949.             };
  950.             var distance =
  951.                 typeof target == 'string'
  952.                     ? opt.offset +
  953.                       document.querySelector(target).getBoundingClientRect().top
  954.                     : target;
  955.             var duration =
  956.                 typeof opt.duration == 'function'
  957.                     ? opt.duration(distance)
  958.                     : opt.duration;
  959.             //console.log('duration: ' + duration);
  960.             var timeStart = null,
  961.                 timeElapsed;
  962.             if (!isScrolling) {
  963.                 //console.log('Scroll Start!')
  964.                 window.removeEventListener('scroll', onScroll);
  965.                 document.body.classList.add('gde-scroll');
  966.                 isScrolling = true;
  967.             }
  968.             requestAnimationFrame(function(time) {
  969.                 timeStart = time;
  970.                 loop(time);
  971.             });
  972.  
  973.             function loop(time) {
  974.                 timeElapsed = time - timeStart;
  975.                 window.scrollTo(
  976.                     0,
  977.                     opt.easing(timeElapsed, start, distance, duration)
  978.                 );
  979.                 if (timeElapsed < duration) requestAnimationFrame(loop);
  980.                 else end();
  981.             }
  982.  
  983.             function end() {
  984.                 window.scrollTo(0, start + distance);
  985.                 typeof opt.callback == 'function' && opt.callback();
  986.                 timeStart = null;
  987.                 setTimeout(function() {
  988.                     window.addEventListener('scroll', onScroll);
  989.                 }, 200);
  990.             }
  991.  
  992.             function easeOutQuad(t, b, c, d) {
  993.                 return -c * (t /= d) * (t - 2) + b;
  994.             }
  995.         };
  996.         return GDE;
  997.     })();
  998.     GDEnhancer.init();
  999. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement