<commit_before>/**
 * Copyright 2014 Francesco Camarlinghi
 *
 * 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.
 */

module.exports = function(grunt)
{
    'use strict';
    var path = require('path'),
        async = require('async'),
        _ = require('lodash'),
        cep = require('./cep.js')(grunt);

    /**
     * Compiles the specified build.
     */
    var compile = function(callback, build)
    {
        var tasks = [];
        grunt.log.writeln().writeln(('Compiling bundle for Adobe ' + build.products.join(', ').cyan + ' - ' + build.families.join(', ').cyan + '...').bold);
        var exec = require('child_process').exec;
        tasks.push(
            /**
             * Do some cleanup.
             */
            function(callback)
            {
                // Validate input/output files
                if (typeof build.staging !== 'string' || !build.staging.length)
                    grunt.fatal('Invalid "staging" folder: ' + String(build.staging).cyan + '.');

                if (typeof build.source !== 'string' || !build.source.length)
                    grunt.fatal('Invalid "source" folder: ' + String(build.source).cyan + '.');

                // Clean current output folder
                if (grunt.file.exists(build.staging) && grunt.file.isDir(build.staging))
                    grunt.file.delete(build.staging, { force: true });

                grunt.file.mkdir(build.staging);
                callback();
            },

            /**
             * Copy all files.
             */
            function(callback)
            {
                // Copy all the content of the source folder over to the output folder
                var message = 'Copying ' + build.source.cyan + ' folder...';
                grunt.verbose.writeln(message).or.write(message);

                var cmd = 'cp -Ri ' + build.source + '/ ' + build.staging + '/';
                exec(cmd, function(error, result, code) {
                    grunt.verbose.or.ok();
                    callback();
                });
            },

            /**
             * Generate .debug file.
             */
            function(callback)
            {
                if (build.profile === 'debug' || build.profile === 'launch')
                {
                    var message = 'Generating ' + '.debug'.cyan + ' file...';
                    grunt.verbose.writeln(message).or.write(message);

                    var dotdebug_file = path.join(cep.utils.plugin_folder(), 'res/.debug');

                    if (grunt.file.exists(dotdebug_file))
                    {
                        if (typeof build.launch.host_port !== 'number' || build.launch.host_port < 0)
                        {
                            grunt.verbose.or.error();
                            grunt.fatal('Invalid host debug port ' + build.launch.host_port + '.');
                        }

                        var data = { 'build': build },
                            processed = grunt.template.process(grunt.file.read(dotdebug_file), { data: data });

                        grunt.file.write(path.join(build.staging, '.debug'), processed);
                    }

                    grunt.verbose.or.ok();
                }

                callback();
            },

            /**
             * Generate appropriate manifest file.
             */
            function(callback)
            {
                require('./xml')(grunt).manifest(callback, build);
            }
        );

        // Run child tasks
        async.series(tasks, function(err, result) { callback(err, result); });
    };

    /**
     * Launches debug with specified settings.
     */
    var launch = function(callback, build, host)
    {
        var tasks = [],
            launch_config = {
                product: build.launch.product,
                family: build.launch.family,
                host: host
            },
            exec = require('child_process').exec;

        grunt.log.writeln().writeln('Launching application...'.bold);

        tasks.push(
            /**
             * Detect application executable location.
             */
            function(callback)
            {
                var folder_apps, folder_servicemgr;

                if (global.IS_WINDOWS)
                {
                    folder_apps = path.join(process.env['PROGRAMFILES'], '/Adobe');

                    if (launch_config.family === 'CC')
                        folder_servicemgr = path.join(process.env['APPDATA'], '/Adobe/CEPServiceManager4/extensions');
                    else
                        folder_servicemgr = path.join(process.env['APPDATA'], '/Adobe/CEP/extensions');
                }
                else
                {
                    folder_apps = '/Applications';

                    if (launch_config.family === 'CC')
                        folder_servicemgr = process.env['HOME'] + '/Library/Application Support/Adobe/CEPServiceManager4/extensions';
                    else
                        folder_servicemgr = process.env['HOME'] + '/Library/Application\ Support/Adobe/CEP/extensions';
                }

                // Extension install path
                launch_config.install_path = path.join(folder_servicemgr, build.bundle.basename) + '.debug';

                // Application folder
                var folder_family = {
                    'CC': 'CC',
                    'CC2014': 'CC 2014',
                    'CC2015': 'CC 2015'
                };

                var folder_name = launch_config.host.hasOwnProperty('folder') ? launch_config.host.folder : '/Adobe ' + launch_config.host.name + ' ' + folder_family[launch_config.family];
                launch_config.app_folder = path.join(folder_apps, folder_name);

                if (launch_config.family === 'CC' && launch_config.host.x64 && global.IS_X64 && global.IS_WINDOWS)
                    launch_config.app_folder += ' (64 Bit)';

                if (!grunt.file.exists(launch_config.app_folder))
                {
                    grunt.fatal('Unable to find Adobe ' + launch_config.host.name + ' ' + launch_config.family + ' folder at "' + launch_config.app_folder + '".');
                    return false;
                }

                // Application executable path
                launch_config.app_bin = path.join(launch_config.app_folder, global.IS_WINDOWS ? launch_config.host.bin.win : launch_config.host.bin.mac);

                if (!grunt.file.exists(launch_config.app_bin))
                {
                    grunt.fatal('Unable to find Adobe ' + launch_config.host.name + ' ' + launch_config.family + ' executable at "' + launch_config.app_bin + '".');
                    return false;
                }

                callback();
            },

            /**
             * Kill the specified host application process if it is running.
             */
             function (callback)
            {
                var options = {};

                if (global.IS_WINDOWS)
                {
                    options.cmd = 'Taskkill';
                    options.args = ['/IM', launch_config.host.bin.win];
                     grunt.verbose.writeln((options.cmd + ' ' + options.args.join(' ')).magenta)
                      .or.write('Killing host application process...');
                      var spawned = grunt.util.spawn(options, function (error, result, code)
                      {
                          grunt.verbose.or.ok();
                          // Let some time pass so that application can be closed correctly
                          // TODO: find a better way of doing this
                          setTimeout(function ()
                          {
                              callback();
                          }, 1000);
                      });
                      spawned.stdout.on('data', function (data) { grunt.verbose.writeln(data); });
                      spawned.stderr.on('data', function (data) { grunt.verbose.writeln(data); });
                }
                else
                {
                    var appMac = launch_config.host.bin.mac;
                    var processMac = appMac.slice(0, - 4); // - .app
                    var cmd = 'pkill -9 "' + processMac + '"';
                    grunt.verbose.writeln((cmd).magenta).or.write('Killing host application process...');
                    exec(cmd, function(error, result, code) {
                        grunt.verbose.or.ok();
                        callback();
                    });
                }
            },

            /**
             * Set "PlayerDebugMode" flag in plist file or Windows registry.
             */
            function(callback)
            {
                var PLISTS,
                    options,
                    host_family = launch_config.family;

                if (global.IS_MAC)
                {
                    PLISTS = {
                        'CC': path.join(process.env['HOME'], 'com.adobe.CSXS.4'),
                        'CC2014': path.join(process.env['HOME'], 'com.adobe.CSXS.5'),
                        'CC2015': path.join(process.env['HOME'], 'com.adobe.CSXS.6')
                    };

                    if (!PLISTS.hasOwnProperty(host_family))
                        return;

                    options = {
                        cmd: 'defaults',
                        args: ['write', PLISTS[host_family], 'PlayerDebugMode', '1']
                    };
                }
                else
                {
                    PLISTS = {
                        'CC': 'HKEY_CURRENT_USER\\Software\\Adobe\\CSXS.4\\',
                        'CC2014': 'HKEY_CURRENT_USER\\Software\\Adobe\\CSXS.5\\',
                        'CC2015': 'HKEY_CURRENT_USER\\Software\\Adobe\\CSX6\\'
                    };

                    if (!PLISTS.hasOwnProperty(host_family))
                        return;

                    options = {
                        cmd: 'reg',
                        args: ['add', PLISTS[host_family], '/v', 'PlayerDebugMode', '/d', '1', '/f']
                    };
                }

                grunt.verbose.writeln((options.cmd + ' ' + options.args.join(' ')).magenta)
                .or.write('Setting OS debug mode...');
                var spawned = grunt.util.spawn(options, function(error, result, code)
                {
                    if (code !== 0)
                    {
                        grunt.verbose.or.ok();
                        grunt.fatal(error);
                    }
                    else
                        grunt.verbose.or.ok();
                    // note for macUSER
                    // Special notes for Mac 10.9 and higher
                    //
                    //Staring with Mac 10.9, Apple introduced a caching mechanism for plist files.
                    //Your modifications to plist files does not take effect until the cache gets updated
                    //(on a periodic basis, you cannot know
                    //exactly when the update will happen). To make sure your modifications take effect, there are two methods.
                    //
                    // - Kill cfprefsd process. It will restart automatically. Then the update takes effect.
                    // - Restart your Mac, or log out the current user and re-log in.
                     if (global.IS_MAC && true) {
                        var cmd = 'pkill -9 cfprefsd';
                        grunt.verbose.writeln((cmd).magenta).or.write('Killing cfprefsd process for Mac 10.9 and higher');
                        exec(cmd, function(error, result, code) {
                            grunt.verbose.or.ok();
                            callback();
                        });
                     }
                     else {
                      callback(error, result);
                    }
                });
                spawned.stdout.on('data', function(data) { grunt.verbose.writeln(data); });
                spawned.stderr.on('data', function(data) { grunt.verbose.writeln(data); });
            },

            /**
             * Install extension by copying files to the 'extensions' folder.
             */
            function(callback)
            {
                var message = 'Installing extension at ' + launch_config.install_path.cyan + '...';
                grunt.verbose.writeln(message).or.write(message);

                // Clean-up install folder
                if (grunt.file.exists(launch_config.install_path))
                    grunt.file.delete(launch_config.install_path, { force: true });

                // Copy files over

                var cmd = 'cp -Ri "' + build.staging + '"  "' + launch_config.install_path + '"';
                exec(cmd, function(error, result, code) {
                    grunt.verbose.or.ok();
                callback();
                });

            },

            /**
             * Launch the specified host application.
             */
            function(callback)
            {
                var options = {};

                if (global.IS_MAC)
                {
                    options = {
                        cmd: 'open',
                        args: ['-F', '-n', "'" + launch_config.app_bin + "'"]
                    };
                }
                else
                {
                    options = {
                        cmd: 'explorer.exe',
                        args: ['"' + launch_config.app_bin + '"']
                    };
                }

                grunt.verbose.writeln((options.cmd + ' ' + options.args.join(' ')).magenta)
                .or.write('Starting host application...');

                exec(options.cmd + ' ' + options.args.join(' '), function(error, result, code)
                {
                    grunt.verbose.or.ok();
                    // REVIEW: command seems to fail on Windows even if in practice it works just fine...
                    // For now we just do not pass error to the callback to prevent the task from failing
                    callback(/*error, result*/);
                });
            }
        );

        // Run child tasks
        async.series(tasks, function(err, result) { callback(err, result); });
    };

    // Public interface
    var compiler = {};
    compiler.compile = compile;
    compiler.launch = launch;
    return compiler;
};
<commit_msg>cc2015 mac<commit_after>/**
 * Copyright 2014 Francesco Camarlinghi
 *
 * 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.
 */

module.exports = function(grunt)
{
    'use strict';
    var path = require('path'),
        async = require('async'),
        _ = require('lodash'),
        cep = require('./cep.js')(grunt);

    /**
     * Compiles the specified build.
     */
    var compile = function(callback, build)
    {
        var tasks = [];
        grunt.log.writeln().writeln(('Compiling bundle for Adobe ' + build.products.join(', ').cyan + ' - ' + build.families.join(', ').cyan + '...').bold);
        var exec = require('child_process').exec;
        tasks.push(
            /**
             * Do some cleanup.
             */
            function(callback)
            {
                // Validate input/output files
                if (typeof build.staging !== 'string' || !build.staging.length)
                    grunt.fatal('Invalid "staging" folder: ' + String(build.staging).cyan + '.');

                if (typeof build.source !== 'string' || !build.source.length)
                    grunt.fatal('Invalid "source" folder: ' + String(build.source).cyan + '.');

                // Clean current output folder
                if (grunt.file.exists(build.staging) && grunt.file.isDir(build.staging))
                    grunt.file.delete(build.staging, { force: true });

                grunt.file.mkdir(build.staging);
                callback();
            },

            /**
             * Copy all files.
             */
            function(callback)
            {
                // Copy all the content of the source folder over to the output folder
                var message = 'Copying ' + build.source.cyan + ' folder...';
                grunt.verbose.writeln(message).or.write(message);

                var cmd = 'cp -Ri ' + build.source + '/ ' + build.staging + '/';
                exec(cmd, function(error, result, code) {
                    grunt.verbose.or.ok();
                    callback();
                });
            },

            /**
             * Generate .debug file.
             */
            function(callback)
            {
                if (build.profile === 'debug' || build.profile === 'launch')
                {
                    var message = 'Generating ' + '.debug'.cyan + ' file...';
                    grunt.verbose.writeln(message).or.write(message);

                    var dotdebug_file = path.join(cep.utils.plugin_folder(), 'res/.debug');

                    if (grunt.file.exists(dotdebug_file))
                    {
                        if (typeof build.launch.host_port !== 'number' || build.launch.host_port < 0)
                        {
                            grunt.verbose.or.error();
                            grunt.fatal('Invalid host debug port ' + build.launch.host_port + '.');
                        }

                        var data = { 'build': build },
                            processed = grunt.template.process(grunt.file.read(dotdebug_file), { data: data });

                        grunt.file.write(path.join(build.staging, '.debug'), processed);
                    }

                    grunt.verbose.or.ok();
                }

                callback();
            },

            /**
             * Generate appropriate manifest file.
             */
            function(callback)
            {
                require('./xml')(grunt).manifest(callback, build);
            }
        );

        // Run child tasks
        async.series(tasks, function(err, result) { callback(err, result); });
    };

    /**
     * Launches debug with specified settings.
     */
    var launch = function(callback, build, host)
    {
        var tasks = [],
            launch_config = {
                product: build.launch.product,
                family: build.launch.family,
                host: host
            },
            exec = require('child_process').exec;

        grunt.log.writeln().writeln('Launching application...'.bold);

        tasks.push(
            /**
             * Detect application executable location.
             */
            function(callback)
            {
                var folder_apps, folder_servicemgr;

                if (global.IS_WINDOWS)
                {
                    folder_apps = path.join(process.env['PROGRAMFILES'], '/Adobe');

                    if (launch_config.family === 'CC')
                        folder_servicemgr = path.join(process.env['APPDATA'], '/Adobe/CEPServiceManager4/extensions');
                    else
                        folder_servicemgr = path.join(process.env['APPDATA'], '/Adobe/CEP/extensions');
                }
                else
                {
                    folder_apps = '/Applications';

                    if (launch_config.family === 'CC')
                        folder_servicemgr = process.env['HOME'] + '/Library/Application Support/Adobe/CEPServiceManager4/extensions';
                    else
                        folder_servicemgr = process.env['HOME'] + '/Library/Application\ Support/Adobe/CEP/extensions';
                }

                // Extension install path
                launch_config.install_path = path.join(folder_servicemgr, build.bundle.basename) + '.debug';

                // Application folder
                var folder_family = {
                    'CC': 'CC',
                    'CC2014': 'CC 2014',
                    'CC2015': 'CC 2015'
                };

                var folder_name = launch_config.host.hasOwnProperty('folder') ? launch_config.host.folder : '/Adobe ' + launch_config.host.name + ' ' + folder_family[launch_config.family];
                launch_config.app_folder = path.join(folder_apps, folder_name);

                if (launch_config.family === 'CC' && launch_config.host.x64 && global.IS_X64 && global.IS_WINDOWS)
                    launch_config.app_folder += ' (64 Bit)';

                if (!grunt.file.exists(launch_config.app_folder))
                {
                    grunt.fatal('Unable to find Adobe ' + launch_config.host.name + ' ' + launch_config.family + ' folder at "' + launch_config.app_folder + '".');
                    return false;
                }

                // Application executable path
                launch_config.app_bin = path.join(launch_config.app_folder, global.IS_WINDOWS ? launch_config.host.bin.win : launch_config.host.bin.mac);

                if (!grunt.file.exists(launch_config.app_bin))
                {
                    grunt.fatal('Unable to find Adobe ' + launch_config.host.name + ' ' + launch_config.family + ' executable at "' + launch_config.app_bin + '".');
                    return false;
                }

                callback();
            },

            /**
             * Kill the specified host application process if it is running.
             */
             function (callback)
            {
                var options = {};

                if (global.IS_WINDOWS)
                {
                    options.cmd = 'Taskkill';
                    options.args = ['/IM', launch_config.host.bin.win];
                     grunt.verbose.writeln((options.cmd + ' ' + options.args.join(' ')).magenta)
                      .or.write('Killing host application process...');
                      var spawned = grunt.util.spawn(options, function (error, result, code)
                      {
                          grunt.verbose.or.ok();
                          // Let some time pass so that application can be closed correctly
                          // TODO: find a better way of doing this
                          setTimeout(function ()
                          {
                              callback();
                          }, 1000);
                      });
                      spawned.stdout.on('data', function (data) { grunt.verbose.writeln(data); });
                      spawned.stderr.on('data', function (data) { grunt.verbose.writeln(data); });
                }
                else
                {
                    var appMac = launch_config.host.bin.mac;
                    var processMac = appMac.slice(0, - 4); // - .app
                    var cmd = 'pkill -9 "' + processMac + '"';
                    grunt.verbose.writeln((cmd).magenta).or.write('Killing host application process...');
                    exec(cmd, function(error, result, code) {
                        grunt.verbose.or.ok();
                        callback();
                    });
                }
            },

            /**
             * Set "PlayerDebugMode" flag in plist file or Windows registry.
             */
            function(callback)
            {
                var PLISTS,
                    options,
                    host_family = launch_config.family;

                if (global.IS_MAC)
                {
                    PLISTS = {
                        'CC': 'com.adobe.CSXS.4',
                        'CC2014': 'com.adobe.CSXS.5',
                        'CC2015': 'com.adobe.CSXS.6'
                    };

                    if (!PLISTS.hasOwnProperty(host_family))
                        return;

                    options = {
                        cmd: 'defaults',
                        args: ['write', PLISTS[host_family], 'PlayerDebugMode', '1']
                    };
                }
                else
                {
                    PLISTS = {
                        'CC': 'HKEY_CURRENT_USER\\Software\\Adobe\\CSXS.4\\',
                        'CC2014': 'HKEY_CURRENT_USER\\Software\\Adobe\\CSXS.5\\',
                        'CC2015': 'HKEY_CURRENT_USER\\Software\\Adobe\\CSX6\\'
                    };

                    if (!PLISTS.hasOwnProperty(host_family))
                        return;

                    options = {
                        cmd: 'reg',
                        args: ['add', PLISTS[host_family], '/v', 'PlayerDebugMode', '/d', '1', '/f']
                    };
                }

                grunt.verbose.writeln((options.cmd + ' ' + options.args.join(' ')).magenta)
                .or.write('Setting OS debug mode...');
                var spawned = grunt.util.spawn(options, function(error, result, code)
                {
                    if (code !== 0)
                    {
                        grunt.verbose.or.ok();
                        grunt.fatal(error);
                    }
                    else
                        grunt.verbose.or.ok();
                    // note for macUSER
                    // Special notes for Mac 10.9 and higher
                    //
                    //Staring with Mac 10.9, Apple introduced a caching mechanism for plist files.
                    //Your modifications to plist files does not take effect until the cache gets updated
                    //(on a periodic basis, you cannot know
                    //exactly when the update will happen). To make sure your modifications take effect, there are two methods.
                    //
                    // - Kill cfprefsd process. It will restart automatically. Then the update takes effect.
                    // - Restart your Mac, or log out the current user and re-log in.
                     if (global.IS_MAC && true) {
                        // var cmd = 'pkill -9 cfprefsd';
                        // grunt.verbose.writeln((cmd).magenta).or.write('Killing cfprefsd process for Mac 10.9 and higher');
                        // exec(cmd, function(error, result, code) {
                        //     grunt.verbose.or.ok();
                        //     callback();
                        // });
                     }
                     else {
                      callback(error, result);
                    }
                });
                spawned.stdout.on('data', function(data) { grunt.verbose.writeln(data); });
                spawned.stderr.on('data', function(data) { grunt.verbose.writeln(data); });
            },

            /**
             * Install extension by copying files to the 'extensions' folder.
             */
            function(callback)
            {
                var message = 'Installing extension at ' + launch_config.install_path.cyan + '...';
                grunt.verbose.writeln(message).or.write(message);

                // Clean-up install folder
                if (grunt.file.exists(launch_config.install_path))
                    grunt.file.delete(launch_config.install_path, { force: true });

                // Copy files over

                var cmd = 'cp -Ri "' + build.staging + '"  "' + launch_config.install_path + '"';
                exec(cmd, function(error, result, code) {
                    grunt.verbose.or.ok();
                callback();
                });

            },

            /**
             * Launch the specified host application.
             */
            function(callback)
            {
                var options = {};

                if (global.IS_MAC)
                {
                    options = {
                        cmd: 'open',
                        args: ['-F', '-n', "'" + launch_config.app_bin + "'"]
                    };
                }
                else
                {
                    options = {
                        cmd: 'explorer.exe',
                        args: ['"' + launch_config.app_bin + '"']
                    };
                }

                grunt.verbose.writeln((options.cmd + ' ' + options.args.join(' ')).magenta)
                .or.write('Starting host application...');

                exec(options.cmd + ' ' + options.args.join(' '), function(error, result, code)
                {
                    grunt.verbose.or.ok();
                    // REVIEW: command seems to fail on Windows even if in practice it works just fine...
                    // For now we just do not pass error to the callback to prevent the task from failing
                    callback(/*error, result*/);
                });
            }
        );

        // Run child tasks
        async.series(tasks, function(err, result) { callback(err, result); });
    };

    // Public interface
    var compiler = {};
    compiler.compile = compile;
    compiler.launch = launch;
    return compiler;
};
<|endoftext|>


<commit_before>/*global define*/
define([
	'jQuery-2.1.4.min',
	'underscore_1.3.3',
	'backbone_0.9.2',
  'text!../../../js/app/templates/siteSettings.html'
], function ($, _, Backbone, SiteSettingsTemplate) {
	'use strict';

	var SiteSettingsView = Backbone.View.extend({

    /*
     * Dev Notes:
     * -It is assumed that the keyDisplay and keyNames array exist in both private and public JSON files.
     * -It is assumed that the keyDisplay and keyNames arrays are the same length.
     */

		tagName:  'div',

    el: '#siteSettingsView',

		template: _.template(SiteSettingsTemplate),

		events: {
      //'hidden.bs.modal #fileLibraryModal': 'refreshView'
      'click #saveSettingsBtn': 'saveSettings'
		},

		initialize: function () {
			this.privateData = new Object();
      this.publicData = new Object();
		},

    render: function () {
      //debugger;
      log.push('siteSettingsView.js/render() called.');

      this.$el.html(this.template);

      this.populateView();

			return this;
		},

    //This function reads in the public and private JSON files and popultes the View with the data inside of them.
    //This function is called by render().
    populateView: function() {
      //debugger;
      log.push('siteSettingsView.js/populateView() called.');

      var thisView = this;

      $.getJSON('/api/serversettings/getprivate', '', function(data) {
        //debugger;
        log.push('Data successfully retrieved from /api/serversettings/getprivate');

        thisView.privateData = data.privateSettings;

        thisView.populatePrivateData();
      });

      $.getJSON('/js/publicsettings.json', '', function(data) {
        //debugger;
        log.push('Data successfully retrieved from publicsettings.json');

        thisView.publicData = data;

        thisView.populatePublicData();
      });

    },

    //This function populates the DOM with data stored inside the private settings file.
    //This function is called by populateView() after the data has been retrieved from the server.
    populatePrivateData: function() {
      //debugger;
      log.push('siteSettingsView.js/populatePrivateData() called.');

      for(var i=0; i < this.privateData.keyNames.length; i++) {

        //Clone the scaffolding element
        var thisForm = this.$el.find('#privateScaffold').clone();
        thisForm.prop('id', this.privateData.keyNames[i]);

        //Get the display name and display value from the JSON data.
        var displayName = this.privateData.keyDisplay[i];
        var displayVal = this.privateData[this.privateData.keyNames[i]]

        //Add the JSON data to the DOM.
        thisForm.find('label').text(displayName);
        thisForm.find('input').val(displayVal);

        //Append this new form element to the DOM.
        this.$el.find('#privateSettingsForm').append(thisForm);
      }

      //Hide the scaffolding element.
      this.$el.find('#privateScaffold').hide();
    },

    //This function populated the DOM with the data stored inside the public settings file.
    //This function is called by populateView() after the data has been retrieved.
    populatePublicData: function() {
      //debugger;
      log.push('siteSettingsView.js/populatePublicData() called.');

      for(var i=0; i < this.publicData.keyNames.length; i++) {

        //Clone the scaffolding element
        var thisForm = this.$el.find('#publicScaffold').clone();
        thisForm.prop('id', this.publicData.keyNames[i]);

        //Get the display name and display value from the JSON data.
        var displayName = this.publicData.keyDisplay[i];
        var displayVal = this.publicData[this.publicData.keyNames[i]]

        //Add the JSON data to the DOM.
        thisForm.find('label').text(displayName);
        thisForm.find('input').val(displayVal);

        //Append this new form element to the DOM.
        this.$el.find('#publicSettingsForm').append(thisForm);
      }

      //Hide the scaffolding element.
      this.$el.find('#publicScaffold').hide();
    },

    //This function is called when the user clicks on the Save Settings button.
    saveSettings: function(event) {
      debugger;

      for(var i=0; i < this.privateData.keyNames.length; i++) {

        //Get a handle on the form element.
        var thisForm = this.$el.find('#'+this.privateData.keyNames[i]);

        //Retrieve the value from the input field.
        var inputString = thisForm.find('input').val();

        //If the input contains commas, then split it into an array of values.
        if(inputString.indexOf(',') != -1) {
          inputString = inputString.split(',');
        }

        //Overwrite the old value with the new value.
        this.privateData[this.privateData.keyNames[i]] = inputString;

      }

      //Send the updated data to the server.
      $.get('/api/serversettings/saveprivate', this.privateData, function(data) {
        debugger;
      });

      //for(var i=0; i < this.publicData.keyNames.length; i++) {

      //}
    }

	});

  //debugger;
	return SiteSettingsView;
});
<commit_msg>Developing the Site Settings View.<commit_after>/*global define*/
define([
	'jQuery-2.1.4.min',
	'underscore_1.3.3',
	'backbone_0.9.2',
  'text!../../../js/app/templates/siteSettings.html'
], function ($, _, Backbone, SiteSettingsTemplate) {
	'use strict';

	var SiteSettingsView = Backbone.View.extend({

    /*
     * Dev Notes:
     * -It is assumed that the keyDisplay and keyNames array exist in both private and public JSON files.
     * -It is assumed that the keyDisplay and keyNames arrays are the same length.
     */

		tagName:  'div',

    el: '#siteSettingsView',

		template: _.template(SiteSettingsTemplate),

		events: {
      //'hidden.bs.modal #fileLibraryModal': 'refreshView'
      'click #saveSettingsBtn': 'saveSettings'
		},

		initialize: function () {
			this.privateData = new Object();
      this.publicData = new Object();
		},

    render: function () {
      //debugger;
      log.push('siteSettingsView.js/render() called.');

      this.$el.html(this.template);

      this.populateView();

			return this;
		},

    //This function reads in the public and private JSON files and popultes the View with the data inside of them.
    //This function is called by render().
    populateView: function() {
      //debugger;
      log.push('siteSettingsView.js/populateView() called.');

      var thisView = this;

      $.getJSON('/api/serversettings/getprivate', '', function(data) {
        //debugger;
        log.push('Data successfully retrieved from /api/serversettings/getprivate');

        thisView.privateData = data.privateSettings;

        thisView.populatePrivateData();
      });

      $.getJSON('/js/publicsettings.json', '', function(data) {
        //debugger;
        log.push('Data successfully retrieved from publicsettings.json');

        thisView.publicData = data;

        thisView.populatePublicData();
      });

    },

    //This function populates the DOM with data stored inside the private settings file.
    //This function is called by populateView() after the data has been retrieved from the server.
    populatePrivateData: function() {
      //debugger;
      log.push('siteSettingsView.js/populatePrivateData() called.');

      for(var i=0; i < this.privateData.keyNames.length; i++) {

        //Clone the scaffolding element
        var thisForm = this.$el.find('#privateScaffold').clone();
        thisForm.prop('id', this.privateData.keyNames[i]);

        //Get the display name and display value from the JSON data.
        var displayName = this.privateData.keyDisplay[i];
        var displayVal = this.privateData[this.privateData.keyNames[i]]

        //Add the JSON data to the DOM.
        thisForm.find('label').text(displayName);
        thisForm.find('input').val(displayVal);

        //Append this new form element to the DOM.
        this.$el.find('#privateSettingsForm').append(thisForm);
      }

      //Hide the scaffolding element.
      this.$el.find('#privateScaffold').hide();
    },

    //This function populated the DOM with the data stored inside the public settings file.
    //This function is called by populateView() after the data has been retrieved.
    populatePublicData: function() {
      //debugger;
      log.push('siteSettingsView.js/populatePublicData() called.');

      for(var i=0; i < this.publicData.keyNames.length; i++) {

        //Clone the scaffolding element
        var thisForm = this.$el.find('#publicScaffold').clone();
        thisForm.prop('id', this.publicData.keyNames[i]);

        //Get the display name and display value from the JSON data.
        var displayName = this.publicData.keyDisplay[i];
        var displayVal = this.publicData[this.publicData.keyNames[i]]

        //Add the JSON data to the DOM.
        thisForm.find('label').text(displayName);
        thisForm.find('input').val(displayVal);

        //Append this new form element to the DOM.
        this.$el.find('#publicSettingsForm').append(thisForm);
      }

      //Hide the scaffolding element.
      this.$el.find('#publicScaffold').hide();
    },

    //This function is called when the user clicks on the Save Settings button.
    saveSettings: function(event) {
      debugger;

      for(var i=0; i < this.privateData.keyNames.length; i++) {

        //Get a handle on the form element.
        var thisForm = this.$el.find('#'+this.privateData.keyNames[i]);

        //Retrieve the value from the input field.
        var inputString = thisForm.find('input').val();

        //If the input contains commas, then split it into an array of values.
        if(inputString.indexOf(',') != -1) {
          inputString = inputString.split(',');
        }

        //Overwrite the old value with the new value.
        this.privateData[this.privateData.keyNames[i]] = inputString;

      }

      //Send the updated data to the server.
      $.get('/api/serversettings/saveprivate', this.privateData, function(data) {
        debugger;

        if(data.success) {
          log.push('Successfly updated privatesettings.json file using /api/serversettings/saveprivate API.');
        } else {
          log.push('Unknown value returned by /api/serversettings/saveprivate');
        }
      });

      for(var i=0; i < this.publicData.keyNames.length; i++) {

        //Get a handle on the form element.
        var thisForm = this.$el.find('#'+this.publicData.keyNames[i]);

        //Retrieve the value from the input field.
        var inputString = thisForm.find('input').val();

        //If the input contains commas, then split it into an array of values.
        if(inputString.indexOf(',') != -1) {
          inputString = inputString.split(',');
        }

        //Overwrite the old value with the new value.
        this.publicData[this.publicData.keyNames[i]] = inputString;
      }

      //Send the updated data to the server.
      $.get('/api/serversettings/savepublic', this.publicData, function(data) {
        debugger;

        if(data.success) {
          log.push('Successfly updated publicsettings.json file using /api/serversettings/savepublic API.');
        } else {
          log.push('Unknown value returned by /api/serversettings/savepublic');
        }
      });
    }

	});

  //debugger;
	return SiteSettingsView;
});
<|endoftext|>


<commit_before>/*
 * grunt-nice-package
 * https://github.com/bahmutov/grunt-nice-package
 *
 * Copyright (c) 2013 Gleb Bahmutov
 * Licensed under the MIT license.
 */

'use strict';

var PJV = require('package-json-validator');
var check = require('check-types');

module.exports = function(grunt) {

  var is = function (type, name, value) {
    if (!check['is' + type](value)) {
      grunt.log.error('expected', name, 'to be', type, 'not', value);
      return false;
    }
    return true;
  };

  var defaultValidators = {
    name: is.bind(null, 'String', 'name'),
    version: is.bind(null, 'String', 'version'),
    description: is.bind(null, 'String', 'description'),
    keywords: function (values) {
      if (!check.isArray(values)) {
        grunt.log.error('expected keywords to be an Array');
        return false;
      }

      return values.every(function (keyword) {
        if (!check.isString(keyword)) {
          grunt.log.error('every keyword should be a string, found', keyword);
          return false;
        }
        return true;
      });
    },
    author: function (value) {
      if (!check.isObject(value) &&
        !check.iString(value)) {
        grunt.log.error('invalid author value', value);
        return false;
      }
      return true;
    },
    repository: function (value) {
      if (!check.isObject(value)) {
        grunt.log.error('expected repository to be an object, not', value);
        return false;
      }
      if (!check.isString(value.type)) {
        grunt.log.error('expected repository type to be a string, not', value.type);
        return false;
      }
      if (!check.isString(value.url)) {
        grunt.log.error('expected repository url to be a string, not', value.url);
        return false;
      }
      return true;
    }
  };

  grunt.registerMultiTask('nice-package', 'Opinionated package.json validator', function() {
    // Merge custom validation functions with default ones
    var options = this.options(defaultValidators);

    var pkg = grunt.file.readJSON('package.json');

    var every = Object.keys(options).every(function (key) {
      grunt.verbose.writeln('checking property', key);

      var property = pkg[key];
      if (!property) {
        grunt.log.error('package.json missing', key);
        return false;
      }
      if (typeof options[key] === 'function') {
        if (!options[key](property)) {
          grunt.log.error('failed check for property', key);
          return false;
        }
      }

      return true;
    });

    if (!every) {
      return false;
    }

    // advanced checking
    if (!check.isString(pkg.license) &&
      !check.isArray(pkg.licenses)) {
      grunt.log.error('missing license information');
      return false;
    }
    // todo: use package validator

    return true;
  });

};
<commit_msg>added package.json-validator error checking and recommendations<commit_after>/*
 * grunt-nice-package
 * https://github.com/bahmutov/grunt-nice-package
 *
 * Copyright (c) 2013 Gleb Bahmutov
 * Licensed under the MIT license.
 */

'use strict';

var PJV = require('package-json-validator').PJV;
var check = require('check-types');

module.exports = function(grunt) {

  var is = function (type, name, value) {
    if (!check['is' + type](value)) {
      grunt.log.error('expected', name, 'to be', type, 'not', value);
      return false;
    }
    return true;
  };

  var defaultValidators = {
    name: is.bind(null, 'String', 'name'),
    version: is.bind(null, 'String', 'version'),
    description: is.bind(null, 'String', 'description'),
    keywords: function (values) {
      if (!check.isArray(values)) {
        grunt.log.error('expected keywords to be an Array');
        return false;
      }

      return values.every(function (keyword) {
        if (!check.isString(keyword)) {
          grunt.log.error('every keyword should be a string, found', keyword);
          return false;
        }
        return true;
      });
    },
    author: function (value) {
      if (!check.isObject(value) &&
        !check.iString(value)) {
        grunt.log.error('invalid author value', value);
        return false;
      }
      return true;
    },
    repository: function (value) {
      if (!check.isObject(value)) {
        grunt.log.error('expected repository to be an object, not', value);
        return false;
      }
      if (!check.isString(value.type)) {
        grunt.log.error('expected repository type to be a string, not', value.type);
        return false;
      }
      if (!check.isString(value.url)) {
        grunt.log.error('expected repository url to be a string, not', value.url);
        return false;
      }
      return true;
    }
  };

  grunt.registerMultiTask('nice-package', 'Opinionated package.json validator', function() {
    // Merge custom validation functions with default ones
    var options = this.options(defaultValidators);

    var pkg = grunt.file.readJSON('package.json');

    var every = Object.keys(options).every(function (key) {
      grunt.verbose.writeln('checking property', key);

      var property = pkg[key];
      if (!property) {
        grunt.log.error('package.json missing', key);
        return false;
      }
      if (typeof options[key] === 'function') {
        if (!options[key](property)) {
          grunt.log.error('failed check for property', key);
          return false;
        }
      }

      return true;
    });

    if (!every) {
      // return false;
    }

    // advanced checking
    if (!check.isString(pkg.license) &&
      !check.isArray(pkg.licenses)) {
      grunt.log.error('missing license information');
      return false;
    }
    // todo: use package validator
    var result = PJV.validate(JSON.stringify(pkg, null, 2));
    if (!result.valid) {
      grunt.log.error(result.errors);
      return false;
    }
    grunt.verbose.writeln(result.warnings);

    return true;
  });

};
<|endoftext|>


<commit_before>angular.module('imageDirectives', [])
    .directive('imagesNavbar', function() {
        return {
            restrict: 'E',
            replace: 'true',
            templateUrl: 'views/navbar.html'
        };
    })
    .directive('images', function(ngDialog) {
        return {
            restrict: 'E',
            replace: 'true',
            templateUrl: 'views/images.html',
            link: function(scope, elem, attrs) {
                scope.open = function() {
                    ngDialog.open({
                        template: 'views/imageDialog.html',
                        className: 'ngdialog-theme-default',
                        scope: scope
                    });
                }
            }
        };
    })
    .directive('uploader', ['$timeout', function(timer) {
        return {
            restrict: 'E',
            replace: 'true',
            templateUrl: 'views/uploader.html',
            link: function(scope, elem, attrs) {
                var jumbotron = elem.get(0);
                var previewNode = elem.find('#template').get(0);
                var previewTemplate = previewNode.parentNode.innerHTML;

                previewNode.id = '';
                previewNode.parentNode.removeChild(previewNode);

                var myDropzone = new Dropzone(jumbotron, {
                    url: '/upload',
                    thumbnailWidth: 80,
                    thumbnailHeight: 80,
                    parallelUploads: 20,
                    previewTemplate: previewTemplate,
                    autoProcessQueue: false,
                    previewsContainer: '#previews',
                    clickable: '.fileinput-button',
                    acceptedFiles: 'image/*, .jpg, .jpeg, .gif, .png'
                });

                myDropzone.on('addedfile', function(file) {
                    file.previewElement.querySelector('.start').onclick = function() {myDropzone.processQueue(file); };
                });

                // Update the total progress bar
                myDropzone.on("totaluploadprogress", function(progress) {
                    elem.find("#total-progress .progress-bar").get(0).style.width = progress + "%";
                });

                myDropzone.on("sending", function(file) {
                    // Show the total progress bar when upload starts
                    elem.find("#total-progress").get(0).style.opacity = "1";
                    // And disable the start button
                    file.previewElement.querySelector(".start").setAttribute("disabled", "disabled");
                });

                // Hide the total progress bar when nothing's uploading anymore
                myDropzone.on("queuecomplete", function(progress) {
                    elem.find("#total-progress").get(0).style.opacity = "0";
                    timer(function() {
                        elem.find('.preview-box').css('display', 'none');
                    }, 5000);
                });

                // Setup the buttons for all transfers
                // The "add files" button doesn't need to be setup because the config
                // `clickable` has already been specified.
                elem.find('#actions .start').on('click', function() {
                    myDropzone.processQueue(myDropzone.getQueuedFiles());
                });

                elem.find('#actions .cancel').on('click', function() {
                   myDropzone.removeAllFiles(true);
                });
            }
        };
    }])
    .directive('imagesFooter', function() {
        return {
            restrict: 'E',
            replace: 'true',
            templateUrl: 'views/footer.html'
        };
    });<commit_msg>push the newly uploaded image onto the image array again, so it'll display immediately once uploaded<commit_after>angular.module('imageDirectives', [])
    .directive('imagesNavbar', function() {
        return {
            restrict: 'E',
            replace: 'true',
            templateUrl: 'views/navbar.html'
        };
    })
    .directive('images', function(ngDialog) {
        return {
            restrict: 'E',
            replace: 'true',
            templateUrl: 'views/images.html',
            link: function(scope, elem, attrs) {
                scope.open = function() {
                    ngDialog.open({
                        template: 'views/imageDialog.html',
                        className: 'ngdialog-theme-default',
                        scope: scope
                    });
                }
            }
        };
    })
    .directive('uploader', ['$timeout', function(timer) {
        return {
            restrict: 'E',
            replace: 'true',
            templateUrl: 'views/uploader.html',
            link: function(scope, elem, attrs) {
                var jumbotron = elem.get(0);
                var previewNode = elem.find('#template').get(0);
                var previewTemplate = previewNode.parentNode.innerHTML;

                previewNode.id = '';
                previewNode.parentNode.removeChild(previewNode);

                var myDropzone = new Dropzone(jumbotron, {
                    url: '/upload',
                    thumbnailWidth: 80,
                    thumbnailHeight: 80,
                    parallelUploads: 20,
                    previewTemplate: previewTemplate,
                    autoProcessQueue: false,
                    previewsContainer: '#previews',
                    clickable: '.fileinput-button',
                    acceptedFiles: 'image/*, .jpg, .jpeg, .gif, .png'
                });

                myDropzone.on('addedfile', function(file) {
                    file.previewElement.querySelector('.start').onclick = function() {myDropzone.processQueue(file); };
                });

                // Update the total progress bar
                myDropzone.on("totaluploadprogress", function(progress) {
                    elem.find("#total-progress .progress-bar").get(0).style.width = progress + "%";
                });

                myDropzone.on("sending", function(file) {
                    // Show the total progress bar when upload starts
                    elem.find("#total-progress").get(0).style.opacity = "1";
                    // And disable the start button
                    file.previewElement.querySelector(".start").setAttribute("disabled", "disabled");
                });

                // Hide the total progress bar when nothing's uploading anymore
                myDropzone.on("queuecomplete", function(progress) {
                    elem.find("#total-progress").get(0).style.opacity = "0";
                    timer(function() {
                        elem.find('.file-row').remove();
                    }, 5000);
                });

                myDropzone.on('success', function(file, image) {
                    scope.images.push(image);
                })

                // Setup the buttons for all transfers
                // The "add files" button doesn't need to be setup because the config
                // `clickable` has already been specified.
                elem.find('#actions .start').on('click', function() {
                    myDropzone.processQueue(myDropzone.getQueuedFiles());
                });

                elem.find('#actions .cancel').on('click', function() {
                   myDropzone.removeAllFiles(true);
                });
            }
        };
    }])
    .directive('imagesFooter', function() {
        return {
            restrict: 'E',
            replace: 'true',
            templateUrl: 'views/footer.html'
        };
    });<|endoftext|>


<commit_before>/*
 * Regex for converting Bootstrap's liquid
 * templates over to Handlebars.
 * Copyright (c) 2013 Jon Schlinkert
 * Licensed under the MIT license.
 */

exports.init = function(grunt) {

  exports.regex = {
    patterns: [
      // Layouts
      // -------------------------------------------------
      {
        // Replace {{content}} tag with {{> body }} partial
        pattern: /(?:\{\{\s*content\s*\}\})/g,
        replacement: '{{> body }}'
      },
      {
        // Append `.html` ext to layouts defined in YFM
        pattern: /(---\s*layout:.*)/g,
        replacement: '$1.hbs'
      },

      // Titles and basic variables
      // -------------------------------------------------
      {
        pattern: /(\{%\s*)(if\s(page\..+)\s==\s(.+))\s(%\})\s*(.+)(\{\{.*\}\}.*)/g,
        replacement: '{{#is $3 $4}}\n    $7\n  {{/is}}'
      },
      {
        pattern: /(\{% else if %\})\s*(\{\{.*)\s*(\{% endif %\})/g,
        replacement: '{{#isnt title "Bootstrap"}}\n    $2\n  {{/isnt}}'
      },

      // Navigation
      // -------------------------------------------------
      {
        // Replace liquid tags in nav anchors with Handlebars helpers.
        //
        // Example:
        //    From: {% if page.slug == "getting-started" %} class="active"{% endif %}
        //    To:   {{#is basename "getting-started"}} class="active"{{/is}}
        //
        pattern: /(\{%\s*if|elsif)\s(page\.slug[ ]?==[ ]?)(".*)[ ]%\}(.*)(?:\{% endif %\})/g,
        replacement: '{{#is slug $3}}$4{{/is}}'
      },
      {
        // Replace liquid {% if/elseif %} navigation blocks with Handlebars {{#is/unless}}
        pattern: /(\{%\s*)\b(.*)\b\s(\b(.*)\b\.(.*)\s==\s)(.*\s*)(%\})(\s.*)(\s*)(\{(%|\{)\s*\b(.*)\b)\s(.*)(?:\.html)(\s*%\})/g,
        replacement: '{{#is slug $6}} $9 {{> $13 }}\n              {{/is}}'
      },
      {
        // Clean up any remaining {% endif %}'s
        pattern: /(?:\{%\s*endif\s*%\})/g,
        replacement: '\n'
      },

      // Tags
      // -------------------------------------------------
      {
        // Replace liquid includes with Handlebars partials
        pattern: /(\{%\s*include\s*)(|(?:.*)+)(?:\.html\s*%\})/g,
        replacement: '{{> $2 }}'
      },
      {
        // Strip 'page' path from tag variables
        pattern: /(\{\{\s*page\.)(.*)(?:\}\})/g,
        replacement: '{{ $2}}'
      },
      {
        // Remove leftover "page" variables
        pattern: /\b(is )(?:page\.)\b/g,
        replacement: '$1'
      },
      {
        // Replace "{{ base_url }}/dist" and "{{ base_url }}/assets" with "{{ assets }}"
        pattern: /(?:\{\{\s*base_url\s*\}\}(assets|dist))/g,
        replacement: '{{ assets }}'
      },
      // Use {{root}} variable once it's implemented in Assemble
      // {
      //   // Replace "{{ base_url }}/dist" and "{{ base_url }}/assets" with "{{ assets }}"
      //   pattern: /(href=")(\{\{[ ]?base_url[ ]?\}\})[\/]?(|.*)[ ]?"/g,
      //   replacement: 'href="{{root}}/$3.html\"'
      // },
      // {
      //   // cleanup from previous regex
      //   pattern: /({{root}}\/.html)/g,
      //   replacement: '{{root}}\/'
      // },

      {
        // Replace "{{ base_url }}/dist" and "{{ base_url }}/assets" with "{{ assets }}"
        pattern: /(\{\{ base_url \}\}2\.3\.2)/g,
        replacement: 'http://getbootstrap.com/2.3.2'
      },
      {
        // Replace "{{ base_url }}/dist" and "{{ base_url }}/assets" with "{{ assets }}"
        pattern: /(href=")(\{\{[ ]?base_url[ ]?\}\})[\/]?(|.*)[ ]?"/g,
        replacement: 'href="./$3.html\"'
      },
      {
        // cleanup from previous regex
        pattern: /.\/.html/g,
        replacement: 'index.html'
      },
      {
        // Replace liquid filter with {{now}} helper
        pattern: /site\.time \| date\:/g,
        replacement: 'now'
      },

      // Code blocks and syntax highlighting
      // -------------------------------------------------
      {
        // highlight.js doesn't support line numbers, so convert the
        // language definition to just "html"
        pattern: /html linenos/g,
        replacement: 'html'
      },
      {
        // Identify the language definitions after the first code
        // fence (```) for each highlighted code block.
        pattern: /(\{%\s*)\s*(?:highlight)\s*(bash|js|html|css|less)\s*(%\})/g,
        replacement: '\n{{#markdown}}\n```$2'
      },
      {
        pattern: /(\{%\s*endhighlight\s*%\})/g,
        replacement: '```\n{{/markdown}}\n'
      },

      // Add script and link tags for highlight.js
      // -------------------------------------------------
      {
        pattern: /(\<meta name=\"description\" content=\"\"\>)/g,
        replacement: '<meta name="description" content="{{pkg.description}}">'
      },
      {
        // Find the holder.js script tag, then just add it back
        // with highlight.js directly afterwards
        pattern: /(<script.*holder.js"><\/script>)/g,
        replacement: '$1\n<script src="{{ assets }}\/js/highlight.js"><\/script>' +
                     '\n<script>hljs.initHighlightingOnLoad();<\/script>'
      },
      {
        // replace Jekyll's 'pygments-manni.css' with 'github.css' for highlight.js,
        // and override the background color on github.css so it won't conflict
        // with Bootstrap's styles.
        pattern: /(pygments-manni)(.*">)/,
        replacement: 'github$2\n<style>pre code { background: transparent; }<\/style>'
      }
    ]
  };

  return exports;
};<commit_msg>improvents to replacements structure<commit_after>/*
 * Regex for converting Bootstrap's liquid
 * templates over to Handlebars.
 * Copyright (c) 2013 Jon Schlinkert
 * Licensed under the MIT license.
 */

module.exports.regex = exports.regex = {
  patterns: [
    // Layouts
    // -------------------------------------------------
    {
      // Replace {{content}} tag with {{> body }} partial
      pattern: /(?:\{\{\s*content\s*\}\})/g,
      replacement: '{{> body }}'
    },
    {
      // Append `.html` ext to layouts defined in YFM
      pattern: /(---\s*layout:.*)/g,
      replacement: '$1.hbs'
    },

    // Titles and basic variables
    // -------------------------------------------------
    {
      pattern: /(\{%\s*)(if\s(page\..+)\s==\s(.+))\s(%\})\s*(.+)(\{\{.*\}\}.*)/g,
      replacement: '{{#is $3 $4}}\n    $7\n  {{/is}}'
    },
    {
      pattern: /(\{% else if %\})\s*(\{\{.*)\s*(\{% endif %\})/g,
      replacement: '{{#isnt title "Bootstrap"}}\n    $2\n  {{/isnt}}'
    },

    // Navigation
    // -------------------------------------------------
    {
      // Replace liquid tags in nav anchors with Handlebars helpers.
      //
      // Example:
      //    From: {% if page.slug == "getting-started" %} class="active"{% endif %}
      //    To:   {{#is basename "getting-started"}} class="active"{{/is}}
      //
      pattern: /(\{%\s*if|elsif)\s(page\.slug[ ]?==[ ]?)(".*)[ ]%\}(.*)(?:\{% endif %\})/g,
      replacement: '{{#is slug $3}}$4{{/is}}'
    },
    {
      // Replace liquid {% if/elseif %} navigation blocks with Handlebars {{#is/unless}}
      pattern: /(\{%\s*)\b(.*)\b\s(\b(.*)\b\.(.*)\s==\s)(.*\s*)(%\})(\s.*)(\s*)(\{(%|\{)\s*\b(.*)\b)\s(.*)(?:\.html)(\s*%\})/g,
      replacement: '{{#is slug $6}} $9 {{> $13 }}\n              {{/is}}'
    },
    {
      // Clean up any remaining {% endif %}'s
      pattern: /(?:\{%\s*endif\s*%\})/g,
      replacement: '\n'
    },

    // Tags
    // -------------------------------------------------
    {
      // Replace liquid includes with Handlebars partials
      pattern: /(\{%\s*include\s*)(|(?:.*)+)(?:\.html\s*%\})/g,
      replacement: '{{> $2 }}'
    },
    {
      // Strip 'page' path from tag variables
      pattern: /(\{\{\s*page\.)(.*)(?:\}\})/g,
      replacement: '{{ $2}}'
    },
    {
      // Remove leftover "page" variables
      pattern: /\b(is )(?:page\.)\b/g,
      replacement: '$1'
    },
    {
      // Replace "{{ base_url }}/dist" and "{{ base_url }}/assets" with "{{ assets }}"
      pattern: /(?:\{\{\s*base_url\s*\}\}(assets|dist))/g,
      replacement: '{{ assets }}'
    },
    // Use {{root}} variable once it's implemented in Assemble
    // {
    //   // Replace "{{ base_url }}/dist" and "{{ base_url }}/assets" with "{{ assets }}"
    //   pattern: /(href=")(\{\{[ ]?base_url[ ]?\}\})[\/]?(|.*)[ ]?"/g,
    //   replacement: 'href="{{root}}/$3.html\"'
    // },
    // {
    //   // cleanup from previous regex
    //   pattern: /({{root}}\/.html)/g,
    //   replacement: '{{root}}\/'
    // },

    {
      // Replace "{{ base_url }}/dist" and "{{ base_url }}/assets" with "{{ assets }}"
      pattern: /(\{\{ base_url \}\}2\.3\.2)/g,
      replacement: 'http://getbootstrap.com/2.3.2'
    },
    {
      // Replace "{{ base_url }}/dist" and "{{ base_url }}/assets" with "{{ assets }}"
      pattern: /(href=")(\{\{[ ]?base_url[ ]?\}\})[\/]?(|.*)[ ]?"/g,
      replacement: 'href="./$3.html\"'
    },
    {
      // cleanup from previous regex
      pattern: /.\/.html/g,
      replacement: 'index.html'
    },
    {
      // Replace liquid filter with {{now}} helper
      pattern: /site\.time \| date\:/g,
      replacement: 'now'
    },

    // Code blocks and syntax highlighting
    // -------------------------------------------------
    {
      // highlight.js doesn't support line numbers, so convert the
      // language definition to just "html"
      pattern: /html linenos/g,
      replacement: 'html'
    },
    {
      // Identify the language definitions after the first code
      // fence (```) for each highlighted code block.
      pattern: /(\{%\s*)\s*(?:highlight)\s*(bash|js|html|css|less)\s*(%\})/g,
      replacement: '\n{{#markdown}}\n```$2'
    },
    {
      pattern: /(\{%\s*endhighlight\s*%\})/g,
      replacement: '```\n{{/markdown}}\n'
    },

    // Add script and link tags for highlight.js
    // -------------------------------------------------
    {
      pattern: /(\<meta name=\"description\" content=\"\"\>)/g,
      replacement: '<meta name="description" content="{{pkg.description}}">'
    },
    {
      // Find the holder.js script tag, then just add it back
      // with highlight.js directly afterwards
      pattern: /(<script.*holder.js"><\/script>)/g,
      replacement: '$1\n<script src="{{ assets }}\/js/highlight.js"><\/script>' +
                   '\n<script>hljs.initHighlightingOnLoad();<\/script>'
    },
    {
      // replace Jekyll's 'pygments-manni.css' with 'github.css' for highlight.js,
      // and override the background color on github.css so it won't conflict
      // with Bootstrap's styles.
      pattern: /(pygments-manni)(.*">)/,
      replacement: 'github$2\n<style>pre code { background: transparent; }<\/style>'
    }
  ]
};

<|endoftext|>


<commit_before>'use strict';
var chatInterval;

/**
 * @ngdoc function
 * @name anyandgoApp.controller:MainCtrl
 * @description
 * # MainCtrl
 * Controller of the anyandgoApp
 */
angular.module('anyandgoApp')
  .controller('MainCtrl', function ($scope, $routeParams, ChatService, $interval) {
    $scope.messages = [];
    $scope.lastmsghash = '';
    $scope.chatmsg = '';
    $scope.anyandgoversion = 'v0.1';

    $scope.userto = $routeParams.userto || '';
    $scope.users = {};

    $scope.setChatRoomUser = function($event){
        $event.preventDefault();
        console.log($event);
        // $scope.userto =
        // message
    };

    //https://github.com/lifeentity/chat-app/blob/master/public/app/scripts/controllers/chat-room.js
    var clearTextarea = function(r){
        console.log("aaaa");
        $scope.chatmsg = "";
        return r;
    };

    var reloadMessages = function(r){
        $scope.messages = r.data.history;
        if(r.data.history.length > 0){
            $scope.lastmsghash = r.data.history[r.data.history.length-1]._id;
        }
        return r;
    };

    var reloadUserTo = function(r){
        $scope.users[r.data._id] = r.data;
        return r;
    };

    var updateMessages = function(r){
        return ChatService.updateChatHistory($scope.userto, $scope.lastmsghash)
            .then(showUpdateMessages);
    };

    var showUpdateMessages = function(r){
        if(r.data.history.length > 0 && $scope.userto !== "" && $scope.lastmsghash !== "") {
            $scope.messages = $scope.messages.concat(r.data.history);
            $scope.lastmsghash = r.data.history[r.data.history.length-1]._id;
        }
        return r;
    };

    $scope.sendPrivateChat = function(){
        //console.log($scope.chatmsg);
        if($scope.userto !== "") {
            ChatService.sendChat($scope.userto, $scope.chatmsg)
                .then(clearTextarea)
                .then(updateMessages);
                //.then(showUpdateMessages);
        }
    };

    /*
    if($scope.userto !== "") {
        ChatService.getChatHistory($scope.userto, 'day')
            .then(reloadMessages);
    }
    */

    if(typeof chatInterval !== 'undefined') {
        //Cancel it
        $interval.cancel(chatInterval);
    }
    //Get current user data
    ChatService.getUserInfo('me').then(reloadUserTo);

    // Start a new one
    chatInterval = $interval(function(){
        if($scope.lastmsghash !== "") {
            updateMessages();
        } else if($scope.userto !== "") {
            ChatService.getChatHistory($scope.userto, 'day')
                .then(reloadMessages).then(function(r){
                    ChatService.getUserInfo($scope.userto).then(reloadUserTo);
                });
        }

    }, 1000);

  });
<commit_msg>Chat Improvement<commit_after>'use strict';
var chatInterval;

/**
 * @ngdoc function
 * @name anyandgoApp.controller:MainCtrl
 * @description
 * # MainCtrl
 * Controller of the anyandgoApp
 */
angular.module('anyandgoApp')
  .controller('MainCtrl', function ($scope, $routeParams, ChatService, $interval) {
    $scope.messages = [];
    $scope.lastmsghash = '';
    $scope.chatmsg = '';
    $scope.anyandgoversion = 'v0.1';

    $scope.userto = $routeParams.userto || '';
    $scope.users = {};

    $scope.setChatRoomUser = function($event){
        $event.preventDefault();
        console.log($event);
        // $scope.userto =
        // message
    };

    //https://github.com/lifeentity/chat-app/blob/master/public/app/scripts/controllers/chat-room.js
    var clearTextarea = function(r){
        $scope.chatmsg = "";
        return r;
    };

    var reloadMessages = function(r){
        $scope.messages = r.data.history;
        if(r.data.history.length > 0){
            $scope.lastmsghash = r.data.history[r.data.history.length-1]._id;
        }
        return r;
    };

    var reloadUserTo = function(r){
        $scope.users[r.data._id] = r.data;
        return r;
    };

    var updateMessages = function(r){
        return ChatService.updateChatHistory($scope.userto, $scope.lastmsghash)
            .then(showUpdateMessages);
    };

    var showUpdateMessages = function(r){
        if(typeof r.data.history !== 'undefined' && r.data.history.length > 0 && $scope.userto !== "" && $scope.lastmsghash !== "") {
            $scope.messages = $scope.messages.concat(r.data.history);
            $scope.lastmsghash = r.data.history[r.data.history.length-1]._id;
        }
        return r;
    };

    $scope.sendPrivateChat = function(){
        //console.log($scope.chatmsg);
        if($scope.userto !== "") {
            ChatService.sendChat($scope.userto, $scope.chatmsg)
                .then(clearTextarea)
                .then(updateMessages);
                //.then(showUpdateMessages);
        }
    };

    /*
    if($scope.userto !== "") {
        ChatService.getChatHistory($scope.userto, 'day')
            .then(reloadMessages);
    }
    */

    if(typeof chatInterval !== 'undefined') {
        //Cancel it
        $interval.cancel(chatInterval);
    }
    //Get current user data
    ChatService.getUserInfo('me').then(reloadUserTo);

    // Start a new one
    chatInterval = $interval(function(){
        if($scope.lastmsghash !== "") {
            updateMessages();
        } else if($scope.userto !== "") {
            ChatService.getChatHistory($scope.userto, 'day')
                .then(reloadMessages).then(function(r){
                    ChatService.getUserInfo($scope.userto).then(reloadUserTo);
                });
        }

    }, 1000);

  });
<|endoftext|>


<commit_before>function LTmap() {

	// Singleton
	if (typeof LTmap.instance === 'object') {
		return LTmap.instance;
	}
	LTmap.instance = this;

	google.maps.Circle.prototype.contains = function(latLng) {
		return this.getBounds().contains(latLng)
				&& google.maps.geometry.spherical.computeDistanceBetween(this
						.getCenter(), latLng) <= this.getRadius();
	};

	// Defaults
	LTmap.elementId = 'map';
	LTmap.lat = '53.147086';
	LTmap.lng = '8.180434';
	LTmap.zoom = 4;
	LTmap.markerUnread = {
		url : 'TwitterBlue.png',
		size : new google.maps.Size(43, 36),
		origin : new google.maps.Point(0, 0),
		anchor : new google.maps.Point(21, 18)
	};
	LTmap.markerRead = {
		url : 'TwitterDark.png',
		size : new google.maps.Size(43, 36),
		origin : new google.maps.Point(0, 0),
		anchor : new google.maps.Point(21, 18)
	};
	LTmap.markerSpiderfiedUnread = {
		url : 'TwitterRedBlue.png',
		size : new google.maps.Size(43, 36),
		origin : new google.maps.Point(0, 0),
		anchor : new google.maps.Point(21, 18)
	};
	LTmap.markerSpiderfiedRead = {
		url : 'TwitterRedDark.png',
		size : new google.maps.Size(43, 36),
		origin : new google.maps.Point(0, 0),
		anchor : new google.maps.Point(21, 18)
	};
	LTmap.markerShape = {
		coords : [ 0, 33, 7, 36, 22, 36, 31, 31, 38, 22, 39, 19, 39, 12, 43, 8,
				43, 0, 24, 0, 22, 1, 19, 5, 18, 8, 17, 9, 15, 7, 13, 7, 5, 1,
				3, 1, 1, 4, 1, 17, 4, 21, 4, 24, 7, 26, 5, 28, 1, 28, 0, 29 ],
		type : 'poly'
	};

	var firstSetLocation = true;
	var center = new google.maps.LatLng(LTmap.lat, LTmap.lng);
	var circle = null;
	var openedMarker = null;
	var onMap = {};

	// Initialize map with defaults
	var map = new google.maps.Map(document.getElementById(LTmap.elementId), {
		zoom : LTmap.zoom,
		center : new google.maps.LatLng(LTmap.lat, LTmap.lng),
		mapTypeId : google.maps.MapTypeId.HYBRID,
		minZoom : 4,
		maxZoom : 18,
		zoomControlOptions : {
			position : google.maps.ControlPosition.RIGHT_TOP,
		},
		streetViewControlOptions : {
			position : google.maps.ControlPosition.RIGHT_TOP,
		},
		panControlOptions : {
			position : google.maps.ControlPosition.RIGHT_TOP,
		},
	});
	var oms = new OverlappingMarkerSpiderfier(map, {
		nearbyDistance : 40,
		circleFootSeparation : 40,
		spiralFootSeparation : 35,
		spiralLengthFactor : 7,
		spiralLengthStart : 12
	});
	oms.addListener('click', function(marker, event) {
		marker.openclick();
	});
	oms.addListener('spiderfy', function(markers) {
		for(var key in markers)
			if(markers[key].isRead)
				markers[key].setIcon(LTmap.markerSpiderfiedRead);
			else
				markers[key].setIcon(LTmap.markerSpiderfiedUnread);
	});
	oms.addListener('unspiderfy', function(markers) {
		for(var key in markers)
			if(markers[key].isRead)
				markers[key].setIcon(LTmap.markerRead);
			else
				markers[key].setIcon(LTmap.markerUnread);
	});

	var checkAddMarker = function(tweet) {
		if (tweet.coordinates && tweet.coordinates.type
				&& tweet.coordinates.type == 'Point'
				&& tweet.coordinates.coordinates
				&& tweet.coordinates.coordinates[1]
				&& tweet.coordinates.coordinates[0]) {
			if (circle.contains(new google.maps.LatLng(
					tweet.coordinates.coordinates[1],
					tweet.coordinates.coordinates[0]))
					&& new Date(tweet.created_at) > new Date(new Date()
							- new TimeFrame().getTime())) {
				return true;
			} else
				return false;
		} else
			return false;
	};

	var removeMessage = function(id_str) {
		// Never remove open markers or markers which should not be removed
		if (onMap[id_str].marker.isOpen || checkAddMarker(onMap[id_str].tweet))
			return;
		onMap[id_str].marker.setMap(null);
		delete onMap[id_str];
	};

	this.cleanMarkers = function() {
		for ( var id_str in onMap)
			removeMessage(id_str);
	};

	this.addMessage = function(tweet) {
		// Never add markers which should not be added or markers which already
		// exist
		if (!checkAddMarker(tweet) || onMap.hasOwnProperty(tweet.id_str))
			return;

		var isRead = new MessageReadStorage().messageRead(tweet.id_str);
		var icon = isRead ? LTmap.markerRead : LTmap.markerUnread;
		var marker = new google.maps.Marker({
			position : new google.maps.LatLng(tweet.coordinates.coordinates[1],
					tweet.coordinates.coordinates[0]),
			map : map,
			title : 'Zum Öffnen klicken!',
			icon : icon,
			shape : LTmap.markerShape,
			zIndex : 1
		});
		oms.addMarker(marker);
		marker.isRead = isRead;

		marker.message = new google.maps.InfoWindow({
			content : $('<div />').addClass('tweet').html(
					new TweetParser(tweet).parse()).get(0),
			maxWidth : 150
		});

		marker.isOpen = false;

		marker.closeclick = function() {
			openedMarker = null;
			marker.isOpen = false;
			// Remove from map when under certain conditions
			removeMessage(tweet.id_str);
			marker.message.close();
		};

		marker.openclick = function() {
			if (openedMarker != null)
				openedMarker.closeclick();
			marker.isOpen = true;
			openedMarker = marker;
			marker.message.open(map, marker);
			marker.setIcon(LTmap.markerRead);
			new MessageReadStorage().addMessage(tweet);
			marker.isRead = true;
		};

		google.maps.event.addListener(marker.message, 'closeclick',
				marker.closeclick);

		onMap[tweet.id_str] = {
			marker : marker,
			tweet : tweet
		};

		if (!marker.isRead && openedMarker == null)
			marker.openclick();
	};

	this.setLocation = function(lat, lng) {
		center = new google.maps.LatLng(lat, lng);
		if (firstSetLocation) {
			firstSetLocation = false;
			new Overlay().show('loadmap');
			map.setCenter(center);
			circle = new google.maps.Circle({
				strokeColor : '#00f',
				strokeOpacity : 0.8,
				strokeWeight : 4,
				fillColor : '#00f',
				fillOpacity : 0,
				map : map,
				center : center,
				radius : 2000,
				clickable : false
			});
			circle.dot = new google.maps.Circle({
				strokeColor : '#f00',
				strokeOpacity : 0.8,
				strokeWeight : 20,
				fillColor : '#f00',
				fillOpacity : 0,
				map : map,
				center : center,
				radius : 1,
				clickable : false
			});
			map.fitBounds(circle.getBounds());
			map.setZoom(map.getZoom() + 1);
			google.maps.event.addListenerOnce(map, 'idle', function() {
				google.maps.event.addListenerOnce(map, 'tilesloaded',
						function() {
							new Overlay().hide();
						});
			});
		} else {
			circle.setCenter(center);
			circle.dot.setCenter(center);
		}
		this.update();
	};

	this.update = function() {
		this.cleanMarkers();
		// TODO: Server communication
		setTimeout(sampleMarkers, 100);
	};

	this.getGoogleMap = function() {
		return map;
	};

	this.getGoogleCircle = function() {
		return circle;
	};

	setInterval(this.cleanMarkers, 1000);

}
<commit_msg>LTmap communicates to Websocket<commit_after>function LTmap() {

	// Singleton
	if (typeof LTmap.instance === 'object') {
		return LTmap.instance;
	}
	LTmap.instance = this;

	google.maps.Circle.prototype.contains = function(latLng) {
		return this.getBounds().contains(latLng)
				&& google.maps.geometry.spherical.computeDistanceBetween(this
						.getCenter(), latLng) <= this.getRadius();
	};

	// Defaults
	LTmap.elementId = 'map';
	LTmap.lat = '53.147086';
	LTmap.lng = '8.180434';
	LTmap.zoom = 4;
	LTmap.markerUnread = {
		url : 'TwitterBlue.png',
		size : new google.maps.Size(43, 36),
		origin : new google.maps.Point(0, 0),
		anchor : new google.maps.Point(21, 18)
	};
	LTmap.markerRead = {
		url : 'TwitterDark.png',
		size : new google.maps.Size(43, 36),
		origin : new google.maps.Point(0, 0),
		anchor : new google.maps.Point(21, 18)
	};
	LTmap.markerSpiderfiedUnread = {
		url : 'TwitterRedBlue.png',
		size : new google.maps.Size(43, 36),
		origin : new google.maps.Point(0, 0),
		anchor : new google.maps.Point(21, 18)
	};
	LTmap.markerSpiderfiedRead = {
		url : 'TwitterRedDark.png',
		size : new google.maps.Size(43, 36),
		origin : new google.maps.Point(0, 0),
		anchor : new google.maps.Point(21, 18)
	};
	LTmap.markerShape = {
		coords : [ 0, 33, 7, 36, 22, 36, 31, 31, 38, 22, 39, 19, 39, 12, 43, 8,
				43, 0, 24, 0, 22, 1, 19, 5, 18, 8, 17, 9, 15, 7, 13, 7, 5, 1,
				3, 1, 1, 4, 1, 17, 4, 21, 4, 24, 7, 26, 5, 28, 1, 28, 0, 29 ],
		type : 'poly'
	};

	var firstSetLocation = true;
	var center = new google.maps.LatLng(LTmap.lat, LTmap.lng);
	var circle = null;
	var openedMarker = null;
	var onMap = {};

	// Initialize map with defaults
	var map = new google.maps.Map(document.getElementById(LTmap.elementId), {
		zoom : LTmap.zoom,
		center : new google.maps.LatLng(LTmap.lat, LTmap.lng),
		mapTypeId : google.maps.MapTypeId.HYBRID,
		minZoom : 4,
		maxZoom : 18,
		zoomControlOptions : {
			position : google.maps.ControlPosition.RIGHT_TOP,
		},
		streetViewControlOptions : {
			position : google.maps.ControlPosition.RIGHT_TOP,
		},
		panControlOptions : {
			position : google.maps.ControlPosition.RIGHT_TOP,
		},
	});
	var oms = new OverlappingMarkerSpiderfier(map, {
		nearbyDistance : 40,
		circleFootSeparation : 40,
		spiralFootSeparation : 35,
		spiralLengthFactor : 7,
		spiralLengthStart : 12
	});
	oms.addListener('click', function(marker, event) {
		marker.openclick();
	});
	oms.addListener('spiderfy', function(markers) {
		for(var key in markers)
			if(markers[key].isRead)
				markers[key].setIcon(LTmap.markerSpiderfiedRead);
			else
				markers[key].setIcon(LTmap.markerSpiderfiedUnread);
	});
	oms.addListener('unspiderfy', function(markers) {
		for(var key in markers)
			if(markers[key].isRead)
				markers[key].setIcon(LTmap.markerRead);
			else
				markers[key].setIcon(LTmap.markerUnread);
	});

	var checkAddMarker = function(tweet) {
		if (tweet.coordinates && tweet.coordinates.type
				&& tweet.coordinates.type == 'Point'
				&& tweet.coordinates.coordinates
				&& tweet.coordinates.coordinates[1]
				&& tweet.coordinates.coordinates[0]) {
			if (circle.contains(new google.maps.LatLng(
					tweet.coordinates.coordinates[1],
					tweet.coordinates.coordinates[0]))
					&& new Date(tweet.created_at) > new Date(new Date()
							- new TimeFrame().getTime())) {
				return true;
			} else
				return false;
		} else
			return false;
	};

	var removeMessage = function(id_str) {
		// Never remove open markers or markers which should not be removed
		if (onMap[id_str].marker.isOpen || checkAddMarker(onMap[id_str].tweet))
			return;
		onMap[id_str].marker.setMap(null);
		delete onMap[id_str];
	};

	this.cleanMarkers = function() {
		for ( var id_str in onMap)
			removeMessage(id_str);
	};

	this.addMessage = function(tweet) {
		// Never add markers which should not be added or markers which already
		// exist
		if (!checkAddMarker(tweet) || onMap.hasOwnProperty(tweet.id_str))
			return;

		var isRead = new MessageReadStorage().messageRead(tweet.id_str);
		var icon = isRead ? LTmap.markerRead : LTmap.markerUnread;
		var marker = new google.maps.Marker({
			position : new google.maps.LatLng(tweet.coordinates.coordinates[1],
					tweet.coordinates.coordinates[0]),
			map : map,
			title : 'Zum Öffnen klicken!',
			icon : icon,
			shape : LTmap.markerShape,
			zIndex : 1
		});
		oms.addMarker(marker);
		marker.isRead = isRead;

		marker.message = new google.maps.InfoWindow({
			content : $('<div />').addClass('tweet').html(
					new TweetParser(tweet).parse()).get(0),
			maxWidth : 150
		});

		marker.isOpen = false;

		marker.closeclick = function() {
			openedMarker = null;
			marker.isOpen = false;
			// Remove from map when under certain conditions
			removeMessage(tweet.id_str);
			marker.message.close();
		};

		marker.openclick = function() {
			if (openedMarker != null)
				openedMarker.closeclick();
			marker.isOpen = true;
			openedMarker = marker;
			marker.message.open(map, marker);
			marker.setIcon(LTmap.markerRead);
			new MessageReadStorage().addMessage(tweet);
			marker.isRead = true;
		};

		google.maps.event.addListener(marker.message, 'closeclick',
				marker.closeclick);

		onMap[tweet.id_str] = {
			marker : marker,
			tweet : tweet
		};

		if (!marker.isRead && openedMarker == null)
			marker.openclick();
	};

	this.setLocation = function(lat, lng) {
		center = new google.maps.LatLng(lat, lng);
		if (firstSetLocation) {
			firstSetLocation = false;
			new Overlay().show('loadmap');
			map.setCenter(center);
			circle = new google.maps.Circle({
				strokeColor : '#00f',
				strokeOpacity : 0.8,
				strokeWeight : 4,
				fillColor : '#00f',
				fillOpacity : 0,
				map : map,
				center : center,
				radius : 2000,
				clickable : false
			});
			circle.dot = new google.maps.Circle({
				strokeColor : '#f00',
				strokeOpacity : 0.8,
				strokeWeight : 20,
				fillColor : '#f00',
				fillOpacity : 0,
				map : map,
				center : center,
				radius : 1,
				clickable : false
			});
			map.fitBounds(circle.getBounds());
			map.setZoom(map.getZoom() + 1);
			google.maps.event.addListenerOnce(map, 'idle', function() {
				google.maps.event.addListenerOnce(map, 'tilesloaded',
						function() {
							new Overlay().hide();
						});
			});
		} else {
			circle.setCenter(center);
			circle.dot.setCenter(center);
		}
		this.update();
	};

	this.update = function() {
		this.cleanMarkers();
		var bounds = circle.getBounds();
		var northEast = bounds.getNorthEast();
		var southWest = bounds.getSouthWest();
		var boundaries = {
			north : northEast.lat(),
			east : northEast.lng(),
			south : southWest.lat(),
			west : southWest.lng()
		};
		new Websocket().send(boundaries);
	};

	this.getGoogleMap = function() {
		return map;
	};

	this.getGoogleCircle = function() {
		return circle;
	};

	setInterval(this.cleanMarkers, 1000);

}
<|endoftext|>


<commit_before>const express = require('express')
const path = require('path')
const port = process.env.PORT || 8000
const app = express()
var requestProxy = require('express-request-proxy');

app.use(require('connect-livereload')())

app.use(express.static(__dirname + '/public'))

app.all('/services/*', requestProxy({
  url: "http://services:8005/*"
}))

app.get('*', function (request, response) {
  response.sendFile(path.resolve(__dirname, 'public', 'index.html'))
})

app.listen(port)
console.log("server started on port " + port)

<commit_msg>Patron-client: Use only ' in server.js<commit_after>const express = require('express')
const path = require('path')
const port = process.env.PORT || 8000
const app = express()
var requestProxy = require('express-request-proxy');

app.use(require('connect-livereload')())

app.use(express.static(__dirname + '/public'))

app.all('/services/*', requestProxy({
  url: 'http://services:8005/*'
}))

app.get('*', function (request, response) {
  response.sendFile(path.resolve(__dirname, 'public', 'index.html'))
})

app.listen(port)
console.log('Server started on port ' + port)

<|endoftext|>