WAFRA

Web Augmentation Framework for Accessibility (WAFRA)

安装此脚本
作者推荐脚本

您可能也喜欢WAFRA4WikiTravel

安装此脚本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         WAFRA
// @namespace    http://tampermonkey.net/
// @version      2.3.2
// @description  Web Augmentation Framework for Accessibility (WAFRA)
// @author       Cesar Gonzalez Mora
// @match        *://*/*
// @noframes
// @exclude      *://www.youtube.com/embed/*
// @grant        none
// @require http://code.jquery.com/jquery-3.3.1.slim.min.js
// @require http://code.jquery.com/jquery-3.3.1.min.js
// ==/UserScript==


/*********************** Variables ************************/
var myStorage = window.localStorage;
var readerRate = 1.0;
const SpeechRecognition = window.webkitSpeechRecognition || window.SpeechRecognition;
const SpeechGrammarList = window.SpeechGrammarList || window.webkitSpeechGrammarList;
const recognition = new SpeechRecognition();
var timeoutResumeInfinity;

//var listeningActive = true;

var recognitionActive = true;
var recognitionFailedFirstTime = true;
var recognitionFailedText = "Command not recognised, please try again.";
var recognitionFailedTextES = "Comando no reconocido, por favor inténtelo de nuevo.";
var reading = false;
var readFirstTime = true;

var localStoragePrefix;

var operations = [];
var annotations = [];

var languageCodeSyntesis = "en";
var languageCodeCommands = "en";

var spanishDomain = false;

var languageCodeSyntesisES = "es";
var languageCodeCommandsES = "es";

var listOperationsCommand = "list operations";
var listSectionsCommand = "list sections";
var listSectionCommand = "list section";
var welcomeCommand = "welcome";
var stopListeningCommand = "stop listening";
var changeCommand = "change";
var cancelCommand = "cancel";
var activateCommand = "activate";
var deactivateCommand = "deactivate";
var loadAnnotationsCommand = "load annotations";
var loadAnnotationCommand = "load annotation";
var rateCommand = "score";
var changeCommandQuestion = "which command";
var newCommandQuestion = "which is the new command";

var listOperationsCommandES = "listar operaciones";
var listSectionsCommandES = "listar secciones";
var listSectionCommandES = "listar sección";

var readSectionsCommand = "read sections";
var readSectionsCommandES = "leer secciones";
var readNextSectionCommand = "read next";
var readNextSectionCommandES = "leer siguiente";
var readPreviousSectionCommand = "read previous";
var readPreviousSectionCommandES = "leer anterior";

var readFasterCommand = "faster";
var readFasterCommandES = "más rápido";
var readSlowerCommand = "slower";
var readSlowerCommandES = "más despacio";

var welcomeCommandES = "bienvenida";
var stopListeningCommandES = "parar de escuchar";
var changeCommandES = "cambiar";
var cancelCommandES = "cancelar";
var activateCommandES = "activar";
var deactivateCommandES = "desactivar";
var loadAnnotationsCommandES = "cargar anotaciones";
var loadAnnotationCommandES = "cargar anotación";
var rateCommandES = "valorar";
var changeCommandQuestionES = "que comando";
var newCommandQuestionES = "cuál es el nuevo comando?";

var readAllSections;
var lastSectionRead = "";

var changeCommandInProcess1 = false;
var changeCommandInProcess2 = false;
var newCommandString = "";
var activateClickDetector = false;
var activateTextDetector = false;

var paragraphItemsXPath = [];
var paragraphItemsXPathAux = [];

var annotationActive = false;
var annotationId = "";
var annotatedItemsAux = [];
var annotationElements = [];

var operationToChange;

/*********************** Page is loaded ************************/
$(document).ready(function() {
    createCSSSelector('.hideSectionsLinks', 'pointer-events: none');
    createCSSSelector('.hideUselessSections', 'display: none !important;');
    createCSSSelector('.hoverColor:hover', 'background-color: grey !important;');
    createCSSSelector('.selectedColor', 'background-color: grey !important;;');
    createCSSSelector('.modal', 'display: none; position: fixed; z-index: 1; padding-top: 100px; left: 0; top: 0; width: 100%; height: 100%; overflow: auto; background-color: rgb(0,0,0); background-color: rgba(0,0,0,0.4);');
    createCSSSelector('.modal-content', 'background-color: #fefefe; margin: auto; padding: 20px; border: 1px solid #888; width: 70% !important;');
    createCSSSelector('.close', 'color: #aaaaaa; position: absolute; right: 5%; font-size: 28px; font-weight: bold;');
    createCSSSelector('.close:hover', 'color: #000; text-decoration: none; cursor: pointer;');
    createCSSSelector('.close:focus', 'color: #000; text-decoration: none; cursor: pointer;');
    var link = document.createElement('link');
    link.rel = 'stylesheet';
    link.href = 'https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css';
    document.head.appendChild(link);
    $('*[class=""]').removeAttr('class');

    /*var meta = document.createElement('meta');
    meta.setAttribute('http-equiv', 'Content-Security-Policy-Report-Only');
    meta.content = "default-src 'self'; script-src 'self' 'unsafe-inline' https:; manifest-src 'self'";
    document.head.appendChild(meta);*/
    //<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">

    // Browsers require user interaction for speech synthesis
    var hiddenButton = document.createElement("button");
    hiddenButton.onclick = function(){console.log("User interaction");}
    document.body.appendChild(hiddenButton);
    //hiddenButton.focus();
    hiddenButton.click();
    hiddenButton.style.display = "none";
    //swal("Click OK to speak").then(() => hiddenButton.click());
    /*var firstTimeReadWelcome = function(){
        console.log("Read welcome onmouseover");
        document.body.removeEventListener("mouseover", firstTimeReadWelcome);
        readWelcome();
    }
    document.body.addEventListener("mouseover", firstTimeReadWelcome);*/

    clickDetector();

    // Local storage independent for each visitated website
    localStoragePrefix = encodeURI(document.URL) + "_";

    // Detect if domain is spanish or english
    if(document.domain.endsWith(".es") || document.domain.startsWith("es.")){
        spanishDomain = true;
    }


    /*********************** Add new annotations here ************************/
    var textAnnotation, paragraphAnnotation, uselessAnnotation;

    if(!spanishDomain){
        textAnnotation = new TextAnnotation("textAnnotation", "Text Annotation", ["text"], []);
        paragraphAnnotation = new ParagraphAnnotation("paragraphAnnotation", "Paragraph Annotation", ["P"], []);
        uselessAnnotation = new UselessAnnotation("uselessAnnotation", "Useless sections Annotation", ["all"], []);
    } else {
        textAnnotation = new TextAnnotation("textAnnotation", "Anotación de texto", ["text"], []);
        paragraphAnnotation = new ParagraphAnnotation("paragraphAnnotation", "Anotación de párrafos", ["P"], []);
        uselessAnnotation = new UselessAnnotation("uselessAnnotation", "Anotación de secciones inservibles", ["all"], []);
    }

    /*********************** Add new operations here ************************/
    var increaseFontSizeOperation, decreaseFontSizeOperation, readAloudOperation, goToOperation, goBackOperation, goForwardOperation, videosOperation, breadCrumbOperation, hideOperation;
    if(!spanishDomain){
        increaseFontSizeOperation = new IncreaseFontSizeOperation("increaseFontSizeOperation", "Increase Font Size", "increase font size", true, true, true, false, []);
        decreaseFontSizeOperation = new DecreaseFontSizeOperation("decreaseFontSizeOperation", "Decrease Font Size", "decrease font size", true, true, true, false, []);
        readAloudOperation = new ReadAloudOperation("readAloud", "Read Aloud", "read aloud", true, true, true, true, ["textAnnotation", "paragraphAnnotation"]);
        goToOperation = new GoToOperation("goTo", "Go To", "go to", true, true, true, true, ["textAnnotation", "paragraphAnnotation"]);
        goBackOperation = new GoBackOperation("goBack", "Go Back", "go back", true, true, true, false, []);
        goForwardOperation = new GoForwardOperation("goForward", "Go Forward", "go forward", true, true, true, false, []);
        videosOperation = new VideosOperation("videos", "Videos", "videos", true, true, true, false, []);
        breadCrumbOperation = new BreadcrumbOperation("breadcrumb", "Breadcrumb", "", true, true, true, false, []);
        hideOperation = new HideOperation("hide", "Hide useless sections", "", true, true, true, false, ["uselessAnnotation"]);
    } else {
        increaseFontSizeOperation = new IncreaseFontSizeOperation("increaseFontSizeOperation", "Aumentar Tamaño Letra", "aumentar tamaño letra", true, true, true, false, []);
        decreaseFontSizeOperation = new DecreaseFontSizeOperation("decreaseFontSizeOperation", "Reducir Tamaño Letra", "reducir tamaño letra", true, true, true, false, []);
        readAloudOperation = new ReadAloudOperation("readAloud", "Leer en voz alta", "leer", true, true, true, true, ["textAnnotation", "paragraphAnnotation"]);
        goToOperation = new GoToOperation("goTo", "Ir a", "ir a", true, true, true, true, ["textAnnotation", "paragraphAnnotation"]);
        goBackOperation = new GoBackOperation("goBack", "Volver", "volver", true, true, true, false, []);
        goForwardOperation = new GoForwardOperation("goForward", "Avanzar página", "avanzar página", true, true, true, false, []);
        videosOperation = new VideosOperation("videos", "Videos", "videos", true, true, true, false, []);
        breadCrumbOperation = new BreadcrumbOperation("breadcrumb", "Panel navegación", "", true, true, true, false, []);
        hideOperation = new HideOperation("hide", "Esconder secciones inservibles", "", true, true, true, false, ["uselessAnnotation"]);
    }

    checkFocus();
    initWAFRA();
    textToAudio();
    audioToText();

    var wafra = new WAFRA();
    wafra.getAndSetStorage();
    wafra.createWebAugmentedMenu();
    wafra.createAnnotationsMenu();
    wafra.createOperationsMenu();
    wafra.createCommandsMenu();
    wafra.basicAnnotation();
    document.onkeydown = KeyPress;

    setTimeout(function(){
        toggleHiddenSections();
    }, 1000);


});


/**
 * Class WAFRA.
 *
 * @class WAFRA
 */
class WAFRA {

    constructor() {

    }

    getAndSetStorage() {

        if(myStorage.getItem(localStoragePrefix + "readerRate") !== null){
            try {
                readerRate = myStorage.getItem(localStoragePrefix + "readerRate");
            } catch (e) {
            }
        } else {
            myStorage.setItem(localStoragePrefix + "readerRate", readerRate);
        }

        for(var annotationsIndex = 0; annotationsIndex < annotations.length; annotationsIndex++){
            // Annotated items
            if(myStorage.getItem(localStoragePrefix + annotations[annotationsIndex].id) !== null){
                annotations[annotationsIndex].items = myStorage.getItem(localStoragePrefix + annotations[annotationsIndex].id);
            } else {
                if(annotations[annotationsIndex].items.length > 0){
                    myStorage.setItem(localStoragePrefix + annotations[annotationsIndex].id, annotations[annotationsIndex].items);
                } else {
                    myStorage.setItem(localStoragePrefix + annotations[annotationsIndex].id, "[]");
                }
            }
        }
        for(var operationsIndex = 0; operationsIndex < operations.length; operationsIndex++){
            // Voice commands names
            if(myStorage.getItem(localStoragePrefix + operations[operationsIndex].id) !== null){
                operations[operationsIndex].voiceCommand = myStorage.getItem(localStoragePrefix + operations[operationsIndex].id);
            } else {
                myStorage.setItem(localStoragePrefix + operations[operationsIndex].id, operations[operationsIndex].voiceCommand);
            }

            // Operations & commands active?
            if(myStorage.getItem(localStoragePrefix + operations[operationsIndex].id + "Active") !== null){
                operations[operationsIndex].active = (myStorage.getItem(localStoragePrefix + operations[operationsIndex].id + "Active") == 'true');
            } else {
                myStorage.setItem(localStoragePrefix + operations[operationsIndex].id + "Active", operations[operationsIndex].active);
            }
        }


        //TODO: refactor
        if(myStorage.getItem(localStoragePrefix + "paragraphItemsXPath") !== null){
            try {
                paragraphItemsXPath = JSON.parse(myStorage.getItem(localStoragePrefix + "paragraphItemsXPath"))
            } catch (e) {
            }
        } else {
            myStorage.setItem(localStoragePrefix + "paragraphItemsXPath", JSON.stringify(paragraphItemsXPath));
        }
    }


    createWebAugmentedMenu(){
        createMenus();
    }

    createAnnotationsMenu(){
        createAnnotationsMenu();
    }

    createOperationsMenu(){
        createOperationsMenu();
    }

    createCommandsMenu(){
        createCommandsMenu();
    }

    basicAnnotation(){
        basicAnnotation();
    }

}

/**
 * Abstract Class Annotation.
 *
 * @class Annotation
 */
class Annotation {

    /*id;
    name;
    domElement;*/

    constructor() {
        if (this.constructor == Annotation) {
            throw new Error("Abstract classes can't be instantiated.");
        }
    }

    initAnnotationProcess() {
        throw new Error("Method 'initAnnotationProcess()' must be implemented.");
    }

    start() {
        throw new Error("Method 'start()' must be implemented.");
    }

    save() {
        throw new Error("Method 'save()' must be implemented.");
    }

    stop() {
        throw new Error("Method 'stop()' must be implemented.");
    }

    reset() {
        throw new Error("Method 'reset()' must be implemented.");
    }

    edit() {
        throw new Error("Method 'edit()' must be implemented.");
    }

    undo() {
        throw new Error("Method 'undo()' must be implemented.");
    }

    openMenu(){
        throw new Error("Method 'openMenu()' must be implemented.");
    }

    initAnnotation(id, name, domElements, items) {
        this.id = id;
        this.name = name;
        this.domElements = domElements;
        this.items = items
        annotations.push(this);
    }
}

class TextAnnotation extends Annotation {

    constructor(id, name, domElements, items){
        super();
        this.initAnnotation(id, name, domElements, items);
        /*this.id = id;
        this.name = name;
        this.domElement = domElement;*/
    }

    initAnnotationProcess() {
    }

    start() {
        console.log("annotationActive: " + annotationActive);
        if(!annotationActive){
            annotationActive = true;
            annotationId = this.id;
            startAnnotations(this);
        }
    }

    save() {
        saveAnnotations(this);
    }

    stop() {
        stopAnnotations(this);
    }

    reset(name) {
        resetAnnotationsById(this.id, name);
    }

    edit(name) {
        editAnnotationsByName(this.id, name);
    }

    undo() {
        undoAnnotations(this);
    }

    openMenu() {
        closeAnnotationsMenu();
        showSubmenu("menu-" + this.id);
    }
}

class ParagraphAnnotation extends Annotation {

    constructor(id, name, domElements, items){
        super();
        this.initAnnotation(id, name, domElements, items);
    }

    initAnnotationProcess() {
    }

    start() {
        console.log("annotationActive: " + annotationActive);
        if(!annotationActive){
            annotationActive = true;
            annotationId = this.id;
            startAnnotations(this);
        }
    }

    save() {
        saveAnnotations(this);
    }

    stop() {
        stopAnnotations(this);
    }

    reset(name) {
        resetAnnotationsById(this.id, name);
    }

    edit(name) {
        editAnnotationsByName(this.id, name);
    }

    undo() {
        undoAnnotations(this);
    }

    openMenu() {
        closeAnnotationsMenu();
        showSubmenu("menu-" + this.id);
    }
}


class UselessAnnotation extends Annotation {

    constructor(id, name, domElements, items){
        super();
        this.initAnnotation(id, name, domElements, items);
    }

    initAnnotationProcess() {
    }

    start() {
        console.log("annotationActive: " + annotationActive);
        if(!annotationActive){
            annotationActive = true;
            annotationId = this.id;
            startAnnotations(this);
        }
    }

    save() {
        saveAnnotations(this);
    }

    stop() {
        stopAnnotations(this);
    }

    reset(name) {
        resetAnnotationsById(this.id, name);
    }

    edit(name) {
        editAnnotationsByName(this.id, name);
    }

    undo() {
        undoAnnotations(this);
    }

    openMenu() {
        closeAnnotationsMenu();
        showSubmenu("menu-" + this.id);
    }
}


/*********************** Add new annotations classes here ************************/


/**
 * Abstract Class Operation.
 *
 * @class Operation
 */
class Operation {

    /*id;
    name;
    voiceCommand;
    activable;
    editable;*/

    constructor() {
        if (this.constructor == Operation) {
            throw new Error("Abstract classes can't be instantiated.");
        }
    }

    configureOperation() {
        throw new Error("Method 'initOperation()' must be implemented.");
    }

    initOperation() {
        throw new Error("Method 'initOperation()' must be implemented.");
    }

    startOperation() {
        throw new Error("Method 'startOperation()' must be implemented.");
    }

    stopOperation() {
        throw new Error("Method 'stopOperation()' must be implemented.");
    }


    initOperation(id, name, voiceCommand, activable, active, editable, hasMenu, annotations) {
        this.id = id;
        this.name = name;
        this.voiceCommand = voiceCommand;
        //this.section = section;
        this.activable = activable;
        this.active = active;
        this.editable = editable;
        this.hasMenu = hasMenu;
        this.annotations = annotations;
        operations.push(this);
    }
}


class IncreaseFontSizeOperation extends Operation {
    constructor(id, name, voiceCommand, activable, active, editable, hasMenu, annotations){
        super();
        this.initOperation(id, name, voiceCommand, activable, active, editable, hasMenu, annotations);
    }

    configureOperation(){

    }

    startOperation() {
        var scroll = window.scrollY;
        var totalScroll = Math.max(document.body.scrollHeight, document.body.offsetHeight,
                                   document.documentElement.clientHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight);

        var bodyContent = document.getElementsByTagName('div');

        for(var i = 0; i < bodyContent.length; i++) {
            var styleI = window.getComputedStyle(bodyContent[i], null).getPropertyValue('font-size');
            var fontSizeI = parseFloat(styleI);
            bodyContent[i].style.fontSize = (fontSizeI + 2) + 'px';
        }

        var currentTotalScroll = Math.max(document.body.scrollHeight, document.body.offsetHeight,
                                          document.documentElement.clientHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight);
        var currentScroll = (scroll * currentTotalScroll) / totalScroll;
        window.scrollTo(0, currentScroll);
    }

    stopOperation() {
        console.log("Stop operation");
    }
}


class DecreaseFontSizeOperation extends Operation {
    constructor(id, name, voiceCommand, activable, active, editable, hasMenu, annotations){
        super();
        this.initOperation(id, name, voiceCommand, activable, active, editable, hasMenu, annotations);
    }

    configureOperation(){

    }

    startOperation() {
        var scroll = window.scrollY;
        var totalScroll = Math.max(document.body.scrollHeight, document.body.offsetHeight,
                                   document.documentElement.clientHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight);

        var bodyContent = document.getElementsByTagName('div');

        for(var j = 0; j < bodyContent.length; j++) {
            var styleJ = window.getComputedStyle(bodyContent[j], null).getPropertyValue('font-size');
            var fontSizeJ = parseFloat(styleJ);
            bodyContent[j].style.fontSize = (fontSizeJ - 2) + 'px';
        }

        var currentTotalScroll = Math.max(document.body.scrollHeight, document.body.offsetHeight,
                                          document.documentElement.clientHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight);
        var currentScroll = (scroll * currentTotalScroll) / totalScroll;
        window.scrollTo(0, currentScroll);
    }

    stopOperation() {
        console.log("Stop operation");
    }
}

class ReadAloudOperation extends Operation {
    constructor(id, name, voiceCommand, activable, active, editable, hasMenu, annotations){
        super();
        this.initOperation(id, name, voiceCommand, activable, active, editable, hasMenu, annotations);
    }

    configureOperation() {
        //TODO: annotations parameters as objects
        createSubmenuForOperationAndAnnotations("menu-" + this.id, this);
    }

    openMenu() {
        closeOperationsMenu();
        showSubmenu("menu-" + this.id);
    }

    startOperation(params) {
        var sectionNameParam = params.currentTarget.sectionName;
        var operationParam = params.currentTarget.operation;
        readAloudFromSectionName("menu-" + operationParam.id, operationParam, sectionNameParam);
    }

    stopOperation() {
        console.log("Stop operation");
    }
}

function readAloudFromSectionName(menuId, operation, sectionName){

    var annotationsForOperation = operation.annotations;
    closeSubmenu(menuId);
    var sectionNameToRead = sectionName;
    if(typeof sectionName.parentElement === 'undefined' && typeof sectionName.currentTarget !== 'undefined'){
        sectionNameToRead = sectionName.currentTarget.sectionName
    }
    console.log("readFromSectionName: " + sectionNameToRead);
    //closeGoToMenu();
    closeMenu();
    closeOperationsMenu();

    var readContent = ""

    var sectionsNames;
    for(var i = 0; i < annotationsForOperation.length; i++){
        var items = JSON.parse(myStorage.getItem(localStoragePrefix + annotationsForOperation[i]));
        for(var j = 0; j < items.length; j++){
            if(sectionNameToRead === items[j].name){
                if(annotationsForOperation[i] === "textAnnotation"){
                    lastSectionRead = sectionNameToRead;
                    if(!spanishDomain){
                        readContent += "Section " + sectionNameToRead + ". " ;
                    } else {
                        readContent += "Sección " + sectionNameToRead + ". " ;
                    }
                    if(readFirstTime){
                        readFirstTime = false;
                        if(!spanishDomain){
                            readContent += "You can use control + space to stop the reading aloud operation. ";
                        } else {
                            readContent += "Puedes utilizar control + espacio para detener la lectura en voz alta. ";
                        }
                    }
                    for(var b = 0; b < items[j].value.length; b++){
                        readContent += items[j].value[b] + " ";
                        console.log("content: " + readContent);
                    }
                } else {
                    if(!spanishDomain){
                        readContent += "Section " + sectionNameToRead + ". " ;
                    } else {
                        readContent += "Sección " + sectionNameToRead + ". " ;
                    }
                    if(readFirstTime){
                        readFirstTime = false;
                        if(!spanishDomain){
                            readContent += "You can use control + space to stop the reading aloud operation. ";
                        } else {
                            readContent += "Puedes utilizar control + espacio para detener la lectura en voz alta. ";
                        }
                    }
                    for(var z = 0; z < items[j].value.length; z++){
                        var element = getElementByXPath(items[j].value[z]);
                        var domParser = new DOMParser().parseFromString(element.outerHTML, 'text/html');
                        readContent += domParser.body.innerText;
                        console.log("domParser: " + JSON.stringify(domParser));
                        console.log("content: " + readContent);
                    }
                }
            }
        }
    }
    Read(readContent);
}

class GoToOperation extends Operation {
    constructor(id, name, voiceCommand, activable, active, editable, hasMenu, annotations){
        super();
        this.initOperation(id, name, voiceCommand, activable, active, editable, hasMenu, annotations);
    }

    configureOperation() {
        //TODO: annotations parameters as objects
        createSubmenuForOperationAndAnnotations("menu-" + this.id, this);
    }

    openMenu() {
        closeOperationsMenu();
        showSubmenu("menu-" + this.id);
    }

    startOperation(params) {
        var sectionNameParam = params.currentTarget.sectionName;
        var operationParam = params.currentTarget.operation;
        goToFromSectionName("menu-" + operationParam.id, operationParam, sectionNameParam);
    }

    stopOperation() {
        console.log("Stop operation");
    }
}

// Go to
function goToFromSectionName(menuId, operation, sectionName){
    var annotationsForOperation = operation.annotations;
    closeSubmenu(menuId);
    var sectionNameToGo = sectionName;
    if(typeof sectionName.parentElement === 'undefined' && typeof sectionName.currentTarget !== 'undefined'){
        sectionNameToGo = sectionName.currentTarget.sectionName
    }
    console.log("goToFromSectionName: " + sectionNameToGo);
    //closeGoToMenu();
    closeMenu();
    closeOperationsMenu();

    var sectionsNames;
    for(var i = 0; i < annotationsForOperation.length; i++){
        var items = JSON.parse(myStorage.getItem(localStoragePrefix + annotationsForOperation[i]));
        for(var j = 0; j < items.length; j++){
            if(sectionNameToGo === items[j].name){
                if(annotationsForOperation[i] === "textAnnotation"){
                    if(items[j].value.length > 0){
                        var foundItem = $("*:contains('" + items[j].value[0] + "'):first").offset();
                        if(typeof foundItem != 'undefined'){
                            $(window).scrollTop(foundItem.top);
                        }
                    }
                } else {
                    var element = getElementByXPath(items[j].value[0]);
                    element.scrollIntoView();
                }
            }
        }
    }

}

// Go back
class GoBackOperation extends Operation {
    constructor(id, name, voiceCommand, activable, active, editable, hasMenu, annotations){
        super();
        this.initOperation(id, name, voiceCommand, activable, active, editable, hasMenu, annotations);
    }

    configureOperation() {
    }

    startOperation() {
        goBack();
    }

    stopOperation() {
    }
}

// Go forward
class GoForwardOperation extends Operation {
    constructor(id, name, voiceCommand, activable, active, editable, hasMenu, annotations){
        super();
        this.initOperation(id, name, voiceCommand, activable, active, editable, hasMenu, annotations);
    }

    configureOperation() {
    }

    startOperation() {
        goBack();
    }

    stopOperation() {
    }
}

// Videos
class VideosOperation extends Operation {
    constructor(id, name, voiceCommand, activable, active, editable, hasMenu, annotations){
        super();
        this.initOperation(id, name, voiceCommand, activable, active, editable, hasMenu, annotations);
    }

    configureOperation() {
    }

    startOperation() {
        goToVideos();
    }

    stopOperation() {
        console.log("Stop operation");
    }
}

// BreadCrumb
class BreadcrumbOperation extends Operation {
    constructor(id, name, voiceCommand, activable, active, editable, hasMenu){
        super();
        this.initOperation(id, name, voiceCommand, activable, active, editable, hasMenu);
    }

    configureOperation() {
        breadcrumb();
    }

    startOperation() {

    }

    stopOperation() {
        console.log("Stop operation");
    }
}

// Hide sections
class HideOperation extends Operation {
    constructor(id, name, voiceCommand, activable, active, editable, hasMenu, annotations){
        super();
        this.initOperation(id, name, voiceCommand, activable, active, editable, hasMenu, annotations);
    }

    configureOperation() {

    }

    startOperation() {

    }

    stopOperation() {
        console.log("Stop operation");
    }
}

// Show sections
class ShowOperation extends Operation {
    constructor(id, name, voiceCommand, activable, active, editable, hasMenu, annotations){
        super();
        this.initOperation(id, name, voiceCommand, activable, active, editable, hasMenu, annotations);
    }

    configureOperation() {

    }

    startOperation() {

    }

    stopOperation() {
        console.log("Stop operation");
    }
}


/*********************** Add new operations classes here ************************/


// *************************** Helpers ***************************

var hidden, visibilityChange, state;
function checkFocus(){
    // Set the name of the hidden property and the change event for visibility
    if (typeof document.hidden !== "undefined") { // Opera 12.10 and Firefox 18 and later support
        hidden = "hidden";
        visibilityChange = "visibilitychange";
        state = "visibilityState";
    } else if (typeof document.mozHidden !== "undefined") {
        hidden = "mozHidden";
        visibilityChange = "mozvisibilitychange";
        state = "mozVisibilityState";
    } else if (typeof document.msHidden !== "undefined") {
        hidden = "msHidden";
        visibilityChange = "msvisibilitychange";
        state = "msVisibilityState";
    } else if (typeof document.webkitHidden !== "undefined") {
        hidden = "webkitHidden";
        visibilityChange = "webkitvisibilitychange";
        state = "webkitVisibilityState";
    }

}

function initWAFRA() {
    var link1 = document.createElement('link');
    link1.rel = 'stylesheet';
    link1.href = 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css';
    document.head.appendChild(link1);
    var link2 = document.createElement('link');
    link1.rel = 'stylesheet';
    link2.href= 'https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css';
    document.head.appendChild(link2);

    var divMenu = document.createElement("div");
    divMenu.id = "menu-webaugmentation";
    divMenu.style = "position: fixed; left: 2%; top: 2%; z-index: 100; line-height: 140%;";
    var menuLinkDiv = document.createElement("div");
    menuLinkDiv.id = "div-webaugmentation";
    var menuLink = document.createElement("a");
    menuLink.id = "a-webaugmentation";
    menuLink.href = "javascript:void(0);";
    menuLink.className = "icon";
    menuLink.addEventListener("click", toggleMenu);
    var menuIcon = document.createElement("i");
    menuIcon.className = "fa fa-bars fa-2x fa-border";
    menuIcon.style="background-color: white;";
    menuLink.appendChild(menuIcon);
    menuLinkDiv.appendChild(menuLink);
    divMenu.appendChild(menuLinkDiv);
    document.body.appendChild(divMenu);

}


function createMenus(){

    var divButtons = document.createElement('div');
    divButtons.id = "foldingMenu";
    divButtons.style = "padding: 10px; border: 2px solid black; display: none; background-color: white";

    var toggleListeningIcon = document.createElement("i");
    toggleListeningIcon.id = "toggleListeningIcon";
    toggleListeningIcon.className = "fa fa-circle";

    var aToggleListening = document.createElement('a');
    aToggleListening.id = "toggleListeningA";
    aToggleListening.addEventListener("click", function(){
        closeMenu();
        if(recognitionActive){
            console.log("recognition deactivated")
            recognitionActive = false;
            if(!spanishDomain){
                aToggleListening.text = 'Start Listening';
            } else {
                aToggleListening.text = 'Activar comandos por voz';
            }
            toggleListeningIcon.style = "color:red; margin-left: 8px";
            recognition.abort();
        } else{
            console.log("recognition activated")
            recognitionActive = true;
            recognition.start();
            if(!spanishDomain){
                aToggleListening.text = 'Stop Listening';
            } else {
                aToggleListening.text = 'Desactivar comandos por voz';
            }
            //inputVoiceCommands.checked = recognitionActive;
            toggleListeningIcon.style = "color:gray; margin-left: 8px";
        }
        //document.getElementById("voiceCommandsInput").checked = recognitionActive;
        myStorage.setItem("recognitionActive", recognitionActive);
    }, false);
    if(recognitionActive){
        if(!spanishDomain){
            aToggleListening.text = 'Stop Listening';
        } else {
            aToggleListening.text = 'Desactivar comandos por voz';
        }
        toggleListeningIcon.style = "color:gray; margin-left: 8px";
    }
    else{
        if(!spanishDomain){
            aToggleListening.text = 'Start Listening';
        } else {
            aToggleListening.text = 'Activar comandos por voz';
        }
        toggleListeningIcon.style = "color:red; margin-left: 8px";
    }
    divButtons.appendChild(aToggleListening);
    divButtons.appendChild(toggleListeningIcon);
    divButtons.appendChild(document.createElement('br'));

    var a5 = document.createElement('a');
    a5.id = "voiceCommandsA";
    //a5.href = '';
    a5.addEventListener("click", function(){
        toggleMenu();
        toggleCommandsMenu();
        closeAnnotationsMenu();
        closeOperationsMenu();
    }, false);
    if(!spanishDomain){
        a5.text = 'Voice commands';
    } else {
        a5.text = 'Comandos por voz';
    }
    divButtons.appendChild(a5);
    /*var inputVoiceCommands = document.createElement('input');
    inputVoiceCommands.type = 'checkbox';
    inputVoiceCommands.id = 'voiceCommandsInput';
    inputVoiceCommands.value = 'voiceCommandsInput';
    inputVoiceCommands.checked = recognitionActive;
    inputVoiceCommands.addEventListener("change", function(){
        if(!this.checked){
            console.log("recognition deactivated")
            recognitionActive = false;
            recognition.abort();
            aToggleListening.text = 'Start Listening';
            toggleListeningIcon.style = "color:red; margin-left: 8px";
        } else {
            console.log("recognition activated")
            recognitionActive = true;
            recognition.start();
            aToggleListening.text = 'Stop Listening';
            toggleListeningIcon.style = "color:gray; margin-left: 8px";
        }
        myStorage.setItem("recognitionActive", recognitionActive);
    }, false);
    divButtons.appendChild(inputVoiceCommands);*/
    divButtons.appendChild(document.createElement('br'));

    var aOperations = document.createElement('a');
    aOperations.id = "operationsA";
    aOperations.addEventListener("click", toggleOperationsMenu, false);
    if(!spanishDomain){
        aOperations.text = 'Accessibility Operations';
    } else {
        aOperations.text = 'Operaciones de Accesibilidad';
    }
    divButtons.appendChild(aOperations);

    var i = document.createElement('i');
    i.className = 'fa fa-close'
    i.style = "position: absolute; right: 10%; top: 20%; z-index: 100;"
    i.addEventListener("click", closeMenu, false);
    divButtons.appendChild(i);


    document.getElementById("div-webaugmentation").appendChild(divButtons);

}

function createAnnotationsMenu(){

    var divMenuAnnotations = document.createElement("div");
    divMenuAnnotations.id = "menu-intermediary";
    divMenuAnnotations.style = "position: fixed; right: 2%; top: 2%; z-index: 101 !important; line-height: 140%;"
    var menuAnnotationsLinkDiv = document.createElement("div");
    menuAnnotationsLinkDiv.id = "div-intermediary";
    menuAnnotationsLinkDiv.style = "text-align: right;";
    var menuAnnotationsLink = document.createElement("a");
    menuAnnotationsLink.id = "a-intermediary";
    menuAnnotationsLink.href = "javascript:void(0);";
    menuAnnotationsLink.className = "icon";
    menuAnnotationsLink.addEventListener("click", toggleAnnotationsMenu)
    var menuAnnotationsIcon = document.createElement("i");
    menuAnnotationsIcon.className = "fa fa-pencil-square-o fa-2x fa-border";
    menuAnnotationsIcon.style="background-color: white;";
    menuAnnotationsLink.appendChild(menuAnnotationsIcon);

    var aSave = document.createElement('a');
    aSave.id = "saveAnnotationsA";
    aSave.href = "javascript:void(0);";
    aSave.className = "icon";
    if(!spanishDomain){
        aSave.title = "Save";
    } else {
        aSave.title = "Guardar";
    }
    aSave.style = "display: none";
    aSave.addEventListener("click", saveAnnotationsSections, false);
    var saveIcon = document.createElement("i");
    saveIcon.className = "fa fa-floppy-o fa-2x fa-border";
    saveIcon.style="background-color: white;";
    aSave.appendChild(saveIcon);
    menuAnnotationsLinkDiv.appendChild(aSave);

    var aStop = document.createElement('a');
    aStop.id = "stopAnnotationsA";
    aStop.href = "javascript:void(0);";
    aStop.className = "icon";
    if(!spanishDomain){
        aStop.title = "Stop";
    } else {
        aStop.title = "Detener";
    }
    aStop.style = "display: none";
    aStop.addEventListener("click", stopAnnotationsSections, false);
    var stopIcon = document.createElement("i");
    stopIcon.className = "fa fa-stop fa-2x fa-border";
    stopIcon.style="background-color: white;";
    aStop.appendChild(stopIcon);
    menuAnnotationsLinkDiv.appendChild(aStop);

    var aUndo = document.createElement('a');
    aUndo.id = "undoAnnotationsA";
    aUndo.href = "javascript:void(0);";
    aUndo.className = "icon";
    if(!spanishDomain){
        aUndo.title = "Undo";
    } else {
        aUndo.title = "Deshacer";
    }
    aUndo.style = "display: none";
    aUndo.addEventListener("click", undoAnnotationsSections, false);
    var undoIcon = document.createElement("i");
    undoIcon.className = "fa fa-undo fa-2x fa-border";
    undoIcon.style="background-color: white;";
    aUndo.appendChild(undoIcon);
    menuAnnotationsLinkDiv.appendChild(aUndo);

    menuAnnotationsLinkDiv.appendChild(menuAnnotationsLink);
    divMenuAnnotations.appendChild(menuAnnotationsLinkDiv);

    var divAnnotationsMenu = document.createElement("div")
    divAnnotationsMenu.id = "menu-annotations";
    divAnnotationsMenu.style = "z-index: 100; padding: 10px; border: 2px solid black; display: none; background-color: white"

    var i = document.createElement('i');
    i.className = 'fa fa-close'
    i.style = "position: absolute; right: 1%; top: 31%; z-index: 100;"
    i.addEventListener("click", function(){
        closeAnnotationsMenu();
    }, false);
    divAnnotationsMenu.appendChild(i);

    for(var annotationsIndex = 0; annotationsIndex < annotations.length; annotationsIndex++){
        var a2 = document.createElement('a');
        a2.id = annotations[annotationsIndex].id;
        //a2.href = '';
        a2.addEventListener("click", function(){
            for(var i = 0; i < annotations.length; i++){
                if(annotations[i].id === this.id){
                    annotations[i].start();
                }
            }
        }, false);
        a2.text = annotations[annotationsIndex].name;
        divAnnotationsMenu.appendChild(a2);

        var a2b = document.createElement('a');
        a2b.id = "edit" + annotations[annotationsIndex].id;
        a2b.className = "icon";
        if(!spanishDomain){
            a2b.title = "Edit" + annotations[annotationsIndex].name;
        } else {
            a2b.title = "Editar" + annotations[annotationsIndex].name;
        }
        a2b.addEventListener("click", function(){
            for(var i = 0; i < annotations.length; i++){
                if(annotations[i].id === this.id.split("edit").join("")){
                    annotations[i].openMenu();
                }
            }
        }, false);
        var a2bIcon = document.createElement("i");
        a2bIcon.className = "fa fa-edit";
        a2bIcon.style = "margin-left: 8px";
        a2b.appendChild(a2bIcon);
        divAnnotationsMenu.appendChild(a2b);

        var a2bTrash = document.createElement('a');
        a2bTrash.id = "reset" + annotations[annotationsIndex].id;
        a2bTrash.className = "icon";
        if(!spanishDomain){
            a2bTrash.title = "Reset" + annotations[annotationsIndex].name;
        } else {
            a2bTrash.title = "Resetear" + annotations[annotationsIndex].name;
        }
        a2bTrash.addEventListener("click", function(){
                for(var i = 0; i < annotations.length; i++){
                    if(annotations[i].id === this.id.split("reset").join("")){
                        if(!spanishDomain){
                            if(confirm("Are you sure to delete all the " + annotations[i].name + " annotations?")){
                                annotations[i].reset();
                            }
                        } else {
                            if(confirm("¿Estás seguro de borrar todas las anotaciones " + annotations[i].name + "?")){
                                annotations[i].reset();
                            }
                        }
                    }
                }
        }, false);
        var a2bTrashIcon = document.createElement("i");
        a2bTrashIcon.className = "fa fa-trash-o";
        a2bTrashIcon.style = "margin-left: 8px";
        a2bTrash.appendChild(a2bTrashIcon);
        divAnnotationsMenu.appendChild(a2bTrash);

        divAnnotationsMenu.appendChild(document.createElement('br'));
    }

    var a7 = document.createElement('a');
    a7.id = "loadAnnotationsA";
    if(!spanishDomain){
        a7.text = "Load annotations";
    } else {
        a7.text = "Cargar anotaciones";
    }
    a7.addEventListener("click", loadAnnotationsFromServer, false);
    divAnnotationsMenu.appendChild(a7);
    divAnnotationsMenu.appendChild(document.createElement('br'));

    var a8 = document.createElement('a');
    a8.id = "saveAnnotationsA";
    a8.text = "Save annotations";
    if(!spanishDomain){
        a8.text = "Save annotations";
    } else {
        a8.text = "Guardar anotaciones";
    }
    a8.addEventListener("click", askAnnotationsInfoForServer, false);
    divAnnotationsMenu.appendChild(a8);
    divAnnotationsMenu.appendChild(document.createElement('br'));


    var divLoadAnnotations = document.createElement('div')
    divLoadAnnotations.id = "menu-loadAnnotations"
    divLoadAnnotations.style = "z-index: 100; padding: 10px; border: 2px solid black; display: none; background-color: white"

    var iLoad = document.createElement('i');
    iLoad.className = 'fa fa-close'
    iLoad.style = "position: absolute; right: 1%; top: 91%; z-index: 100;"
    iLoad.addEventListener("click", function(){
        closeLoadMenu();
    }, false);
    divLoadAnnotations.appendChild(iLoad);

    divMenuAnnotations.appendChild(divAnnotationsMenu);
    divMenuAnnotations.appendChild(divLoadAnnotations);

    document.body.appendChild(divMenuAnnotations);

    for(var annotationsI = 0; annotationsI < annotations.length; annotationsI++){
        createSubmenuForAnnotations("menu-" + annotations[annotationsI].id, annotations[annotationsI].id);
    }


    var saveModal = document.createElement("div");
    saveModal.id = "saveModal";
    saveModal.classList.add("modal");
    var saveModalContent = document.createElement("div");
    saveModalContent.classList.add("modal-content");
    var spanClose = document.createElement("span");
    spanClose.classList.add("close");
    spanClose.innerHTML = "&times;";
    spanClose.onclick = function(){
        saveModal.style.display = "none";
    };
    saveModalContent.appendChild(spanClose);

    var h2 = document.createElement("h2");
    if(!spanishDomain){
        h2.innerHTML = "Save annotations in server";
    } else {
        h2.innerHTML = "Guardar anotaciones en el servidor";
    }
    saveModalContent.appendChild(h2);

    var form = document.createElement("form");

    // title should be unique and easy to say (recongnisable)
    var labelTitleModal = document.createElement("label");
    if(!spanishDomain){
        labelTitleModal.innerHTML = "Title of annotations: ";
    } else {
        labelTitleModal.innerHTML = "Nombre de las anotaciones: ";
    }
    labelTitleModal.for = "inputTitleModal";
    form.appendChild(labelTitleModal);

    var inputTitleModal = document.createElement("input");
    inputTitleModal.id = "inputTitleModal";
    inputTitleModal.type = "text";
    inputTitleModal.classList.add("form-control");
    inputTitleModal.required = true;
    if(!spanishDomain){
        inputTitleModal.placeholder = "A unique title that can be recognised by voice";
    } else {
        inputTitleModal.placeholder = "Un nombre único que pueda ser reconocido por voz";
    }
    form.appendChild(inputTitleModal);

    var br = document.createElement("br");
    form.appendChild(br);

    var labelDescriptionModal = document.createElement("label");
    if(!spanishDomain){
        labelDescriptionModal.innerHTML = "Description of annotations: ";
    } else {
        labelDescriptionModal.innerHTML = "Descripción de las annotaciones: ";
    }
    labelDescriptionModal.for = "inputDescriptionModal";
    form.appendChild(labelDescriptionModal);

    var inputDescriptionModal = document.createElement("input");
    inputDescriptionModal.id = "inputDescriptionModal";
    inputDescriptionModal.type = "text";
    inputDescriptionModal.classList.add("form-control");
    if(!spanishDomain){
        inputDescriptionModal.placeholder = "A description about the annotations done";
    } else {
        inputDescriptionModal.placeholder = "Una descripción de las anotaciones realizadas";
    }
    form.appendChild(inputDescriptionModal);

    br = document.createElement("br");
    form.appendChild(br);

    var labelTargetUsersModal = document.createElement("label");
    if(!spanishDomain){
        labelTargetUsersModal.innerHTML = "Target users: ";
    } else {
        labelTargetUsersModal.innerHTML = "Usuarios destinatarios: ";
    }
    labelTargetUsersModal.for = "selectTargetUsersModal";
    form.appendChild(labelTargetUsersModal);

    var selectTargetUsersModal = document.createElement("select");
    selectTargetUsersModal.id = "selectTargetUsersModal";
    //selectTargetUsersModal.type = "text";
    selectTargetUsersModal.classList.add("form-control");
    //selectTargetUsersModal.placeholder = "A description about the annotations done";

    var option1 = document.createElement("option");
    var option2 = document.createElement("option");
    var option3 = document.createElement("option");
    if(!spanishDomain){
        option1.text = "All users";
        option2.text = "Users with some visual impairment";
        option3.text = "Blind people";
    } else {
        option1.text = "Todos los usuarios";
        option2.text = "Usuarios con problemas de visión";
        option3.text = "Personas ciegas";
    }
    selectTargetUsersModal.add(option1);
    selectTargetUsersModal.add(option2);
    selectTargetUsersModal.add(option3);

    form.appendChild(selectTargetUsersModal);

    br = document.createElement("br");
    form.appendChild(br);

    var labelCategoryModal = document.createElement("label");
    if(!spanishDomain){
        labelCategoryModal.innerHTML = "Category: ";
    } else {
        labelCategoryModal.innerHTML = "Categoría: ";
    }
    labelCategoryModal.for = "selectCategoryModal";
    form.appendChild(labelCategoryModal);

    var selectCategoryModal = document.createElement("select");
    selectCategoryModal.id = "selectCategoryModal";
    //selectCategoryModal.type = "text";
    selectCategoryModal.classList.add("form-control");
    //selectCategoryModal.placeholder = "A description about the annotations done";

    var selectCategoryModalOption1 = document.createElement("option");
    var selectCategoryModalOption2 = document.createElement("option");
    if(!spanishDomain){
        selectCategoryModalOption1.text = "General overview";
        selectCategoryModalOption2.text = "Detailed information";
    } else {
        selectCategoryModalOption1.text = "Resumen general";
        selectCategoryModalOption2.text = "Información detallada";
    }
    selectCategoryModal.add(selectCategoryModalOption1);
    selectCategoryModal.add(selectCategoryModalOption2);

    form.appendChild(selectCategoryModal);

    br = document.createElement("br");
    form.appendChild(br);

    var buttonSaveModal = document.createElement("button");
    buttonSaveModal.id = "buttonSaveModal";
    if(!spanishDomain){
        buttonSaveModal.innerHTML = "Save";
    } else {
        buttonSaveModal.innerHTML = "Guardar";
    }
    buttonSaveModal.classList.add("btn");
    buttonSaveModal.classList.add("btn-primary");
    buttonSaveModal.style = "margin: auto !important; display: block !important;"
    buttonSaveModal.onclick = function () {
        //TODO: create form with onclick to saveAnnotationsInServer with object param obj: {title: "", category: "", targetUsers: "", "description: ""}
        var selectTargetUsersModal = document.getElementById("selectTargetUsersModal");
        var selectTargetUsersModalValue = selectTargetUsersModal.options[selectTargetUsersModal.selectedIndex].text;
        var selectCategoryModal = document.getElementById("selectCategoryModal");
        var selectCategoryModalValue = selectCategoryModal.options[selectCategoryModal.selectedIndex].text;

        var obj = {};
        obj.title = document.getElementById("inputTitleModal").value;
        obj.description = document.getElementById("inputDescriptionModal").value;
        obj.category = selectCategoryModalValue;
        obj.targetUsers = selectTargetUsersModalValue;
        event.preventDefault();
        saveAnnotationsInServer(obj);

    }
    form.appendChild(buttonSaveModal);
    saveModalContent.appendChild(form);

    saveModal.appendChild(saveModalContent);
    document.body.appendChild(saveModal);

    var loadModal = document.createElement("div");
    loadModal.id = "loadModal";
    loadModal.classList.add("modal");
    var loadModalContent = document.createElement("div");
    loadModalContent.classList.add("modal-content");
    loadModalContent.id = "loadModalContent";
    var spanLoadClose = document.createElement("span");
    spanLoadClose.classList.add("close");
    spanLoadClose.innerHTML = "&times;";
    spanLoadClose.onclick = function(){
        loadModal.style.display = "none";
    };
    loadModalContent.appendChild(spanLoadClose);

    var h2Load = document.createElement("h2");
    if(!spanishDomain){
        h2Load.innerHTML = "Load annotations from server";
    } else {
        h2Load.innerHTML = "Cargar anotaciones del servidor";
    }
    loadModalContent.appendChild(h2Load);

    var divLoad = document.createElement("div");
    divLoad.id = "divLoad";
    loadModalContent.appendChild(divLoad);

    loadModal.appendChild(loadModalContent);
    document.body.appendChild(loadModal);

}



function saveAnnotationsSections(){

    if(annotationActive){
        for(var i = 0; i < annotations.length; i++){
            if(annotationId === annotations[i].id){
                annotations[i].save();
            }
        }
    }
}

function stopAnnotationsSections(){

    if(annotationActive){
        for(var i = 0; i < annotations.length; i++){
            if(annotationId === annotations[i].id){
                annotations[i].stop();
            }
        }
    }
}

function undoAnnotationsSections(){

    if(annotationActive){
        for(var i = 0; i < annotations.length; i++){
            if(annotationId === annotations[i].id){
                annotations[i].undo();
            }
        }
    }
}

function resetAnnotationsSections(){

    if(annotationActive){
        for(var i = 0; i < annotations.length; i++){
            if(annotationId === annotations[i].id){
                annotations[i].reset();
            }
        }
    }
}

function startAnnotations(annotation){
    if(annotation.domElements.length === 1 && annotation.domElements[0] === "text"){
        startAnnotationsTextSections();
    } else {
        annotationElements = annotation.domElements;
        startAnnotationsElements();
    }
}

function startAnnotationsTextSections(){
    activateTextDetector = true;
    closeAnnotationsMenu();

    showAnnotationsButtons();
    hideAnnotationMainButton();

    var textSelectionDiv
    //annotationActive = true;
    //annotationId = annotation.id;
    annotatedItemsAux = [];
    document.addEventListener("mouseup", saveTextSelected);
    document.addEventListener("keyup", saveTextSelected);
    //document.getElementById("annotateTextA").text = "Save text section";
    textSelectionDiv = document.createElement("div");
    textSelectionDiv.id = "textSelectionDiv";
    textSelectionDiv.style = "position: fixed; top: 80%; margin: 10px; padding: 10px; width: 95%; height: 100px; overflow: scroll; background-color: #E6E6E6; border: 1px solid #00000F; display: none";
    document.body.appendChild(textSelectionDiv);
    if(!spanishDomain){
        alert("Please select text from a specific section with important information and then click the save icon.");
    } else {
        alert("Por favor selecciona texto de una sección específica con información importante y después pulsa el icono de guardar.");
    }

}

function startAnnotationsElements(){
    activateClickDetector = true;
    annotationActive = true;
    closeAnnotationsMenu();

    showAnnotationsButtons();
    hideAnnotationMainButton();

    $('button').attr('disabled', 'disabled');
    $('a').addClass("hideSectionsLinks");
    /*all = document.body.getElementsByTagName("*");
        for (var i = 0; i < all.length; i++) {
            all[i].classList.add('hoverColor');
        }*/
    //$('a').css({'pointer-events': 'none'});
    $("#saveAnnotationsA").css({'pointer-events': 'all'});
    $("#stopAnnotationsA").css({'pointer-events': 'all'});
    $("#undoAnnotationsA").css({'pointer-events': 'all'});
    annotatedItemsAux = [];
    if(!spanishDomain){
        alert("Please click on the elements from a specific section and then click the save icon.");
    } else {
        alert("Por favor haz click en los elementos de una sección específica y después pulsa el icono de guardar.");
    }
}

function saveAnnotations(annotation){
    if(annotation.domElements.length === 1 && annotation.domElements[0] === "text"){
        saveAnnotationsTextSections();
    } else {
        saveAnnotationsElements();
    }
}

function saveAnnotationsTextSections(){
    if(Array.isArray(annotatedItemsAux) && annotatedItemsAux.length > 0){

        var result;
        if(!spanishDomain){
            result = prompt("Title of these text selections (must be recognisable by voice)", "");
        } else {
            result = prompt("Título de la selección de texto (tiene que ser un título reconocible por voz)", "");
        }

        var exists = false;
        try{
            var currentItems = JSON.parse(myStorage.getItem(localStoragePrefix + annotationId));
            var otherItems = JSON.parse(myStorage.getItem(localStoragePrefix + "paragraphAnnotation"))
            var allItems = currentItems.concat(otherItems);
            if(Array.isArray(allItems) && allItems.length > 0){
                for(var i = 0; i < allItems.length; i++){
                    if(allItems[i].name.toLowerCase() === result.toLowerCase()){
                        exists = true;
                    }
                }
            }
        } catch(e){
            console.log("error merging elements");
        }

        while(exists){
            exists = false;
            if(!spanishDomain){
                result = prompt("Title of these text selections (choose a title that does not exist)", "");
            } else {
                result = prompt("Título de la selección de texto (elija uno que no exista)", "");
            }
            try{
                if(Array.isArray(allItems) && allItems.length > 0){
                    for(var j = 0; j < allItems.length; j++){
                        if(allItems[j].name.toLowerCase() === result.toLowerCase()){
                            exists = true;
                        }
                    }
                }
            } catch(e){}
        }

        var jsonText = new Object();
        jsonText.name = result;
        jsonText.value = annotatedItemsAux;
        var jsons = new Array();
        try{
            var items = JSON.parse(myStorage.getItem(localStoragePrefix + annotationId));
            if(Array.isArray(items) && items.length > 0){
                jsons = items;
            }
        } catch(e){}
        jsons.push(jsonText);
        myStorage.setItem(localStoragePrefix + annotationId, JSON.stringify(jsons));
        annotatedItemsAux = [];

        var textSelectionDiv = document.getElementById("textSelectionDiv");
        textSelectionDiv.innerHTML = "";
    }

    if(annotationActive){
        if(!spanishDomain){
            alert("Please continue selecting text from other specific section (until you click the stop icon).");
        } else {
            alert("Por favor continúa seleccionando texto de otras secciones (hasta que pulses el icono de stop).");
        }
    }
}

function saveAnnotationsElements(){
    if(Array.isArray(annotatedItemsAux) && annotatedItemsAux.length > 0){
        var result;
        if(!spanishDomain){
            result = prompt("Title of this section (must be recognisable by voice)", "");
        } else {
            result = prompt("Título de la sección (tiene que ser reconocible por voz)", "");
        }
        if(result !== null){
            var exists = false;
            try{
                var currentItems = JSON.parse(myStorage.getItem(localStoragePrefix + annotationId));
                var otherItems = JSON.parse(myStorage.getItem(localStoragePrefix + "textAnnotation"))
                var allItems = currentItems.concat(otherItems);
                if(Array.isArray(allItems) && allItems.length > 0){
                    for(var i = 0; i < allItems.length; i++){
                        if(allItems[i].name.toLowerCase() === result.toLowerCase()){
                            exists = true;
                        }
                    }
                }
            } catch(e){
                console.log("error merging elements");
            }

            while(exists){
                exists = false;
                if(!spanishDomain){
                    result = prompt("Title of this section (choose a title that does not exist)", "");
                } else {
                    result = prompt("Título de la sección (elija uno que no exista)", "");
                }
                try{
                    if(Array.isArray(allItems) && allItems.length > 0){
                        for(var j = 0; j < allItems.length; j++){
                            if(allItems[j].name.toLowerCase() === result.toLowerCase()){
                                exists = true;
                            }
                        }
                    }
                } catch(e){}
            }

            var all = document.body.getElementsByTagName("*");
            for (var k = 0; k < all.length; k++) {
                all[k].classList.remove('hoverColor');
                all[k].classList.remove('selectedColor');
            }

            $('*[class=""]').removeAttr('class');

            var jsonParagraph = new Object();
            jsonParagraph.name = result;
            jsonParagraph.value = annotatedItemsAux;
            var jsons = new Array();
            try{
                var items = JSON.parse(myStorage.getItem(localStoragePrefix + annotationId));
                if(Array.isArray(items) && items.length > 0){
                    jsons = items;
                }
            } catch(e){}
            jsons.push(jsonParagraph);
            myStorage.setItem(localStoragePrefix + annotationId, JSON.stringify(jsons));
            annotatedItemsAux = [];

            //TODO: refactor xpath annotations
            if(annotationId === "paragraphAnnotation"){
                var jsonParagraphXPath = new Object();
                jsonParagraphXPath.name = result;
                jsonParagraphXPath.value = paragraphItemsXPathAux;
                var jsonsXPath = new Array();
                try{
                    var paragraphItemsXPath = JSON.parse(myStorage.getItem(localStoragePrefix + "paragraphItemsXPath"));
                    if(Array.isArray(paragraphItemsXPath) && paragraphItemsXPath.length > 0){
                        jsonsXPath = paragraphItemsXPath;
                    }
                } catch(e){}
                jsonsXPath.push(jsonParagraphXPath);
                myStorage.setItem(localStoragePrefix + "paragraphItemsXPath", JSON.stringify(jsonsXPath));
                paragraphItemsXPathAux = [];
            }

            if(annotationActive){
                if(!spanishDomain){
                    alert("Please continue clicking on other sections (until you click the stop icon).");
                } else {
                    alert("Por favor continúe haciendo click en otras secciones (hasta que pulses el botón de stop).");
                }
            }
        }
    }
}


function stopAnnotations(annotation){
    if(annotation.domElements.length === 1 && annotation.domElements[0] === "text"){
        stopAnnotationsTextSections();
    } else {
        stopAnnotationsElements();
    }
}

function stopAnnotationsTextSections(){
    if(activateTextDetector){
        document.removeEventListener("mouseup", saveTextSelected);
        document.removeEventListener("keyup", saveTextSelected);

        annotationActive = false;
        saveAnnotationsTextSections();
        annotationId = "";
        activateTextDetector = false;

        hideAnnotationsButtons();
        showAnnotationMainButton();

        var textSelectionDiv = document.getElementById("textSelectionDiv");
        document.body.removeChild(textSelectionDiv);

        toggleReadAloud();

        for(var i = 0; i < operations.length; i++){
            if(operations[i].hasMenu){
                updateSubmenuForOperationAndAnnotations("menu-" + operations[i].id, operations[i], operations[i].annotations);
            }
        }

        for(var j = 0; j < annotations.length; j++){
            updateSubmenuForAnnotations("menu-" + annotations[j].id, annotations[j].id);
        }

        toggleHiddenSections();

    }
}

function stopAnnotationsElements(){
    annotationActive = false;
    saveAnnotationsElements()
    $('button').removeAttr('disabled');
    //$('a').css({'pointer-events': 'all'});
    $('a').removeClass("hideSectionsLinks");
    activateClickDetector = false;
    $('*[class=""]').removeAttr('class');

    // save sections names from paragraphItems
    /*var paragraphItems = JSON.parse(myStorage.getItem(localStoragePrefix + "paragraphItems"));
    var textItems = JSON.parse(myStorage.getItem(localStoragePrefix + "textItems"));
    var sectionsNames = [];
    for(var i = 0; i < paragraphItems.length; i++){
        sectionsNames.push(paragraphItems[i].name);
    }
    for(var j = 0; j < textItems.length; j++){
        sectionsNames.push(textItems[j].name);
    }
    myStorage.setItem(localStoragePrefix + "sectionsNames", JSON.stringify(sectionsNames));*/

    hideAnnotationsButtons();
    showAnnotationMainButton();

    updateScriptXPath();
    toggleReadAloud();

    for(var i = 0; i < operations.length; i++){
        if(operations[i].hasMenu){
            updateSubmenuForOperationAndAnnotations("menu-" + operations[i].id, operations[i], operations[i].annotations);
        }
    }

    for(var j = 0; j < annotations.length; j++){
        updateSubmenuForAnnotations("menu-" + annotations[j].id, annotations[j].id);
    }

    toggleHiddenSections();
}

function undoAnnotations(annotation){
    if(annotation.domElements.length === 1 && annotation.domElements[0] === "text"){
        undoAnnotationsTextSections();
    } else {
        undoAnnotationsElements();
    }
}

function undoAnnotationsTextSections(){
    annotatedItemsAux.pop();

    var newContentString = "";
    for(var i = 0; i < annotatedItemsAux.length; i++){
        newContentString += annotatedItemsAux[i] + " ";
    }
    var textSelectionDiv = document.getElementById("textSelectionDiv");
    textSelectionDiv.innerText = newContentString;
}

function undoAnnotationsElements(){

    try{
        var lastItem = getElementByXPath(annotatedItemsAux[annotatedItemsAux.length -1]);
        if(typeof lastItem !== "undefined" && lastItem !== null){
            lastItem.classList.remove('selectedColor');
            annotatedItemsAux.pop();
            if(annotationId === "paragraphAnnotation")
                paragraphItemsXPathAux.pop();
        }/* else {
            var all = document.body.getElementsByTagName("*");
            for (var j=0, max=all.length; j < max; j++) {
                var containsSelectedColor = false;
                if(all[j].classList.contains('selectedColor')){
                    all[j].classList.remove('selectedColor');
                    if(all[j].classList.length === 0){
                        all[j].removeAttribute('class');
                    }
                    containsSelectedColor = true;
                }
                if(all[j].outerHTML === annotatedItemsAux[annotatedItemsAux.length -1]){
                    all[j].classList.remove('selectedColor');
                    annotatedItemsAux.pop();
                    if(annotationId === "paragraphAnnotation")
                        paragraphItemsXPathAux.pop();
                    containsSelectedColor = false;
                }

                if(containsSelectedColor){
                    all[j].classList.add('selectedColor');
                    containsSelectedColor = false;
                }
            }
        }*/
    } catch(error){
        console.log("Error searching for undo");
        console.log(error.message);
    }
}

function resetAnnotationsById(id, name){

    var resetSection = false;

    if(name !== null && typeof name !== 'undefined'){
        resetSection = true;
    }

    if(!resetSection){
        myStorage.setItem(localStoragePrefix + id, JSON.stringify([]));
    } else {
        for(var k = 0; k < annotations.length; k++){
            if(annotations[k].id === id){
                for(var a = 0; a < annotations[k].items.length; a++){
                    if(annotations[k].items[a].name === name){
                        annotations[k].items.splice(a, 1);
                    }
                }
                myStorage.setItem(localStoragePrefix + id, JSON.stringify(annotations[k].items));
            }
        }
    }

    for(var i = 0; i < operations.length; i++){
        if(operations[i].hasMenu){
            updateSubmenuForOperationAndAnnotations("menu-" + operations[i].id, operations[i], operations[i].annotations);
        }
    }

    for(var j = 0; j < annotations.length; j++){
        updateSubmenuForAnnotations("menu-" + annotations[j].id, annotations[j].id);
    }

    closeAnnotationsMenu();
    closeSubmenu("menu-" + id);
    toggleHiddenSections();
}

function editAnnotationsByName(id, name){

    var editSection = false;

    if(name !== null && typeof name !== 'undefined'){
        editSection = true;
    }

    if(editSection){
        for(var k = 0; k < annotations.length; k++){
            if(annotations[k].id === id){
                for(var a = 0; a < annotations[k].items.length; a++){
                    if(annotations[k].items[a].name === name){
                        var result;
                        if(!spanishDomain){
                            result = prompt("Title of this section (must be recognisable by voice)", "");
                        } else {
                            result = prompt("Título de esta sección (tiene que ser reconocible por voz)", "");
                        }

                        var exists = false;
                        try{
                            var currentItems = JSON.parse(myStorage.getItem(localStoragePrefix + "textAnnotation"));
                            var otherItems = JSON.parse(myStorage.getItem(localStoragePrefix + "paragraphAnnotation"))
                            var allItems = currentItems.concat(otherItems);
                            if(Array.isArray(allItems) && allItems.length > 0){
                                for(var i = 0; i < allItems.length; i++){
                                    if(allItems[i].name.toLowerCase() === result.toLowerCase()){
                                        exists = true;
                                    }
                                }
                            }
                        } catch(e){
                            console.log("error merging elements");
                        }

                        while(exists){
                            exists = false;
                            if(!spanishDomain){
                                result = prompt("Title of this section (choose a title that does not exist)", "");
                            } else {
                                result = prompt("Título de esta sección (elija uno que no exista)", "");
                            }
                            try{
                                if(Array.isArray(allItems) && allItems.length > 0){
                                    for(var j = 0; j < allItems.length; j++){
                                        if(allItems[j].name.toLowerCase() === result.toLowerCase()){
                                            exists = true;
                                        }
                                    }
                                }
                            } catch(e){}
                        }
                        if(result !== null && result !== "" && typeof result !== 'undefined'){
                            annotations[k].items[a].name = result;
                        }
                    }
                }
                myStorage.setItem(localStoragePrefix + id, JSON.stringify(annotations[k].items));
            }
        }
    }

    for(var x = 0; x < operations.length; x++){
        if(operations[x].hasMenu){
            updateSubmenuForOperationAndAnnotations("menu-" + operations[x].id, operations[x], operations[x].annotations);
        }
    }

    for(var y = 0; y < annotations.length; y++){
        updateSubmenuForAnnotations("menu-" + annotations[y].id, annotations[y].id);
    }

    closeAnnotationsMenu();
    closeSubmenu("menu-" + id);
    toggleHiddenSections();
}

function clickDetector(){
    document.addEventListener('click', function(event) {
        if (event===undefined) event= window.event;
        var target= 'target' in event? event.target : event.srcElement;

        if(activateClickDetector){
            var menu = document.getElementById("menu-webaugmentation");
            var menuAnnotations = document.getElementById("menu-intermediary");
            if(!menu.contains(target) && !menuAnnotations.contains(target)){
                console.log('clicked on ' + target.tagName);
                for(var i = 0; i < annotationElements.length; i++){
                    if(target.tagName === annotationElements[i] || annotationElements[i] === "all"){
                        annotatedItemsAux.push(getXPathForElement(target));
                        target.classList.add('selectedColor');
                        if(annotationId === "paragraphAnnotation"){
                            paragraphItemsXPathAux.push(getXPathForElement(target))
                        }
                    }
                }
            }
            event.stopPropagation()
            event.preventDefault()
            return false;
        }
    }, false);
}

function getSelectedText() {
    var text = "";
    if (typeof window.getSelection != "undefined") {
        text = window.getSelection().toString();
    } else if (typeof document.selection != "undefined" && document.selection.type == "Text") {
        text = document.selection.createRange().text;
    }
    return text;
}

function saveTextSelected() {
    var selectedText = getSelectedText();
    console.log(selectedText);
    if (selectedText && !annotatedItemsAux.includes(selectedText)) {
        annotatedItemsAux.push(selectedText);

        var newContent = document.createTextNode(selectedText + " ");
        var textSelectionDiv = document.getElementById("textSelectionDiv");
        textSelectionDiv.appendChild(newContent);
        textSelectionDiv.style.display = "block";
    }
    clearTextSelected();
}

function clearTextSelected() {
    if (window.getSelection) {
        if (window.getSelection().empty) {  // Chrome
            window.getSelection().empty();
        } else if (window.getSelection().removeAllRanges) {  // Firefox
            window.getSelection().removeAllRanges();
        }
    } else if (document.selection) {  // IE?
        document.selection.empty();
    }
}

function basicAnnotation(){
    var queryURL = "https://dbpedia.org/sparql";

    var propertyName1 = "name";
    var propertyName1ES = "nombre";
    var propertyURL1 = "http://xmlns.com/foaf/0.1/name";
    var property1 = {name : propertyName1, nameES : propertyName1ES, URL: propertyURL1};
    basicAnnotationByQueryAndProperty(queryURL, property1);

    var propertyName2 = "summary";
    var propertyName2ES = "resumen";
    var propertyURL2 = "http://dbpedia.org/ontology/abstract";
    var property2 = {name : propertyName2, nameES : propertyName2ES, URL: propertyURL2};
    basicAnnotationByQueryAndProperty(queryURL, property2);

    var propertyName3 = "birth date";
    var propertyName3ES = "fecha nacimiento";
    var propertyURL3 = "http://dbpedia.org/ontology/birthDate";
    var property3 = {name : propertyName3, nameES : propertyName3ES, URL: propertyURL3};
    basicAnnotationByQueryAndProperty(queryURL, property3);

    var propertyName4 = "death date";
    var propertyName4ES = "fecha fallecimiento";
    var propertyURL4 = "http://dbpedia.org/ontology/deathDate";
    var property4 = {name : propertyName4, nameES : propertyName4ES, URL: propertyURL4};
    basicAnnotationByQueryAndProperty(queryURL, property4);


}

function basicAnnotationByQueryAndProperty(queryURL, property){

    var exists = false;

    var annotationId = "textAnnotation";
    try{
        var items = JSON.parse(myStorage.getItem(localStoragePrefix + annotationId));
        if(Array.isArray(items) && items.length > 0){
            for(var i = 0; i < items.length; i++){
                if(items[i].name === property.name || items[i].name === property.nameES){
                    exists = true;
                }
            }
        }
    } catch(e){}

    if(!exists){
        var currentURL = window.location.hostname + window.location.pathname;
        var queryPart1 = encodeURIComponent([
            "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>",
            "SELECT distinct ?stripped_value",
            "WHERE {",
            "<http://"
        ].join(" "));

        var queryPart2 = encodeURIComponent([
            "> foaf:primaryTopic ?label.",
            "?label <" + property.URL + "> ?value",
            "FILTER (LANG(?value)='en')",
            "BIND (STR(?value)  AS ?stripped_value)",
            "} LIMIT 1"
        ].join(" "));

        var query = queryPart1 + currentURL + queryPart2;

        var queryUrl = queryURL+"?query="+ query +"&format=json";
        console.log("query: " + query);
        console.log("queryUrl: " + queryUrl);
        $.ajax({
            dataType: "jsonp",
            url: queryUrl,
            success: function( data ) {
                console.log(JSON.stringify(data));
                var results = data.results.bindings;
                if(results.length > 0) {
                    var res = results[0].stripped_value.value;
                    console.log("query result: " + res);

                    var annotationId = "textAnnotation";
                    var jsons = new Array();
                    try{
                        var items = JSON.parse(myStorage.getItem(localStoragePrefix + annotationId));
                        if(Array.isArray(items) && items.length > 0){
                            jsons = items;
                        }
                    } catch(e){}
                    var newItem = {name: property.name, value: [res]};
                    jsons.push(newItem);
                    console.log("saved annotations: " + JSON.stringify(jsons));
                    myStorage.setItem(localStoragePrefix + annotationId, JSON.stringify(jsons));
                    //myStorage.setItem(localStoragePrefix + propertyName.name, res);

                    for(var i = 0; i < operations.length; i++){
                        if(operations[i].hasMenu){
                            updateSubmenuForOperationAndAnnotations("menu-" + operations[i].id, operations[i], operations[i].annotations);
                        }
                    }

                    for(var j = 0; j < annotations.length; j++){
                        updateSubmenuForAnnotations("menu-" + annotations[j].id, annotations[j].id);
                    }
                }
            },
            error: function(data) {
                console.log(JSON.stringify(data));
            }
        });
    }
}

function createOperationsMenu(){
    var divButtons = document.createElement('div')
    divButtons.id = "menu-operations"
    divButtons.style = "z-index: 100; padding: 10px; border: 2px solid black; display: none; background-color: white"


    var i = document.createElement('i');
    i.className = 'fa fa-close'
    i.style = "position: absolute; right: 1%; top: 31%; z-index: 100;"
    i.addEventListener("click", function(){
        closeOperationsMenu();
    }, false);
    divButtons.appendChild(i);

    for(var operationsIndex = 0; operationsIndex < operations.length; operationsIndex++){
        var a = document.createElement('a');
        a.id = operations[operationsIndex].id;
        //a.href = '';
        a.text = operations[operationsIndex].name;
        operations[operationsIndex].configureOperation();
        if(operations[operationsIndex].hasMenu){
            a.addEventListener("click", operations[operationsIndex].openMenu, false);
        } else {
            a.addEventListener("click", operations[operationsIndex].startOperation, false);
        }
        divButtons.appendChild(a);

        if(operations[operationsIndex].activable){
            var input = document.createElement('input');
            input.type = 'checkbox';
            input.id = operations[operationsIndex].id + "Input";
            input.value = operations[operationsIndex].id + "Input";
            input.checked = operations[operationsIndex].active;
            input.style.setProperty("margin-left", "5px");
            if(operations[operationsIndex].active){
                a.style.setProperty("pointer-events", "all");
            } else {
                a.style.setProperty("pointer-events", "none");
            }
            //TODO: Refactor for reusability
            input.addEventListener("change", function(){
                for(var operationsI = 0; operationsI < operations.length; operationsI++){
                    if(operations[operationsI].id === this.id.split("Input").join("")){
                        if(!this.checked){
                            operations[operationsI].active = false;
                            myStorage.setItem(localStoragePrefix + operations[operationsI].id + "Active", operations[operationsI].active);
                            document.getElementById(operations[operationsI].id).style.setProperty("pointer-events", "none");
                            if(this.id.split("Input").join("") === "readAloud"){
                                toggleReadAloud();
                            } else if(this.id.split("Input").join("") === "videos"){
                                toggleYoutubeVideos();
                            } else if(this.id.split("Input").join("") === "breadcrumb"){
                                toggleBreadcrumb();
                            } else if(this.id.split("Input").join("") === "hide"){
                                toggleHiddenSections();
                            }
                        } else {
                            operations[operationsI].active = true;
                            myStorage.setItem(localStoragePrefix + operations[operationsI].id + "Active", operations[operationsI].active);
                            document.getElementById(operations[operationsI].id).style.setProperty("pointer-events", "all");
                            if(this.id.split("Input").join("") === "readAloud"){
                                toggleReadAloud();
                            } else if(this.id.split("Input").join("") === "videos"){
                                toggleYoutubeVideos();
                            } else if(this.id.split("Input").join("") === "breadcrumb"){
                                toggleBreadcrumb();
                            } else if(this.id.split("Input").join("") === "hide"){
                                toggleHiddenSections();
                            }
                        }
                    }
                }
            }, false);
            divButtons.appendChild(input);
        }
        divButtons.appendChild(document.createElement('br'));
    }
    document.getElementById("div-webaugmentation").appendChild(divButtons);

    /*  createReadMenu();
        createGoToMenu();*/
    createSpeakableAnnotations();
    //readWelcome();
    setTimeout(function() { say(); }, 1000);

    //TODO: refactor Toggle some operations
    toggleYoutubeVideos();
    toggleReadAloud();
    toggleBreadcrumb();
    toggleHiddenSections();
}


function say() {
    //speechSynthesis.speak(new SpeechSynthesisUtterance(txt));
    readWelcome();
}


function createCommandsMenu(){
    var divCommandsMenu = document.createElement("div")
    divCommandsMenu.id = "menu-commands";
    divCommandsMenu.style = "z-index: 100; padding: 10px; border: 2px solid black; display: none; background-color: white"

    var i = document.createElement('i');
    i.className = 'fa fa-close'
    i.style = "position: absolute; right: 1%; top: 31%; z-index: 100;"
    i.addEventListener("click", function(){
        closeCommandsMenu();
    }, false);
    divCommandsMenu.appendChild(i);

    for(var index = 0; index < operations.length; index++){
        var a1 = document.createElement('a');
        a1.id = operations[index].id + "Edit";
        if(!spanishDomain){
            a1.text = "'" + operations[index].name + "' command (" + operations[index].voiceCommand + ") ";
        } else {
            a1.text = "Comando '" + operations[index].name + "' (" + operations[index].voiceCommand + ") ";
        }
        a1.addEventListener("click", function(){
            for(var index = 0; index < operations.length; index++){
                if(operations[index].id === this.id.split("Edit").join("")){
                    var result;
                    if(!spanishDomain){
                        result = prompt("New command value for '" + operations[index].name + "' command (must be recognisable by voice)", operations[index].voiceCommand);;
                    } else {
                        result = prompt("Nuevo comando para '" + operations[index].name + "' (tiene que ser reconocible por voz)", operations[index].voiceCommand);;
                    }
                    if(result !== null){
                        operations[index].voiceCommand = result.toLowerCase();
                        myStorage.setItem(localStoragePrefix + operations[index].id, result.toLowerCase());
                        console.log(result);
                    }
                }
            }
        }, false);
        var a1i = document.createElement('i');
        a1i.className = 'fa fa-edit'
        a1.appendChild(a1i);
        divCommandsMenu.appendChild(a1);
        divCommandsMenu.appendChild(document.createElement('br'));
    }

    document.getElementById("div-webaugmentation").appendChild(divCommandsMenu);
}


function createSubmenuForOperationAndAnnotations(menuId, operationForSubmenu){

    var annotationsForSubmenu = operationForSubmenu.annotations;
    var divSubMenu = document.createElement("div");
    divSubMenu.id = menuId;
    divSubMenu.style = "z-index: 100; padding: 10px; border: 2px solid black; display: none; background-color: white";

    var i = document.createElement('i');
    i.className = 'fa fa-close';
    i.style = "position: absolute; right: 1%; top: 31%; z-index: 100;";
    i.addEventListener("click", closeSubmenu, false);
    i.menuId = menuId;
    divSubMenu.appendChild(i);

    try{
        for(var annotationsForSubmenuIndex = 0; annotationsForSubmenuIndex < annotationsForSubmenu.length; annotationsForSubmenuIndex++){
            for(var annotationsIndex = 0; annotationsIndex < annotations.length; annotationsIndex++){
                if(annotationsForSubmenu[annotationsForSubmenuIndex] === annotations[annotationsIndex].id){
                    var annotationItems = myStorage.getItem(localStoragePrefix + annotations[annotationsIndex].id);
                    annotations[annotationsIndex].items = JSON.parse(annotationItems);
                    var items = annotations[annotationsIndex].items
                    for(var sectionsIndex = 0; sectionsIndex < items.length; sectionsIndex ++){
                        var a1 = document.createElement('a');
                        a1.text = items[sectionsIndex].name
                        var sectionName = items[sectionsIndex].name
                        a1.addEventListener("click", operationForSubmenu.startOperation, false);
                        a1.sectionName = items[sectionsIndex].name;
                        a1.operation = operationForSubmenu;
                        divSubMenu.appendChild(a1);
                        divSubMenu.appendChild(document.createElement('br'));
                    }
                }
            }
        }
    } catch(e){}

    document.getElementById("div-webaugmentation").appendChild(divSubMenu);
}

function updateSubmenuForOperationAndAnnotations(menuId, operationForSubmenu, annotationsForSubmenu){

    var divSubMenu = document.getElementById(menuId);
    while (divSubMenu.firstChild) {
        divSubMenu.removeChild(divSubMenu.firstChild);
    }
    //divSubMenu.innerHTML = "";


    var i = document.createElement('i');
    i.className = 'fa fa-close';
    i.style = "position: absolute; right: 1%; top: 31%; z-index: 100;";
    i.addEventListener("click", closeSubmenu, false);
    i.menuId = menuId;
    divSubMenu.appendChild(i);

    try{
        for(var annotationsForSubmenuIndex = 0; annotationsForSubmenuIndex < annotationsForSubmenu.length; annotationsForSubmenuIndex++){
            for(var annotationsIndex = 0; annotationsIndex < annotations.length; annotationsIndex++){
                if(annotationsForSubmenu[annotationsForSubmenuIndex] === annotations[annotationsIndex].id){
                    var annotationItems = myStorage.getItem(localStoragePrefix + annotations[annotationsIndex].id);
                    annotations[annotationsIndex].items = JSON.parse(annotationItems);
                    var items = annotations[annotationsIndex].items
                    for(var sectionsIndex = 0; sectionsIndex < items.length; sectionsIndex ++){
                        var a1 = document.createElement('a');
                        a1.text = items[sectionsIndex].name
                        var sectionName = items[sectionsIndex].name
                        a1.addEventListener("click", operationForSubmenu.startOperation, false);
                        a1.sectionName = items[sectionsIndex].name;
                        a1.operation = operationForSubmenu;
                        divSubMenu.appendChild(a1);
                        divSubMenu.appendChild(document.createElement('br'));
                    }
                }
            }
        }
    } catch(e){}

    document.getElementById("div-webaugmentation").appendChild(divSubMenu);
}

function createSubmenuForAnnotations(menuId, annotationId){

    var divSubMenu = document.createElement("div");
    divSubMenu.id = menuId;
    divSubMenu.style = "z-index: 100; padding: 10px; border: 2px solid black; display: none; background-color: white";

    var i = document.createElement('i');
    i.className = 'fa fa-close';
    i.style = "position: absolute; right: 1%; top: 31%; z-index: 100;";
    i.addEventListener("click", closeSubmenu, false);
    i.menuId = menuId;
    divSubMenu.appendChild(i);

    try{
        for(var annotationsIndex = 0; annotationsIndex < annotations.length; annotationsIndex++){
            if(annotationId === annotations[annotationsIndex].id){
                var annotationItems = myStorage.getItem(localStoragePrefix + annotations[annotationsIndex].id);
                annotations[annotationsIndex].items = JSON.parse(annotationItems);
                var items = annotations[annotationsIndex].items
                for(var sectionsIndex = 0; sectionsIndex < items.length; sectionsIndex ++){
                    var label = document.createElement('label');
                    label.innerText = items[sectionsIndex].name;

                    divSubMenu.appendChild(label);

                    var a2b = document.createElement('a');
                    a2b.id = annotations[annotationsIndex].id + "editSection" + items[sectionsIndex].name;
                    a2b.className = "icon";
                    if(!spanishDomain){
                        a2b.title = "Edit" + items[sectionsIndex].name;
                    } else {
                        a2b.title = "Editar" + items[sectionsIndex].name;
                    }
                    a2b.addEventListener("click", function(){
                        for(var i = 0; i < annotations.length; i++){
                            if(annotations[i].id === this.id.split("editSection")[0]){
                                annotations[i].edit(this.id.split("editSection")[1]);
                            }
                        }
                    }, false);
                    var a2bIcon = document.createElement("i");
                    a2bIcon.className = "fa fa-edit";
                    a2bIcon.style = "margin-left: 8px";
                    a2b.appendChild(a2bIcon);
                    divSubMenu.appendChild(a2b);

                    var a2bTrash = document.createElement('a');
                    a2bTrash.id = annotations[annotationsIndex].id + "resetSection" + items[sectionsIndex].name;
                    a2bTrash.className = "icon";
                    a2bTrash.title = "Reset" + annotations[annotationsIndex].name;
                    a2bTrash.addEventListener("click", function(){
                        var confirmText = "";
                        if(!spanishDomain){
                            confirmText = "Are you sure to delete this section?";
                        } else {
                            confirmText = "¿Estás seguro de borrar esta sección?";
                        }
                        if(confirm(confirmText)){
                            for(var i = 0; i < annotations.length; i++){
                                if(annotations[i].id === this.id.split("resetSection")[0]){
                                    annotations[i].reset(this.id.split("resetSection")[1]);
                                }
                            }
                        }
                    }, false);
                    var a2bTrashIcon = document.createElement("i");
                    a2bTrashIcon.className = "fa fa-trash-o";
                    a2bTrashIcon.style = "margin-left: 8px";
                    a2bTrash.appendChild(a2bTrashIcon);
                    divSubMenu.appendChild(a2bTrash);

                    divSubMenu.appendChild(document.createElement('br'));
                }
            }
        }
    } catch(e){}

    document.getElementById("div-intermediary").appendChild(divSubMenu);
}

function updateSubmenuForAnnotations(menuId, annotationsId){

    var divSubMenu = document.getElementById(menuId);
    while (divSubMenu.firstChild) {
        divSubMenu.removeChild(divSubMenu.firstChild);
    }
    //divSubMenu.innerHTML = "";


    var i = document.createElement('i');
    i.className = 'fa fa-close';
    i.style = "position: absolute; right: 1%; top: 31%; z-index: 100;";
    i.addEventListener("click", closeSubmenu, false);
    i.menuId = menuId;
    divSubMenu.appendChild(i);

    try{
        for(var annotationsIndex = 0; annotationsIndex < annotations.length; annotationsIndex++){
            if(annotationsId === annotations[annotationsIndex].id){
                var annotationItems = myStorage.getItem(localStoragePrefix + annotations[annotationsIndex].id);
                annotations[annotationsIndex].items = JSON.parse(annotationItems);
                var items = annotations[annotationsIndex].items
                for(var sectionsIndex = 0; sectionsIndex < items.length; sectionsIndex ++){
                    var label = document.createElement('label');
                    label.innerText = items[sectionsIndex].name;

                    divSubMenu.appendChild(label);

                    var a2b = document.createElement('a');
                    a2b.id = annotations[annotationsIndex].id + "editSection" + items[sectionsIndex].name;
                    a2b.className = "icon";
                    if(!spanishDomain){
                        a2b.title = "Edit" + items[sectionsIndex].name;
                    } else {
                        a2b.title = "Editar" + items[sectionsIndex].name;
                    }
                    a2b.addEventListener("click", function(){
                        for(var i = 0; i < annotations.length; i++){
                            if(annotations[i].id === this.id.split("editSection")[0]){
                                annotations[i].edit(this.id.split("editSection")[1]);
                            }
                        }
                    }, false);
                    var a2bIcon = document.createElement("i");
                    a2bIcon.className = "fa fa-edit";
                    a2bIcon.style = "margin-left: 8px";
                    a2b.appendChild(a2bIcon);
                    divSubMenu.appendChild(a2b);

                    var a2bTrash = document.createElement('a');
                    a2bTrash.id = annotations[annotationsIndex].id + "resetSection" + items[sectionsIndex].name;
                    a2bTrash.className = "icon";
                    a2bTrash.title = "Reset" + annotations[annotationsIndex].name;
                    a2bTrash.addEventListener("click", function(){
                        var confirmText = "";
                        if(!spanishDomain){
                            confirmText = "Are you sure to delete this section?";
                        } else {
                            confirmText = "¿Estás seguro de borrar esta sección?";
                        }
                        if(confirm(confirmText)){
                            for(var i = 0; i < annotations.length; i++){
                                if(annotations[i].id === this.id.split("resetSection")[0]){
                                    annotations[i].reset(this.id.split("resetSection")[1]);
                                }
                            }
                        }
                    }, false);
                    var a2bTrashIcon = document.createElement("i");
                    a2bTrashIcon.className = "fa fa-trash-o";
                    a2bTrashIcon.style = "margin-left: 8px";
                    a2bTrash.appendChild(a2bTrashIcon);
                    divSubMenu.appendChild(a2bTrash);

                    divSubMenu.appendChild(document.createElement('br'));

                    divSubMenu.appendChild(document.createElement('br'));
                }
            }
        }
    } catch(e){}

    document.getElementById("div-intermediary").appendChild(divSubMenu);
}

function showSubmenu(id){
    var divSubMenu = document.getElementById(id);
    if(divSubMenu !== null){
        var x = divSubMenu.style;
        x.display = "block";
    }
}

function closeSubmenu(menuId){
    var menuIdToClose = menuId;
    if(typeof menuId.parentElement === 'undefined' && typeof menuId.currentTarget !== 'undefined'){
        menuIdToClose = menuId.currentTarget.menuId
    }
    var divSubMenu = document.getElementById(menuIdToClose);
    if(divSubMenu !== null){
        var x = divSubMenu.style;
        x.display = "none";
    }
}


function readWelcome(){
    var readContent = "";
    if(!spanishDomain){
        readContent = "Welcome to " + document.title + "! The voice commands available are: ";
        for(var i = 0; i < operations.length; i++){
            readContent += operations[i].voiceCommand + ", ";
        }
        readContent += listOperationsCommand + ", " + listSectionsCommand + ", " + welcomeCommand + ", " + stopListeningCommand + ", " + changeCommand + ", "
            + activateCommand + ", " + deactivateCommand + ", " + readFasterCommand + ", " + readSlowerCommand + ". ";
        readContent += sectionsToString();
    } else {
        readContent = "¡Bienvenido a " + document.title + "! Los comandos de voz disponibles son: ";
        for(var j = 0; j < operations.length; j++){
            readContent += operations[j].voiceCommand + ", ";
        }
        readContent += listOperationsCommandES + ", " + listSectionsCommandES + ", " + welcomeCommandES + ", " + stopListeningCommandES + ", " + changeCommandES + ", "
            + activateCommandES + ", " + deactivateCommandES + ", " + readFasterCommandES + ", " + readSlowerCommandES + ". ";
        readContent += sectionsToString();
    }


    //TODO: explain and add loadAnnotations operation
    Read(readContent);
}

function readOperations(){
    var readContent = "";
    if(!spanishDomain){
        readContent = "The voice commands available are: ";
        for(var i = 0; i < operations.length; i++){
            readContent += operations[i].voiceCommand + ", ";
        }
        readContent += listOperationsCommand + ", " + listSectionsCommand + ", " + welcomeCommand + ", " + stopListeningCommand + ", " + changeCommand + ", "
            + activateCommand + ", " + deactivateCommand + ". ";
        readContent += sectionsToString();
    } else {
        readContent = "Los comandos de voz disponibles son: ";
        for(var j = 0; j < operations.length; j++){
            readContent += operations[j].voiceCommand + ", ";
        }
        readContent += listOperationsCommandES + ", " + listSectionsCommandES + ", " + welcomeCommandES + ", " + stopListeningCommandES + ", " + changeCommandES + ", "
            + activateCommandES + ", " + deactivateCommandES + ". ";
        readContent += sectionsToString();
    }
    Read(readContent);
}

function readSections(){
    var readContent = sectionsToString()

    Read(readContent);
}

function sectionsToString(){

    var readContent = "";
    var names = [];
    for(var i = 0; i < operations.length; i++){
        try{
            for(var j = 0; j < operations[i].annotations.length; j++){
                var items = JSON.parse(myStorage.getItem(localStoragePrefix + operations[i].annotations[j]));
                for(var k = 0; k < items.length; k++){
                    if(!names.includes(items[k].name)){
                        names.push(items[k].name);
                    }
                }
            }
        } catch(e){}
    }

    if(names.length > 0){
        if(!spanishDomain){
            readContent += "The sections of the website are: ";
        } else {
            readContent += "Las secciones de esta web son: ";
        }
    }

    for(var index = 0; index < names.length; index++){
        if(index > 0){
            readContent += ", ";
        }
        readContent += names[index];
    }

    if(!spanishDomain){
        readContent += ". You can dowload more annotations using the voice command: " + loadAnnotationsCommand;
    } else {
        readContent += ". Puedes descargar más anotaciones usando el comando de voz: " + loadAnnotationsCommandES;
    }

    return readContent;
}

function readSectionsText(){

    var readAloudPosition = 0;
    var lastAnnotationName = "";
    for(var i = 0; i < operations.length; i++){
        if(operations[i].id == "readAloud"){
            readAloudPosition = i;
            try{
                for(var j = 0; j < operations[i].annotations.length; j++){
                    var items = JSON.parse(myStorage.getItem(localStoragePrefix + operations[i].annotations[j]));
                    for(var k = 0; k < items.length; k++){
                        if(k == items.length -1){
                            lastAnnotationName = items[k].name;
                        }
                    }
                }
            } catch(e){
            }
        }
    }

    var readFirst = false;
    if (lastSectionRead == lastAnnotationName){
        readFirst = true;
    }

    readAllSections = setInterval(function(){
        //console.log("setInterval");
        //console.log("reading: " + reading);
        var error = false;
        try{
            //console.log("lastSectionRead: " + lastSectionRead);
            //console.log("lastAnnotationName: " + lastAnnotationName);
            if (lastSectionRead != lastAnnotationName || readFirst){
                if(!reading){
                    //console.log("readNextSectionText");
                    readNextSectionText();
                    readFirst = false;
                }
            } else {
                clearInterval(readAllSections);
                //console.log("clearInterval");
            }
        } catch(e){
            error = true;
            console.log(e);
        }

        if(error){
            try{
                clearInterval(readAllSections);
                //console.log("clearInterval");
            } catch (e2){
            }
        }

    } , 1000);
}

function readNextSectionText(){

    for(var i = 0; i < operations.length; i++){
        if(operations[i].id == "readAloud" && operations[i].active){

            try{
                for(var j = 0; j < operations[i].annotations.length; j++){
                    var items = JSON.parse(myStorage.getItem(localStoragePrefix + operations[i].annotations[j]));
                    for(var k = 0; k < items.length; k++){
                        var ok = false;
                        if(items[k].name == lastSectionRead){
                            k++;
                            if(k >= items.length){
                                k = 0;
                            }
                            ok = true;
                        } else if(lastSectionRead == ""){
                            k = 0;
                            ok = true;
                        }

                        if(ok){
                            var params = {};
                            var current = {};
                            params.currentTarget = current;
                            params.currentTarget.sectionName = items[k].name;
                            params.currentTarget.operation = operations[i];
                            operations[i].startOperation(params);
                            return;
                        }
                    }
                }
            } catch(e){}
        }
    }
}

function readPreviousSectionText(){

    for(var i = 0; i < operations.length; i++){
        if(operations[i].id == "readAloud" && operations[i].active){

            try{
                for(var j = 0; j < operations[i].annotations.length; j++){
                    var items = JSON.parse(myStorage.getItem(localStoragePrefix + operations[i].annotations[j]));
                    for(var k = 0; k < items.length; k++){
                        var ok = false;
                        if(items[k].name == lastSectionRead){
                            k--;
                            if(k < 0){
                                k = items.length -1;
                            }
                            ok = true;
                        } else if(lastSectionRead == ""){
                            k = 0;
                            ok = true;
                        }
                        if(ok){
                            var params = {};
                            var current = {};
                            params.currentTarget = current;
                            params.currentTarget.sectionName = items[k].name;
                            params.currentTarget.operation = operations[i];
                            operations[i].startOperation(params);
                            return;
                        }
                    }
                }
            } catch(e){}
        }
    }
}

function textToAudio(){
    createPlayButtons();

    var cancelfooter = document.createElement('div');
    cancelfooter.id = "cancel";
    var buttonStop = document.createElement('button');
    if(!spanishDomain){
        buttonStop.innerText = "Stop";
    } else {
        buttonStop.innerText = "Detener";
    }
    buttonStop.addEventListener('click', stopReading);
    buttonStop.style.height = "50px";
    buttonStop.style.fontSize = "25px";
    cancelfooter.appendChild(buttonStop);
    document.body.appendChild(cancelfooter);
    $('#cancel').css({
        'position': 'fixed',
        'left': '0',
        'bottom': '0',
        'width': '100%',
        'background-color': 'black',
        'color': 'white',
        'text-align': 'center',
        'visibility': 'hidden',
    });
}

function createPlayButtons(){
    $('p').each(function() {
        if($(this).parent().attr('role') != 'navigation'){
            var button = document.createElement('button');
            button.innerHTML = "&#9658;";
            button.value = $(this).prop('innerText');
            button.className = "readAloudButton";
            button.style.fontSize = "18px";
            button.addEventListener('click', function(){
                Read($(this).prop('value'));
            });
            $(this).append(button);
        }
    });
}

function toggleReadAloud(){
    var divsToHide = document.getElementsByClassName("readAloudButton");
    var readCommandActive;
    if(!document.getElementById("readAloudInput").checked){
        readCommandActive = false;
        document.getElementById("readAloud").style.setProperty("pointer-events", "none");
        for(var i = 0; i < divsToHide.length; i++){
            divsToHide[i].style.display = "none";
        }
    } else {
        readCommandActive = true;
        document.getElementById("readAloud").style.setProperty("pointer-events", "all");
        for(var i2 = 0; i2 < divsToHide.length; i2++){
            divsToHide[i2].style.display = "block";
        }
    }
    myStorage.setItem(localStoragePrefix + "readAloudActive", readCommandActive);
}

function resumeInfinity() {
    reading = true;
    window.speechSynthesis.pause();
    window.speechSynthesis.resume();
    timeoutResumeInfinity = setTimeout(resumeInfinity, 10000);
    $('#cancel').css('visibility', 'visible');
}

function Read(message){
    //console.log("Read function: " + message)
    window.speechSynthesis.cancel();
    clearTimeout(timeoutResumeInfinity);

    if(!document[hidden]){

        var reader = new SpeechSynthesisUtterance(message);
        reader.rate = readerRate;
        if(!spanishDomain){
            reader.lang = languageCodeSyntesis;
        } else {
            reader.lang = languageCodeSyntesisES;
        }
        reader.onstart = function(event) {
            resumeInfinity();
        };
        reader.onend = function(event) {
            clearTimeout(timeoutResumeInfinity);
            $('#cancel').css('visibility', 'hidden');
            setTimeout(function(){
                reading = false;
                if(recognitionActive){
                    recognition.start();
                }
            }, 1000);
        };

        try{
            reading = true;
            if(recognitionActive){
                recognition.abort();
            }
            window.speechSynthesis.speak(reader);
        } catch(e){
            stopReading();
        }
        if(window.speechSynthesis.speaking){
            $('#cancel').css('visibility', 'visible');
        } else {
            stopReading();
        }

    } else {
        console.log("Window tab is not focused, reading aloud not allowed");
    }
}

function readFaster(){
    //console.log(readerRate);
    //readerRate = parseFloat(readerRate);
    if(readerRate <= 9){
        readerRate = readerRate + 0.5;
        myStorage.setItem(localStoragePrefix + "readerRate", readerRate);

        if(!spanishDomain){
            Read("Read speed " + readerRate + " out of 10.");
        } else {
            Read("Velocidad de lectura " + readerRate + " sobre 10.");
        }
    } else {
        if(!spanishDomain){
            Read("Read speed at maximum level.")
        } else {
            Read("Velocidad de lectura al máximo.")
        }
    }
}

function readSlower(){
    //console.log(readerRate);
    //readerRate = parseFloat(readerRate);
    if(readerRate > 0.5){
        readerRate = readerRate - 0.5;
        myStorage.setItem(localStoragePrefix + "readerRate", readerRate);

        if(!spanishDomain){
            Read("Read speed " + readerRate + " out of 10.");
        } else {
            Read("Velocidad de lectura " + readerRate + " sobre 10.");
        }
    } else {
        if(!spanishDomain){
            Read("Read speed at minimum level.")
        } else {
            Read("Velocidad de lectura al mínimo.")
        }
    }
}

function stopReading(){
    window.speechSynthesis.cancel();
    clearTimeout(timeoutResumeInfinity);
    $('#cancel').css('visibility', 'hidden');

    try{
        clearInterval(readAllSections);
    } catch (e2){
    }
    setTimeout(function(){
        reading = false;

        if(recognitionActive){
            recognition.start();
        }
    }, 1000);
}

function KeyPress(e) {
    var evtobj = window.event? event : e

    // No mic tests
    /*if(evtobj.ctrlKey && evtobj.shiftKey){
        console.log("No mic tests");
        readSectionsText();
    }*/
    if(evtobj.keyCode == 32 && evtobj.ctrlKey && evtobj.shiftKey){
        if(!reading){
            readWelcome();
        }
    }
    else if (evtobj.keyCode == 32 && evtobj.ctrlKey){
        if(reading){
            stopReading();
        }
        else if(!recognitionActive){
            recognitionActive = true;
            recognition.start();
            var aToggleListening = document.getElementById("toggleListeningA");
            if(!spanishDomain){
                aToggleListening.text = 'Stop Listening';
            } else {
                aToggleListening.text = 'Desactivar comandos por voz';
            }
            //var inputVoiceCommands = document.getElementById("voiceCommandsInput");
            //inputVoiceCommands.checked = recognitionActive;
            var toggleListeningIcon = document.getElementById("toggleListeningIcon");
            toggleListeningIcon.style = "color:gray; margin-left: 8px";
            if(!spanishDomain){
                Read("Listening active, to stop listening use the " + stopListeningCommand + " voice command, which disables all voice commands.");
            } else {
                Read("Comandos por voz activos, para desactivarlos use el comando " + stopListeningCommand + ".");
            }
        }
        else {
            recognitionActive = false;
            recognition.abort();
            var aToggleListening2 = document.getElementById("toggleListeningA");
            if(!spanishDomain){
                aToggleListening2.text = 'Start Listening';
            } else {
                aToggleListening2.text = 'Activar comandos por voz';
            }
            //var inputVoiceCommands2 = document.getElementById("voiceCommandsInput");
            //inputVoiceCommands2.checked = recognitionActive;
            var toggleListeningIcon2 = document.getElementById("toggleListeningIcon");
            toggleListeningIcon2.style = "color:red; margin-left: 8px";
            if(!spanishDomain){
                Read("Listening stop, to start listening use the control and space keys, which enables all voice commands.");
            } else {
                Read("Comandos por voz desactivados, para activarlos use el comando " + stopListeningCommand + ".");
            }
        }

        myStorage.setItem("recognitionActive", recognitionActive);
    }
}

var commandListened;

// Speech recognition
function audioToText(){
    //headlines = document.getElementsByClassName("mw-headline")
    //sectionsNames = JSON.parse(myStorage.getItem(localStoragePrefix + "sectionsNames"));

    console.log("Configure speech recognition");

    updateGrammar();
    if(!spanishDomain){
        recognition.lang = languageCodeCommands;
    } else {
        recognition.lang = languageCodeCommandsES;
    }
    recognition.interimResults = false;
    recognition.continuous = true;

    recognition.onresult = event => {
        if(reading === false) {
            const speechToText = event.results[event.results.length -1][0].transcript.toLowerCase().trim();
            commandListened = speechToText;
            console.log(speechToText);
            if(!changeCommandInProcess1 && !changeCommandInProcess2){
                if(speechToText.includes(listOperationsCommand) || speechToText.includes(listOperationsCommandES)){
                    readOperations();
                }
                else if(speechToText.includes(welcomeCommand) || speechToText.includes(welcomeCommandES)){
                    readWelcome();
                }
                else if(speechToText.includes(listSectionsCommand) || speechToText.includes(listSectionCommand) ||
                        speechToText.includes(listSectionsCommandES) || speechToText.includes(listSectionCommandES)){
                    readSections();
                }
                else if(speechToText.includes(readSectionsCommand) || speechToText.includes(readSectionsCommandES)){
                    readSectionsText();
                }
                else if(speechToText.includes(readNextSectionCommand) || speechToText.includes(readNextSectionCommandES)){
                    readNextSectionText();
                }
                else if(speechToText.includes(readPreviousSectionCommand) || speechToText.includes(readPreviousSectionCommandES)){
                    readPreviousSectionText();
                }
                else if(speechToText.includes(readFasterCommand) || speechToText.includes(readFasterCommandES)){
                    readFaster();
                }
                else if(speechToText.includes(readSlowerCommand) || speechToText.includes(readSlowerCommandES)){
                    readSlower();
                }
                else if((speechToText.includes(activateCommand) && !speechToText.includes(deactivateCommand)) ||
                       (speechToText.includes(activateCommandES) && !speechToText.includes(deactivateCommandES))){
                    console.log("Activate operation: ");
                    for(var a = 0; a < operations.length; a++){
                        if((speechToText.includes(activateCommand + " " + operations[a].voiceCommand) ||
                            speechToText.includes(activateCommandES + " " + operations[a].voiceCommand)) && !operations[a].active){
                            console.log(operations[a].name);
                            var input = document.getElementById(operations[a].id + "Input");
                            input.checked = true;
                            var eventChange = new Event('change');
                            input.dispatchEvent(eventChange);
                            if(!spanishDomain){
                                Read("Operation " + operations[a].voiceCommand + " activated.");
                            } else {
                                Read("Operación " + operations[a].voiceCommand + " activada.");
                            }
                        }
                    }
                }
                else if(speechToText.includes(deactivateCommand) || speechToText.includes(deactivateCommandES)){
                    console.log("Deactivate operation: ");
                    for(var b = 0; b < operations.length; b++){
                        if((speechToText.includes(deactivateCommand + " " + operations[b].voiceCommand) ||
                            speechToText.includes(deactivateCommandES + " " + operations[b].voiceCommand)) && operations[b].active){
                            console.log(operations[b].name);
                            var input2 = document.getElementById(operations[b].id + "Input");
                            input2.checked = false;
                            var eventChange2 = new Event('change');
                            input2.dispatchEvent(eventChange2);
                            if(!spanishDomain){
                                Read("Operation " + operations[b].voiceCommand + " deactivated.");
                            } else {
                                Read("Operación " + operations[b].voiceCommand + " desactivada.");
                            }
                        }
                    }
                }
                else if(speechToText.includes(loadAnnotationsCommand) || speechToText.includes(loadAnnotationCommand) ||
                        speechToText.includes(loadAnnotationsCommandES) || speechToText.includes(loadAnnotationCommandES)){
                    loadAnnotationsFromServerByVoice();
                }
                else if(speechToText.includes(rateCommand)){
                    var rating = 0;
                    if(speechToText.includes("one") || speechToText.includes("uno") || speechToText.includes("1")){
                       rating = 1;
                    } else if(speechToText.includes("two") || speechToText.includes("dos") || speechToText.includes("2")){
                       rating = 2;
                    } else if(speechToText.includes("three") || speechToText.includes("tres") || speechToText.includes("3")){
                       rating = 3;
                    } else if(speechToText.includes("four") || speechToText.includes("for") || speechToText.includes("cuatro") || speechToText.includes("4")){
                       rating = 4;
                    } else if(speechToText.includes("five") || speechToText.includes("cinco") || speechToText.includes("5")){
                       rating = 5;
                    }

                    var annotationTitle = myStorage.getItem(localStoragePrefix + "annotationTitle");
                    if(annotationTitle != null && typeof annotationTitle != 'undefined' && annotationTitle.length > 0){
                        if(rating > 0){
                            saveRatingsOfAnnotationInServer(rating, annotationTitle);
                            //TODO: check if an error occurred
                            if(!spanishDomain){
                                Read("Score saved to annotations: " + annotationTitle + ".");
                            } else {
                                Read("Valoración guardada en anotación: " + annotationTitle + ".");
                            }
                        } else {
                            if(!spanishDomain){
                                Read("Score should be from 1 to 5.");
                            } else {
                                Read("La valoración debe ser entre 1 y 5.");
                            }
                        }
                    } else {
                        if(!spanishDomain){
                            Read("You need to load annotations first using the voice command: " + loadAnnotationsCommand + ".");
                        } else {
                            Read("Necesitar cargar las anotaciones usando el comando de voz: " + loadAnnotationsCommandES + ".");
                        }
                    }
                }
                else if(speechToText.includes(changeCommand) || speechToText.includes(changeCommandES)){
                    console.log("changeCommandInProcess = true")
                    changeCommandInProcess1 = true;
                    if(!spanishDomain){
                        Read(changeCommandQuestion + "?");
                    } else {
                        Read(changeCommandQuestionES + "?");
                    }
                }
                else if(speechToText.includes(stopListeningCommand) || speechToText.includes(stopListeningCommandES)){
                    if(recognitionActive){
                        console.log("recognition deactivated")
                        recognitionActive = false;
                        recognition.abort();
                    }
                    if(!spanishDomain){
                        document.getElementById("toggleListeningA").text = "Start Listening";
                        document.getElementById("toggleListeningIcon").style = "color:red";
                        Read("Listening stopped, to start listening use control and space keys.");
                    } else {
                        document.getElementById("toggleListeningA").text = "Activar comandos por voz";
                        document.getElementById("toggleListeningIcon").style = "color:red";
                        Read("Comandos desactivados, para activar comandos por voz use las teclas control más espacio.");
                    }
                } else {
                    for(var i = 0; i < operations.length; i++){
                        if(speechToText.startsWith(operations[i].voiceCommand) && operations[i].voiceCommand.length > 0){
                            if(operations[i].active){
                                try{
                                    if(operations[i].annotations.length > 0) {
                                        for(var j = 0; j < operations[i].annotations.length; j++){
                                            var items = JSON.parse(myStorage.getItem(localStoragePrefix + operations[i].annotations[j]));
                                            for(var k = 0; k < items.length; k++){
                                                var cleanSpeechText = speechToText.normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^\w\s]/gi, '').replace(/\s+/g,' ').trim().toLowerCase();
                                                var cleanSection = items[k].name.normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^\w\s]/gi, '').replace(/\s+/g,' ').trim().toLowerCase();
                                                if(cleanSpeechText.includes(operations[i].voiceCommand + " " + cleanSection)){
                                                    var params = {};
                                                    var current = {};
                                                    params.currentTarget = current;
                                                    params.currentTarget.sectionName = items[k].name;
                                                    params.currentTarget.operation = operations[i];
                                                    operations[i].startOperation(params);
                                                    return;
                                                }
                                            }
                                        }
                                    } else {
                                        operations[i].startOperation();
                                        return;
                                    }
                                }catch(e){}
                            } else {
                                if(!spanishDomain){
                                    Read("Operation " + operations[i].voiceCommand + " is not activated, please activate using the voice command: " + activateCommand + " " + operations[i].voiceCommand + ".");
                                } else {
                                    Read("Operación " + operations[i].voiceCommand + " está desactivada, por favor actívala usando el comando de voz: " + activateCommandES + " " + operations[i].voiceCommand + ".");
                                }
                                return;
                            }
                        }
                    }
                    if(recognitionFailedFirstTime){
                        recognitionFailedFirstTime = false;
                        if(!spanishDomain){
                            Read(recognitionFailedText + " You can use: " + listOperationsCommand + " to know which operations are available and: "
                             + listSectionsCommand + " to know which sections can be read aloud.");
                        } else {
                            Read(recognitionFailedTextES + " Puedes usar: " + listOperationsCommandES + " para saber que operaciones están disponibles y: "
                             + listSectionsCommandES + " para saber qué secciones se pueden leer en voz alta.");
                        }
                    } else {
                        if(!spanishDomain){
                            Read(recognitionFailedText);
                        } else {
                            Read(recognitionFailedTextES);
                        }
                    }
                }
            } else {
                if(changeCommandInProcess1){
                    //Command change in process
                    if(!speechToText.includes(changeCommandQuestion) && !speechToText.includes(newCommandQuestion) &&
                       !speechToText.includes(changeCommandQuestionES) && !speechToText.includes(newCommandQuestionES)){
                        if(speechToText.toLowerCase() == cancelCommand || speechToText.toLowerCase() == cancelCommandES) {
                            console.log("Cancel change of command")
                            changeCommandInProcess1 = false;
                            changeCommandInProcess2 = false;
                            return;
                        }
                        for(var opIndex = 0; opIndex < operations.length; opIndex++){
                            if(speechToText.includes(operations[opIndex].voiceCommand)){

                                if(!spanishDomain){
                                    Read(newCommandQuestion + "?");
                                } else {
                                    Read(newCommandQuestionES + "");
                                }
                                newCommandString = speechToText.toLowerCase();
                                operationToChange = operations[opIndex];
                                changeCommandInProcess1 = false;
                                changeCommandInProcess2 = true;
                                return;
                            }
                        }

                        if(!spanishDomain){
                            Read(speechToText + " is not an existing command. Try again.");
                        } else {
                            Read(speechToText + " no es un comando. Inténtelo de nuevo.");
                        }
                    }
                } else if(changeCommandInProcess2){
                    //Command change in process
                    if(!speechToText.includes(changeCommandQuestion) && !speechToText.includes(newCommandQuestion) &&
                      !speechToText.includes(changeCommandQuestionES) && !speechToText.includes(newCommandQuestionES)){
                        if(speechToText.toLowerCase() == cancelCommand) {
                            console.log("Cancel change of command")
                            changeCommandInProcess1 = false;
                            changeCommandInProcess2 = false;
                        } else {
                            if(!spanishDomain){
                                Read(speechToText + " is the new command");
                            } else {
                                Read(speechToText + " es el nuevo comando");
                            }
                            myStorage.setItem(localStoragePrefix + operationToChange.id, speechToText.toLowerCase());
                            operationToChange.voiceCommand = speechToText.toLowerCase();
                            //console.log("new variable value " + eval(camelize(newCommandString) + "Command"))
                            changeCommandInProcess1 = false;
                            changeCommandInProcess2 = false;
                        }
                    }
                }
            }
        }
    }

    recognition.onspeechend = function() {
        console.log("onspeechend");
        /*setTimeout(function(){
            if(recognitionActive && !reading){
                console.log("recognition reset");
                recognition.start();
            }
        }, 1000);*/
    }

    recognition.onend = function() {
        console.log("onend");
        recognition.stop();
        setTimeout(function(){
            if(recognitionActive && !reading){
                console.log("recognition reset");
                recognition.start();
            }
        }, 100);
    }

    recognition.onerror = function(event) {
        console.log("onerror");
        console.log('Speech recognition error detected: ' + event.error);
        event.preventDefault();
        return false;
    }

    recognition.onstart = function() {
        console.log("onstart");
    }

    if(myStorage.getItem("recognitionActive") !== null){
        recognitionActive = (myStorage.getItem("recognitionActive") == 'true')
    } else {
        myStorage.setItem("recognitionActive", recognitionActive);
    }

    if(document[hidden]){
        recognitionActive = false;
        //myStorage.setItem("recognitionActive", recognitionActive);

        console.log("Window tab is not focused, listening not allowed");
    }

    //setInterval(function(){
        if(recognitionActive && !reading){
            try{
                recognitionActive = true;
                recognition.start();
                console.log("recognition activated")
            } catch(e){

            }
        }
    //}, 1000);
}


function updateGrammar(){

    var commandsGrammar, commandsAux = [], grammar;
    if(!spanishDomain){
        commandsGrammar = [ 'increase', 'magnify', 'read', 'play', 'font', 'size', 'decrease', 'reduce', 'stop', 'listening', 'score', 'one', 'two', 'three', 'four', 'five' ];
        commandsAux = [];
        for(var i = 0; i < operations.length; i++){
            //TODO: add operation + annotations names to grammar
            /*if(operations[i].voiceCommand === "read" || operations[i].voiceCommand === "go to"){
            for(var j = 0; j < sectionsNames.length; j++){
                commandsAux.push(operations[i] + " " + sectionsNames[j].toLowerCase())
            }
        } else {*/
            commandsAux.push(operations[i].voiceCommand)
            //}
        }
    } else {
        commandsGrammar = [ 'aumentar', 'incrementar', 'leer', 'play', 'letra', 'tamaño', 'decrementar', 'reducir', 'detener', 'activar', 'desactivar', 'valoración', 'uno', 'dos', 'tres', 'cuatro', 'cinco' ];
        commandsAux = [];
        for(var j = 0; j < operations.length; j++){
            //TODO: add operation + annotations names to grammar
            /*if(operations[i].voiceCommand === "read" || operations[i].voiceCommand === "go to"){
            for(var j = 0; j < sectionsNames.length; j++){
                commandsAux.push(operations[i] + " " + sectionsNames[j].toLowerCase())
            }
        } else {*/
            commandsAux.push(operations[j].voiceCommand)
            //}
        }
    }

    grammar = '#JSGF V1.0; grammar commands; public <command> = ' + commandsGrammar.concat(commandsAux).join(' | ') + ' ;';
    console.log("grammar: " + grammar);
    var speechRecognitionList = new SpeechGrammarList();
    speechRecognitionList.addFromString(grammar, 1);
    recognition.grammars = speechRecognitionList;
}


function camelize(str) {
  return str.replace(/(?:^\w|[A-Z]|\b\w|\s+)/g, function(match, index) {
    if (+match === 0) return ""; // or if (/\s+/.test(match)) for white spaces
    return index == 0 ? match.toLowerCase() : match.toUpperCase();
  });
}


// Youtube videos
function youtubeVideos(){
    //videoRequest($("#firstHeading").prop('innerText'));
    videoRequest(document.title);
}

function videoRequest(searchTerm) {
    var url = 'https://www.googleapis.com/youtube/v3/search';
    var params = {
        part: 'snippet',
        //key: 'AIzaSyBB9Vs9M1WcozRTjf9rGBU-M-HEpGYGXv8',
        key: 'AIzaSyA9c14XqejmcLW_KMVlSZZngrPfyF3X5rY',
        type: 'video',
        maxResults: 6,
        q: searchTerm
    };

    $.getJSON(url, params, showResults);
}

function showResults(results) {
    var html = "";
    var entries = results.items;
    var content = document.createElement('div');

    $.each(entries, function (index, value) {
        var videoId = value.id.videoId;
        var vid = '<iframe width="380" height="200" src="https://www.youtube.com/embed/'+videoId
        +'" frameborder="1" margin="5px" padding="5px" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>';
        content.innerHTML += vid;
    });

    //$('.mw-parser-output').append("<div id='youtubeVideos' style='display: block'><br><h2><span class='mw-headline' id='Youtube_videos'>Youtube videos</span></h2></div>")

    var youtubeVideoContent = document.createElement("DIV");
    if(!spanishDomain){
        youtubeVideoContent.innerHTML = "<div id='youtubeVideos' style='display: block'><br><h2><span class='mw-headline' id='Youtube_videos'>Youtube videos</span></h2></div>";
    } else {
        youtubeVideoContent.innerHTML = "<div id='youtubeVideos' style='display: block'><br><h2><span class='mw-headline' id='Youtube_videos'>Vídeos de Youtube</span></h2></div>";
    }
    document.body.appendChild(youtubeVideoContent);
    $('#youtubeVideos').append(content)

}

function goToVideos(){
    var videosCommandActive = myStorage.getItem(localStoragePrefix + "videosActive");
    closeOperationsMenu();
    closeMenu();

    if(videosCommandActive){
        $(window).scrollTop($('#youtubeVideos').offset().top);
    }
}

function toggleYoutubeVideos(){
    var x = document.getElementById("youtubeVideos");
    var videosCommandActive;
    if (!document.getElementById("videosInput").checked) {
        if(x !== null){
            x.style.display = "none";
        }
        document.getElementById("videos").style.setProperty("pointer-events", "none");
        videosCommandActive = false;
    } else {
        if(x !== null){
            x.style.display = "block";
        } else {
            youtubeVideos();
        }
        document.getElementById("videos").style.setProperty("pointer-events", "all");
        videosCommandActive = true;
    }
    myStorage.setItem(localStoragePrefix + "videosActive", videosCommandActive);
}


// Bread Crumb (History)
function breadcrumb(){
    var lastVisitedSitesURL = []
    var lastVisitedSitesTitle = []
    var breadcrumb = document.createElement('ol');
    breadcrumb.id = "BreadCrumb";
    breadcrumb.setAttribute('vocab',"https://schema.org/");
    breadcrumb.setAttribute('typeof',"BreadcrumbList");

    var maxBreadCrumb = 4;
    if(myStorage.getItem("lastVisitedSitesTitle" + "0") !== document.title){
        lastVisitedSitesURL.push(location.href)
        lastVisitedSitesTitle.push(document.title)
    } else{
        maxBreadCrumb++;
    }
    for(var i = 0; i < maxBreadCrumb; i++){
        if(myStorage.getItem("lastVisitedSitesURL" + i) !== null){
            lastVisitedSitesURL.push(myStorage.getItem("lastVisitedSitesURL" + i))
        }
        if(myStorage.getItem("lastVisitedSitesTitle" + i) !== null){
            lastVisitedSitesTitle.push(myStorage.getItem("lastVisitedSitesTitle" + i))
        }
    }
    for(var lastVisitedSitesIndex = 0; lastVisitedSitesIndex < lastVisitedSitesURL.length; lastVisitedSitesIndex++){
        myStorage.setItem("lastVisitedSitesURL" + lastVisitedSitesIndex, lastVisitedSitesURL[lastVisitedSitesIndex])
        myStorage.setItem("lastVisitedSitesTitle" + lastVisitedSitesIndex, lastVisitedSitesTitle[lastVisitedSitesIndex])
    }
    document.body.appendChild(breadcrumb);
    $('#BreadCrumb').css({
        'position': 'fixed',
        'height': '50px',
        'left': '15%',
        'top': '0',
        //'width': '100%',
        'padding': '10px',
        'background-color': '#FFFFFF',
        'vertical-align': 'bottom',
        'visibility': 'visible',
        'border': 'solid black',
        'z-index': '100'
    });
    var lastVisitedSitesURLReverse = lastVisitedSitesURL.reverse()
    var lastVisitedSitesTitleReverse = lastVisitedSitesTitle.reverse()
    for(var x = 0; x < lastVisitedSitesURLReverse.length; x++){
        var li = document.createElement("li");
        li.setAttribute('property',"itemListElement");
        li.setAttribute('typeof',"ListItem");
        li.style.display = "inline";

        var link = document.createElement("a");
        if(x < lastVisitedSitesURLReverse.length - 1) {
            link.href = lastVisitedSitesURLReverse[x];
            link.style = "color: #0645ad !important;"
        } else {
            link.style = "color: #000000 !important;text-decoration: none;"
        }
        link.setAttribute('property',"item");
        link.setAttribute('typeof',"WebPage");
        link.className = "linkBread";
        var span = document.createElement("span");
        span.setAttribute('property',"name");
        span.innerText = lastVisitedSitesTitleReverse[x];
        var meta = document.createElement("meta");
        meta.setAttribute('property',"position");
        var position = x+1;
        meta.setAttribute('content',position+"");
        link.appendChild(span);
        li.appendChild(link);
        li.appendChild(meta);
        breadcrumb.appendChild(li);
        breadcrumb.innerHTML += " > ";
    }
    $('.linkBread').each(function(){
        $(this).css({
            'padding':'3px',
        });
    });

    //toggleBreadcrumb()
}

function goBack(){
    var breadcrumbChildren = document.getElementById("BreadCrumb").children;
    if(breadcrumbChildren.length > 1){
        breadcrumbChildren[breadcrumbChildren.length-2].firstElementChild.click();
    } else {
        if(!spanishDomain){
            Read("There is no previous page in the history from same web domain");
        } else {
            Read("No hay una página anterior en el historial que pertenezca al mismo dominio");
        }
    }
}


function toggleBreadcrumb(){
    var breadcrumbCommandActive;
    if(document.getElementById("breadcrumbInput").checked){
        breadcrumbCommandActive = true;
        document.getElementById("BreadCrumb").style.setProperty("display", "block");
    } else {
        breadcrumbCommandActive = false;
        document.getElementById("BreadCrumb").style.setProperty("display", "none");
    }
    myStorage.setItem(localStoragePrefix + "breadcrumbActive", breadcrumbCommandActive);
}

function toggleHiddenSections(){
    console.log("toggleHiddenSections");
    var hiddenSectionsCommandActive;
    //$('.readAloudButton').attr('disabled', 'disabled');
    try{
        var hiddenItems = JSON.parse(myStorage.getItem(localStoragePrefix + "uselessAnnotation"));
        if(hiddenItems !== null){
            for(var i = 0; i < hiddenItems.length; i++){
                for(var j = 0; j < hiddenItems[i].value.length; j++){
                        var element = getElementByXPath(hiddenItems[i].value[j]);
                    if (document.getElementById("hideInput").checked) {
                        element.classList.add("hideUselessSections");
                        hiddenSectionsCommandActive = true;
                    } else {
                        element.classList.remove("hideUselessSections");
                        hiddenSectionsCommandActive = false;
                    }
                }
            }
        }

        myStorage.setItem(localStoragePrefix + "hideActive", hiddenSectionsCommandActive);

        closeMenu();
        closeOperationsMenu();
    } catch(e){

    }
    //$('.readAloudButton').removeAttr('disabled');

}


function toggleMenu(){
    var x = document.getElementById("foldingMenu");
    if(x !== null){
        if (x.style.display === "block") {
            x.style.display = "none";
        } else {
            x.style.display = "block";
        }
        closeCommandsMenu();
        closeAnnotationsMenu();
        closeOperationsMenu();
    }
}
function closeMenu(){
    var x = document.getElementById("foldingMenu");
    if(x !== null){
        x.style.display = "none";
    }
}

function toggleOperationsMenu(){
    var x = document.getElementById("menu-operations");
    if(x !== null){
        if (x.style.display === "block") {
            x.style.display = "none";
        } else {
            x.style.display = "block";
            closeMenu();
        }
    }
}
function closeOperationsMenu(){
    var x = document.getElementById("menu-operations");
    if(x !== null){
        x.style.display = "none";
    }
}

function toggleAnnotationsMenu(){
    var x = document.getElementById("menu-annotations");
    if(x !== null){
        if (x.style.display === "block") {
            x.style.display = "none";
        } else {
            x.style.display = "block";
            closeMenu();
            closeOperationsMenu();
        }
    }
}
function closeAnnotationsMenu(){
    var x = document.getElementById("menu-annotations");
    if(x !== null){
        x.style.display = "none";
    }
}

function toggleCommandsMenu(){
    var x = document.getElementById("menu-commands");
    if(x !== null){
        if (x.style.display === "block") {
            x.style.display = "none";
        } else {
            x.style.display = "block";
        }
    }
}
function closeCommandsMenu(){
    var x = document.getElementById("menu-commands");
    if(x !== null){
        x.style.display = "none";
    }
}


function showAnnotationMainButton(){
    var aIntermediary = document.getElementById("a-intermediary");
    aIntermediary.style = "display: block";
}

function showAnnotationsButtons(){

    var aSave = document.getElementById("saveAnnotationsA");
    aSave.style = "display: block";

    var aStop = document.getElementById("stopAnnotationsA");
    aStop.style = "display: block";

    var aUndo = document.getElementById("undoAnnotationsA");
    aUndo.style = "display: block";

}

function hideAnnotationMainButton(){
    var aIntermediary = document.getElementById("a-intermediary");
    aIntermediary.style = "display: none";
}

function hideAnnotationsButtons(){

    var aSave = document.getElementById("saveAnnotationsA");
    aSave.style = "display: none";

    var aStop = document.getElementById("stopAnnotationsA");
    aStop.style = "display: none";

    var aUndo = document.getElementById("undoAnnotationsA");
    aUndo.style = "display: none";

}

/*function saveAnnotationsSections(){

    if(annotationsUselessActive){
        saveAnnotationsUselessSections();
    } else if(annotationsParagraphActive){
        saveAnnotationsParagraphSections();
    } else if(annotationsTextActive){
        saveAnnotationsTextSections();
    }
}

function stopAnnotationsSections(){

    if(annotationsUselessActive){
        //stopAnnotationsUselessSections();
    } else if(annotationsParagraphActive){
        stopAnnotationsParagraphSections();
    } else if(annotationsTextActive){
        stopAnnotationsTextSections();
    }
}

function undoAnnotationsSections(){

    if(annotationsUselessActive){
        undoAnnotationsUselessSections();
    } else if(annotationsParagraphActive){
        undoAnnotationsParagraphSections();
    } else if(annotationsTextActive){
        undoAnnotationsTextSections();
    }
}*/


function hideLoadAnnotationsInfoForServer(){
    var loadModal = document.getElementById("loadModal");
    loadModal.style.display = "none";
}

function loadAnnotationsFromServer(){
    //var menuLoadAnnotations = document.getElementById("menu-loadAnnotations");
    //menuLoadAnnotations.style.display = "block";

    closeAnnotationsMenu();
    var loadModal = document.getElementById("loadModal");
    loadModal.style.display = "block";
    var divLoad = document.getElementById("divLoad");

    var xmlhttp = new XMLHttpRequest();
    var url = "https://wake.dlsi.ua.es/AnnotationsServer/?operation=loadWebsite&website="+encodeURI(document.URL);

    xmlhttp.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {
            var annotationsLoaded = JSON.parse(this.responseText).results;
            console.log("annotationsLoaded: " + JSON.stringify(annotationsLoaded));
            divLoad.innerHTML = "";

            for(var i = 0; i < annotationsLoaded.length; i++){
                var a = document.createElement('a');
                a.text = annotationsLoaded[i].title;
                a.href = "javascript:void(0);";
                var title = annotationsLoaded[i].title;
                a.title = annotationsLoaded[i].title;
                a.addEventListener("click", function(title){
                    loadAnnotationByTitleAndWebsite(title);
                    return false;
                }, false);
                divLoad.appendChild(a);

                if(annotationsLoaded[i].ratings != null && typeof annotationsLoaded[i].ratings != 'undefined'
                   && annotationsLoaded[i].ratings.length > 0){
                    var finalRating = 0;
                    for(var ratingsStored = 0; ratingsStored < annotationsLoaded[i].ratings.length; ratingsStored++){
                        finalRating += annotationsLoaded[i].ratings[ratingsStored];
                    }
                    finalRating = Math.round(finalRating * 100.0 / annotationsLoaded[i].ratings.length) / 100;
                    var labelRating = document.createElement("label");
                    labelRating.style.marginLeft = "5px";
                    labelRating.innerHTML = " (" + finalRating + "/5 stars)";
                    divLoad.appendChild(labelRating);
                }

                var divRating = document.createElement('div');
                var rateLabel = document.createElement('label');
                if(!spanishDomain){
                    rateLabel.innerHTML = "Rate: ";
                } else {
                    rateLabel.innerHTML = "Valoración: ";
                }
                rateLabel.style.marginRight = "5px";
                divRating.appendChild(rateLabel);

                var spanRating1 = document.createElement('span');
                spanRating1.classList.add("icon");
                spanRating1.style.cursor = "pointer";
                spanRating1.innerHTML = "&#9733;";
                spanRating1.onmouseover = function(){changeColor(this, 1, true);};
                spanRating1.onmouseout = function(){changeColor(this, 1, false);};
                spanRating1.onclick= function(title){
                    changeColor(this, 1, true);
                    disableChangeColor(this);
                    saveRatingsOfAnnotationInServer(1, title);
                };
                spanRating1.title = title;
                divRating.appendChild(spanRating1);

                var spanRating2 = document.createElement('span');
                spanRating2.classList.add("icon");
                spanRating2.style.cursor = "pointer";
                spanRating2.innerHTML = "&#9733;";
                spanRating2.onmouseover = function(){changeColor(this, 2, true);};
                spanRating2.onmouseout = function(){changeColor(this, 2, false);};
                spanRating2.onclick= function(title){
                    changeColor(this, 2, true);
                    disableChangeColor(this);
                    saveRatingsOfAnnotationInServer(2, title);
                };
                spanRating2.title = title;
                divRating.appendChild(spanRating2);

                var spanRating3 = document.createElement('span');
                spanRating3.classList.add("icon");
                spanRating3.style.cursor = "pointer";
                spanRating3.innerHTML = "&#9733;";
                spanRating3.onmouseover = function(){changeColor(this, 3, true);};
                spanRating3.onmouseout = function(){changeColor(this, 3, false);};
                spanRating3.onclick= function(title){
                    changeColor(this, 3, true);
                    disableChangeColor(this);
                    saveRatingsOfAnnotationInServer(3, title);
                };
                spanRating3.title = title;
                divRating.appendChild(spanRating3);

                var spanRating4 = document.createElement('span');
                spanRating4.classList.add("icon");
                spanRating4.style.cursor = "pointer";
                spanRating4.innerHTML = "&#9733;";
                spanRating4.onmouseover = function(){changeColor(this, 4, true);};
                spanRating4.onmouseout = function(){changeColor(this, 4, false);};
                spanRating4.onclick= function(title){
                    changeColor(this, 4, true);
                    disableChangeColor(this);
                    saveRatingsOfAnnotationInServer(4, title);
                };
                spanRating4.title = title;
                divRating.appendChild(spanRating4);

                var spanRating5 = document.createElement('span');
                spanRating5.classList.add("icon");
                spanRating5.style.cursor = "pointer";
                spanRating5.innerHTML = "&#9733;";
                spanRating5.onmouseover = function(){changeColor(this, 5, true);};
                spanRating5.onmouseout = function(){changeColor(this, 5, false);};
                spanRating5.onclick= function(title){
                    changeColor(this, 5, true);
                    disableChangeColor(this);
                    saveRatingsOfAnnotationInServer(5, title);
                };
                spanRating5.title = title;
                divRating.appendChild(spanRating5);

                divLoad.appendChild(divRating);

                divLoad.appendChild(document.createElement('br'));

                if(typeof annotationsLoaded[i].description != 'undefined'){
                    var label = document.createElement('label');
                    if(!spanishDomain){
                        label.innerHTML = "<b>Description: </b>" + annotationsLoaded[i].description;
                    } else {
                        label.innerHTML = "<b>Descripción: </b>" + annotationsLoaded[i].description;
                    }
                    divLoad.appendChild(label);
                    divLoad.appendChild(document.createElement('br'));
                }
                if(typeof annotationsLoaded[i].category != 'undefined'){
                    var label2 = document.createElement('label');
                    if(!spanishDomain){
                        label2.innerHTML = "<b>Category: </b>" + annotationsLoaded[i].category;
                    } else {
                        label2.innerHTML = "<b>Categoría: </b>" + annotationsLoaded[i].category;
                    }
                    divLoad.appendChild(label2);
                    divLoad.appendChild(document.createElement('br'));
                }
                if(typeof annotationsLoaded[i].targetUsers != 'undefined'){
                    var label3 = document.createElement('label');
                    if(!spanishDomain){
                        label3.innerHTML = "<b>Target users: </b>" + annotationsLoaded[i].targetUsers;
                    } else {
                        label3.innerHTML = "<b>Destinatarios: </b>" + annotationsLoaded[i].targetUsers;
                    }
                    divLoad.appendChild(label3);
                    divLoad.appendChild(document.createElement('br'));
                }
                divLoad.appendChild(document.createElement('br'));
            }
        }
    };

    xmlhttp.open("GET", url, true);
    xmlhttp.send();
}

function saveRatingsOfAnnotationInServer(rating, annotationTitle){
    if(typeof annotationTitle.currentTarget !== 'undefined'){
        annotationTitle = annotationTitle.currentTarget.title
    }
    //annotationTitle = annotationTitle.currentTarget.title
    console.log("saveRatingsOfAnnotationInServer: " + rating + ", " + annotationTitle);
    if(rating != null && annotationTitle != null){

        var xmlhttp = new XMLHttpRequest();
        var url = "https://wake.dlsi.ua.es/AnnotationsServer/";

        xmlhttp.onreadystatechange = function() {
            if (this.readyState == 4 && this.status == 200) {
                var annotationsSaved = JSON.parse(this.responseText);
                console.log(JSON.stringify(annotationsSaved));
            }
        };

        xmlhttp.open("POST", url, true);
        xmlhttp.setRequestHeader("Content-Type", "application/json");
        var params = {}
        params.operation = "rate";
        params.rating = rating;
        params.annotationTitle = annotationTitle;
        //console.log(JSON.stringify(params));
        xmlhttp.send(JSON.stringify(params));

        //hideAnnotationsInfoForServer();
    } else {
        //TODO: check errors
        console.log("error");
    }
}

function disableChangeColor(element){
  var childs = element.parentNode.childNodes;
  for(var i = 0; i < childs.length; i++){
      childs[i].onmouseover = '';
      childs[i].onmouseout = '';
      childs[i].onclick = '';
  }
}

function changeColor(element, previousSiblings, fill){
  var color
  if(fill){
    color = "#F1C40F";
  } else {
    color = "#000";
  }
  var previousSiblingsAux = previousSiblings - 1;
  element.style.color = color;
  var elementAux = element
  for(var i = 0; i < previousSiblingsAux; i++){
    elementAux = elementAux.previousElementSibling
    elementAux.style.color = color;
  }
}

function loadAnnotationsFromServerByVoice(){

    var xmlhttp = new XMLHttpRequest();
    var url = "https://wake.dlsi.ua.es/AnnotationsServer/?operation=loadWebsite&website="+encodeURI(document.URL);

    xmlhttp.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {
            var annotationsLoaded = JSON.parse(this.responseText).results;
            console.log("annotationsLoaded: " + JSON.stringify(annotationsLoaded));

            var annotationsToRead = "";

            if(annotationsLoaded.length > 0){
                if(!spanishDomain){
                    annotationsToRead += "The available annotations to download are: ";
                } else {
                    annotationsToRead += "Las anotaciones disponibles para descargar son: ";
                }
            }

            var title = ""
            for(var i = 0; i < annotationsLoaded.length; i++){
                title = annotationsLoaded[i].title;
                var description = annotationsLoaded[i].description;
                var category = annotationsLoaded[i].category;
                var targetUsers = annotationsLoaded[i].targetUsers;
                var ratings = annotationsLoaded[i].ratings;
                if(commandListened.toLowerCase().includes(title.toLowerCase())){
                    loadAnnotationByTitleAndWebsite(title, true);
                    return;
                } else {
                    annotationsToRead += "title: " + title;
                    if(typeof description != 'undefined'){
                        if(!spanishDomain){
                            annotationsToRead += "; description: " + description;
                        } else {
                            annotationsToRead += "; descripción: " + description;
                        }
                    }
                    if(typeof targetUsers != 'undefined'){
                        if(!spanishDomain){
                            annotationsToRead += "; for: " + targetUsers;
                        } else {
                            annotationsToRead += "; para: " + targetUsers;
                        }
                    }
                    if(typeof category != 'undefined'){
                        if(!spanishDomain){
                            annotationsToRead += "; category: " + category;
                        } else {
                            annotationsToRead += "; categoría: " + category;
                        }
                    }
                    if(typeof ratings != 'undefined'){
                        var finalRating = 0;
                        for(var ratingsStored = 0; ratingsStored < ratings.length; ratingsStored++){
                            finalRating += ratings[ratingsStored];
                        }
                        finalRating = Math.round(finalRating * 100.0 / annotationsLoaded[i].ratings.length) / 100;
                        if(!spanishDomain){
                            annotationsToRead += "; ratings: " + finalRating + " out of 5";
                        } else {
                            annotationsToRead += "; valoración: " + finalRating + " de 5";
                        }
                    }
                    annotationsToRead += ".  ";
                }
            }

            if(annotationsLoaded.length > 0){
                if(!spanishDomain){
                    annotationsToRead +=
                    ". If you want to download one of these annotations just say the load annotations command and the title of the annotations. For example: load annotations "
                    + title + ". To rate your current loaded annotations you can use the voice command 'score' and the rating number between 1 and 5: for example score 5." ;
                } else {
                    annotationsToRead +=
                    ". Si quieres descargar una de estas anotaciones solo utiliza el comando cargar anotaciones y el título de la anotación. Por ejemplo: cargar anotaciones "
                    + title + ". Para valorar las anotaciones descargadas utiliza el comando 'valorar' y la valoración numérica entre 1 y 5, por ejemplo: valorar 5." ;
                }

            } else {
                if(!spanishDomain){
                    annotationsToRead += "There aren't annotations to download for this website.";
                } else {
                    annotationsToRead += "No hay anotaciones para descargar en esta web.";
                }
            }
            Read(annotationsToRead);
        }
    };

    xmlhttp.open("GET", url, true);
    xmlhttp.send();
}

function closeLoadMenu(){
    document.getElementById("menu-loadAnnotations").style.display = "none";
}

function loadAnnotationByTitleAndWebsite(title, byVoice){
    var titleToLoad = title;
    if(typeof title.parentElement === 'undefined' && typeof title.currentTarget !== 'undefined'){
        titleToLoad = title.currentTarget.title
    }
    var xmlhttp = new XMLHttpRequest();
    var url = "https://wake.dlsi.ua.es/AnnotationsServer/?operation=loadAnnotation&title="+titleToLoad+"&website="+encodeURI(document.URL);

    xmlhttp.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {
            var annotationsLoaded = JSON.parse(this.responseText).results;
            if(annotationsLoaded.length > 0){
                //var annotationsJSON = JSON.parse(annotationsLoaded[0]);
                var annotationsJSON = annotationsLoaded[0];
                //TODO: refactor
                console.log(annotationsJSON);

                myStorage.setItem(localStoragePrefix + "annotationTitle", annotationsJSON.title);

                for(var annotationsIndex = 0; annotationsIndex < annotations.length; annotationsIndex++){
                    myStorage.setItem(localStoragePrefix + annotations[annotationsIndex].id, annotationsJSON[localStoragePrefix + annotations[annotationsIndex].id]);
                }
                myStorage.setItem(localStoragePrefix + "paragraphItemsXPath", annotationsJSON[localStoragePrefix + "paragraphItemsXPath"]);

                for(var i = 0; i < operations.length; i++){
                    if(operations[i].hasMenu){
                        updateSubmenuForOperationAndAnnotations("menu-" + operations[i].id, operations[i], operations[i].annotations);
                    }
                }

                for(var j = 0; j < annotations.length; j++){
                    updateSubmenuForAnnotations("menu-" + annotations[j].id, annotations[j].id);
                }
                updateScriptXPath();

                //TODO: toggle operations that are toggleable(?)
                toggleHiddenSections();

                if(byVoice === true){
                    if(!spanishDomain){
                        Read("Annotations loaded, use list sections to know the new sections available."
                         + " To rate your current loaded annotations you can use the voice command 'score' and the rating number between 1 and 5: for example score 5." );
                    } else {
                        Read("Anotaciones cargadas, utiliza listar secciones para saber qué secciones hay disponibles."
                         + " Para valorar las anotaciones descargadas utiliza el comando 'valorar' y la valoración numérica entre 1 y 5, por ejemplo: valorar 5." );
                    }
                } else {
                    if(!spanishDomain){
                        alert("Annotations loaded!");
                    } else {
                        alert("¡Anotaciones cargadas!");
                    }
                    hideLoadAnnotationsInfoForServer();
                }
            }
            //console.log(JSON.stringify(annotationsLoaded));
        }
    };

    xmlhttp.open("GET", url, true);
    xmlhttp.send();
}

function askAnnotationsInfoForServer(){
    closeAnnotationsMenu();
    var saveModal = document.getElementById("saveModal");
    saveModal.style.display = "block";
}


function hideAnnotationsInfoForServer(){
    var saveModal = document.getElementById("saveModal");
    saveModal.style.display = "none";
}

function saveAnnotationsInServer(result){
    console.log("saveAnnotationsInServer: " + JSON.stringify(result));

    //var result = prompt("Title for annotations", "");
    if(result!=null && result.title != null){
        var annotationsObject = {};
        annotationsObject.title = result.title;
        annotationsObject.description = result.description;
        annotationsObject.targetUsers = result.targetUsers;
        annotationsObject.category = result.category;
        annotationsObject.website = encodeURI(document.URL);
        annotationsObject.ratings = [];

        for(var annotationsIndex = 0; annotationsIndex < annotations.length; annotationsIndex++){
            annotationsObject[localStoragePrefix + annotations[annotationsIndex].id] = myStorage.getItem(localStoragePrefix + annotations[annotationsIndex].id);
        }
        annotationsObject[localStoragePrefix + "paragraphItemsXPath"] = myStorage.getItem(localStoragePrefix + "paragraphItemsXPath");
        console.log(JSON.stringify(annotationsObject));
        var xmlhttp = new XMLHttpRequest();
        var url = "https://wake.dlsi.ua.es/AnnotationsServer/";

        xmlhttp.onreadystatechange = function() {
            if (this.readyState == 4 && this.status == 200) {
                var annotationsSaved = JSON.parse(this.responseText);
                console.log(JSON.stringify(annotationsSaved));
            }
        };

        xmlhttp.open("POST", url, true);
        xmlhttp.setRequestHeader("Content-Type", "application/json");
        var params = {}
        params.operation = "save";
        params.annotations = JSON.stringify(annotationsObject);
        //console.log(JSON.stringify(params));
        xmlhttp.send(JSON.stringify(params));

        hideAnnotationsInfoForServer();
    } else {
        //TODO: check if title already exists for that website
        console.log("error");
    }
}



function createSpeakableAnnotations(){
    var script = document.createElement('script'); // Create a script element
    script.type = "application/ld+json";
    script.id = "AnnotationsScript";
    script.text = '{"@context": "https://schema.org/","@type": "WebPage","name": "' + document.title + '","speakable":{"@type": "SpeakableSpecification","xpath": [';

    var paragraphItemsXPath = myStorage.getItem(localStoragePrefix + "paragraphItemsXPath");
    try{
        paragraphItemsXPath = JSON.parse(paragraphItemsXPath);
    } catch(e){
    }

    if(paragraphItemsXPath !== null){
        var all
        var added = false;
        for(var i = 0; i < paragraphItemsXPath.length; i++){
            if(typeof paragraphItemsXPath[i].value[0] !== 'undefined'){
                script.text += '"' + paragraphItemsXPath[i].value[0] + '",';
                added = true;
            }
        }
        if(added){
            script.text += script.text.substring(0, script.text.length - 1);
        }
    }
    script.text += ']  }, "url": "' + document.URL + '" }';
    document.body.appendChild(script);
}

function updateScriptXPath(){
    try{
        var script = document.getElementById("AnnotationsScript");
        script.text = '{"@context": "https://schema.org/","@type": "WebPage","name": "' + document.title + '","speakable":{"@type": "SpeakableSpecification","xpath": [';

        var paragraphItemsXPath = myStorage.getItem(localStoragePrefix + "paragraphItemsXPath");
        try{
            paragraphItemsXPath = JSON.parse(paragraphItemsXPath);
        } catch(e){
        }

        if(paragraphItemsXPath !== null){
            var all
            var added = false;
            for(var i = 0; i < paragraphItemsXPath.length; i++){
                if(typeof paragraphItemsXPath[i].value !== 'undefined' && paragraphItemsXPath[i].value.length > 0 && typeof paragraphItemsXPath[i].value[0] !== 'undefined'){
                    script.text += '"' + paragraphItemsXPath[i].value[0] + '",';
                    added = true;
                }
            }
            if(added){
                script.text += script.text.substring(0, script.text.length - 1);
            }
        }
        script.text += ']  }, "url": "' + document.URL + '" }';
        document.body.appendChild(script);
    } catch(e){
    }
}

function createCSSSelector (selector, style) {
  if (!document.styleSheets) return;
  if (document.getElementsByTagName('head').length == 0) return;

  var styleSheet,mediaType;

  if (document.styleSheets.length > 0) {
    for (var i = 0, l = document.styleSheets.length; i < l; i++) {
      if (document.styleSheets[i].disabled)
        continue;
      var media = document.styleSheets[i].media;
      mediaType = typeof media;

      if (mediaType === 'string') {
        if (media === '' || (media.indexOf('screen') !== -1)) {
          styleSheet = document.styleSheets[i];
        }
      }
      else if (mediaType=='object') {
        if (media.mediaText === '' || (media.mediaText.indexOf('screen') !== -1)) {
          styleSheet = document.styleSheets[i];
        }
      }

      if (typeof styleSheet !== 'undefined')
        break;
    }
  }

  if (typeof styleSheet === 'undefined') {
    var styleSheetElement = document.createElement('style');
    styleSheetElement.type = 'text/css';
    document.getElementsByTagName('head')[0].appendChild(styleSheetElement);

    for (i = 0; i < document.styleSheets.length; i++) {
      if (document.styleSheets[i].disabled) {
        continue;
      }
      styleSheet = document.styleSheets[i];
    }

    mediaType = typeof styleSheet.media;
  }

  if (mediaType === 'string') {
    for (i = 0, l = styleSheet.rules.length; i < l; i++) {
      if(styleSheet.rules[i].selectorText && styleSheet.rules[i].selectorText.toLowerCase()==selector.toLowerCase()) {
        styleSheet.rules[i].style.cssText = style;
        return;
      }
    }
    styleSheet.addRule(selector,style);
  }
  else if (mediaType === 'object') {
    var styleSheetLength = (styleSheet.cssRules) ? styleSheet.cssRules.length : 0;
    for (i = 0; i < styleSheetLength; i++) {
      if (styleSheet.cssRules[i].selectorText && styleSheet.cssRules[i].selectorText.toLowerCase() == selector.toLowerCase()) {
        styleSheet.cssRules[i].style.cssText = style;
        return;
      }
    }
    styleSheet.insertRule(selector + '{' + style + '}', styleSheetLength);
  }
}

function getXPathForElement(element) {
    const idx = (sib, name) => sib
        ? idx(sib.previousElementSibling, name||sib.localName) + (sib.localName == name)
        : 1;
    const segs = elm => !elm || elm.nodeType !== 1
        ? ['']
        : elm.id && document.getElementById(elm.id) === elm
            ? [`id("${elm.id}")`]
            : [...segs(elm.parentNode), `${elm.localName.toLowerCase()}[${idx(elm)}]`];
    return segs(element).join('/').split('"').join("'");
}

function getElementByXPath(path) {
    return (new XPathEvaluator())
        .evaluate(path, document.documentElement, null,
                        XPathResult.FIRST_ORDERED_NODE_TYPE, null)
        .singleNodeValue;
}


/*(function() {
    'use strict';

    // Your code here...
})();*/