<commit_before>"use strict"

var LeafletMap = function(mapId, opt){

    if (!mapId && !$("#"+mapId)){ return }
    this.mapId = mapId;

    if (!opt) {
        console.log("There is no options in LeafletMap, check this.");
        return;
     }

    var parent = this;

    this.mapTilesLayer; // copy of LeafletTiles class
    this.marksLayer;

    this.map;

    this.zoomControl;
    this.scaleControl;
    this.copyrightControl;
    this.nameControl;
    this.zoomLevelControl;

    this.onMapMoveEnd = function(e){
        if (!parent.map){return}

        var latlng = parent.map.getCenter();
        opt.setOption("current", "mapCenterLatLng", [latlng.lat, latlng.lng]);
        opt.setHash();

        for (var i = 0; i < parent.instances.length; i++) {
            parent.instances[i].setMapCenter(latlng);
        };
     }

    this.onZoomEnd = function(e){
        if (!parent.map) { return }
        this.setMapZoom(parent.map.getZoom());
        this.onMapMoveEnd();
     }

    this.updateMapControls = function(){
        if (!this.map) { return }

        if (this.zoomLevelControl){
            this.zoomLevelControl.setPrefix(this.map.getZoom());
        }

        var title;
        try { title = this.mapTilesLayer.title; }
        catch (e) { title = "No title" }

        if (this.nameControl){
            this.nameControl.setPrefix(title);
        }
     }

    this._setMapControls = function(){

        if (!this.map) { return }

        // Zoom Control
        if (opt.getOption("global", "viewControlsZoom")){
            this.zoomControl = L.control.zoom(opt.getOption("global", "viewControlsZoomPosition"))
            this.map.addControl(this.zoomControl);
         }

        // Scale Control
        if (opt.getOption("global", "viewControlsScale")){
            this.scaleControl = L.control.scale({
                position: opt.getOption("global", "viewControlsScalePosition"),
                imperial: opt.getOption("global", "viewControlsScaleMiles"),
            })
            this.map.addControl(this.scaleControl);
         }

        // Cporyright
        if (opt.getOption("global", "viewControlsInfoCopyright")){
            this.copyrightControl = L.control.attribution({
                position: opt.getOption("global", "viewControlsInfoCopyrightPosition"),
                prefix: opt.getOption("global", "viewControlsInfoCopyrightText"),
            })
            this.map.addControl(this.copyrightControl);
         }

        // Map Title
        if (opt.getOption("global", "viewControlsInfoName")){
            var title;
            try {
                title = this.mapTilesLayer.title;
            }
            catch (e) {
                title = "No title"
            }
            this.nameControl = L.control.attribution({
                position: opt.getOption("global", "viewControlsInfoNamePosition"),
                prefix: title,
            })
            this.map.addControl(this.nameControl);
         }

        // Zoom Level
        if (opt.getOption("global", "viewControlsInfoZoom")){
            this.zoomLevelControl = L.control.attribution({
                position: opt.getOption("global", "viewControlsInfoZoomPosition"),
                prefix: this.map.getZoom(),
            })
            this.map.addControl(this.zoomLevelControl);
         }

     }

    this._validateLatLng = function(latlng){

        latlng = latlng ? latlng : opt.getOption("global", "mapDefaultCenterLatLng");

        try {
            latlng = L.latLng(latlng);
        }
        catch(e) {
            latlng = L.latLng(opt.getOption("global", "mapDefaultCenterLatLng"));
        }

        return latlng;
     }

    this._validateZoom = function(zoom){

        if (!this.mapTilesLayer){ return opt.getOption("global", "mapDefaultZoom") }

        zoom = zoom ? zoom : opt.getOption("global", "mapDefaultZoom");

        var minZoom = this.mapTilesLayer.minZoom;
        var maxZoom = this.mapTilesLayer.maxZoom;

        zoom = zoom>=minZoom && zoom<=maxZoom ? zoom : opt.getOption("global", "mapDefaultZoom");

        return zoom;

     }

    this.createMap = function(){
        this.map = L.map(this.mapId, {
            zoomControl: false,
            attributionControl: false,
            center: this._validateLatLng(opt.getOption("current", "mapCenterLatLng") || opt.getOption("global", "mapDefaultCenterLatLng")),
            zoom: this._validateZoom(opt.getOption("current", "mapZoom") || opt.getOption("global", "mapDefaultZoom")),
            inertia: false,
        });

        this.map.on("zoomend", function(e){ parent.onZoomEnd(); });
        // this.map.on("zoomend", this.onZoomEnd); // Srange but this not work in Chrome ??????
        this.map.on("dragend", this.onMapMoveEnd); // if I use moveend, on setting all maps position it`s fall to recursion a little

        this._setMapControls();
     }

    this.setMapCenter = function(latlng){
        if (!this.map){return}
        latlng = this._validateLatLng(latlng);
        this.map.panTo(latlng);
     }

    this.setMapZoom = function(zoom){
        if (!this.map){return}
        zoom = this._validateZoom(zoom);
        this.map.setZoom(zoom);
        this.updateMapControls();
     }

    this.setMapTilesLayer = function(layerObj){

        if (this.mapTilesLayer && this.map.hasLayer(this.mapTilesLayer)){
            this.map.removeLayer(this.mapTilesLayer)
        }

        this.mapTilesLayer = layerObj;
        this.map.addLayer(this.mapTilesLayer.layer);

        this.updateMapControls();

     }

    this.refreshMapAfterResize = function(){
        this.map.invalidateSize();
     }

    this.instances.push(this);

 }

LeafletMap.prototype.instances = []; // Collect all instanses of class

(function(){
    window.onresize = function(){
        for (var i=0; i<LeafletMap.prototype.instances.length; i++){
            LeafletMap.prototype.instances[i].refreshMapAfterResize();
        }
    }
 })()

var LeafletTiles = function(opt){

    var parent = this;

    this.layer;

    this.server;
    this.tilesURL;
    this.maxZoom;
    this.minZoom;
    this.startZoom;
    this.title;

    if (!opt) {
        console.log("There is no options in LeafletTiles, check this.");
        return;
     }

    // TODO: сделать проверку что это строка и ссылка
    this._validateTilesURL = function(url){
        if (url) {
            return url;
        }
        else {
            return "http://{s}.tiles.mapbox.com/v3/examples.map-y7l23tes/{z}/{x}/{y}.png";
        }
     }

    this._validateServer = function(server){
        return server && server in ["img", "wms"] ? server : "img";
     }

    this._validateMinZoom = function(minZoom){
        minZoom = parseInt(minZoom, 10);
        minZoom = minZoom<=18 && minZoom>0 ? minZoom : minZoom>18 ? 18 : 1; // If return 0 exept 1 all crashed
        return minZoom;
     }

    this._validateMaxZoom = function(maxZoom){
        maxZoom = parseInt(maxZoom, 10);
        maxZoom = maxZoom<=18 && maxZoom>0 ? maxZoom : 18;
        return maxZoom;
     }

    this._validateStartZoom = function(startZoom){
        startZoom = parseInt(startZoom, 10);
        startZoom = startZoom<=18 && startZoom>0 ? startZoom : opt.getOption("global", "mapDefaultZoom");
        return startZoom;
     }

    this._validateZoomBounds = function(){
        if (!this.maxZoom || !this.minZoom) { return }

        if (this.maxZoom < this.minZoom) {
            this.maxZoom = this.minZoom;
        }
     }

    this.setLayerOptions = function(mapName){

        var data = opt.getOption("maps", mapName);

        if (!data) { return }

        this.server = this._validateServer(data.server);
        this.tilesURL = this._validateTilesURL(data.tilesURL);
        this.maxZoom = this._validateMaxZoom(data.maxZoom);
        this.minZoom = this._validateMinZoom(data.minZoom);
        this.startZoom = this._validateStartZoom(data.startZoom);
        this.title = data.title ? data.title : "Unknown Map";

        this._validateZoomBounds();
     }

    this.setLayer = function(url, minZoom, maxZoom, startZoom){

        // WMS server always set using the setLayerOptions
        this.server = this.server ? this.server : this._validateServer();
        this.tilesURL = url ? this._validateTilesURL(url): this.tilesURL;
        this.maxZoom = maxZoom ? his._validateMinZoom(maxZoom): this.maxZoom;
        this.minZoom = minZoom ? this._validateMaxZoom(minZoom): this.minZoom;
        this.startZoom = startZoom ? this._validateStartZoom(startZoom): this.startZoom;
        this.title = this.title ? this.title : "Unknown Map";

        this._validateZoomBounds();

        if (this.server && this.server === "wms"){
            // TODO: server wms type
        }
        else {
            this.layer = L.tileLayer(this.tilesURL, {
                maxZoom: this.maxZoom,
                minZoom: this.minZoom,
            });
        }
     }

 }

var Options = function(){

    var parent = this;

    this.global = {

        "mapDefaultCenterLatLng": [54.31727, 48.3946],
        "mapDefaultZoom": 12,
        "mapSyncMoving": true,
        "mapSyncZooming": false,

        "viewControlsZoom": true,
        "viewControlsZoomPosition": "topleft",
        "viewControlsScale": true,
        "viewControlsScalePosition": "bottomleft",
        "viewControlsScaleMiles": false,
        "viewControlsInfoName": true,
        "viewControlsInfoNamePosition": "bottomright",
        "viewControlsInfoZoom": true,
        "viewControlsInfoZoomPosition": "bottomright",
        "viewControlsInfoCopyright": true,
        "viewControlsInfoCopyrightPosition": "bottomright",
        "viewControlsInfoCopyrightText": "Copyleft by Starik",

        "hashChange": true,

     };

    this.current = {
        "mapCenterLatLng": [],
        "mapZoom": undefined,

        "stage": {
            "stageName": "current",
            "stageMapsGrid": [
                [0, 0, 100, 50],
                [0, 50, 100, 50],
            ],
            "stageMapsNames": ["cloudmate", "cloudmate"],
            "stageMapsZooms": [12, 8],
        },

     }

    this.maps = {
        "cloudmate": {
            tags: ["0. Современные онлайн карты"],
            src: "Internet",
            server: "img",
            title: 'Cloudmate',
            tilesURL: 'http://{s}.tile.cloudmade.com/BC9A493B41014CAABB98F0471D759707/997/256/{z}/{x}/{y}.png',
            maxZoom: 15,
            minZoom: 0,
            startZoom: 5,
        },
     };

    // TODO: написать
    this.initOptions = function(){

     }

    // TODO: нужна проверка наличия всех нужных глобальных переменных, если нет то принудительно обновлять
    // TODO: сделать проверку соответствия viewControlsZoomPosition и подобных определенным значениям
    this.checkOptions = function(){

     }

    this.setOption = function(collection, option, value){
        this[collection][option] = value;
        // TODO: Update in localstorage and files in dropbox
     }

    this.getOption = function(collection, option){
        return this[collection][option];
     }

    this.setHash = function(){

        if (!this.getOption("global", "hashChange") || !this.getOption("global", "mapSyncMoving")) {
            window.location.hash = "";
            return
        }

        window.location.hash = this.getOption("current", "mapCenterLatLng").join(",");

     }

    this.getHash = function(){

        if (!this.getOption("global", "hashChange")) { return }

        var hash = window.location.hash;

        try {
            var latlng = L.latLng(hash.split("#").pop().split(","))
            this.setOption("current", "mapCenterLatLng", [latlng.lat, latlng.lng]);
        }
        catch (e) {}

     }

    this.initOptions();

 }

var StageMaps = function(container, opt){
    var parent = this;

    if (!opt) {
        console.log("There is no options in StageMaps, check this.");
        return;
     }

    if (!container) { return }
    this.$container = $("#"+container);

    this.stageCurr;

    this.initStage = function(){
        this._clearHTML();
        this._getCurrentStage();
        this.$container.append(this._createStageHTML());
        this._createMaps();
     }

    this._getCurrentStage = function(){
        this.stageCurr = opt.getOption("current", "stage");
     }

    this._clearHTML = function(){
        this.$container.empty();
     }

    this._createMaps = function(){
        if (!this.stageCurr.stageMapsGrid || !this.stageCurr.stageMapsGrid.length){ return }

        var names = this.stageCurr.stageMapsNames;
        var zooms = this.stageCurr.stageMapsZooms;
        var grid = this.stageCurr.stageMapsGrid;
        for (var i=0; i<grid.length; i++){
            window["layer"+i] = new LeafletTiles(opt);
            window["layer"+i].setLayerOptions(names[i]);
            window["layer"+i].setLayer();

            window["map"+i] = new LeafletMap("map"+i, opt);
            window["map"+i].createMap();
            window["map"+i].setMapTilesLayer(window["layer"+i]);
            window["map"+i].setMapCenter(opt.getOption("current","mapCenterLatLng"));
            window["map"+i].setMapZoom(zooms[i] || window["layer"+i].startZoom);
        }

     }

    this._createStageHTML = function(){
        var divs = "";
        if (!this.stageCurr.stageMapsGrid || !this.stageCurr.stageMapsGrid.length){ return divs }

        var grid = this.stageCurr.stageMapsGrid;
        for (var i=0; i<grid.length; i++){
            divs += "

".format(i, grid[i][0], grid[i][1], grid[i][2], grid[i][3]);
        }
        return divs;
     }

    this.setStageOptions = function(){

     }

 }

var opt = new Options();
opt.getHash();

var stage = new StageMaps("container", opt);
stage.initStage();

console.log(opt)
<commit_msg>Ref: move all maps function<commit_after>"use strict"

var LeafletMap = function(mapId, opt){

    if (!mapId && !$("#"+mapId)){ return }
    this.mapId = mapId;

    if (!opt) {
        console.log("There is no options in LeafletMap, check this.");
        return;
     }

    var parent = this;

    this.mapTilesLayer; // copy of LeafletTiles class
    this.marksLayer;

    this.map;

    this.zoomControl;
    this.scaleControl;
    this.copyrightControl;
    this.nameControl;
    this.zoomLevelControl;

    this.moveAllMaps = function(latlng){
        for (var i = 0; i < parent.instances.length; i++) {
            parent.instances[i].setMapCenter(latlng);
        };
    }

    this.onMapMoveEnd = function(e){
        if (!parent.map){return}

        var latlng = parent.map.getCenter();
        opt.setOption("current", "mapCenterLatLng", [latlng.lat, latlng.lng]);
        opt.setHash();

        if (opt.getOption("global", "mapSyncMoving")){
            parent.moveAllMaps(latlng);
        }
     }

    this.onZoomEnd = function(e){
        if (!parent.map) { return }
        this.setMapZoom(parent.map.getZoom());
        this.onMapMoveEnd();
     }

    this.updateMapControls = function(){
        if (!this.map) { return }

        if (this.zoomLevelControl){
            this.zoomLevelControl.setPrefix(this.map.getZoom());
        }

        var title;
        try { title = this.mapTilesLayer.title; }
        catch (e) { title = "No title" }

        if (this.nameControl){
            this.nameControl.setPrefix(title);
        }
     }

    this._setMapControls = function(){

        if (!this.map) { return }

        // Zoom Control
        if (opt.getOption("global", "viewControlsZoom")){
            this.zoomControl = L.control.zoom(opt.getOption("global", "viewControlsZoomPosition"))
            this.map.addControl(this.zoomControl);
         }

        // Scale Control
        if (opt.getOption("global", "viewControlsScale")){
            this.scaleControl = L.control.scale({
                position: opt.getOption("global", "viewControlsScalePosition"),
                imperial: opt.getOption("global", "viewControlsScaleMiles"),
            })
            this.map.addControl(this.scaleControl);
         }

        // Cporyright
        if (opt.getOption("global", "viewControlsInfoCopyright")){
            this.copyrightControl = L.control.attribution({
                position: opt.getOption("global", "viewControlsInfoCopyrightPosition"),
                prefix: opt.getOption("global", "viewControlsInfoCopyrightText"),
            })
            this.map.addControl(this.copyrightControl);
         }

        // Map Title
        if (opt.getOption("global", "viewControlsInfoName")){
            var title;
            try {
                title = this.mapTilesLayer.title;
            }
            catch (e) {
                title = "No title"
            }
            this.nameControl = L.control.attribution({
                position: opt.getOption("global", "viewControlsInfoNamePosition"),
                prefix: title,
            })
            this.map.addControl(this.nameControl);
         }

        // Zoom Level
        if (opt.getOption("global", "viewControlsInfoZoom")){
            this.zoomLevelControl = L.control.attribution({
                position: opt.getOption("global", "viewControlsInfoZoomPosition"),
                prefix: this.map.getZoom(),
            })
            this.map.addControl(this.zoomLevelControl);
         }

     }

    this._validateLatLng = function(latlng){

        latlng = latlng ? latlng : opt.getOption("global", "mapDefaultCenterLatLng");

        try {
            latlng = L.latLng(latlng);
        }
        catch(e) {
            latlng = L.latLng(opt.getOption("global", "mapDefaultCenterLatLng"));
        }

        return latlng;
     }

    this._validateZoom = function(zoom){

        if (!this.mapTilesLayer){ return opt.getOption("global", "mapDefaultZoom") }

        zoom = zoom ? zoom : opt.getOption("global", "mapDefaultZoom");

        var minZoom = this.mapTilesLayer.minZoom;
        var maxZoom = this.mapTilesLayer.maxZoom;

        zoom = zoom>=minZoom && zoom<=maxZoom ? zoom : opt.getOption("global", "mapDefaultZoom");

        return zoom;

     }

    this.createMap = function(){
        this.map = L.map(this.mapId, {
            zoomControl: false,
            attributionControl: false,
            center: this._validateLatLng(opt.getOption("current", "mapCenterLatLng") || opt.getOption("global", "mapDefaultCenterLatLng")),
            zoom: this._validateZoom(opt.getOption("current", "mapZoom") || opt.getOption("global", "mapDefaultZoom")),
            inertia: false,
        });

        this.map.on("zoomend", function(e){ parent.onZoomEnd(); });
        // this.map.on("zoomend", this.onZoomEnd); // Srange but this not work in Chrome ??????
        this.map.on("dragend", this.onMapMoveEnd); // if I use moveend, on setting all maps position it`s fall to recursion a little

        this._setMapControls();
     }

    this.setMapCenter = function(latlng){
        if (!this.map){return}
        latlng = this._validateLatLng(latlng);
        this.map.panTo(latlng);
     }

    this.setMapZoom = function(zoom){
        if (!this.map){return}
        zoom = this._validateZoom(zoom);
        this.map.setZoom(zoom);
        this.updateMapControls();
     }

    this.setMapTilesLayer = function(layerObj){

        if (this.mapTilesLayer && this.map.hasLayer(this.mapTilesLayer)){
            this.map.removeLayer(this.mapTilesLayer)
        }

        this.mapTilesLayer = layerObj;
        this.map.addLayer(this.mapTilesLayer.layer);

        this.updateMapControls();

     }

    this.refreshMapAfterResize = function(){
        this.map.invalidateSize();
     }

    this.instances.push(this);

 }

LeafletMap.prototype.instances = []; // Collect all instanses of class

(function(){
    window.onresize = function(){
        for (var i=0; i<LeafletMap.prototype.instances.length; i++){
            LeafletMap.prototype.instances[i].refreshMapAfterResize();
        }
    }
 })()

var LeafletTiles = function(opt){

    var parent = this;

    this.layer;

    this.server;
    this.tilesURL;
    this.maxZoom;
    this.minZoom;
    this.startZoom;
    this.title;

    if (!opt) {
        console.log("There is no options in LeafletTiles, check this.");
        return;
     }

    // TODO: сделать проверку что это строка и ссылка
    this._validateTilesURL = function(url){
        if (url) {
            return url;
        }
        else {
            return "http://{s}.tiles.mapbox.com/v3/examples.map-y7l23tes/{z}/{x}/{y}.png";
        }
     }

    this._validateServer = function(server){
        return server && server in ["img", "wms"] ? server : "img";
     }

    this._validateMinZoom = function(minZoom){
        minZoom = parseInt(minZoom, 10);
        minZoom = minZoom<=18 && minZoom>0 ? minZoom : minZoom>18 ? 18 : 1; // If return 0 exept 1 all crashed
        return minZoom;
     }

    this._validateMaxZoom = function(maxZoom){
        maxZoom = parseInt(maxZoom, 10);
        maxZoom = maxZoom<=18 && maxZoom>0 ? maxZoom : 18;
        return maxZoom;
     }

    this._validateStartZoom = function(startZoom){
        startZoom = parseInt(startZoom, 10);
        startZoom = startZoom<=18 && startZoom>0 ? startZoom : opt.getOption("global", "mapDefaultZoom");
        return startZoom;
     }

    this._validateZoomBounds = function(){
        if (!this.maxZoom || !this.minZoom) { return }

        if (this.maxZoom < this.minZoom) {
            this.maxZoom = this.minZoom;
        }
     }

    this.setLayerOptions = function(mapName){

        var data = opt.getOption("maps", mapName);

        if (!data) { return }

        this.server = this._validateServer(data.server);
        this.tilesURL = this._validateTilesURL(data.tilesURL);
        this.maxZoom = this._validateMaxZoom(data.maxZoom);
        this.minZoom = this._validateMinZoom(data.minZoom);
        this.startZoom = this._validateStartZoom(data.startZoom);
        this.title = data.title ? data.title : "Unknown Map";

        this._validateZoomBounds();
     }

    this.setLayer = function(url, minZoom, maxZoom, startZoom){

        // WMS server always set using the setLayerOptions
        this.server = this.server ? this.server : this._validateServer();
        this.tilesURL = url ? this._validateTilesURL(url): this.tilesURL;
        this.maxZoom = maxZoom ? his._validateMinZoom(maxZoom): this.maxZoom;
        this.minZoom = minZoom ? this._validateMaxZoom(minZoom): this.minZoom;
        this.startZoom = startZoom ? this._validateStartZoom(startZoom): this.startZoom;
        this.title = this.title ? this.title : "Unknown Map";

        this._validateZoomBounds();

        if (this.server && this.server === "wms"){
            // TODO: server wms type
        }
        else {
            this.layer = L.tileLayer(this.tilesURL, {
                maxZoom: this.maxZoom,
                minZoom: this.minZoom,
            });
        }
     }

 }

var Options = function(){

    var parent = this;

    this.global = {

        "mapDefaultCenterLatLng": [54.31727, 48.3946],
        "mapDefaultZoom": 12,
        "mapSyncMoving": true,
        "mapSyncZooming": false,

        "viewControlsZoom": true,
        "viewControlsZoomPosition": "topleft",
        "viewControlsScale": true,
        "viewControlsScalePosition": "bottomleft",
        "viewControlsScaleMiles": false,
        "viewControlsInfoName": true,
        "viewControlsInfoNamePosition": "bottomright",
        "viewControlsInfoZoom": true,
        "viewControlsInfoZoomPosition": "bottomright",
        "viewControlsInfoCopyright": true,
        "viewControlsInfoCopyrightPosition": "bottomright",
        "viewControlsInfoCopyrightText": "Copyleft by Starik",

        "hashChange": true,

     };

    this.current = {
        "mapCenterLatLng": [],
        "mapZoom": undefined,

        "stage": {
            "stageName": "current",
            "stageMapsGrid": [
                [0, 0, 100, 50],
                [0, 50, 100, 50],
            ],
            "stageMapsNames": ["cloudmate", "cloudmate"],
            "stageMapsZooms": [12, 8],
        },

     }

    this.maps = {
        "cloudmate": {
            tags: ["0. Современные онлайн карты"],
            src: "Internet",
            server: "img",
            title: 'Cloudmate',
            tilesURL: 'http://{s}.tile.cloudmade.com/BC9A493B41014CAABB98F0471D759707/997/256/{z}/{x}/{y}.png',
            maxZoom: 15,
            minZoom: 0,
            startZoom: 5,
        },
     };

    // TODO: написать
    this.initOptions = function(){

     }

    // TODO: нужна проверка наличия всех нужных глобальных переменных, если нет то принудительно обновлять
    // TODO: сделать проверку соответствия viewControlsZoomPosition и подобных определенным значениям
    this.checkOptions = function(){

     }

    this.setOption = function(collection, option, value){
        this[collection][option] = value;
        // TODO: Update in localstorage and files in dropbox
     }

    this.getOption = function(collection, option){
        return this[collection][option];
     }

    this.setHash = function(){

        if (!this.getOption("global", "hashChange") || !this.getOption("global", "mapSyncMoving")) {
            window.location.hash = "";
            return
        }

        window.location.hash = this.getOption("current", "mapCenterLatLng").join(",");

     }

    this.getHash = function(){

        if (!this.getOption("global", "hashChange")) { return }

        var hash = window.location.hash;

        try {
            var latlng = L.latLng(hash.split("#").pop().split(","))
            this.setOption("current", "mapCenterLatLng", [latlng.lat, latlng.lng]);
        }
        catch (e) {}

     }

    this.initOptions();

 }

var StageMaps = function(container, opt){
    var parent = this;

    if (!opt) {
        console.log("There is no options in StageMaps, check this.");
        return;
     }

    if (!container) { return }
    this.$container = $("#"+container);

    this.stageCurr;

    this.initStage = function(){
        this._clearHTML();
        this._getCurrentStage();
        this.$container.append(this._createStageHTML());
        this._createMaps();
     }

    this._getCurrentStage = function(){
        this.stageCurr = opt.getOption("current", "stage");
     }

    this._clearHTML = function(){
        this.$container.empty();
     }

    this._createMaps = function(){
        if (!this.stageCurr.stageMapsGrid || !this.stageCurr.stageMapsGrid.length){ return }

        var names = this.stageCurr.stageMapsNames;
        var zooms = this.stageCurr.stageMapsZooms;
        var grid = this.stageCurr.stageMapsGrid;
        for (var i=0; i<grid.length; i++){
            window["layer"+i] = new LeafletTiles(opt);
            window["layer"+i].setLayerOptions(names[i]);
            window["layer"+i].setLayer();

            window["map"+i] = new LeafletMap("map"+i, opt);
            window["map"+i].createMap();
            window["map"+i].setMapTilesLayer(window["layer"+i]);
            window["map"+i].setMapCenter(opt.getOption("current","mapCenterLatLng"));
            window["map"+i].setMapZoom(zooms[i] || window["layer"+i].startZoom);
        }

     }

    this._createStageHTML = function(){
        var divs = "";
        if (!this.stageCurr.stageMapsGrid || !this.stageCurr.stageMapsGrid.length){ return divs }

        var grid = this.stageCurr.stageMapsGrid;
        for (var i=0; i<grid.length; i++){
            divs += "

".format(i, grid[i][0], grid[i][1], grid[i][2], grid[i][3]);
        }
        return divs;
     }

    this.setStageOptions = function(){

     }

 }

var opt = new Options();
opt.getHash();

var stage = new StageMaps("container", opt);
stage.initStage();

console.log(opt)
<|endoftext|>


<commit_before>import React, {Component} from 'react';
import {View} from 'react-native';
import {NativeRouter, Route, Redirect, Link} from 'react-router-native';
import {getItem} from '../storage';
import Home from './Home';
import Login from './auth/Login';

class AuthGuard extends Component {
  constructor(props, state) {
    super(props, state);

    this.state = {isAuthenticated: null};
  }

  componentDidMount() {
    getItem(process.env.ACCESS_TOKEN_KEY)
      .bimap(
        error => this.setState({isAuthenticated: false}),
        () => this.setState({isAuthenticated: true})
      )
      .run()
  }

  render() {
    const Component = this.props.component;

    if(this.state.isAuthenticated === null) return null;

    return this.state.isAuthenticated
      ? <Component />
      : <Redirect to={{
          pathname: '/login',
          state: {
            from: this.props.location
          }
        }}/>
  }
}

const PrivateRoute = ({component: Component, ...rest}) =>
  <Route {...rest} render={props => <AuthGuard {...props} component={Component} /> }/>

export default () =>
  <NativeRouter>
    <View>
      <PrivateRoute exact path="/" component={Home}/>
      <Route path="/login" component={Login}/>
    </View>
  </NativeRouter>;
<commit_msg>add a todo placeholder to add a spinner in auth guard<commit_after>import React, {Component} from 'react';
import {View} from 'react-native';
import {NativeRouter, Route, Redirect, Link} from 'react-router-native';
import {getItem} from '../storage';
import Home from './Home';
import Login from './auth/Login';

class AuthGuard extends Component {
  constructor(props, state) {
    super(props, state);

    this.state = {isAuthenticated: null};
  }

  componentDidMount() {
    getItem(process.env.ACCESS_TOKEN_KEY)
      .bimap(
        error => this.setState({isAuthenticated: false}),
        () => this.setState({isAuthenticated: true})
      )
      .run()
  }

  render() {
    const Component = this.props.component;

    if(this.state.isAuthenticated === null) {
      // TODO: this is the place were we can add a spinner
      // or something more sophisticated
      return null;
    }

    return this.state.isAuthenticated
      ? <Component />
      : <Redirect to={{
          pathname: '/login',
          state: {
            from: this.props.location
          }
        }}/>
  }
}

const PrivateRoute = ({component: Component, ...rest}) =>
  <Route {...rest} render={props => <AuthGuard {...props} component={Component} /> }/>

export default () =>
  <NativeRouter>
    <View>
      <PrivateRoute exact path="/" component={Home}/>
      <Route path="/login" component={Login}/>
    </View>
  </NativeRouter>;
<|endoftext|>


<commit_before>import cytoscape from 'cytoscape';
import sbgnStyleSheet from 'sbgn-renderer';
import convertSbgn from 'sbgnml-to-cytoscape';

//layouts
import cola from 'cytoscape-cola';
import klay from 'cytoscape-klay';
import klayjs from 'klayjs';
import coseBilkent from 'cytoscape-cose-bilkent';
import dagre from 'cytoscape-dagre';

import expandCollapse from 'cytoscape-expand-collapse';

expandCollapse( cytoscape );   // TODO use cytoscape 3.x when these are compatible
cytoscape.use( cola );
cytoscape.use( coseBilkent );
cytoscape.use( dagre );
cytoscape.use( klay, klayjs ); // cytoscape 3.x extension register

// set the sbgn style sheet
// bind interaction events (mouse hovering, collapsing)
export const initGraph = (graphContainer) => {
  const graphInstance = cytoscape({
    container: graphContainer,
    style: sbgnStyleSheet(cytoscape)
  })

  graphInstance.expandCollapse({
    fisheye: true,
    animate: true,
    undoable: false,
    cueEnabled: false
  });

  graphInstance.style().selector('edge').css({'opacity': 0.3});

  graphInstance.on('mouseover', 'node', function (evt) {
    const node = evt.target;
    if (node.data('class') === 'compartment') {
      return;
    }
    const neighborhood = node.neighborhood();

    node.style({
      'background-color': 'blue',
      'opacity': 1
    });
    neighborhood.nodes().style({
      'background-color': 'blue',
      'opacity': 1,
      'z-compound-depth': 'top'
    });
    neighborhood.edges().style({
      'line-color': 'orange',
      'opacity': 1
    });
  });

  graphInstance.on('mouseout', 'node', function (evt) {
    const node = evt.target;
    if (node.data('class') === 'compartment') {
      return;
    }
    const neighborhood = node.neighborhood();

    node.style({
      'background-color': 'white',
    });
    neighborhood.nodes().style({
      'background-color': 'white',
      'z-compound-depth': 'auto'
    });
    neighborhood.edges().style({
      'line-color': 'black',
      'opacity': 0.3
    });
  });

  graphInstance.on('mouseover', 'edge', function (evt) {
    const edge = evt.target;
    edge.style({
      'line-color': 'orange',
      'opacity': 1
    });

    edge.source().style({
      'background-color': 'blue',
      'z-compound-depth': 'top'

    });
    edge.target().style({
      'background-color': 'blue',
      'z-compound-depth': 'top'
    });
  });

  graphInstance.on('mouseout', 'edge', function (evt) {
    const edge = evt.target;
    edge.style({
      'line-color': 'black',
      'opacity': 0.3
    });

    edge.source().style({
      'background-color': 'white',
      'z-compound-depth': 'auto'
    });
    edge.target().style({
      'background-color': 'white',
      'z-compound-depth': 'auto'
    });
  });

  let parentPos;
  graphInstance.on('expandcollapse.beforeexpand', function (evt) {
    console.log(evt);
    parentPos = evt.target.position();
  });

  graphInstance.on('expandcollapse.afterexpand', function (evt) {
    const node = evt.target;
    graphInstance.zoomingEnabled(false);
    node.children().position(parentPos);
    node.children().layout({
      name:'grid',
      fit: 'false',
      avoidOverlap: true,
      condense: true,
      animate: true,
      rows: node.children().size() / 2,
      cols: node.children().size() / 2,
      boundingBox: node.boundingBox()
    }).run();
    graphInstance.zoomingEnabled(true);
  });

  graphInstance.on('tap', 'node[class="complex"], node[class="complex multimer"]', function (evt) {
    evt.preventDefault();
    const node = evt.target;
    const api = graphInstance.expandCollapse('get');
    if (api.isCollapsible(node)) {
      api.collapse(node);
    } else {
      api.expand(node);
    }
  });

  return graphInstance;
}
<commit_msg>remove log statement<commit_after>import cytoscape from 'cytoscape';
import sbgnStyleSheet from 'sbgn-renderer';
import convertSbgn from 'sbgnml-to-cytoscape';

//layouts
import cola from 'cytoscape-cola';
import klay from 'cytoscape-klay';
import klayjs from 'klayjs';
import coseBilkent from 'cytoscape-cose-bilkent';
import dagre from 'cytoscape-dagre';

import expandCollapse from 'cytoscape-expand-collapse';

expandCollapse( cytoscape );   // TODO use cytoscape 3.x when these are compatible
cytoscape.use( cola );
cytoscape.use( coseBilkent );
cytoscape.use( dagre );
cytoscape.use( klay, klayjs ); // cytoscape 3.x extension register

// set the sbgn style sheet
// bind interaction events (mouse hovering, collapsing)
export const initGraph = (graphContainer) => {
  const graphInstance = cytoscape({
    container: graphContainer,
    style: sbgnStyleSheet(cytoscape)
  })

  graphInstance.expandCollapse({
    fisheye: true,
    animate: true,
    undoable: false,
    cueEnabled: false
  });

  graphInstance.style().selector('edge').css({'opacity': 0.3});

  graphInstance.on('mouseover', 'node', function (evt) {
    const node = evt.target;
    if (node.data('class') === 'compartment') {
      return;
    }
    const neighborhood = node.neighborhood();

    node.style({
      'background-color': 'blue',
      'opacity': 1
    });
    neighborhood.nodes().style({
      'background-color': 'blue',
      'opacity': 1,
      'z-compound-depth': 'top'
    });
    neighborhood.edges().style({
      'line-color': 'orange',
      'opacity': 1
    });
  });

  graphInstance.on('mouseout', 'node', function (evt) {
    const node = evt.target;
    if (node.data('class') === 'compartment') {
      return;
    }
    const neighborhood = node.neighborhood();

    node.style({
      'background-color': 'white',
    });
    neighborhood.nodes().style({
      'background-color': 'white',
      'z-compound-depth': 'auto'
    });
    neighborhood.edges().style({
      'line-color': 'black',
      'opacity': 0.3
    });
  });

  graphInstance.on('mouseover', 'edge', function (evt) {
    const edge = evt.target;
    edge.style({
      'line-color': 'orange',
      'opacity': 1
    });

    edge.source().style({
      'background-color': 'blue',
      'z-compound-depth': 'top'

    });
    edge.target().style({
      'background-color': 'blue',
      'z-compound-depth': 'top'
    });
  });

  graphInstance.on('mouseout', 'edge', function (evt) {
    const edge = evt.target;
    edge.style({
      'line-color': 'black',
      'opacity': 0.3
    });

    edge.source().style({
      'background-color': 'white',
      'z-compound-depth': 'auto'
    });
    edge.target().style({
      'background-color': 'white',
      'z-compound-depth': 'auto'
    });
  });

  let parentPos;
  graphInstance.on('expandcollapse.beforeexpand', function (evt) {
    parentPos = evt.target.position();
  });

  graphInstance.on('expandcollapse.afterexpand', function (evt) {
    const node = evt.target;
    graphInstance.zoomingEnabled(false);
    node.children().position(parentPos);
    node.children().layout({
      name:'grid',
      fit: 'false',
      avoidOverlap: true,
      condense: true,
      animate: true,
      rows: node.children().size() / 2,
      cols: node.children().size() / 2,
      boundingBox: node.boundingBox()
    }).run();
    graphInstance.zoomingEnabled(true);
  });

  graphInstance.on('tap', 'node[class="complex"], node[class="complex multimer"]', function (evt) {
    evt.preventDefault();
    const node = evt.target;
    const api = graphInstance.expandCollapse('get');
    if (api.isCollapsible(node)) {
      api.collapse(node);
    } else {
      api.expand(node);
    }
  });

  return graphInstance;
}
<|endoftext|>


<commit_before>//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
//>>description: Custom-styled native input/buttons
//>>label: Buttons: Input or button-based
//>>group: Forms
//>>css.structure: ../css/structure/jquery.mobile.button.css
//>>css.theme: ../css/themes/default/jquery.mobile.theme.css

define( [ "jquery", "../../jquery.mobile.widget", "../../jquery.mobile.registry"  ], function( jQuery ) {
//>>excludeEnd("jqmBuildExclude");
(function( $, undefined ) {

$.widget( "mobile.button", {
	options: {
		theme: "inherit",
		icon: null,
		iconpos: "left",
		iconshadow: false, /* TODO: Deprecated in 1.4, remove in 1.5. */
		corners: true,
		shadow: true,
		inline: null,
		mini: null,
		wrapperClass: null,
		enhanced: false
	},

	_create: function() {

		if ( this.element.is( ":disabled" ) ) {
			this.options.disabled = true;
		}

		if ( !this.options.enhanced ) {
			this._enhance();
		}

		$.extend( this, {
			wrapper: this.element.parent()
		});

		this._on( {
			focus: function() {
				this.widget().addClass( $.mobile.focusClass );
			},

			blur: function() {
				this.widget().removeClass( $.mobile.focusClass );
			}
		});

		this.refresh( true );
	},

	_enhance: function() {
		this.element.wrap( this._button() );
	},

	_button: function() {
		return $("<div class='ui-btn ui-input-btn " +
			this.options.wrapperClass +
			" ui-btn-" + this.options.theme +
			( this.options.corners ? " ui-corner-all" : "" ) +
			( this.options.shadow ? " ui-shadow" : "" ) +
			( this.options.inline ? " ui-btn-inline" : "" ) +
			( this.options.mini ? " ui-mini" : "" ) +
			( this.options.disabled ? " ui-disabled" : "" ) +
			( this.options.iconpos ? " ui-btn-icon-" + this.options.iconpos : ( this.options.icon ? " ui-btn-icon-left" : "" ) ) +
			( this.options.icon ? "ui-icon-" + this.options.icon : "" ) +
			"' >" + this.element.val() + "
");
	},

	widget: function() {
		return this.wrapper;
	},

	_destroy: function() {
			this.element.insertBefore( this.button );
			this.button.remove();
	},

	_setOptions: function( options ) {
		if ( options.theme !== undefined ) {
			this.widget().removeClass( this.options.theme ).addClass( "ui-btn-" + options.theme );
		}
		if ( options.corners !== undefined ) {
			this.widget().toggleClass( "ui-corner-all", options.corners );
		}
		if ( options.shadow !== undefined ) {
			this.widget().toggleClass( "ui-shadow", options.shadow );
		}
		if ( options.inline !== undefined ) {
			this.widget().toggleClass( "ui-btn-inline", options.inline );
		}
		if ( options.mini !== undefined ) {
			this.widget().toggleClass( "ui-mini", options.mini );
		}
		if ( options.iconpos !== undefined ) {
			this.widget().removeClass( "ui-btn-icon-" + options.iconpos );
		}
		if ( options.icon !== undefined ) {
			if ( !this.options.iconpos && !options.iconpos ) {
				this.widget.toggleClass( "ui-btn-icon-left", options.icon );
			}
			this.widget().removeClass( "ui-icon-" + this.options.icon ).toggleClass( "ui-icon-" + options.icon, options.icon );
		}
	},

	refresh: function( create ) {
		if ( this.options.icon && this.options.iconpos === "notext" && this.element.attr( "title" ) ) {
			this.element.attr( "title", this.element.val() );
		}
		if ( !create ) {
			var originalElement = this.element.detach();
			$( this.wrapper ).text( this.element.val() ).append( originalElement );
		}
	}
});

$.mobile.button.initSelector = "[type='button'], [type='submit'], [type='reset']";

//auto self-init widgets
$.mobile._enhancer.add( "mobile.button" );

})( jQuery );
//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
});
//>>excludeEnd("jqmBuildExclude");
<commit_msg>Button: Fix initSelector to only do input[type=button] to exclude button elements with type=button Fixes #6237 - JQM 1.4 alpha button on form has a large border<commit_after>//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
//>>description: Custom-styled native input/buttons
//>>label: Buttons: Input or button-based
//>>group: Forms
//>>css.structure: ../css/structure/jquery.mobile.button.css
//>>css.theme: ../css/themes/default/jquery.mobile.theme.css

define( [ "jquery", "../../jquery.mobile.widget", "../../jquery.mobile.registry"  ], function( jQuery ) {
//>>excludeEnd("jqmBuildExclude");
(function( $, undefined ) {

$.widget( "mobile.button", {
	options: {
		theme: "inherit",
		icon: null,
		iconpos: "left",
		iconshadow: false, /* TODO: Deprecated in 1.4, remove in 1.5. */
		corners: true,
		shadow: true,
		inline: null,
		mini: null,
		wrapperClass: null,
		enhanced: false
	},

	_create: function() {

		if ( this.element.is( ":disabled" ) ) {
			this.options.disabled = true;
		}

		if ( !this.options.enhanced ) {
			this._enhance();
		}

		$.extend( this, {
			wrapper: this.element.parent()
		});

		this._on( {
			focus: function() {
				this.widget().addClass( $.mobile.focusClass );
			},

			blur: function() {
				this.widget().removeClass( $.mobile.focusClass );
			}
		});

		this.refresh( true );
	},

	_enhance: function() {
		this.element.wrap( this._button() );
	},

	_button: function() {
		return $("<div class='ui-btn ui-input-btn " +
			this.options.wrapperClass +
			" ui-btn-" + this.options.theme +
			( this.options.corners ? " ui-corner-all" : "" ) +
			( this.options.shadow ? " ui-shadow" : "" ) +
			( this.options.inline ? " ui-btn-inline" : "" ) +
			( this.options.mini ? " ui-mini" : "" ) +
			( this.options.disabled ? " ui-disabled" : "" ) +
			( this.options.iconpos ? " ui-btn-icon-" + this.options.iconpos : ( this.options.icon ? " ui-btn-icon-left" : "" ) ) +
			( this.options.icon ? "ui-icon-" + this.options.icon : "" ) +
			"' >" + this.element.val() + "
");
	},

	widget: function() {
		return this.wrapper;
	},

	_destroy: function() {
			this.element.insertBefore( this.button );
			this.button.remove();
	},

	_setOptions: function( options ) {
		if ( options.theme !== undefined ) {
			this.widget().removeClass( this.options.theme ).addClass( "ui-btn-" + options.theme );
		}
		if ( options.corners !== undefined ) {
			this.widget().toggleClass( "ui-corner-all", options.corners );
		}
		if ( options.shadow !== undefined ) {
			this.widget().toggleClass( "ui-shadow", options.shadow );
		}
		if ( options.inline !== undefined ) {
			this.widget().toggleClass( "ui-btn-inline", options.inline );
		}
		if ( options.mini !== undefined ) {
			this.widget().toggleClass( "ui-mini", options.mini );
		}
		if ( options.iconpos !== undefined ) {
			this.widget().removeClass( "ui-btn-icon-" + options.iconpos );
		}
		if ( options.icon !== undefined ) {
			if ( !this.options.iconpos && !options.iconpos ) {
				this.widget.toggleClass( "ui-btn-icon-left", options.icon );
			}
			this.widget().removeClass( "ui-icon-" + this.options.icon ).toggleClass( "ui-icon-" + options.icon, options.icon );
		}
	},

	refresh: function( create ) {
		if ( this.options.icon && this.options.iconpos === "notext" && this.element.attr( "title" ) ) {
			this.element.attr( "title", this.element.val() );
		}
		if ( !create ) {
			var originalElement = this.element.detach();
			$( this.wrapper ).text( this.element.val() ).append( originalElement );
		}
	}
});

$.mobile.button.initSelector = "input[type='button'], [type='submit'], [type='reset']";

//auto self-init widgets
$.mobile._enhancer.add( "mobile.button" );

})( jQuery );
//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
});
//>>excludeEnd("jqmBuildExclude");
<|endoftext|>


<commit_before>export default function HTMLRenderer(app, dom) {
	this.app = app;
	dom = dom || document.body;
	this.root_dom = dom;
}

HTMLRenderer.prototype.render = function() {
	var diff = this.app.render();

	// TODO: this is not really the diff nor are we doing any patching
	this.root_dom.innerHTML = '';

	if (diff) {
		var el = this.createElement(diff);

		this.root_dom.appendChild(el);
	}
}

HTMLRenderer.prototype.createElement = function(attr) {
	var el = document.createElement(attr.tag || 'div');

	if (attr.uid)
		el.id = attr.uid;

	el.style.position = 'absolute';

	if (attr.text)
		el.textContent = attr.text;

	var children = attr.children;

	if (children) {
		for (var k in children) {
			var child_attr = children[k];

			if (!child_attr) continue;

			var child_el = this.createElement(child_attr);

			el.appendChild(child_el);
		}
	}

	return el;
}
<commit_msg>Prefix DOM IDs with "jx:"<commit_after>export default function HTMLRenderer(app, dom) {
	this.app = app;
	dom = dom || document.body;
	this.root_dom = dom;
}

HTMLRenderer.prototype.render = function() {
	var diff = this.app.render();

	// TODO: this is not really the diff nor are we doing any patching
	this.root_dom.innerHTML = '';

	if (diff) {
		var el = this.createElement(diff);

		this.root_dom.appendChild(el);
	}
}

HTMLRenderer.prototype.createElement = function(attr) {
	var el = document.createElement(attr.tag || 'div');

	if (attr.uid)
		el.id = 'jx:' + attr.uid;

	el.style.position = 'absolute';

	if (attr.text)
		el.textContent = attr.text;

	var children = attr.children;

	if (children) {
		for (var k in children) {
			var child_attr = children[k];

			if (!child_attr) continue;

			var child_el = this.createElement(child_attr);

			el.appendChild(child_el);
		}
	}

	return el;
}
<|endoftext|>


<commit_before>// tempart templating library

;(function(tempartCompiler) {
	////-----------------------------------------------------------------------------------------
	// you need to overwrite this function, to have working partial support
	tempartCompiler.partial = function(block, context, currentValues, dirties, path ){
		// @TODO do a better api for that..
		console.error('Overwrite the function tempartCompiler.partial to have partials');
		return '';
	};
	////-----------------------------------------------------------------------------------------
	// returns the html and adds context to currentValues
	// path is not used, it only is passed to partial
	tempartCompiler.compile = function( blocks, content, currentValues, dirties, path, prefix ){
		if(!prefix) prefix = '';
		var local = {};
		return this._handleBlocks(blocks, content, local, currentValues, this._batchDirties( dirties ), path, prefix);
	};
	////-----------------------------------------------------------------------------------------
	// batches the dirties
	// @FIXME shouldn't be inside lib, should be given as this in the parameter
	tempartCompiler._batchDirties = function( dirties ){
		if( dirties === '*' ) return dirties;
		var result = {};
		var batchMap = {push: 'append', unshift: 'prepend', set: 'update'};
		// @TODO update / remove
		for( var key in dirties ){
			if( dirties.hasOwnProperty( key )){
				var dirty = dirties[ key ];
				result[key] = {append: [], prepend: [], update: []};
				for( var i = 0; i < dirty.length; i++ ){
					var entity = dirty[ i ];
					result[ key ][ batchMap[ entity.type ]].push( entity.value );
				}
			}
		}
		return result;
	};

	////-----------------------------------------------------------------------------------------
	// iterates threw the block on one level and calls the type-handler
	tempartCompiler._handleBlocks = function( blocks, content, local, currentValues, dirties, path, prefix ){
		var result = "";
		for( var i = 0; i < blocks.length; i++ ){
			result += this._handleBlock( blocks[i], content, local, currentValues, dirties, path, prefix );
		}
		return result;
	};
	////-----------------------------------------------------------------------------------------
	// returns the compiled block, depending on the inserted data
	tempartCompiler._handleBlock = function( block, content, local, currentValues, dirties, path, prefix ){
		var detailPrefix = prefix + this.types.executes.options.prefixDelimiter + block.id;
		if(block.type === 'log') { // No need for pre and suffix at an log
			return this.types[block.type]( block, content, local, currentValues, dirties, path, prefix );
		} else {
			if( dirties === '*' ){
				return this.types.executes.prefix( detailPrefix ) + this.types[ block.type ]( block, content, local, currentValues, dirties, path, prefix ) + this.types.executes.suffix( detailPrefix );
			} else {
				return this.types.dirties[ block.type ]( block, content, local, currentValues, dirties, path, prefix );
			}
		}

	};

	////-----------------------------------------------------------------------------------------
	// Contains the possible handlers
	tempartCompiler.types = {
		////-----------------------------------------------------------------------------------------
		// checks if a variable changed and update its attribute
		bindAttr: function( block, content, local, currentValues, dirties ){
			throw 'Not yet implemented';
		},
		////-----------------------------------------------------------------------------------------
		// returns a variable
		variable: function( block, content, local, currentValues, dirties ){
			var value = this.executes.get(block.depending[ 0 ], content, local );
			currentValues[ block.id ] = value;
			return value;
		},
		////-----------------------------------------------------------------------------------------
		// returns html
		echo: function( block, content, local, currentValues, dirties ){
			return block.content;
		},
		////-----------------------------------------------------------------------------------------
		// calls handleBlocks depending on the data contributed
		if: function( block, content, local, currentValues, dirties, path, prefix ) {
			var type = this.executes.condition( block.depending[ 0 ], content, local );
			currentValues[ block.id ] = {type: type, contains: {}};
			prefix += this.executes.options.prefixDelimiter + block.id;

			return tempartCompiler._handleBlocks(block[type], content, local, currentValues[block.id].contains, dirties, path, prefix);
		},
		////-----------------------------------------------------------------------------------------
		// sets a variable of an array and calls handleBlocks in the containing level
		each: function( block, content, local, currentValues, dirties, path, prefix ) {
			var value = this.executes.get(block.depending[ 0 ], content, local );
			currentValues[block.id] = {values: {}, order: []};

			if( value && value.length ){
				var result = "";
				for(var i = 0; i < value.length; i++) {
					var rand = this.executes.random();
					currentValues[ block.id ].values[ rand ] = {};
					currentValues[block.id].order.push( rand );
					var detailPrefix = prefix + this.executes.options.prefixDelimiter + block.id + ':' + rand;
					this.executes.set( block.depending[2], value[i], local );
					result += tempartCompiler._handleBlocks( block.contains, content, local, currentValues[ block.id ].values[ rand ], dirties, path, detailPrefix );
				}
				return result;
			} else {
				var elsePrefix = prefix + this.executes.options.prefixDelimiter + block.id;
				return tempartCompiler._handleBlocks( block.elseContains, content, local, currentValues, dirties, path, elsePrefix);
			}
		},
		////-----------------------------------------------------------------------------------------
		// puts values in the console
		log: function(block, content, local) {
			console.log( this.executes.get(block.depending[ 0 ], content, local ));
			return "";
		},
		////-----------------------------------------------------------------------------------------
		// patial handler, for rewriting contexts and stuff
		partial: function( block, content, local, currentValues, dirties, path ) {
			if(block.path !== '/') {
				path = path + '/' + block.path;
			}
			return tempartCompiler.partial(block, content, currentValues, dirties, path);
		},
		executes: {
			////-----------------------------------------------------------------------------------------
			// Executables are in need of options too!
			options: {
				domNode:   'script',
				attrStart: 'tempartStart',
				attrEnd: 'tempartEnd',
				prefixDelimiter: '-'
			},
			////-----------------------------------------------------------------------------------------
			// Checks if something is in the local space
			get: function( key, global, local ){
				if( local.hasOwnProperty( key )){
					return local[ key ];
				} else {
					return this._get( key.split( '.' ), global );
				}
			},
			////-----------------------------------------------------------------------------------------
			// handles dotnotation for getting values
			_get: function( keyParts, global) {
				var firstKey = keyParts.shift();
				if(!keyParts.length) {
					return global[ firstKey ];
				} else {
					return this._get( keyParts, global[ firstKey ] );
				}
			},
			////-----------------------------------------------------------------------------------------
			// sets things in the local space, we dont want to manipulate the original object
			set: function( key, value, scope ){
				scope[ key ] = value;
			},
			////-----------------------------------------------------------------------------------------
			// Removes some values from the local place
			unset: function( key, scope ){
				delete scope[key];
			},
			////-----------------------------------------------------------------------------------------
			// Generates start-element of an block
			prefix: function( prefix ){
				return '<' +this.options.domNode+ ' ' +this.options.attrStart+ '="' +prefix + '"></' +this.options.domNode+ '>';
			},
			////-----------------------------------------------------------------------------------------
			// Generates end-element of an block
			suffix: function( suffix ){
				return '<' +this.options.domNode+ ' ' +this.options.attrEnd+ '="' +suffix + '"></' +this.options.domNode+ '>';
			},
			////-----------------------------------------------------------------------------------------
			// Generates a random string (needed for length changing #each)
			random: function() {
				return Math.random().toString(36).substring(7);
			},
			////-----------------------------------------------------------------------------------------
			// decides what type will be used
			condition: function( key, global, local ){
				if(this.get( key, global, local )) {
					return 'contains';
				} else {
					return 'elseContains';
				}
			}
		},
		////-----------------------------------------------------------------------------------------
		// Special implementation of each lazy-block
		dirties: {
			////-----------------------------------------------------------------------------------------
			// only changed values should be iterated, or when in contains dependings something changed
			each: function( block, content, local, currentValues, dirties, path, prefix ){
				var previous = currentValues[ block.id ];
				var key = block.depending[ 0 ];
				if( dirties[ key ] !== undefined ){
					var types = ['prepend', 'append'];
					for( var i = 0; i < types.length; i++ ){
						var type  = types[ i ];
						var value = dirties[ key ][ type ];
						if( value.length ){
							tempartCompiler.types.executes.set( key, value, local );
							var tmpCurrentValues = {};
							// @FIXME overwriting result is not possible in server side
							var result = tempartCompiler.types[ block.type ]( block, content, local, tmpCurrentValues, '*', path, prefix );
							for( var orderIndex = 0; orderIndex < tmpCurrentValues[ block.id ].order.length; orderIndex++ ) {
								var rand = null;
								if( type == 'append' ){
									rand =  tmpCurrentValues[ block.id ].order[ orderIndex ];
									currentValues[ block.id ].order.push( rand );
								} else {
									var order = tmpCurrentValues[ block.id ].order;
									rand =  order[ order.length - orderIndex - 1];
									currentValues[ block.id ].order.unshift( rand );
								}
								currentValues[ block.id ].values[ rand ] = tmpCurrentValues[ block.id ].values[ rand ];
							}
							tempartCompiler.dom[ type ]( prefix + tempartCompiler.types.executes.options.prefixDelimiter + block.id, result );
							tempartCompiler.types.executes.unset( key, local ); // @FIXME is this actually needed?
						}
					}
				} else {
					// @TODO searchblocks
					throw "Not yet implemented";
				}

			},
			////-----------------------------------------------------------------------------------------
			// checks if a variable changed and update its attribute
			bindAttr: function( block, content, local, currentValues, dirties, path, prefix ){
				throw 'Not yet implemented';
			},
			////-----------------------------------------------------------------------------------------
			// checks if a variable changed
			variable: function( block, content, local, currentValues, dirties, path, prefix ){
				var previous = currentValues[ block.id ];
				var now      = tempartCompiler.types[ block.type ]( block, content, local, currentValues, dirties );
				if( previous != now ){
					tempartCompiler.dom.updateNode( prefix + tempartCompiler.types.executes.options.prefixDelimiter + block.id, now );
				}
			},
			////-----------------------------------------------------------------------------------------
			// an echo of a constant never changes
			echo: function() {},
			////-----------------------------------------------------------------------------------------
			// only updates when something is different, or an contains depending changed
			// @TODO
			if: function( block, content, local, currentValues, dirties, path, prefix ) {
				var type = tempartCompiler.types.executes.condition( block.depending[ 0 ], content, local );

				if( currentValues[ block.id ].type == type ){
					currentValues[ block.id ] = {type: type, contains: {}};
					prefix += tempartCompiler.types.executes.options.prefixDelimiter + block.id;
					return tempartCompiler._handleBlocks( block[ type ], content, local, currentValues[ block.id ].contains, dirties, path, prefix);
				} else {
					currentValues[ block.id ].type = type;
					var now = tempartCompiler._handleBlocks( block[ type ], content, local, currentValues[ block.id ].contains, '*', path, prefix);
					tempartCompiler.dom.updateNode( prefix + tempartCompiler.types.executes.options.prefixDelimiter + block.id, now );
				}

			},
			////-----------------------------------------------------------------------------------------
			// I actually don't know what exactly will happen here, some dependencieneeds to be done...
			// @TODO
			partial: function() {

			}
		},
	};

	tempartCompiler.dom = {
		////-----------------------------------------------------------------------------------------
		// Puts the things where they belong
		prepend: function( id, html ){
			this.obj( id, tempartCompiler.types.executes.options.attrStart).insertAdjacentHTML( 'afterend', html );
		},
		////-----------------------------------------------------------------------------------------
		// Puts the things where they belong
		append: function( id, html ){
			this.obj( id, tempartCompiler.types.executes.options.attrEnd).insertAdjacentHTML( 'beforebegin', html );
		},
		////-----------------------------------------------------------------------------------------
		// Realises nextUntil and its replacement
		updateNode: function( id, html ) {
			var first = this.obj( id, tempartCompiler.types.executes.options.attrStart );
			var end   = this.obj( id, tempartCompiler.types.executes.options.attrEnd );
			while( first.nextSibling != end ) {
				first.nextSibling.remove(); // @FIXME I want to batch that, but how?
			}
			first.insertAdjacentHTML( 'beforebegin', html );
		},
		////-----------------------------------------------------------------------------------------
		// Searches for the right objects
		obj: function( id, attr ){
			var objs = document.querySelectorAll( '[' + attr + ']' );
			for(var i = 0; i < objs.length; i++) {
				var obj = objs[ i ];
				if( obj.getAttribute( attr ) === id ){
					return obj;
				}
			}
		}
	};
}(typeof module == 'object' ? module.exports : window.tempartCompiler= {}));
<commit_msg>[each] update is now working as well<commit_after>// tempart templating library

;(function(tempartCompiler) {
	////-----------------------------------------------------------------------------------------
	// you need to overwrite this function, to have working partial support
	tempartCompiler.partial = function(block, context, currentValues, dirties, path ){
		// @TODO do a better api for that..
		console.error('Overwrite the function tempartCompiler.partial to have partials');
		return '';
	};
	////-----------------------------------------------------------------------------------------
	// returns the html and adds context to currentValues
	// path is not used, it only is passed to partial
	tempartCompiler.compile = function( blocks, content, currentValues, dirties, path, prefix ){
		if(!prefix) prefix = '';
		var local = {};
		return this._handleBlocks(blocks, content, local, currentValues, this._batchDirties( dirties ), path, prefix);
	};
	////-----------------------------------------------------------------------------------------
	// batches the dirties
	// @FIXME shouldn't be inside lib, should be given as this in the parameter
	tempartCompiler._batchDirties = function( dirties ){
		if( dirties === '*' ) return dirties;
		var result = {};
		var batchMap = {push: 'append', unshift: 'prepend', set: 'update'};
		// @TODO update / remove
		for( var key in dirties ){
			if( dirties.hasOwnProperty( key )){
				var dirty = dirties[ key ];
				result[key] = {append: [], prepend: [], update: []};
				for( var i = 0; i < dirty.length; i++ ){
					var entity = dirty[ i ];
					var type = batchMap[ entity.type ];
					if( type == 'update' ){
						result[ key ][ type ] = entity.value;
						break; // Update is alway a reference, prepend update are included
					} else {
						result[ key ][ type ].push( entity.value );
					}
				}
			}
		}
		return result;
	};

	////-----------------------------------------------------------------------------------------
	// iterates threw the block on one level and calls the type-handler
	tempartCompiler._handleBlocks = function( blocks, content, local, currentValues, dirties, path, prefix ){
		var result = "";
		for( var i = 0; i < blocks.length; i++ ){
			result += this._handleBlock( blocks[i], content, local, currentValues, dirties, path, prefix );
		}
		return result;
	};
	////-----------------------------------------------------------------------------------------
	// returns the compiled block, depending on the inserted data
	tempartCompiler._handleBlock = function( block, content, local, currentValues, dirties, path, prefix ){
		var detailPrefix = prefix + this.types.executes.options.prefixDelimiter + block.id;
		if(block.type === 'log') { // No need for pre and suffix at an log
			return this.types[block.type]( block, content, local, currentValues, dirties, path, prefix );
		} else {
			if( dirties === '*' ){
				return this.types.executes.prefix( detailPrefix ) + this.types[ block.type ]( block, content, local, currentValues, dirties, path, prefix ) + this.types.executes.suffix( detailPrefix );
			} else {
				return this.types.dirties[ block.type ]( block, content, local, currentValues, dirties, path, prefix );
			}
		}

	};

	////-----------------------------------------------------------------------------------------
	// Contains the possible handlers
	tempartCompiler.types = {
		////-----------------------------------------------------------------------------------------
		// checks if a variable changed and update its attribute
		bindAttr: function( block, content, local, currentValues, dirties ){
			throw 'Not yet implemented';
		},
		////-----------------------------------------------------------------------------------------
		// returns a variable
		variable: function( block, content, local, currentValues, dirties ){
			var value = this.executes.get(block.depending[ 0 ], content, local );
			currentValues[ block.id ] = value;
			return value;
		},
		////-----------------------------------------------------------------------------------------
		// returns html
		echo: function( block, content, local, currentValues, dirties ){
			return block.content;
		},
		////-----------------------------------------------------------------------------------------
		// calls handleBlocks depending on the data contributed
		if: function( block, content, local, currentValues, dirties, path, prefix ) {
			var type = this.executes.condition( block.depending[ 0 ], content, local );
			currentValues[ block.id ] = {type: type, contains: {}};
			prefix += this.executes.options.prefixDelimiter + block.id;

			return tempartCompiler._handleBlocks(block[type], content, local, currentValues[block.id].contains, dirties, path, prefix);
		},
		////-----------------------------------------------------------------------------------------
		// sets a variable of an array and calls handleBlocks in the containing level
		each: function( block, content, local, currentValues, dirties, path, prefix ) {
			var value = this.executes.get(block.depending[ 0 ], content, local );
			currentValues[block.id] = {values: {}, order: []};

			if( value && value.length ){
				var result = "";
				for(var i = 0; i < value.length; i++) {
					var rand = this.executes.random();
					currentValues[ block.id ].values[ rand ] = {};
					currentValues[block.id].order.push( rand );
					var detailPrefix = prefix + this.executes.options.prefixDelimiter + block.id + ':' + rand;
					this.executes.set( block.depending[2], value[i], local );
					result += tempartCompiler._handleBlocks( block.contains, content, local, currentValues[ block.id ].values[ rand ], dirties, path, detailPrefix );
				}
				return result;
			} else {
				var elsePrefix = prefix + this.executes.options.prefixDelimiter + block.id;
				return tempartCompiler._handleBlocks( block.elseContains, content, local, currentValues, dirties, path, elsePrefix);
			}
		},
		////-----------------------------------------------------------------------------------------
		// puts values in the console
		log: function(block, content, local) {
			console.log( this.executes.get(block.depending[ 0 ], content, local ));
			return "";
		},
		////-----------------------------------------------------------------------------------------
		// patial handler, for rewriting contexts and stuff
		partial: function( block, content, local, currentValues, dirties, path ) {
			if(block.path !== '/') {
				path = path + '/' + block.path;
			}
			return tempartCompiler.partial(block, content, currentValues, dirties, path);
		},
		executes: {
			////-----------------------------------------------------------------------------------------
			// Executables are in need of options too!
			options: {
				domNode:   'script',
				attrStart: 'tempartStart',
				attrEnd: 'tempartEnd',
				prefixDelimiter: '-'
			},
			////-----------------------------------------------------------------------------------------
			// Checks if something is in the local space
			get: function( key, global, local ){
				if( local.hasOwnProperty( key )){
					return local[ key ];
				} else {
					return this._get( key.split( '.' ), global );
				}
			},
			////-----------------------------------------------------------------------------------------
			// handles dotnotation for getting values
			_get: function( keyParts, global) {
				var firstKey = keyParts.shift();
				if(!keyParts.length) {
					return global[ firstKey ];
				} else {
					return this._get( keyParts, global[ firstKey ] );
				}
			},
			////-----------------------------------------------------------------------------------------
			// sets things in the local space, we dont want to manipulate the original object
			set: function( key, value, scope ){
				scope[ key ] = value;
			},
			////-----------------------------------------------------------------------------------------
			// Removes some values from the local place
			unset: function( key, scope ){
				delete scope[key];
			},
			////-----------------------------------------------------------------------------------------
			// Generates start-element of an block
			prefix: function( prefix ){
				return '<' +this.options.domNode+ ' ' +this.options.attrStart+ '="' +prefix + '"></' +this.options.domNode+ '>';
			},
			////-----------------------------------------------------------------------------------------
			// Generates end-element of an block
			suffix: function( suffix ){
				return '<' +this.options.domNode+ ' ' +this.options.attrEnd+ '="' +suffix + '"></' +this.options.domNode+ '>';
			},
			////-----------------------------------------------------------------------------------------
			// Generates a random string (needed for length changing #each)
			random: function() {
				return Math.random().toString(36).substring(7);
			},
			////-----------------------------------------------------------------------------------------
			// decides what type will be used
			condition: function( key, global, local ){
				if(this.get( key, global, local )) {
					return 'contains';
				} else {
					return 'elseContains';
				}
			}
		},
		////-----------------------------------------------------------------------------------------
		// Special implementation of each lazy-block
		dirties: {
			////-----------------------------------------------------------------------------------------
			// only changed values should be iterated, or when in contains dependings something changed
			each: function( block, content, local, currentValues, dirties, path, prefix ){
				var previous = currentValues[ block.id ];
				var key = block.depending[ 0 ];
				if( dirties[ key ] !== undefined ){
					var types = ['update', 'prepend', 'append'];
					for( var i = 0; i < types.length; i++ ){
						var type  = types[ i ];
						var value = dirties[ key ][ type ];
						if( value.length ){
							tempartCompiler.types.executes.set( key, value, local );
							var tmpCurrentValues = {};
							// @FIXME overwriting result is not possible in server side
							var result = tempartCompiler.types[ block.type ]( block, content, local, tmpCurrentValues, '*', path, prefix );
							if( type === 'update' ){
								currentValues[ block.id ] = tmpCurrentValues[ block.id ];
							} else {
								for( var orderIndex = 0; orderIndex < tmpCurrentValues[ block.id ].order.length; orderIndex++ ) {
									var rand = null;
									if( type === 'append' ){
										rand =  tmpCurrentValues[ block.id ].order[ orderIndex ];
										currentValues[ block.id ].order.push( rand );
									} else if( type === 'prepend' ){
										var order = tmpCurrentValues[ block.id ].order;
										rand =  order[ order.length - orderIndex - 1];
										currentValues[ block.id ].order.unshift( rand );
									} else {
										throw 'Unknown type!';
									}
									currentValues[ block.id ].values[ rand ] = tmpCurrentValues[ block.id ].values[ rand ];
								}
							}
							tempartCompiler.dom[ type ]( prefix + tempartCompiler.types.executes.options.prefixDelimiter + block.id, result );
							tempartCompiler.types.executes.unset( key, local ); // @FIXME is this actually needed?
						}
					}
				} else {
					// @TODO searchblocks
					throw "Not yet implemented";
				}

			},
			////-----------------------------------------------------------------------------------------
			// checks if a variable changed and update its attribute
			bindAttr: function( block, content, local, currentValues, dirties, path, prefix ){
				throw 'Not yet implemented';
			},
			////-----------------------------------------------------------------------------------------
			// checks if a variable changed
			variable: function( block, content, local, currentValues, dirties, path, prefix ){
				var previous = currentValues[ block.id ];
				var now      = tempartCompiler.types[ block.type ]( block, content, local, currentValues, dirties );
				if( previous != now ){
					tempartCompiler.dom.update( prefix + tempartCompiler.types.executes.options.prefixDelimiter + block.id, now );
				}
			},
			////-----------------------------------------------------------------------------------------
			// an echo of a constant never changes
			echo: function() {},
			////-----------------------------------------------------------------------------------------
			// only updates when something is different, or an contains depending changed
			// @TODO
			if: function( block, content, local, currentValues, dirties, path, prefix ) {
				var type = tempartCompiler.types.executes.condition( block.depending[ 0 ], content, local );

				if( currentValues[ block.id ].type == type ){
					currentValues[ block.id ] = {type: type, contains: {}};
					prefix += tempartCompiler.types.executes.options.prefixDelimiter + block.id;
					return tempartCompiler._handleBlocks( block[ type ], content, local, currentValues[ block.id ].contains, dirties, path, prefix);
				} else {
					currentValues[ block.id ].type = type;
					var now = tempartCompiler._handleBlocks( block[ type ], content, local, currentValues[ block.id ].contains, '*', path, prefix);
					tempartCompiler.dom.update( prefix + tempartCompiler.types.executes.options.prefixDelimiter + block.id, now );
				}

			},
			////-----------------------------------------------------------------------------------------
			// I actually don't know what exactly will happen here, some dependencieneeds to be done...
			// @TODO
			partial: function() {

			}
		},
	};

	tempartCompiler.dom = {
		////-----------------------------------------------------------------------------------------
		// Puts the things where they belong
		prepend: function( id, html ){
			this.obj( id, tempartCompiler.types.executes.options.attrStart).insertAdjacentHTML( 'afterend', html );
		},
		////-----------------------------------------------------------------------------------------
		// Puts the things where they belong
		append: function( id, html ){
			this.obj( id, tempartCompiler.types.executes.options.attrEnd).insertAdjacentHTML( 'beforebegin', html );
		},
		////-----------------------------------------------------------------------------------------
		// Realises nextUntil and its replacement
		update: function( id, html ) {
			var first = this.obj( id, tempartCompiler.types.executes.options.attrStart );
			var end   = this.obj( id, tempartCompiler.types.executes.options.attrEnd );
			while( first.nextSibling != end ) {
				first.nextSibling.remove(); // @FIXME I want to batch that, but how?
			}
			first.insertAdjacentHTML( 'beforebegin', html );
		},
		////-----------------------------------------------------------------------------------------
		// Searches for the right objects
		obj: function( id, attr ){
			var objs = document.querySelectorAll( '[' + attr + ']' );
			for(var i = 0; i < objs.length; i++) {
				var obj = objs[ i ];
				if( obj.getAttribute( attr ) === id ){
					return obj;
				}
			}
		}
	};
}(typeof module == 'object' ? module.exports : window.tempartCompiler= {}));
<|endoftext|>


<commit_before>
var level = require('level-test')()
var tape = require('tape')
//var join = require('path').join

var db = require('../')(level('test-mynosql', {encoding: 'json'}))
var db2 = require('../')(level('test-mynosql2', {encoding: 'json'}))

var pl   = require('pull-level')
var pull = require('pull-stream')

var pull = require('pull-stream')
var pfs  = require('pull-fs')
var glob = require('pull-glob')
var pl   = require('pull-level')

var LO = null
var HI = undefined

var createHash = require('crypto').createHash

function hash(o) {
  return createHash('sha256')
    .update(JSON.stringify(o))
    .digest().slice(0, 20).toString('base64')
}

function compare (a, b) {
  return a < b ? -1 : a > b ? 1 : 0
}

var all = function (stream, cb) {
  if('function' === typeof cb) return go(cb)

  function go (cb) {
    pull(stream, pull.collect(cb))
  }

  return go
}

//load all the dependencies into database.

tape('query dependency database', function (t) {

  require('../example').init(db, null, function (err) {
    if(err) throw err
    t.end()
  })

})

var query = [{path: ['version'], lt: '1.0.0'}]

tape('full scan', function (t) {

  all(require('../query/scan')(db, query).exec())
    (function (err, fullScanAry) {

      fullScanAry.forEach(function (pkg) {
        t.ok(pkg.value.version < '1.0.0')
      })

      db.createIndex([['version']], function (err) {
        pull(
          require('../query/filtered-index')(db, query).exec(),
          pull.collect(function (err, ary) {
            ary.forEach(function (pkg) {
              t.ok(pkg.value.version < '1.0.0')
            })

            fullScanAry.sort(function (a, b) {
              return (
                compare(a.value.version, b.value.version) ||
                compare(a.key, b.key)
              )
            })

            t.equal(ary.length, fullScanAry.length)

            function min (e) {
              return [e.key, e.value.name, e.value.version]
            }

            t.deepEqual(ary.map(min), fullScanAry.map(min))

            t.deepEqual(ary.slice(0, 3), fullScanAry.map(function (e) {
              delete e.ts; return e
            }).slice(0, 3))

            t.end()
          })
        )

      })

    })

})

tape('compound indexes', function (t) {

  t.deepEqual(db.indexes.map(function (e) { return e.path }), [
    [['version']]
  ])

  db.createIndex([['name'], ['version']], function (err) {
    pull(
      pl.read(db.sublevel('idx'), {
        values: false,
        gte: [['name'], undefined],
        lte: [['name'], null]
      }),
      pull.through(function (key) {
        t.deepEqual(key[0], [[['name'], ['version']]])
        t.ok(key[1].length, 2)
        t.ok('string' === typeof key[2])
        console.log(JSON.stringify(key))
      }),
      pull.drain(null, function (err) {

        all(db.query([
          {path: ['name'], eq: 'ltgt'},
          {path: ['version'], gte: '2.0.0', lt: '3.0.0'}
        ])) (function (err, ary) {
          if(err) throw err
          console.log(ary)
          t.ok(ary.length >= 1)
          ary.forEach(function (pkg) {
            t.equal(pkg.value.name, 'ltgt')
            t.ok(pkg.value.version >= '2.0.0')
            t.ok(pkg.value.version < '3.0.0')
          })
          t.end()
        })
      })
    )
  })

})

tape('glob query for keyword.*', function (t) {
  var start = Date.now()
  all(db.query([
    {path: ['keywords', true], eq: 'database'}
  ], {index: false})) (function (err, ary) {
    var p = ary.filter(function (pkg) {
      return pkg.value.name === 'level'
    }).shift()
    t.equal(p.value.name, 'level')
    var scantime = Date.now() - start
    console.log('FULL SCAN TIME', scantime)

    db.createIndex([['keywords', true]], function (err) {
      all(pl.read(db.sublevel('idx'), {
        values: false,
        gte: [[['keywords', true]], LO],
        lte: [[['keywords', true]], HI]
      })) (function (err, ary) {
        console.log('GLOB INDEX', ary.map(JSON.stringify))

        return t.end()

        t.ok(ary.length)
        var start = Date.now()
        all(db.query([
          {path: ['keywords', true], eq: 'database'}
        ])) (function (err, ary) {
          //check the index time is smaller than full scan time
          //although both will be small since the database is tiny.
          t.ok(Date.now() - start < scantime)
          console.log('indexed query time', Date.now() - start)
          t.end()
        })
      })
    })
  })
})

tape('build glob index in realtime', function (t) {

  db2.createIndex([['keywords', true]], function (err) {
    if(err) throw err
    pull(
      db.scan(),
      pl.write(db2, function (err) {
        all(pl.read(db.sublevel('idx'), {
            values: false,
            gte: [[['keywords', true]], LO],
            lte: [[['keywords', true]], HI]
          })) (function (err, ary) {
            console.log(ary)
            t.ok(ary.length, 'realtime index non-empty')
            t.end()
          })
      })
    )
  })
})

<commit_msg>tidy up db tests<commit_after>
var level = require('level-test')()
var tape = require('tape')

var db = require('../')(level('test-mynosql', {encoding: 'json'}))
var db2 = require('../')(level('test-mynosql2', {encoding: 'json'}))

var pl   = require('pull-level')
var pull = require('pull-stream')

var pull = require('pull-stream')
var pl   = require('pull-level')

var LO = null
var HI = undefined

function compare (a, b) {
  return a < b ? -1 : a > b ? 1 : 0
}

var all = function (stream, cb) {
  if('function' === typeof cb) return go(cb)

  function go (cb) {
    pull(stream, pull.collect(cb))
  }

  return go
}

//load all the dependencies into database.

tape('query dependency database', function (t) {

  require('../example').init(db, null, function (err) {
    if(err) throw err
    t.end()
  })

})

var query = [{path: ['version'], lt: '1.0.0'}]

tape('full scan', function (t) {

  all(require('../query/scan')(db, query).exec())
    (function (err, fullScanAry) {

      fullScanAry.forEach(function (pkg) {
        t.ok(pkg.value.version < '1.0.0')
      })

      db.createIndex([['version']], function (err) {
        pull(
          require('../query/filtered-index')(db, query).exec(),
          pull.collect(function (err, ary) {
            ary.forEach(function (pkg) {
              t.ok(pkg.value.version < '1.0.0')
            })

            fullScanAry.sort(function (a, b) {
              return (
                compare(a.value.version, b.value.version) ||
                compare(a.key, b.key)
              )
            })

            t.equal(ary.length, fullScanAry.length)

            function min (e) {
              return [e.key, e.value.name, e.value.version]
            }

            t.deepEqual(ary.map(min), fullScanAry.map(min))

            t.deepEqual(ary.slice(0, 3), fullScanAry.map(function (e) {
              delete e.ts; return e
            }).slice(0, 3))

            t.end()
          })
        )

      })

    })

})

tape('compound indexes', function (t) {

  t.deepEqual(db.indexes.map(function (e) { return e.path }), [
    [['version']]
  ])

  db.createIndex([['name'], ['version']], function (err) {
    pull(
      pl.read(db.sublevel('idx'), {
        values: false,
        gte: [['name'], undefined],
        lte: [['name'], null]
      }),
      pull.through(function (key) {
        t.deepEqual(key[0], [[['name'], ['version']]])
        t.ok(key[1].length, 2)
        t.ok('string' === typeof key[2])
        console.log(JSON.stringify(key))
      }),
      pull.drain(null, function (err) {

        all(db.query([
          {path: ['name'], eq: 'ltgt'},
          {path: ['version'], gte: '2.0.0', lt: '3.0.0'}
        ])) (function (err, ary) {
          if(err) throw err
          console.log(ary)
          t.ok(ary.length >= 1)
          ary.forEach(function (pkg) {
            t.equal(pkg.value.name, 'ltgt')
            t.ok(pkg.value.version >= '2.0.0')
            t.ok(pkg.value.version < '3.0.0')
          })
          t.end()
        })
      })
    )
  })

})

tape('glob query for keyword.*', function (t) {
  var start = Date.now()
  all(db.query([
    {path: ['keywords', true], eq: 'database'}
  ], {index: false})) (function (err, ary) {
    var p = ary.filter(function (pkg) {
      return pkg.value.name === 'level'
    }).shift()
    t.equal(p.value.name, 'level')
    var scantime = Date.now() - start
    console.log('FULL SCAN TIME', scantime)

    db.createIndex([['keywords', true]], function (err) {
      all(pl.read(db.sublevel('idx'), {
        values: false,
        gte: [[['keywords', true]], LO],
        lte: [[['keywords', true]], HI]
      })) (function (err, ary) {
        console.log('GLOB INDEX', ary.map(JSON.stringify))

        t.ok(ary.length)
        var start = Date.now()
        all(db.query([
          {path: ['keywords', true], eq: 'database'}
        ])) (function (err, ary) {
          //check the index time is smaller than full scan time
          //although both will be small since the database is tiny.
          t.ok(Date.now() - start < scantime)
          console.log('indexed query time', Date.now() - start)
          t.end()
        })
      })
    })
  })
})

tape('build glob index in realtime', function (t) {

  db2.createIndex([['keywords', true]], function (err) {
    if(err) throw err
    pull(
      db.scan(),
      pl.write(db2, function (err) {
        all(pl.read(db.sublevel('idx'), {
            values: false,
            gte: [[['keywords', true]], LO],
            lte: [[['keywords', true]], HI]
          })) (function (err, ary) {
            console.log(ary)
            t.ok(ary.length, 'realtime index non-empty')
            t.end()
          })
      })
    )
  })
})

<|endoftext|>