<commit_before>/**
 * Wheel, copyright (c) 2020 - present by Arno van der Vegt
 * Distributed under an MIT license: https://arnovandervegt.github.io/wheel/license.txt
**/
const sensorModuleConstants = require('../../vm/modules/sensorModuleConstants');
const motorModuleConstants  = require('../../vm/modules/motorModuleConstants');
const spikeModuleConstants  = require('../../vm/modules/spikeModuleConstants');
const BasicDevice           = require('../BasicDevice').BasicDevice;
const CommandQueue          = require('./CommandQueue').CommandQueue;

const PORT_TO_INDEX         = {A: 0, B: 1, C: 2, D: 3, E: 4, F: 5};
const INDEX_TO_PORT         = ['A', 'B', 'C', 'D', 'E', 'F'];

exports.Spike = class extends BasicDevice {
    constructor(opts) {
        opts.layerCount = spikeModuleConstants.SPIKE_LAYER_COUNT;
        super(opts);
        this._serialPortConstructor = opts.serialPortConstructor;
        this._layers                = [];
        for (let i = 0; i < spikeModuleConstants.SPIKE_LAYER_COUNT; i++) {
            this._layers.push(this.initLayer());
        }
    }

    initLayer() {
        let result = {
                connected:       false,
                connecting:      false,
                commandQueue:    null,
                deviceName:      '',
                gyro:            {x: 0, y: 0, z: 0},
                accel:           {x: 0, y: 0, z: 0},
                pos:             {x: 0, y: 0, z: 0},
                ports:           [],
                button:          0
            };
        for (let i = 0; i < 6; i++) {
            result.ports.push({
                value:        0,
                reset:        0,
                assigned:     0,
                mode:         0,
                startDegrees: 0,
                endDegrees:   null,
                threshold:    45
            });
        }
        return result;
    }

    getLayerPort(layer, port) {
        if (this._layers[layer] && this._layers[layer].ports[port]) {
            return this._layers[layer].ports[port];
        }
        return {};
    }

    getPort() {
        return this._port;
    }

    getConnected(deviceName) {
        let layers = this._layers;
        for (let i = 0; i < Math.min(this._activeLayerCount, layers.length); i++) {
            let layer = layers[i];
            if (layer.connected && ((deviceName === undefined) || (layer.deviceName === deviceName))) {
                return true;
            }
        }
        return false;
    }

    getConnecting(deviceName) {
        let layers = this._layers;
        for (let i = 0; i < Math.min(this._activeLayerCount, layers.length); i++) {
            let layer = layers[i];
            if (layer.deviceName === deviceName) {
                return layer.connecting;
            }
        }
        return false;
    }

    getMotorPosition(layer, port) {
        return this._port[port] || 0;
    }

    connect(deviceName, callback) {
        let layers = this._layers;
        let found  = false;
        for (let i = 0; i < Math.min(this._activeLayerCount, layers.length); i++) {
            if (layers[i].commandQueue === null) {
                found = i;
                break;
            }
        }
        if (found === false) {
            return -1;
        }
        let layer = layers[found];
        layer.connecting   = true;
        layer.deviceName   = deviceName;
        layer.commandQueue = new CommandQueue({
            spike:                 this,
            serialPortConstructor: this._serialPortConstructor,
            deviceName:            deviceName,
            layer:                 layer
        });
        return found;
    }

    playtone(frequency, duration, volume, callback) {
        let tone = frequency;
        const frequencies     = [262, 294, 330, 349, 392, 440, 494, 523, 587, 659, 277, 311, 370, 415, 466, 554, 622];
        const frequencyToTone = [ 60,  62,  64,  65,  67,  69,  71,  72,  74,  76,  61,  63,  66,  68,  70,  73,  75];
        if (frequencies.indexOf(frequency) !== -1) {
            tone = frequencyToTone[frequencies.indexOf(frequency)];
        }
        this._layers.forEach((layer) => {
            if (!layer.commandQueue) {
                return;
            }
            if (layer.toneTimeout) {
                clearTimeout(layer.toneTimeout);
            }
            layer.toneTimeout = setTimeout(
                () => {
                    layer.commandQueue.addToCommandQueue({
                        m: commands.COMMAND_SOUND_OFF
                    });
                    layer.toneTimeout = null;
                },
                duration
            );
            layer.commandQueue.addToCommandQueue({
                m: commands.COMMAND_SOUND_BEEP,
                p: {
                    volume: volume,
                    note:   tone
                }
            });
        });
    }

    motorReset(layer, id) {
        layer = this._layers[layer];
        if (!layer || !layer.ports[id]) {
            return;
        }
        let motor = layer.ports[id];
        motor.reset = motor.value;
    }

    motorDegrees(layer, motor, speed, degrees, brake, callback) {
        layer = this._layers[layer];
        if (!layer || !layer.ports[motor]) {
            return;
        }
        let port = layer.ports[motor];
        port.startDegrees = port.value;
        port.endDegrees   = port.value + degrees;
        port.speed        = speed;
        speed             = Math.abs(speed);
        layer.commandQueue.addToCommandQueue({
            m: constants.COMMAND_RUN_FOR_DEGREES,
            p: {
                port:    INDEX_TO_PORT[motor],
                degrees: Math.abs(degrees),
                speed:   (degrees < 0) ? -speed : speed,
                stall:   false,
                stop:    true
            }
        });
        callback && callback();
    }

    motorOn(layer, id, speed, brake, callback) {
        layer = this._layers[layer];
        if (!layer || !layer.commandQueue || !(id in INDEX_TO_PORT)) {
            return;
        }
        layer.ports[id].endDegrees = null;
        layer.commandQueue.addToCommandQueue({
            m: constants.COMMAND_MOTOR_START,
            p: {
                port:  INDEX_TO_PORT[id],
                speed: speed,
                stall: true
            }
        });
        callback && callback();
    }

    motorStop(layer, id, brake, callback) {
        this.motorOn(layer, id, 0, brake, callback);
    }

    motorThreshold(layer, motor, threshold) {
        if (!this.getHubConnected(layer)) {
            return;
        }
        this.getLayerPort(layer, motor).threshold = threshold;
    }

    module(module, command, data) {
        if (this._modules[module]) {
            this._modules[module].run(command, data);
        }
    }

    getState() {
        let layers = this._layers;
        let result = {layers: []};
        for (let i = 0; i < Math.min(this._activeLayerCount, layers.length); i++) {
            result.layers.push(this.cloneLayer(layers[i]));
        }
        return result;
    }

    setMode(layer, port, mode) {
        this.getLayerPort(layer, port).mode = parseInt(mode, 10);
    }

    cloneLayer(layer) {
        let result = {
                deviceName: layer.deviceName,
                connecting: layer.connecting,
                connected:  layer.connected,
                button:     layer.button,
                gyro:       layer.gyro,
                accel:      layer.accel,
                pos:        layer.pos,
                ports:      []
            };
        for (let i = 0; i < 6; i++) {
            let port = layer.ports[i];
            result.ports.push({
                value:    port.value - (port.isMotor ? port.reset : 0),
                degrees:  port.value,
                assigned: port.assigned,
                ready:    (port.endDegrees === null) ? true : (Math.abs(port.endDegrees - port.value) <= port.threshold)
            });
        }
        return result;
    }

    setLed(layer, color) {
        layer = this._layers[layer];
        if (!layer) {
            return;
        }
        layer.commandQueue.addToCommandQueue({
            m: constants.COMMAND_BUTTON_LIGHTS,
            p: {
                color: color
            }
        });
    }

    matrixClearLeds(layer) {
        layer = this._layers[layer];
        if (!layer) {
            return;
        }
        layer.commandQueue.addToCommandQueue({
            m: constants.COMMAND_DISPLAY_CLEAR
        });
    }

    matrixSetLed(layer, x, y, brightness) {
        layer = this._layers[layer];
        if (!layer) {
            return;
        }
        layer.commandQueue.addToCommandQueue({
            m: constants.COMMAND_DISPLAY_SET_PIXEL,
            p: {
                x:          x,
                y:          y,
                brightness: brightness
            }
        });
    }

    matrixSetText(layer, text) {
        layer = this._layers[layer];
        if (!layer) {
            return;
        }
        layer.commandQueue.addToCommandQueue({
            m: constants.COMMAND_DISPLAY_TEXT,
            p: {
                text: text
            }
        });
    }

    getPortsPerLayer() {
        return 6;
    }
};
<commit_msg>Require constants.<commit_after>/**
 * Wheel, copyright (c) 2020 - present by Arno van der Vegt
 * Distributed under an MIT license: https://arnovandervegt.github.io/wheel/license.txt
**/
const sensorModuleConstants = require('../../vm/modules/sensorModuleConstants');
const motorModuleConstants  = require('../../vm/modules/motorModuleConstants');
const spikeModuleConstants  = require('../../vm/modules/spikeModuleConstants');
const BasicDevice           = require('../BasicDevice').BasicDevice;
const constants             = require('./constants');
const CommandQueue          = require('./CommandQueue').CommandQueue;

const PORT_TO_INDEX         = {A: 0, B: 1, C: 2, D: 3, E: 4, F: 5};
const INDEX_TO_PORT         = ['A', 'B', 'C', 'D', 'E', 'F'];

exports.Spike = class extends BasicDevice {
    constructor(opts) {
        opts.layerCount = spikeModuleConstants.SPIKE_LAYER_COUNT;
        super(opts);
        this._serialPortConstructor = opts.serialPortConstructor;
        this._layers                = [];
        for (let i = 0; i < spikeModuleConstants.SPIKE_LAYER_COUNT; i++) {
            this._layers.push(this.initLayer());
        }
    }

    initLayer() {
        let result = {
                connected:       false,
                connecting:      false,
                commandQueue:    null,
                deviceName:      '',
                gyro:            {x: 0, y: 0, z: 0},
                accel:           {x: 0, y: 0, z: 0},
                pos:             {x: 0, y: 0, z: 0},
                ports:           [],
                button:          0
            };
        for (let i = 0; i < 6; i++) {
            result.ports.push({
                value:        0,
                reset:        0,
                assigned:     0,
                mode:         0,
                startDegrees: 0,
                endDegrees:   null,
                threshold:    45
            });
        }
        return result;
    }

    getLayerPort(layer, port) {
        if (this._layers[layer] && this._layers[layer].ports[port]) {
            return this._layers[layer].ports[port];
        }
        return {};
    }

    getPort() {
        return this._port;
    }

    getConnected(deviceName) {
        let layers = this._layers;
        for (let i = 0; i < Math.min(this._activeLayerCount, layers.length); i++) {
            let layer = layers[i];
            if (layer.connected && ((deviceName === undefined) || (layer.deviceName === deviceName))) {
                return true;
            }
        }
        return false;
    }

    getConnecting(deviceName) {
        let layers = this._layers;
        for (let i = 0; i < Math.min(this._activeLayerCount, layers.length); i++) {
            let layer = layers[i];
            if (layer.deviceName === deviceName) {
                return layer.connecting;
            }
        }
        return false;
    }

    getMotorPosition(layer, port) {
        return this._port[port] || 0;
    }

    connect(deviceName, callback) {
        let layers = this._layers;
        let found  = false;
        for (let i = 0; i < Math.min(this._activeLayerCount, layers.length); i++) {
            if (layers[i].commandQueue === null) {
                found = i;
                break;
            }
        }
        if (found === false) {
            return -1;
        }
        let layer = layers[found];
        layer.connecting   = true;
        layer.deviceName   = deviceName;
        layer.commandQueue = new CommandQueue({
            spike:                 this,
            serialPortConstructor: this._serialPortConstructor,
            deviceName:            deviceName,
            layer:                 layer
        });
        return found;
    }

    playtone(frequency, duration, volume, callback) {
        let tone = frequency;
        const frequencies     = [262, 294, 330, 349, 392, 440, 494, 523, 587, 659, 277, 311, 370, 415, 466, 554, 622];
        const frequencyToTone = [ 60,  62,  64,  65,  67,  69,  71,  72,  74,  76,  61,  63,  66,  68,  70,  73,  75];
        if (frequencies.indexOf(frequency) !== -1) {
            tone = frequencyToTone[frequencies.indexOf(frequency)];
        }
        this._layers.forEach((layer) => {
            if (!layer.commandQueue) {
                return;
            }
            if (layer.toneTimeout) {
                clearTimeout(layer.toneTimeout);
            }
            layer.toneTimeout = setTimeout(
                () => {
                    layer.commandQueue.addToCommandQueue({
                        m: commands.COMMAND_SOUND_OFF
                    });
                    layer.toneTimeout = null;
                },
                duration
            );
            layer.commandQueue.addToCommandQueue({
                m: commands.COMMAND_SOUND_BEEP,
                p: {
                    volume: volume,
                    note:   tone
                }
            });
        });
    }

    motorReset(layer, id) {
        layer = this._layers[layer];
        if (!layer || !layer.ports[id]) {
            return;
        }
        let motor = layer.ports[id];
        motor.reset = motor.value;
    }

    motorDegrees(layer, motor, speed, degrees, brake, callback) {
        layer = this._layers[layer];
        if (!layer || !layer.ports[motor]) {
            return;
        }
        let port = layer.ports[motor];
        port.startDegrees = port.value;
        port.endDegrees   = port.value + degrees;
        port.speed        = speed;
        speed             = Math.abs(speed);
        layer.commandQueue.addToCommandQueue({
            m: constants.COMMAND_RUN_FOR_DEGREES,
            p: {
                port:    INDEX_TO_PORT[motor],
                degrees: Math.abs(degrees),
                speed:   (degrees < 0) ? -speed : speed,
                stall:   false,
                stop:    true
            }
        });
        callback && callback();
    }

    motorOn(layer, id, speed, brake, callback) {
        layer = this._layers[layer];
        if (!layer || !layer.commandQueue || !(id in INDEX_TO_PORT)) {
            return;
        }
        layer.ports[id].endDegrees = null;
        layer.commandQueue.addToCommandQueue({
            m: constants.COMMAND_MOTOR_START,
            p: {
                port:  INDEX_TO_PORT[id],
                speed: speed,
                stall: true
            }
        });
        callback && callback();
    }

    motorStop(layer, id, brake, callback) {
        this.motorOn(layer, id, 0, brake, callback);
    }

    motorThreshold(layer, motor, threshold) {
        if (!this.getHubConnected(layer)) {
            return;
        }
        this.getLayerPort(layer, motor).threshold = threshold;
    }

    module(module, command, data) {
        if (this._modules[module]) {
            this._modules[module].run(command, data);
        }
    }

    getState() {
        let layers = this._layers;
        let result = {layers: []};
        for (let i = 0; i < Math.min(this._activeLayerCount, layers.length); i++) {
            result.layers.push(this.cloneLayer(layers[i]));
        }
        return result;
    }

    setMode(layer, port, mode) {
        this.getLayerPort(layer, port).mode = parseInt(mode, 10);
    }

    cloneLayer(layer) {
        let result = {
                deviceName: layer.deviceName,
                connecting: layer.connecting,
                connected:  layer.connected,
                button:     layer.button,
                gyro:       layer.gyro,
                accel:      layer.accel,
                pos:        layer.pos,
                ports:      []
            };
        for (let i = 0; i < 6; i++) {
            let port = layer.ports[i];
            result.ports.push({
                value:    port.value - (port.isMotor ? port.reset : 0),
                degrees:  port.value,
                assigned: port.assigned,
                ready:    (port.endDegrees === null) ? true : (Math.abs(port.endDegrees - port.value) <= port.threshold)
            });
        }
        return result;
    }

    setLed(layer, color) {
        layer = this._layers[layer];
        if (!layer) {
            return;
        }
        layer.commandQueue.addToCommandQueue({
            m: constants.COMMAND_BUTTON_LIGHTS,
            p: {
                color: color
            }
        });
    }

    matrixClearLeds(layer) {
        layer = this._layers[layer];
        if (!layer) {
            return;
        }
        layer.commandQueue.addToCommandQueue({
            m: constants.COMMAND_DISPLAY_CLEAR
        });
    }

    matrixSetLed(layer, x, y, brightness) {
        layer = this._layers[layer];
        if (!layer) {
            return;
        }
        layer.commandQueue.addToCommandQueue({
            m: constants.COMMAND_DISPLAY_SET_PIXEL,
            p: {
                x:          x,
                y:          y,
                brightness: brightness
            }
        });
    }

    matrixSetText(layer, text) {
        layer = this._layers[layer];
        if (!layer) {
            return;
        }
        layer.commandQueue.addToCommandQueue({
            m: constants.COMMAND_DISPLAY_TEXT,
            p: {
                text: text
            }
        });
    }

    getPortsPerLayer() {
        return 6;
    }
};
<|endoftext|>


<commit_before>$("#homepageTemplate").on('complete.cycle',function(state,$ele,infoObj){
	dump(" -> executed homepage.complete");
	$('.productSlideshow',$ele).cycle();
	});

//unbind this from window anytime a category page is left.
//NOTE! if infinite prodlist is used on other pages, remove run this on that template as well.
$("#categoryTemplate").on('complete.infinitescroll',function(state,$ele,infoObj){
	$(window).off('scroll.infiniteScroll');
	});

$("#productTemplate, #productTemplateQuickView").on('complete.dynimaging',function(state,$ele,infoObj){
	handleSrcSetUpdate($ele);
	$('.prodDetailImagesContainer',$ele).imagegallery({
		show: 'fade',
		hide: 'fade',
		fullscreen: false,
		slideshow: false
		});
	});

$("#productTemplateQuickView").on('complete.dynimaging',function(state,$ele,infoObj){
	handleSrcSetUpdate($ele);
	$('.prodDetailImagesContainer.dynimaging',$ele).imagegallery({
		show: 'fade',
		hide: 'fade',
		fullscreen: false,
		slideshow: false
		});
	});

/*
if(typeof window.matchMedia != "undefined" || typeof window.msMatchMedia != "undefined")    {}
else{
	dump(" -> media queries are NOT supported. use polyfill ");
	myApp.rq.push(['script',0,myApp.vars.baseURL+'css3-mediaqueries.js']); //in zero pass in case product page is first page.
    }
*/

myApp.rq.push(['script',0,(document.location.protocol == 'file:') ? myApp.vars.testURL+'jsonapi/config.js' : myApp.vars.baseURL+'jsonapi/config.js',function(){
//in some cases, such as the zoovy UI, zglobals may not be defined. If that's the case, certain vars, such as jqurl, must be passed in via P in initialize:
//	myApp.u.dump(" ->>>>>>>>>>>>>>>>>>>>>>>>>>>>> zGlobals is an object");
	window.myApp.vars.username = zGlobals.appSettings.username.toLowerCase(); //used w/ image URL's.
//need to make sure the secureURL ends in a / always. doesn't seem to always come in that way via zGlobals
	window.myApp.vars.secureURL = zGlobals.appSettings.https_app_url;
	window.myApp.vars.domain = zGlobals.appSettings.sdomain; //passed in ajax requests.
	window.myApp.vars.jqurl = (document.location.protocol === 'file:') ? myApp.vars.testURL+'jsonapi/' : '/jsonapi/';
	}]); //The config.js is dynamically generated.

myApp.rq.push(['extension',0,'order_create','extensions/checkout/extension.js']);
myApp.rq.push(['extension',0,'cco','extensions/cart_checkout_order.js']);
myApp.rq.push(['extension',0,'greenspeed','app-greenspeed.js']);

myApp.rq.push(['extension',0,'store_prodlist','extensions/store_prodlist.js']);
myApp.rq.push(['extension',0,'store_navcats','extensions/store_navcats.js']);
myApp.rq.push(['extension',0,'prodlist_infinite','extensions/prodlist_infinite.js']);
myApp.rq.push(['extension',0,'store_search','extensions/store_search.js']);
myApp.rq.push(['extension',0,'store_product','extensions/store_product.js']);
myApp.rq.push(['extension',0,'store_crm','extensions/store_crm.js']);
myApp.rq.push(['extension',0,'quickstart','app-quickstart.js','startMyProgram']);
myApp.rq.push(['extension',0,'cart_message','extensions/cart_message/extension.js']);
myApp.rq.push(['extension',0,'store_routing','extensions/store_routing.js']);

myApp.rq.push(['script',0,myApp.vars.baseURL+'resources/jsonpath.0.8.0.js']); //used pretty early in process..

//once peg is loaded, need to retrieve the grammar file. Order is important there. This will validate the file too.
myApp.u.loadScript(myApp.vars.baseURL+'resources/peg-0.8.0.js',function(){
	myApp.model.getGrammar(myApp.vars.baseURL+"resources/pegjs-grammar-20140203.pegjs");
	}); // ### TODO -> callback on RQ.push wasn't getting executed. investigate.

myApp.rq.push(['script',0,myApp.vars.baseURL+'resources/tlc.js']); //in zero pass in case product page is first page.
myApp.rq.push(['script',0,myApp.vars.baseURL+'resources/jquery.showloading-v1.0.jt.js']); //used pretty early in process..
myApp.rq.push(['script',0,myApp.vars.baseURL+'resources/jquery.ui.anyplugins.js']); //in zero pass in case product page is first page.
myApp.rq.push(['css',1,myApp.vars.baseURL+'resources/anyplugins.css']);

myApp.rq.push(['script',0,myApp.vars.baseURL+'jquery.cycle2.min.js']); //used pretty early in process..
myApp.rq.push(['script',0,myApp.vars.baseURL+'jquery.cycle2.swipe.min.js']); //in zero pass in case product page is first page

//used for image enlargement in product layout
myApp.rq.push(['script',0,myApp.vars.baseURL+'resources/load-image.min.js']); //in zero pass in case product page is first page.
myApp.rq.push(['script',0,myApp.vars.baseURL+'resources/jquery.image-gallery.jt.js']); //in zero pass in case product page is first page.

//myApp.rq.push(['script',0,myApp.vars.baseURL+'srcset-polyfill-1.1.1-jt.js']); //in zero pass in case product page is first page.

//Cart Messaging Responses.

myApp.cmr.push(['chat.join',function(message){
	var $ui = myApp.ext.quickstart.a.showBuyerCMUI();
	$("[data-app-role='messageInput']",$ui).show();
	$("[data-app-role='messageHistory']",$ui).append("
"+message.FROM+" has joined the chat.<\/p>");
	$('.show4ActiveChat',$ui).show();
	$('.hide4ActiveChat',$ui).hide();
	}]);

myApp.cmr.push(['goto',function(message,$context){
	var $history = $("[data-app-role='messageHistory']",$context);
	$P = $("
")
		.addClass('chat_post')
		.append(""+message.FROM+"<\/span> has sent over a "+(message.vars.pageType || "")+" link for you within this store. Click here<\/span> to view.")
		.on('click',function(){
			showContent(myApp.ext.quickstart.u.whatAmIFor(message.vars),message.vars);
			});
	$history.append($P);
	$history.parent().scrollTop($history.height());
	}]);

//gets executed from app-admin.html as part of controller init process.
//progress is an object that will get updated as the resources load.
/*
'passZeroResourcesLength' : [INT],
'passZeroResourcesLoaded' : [INT],
'passZeroTimeout' : null //the timeout instance running within loadResources that updates this object. it will run indef unless clearTimeout run here OR all resources are loaded.

*/
myApp.u.showProgress = function(progress)	{
	function showProgress(attempt)	{
		if(progress.passZeroResourcesLength == progress.passZeroResourcesLoaded)	{
			//All pass zero resources have loaded.
			//the app will handle hiding the loading screen.
			}
		else if(attempt > 150)	{
			//hhhhmmm.... something must have gone wrong.
			clearTimeout(progress.passZeroTimeout); //end the resource loading timeout.
			}
		else	{
			var percentPerInclude = (100 / progress.passZeroResourcesLength);
			var percentComplete = Math.round(progress.passZeroResourcesLength * percentPerInclude); //used to sum how many includes have successfully loaded.
//			dump(" -> percentPerInclude: "+percentPerInclude+" and percentComplete: "+percentComplete);
			$('#appPreViewProgressBar').val(percentComplete);
			$('#appPreViewProgressText').empty().append(percentComplete+"% Complete");
			attempt++;
			setTimeout(function(){showProgress(attempt);},250);
			}
		}
	showProgress(0)
	}

//Any code that needs to be executed after the app init has occured can go here.
//will pass in the page info object. (pageType, templateID, pid/navcat/show and more)
myApp.u.appInitComplete = function(P)	{
	myApp.u.dump("Executing myAppIsLoaded code...");

	myApp.ext.order_create.checkoutCompletes.push(function(vars,$checkout){
//append this to
		$("[data-app-role='thirdPartyContainer']",$checkout).append("
What next?

");
		$('.ocmTwitterComment',$checkout).click(function(){
			window.open('http://twitter.com/home?status='+cartContentsAsLinks,'twitter');
			_gaq.push(['_trackEvent','Checkout','User Event','Tweeted about order']);
			});
		//the fb code only works if an appID is set, so don't show banner if not present.
		if(myApp.u.thisNestedExists("zGlobals.thirdParty.facebook.appId") && typeof FB == 'object')	{
			$('.ocmFacebookComment',$checkout).click(function(){
				myApp.ext.quickstart.thirdParty.fb.postToWall(cartContentsAsLinks);
				_gaq.push(['_trackEvent','Checkout','User Event','FB message about order']);
				});
			}
		else	{$('.ocmFacebookComment').hide()}
		});
	}

//this will trigger the content to load on app init. so if you push refresh, you don't get a blank page.
//it'll also handle the old 'meta' uri params.
myApp.router.appendInit({
	'type':'function',
	'route': function(v){
		return {'init':true} //returning anything but false triggers a match.
		},
	'callback':function(f,g){
		dump(" -> triggered callback for appendInit");
		g = g || {};
		if(document.location.hash)	{
			myApp.router.handleHashChange();
			}
		else	{
			//IE8 didn't like the shortcut to showContent here.
			myApp.ext.quickstart.a.showContent('homepage');
			}
		if(g.uriParams && g.uriParams.meta)	{
			myApp.ext.cco.calls.cartSet.init({'want/refer':infoObj.uriParams.meta,'cartID':_app.model.fetchCartID()},{},'passive');
			}
		if(g.uriParams && g.uriParams.meta_src)	{
			myApp.ext.cco.calls.cartSet.init({'want/refer_src':infoObj.uriParams.meta_src,'cartID':_app.model.fetchCartID()},{},'passive');
			}
		}
	});

<commit_msg>new page transition<commit_after>$("#homepageTemplate").on('complete.cycle',function(state,$ele,infoObj){
	dump(" -> executed homepage.complete");
	$('.productSlideshow',$ele).cycle();
	});

//unbind this from window anytime a category page is left.
//NOTE! if infinite prodlist is used on other pages, remove run this on that template as well.
$("#categoryTemplate").on('complete.infinitescroll',function(state,$ele,infoObj){
	$(window).off('scroll.infiniteScroll');
	});

$("#productTemplate, #productTemplateQuickView").on('complete.dynimaging',function(state,$ele,infoObj){
	handleSrcSetUpdate($ele);
	$('.prodDetailImagesContainer',$ele).imagegallery({
		show: 'fade',
		hide: 'fade',
		fullscreen: false,
		slideshow: false
		});
	});
/*
$("#productTemplateQuickView").on('complete.dynimaging',function(state,$ele,infoObj){
	handleSrcSetUpdate($ele);
	$('.prodDetailImagesContainer.dynimaging',$ele).imagegallery({
		show: 'fade',
		hide: 'fade',
		fullscreen: false,
		slideshow: false
		});
	});
*/

/*
if(typeof window.matchMedia != "undefined" || typeof window.msMatchMedia != "undefined")    {}
else{
	dump(" -> media queries are NOT supported. use polyfill ");
	myApp.rq.push(['script',0,myApp.vars.baseURL+'css3-mediaqueries.js']); //in zero pass in case product page is first page.
    }
*/

myApp.rq.push(['script',0,(document.location.protocol == 'file:') ? myApp.vars.testURL+'jsonapi/config.js' : myApp.vars.baseURL+'jsonapi/config.js',function(){
//in some cases, such as the zoovy UI, zglobals may not be defined. If that's the case, certain vars, such as jqurl, must be passed in via P in initialize:
//	myApp.u.dump(" ->>>>>>>>>>>>>>>>>>>>>>>>>>>>> zGlobals is an object");
	window.myApp.vars.username = zGlobals.appSettings.username.toLowerCase(); //used w/ image URL's.
//need to make sure the secureURL ends in a / always. doesn't seem to always come in that way via zGlobals
	window.myApp.vars.secureURL = zGlobals.appSettings.https_app_url;
	window.myApp.vars.domain = zGlobals.appSettings.sdomain; //passed in ajax requests.
	window.myApp.vars.jqurl = (document.location.protocol === 'file:') ? myApp.vars.testURL+'jsonapi/' : '/jsonapi/';
	}]); //The config.js is dynamically generated.

myApp.rq.push(['extension',0,'order_create','extensions/checkout/extension.js']);
myApp.rq.push(['extension',0,'cco','extensions/cart_checkout_order.js']);
myApp.rq.push(['extension',0,'greenspeed','app-greenspeed.js']);

myApp.rq.push(['extension',0,'store_prodlist','extensions/store_prodlist.js']);
myApp.rq.push(['extension',0,'store_navcats','extensions/store_navcats.js']);
myApp.rq.push(['extension',0,'prodlist_infinite','extensions/prodlist_infinite.js']);
myApp.rq.push(['extension',0,'store_search','extensions/store_search.js']);
myApp.rq.push(['extension',0,'store_product','extensions/store_product.js']);
myApp.rq.push(['extension',0,'store_crm','extensions/store_crm.js']);
myApp.rq.push(['extension',0,'quickstart','app-quickstart.js','startMyProgram']);
myApp.rq.push(['extension',0,'cart_message','extensions/cart_message/extension.js']);
myApp.rq.push(['extension',0,'store_routing','extensions/store_routing.js']);

myApp.rq.push(['script',0,myApp.vars.baseURL+'resources/jsonpath.0.8.0.js']); //used pretty early in process..

//once peg is loaded, need to retrieve the grammar file. Order is important there. This will validate the file too.
myApp.u.loadScript(myApp.vars.baseURL+'resources/peg-0.8.0.js',function(){
	myApp.model.getGrammar(myApp.vars.baseURL+"resources/pegjs-grammar-20140203.pegjs");
	}); // ### TODO -> callback on RQ.push wasn't getting executed. investigate.

myApp.rq.push(['script',0,myApp.vars.baseURL+'resources/tlc.js']); //in zero pass in case product page is first page.
myApp.rq.push(['script',0,myApp.vars.baseURL+'resources/jquery.showloading-v1.0.jt.js']); //used pretty early in process..
myApp.rq.push(['script',0,myApp.vars.baseURL+'resources/jquery.ui.anyplugins.js']); //in zero pass in case product page is first page.
myApp.rq.push(['css',1,myApp.vars.baseURL+'resources/anyplugins.css']);

myApp.rq.push(['script',0,myApp.vars.baseURL+'jquery.cycle2.min.js']); //used pretty early in process..
myApp.rq.push(['script',0,myApp.vars.baseURL+'jquery.cycle2.swipe.min.js']); //in zero pass in case product page is first page

//used for image enlargement in product layout
myApp.rq.push(['script',0,myApp.vars.baseURL+'resources/load-image.min.js']); //in zero pass in case product page is first page.
myApp.rq.push(['script',0,myApp.vars.baseURL+'resources/jquery.image-gallery.jt.js']); //in zero pass in case product page is first page.

//myApp.rq.push(['script',0,myApp.vars.baseURL+'srcset-polyfill-1.1.1-jt.js']); //in zero pass in case product page is first page.

//Cart Messaging Responses.

myApp.cmr.push(['chat.join',function(message){
	var $ui = myApp.ext.quickstart.a.showBuyerCMUI();
	$("[data-app-role='messageInput']",$ui).show();
	$("[data-app-role='messageHistory']",$ui).append("
"+message.FROM+" has joined the chat.<\/p>");
	$('.show4ActiveChat',$ui).show();
	$('.hide4ActiveChat',$ui).hide();
	}]);

myApp.cmr.push(['goto',function(message,$context){
	var $history = $("[data-app-role='messageHistory']",$context);
	$P = $("
")
		.addClass('chat_post')
		.append(""+message.FROM+"<\/span> has sent over a "+(message.vars.pageType || "")+" link for you within this store. Click here<\/span> to view.")
		.on('click',function(){
			showContent(myApp.ext.quickstart.u.whatAmIFor(message.vars),message.vars);
			});
	$history.append($P);
	$history.parent().scrollTop($history.height());
	}]);

//gets executed from app-admin.html as part of controller init process.
//progress is an object that will get updated as the resources load.
/*
'passZeroResourcesLength' : [INT],
'passZeroResourcesLoaded' : [INT],
'passZeroTimeout' : null //the timeout instance running within loadResources that updates this object. it will run indef unless clearTimeout run here OR all resources are loaded.

*/
myApp.u.showProgress = function(progress)	{
	function showProgress(attempt)	{
		if(progress.passZeroResourcesLength == progress.passZeroResourcesLoaded)	{
			//All pass zero resources have loaded.
			//the app will handle hiding the loading screen.
			myApp.u.appInitComplete();
			}
		else if(attempt > 150)	{
			//hhhhmmm.... something must have gone wrong.
			clearTimeout(progress.passZeroTimeout); //end the resource loading timeout.
			}
		else	{
			var percentPerInclude = (100 / progress.passZeroResourcesLength);
			var percentComplete = Math.round(progress.passZeroResourcesLength * percentPerInclude); //used to sum how many includes have successfully loaded.
//			dump(" -> percentPerInclude: "+percentPerInclude+" and percentComplete: "+percentComplete);
			$('#appPreViewProgressBar').val(percentComplete);
			$('#appPreViewProgressText').empty().append(percentComplete+"% Complete");
			attempt++;
			setTimeout(function(){showProgress(attempt);},250);
			}
		}
	showProgress(0)
	}

//Any code that needs to be executed after the app init has occured can go here.
//will pass in the page info object. (pageType, templateID, pid/navcat/show and more)
myApp.u.appInitComplete = function(P)	{
	myApp.u.dump("Executing myAppIsLoaded code...");

	dump(" -> HEY! just a head's up, the default pageTransition was just overwritten from app-greenspeed-init.js");
	myApp.ext.quickstart.pageTransition = function($o,$n,infoObj){
		var $hotw = $('#hotwButton').show();
		function transitionThePage()	{
//if $o doesn't exist, the animation doesn't run and the new element doesn't show up, so that needs to be accounted for.
//$o MAY be a jquery instance but have no length, so check both.
			if($o instanceof jQuery && $o.length)	{
				$('#mainContentArea').height($o.outerHeight()); //add a fixed height temporarily so that page doesn't 'collapse'
				dump(" -> offsetleft: " + $('#mainContentArea').width());
				$o.animate({'height':20,'width':20,'overflow':'hidden','left':$('#mainContentArea').width(),'top':-30},function(){
					$('#mainContentArea').height('');
					$o.hide().removeAttr('style');
					$n.css({'position':'relative','z-index':10}); //
					});
				}
			else	{
				//if o isn't set, n needs to be reset to relative positioning or the display will be wonky.
				$n.css({'position':'relative','z-index':10}); //
				}

			}

		$o.css({'position':'relative','z-index':'10'}); //make sure the old page is 'above' the new.
//$n isn't populated yet, most likely. So instead of animating it, just show it. Then animate the old layer above it.
		if($n instanceof jQuery)	{
			$n.addClass('pageTemplateBG').css({position:'absolute','z-index':9,'left':0,'top':0,'right':0}).show();
			}
//only 'jump to top' if we are partially down the page.  Using the header height as > means if a link in the header is clicked, we don't jump down to the content area. feels natural that way.
		if(infoObj.performJumpToTop && $(window).scrollTop() > $('header','#appView').height())	{
			$('html, body').animate({scrollTop : ($('header','#appView').length ? $('header','#appView').first().height() : 0)},500,function(){
				transitionThePage();
				});
			} //new page content loading. scroll to top.
		else	{
			transitionThePage();
			}

		}

	myApp.ext.order_create.checkoutCompletes.push(function(vars,$checkout){
//append this to
		$("[data-app-role='thirdPartyContainer']",$checkout).append("
What next?

");
		$('.ocmTwitterComment',$checkout).click(function(){
			window.open('http://twitter.com/home?status='+cartContentsAsLinks,'twitter');
			_gaq.push(['_trackEvent','Checkout','User Event','Tweeted about order']);
			});
		//the fb code only works if an appID is set, so don't show banner if not present.
		if(myApp.u.thisNestedExists("zGlobals.thirdParty.facebook.appId") && typeof FB == 'object')	{
			$('.ocmFacebookComment',$checkout).click(function(){
				myApp.ext.quickstart.thirdParty.fb.postToWall(cartContentsAsLinks);
				_gaq.push(['_trackEvent','Checkout','User Event','FB message about order']);
				});
			}
		else	{$('.ocmFacebookComment').hide()}
		});
	}

//this will trigger the content to load on app init. so if you push refresh, you don't get a blank page.
//it'll also handle the old 'meta' uri params.
myApp.router.appendInit({
	'type':'function',
	'route': function(v){
		return {'init':true} //returning anything but false triggers a match.
		},
	'callback':function(f,g){
		dump(" -> triggered callback for appendInit");
		g = g || {};
		if(document.location.hash)	{
			myApp.router.handleHashChange();
			}
		else	{
			//IE8 didn't like the shortcut to showContent here.
			myApp.ext.quickstart.a.showContent('homepage');
			}
		if(g.uriParams && g.uriParams.meta)	{
			myApp.ext.cco.calls.cartSet.init({'want/refer':infoObj.uriParams.meta,'cartID':_app.model.fetchCartID()},{},'passive');
			}
		if(g.uriParams && g.uriParams.meta_src)	{
			myApp.ext.cco.calls.cartSet.init({'want/refer_src':infoObj.uriParams.meta_src,'cartID':_app.model.fetchCartID()},{},'passive');
			}
		}
	});

/*
myApp.ext.myRIA.pageTransition = function($o,$n){
	$('#hotwButton').show();
	if($o.length){
		var $newO=$o.clone().width($o.width()).css($o.offset()).css('position','absolute');
		$newO.appendTo(document.body);
		$o.hide();
		$newO.animate({'height':20,'width':20,'overflow':'hidden','left':$('#hotwButton').offset().left,'top':$('#hotwButton').offset().top},'slow',function(){
			$(this).hide().empty().remove();
			});
		$n.fadeIn(1000);
		}
	else{
		$n.fadeIn(1000);
		}
	});
*/<|endoftext|>


<commit_before>
myApp.rq.push(['script',0,(document.location.protocol == 'file:') ? myApp.vars.testURL+'jsonapi/config.js' : myApp.vars.baseURL+'jsonapi/config.js',function(){
//in some cases, such as the zoovy UI, zglobals may not be defined. If that's the case, certain vars, such as jqurl, must be passed in via P in initialize:
//	myApp.u.dump(" ->>>>>>>>>>>>>>>>>>>>>>>>>>>>> zGlobals is an object");
	myApp.vars.username = zGlobals.appSettings.username.toLowerCase(); //used w/ image URL's.
//need to make sure the secureURL ends in a / always. doesn't seem to always come in that way via zGlobals
	myApp.vars.secureURL = zGlobals.appSettings.https_app_url;
	myApp.vars.domain = zGlobals.appSettings.sdomain; //passed in ajax requests.
	myApp.vars.jqurl = (document.location.protocol === 'file:') ? myApp.vars.testURL+'jsonapi/' : '/jsonapi/';
	}]); //The config.js is dynamically generated.

myApp.rq.push(['extension',0,'order_create','extensions/checkout/extension.js']);
myApp.rq.push(['extension',0,'cco','extensions/cart_checkout_order.js']);

myApp.rq.push(['extension',0,'store_routing','extensions/store_routing.js']);

myApp.rq.push(['extension',0,'store_prodlist','extensions/store_prodlist.js']);
myApp.rq.push(['extension',0,'store_navcats','extensions/store_navcats.js']);
myApp.rq.push(['extension',0,'store_search','extensions/store_search.js']);
myApp.rq.push(['extension',0,'store_product','extensions/store_product.js']);
myApp.rq.push(['extension',0,'cart_message','extensions/cart_message/extension.js']);
myApp.rq.push(['extension',0,'store_crm','extensions/store_crm.js']);
myApp.rq.push(['extension',0,'store_tracking','extensions/store_tracking.js']);
myApp.rq.push(['extension',0,'quickstart','app-quickstart.js','startMyProgram']);

//myApp.rq.push(['extension',0,'entomologist','extensions/entomologist/extension.js']);
//myApp.rq.push(['extension',0,'tools_animation','extensions/tools_animation.js']);

// 201405 - Deprecated for Universal Analytics
//myApp.rq.push(['extension',1,'google_analytics','extensions/partner_google_analytics.js','startExtension']);

//myApp.rq.push(['extension',1,'tools_ab_testing','extensions/tools_ab_testing.js']);
//myApp.rq.push(['extension',0,'partner_addthis','extensions/partner_addthis.js']);
//myApp.rq.push(['extension',1,'resellerratings_survey','extensions/partner_buysafe_guarantee.js','startExtension']); /// !!! needs testing.
//myApp.rq.push(['extension',1,'buysafe_guarantee','extensions/partner_buysafe_guarantee.js','startExtension']);
//myApp.rq.push(['extension',1,'powerReviews_reviews','extensions/partner_powerreviews_reviews.js','startExtension']);
//myApp.rq.push(['extension',0,'magicToolBox_mzp','extensions/partner_magictoolbox_mzp.js','startExtension']); // (not working yet - ticket in to MTB)

myApp.rq.push(['script',0,myApp.vars.baseURL+'resources/jquery.showloading-v1.0.jt.js']); //used pretty early in process..
myApp.rq.push(['script',0,myApp.vars.baseURL+'resources/jquery.ui.anyplugins.js']); //in zero pass because it's essential to rendering and error handling.
myApp.rq.push(['script',0,myApp.vars.baseURL+'resources/tlc.js']); //in zero pass cuz you can't render a page without it..
myApp.rq.push(['css',1,myApp.vars.baseURL+'resources/anyplugins.css']);

myApp.rq.push(['script',0,myApp.vars.baseURL+'resources/jsonpath.0.8.0.js']); //used pretty early in process..

//once peg is loaded, need to retrieve the grammar file. Order is important there. This will validate the file too.
myApp.u.loadScript(myApp.vars.baseURL+'resources/peg-0.8.0.js',function(){
	myApp.model.getGrammar(myApp.vars.baseURL+"resources/pegjs-grammar-20140203.pegjs");
	}); // ### TODO -> callback on RQ.push wasn't getting executed. investigate.

//gets executed from app-admin.html as part of controller init process.
//progress is an object that will get updated as the resources load.
/*
'passZeroResourcesLength' : [INT],
'passZeroResourcesLoaded' : [INT],
'passZeroTimeout' : null //the timeout instance running within loadResources that updates this object. it will run indef unless clearTimeout run here OR all resources are loaded.

*/
myApp.u.showProgress = function(progress)	{
	function showProgress(attempt)	{
		if(progress.passZeroResourcesLength == progress.passZeroResourcesLoaded)	{
			//All pass zero resources have loaded.
			//the app will handle hiding the loading screen.
			myApp.u.appInitComplete();
			}
		else if(attempt > 150)	{
			//hhhhmmm.... something must have gone wrong.
			clearTimeout(progress.passZeroTimeout); //end the resource loading timeout.
			$('.appMessaging','#appPreView').anymessage({'message':'Init failed to load all the resources within a reasonable number of attempts.','gMessage':true,'persistent':true});
			}
		else	{
			var percentPerInclude = (100 / progress.passZeroResourcesLength);
			var percentComplete = Math.round(progress.passZeroResourcesLength * percentPerInclude); //used to sum how many includes have successfully loaded.
//			dump(" -> percentPerInclude: "+percentPerInclude+" and percentComplete: "+percentComplete);
			$('#appPreViewProgressBar').val(percentComplete);
			$('#appPreViewProgressText').empty().append(percentComplete+"% Complete");
			attempt++;
			setTimeout(function(){showProgress(attempt);},250);
			}
		}
	showProgress(0)
	}

//Any code that needs to be executed after the app init has occured can go here.
//will pass in the page info object. (pageType, templateID, pid/navcat/show and more)
myApp.u.appInitComplete = function()	{
//	myApp.u.dump("Executing myAppIsLoaded code...");

	myApp.ext.order_create.checkoutCompletes.push(function(vars,$checkout){
		dump(" -> begin checkoutCOmpletes code: "); dump(vars);

		var cartContentsAsLinks = encodeURIComponent(myApp.ext.cco.u.cartContentsAsLinks(myApp.data[vars.datapointer].order));

//append this to
		$("[data-app-role='thirdPartyContainer']",$checkout).append("
What next?

");
		$('.ocmTwitterComment',$checkout).click(function(){
			window.open('http://twitter.com/home?status='+cartContentsAsLinks,'twitter');
			window[myApp.vars.analyticsPointer]('send', 'event','Checkout','User Event','Tweeted about order');
			});
		//the fb code only works if an appID is set, so don't show banner if not present.
		if(myApp.u.thisNestedExists("zGlobals.thirdParty.facebook.appId") && typeof FB == 'object')	{
			$('.ocmFacebookComment',$checkout).click(function(){
				myApp.ext.quickstart.thirdParty.fb.postToWall(cartContentsAsLinks);
				_gaq.push(['_trackEvent','Checkout','User Event','FB message about order']);
				window[myApp.vars.analyticsPointer]('send', 'event','Checkout','User Event','FB message about order');
				});
			}
		else	{$('.ocmFacebookComment').hide()}
		});

	//Cart Messaging Responses.
	myApp.cmr.push(['chat.join',function(message){
		if(message.FROM == 'ADMIN')	{
			var $ui = myApp.ext.quickstart.a.showBuyerCMUI();
			$("[data-app-role='messageInput']",$ui).show();
			$("[data-app-role='messageHistory']",$ui).append("
"+message.FROM+" has joined the chat.<\/p>");
			$('.show4ActiveChat',$ui).show();
			$('.hide4ActiveChat',$ui).hide();
			}
		}]);

	myApp.cmr.push(['goto',function(message,$context){
		var $history = $("[data-app-role='messageHistory']",$context);
		$P = $("
")
			.addClass('chat_post')
			.append(""+message.FROM+"<\/span> has sent over a "+(message.vars.pageType || "")+" link for you within this store. Click here<\/span> to view.")
			.on('click',function(){
				showContent(myApp.ext.quickstart.u.whatAmIFor(message.vars),message.vars);
				});
		$history.append($P);
		$history.parent().scrollTop($history.height());
		}]);

	}

//this will trigger the content to load on app init. so if you push refresh, you don't get a blank page.
//it'll also handle the old 'meta' uri params.
//this will trigger the content to load on app init. so if you push refresh, you don't get a blank page.
//it'll also handle the old 'meta' uri params.
myApp.router.appendInit({
	'type':'function',
	'route': function(v){
		return {'init':true} //returning anything but false triggers a match.
		},
	'callback':function(f,g){
		dump(" -> triggered callback for appendInit");
		g = g || {};
		if(g.uriParams.seoRequest){
			showContent(g.uriParams.pageType, g.uriParams);
			}
		else if(document.location.hash)	{
			myApp.u.dump('triggering handleHash');
			myApp.router.handleHashChange();
			}
		else	{
			//IE8 didn't like the shortcut to showContent here.
			myApp.ext.quickstart.a.showContent('homepage');
			}
		if(g.uriParams && g.uriParams.meta)	{
			myApp.ext.cco.calls.cartSet.init({'want/refer':infoObj.uriParams.meta,'cartID':_app.model.fetchCartID()},{},'passive');
			}
		if(g.uriParams && g.uriParams.meta_src)	{
			myApp.ext.cco.calls.cartSet.init({'want/refer_src':infoObj.uriParams.meta_src,'cartID':_app.model.fetchCartID()},{},'passive');
			}
		}
	});

<commit_msg>app-quickstart-init - marketplace / syndication url handling<commit_after>
myApp.rq.push(['script',0,(document.location.protocol == 'file:') ? myApp.vars.testURL+'jsonapi/config.js' : myApp.vars.baseURL+'jsonapi/config.js',function(){
//in some cases, such as the zoovy UI, zglobals may not be defined. If that's the case, certain vars, such as jqurl, must be passed in via P in initialize:
//	myApp.u.dump(" ->>>>>>>>>>>>>>>>>>>>>>>>>>>>> zGlobals is an object");
	myApp.vars.username = zGlobals.appSettings.username.toLowerCase(); //used w/ image URL's.
//need to make sure the secureURL ends in a / always. doesn't seem to always come in that way via zGlobals
	myApp.vars.secureURL = zGlobals.appSettings.https_app_url;
	myApp.vars.domain = zGlobals.appSettings.sdomain; //passed in ajax requests.
	myApp.vars.jqurl = (document.location.protocol === 'file:') ? myApp.vars.testURL+'jsonapi/' : '/jsonapi/';
	}]); //The config.js is dynamically generated.

myApp.rq.push(['extension',0,'order_create','extensions/checkout/extension.js']);
myApp.rq.push(['extension',0,'cco','extensions/cart_checkout_order.js']);

myApp.rq.push(['extension',0,'store_routing','extensions/store_routing.js']);

myApp.rq.push(['extension',0,'store_prodlist','extensions/store_prodlist.js']);
myApp.rq.push(['extension',0,'store_navcats','extensions/store_navcats.js']);
myApp.rq.push(['extension',0,'store_search','extensions/store_search.js']);
myApp.rq.push(['extension',0,'store_product','extensions/store_product.js']);
myApp.rq.push(['extension',0,'cart_message','extensions/cart_message/extension.js']);
myApp.rq.push(['extension',0,'store_crm','extensions/store_crm.js']);
myApp.rq.push(['extension',0,'store_tracking','extensions/store_tracking.js']);
myApp.rq.push(['extension',0,'quickstart','app-quickstart.js','startMyProgram']);

//myApp.rq.push(['extension',0,'entomologist','extensions/entomologist/extension.js']);
//myApp.rq.push(['extension',0,'tools_animation','extensions/tools_animation.js']);

// 201405 - Deprecated for Universal Analytics
//myApp.rq.push(['extension',1,'google_analytics','extensions/partner_google_analytics.js','startExtension']);

//myApp.rq.push(['extension',1,'tools_ab_testing','extensions/tools_ab_testing.js']);
//myApp.rq.push(['extension',0,'partner_addthis','extensions/partner_addthis.js']);
//myApp.rq.push(['extension',1,'resellerratings_survey','extensions/partner_buysafe_guarantee.js','startExtension']); /// !!! needs testing.
//myApp.rq.push(['extension',1,'buysafe_guarantee','extensions/partner_buysafe_guarantee.js','startExtension']);
//myApp.rq.push(['extension',1,'powerReviews_reviews','extensions/partner_powerreviews_reviews.js','startExtension']);
//myApp.rq.push(['extension',0,'magicToolBox_mzp','extensions/partner_magictoolbox_mzp.js','startExtension']); // (not working yet - ticket in to MTB)

myApp.rq.push(['script',0,myApp.vars.baseURL+'resources/jquery.showloading-v1.0.jt.js']); //used pretty early in process..
myApp.rq.push(['script',0,myApp.vars.baseURL+'resources/jquery.ui.anyplugins.js']); //in zero pass because it's essential to rendering and error handling.
myApp.rq.push(['script',0,myApp.vars.baseURL+'resources/tlc.js']); //in zero pass cuz you can't render a page without it..
myApp.rq.push(['css',1,myApp.vars.baseURL+'resources/anyplugins.css']);

myApp.rq.push(['script',0,myApp.vars.baseURL+'resources/jsonpath.0.8.0.js']); //used pretty early in process..

//once peg is loaded, need to retrieve the grammar file. Order is important there. This will validate the file too.
myApp.u.loadScript(myApp.vars.baseURL+'resources/peg-0.8.0.js',function(){
	myApp.model.getGrammar(myApp.vars.baseURL+"resources/pegjs-grammar-20140203.pegjs");
	}); // ### TODO -> callback on RQ.push wasn't getting executed. investigate.

//gets executed from app-admin.html as part of controller init process.
//progress is an object that will get updated as the resources load.
/*
'passZeroResourcesLength' : [INT],
'passZeroResourcesLoaded' : [INT],
'passZeroTimeout' : null //the timeout instance running within loadResources that updates this object. it will run indef unless clearTimeout run here OR all resources are loaded.

*/
myApp.u.showProgress = function(progress)	{
	function showProgress(attempt)	{
		if(progress.passZeroResourcesLength == progress.passZeroResourcesLoaded)	{
			//All pass zero resources have loaded.
			//the app will handle hiding the loading screen.
			myApp.u.appInitComplete();
			}
		else if(attempt > 150)	{
			//hhhhmmm.... something must have gone wrong.
			clearTimeout(progress.passZeroTimeout); //end the resource loading timeout.
			$('.appMessaging','#appPreView').anymessage({'message':'Init failed to load all the resources within a reasonable number of attempts.','gMessage':true,'persistent':true});
			}
		else	{
			var percentPerInclude = (100 / progress.passZeroResourcesLength);
			var percentComplete = Math.round(progress.passZeroResourcesLength * percentPerInclude); //used to sum how many includes have successfully loaded.
//			dump(" -> percentPerInclude: "+percentPerInclude+" and percentComplete: "+percentComplete);
			$('#appPreViewProgressBar').val(percentComplete);
			$('#appPreViewProgressText').empty().append(percentComplete+"% Complete");
			attempt++;
			setTimeout(function(){showProgress(attempt);},250);
			}
		}
	showProgress(0)
	}

//Any code that needs to be executed after the app init has occured can go here.
//will pass in the page info object. (pageType, templateID, pid/navcat/show and more)
myApp.u.appInitComplete = function()	{
//	myApp.u.dump("Executing myAppIsLoaded code...");

	myApp.ext.order_create.checkoutCompletes.push(function(vars,$checkout){
		dump(" -> begin checkoutCOmpletes code: "); dump(vars);

		var cartContentsAsLinks = encodeURIComponent(myApp.ext.cco.u.cartContentsAsLinks(myApp.data[vars.datapointer].order));

//append this to
		$("[data-app-role='thirdPartyContainer']",$checkout).append("
What next?

");
		$('.ocmTwitterComment',$checkout).click(function(){
			window.open('http://twitter.com/home?status='+cartContentsAsLinks,'twitter');
			window[myApp.vars.analyticsPointer]('send', 'event','Checkout','User Event','Tweeted about order');
			});
		//the fb code only works if an appID is set, so don't show banner if not present.
		if(myApp.u.thisNestedExists("zGlobals.thirdParty.facebook.appId") && typeof FB == 'object')	{
			$('.ocmFacebookComment',$checkout).click(function(){
				myApp.ext.quickstart.thirdParty.fb.postToWall(cartContentsAsLinks);
				_gaq.push(['_trackEvent','Checkout','User Event','FB message about order']);
				window[myApp.vars.analyticsPointer]('send', 'event','Checkout','User Event','FB message about order');
				});
			}
		else	{$('.ocmFacebookComment').hide()}
		});

	//Cart Messaging Responses.
	myApp.cmr.push(['chat.join',function(message){
		if(message.FROM == 'ADMIN')	{
			var $ui = myApp.ext.quickstart.a.showBuyerCMUI();
			$("[data-app-role='messageInput']",$ui).show();
			$("[data-app-role='messageHistory']",$ui).append("
"+message.FROM+" has joined the chat.<\/p>");
			$('.show4ActiveChat',$ui).show();
			$('.hide4ActiveChat',$ui).hide();
			}
		}]);

	myApp.cmr.push(['goto',function(message,$context){
		var $history = $("[data-app-role='messageHistory']",$context);
		$P = $("
")
			.addClass('chat_post')
			.append(""+message.FROM+"<\/span> has sent over a "+(message.vars.pageType || "")+" link for you within this store. Click here<\/span> to view.")
			.on('click',function(){
				showContent(myApp.ext.quickstart.u.whatAmIFor(message.vars),message.vars);
				});
		$history.append($P);
		$history.parent().scrollTop($history.height());
		}]);

	}

//this will trigger the content to load on app init. so if you push refresh, you don't get a blank page.
//it'll also handle the old 'meta' uri params.
//this will trigger the content to load on app init. so if you push refresh, you don't get a blank page.
//it'll also handle the old 'meta' uri params.
myApp.router.appendInit({
	'type':'function',
	'route': function(v){
		return {'init':true} //returning anything but false triggers a match.
		},
	'callback':function(f,g){
		dump(" -> triggered callback for appendInit");
		g = g || {};
		if(g.uriParams.seoRequest){
			showContent(g.uriParams.pageType, g.uriParams);
			}
		else if (g.uriParams.marketplace){
			showContent("product",{"pid":g.uriParams.product});
			}
		else if(document.location.hash)	{
			myApp.u.dump('triggering handleHash');
			myApp.router.handleHashChange();
			}
		else	{
			//IE8 didn't like the shortcut to showContent here.
			myApp.ext.quickstart.a.showContent('homepage');
			}
		if(g.uriParams && g.uriParams.meta)	{
			myApp.ext.cco.calls.cartSet.init({'want/refer':infoObj.uriParams.meta,'cartID':_app.model.fetchCartID()},{},'passive');
			}
		if(g.uriParams && g.uriParams.meta_src)	{
			myApp.ext.cco.calls.cartSet.init({'want/refer_src':infoObj.uriParams.meta_src,'cartID':_app.model.fetchCartID()},{},'passive');
			}
		}
	});

<|endoftext|>


<commit_before>// TryMongo
//
// Copyright (c) 2009 Kyle Banker
// Licensed under the MIT Licence.
// http://www.opensource.org/licenses/mit-license.php

// Readline class to handle line input.
var ReadLine = function(options) {
  this.options      = options || {};
  this.htmlForInput = this.options.htmlForInput;
  this.inputHandler = this.options.handler || this.mockHandler;
  this.scoper       = this.options.scoper;
  this.terminal     = $(this.options.terminalId || "#terminal");
  this.lineClass    = this.options.lineClass || '.readLine';
  this.history      = [];
  this.historyPtr   = 0;

  this.initialize();
};

ReadLine.prototype = {

  initialize: function() {
    this.addInputLine();
  },

  // Enter a new input line with proper behavior.
  addInputLine: function(stackLevel) {
    stackLevel = stackLevel || 0;
    this.terminal.append(this.htmlForInput(stackLevel));
    var ctx = this;
    ctx.activeLine = $(this.lineClass + '.active');

    // Bind key events for entering and navigting history.
    ctx.activeLine.bind("keydown", function(ev) {
      switch (ev.keyCode) {
        case EnterKeyCode:
          ctx.processInput(this.value);
          break;
        case UpArrowKeyCode:
          ctx.getCommand('previous');
          break;
        case DownArrowKeyCode:
          ctx.getCommand('next');
          break;
      }
    });

    this.activeLine.focus();
  },

  // Returns the 'next' or 'previous' command in this history.
  getCommand: function(direction) {
    if(this.history.length === 0) {
      return;
    }
    this.adjustHistoryPointer(direction);
    this.activeLine[0].value = this.history[this.historyPtr];
    $(this.activeLine[0]).focus();
    //this.activeLine[0].value = this.activeLine[0].value;
  },

  // Moves the history pointer to the 'next' or 'previous' position.
  adjustHistoryPointer: function(direction) {
    if(direction == 'previous') {
      if(this.historyPtr - 1 >= 0) {
        this.historyPtr -= 1;
      }
    }
    else {
      if(this.historyPtr + 1 < this.history.length) {
        this.historyPtr += 1;
      }
    }
  },

  // Return the handler's response.
  processInput: function(value) {
    var response = this.inputHandler.apply(this.scoper, [value]);
    this.insertResponse(response.result);

    // Save to the command history...
    if((lineValue = value.trim()) !== "") {
      this.history.push(lineValue);
      this.historyPtr = this.history.length;
    }

    // deactivate the line...
    this.activeLine.value = "";
    this.activeLine.attr({disabled: true});
    this.activeLine.removeClass('active');

    // and add add a new command line.
    this.addInputLine(response.stack);
  },

  insertResponse: function(response) {
    if((response.length < 1) || (response=='"donotprintme"')) {
      this.activeLine.parent().append("

");
    }
    else {
      this.activeLine.parent().append("
" + response + "
");
    }
  },

  // Simply return the entered string if the user hasn't specified a smarter handler.
  mockHandler: function(inputString) {
    return function() {
      this._process = function() { return inputString; };
    };
  }
};

var MongoHandler = function() {
  this._currentCommand = "";
  this._rawCommand     = "";
  this._commandStack   = 0;
  this._tutorialPtr    = 0;
  this._tutorialMax    = 4;

  this._mongo          = {};
  this._mongo.test     = [];
  this.collections     = [];
};

MongoHandler.prototype = {

  _process: function(inputString, errorCheck) {
    this._rawCommand += ' ' + inputString;

    try {
      inputString += '  '; // fixes certain bugs with the tokenizer.
      var tokens    = inputString.tokens();
      var mongoFunc = this._getCommand(tokens);
      if(this._commandStack === 0 && inputString.match(/^\s*$/)) {
        return {stack: 0, result: ''};
      }
      else if(this._commandStack === 0 && mongoFunc) {
        this._resetCurrentCommand();
        return {stack: 0, result: mongoFunc.apply(this, [tokens])};
      }
      else {
        return this._evaluator(tokens);
      }
    }

    catch(err) {
        this._resetCurrentCommand();
        console.trace();
        return {stack: 0, result: "JS Error: " + err};
    }
  },

  // Calls eval on the input string when ready.
  _evaluator: function(tokens) {
    isAssignment = tokens.length>=2 && tokens[0].type=="name" && tokens[1].type=="operator" && tokens[1].value=="=";

    this._currentCommand += " " + this._massageTokens(tokens);
    if(this._shouldEvaluateCommand(tokens))  {
        opencloud = new OpenCloud();
        print = this.print;

        // So this eval statement is the heart of the REPL.
        var result = eval(this._currentCommand.trim());
        if(result === undefined) {
          throw('result is undefined');
        } else {
          result = $htmlFormat(result);
        }
        this._resetCurrentCommand();
        if (isAssignment) {
            return {stack: this._commandStack, result: ""};
        } else {
            return {stack: this._commandStack, result: result};
        }
      }

    else {
      return {stack: this._commandStack, result: ""};
    }
  },

  _resetCurrentCommand: function() {
    this._currentCommand = '';
    this._rawCommand     = '';
  },

  // Evaluate only when we've exited any blocks.
  _shouldEvaluateCommand: function(tokens) {
    for(var i=0; i < tokens.length; i++) {
      var token = tokens[i];
      if(token.type == 'operator') {
        if(token.value == '(' || token.value == '{') {
          this._commandStack += 1;
        }
        else if(token.value == ')' || token.value == '}') {
          this._commandStack -= 1;
        }
      }
    }

    if(this._commandStack === 0) {
      return true;
    }
    else {
      return false;
    }
  },

  _massageTokens: function(tokens) {
    for(var i=0; i < tokens.length; i++) {
      if(tokens[i].type == 'name') {
        if(tokens[i].value == 'var') {
          tokens[i].value = '';
        }
      }
    }
    return this._collectTokens(tokens);
  },

  // Collects tokens into a string, placing spaces between variables.
  // This methods is called after we scope the vars.
  _collectTokens: function(tokens) {
    var result = "";
    for(var i=0; i < tokens.length; i++) {
      if(tokens[i].type == "name" && tokens[i+1] && tokens[i+1].type == 'name') {
        result += tokens[i].value + ' ';
      }
      else if (tokens[i].type == 'string') {
        result += "'" + tokens[i].value + "'";
      }
      else {
        result += tokens[i].value;
      }
    }
    return result;
  },

  // print output to the screen, e.g., in a loop
  // TODO: remove dependency here
  print: function() {
   $('.readLine.active').parent().append('
' + JSON.stringify(arguments[0]) + '
');
   return "donotprintme";
  },

  /* MongoDB     */
  /* ________________________________________ */

  // help command
  _help: function() {
      return PTAG('HELP') +
             PTAG('opencloud                                 list opencloud API object types') +
             PTAG('opencloud.slices                          list methods to can call on slices') +
             PTAG('opencloud.slices.all()                    get all slices') +
             PTAG('opencloud.slices.filter({key: "value"})   filter using dictionary') +
             PTAG('opencloud.slices.get({key: "value"}))     get using dictionary')

  },

  _tutorial: function() {
    this._tutorialPtr = 0;
    return PTAG("This is a self-guided tutorial on the OpenCloud shell.") +
           PTAG("The tutorial is simple, more or less a few basic commands to try.") +
           PTAG("To go directly to any part tutorial, enter one of the commands t0, t1, t2...t10") +
           PTAG("Otherwise, use 'next' and 'back'. Start by typing 'next' and pressing enter.");
  },

  // go to the next step in the tutorial.
  _next: function() {
    if(this._tutorialPtr < this._tutorialMax) {
      return this['_t' + (this._tutorialPtr + 1)]();
    }
    else {
      return "You've reached the end of the tutorial. To go to the beginning, type 'tutorial'";
    }
  },

  // go to the previous step in the tutorial.
  _back: function() {
    if(this._tutorialPtr > 1) {
      return this['_t' + (this._tutorialPtr - 1)]();
    }
    else {
      return this._tutorial();
    }
  },

  _t1: function() {
    this._tutorialPtr = 1;
    return PTAG('1. JavaScript Shell') +
           PTAG('The first thing to notice is that the MongoDB shell is JavaScript-based.') +
           PTAG('So you can do things like:') +
           PTAG('  a = 5; ') +
           PTAG('  a * 10; ') +
           PTAG('  print(a); ') +
           PTAG("  for(i=0; i<10; i++) { print('hello'); }; ") +
           PTAG("Try a few JS commands; when you're ready to move on, enter 'next'");

  },

  _t2: function() {
    this._tutorialPtr = 2;
    return PTAG('2. List some objects') +
           PTAG('Try these:') +
           PTAG('    opencloud.slices.all();') +
           PTAG('    opencloud.slivers.all();') +
           PTAG('    opencloud.sites.all();') +
           PTAG('    opencloud.nodes.all();');

  },

  _t3: function() {
    this._tutorialPtr = 3;
    return PTAG('3. Filter some objects') +
           PTAG('Try these:') +
           PTAG('    opencloud.slices.get({name: "HyperCache"});');
           PTAG('    opencloud.nodes.filter({site_id: opencloud.sites.get({name: "Princeton"})["id"]});');

  },

  _t4: function() {
    this._tutorialPtr = 4;
    return PTAG('4. Available OpenCloud objects and methods') +
           PTAG('Try these:') +
           PTAG('    opencloud;') +
           PTAG('    opencloud.nodes;');

  },

  _getCommand: function(tokens) {
    if(tokens[0] && ArrayInclude(MongoKeywords,(tokens[0].value + '').toLowerCase())) {
      switch(tokens[0].value.toLowerCase()) {
        case 'help':
          return this._help;

        case 'tutorial':
          return this._tutorial;
        case 'next':
          return this._next;
        case 'back':
          return this._back;
        case 't0':
          return this._tutorial;
        case 't1':
          return this._t1;
        case 't2':
          return this._t2;
        case 't3':
          return this._t3;
        case 't4':
          return this._t4;
      }
    }
  }
};

function replaceAll(find, replace, str) {
  return str.replace(new RegExp(find, 'g'), replace);
}

/* stackoverflow: http://stackoverflow.com/questions/4810841/how-can-i-pretty-print-json-using-javascript */
function syntaxHighlight(json) {
    if ( json.hasOwnProperty("__str__")) {
        return syntaxHighlight(json.__str__());
    }
    if (typeof json != 'string') {
         json = JSON.stringify(json, undefined, "\t");
    }
    json = json.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
    return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match) {
        var cls = 'terminal_number';
        if (/^"/.test(match)) {
            if (/:$/.test(match)) {
                cls = 'terminal_key';
            } else {
                cls = 'terminal_string';
            }
        } else if (/true|false/.test(match)) {
            cls = 'terminal_boolean';
        } else if (/null/.test(match)) {
            cls = 'terminal_null';
        }
        return '' + match + '';
    });
}

$htmlFormat = function(obj) {
  //JSON.stringify(obj,undefined,2)
  result=replaceAll("\t"," ",replaceAll("\n","
",syntaxHighlight(obj))); //tojson(obj, ' ', ' ', true);
  return result;
}

function startTerminal() {
  var mongo       = new MongoHandler();
  var terminal    = new ReadLine({htmlForInput: DefaultInputHtml,
                                  handler: mongo._process,
                                  scoper: mongo});
  $("#terminal_help1").show();
  $("#terminal_help2").show();
  $("#terminal_wait").hide();

  $("#terminal").bind('click', function() { $(".readLine.active").focus(); });
};

$(document).ready(function() {
    updateOpenCloud(onLoaded = startTerminal);
});
<commit_msg>fix donotprintme printed by print()<commit_after>// TryMongo
//
// Copyright (c) 2009 Kyle Banker
// Licensed under the MIT Licence.
// http://www.opensource.org/licenses/mit-license.php

// Readline class to handle line input.
var ReadLine = function(options) {
  this.options      = options || {};
  this.htmlForInput = this.options.htmlForInput;
  this.inputHandler = this.options.handler || this.mockHandler;
  this.scoper       = this.options.scoper;
  this.terminal     = $(this.options.terminalId || "#terminal");
  this.lineClass    = this.options.lineClass || '.readLine';
  this.history      = [];
  this.historyPtr   = 0;

  this.initialize();
};

ReadLine.prototype = {

  initialize: function() {
    this.addInputLine();
  },

  // Enter a new input line with proper behavior.
  addInputLine: function(stackLevel) {
    stackLevel = stackLevel || 0;
    this.terminal.append(this.htmlForInput(stackLevel));
    var ctx = this;
    ctx.activeLine = $(this.lineClass + '.active');

    // Bind key events for entering and navigting history.
    ctx.activeLine.bind("keydown", function(ev) {
      switch (ev.keyCode) {
        case EnterKeyCode:
          ctx.processInput(this.value);
          break;
        case UpArrowKeyCode:
          ctx.getCommand('previous');
          break;
        case DownArrowKeyCode:
          ctx.getCommand('next');
          break;
      }
    });

    this.activeLine.focus();
  },

  // Returns the 'next' or 'previous' command in this history.
  getCommand: function(direction) {
    if(this.history.length === 0) {
      return;
    }
    this.adjustHistoryPointer(direction);
    this.activeLine[0].value = this.history[this.historyPtr];
    $(this.activeLine[0]).focus();
    //this.activeLine[0].value = this.activeLine[0].value;
  },

  // Moves the history pointer to the 'next' or 'previous' position.
  adjustHistoryPointer: function(direction) {
    if(direction == 'previous') {
      if(this.historyPtr - 1 >= 0) {
        this.historyPtr -= 1;
      }
    }
    else {
      if(this.historyPtr + 1 < this.history.length) {
        this.historyPtr += 1;
      }
    }
  },

  // Return the handler's response.
  processInput: function(value) {
    var response = this.inputHandler.apply(this.scoper, [value]);
    this.insertResponse(response.result);

    // Save to the command history...
    if((lineValue = value.trim()) !== "") {
      this.history.push(lineValue);
      this.historyPtr = this.history.length;
    }

    // deactivate the line...
    this.activeLine.value = "";
    this.activeLine.attr({disabled: true});
    this.activeLine.removeClass('active');

    // and add add a new command line.
    this.addInputLine(response.stack);
  },

  insertResponse: function(response) {
    if((response.length < 1) || (response=='"donotprintme"') || (response=='donotprintme')) {
      this.activeLine.parent().append("

");
    }
    else {
      this.activeLine.parent().append("
" + response + "
");
    }
  },

  // Simply return the entered string if the user hasn't specified a smarter handler.
  mockHandler: function(inputString) {
    return function() {
      this._process = function() { return inputString; };
    };
  }
};

var MongoHandler = function() {
  this._currentCommand = "";
  this._rawCommand     = "";
  this._commandStack   = 0;
  this._tutorialPtr    = 0;
  this._tutorialMax    = 4;

  this._mongo          = {};
  this._mongo.test     = [];
  this.collections     = [];
};

MongoHandler.prototype = {

  _process: function(inputString, errorCheck) {
    this._rawCommand += ' ' + inputString;

    try {
      inputString += '  '; // fixes certain bugs with the tokenizer.
      var tokens    = inputString.tokens();
      var mongoFunc = this._getCommand(tokens);
      if(this._commandStack === 0 && inputString.match(/^\s*$/)) {
        return {stack: 0, result: ''};
      }
      else if(this._commandStack === 0 && mongoFunc) {
        this._resetCurrentCommand();
        return {stack: 0, result: mongoFunc.apply(this, [tokens])};
      }
      else {
        return this._evaluator(tokens);
      }
    }

    catch(err) {
        this._resetCurrentCommand();
        console.trace();
        return {stack: 0, result: "JS Error: " + err};
    }
  },

  // Calls eval on the input string when ready.
  _evaluator: function(tokens) {
    isAssignment = tokens.length>=2 && tokens[0].type=="name" && tokens[1].type=="operator" && tokens[1].value=="=";

    this._currentCommand += " " + this._massageTokens(tokens);
    if(this._shouldEvaluateCommand(tokens))  {
        opencloud = new OpenCloud();
        print = this.print;

        // So this eval statement is the heart of the REPL.
        var result = eval(this._currentCommand.trim());
        if(result === undefined) {
          throw('result is undefined');
        } else {
          result = $htmlFormat(result);
        }
        this._resetCurrentCommand();
        if (isAssignment) {
            return {stack: this._commandStack, result: ""};
        } else {
            return {stack: this._commandStack, result: result};
        }
      }

    else {
      return {stack: this._commandStack, result: ""};
    }
  },

  _resetCurrentCommand: function() {
    this._currentCommand = '';
    this._rawCommand     = '';
  },

  // Evaluate only when we've exited any blocks.
  _shouldEvaluateCommand: function(tokens) {
    for(var i=0; i < tokens.length; i++) {
      var token = tokens[i];
      if(token.type == 'operator') {
        if(token.value == '(' || token.value == '{') {
          this._commandStack += 1;
        }
        else if(token.value == ')' || token.value == '}') {
          this._commandStack -= 1;
        }
      }
    }

    if(this._commandStack === 0) {
      return true;
    }
    else {
      return false;
    }
  },

  _massageTokens: function(tokens) {
    for(var i=0; i < tokens.length; i++) {
      if(tokens[i].type == 'name') {
        if(tokens[i].value == 'var') {
          tokens[i].value = '';
        }
      }
    }
    return this._collectTokens(tokens);
  },

  // Collects tokens into a string, placing spaces between variables.
  // This methods is called after we scope the vars.
  _collectTokens: function(tokens) {
    var result = "";
    for(var i=0; i < tokens.length; i++) {
      if(tokens[i].type == "name" && tokens[i+1] && tokens[i+1].type == 'name') {
        result += tokens[i].value + ' ';
      }
      else if (tokens[i].type == 'string') {
        result += "'" + tokens[i].value + "'";
      }
      else {
        result += tokens[i].value;
      }
    }
    return result;
  },

  // print output to the screen, e.g., in a loop
  // TODO: remove dependency here
  print: function() {
   $('.readLine.active').parent().append('
' + JSON.stringify(arguments[0]) + '
');
   return "donotprintme";
  },

  /* MongoDB     */
  /* ________________________________________ */

  // help command
  _help: function() {
      return PTAG('HELP') +
             PTAG('opencloud                                 list opencloud API object types') +
             PTAG('opencloud.slices                          list methods to can call on slices') +
             PTAG('opencloud.slices.all()                    get all slices') +
             PTAG('opencloud.slices.filter({key: "value"})   filter using dictionary') +
             PTAG('opencloud.slices.get({key: "value"}))     get using dictionary')

  },

  _tutorial: function() {
    this._tutorialPtr = 0;
    return PTAG("This is a self-guided tutorial on the OpenCloud shell.") +
           PTAG("The tutorial is simple, more or less a few basic commands to try.") +
           PTAG("To go directly to any part tutorial, enter one of the commands t0, t1, t2...t10") +
           PTAG("Otherwise, use 'next' and 'back'. Start by typing 'next' and pressing enter.");
  },

  // go to the next step in the tutorial.
  _next: function() {
    if(this._tutorialPtr < this._tutorialMax) {
      return this['_t' + (this._tutorialPtr + 1)]();
    }
    else {
      return "You've reached the end of the tutorial. To go to the beginning, type 'tutorial'";
    }
  },

  // go to the previous step in the tutorial.
  _back: function() {
    if(this._tutorialPtr > 1) {
      return this['_t' + (this._tutorialPtr - 1)]();
    }
    else {
      return this._tutorial();
    }
  },

  _t1: function() {
    this._tutorialPtr = 1;
    return PTAG('1. JavaScript Shell') +
           PTAG('The first thing to notice is that the MongoDB shell is JavaScript-based.') +
           PTAG('So you can do things like:') +
           PTAG('  a = 5; ') +
           PTAG('  a * 10; ') +
           PTAG('  print(a); ') +
           PTAG("  for(i=0; i<10; i++) { print('hello'); }; ") +
           PTAG("Try a few JS commands; when you're ready to move on, enter 'next'");

  },

  _t2: function() {
    this._tutorialPtr = 2;
    return PTAG('2. List some objects') +
           PTAG('Try these:') +
           PTAG('    opencloud.slices.all();') +
           PTAG('    opencloud.slivers.all();') +
           PTAG('    opencloud.sites.all();') +
           PTAG('    opencloud.nodes.all();');

  },

  _t3: function() {
    this._tutorialPtr = 3;
    return PTAG('3. Filter some objects') +
           PTAG('Try these:') +
           PTAG('    opencloud.slices.get({name: "HyperCache"});');
           PTAG('    opencloud.nodes.filter({site_id: opencloud.sites.get({name: "Princeton"})["id"]});');

  },

  _t4: function() {
    this._tutorialPtr = 4;
    return PTAG('4. Available OpenCloud objects and methods') +
           PTAG('Try these:') +
           PTAG('    opencloud;') +
           PTAG('    opencloud.nodes;');

  },

  _getCommand: function(tokens) {
    if(tokens[0] && ArrayInclude(MongoKeywords,(tokens[0].value + '').toLowerCase())) {
      switch(tokens[0].value.toLowerCase()) {
        case 'help':
          return this._help;

        case 'tutorial':
          return this._tutorial;
        case 'next':
          return this._next;
        case 'back':
          return this._back;
        case 't0':
          return this._tutorial;
        case 't1':
          return this._t1;
        case 't2':
          return this._t2;
        case 't3':
          return this._t3;
        case 't4':
          return this._t4;
      }
    }
  }
};

function replaceAll(find, replace, str) {
  return str.replace(new RegExp(find, 'g'), replace);
}

/* stackoverflow: http://stackoverflow.com/questions/4810841/how-can-i-pretty-print-json-using-javascript */
function syntaxHighlight(json) {
    if ( json.hasOwnProperty("__str__")) {
        return syntaxHighlight(json.__str__());
    }
    if (typeof json != 'string') {
         json = JSON.stringify(json, undefined, "\t");
    }
    json = json.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
    return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match) {
        var cls = 'terminal_number';
        if (/^"/.test(match)) {
            if (/:$/.test(match)) {
                cls = 'terminal_key';
            } else {
                cls = 'terminal_string';
            }
        } else if (/true|false/.test(match)) {
            cls = 'terminal_boolean';
        } else if (/null/.test(match)) {
            cls = 'terminal_null';
        }
        return '' + match + '';
    });
}

$htmlFormat = function(obj) {
  //JSON.stringify(obj,undefined,2)
  result=replaceAll("\t"," ",replaceAll("\n","
",syntaxHighlight(obj))); //tojson(obj, ' ', ' ', true);
  return result;
}

function startTerminal() {
  var mongo       = new MongoHandler();
  var terminal    = new ReadLine({htmlForInput: DefaultInputHtml,
                                  handler: mongo._process,
                                  scoper: mongo});
  $("#terminal_help1").show();
  $("#terminal_help2").show();
  $("#terminal_wait").hide();

  $("#terminal").bind('click', function() { $(".readLine.active").focus(); });
};

$(document).ready(function() {
    updateOpenCloud(onLoaded = startTerminal);
});
<|endoftext|>


<commit_before>define([
    "use!backbone",
    "use!handlebars",
    "text!datum/datum.handlebars",
    "audio_video/AudioVideoView",
    "confidentiality_encryption/Confidential",
    "datum/Datum",
    "datum/DatumFieldView",
    "datum/DatumStateView",
    "datum/DatumTagsView",
    "app/UpdatingCollectionView",
    "libs/Utils"
], function(
    Backbone,
    Handlebars,
    datumTemplate,
    AudioVideoView,
    Confidential,
    Datum,
    DatumFieldView,
    DatumStateView,
    DatumTagsView,
    UpdatingCollectionView
) {
  var DatumView = Backbone.View.extend(
  /** @lends DatumView.prototype */
  {
    /**
     * @class The layout of a single Datum. It contains a datum state,
     *        datumFields, datumTags and a datum menu.
     *
     * @extends Backbone.View
     * @constructs
     */
    initialize : function() {
      // Create a AudioVideoView
      this.audioVideoView = new AudioVideoView({
        model : this.model.get("audioVideo"),
      });

      // Create a DatumStateView
      this.stateView = new DatumStateView({
        model : this.model.get("state"),
      });

      // Create a DatumTagView
      this.tagsview = new DatumTagsView({
        model : this.model.get("datumTag"),
      });

      // Create the DatumFieldsView
      this.datumFieldsView = new UpdatingCollectionView({
        collection           : this.model.get("datumFields"),
        childViewConstructor : DatumFieldView,
        childViewTagName     : "li",
      });
    },

    /**
     * The underlying model of the DatumView is a Datum.
     */
    model : Datum,

    /**
     * The audioVideoView is not a partial of the DatumView, it must be called to render it.
     */
    audioVideoView : AudioVideoView,

    /**
     * The stateView is a partial of the DatumView.
     */
    stateView : DatumStateView,

    /**
     * The tagview is a partial of the DatumView.
     */
    tagsview : DatumTagsView,

    /**
     * The datumFieldsView displays the all the DatumFieldViews.
     */
    datumFieldsView : UpdatingCollectionView,

    /**
     * Events that the DatumView is listening to and their handlers.
     */
    events : {
      "click #new" : "newDatum",
      "click .icon-lock" : "encryptDatum",
      "click .icon-unlock" : "decryptDatum",
      "click .datum_state_select" : "renderState",
      "click #clipboard" : "copyDatum",
      "change" : "updatePouch",
    },

    /**
     * The Handlebars template rendered as the DatumView.
     */
    template : Handlebars.compile(datumTemplate),

    /**
     * Renders the DatumView and all of its partials.
     */
    render : function() {
      Utils.debug("DATUM render: " + this.el);

      if (this.model != undefined) {
        // Display the DatumView
        this.setElement($("#datum-view"));
        $(this.el).html(this.template(this.model.toJSON()));

        // Display StateView
        this.stateView.render();

        // Display audioVideo View
        this.audioVideoView.render();

        // Display the DatumFieldsView
        this.datumFieldsView.el = this.$(".datum_fields_ul");
        this.datumFieldsView.render();
      } else {
        Utils.debug("\tDatum model was undefined");
      }

      return this;
    },

    renderState : function() {
      if (this.stausview != undefined) {
        this.stateView.render();
      }
    },

    /**
     * Encrypts the datum if it is confidential
     *
     * @returns {Boolean}
     */
    encryptDatum : function() {
      // TODO Redo to make it loop through the this.model.get("datumFields")
      // console.log("Fake encrypting");
      var confidential = appView.corpusView.model.confidential;

      if (confidential == undefined) {
        appView.corpusView.model.confidential = new Confidential();
        confidential = appView.corpusView.model.confidential;
      }

      this.model.set("utterance", confidential.encrypt(this.model
          .get("utterance")));
      this.model.set("morphemes", confidential.encrypt(this.model
          .get("morphemes")));
      this.model.set("gloss", confidential.encrypt(this.model.get("gloss")));
      this.model.set("translation", confidential.encrypt(this.model
          .get("translation")));

      // this.model.set("utterance", this.model.get("utterance").replace(/[^
      // -.]/g,"x"));
      // this.model.set("morphemes", this.model.get("morphemes").replace(/[^
      // -.]/g,"x"));
      // this.model.set("gloss", this.model.get("gloss").replace(/[^
      // -.]/g,"x"));
      // this.model.set("translation", this.model.get("translation").replace(/[^
      // -.]/g,"x"));
      this.render();
      $(".icon-lock").toggleClass("icon-lock icon-unlock");

      // console.log(confidential);
      // this.model.set()
    },

    /**
     * Decrypts the datum if it was encrypted
     */
    decryptDatum : function() {
      // TODO Redo to make it loop through the this.model.get("datumFields")
      var confidential = appView.corpusView.model.confidential;
      this.model.set("utterance", confidential.decrypt(this.model
          .get("utterance")));
      this.model.set("morphemes", confidential.decrypt(this.model
          .get("morphemes")));
      this.model.set("gloss", confidential.decrypt(this.model.get("gloss")));
      this.model.set("translation", confidential.decrypt(this.model
          .get("translation")));
      this.render();
      $(".icon-lock").toggleClass("icon-lock icon-unlock");
    },

    newDatum : function() {
      /*
       * First, we build a new datum model, this datum model then asks if it
       * belongs to a session if it belongs to a session it goes ahead and
       * renders a new datum if it does not belong to a session, it builds a new
       * session and renders a new session view. after the new session is sent
       * to pouch, then a new datumview can be rendered.
       */

      // var newDatum = new DatumView({model: new Datum()});
      // $("#fullscreen-datum-view").append(newDatum.render().el);
      // var sID = this.newDatum.get("sessionID");
      // console.log(sID);
      //
      // if(newDatum.sessionID == 0){
      // var newSession = new SessionView({model: new Session()});
      // $("#new-session-view").append(newSession.render().el);
      //
      // }
      Utils.debug("I'm a new datum!");
      return true;
    },

    needsSave : false,

    updatePouch : function() {
      this.needsSave = true;
    },

    /**
     * If the model needs to be saved, saves it.
     */
    saveScreen : function() {
      if (this.needsSave) {
        // Change the needsSave flag before saving just in case another change
        // happens
        // before the saving is done
        this.needsSave = false;

        Utils.debug("Saving the Datum");
        this.model.save();
      }
    },
    //Functions relating to the row of icon-buttons
    /**
     * The LaTeXiT function automatically mark-ups an example in LaTeX code
     * (\exg. \"a) and then copies it on the clipboard so that when the user
     * switches over to their LaTeX file they only need to paste it in.
     */
    laTeXiT : function() {
      return "";
    },
    /**
     * The copyDatum function copies all datum fields to the clipboard.
     */
    copyDatum : function() {

      var text = $(".datum_field_input").val() || [];
     // $(".datum_fields_ul")[0].focus();
    //  $(".datum_fields_ul")[0].select();
      console.log(text);

      return "";
    },

    /**
     * The duplicateDatum function opens a new datum field set with the fields
     * already filled exactly like the previous datum so that the user can
     * minimally edit the datum.
     */
    duplicateDatum : function() {
//      var datum = new Datum();
      return datum;
    }
  });

  return DatumView;
});
<commit_msg>updating references to audiovideo following new conventions rename o audio video<commit_after>define([
    "use!backbone",
    "use!handlebars",
    "text!datum/datum.handlebars",
    "audio_video/AudioVideoEditView",
    "confidentiality_encryption/Confidential",
    "datum/Datum",
    "datum/DatumFieldView",
    "datum/DatumStateView",
    "datum/DatumTagsView",
    "app/UpdatingCollectionView",
    "libs/Utils"
], function(
    Backbone,
    Handlebars,
    datumTemplate,
    AudioVideoEditView,
    Confidential,
    Datum,
    DatumFieldView,
    DatumStateView,
    DatumTagsView,
    UpdatingCollectionView
) {
  var DatumView = Backbone.View.extend(
  /** @lends DatumView.prototype */
  {
    /**
     * @class The layout of a single Datum. It contains a datum state,
     *        datumFields, datumTags and a datum menu.
     *
     * @extends Backbone.View
     * @constructs
     */
    initialize : function() {
      // Create a AudioVideoEditView
      this.audioVideoEditView = new AudioVideoEditView({
        model : this.model.get("audioVideo"),
      });

      // Create a DatumStateView
      this.stateView = new DatumStateView({
        model : this.model.get("state"),
      });

      // Create a DatumTagView
      this.tagsview = new DatumTagsView({
        model : this.model.get("datumTag"),
      });

      // Create the DatumFieldsView
      this.datumFieldsView = new UpdatingCollectionView({
        collection           : this.model.get("datumFields"),
        childViewConstructor : DatumFieldView,
        childViewTagName     : "li",
      });
    },

    /**
     * The underlying model of the DatumView is a Datum.
     */
    model : Datum,

    /**
     * The audioVideoEditView is not a partial of the DatumView, it must be called to render it.
     */
    audioVideoEditView : AudioVideoEditView,

    /**
     * The stateView is a partial of the DatumView.
     */
    stateView : DatumStateView,

    /**
     * The tagview is a partial of the DatumView.
     */
    tagsview : DatumTagsView,

    /**
     * The datumFieldsView displays the all the DatumFieldViews.
     */
    datumFieldsView : UpdatingCollectionView,

    /**
     * Events that the DatumView is listening to and their handlers.
     */
    events : {
      "click #new" : "newDatum",
      "click .icon-lock" : "encryptDatum",
      "click .icon-unlock" : "decryptDatum",
      "click .datum_state_select" : "renderState",
      "click #clipboard" : "copyDatum",
      "change" : "updatePouch",
    },

    /**
     * The Handlebars template rendered as the DatumView.
     */
    template : Handlebars.compile(datumTemplate),

    /**
     * Renders the DatumView and all of its partials.
     */
    render : function() {
      Utils.debug("DATUM render: " + this.el);

      if (this.model != undefined) {
        // Display the DatumView
        this.setElement($("#datum-view"));
        $(this.el).html(this.template(this.model.toJSON()));

        // Display StateView
        this.stateView.render();

        // Display audioVideo View
        this.audioVideoEditView.render();

        // Display the DatumFieldsView
        this.datumFieldsView.el = this.$(".datum_fields_ul");
        this.datumFieldsView.render();
      } else {
        Utils.debug("\tDatum model was undefined");
      }

      return this;
    },

    renderState : function() {
      if (this.stausview != undefined) {
        this.stateView.render();
      }
    },

    /**
     * Encrypts the datum if it is confidential
     *
     * @returns {Boolean}
     */
    encryptDatum : function() {
      // TODO Redo to make it loop through the this.model.get("datumFields")
      // console.log("Fake encrypting");
      var confidential = appView.corpusView.model.confidential;

      if (confidential == undefined) {
        appView.corpusView.model.confidential = new Confidential();
        confidential = appView.corpusView.model.confidential;
      }

      this.model.set("utterance", confidential.encrypt(this.model
          .get("utterance")));
      this.model.set("morphemes", confidential.encrypt(this.model
          .get("morphemes")));
      this.model.set("gloss", confidential.encrypt(this.model.get("gloss")));
      this.model.set("translation", confidential.encrypt(this.model
          .get("translation")));

      // this.model.set("utterance", this.model.get("utterance").replace(/[^
      // -.]/g,"x"));
      // this.model.set("morphemes", this.model.get("morphemes").replace(/[^
      // -.]/g,"x"));
      // this.model.set("gloss", this.model.get("gloss").replace(/[^
      // -.]/g,"x"));
      // this.model.set("translation", this.model.get("translation").replace(/[^
      // -.]/g,"x"));
      this.render();
      $(".icon-lock").toggleClass("icon-lock icon-unlock");

      // console.log(confidential);
      // this.model.set()
    },

    /**
     * Decrypts the datum if it was encrypted
     */
    decryptDatum : function() {
      // TODO Redo to make it loop through the this.model.get("datumFields")
      var confidential = appView.corpusView.model.confidential;
      this.model.set("utterance", confidential.decrypt(this.model
          .get("utterance")));
      this.model.set("morphemes", confidential.decrypt(this.model
          .get("morphemes")));
      this.model.set("gloss", confidential.decrypt(this.model.get("gloss")));
      this.model.set("translation", confidential.decrypt(this.model
          .get("translation")));
      this.render();
      $(".icon-lock").toggleClass("icon-lock icon-unlock");
    },

    newDatum : function() {
      /*
       * First, we build a new datum model, this datum model then asks if it
       * belongs to a session if it belongs to a session it goes ahead and
       * renders a new datum if it does not belong to a session, it builds a new
       * session and renders a new session view. after the new session is sent
       * to pouch, then a new datumview can be rendered.
       */

      // var newDatum = new DatumView({model: new Datum()});
      // $("#fullscreen-datum-view").append(newDatum.render().el);
      // var sID = this.newDatum.get("sessionID");
      // console.log(sID);
      //
      // if(newDatum.sessionID == 0){
      // var newSession = new SessionView({model: new Session()});
      // $("#new-session-view").append(newSession.render().el);
      //
      // }
      Utils.debug("I'm a new datum!");
      return true;
    },

    needsSave : false,

    updatePouch : function() {
      this.needsSave = true;
    },

    /**
     * If the model needs to be saved, saves it.
     */
    saveScreen : function() {
      if (this.needsSave) {
        // Change the needsSave flag before saving just in case another change
        // happens
        // before the saving is done
        this.needsSave = false;

        Utils.debug("Saving the Datum");
        this.model.save();
      }
    },
    //Functions relating to the row of icon-buttons
    /**
     * The LaTeXiT function automatically mark-ups an example in LaTeX code
     * (\exg. \"a) and then copies it on the clipboard so that when the user
     * switches over to their LaTeX file they only need to paste it in.
     */
    laTeXiT : function() {
      return "";
    },
    /**
     * The copyDatum function copies all datum fields to the clipboard.
     */
    copyDatum : function() {

      var text = $(".datum_field_input").val() || [];
     // $(".datum_fields_ul")[0].focus();
    //  $(".datum_fields_ul")[0].select();
      console.log(text);

      return "";
    },

    /**
     * The duplicateDatum function opens a new datum field set with the fields
     * already filled exactly like the previous datum so that the user can
     * minimally edit the datum.
     */
    duplicateDatum : function() {
//      var datum = new Datum();
      return datum;
    }
  });

  return DatumView;
});
<|endoftext|>