<commit_before>// ==UserScript==
// @name         Duoling Reverse Tree Enhancer
// @namespace    https://github.com/guillaumebrunerie/reversetreeenhancer
// @version      0.1.7
// @description  Enhance reverse trees by adding a TTS (currently Google Translate) and turning most exercices into listening exercices by hiding the text in the target language.
// @author       Guillaume Brunerie
// @match        https://www.duolingo.com/*
// @downloadURL  https://github.com/guillaumebrunerie/reversetreeenhancer/raw/master/DuolingoReverseTreeEnhancer.user.js
// @grant        none
// ==/UserScript==

console.debug('Duolingo: Reverse Tree Enhancer');

/* The color used for hiding */
var hColor = "lightgray";

/* Turns a stylesheet (as a string) into a style element */
function toStyleElem(css) {
    var style = document.createElement('style');

    style.type = 'text/css';
    if (style.styleSheet){
        style.styleSheet.cssText = css;
    } else {
        style.appendChild(document.createTextNode(css));
    }

    return style;
}

/* Stylesheet for the button and the error box */
var css_button_seb = toStyleElem('' +
'#reverse-tree-enhancer-button { margin-left: 10px; }\n' +
'#reverse-tree-enhancer-button.selected { background-color: purple; color: white; border-color: purple; }\n' +
'#reverse-tree-enhancer-button.selected:hover { background-color: #A000A0; border-color: #A000A0; }\n' +
'\n' +
'#sound-error-box { left: 50%; transform: translate(-50%, 0); top: 20px; color: #FF3333; font-weight: bold; }\n' +
'#sound-error-box .tooltip-inner { color: #FF3333; font-weight: bold; }\n' +
'#sound-error-box button { padding: 5px 10px; border: none; border-radius: 100px; }\n' +
'#sound-error-box button:hover { background-color: #EEE; }');

document.head.appendChild(css_button_seb);

/* Stylesheet for the hiding for the multiple-choice questions */
var css_hiding = toStyleElem('' +
'.list-judge-options.hover-effect:not(.nothiding) .white-label:not(:hover):not(.active) { color: ' + hColor +'; background-color: ' + hColor + '; border-color: ' + hColor + '; }\n' +
'.list-judge-options.hover-effect:not(.nothiding) .white-label:not(:hover):not(.active) input[type=checkbox] { visibility: hidden; }\n' +
'\n' +
'.select-images.hover-effect:not(.nothiding)>li:not(:hover):not(.selected) { color: ' + hColor +'; background-color: ' + hColor + '; border-color: ' + hColor + '; }\n' +
'.select-images.hover-effect:not(.nothiding)>li:not(:hover):not(.selected) input[type=radio] { visibility: hidden; }\n' +
'.select-images.hover-effect:not(.nothiding)>li:not(:hover):not(.selected) .select-images-frame { visibility: hidden; }');

function addCSSHiding() {
    document.head.appendChild(css_hiding);
}

function removeCSSHiding() {
    document.head.appendChild(css_hiding);
    document.head.removeChild(css_hiding);
}

/* Sound Error box */
var soundErrorBox = document.createElement('div');
soundErrorBox.className = "tooltip top";
soundErrorBox.id = "sound-error-box";
soundErrorBox.innerHTML = '
Error when loading the sound, click here and try to fix the problem. <button id="sound-error-button">Done</button>
';

function tryagain() {
    hideSoundErrorBox();
    audio.load();
}

function hideSoundErrorBox() {
    soundErrorBox.style.display = "none";
}

function displaySoundErrorBox(url) {
    var container = document.getElementsByClassName("player-container")[0];
    container.insertBefore(soundErrorBox, container.firstChild);
    document.getElementById("sound-error-link").href = url;
    soundErrorBox.style.display = "";
    document.getElementById("sound-error-button").onclick = tryagain;
}

/* Audio functions */

var audio;
var prevAudio;
var waiting = false;
var counter = 0;

function playSound(url) {
    counter = counter + 1;
    if(prevAudio){ prevAudio.destruct(); }
    prevAudio = audio;
    waiting = (prevAudio && prevAudio.playState == 1);
    // race condition here…
    audio = soundManager.createSound({
        id: "sound-" + counter,
        url: url,
        autoLoad: true,
        onload: function() {
            if(audio.readyState == 2){
                displaySoundErrorBox(audio.url);
            } else if(!waiting){
                audio.play();
            }
        },
        onfinish: function () {
            if(waiting) {
                waiting = false;
                audio.play();
            }
        }
    });
}

function say(sentence) {
    console.debug("Reverse Tree Enhancer: saying " + sentence);
    playSound("http://translate.google.com/translate_tts?tl=" + targetLang + "&q=" + sentence);
}

function keyUpHandler(e) {
    if (e.shiftKey && e.keyCode == 32 && audio) {
        audio.stop().play();
    }
}

document.addEventListener('keyup', keyUpHandler, false);

/* jQuery hack to avoid reading things in display:none, copy-pasted from StackOverflow */
function sayCell(cell) {
    var t = $(cell).clone();
    $('body').append(t);
    t.find('*:not(:visible)').remove();
    t.remove();
    say(t.text());
}

/* Functions acting on the various types of exercices */

/* Translation from target language (eg. Polish) */
function challengeTranslateTarget(){
    var cell = challenge.getElementsByClassName("text-to-translate")[0];
    if(grade.children.length === 0){
        sayCell(cell);
        cell.style.color = hColor;
        cell.style.backgroundColor = hColor;
        cell.getElementsByTagName("bdi")[0].style.display = "none";
    } else {
        cell.style.color = "";
        cell.style.backgroundColor = "";
        cell.getElementsByTagName("bdi")[0].style.display = "";
    }
}

/* Translation from source language (eg. English) */
function challengeTranslateSource(){
    if(grade.children.length > 0){
        var betterAnswer = grade.getElementsByTagName("h1")[0].getElementsByTagName("span");
        // Hack for making timed practice work
        var isTimedPractice = (grade.getElementsByClassName("icon-clock-medium").length !== 0);
        var blame = document.getElementById("blame-1")
        var isTypo = blame && blame.offsetParent !== null
        if(isTimedPractice && !isTypo){
            betterAnswer = [];
        }

        if(betterAnswer.length === 0){
            say(document.getElementById("submitted-text").textContent);
        } else {
            say(betterAnswer[0].textContent);
        }
    }
}

/* Multiple-choice translation question */
function challengeJudge(){
    var textCell = challenge.getElementsByClassName("col-left")[0].getElementsByTagName("bdi")[0];
    var ul = challenge.getElementsByTagName("ul")[0];
    if(grade.children.length === 0){
        textCell.style.color = hColor;
        textCell.style.backgroundColor = hColor;
        textCell.style.display = "block";

        say(textCell.textContent);
    } else {
        textCell.style.color = "";
        textCell.style.backgroundColor = "";
        ul.className += " nothiding";
    }
}

var quotMark = /["“”]/;

/* Select the correct image */
function challengeSelect(){
    var hone = challenge.getElementsByTagName("h1")[0];
    var ul = challenge.getElementsByTagName("ul")[0];
    var span;
    if(grade.children.length === 0){
        hone.innerHTML = hone.textContent.split(quotMark)[0] + "“" + hone.textContent.split(quotMark)[1] + "”";
        span = hone.getElementsByTagName("span")[0];
        say(span.textContent);
        span.style.color = hColor;
        span.style.backgroundColor = hColor;
    } else {
        span = hone.getElementsByTagName("span")[0];
        span.style.color = "";
        span.style.backgroundColor = "";
        ul.className += " nothiding";
    }
}

/* Type the word corresponding to the images */
function challengeName(){
    var lis = challenge.getElementsByClassName("list-tilted-images")[0].getElementsByTagName("li");
    var hone = challenge.getElementsByTagName("h1")[0];
    var span, i;
    if(grade.children.length === 0){
        hone.innerHTML = hone.textContent.split(quotMark)[0] + "“" + hone.textContent.split(quotMark)[1] + "”";
        span = hone.getElementsByTagName("span")[0];
        say(span.textContent);
        span.style.color = hColor;
        span.style.backgroundColor = hColor;
        for(i=0; i < lis.length; i++){
            lis[i].style.backgroundColor = hColor;
            lis[i].dataset.oldImage = lis[i].style.backgroundImage;
            lis[i].style.backgroundImage = "";
        }
    } else {
        span = hone.getElementsByTagName("span")[0];
        span.style.color = "";
        span.style.backgroundColor = "";

        for(i=0; i < lis.length; i++){
            lis[i].style.backgroundImage = lis[i].dataset.oldImage;
        }
    }
}

/* Multiple-choice question where we have to choose a word in the source language. Those are useless exercices, but we can’t get rid of them. */
function challengeForm(){
    if(grade.children.length !== 0){
        say(grade.getElementsByTagName("h2")[0].children[1].textContent);
    }
}

/* Function dealing with the button on the home page */

function isReverseTree() {
    var reverseTrees = JSON.parse(localStorage.getItem("reverse_trees"));
    if(reverseTrees === null) {
        return false;
    }
    var item = document.body.lang + "-" + duo.user.attributes.learning_language;
    return !!(reverseTrees[item]);
}

function toggleLang() {
    var reverseTrees = JSON.parse(localStorage.getItem("reverse_trees"));
    if(reverseTrees === null) { reverseTrees = {}; }
    var item = document.body.lang + "-" + duo.user.attributes.learning_language;
    reverseTrees[item] = !reverseTrees[item];
    localStorage.setItem("reverse_trees", JSON.stringify(reverseTrees));
    updateButton();
}

function updateButton() {
    var button = document.getElementById("reverse-tree-enhancer-button");
    if(button === null){ return; }
    if(isReverseTree()) {
        button.textContent = "This is a reverse tree!";
        button.className = "btn btn-standard right btn-store selected";
    } else {
        button.textContent = "Is this a reverse tree?";
        button.className = "btn btn-standard right btn-store";
    }
}

/* Function dispatching the changes in the page to the other functions */

var oldclass = "";
var targetLang;
var grade, challenge;

function onChange() {
    var newclass = document.getElementById("app").className;

    if(/home/.test(newclass) && !document.getElementById("reverse-tree-enhancer-button")){
        var tree = document.getElementsByClassName("tree")[0];
        var button = document.createElement("button");
        button.id = "reverse-tree-enhancer-button";
        button.onclick = toggleLang;
        tree.insertBefore(button, tree.firstChild);
        updateButton();
    }

    if(newclass != oldclass){
        oldclass = newclass;

        hideSoundErrorBox();

        if(!isReverseTree()) {
            targetLang = "";
            removeCSSHiding();
            return;
        }
        targetLang = document.body.lang;
        if(!document.getElementById("timer")) { addCSSHiding(); } else { removeCSSHiding(); }

        var sec = document.getElementById("session-element-container");
        if(!sec){return;}
        challenge = sec.children[0];
        grade = document.getElementById("grade");

        if(/translate/.test(newclass)){
            if (challenge.getElementsByTagName("textarea")[0].getAttribute("lang") == targetLang){
                challengeTranslateSource();
            } else {
                challengeTranslateTarget();
            }
        }
        if(/judge/.test(newclass)){
            challengeJudge();
        }
        if(/select/.test(newclass)){
            challengeSelect();
        }
        if(/name/.test(newclass)){
            challengeName();
        }
        if(/form/.test(newclass)){
            challengeForm();
        }
    }
}

new MutationObserver(onChange).observe(document.body, {attributes: true, childList: true, subtree: true});
<commit_msg>Stop audio element from leaking outside of lessons<commit_after>// ==UserScript==
// @name         Duoling Reverse Tree Enhancer
// @namespace    https://github.com/guillaumebrunerie/reversetreeenhancer
// @version      0.1.7
// @description  Enhance reverse trees by adding a TTS (currently Google Translate) and turning most exercices into listening exercices by hiding the text in the target language.
// @author       Guillaume Brunerie
// @match        https://www.duolingo.com/*
// @downloadURL  https://github.com/guillaumebrunerie/reversetreeenhancer/raw/master/DuolingoReverseTreeEnhancer.user.js
// @grant        none
// ==/UserScript==

console.debug('Duolingo: Reverse Tree Enhancer');

/* The color used for hiding */
var hColor = "lightgray";

/* Turns a stylesheet (as a string) into a style element */
function toStyleElem(css) {
    var style = document.createElement('style');

    style.type = 'text/css';
    if (style.styleSheet){
        style.styleSheet.cssText = css;
    } else {
        style.appendChild(document.createTextNode(css));
    }

    return style;
}

/* Stylesheet for the button and the error box */
var css_button_seb = toStyleElem('' +
'#reverse-tree-enhancer-button { margin-left: 10px; }\n' +
'#reverse-tree-enhancer-button.selected { background-color: purple; color: white; border-color: purple; }\n' +
'#reverse-tree-enhancer-button.selected:hover { background-color: #A000A0; border-color: #A000A0; }\n' +
'\n' +
'#sound-error-box { left: 50%; transform: translate(-50%, 0); top: 20px; color: #FF3333; font-weight: bold; }\n' +
'#sound-error-box .tooltip-inner { color: #FF3333; font-weight: bold; }\n' +
'#sound-error-box button { padding: 5px 10px; border: none; border-radius: 100px; }\n' +
'#sound-error-box button:hover { background-color: #EEE; }');

document.head.appendChild(css_button_seb);

/* Stylesheet for the hiding for the multiple-choice questions */
var css_hiding = toStyleElem('' +
'.list-judge-options.hover-effect:not(.nothiding) .white-label:not(:hover):not(.active) { color: ' + hColor +'; background-color: ' + hColor + '; border-color: ' + hColor + '; }\n' +
'.list-judge-options.hover-effect:not(.nothiding) .white-label:not(:hover):not(.active) input[type=checkbox] { visibility: hidden; }\n' +
'\n' +
'.select-images.hover-effect:not(.nothiding)>li:not(:hover):not(.selected) { color: ' + hColor +'; background-color: ' + hColor + '; border-color: ' + hColor + '; }\n' +
'.select-images.hover-effect:not(.nothiding)>li:not(:hover):not(.selected) input[type=radio] { visibility: hidden; }\n' +
'.select-images.hover-effect:not(.nothiding)>li:not(:hover):not(.selected) .select-images-frame { visibility: hidden; }');

function addCSSHiding() {
    document.head.appendChild(css_hiding);
}

function removeCSSHiding() {
    document.head.appendChild(css_hiding);
    document.head.removeChild(css_hiding);
}

/* Sound Error box */
var soundErrorBox = document.createElement('div');
soundErrorBox.className = "tooltip top";
soundErrorBox.id = "sound-error-box";
soundErrorBox.innerHTML = '
Error when loading the sound, click here and try to fix the problem. <button id="sound-error-button">Done</button>
';

function tryagain() {
    hideSoundErrorBox();
    audio.load();
}

function hideSoundErrorBox() {
    soundErrorBox.style.display = "none";
}

function displaySoundErrorBox(url) {
    var container = document.getElementsByClassName("player-container")[0];
    container.insertBefore(soundErrorBox, container.firstChild);
    document.getElementById("sound-error-link").href = url;
    soundErrorBox.style.display = "";
    document.getElementById("sound-error-button").onclick = tryagain;
}

/* Audio functions */

var audio;
var prevAudio;
var waiting = false;
var counter = 0;

function playSound(url) {
    counter = counter + 1;
    if(prevAudio){ prevAudio.destruct(); }
    prevAudio = audio;
    waiting = (prevAudio && prevAudio.playState == 1);
    // race condition here…
    audio = soundManager.createSound({
        id: "sound-" + counter,
        url: url,
        autoLoad: true,
        onload: function() {
            if(audio.readyState == 2){
                displaySoundErrorBox(audio.url);
            } else if(!waiting){
                audio.play();
            }
        },
        onfinish: function () {
            if(waiting) {
                waiting = false;
                audio.play();
            }
        }
    });
}

function say(sentence) {
    console.debug("Reverse Tree Enhancer: saying " + sentence);
    playSound("http://translate.google.com/translate_tts?tl=" + targetLang + "&q=" + sentence);
}

function keyUpHandler(e) {
    if (e.shiftKey && e.keyCode == 32 && audio) {
        audio.stop().play();
    }
}

document.addEventListener('keyup', keyUpHandler, false);

/* jQuery hack to avoid reading things in display:none, copy-pasted from StackOverflow */
function sayCell(cell) {
    var t = $(cell).clone();
    $('body').append(t);
    t.find('*:not(:visible)').remove();
    t.remove();
    say(t.text());
}

/* Functions acting on the various types of exercices */

/* Translation from target language (eg. Polish) */
function challengeTranslateTarget(){
    var cell = challenge.getElementsByClassName("text-to-translate")[0];
    if(grade.children.length === 0){
        sayCell(cell);
        cell.style.color = hColor;
        cell.style.backgroundColor = hColor;
        cell.getElementsByTagName("bdi")[0].style.display = "none";
    } else {
        cell.style.color = "";
        cell.style.backgroundColor = "";
        cell.getElementsByTagName("bdi")[0].style.display = "";
    }
}

/* Translation from source language (eg. English) */
function challengeTranslateSource(){
    if(grade.children.length > 0){
        var betterAnswer = grade.getElementsByTagName("h1")[0].getElementsByTagName("span");
        // Hack for making timed practice work
        var isTimedPractice = (grade.getElementsByClassName("icon-clock-medium").length !== 0);
        var blame = document.getElementById("blame-1")
        var isTypo = blame && blame.offsetParent !== null
        if(isTimedPractice && !isTypo){
            betterAnswer = [];
        }

        if(betterAnswer.length === 0){
            say(document.getElementById("submitted-text").textContent);
        } else {
            say(betterAnswer[0].textContent);
        }
    }
}

/* Multiple-choice translation question */
function challengeJudge(){
    var textCell = challenge.getElementsByClassName("col-left")[0].getElementsByTagName("bdi")[0];
    var ul = challenge.getElementsByTagName("ul")[0];
    if(grade.children.length === 0){
        textCell.style.color = hColor;
        textCell.style.backgroundColor = hColor;
        textCell.style.display = "block";

        say(textCell.textContent);
    } else {
        textCell.style.color = "";
        textCell.style.backgroundColor = "";
        ul.className += " nothiding";
    }
}

var quotMark = /["“”]/;

/* Select the correct image */
function challengeSelect(){
    var hone = challenge.getElementsByTagName("h1")[0];
    var ul = challenge.getElementsByTagName("ul")[0];
    var span;
    if(grade.children.length === 0){
        hone.innerHTML = hone.textContent.split(quotMark)[0] + "“" + hone.textContent.split(quotMark)[1] + "”";
        span = hone.getElementsByTagName("span")[0];
        say(span.textContent);
        span.style.color = hColor;
        span.style.backgroundColor = hColor;
    } else {
        span = hone.getElementsByTagName("span")[0];
        span.style.color = "";
        span.style.backgroundColor = "";
        ul.className += " nothiding";
    }
}

/* Type the word corresponding to the images */
function challengeName(){
    var lis = challenge.getElementsByClassName("list-tilted-images")[0].getElementsByTagName("li");
    var hone = challenge.getElementsByTagName("h1")[0];
    var span, i;
    if(grade.children.length === 0){
        hone.innerHTML = hone.textContent.split(quotMark)[0] + "“" + hone.textContent.split(quotMark)[1] + "”";
        span = hone.getElementsByTagName("span")[0];
        say(span.textContent);
        span.style.color = hColor;
        span.style.backgroundColor = hColor;
        for(i=0; i < lis.length; i++){
            lis[i].style.backgroundColor = hColor;
            lis[i].dataset.oldImage = lis[i].style.backgroundImage;
            lis[i].style.backgroundImage = "";
        }
    } else {
        span = hone.getElementsByTagName("span")[0];
        span.style.color = "";
        span.style.backgroundColor = "";

        for(i=0; i < lis.length; i++){
            lis[i].style.backgroundImage = lis[i].dataset.oldImage;
        }
    }
}

/* Multiple-choice question where we have to choose a word in the source language. Those are useless exercices, but we can’t get rid of them. */
function challengeForm(){
    if(grade.children.length !== 0){
        say(grade.getElementsByTagName("h2")[0].children[1].textContent);
    }
}

/* Function dealing with the button on the home page */

function isReverseTree() {
    var reverseTrees = JSON.parse(localStorage.getItem("reverse_trees"));
    if(reverseTrees === null) {
        return false;
    }
    var item = document.body.lang + "-" + duo.user.attributes.learning_language;
    return !!(reverseTrees[item]);
}

function toggleLang() {
    var reverseTrees = JSON.parse(localStorage.getItem("reverse_trees"));
    if(reverseTrees === null) { reverseTrees = {}; }
    var item = document.body.lang + "-" + duo.user.attributes.learning_language;
    reverseTrees[item] = !reverseTrees[item];
    localStorage.setItem("reverse_trees", JSON.stringify(reverseTrees));
    updateButton();
}

function updateButton() {
    var button = document.getElementById("reverse-tree-enhancer-button");
    if(button === null){ return; }
    if(isReverseTree()) {
        button.textContent = "This is a reverse tree!";
        button.className = "btn btn-standard right btn-store selected";
    } else {
        button.textContent = "Is this a reverse tree?";
        button.className = "btn btn-standard right btn-store";
    }
}

/* Function dispatching the changes in the page to the other functions */

var oldclass = "";
var targetLang;
var grade, challenge;

function onChange() {
    var newclass = document.getElementById("app").className;

    if(/home/.test(newclass) && !document.getElementById("reverse-tree-enhancer-button")){
        var tree = document.getElementsByClassName("tree")[0];
        var button = document.createElement("button");
        button.id = "reverse-tree-enhancer-button";
        button.onclick = toggleLang;
        tree.insertBefore(button, tree.firstChild);
        updateButton();
    }

    if (/slide-session-end/.test(newclass)) {
        // End screen ("you beat the clock...").
        // Destroy the reference to the audio object
        // so that subsequent <S-Space> keypresses
        // don't cause the audio to repeat in, e.g., the tree or discussions.
        audio = null;
    }

    if(newclass != oldclass){
        oldclass = newclass;

        hideSoundErrorBox();

        if(!isReverseTree()) {
            targetLang = "";
            removeCSSHiding();
            return;
        }
        targetLang = document.body.lang;
        if(!document.getElementById("timer")) { addCSSHiding(); } else { removeCSSHiding(); }

        var sec = document.getElementById("session-element-container");
        if(!sec){return;}
        challenge = sec.children[0];
        grade = document.getElementById("grade");

        if(/translate/.test(newclass)){
            if (challenge.getElementsByTagName("textarea")[0].getAttribute("lang") == targetLang){
                challengeTranslateSource();
            } else {
                challengeTranslateTarget();
            }
        }
        if(/judge/.test(newclass)){
            challengeJudge();
        }
        if(/select/.test(newclass)){
            challengeSelect();
        }
        if(/name/.test(newclass)){
            challengeName();
        }
        if(/form/.test(newclass)){
            challengeForm();
        }
    }
}

new MutationObserver(onChange).observe(document.body, {attributes: true, childList: true, subtree: true});
<|endoftext|>


<commit_before>// ==UserScript==
// @name         Legend mod - Mass Bar Addon
// @namespace    Legend mod - Mass Bar Addon
// @version      0.1
// @description  Legend mod - Mass Bar Addon
// @author       DAVI すべての最強!
// @match        https://agar.io/*
// ==/UserScript==

/*MIT License
Copyright (c) [The Legend Mod]
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
  var tamp = setInterval(function() {
          clearInterval(tamp);
          var elem = document.body;
          var script = document.createElement('script');
          script.src = 'https://legendmod.ml/ExampleScripts/legendmodAddonDAVI.js';
          document.head.appendChild(script);
          elem.appendChild(script);
  }, 5000);

<commit_msg>Update MassBarAddon.user.js<commit_after>// ==UserScript==
// @name         Legend mod - Mass Bar Addon
// @namespace    Legend mod - Mass Bar Addon
// @version      0.1
// @description  Legend mod - Mass Bar Addon
// @author       DAVI すべての最強!
// @match        https://agar.io/*
// ==/UserScript==

/*MIT License
Copyright (c) [The Legend Mod]
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
  var tamp = setInterval(function() {
          clearInterval(tamp);
          var elem = document.body;
          var script = document.createElement('script');
          script.src = 'https://legendmod.ml/ExampleScripts/legendmodAddonDAVI.js';
          document.head.appendChild(script);
          elem.appendChild(script);
  }, 100);

<|endoftext|>


<commit_before>function initMap() {
    var uluru = {lat: 33.950747, lng: -83.375816};
    var map = new google.maps.Map(document.getElementById('map'), {
        zoom: 17,
        center: uluru
    });
    var marker = new google.maps.Marker({
        position: uluru,
        map: map
    });
}

$(document).ready(function(){
	$("#submitSearch").click(function(){
		callServlet();
	});

	function callServlet(){

		var dataInfo = $("#searchFilter").serializeArray();
		dataInfo.push({name: "type", value: "search"});

		$.ajax({
			url : 'SearchServlet',
			data : dataInfo,
			success : function(responseText) {
				$('#tableview').html(responseText);
			}
		});
	}

	$.fn.popup.defaults.transition = 'all 0.3s';
	$.fn.popup.defaults.pagecontainer = '.container';
	$('#my_popup').popup();
});<commit_msg>Update searchPage.js<commit_after>function initMap() {
        var map = new google.maps.Map(document.getElementById('map'), {
          zoom: 17,
          center: {lat: 33.950747, lng: -83.375816}
        });
        var geocoder = new google.maps.Geocoder();
        document.getElementById('submit').addEventListener('click', function() {
          geocodeAddress(geocoder, map);
        });
      }
      function geocodeAddress(geocoder, resultsMap) {
        var address = document.getElementById('address').value;
        geocoder.geocode({'address': address}, function(results, status) {
          if (status === 'OK') {
            resultsMap.setCenter(results[0].geometry.location);
            resultsMap.setZoom(17);
            var marker = new google.maps.Marker({
              map: resultsMap,
              position: results[0].geometry.location
            });
          } else {
            alert('Geocode was not successful for the following reason: ' + status);
          }
        });
      }

$(document).ready(function(){
	$("#submitSearch").click(function(){
		callServlet();
	});

	function callServlet(){

		var dataInfo = $("#searchFilter").serializeArray();
		dataInfo.push({name: "type", value: "search"});

		$.ajax({
			url : 'SearchServlet',
			data : dataInfo,
			success : function(responseText) {
				$('#tableview').html(responseText);
			}
		});
	}

	$("#applicationSubmit").click(function(){
		callServlet2();
	});

	function callServlet2(){

		var dataInfo = $("#applyPopUp").serializeArray();
		dataInfo.push({name: "type", value: "apply"});

		$.ajax({
			url : 'SearchServlet',
			data : dataInfo,
			success : function(responseText) {
				if(responseText == "invalid"){
					alert("This email does not exist. Please try again");
				}
				else{
					alert("Your message was successfully sent!")
					$('#my_popup').popup('hide');
				}
			}
		});
	}

	$.fn.popup.defaults.transition = 'all 0.3s';
	$.fn.popup.defaults.pagecontainer = '.container';
	$('#my_popup').popup();
});
<|endoftext|>


<commit_before>dojo.require("esri.map");
var map, canvas, btnC, cdot, leapOutput, prevGesture, lastX, lastY, _sr,
  pauseGestures=false, controllerOptions={enableGestures: true},
  calib={left:-60, top:300, right:60, bottom:100},
  calibMS = 2250, showDots=true, msgTimeout;
dojo.ready(function (){
  map = new esri.Map("mapDiv", {center: [-84, 32], zoom: 5, basemap: "gray"});
  dojo.connect(map, "onLoad", function(){_sr = map.spatialReference;});
  canvas = document.getElementById("canvasLayer");
  canvas.setAttribute("width", window.innerWidth);
  canvas.setAttribute("height", window.innerHeight);
  btnC = document.getElementById("btnCalibrate");
  btnC.onclick = calibrateScreen;
  cdot = document.getElementById("cdot");
  leapOutput = document.getElementById("leapOutput");
});
function calibrateScreen() {
  alert("Point at the calibration dots:\n1. Top left\n2. Bottom right");
  showDots = false;
  calib = {left:9999, top:-9999, right:-9999, bottom:9999};
  tempPauseGestures(calibMS*2/1000);
  calibrateDot(1);
  setTimeout (function(){calibrateDot(2);}, calibMS);
  setTimeout (function(){
      showDots=true;
      cdot.setAttribute("class","");
  }, calibMS*2);
}
function calibrateDot(count) {
  cdot.setAttribute("class","cdot_pos" + count);
  setTimeout (function(){
    calib.left = Math.min(calib.left, lastX);
    calib.right = Math.max(calib.right, lastX);
    calib.bottom = Math.min(calib.bottom, lastY);
    calib.top = Math.max(calib.top, lastY);
  }, calibMS-500);
}
function drawCircle(x, y, radius, color, alpha) {
  var context = canvas.getContext('2d');
  context.globalAlpha = alpha;
  context.beginPath();
  context.arc(x, y, radius, 0, 2*Math.PI, false);
  context.fillStyle = color;
  context.fill();
}
function toScreen(px, py) {
  return {x:map.width*(px-calib.left)/(calib.right-calib.left),
    y:map.height-map.height*(py-calib.bottom)/(calib.top-calib.bottom)};
}
function drawPointable(p) {
  var cp = toScreen(p.tipPosition[0], p.tipPosition[1]);
  drawCircle(cp.x, cp.y,10, '#f00', .5);
}
Leap.loop(controllerOptions, function(frame) {
  if (frame.pointables.length > 0) {
    lastX = frame.pointables[0].tipPosition[0];
    lastY = frame.pointables[0].tipPosition[1];
    if(showDots) {
      canvas.setAttribute("style", "display:block");
      canvas.getContext("2d").clearRect(0, 0, map.width, map.height);
      for (var i = 0; i < frame.pointables.length; i++) {
        drawPointable(frame.pointables[i]);
      }
    }
  } else {
    canvas.setAttribute("style", "display:none");
  }
  if (frame.gestures !== undefined && frame.gestures.length > 0) {
    for (var i = 0; i < frame.gestures.length; i++) {
      var gesture = frame.gestures[i], type = gesture.type;
      if(prevGesture !== undefined && prevGesture.id === gesture.id) break;
      prevGesture = gesture;
      if(pauseGestures) continue;
      if(type == "circle") {
        handleCircle(gesture);
      } else if (type == "swipe") {
        handleSwipe(frame, gesture);
      } else if (type == "screenTap" || type == "keyTap" ) {
        handleTap(gesture);
      }
    }
  }
});
function handleCircle(gest) {
  if(gest.radius < 5) return;
  var r = gest.radius, c = gest.center;
  var tl = map.toMap(toScreen(c[0]-r, c[1]+r));
  var br = map.toMap(toScreen(c[0]+r, c[1]-r));
  map.setExtent(new esri.geometry.Extent(tl.x, br.y, br.x, tl.y, _sr));
  outputGestureMessage("...zooming to extent...");
}
function handleSwipe(frame, gesture) {
  var startPos = gesture.startPosition;
  if(frame.fingers.length <= 2) {
    outputGestureMessage("...panning...");
    map.centerAt(map.toMap(toScreen(startPos[0], startPos[1])));
  } else {
    var zoomLevels = frame.fingers.length - 2
    map.setLevel(map.getLevel() - zoomLevels);
    outputGestureMessage("...zooming out (" + zoomLevels + " levels)...");
  }
}
function handleTap(gesture) {
  map.centerAt(map.toMap(toScreen(gesture.position[0], gesture.position[1])));
  outputGestureMessage("...centering map...");
}
function outputGestureMessage(msg) {
  tempPauseGestures(1.5);
  leapOutput.innerHTML = msg;
  if(msgTimeout !== undefined) clearTimeout(msgTimeout);
  msgTimeout = setTimeout(function(){leapOutput.innerHTML = " "}, 3000);
}
function tempPauseGestures(seconds) {
  pauseGestures = true;
  setTimeout(function(){pauseGestures = false;}, seconds * 1000);
}<commit_msg>renamed controllerOptions to save some room<commit_after>dojo.require("esri.map");
var map, canvas, btnC, cdot, leapOutput, prevGesture, lastX, lastY, _sr,
  pauseGestures=false, ctrlOpts={enableGestures: true}, calibMS = 2250,
  calib={left:-60, top:300, right:60, bottom:100},
   showDots=true, msgTimeout;
dojo.ready(function (){
  map = new esri.Map("mapDiv", {center: [-84, 32], zoom: 5, basemap: "gray"});
  dojo.connect(map, "onLoad", function(){_sr = map.spatialReference;});
  canvas = document.getElementById("canvasLayer");
  canvas.setAttribute("width", window.innerWidth);
  canvas.setAttribute("height", window.innerHeight);
  btnC = document.getElementById("btnCalibrate");
  btnC.onclick = calibrateScreen;
  cdot = document.getElementById("cdot");
  leapOutput = document.getElementById("leapOutput");
});
function calibrateScreen() {
  alert("Point at the calibration dots:\n1. Top left\n2. Bottom right");
  showDots = false;
  calib = {left:9999, top:-9999, right:-9999, bottom:9999};
  tempPauseGestures(calibMS*2/1000);
  calibrateDot(1);
  setTimeout (function(){calibrateDot(2);}, calibMS);
  setTimeout (function(){
      showDots=true;
      cdot.setAttribute("class","");
  }, calibMS*2);
}
function calibrateDot(count) {
  cdot.setAttribute("class","cdot_pos" + count);
  setTimeout (function(){
    calib.left = Math.min(calib.left, lastX);
    calib.right = Math.max(calib.right, lastX);
    calib.bottom = Math.min(calib.bottom, lastY);
    calib.top = Math.max(calib.top, lastY);
  }, calibMS-500);
}
function drawCircle(x, y, radius, color, alpha) {
  var context = canvas.getContext('2d');
  context.globalAlpha = alpha;
  context.beginPath();
  context.arc(x, y, radius, 0, 2*Math.PI, false);
  context.fillStyle = color;
  context.fill();
}
function toScreen(px, py) {
  return {x:map.width*(px-calib.left)/(calib.right-calib.left),
    y:map.height-map.height*(py-calib.bottom)/(calib.top-calib.bottom)};
}
function drawPointable(p) {
  var cp = toScreen(p.tipPosition[0], p.tipPosition[1]);
  drawCircle(cp.x, cp.y,10, '#f00', .5);
}
Leap.loop(ctrlOpts, function(frame) {
  if (frame.pointables.length > 0) {
    lastX = frame.pointables[0].tipPosition[0];
    lastY = frame.pointables[0].tipPosition[1];
    if(showDots) {
      canvas.setAttribute("style", "display:block");
      canvas.getContext("2d").clearRect(0, 0, map.width, map.height);
      for (var i = 0; i < frame.pointables.length; i++) {
        drawPointable(frame.pointables[i]);
      }
    }
  } else {
    canvas.setAttribute("style", "display:none");
  }
  if (frame.gestures !== undefined && frame.gestures.length > 0) {
    for (var i = 0; i < frame.gestures.length; i++) {
      var gesture = frame.gestures[i], type = gesture.type;
      if(prevGesture !== undefined && prevGesture.id === gesture.id) break;
      prevGesture = gesture;
      if(pauseGestures) continue;
      if(type == "circle") {
        handleCircle(gesture);
      } else if (type == "swipe") {
        handleSwipe(frame, gesture);
      } else if (type == "screenTap" || type == "keyTap" ) {
        handleTap(gesture);
      }
    }
  }
});
function handleCircle(gest) {
  if(gest.radius < 5) return;
  var r = gest.radius, c = gest.center;
  var tl = map.toMap(toScreen(c[0]-r, c[1]+r));
  var br = map.toMap(toScreen(c[0]+r, c[1]-r));
  map.setExtent(new esri.geometry.Extent(tl.x, br.y, br.x, tl.y, _sr));
  outputGestureMessage("...zooming to extent...");
}
function handleSwipe(frame, gesture) {
  var startPos = gesture.startPosition;
  if(frame.fingers.length <= 2) {
    outputGestureMessage("...panning...");
    map.centerAt(map.toMap(toScreen(startPos[0], startPos[1])));
  } else {
    var zoomLevels = frame.fingers.length - 2
    map.setLevel(map.getLevel() - zoomLevels);
    outputGestureMessage("...zooming out (" + zoomLevels + " levels)...");
  }
}
function handleTap(gesture) {
  map.centerAt(map.toMap(toScreen(gesture.position[0], gesture.position[1])));
  outputGestureMessage("...centering map...");
}
function outputGestureMessage(msg) {
  tempPauseGestures(1.5);
  leapOutput.innerHTML = msg;
  if(msgTimeout !== undefined) clearTimeout(msgTimeout);
  msgTimeout = setTimeout(function(){leapOutput.innerHTML = " "}, 3000);
}
function tempPauseGestures(seconds) {
  pauseGestures = true;
  setTimeout(function(){pauseGestures = false;}, seconds * 1000);
}<|endoftext|>


<commit_before>var PubNub = require('pubnub')
var async = require('async')
var os = require("os");
var config = require('./config.json');

var hostname = process.argv[2].split(".", 2);

workerID=hostname[0];
region=hostname[1];

var subscribe = function(subID) {

  return function (callback) {

    var subscriber = workerID + '_' + subID;
    pubnub = new PubNub({
       subscribeKey: config.subscribeKey,
       ssl: true,
       keepAlive: true
       // Add for debugging purposes only.  Do not enable during load test
       //logVerbosity: "true"
    })

    // Ensure this is set to 0.  Will not perform a heartbeat
    pubnub._config.setHeartbeatInterval(0);

    pubnub.addListener({
      message: function(message) {
        // Calculate Latency from time published to time received on client
        var now = new Date();
        var sent = new Date(message.message.Date);
        var diff = now - sent;

        console.log(message.message.Date + ' ' + subscriber +
          ' ' + message.message['E-Tag'] + ' ' + message.message.Status +
          ' ' + diff);
      },

      // https://www.pubnub.com/docs/nodejs-javascript/pubnub-javascript-sdk#listeners
      status: function(s) {
      var now = (new Date()).toISOString();
        if(s.errorData) {console.log(now + ' ' + region + ' ' + subscriber + ' ' + s.category + ' ' + s.operation + ' ' + s.errorData);}
      else {
        console.log(now + ' ' + region + ' ' + subscriber + ' ' + s.category + ' ' + s.operation);
      }
    }

      // Example payloads

      // connect occurred { category: 'PNConnectedCategory',
      //   operation: 'PNSubscribeOperation',
      //   affectedChannels: [ 'test' ],
      //   subscribedChannels: [ 'test' ],
      //   affectedChannelGroups: [],
      //   lastTimetoken: 0,
      //   currentTimetoken: '15032999507074655' }

      // connect occurred { error: true,
      //   operation: 'PNHeartbeatOperation',
      //   errorData:
      //    { Error: timeout of 15000ms exceeded
      //        at Timeout.<anonymous> (/Users/chrisdelorenzo/repos/ao-client-pubnub/node_modules/superagent/lib/node/index.js:693:17)
      //        at tryOnTimeout (timers.js:224:11)
      //        at Timer.listOnTimeout (timers.js:198:5) timeout: 15000, code: 'ECONNABORTED', response: undefined },
      //   category: 'PNTimeoutCategory' }

    })

    pubnub.subscribe({
      channels: ['test']
    });

    callback(null, subscriber + ' subscribed');
  }
};

if (require.main === module) {
  // Number of connections to run on server.
  var connections = config.connections;
  // Number of seconds to ramp up over.
  var ramp = config.ramp;
  // Concurrent connections attempted per second.
  var rate = Math.ceil((connections / ramp) * 100)/100;;

  var count = 1;

  intervalPerConnection = (1/rate)*1000;

  console.log((new Date()).toISOString() + ' ' + region + ' ' + "Ramping up " + connections +
    " connection/s Rate " + rate +
    " per second over a period of " + ramp + " second/s");

  var subscribers = [];

  setTimeout(function request() {
    subscribers.length = 0
    subscribers.push(subscribe(count));
    async.parallel(subscribers, function(err, result){
      //console.log((new Date()).toISOString() + ' ' + region + ' ' + result )
    });

    if(count == connections){
    }
    else {
      interval = setTimeout(request,intervalPerConnection);
      count++;
    }
  }, intervalPerConnection);

} else {
  console.log('please start via node subscribe.js');
}
<commit_msg>added keepalive object<commit_after>var PubNub = require('pubnub')
var async = require('async')
var os = require("os");
var config = require('./config.json');

var hostname = process.argv[2].split(".", 2);

workerID=hostname[0];
region=hostname[1];

var subscribe = function(subID) {

  return function (callback) {

    var subscriber = workerID + '_' + subID;
    pubnub = new PubNub({
      subscribeKey: config.subscribeKey,
      ssl: true,
      keepAlive: true,
      keepAliveSettings: {
        maxSockets: 100,
        maxFreeSockets: 10,
        timeout: 100000, // should be freeSocketKeepAliveTimeout * 2
        freeSocketKeepAliveTimeout: 50000
      }
      // Add for debugging purposes only.  Do not enable during load test
      //logVerbosity: "true"
    })

    // Ensure this is set to 0.  Will not perform a heartbeat
    pubnub._config.setHeartbeatInterval(0);

    pubnub.addListener({
      message: function(message) {
        // Calculate Latency from time published to time received on client
        var now = new Date();
        var sent = new Date(message.message.Date);
        var diff = now - sent;

        console.log(message.message.Date + ' ' + subscriber +
          ' ' + message.message['E-Tag'] + ' ' + message.message.Status +
          ' ' + diff);
      },

      // https://www.pubnub.com/docs/nodejs-javascript/pubnub-javascript-sdk#listeners
      status: function(s) {
      var now = (new Date()).toISOString();
        if(s.errorData) {console.log(now + ' ' + region + ' ' + subscriber + ' ' + s.category + ' ' + s.operation + ' ' + s.errorData);}
      else {
        console.log(now + ' ' + region + ' ' + subscriber + ' ' + s.category + ' ' + s.operation);
      }
    }

      // Example payloads

      // connect occurred { category: 'PNConnectedCategory',
      //   operation: 'PNSubscribeOperation',
      //   affectedChannels: [ 'test' ],
      //   subscribedChannels: [ 'test' ],
      //   affectedChannelGroups: [],
      //   lastTimetoken: 0,
      //   currentTimetoken: '15032999507074655' }

      // connect occurred { error: true,
      //   operation: 'PNHeartbeatOperation',
      //   errorData:
      //    { Error: timeout of 15000ms exceeded
      //        at Timeout.<anonymous> (/Users/chrisdelorenzo/repos/ao-client-pubnub/node_modules/superagent/lib/node/index.js:693:17)
      //        at tryOnTimeout (timers.js:224:11)
      //        at Timer.listOnTimeout (timers.js:198:5) timeout: 15000, code: 'ECONNABORTED', response: undefined },
      //   category: 'PNTimeoutCategory' }

    })

    pubnub.subscribe({
      channels: ['test']
    });

    callback(null, subscriber + ' subscribed');
  }
};

if (require.main === module) {
  // Number of connections to run on server.
  var connections = config.connections;
  // Number of seconds to ramp up over.
  var ramp = config.ramp;
  // Concurrent connections attempted per second.
  var rate = Math.ceil((connections / ramp) * 100)/100;;

  var count = 1;

  intervalPerConnection = (1/rate)*1000;

  console.log((new Date()).toISOString() + ' ' + region + ' ' + "Ramping up " + connections +
    " connection/s Rate " + rate +
    " per second over a period of " + ramp + " second/s");

  var subscribers = [];

  setTimeout(function request() {
    subscribers.length = 0
    subscribers.push(subscribe(count));
    async.parallel(subscribers, function(err, result){
      //console.log((new Date()).toISOString() + ' ' + region + ' ' + result )
    });

    if(count == connections){
    }
    else {
      interval = setTimeout(request,intervalPerConnection);
      count++;
    }
  }, intervalPerConnection);

} else {
  console.log('please start via node subscribe.js');
}
<|endoftext|>


<commit_before>// ==UserScript==
// @name         Table to Markdown Copier
// @name:vi      Chép bảng HTML qua dạng markdown
// @namespace    https://github.com/hotmit/table-markdown-userscript
// @version      1.0.1
// @description  Convert html table to markdown format
// @description:vi  Chuyển bảng html (table) qua dạng markdown.
// @author       Du Dang
// @include      http://*/*
// @include      https://*/*
// @grant        none
// @require      https://code.jquery.com/jquery-3.1.1.min.js
// @require 	 https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/1.5.16/clipboard.min.js
// ==/UserScript==
(function($) {
    'use strict';

    // max cell with in chars count
    var MAX_COL_SIZE = 80;

    var Str = {};

    $(function(){
        var lastThreeKeys = [], combinationLength = 3;

        // region [ Display Control ]
        /**
         * Insert the "MD" button to all the last cell in the header of
         * all the tables in the current page.
         * @private
         */
        function displayTableControl(){
            $('table').each(function(i, e){
                var id = 'btn-copy-md-' + i, $tb = $(e),
                    $btnMd = $('<button type="button" class="convert-to-markdown btn btn-primary" />'),
                    $lastCell = $tb.find('tr:first').find('td:last, th:last').first();

                $btnMd.css({
                    height: '20px',
                    width: '30px',
                    'background-color': '#81358c',
                    color: '#fff',
                    padding: '0'
                }).text('MD').attr('id', id);

                // copy markdown content to the clipboard
                new Clipboard('#' + id, {
                    text: function() {
                        return convertTableToMd($btnMd);
                    }
                });

                $lastCell.append($btnMd);
            });

            //$('.convert-to-markdown').click(convertTableToMd);
        }
        // endregion

        // region [ Code ]
        /**
         * Extract the data from the table. Return array of row of data along with
         * the maximum length for each column.
         *
         * @param $table
         * @returns {{maxLengths: Array, tableData: Array}}
         * @private
         */
        function getData($table){
            var maxLengths = [], tableData = [];

            function setMax(index, length){
                // create new column if does not exist
                while(index >= maxLengths.length){
                    maxLengths.push(0);
                }
                maxLengths[index] = Math.max(maxLengths[index], length);
            }

            $table.find('tr').each(function(trIndex, tr){
                var $tr = $(tr), row = [], offset = 0;

                $tr.find('td, th').each(function(i, td){
                    var $td = $(td), text = getText($td, trIndex), tl = text.length,
                        index = i + offset, colspan = $td.attr('colspan');

                    setMax(index, tl);
                    row.push(text);

                    if (colspan && $.isNumeric(colspan) && Number(colspan) > 1){
                        colspan = Number(colspan);
                        offset += colspan - 1;
                        for (var k=0; k<colspan; k++){
                            row.push('');
                        }
                    }
                });

                tableData.push(row);
            });

            return {
                maxLengths: maxLengths,
                tableData: tableData
            };
        }

        /**
         * Convert the data from getData to actual markdown content.
         *
         * @param $btn - The "MD" button housed inside the table.
         * @returns {string} - The markdown table content
         * @private
         */
        function convertTableToMd($btn){
            var md = '', $table = $btn.parents('table').first(), data = getData($table), i, k,
                maxLengths = data.maxLengths;

            for (i=0; i<data.tableData.length; i++){
                var row = data.tableData[i], rowMd = '| ', sepMd = '| ';

                for(k=0; k<row.length; k++){
                    var rowWidth = Math.min(maxLengths[k], MAX_COL_SIZE),
                        text = Str.padRight(row[k], ' ', rowWidth);
                    rowMd += text + ' | ';

                    // add header separator
                    if (i === 0){
                        sepMd += Str.repeat(' ', rowWidth) + ' | ';
                    }
                }

                if (rowMd.length > 2){
                    md += Str.trim(rowMd) + "\n";
                    if (sepMd.length > 2){
                        md += Str.trim(sepMd).replace(/ /g, '-') + "\n";
                    }
                }
            }

            md += getReferenceLink($table);

            // copied indicator
            $btn.css('background-color', '#6AB714');
            setTimeout(function(){
                $btn.css('background-color', '#81358c');
            }, 3000);

            return md;
        }

        /**
         * Generate markdown link to the table for future reference.
         *
         * @param $table
         * @returns {*}
         */
        function getReferenceLink($table) {
            var refLink, $anchor, refId = $table.attr('id'), href = location.href;

            if(!refId) {
                $anchor = $table.parents('[id]').first();
                if ($anchor.length){
                    refId = $anchor.attr('id');
                }
            }

            if (refId) {
                if (href.indexOf('#') != -1) {
                    refLink = href.replace(/#.+/, '#' + refId);
                }
                else {
                    refLink = href + '#' + refId;
                }
            }
            // if no id link, then just use the main link as reference
            refLink = refLink || href;
            return '[Table Source](' + refLink + ')';
        }

        /**
         * Clean up the text for the cell content. Like remove new line so it doesn't break the table.
         *
         * @param $td
         * @param trIndex
         * @returns {string|*}
         */
        function getText($td, trIndex) {
            var text = $td.text();
            if (trIndex === 0){
                // remove the MD link from the text
                text = text.replace(/MD$/, '');
            }
            text = text.replace("\n", '');
            text = text.replace(/\s/g, ' ');
            return Str.trim(text);
        }
        // endregion

        // region [ Capture shortcut keys ]
        // Activate Markdown Converter Interface
        //      => Shift, Shift, T (3 key strokes as a sequence, NOT press all together)
        $(document).on('keydown', function(e) {
            lastThreeKeys.push(e.which);
            lastThreeKeys = lastThreeKeys.slice(-combinationLength);
            if (lastThreeKeys.toString() == '16,16,84') {
                displayTableControl();
                e.preventDefault();
                return false;
            }
        });
        // endregion

        // uncomment for dev
        // displayTableControl();

    }); //end jqReady

    // region [ Str Lib ]
    Str.trim = function (s) {
        return s.replace(/^\s+/, '').replace(/\s+$/, '');
    };

    Str.padRight = function(s, padStr, totalLength){
        return s.length >= totalLength  ? s : s + Str.repeat(padStr, (totalLength-s.length)/padStr.length);
    };

    Str.repeat = function(s, count) {
        var newS = "", i;
        for (i=0; i<count; i++) {
            newS += s;
        }
        return newS;
    };
    // endregion

})(jQuery.noConflict(true));
<commit_msg>added license to the meta tag<commit_after>// ==UserScript==
// @name         Table to Markdown Copier
// @name:vi      Chép bảng HTML qua dạng markdown
// @namespace    https://github.com/hotmit/table-markdown-userscript
// @version      1.0.1
// @description  Convert html table to markdown format
// @description:vi  Chuyển bảng html (table) qua dạng markdown.
// @author       Du Dang
// @include      http://*/*
// @include      https://*/*
// @grant        none
// @require      https://code.jquery.com/jquery-3.1.1.min.js
// @require 	 https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/1.5.16/clipboard.min.js
// @license      MIT
// ==/UserScript==
(function($) {
    'use strict';

    // max cell with in chars count
    var MAX_COL_SIZE = 80;

    var Str = {};

    $(function(){
        var lastThreeKeys = [], combinationLength = 3;

        // region [ Display Control ]
        /**
         * Insert the "MD" button to all the last cell in the header of
         * all the tables in the current page.
         * @private
         */
        function displayTableControl(){
            $('table').each(function(i, e){
                var id = 'btn-copy-md-' + i, $tb = $(e),
                    $btnMd = $('<button type="button" class="convert-to-markdown btn btn-primary" />'),
                    $lastCell = $tb.find('tr:first').find('td:last, th:last').first();

                $btnMd.css({
                    height: '20px',
                    width: '30px',
                    'background-color': '#81358c',
                    color: '#fff',
                    padding: '0'
                }).text('MD').attr('id', id);

                // copy markdown content to the clipboard
                new Clipboard('#' + id, {
                    text: function() {
                        return convertTableToMd($btnMd);
                    }
                });

                $lastCell.append($btnMd);
            });

            //$('.convert-to-markdown').click(convertTableToMd);
        }
        // endregion

        // region [ Code ]
        /**
         * Extract the data from the table. Return array of row of data along with
         * the maximum length for each column.
         *
         * @param $table
         * @returns {{maxLengths: Array, tableData: Array}}
         * @private
         */
        function getData($table){
            var maxLengths = [], tableData = [];

            function setMax(index, length){
                // create new column if does not exist
                while(index >= maxLengths.length){
                    maxLengths.push(0);
                }
                maxLengths[index] = Math.max(maxLengths[index], length);
            }

            $table.find('tr').each(function(trIndex, tr){
                var $tr = $(tr), row = [], offset = 0;

                $tr.find('td, th').each(function(i, td){
                    var $td = $(td), text = getText($td, trIndex), tl = text.length,
                        index = i + offset, colspan = $td.attr('colspan');

                    setMax(index, tl);
                    row.push(text);

                    if (colspan && $.isNumeric(colspan) && Number(colspan) > 1){
                        colspan = Number(colspan);
                        offset += colspan - 1;
                        for (var k=0; k<colspan; k++){
                            row.push('');
                        }
                    }
                });

                tableData.push(row);
            });

            return {
                maxLengths: maxLengths,
                tableData: tableData
            };
        }

        /**
         * Convert the data from getData to actual markdown content.
         *
         * @param $btn - The "MD" button housed inside the table.
         * @returns {string} - The markdown table content
         * @private
         */
        function convertTableToMd($btn){
            var md = '', $table = $btn.parents('table').first(), data = getData($table), i, k,
                maxLengths = data.maxLengths;

            for (i=0; i<data.tableData.length; i++){
                var row = data.tableData[i], rowMd = '| ', sepMd = '| ';

                for(k=0; k<row.length; k++){
                    var rowWidth = Math.min(maxLengths[k], MAX_COL_SIZE),
                        text = Str.padRight(row[k], ' ', rowWidth);
                    rowMd += text + ' | ';

                    // add header separator
                    if (i === 0){
                        sepMd += Str.repeat(' ', rowWidth) + ' | ';
                    }
                }

                if (rowMd.length > 2){
                    md += Str.trim(rowMd) + "\n";
                    if (sepMd.length > 2){
                        md += Str.trim(sepMd).replace(/ /g, '-') + "\n";
                    }
                }
            }

            md += getReferenceLink($table);

            // copied indicator
            $btn.css('background-color', '#6AB714');
            setTimeout(function(){
                $btn.css('background-color', '#81358c');
            }, 3000);

            return md;
        }

        /**
         * Generate markdown link to the table for future reference.
         *
         * @param $table
         * @returns {*}
         */
        function getReferenceLink($table) {
            var refLink, $anchor, refId = $table.attr('id'), href = location.href;

            if(!refId) {
                $anchor = $table.parents('[id]').first();
                if ($anchor.length){
                    refId = $anchor.attr('id');
                }
            }

            if (refId) {
                if (href.indexOf('#') != -1) {
                    refLink = href.replace(/#.+/, '#' + refId);
                }
                else {
                    refLink = href + '#' + refId;
                }
            }
            // if no id link, then just use the main link as reference
            refLink = refLink || href;
            return '[Table Source](' + refLink + ')';
        }

        /**
         * Clean up the text for the cell content. Like remove new line so it doesn't break the table.
         *
         * @param $td
         * @param trIndex
         * @returns {string|*}
         */
        function getText($td, trIndex) {
            var text = $td.text();
            if (trIndex === 0){
                // remove the MD link from the text
                text = text.replace(/MD$/, '');
            }
            text = text.replace("\n", '');
            text = text.replace(/\s/g, ' ');
            return Str.trim(text);
        }
        // endregion

        // region [ Capture shortcut keys ]
        // Activate Markdown Converter Interface
        //      => Shift, Shift, T (3 key strokes as a sequence, NOT press all together)
        $(document).on('keydown', function(e) {
            lastThreeKeys.push(e.which);
            lastThreeKeys = lastThreeKeys.slice(-combinationLength);
            if (lastThreeKeys.toString() == '16,16,84') {
                displayTableControl();
                e.preventDefault();
                return false;
            }
        });
        // endregion

        // uncomment for dev
        // displayTableControl();

    }); //end jqReady

    // region [ Str Lib ]
    Str.trim = function (s) {
        return s.replace(/^\s+/, '').replace(/\s+$/, '');
    };

    Str.padRight = function(s, padStr, totalLength){
        return s.length >= totalLength  ? s : s + Str.repeat(padStr, (totalLength-s.length)/padStr.length);
    };

    Str.repeat = function(s, count) {
        var newS = "", i;
        for (i=0; i<count; i++) {
            newS += s;
        }
        return newS;
    };
    // endregion

})(jQuery.noConflict(true));
<|endoftext|>


<commit_before>/// Required Core Modules
var vm = require('vm');
///
/// Modules
var async = require('async');
var defaultsDeep = require('lodash.defaultsdeep');
///
/// Predefined Types
// TYPES
var ST_LOCAL_TYPE = 0, ST_SHARED_TYPE = 1, ST_FOREIGN_TYPE = 2;
// PERMISSIONS
var ST_NONE = 0, ST_RESTRICTED = 1, ST_MINIMAL = 2, ST_UNRESTRICTED = 3;
///

var SuperTask = function ST_INIT() {
    this.cargo = async.cargo(this._next, 50);
    this._batch = [];
    this._paused = true;
    this._busy = false;
    this.map = new Map();
};

SuperTask.prototype._createTask = function ST__CREATE_TASK(func, type, access, context, isModule, remote, sandboxed) {
    return {
        func: func,
        local: (type === ST_LOCAL_TYPE),
        shared: (type === ST_SHARED_TYPE),
        sandboxed: ((!!sandboxed) || (type === ST_FOREIGN_TYPE)),
        module: (isModule === false) ? false : true,
        isCompiled: (typeof func === 'function'),
        isRemote: (!!remote),
        lastStarted: [],
        lastFinished: [],
        lastDiff: 0,
        averageExecutionTime: -1,
        executionRounds: 0,
        defaultContext: context || {},
        access: access || ST_NONE
    };
};

SuperTask.prototype._extendContextFromPermissions = require('./lib/ContextPermissions');

SuperTask.prototype._next = function ST__CARGO_NEXT(tasks, callback) {
    /* At this point the source is fully compiled
    /* to a function or a function is resupplied
    /* from cache to be executed. Here we transfer
    /* the given function (task.func) to the cargo
    /* after attaching the pre tracker */

    // Go through tasks in parallel
    async.each(tasks, function ST__CARGO_EACH(task, done) {
        // Cargo Tracker
        function ST__CARGO_TRACKER(error) {
            done();
            task.callback.apply(this, arguments);
        }
        // Call preTracker
        task.pre();
        // Push Callback to args
        task.args.push(ST__CARGO_TRACKER);
        // Call Function with context & args
        if(task.sandboxed) {
            try {
                task.func.apply(task.context, task.args);
            }catch(error) {
                ST__CARGO_TRACKER(error);
            }
        }else{
            task.func.apply(task.context, task.args);
        }

    }, callback);
};

SuperTask.prototype._newCargo = function ST__CARGO_ADD(name, func, sandboxed, context, args, preTracker, postTracker) {
    // Push Cargo Object & Attach postTracker
    this.cargo.push({
        name: name,
        pre: preTracker,
        func: func,
        context: context,
        args: args,
        sandboxed: sandboxed,
        callback: postTracker
    });
    // Resume Cargo
    this.cargo.resume();
};

SuperTask.prototype._addTask = function ST__ADD_TASK() {
    var args = Array.prototype.slice.call(arguments);
    var name = args.shift();
    var callback = args.pop();

    // Make sure Map Key is not taken
    if (this.map.has(name)) {
        if (typeof callback === 'function') callback(new Error('Enable to create new task. A Task with the given name already exists.'));
        return;
    }

    var task = this._createTask.apply(this, args);
    // Add Task to Map
    this.map.set(name, task);

    if (typeof callback === 'function') callback(null, task);
};

SuperTask.prototype.addLocal = function ST_ADD_LOCAL(name, func, callback) {
    this._addTask(name, func, ST_LOCAL_TYPE, callback);
};

SuperTask.prototype.addLocalWithContext = function ST_ADD_LOCAL_W_CONTEXT(name, func, context, permissions, callback) {
    this._addTask(name, func, ST_LOCAL_TYPE, permissions, context, callback);
};

SuperTask.prototype.addForeign = function ST_ADD_FOREIGN(name, source, callback) {
    // VM requires a String source to compile
    // If given source is a function convert it to source (context is lost)
    if (typeof source === 'function') {
        source = 'module.exports = ' + source.toString();
    }
    this._addTask(name, source, ST_FOREIGN_TYPE, callback);
};

SuperTask.prototype.addForeignWithContext = function ST_ADD_FOREIGN_W_CONTEXT(name, source, context, permissions, callback) {
    // VM requires a String source to compile
    // If given source is a function convert it to source (context is lost)
    if (typeof source === 'function') {
        source = 'module.exports = ' + source.toString();
    }
    this._addTask(name, source, ST_FOREIGN_TYPE, permissions, context, callback);
};

SuperTask.prototype.do = function ST_DO(name, context, args, callback, permissions) {
    if (!this.map.has(name)) {
        if (typeof callback === 'function') callback(new Error('Task not found!'));
        return;
    }
    var task = this.map.get(name);
    // Combine Contexts
    if (task.defaultContext && (Object.keys(task.defaultContext).length !== 0)) defaultsDeep(context, task.defaultContext);
    // Combine Permissions Context (SLOWS DOWN EXECUTION)
    if (task.access !== ST_NONE) {
        context = this._extendContextFromPermissions(context, permissions || task.access);
    }
    // Function executed on cargo execution
    var preTracker = function ST_DO_PRETRACKER() {
        task.lastStarted = process.hrtime();
    };
    var postTracker = function ST_DO_POSTTRACKER(error) {
        // Calculate High Resolution time it took to run the function
        task.lastFinished = process.hrtime(task.lastStarted);
        // Calculate Time Difference
        task.lastDiff = task.lastFinished[0] * 1e9 + task.lastFinished[1];
        // Calculate Average Execution Time
        if (task.averageExecutionTime === -1) {
            task.averageExecutionTime = task.lastDiff;
        } else {
            task.averageExecutionTime = ((task.averageExecutionTime * task.executionRounds) + task.lastDiff) / (task.executionRounds + 1);
        }
        // Bump execution rounds
        task.executionRounds++;
        // Call Callback function if provided
        if (typeof callback === 'function') callback.apply(task, arguments);
    };
    // Sanitize args
    args = (Array.isArray(args)) ? args : [];

    if (typeof task.func !== 'function') {
        // Check if script is not compiled
        if (typeof task.func === 'string') {
            // Compile script using VM
            task.func = new vm.Script(task.func);
        }
        // Make sure we can call run on the compiled script
        if (typeof task.func.runInContext !== 'function') {
            if (typeof callback === 'function') callback(new Error("Unknown Error Occurred. Function property of Task is invalid or failed to compile."));
            return;
        }
        // Define module.exports and exports in context
        context.module = {};
        context.exports = context.module.exports = {};

        // Create VM Context from context object
        vm.createContext(context);
        // Run Compiled Script
        task.func.runInContext(context);
        // If task is defined as module
        if (task.module) {
            // Make sure module.exports is set to a function
            if (typeof context.module.exports === 'function') {
                // Cache and Call the function
                task.func = context.module.exports;
                // Set isCompiled property
                task.isCompiled = true;
                // Push to Cargo
                this._newCargo(name, task.func, task.sandboxed, context, args, preTracker, postTracker);
            } else {
                // Call Callback with an error if module.exports is not set to a function
                if (typeof callback === 'function') callback(new Error("Compiled Script is not a valid foreign task or module. Failed to identify module.exports as a function."));
            }
        }
    } else {
        // Push to Cargo
        this._newCargo(name, task.func, task.sandboxed, context, args, preTracker, postTracker);
    }
};

SuperTask.prototype.remove = function ST_REMOVE(name, callback) {
    var result = this.map.delete(name);
    if (typeof callback === 'function') callback((!result) ? (new Error('Task not found!')) : null);
};

SuperTask.prototype.has = function ST_HAS(name, callback) {
    if (typeof callback === 'function') callback(null, (!!this.map.has(name)));
};

/// EXTEND PREDEFINED VARS
SuperTask.ST_LOCAL_TYPE = ST_LOCAL_TYPE;
SuperTask.ST_SHARED_TYPE = ST_SHARED_TYPE;
SuperTask.ST_FOREIGN_TYPE = ST_FOREIGN_TYPE;

SuperTask.ST_NONE = ST_NONE;
SuperTask.ST_RESTRICTED = ST_RESTRICTED;
SuperTask.ST_MINIMAL = ST_MINIMAL;
SuperTask.ST_UNRESTRICTED = ST_UNRESTRICTED;
///

module.exports = SuperTask;<commit_msg>Changes context after compile is expensive<commit_after>/// Required Core Modules
var vm = require('vm');
///
/// Modules
var async = require('async');
var defaultsDeep = require('lodash.defaultsdeep');
///
/// Predefined Types
// TYPES
var ST_LOCAL_TYPE = 0, ST_SHARED_TYPE = 1, ST_FOREIGN_TYPE = 2;
// PERMISSIONS
var ST_NONE = 0, ST_RESTRICTED = 1, ST_MINIMAL = 2, ST_UNRESTRICTED = 3;
///

var SuperTask = function ST_INIT() {
    this.cargo = async.cargo(this._next, 50);
    this._batch = [];
    this._paused = true;
    this._busy = false;
    this.map = new Map();
};

SuperTask.prototype._createTask = function ST__CREATE_TASK(func, type, access, context, isModule, remote, sandboxed) {
    return {
        func: func,
        local: (type === ST_LOCAL_TYPE),
        shared: (type === ST_SHARED_TYPE),
        sandboxed: ((!!sandboxed) || (type === ST_FOREIGN_TYPE)),
        module: (isModule === false) ? false : true,
        isCompiled: (typeof func === 'function'),
        isRemote: (!!remote),
        lastStarted: [],
        lastFinished: [],
        lastDiff: 0,
        averageExecutionTime: -1,
        executionRounds: 0,
        defaultContext: context || {},
        access: access || ST_NONE
    };
};

SuperTask.prototype._extendContextFromPermissions = require('./lib/ContextPermissions');

SuperTask.prototype._next = function ST__CARGO_NEXT(tasks, callback) {
    /* At this point the source is fully compiled
    /* to a function or a function is resupplied
    /* from cache to be executed. Here we transfer
    /* the given function (task.func) to the cargo
    /* after attaching the pre tracker */

    // Go through tasks in parallel
    async.each(tasks, function ST__CARGO_EACH(task, done) {
        // Cargo Tracker
        function ST__CARGO_TRACKER(error) {
            done();
            task.callback.apply(this, arguments);
        }
        // Call preTracker
        task.pre();
        // Push Callback to args
        task.args.push(ST__CARGO_TRACKER);
        // Call Function with context & args
        if(task.sandboxed) {
            try {
                task.func.apply(task.context, task.args);
            }catch(error) {
                ST__CARGO_TRACKER(error);
            }
        }else{
            task.func.apply(task.context, task.args);
        }

    }, callback);
};

SuperTask.prototype._newCargo = function ST__CARGO_ADD(name, func, sandboxed, context, args, preTracker, postTracker) {
    // Push Cargo Object & Attach postTracker
    this.cargo.push({
        name: name,
        pre: preTracker,
        func: func,
        context: context,
        args: args,
        sandboxed: sandboxed,
        callback: postTracker
    });
    // Resume Cargo
    this.cargo.resume();
};

SuperTask.prototype._addTask = function ST__ADD_TASK() {
    var args = Array.prototype.slice.call(arguments);
    var name = args.shift();
    var callback = args.pop();

    // Make sure Map Key is not taken
    if (this.map.has(name)) {
        if (typeof callback === 'function') callback(new Error('Enable to create new task. A Task with the given name already exists.'));
        return;
    }

    var task = this._createTask.apply(this, args);
    // Add Task to Map
    this.map.set(name, task);

    if (typeof callback === 'function') callback(null, task);
};

SuperTask.prototype.addLocal = function ST_ADD_LOCAL(name, func, callback) {
    this._addTask(name, func, ST_LOCAL_TYPE, callback);
};

SuperTask.prototype.addLocalWithContext = function ST_ADD_LOCAL_W_CONTEXT(name, func, context, permissions, callback) {
    this._addTask(name, func, ST_LOCAL_TYPE, permissions, context, callback);
};

SuperTask.prototype.addForeign = function ST_ADD_FOREIGN(name, source, callback) {
    // VM requires a String source to compile
    // If given source is a function convert it to source (context is lost)
    if (typeof source === 'function') {
        source = 'module.exports = ' + source.toString();
    }
    this._addTask(name, source, ST_FOREIGN_TYPE, callback);
};

SuperTask.prototype.addForeignWithContext = function ST_ADD_FOREIGN_W_CONTEXT(name, source, context, permissions, callback) {
    // VM requires a String source to compile
    // If given source is a function convert it to source (context is lost)
    if (typeof source === 'function') {
        source = 'module.exports = ' + source.toString();
    }
    this._addTask(name, source, ST_FOREIGN_TYPE, permissions, context, callback);
};

SuperTask.prototype.do = function ST_DO(name, context, args, callback) {
    if (!this.map.has(name)) {
        if (typeof callback === 'function') callback(new Error('Task not found!'));
        return;
    }
    var task = this.map.get(name);
    // Combine Contexts
    if (task.defaultContext && (Object.keys(task.defaultContext).length !== 0)) defaultsDeep(context, task.defaultContext);
    // Combine Permissions Context (SLOWS DOWN EXECUTION)
    if (task.access !== ST_NONE) {
        context = this._extendContextFromPermissions(context, task.access);
    }
    // Function executed on cargo execution
    var preTracker = function ST_DO_PRETRACKER() {
        task.lastStarted = process.hrtime();
    };
    var postTracker = function ST_DO_POSTTRACKER(error) {
        // Calculate High Resolution time it took to run the function
        task.lastFinished = process.hrtime(task.lastStarted);
        // Calculate Time Difference
        task.lastDiff = task.lastFinished[0] * 1e9 + task.lastFinished[1];
        // Calculate Average Execution Time
        if (task.averageExecutionTime === -1) {
            task.averageExecutionTime = task.lastDiff;
        } else {
            task.averageExecutionTime = ((task.averageExecutionTime * task.executionRounds) + task.lastDiff) / (task.executionRounds + 1);
        }
        // Bump execution rounds
        task.executionRounds++;
        // Call Callback function if provided
        if (typeof callback === 'function') callback.apply(task, arguments);
    };
    // Sanitize args
    args = (Array.isArray(args)) ? args : [];

    if (typeof task.func !== 'function') {
        // Check if script is not compiled
        if (typeof task.func === 'string') {
            // Compile script using VM
            task.func = new vm.Script(task.func);
        }
        // Make sure we can call run on the compiled script
        if (typeof task.func.runInContext !== 'function') {
            if (typeof callback === 'function') callback(new Error("Unknown Error Occurred. Function property of Task is invalid or failed to compile."));
            return;
        }
        // Define module.exports and exports in context
        context.module = {};
        context.exports = context.module.exports = {};

        // Create VM Context from context object
        vm.createContext(context);
        // Run Compiled Script
        task.func.runInContext(context);
        // If task is defined as module
        if (task.module) {
            // Make sure module.exports is set to a function
            if (typeof context.module.exports === 'function') {
                // Cache and Call the function
                task.func = context.module.exports;
                // Set isCompiled property
                task.isCompiled = true;
                // Push to Cargo
                this._newCargo(name, task.func, task.sandboxed, context, args, preTracker, postTracker);
            } else {
                // Call Callback with an error if module.exports is not set to a function
                if (typeof callback === 'function') callback(new Error("Compiled Script is not a valid foreign task or module. Failed to identify module.exports as a function."));
            }
        }
    } else {
        // Push to Cargo
        this._newCargo(name, task.func, task.sandboxed, context, args, preTracker, postTracker);
    }
};

SuperTask.prototype.remove = function ST_REMOVE(name, callback) {
    var result = this.map.delete(name);
    if (typeof callback === 'function') callback((!result) ? (new Error('Task not found!')) : null);
};

SuperTask.prototype.has = function ST_HAS(name, callback) {
    if (typeof callback === 'function') callback(null, (!!this.map.has(name)));
};

/// EXTEND PREDEFINED VARS
SuperTask.ST_LOCAL_TYPE = ST_LOCAL_TYPE;
SuperTask.ST_SHARED_TYPE = ST_SHARED_TYPE;
SuperTask.ST_FOREIGN_TYPE = ST_FOREIGN_TYPE;

SuperTask.ST_NONE = ST_NONE;
SuperTask.ST_RESTRICTED = ST_RESTRICTED;
SuperTask.ST_MINIMAL = ST_MINIMAL;
SuperTask.ST_UNRESTRICTED = ST_UNRESTRICTED;
///

module.exports = SuperTask;<|endoftext|>