<commit_before>'use strict';

var gulp = require('gulp');
var plugins = require('gulp-load-plugins')();
var sass = require('gulp-sass');
var pkg = require('./package');
var scripts = {
      name: 'jquery.contextMenu.js',
      min: 'jquery.contextMenu.min.js',
      all: [
        'gulpfile.js',
        'src/jquery.contextMenu.js',
        'dist/jquery.contextMenu.js'
      ],
      main: 'dist/jquery.contextMenu.js',
      src: [
          'src/jquery.contextMenu.js'
      ],
      dest: 'dist',
      libs: [
      ]
    };
var styles = {
      name: 'jquery.contextMenu.css',
      min: 'jquery.contextMenu.min.css',
      all: [
        'src/sass/**/*.scss'
      ],
      main: 'dist/jquery.contextMenu.css',
      src: 'src/sass/jquery.contextMenu.scss',
      dest: 'dist'
    };
var icons = {
    src: 'src/icons/*.svg',
    templateFileFont: 'src/sass/icons/_variables.scss.tpl',
    templateFileIconClasses: 'src/sass/icons/_icon_classes.scss.tpl',
    fontOutputPath: 'dist/font',
    scssOutputPath: 'src/sass/icons/'
};
var replacement = {
      regexp: /@\w+/g,
      filter: function (placeholder) {
        switch (placeholder) {
          case '@VERSION':
            placeholder = pkg.version;
            break;

          case '@YEAR':
            placeholder = (new Date()).getFullYear();
            break;

          case '@DATE':
            placeholder = (new Date()).toISOString();
            break;
        }

        return placeholder;
      }
    };

gulp.task('jshint', function () {
  return gulp.src(scripts.src).
    pipe(plugins.jshint('src/.jshintrc')).
    pipe(plugins.jshint.reporter('default'));
});

gulp.task('jscs', function () {
  return gulp.src(scripts.src).
    pipe(plugins.jscs());
});

gulp.task('js', ['jshint', 'jscs', 'jslibs'], function () {
  return gulp.src(scripts.src).
    pipe(plugins.sourcemaps.init()).
    pipe(plugins.replace(replacement.regexp, replacement.filter)).
    pipe(gulp.dest(scripts.dest)).
    pipe(plugins.rename(scripts.min)).
    pipe(plugins.uglify({
      preserveComments: 'some'
    })).
    pipe(plugins.sourcemaps.write('.')).
    pipe(gulp.dest(scripts.dest));
});

gulp.task('jslibs', function (){
    return gulp.src(scripts.libs).
        pipe(plugins.rename({prefix: 'jquery.ui.'})).
        pipe(gulp.dest('src')).
        pipe(gulp.dest('dist')).
        pipe(plugins.rename({extname: '.min.js'})).
        pipe(gulp.dest('dist')).
        pipe(plugins.uglify({
            preserveComments: 'some'
        })).
        pipe(plugins.sourcemaps.write('.')).
        pipe(gulp.dest(scripts.dest));
});

gulp.task('css', function () {
  return gulp.src(styles.src).
    pipe(sass()).
    pipe(plugins.csslint('src/.csslintrc')).
    pipe(plugins.csslint.reporter()).
    pipe(plugins.sourcemaps.init()).
    pipe(plugins.replace(replacement.regexp, replacement.filter)).
    pipe(plugins.autoprefixer({
      browsers: [
        'Android 2.3',
        'Android >= 4',
        'Chrome >= 20',
        'Firefox >= 24',
        'Explorer >= 8',
        'iOS >= 6',
        'Opera >= 12',
        'Safari >= 6'
      ]
    })).
    pipe(plugins.csscomb('src/.csscomb.json')).
    pipe(plugins.rename(styles.name)).
    pipe(gulp.dest(styles.dest)).
    pipe(plugins.rename(styles.min)).
    pipe(plugins.minifyCss()).
    pipe(plugins.sourcemaps.write('.')).
    pipe(gulp.dest(styles.dest));
});

gulp.task('build-icons', function () {
    var iconfont = require('gulp-iconfont');
    var consolidate = require('gulp-consolidate');

    gulp.src(icons.src)
        .pipe(iconfont({
            fontName: 'context-menu-icons',
            fontHeight: 1024,
            descent: 64,
            normalize: true,
            appendCodepoints: false,
            startCodepoint: 0xE001,
			formats: ['ttf', 'eot', 'woff', 'woff2']
        }))
        .on('glyphs', function (glyphs) {
            var options = {
                glyphs: glyphs,
                className: 'context-menu-icon',
                mixinName: 'context-menu-item-icon'
            };

            gulp.src(icons.templateFileFont)
                .pipe(consolidate('lodash',  options))
                .pipe(plugins.rename({basename: '_variables', extname: '.scss'}))
                .pipe(gulp.dest(icons.scssOutputPath));

            gulp.src(icons.templateFileIconClasses)
                .pipe(consolidate('lodash', options))
                .pipe(plugins.rename('_icons.scss'))
                .pipe(gulp.dest('src/sass')); // set path to export your sample HTML
        })
        .pipe(gulp.dest(icons.fontOutputPath));
});

/**
 * Update paths in integration tests that are generated by the documentation
 * generator so they use the local source.
 */
gulp.task('integration-test-paths', function(){
    return gulp.src('test/integration/html/*.html').
    pipe(plugins.replace('http\:\/\/swisnl\.github\.io\/jQuery\-contextMenu\/dist\/', '\.\.\/\.\.\/\.\.\/src\/')).
    pipe(plugins.replace('\/src\/jquery.contextMenu.css', '\/dist\/jquery.contextMenu.css')).
    pipe(plugins.replace('http\:\/\/swisnl\.github\.io\/jQuery-contextMenu\/js\/jquery\.ui\.position\.min\.js', '\.\.\/\.\.\/\.\.\/src\/jquery\.ui\.position\.min\.js')).
    pipe(gulp.dest('test/integration/html/'));
});

gulp.task('watch', ['js', 'css'], function () {
  gulp.watch(scripts.src, ['js']);
  gulp.watch(styles.all, ['css']);
});

gulp.task('build', ['build-icons', 'css', 'js', 'integration-test-paths']);

gulp.task('default', ['watch']);
<commit_msg>Remove integratino test paths from gulp tasks<commit_after>'use strict';

var gulp = require('gulp');
var plugins = require('gulp-load-plugins')();
var sass = require('gulp-sass');
var pkg = require('./package');
var scripts = {
      name: 'jquery.contextMenu.js',
      min: 'jquery.contextMenu.min.js',
      all: [
        'gulpfile.js',
        'src/jquery.contextMenu.js',
        'dist/jquery.contextMenu.js'
      ],
      main: 'dist/jquery.contextMenu.js',
      src: [
          'src/jquery.contextMenu.js'
      ],
      dest: 'dist',
      libs: [
      ]
    };
var styles = {
      name: 'jquery.contextMenu.css',
      min: 'jquery.contextMenu.min.css',
      all: [
        'src/sass/**/*.scss'
      ],
      main: 'dist/jquery.contextMenu.css',
      src: 'src/sass/jquery.contextMenu.scss',
      dest: 'dist'
    };
var icons = {
    src: 'src/icons/*.svg',
    templateFileFont: 'src/sass/icons/_variables.scss.tpl',
    templateFileIconClasses: 'src/sass/icons/_icon_classes.scss.tpl',
    fontOutputPath: 'dist/font',
    scssOutputPath: 'src/sass/icons/'
};
var replacement = {
      regexp: /@\w+/g,
      filter: function (placeholder) {
        switch (placeholder) {
          case '@VERSION':
            placeholder = pkg.version;
            break;

          case '@YEAR':
            placeholder = (new Date()).getFullYear();
            break;

          case '@DATE':
            placeholder = (new Date()).toISOString();
            break;
        }

        return placeholder;
      }
    };

gulp.task('jshint', function () {
  return gulp.src(scripts.src).
    pipe(plugins.jshint('src/.jshintrc')).
    pipe(plugins.jshint.reporter('default'));
});

gulp.task('jscs', function () {
  return gulp.src(scripts.src).
    pipe(plugins.jscs());
});

gulp.task('js', ['jshint', 'jscs', 'jslibs'], function () {
  return gulp.src(scripts.src).
    pipe(plugins.sourcemaps.init()).
    pipe(plugins.replace(replacement.regexp, replacement.filter)).
    pipe(gulp.dest(scripts.dest)).
    pipe(plugins.rename(scripts.min)).
    pipe(plugins.uglify({
      preserveComments: 'some'
    })).
    pipe(plugins.sourcemaps.write('.')).
    pipe(gulp.dest(scripts.dest));
});

gulp.task('jslibs', function (){
    return gulp.src(scripts.libs).
        pipe(plugins.rename({prefix: 'jquery.ui.'})).
        pipe(gulp.dest('src')).
        pipe(gulp.dest('dist')).
        pipe(plugins.rename({extname: '.min.js'})).
        pipe(gulp.dest('dist')).
        pipe(plugins.uglify({
            preserveComments: 'some'
        })).
        pipe(plugins.sourcemaps.write('.')).
        pipe(gulp.dest(scripts.dest));
});

gulp.task('css', function () {
  return gulp.src(styles.src).
    pipe(sass()).
    pipe(plugins.csslint('src/.csslintrc')).
    pipe(plugins.csslint.reporter()).
    pipe(plugins.sourcemaps.init()).
    pipe(plugins.replace(replacement.regexp, replacement.filter)).
    pipe(plugins.autoprefixer({
      browsers: [
        'Android 2.3',
        'Android >= 4',
        'Chrome >= 20',
        'Firefox >= 24',
        'Explorer >= 8',
        'iOS >= 6',
        'Opera >= 12',
        'Safari >= 6'
      ]
    })).
    pipe(plugins.csscomb('src/.csscomb.json')).
    pipe(plugins.rename(styles.name)).
    pipe(gulp.dest(styles.dest)).
    pipe(plugins.rename(styles.min)).
    pipe(plugins.minifyCss()).
    pipe(plugins.sourcemaps.write('.')).
    pipe(gulp.dest(styles.dest));
});

gulp.task('build-icons', function () {
    var iconfont = require('gulp-iconfont');
    var consolidate = require('gulp-consolidate');

    gulp.src(icons.src)
        .pipe(iconfont({
            fontName: 'context-menu-icons',
            fontHeight: 1024,
            descent: 64,
            normalize: true,
            appendCodepoints: false,
            startCodepoint: 0xE001,
			formats: ['ttf', 'eot', 'woff', 'woff2']
        }))
        .on('glyphs', function (glyphs) {
            var options = {
                glyphs: glyphs,
                className: 'context-menu-icon',
                mixinName: 'context-menu-item-icon'
            };

            gulp.src(icons.templateFileFont)
                .pipe(consolidate('lodash',  options))
                .pipe(plugins.rename({basename: '_variables', extname: '.scss'}))
                .pipe(gulp.dest(icons.scssOutputPath));

            gulp.src(icons.templateFileIconClasses)
                .pipe(consolidate('lodash', options))
                .pipe(plugins.rename('_icons.scss'))
                .pipe(gulp.dest('src/sass')); // set path to export your sample HTML
        })
        .pipe(gulp.dest(icons.fontOutputPath));
});

gulp.task('watch', ['js', 'css'], function () {
  gulp.watch(scripts.src, ['js']);
  gulp.watch(styles.all, ['css']);
});

gulp.task('build', ['build-icons', 'css', 'js']);

gulp.task('default', ['watch']);
<|endoftext|>


<commit_before>// Copyright 2015 Eryx <evorui аt gmаil dοt cοm>, All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

var hpress = {
    base: "/hpress/",
    sys_version: "1.0",
    debug: true,
}

hpress.urlver = function(debug_off) {
    var u = "?_v="+ hpress.sys_version;
    if (!debug_off && hpress.debug) {
        u += "&_=" + Math.random();
    }
    return u;
}

hpress.Boot = function() {
    if (window._basepath && window._basepath.length > 1) {
        hpress.base = window._basepath;
        if (hpress.base.substring(hpress.base.length - 1) != "/") {
            hpress.base += "/";
        }
    }
    if (window._sys_version && window._sys_version.length > 1) {
        hpress.sys_version = window._sys_version;
    }

    if (!hpress.base || hpress.base == "") {
        hpress.base = "/";
    }

    seajs.config({
        base: hpress.base,
    });

    seajs.use([
        "~/hpress/js/jquery.js"+ hpress.urlver(),
    ], function() {

        seajs.use([
            "~/lessui/js/lessui.js"+ hpress.urlver(),
        ], function() {

            setTimeout(function() {
                for (var i in window.onload_hooks) {
                    window.onload_hooks[i]();
                }
            }, 100);
        });
    });
}

hpress.HttpSrvBasePath = function(url) {
    if (hpress.base == "") {
        return url;
    }

    if (url.substr(0, 1) == "/") {
        return url;
    }

    return hpress.base + url;
}

hpress.CodeRender = function() {
    $("code[class^='language-']").each(function(i, el) {

        var lang = el.className.substr("language-".length);
        if (lang == "hchart" || lang == "hooto_chart") {
            return hpress.hchartRender(i, el);
        }

        var modes = [];

        if (lang == "html") {
            lang = "htmlmixed";
        }

        switch (lang) {

            case "php":
                modes.push("~/cm/5/mode/php/php.js"+ hpress.urlver());
            case "htmlmixed":
                modes.push("~/cm/5/mode/xml/xml.js"+ hpress.urlver());
                modes.push("~/cm/5/mode/javascript/javascript.js"+ hpress.urlver());
                modes.push("~/cm/5/mode/css/css.js"+ hpress.urlver());
                modes.push("~/cm/5/mode/htmlmixed/htmlmixed.js"+ hpress.urlver());
                break;

            case "c":
            case "cpp":
            case "clike":
            case "java":
                lang = "clike";
                break;

            case "json":
                modes.push("~/cm/5/mode/javascript/javascript.js"+ hpress.urlver());
                lang = "application/ld+json";
                break;

            case "go":
            case "javascript":
            case "css":
            case "xml":
            case "yaml":
            case "lua":
            case "markdown":
            case "r":
            case "shell":
            case "sql":
            case "swift":
            case "erlang":
            case "nginx":
                modes.push("~/cm/5/mode/" + lang + "/" + lang + ".js"+ hpress.urlver());
                break;

            default:
                return;
        }

        seajs.use([
            "~/cm/5/lib/codemirror.css"+ hpress.urlver(),
            "~/cm/5/lib/codemirror.js"+ hpress.urlver(),
        ], function() {

            modes.push("~/cm/5/addon/runmode/runmode.js"+ hpress.urlver());
            modes.push("~/cm/5/mode/clike/clike.js"+ hpress.urlver());

            seajs.use(modes, function() {

                $(el).addClass('cm-s-default'); // apply a theme class
                CodeMirror.runMode($(el).text(), lang, $(el)[0]);
            });
        });
    });
}

hpress.hchartRender = function(i, elem) {
    var elem_id = "hchart-id-" + i;
    elem.setAttribute("id", elem_id);
    seajs.use([
        "~/hchart/hchart.js"+ hpress.urlver(),
    ], function() {
        hooto_chart.basepath = hpress.base + "/~/hchart";
        hooto_chart.opts_width = "600px";
        hooto_chart.opts_height = "400px";
        hooto_chart.JsonRenderElement(elem, elem_id);
    });
}

hpress.NavActive = function(tplid, path) {
    if (!tplid || !path) {
        return;
    }

    var nav = $("#" + tplid);
    nav.find("a").each(function() {

        var href = $(this).attr("href");

        if (href) {

            if (href.match(path)) {
                nav.find("a.active").removeClass("active");
                $(this).addClass("active");
            }
        }
    });
}

hpress.Ajax = function(url, options) {
    options = options || {};

    //
    if (url.substr(0, 1) != "/" && url.substr(0, 4) != "http") {
        url = hpress.HttpSrvBasePath(url);
    }

    l4i.Ajax(url, options)
}

hpress.ActionLoader = function(target, url) {
    hpress.Ajax(hpress.HttpSrvBasePath(url), {
        callback: function(err, data) {
            $("#" + target).html(data);
        }
    });
}

hpress.ApiCmd = function(url, options) {
    hpress.Ajax(hpress.HttpSrvBasePath(url), options);
}

hpress.AuthSessionRefresh = function() {
    hpress.Ajax(hpress.HttpSrvBasePath("auth/session"), {
        callback: function(err, data) {

            if (err || !data || data.kind != "AuthSession") {

                return l4iTemplate.Render({
                    dstid: "hpress-topbar-userbar",
                    tplid: "hpress-topbar-user-unsigned-tpl",
                });
            }

            l4iTemplate.Render({
                dstid: "hpress-topbar-userbar",
                tplid: "hpress-topbar-user-signed-tpl",
                data: data,
                success: function() {

                    $("#hpress-topbar-userbar").hover(function() {
                        $("#hpress-topbar-user-signed-modal").fadeIn(200);
                    }, function() {}
                    );
                    $("#hpress-topbar-user-signed-modal").hover(function() {}, function() {
                        $("#hpress-topbar-user-signed-modal").fadeOut(200);
                    }
                    );
                },
            });
        },
    });
}

<commit_msg>[CHG] jsfmt<commit_after>// Copyright 2015 Eryx <evorui аt gmаil dοt cοm>, All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

var hpress = {
    base: "/hpress/",
    sys_version: "1.0",
    debug: true,
}

hpress.urlver = function(debug_off) {
    var u = "?_v=" + hpress.sys_version;
    if (!debug_off && hpress.debug) {
        u += "&_=" + Math.random();
    }
    return u;
}

hpress.Boot = function() {
    if (window._basepath && window._basepath.length > 1) {
        hpress.base = window._basepath;
        if (hpress.base.substring(hpress.base.length - 1) != "/") {
            hpress.base += "/";
        }
    }
    if (window._sys_version && window._sys_version.length > 1) {
        hpress.sys_version = window._sys_version;
    }

    if (!hpress.base || hpress.base == "") {
        hpress.base = "/";
    }

    seajs.config({
        base: hpress.base,
    });

    seajs.use([
        "~/hpress/js/jquery.js" + hpress.urlver(),
    ], function() {

        seajs.use([
            "~/lessui/js/lessui.js" + hpress.urlver(),
        ], function() {

            setTimeout(function() {
                for (var i in window.onload_hooks) {
                    window.onload_hooks[i]();
                }
            }, 100);
        });
    });
}

hpress.HttpSrvBasePath = function(url) {
    if (hpress.base == "") {
        return url;
    }

    if (url.substr(0, 1) == "/") {
        return url;
    }

    return hpress.base + url;
}

hpress.CodeRender = function() {
    $("code[class^='language-']").each(function(i, el) {

        var lang = el.className.substr("language-".length);
        if (lang == "hchart" || lang == "hooto_chart") {
            return hpress.hchartRender(i, el);
        }

        var modes = [];

        if (lang == "html") {
            lang = "htmlmixed";
        }

        switch (lang) {

            case "php":
                modes.push("~/cm/5/mode/php/php.js" + hpress.urlver());
            case "htmlmixed":
                modes.push("~/cm/5/mode/xml/xml.js" + hpress.urlver());
                modes.push("~/cm/5/mode/javascript/javascript.js" + hpress.urlver());
                modes.push("~/cm/5/mode/css/css.js" + hpress.urlver());
                modes.push("~/cm/5/mode/htmlmixed/htmlmixed.js" + hpress.urlver());
                break;

            case "c":
            case "cpp":
            case "clike":
            case "java":
                lang = "clike";
                break;

            case "json":
                modes.push("~/cm/5/mode/javascript/javascript.js" + hpress.urlver());
                lang = "application/ld+json";
                break;

            case "go":
            case "javascript":
            case "css":
            case "xml":
            case "yaml":
            case "lua":
            case "markdown":
            case "r":
            case "shell":
            case "sql":
            case "swift":
            case "erlang":
            case "nginx":
                modes.push("~/cm/5/mode/" + lang + "/" + lang + ".js" + hpress.urlver());
                break;

            default:
                return;
        }

        seajs.use([
            "~/cm/5/lib/codemirror.css" + hpress.urlver(),
            "~/cm/5/lib/codemirror.js" + hpress.urlver(),
        ], function() {

            modes.push("~/cm/5/addon/runmode/runmode.js" + hpress.urlver());
            modes.push("~/cm/5/mode/clike/clike.js" + hpress.urlver());

            seajs.use(modes, function() {

                $(el).addClass('cm-s-default'); // apply a theme class
                CodeMirror.runMode($(el).text(), lang, $(el)[0]);
            });
        });
    });
}

hpress.hchartRender = function(i, elem) {
    var elem_id = "hchart-id-" + i;
    elem.setAttribute("id", elem_id);
    seajs.use([
        "~/hchart/hchart.js" + hpress.urlver(),
    ], function() {
        hooto_chart.basepath = hpress.base + "/~/hchart";
        hooto_chart.opts_width = "600px";
        hooto_chart.opts_height = "400px";
        hooto_chart.JsonRenderElement(elem, elem_id);
    });
}

hpress.NavActive = function(tplid, path) {
    if (!tplid || !path) {
        return;
    }

    var nav = $("#" + tplid);
    nav.find("a").each(function() {

        var href = $(this).attr("href");

        if (href) {

            if (href.match(path)) {
                nav.find("a.active").removeClass("active");
                $(this).addClass("active");
            }
        }
    });
}

hpress.Ajax = function(url, options) {
    options = options || {};

    //
    if (url.substr(0, 1) != "/" && url.substr(0, 4) != "http") {
        url = hpress.HttpSrvBasePath(url);
    }

    l4i.Ajax(url, options)
}

hpress.ActionLoader = function(target, url) {
    hpress.Ajax(hpress.HttpSrvBasePath(url), {
        callback: function(err, data) {
            $("#" + target).html(data);
        }
    });
}

hpress.ApiCmd = function(url, options) {
    hpress.Ajax(hpress.HttpSrvBasePath(url), options);
}

hpress.AuthSessionRefresh = function() {
    hpress.Ajax(hpress.HttpSrvBasePath("auth/session"), {
        callback: function(err, data) {

            if (err || !data || data.kind != "AuthSession") {

                return l4iTemplate.Render({
                    dstid: "hpress-topbar-userbar",
                    tplid: "hpress-topbar-user-unsigned-tpl",
                });
            }

            l4iTemplate.Render({
                dstid: "hpress-topbar-userbar",
                tplid: "hpress-topbar-user-signed-tpl",
                data: data,
                success: function() {

                    $("#hpress-topbar-userbar").hover(function() {
                        $("#hpress-topbar-user-signed-modal").fadeIn(200);
                    }, function() {}
                    );
                    $("#hpress-topbar-user-signed-modal").hover(function() {}, function() {
                        $("#hpress-topbar-user-signed-modal").fadeOut(200);
                    }
                    );
                },
            });
        },
    });
}

<|endoftext|>


<commit_before>define([
    "dojo/_base/declare",
    "esri/graphic",
    "esri/layers/GraphicsLayer",
    "esri/InfoTemplate",
    "esri/graphicsUtils",
    "esri/Color",
    "esri/symbols/SimpleMarkerSymbol",
    "esri/symbols/SimpleLineSymbol",
    "esri/symbols/SimpleFillSymbol",
    "esri/renderers/SimpleRenderer",
    "esri/SpatialReference",
    "esri/geometry/webMercatorUtils",
    "esri/request",
    "esri/config",
    "dojo/_base/url",
    "dojo/_base/lang"
],  function (declare, Graphic, GraphicsLayer, InfoTemplate, graphicsUtils, Color, SimpleMarkerSymbol,
        SimpleLineSymbol, SimpleFillSymbol, SimpleRenderer, SpatialReference, webMercatorUtils, esriRequest, esriConfig, Url, lang
    ) {
    return declare([GraphicsLayer], {

        // Required Terrformer library reference
        _terrafomer: (typeof Terraformer !== 'undefined') ? Terraformer : null,

        constructor: function (options) {
            // options:
            //      url: String
            //          Path to file or server endpoint. Server must be on the same domain or cors enabled. Or use a proxy.
            //      data: Object[]
            //          Optional: FeatureCollection of GeoJson features. This will override url if both are provided.
            //      maxdraw: Number
            //          Optional: The maximum graphics to render. Default is 1000.
            this._validState = true;
            // First look for url
            this._url = options.url;
            // Accept data as geojson features array. This will override options.url!
            this._data = options.data;
            // GeoJSON spatial reference (not optional)
            this._inSpatialReference = new SpatialReference({wkid: 4326});  // Data must be in Geographic Coordinates
            // GeoJSON transformation (optional)
            this._outSpatialReference = null;
            // Default popup
            if (options.infoTemplate !== false) {
                this.setInfoTemplate(options.infoTemplate || new InfoTemplate("GeoJSON Data", "${*}"));
            }
            // Default symbols
            this._setDefaultSymbols();
            // Enable browser to make cross-domain requests
            this._setCorsSevers();
            this._setXhrDefaults(10000);
            // Manage drawing
            this._maxDraw = options.maxdraw || 1000;  // default to 1000 graphics
            this._drawCount = 0;
            this._drawCountTotal = 0;
            // Extended public properties
            this.extent = null;
            // Make sure the environment is good to go!
            this._updateState();
        },

        _setDefaultSymbols: function () {
            function getRandomColor(mainColor, transparency) {
                function getRandomInt(min, max) {
                    return Math.floor(Math.random() * (max - min + 1)) + min;
                }
                switch (mainColor) {
                    case "red":
                        return new Color([getRandomInt(150, 255), getRandomInt(0, 255), getRandomInt(0, 255), transparency]);
                    case "green":
                        return new Color([getRandomInt(0, 155), getRandomInt(150, 255), getRandomInt(0, 155), transparency]);
                    case "blue":
                        return new Color([getRandomInt(0, 255), getRandomInt(0, 255), getRandomInt(150, 255), transparency]);
                }
            }
            // Random colors
            this._simplePointSym = new SimpleMarkerSymbol(SimpleMarkerSymbol.STYLE_CIRCLE, 8,
                new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, getRandomColor("blue", 0.5), 1),
                    getRandomColor("blue", 0.75));
            this._simpleLineSym = new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, getRandomColor("red", 0.9), 2);
            this._simplePolygonSym = new SimpleFillSymbol("solid",
                    new SimpleLineSymbol("solid", new Color([50, 50, 50, 0.15]), 1),
                    getRandomColor("green", 0.15));
            // Option to hardcod colors here
            // this._simplePointSym = new SimpleMarkerSymbol(SimpleMarkerSymbol.STYLE_CIRCLE, 8,
            //      new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([150, 150, 150]), 0.5),
            //      new Color([50, 130, 255, 0.75]));
            // this._simpleLineSym = new SimpleLineSymbol("solid", new Color([255, 50, 50, 0.75]), 2);
            // this._simplePolygonSym = new SimpleFillSymbol("solid",
            //         new SimpleLineSymbol("solid", new Color([0, 0, 0, 0.10]), 1),
            //         new Color([150, 255, 150, 0.10]));
        },

        _setCorsSevers: function () {
            // Allow browser to make cross-domain requests
            esriConfig.defaults.io.corsEnabledServers.push("http://sampleserver6.arcgisonline.com");
            // Add server
            if (this._url) {
                var url = new Url(this._url),
                    scheme = url.scheme,
                    host = url.host,
                    port = url.port,
                    server = scheme + "://" + host; // + "/"; // + (port ? port : ""); // TODO
                if (scheme && host) {
                    esriConfig.defaults.io.corsEnabledServers.push(server);
                }
            }
        },

        _setXhrDefaults: function (postSize) {
            esriConfig.defaults.io.postLength = postSize;  // max size of post request
        },

        _updateState: function () {
            if (!this._inSpatialReference) {
                this._validState = false;
                console.error("GeoJsonLayer Error: Invalid SpatialReference.");
            }
            if (!this._terrafomer) {
                this._validState = false;
                console.error("GeoJsonLayer Error: Invalid Terraformer reference. Please add a reference to your html page.");
            }
        },

        // GraphicLayer overrides
        _setMap: function (map, surface) {
            var div = this.inherited(arguments);
            // Check spatial reference
            if (!this._validState) {
                return div;
            }
            // Set sr if need to project
            this._outSpatialReference = map.spatialReference;
            // Load GeoJSON as graphics
            this._loadGeoJson();
            // Return div - sets this.id
            return div;
        },

        _unsetMap: function () {
            return this.inherited(arguments);
        },

        add: function (graphic) {
            if (!this._validState) {
                return;
            }
            // Can do more with graphic if needed
            this.inherited(arguments);
            this._incrementDrawCount();
            return;
        },

        clear: function () {
            this._drawCount = 0;
            this._drawCountMax = 0;
            return this.inherited(arguments);
        },

        // GeoJsonLayer class functions
        _loadGeoJson: function () {
            if (this._data) {
                // Load data
                this._getGeoJson(this._data);
            } else if (this._url) {
                 // XHR request
                this._getGeoJsonXhr(this._url);
            }
        },

        _getGeoJsonXhr: function (url) {
            // xhr request to get data
            var requestHandle = esriRequest({
                url: url,
                handleAs: "json"
            });
            requestHandle.then(lang.hitch(this, this._getGeoJson),
                lang.hitch(this, this._errorGetGeoJsonXhr));
        },

        _getGeoJson: function (geojson) {
            // Check data
            if (geojson.type !== "FeatureCollection" || !geojson.features) {
                console.error("GeoJsonLayer Error: Invalid GeoJSON FeatureCollection. Check url or data structure.");
                return;
            }
            // Convert GeoJSON to ArcGIS JSON
            var arcgisJson = this._terraformerConverter(geojson);
            // Add graphics to layer
            this._addGraphics(arcgisJson);
        },

        // GeoJSON to ArcGIS JSON
        _terraformerConverter: function (geojson) {
            var json,
                arcgis;
            // Convert the geojson object to a Primitive json representation
            json = new this._terrafomer.Primitive(geojson);
            // Convert to ArcGIS JSON
            arcgis = this._terrafomer.ArcGIS.convert(json);
            return arcgis;
        },

        _errorGetGeoJsonXhr: function (e) {
            console.error("GeoJsonLayer Error: Couldn't load GeoJSON. Check url. File must be on the same domain or server must be CORS enabled.\n\n" + e);
        },

        _incrementDrawCount: function () {
            this._drawCount++;
            if (this._drawCount === this._drawCountTotal) {
                this._updateLayerExtent();
                this.onUpdateEnd();
            }
        },

        _decrementDrawCount: function () {
            this._drawCountTotal--;
        },

        _updateLayerExtent: function () {
            var extent;
            if (this.graphics.length) {
                extent = graphicsUtils.graphicsExtent(this.graphics);
            }
            this.extent = extent;
        },

         // Type functions
        _getEsriSymbol: function (geometryType) {
            var sym;
            switch (geometryType) {
            case "point":
                sym = this._simplePointSym;
                break;
            case "multipoint":
                sym = this._simplePointSym;
                break;
            case "polyline":
                sym = this._simpleLineSym;
                break;
            case "polygon":
                sym = this._simplePolygonSym;
                break;
            case "extent":
                sym = this._simplePolygonSym;
                break;
            }
            return sym;
        },

        _addGraphicToLayer: function (graphic) {
            // Add or project and then add graphic
            if (this._inSpatialReference.wkid === 4326 || this._inSpatialReference.wkid === 102100) {
                // ArcGIS API automatically translates between these!
                // if (graphic.geometry.spatialReference.wkid === 4326) {
                //     graphic.setGeometry(webMercatorUtils.geographicToWebMercator(graphic.geometry));
                // }
                // Add graphic directly
                this.add(graphic);
            }
        },

        _createGraphic: function (arcgisJson) {
            var graphic;
            // This magically sets geometry type!
            graphic = new Graphic(arcgisJson);
            // Set the correct symbol based on type and render - NOTE: Only supports simple renderers
            if (this.renderer && this.renderer.symbol) {
                //graphic.setSymbol(this.render.getSymbol(graphic));  // use for complex renderers
                graphic.setSymbol(this.renderer.symbol);
            } else {
                graphic.setSymbol(this._getEsriSymbol(graphic.geometry.type));
            }
            // Update SR because terraformer sets incorrect spatial reference
            graphic.geometry.setSpatialReference(this._inSpatialReference); // NOTE: Has to match features!
            return graphic;
        },

        _addGraphics: function (arcgisJson) {
            var i,
                feature,
                graphic;
            // Limit size of data that can be drawn
            if (arcgisJson.length > this._maxDraw) {
                this._drawCountTotal = this._maxDraw;
                console.warn("GeoJsonLayer Warning: Large dataset detected. Only drawing the first " + this._maxDraw + " features!");
            } else {
                this._drawCountTotal = arcgisJson.length;
            }
            // Add graphics to the layer with symbols, project if needed
            for (i = 0; i < this._drawCountTotal; i++) {
                feature = arcgisJson[i];
                // Create graphic - magically sets the geometry type!
                graphic = this._createGraphic(feature);
                // Add to layer
                this._addGraphicToLayer(graphic);
            }
        }
    });
});<commit_msg>fire load event after features added to layer<commit_after>define([
    "dojo/_base/declare",
    "esri/graphic",
    "esri/layers/GraphicsLayer",
    "esri/InfoTemplate",
    "esri/graphicsUtils",
    "esri/Color",
    "esri/symbols/SimpleMarkerSymbol",
    "esri/symbols/SimpleLineSymbol",
    "esri/symbols/SimpleFillSymbol",
    "esri/renderers/SimpleRenderer",
    "esri/SpatialReference",
    "esri/geometry/webMercatorUtils",
    "esri/request",
    "esri/config",
    "dojo/_base/url",
    "dojo/_base/lang"
],  function (declare, Graphic, GraphicsLayer, InfoTemplate, graphicsUtils, Color, SimpleMarkerSymbol,
        SimpleLineSymbol, SimpleFillSymbol, SimpleRenderer, SpatialReference, webMercatorUtils, esriRequest, esriConfig, Url, lang
    ) {
    return declare([GraphicsLayer], {

        // Required Terrformer library reference
        _terrafomer: (typeof Terraformer !== 'undefined') ? Terraformer : null,

        constructor: function (options) {
            // options:
            //      url: String
            //          Path to file or server endpoint. Server must be on the same domain or cors enabled. Or use a proxy.
            //      data: Object[]
            //          Optional: FeatureCollection of GeoJson features. This will override url if both are provided.
            //      maxdraw: Number
            //          Optional: The maximum graphics to render. Default is 1000.
            this._validState = true;
            // First look for url
            this._url = options.url;
            // Accept data as geojson features array. This will override options.url!
            this._data = options.data;
            // GeoJSON spatial reference (not optional)
            this._inSpatialReference = new SpatialReference({wkid: 4326});  // Data must be in Geographic Coordinates
            // GeoJSON transformation (optional)
            this._outSpatialReference = null;
            // Default popup
            if (options.infoTemplate !== false) {
                this.setInfoTemplate(options.infoTemplate || new InfoTemplate("GeoJSON Data", "${*}"));
            }
            // Default symbols
            this._setDefaultSymbols();
            // Enable browser to make cross-domain requests
            this._setCorsSevers();
            this._setXhrDefaults(10000);
            // Manage drawing
            this._maxDraw = options.maxdraw || 1000;  // default to 1000 graphics
            this._drawCount = 0;
            this._drawCountTotal = 0;
            // Extended public properties
            this.extent = null;
            // Graphics layer does not call onLoad natively but we'll call it after features have been added to layer
            if (options.onLoad && typeof options.onLoad === 'function') {
                this.onLoad = options.onLoad;
            }
            // Make sure the environment is good to go!
            this._updateState();
        },

        _setDefaultSymbols: function () {
            function getRandomColor(mainColor, transparency) {
                function getRandomInt(min, max) {
                    return Math.floor(Math.random() * (max - min + 1)) + min;
                }
                switch (mainColor) {
                    case "red":
                        return new Color([getRandomInt(150, 255), getRandomInt(0, 255), getRandomInt(0, 255), transparency]);
                    case "green":
                        return new Color([getRandomInt(0, 155), getRandomInt(150, 255), getRandomInt(0, 155), transparency]);
                    case "blue":
                        return new Color([getRandomInt(0, 255), getRandomInt(0, 255), getRandomInt(150, 255), transparency]);
                }
            }
            // Random colors
            this._simplePointSym = new SimpleMarkerSymbol(SimpleMarkerSymbol.STYLE_CIRCLE, 8,
                new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, getRandomColor("blue", 0.5), 1),
                    getRandomColor("blue", 0.75));
            this._simpleLineSym = new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, getRandomColor("red", 0.9), 2);
            this._simplePolygonSym = new SimpleFillSymbol("solid",
                    new SimpleLineSymbol("solid", new Color([50, 50, 50, 0.15]), 1),
                    getRandomColor("green", 0.15));
            // Option to hardcod colors here
            // this._simplePointSym = new SimpleMarkerSymbol(SimpleMarkerSymbol.STYLE_CIRCLE, 8,
            //      new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([150, 150, 150]), 0.5),
            //      new Color([50, 130, 255, 0.75]));
            // this._simpleLineSym = new SimpleLineSymbol("solid", new Color([255, 50, 50, 0.75]), 2);
            // this._simplePolygonSym = new SimpleFillSymbol("solid",
            //         new SimpleLineSymbol("solid", new Color([0, 0, 0, 0.10]), 1),
            //         new Color([150, 255, 150, 0.10]));
        },

        _setCorsSevers: function () {
            // Allow browser to make cross-domain requests
            esriConfig.defaults.io.corsEnabledServers.push("http://sampleserver6.arcgisonline.com");
            // Add server
            if (this._url) {
                var url = new Url(this._url),
                    scheme = url.scheme,
                    host = url.host,
                    port = url.port,
                    server = scheme + "://" + host; // + "/"; // + (port ? port : ""); // TODO
                if (scheme && host) {
                    esriConfig.defaults.io.corsEnabledServers.push(server);
                }
            }
        },

        _setXhrDefaults: function (postSize) {
            esriConfig.defaults.io.postLength = postSize;  // max size of post request
        },

        _updateState: function () {
            if (!this._inSpatialReference) {
                this._validState = false;
                console.error("GeoJsonLayer Error: Invalid SpatialReference.");
            }
            if (!this._terrafomer) {
                this._validState = false;
                console.error("GeoJsonLayer Error: Invalid Terraformer reference. Please add a reference to your html page.");
            }
        },

        // GraphicLayer overrides
        _setMap: function (map, surface) {
            var div = this.inherited(arguments);
            // Check spatial reference
            if (!this._validState) {
                return div;
            }
            // Set sr if need to project
            this._outSpatialReference = map.spatialReference;
            // Load GeoJSON as graphics
            this._loadGeoJson();
            // Return div - sets this.id
            return div;
        },

        _unsetMap: function () {
            return this.inherited(arguments);
        },

        add: function (graphic) {
            if (!this._validState) {
                return;
            }
            // Can do more with graphic if needed
            this.inherited(arguments);
            this._incrementDrawCount();
            return;
        },

        clear: function () {
            this._drawCount = 0;
            this._drawCountMax = 0;
            return this.inherited(arguments);
        },

        // GeoJsonLayer class functions
        _loadGeoJson: function () {
            if (this._data) {
                // Load data
                this._getGeoJson(this._data);
            } else if (this._url) {
                 // XHR request
                this._getGeoJsonXhr(this._url);
            }
        },

        _getGeoJsonXhr: function (url) {
            // xhr request to get data
            var requestHandle = esriRequest({
                url: url,
                handleAs: "json"
            });
            requestHandle.then(lang.hitch(this, this._getGeoJson),
                lang.hitch(this, this._errorGetGeoJsonXhr));
        },

        _getGeoJson: function (geojson) {
            // Check data
            if (geojson.type !== "FeatureCollection" || !geojson.features) {
                console.error("GeoJsonLayer Error: Invalid GeoJSON FeatureCollection. Check url or data structure.");
                return;
            }
            // Convert GeoJSON to ArcGIS JSON
            var arcgisJson = this._terraformerConverter(geojson);
            // Add graphics to layer
            this._addGraphics(arcgisJson);
        },

        // GeoJSON to ArcGIS JSON
        _terraformerConverter: function (geojson) {
            var json,
                arcgis;
            // Convert the geojson object to a Primitive json representation
            json = new this._terrafomer.Primitive(geojson);
            // Convert to ArcGIS JSON
            arcgis = this._terrafomer.ArcGIS.convert(json);
            return arcgis;
        },

        _errorGetGeoJsonXhr: function (e) {
            console.error("GeoJsonLayer Error: Couldn't load GeoJSON. Check url. File must be on the same domain or server must be CORS enabled.\n\n" + e);
        },

        _incrementDrawCount: function () {
            this._drawCount++;
            if (this._drawCount === this._drawCountTotal) {
                this._updateLayerExtent();
                this.onUpdateEnd();
            }
        },

        _decrementDrawCount: function () {
            this._drawCountTotal--;
        },

        _updateLayerExtent: function () {
            var extent;
            if (this.graphics.length) {
                extent = graphicsUtils.graphicsExtent(this.graphics);
            }
            this.extent = extent;
        },

         // Type functions
        _getEsriSymbol: function (geometryType) {
            var sym;
            switch (geometryType) {
            case "point":
                sym = this._simplePointSym;
                break;
            case "multipoint":
                sym = this._simplePointSym;
                break;
            case "polyline":
                sym = this._simpleLineSym;
                break;
            case "polygon":
                sym = this._simplePolygonSym;
                break;
            case "extent":
                sym = this._simplePolygonSym;
                break;
            }
            return sym;
        },

        _addGraphicToLayer: function (graphic) {
            // Add or project and then add graphic
            if (this._inSpatialReference.wkid === 4326 || this._inSpatialReference.wkid === 102100) {
                // ArcGIS API automatically translates between these!
                // if (graphic.geometry.spatialReference.wkid === 4326) {
                //     graphic.setGeometry(webMercatorUtils.geographicToWebMercator(graphic.geometry));
                // }
                // Add graphic directly
                this.add(graphic);
            }
        },

        _createGraphic: function (arcgisJson) {
            var graphic;
            // This magically sets geometry type!
            graphic = new Graphic(arcgisJson);
            // Set the correct symbol based on type and render - NOTE: Only supports simple renderers
            if (this.renderer && this.renderer.symbol) {
                //graphic.setSymbol(this.render.getSymbol(graphic));  // use for complex renderers
                graphic.setSymbol(this.renderer.symbol);
            } else {
                graphic.setSymbol(this._getEsriSymbol(graphic.geometry.type));
            }
            // Update SR because terraformer sets incorrect spatial reference
            graphic.geometry.setSpatialReference(this._inSpatialReference); // NOTE: Has to match features!
            return graphic;
        },

        _addGraphics: function (arcgisJson) {
            var i,
                feature,
                graphic;
            // Limit size of data that can be drawn
            if (arcgisJson.length > this._maxDraw) {
                this._drawCountTotal = this._maxDraw;
                console.warn("GeoJsonLayer Warning: Large dataset detected. Only drawing the first " + this._maxDraw + " features!");
            } else {
                this._drawCountTotal = arcgisJson.length;
            }
            // Add graphics to the layer with symbols, project if needed
            for (i = 0; i < this._drawCountTotal; i++) {
                feature = arcgisJson[i];
                // Create graphic - magically sets the geometry type!
                graphic = this._createGraphic(feature);
                // Add to layer
                this._addGraphicToLayer(graphic);
            }
            // Call onLoad
            // emit mixes in `layer` and `target` properties as event object
            // onLoad provided via constructor just returns `layer` object
            this.onLoad(this);
        }
    });
});<|endoftext|>


<commit_before>'use strict';

/***
 *    ___▄▄▄▄▄___▄███▄___█▄▄▄▄____▄___▄███▄___█▄▄▄▄_
 *    __█_____▀▄_█▀___▀__█__▄▀_____█__█▀___▀__█__▄▀_
 *    ▄__▀▀▀▀▄___██▄▄____█▀▀▌_█_____█_██▄▄____█▀▀▌__
 *    _▀▄▄▄▄▀____█▄___▄▀_█__█__█____█_█▄___▄▀_█__█__
 *    ___________▀███▀_____█____█__█__▀███▀_____█___
 *    ____________________▀______█▐____________▀____
 *    ___________________________▐__________________
 */
var fs = require('fs');
var path = require('path');
var musicMetadata = require('musicmetadata');
var port = 1404;
var express = require('express');
var http2 = require('spdy');
var logger = require('morgan');
var app = express();
var ip = require('ip').address();
var options = {
    key: fs.readFileSync('./certs/server.key'),
    cert: fs.readFileSync('./certs/server.crt')
};
var server = http2.createServer(options, app).listen(port, (error) => {
    if (error) {
        notify('Error', error);
    } else {
        notify('Server', 'Musitop server started');
        notify('Server', 'https://localhost:' + port);
        notify('Server', 'https://' + ip + ':' + port);
    }
});
var io = require('socket.io')(server);

// app.use(logger('dev'));

app.get('/pushy', (req, res) => {
    var stream = res.push('/main.js', {
        status: 200, // optional
        method: 'GET', // optional
        request: {
            accept: '*/*'
        },
        response: {
            'content-type': 'application/javascript'
        }
    });
    stream.on('error', function (e) {
        notify('warn', e);
    });
    stream.end('alert("hello from push stream!");');
    res.end('<script src="/main.js"></script>');
});

app.get('/stream.mp3', function (req, res) {
    res.sendFile(song);
});

var onDisconnect = function () {
    // notify('Socket', 'server side disconnected');
};

var onConnection = function () {
    notify('Socket', 'Server side connection established');
};

var onMusicIs = function (musicIs) {
    if (musicIs === 'good') {
        notify('Client', '★ Keep this song :D');
        notify('Will keep', fileName(song), 'info');
        keep = true;
        io.emit('music was', musicIs);
    } else if (musicIs === 'bad') {
        notify('Client', '✕ Delete this song :|');
        notify('Deleting', fileName(song), 'info');
        deleteSong();
        playNext('onMusicIs bad');
        io.emit('music was', musicIs);
    } else if (musicIs === 'next') {
        notify('Client', '» Next song please :)');
        if (keep) {
            moveSong();
        }
        playNext('onMusicIs next');
        io.emit('music was', musicIs);
    } else if (musicIs === 'pause') {
        notify('Client', '|| Pause song please');
        io.emit('pause', 'please :)');
    } else {
        notify('Server', 'Client said that music is "' + musicIs + '" ?!?', 'info');
    }
};

var onError = function (err) {
    notify('Socket', 'Client had errors', 'error', err);
};

var onEvent = function (e) {
    notify('Event', e);
};

// var io = require('socket.io')(socketPort);
var connectSocket = function () {
    notify('Socket', 'Server connecting...');
    io.on('connection', function (socket) {
        // notify('Socket', 'Server side connection detected');
        socket.on('music is', onMusicIs);
        socket.on('error', onError);
        socket.on('disconnect', onDisconnect);
        socket.on('connect', onConnection);
        socket.on('event', onEvent);
        io.emit('options', {
            audioClientSide: config.get('audioClientSide')
        });
        io.emit('metadata', metadata);
    });
};

connectSocket();

/***
 *    █_▄▄__█____██__▀▄____▄_▄███▄___█▄▄▄▄_
 *    █___█_█____█_█___█__█__█▀___▀__█__▄▀_
 *    █▀▀▀__█____█▄▄█___▀█___██▄▄____█▀▀▌__
 *    █_____███▄_█__█___█____█▄___▄▀_█__█__
 *    _█________▀___█_▄▀_____▀███▀_____█___
 *    __▀__________█__________________▀____
 *    ____________▀________________________
 */
var childProcess = require('child_process');
var notifier = require('node-notifier');
var os = require('os');
var isLinux = (os.type() === 'Linux');
var configFile = 'config.json';
var config = require('config-prompt')({
    musicPath: {
        type: 'string',
        required: true
    },
    keepPath: {
        type: 'string',
        required: true
    },
    clientPath: {
        type: 'string',
        required: false,
        default: 'web'
    },
    audioClientSide: {
        type: 'boolean',
        default: true,
        required: false
    },
    keepFeature: {
        type: 'boolean',
        default: true,
        required: false
    },
    deleteFeature: {
        type: 'boolean',
        default: true,
        required: false
    },
    shuffleMusic: {
        type: 'boolean',
        default: true
    }
});
var shuffle = require('shuffle-array');
var playlist = [];
var song = '';
var player = null;
var autoKill = false;
var manualKill = false;
var keep = false;
var metadata = null;
var startTimestamp = null;

function playFolder() {
    var musicPath = config.get('musicPath');
    notify('Server', 'Scanning "' + musicPath + '"' + ' for songs');
    fs.readdir(musicPath, function (err, files) {
        if (err) {
            config.trash();
            notify('Error', 'Failed at reading musicPath', 'error', err);
        } else {
            // inject files
            files.forEach(function (fileName) {
                var filePath = path.join(musicPath, fileName);
                var fileStat = fs.statSync(filePath);
                if (fileStat.isFile() && (fileName.indexOf('.mp3') !== -1)) {
                    playlist.push(filePath);
                }
            });
            // shuffle if necessary
            if (config.get('shuffleMusic')) {
                shuffle(playlist);
            }
            // start playing
            playNext('playFolder');
        }
    });
}

function fileName(filePath) {
    // input  : "C:\Stuff\Music\to test\Mike feat. Snowball - Animal.mp3"
    // output : "Mike feat. Snowball - Animal"
    return path.basename(filePath).split('.').reverse().splice(1).reverse().join('.');
}

function playNext() {
    // notify('Server', 'playNext init' + (from ? ' from : ' + from : ''));
    // here splice return first item & remove it from playlist
    song = playlist.splice(0, 1)[0];
    getMetadata();
    // if audio output is server side
    if (!config.get('audioClientSide')) {
        playSong();
    }
    setTimeout(function () {
        notify('Server', '♫ Remaining ' + playlist.length + ' track(s)');
        notify('Playing', fileName(song), 'info');
        io.emit('metadata', metadata);
    }, 1100);
}

function getMetadata() {
    metadata = null;
    startTimestamp = Math.round(Date.now() / 1000);
    var readableStream = fs.createReadStream(song);
    musicMetadata(readableStream, {
        duration: true
    }, function (err, meta) {
        if (err) {
            notify('Error', 'Fail at reading mp3 metadata for song "' + song + '"', 'error', err);
        } else {
            metadata = meta;
            metadata.startTimestamp = startTimestamp;
            metadata.stream = '/stream.mp3';
            readableStream.close();
        }
    });
}

function moveSong() {
    // notify('Server', 'moveSong init');
    // because keep was true, we came here in moveSong
    // first thing to do is to reset this toggle :)
    keep = false;
    // because the file is actually read/locked by player
    // will move the file in an async way
    doAsync(function (lastSongPath) {
        var newLastSongPath = path.join(config.get('keepPath'), path.basename(lastSongPath));
        // notify('Server', 'will move it to : "' + newLastSongPath + '"');
        fs.rename(lastSongPath, newLastSongPath, function (err) {
            if (err) {
                notify('Server', 'Move failed, see me');
                throw new Error(err);
            } else {
                notify('Server', '> Moved ' + fileName(lastSongPath));
            }
        });
    });
}

function deleteSong() {
    doAsync(function (lastSongPath) {
        fs.unlink(lastSongPath, function (err) {
            if (err) {
                notify('Error', 'Delete failed', 'error', err);
            } else {
                notify('Server', '✕ Deleted ' + fileName(lastSongPath));
            }
        });
    });
}

function doAsync(callback) {
    if (!callback) {
        notify('Error', 'Do Async need a callback', 'error');
    } else {
        var lastSongPath = song + '';
        setTimeout(function () {
            callback(lastSongPath);
        }, 1000);
    }
}

function notify(action, message, type, bonus) {
    if (type) {
        // notify client side
        notifier.notify({
            title: action,
            message: message,
            type: type
        });
        type = null;
    }
    // in order to align logs :p
    var actionAligned = action;
    while (actionAligned.length < 6) {
        actionAligned += ' ';
    }
    console.log(actionAligned + ' : ' + message); // eslint-disable-line no-console
    if (bonus) {
        console.log(bonus); // eslint-disable-line no-console
    }
    if (action.toLowerCase() === 'error') {
        process.exit(0);
    }
}

function playSong() {
    // notify('playSong', 'autoKill is ' + autoKill);
    if (player && !autoKill) {
        // if any player we kill it, we don't want to have multiple players at the same time
        // notify('playSong', 'manualKill was ' + manualKill + ', now true');
        manualKill = true;
        player.kill();
    }

    if (isLinux) {
        // use cvlc on linux
        player = childProcess.spawn('cvlc', [song, '--play-and-exit']);
    } else {
        // use 1by1 on win
        player = childProcess.spawn('lib/1by1/1by1.exe', [song, '/hide', '/close']);
    }

    // because new player started
    // notify('playSong', 'autoKill was ' + autoKill + ', now false');
    autoKill = false;

    // when user did not asked anything, player close by itself
    player.on('close', function (code) {
        // notify('close', 'manualKill is ' + manualKill);
        if (manualKill) {
            // notify('Server', 'Player closed, was manual kill');
            // this avoid making move or play next if player was killed on purpose
            // notify('close', 'manualKill was ' + manualKill + ', now false');
            // notify('close', 'autoKill was ' + autoKill + ', now false');
            manualKill = false;
            autoKill = false;
        } else {
            // notify('Server', 'Player closed, was auto kill');
            // notify('close', 'autoKill was ' + autoKill + ', now true');
            autoKill = true;
            // here player just went until the end of the song & then exited
            if (code === null || code === 0) {
                if (keep) {
                    moveSong();
                }
                playNext('player closed');
            } else {
                notify('Server', 'Player process exited with non-handled code "' + code + '"', 'error');
            }
        }
    });
}

function getConfigFromUser(callback) {
    notify('Server', 'Will ask user for conf then save it locally');
    config.prompt({
        all: true,
        nodeEnv: false,
        silent: false
    }, function (err) {

        if (err) {
            config.trash();
            notify('Server', 'Failed at reading config, see logs', 'error', err);
        }
        // move conf file in config store to local folder
        // from : C:\Users\ME\.config\configstore\musitop.json
        // to   : .
        // notify('Server', 'Config path ' + config.path);
        fs.createReadStream(config.path).pipe(fs.createWriteStream(configFile));

        // if any callback, execute it
        if (callback && typeof callback === 'function') {
            callback();
        }
    });
}

function getConfig(callback) {
    // get local config
    fs.readFile(configFile, function (err, configContent) {
        if (err) {
            notify('Server', 'No local config found');
        } else {
            notify('Server', 'Local config found, set found conf key/values into in-memory conf');
            config.all = JSON.parse(configContent);
        }
        var configErrors = config.validate();
        if (err || configErrors.length) {
            getConfigFromUser(callback);
        } else if (callback && typeof callback === 'function') {
            // will expose musitop client if defined or just the web directory
            var staticPath = config.get('clientPath') || 'web';
            notify('Info', 'will serve "' + staticPath + '"');
            app.use('/', express.static(staticPath));
            callback();
        } else {
            notify('Error', 'Error, no callback provided', 'error');
        }
    });
}

function init() {
    // get conf then play music
    getConfig(playFolder);
    // add systray controls
    childProcess.spawn('node_modules/electron/dist/electron', ['systray']);
}

// init
setTimeout(init, 100);
<commit_msg>added dessktop notif toggle<commit_after>'use strict';

/***
 *    ___▄▄▄▄▄___▄███▄___█▄▄▄▄____▄___▄███▄___█▄▄▄▄_
 *    __█_____▀▄_█▀___▀__█__▄▀_____█__█▀___▀__█__▄▀_
 *    ▄__▀▀▀▀▄___██▄▄____█▀▀▌_█_____█_██▄▄____█▀▀▌__
 *    _▀▄▄▄▄▀____█▄___▄▀_█__█__█____█_█▄___▄▀_█__█__
 *    ___________▀███▀_____█____█__█__▀███▀_____█___
 *    ____________________▀______█▐____________▀____
 *    ___________________________▐__________________
 */
var fs = require('fs');
var path = require('path');
var musicMetadata = require('musicmetadata');
var port = 1404;
var express = require('express');
var http2 = require('spdy');
var logger = require('morgan');
var app = express();
var ip = require('ip').address();
var options = {
    key: fs.readFileSync('./certs/server.key'),
    cert: fs.readFileSync('./certs/server.crt')
};
var server = http2.createServer(options, app).listen(port, (error) => {
    if (error) {
        notify('Error', error);
    } else {
        notify('Server', 'Musitop server started');
        notify('Server', 'https://localhost:' + port);
        notify('Server', 'https://' + ip + ':' + port);
    }
});
var io = require('socket.io')(server);

// app.use(logger('dev'));

app.get('/pushy', (req, res) => {
    var stream = res.push('/main.js', {
        status: 200, // optional
        method: 'GET', // optional
        request: {
            accept: '*/*'
        },
        response: {
            'content-type': 'application/javascript'
        }
    });
    stream.on('error', function (e) {
        notify('warn', e);
    });
    stream.end('alert("hello from push stream!");');
    res.end('<script src="/main.js"></script>');
});

app.get('/stream.mp3', function (req, res) {
    res.sendFile(song);
});

var onDisconnect = function () {
    // notify('Socket', 'server side disconnected');
};

var onConnection = function () {
    notify('Socket', 'Server side connection established');
};

var onMusicIs = function (musicIs) {
    if (musicIs === 'good') {
        notify('Client', '★ Keep this song :D');
        notify('Will keep', fileName(song), 'info');
        keep = true;
        io.emit('music was', musicIs);
    } else if (musicIs === 'bad') {
        notify('Client', '✕ Delete this song :|');
        notify('Deleting', fileName(song), 'info');
        deleteSong();
        playNext('onMusicIs bad');
        io.emit('music was', musicIs);
    } else if (musicIs === 'next') {
        notify('Client', '» Next song please :)');
        if (keep) {
            moveSong();
        }
        playNext('onMusicIs next');
        io.emit('music was', musicIs);
    } else if (musicIs === 'pause') {
        notify('Client', '|| Pause song please');
        io.emit('pause', 'please :)');
    } else {
        notify('Server', 'Client said that music is "' + musicIs + '" ?!?', 'info');
    }
};

var onError = function (err) {
    notify('Socket', 'Client had errors', 'error', err);
};

var onEvent = function (e) {
    notify('Event', e);
};

// var io = require('socket.io')(socketPort);
var connectSocket = function () {
    notify('Socket', 'Server connecting...');
    io.on('connection', function (socket) {
        // notify('Socket', 'Server side connection detected');
        socket.on('music is', onMusicIs);
        socket.on('error', onError);
        socket.on('disconnect', onDisconnect);
        socket.on('connect', onConnection);
        socket.on('event', onEvent);
        io.emit('options', {
            audioClientSide: config.get('audioClientSide')
        });
        io.emit('metadata', metadata);
    });
};

connectSocket();

/***
 *    █_▄▄__█____██__▀▄____▄_▄███▄___█▄▄▄▄_
 *    █___█_█____█_█___█__█__█▀___▀__█__▄▀_
 *    █▀▀▀__█____█▄▄█___▀█___██▄▄____█▀▀▌__
 *    █_____███▄_█__█___█____█▄___▄▀_█__█__
 *    _█________▀___█_▄▀_____▀███▀_____█___
 *    __▀__________█__________________▀____
 *    ____________▀________________________
 */
var childProcess = require('child_process');
var notifier = require('node-notifier');
var os = require('os');
var isLinux = (os.type() === 'Linux');
var configFile = 'config.json';
var config = require('config-prompt')({
    musicPath: {
        type: 'string',
        required: true
    },
    keepPath: {
        type: 'string',
        required: true
    },
    clientPath: {
        type: 'string',
        required: false,
        default: 'web'
    },
    audioClientSide: {
        type: 'boolean',
        default: true,
        required: false
    },
    keepFeature: {
        type: 'boolean',
        default: true,
        required: false
    },
    deleteFeature: {
        type: 'boolean',
        default: true,
        required: false
    },
    shuffleMusic: {
        type: 'boolean',
        default: true
    },
    desktopNotifications: {
        type: 'boolean',
        default: true
    }
});
var shuffle = require('shuffle-array');
var playlist = [];
var song = '';
var player = null;
var autoKill = false;
var manualKill = false;
var keep = false;
var metadata = null;
var startTimestamp = null;

function playFolder() {
    var musicPath = config.get('musicPath');
    notify('Server', 'Scanning "' + musicPath + '"' + ' for songs');
    fs.readdir(musicPath, function (err, files) {
        if (err) {
            config.trash();
            notify('Error', 'Failed at reading musicPath', 'error', err);
        } else {
            // inject files
            files.forEach(function (fileName) {
                var filePath = path.join(musicPath, fileName);
                var fileStat = fs.statSync(filePath);
                if (fileStat.isFile() && (fileName.indexOf('.mp3') !== -1)) {
                    playlist.push(filePath);
                }
            });
            // shuffle if necessary
            if (config.get('shuffleMusic')) {
                shuffle(playlist);
            }
            // start playing
            playNext('playFolder');
        }
    });
}

function fileName(filePath) {
    // input  : "C:\Stuff\Music\to test\Mike feat. Snowball - Animal.mp3"
    // output : "Mike feat. Snowball - Animal"
    return path.basename(filePath).split('.').reverse().splice(1).reverse().join('.');
}

function playNext() {
    // notify('Server', 'playNext init' + (from ? ' from : ' + from : ''));
    // here splice return first item & remove it from playlist
    song = playlist.splice(0, 1)[0];
    getMetadata();
    // if audio output is server side
    if (!config.get('audioClientSide')) {
        playSong();
    }
    setTimeout(function () {
        notify('Server', '♫ Remaining ' + playlist.length + ' track(s)');
        notify('Playing', fileName(song), 'info');
        io.emit('metadata', metadata);
    }, 1100);
}

function getMetadata() {
    metadata = null;
    startTimestamp = Math.round(Date.now() / 1000);
    var readableStream = fs.createReadStream(song);
    musicMetadata(readableStream, {
        duration: true
    }, function (err, meta) {
        if (err) {
            notify('Error', 'Fail at reading mp3 metadata for song "' + song + '"', 'error', err);
        } else {
            metadata = meta;
            metadata.startTimestamp = startTimestamp;
            metadata.stream = '/stream.mp3';
            readableStream.close();
        }
    });
}

function moveSong() {
    // notify('Server', 'moveSong init');
    // because keep was true, we came here in moveSong
    // first thing to do is to reset this toggle :)
    keep = false;
    // because the file is actually read/locked by player
    // will move the file in an async way
    doAsync(function (lastSongPath) {
        var newLastSongPath = path.join(config.get('keepPath'), path.basename(lastSongPath));
        // notify('Server', 'will move it to : "' + newLastSongPath + '"');
        fs.rename(lastSongPath, newLastSongPath, function (err) {
            if (err) {
                notify('Server', 'Move failed, see me');
                throw new Error(err);
            } else {
                notify('Server', '> Moved ' + fileName(lastSongPath));
            }
        });
    });
}

function deleteSong() {
    doAsync(function (lastSongPath) {
        fs.unlink(lastSongPath, function (err) {
            if (err) {
                notify('Error', 'Delete failed', 'error', err);
            } else {
                notify('Server', '✕ Deleted ' + fileName(lastSongPath));
            }
        });
    });
}

function doAsync(callback) {
    if (!callback) {
        notify('Error', 'Do Async need a callback', 'error');
    } else {
        var lastSongPath = song + '';
        setTimeout(function () {
            callback(lastSongPath);
        }, 1000);
    }
}

function notify(action, message, type, bonus) {
    if (type && config.get('desktopNotifications')) {
        // notify client side
        notifier.notify({
            title: action,
            message: message,
            type: type
        });
    }
    // in order to align logs :p
    var actionAligned = action;
    while (actionAligned.length < 6) {
        actionAligned += ' ';
    }
    console.log(actionAligned + ' : ' + message); // eslint-disable-line no-console
    if (bonus) {
        console.log(bonus); // eslint-disable-line no-console
    }
    if (action.toLowerCase() === 'error') {
        process.exit(0);
    }
}

function playSong() {
    // notify('playSong', 'autoKill is ' + autoKill);
    if (player && !autoKill) {
        // if any player we kill it, we don't want to have multiple players at the same time
        // notify('playSong', 'manualKill was ' + manualKill + ', now true');
        manualKill = true;
        player.kill();
    }

    if (isLinux) {
        // use cvlc on linux
        player = childProcess.spawn('cvlc', [song, '--play-and-exit']);
    } else {
        // use 1by1 on win
        player = childProcess.spawn('lib/1by1/1by1.exe', [song, '/hide', '/close']);
    }

    // because new player started
    // notify('playSong', 'autoKill was ' + autoKill + ', now false');
    autoKill = false;

    // when user did not asked anything, player close by itself
    player.on('close', function (code) {
        // notify('close', 'manualKill is ' + manualKill);
        if (manualKill) {
            // notify('Server', 'Player closed, was manual kill');
            // this avoid making move or play next if player was killed on purpose
            // notify('close', 'manualKill was ' + manualKill + ', now false');
            // notify('close', 'autoKill was ' + autoKill + ', now false');
            manualKill = false;
            autoKill = false;
        } else {
            // notify('Server', 'Player closed, was auto kill');
            // notify('close', 'autoKill was ' + autoKill + ', now true');
            autoKill = true;
            // here player just went until the end of the song & then exited
            if (code === null || code === 0) {
                if (keep) {
                    moveSong();
                }
                playNext('player closed');
            } else {
                notify('Server', 'Player process exited with non-handled code "' + code + '"', 'error');
            }
        }
    });
}

function getConfigFromUser(callback) {
    notify('Server', 'Will ask user for conf then save it locally');
    config.prompt({
        all: true,
        nodeEnv: false,
        silent: false
    }, function (err) {

        if (err) {
            config.trash();
            notify('Server', 'Failed at reading config, see logs', 'error', err);
        }
        // move conf file in config store to local folder
        // from : C:\Users\ME\.config\configstore\musitop.json
        // to   : .
        // notify('Server', 'Config path ' + config.path);
        fs.createReadStream(config.path).pipe(fs.createWriteStream(configFile));

        // if any callback, execute it
        if (callback && typeof callback === 'function') {
            callback();
        }
    });
}

function getConfig(callback) {
    // get local config
    fs.readFile(configFile, function (err, configContent) {
        if (err) {
            notify('Server', 'No local config found');
        } else {
            notify('Server', 'Local config found, set found conf key/values into in-memory conf');
            config.all = JSON.parse(configContent);
        }
        var configErrors = config.validate();
        if (err || configErrors.length) {
            getConfigFromUser(callback);
        } else if (callback && typeof callback === 'function') {
            // will expose musitop client if defined or just the web directory
            var staticPath = config.get('clientPath') || 'web';
            notify('Info', 'will serve "' + staticPath + '"');
            app.use('/', express.static(staticPath));
            callback();
        } else {
            notify('Error', 'Error, no callback provided', 'error');
        }
    });
}

function init() {
    // get conf then play music
    getConfig(playFolder);
    // add systray controls
    childProcess.spawn('node_modules/electron/dist/electron', ['systray']);
}

// init
setTimeout(init, 100);
<|endoftext|>


<commit_before>/**
 * @author: Ruoyi Chen
 **/
$(function () {
	loadMap();
	$.getJSON ('js/stores.json', function(data) {
		var stores = [];
		var menu = [];
		$.each (data['Provinces'], function(i, pval) {
			var name = pval['Name'];
			var item = $('
' + name +'
' );
			item.val(name);
			// Add each city to the menu.
			var cityMenu = $('
');
			$.each(pval['Cities'], function(i, cval) {
				var citem = createCityDom(cval['Name'], cval['Stores']);
				citem.appendTo(cityMenu);
			});
			item.data('cityMenu', cityMenu);
			// Click event handler for province selector.
			item.on('click', function(){
				$('#prov-input').val(name);
				$('#city-input').val('');
				$('#search-btn').data('city', null);
				$('#city-menu').detach();
			    $(this).data('cityMenu').appendTo('#city-dropdown');
			});
			item.appendTo('#prov-menu');
		});

		if ($('#prov-menu').data("map")) {
			addEventHandlers();
		} else {
			setTimeout(addEventHandlers, 2000);
		}
	});
});

// Create a jQuery object containing dom and data values for a given city.
var createCityDom = function(name, storeList) {
	var city = $('
' + name + '
');
	/* Use the data- property to store all store information belong to this city. */
	city.val(name);
	city.data('stores', storeList);
	city.data('drawn', false); // Newly created city is not drawn yet.
	return city;
}

function loadMap() { // Asynchronously load the lib script.
	var script = document.createElement("script");
	script.type = "text/javascript";
	script.src = "http://api.map.baidu.com/api?v=2.0&ak=Ch1jgxD8xmtI5tObYIoEZ9dL&callback=initMap";
	document.body.appendChild(script);
}

function initMap() {
	var map = new BMap.Map("map-pane");
	var originP = new BMap.Point(116.404, 39.915);
	map.centerAndZoom(originP, 5);
	var leftNavigation = new BMap.NavigationControl();
	map.addControl(leftNavigation);
	map.setCurrentCity("上海");
	map.enableScrollWheelZoom();
	$('#prov-menu').data("map", map);
}

function addEventHandlers () {
	var map = $('#prov-menu').data("map");
	$.each($('#prov-menu').children(), function(i, prov) {
		$.each($(prov).data('cityMenu').children(), function(j, city) {
			$(city).on('click', function () {
				$('#city-input').val($(city).text());
				if ($('#search-btn').is(':visible')) { // Don't trigger search event handler when search button is shown.
					$('#search-btn').data('city', $(city));
				    return;
				}
				searchEventHandler.bind($(city))();
			});
		});
	});

	$('#search-btn').on('click', function() {
		if ($(this).data('city')) {
			searchEventHandler.bind($(this).data('city'))();
		} else { // When no city is chosen, show China map;
			map.centerAndZoom(originP, 5);
		}
	});
}

function searchEventHandler() { // Use this to refer to the city item.
	var map = $('#prov-menu').data("map");
	var name = this.text();
	map.setCurrentCity(name);
	$('.info-list').empty(); // Empty the list pane;
	var storeList = $(this).data('stores');
	if ($(this).data('drawn') == false) { // Don't drawn the same city twice.
		var pointList = [];
	    $.each(storeList, function(i, store){
			var point = new BMap.Point(store['Longitude'], store['Latitude']);
			pointList.push(point);
			drawOnMap(map, store['Name'], store['Address'], point);
		});
		$(this).data('pointList', pointList);
		$(this).data('drawn', true);
	}
	// Show store infor on the list pane.
	$.each(storeList, function(i, store){
		showOnList(store['Name'], store['Address']);
	});
	// Use this line to show all points within the map view.
	// map.setViewport($(this).data('pointList'));
	map.centerAndZoom(name, 12);
}

function drawOnMap(name, address, point) {
	var map = $('#prov-menu').data("map");
	var marker = new BMap.Marker(point);        // Create a marker
	var opts = {
		width : 150,
		height: 100,
		title: ""+name+""
	}
	var infoWindow = new BMap.InfoWindow(address, opts);  // Create infor window object.
	marker.infoWindow = infoWindow;
	marker.addEventListener("click", function(e){ // Open the inforWindow when clicking on marker.
		this.openInfoWindow(e.target.infoWindow);
	});
	map.addOverlay(marker);
}

function showOnList(name, address) {
	var item = $('

').addClass('info-list-item row');
	var icon = $('').addClass('map-marker').appendTo(item);
	var title = $('

').addClass('info-name').append('' + name + '');
	title.appendTo(item);
	var info = $('

').addClass('info-address').append('地址:' + address + '');
	info.appendTo(item);
	item.appendTo('.info-list');
}
<commit_msg>Small typo fix.<commit_after>/**
 * @author: Ruoyi Chen
 **/
$(function () {
	loadMap();
	$.getJSON ('js/stores.json', function(data) {
		var stores = [];
		var menu = [];
		$.each (data['Provinces'], function(i, pval) {
			var name = pval['Name'];
			var item = $('
' + name +'
' );
			item.val(name);
			// Add each city to the menu.
			var cityMenu = $('
');
			$.each(pval['Cities'], function(i, cval) {
				var citem = createCityDom(cval['Name'], cval['Stores']);
				citem.appendTo(cityMenu);
			});
			item.data('cityMenu', cityMenu);
			// Click event handler for province selector.
			item.on('click', function(){
				$('#prov-input').val(name);
				$('#city-input').val('');
				$('#search-btn').data('city', null);
				$('#city-menu').detach();
			    $(this).data('cityMenu').appendTo('#city-dropdown');
			});
			item.appendTo('#prov-menu');
		});

		if ($('#prov-menu').data("map")) {
			addEventHandlers();
		} else {
			setTimeout(addEventHandlers, 2000);
		}
	});
});

// Create a jQuery object containing dom and data values for a given city.
var createCityDom = function(name, storeList) {
	var city = $('
' + name + '
');
	/* Use the data- property to store all store information belong to this city. */
	city.val(name);
	city.data('stores', storeList);
	city.data('drawn', false); // Newly created city is not drawn yet.
	return city;
}

function loadMap() { // Asynchronously load the lib script.
	var script = document.createElement("script");
	script.type = "text/javascript";
	script.src = "http://api.map.baidu.com/api?v=2.0&ak=Ch1jgxD8xmtI5tObYIoEZ9dL&callback=initMap";
	document.body.appendChild(script);
}

function initMap() {
	var map = new BMap.Map("map-pane");
	var originP = new BMap.Point(116.404, 39.915);
	map.centerAndZoom(originP, 5);
	var leftNavigation = new BMap.NavigationControl();
	map.addControl(leftNavigation);
	map.setCurrentCity("上海");
	map.enableScrollWheelZoom();
	$('#prov-menu').data("map", map);
}

function addEventHandlers () {
	var map = $('#prov-menu').data("map");
	$.each($('#prov-menu').children(), function(i, prov) {
		$.each($(prov).data('cityMenu').children(), function(j, city) {
			$(city).on('click', function () {
				$('#city-input').val($(city).text());
				if ($('#search-btn').is(':visible')) { // Don't trigger search event handler when search button is shown.
					$('#search-btn').data('city', $(city));
				    return;
				}
				searchEventHandler.bind($(city))();
			});
		});
	});

	$('#search-btn').on('click', function() {
		if ($(this).data('city')) {
			searchEventHandler.bind($(this).data('city'))();
		} else { // When no city is chosen, show China map;
			map.centerAndZoom(originP, 5);
		}
	});
}

function searchEventHandler() { // Use this to refer to the city item.
	var map = $('#prov-menu').data("map");
	var name = this.text();
	map.setCurrentCity(name);
	$('.info-list').empty(); // Empty the list pane;
	var storeList = $(this).data('stores');
	if ($(this).data('drawn') == false) { // Don't drawn the same city twice.
		var pointList = [];
	    $.each(storeList, function(i, store){
			var point = new BMap.Point(store['Longitude'], store['Latitude']);
			pointList.push(point);
			drawOnMap(store['Name'], store['Address'], point);
		});
		$(this).data('pointList', pointList);
		$(this).data('drawn', true);
	}
	// Show store infor on the list pane.
	$.each(storeList, function(i, store){
		showOnList(store['Name'], store['Address']);
	});
	// Use this line to show all points within the map view.
	// map.setViewport($(this).data('pointList'));
	map.centerAndZoom(name, 12);
}

function drawOnMap(name, address, point) {
	var map = $('#prov-menu').data("map");
	var marker = new BMap.Marker(point);        // Create a marker
	var opts = {
		width : 150,
		height: 100,
		title: ""+name+""
	}
	var infoWindow = new BMap.InfoWindow(address, opts);  // Create infor window object.
	marker.infoWindow = infoWindow;
	marker.addEventListener("click", function(e){ // Open the inforWindow when clicking on marker.
		this.openInfoWindow(e.target.infoWindow);
	});
	map.addOverlay(marker);
}

function showOnList(name, address) {
	var item = $('

').addClass('info-list-item row');
	var icon = $('').addClass('map-marker').appendTo(item);
	var title = $('

').addClass('info-name').append('' + name + '');
	title.appendTo(item);
	var info = $('

').addClass('info-address').append('地址:' + address + '');
	info.appendTo(item);
	item.appendTo('.info-list');
}
<|endoftext|>


<commit_before>'use strict';

var async = require('async'),
	path = require('path'),
	fs = require('fs'),
	exec = require('child_process').exec,
	sprintf = require('sprintf').sprintf,
	swintHelper = require('swint-helper'),
	defaultize = swintHelper.defaultize,
	walk = swintHelper.walk;

module.exports = function(options, callback) {
	defaultize({
		name: 'Project',
		inDir: path.dirname(require.main.filename),
		outDir: path.join(path.dirname(require.main.filename), '../out'),
		imgMetaDir: path.join(path.dirname(require.main.filename), '../imgMeta'),
		walkOption: {
			ext: '*'
		}
	}, options);

	return proceed(options, callback);
};

var proceed = function(options, callback) {
	if(callback === undefined) {
		var msg = 'swint-builder-png function needs callback';
		print(4, msg);
		throw new Error(msg);
	}

	if(!fs.existsSync(options.inDir)) {
		callback('swint-builder-png: inDir doesn\'t exist', false);
		return;
	}

	if(!fs.existsSync(options.outDir)) {
		fs.mkdirSync(options.outDir);
	}

	if(!fs.existsSync(options.imgMetaDir)) {
		fs.mkdirSync(options.imgMetaDir);
	}

	var dirList = fs.readdirSync(options.inDir).filter(function(dir) {
			return fs.lstatSync(path.join(options.inDir, dir)).isDirectory();
		}),
		walkers = dirList.map(function(dir) {
			var walkOption = options.walkOption;
			walkOption.dir = path.join(options.inDir, dir);
			return walk(walkOption);
		}),
		imgMeta = dirList.map(function(dir, idx) {
			var filePath = walkers[idx],
				offset = 0;

			return filePath.map(function(file) {
				var buff = fs.readFileSync(file),
					width = buff.readUInt32BE(16);

				offset += width;

				return {
					name: path.basename(file),
					timeStamp: fs.statSync(file).ctime,
					width: width,
					height: buff.readUInt32BE(20),
					offset: offset - width
				};
			});
		});

	async.parallel(
		dirList.map(function(dir, idx) {
			return function(callback) {
				var filePath = walkers[idx],
					metaFile = path.join(options.imgMetaDir, sprintf('%s.meta.json', dir));

				if(fs.existsSync(metaFile) && (fs.readFileSync(metaFile, 'utf8') === JSON.stringify(imgMeta[idx]))) {
					callback(null, true);
					return;
				}

				fs.writeFileSync(metaFile, JSON.stringify(imgMeta[idx]));

				exec(
					sprintf('montage -background transparent -mode concatenate -tile x1 %s %s',
						filePath.map(function(p) {
							return '"' + p + '"';
						}).join(' '),
						path.join(options.outDir, sprintf('%s.png', dir))
					),
					function(err, stdout, stderr) {
						if(stderr) print(stderr);
						callback(null, true);
					}
				);
			};
		}),
		function(err, results) {
			callback(err, results);
		}
	);
};
<commit_msg>just to initiate travis<commit_after>'use strict';

var async = require('async'),
	path = require('path'),
	fs = require('fs'),
	exec = require('child_process').exec,
	sprintf = require('sprintf').sprintf,
	swintHelper = require('swint-helper'),
	defaultize = swintHelper.defaultize,
	walk = swintHelper.walk;

module.exports = function(options, callback) {
	defaultize({
		name: 'Project',
		inDir: path.dirname(require.main.filename),
		outDir: path.join(path.dirname(require.main.filename), '../out'),
		imgMetaDir: path.join(path.dirname(require.main.filename), '../imgMeta'),
		walkOption: {
			ext: '*'
		}
	}, options);

	return proceed(options, callback);
};

var proceed = function(options, callback) {
	if(callback === undefined) {
		var msg = 'swint-builder-png function needs callback';
		print(4, msg);
		throw new Error(msg);
	}

	if(!fs.existsSync(options.inDir)) {
		callback('swint-builder-png: inDir doesn\'t exist', false);
		return;
	}

	if(!fs.existsSync(options.outDir)) {
		fs.mkdirSync(options.outDir);
	}

	if(!fs.existsSync(options.imgMetaDir)) {
		fs.mkdirSync(options.imgMetaDir);
	}

	var dirList = fs.readdirSync(options.inDir).filter(function(dir) {
			return fs.lstatSync(path.join(options.inDir, dir)).isDirectory();
		}),
		walkers = dirList.map(function(dir) {
			var walkOption = options.walkOption;
			walkOption.dir = path.join(options.inDir, dir);
			return walk(walkOption);
		}),
		imgMeta = dirList.map(function(dir, idx) {
			var filePath = walkers[idx],
				offset = 0;

			return filePath.map(function(file) {
				var buff = fs.readFileSync(file),
					width = buff.readUInt32BE(16);

				offset += width;

				return {
					name: path.basename(file),
					timeStamp: fs.statSync(file).ctime,
					width: width,
					height: buff.readUInt32BE(20),
					offset: offset - width
				};
			});
		});

	async.parallel(
		dirList.map(function(dir, idx) {
			return function(callback) {
				var filePath = walkers[idx],
					metaFile = path.join(options.imgMetaDir, sprintf('%s.meta.json', dir));

				if(fs.existsSync(metaFile) && (fs.readFileSync(metaFile, 'utf8') === JSON.stringify(imgMeta[idx]))) {
					callback(null, true);
					return;
				}

				fs.writeFileSync(metaFile, JSON.stringify(imgMeta[idx]));

				exec(
					sprintf('montage -background transparent -mode concatenate -tile x1 %s %s',
						filePath.map(function(p) {
							return '"' + p + '"';
						}).join(' '),
						path.join(options.outDir, sprintf('%s.png', dir))
					),
					function(err, stdout, stderr) {
						if(stderr) print(stderr);
						callback(null, true);
					}
				);
			};
		}),
		function(err, results) {
			callback(err, results);
		}
	);
};

<|endoftext|>