<commit_before>if (window.golab === undefined) {
    window.golab = {};
}

golab = window.golab;

golab.getParameterByName = function(name, url) {
    if (!url) url = window.location.href;
    name = name.replace(/[\[\]]/g, '\\$&');
    var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)');
    var results = regex.exec(url);
    if (!results) return null;
    if (!results[2]) return '';
    return decodeURIComponent(results[2].replace(/\+/g, ' '));
}

golab._relative2absolute = function(url, base_url) {
  // https://stackoverflow.com/questions/470832/getting-an-absolute-url-from-a-relative-one-ie6-issue
  var doc      = document
    , old_base = doc.getElementsByTagName('base')[0]
    , old_href = old_base && old_base.href
    , doc_head = doc.head || doc.getElementsByTagName('head')[0]
    , our_base = old_base || doc_head.appendChild(doc.createElement('base'))
    , resolver = doc.createElement('a')
    , resolved_url
    ;
  our_base.href = base_url || '';
  resolver.href = url;
  resolved_url  = resolver.href; // browser magic at work here

  if (old_base) old_base.href = old_href;
  else doc_head.removeChild(our_base);
  return resolved_url;
}

golab.i18n_instance = null;

golab.i18n = function(options) {
    // options:
    //  - endpoint (defaults to https://composer.golabz.eu/)
    //  - language
    //  - standalone (defaults to false)
    //  - debug (defaults to false)

    var self = this;
    golab.i18n_instance = this;

    if (options === null || options === undefined)
        options = {};

    if (options.debug === true) {
        self._debug = true;
    } else {
        self._debug = false;
    }
    if (options.endpoint && options.endpoint.length > 0) {
        self.endpoint = options.endpoint;
    } else {
        self.endpoint = 'https://composer.golabz.eu/translations/v1';
    }
    if (options.avoidMutation === true) {
        self._avoidMutation = true;
    } else {
        self._avoidMutation = false;
    }

    if (options.standalone === true) {
        self.standalone = true;
    } else {
        var standaloneParameter = golab.getParameterByName("standalone");
        if (standaloneParameter === "true" || standaloneParameter === "1") {
            self.standalone = true;
        } else {
            self.standalone = false;
        }
    }

    function getLanguage() {
        if (options.language !== undefined && options.language !== null)
            return options.language.replace('-', '_');

        var langParam = golab.getParameterByName('lang');
        if (langParam != null && langParam.length > 0)
            return langParam.replace('-','_');

        if (navigator.language !== null && navigator.language !== undefined) {
            return navigator.language.replace('-','_');
        }
        return 'en';
    }

    this._fullUrl = null;

    var defaultLanguage = 'en_ALL';
    this.language = getLanguage();

    if (this.language.indexOf('_') > 0) {
        this.languageGroup = this.language.split('_')[0];
        this.languageCountry = this.language.split('_')[1];
    } else {
        this.languageGroup = this.language;
        this.languageCountry = 'ALL';
        this.language = this.language + '_ALL';
    }
    this.languageGeneric = this.language.split('_')[0] + '_ALL';

    this._supportedLanguages = [];

    // Only include the messages in those languages that are either English (default)
    // or the current language
    this._allMessages = [
        // {
        //    'url': 'https://.../locales/lang.json'
        //    'lang': 'en_ALL'
        //    'messages': {
        //       'key': 'value',
        //    },
        //    'translation: {
        //       'key': 'value',
        //    }
        // }
    ];

    // Only include the messages in those languages that are either English (default)
    // or the current language
    this._mergedMessages = {
        // lang: {
        //      key: value
        // }
    };
    this._mergedMessages[defaultLanguage] = {};
    this._mergedMessages[this.languageGeneric] = {};
    this._mergedMessages[this.language] = {};

    this._ready = $.Deferred();

    function startIteratingElements() {
        function translateElement(pos, element) {
            var $element = $(element);
            var message = $element.attr('golab-lang');
            if (message !== undefined && message !== null) {
                var translation = golab.i18n_instance.getMessage(message);
                $element.html(translation);
            }
        };

        $("*").each(translateElement);

        if (!self._avoidMutation && window.MutationObserver) {
            function mutationCallback (mutationsList, observer) {
                for(var mutation of mutationsList) {
                    if (typeof mutation.addedNodes == "object") {
                        $(mutation.addedNodes).each(translateElement)
                    }
                }
            }

            var observer = new MutationObserver(mutationCallback);
            observer.observe(document.getElementsByTagName('body')[0], {attributes: false, childList: true, characterData: false, subtree:true});
        }
    }

    function checkPending() {
        var anyPendingHolder = {
            anyPending: false
        };

        $(self._allMessages).each(function (pos, obj) {
            if (obj.pendingMessages || obj.pendingTranslation) {
                anyPendingHolder.anyPending = true;
            }
        });

        if (anyPendingHolder.anyPending)
            return;

        // Resolve
        if (self._debug)
            console.log('AppComposer ready');

        self._ready.resolve();

        startIteratingElements();
    }

    $("meta[name='translations']").each(function(position, metaObject) {
        $metaObject = $(metaObject);
        var lang = $metaObject.attr('lang');
        if (lang == null || lang === undefined || lang.length == 0)
            lang = 'en_ALL';

        var country;
        if (lang.indexOf('_') > 0) {
            var pieces = lang.split('_');
            lang = pieces[0];
            country = pieces[1];
        } else {
            var country = $metaObject.attr('country');
            if (!country)
                country = 'ALL';
        }
        var currentLanguage = lang + '_' + country;

        // if self.language is es_PE, I am interested in es_PE (currentLanguage), es_ALL (languageGeneric) and en_ALL (default).
        // Everything else I don't care
        if (currentLanguage != defaultLanguage && currentLanguage != self.language && currentLanguage != self.languageGeneric) {
            // Ignore other message files
            if (self._debug)
                console.log("Ignoring ", metaObject);
            return;
        }

        var url = $metaObject.attr('value');
        if (url === undefined) {
            console.log('meta', metaObject, 'does not have value');
            return;
        }
        var fullUrl = golab._relative2absolute(url);
        if (lang === 'en_ALL' && self._fullUrl == null) {
            self._fullUrl = fullUrl;
        }
        var currentRecord = {
            url: fullUrl,
            lang: currentLanguage,
            messages: {},
            translations: {},
            pendingMessages: true,
            pendingTranslation: true
        };
        self._allMessages.push(currentRecord);

        $.get(fullUrl).done(function(messages, textStatus, jqXHR) {

            if (jqXHR.responseXML) {
                currentRecord.messages = {};

                $(messages).find('msg').each(function (pos, message) {
                    var key = $(message).attr('name');
                    var value = $(message).html();
                    currentRecord.messages[key] = value;
                    var currentStore = self._mergedMessages[currentRecord.lang];
                    currentStore[key] = value;
                });
            }

            if (jqXHR.responseJSON) {
                if (messages !== undefined && messages.messages !== undefined) {
                    currentRecord.messages = messages.messages;
                    $(messages.messages).each(function (pos, message) {
                        var currentStore = self._mergedMessages[currentRecord.lang];
                        if (message.key !== undefined)
                            currentStore[message.key] = message.value;
                    });
                }
            }
        }).always(function () {
            currentRecord.pendingMessages = false;
            checkPending();
        });

        var currentEndpoint = self.endpoint + '/' + self.language + '/' + fullUrl;

        // if the self.language is English; don't contact app composer at all (no translation needed)
        // also, if the current language is not English, don't contact it
        if (self.language !== defaultLanguage && currentLanguage === defaultLanguage) {
            $.get(currentEndpoint)
                .done(function (messages) {
                    currentRecord.translations = messages;
                    for (var key in messages) {
                        var currentStore = self._mergedMessages[self.language];
                        currentStore[key] = messages[key];
                    };
                })
                .always(function () {
                    currentRecord.pendingTranslation = false;
                    checkPending();
                });
        } else {
            currentRecord.pendingTranslation = false;
        }
    });

    this.ready = function(handler) {
        self._ready.done(handler);
    }

    this.getLanguages = function() {
        var response = $.Deferred();
        $.get(fullUrl).done(function(contents) {
            response.done(contents.languages);
        }
        return response;
    }

    this.getMessage = function(key) {
        if (self._mergedMessages[self.language][key] !== undefined)
            return self._mergedMessages[self.language][key];
        if (self._mergedMessages[self.languageGeneric][key] !== undefined)
            return self._mergedMessages[self.languageGeneric][key];
        if (self._mergedMessages[defaultLanguage][key] !== undefined)
            return self._mergedMessages[defaultLanguage][key];
        return null;
    }
}

golab._checkAutoLoad = function () {
    $(document).ready(function () {
        if (golab.i18n_instance !== null)
            return;

        var autoload = $("meta[name='golab-i18n-autoload'")[0];
        if (autoload !== undefined && $(autoload).attr('value') === 'true') {
            var new_instance = new golab.i18n();
        }
    });
}

if (typeof jQuery == 'undefined') {
    console.log('jQuery not found before GoLab i18n');
    var script = document.createElement('script');
    script.type = "text/javascript";
    script.src = "https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js";
    script.onload = golab._checkAutoLoad;
    document.getElementsByTagName('head')[0].appendChild(script);
} else {
    $(document).ready(function() {
        golab._checkAutoLoad();
    });
}

<commit_msg>Fix js<commit_after>if (window.golab === undefined) {
    window.golab = {};
}

golab = window.golab;

golab.getParameterByName = function(name, url) {
    if (!url) url = window.location.href;
    name = name.replace(/[\[\]]/g, '\\$&');
    var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)');
    var results = regex.exec(url);
    if (!results) return null;
    if (!results[2]) return '';
    return decodeURIComponent(results[2].replace(/\+/g, ' '));
}

golab._relative2absolute = function(url, base_url) {
  // https://stackoverflow.com/questions/470832/getting-an-absolute-url-from-a-relative-one-ie6-issue
  var doc      = document
    , old_base = doc.getElementsByTagName('base')[0]
    , old_href = old_base && old_base.href
    , doc_head = doc.head || doc.getElementsByTagName('head')[0]
    , our_base = old_base || doc_head.appendChild(doc.createElement('base'))
    , resolver = doc.createElement('a')
    , resolved_url
    ;
  our_base.href = base_url || '';
  resolver.href = url;
  resolved_url  = resolver.href; // browser magic at work here

  if (old_base) old_base.href = old_href;
  else doc_head.removeChild(our_base);
  return resolved_url;
}

golab.i18n_instance = null;

golab.i18n = function(options) {
    // options:
    //  - endpoint (defaults to https://composer.golabz.eu/)
    //  - language
    //  - standalone (defaults to false)
    //  - debug (defaults to false)

    var self = this;
    golab.i18n_instance = this;

    if (options === null || options === undefined)
        options = {};

    if (options.debug === true) {
        self._debug = true;
    } else {
        self._debug = false;
    }
    if (options.endpoint && options.endpoint.length > 0) {
        self.endpoint = options.endpoint;
    } else {
        self.endpoint = 'https://composer.golabz.eu/translations/v1';
    }
    if (options.avoidMutation === true) {
        self._avoidMutation = true;
    } else {
        self._avoidMutation = false;
    }

    if (options.standalone === true) {
        self.standalone = true;
    } else {
        var standaloneParameter = golab.getParameterByName("standalone");
        if (standaloneParameter === "true" || standaloneParameter === "1") {
            self.standalone = true;
        } else {
            self.standalone = false;
        }
    }

    function getLanguage() {
        if (options.language !== undefined && options.language !== null)
            return options.language.replace('-', '_');

        var langParam = golab.getParameterByName('lang');
        if (langParam != null && langParam.length > 0)
            return langParam.replace('-','_');

        if (navigator.language !== null && navigator.language !== undefined) {
            return navigator.language.replace('-','_');
        }
        return 'en';
    }

    this._fullUrl = null;

    var defaultLanguage = 'en_ALL';
    this.language = getLanguage();

    if (this.language.indexOf('_') > 0) {
        this.languageGroup = this.language.split('_')[0];
        this.languageCountry = this.language.split('_')[1];
    } else {
        this.languageGroup = this.language;
        this.languageCountry = 'ALL';
        this.language = this.language + '_ALL';
    }
    this.languageGeneric = this.language.split('_')[0] + '_ALL';

    this._supportedLanguages = [];

    // Only include the messages in those languages that are either English (default)
    // or the current language
    this._allMessages = [
        // {
        //    'url': 'https://.../locales/lang.json'
        //    'lang': 'en_ALL'
        //    'messages': {
        //       'key': 'value',
        //    },
        //    'translation: {
        //       'key': 'value',
        //    }
        // }
    ];

    // Only include the messages in those languages that are either English (default)
    // or the current language
    this._mergedMessages = {
        // lang: {
        //      key: value
        // }
    };
    this._mergedMessages[defaultLanguage] = {};
    this._mergedMessages[this.languageGeneric] = {};
    this._mergedMessages[this.language] = {};

    this._ready = $.Deferred();

    function startIteratingElements() {
        function translateElement(pos, element) {
            var $element = $(element);
            var message = $element.attr('golab-lang');
            if (message !== undefined && message !== null) {
                var translation = golab.i18n_instance.getMessage(message);
                $element.html(translation);
            }
        };

        $("*").each(translateElement);

        if (!self._avoidMutation && window.MutationObserver) {
            function mutationCallback (mutationsList, observer) {
                for(var mutation of mutationsList) {
                    if (typeof mutation.addedNodes == "object") {
                        $(mutation.addedNodes).each(translateElement)
                    }
                }
            }

            var observer = new MutationObserver(mutationCallback);
            observer.observe(document.getElementsByTagName('body')[0], {attributes: false, childList: true, characterData: false, subtree:true});
        }
    }

    function checkPending() {
        var anyPendingHolder = {
            anyPending: false
        };

        $(self._allMessages).each(function (pos, obj) {
            if (obj.pendingMessages || obj.pendingTranslation) {
                anyPendingHolder.anyPending = true;
            }
        });

        if (anyPendingHolder.anyPending)
            return;

        // Resolve
        if (self._debug)
            console.log('AppComposer ready');

        self._ready.resolve();

        startIteratingElements();
    }

    $("meta[name='translations']").each(function(position, metaObject) {
        $metaObject = $(metaObject);
        var lang = $metaObject.attr('lang');
        if (lang == null || lang === undefined || lang.length == 0)
            lang = 'en_ALL';

        var country;
        if (lang.indexOf('_') > 0) {
            var pieces = lang.split('_');
            lang = pieces[0];
            country = pieces[1];
        } else {
            var country = $metaObject.attr('country');
            if (!country)
                country = 'ALL';
        }
        var currentLanguage = lang + '_' + country;

        // if self.language is es_PE, I am interested in es_PE (currentLanguage), es_ALL (languageGeneric) and en_ALL (default).
        // Everything else I don't care
        if (currentLanguage != defaultLanguage && currentLanguage != self.language && currentLanguage != self.languageGeneric) {
            // Ignore other message files
            if (self._debug)
                console.log("Ignoring ", metaObject);
            return;
        }

        var url = $metaObject.attr('value');
        if (url === undefined) {
            console.log('meta', metaObject, 'does not have value');
            return;
        }
        var fullUrl = golab._relative2absolute(url);
        if (lang === 'en_ALL' && self._fullUrl == null) {
            self._fullUrl = fullUrl;
        }
        var currentRecord = {
            url: fullUrl,
            lang: currentLanguage,
            messages: {},
            translations: {},
            pendingMessages: true,
            pendingTranslation: true
        };
        self._allMessages.push(currentRecord);

        $.get(fullUrl).done(function(messages, textStatus, jqXHR) {

            if (jqXHR.responseXML) {
                currentRecord.messages = {};

                $(messages).find('msg').each(function (pos, message) {
                    var key = $(message).attr('name');
                    var value = $(message).html();
                    currentRecord.messages[key] = value;
                    var currentStore = self._mergedMessages[currentRecord.lang];
                    currentStore[key] = value;
                });
            }

            if (jqXHR.responseJSON) {
                if (messages !== undefined && messages.messages !== undefined) {
                    currentRecord.messages = messages.messages;
                    $(messages.messages).each(function (pos, message) {
                        var currentStore = self._mergedMessages[currentRecord.lang];
                        if (message.key !== undefined)
                            currentStore[message.key] = message.value;
                    });
                }
            }
        }).always(function () {
            currentRecord.pendingMessages = false;
            checkPending();
        });

        var currentEndpoint = self.endpoint + '/' + self.language + '/' + fullUrl;

        // if the self.language is English; don't contact app composer at all (no translation needed)
        // also, if the current language is not English, don't contact it
        if (self.language !== defaultLanguage && currentLanguage === defaultLanguage) {
            $.get(currentEndpoint)
                .done(function (messages) {
                    currentRecord.translations = messages;
                    for (var key in messages) {
                        var currentStore = self._mergedMessages[self.language];
                        currentStore[key] = messages[key];
                    };
                })
                .always(function () {
                    currentRecord.pendingTranslation = false;
                    checkPending();
                });
        } else {
            currentRecord.pendingTranslation = false;
        }
    });

    this.ready = function(handler) {
        self._ready.done(handler);
    }

    this.getLanguages = function() {
        var response = $.Deferred();
        $.get(fullUrl).done(function(contents) {
            response.resolve(contents.languages);
        });
        return response;
    }

    this.getMessage = function(key) {
        if (self._mergedMessages[self.language][key] !== undefined)
            return self._mergedMessages[self.language][key];
        if (self._mergedMessages[self.languageGeneric][key] !== undefined)
            return self._mergedMessages[self.languageGeneric][key];
        if (self._mergedMessages[defaultLanguage][key] !== undefined)
            return self._mergedMessages[defaultLanguage][key];
        return null;
    }
}

golab._checkAutoLoad = function () {
    $(document).ready(function () {
        if (golab.i18n_instance !== null)
            return;

        var autoload = $("meta[name='golab-i18n-autoload'")[0];
        if (autoload !== undefined && $(autoload).attr('value') === 'true') {
            var new_instance = new golab.i18n();
        }
    });
}

if (typeof jQuery == 'undefined') {
    console.log('jQuery not found before GoLab i18n');
    var script = document.createElement('script');
    script.type = "text/javascript";
    script.src = "https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js";
    script.onload = golab._checkAutoLoad;
    document.getElementsByTagName('head')[0].appendChild(script);
} else {
    $(document).ready(function() {
        golab._checkAutoLoad();
    });
}

<|endoftext|>


<commit_before>// old-style core JSROOT main script
// temporary introduced here to support older JSROOT application
// will be removed with JSROOT v 6.2

"use strict";

if ((typeof document === "undefined") || (typeof window === "undefined")) {
   throw Error("JSRootCore.js can only be used with web browser")
}

(function() {

   function loadCoreScript(path) {
      let element = document.createElement("script");
      element.setAttribute('type', "text/javascript");
      element.setAttribute('src', path);

      return new Promise(resolveFunc => {
         element.onload = function() {
            element.onload = null;
            resolveFunc();
         }
         document.getElementsByTagName("head")[0].appendChild(element);
      })
   }

   let source_fullpath = document.currentScript.src;
   let minified = source_fullpath.indexOf("JSRootCore.min.js") >= 0;
   let p0 = source_fullpath.indexOf("JSRootCore.");
   let path0 = (p0>=0) ? source_fullpath.substr(0, p0) : "./";
   let _redirects = [];

   loadCoreScript(path0 + "JSRoot.core" + (minified ? ".min.js" : ".js")).then(() => {

      if (!JSROOT)
         throw Error("Fail to load JSRoot.core.js script from " + path0);

      let _warned = {};
      warnOnce = function(msg) {
         if (!_warned[msg]) {
            console.warn(msg);
            _warned[msg] = true;
         }
      }

      JSROOT.GetUrlOption = function(opt, url, dflt) {
         warnOnce('Using obsolete JSROOT.GetUrlOption, change to JSROOT.decodeUrl');
         return JSROOT.decodeUrl(url).get(opt, dflt === undefined ? null : dflt);
      }

      JSROOT.AssertPrerequisites = function(req, callback) {
         warnOnce('Using obsolete JSROOT.AssertPrerequisites, change to JSROOT.require');
         req = req.replace(/2d;v7;/g, "v7gpad;").replace(/2d;v6;/g, "gpad;").replace(/more2d;/g, 'more;').replace(/2d;/g, 'gpad;').replace(/;v6;v7/g, ";gpad;v7gpad");
         JSROOT.require(req).then(callback);
      }

      JSROOT.OpenFile = function(filename, callback) {
         warnOnce('Using obsolete JSROOT.OpenFile function, change to JSROOT.openFile');
         let res = JSROOT.openFile(filename);
         return !callback ? res : res.then(callback);
      }

      JSROOT.JSONR_unref = function(arg) {
         warnOnce('Using obsolete JSROOT.JSONR_unref function, change to JSROOT.parse');
         return JSROOT.parse(arg);
      }

      JSROOT.MakeSVG = function(args) {
         warnOnce('Using obsolete JSROOT.MakeSVG function, change to JSROOT.makeSVG');
         return JSROOT.makeSVG(args);
      }

      JSROOT.CallBack = function(func, arg1, arg2) {
         warnOnce('Using obsolete JSROOT.CallBack function');

         if (typeof func == 'string') func = JSROOT.findFunction(func);

         if (!func) return;

         if (typeof func == 'function') return func(arg1,arg2);

         if (typeof func != 'object') return;

         if (('obj' in func) && ('func' in func) &&
            (typeof func.obj == 'object') && (typeof func.func == 'string') &&
            (typeof func.obj[func.func] == 'function')) {
                return func.obj[func.func](arg1, arg2);
         }
      }

      function window_on_load(tmout, func) {
         if (document.attachEvent ? document.readyState === 'complete' : document.readyState !== 'loading')
            return tmout ? setTimeout(func, 10) : func();

         window.onload = tmout ? () => setTimeout(func, 10) : func;
      }

      _redirects.forEach(args => {
         let name = args.shift();
         if (typeof name == 'string') {
            JSROOT[name](...args);
         } else {
            let resolve = name;
            name = args.shift();
            JSROOT[name](...args).then(resolve);
         }
      });

      let d = JSROOT.decodeUrl(source_fullpath);

      // use timestamp to overcome cache limitation
      if (d.has('nocache')) JSROOT.settings.NoCache = (new Date).getTime();
      // server may send wrong content length by partial requests, use other method to control this
      if (d.has('wrong_http_response') || JSROOT.decodeUrl().has('wrong_http_response'))
         JSROOT.settings.HandleWrongHttpResponse = true;
      // let ignore sap loader even with openui5 loaded
      if (d.has('nosap')) JSROOT._.sap = undefined;

      if (d.has('gui') || JSROOT._.amd) {
         return window_on_load(JSROOT._.amd, () => {
            let gui_elem, gui_kind;
            function testDiv(id, kind) {
               if (gui_elem) return;
               let elem = document.getElementById(id);
               if (elem) { gui_elem = elem; gui_kind = kind; }
            }
            testDiv('simpleGUI', 'gui');
            testDiv('drawGUI', 'draw');
            testDiv('onlineGUI', 'online');
            if (gui_elem) JSROOT.buildGUI(gui_elem, gui_kind);
         })
      }

      let prereq = "", user = d.get('load'), onload = d.get('onload');
      if (d.has('io')) prereq += "io;";
      if (d.has('tree')) prereq += "tree;";
      if (d.has('2d')) prereq += "gpad;";
      if (d.has('v7')) prereq += "v7gpad;";
      if (d.has('hist')) prereq += "hist;";
      if (d.has('hierarchy')) prereq += "hierarchy;";
      if (d.has('jq2d')) prereq += "jq2d;";
      if (d.has('more2d')) prereq += "more;";
      if (d.has('geom')) prereq += "geom;";
      if (d.has('3d')) prereq += "base3d;";
      if (d.has('math')) prereq += "math;";
      if (d.has('mathjax')) prereq += "mathjax;";
      if (d.has('openui5')) prereq += "openui5;";

      if (user) { prereq += "io;gpad;"; user = user.split(";"); }

      if (prereq || onload || user)
         window_on_load(false, () => JSROOT.require(prereq)
                               .then(() => JSROOT.loadScript(user))
                               .then(() => JSROOT.CallBack(onload)));
   });

   let tmpJSROOT = { _workaround: true };

   tmpJSROOT.OpenFile = function(filename, call_back) {
      if (JSROOT !== tmpJSROOT)
         JSROOT.OpenFile(filename, call_back);
      else
         _redirects.push(["OpenFile", filename, call_back]);
   }

   tmpJSROOT.openFile = function(filename) {
      if (JSROOT !== tmpJSROOT)
         return JSROOT.openFile(filename);
      return new Promise(resolve => _redirects.push([resolve, "openFile", filename]));
   }

   tmpJSROOT.draw = function(divid, obj, opt, call_back) {
      if (JSROOT !== tmpJSROOT)
         return JSROOT.draw(divid, obj, opt).then(call_back);
     _redirects.push(["draw", divid, obj, opt, call_back]);
   }

   tmpJSROOT.redraw = function(divid, obj, opt, call_back) {
      if (JSROOT !== tmpJSROOT)
         return JSROOT.redraw(divid, obj, opt).then(call_back);
     _redirects.push(["redraw", divid, obj, opt, call_back]);
   }

   // until real JSROOT is loaded, provide minimal functions
   globalThis.JSROOT = tmpJSROOT;

})();<commit_msg>Fix in fallback<commit_after>// old-style core JSROOT main script
// temporary introduced here to support older JSROOT application
// will be removed with JSROOT v 6.2

"use strict";

if ((typeof document === "undefined") || (typeof window === "undefined")) {
   throw Error("JSRootCore.js can only be used with web browser")
}

(function() {

   function loadCoreScript(path) {
      let element = document.createElement("script");
      element.setAttribute('type', "text/javascript");
      element.setAttribute('src', path);

      return new Promise(resolveFunc => {
         element.onload = function() {
            element.onload = null;
            resolveFunc();
         }
         document.getElementsByTagName("head")[0].appendChild(element);
      })
   }

   let source_fullpath = document.currentScript.src;
   let minified = source_fullpath.indexOf("JSRootCore.min.js") >= 0;
   let p0 = source_fullpath.indexOf("JSRootCore.");
   let path0 = (p0>=0) ? source_fullpath.substr(0, p0) : "./";
   let _redirects = [];

   loadCoreScript(path0 + "JSRoot.core" + (minified ? ".min.js" : ".js")).then(() => {

      if (!JSROOT)
         throw Error("Fail to load JSRoot.core.js script from " + path0);

      let _warned = {};
      function warnOnce(msg) {
         if (!_warned[msg]) {
            console.warn(msg);
            _warned[msg] = true;
         }
      }

      JSROOT.GetUrlOption = function(opt, url, dflt) {
         warnOnce('Using obsolete JSROOT.GetUrlOption, change to JSROOT.decodeUrl');
         return JSROOT.decodeUrl(url).get(opt, dflt === undefined ? null : dflt);
      }

      JSROOT.AssertPrerequisites = function(req, callback) {
         warnOnce('Using obsolete JSROOT.AssertPrerequisites, change to JSROOT.require');
         req = req.replace(/2d;v7;/g, "v7gpad;").replace(/2d;v6;/g, "gpad;").replace(/more2d;/g, 'more;').replace(/2d;/g, 'gpad;').replace(/;v6;v7/g, ";gpad;v7gpad");
         JSROOT.require(req).then(callback);
      }

      JSROOT.OpenFile = function(filename, callback) {
         warnOnce('Using obsolete JSROOT.OpenFile function, change to JSROOT.openFile');
         let res = JSROOT.openFile(filename);
         return !callback ? res : res.then(callback);
      }

      JSROOT.JSONR_unref = function(arg) {
         warnOnce('Using obsolete JSROOT.JSONR_unref function, change to JSROOT.parse');
         return JSROOT.parse(arg);
      }

      JSROOT.MakeSVG = function(args) {
         warnOnce('Using obsolete JSROOT.MakeSVG function, change to JSROOT.makeSVG');
         return JSROOT.makeSVG(args);
      }

      JSROOT.CallBack = function(func, arg1, arg2) {
         warnOnce('Using obsolete JSROOT.CallBack function');

         if (typeof func == 'string') func = JSROOT.findFunction(func);

         if (!func) return;

         if (typeof func == 'function') return func(arg1,arg2);

         if (typeof func != 'object') return;

         if (('obj' in func) && ('func' in func) &&
            (typeof func.obj == 'object') && (typeof func.func == 'string') &&
            (typeof func.obj[func.func] == 'function')) {
                return func.obj[func.func](arg1, arg2);
         }
      }

      function window_on_load(tmout, func) {
         if (document.attachEvent ? document.readyState === 'complete' : document.readyState !== 'loading')
            return tmout ? setTimeout(func, 10) : func();

         window.onload = tmout ? () => setTimeout(func, 10) : func;
      }

      _redirects.forEach(args => {
         let name = args.shift();
         if (typeof name == 'string') {
            JSROOT[name](...args);
         } else {
            let resolve = name;
            name = args.shift();
            JSROOT[name](...args).then(resolve);
         }
      });

      let d = JSROOT.decodeUrl(source_fullpath);

      // use timestamp to overcome cache limitation
      if (d.has('nocache')) JSROOT.settings.NoCache = (new Date).getTime();
      // server may send wrong content length by partial requests, use other method to control this
      if (d.has('wrong_http_response') || JSROOT.decodeUrl().has('wrong_http_response'))
         JSROOT.settings.HandleWrongHttpResponse = true;
      // let ignore sap loader even with openui5 loaded
      if (d.has('nosap')) JSROOT._.sap = undefined;

      if (d.has('gui') || JSROOT._.amd) {
         return window_on_load(JSROOT._.amd, () => {
            let gui_elem, gui_kind;
            function testDiv(id, kind) {
               if (gui_elem) return;
               let elem = document.getElementById(id);
               if (elem) { gui_elem = elem; gui_kind = kind; }
            }
            testDiv('simpleGUI', 'gui');
            testDiv('drawGUI', 'draw');
            testDiv('onlineGUI', 'online');
            if (gui_elem) JSROOT.buildGUI(gui_elem, gui_kind);
         })
      }

      let prereq = "", user = d.get('load'), onload = d.get('onload');
      if (d.has('io')) prereq += "io;";
      if (d.has('tree')) prereq += "tree;";
      if (d.has('2d')) prereq += "gpad;";
      if (d.has('v7')) prereq += "v7gpad;";
      if (d.has('hist')) prereq += "hist;";
      if (d.has('hierarchy')) prereq += "hierarchy;";
      if (d.has('jq2d')) prereq += "jq2d;";
      if (d.has('more2d')) prereq += "more;";
      if (d.has('geom')) prereq += "geom;";
      if (d.has('3d')) prereq += "base3d;";
      if (d.has('math')) prereq += "math;";
      if (d.has('mathjax')) prereq += "mathjax;";
      if (d.has('openui5')) prereq += "openui5;";

      if (user) { prereq += "io;gpad;"; user = user.split(";"); }

      if (prereq || onload || user)
         window_on_load(false, () => JSROOT.require(prereq)
                               .then(() => JSROOT.loadScript(user))
                               .then(() => JSROOT.CallBack(onload)));
   });

   let tmpJSROOT = { _workaround: true };

   tmpJSROOT.OpenFile = function(filename, call_back) {
      if (JSROOT !== tmpJSROOT)
         JSROOT.OpenFile(filename, call_back);
      else
         _redirects.push(["OpenFile", filename, call_back]);
   }

   tmpJSROOT.openFile = function(filename) {
      if (JSROOT !== tmpJSROOT)
         return JSROOT.openFile(filename);
      return new Promise(resolve => _redirects.push([resolve, "openFile", filename]));
   }

   tmpJSROOT.draw = function(divid, obj, opt, call_back) {
      if (JSROOT !== tmpJSROOT)
         return JSROOT.draw(divid, obj, opt).then(call_back);
     _redirects.push(["draw", divid, obj, opt, call_back]);
   }

   tmpJSROOT.redraw = function(divid, obj, opt, call_back) {
      if (JSROOT !== tmpJSROOT)
         return JSROOT.redraw(divid, obj, opt).then(call_back);
     _redirects.push(["redraw", divid, obj, opt, call_back]);
   }

   // until real JSROOT is loaded, provide minimal functions
   globalThis.JSROOT = tmpJSROOT;

})();<|endoftext|>


<commit_before>var tags = [],
	textLen = text.length;

matches.forEach(function(m)
{
	var bbcodeName = m[1][0].toUpperCase();

	if (!config.bbcodesConfig[bbcodeName])
	{
		// Not a known BBCode
		return;
	}

	var bbcodeConfig = config.bbcodesConfig[bbcodeName],
	    tagName      = bbcodeConfig.tagName;

	/**
	* Position of the first character of current BBCode, which should be a [
	*/
	var lpos = m[0][1];

	/**
	* Position of the last character of current BBCode, starts as the position of
	* the =, ] or : char, then moves to the right as the BBCode is parsed
	*/
	var rpos = lpos + m[0][0].length;

	/**
	* Attributes parsed from the text
	*/
	var attrs = {};

	/**
	* Check for BBCode suffix
	*
	* Used to skip the parsing of closing BBCodes, e.g.
	*   [code:1][code]type your code here[/code][/code:1]
	*
	*/
	var suffix = '';

	if (text[rpos] === ':')
	{
		/**
		* [code:1] or [/code:1]
		* suffix = ':1'
		*/
		suffix  = /^:[0-9]*/.exec(text.substr(rpos))[0];
		rpos   += suffix.length;
	}

	var type;

	if (m[0][0][1] === '/')
	{
		if (text[rpos] !== ']')
		{
			log('warning', {
				'pos'    : rpos,
				'len'    : 1,
				'msg'    : 'Unexpected character: expected %1$s found %2$s',
				'params' : [']', text[rpos]]
			});
			return;
		}

		type = END_TAG;
	}
	else
	{
		type = START_TAG;

		var wellFormed = false,
		    attrName   = '';

		if (text[rpos] === '=')
		{
			/**
			* [quote=
			*
			* Set the default param. If there's no default param, we issue a warning and
			* reuse the BBCode's name instead
			*/
			if (bbcodeConfig.defaultAttr)
			{
				attrName = bbcodeConfig.defaultAttr;
			}
			else
			{
				attrName = bbcodeName.toLowerCase();

				log('debug', {
					'pos'    : rpos,
					'len'    : 1,
					'msg'    : 'BBCode %1$s does not have a default attribute, using BBCode name as attribute name',
					'params' : [bbcodeName]
				});
			}

			++rpos;
		}

		while (rpos < textLen)
		{
			var c = text[rpos];

			if (c === ']' || c === '/')
			{
				/**
				* We're closing this tag
				*/
				if (attrName)
				{
					/**
					* [quote=]
					* [quote username=]
					*/
					attrs[attrName] = ''
					attrName = '';
				}

				if (c === '/')
				{
					/**
					* Self-closing tag, e.g. [foo/]
					*/
					type = SELF_CLOSING_TAG;
					++rpos;

					if (rpos === textLen)
					{
						// text ends with [some tag/
						return;
					}

					c = text[rpos];
					if (c !== ']')
					{
						log('warning', {
							'pos'    : rpos,
							'len'    : 1,
							'msg'    : 'Unexpected character: expected %1$s found %2$s',
							'params' : [']', c]
						});
						return;
					}
				}

				wellFormed = true;
				break;
			}

			if (!attrName)
			{
				if (c === ' ')
				{
					++rpos;
					continue;
				}

				/**
				* Capture the attribute name
				*/
				attrName = /^[a-z_0-9]*/i.exec(text.substr(rpos))[0].toLowerCase();

				if (!attrName)
				{
					log('warning', {
						'pos'    : rpos,
						'len'    : 1,
						'msg'    : 'Unexpected character %s',
						'params' : [c]
					});
					return;
				}

				if (rpos + attrName.length >= textLen)
				{
					log('debug', {
						'pos' : rpos,
						'len' : attrName.length,
						'msg' : 'Attribute name seems to extend till the end of text'
					});
					return;
				}

				rpos += attrName.length;

				if (text[rpos] !== '=')
				{
					if (text[rpos] === ']'
					 || text.substr(rpos, 2) === '/]')
					{
						 // remove the current attribute then go on and close this tag
						 attrName = '';
						 continue;
					}

					log('debug', {
						'pos'    : rpos,
						'len'    : 1,
						'msg'    : 'Unexpected character: expected %1$s found %2$s',
						'params' : ['=', text[rpos]]
					});
					return;
				}

				++rpos;
				continue;
			}

			if (c === '"' || c === "'")
			{
				var valuePos = rpos + 1;

				while (++rpos < textLen)
				{
					rpos = text.indexOf(c, rpos);

					if (rpos === -1)
					{
						/**
						* No matching quote, apparently that string never ends...
						*/
						log('warning', {
							'pos' : valuePos - 1,
							'len' : 1,
							'msg' : 'Could not find matching quote'
						});
						return;
					}

					if (text[rpos - 1] === '\\')
					{
						var n = 1;
						do
						{
							++n;
						}
						while (text[rpos - n] === '\\');

						if (n % 2 === 0)
						{
							continue;
						}
					}

					break;
				}

				value = text.substr(valuePos, rpos - valuePos).replace(/\\(.)/g, '$1');

				// Skip past the closing quote
				++rpos;
			}
			else
			{
				value = /^[^\] \n\r]*/.exec(text.substr(rpos))[0];
				rpos += value.length;
			}

			attrs[attrName] = value;
			attrName = '';
		}

		if (!wellFormed)
		{
			return;
		}

		var usesContent = false;

		if (type === START_TAG
		 && bbcodeConfig.contentAttr
		 && attrs[bbcodeConfig.contentAttr] === undefined)
		{
			/**
			* Capture the content of that tag and use it as attribute value
			*/
			var pos = text.toUpperCase().indexOf('[/' + bbcodeName + suffix + ']', rpos);

			if (pos > -1)
			{
				attrs[bbcodeConfig.contentAttr]
					= text.substr(1 + rpos, pos - (1 + rpos));

				usesContent = true;
			}
		}
	}

	if (type === START_TAG
	 && !usesContent
	 && bbcodeConfig.autoClose)
	{
		var endTag = '[/' + bbcodeName + suffix + ']';

		/**
		* Make sure that the start tag isn't immediately followed by an endtag
		*/
		if (text.substr(1 + rpos, endTag.length).toUpperCase() !== endTag)
		{
			type = SELF_CLOSING_TAG;
		}
	}

	tags.push({
		name   : tagName,
		pos    : lpos,
		len    : rpos + 1 - lpos,
		type   : type,
		suffix : suffix,
		attrs  : attrs
	});
});

return tags;<commit_msg>TextFormatter: synced the Javascript BBCodes parser with the PHP parser<commit_after>var tags = [],
	textLen = text.length;

matches.forEach(function(m)
{
	var bbcodeName = m[1][0].toUpperCase();

	if (!config.bbcodesConfig[bbcodeName])
	{
		// Not a known BBCode
		return;
	}

	var bbcodeConfig = config.bbcodesConfig[bbcodeName],
	    tagName      = bbcodeConfig.tagName;

	/**
	* Position of the first character of current BBCode, which should be a [
	*/
	var lpos = m[0][1];

	/**
	* Position of the last character of current BBCode, starts as the position of
	* the =, ] or : char, then moves to the right as the BBCode is parsed
	*/
	var rpos = lpos + m[0][0].length;

	/**
	* Attributes parsed from the text
	*/
	var attrs = {};

	/**
	* Check for BBCode suffix
	*
	* Used to skip the parsing of closing BBCodes, e.g.
	*   [code:1][code]type your code here[/code][/code:1]
	*
	*/
	var suffix = '';

	if (text[rpos] === ':')
	{
		/**
		* [code:1] or [/code:1]
		* suffix = ':1'
		*/
		suffix  = /^:[0-9]*/.exec(text.substr(rpos))[0];
		rpos   += suffix.length;
	}

	var type;

	if (m[0][0][1] === '/')
	{
		if (text[rpos] !== ']')
		{
			log('warning', {
				'pos'    : rpos,
				'len'    : 1,
				'msg'    : 'Unexpected character: expected %1$s found %2$s',
				'params' : [']', text[rpos]]
			});
			return;
		}

		type = END_TAG;
	}
	else
	{
		type = START_TAG;

		var wellFormed = false,
		    firstPos   = rpos;

		while (rpos < textLen)
		{
			c = text[rpos];

			if (c === ']' || c === '/')
			{
				/**
				* We're closing this tag
				*/
				if (c === '/')
				{
					/**
					* Self-closing tag, e.g. [foo/]
					*/
					type = SELF_CLOSING_TAG;
					++rpos;

					if (rpos === textLen)
					{
						// text ends with [some tag/
						return;
					}

					c = text[rpos];
					if (c !== ']')
					{
						log('warning', {
							'pos'    : rpos,
							'len'    : 1,
							'msg'    : 'Unexpected character: expected %1$s found %2$s',
							'params' : [']', c]
						});
						return;
					}
				}

				wellFormed = true;
				break;
			}

			if (c === ' ')
			{
				++rpos;
				continue;
			}

			/**
			* Capture the attribute name
			*/
			var attrName = /^[a-z_0-9]*/i.exec(text.substr(rpos))[0].toLowerCase();

			if (attrName)
			{
				if (rpos + attrName.length >= textLen)
				{
					log('debug', {
						'pos' : rpos,
						'len' : attrName.length,
						'msg' : 'Attribute name seems to extend till the end of text'
					});
					return;
				}

				rpos += attrName.length;
			}
			else
			{
				if (c === '='
				 && rpos === firstPos)
				{
					/**
					* [quote=
					*
					* This is the default param. If there's no default param, we issue a
					* warning and reuse the BBCode's name instead.
					*/
					if (bbcodeConfig.defaultAttr)
					{
						attrName = bbcodeConfig.defaultAttr;
					}
					else
					{
						attrName = bbcodeName.toLowerCase();

						log('debug', {
							'pos'    : rpos,
							'len'    : 1,
							'msg'    : 'BBCode %1$s does not have a default attribute, using BBCode name as attribute name',
							'params' : [bbcodeName]
						});
					}
				}
				else
				{
					log('warning', {
						'pos'    : rpos,
						'len'    : 1,
						'msg'    : 'Unexpected character %s',
						'params' : [c]
					});
					return;
				}
			}

			if (text[rpos] !== '=')
			{
				/**
				* It's an attribute name not followed by an equal sign, let's just
				* ignore it
				*/
				continue;
			}

			/**
			* Move past the = and make sure we're not at the end of the text
			*/
			if (++rpos >= textLen)
			{
				log('debug', {
					'pos' : rpos,
					'len' : spn,
					'msg' : 'Attribute definition seems to extend till the end of text'
				});
				return;
			}

			c = text[rpos];
			if (c === '"' || c === "'")
			{
				var valuePos = rpos + 1;

				while (++rpos < textLen)
				{
					rpos = text.indexOf(c, rpos);

					if (rpos === -1)
					{
						/**
						* No matching quote, apparently that string never ends...
						*/
						log('warning', {
							'pos' : valuePos - 1,
							'len' : 1,
							'msg' : 'Could not find matching quote'
						});
						return;
					}

					if (text[rpos - 1] === '\\')
					{
						var n = 1;
						do
						{
							++n;
						}
						while (text[rpos - n] === '\\');

						if (n % 2 === 0)
						{
							continue;
						}
					}

					break;
				}

				value = text.substr(valuePos, rpos - valuePos).replace(/\\(.)/g, '$1');

				// Skip past the closing quote
				++rpos;
			}
			else
			{
				value = /^[^\] \n\r]*/.exec(text.substr(rpos))[0];
				rpos += value.length;
			}

			attrs[attrName] = value;
		}

		if (!wellFormed)
		{
			return;
		}

		var usesContent = false;

		if (type === START_TAG
		 && bbcodeConfig.contentAttr
		 && attrs[bbcodeConfig.contentAttr] === undefined)
		{
			/**
			* Capture the content of that tag and use it as attribute value
			*/
			var pos = text.toUpperCase().indexOf('[/' + bbcodeName + suffix + ']', rpos);

			if (pos > -1)
			{
				attrs[bbcodeConfig.contentAttr]
					= text.substr(1 + rpos, pos - (1 + rpos));

				usesContent = true;
			}
		}
	}

	if (type === START_TAG
	 && !usesContent
	 && bbcodeConfig.autoClose)
	{
		var endTag = '[/' + bbcodeName + suffix + ']';

		/**
		* Make sure that the start tag isn't immediately followed by an endtag
		*/
		if (text.substr(1 + rpos, endTag.length).toUpperCase() !== endTag)
		{
			type = SELF_CLOSING_TAG;
		}
	}

	tags.push({
		name   : tagName,
		pos    : lpos,
		len    : rpos + 1 - lpos,
		type   : type,
		suffix : suffix,
		attrs  : attrs
	});
});

return tags;<|endoftext|>


<commit_before>/**
 * Prepare hypothes.is URL to request API.
 */
function hypothesis_api_url(url, type) {
  if (!/^https?:\/\//i.test(url)) {
    url = 'http://' + url;
  }
  if (type === 'domain') {
    const url_obj = new URL(url);
    const query = 'uri.parts=' + url_obj.host.split('.').join('&uri.parts=')
    return 'https://hypothes.is/api/search?' + query;
  } else if (type === 'url') {
    return 'https://hypothes.is/api/search?uri=' + url;
  }
}

/**
 * Get hypothes.is data and render results.
 */
function get_annotations(type='url') {
  const url = getUrlByParameter('url');
  const new_url = hypothesis_api_url(url, type);
  $.getJSON(new_url, function(data) {
    const length = data.rows.length;
    if (length > 0) {
      for(let i=0; i<length; i++) {
        const rowData = data.rows[i];
        const date = rowData.created.substring(0,10);
        const source = rowData.target[0].source;
        const exactData = rowData.text;
        const user = rowData.user.substring(5, rowData.user.indexOf('@'));
        let title = '';
        if(rowData.document.title) {
          title = rowData.document.title[0];
        }
        let row = $('#row_contain-' + type);
        let item = row.clone();
        item.attr('id', 'row-' + i);
        item.find('.date').html('Dated on ' + date);
        item.find('.userinfo').html(user);
        item.find('#source-contain').html('(' + source + ')');
        item.find('#text-contain').html(exactData);
        item.find('.title').html(title);
        item.find('.links').append(
          $('<a>').attr({'href': rowData.links.incontext, 'id': 'link-incontext'})
                  .html('Click to see in context'),
          $('<a>').attr({'href': rowData.links.html, 'id': 'link-html'})
                  .html('Click to see the HTML')
        )
        if(rowData.target[0].hasOwnProperty('selector')){
          var selector_length = rowData.target[0].selector.length;
          var exact = rowData.target[0].selector[selector_length-1].exact;
          item.find('.target-selector-exact').html(exact);
        } else {
          item.find('.target-selector-exact').hide();
        }
        $('#container-whole-' + type).append(item);
      }
    } else {
      let error_msg;
      if (type === 'domain') {
        error_msg = 'There are no annotations for the current domain.';
      } else {
        error_msg = 'There are no annotations for the current URL.';
      }
      let row = $('#row_contain-' + type);
      let item = row.clone();
      item.html(
        $('<div>').addClass('col-sm-6 col-sm-offset-3 text-center')
                  .html(error_msg)
      );
      $('#container-whole-' + type).hide();
      $('#title-' + type).hide();
      return "not found " + type;
    }
  });
}

function showAnnotations(type){
  $('.tabcontent').hide()
  $('.tablink').removeClass('active')
  $('.tablink[value="' + type + '"]').addClass('active')
  $('#' + type).show()
}

$('.tablink').click(function(){
  showAnnotations($(this).attr('value'))
})

if (typeof module !== 'undefined') {
  module.exports = {hypothesis_api_url: hypothesis_api_url,
                    get_annotations: get_annotations}
}
<commit_msg>open annotations URLs in a new tab<commit_after>/**
 * Prepare hypothes.is URL to request API.
 */
function hypothesis_api_url(url, type) {
  if (!/^https?:\/\//i.test(url)) {
    url = 'http://' + url;
  }
  if (type === 'domain') {
    const url_obj = new URL(url);
    const query = 'uri.parts=' + url_obj.host.split('.').join('&uri.parts=')
    return 'https://hypothes.is/api/search?' + query;
  } else if (type === 'url') {
    return 'https://hypothes.is/api/search?uri=' + url;
  }
}

/**
 * Get hypothes.is data and render results.
 */
function get_annotations(type='url') {
  const url = getUrlByParameter('url');
  const new_url = hypothesis_api_url(url, type);
  $.getJSON(new_url, function(data) {
    const length = data.rows.length;
    if (length > 0) {
      for(let i=0; i<length; i++) {
        const rowData = data.rows[i];
        const date = rowData.created.substring(0,10);
        const source = rowData.target[0].source;
        const exactData = rowData.text;
        const user = rowData.user.substring(5, rowData.user.indexOf('@'));
        let title = '';
        if(rowData.document.title) {
          title = rowData.document.title[0];
        }
        let row = $('#row_contain-' + type);
        let item = row.clone();
        item.attr('id', 'row-' + i);
        item.find('.date').html('Dated on ' + date);
        item.find('.userinfo').html(user);
        item.find('#source-contain').html('(' + source + ')');
        item.find('#text-contain').html(exactData);
        item.find('.title').html(title);
        item.find('.links').append(
          $('<a>').attr({'href': rowData.links.incontext, 'id': 'link-incontext','target':'_blank'})
                  .html('Click to see in context'),
          $('<a>').attr({'href': rowData.links.html, 'id': 'link-html','target':'_blank'})
                  .html('Click to see the HTML')
        )
        if(rowData.target[0].hasOwnProperty('selector')){
          var selector_length = rowData.target[0].selector.length;
          var exact = rowData.target[0].selector[selector_length-1].exact;
          item.find('.target-selector-exact').html(exact);
        } else {
          item.find('.target-selector-exact').hide();
        }
        $('#container-whole-' + type).append(item);
      }
    } else {
      let error_msg;
      if (type === 'domain') {
        error_msg = 'There are no annotations for the current domain.';
      } else {
        error_msg = 'There are no annotations for the current URL.';
      }
      let row = $('#row_contain-' + type);
      let item = row.clone();
      item.html(
        $('<div>').addClass('col-sm-6 col-sm-offset-3 text-center')
                  .html(error_msg)
      );
      $('#container-whole-' + type).hide();
      $('#title-' + type).hide();
      return "not found " + type;
    }
  });
}

function showAnnotations(type){
  $('.tabcontent').hide()
  $('.tablink').removeClass('active')
  $('.tablink[value="' + type + '"]').addClass('active')
  $('#' + type).show()
}

$('.tablink').click(function(){
  showAnnotations($(this).attr('value'))
})

if (typeof module !== 'undefined') {
  module.exports = {hypothesis_api_url: hypothesis_api_url,
                    get_annotations: get_annotations}
}
<|endoftext|>


<commit_before>
import '../js/dom.switchable.js';
import '../js/dom.swipeable.js';
import { get, weakCache } from '../../fn/fn.js';
import { after, append, attribute, before, children, classes, clone, closest, events, matches, query, trigger } from '../dom.js';

const duration = 6000;
const jitter   = 0;
const getData  = weakCache(() => {});

var data = (function(store) {
	return function data(node) {
		var object = store.get(node);
		if (object) { return object; }
		object = {};
		store.set(node, object);
		return object;
	};
})(new WeakMap());

function triggerNext(block) {
	var timer = data(block).timer;
	var next  = data(block).nextSlide;

	clearTimeout(timer);
	data(block).timer = true;
	trigger('dom-activate', next);
}

function reposition(block, pane) {
	var width = block.clientWidth;
	var x     = pane.offsetLeft;
	var xMarg = 0;//dom.style('margin-left', pane);
	block.style.transform = "translate(calc(" + (-100 * x / width) + "% + " + xMarg + "px), 0)";
}

function rearrange(block, panes, n) {
	var pane0    = panes[0];
	var paneLast = panes[panes.length - 1];
	var classy  = classes(block);

	classy.add('notransition');

	if (n < 3) {
		before(pane0, paneLast);
	}
	else {
		after(paneLast, pane0);
	}

	reposition(block, panes[n]);

	// FF requires 2 frames before it calms down enough to respect
	// the notransition class
	requestAnimationFrame(function() {
		requestAnimationFrame(function() {
			classy.remove('notransition');
		});
	});
}

function touch(e) {
	if (e.defaultPrevented) { return; }

	// Pause auto activate during touch
	var block = closest('.swipe-block', e.target);
	var timer = data(block).timer;
	if (timer) {
		clearTimeout(timer);
		data(block).timer = true;
	}
}

function isSwitchable(node) {
	return classes(node).contains('switchable');
}

function cloneAttr(name, node, suffix) {
	var value = attribute(name, node);
	if (!value) { return; }
	node.setAttribute(name, value + suffix);
}

function duplicateSlides(slides, layers, texts, n, suffix) {
	var cloneSlides = slides
	.map(clone)
	.map(function(node) {
		node.id = node.id + suffix;
		classes(node).remove('active');
		return node;
	});

	append(slides[0].parentNode, cloneSlides);

	if (layers.length) {
		var cloneLayers = layers
		.map(clone)
		.map(function(node) {
			cloneAttr('href', node, suffix);
			cloneAttr('data-href', node, suffix);
			classes(node).remove('on');
			return node;
		});

		append(layers[0].parentNode, cloneLayers);
	}

	if (texts.length) {
		var cloneTexts = texts
		.map(clone)
		.map(function(node) {
			cloneAttr('href', node, suffix);
			cloneAttr('data-href', node, suffix);
			classes(node).remove('on');
			return node;
		});

		append(texts[0].parentNode, cloneTexts);
	}

	n = n + cloneSlides.length;

	if (n < 6) {
		duplicateSlides(slides, layers, texts, n, suffix + '-clone');
	}
}

function activate(e) {
	// Ignore activate events from inside slides
	if (e.target !== e.delegateTarget) { return; }

	var block  = e.delegateTarget.parentNode;
	var slides = children(block).filter(isSwitchable);
	var index  = slides.indexOf(e.target);
	var prev   = query('.prev_thumb[data-target="#' + block.id + '"]', document);
	var next   = query('.next_thumb[data-target="#' + block.id + '"]', document);

	// Replace hrefs of previous and next buttons
	if (index === 0) {
		prev.forEach(function(node) {
			node.setAttribute('href', '#' + slides[slides.length - 1].id);
		});
	}
	else {
		prev.forEach(function(node) {
			node.setAttribute('href', '#' + slides[index - 1].id);
		});
	}

	if (index === slides.length - 1) {
		next.forEach(function(node) {
			node.setAttribute('href', '#' + slides[0].id);
		});
		data(block).nextSlide = slides[0];
	}
	else {
		next.forEach(function(node) {
			node.setAttribute('href', '#' + slides[index + 1].id);
		});
		data(block).nextSlide = slides[index + 1];
	}

	function transitionend(e) {
		clearTimeout(endTimer);
		rearrange(block, slides, index);

		var selector = attribute('data-slide-slave', block);
		if (!selector) { return; }

		var slaves = query(selector, document);
		slaves.forEach(function(slave) {
			var slides = children(slave);
			if (!slides.length) { return; }
			rearrange(slave, slides, index);
		});
	}

	// Transitionend appears to fire to early for the end of the transition
	var endTimer = setTimeout(transitionend, 333);
}

function activateTimer(switchable) {
	const block = switchable.parentNode;
    const data  = getData(block);

	clearTimeout(getData(block).timer);

	if (data(block).timer !== false) {
		data(block).timer = setTimeout(triggerNext, interval + (Math.random() + Math.random() - 1) * jitter, block);
	}
}

function clickPlay(e) {
	var block = query(attribute('data-target', e.delegateTarget), document)[0];
	triggerNext(block);
	var classy = classes(e.delegateTarget.parentNode);
	classy.remove('paused');
}

function clickPause(e) {
	var block = query(attribute('data-target', e.delegateTarget), document)[0];
	var timer = data(block).timer;
	clearTimeout(timer);
	data(block).timer = false;
	var classy = classes(e.delegateTarget.parentNode);
	classy.add('paused');
}

const getTarget = get('target');

events('dom-activate', document)
.map(getTarget)
.filter(matches('.autoswitch > .switchable'))
.each(activateTimer);

//on(document, 'click',        dom.delegate('.play_thumb[data-target]',  clickPlay));
//on(document, 'click',        dom.delegate('.pause_thumb[data-target]', clickPause));

/*
dom('.swipe-wrap-block').forEach(function(node) {
	var slides = query('.switchable', node);
	var layers = query('.fg-layer > .swipe-block > .block', node);
	var texts  = query('.text-layer', node);

	if (slides.length < 6) {
		duplicateSlides(slides, layers, texts, slides.length, '-clone');
	}
});
*/
<commit_msg>Add autswitch script<commit_after>
import '../js/dom.switchable.js';
import '../js/dom.swipeable.js';
import { get, weakCache } from '../../fn/fn.js';
import { children, events, matches, trigger } from '../dom.js';

const config    = { duration: 6 };
const getData   = weakCache(() => ({}));
const getTarget = get('target');

function triggerNext(block) {
    const data  = getData(block);
	const timer = data.timer;
	const next  = children(block).find(matches('.active.switchable, .active[switchable]')).nextElementSibling;

	clearTimeout(timer);
	data.timer = true;

	trigger('dom-activate', next);
}

function activate(switchable) {
    const block    = switchable.parentNode;
    const duration = switchable.getAttribute('data-duration') || config.duration;
    const data     = getData(block);

	clearTimeout(data.timer);
	if (data.timer !== false) {
		data.timer = setTimeout(triggerNext, parseFloat(duration) * 1000, block);
	}
}

events('dom-activate', document)
.map(getTarget)
.filter(matches('.autoswitch > .switchable'))
.each(activate);
<|endoftext|>


<commit_before>/**
 * @file VerticalPointStep component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component} from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';

import VerticalPointStepItem from '../_VerticalPointStepItem';

class VerticalPointStep extends Component {

    constructor(props, ...restArgs) {

        super(props, ...restArgs);

        this.state = {
            activatedStep: props.activatedStep,
            finishedStep: props.finishedStep
        };

    }

    handleClick = activatedStep => {

        const {onChange} = this.props;

        this.setState({
            activatedStep
        }, () => {
            onChange && onChange({
                activatedStep,
                finishedStep: this.state.finishedStep
            });
        });

    };

    componentWillReceiveProps(nextProps) {
        if (nextProps.activatedStep !== this.state.activatedStep
            || nextProps.finishedStep !== this.state.finishedStep) {
            this.setState({
                activatedStep: nextProps.activatedStep,
                finishedStep: nextProps.finishedStep
            });
        }
    }

    render() {

        const {className, style, steps, disabled} = this.props,
            {activatedStep, finishedStep} = this.state;

        return (

                {
                    steps && steps.map((item, index) =>
                        <VerticalPointStepItem key={index}
                                               index={index}
                                               className={item.className}
                                               style={item.style}
                                               activatedStep={activatedStep}
                                               finishedStep={finishedStep}
                                               value={item}
                                               isFirst={index === 0}
                                               isLast={index === steps.length - 1}
                                               disabled={disabled}
                                               onClick={this.handleClick}/>
                    )
                }

        );

    }
}

VerticalPointStep.propTypes = {

    /**
     * The CSS class name of the root element.
     */
    className: PropTypes.string,

    /**
     * Override the styles of the root element.
     */
    style: PropTypes.object,

    /**
     * The render content of step.
     */
    steps: PropTypes.arrayOf(PropTypes.shape({

        /**
         * The CSS class name of step element.
         */
        className: PropTypes.string,

        /**
         * Override the styles of the step element.
         */
        style: PropTypes.object,

        /**
         * The text value of step.
         */
        title: PropTypes.string

    })).isRequired,

    /**
     * Sets the step as active.
     */
    activatedStep: PropTypes.number,

    /**
     * The final step.
     */
    finishedStep: PropTypes.number,

    disabled: PropTypes.bool,

    /**
     * Callback function fired when step change.
     */
    onChange: PropTypes.func

};

VerticalPointStep.defaultProps = {

    activatedStep: 0,
    finishedStep: 0,

    disabled: false

};

export default VerticalPointStep;
<commit_msg>update VerticalPointStep<commit_after>/**
 * @file VerticalPointStep component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component} from 'react';
import PropTypes from 'prop-types';

// Vendors
import classNames from 'classnames';
import VerticalPointStepItem from '../_VerticalPointStepItem';
import ComponentUtil from '../_vendors/ComponentUtil';

class VerticalPointStep extends Component {

    static getDerivedStateFromProps(props, state) {
        return {
            prevProps: props,
            activatedStep: ComponentUtil.getDerivedState(props, state, 'activatedStep'),
            finishedStep: ComponentUtil.getDerivedState(props, state, 'finishedStep')
        };
    }

    constructor(props, ...restArgs) {

        super(props, ...restArgs);

        this.state = {
            activatedStep: props.activatedStep,
            finishedStep: props.finishedStep
        };

    }

    handleClick = activatedStep => {

        const {onChange} = this.props;

        this.setState({
            activatedStep
        }, () => {
            onChange && onChange({
                activatedStep,
                finishedStep: this.state.finishedStep
            });
        });

    };

    render() {

        const {className, style, steps, disabled} = this.props,
            {activatedStep, finishedStep} = this.state;

        return (

                {
                    steps && steps.map((item, index) =>
                        <VerticalPointStepItem key={index}
                                               index={index}
                                               className={item.className}
                                               style={item.style}
                                               activatedStep={activatedStep}
                                               finishedStep={finishedStep}
                                               value={item}
                                               isFirst={index === 0}
                                               isLast={index === steps.length - 1}
                                               disabled={disabled}
                                               onClick={this.handleClick}/>
                    )
                }

        );

    }
}

VerticalPointStep.propTypes = {

    /**
     * The CSS class name of the root element.
     */
    className: PropTypes.string,

    /**
     * Override the styles of the root element.
     */
    style: PropTypes.object,

    /**
     * The render content of step.
     */
    steps: PropTypes.arrayOf(PropTypes.shape({

        /**
         * The CSS class name of step element.
         */
        className: PropTypes.string,

        /**
         * Override the styles of the step element.
         */
        style: PropTypes.object,

        /**
         * The text value of step.
         */
        title: PropTypes.string

    })).isRequired,

    /**
     * Sets the step as active.
     */
    activatedStep: PropTypes.number,

    /**
     * The final step.
     */
    finishedStep: PropTypes.number,

    disabled: PropTypes.bool,

    /**
     * Callback function fired when step change.
     */
    onChange: PropTypes.func

};

VerticalPointStep.defaultProps = {

    activatedStep: 0,
    finishedStep: 0,

    disabled: false

};

export default VerticalPointStep;
<|endoftext|>


<commit_before>// import Divmod.UnitTest
// import Methanal.Util

Divmod.UnitTest.TestCase.subclass(Methanal.Tests.TestUtil, 'TestUtil').methods(
    function test_strToInt(self) {
        var CASES = [
            ['1234', 1234],
            ['01234', 1234],
            ['001234', 1234],
            ['019', 19],
            ['123abc', undefined],
            ['abc123', undefined],
            ['0x123', undefined]];

        for (var i = 0; i < CASES.length; ++i) {
            var input = CASES[i][0];
            var expected = CASES[i][1];
            var actual = Methanal.Util.strToInt(input);
            self.assert(expected === actual, 'input = ' + input + ' :: expected = ' + expected + ' :: actual = ' + actual);
        }
    },

    function test_reduce(self) {
        var reduce = Methanal.Util.reduce;

        function add(x, y) {
            return x + y;
        }

        function multiply(x, y) {
            return x * y;
        }

        self.assertIdentical(reduce(add, [1, 2, 3]), 6);
        self.assertIdentical(reduce(multiply, [1, 2, 3], 10), 60);
        self.assertThrows(Error, function () { return reduce(add, []); });
        self.assertIdentical(reduce(add, [], 10), 10);
        self.assertIdentical(reduce(add, [10]), 10);
    },

    /**
     * Test L{Methanal.Util._reprString} correctly escapes various whitespace
     * characters.
     */
    function test_reprString(self) {
        var s = '\r\n\f\b\t';
        var repr = Methanal.Util._reprString(s);
        var expected = "\"\\r\\n\\f\\b\\t\"";
        self.assertIdentical(repr, expected);
    });

/**
 * Tests for L{Methanal.Util.Time}.
 *
 * @type _knownTime: L{Methanal.Util.Time}
 * @ivar _knownTime: A known point in time
 */
Divmod.UnitTest.TestCase.subclass(Methanal.Tests.TestUtil, 'TestTime').methods(
    function setUp(self) {
        self._knownTime = Methanal.Util.Time.fromDate(
            new Date(2009, 8, 6, 1, 36, 23, 2));
    },

    /**
     * L{Methanal.Util.TimeDelta} correctly specifies a given duration in
     * milliseconds.
     */
    function test_timedelta(self) {
        var td = Methanal.Util.TimeDelta({'days': 1});
        self.assertIdentical(td, 1000 * 3600 * 24);

        var td = Methanal.Util.TimeDelta({'days': -1});
        self.assertIdentical(td, 1000 * 3600 * -24);

        var td = Methanal.Util.TimeDelta({'days': 1,
                                          'hours': 2});
        self.assertIdentical(td, 1000 * 3600 * 26);

        var td = Methanal.Util.TimeDelta({'days': 1,
                                          'hours': 2,
                                          'minutes': 3});
        self.assertIdentical(td, 1000 * (3600 * 26 + 60 * 3));

        var td = Methanal.Util.TimeDelta({'days': 1,
                                          'hours': 2,
                                          'minutes': 3,
                                          'seconds': 4});
        self.assertIdentical(td, 1000 * (3600 * 26 + 60 * 3 + 4));

        var td = Methanal.Util.TimeDelta({'days': 1,
                                          'hours': 2,
                                          'minutes': 3,
                                          'seconds': 4,
                                          'milliseconds': 5});
        self.assertIdentical(td, 1000 * (3600 * 26 + 60 * 3 + 4) + 5);
    },

    /**
     * L{Methanal.Util.Time.guess} creates a L{Methanal.Util.Time} instance
     * when given an input format it can parse.
     */
    function test_guess(self) {
        function assertTimeParsed(data, timestamp) {
            self.assertIdentical(
                Methanal.Util.Time.guess(data).asTimestamp(),
                timestamp);
        };

        assertTimeParsed('2009/9/1',   1251756000000);
        assertTimeParsed('2009.09.01', 1251756000000);
        assertTimeParsed('2009-09-01', 1251756000000);
        assertTimeParsed('1/9/2009',   1251756000000);
        assertTimeParsed('01.09.2009', 1251756000000);
        assertTimeParsed('01-09-2009', 1251756000000);
        assertTimeParsed('1/9/2009',   1251756000000);
        assertTimeParsed('29/2/2008',  1204236000000);
    },

    /**
     * L{Methanal.Util.Time.guess} throws L{Methanal.Util.TimeParseError} when
     * the input is not in any recognisable format, and reraises the original
     * exception if something other than L{Methanal.Util.TimeParseError} occurs.
     */
    function test_guessFailure(self) {
        function assertTimeParseError(data) {
            self.assertThrows(
                Methanal.Util.TimeParseError,
                function() { return Methanal.Util.Time.guess(data); });
        };

        assertTimeParseError('');
        assertTimeParseError('hello');
        assertTimeParseError('1/2/3');
        assertTimeParseError('2009/01');
        assertTimeParseError('2009/01');
        assertTimeParseError('2009/01/32');
        assertTimeParseError('2009/02/29');

        self.assertThrows(
            TypeError,
            function() { return Methanal.Util.Time.guess(undefined); });
    },

    /**
     * Create a L{Methanal.Util.Time} instance from a C{Date}.
     */
    function test_fromDate(self) {
        var d = new Date();
        var t = Methanal.Util.Time.fromDate(d);
        self.assertIdentical(t.asTimestamp(), d.getTime());
    },

    /**
     * Create a L{Methanal.Util.Time} instance from a valid relative time
     * reference, while invalid references throw
     * L{Methanal.Util.TimeParseError}.
     */
    function test_fromRelative(self) {
        var today = self._knownTime;

        var t = Methanal.Util.Time.fromRelative('tomorrow', today);
        self.assertIdentical(t.asHumanly(), 'Mon, 7 Sep 2009');
        var t = Methanal.Util.Time.fromRelative('yesterday', today);
        self.assertIdentical(t.asHumanly(), 'Sat, 5 Sep 2009');
        var t = Methanal.Util.Time.fromRelative('today', today);
        self.assertIdentical(t.asHumanly(), 'Sun, 6 Sep 2009');

        var t = Methanal.Util.Time.fromRelative('sun', today);
        self.assertIdentical(t.asHumanly(), 'Sun, 13 Sep 2009');
        var t = Methanal.Util.Time.fromRelative('mon', today);
        self.assertIdentical(t.asHumanly(), 'Mon, 7 Sep 2009');
        var t = Methanal.Util.Time.fromRelative('satur', today);
        self.assertIdentical(t.asHumanly(), 'Sat, 12 Sep 2009');

        self.assertThrows(
            Methanal.Util.TimeParseError,
            function() {
                return Methanal.Util.Time.fromRelative('', today);
            });
        self.assertThrows(
            Methanal.Util.TimeParseError,
            function() {
                return Methanal.Util.Time.fromRelative('hello', today);
            });
    },

    /**
     * L{Methanal.Util.Time.asDate} converts a Time into a C{Date} representing
     * the same time.
     */
    function test_asDate(self) {
        var t = Methanal.Util.Time();
        var d = t.asDate();
        self.assertIdentical(t.asTimestamp(), d.getTime());
    },

    /**
     * L{Methanal.Util.Time.asTimestamp} converts a Time into the number of
     * milliseconds elapsed since the epoch.
     */
    function test_asTimestamp(self) {
        self.assertIdentical(self._knownTime.asTimestamp(), 1252193783002);
    },

    /**
     * L{Methanal.Util.Time.asHumanly} converts a Time into a human-readable
     * string. Times that have been truncated to a date have an appropriately
     * accurate human-readable version.
     */
    function test_asHumanly(self) {
        self.assertIdentical(
            self._knownTime.asHumanly(), 'Sun, 6 Sep 2009 01:36:23');
        self.assertIdentical(
            self._knownTime.oneDay().asHumanly(), 'Sun, 6 Sep 2009');
    },

    /**
     * L{Methanal.Util.Time.oneDay} truncates a Time to only a date.
     */
    function test_oneDay(self) {
        var t = Methanal.Util.Time();
        var od = t.oneDay().asDate();
        t = t.asDate();
        self.assertIdentical(od.getFullYear(), t.getFullYear());
        self.assertIdentical(od.getMonth(), t.getMonth());
        self.assertIdentical(od.getDate(), t.getDate());
        self.assertIdentical(od.getHours(), 0);
        self.assertIdentical(od.getMinutes(), 0);
        self.assertIdentical(od.getSeconds(), 0);
        self.assertIdentical(od.getMilliseconds(), 0);
    },

    /**
     * L{Methanal.Util.Time.offset} offsets a Time by the given number of
     * milliseconds.
     */
    function test_offset(self) {
        var t = self._knownTime.offset(Methanal.Util.TimeDelta({'days': -1}));
        self.assertIdentical(t.asTimestamp(), 1252107383002);
        self.assertIdentical(t.oneDay().asHumanly(), 'Sat, 5 Sep 2009');

        var t = self._knownTime.offset(Methanal.Util.TimeDelta({'days': 1}));
        self.assertIdentical(t.asTimestamp(), 1252280183002);
        self.assertIdentical(t.oneDay().asHumanly(), 'Mon, 7 Sep 2009');
    });
<commit_msg>Additional testing for Time.guess.<commit_after>// import Divmod.UnitTest
// import Methanal.Util

Divmod.UnitTest.TestCase.subclass(Methanal.Tests.TestUtil, 'TestUtil').methods(
    function test_strToInt(self) {
        var CASES = [
            ['1234', 1234],
            ['01234', 1234],
            ['001234', 1234],
            ['019', 19],
            ['123abc', undefined],
            ['abc123', undefined],
            ['0x123', undefined]];

        for (var i = 0; i < CASES.length; ++i) {
            var input = CASES[i][0];
            var expected = CASES[i][1];
            var actual = Methanal.Util.strToInt(input);
            self.assert(expected === actual, 'input = ' + input + ' :: expected = ' + expected + ' :: actual = ' + actual);
        }
    },

    function test_reduce(self) {
        var reduce = Methanal.Util.reduce;

        function add(x, y) {
            return x + y;
        }

        function multiply(x, y) {
            return x * y;
        }

        self.assertIdentical(reduce(add, [1, 2, 3]), 6);
        self.assertIdentical(reduce(multiply, [1, 2, 3], 10), 60);
        self.assertThrows(Error, function () { return reduce(add, []); });
        self.assertIdentical(reduce(add, [], 10), 10);
        self.assertIdentical(reduce(add, [10]), 10);
    },

    /**
     * Test L{Methanal.Util._reprString} correctly escapes various whitespace
     * characters.
     */
    function test_reprString(self) {
        var s = '\r\n\f\b\t';
        var repr = Methanal.Util._reprString(s);
        var expected = "\"\\r\\n\\f\\b\\t\"";
        self.assertIdentical(repr, expected);
    });

/**
 * Tests for L{Methanal.Util.Time}.
 *
 * @type _knownTime: L{Methanal.Util.Time}
 * @ivar _knownTime: A known point in time
 */
Divmod.UnitTest.TestCase.subclass(Methanal.Tests.TestUtil, 'TestTime').methods(
    function setUp(self) {
        self._knownTime = Methanal.Util.Time.fromDate(
            new Date(2009, 8, 6, 1, 36, 23, 2));
    },

    /**
     * L{Methanal.Util.TimeDelta} correctly specifies a given duration in
     * milliseconds.
     */
    function test_timedelta(self) {
        var td = Methanal.Util.TimeDelta({'days': 1});
        self.assertIdentical(td, 1000 * 3600 * 24);

        var td = Methanal.Util.TimeDelta({'days': -1});
        self.assertIdentical(td, 1000 * 3600 * -24);

        var td = Methanal.Util.TimeDelta({'days': 1,
                                          'hours': 2});
        self.assertIdentical(td, 1000 * 3600 * 26);

        var td = Methanal.Util.TimeDelta({'days': 1,
                                          'hours': 2,
                                          'minutes': 3});
        self.assertIdentical(td, 1000 * (3600 * 26 + 60 * 3));

        var td = Methanal.Util.TimeDelta({'days': 1,
                                          'hours': 2,
                                          'minutes': 3,
                                          'seconds': 4});
        self.assertIdentical(td, 1000 * (3600 * 26 + 60 * 3 + 4));

        var td = Methanal.Util.TimeDelta({'days': 1,
                                          'hours': 2,
                                          'minutes': 3,
                                          'seconds': 4,
                                          'milliseconds': 5});
        self.assertIdentical(td, 1000 * (3600 * 26 + 60 * 3 + 4) + 5);
    },

    /**
     * L{Methanal.Util.Time.guess} creates a L{Methanal.Util.Time} instance
     * when given an input format it can parse.
     */
    function test_guess(self) {
        function assertTimeParsed(data, timestamp) {
            var time = Methanal.Util.Time.guess(data);
            self.assertIdentical(time._oneDay, true);
            self.assertIdentical(time.asTimestamp(), timestamp);
        };

        assertTimeParsed('2009/9/1',   1251756000000);
        assertTimeParsed('2009.09.01', 1251756000000);
        assertTimeParsed('2009-09-01', 1251756000000);
        assertTimeParsed('1/9/2009',   1251756000000);
        assertTimeParsed('01.09.2009', 1251756000000);
        assertTimeParsed('01-09-2009', 1251756000000);
        assertTimeParsed('1/9/2009',   1251756000000);
        assertTimeParsed('29/2/2008',  1204236000000);
    },

    /**
     * L{Methanal.Util.Time.guess} throws L{Methanal.Util.TimeParseError} when
     * the input is not in any recognisable format, and reraises the original
     * exception if something other than L{Methanal.Util.TimeParseError} occurs.
     */
    function test_guessFailure(self) {
        function assertTimeParseError(data) {
            self.assertThrows(
                Methanal.Util.TimeParseError,
                function() { return Methanal.Util.Time.guess(data); });
        };

        assertTimeParseError('');
        assertTimeParseError('hello');
        assertTimeParseError('1/2/3');
        assertTimeParseError('2009/01');
        assertTimeParseError('2009/01');
        assertTimeParseError('2009/01/32');
        assertTimeParseError('2009/02/29');

        self.assertThrows(
            TypeError,
            function() { return Methanal.Util.Time.guess(undefined); });
    },

    /**
     * Create a L{Methanal.Util.Time} instance from a C{Date}.
     */
    function test_fromDate(self) {
        var d = new Date();
        var t = Methanal.Util.Time.fromDate(d);
        self.assertIdentical(t.asTimestamp(), d.getTime());
    },

    /**
     * Create a L{Methanal.Util.Time} instance from a valid relative time
     * reference, while invalid references throw
     * L{Methanal.Util.TimeParseError}.
     */
    function test_fromRelative(self) {
        var today = self._knownTime;

        var t = Methanal.Util.Time.fromRelative('tomorrow', today);
        self.assertIdentical(t.asHumanly(), 'Mon, 7 Sep 2009');
        var t = Methanal.Util.Time.fromRelative('yesterday', today);
        self.assertIdentical(t.asHumanly(), 'Sat, 5 Sep 2009');
        var t = Methanal.Util.Time.fromRelative('today', today);
        self.assertIdentical(t.asHumanly(), 'Sun, 6 Sep 2009');

        var t = Methanal.Util.Time.fromRelative('sun', today);
        self.assertIdentical(t.asHumanly(), 'Sun, 13 Sep 2009');
        var t = Methanal.Util.Time.fromRelative('mon', today);
        self.assertIdentical(t.asHumanly(), 'Mon, 7 Sep 2009');
        var t = Methanal.Util.Time.fromRelative('satur', today);
        self.assertIdentical(t.asHumanly(), 'Sat, 12 Sep 2009');

        self.assertThrows(
            Methanal.Util.TimeParseError,
            function() {
                return Methanal.Util.Time.fromRelative('', today);
            });
        self.assertThrows(
            Methanal.Util.TimeParseError,
            function() {
                return Methanal.Util.Time.fromRelative('hello', today);
            });
    },

    /**
     * L{Methanal.Util.Time.asDate} converts a Time into a C{Date} representing
     * the same time.
     */
    function test_asDate(self) {
        var t = Methanal.Util.Time();
        var d = t.asDate();
        self.assertIdentical(t.asTimestamp(), d.getTime());
    },

    /**
     * L{Methanal.Util.Time.asTimestamp} converts a Time into the number of
     * milliseconds elapsed since the epoch.
     */
    function test_asTimestamp(self) {
        self.assertIdentical(self._knownTime.asTimestamp(), 1252193783002);
    },

    /**
     * L{Methanal.Util.Time.asHumanly} converts a Time into a human-readable
     * string. Times that have been truncated to a date have an appropriately
     * accurate human-readable version.
     */
    function test_asHumanly(self) {
        self.assertIdentical(
            self._knownTime.asHumanly(), 'Sun, 6 Sep 2009 01:36:23');
        self.assertIdentical(
            self._knownTime.oneDay().asHumanly(), 'Sun, 6 Sep 2009');
    },

    /**
     * L{Methanal.Util.Time.oneDay} truncates a Time to only a date.
     */
    function test_oneDay(self) {
        var t = Methanal.Util.Time();
        var od = t.oneDay().asDate();
        t = t.asDate();
        self.assertIdentical(od.getFullYear(), t.getFullYear());
        self.assertIdentical(od.getMonth(), t.getMonth());
        self.assertIdentical(od.getDate(), t.getDate());
        self.assertIdentical(od.getHours(), 0);
        self.assertIdentical(od.getMinutes(), 0);
        self.assertIdentical(od.getSeconds(), 0);
        self.assertIdentical(od.getMilliseconds(), 0);
    },

    /**
     * L{Methanal.Util.Time.offset} offsets a Time by the given number of
     * milliseconds.
     */
    function test_offset(self) {
        var t = self._knownTime.offset(Methanal.Util.TimeDelta({'days': -1}));
        self.assertIdentical(t.asTimestamp(), 1252107383002);
        self.assertIdentical(t.oneDay().asHumanly(), 'Sat, 5 Sep 2009');

        var t = self._knownTime.offset(Methanal.Util.TimeDelta({'days': 1}));
        self.assertIdentical(t.asTimestamp(), 1252280183002);
        self.assertIdentical(t.oneDay().asHumanly(), 'Mon, 7 Sep 2009');
    });
<|endoftext|>


<commit_before>/**
 * Script used for the Iframe only
 */

if (typeof window !== 'undefined') global = window;

var FRONT_END_TEST = global.FRONT_END_TEST || false;

var StyleguideIframe = {
  init: function() {
    if (!$('.huge-iframe-content').length && !FRONT_END_TEST) return false;

    this.$sectionAnchors = $('.anchor');

    this.codeToCreateSnippetClass = '.snippet';
    this.sidebarMenuLinkClass = '.huge-sidebar__nav__item__link';
    this.codeSnippetsClass = '.huge-module__toggle-code';
    this.sidebarLinkWasClickedClass = 'side-menu-clicked';
    this.sidebarActiveLinkClass = 'active';
    this.modulesOffsetTop = [];
    this.activeModule = null;

    if (FRONT_END_TEST) return false;

    this.sidebarLinksHighlightSetup();
    this.codeSnippetsSetup();
    this.events();
  },

  /**
   * All events of the iframe
   * should be registered here
   */
  events: function() {
    var _this = this;

    $(window).scroll(function() {
      _this.sidebarLinksHighlight();
    });

    $(this.codeSnippetsClass).click(function(e) {
      e.preventDefault();
      _this.codeSnippetsToggle($(this));
      _this.sidebarLinksHighlightSetup();
    });
  },

  /**
   * Setup markup code snippet.
   * It gets the HTML of the element and creates the code area
   */
  codeSnippetsSetup: function() {
    var _this = this,
      options = {
        "indent":"auto",
        "indent-spaces":2,
        "wrap":80,
        "markup":true,
        "output-xml":false,
        "numeric-entities":true,
        "quote-marks":true,
        "quote-nbsp":false,
        "show-body-only":true,
        "quote-ampersand":false,
        "break-before-br":true,
        "uppercase-tags":false,
        "uppercase-attributes":false,
        "drop-font-tags":true,
        "tidy-mark":false,
        "quiet":"yes",
        "show-warnings":"no"
      };

    $(this.codeToCreateSnippetClass).each(function(i, obj) {
      var snippet = tidy_html5($(obj).get(0).outerHTML.replace(' ' + this.codeToCreateSnippetClass, '').replace(this.codeToCreateSnippetClass, ''), options);

      $(obj).before('');
      $(obj).after('
' + $('
').text(snippet).html() + '
').next().hide();
    });

    Prism.highlightAll();
  },

  /**
   * Function that shows or hide the code snippet area
   */
  codeSnippetsToggle: function($elem) {
    var $code = $elem.next().next();

    $code.toggle();
  },

  /**
   * Records all module's offset top value for reference.
   * Such values will be used later when trying to discover where the user is
   * when scrolling the iframe.
   */
  sidebarLinksHighlightSetup: function() {
    var _this = this;

    this.$sectionAnchors.each(function(i, obj) {
      if (typeof $(obj) === 'undefined') return false;
      var top = $(obj).attr('id') === _this.$sectionAnchors.first().attr('id') ? 0 : $(obj).offset().top + 100;

      _this.modulesOffsetTop.push({
        module: $(obj).attr('id'),
        offset: top
      });
    });
  },

  /**
   * Highlight the current module's sidebar link
   * based on scroll position
   */
  sidebarLinksHighlight: function() {
    var _this = this,
      scrollTop = $(window).scrollTop(),
      actualActiveSectionId,
      top = null,
      i = 0;

    // Shutdown this feature in Chrome.
    // Chrome have a know issue with file protocol and iframe comunication.
    // It is not supported so we should not raise errors.
    if (window.location.protocol === 'file:' && navigator.userAgent.toLowerCase().indexOf('chrome') > -1) return false;

    for (i; i <= this.modulesOffsetTop.length - 1; i++) {
      top = _this.modulesOffsetTop[i].offset;

      if (top < scrollTop + 100) {
        actualActiveSectionId = _this.modulesOffsetTop[i].module;
      }
      if (scrollTop + $(window).height() === $(document).height()) {
        actualActiveSectionId = $(_this.sidebarMenuLinkClass, window.parent.document).last().attr('href').replace('#', '');
      }
    }

    if (_this.activeModule !== actualActiveSectionId && typeof actualActiveSectionId !== 'undefined') {
      if (!$('body', window.parent.document).hasClass(this.sidebarLinkWasClickedClass)) {
        $(this.sidebarMenuLinkClass, window.parent.document).removeClass(this.sidebarActiveLinkClass);
        $(this.sidebarMenuLinkClass + '[href="#' + actualActiveSectionId + '"]', window.parent.document).addClass(this.sidebarActiveLinkClass);

        // Why changing the hash is so slow and produces a lag?
        // Use ! to prevent de default browser behavior of anchor navigation
        window.parent.location.hash = '!' + actualActiveSectionId;
      }
      $('body', window.parent.document).removeClass(this.sidebarLinkWasClickedClass);
      _this.activeModule = actualActiveSectionId;
    }
  }
};

if(!FRONT_END_TEST) {
  $(window).load(function() {
    StyleguideIframe.init();
  });
} else {
  FRONT_END_TEST.StyleguideIframe = StyleguideIframe;
}
<commit_msg>Code snippet preview now properly hides the preview tiggering classname<commit_after>/**
 * Script used for the Iframe only
 */

if (typeof window !== 'undefined') global = window;

var FRONT_END_TEST = global.FRONT_END_TEST || false;

var StyleguideIframe = {
  init: function() {
    if (!$('.huge-iframe-content').length && !FRONT_END_TEST) return false;

    this.$sectionAnchors = $('.anchor');

    this.codeToCreateSnippetClass = '.snippet';
    this.sidebarMenuLinkClass = '.huge-sidebar__nav__item__link';
    this.codeSnippetsClass = '.huge-module__toggle-code';
    this.sidebarLinkWasClickedClass = 'side-menu-clicked';
    this.sidebarActiveLinkClass = 'active';
    this.modulesOffsetTop = [];
    this.activeModule = null;

    if (FRONT_END_TEST) return false;

    this.sidebarLinksHighlightSetup();
    this.codeSnippetsSetup();
    this.events();
  },

  /**
   * All events of the iframe
   * should be registered here
   */
  events: function() {
    var _this = this;

    $(window).scroll(function() {
      _this.sidebarLinksHighlight();
    });

    $(this.codeSnippetsClass).click(function(e) {
      e.preventDefault();
      _this.codeSnippetsToggle($(this));
      _this.sidebarLinksHighlightSetup();
    });
  },

  /**
   * Setup markup code snippet.
   * It gets the HTML of the element and creates the code area
   */
  codeSnippetsSetup: function() {
    var _this = this,
      options = {
        "indent":"auto",
        "indent-spaces":2,
        "wrap":80,
        "markup":true,
        "output-xml":false,
        "numeric-entities":true,
        "quote-marks":true,
        "quote-nbsp":false,
        "show-body-only":true,
        "quote-ampersand":false,
        "break-before-br":true,
        "uppercase-tags":false,
        "uppercase-attributes":false,
        "drop-font-tags":true,
        "tidy-mark":false,
        "quiet":"yes",
        "show-warnings":"no"
      };

    $(this.codeToCreateSnippetClass).each(function(i, obj) {
      var snippetClassName = _this.codeToCreateSnippetClass.replace(/\./g, '');
      var snippet = tidy_html5($(obj).get(0).outerHTML.replace(' ' + snippetClassName, '').replace(snippetClassName, ''), options);

      $(obj).before('');
      $(obj).after('
' + $('
').text(snippet).html() + '
').next().hide();
    });

    Prism.highlightAll();
  },

  /**
   * Function that shows or hide the code snippet area
   */
  codeSnippetsToggle: function($elem) {
    var $code = $elem.next().next();

    $code.toggle();
  },

  /**
   * Records all module's offset top value for reference.
   * Such values will be used later when trying to discover where the user is
   * when scrolling the iframe.
   */
  sidebarLinksHighlightSetup: function() {
    var _this = this;

    this.$sectionAnchors.each(function(i, obj) {
      if (typeof $(obj) === 'undefined') return false;
      var top = $(obj).attr('id') === _this.$sectionAnchors.first().attr('id') ? 0 : $(obj).offset().top + 100;

      _this.modulesOffsetTop.push({
        module: $(obj).attr('id'),
        offset: top
      });
    });
  },

  /**
   * Highlight the current module's sidebar link
   * based on scroll position
   */
  sidebarLinksHighlight: function() {
    var _this = this,
      scrollTop = $(window).scrollTop(),
      actualActiveSectionId,
      top = null,
      i = 0;

    // Shutdown this feature in Chrome.
    // Chrome have a know issue with file protocol and iframe comunication.
    // It is not supported so we should not raise errors.
    if (window.location.protocol === 'file:' && navigator.userAgent.toLowerCase().indexOf('chrome') > -1) return false;

    for (i; i <= this.modulesOffsetTop.length - 1; i++) {
      top = _this.modulesOffsetTop[i].offset;

      if (top < scrollTop + 100) {
        actualActiveSectionId = _this.modulesOffsetTop[i].module;
      }
      if (scrollTop + $(window).height() === $(document).height()) {
        actualActiveSectionId = $(_this.sidebarMenuLinkClass, window.parent.document).last().attr('href').replace('#', '');
      }
    }

    if (_this.activeModule !== actualActiveSectionId && typeof actualActiveSectionId !== 'undefined') {
      if (!$('body', window.parent.document).hasClass(this.sidebarLinkWasClickedClass)) {
        $(this.sidebarMenuLinkClass, window.parent.document).removeClass(this.sidebarActiveLinkClass);
        $(this.sidebarMenuLinkClass + '[href="#' + actualActiveSectionId + '"]', window.parent.document).addClass(this.sidebarActiveLinkClass);

        // Why changing the hash is so slow and produces a lag?
        // Use ! to prevent de default browser behavior of anchor navigation
        window.parent.location.hash = '!' + actualActiveSectionId;
      }
      $('body', window.parent.document).removeClass(this.sidebarLinkWasClickedClass);
      _this.activeModule = actualActiveSectionId;
    }
  }
};

if(!FRONT_END_TEST) {
  $(window).load(function() {
    StyleguideIframe.init();
  });
} else {
  FRONT_END_TEST.StyleguideIframe = StyleguideIframe;
}
<|endoftext|>