text:
/*jslint indent:8, devel:true, browser:true, vars:true*/
/*global jQuery, $, console*/
// ==UserScript==
// @name        AnchorMe
// @namespace   AnchorMe
// @description Set a reading mark in the pages you choose. Never forget where your reading finish last time.
// @include     https://developer.mozilla.org/*
// @include     http://www.2ality.com/*
// @include     http://www.atareao.es/*
// @include     http://addyosmani.github.io/backbone-fundamentals/*
// @include     https://github.com/Nijikokun/the-zen-approach/blob/master/*
// @include     http://getpocket.com/*
// @include     https://leanpub.com/javascript-allonge/read*
// @version     0.1
// @grant       none
// ==/UserScript==
// Puede que la página ya disponga de jQuery, por lo que no se importa por defecto
// -@-require     http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js
//
/*
 * Haciendo Ctrl + doble click sobre un texto se crea un marcador.
 *
 * //TODO: En histórico: Añadir importar e exportar marcador
 *
 */

/*
 The MIT License (MIT)

 Copyright (c) 2014 Samuel González Izquierdo

 Permission is hereby granted, free of charge, to any person obtaining a copy of
 this software and associated documentation files (the "Software"), to deal in
 the Software without restriction, including without limitation the rights to
 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 the Software, and to permit persons to whom the Software is furnished to do so,
 subject to the following conditions:

 The above copyright notice and this permission notice shall be included in all
 copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

(function () {
        "use strict";

        // Activa o desactiva el logging
        var DEBUG = true;

        var log = function (logString) {
                if (DEBUG && console) {
                        console.log(logString);
                }
        };
        log(">>> Greasemonkey\'s working on this page!");

        // Objeto de utilidades: Get y Set del marcador de la página (a localStorage)
        var util = {
                cache: {

                        // Key del objecto de marcadores a guardar en localStorage
                        BM_KEY: "ANCHORME",

                        // Construye el tipo de objeto que espera el método 'setBookMark'
                        // Debe invocarse con el operador new (new util.cache.BookMarkObject)
                        BookMarckObject: function () {
                                this.id = 0;
                                this.type = "";
                                this.position = 0;
                                this.percent = 0;
                                this.tip = "";

                                // Función que serializa los atributos de 'this' en formato 'queryString' ( &nomAttr=valor&... ).
                                this.stringify = function () {
                                        var name, result = "";

                                        // La función acepta 'this' con métodos ("function"), pero no los tiene en cuenta
                                        Object.getOwnPropertyNames(this).forEach(function (name) {
                                                if (typeof this[name] !== "function") {
                                                        result += "&" + name + "=" + this[name];
                                                }
                                        }, this);
                                        return result;
                                };
                        },
                        setBookMark: function (obj) {

                                // Cerciorarse de que 'obj' es del tipo requerido
                                if (!obj instanceof util.cache.BookMarckObject) {
                                        log("El objecto no es compatible");
                                        return false;
                                }

                                // Se crea un identificador único para este marcador
                                obj.id = new Date().getTime();

                                log("----------------");
                                log("Objeto a almacenar: " + obj.stringify());
                                log("----------------");

                                var bookMarks = localStorage.getItem(this.BM_KEY);
                                if (bookMarks) {
                                        bookMarks = JSON.parse(bookMarks);
                                        bookMarks.push(obj);
                                } else {

                                        // Si no existe aún un objeto de marcadores en localStorage lo creamos
                                        bookMarks = [];
                                        bookMarks.push(obj);
                                }

                                localStorage.setItem(this.BM_KEY, JSON.stringify(bookMarks));

                        },

                        // NOTE: Actualmente este método no se utiliza.
                        // Retorna el marcador más moderno
                        getLastBookMark: function () {
                                var bookMarks = localStorage.getItem(this.BM_KEY),
                                        ids = [],
                                        idMarcadorActivo,
                                        marcadorAtivo;

                                if (bookMarks) {
                                        bookMarks = JSON.parse(bookMarks);

                                        bookMarks.forEach(function (reg) {
                                                ids.push(reg.id);
                                        });

                                        // Id más alto. Al ser una fecha es el marcador más reciente
                                        idMarcadorActivo = Math.max.apply(null, ids);

                                        bookMarks.forEach(function (reg) {
                                                if (reg.id === idMarcadorActivo) {
                                                        marcadorAtivo = reg;
                                                        return false; // Es la única manera de que el loop no continue. 'break' no funciona.
                                                }
                                        });

                                        if (marcadorAtivo) {
                                                return marcadorAtivo;
                                        }
                                }
                                return undefined;
                        },

                        // Retorna todos los marcadores
                        getBookMarksHistory: function () {
                                var bookMarks = localStorage.getItem(this.BM_KEY);
                                if (bookMarks) {
                                        bookMarks = JSON.parse(bookMarks);
                                        return bookMarks;
                                }
                                return undefined;
                        },
                        deleteBookMark: function (idBookMark) {
                                var tempBMArr = [];

                                if (idBookMark) {

                                        // Borra el marcador que coincida con idBookMark
                                        var bookMarks = localStorage.getItem(this.BM_KEY);
                                        if (bookMarks) {
                                                bookMarks = JSON.parse(bookMarks);

                                                bookMarks.forEach(function (reg) {
                                                        if (reg.id !== idBookMark) {
                                                                tempBMArr.push(reg);
                                                        }
                                                });

                                                localStorage.setItem(this.BM_KEY, JSON.stringify(tempBMArr));
                                        }
                                        log("Marcador eliminado.");
                                } else {

                                // Borrar todos los marcadores
                                        localStorage.clear();
                                        log("Todos los marcadores han sido eliminados.");
                                }
                        }
                },
                textos: {
                        btoIrHayMarcador:   "Ir al marcador!",
                        btoIrNoHayMarcador: "No hay marcador",
                        infoMarca: "Marcador añadido",
                        infoMarcable: "Marcable",
                        eliminar: "¿Eliminar?",
                        historicoMarcadores: "Histórico de marcadores",
                        btoImportar: "Importar Marcador",
                        btoExportar: "Exportar Marcador"
                }
        };

        // Objeto principal de la aplicación
        var App = {
                ANCHOR: "smuxAnchor",
                hayMarcador: false,
                enConfirmacion: false,
                confirmacionEliminacion: false,

                // Estilos necesarios para el script.
                // Deben prefijarse para evitar repetir nombres de clases que ya pudiesen existir en la página (Me ha pasado!!!!)
                // Mi prefijo será: smx-
                estilos: " " +
                         "@font-face{" +
                         " " +
                         "font-family:smx-FontAwesome;" +
                         " src:url(https://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/fonts/fontawesome-webfont.eot?#iefix) format('eot')," +
                         "url(https://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/fonts/fontawesome-webfont.woff) format('woff')," +
                         "url(https://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/fonts/fontawesome-webfont.ttf) format('truetype')," +
                         "url(https://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/fonts/fontawesome-webfont.svg#FontAwesome) format('svg');" +
                         " font-weight:400;" +
                         " font-style:normal;" +
                         " " +
                         "}" +
                         ".smx-info {" +
                         "        font: 14px/1.5 Courier New, monospace;" +
                         "        font-weight: bold;" +
                         "        display: inline;" +
                         "        background: #d04848;" +
                         "        color: white;" +
                         "        opacity: 0;" +
                         "        padding-right: 20px;" +
                         "        text-align: right;" +
                         "        box-sizing: border-box;" +
                         "        position: fixed;" +
                         "        z-index: 99997;" +
                         "        top: 10px;" +
                         "        left: -150px;" +
                         "        width: 160px;" +
                         "        box-shadow: #b5b5b5 0 2px 6px 2px;" +
                         "        border-radius: 5px 2px 2px 5px;" +
                         "        transition: width 0.3s ease-out;" +
                         "}" +
                         ".smx-contenedor {" +
                         "        font: 14px/1.5 Courier New, monospace;" +
                         "        background: black;" +
                         "        color: white;" +
                         "        opacity: 0.3;" +
                         "        position: fixed;" +
                         "        z-index: 99998;" +
                         "        top: 10px;" +
                         "        left: -150px;" +
                         "        width: 160px;" +
                         "        text-align: right;" +
                         "        box-sizing: border-box;" +
                         "        padding-right: 10px;" +
                         "        border-radius: 5px 2px 2px 5px;" +
                         "        box-shadow: #b5b5b5 0 2px 6px 2px;" +
                         "        cursor: pointer;" +
                         "        transition: width 0.3s ease-out 0.2s;" +
                         "}" +
                         ".smx-contenedor:hover {" +
                         "        width: 310px;" +
                         "}" +
                         ".smx-boton {" +
                         "        display: inline;" +
                         "        font-weight: 800;" +
                         "        /*'bold' es insuficiente*/" +
                         "}" +
                         ".smx-boton:hover {" +
                         "        opacity: 0.6;" +
                         "}" +
                         ".smx-boton-hover-off:hover {" +
                         "        opacity: 1;" +
                         "}" +
                         ".smx-boton:active {" +
                         "        opacity: 0.3;" +
                         "}" +
                         ".smx-boton-active-off:active {" +
                         "        opacity: 1;" +
                         "}" +
                         ".smx-eliminar {" +
                         "        font-family: smx-FontAwesome;" +
                         "        padding: 10px;" +
                         "}" +
                         ".smx-eliminar::after {" +
                         "        content: '\\f014';" +
                         "        font-size: 14px;" +
                         "        display: inline-block;" +
                         "        /* //NOTE: A los elementos inline no se les puede cambiar el ancho o alto */" +
                         "        cursor: pointer;" +
                         "        width: 10px;" +
                         "}" +
                         ".smx-eliminar.off::after {" +
                         "        display: none;" +
                         "        cursor: default;" +
                         "}" +
                         ".smx-eliminar-confirmar::after {" +
                         "        content: '\\f057';" +
                         "        font-size: 14px;" +
                         "}" +
                         ".smx-eliminar:hover::after {" +
                         "        opacity: 0.6;" +
                         "}" +
                         ".smx-eliminar:active::after {" +
                         "        opacity: 0.3;" +
                         "}" +
                         ".smx-exportar {" +
                         "        font-family: smx-FontAwesome;" +
                         "        /* //NOTE: padding: arriba-abajo izquierda-derecha */" +
                         "        padding: 0 5px 0 10px;" +
                         "}" +
                         ".smx-exportar::after {" +
                         "        content: '\\f102';" +
                         "        font-size: 14px;" +
                         "        display: inline-block;" +
                         "        /* //NOTE: A los elementos inline no se les puede cambiar el ancho o alto */" +
                         "        cursor: pointer;" +
                         "        width: 10px;" +
                         "}" +
                         ".smx-exportar:hover::after {" +
                         "        opacity: 0.6;" +
                         "}" +
                         ".smx-exportar:active::after {" +
                         "        opacity: 0.3;" +
                         "}" +
                         ".smx-exportar.off::after {" +
                         "        display: none;" +
                         "        cursor: default;" +
                         "}" +
                         ".smx-importar {" +
                         "        font-family: smx-FontAwesome;" +
                         "        /* //NOTE: padding: arriba-abajo izquierda-derecha */" +
                         "        padding: 0 10px 0 5px;" +
                         "}" +
                         ".smx-importar::after {" +
                         "        content: '\\f103';" +
                         "        font-size: 14px;" +
                         "        display: inline-block;" +
                         "        /* //NOTE: A los elementos inline no se les puede cambiar el ancho o alto */" +
                         "        cursor: pointer;" +
                         "        width: 10px;" +
                         "}" +
                         ".smx-importar:hover::after {" +
                         "        opacity: 0.6;" +
                         "}" +
                         ".smx-importar:active::after {" +
                         "        opacity: 0.3;" +
                         "}" +
                         ".smx-importar.off::after {" +
                         "        display: none;" +
                         "        cursor: default;" +
                         "}" +
                         ".smx-do-importar {" +
                         "        display: none;" +
                         "        background-color: rgba(247, 146, 146, 0.8);" +
                         "        border-radius: 2px;" +
                         "        padding: 0 10px 0 10px;" +
                         "}" +
                         ".smx-marcable {" +
                         "        position: absolute;" +
                         "        /*Si se utiliza 'em' se hereda el tamaño del contenedor*/" +
                         "        font-family: smx-FontAwesome;" +
                         "        width: 15px;" +
                         "        height: 0;" +
                         "        text-align: center;" +
                         "        background-color: rgba(0, 0, 0, 0);" +
                         "        color: black;" +
                         "        opacity: 0;" +
                         "        transform: translate(-15px, -15px);" +
                         "        /*Lo mismo: transform:translateX(-18px);*/" +
                         "        transition: opacity 0.4s ease-out;" +
                         "}" +
                         ".smx-marcable::after {" +
                         "        content: '\\f13d';" +
                         "        font-size: 14px;" +
                         "}" +
                         ".smx-lista-marcadores {" +
                         "        opacity: 1;" +
                         "        font-family: smx-FontAwesome;" +
                         "        padding-right: 4px;" +
                         "        background: black;" +
                         "}" +
                         ".smx-lista-marcadores::after {" +
                         "        content: '\\f039';" +
                         "        font-size: 1em;" +
                         "}" +
                         ".smx-lista-marcadores:hover::after {" +
                         "        opacity: 0.6;" +
                         "}" +
                         ".smx-lista-marcadores:active::after {" +
                         "        opacity: 0.3;" +
                         "}" +
                         ".smx-contenedor-marcadores {" +
                         "        display: none;" +
                         "        overflow: auto;" +
                         "        font: 14px/1.5 Courier New, monospace;" +
                         "        background-color: rgba(0, 0, 0, 0.6);" +
                         "        color: white;" +
                         "        text-align: center;" +
                         "        position: fixed;" +
                         "        z-index: 99999;" +
                         "        top: 15px;" +
                         "        left: 10px;" +
                         "        width: 520px;" +
                         "        height: 300px;" +
                         "        box-sizing: border-box;" +
                         "        padding: 20px 20px 20px 20px;" +
                         "        border-radius: 5px 5px 5px 5px;" +
                         "        box-shadow: #b5b5b5 0 2px 6px 2px;" +
                         "        /*transition: height 0.3s ease-out;" +
                         "	*/" +
                         "}" +
                         ".smx-titulo-historico {" +
                         "        font-weight: bold;" +
                         "        text-shadow: 1px 1px 2px black;" +
                         "        background-color: rgb(247, 146, 146);" +
                         "        margin: 5px;" +
                         "        border-radius: 2px;" +
                         "}" +
                         ".smx-inpor-expor-container {" +
                         "        background-color: rgba(0, 0, 0, 0.3);" +
                         "        border-radius: 2px;" +
                         "        float: right;" +
                         "}" +
                         ".smx-marcador-historico {" +
                         "        text-align: left;" +
                         "        background-color: black;" +
                         "        margin: 5px;" +
                         "        border-radius: 2px;" +
                         "}" +
                         ".smx-area-texto {" +
                         "        display: none;" +
                         "}" +
                         "/* De todos los elementos con la clase '.smx-marcador-historico' " +
                         "   solo al segundo se le aplicará este estilo. */" +
                         " " +
                         ".smx-marcador-historico:nth-child(0n+2) {" +
                         "        font-weight: bold;" +
                         "        color: rgb(247, 146, 146);" +
                         "}" +
                         "/*//NOTE: esta clase debe ser la última para que sobreescriba a las demás. */" +
                         " " +
                         ".activo {" +
                         "        opacity: 1;" +
                         "}",

                loadScript: function () {
                        this.cargarInterfaz();
                        this.cacheElements();
                        this.cargarHistoricoMarcadores();
                        this.bindElements();

                },

                // Carga los elementos de la interfaz y los cachea
                cargarInterfaz: function () {

                        // Añado los estilos a la página
                        $("head").append("<style>" + this.estilos + "</style>");

                        // Añado el botón de "Ir al Marcador"
                        $("body").append("<div class='smx-contenedor'>" +
                                         "      <span class='smx-lista-marcadores'></span>" +
                                         "      <div class='smx-boton'>" + util.textos.btoIrNoHayMarcador + "</div>" +
                                         "</div>" +
                                         "<div class='smx-info'>" + util.textos.infoMarca + "</div>");

                        // Añado el mensaje que informa si el elemento sobre el que está el cursor es "marcable"
                        $("body").append("<div class='smx-marcable'></div>");

                        // Añade contenedor de marcadores almacenados en memoria local (localStorage)
                        $("body").append("<div class='smx-contenedor-marcadores'>" +
                                         "      <div class='smx-titulo-historico'>" + util.textos.historicoMarcadores +
                                         "              <span class='smx-eliminar'></span>" +
                                         "              <div class='smx-inpor-expor-container'>" +
                                         "                      <span class='smx-exportar' alt='" + util.textos.btoExportar + "'></span>" +
                                         "                      <span class='smx-importar' alt='" + util.textos.btoImportar + "'></span>" +
                                         "              </div>" +
                                         "      </div>" +
                                         "      <div class='smx-area-texto'>" +
                                         "              <textarea></textarea>" +
                                         "              <span class='smx-importar smx-do-importar' alt='" + util.textos.btoImportar + "'></span>" +
                                         "      </div>" +
                                         "</div>");
                },

                //Cacheo de elementos
                cacheElements:  function () {
                        this.contenedor = $(".smx-contenedor");
                        this.btoIr = this.contenedor.find(".smx-boton");
                        this.btoListaMarcadores = this.contenedor.find(".smx-lista-marcadores");
                        this.infoNuevoMarcador = $(".smx-info");

                        this.marcable = $(".smx-marcable");

                        this.contenedorMarcadores = $(".smx-contenedor-marcadores");
                        this.eliminar = this.contenedorMarcadores.find(".smx-eliminar");
                        this.btoExportar = this.contenedorMarcadores.find(".smx-exportar");
                        this.btoImportar = this.contenedorMarcadores.find(".smx-importar");
                        this.txtArea = this.contenedorMarcadores.find(".smx-area-texto");
                        this.doImportar = this.txtArea.find(".smx-do-importar");
                },

                // Retorna si hay marcadores o no (true/false)
                // Actualiza el panel de listado de marcadores
                cargarHistoricoMarcadores: function () {

                        // Recupera de localStorage todos los marcadores almacenados y los muestra
                        var marcadores = util.cache.getBookMarksHistory(),
                                marcadoresHTML = "",
                                infoMarcador,
                                fm;

                        // Primero se borra todo el historico de marcadores para luego volver a cargarlo actualizado
                        // Este selector no se puede cachear en la carga de la página porque en ese momento no existen los elementos a seleccionar.
                        $(".smx-marcador-historico").remove();

                        log("Cargando histórico de marcadores");

                        // NOTE: no es buena idea utilizar elementos 'ul' ya que es muy probable que la página tenga estilos por defecto para ese elemento
                        if (marcadores && marcadores.length > 0) {
                                log("Parece que hay marcadores que añadir");
                                marcadores.forEach(function (reg) {
                                        fm = new Date(reg.id); // Fecha del marcador
                                        infoMarcador = reg.percent + "% " + fm.getDate() + "/" + (fm.getMonth() + 1) + "/" + fm.getFullYear() + " " + fm.getHours() + ":" + fm.getMinutes() + ":" + fm.getSeconds() + ": " + reg.tip;
                                        marcadoresHTML = "<div class='smx-marcador-historico'><span class='smx-eliminar' data-id='" + reg.id + "'></span>" + infoMarcador + "</div>" + marcadoresHTML;
                                });

                                this.contenedorMarcadores.append(marcadoresHTML);

                                // Añadir el marcador principal a la página
                                this.agregarMarcadorAlmacenado(marcadores[marcadores.length - 1]);

                                this.activarBoton();
                                this.hayMarcador = true;

                                return true;

                        } else {
                                log("No hay marcadores");
                                this.desactivarBoton();
                                this.hayMarcador = false;
                                return false;
                        }

                },

                bindElements: function () {

                        //Solo es posible añadir un marcador a los elementos h1, h2, h3, h4, y p.
                        $("h1, h2, h3, h4, p").on("dblclick", function (event) {
                                if (event.ctrlKey) {
                                        this.setMarcador.call(this, event);
                                }
                        }.bind(this));

                        $("h1, h2, h3, h4, p").on("mouseover", function (event) {

                                // Mostrar etiqueta informativa de elementno "marcable";
                                $(event.target).prepend(this.marcable);
                                this.marcable.css("opacity", "0.6");
                        }.bind(this));

                        $("h1, h2, h3, h4, p").on("mouseout", function (event) {

                                // Esconder etiqueta informativa de elementno "marcable";
                                this.marcable.css("opacity", "0");
                        }.bind(this));

                        this.btoIr.on("click", function () {
                                window.location.hash = this.ANCHOR;
                        }.bind(this));

                        this.btoListaMarcadores.on("click", function () {
                                this.contenedorMarcadores.show();
                        }.bind(this));

                        this.contenedorMarcadores.on("mouseleave", function (event) {
                                $(event.target).delay(500).queue(function () {
                                        $(event.target).hide("fast").dequeue();
                                        this.txtArea.hide();
                                }.bind(this));
                        }.bind(this));

                        // Se usa la delegación del evento "click" porque en el momento de cargar la página los elementos
                        // a los que se pretende enlazar aún no existen.
                        this.contenedorMarcadores.on("click", ".smx-eliminar", this.confirmarEliminar.bind(this));

                        this.contenedorMarcadores.on("click", ".smx-exportar", this.exportar.bind(this));
                        this.contenedorMarcadores.on("click", ".smx-importar", this.importar.bind(this));

                        this.contenedorMarcadores.on("mouseout", ".smx-eliminar", function (event) {
                                this.confirmacionEliminacion = false;
                                $(event.target).removeClass("smx-eliminar-confirmar");
                        }.bind(this));

                },

                setMarcador: function (event) {

                        // Llamada a la función que guarda la información en localStorage
                        // Machaca si existe un marcador anterior
                        $("a[name='" + this.ANCHOR + "']").remove();

                        var marcador = new util.cache.BookMarckObject();

                        marcador.type = $(event.target)[0].tagName;

                        //Selector con todos los elementos del mismo tipo que el seleccionado
                        var elementos = $($(event.target)[0].tagName);
                        $.each(elementos, function (i) {
                                if (this === event.target) {
                                        marcador.position = i;
                                        marcador.tip = $.trim($(this).text().slice(0, 50)).slice(0, 25) + "...";
                                }
                        });

                        // Cálculo del porcentaje de avance de lectura
                        marcador.percent = Math.round(((marcador.position + 1) * 100) / elementos.length);

                        // Guarda en localStorage el marcador de la página
                        util.cache.setBookMark(marcador);

                        // Se incluye el marcador en la página para ser usuado en esta sesión
                        $(event.target).before("<a name='" + this.ANCHOR + "'></a>");

                        this.activarBoton();
                        this.hayMarcador = true;

                        // Actualiza el panel de histórico de marcadores
                        this.cargarHistoricoMarcadores();

                        // Muestra, mediante animación, que se ha añadido un marcador
                        this.infoNuevoMarcador.css('width', '320px')
                                .delay(2000).queue(function () {
                                        this.infoNuevoMarcador.css('width', '160px').dequeue();
                                }.bind(this));
                        log('Marcador añadido: ' + $(event.target)[0].tagName);
                },

                // Función ejecutada al iniciar que recoge de localStorage el marcador
                // y añade en el lugar adecuado <a name="marcador"></a>
                agregarMarcadorAlmacenado: function (marcador) {
                        var elementos;

                        // Si hay un marcador para esta página
                        if (marcador) {

                                //Colección de los elementos del tipo del elemento marcado
                                elementos = $(marcador.type);

                                $.each(elementos, function (i, elemento) {
                                        if (i === marcador.position) {
                                                $(elemento).before("<a name='" + this.ANCHOR + "'></a>");
                                                return false;
                                        }
                                }.bind(this));

                                log("Marcador Almacenado agregado a la página.");
                        }
                },

                confirmarEliminar: function (event) {
                        var idMarcador;
                        if (this.hayMarcador) {
                                if (!this.confirmacionEliminacion) {
                                        $(event.target).addClass("smx-eliminar-confirmar");
                                        this.confirmacionEliminacion = true;
                                } else {
                                        this.confirmacionEliminacion = false;
                                        $(event.target).removeClass("smx-eliminar-confirmar");
                                        idMarcador = $(event.target).data("id");
                                        this.eliminarMarcador(idMarcador);
                                }
                        }
                },

                eliminarMarcador: function (idMarcador) {
                        $("a[name='" + this.ANCHOR + "']").remove();

                        // Se permite eliminar todos los marcadores o solo uno
                        if (idMarcador) {
                                util.cache.deleteBookMark(idMarcador);
                                this.hayMarcador = this.cargarHistoricoMarcadores();

                                if (!this.hayMarcador) {
                                        this.desactivarBoton();
                                }
                        } else {
                                util.cache.deleteBookMark();
                                this.cargarHistoricoMarcadores();
                                this.desactivarBoton();
                                this.hayMarcador = false;
                        }
                },

                exportar: function (event) {

                        // TODO: Implementar función de exportación: Leer último marcador guardado y mostrarlo por pantalla
                        var marcador = new util.cache.BookMarckObject();

                        this.txtArea.show("slow");
                        this.doImportar.hide("slow");
                },

                importar: function (event) {

                        // TODO: Implementar función de eimportación.
                        // Leer el marcador pegado en un campo de texto, parsearle e invocar a Util.cache.setBookMark
                        var marcador = new util.cache.BookMarckObject();

                        this.txtArea.show("slow");
                        this.doImportar.show("slow");
                },

                desactivarBoton: function () {
                        this.infoNuevoMarcador.removeClass("activo");
                        this.contenedor.removeClass("activo").css("cursor", "text");
                        this.btoListaMarcadores.css("cursor", "pointer");
                        this.btoIr.text(util.textos.btoIrNoHayMarcador).addClass("smx-boton-hover-off smx-boton-active-off");

                        this.eliminar.addClass("off");
                        this.btoExportar.addClass("off");
                        this.btoImportar.addClass("off");
                },

                activarBoton: function () {
                        this.infoNuevoMarcador.addClass("activo");
                        this.contenedor.addClass("activo").css("cursor", "pointer");
                        this.btoIr.text(util.textos.btoIrHayMarcador).removeClass("smx-boton-hover-off smx-boton-active-off");

                        this.eliminar.removeClass("off");
                        this.btoExportar.removeClass("off");
                        this.btoImportar.removeClass("off");
                }
        };

        // Cargar jQuery si la página no lo tiene.
        var isJQuery = (typeof jQuery === "undefined") ? false : true;

        // Si la página no dispone de jQuery hay que incluirlo, por lo que se debe esperar un tiempo
        // a que la biblioteca se descargue
        if (!isJQuery) {
                log(">>No se ha detectado jQuery en la página, por lo que se procede a su carga...");
                var script = document.createElement("script");
                script.src = "http://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js";
                document.head.appendChild(script);

                // NOTE: setTimeout() causes javascript to use the global scope ('this' is 'window')
                setTimeout(App.loadScript.bind(App), 6000);
        } else {

                // Si se dispone de jQuery se podrá esperar menos, pero hay que dar tiempo a que la página cargue completamente
                // Las páginas maś complejas se cargan desde varias fuentes, por lo que el "ready" de jQuery no es definitivo.
                log(">>La página ya dispone de jQuery. Se comenzará con el Script en 2 segundos.");

                // NOTE: setTimeout() causes javascript to use the global scope ('this' is 'window')
                setTimeout(App.loadScript.bind(App), 2000);
        }
}());


text:
$(function(){
    $("#goods_regular").on(ace.click_event, function() {
        $.post(
            '?r=goods/default/ajaxgoodslist',
            {},
            function (data) {
                bootbox.dialog({
                    message: data,
                    buttons:
                    {
                        "success" :
                        {
                            "label" : "<i class='icon-ok'></i> 确定",
                            "className" : "btn-sm btn-success",
                            "callback": function() {
                                var goods_id = $("input[name='goods_id']:checked").val();
                                var goods_name = $("input[name='goods_id']:checked").attr('data');

                                $('#goods_regular').val(goods_name);
                                $('#goods_regular_id').val(goods_id);
                            }
                        }
                    }
                });
            }
        );

    });

    /*表单验证*/
    $('#validation-form').validate({
        errorElement: 'div',
        errorClass: 'help-block',
        focusInvalid: false,
        rules: {
            'Seckill[goods_name]':{
                required:true
            },
            'Seckill[goods_id]': {
                required: true
            },
            'Seckill[num]':{
                required:true
            },
            'Seckill[price]':{
                required:true
            }
        },

        messages: {
            'Seckill[goods_name]':{
                required:"秒杀商品不能为空"
            },
            'Seckill[goods_id]':{
                required:"秒杀商品不能为空"
            },
            'Seckill[num]':{
                required:"秒杀商品数量不能为空"
            },
            'Seckill[price]':{
                required:"秒杀商品价格不能为空"
            }
        },

        invalidHandler: function (event, validator) { //display error alert on form submit
            $('.alert-danger', $('.login-form')).show();
        },

        highlight: function (e) {
            $(e).closest('.form-group').removeClass('has-info').addClass('has-error');
        },

        success: function (e) {
            $(e).closest('.form-group').removeClass('has-error').addClass('has-info');
            $(e).remove();
        },

        errorPlacement: function (error, element) {
            if(element.is(':checkbox') || element.is(':radio')) {
                var controls = element.closest('div[class*="col-"]');
                if(controls.find(':checkbox,:radio').length > 1) controls.append(error);
                else error.insertAfter(element.nextAll('.lbl:eq(0)').eq(0));
            }
            else if(element.is('.select2')) {
                error.insertAfter(element.siblings('[class*="select2-container"]:eq(0)'));
            }
            else if(element.is('.chosen-select')) {
                error.insertAfter(element.siblings('[class*="chosen-container"]:eq(0)'));
            }
            else error.insertAfter(element.parent());
        },

        submitHandler: function (form) {
            form.submit();
        },
        invalidHandler: function (form) {
        }
    });

    $('input[name="Seckill[start_date]"]').datepicker(
        {format:'yyyy-m-d'}
    );

    $('input[name="Seckill[end_date]"]').datepicker(
        {format:'yyyy-m-d'}
    );

    $('#timepicker_start').timepicker({
        minuteStep: 1,
        showSeconds: true,
        showMeridian: false
    }).next().on(ace.click_event, function(){
        $(this).prev().focus();
    });

    $('#timepicker_end').timepicker({
        minuteStep: 1,
        showSeconds: true,
        showMeridian: false
    }).next().on(ace.click_event, function(){
        $(this).prev().focus();
    });
});

redpajama_set_name: RedPajamaGithub


text:
use crate::{RocksEngine, RocksWriteBatch};

use engine_traits::{Error, RaftEngine, RaftLogBatch, Result};
use engine_traits::{
    Iterable, KvEngine, MiscExt, Mutable, Peekable, SyncMutable, WriteBatch, WriteBatchExt,
    WriteOptions, CF_DEFAULT,
};
use kvproto::raft_serverpb::RaftLocalState;
use protobuf::Message;
use raft::eraftpb::Entry;

const RAFT_LOG_MULTI_GET_CNT: u64 = 8;

// FIXME: RaftEngine should probably be implemented generically
// for all KvEngines, but is currently implemented separately for
// every engine.
impl RaftEngine for RocksEngine {
    type LogBatch = RocksWriteBatch;

    fn log_batch(&self, capacity: usize) -> Self::LogBatch {
        RocksWriteBatch::with_capacity(self.as_inner().clone(), capacity)
    }

    fn sync(&self) -> Result<()> {
        self.sync_wal()
    }

    fn get_raft_state(&self, raft_group_id: u64) -> Result<Option<RaftLocalState>> {
        let key = keys::raft_state_key(raft_group_id);
        self.get_msg_cf(CF_DEFAULT, &key)
    }

    fn get_entry(&self, raft_group_id: u64, index: u64) -> Result<Option<Entry>> {
        let key = keys::raft_log_key(raft_group_id, index);
        self.get_msg_cf(CF_DEFAULT, &key)
    }

    fn fetch_entries_to(
        &self,
        region_id: u64,
        low: u64,
        high: u64,
        max_size: Option<usize>,
        buf: &mut Vec<Entry>,
    ) -> Result<usize> {
        let (max_size, mut total_size, mut count) = (max_size.unwrap_or(usize::MAX), 0, 0);

        if high - low <= RAFT_LOG_MULTI_GET_CNT {
            // If election happens in inactive regions, they will just try to fetch one empty log.
            for i in low..high {
                if total_size > 0 && total_size >= max_size {
                    break;
                }
                let key = keys::raft_log_key(region_id, i);
                match self.get_value(&key) {
                    Ok(None) => return Err(Error::EntriesCompacted),
                    Ok(Some(v)) => {
                        let mut entry = Entry::default();
                        entry.merge_from_bytes(&v)?;
                        assert_eq!(entry.get_index(), i);
                        buf.push(entry);
                        total_size += v.len();
                        count += 1;
                    }
                    Err(e) => return Err(box_err!(e)),
                }
            }
            return Ok(count);
        }

        let (mut check_compacted, mut next_index) = (true, low);
        let start_key = keys::raft_log_key(region_id, low);
        let end_key = keys::raft_log_key(region_id, high);
        self.scan(
            &start_key,
            &end_key,
            true, // fill_cache
            |_, value| {
                let mut entry = Entry::default();
                entry.merge_from_bytes(value)?;

                if check_compacted {
                    if entry.get_index() != low {
                        // May meet gap or has been compacted.
                        return Ok(false);
                    }
                    check_compacted = false;
                } else {
                    assert_eq!(entry.get_index(), next_index);
                }
                next_index += 1;

                buf.push(entry);
                total_size += value.len();
                count += 1;
                Ok(total_size < max_size)
            },
        )?;

        // If we get the correct number of entries, returns.
        // Or the total size almost exceeds max_size, returns.
        if count == (high - low) as usize || total_size >= max_size {
            return Ok(count);
        }

        // Here means we don't fetch enough entries.
        Err(Error::EntriesUnavailable)
    }

    fn consume(&self, batch: &mut Self::LogBatch, sync_log: bool) -> Result<usize> {
        let bytes = batch.data_size();
        let mut opts = WriteOptions::default();
        opts.set_sync(sync_log);
        batch.write_opt(&opts)?;
        batch.clear();
        Ok(bytes)
    }

    fn consume_and_shrink(
        &self,
        batch: &mut Self::LogBatch,
        sync_log: bool,
        max_capacity: usize,
        shrink_to: usize,
    ) -> Result<usize> {
        let data_size = self.consume(batch, sync_log)?;
        if data_size > max_capacity {
            *batch = self.write_batch_with_cap(shrink_to);
        }
        Ok(data_size)
    }

    fn clean(
        &self,
        raft_group_id: u64,
        state: &RaftLocalState,
        batch: &mut Self::LogBatch,
    ) -> Result<()> {
        batch.delete(&keys::raft_state_key(raft_group_id))?;
        let seek_key = keys::raft_log_key(raft_group_id, 0);
        let prefix = keys::raft_log_prefix(raft_group_id);
        if let Some((key, _)) = self.seek(&seek_key)? {
            if !key.starts_with(&prefix) {
                // No raft logs for the raft group.
                return Ok(());
            }
            let first_index = match keys::raft_log_index(&key) {
                Ok(index) => index,
                Err(_) => return Ok(()),
            };
            for index in first_index..=state.last_index {
                let key = keys::raft_log_key(raft_group_id, index);
                batch.delete(&key)?;
            }
        }
        Ok(())
    }

    fn append(&self, raft_group_id: u64, entries: Vec<Entry>) -> Result<usize> {
        let mut wb = RocksWriteBatch::new(self.as_inner().clone());
        let buf = Vec::with_capacity(1024);
        wb.append_impl(raft_group_id, &entries, buf)?;
        self.consume(&mut wb, false)
    }

    fn put_raft_state(&self, raft_group_id: u64, state: &RaftLocalState) -> Result<()> {
        self.put_msg(&keys::raft_state_key(raft_group_id), state)
    }

    fn gc(&self, raft_group_id: u64, mut from: u64, to: u64) -> Result<usize> {
        if from >= to {
            return Ok(0);
        }
        if from == 0 {
            let start_key = keys::raft_log_key(raft_group_id, 0);
            let prefix = keys::raft_log_prefix(raft_group_id);
            match self.seek(&start_key)? {
                Some((k, _)) if k.starts_with(&prefix) => from = box_try!(keys::raft_log_index(&k)),
                // No need to gc.
                _ => return Ok(0),
            }
        }

        let mut raft_wb = self.write_batch_with_cap(4 * 1024);
        for idx in from..to {
            let key = keys::raft_log_key(raft_group_id, idx);
            raft_wb.delete(&key)?;
            if raft_wb.count() >= Self::WRITE_BATCH_MAX_KEYS {
                raft_wb.write()?;
                raft_wb.clear();
            }
        }

        // TODO: disable WAL here.
        if !Mutable::is_empty(&raft_wb) {
            raft_wb.write()?;
        }
        Ok((to - from) as usize)
    }

    fn purge_expired_files(&self) -> Result<Vec<u64>> {
        Ok(vec![])
    }

    fn has_builtin_entry_cache(&self) -> bool {
        false
    }

    fn flush_metrics(&self, instance: &str) {
        KvEngine::flush_metrics(self, instance)
    }

    fn reset_statistics(&self) {
        KvEngine::reset_statistics(self)
    }

    fn dump_stats(&self) -> Result<String> {
        MiscExt::dump_stats(self)
    }
}

impl RaftLogBatch for RocksWriteBatch {
    fn append(&mut self, raft_group_id: u64, entries: Vec<Entry>) -> Result<()> {
        if let Some(max_size) = entries.iter().map(|e| e.compute_size()).max() {
            let ser_buf = Vec::with_capacity(max_size as usize);
            return self.append_impl(raft_group_id, &entries, ser_buf);
        }
        Ok(())
    }

    fn cut_logs(&mut self, raft_group_id: u64, from: u64, to: u64) {
        for index in from..to {
            let key = keys::raft_log_key(raft_group_id, index);
            self.delete(&key).unwrap();
        }
    }

    fn put_raft_state(&mut self, raft_group_id: u64, state: &RaftLocalState) -> Result<()> {
        self.put_msg(&keys::raft_state_key(raft_group_id), state)
    }

    fn is_empty(&self) -> bool {
        Mutable::is_empty(self)
    }
}

impl RocksWriteBatch {
    fn append_impl(
        &mut self,
        raft_group_id: u64,
        entries: &[Entry],
        mut ser_buf: Vec<u8>,
    ) -> Result<()> {
        for entry in entries {
            let key = keys::raft_log_key(raft_group_id, entry.get_index());
            ser_buf.clear();
            entry.write_to_vec(&mut ser_buf).unwrap();
            self.put(&key, &ser_buf)?;
        }
        Ok(())
    }
}


text: exports.filename = "foo/bar.js";


text:
'use strict';

import { Event } from 'vs/base/common/event';
import { createDecorator, ServiceIdentifier, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { IEditorInput, IEditor, GroupIdentifier, IEditorInputWithOptions, CloseDirection } from 'vs/workbench/common/editor';
import { IEditorOptions, ITextEditorOptions } from 'vs/platform/editor/common/editor';
import { TPromise } from 'vs/base/common/winjs.base';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';

export const IEditorGroupsService = createDecorator<IEditorGroupsService>('editorGroupsService');

export enum GroupDirection {
	UP,
	DOWN,
	LEFT,
	RIGHT
}

export function preferredSideBySideGroupDirection(configurationService: IConfigurationService): GroupDirection.DOWN | GroupDirection.RIGHT {
	const openSideBySideDirection = configurationService.getValue<'right' | 'down'>('workbench.editor.openSideBySideDirection');

	if (openSideBySideDirection === 'down') {
		return GroupDirection.DOWN;
	}

	return GroupDirection.RIGHT;
}

export enum GroupOrientation {
	HORIZONTAL,
	VERTICAL
}

export enum GroupLocation {
	FIRST,
	LAST,
	NEXT,
	PREVIOUS
}

export interface IFindGroupScope {
	direction?: GroupDirection;
	location?: GroupLocation;
}

export enum GroupsArrangement {

	/**
	 * Make the current active group consume the maximum
	 * amount of space possible.
	 */
	MINIMIZE_OTHERS,

	/**
	 * Size all groups evenly.
	 */
	EVEN
}

export interface GroupLayoutArgument {
	size?: number;
	groups?: GroupLayoutArgument[];
}

export interface EditorGroupLayout {
	orientation: GroupOrientation;
	groups: GroupLayoutArgument[];
}

export interface IMoveEditorOptions {
	index?: number;
	inactive?: boolean;
	preserveFocus?: boolean;
}

export interface ICopyEditorOptions extends IMoveEditorOptions { }

export interface IAddGroupOptions {
	activate?: boolean;
}

export enum MergeGroupMode {
	COPY_EDITORS,
	MOVE_EDITORS
}

export interface IMergeGroupOptions {
	mode?: MergeGroupMode;
	index?: number;
}

export type ICloseEditorsFilter = {
	except?: IEditorInput,
	direction?: CloseDirection,
	savedOnly?: boolean
};

export interface IEditorReplacement {
	editor: IEditorInput;
	replacement: IEditorInput;
	options?: IEditorOptions | ITextEditorOptions;
}

export enum GroupsOrder {

	/**
	 * Groups sorted by creation order (oldest one first)
	 */
	CREATION_TIME,

	/**
	 * Groups sorted by most recent activity (most recent active first)
	 */
	MOST_RECENTLY_ACTIVE,

	/**
	 * Groups sorted by grid widget order
	 */
	GRID_APPEARANCE
}

export enum EditorsOrder {

	/**
	 * Editors sorted by most recent activity (most recent active first)
	 */
	MOST_RECENTLY_ACTIVE,

	/**
	 * Editors sorted by sequential order
	 */
	SEQUENTIAL
}

export interface IEditorGroupsService {

	_serviceBrand: ServiceIdentifier<any>;

	/**
	 * An event for when the active editor group changes. The active editor
	 * group is the default location for new editors to open.
	 */
	readonly onDidActiveGroupChange: Event<IEditorGroup>;

	/**
	 * An event for when a new group was added.
	 */
	readonly onDidAddGroup: Event<IEditorGroup>;

	/**
	 * An event for when a group was removed.
	 */
	readonly onDidRemoveGroup: Event<IEditorGroup>;

	/**
	 * An event for when a group was moved.
	 */
	readonly onDidMoveGroup: Event<IEditorGroup>;

	/**
	 * An active group is the default location for new editors to open.
	 */
	readonly activeGroup: IEditorGroup;

	/**
	 * All groups that are currently visible in the editor area in the
	 * order of their creation (oldest first).
	 */
	readonly groups: ReadonlyArray<IEditorGroup>;

	/**
	 * The number of editor groups that are currently opened.
	 */
	readonly count: number;

	/**
	 * The current layout orientation of the root group.
	 */
	readonly orientation: GroupOrientation;

	/**
	 * Get all groups that are currently visible in the editor area optionally
	 * sorted by being most recent active or grid order. Will sort by creation
	 * time by default (oldest group first).
	 */
	getGroups(order?: GroupsOrder): ReadonlyArray<IEditorGroup>;

	/**
	 * Allows to convert a group identifier to a group.
	 */
	getGroup(identifier: GroupIdentifier): IEditorGroup;

	/**
	 * Set a group as active. An active group is the default location for new editors to open.
	 */
	activateGroup(group: IEditorGroup | GroupIdentifier): IEditorGroup;

	/**
	 * Returns the size of a group.
	 */
	getSize(group: IEditorGroup | GroupIdentifier): number;

	/**
	 * Sets the size of a group.
	 */
	setSize(group: IEditorGroup | GroupIdentifier, size: number): void;

	/**
	 * Arrange all groups according to the provided arrangement.
	 */
	arrangeGroups(arrangement: GroupsArrangement): void;

	/**
	 * Applies the provided layout by either moving existing groups or creating new groups.
	 */
	applyLayout(layout: EditorGroupLayout): void;

	/**
	 * Sets the orientation of the root group to be either vertical or horizontal.
	 */
	setGroupOrientation(orientation: GroupOrientation): void;

	/**
	 * Find a groupd in a specific scope:
	 * * `GroupLocation.FIRST`: the first group
	 * * `GroupLocation.LAST`: the last group
	 * * `GroupLocation.NEXT`: the next group from either the active one or `source`
	 * * `GroupLocation.PREVIOUS`: the previous group from either the active one or `source`
	 * * `GroupDirection.UP`: the next group above the active one or `source`
	 * * `GroupDirection.DOWN`: the next group below the active one or `source`
	 * * `GroupDirection.LEFT`: the next group to the left of the active one or `source`
	 * * `GroupDirection.RIGHT`: the next group to the right of the active one or `source`
	 *
	 * @param scope the scope of the group to search in
	 * @param source optional source to search from
	 * @param wrap optionally wrap around if reaching the edge of groups
	 */
	findGroup(scope: IFindGroupScope, source?: IEditorGroup | GroupIdentifier, wrap?: boolean): IEditorGroup;

	/**
	 * Add a new group to the editor area. A new group is added by splitting a provided one in
	 * one of the four directions.
	 *
	 * @param location the group from which to split to add a new group
	 * @param direction the direction of where to split to
	 * @param options configure the newly group with options
	 */
	addGroup(location: IEditorGroup | GroupIdentifier, direction: GroupDirection, options?: IAddGroupOptions): IEditorGroup;

	/**
	 * Remove a group from the editor area.
	 */
	removeGroup(group: IEditorGroup | GroupIdentifier): void;

	/**
	 * Move a group to a new group in the editor area.
	 *
	 * @param group the group to move
	 * @param location the group from which to split to add the moved group
	 * @param direction the direction of where to split to
	 */
	moveGroup(group: IEditorGroup | GroupIdentifier, location: IEditorGroup | GroupIdentifier, direction: GroupDirection): IEditorGroup;

	/**
	 * Merge the editors of a group into a target group. By default, all editors will
	 * move and the source group will close. This behaviour can be configured via the
	 * `IMergeGroupOptions` options.
	 *
	 * @param group the group to merge
	 * @param target the target group to merge into
	 * @param options controls how the merge should be performed. by default all editors
	 * will be moved over to the target and the source group will close. Configure to
	 * `MOVE_EDITORS_KEEP_GROUP` to prevent the source group from closing. Set to
	 * `COPY_EDITORS` to copy the editors into the target instead of moding them.
	 */
	mergeGroup(group: IEditorGroup | GroupIdentifier, target: IEditorGroup | GroupIdentifier, options?: IMergeGroupOptions): IEditorGroup;

	/**
	 * Copy a group to a new group in the editor area.
	 *
	 * @param group the group to copy
	 * @param location the group from which to split to add the copied group
	 * @param direction the direction of where to split to
	 */
	copyGroup(group: IEditorGroup | GroupIdentifier, location: IEditorGroup | GroupIdentifier, direction: GroupDirection): IEditorGroup;
}

export enum GroupChangeKind {

	/* Group Changes */
	GROUP_ACTIVE,
	GROUP_LABEL,

	/* Editor Changes */
	EDITOR_OPEN,
	EDITOR_CLOSE,
	EDITOR_MOVE,
	EDITOR_ACTIVE,
	EDITOR_LABEL,
	EDITOR_PIN,
	EDITOR_DIRTY
}

export interface IGroupChangeEvent {
	kind: GroupChangeKind;
	editor?: IEditorInput;
	editorIndex?: number;
}

export interface IEditorGroup {

	/**
	 * An aggregated event for when the group changes in any way.
	 */
	readonly onDidGroupChange: Event<IGroupChangeEvent>;

	/**
	 * A unique identifier of this group that remains identical even if the
	 * group is moved to different locations.
	 */
	readonly id: GroupIdentifier;

	/**
	 * A human readable label for the group. This label can change depending
	 * on the layout of all editor groups. Clients should listen on the
	 * `onDidGroupChange` event to react to that.
	 */
	readonly label: string;

	/**
	 * The active control is the currently visible control of the group.
	 */
	readonly activeControl: IEditor;

	/**
	 * The active editor is the currently visible editor of the group
	 * within the current active control.
	 */
	readonly activeEditor: IEditorInput;

	/**
	 * The editor in the group that is in preview mode if any. There can
	 * only ever be one editor in preview mode.
	 */
	readonly previewEditor: IEditorInput;

	/**
	 * The number of opend editors in this group.
	 */
	readonly count: number;

	/**
	 * All opened editors in the group. There can only be one editor active.
	 */
	readonly editors: ReadonlyArray<IEditorInput>;

	/**
	 * Returns the editor at a specific index of the group.
	 */
	getEditor(index: number): IEditorInput;

	/**
	 * Get all editors that are currently opened in the group optionally
	 * sorted by being most recent active. Will sort by sequential appearance
	 * by default (from left to right).
	 */
	getEditors(order?: EditorsOrder): ReadonlyArray<IEditorInput>;

	/**
	 * Returns the index of the editor in the group or -1 if not opened.
	 */
	getIndexOfEditor(editor: IEditorInput): number;

	/**
	 * Open an editor in this group.
	 *
	 * @returns a promise that is resolved when the active editor (if any)
	 * has finished loading
	 */
	openEditor(editor: IEditorInput, options?: IEditorOptions | ITextEditorOptions): TPromise<void>;

	/**
	 * Opens editors in this group.
	 *
	 * @returns a promise that is resolved when the active editor (if any)
	 * has finished loading
	 */
	openEditors(editors: IEditorInputWithOptions[]): TPromise<void>;

	/**
	 * Find out if the provided editor is opened in the group.
	 *
	 * Note: An editor can be opened but not actively visible.
	 */
	isOpened(editor: IEditorInput): boolean;

	/**
	 * Find out if the provided editor is pinned in the group.
	 */
	isPinned(editor: IEditorInput): boolean;

	/**
	 * Find out if the provided editor is active in the group.
	 */
	isActive(editor: IEditorInput): boolean;

	/**
	 * Move an editor from this group either within this group or to another group.
	 */
	moveEditor(editor: IEditorInput, target: IEditorGroup, options?: IMoveEditorOptions): void;

	/**
	 * Copy an editor from this group to another group.
	 *
	 * Note: It is currently not supported to show the same editor more than once in the same group.
	 */
	copyEditor(editor: IEditorInput, target: IEditorGroup, options?: ICopyEditorOptions): void;

	/**
	 * Close an editor from the group. This may trigger a confirmation dialog if
	 * the editor is dirty and thus returns a promise as value.
	 *
	 * @param editor the editor to close, or the currently active editor
	 * if unspecified.
	 *
	 * @returns a promise when the editor is closed.
	 */
	closeEditor(editor?: IEditorInput): TPromise<void>;

	/**
	 * Closes specific editors in this group. This may trigger a confirmation dialog if
	 * there are dirty editors and thus returns a promise as value.
	 *
	 * @returns a promise when all editors are closed.
	 */
	closeEditors(editors: IEditorInput[] | ICloseEditorsFilter): TPromise<void>;

	/**
	 * Closes all editors from the group. This may trigger a confirmation dialog if
	 * there are dirty editors and thus returns a promise as value.
	 *
	 * @returns a promise when all editors are closed.
	 */
	closeAllEditors(): TPromise<void>;

	/**
	 * Replaces editors in this group with the provided replacement.
	 *
	 * @param editors the editors to replace
	 *
	 * @returns a promise that is resolved when the replaced active
	 * editor (if any) has finished loading.
	 */
	replaceEditors(editors: IEditorReplacement[]): TPromise<void>;

	/**
	 * Set an editor to be pinned. A pinned editor is not replaced
	 * when another editor opens at the same location.
	 *
	 * @param editor the editor to pin, or the currently active editor
	 * if unspecified.
	 */
	pinEditor(editor?: IEditorInput): void;

	/**
	 * Move keyboard focus into the group.
	 */
	focus(): void;

	/**
	 * Invoke a function in the context of the services of this group.
	 */
	invokeWithinContext<T>(fn: (accessor: ServicesAccessor) => T): T;
}


text:
'-------------------------------------------------------------------------------------------'
' Inicio del codigo
'-------------------------------------------------------------------------------------------'
' Importando librerias
'-------------------------------------------------------------------------------------------'
Imports System.Data

'-------------------------------------------------------------------------------------------'
' Inicio de clase "rSucursales"
'-------------------------------------------------------------------------------------------'
Partial Class rSucursales
    Inherits vis2Formularios.frmReporte

    Dim loObjetoReporte As CrystalDecisions.CrystalReports.Engine.ReportDocument

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

        Try

            Dim lcParametro0Desde As String = goServicios.mObtenerCampoFormatoSQL(cusAplicacion.goReportes.paParametrosIniciales(0))
            Dim lcParametro0Hasta As String = goServicios.mObtenerCampoFormatoSQL(cusAplicacion.goReportes.paParametrosFinales(0))
            Dim lcParametro1Desde As String = goServicios.mObtenerListaFormatoSQL(cusAplicacion.goReportes.paParametrosIniciales(1))

            Dim loComandoSeleccionar As New StringBuilder()

            loComandoSeleccionar.AppendLine("  SELECT	Cod_Suc, ")
            loComandoSeleccionar.AppendLine("	        Nom_Suc, ")
            loComandoSeleccionar.AppendLine("           case Status ")
            loComandoSeleccionar.AppendLine("	            when  'A' then 'Activa' ")
            loComandoSeleccionar.AppendLine("	            when  'I' then 'Inactiva' ")
            loComandoSeleccionar.AppendLine("	            when  'S' then 'Suspendida' ")
            loComandoSeleccionar.AppendLine("           end as Status, ")
            loComandoSeleccionar.AppendLine("	        Contacto, ")
            loComandoSeleccionar.AppendLine("	        Fax, ")
            loComandoSeleccionar.AppendLine("	        Telefonos, ")
            loComandoSeleccionar.AppendLine("	        Direccion, ")
            loComandoSeleccionar.AppendLine("	        Correo ")
            loComandoSeleccionar.AppendLine(" FROM      Sucursales ")
            loComandoSeleccionar.AppendLine(" WHERE     ")
            loComandoSeleccionar.AppendLine(" 			Cod_Suc BETWEEN " & lcParametro0Desde)
            loComandoSeleccionar.AppendLine(" 			AND " & lcParametro0Hasta)
            loComandoSeleccionar.AppendLine(" 			AND Status IN ( " & lcParametro1Desde & " ) ")
            loComandoSeleccionar.AppendLine(" ORDER BY  Nom_Suc ")

            Dim loServicios As New cusDatos.goDatos

            Dim laDatosReporte As DataSet = loServicios.mObtenerTodos(loComandoSeleccionar.ToString, "curReportes")

            loObjetoReporte = cusAplicacion.goReportes.mCargarReporte("rSucursales", laDatosReporte)

            Me.mTraducirReporte(loObjetoReporte)

            Me.mFormatearCamposReporte(loObjetoReporte)

            Me.crvrSucursales.ReportSource = loObjetoReporte

        Catch loExcepcion As Exception

            Me.WbcAdministradorMensajeModal.mMostrarMensajeModal("Error", _
                          "No se pudo Completar el Proceso: " & loExcepcion.Message, _
                           vis3Controles.wbcAdministradorMensajeModal.enumTipoMensaje.KN_Error, _
                           "auto", _
                           "auto")

        End Try
    End Sub

    Protected Sub Page_Unload(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Unload

        Try

            loObjetoReporte.Close()

        Catch loExcepcion As Exception

        End Try

    End Sub
End Class

'-------------------------------------------------------------------------------------------'
' Fin del codigo
'-------------------------------------------------------------------------------------------'
' CMS: 22/09/08: Programacion inicial
'-------------------------------------------------------------------------------------------'


text:
<?php

namespace Doctrine\ODM\MongoDB\Tests\Types;

use Doctrine\MongoDB\GridFSFile;
use Doctrine\ODM\MongoDB\Types\Type;
use MongoBinData;

class TypeTest extends \Doctrine\ODM\MongoDB\Tests\BaseTest
{
    /**
     * @dataProvider provideTypes
     */
    public function testConversion(Type $type, $test)
    {
        $this->assertEquals($test, $type->convertToPHPValue($type->convertToDatabaseValue($test)));
    }

    public function provideTypes()
    {
        return array(
            array(Type::getType(Type::ID), "507f1f77bcf86cd799439011"),
            array(Type::getType(Type::INTID), 1),
            array(Type::getType(Type::CUSTOMID), (object) array('foo' => 'bar')),
            array(Type::getType(Type::BOOL), true),
            array(Type::getType(Type::BOOLEAN), false),
            array(Type::getType(Type::INT), 69),
            array(Type::getType(Type::INTEGER), 42),
            array(Type::getType(Type::FLOAT), 3.14),
            array(Type::getType(Type::STRING), 'ohai'),
            array(Type::getType(Type::KEY), 0),
            array(Type::getType(Type::KEY), 1),
            array(Type::getType(Type::TIMESTAMP), time()),
            array(Type::getType(Type::BINDATA), 'foobarbaz'),
            array(Type::getType(Type::BINDATAFUNC), 'foobarbaz'),
            array(Type::getType(Type::BINDATABYTEARRAY), 'foobarbaz'),
            array(Type::getType(Type::BINDATAUUID), "7f1c6d80-3e0b-11e5-b8ed-0002a5d5c51b"),
            array(Type::getType(Type::BINDATAUUIDRFC4122), str_repeat('a', 16)),
            array(Type::getType(Type::BINDATAMD5), md5('ODM')),
            array(Type::getType(Type::BINDATACUSTOM), 'foobarbaz'),
            array(Type::getType(Type::FILE), new GridFSFile()),
            array(Type::getType(Type::HASH), array('foo' => 'bar')),
            array(Type::getType(Type::COLLECTION), array('foo', 'bar')),
            array(Type::getType(Type::INCREMENT), 1),
            array(Type::getType(Type::INCREMENT), 1.1),
            array(Type::getType(Type::OBJECTID), "507f1f77bcf86cd799439011"),
            array(Type::getType(Type::RAW), (object) array('foo' => 'bar')),
       );
    }

    /**
     * @dataProvider provideTypesForIdempotent
     */
    public function testConversionIsIdempotent(Type $type, $test)
    {
        $this->assertEquals($test, $type->convertToDatabaseValue($test));
    }

    public function provideTypesForIdempotent()
    {
        return array(
            array(Type::getType(Type::ID), new \MongoId()),
            array(Type::getType(Type::DATE), new \MongoDate()),
            array(Type::getType(Type::TIMESTAMP), new \MongoTimestamp()),
            array(Type::getType(Type::BINDATA), new MongoBinData('foobarbaz', 0)),
            array(Type::getType(Type::BINDATAFUNC), new MongoBinData('foobarbaz', MongoBinData::FUNC)),
            array(Type::getType(Type::BINDATABYTEARRAY), new MongoBinData('foobarbaz', MongoBinData::BYTE_ARRAY)),
            array(Type::getType(Type::BINDATAUUID), new MongoBinData("7f1c6d80-3e0b-11e5-b8ed-0002a5d5c51b", MongoBinData::UUID)),
            array(Type::getType(Type::BINDATAUUIDRFC4122), new MongoBinData(str_repeat('a', 16), 4)),
            array(Type::getType(Type::BINDATAMD5), new MongoBinData(md5('ODM'), MongoBinData::MD5)),
            array(Type::getType(Type::BINDATACUSTOM), new MongoBinData('foobarbaz', MongoBinData::CUSTOM)),
            array(Type::getType(Type::OBJECTID), new \MongoId()),
        );
    }

    public function testConvertDatePreservesMilliseconds()
    {
        $date = new \DateTime();
        $expectedDate = clone $date;

        $cleanMicroseconds = (int) floor(((int) $date->format('u')) / 1000) * 1000;
        $expectedDate->modify($date->format('H:i:s') . '.' . str_pad($cleanMicroseconds, 6, '0', STR_PAD_LEFT));

        $type = Type::getType(Type::DATE);
        $this->assertEquals($expectedDate, $type->convertToPHPValue($type->convertToDatabaseValue($date)));
    }

    public function testConvertImmutableDate()
    {
        $date = new \DateTimeImmutable('now');

        $this->assertInstanceOf('\MongoDate', Type::convertPHPToDatabaseValue($date));
    }
}


text:
require 'rails_helper'

describe 'cases/commissioning_documents/new', type: :view do
  context '#new' do
    let(:data_request) { create(:data_request) }
    let(:commissioning_document) { CommissioningDocument.new(data_request: data_request) }

    before do
      assign(:data_request, data_request)
      assign(:case, data_request.kase)
      assign(:commissioning_document, commissioning_document)

      render
      commissioning_document_page.load(rendered)
      @page = commissioning_document_page
    end

    it 'has required content' do
      expect(@page.page_heading.heading.text).to eq 'Select Day 1 request document'
      expect(@page.form).to have_template_name
      expect(@page.form.submit_button.value).to eq 'Download Day 1 request document'
    end
  end
end


text:
/**
 * Implements the QR code modal
 * @packageDocumentation
 */

import React from 'react';
import { Modal, Row, Col, Select, Space, Button } from 'antd/lib';
import QRCodeReact from 'qrcode.react';

import { LinkInfo } from './LinkInfo';
import './QrCode.less';

/**
 * Props for the [[QrCodeModal]] component
 * @interface
 */
export interface Props {
  /**
   * Whether the modal is vilible
   * @property
   */
  visible: boolean;

  /**
   * The [[LinkInfo]] of the link for which to display QR codes
   * @property
   */
  linkInfo: LinkInfo;

  /**
   * The width of the QR code
   * @property
   */
  width: number;

  /**
   * Callback called when the modal is closed
   * @property
   */
  onCancel: () => void;
}

/**
 * State for the [[QrCodeModal]] component
 * @interface
 */
export interface State {
  /**
   * The currently selected alias
   * @property
   */
  selectedAlias: string | null;

  /**
   * The short URL (e.g. `https://go.rutgers.edu/<alias>`) corresponding to
   * the currently selected alias
   * @property
   */
  selectedShortUrl: string | null;
}

/**
 * The [[QrCodeModal]] component implements the QR code modal as used on the dashboard
 * @class
 */
export class QrCodeModal extends React.Component<Props, State> {
  constructor(props: Props) {
    super(props);
    this.state = {
      selectedAlias: null,
      selectedShortUrl: null,
    };
  }

  componentDidMount(): void {
    this.resetAlias();
  }

  componentDidUpdate(prevProps: Props): void {
    if (this.props !== prevProps) {
      this.resetAlias();
    }
  }

  /**
   * Set the currently active alias to the first alias of the link
   * @method
   */
  resetAlias = (): void => {
    const { linkInfo } = this.props;
    if (linkInfo === null || linkInfo.aliases.length === 0) {
      return;
    }

    this.setAlias(linkInfo.aliases[0].alias);
  };

  /**
   * Update the selected alias and selected short URL
   * @method
   * @param alias The new alias
   */
  setAlias = (alias: string): void => {
    this.setState({
      selectedAlias: alias,
      selectedShortUrl: `${window.location.origin}/${alias}`,
    });
  };

  /**
   * Get a data URL of the QR code image
   * @method
   */
  getQrDataUrl = (): string => {
    const canvasCol = document.getElementsByClassName('qrcode-canvas');
    if (canvasCol.length === 0) {
      throw new Error('could not find QR code canvas');
    }

    const canvas = canvasCol[0] as HTMLCanvasElement;
    return canvas.toDataURL('image/png');
  };

  /**
   * Open a popup window containing the QR code and prompt the user to print it
   * @method
   */
  onPrint = (): void => {
    const popup = window.open();
    if (popup === null) {
      throw new Error('could not open window to print QR code');
    }

    popup.document.write(`
            <!DOCTYPE html>

            `);
    popup.focus();
    popup.print();
  };

  /**
   * Prompt the user to download the QR code for the selected alias
   * @method
   */
  onDownload = (): void => {
    const dlLink = document.createElement('a');
    dlLink.download = `${this.state.selectedAlias}.png`;
    dlLink.href = this.getQrDataUrl();
    document.body.appendChild(dlLink);
    dlLink.click();
  };

  render(): React.ReactNode {
    if (this.props.linkInfo === null) {
      return <></>;
    }

    const aliases = this.props.linkInfo.aliases.filter(
      (alias) => !alias.deleted,
    );

    return (
      <Modal
        visible={this.props.visible}
        title="QR code"
        onCancel={this.props.onCancel}
        width={this.props.width + 2 * 24}
        className="qr-modal"
        footer={
          <Space>
            <Button onClick={this.onPrint}>Print</Button>
            <Button onClick={this.onDownload}>Download</Button>
          </Space>
        }
      >
        {aliases.length <= 1 ? (
          <></>
        ) : (
          <Row>
            <Col>
              <Select
                onSelect={this.setAlias}
                defaultValue={aliases[0].alias}
                className="select"
                style={{ width: this.props.width }}
              >
                {aliases.map((alias) => (
                  <Select.Option key={alias.alias} value={alias.alias}>
                    {alias.alias}
                    {alias.description ? ({alias.description}) : <></>}
                  </Select.Option>
                ))}
              </Select>
            </Col>
          </Row>
        )}

        {this.state.selectedShortUrl === null ? (
          <></>
        ) : (
          <Row>
            <Col>
              <QRCodeReact
                value={this.state.selectedShortUrl}
                className="qrcode-canvas"
                size={this.props.width}
              />
            </Col>
          </Row>
        )}
      </Modal>
    );
  }
}


text:
import {describe, it, before, after, beforeEach} from 'mocha'
import {expect} from 'chai'
import fuerte from '..';
import {serverURL} from './util.js';

describe('Getting the server version', () => {
  describe('using the constructor', () => {
    const conn = new fuerte.connect(serverURL);
    it('has properties', (done) => {
      conn.get('/_api/version')
        .then((res) => {
          expect(res.body).to.haveOwnProperty('server');
          expect(res.body).to.haveOwnProperty('version');
          done();
        }).catch(done);
    })
  })
})


text:
package blade.migrate.liferay70;

import blade.migrate.api.FileMigrator;
import blade.migrate.core.JSPFileChecker;
import blade.migrate.core.JSPTagsFileMigrator;
import blade.migrate.core.SearchResult;

import java.io.File;
import java.util.List;

import org.osgi.service.component.annotations.Component;

@Component(
	property = {
		"file.extensions=jsp,jspf",
		"problem.title=Renamed URI Attribute Used to Generate AUI Tag Library",
		"problem.url=https://github.com/liferay/liferay-portal/blob/master/readme/7.0/BREAKING_CHANGES.markdown#renamed-uri-attribute-used-to-generate-aui-tag-library",
		"problem.summary=We should use the new AUI URI declaration:http://liferay.com/tld/aui",
		"problem.tickets=LPS-57809",
	},
	service = FileMigrator.class
)
public class AUILiferayTags extends JSPTagsFileMigrator {

	@Override
	protected List<SearchResult> searchJSPFile(File file,
			JSPFileChecker jspFileChecker) {

		return jspFileChecker.findJSPTags("jsp:directive.taglib",
				new String[] { "uri" },new String[] { "http://alloy.liferay.com/tld/aui" });
	}
}