<commit_before>//abstract base class
function InboxStateObject() {
    this.baseUrl = $("input[name='baseUrl']").val();
}

InboxStateObject.prototype.undo = function() {

    var me = this;
    $(document).delegate("a.undo", "click", function(e) {
        var feedid    = $(this).attr('href');
        var href      = $(this).attr('hrefaction');
        var undo_type = $(this).attr('undo-type');
        var undo_mode = $('.inbox-state').val();

        var current_catid = me.elem.attr('catid');
        var sec       = 350;

        $("#" + me.feeds.feedid).fadeIn(sec);
        $(this).parents("."+undo_type).fadeOut(sec, function() { $(this).remove(); });
        $.ajax({  type: "POST"
                , url: href
                , data: {"mode": undo_mode, "feed_ids": [me.feeds], "cat_id": current_catid, "catstate": true}
                , success: function () {
                    var myStatus = new Status();
                    myStatus.notify("Processing...", 1000);
                  }
               });
        e.preventDefault();
    });
}

InboxStateObject.prototype.process = function() {

    var me = this;
    var is_single = $(me).attr('feedid');

    if(is_single) {
        $(me.elem).parents('.feedback').fadeOut(350, function() {
            var undo       = "  Undo";
            var close_checky = "  Close";
            var notify_msg = me.message + undo + close_checky;
            var notify     = $('
').addClass(me.identifier).html(notify_msg);
            var checky = $('.checky-bar');

            if(me.state == 0) {
                console.log(me.href);
                /*
                $.ajax({ type: "POST", url: me.href, data: {"mode": me.mode ,"feed_ids": [me.feeds], "cat_id": me.catid, "catstate": me.catstate }
                       , success: function() {
                             checky.html(notify).show();
                             var myStatus = new Status();
                             myStatus.notify("Processing...", 1000);
                         }
                });
                */
            } else {
                //if state is 1 then we're going back to the inbox
                console.log(me.href);
                /*
                $.ajax({ type: "POST", url: me.href, data: {"mode": "inbox" ,"feed_ids": [me.feeds], "cat_id": me.catid }
                      , success: function() {
                            checky.html("
Feedback has been sent to the " + "Inbox " + undo + close_checky + "
")
                            .show();

                            var myStatus = new Status();
                            myStatus.notify("Processing...", 1000);
                        }
                });
                */
            }

        });
    }

    $(document).delegate('a.close-checky', 'click', function(e) {
        $(this).parents('.check').remove();
        e.preventDefault();
    })

}

//child implementation classes
function PublishStateObject(elem) {
    InboxStateObject.apply(this, arguments);
    this.elem = elem;
    this.message = "Feedback has been published and moved to " + "Published Folder";
    this.mode    = "publish";
    this.feedid = $(elem).attr('feedid');
    this.href   = $(elem).attr('hrefaction');
    this.catid  = $(elem).attr('catid');
    this.catstate = $(elem).attr('cat-state');
    this.state  = $(elem).attr('state');
    this.feeds = {feedid: this.feedid};
    this.identifier = $(elem).attr('class');
}
PublishStateObject.prototype = new InboxStateObject();

function FeatureStateObject(elem) {
    InboxStateObject.apply(this, arguments);
    this.elem = elem;
    this.message = "Feedback has been published and moved to " + "Featured Folder";
    this.mode    = "feature";
    this.feedid = $(elem).attr('feedid');
    this.href   = $(elem).attr('hrefaction');
    this.catid  = $(elem).attr('catid');
    this.catstate = $(elem).attr('cat-state');
    this.state  = $(elem).attr('state');
    this.feeds = {feedid: this.feedid};

    this.identifier = $(elem).attr('class');
}
FeatureStateObject.prototype = new InboxStateObject();

function RemoveStateObject(elem) {
    InboxStateObject.apply(this, arguments);
    this.elem = elem;
    this.message = "Feedback has been " + "deleted";
    this.mode    = "delete";
    this.feedid = $(elem).attr('feedid');
    this.href   = $(elem).attr('hrefaction');
    this.catid  = $(elem).attr('catid');
    this.catstate = $(elem).attr('cat-state');
    this.state  = $(elem).attr('state');
    this.feeds = {feedid: this.feedid};
    this.identifier = $(elem).attr('class');
}
RemoveStateObject.prototype = new InboxStateObject();

function CatPickObject(elem) {
    InboxStateObject.apply(this, arguments);
    this.elem = elem;
    this.catstate = $(elem).attr('cat-state');
    if(this.catstate == 'default') {
        this.message = "Feedback has been sent to " + "Inbox";
    } else {
        this.message = "Feedback has been sent to " + "Filed Feedback";
    }
    this.mode    = "fileas";
    $(elem).parents('div.category-picker-holder').hide();
    this.feedid = $(elem).attr('feedid');
    this.href   = $(elem).attr('hrefaction');
    this.catid  = $(elem).attr('catid');
    this.catstate = $(elem).attr('cat-state');
    this.state  = $(elem).attr('state');
    this.feeds = {feedid: this.feedid};
    this.identifier = $(elem).attr('class');
}

CatPickObject.prototype = new InboxStateObject();
CatPickObject.prototype.process = function() {
    var me = this;
    if(location.pathname.match(/filed|modifyfeedback/)) {
        $.ajax({ type: "POST", url: me.href, data: {"mode": me.mode ,"feed_ids": [me.feeds], "cat_id": me.catid, "catstate": me.catstate }, success: function() {
            if(me.catstate == "default") {
                $(me.elem).parents('.feedback').fadeOut(350);
            }
            var myStatus = new Status();
            myStatus.notify("Processing...", 1000);
        }});
    } else {
        $(this.elem).parents('.feedback').fadeOut(350, function() {
            var undo       = " Undo";
            var close_checky = "  Close";
            var notify_msg = me.message + undo + close_checky;
            var notify     = $('
').addClass(me.identifier).html(notify_msg);
            var checky = $('.checky-bar');

            if(me.state == 0) {
                $.ajax({ type: "POST", url: me.href, data: {"mode": me.mode ,"feed_ids": [me.feeds], "cat_id": me.catid, "catstate": me.catstate }, success: function()
                    {

                        var myStatus = new Status();
                        myStatus.notify("Processing...", 1000);
                        checky.html(notify).show();
                    }
                });
            } else {
                //if state is 1 then we're going back to the inbox
                $.ajax({ type: "POST", url: me.href, data: {"mode": "inbox" ,"feed_ids": [me.feeds], "cat_id": me.catid }, success: function()
                    {

                        var myStatus = new Status();
                        myStatus.notify("Processing...", 1000);
                        checky.html("
Feedback has been sent to the " + "Inbox " + undo + close_checky +"
")
                        .show();
                    }
                });
            }
        });

    }

    $(document).delegate('a.close-checky', 'click', function(e) {
        $(this).parents('.check').remove();
        e.preventDefault();
    })
}

//Factory
function InboxStatusChange(opts)  {
    this.inbox_controls = opts;
}

InboxStatusChange.prototype.initialize = function() {
    var me = this;
    $(document).delegate(me.inbox_controls, 'click', function(e) {
        var identifier = $(this).attr('class');
        var us = $(this);

        $.ajax({url: "/feedback/bust_hostfeed_data"});

        if(identifier == 'check') {
            var check = new PublishStateObject(us);
            check.process();
            check.undo();
        }

        if(identifier == 'feature') {
            var feature = new FeatureStateObject(us);
            feature.process();
            feature.undo();
        }

        if(identifier == 'remove' || identifier == 'popup-delete') {
            var remove = new RemoveStateObject(us);
            remove.process();
            remove.undo();
        }

    })
}
<commit_msg>pwets<commit_after>//abstract base class
function InboxStateObject() {
    this.baseUrl = $("input[name='baseUrl']").val();
}

InboxStateObject.prototype.undo = function() {

    var me = this;
    $(document).delegate("a.undo", "click", function(e) {
        var feedid    = $(this).attr('href');
        var href      = $(this).attr('hrefaction');
        var undo_type = $(this).attr('undo-type');
        var undo_mode = $('.inbox-state').val();

        var current_catid = me.elem.attr('catid');
        var sec       = 350;

        $("#" + me.feeds.feedid).fadeIn(sec);
        $(this).parents("."+undo_type).fadeOut(sec, function() { $(this).remove(); });
        $.ajax({  type: "POST"
                , url: href
                , data: {"mode": undo_mode, "feed_ids": [me.feeds], "cat_id": current_catid, "catstate": true}
                , success: function () {
                    var myStatus = new Status();
                    myStatus.notify("Processing...", 1000);
                  }
               });
        e.preventDefault();
    });
}

InboxStateObject.prototype.process = function() {

    var me = this;
    var is_single = $(me).attr('feedid');

    if(is_single) {
        $(me.elem).parents('.feedback').fadeOut(350, function() {
            var undo       = "  Undo";
            var close_checky = "  Close";
            var notify_msg = me.message + undo + close_checky;
            var notify     = $('
').addClass(me.identifier).html(notify_msg);
            var checky = $('.checky-bar');

            if(me.state == 0) {
                console.log(me.href);
                console.log(me.state);
                /*
                $.ajax({ type: "POST", url: me.href, data: {"mode": me.mode ,"feed_ids": [me.feeds], "cat_id": me.catid, "catstate": me.catstate }
                       , success: function() {
                             checky.html(notify).show();
                             var myStatus = new Status();
                             myStatus.notify("Processing...", 1000);
                         }
                });
                */
            } else {
                //if state is 1 then we're going back to the inbox
                console.log(me.href);
                console.log(me.state);
                /*
                $.ajax({ type: "POST", url: me.href, data: {"mode": "inbox" ,"feed_ids": [me.feeds], "cat_id": me.catid }
                      , success: function() {
                            checky.html("
Feedback has been sent to the " + "Inbox " + undo + close_checky + "
")
                            .show();

                            var myStatus = new Status();
                            myStatus.notify("Processing...", 1000);
                        }
                });
                */
            }

        });
    }

    $(document).delegate('a.close-checky', 'click', function(e) {
        $(this).parents('.check').remove();
        e.preventDefault();
    })

}

//child implementation classes
function PublishStateObject(elem) {
    InboxStateObject.apply(this, arguments);
    this.elem = elem;
    this.message = "Feedback has been published and moved to " + "Published Folder";
    this.mode    = "publish";
    this.feedid = $(elem).attr('feedid');
    this.href   = $(elem).attr('hrefaction');
    this.catid  = $(elem).attr('catid');
    this.catstate = $(elem).attr('cat-state');
    this.state  = $(elem).attr('state');
    this.feeds = {feedid: this.feedid};
    this.identifier = $(elem).attr('class');
}
PublishStateObject.prototype = new InboxStateObject();

function FeatureStateObject(elem) {
    InboxStateObject.apply(this, arguments);
    this.elem = elem;
    this.message = "Feedback has been published and moved to " + "Featured Folder";
    this.mode    = "feature";
    this.feedid = $(elem).attr('feedid');
    this.href   = $(elem).attr('hrefaction');
    this.catid  = $(elem).attr('catid');
    this.catstate = $(elem).attr('cat-state');
    this.state  = $(elem).attr('state');
    this.feeds = {feedid: this.feedid};
    this.identifier = $(elem).attr('class');
}
FeatureStateObject.prototype = new InboxStateObject();

function RemoveStateObject(elem) {
    InboxStateObject.apply(this, arguments);
    this.elem = elem;
    this.message = "Feedback has been " + "deleted";
    this.mode    = "delete";
    this.feedid = $(elem).attr('feedid');
    this.href   = $(elem).attr('hrefaction');
    this.catid  = $(elem).attr('catid');
    this.catstate = $(elem).attr('cat-state');
    this.state  = $(elem).attr('state');
    this.feeds = {feedid: this.feedid};
    this.identifier = $(elem).attr('class');
}
RemoveStateObject.prototype = new InboxStateObject();

function CatPickObject(elem) {
    InboxStateObject.apply(this, arguments);
    this.elem = elem;
    this.catstate = $(elem).attr('cat-state');
    if(this.catstate == 'default') {
        this.message = "Feedback has been sent to " + "Inbox";
    } else {
        this.message = "Feedback has been sent to " + "Filed Feedback";
    }
    this.mode    = "fileas";
    $(elem).parents('div.category-picker-holder').hide();
    this.feedid = $(elem).attr('feedid');
    this.href   = $(elem).attr('hrefaction');
    this.catid  = $(elem).attr('catid');
    this.catstate = $(elem).attr('cat-state');
    this.state  = $(elem).attr('state');
    this.feeds = {feedid: this.feedid};
    this.identifier = $(elem).attr('class');
}

CatPickObject.prototype = new InboxStateObject();
CatPickObject.prototype.process = function() {
    var me = this;
    if(location.pathname.match(/filed|modifyfeedback/)) {
        $.ajax({ type: "POST", url: me.href, data: {"mode": me.mode ,"feed_ids": [me.feeds], "cat_id": me.catid, "catstate": me.catstate }, success: function() {
            if(me.catstate == "default") {
                $(me.elem).parents('.feedback').fadeOut(350);
            }
            var myStatus = new Status();
            myStatus.notify("Processing...", 1000);
        }});
    } else {
        $(this.elem).parents('.feedback').fadeOut(350, function() {
            var undo       = " Undo";
            var close_checky = "  Close";
            var notify_msg = me.message + undo + close_checky;
            var notify     = $('
').addClass(me.identifier).html(notify_msg);
            var checky = $('.checky-bar');

            if(me.state == 0) {
                $.ajax({ type: "POST", url: me.href, data: {"mode": me.mode ,"feed_ids": [me.feeds], "cat_id": me.catid, "catstate": me.catstate }, success: function()
                    {

                        var myStatus = new Status();
                        myStatus.notify("Processing...", 1000);
                        checky.html(notify).show();
                    }
                });
            } else {
                //if state is 1 then we're going back to the inbox
                $.ajax({ type: "POST", url: me.href, data: {"mode": "inbox" ,"feed_ids": [me.feeds], "cat_id": me.catid }, success: function()
                    {

                        var myStatus = new Status();
                        myStatus.notify("Processing...", 1000);
                        checky.html("
Feedback has been sent to the " + "Inbox " + undo + close_checky +"
")
                        .show();
                    }
                });
            }
        });

    }

    $(document).delegate('a.close-checky', 'click', function(e) {
        $(this).parents('.check').remove();
        e.preventDefault();
    })
}

//Factory
function InboxStatusChange(opts)  {
    this.inbox_controls = opts;
}

InboxStatusChange.prototype.initialize = function() {
    var me = this;
    $(document).delegate(me.inbox_controls, 'click', function(e) {
        var identifier = $(this).attr('class');
        var us = $(this);

        $.ajax({url: "/feedback/bust_hostfeed_data"});

        if(identifier == 'check') {
            var check = new PublishStateObject(us);
            check.process();
            check.undo();
        }

        if(identifier == 'feature') {
            var feature = new FeatureStateObject(us);
            feature.process();
            feature.undo();
        }

        if(identifier == 'remove' || identifier == 'popup-delete') {
            var remove = new RemoveStateObject(us);
            remove.process();
            remove.undo();
        }

    })
}
<|endoftext|>


<commit_before>// Includes file dependencies
define([
], function () {

    var ConfigPubstorm = {
        serverURL: "https://stagingapi.undergroundtheater.org/parse",
        facebookAppId: "1606746326305984",
        redirect_uri: "https://stagingpatron.undergroundtheater.org/index.html"
    };

    var ConfigGnuLorienDev = ConfigPubstorm;

    return ConfigGnuLorienDev;

});<commit_msg>Add new sample troupe id to the test configuration<commit_after>// Includes file dependencies
define([
], function () {

    var ConfigPubstorm = {
        serverURL: "https://stagingapi.undergroundtheater.org/parse",
        facebookAppId: "1606746326305984",
        redirect_uri: "https://stagingpatron.undergroundtheater.org/index.html",
        SAMPLE_TROUPE_ID: "WOad4CBTsG"
    };

    var ConfigGnuLorienDev = ConfigPubstorm;

    return ConfigGnuLorienDev;

});<|endoftext|>


<commit_before><commit_msg>Deleting gallery.js file and replacing with gallery.jsx file<commit_after><|endoftext|>


<commit_before>// main requestAnimFrame for all the animation
window.requestAnimFrame = (function () {
    return window.requestAnimationFrame ||
    window.webkitRequestAnimationFrame ||
    window.mozRequestAnimationFrame ||
    window.oRequestAnimationFrame ||
    window.msRequestAnimationFrame ||
    function (callback) {
        window.setTimeout(callback, 1000 / 30);
    };
})();

//// for drawing the joystick
var control_canvas,
c, // context 2D
halfWidth,
halfHeight,
leftPointerID = -1,	// variable for mouse left button cursor interactions
leftPointerPos = new Vector2(0, 0),
leftPointerStartPos = new Vector2(0, 0),
leftVector = new Vector2(0, 0);
arrow = new VectorLED(0, 0, 0, 0);	// vector for LED direction
joy_arrow = new VectorLED(0, 0, 0, 0);	// vector used for direction calculations

var touches; // collections of pointers

/////////////////////////////// ARDUINO SETUP

// LED setup
//var led1; //-90 D
//var led2; //0 R
//var led3; //90 U
//var led4; //180=-180 L
var max_val; // threshold radius of the joystick
var LEDloopON = false;

///////////////////////////// ARDUINO SETUP END

var username = "noname";	// for socket.io
var socket;					// for socket.io

document.addEventListener("DOMContentLoaded", init);

window.onorientationchange = resetCanvas;	// resize when you resize the browser
window.onresize = resetCanvas;

function init() {
    setupCanvas();
    setupD3();
    //setupMotionDetection();

    touches = new Collection();

    onReady();
}

function onReady() {
////// jQuery for the socket.io
    // username input
        $('input[name=setUsername]').click(function(){
        	if($('input[name=usernameTxt]').val() != ""){
                username = $('input[name=usernameTxt]').val();
                    var msg = {type:'setUsername', user:username};
                    socket.json.send(msg);
                }
            $('#username').slideUp("slow",function(){
                $('#entergame').slideDown("slow");
            });
        });

        $("input[name=gamestartBtn]").click(function(){
            resetGame();
        });
    // chats and score postings
        socket = new io.connect('http://171.65.102.132:3002');
        var chat = $('#chat');
        var board = $('#board');

        socket.on('connect', function() {
            console.log("Connected!");
            socket.emit('message', {channel:'realtime'});
        });

        socket.on('message', function(message){
		var str = message.split("&&");
		if (Number(str[0]))
		{
			chat.append(str[1] + '
');
		}else{
			var ledArray = str[1].split("^");
			arrow.int1 = ledArray[0];
			arrow.int2 = ledArray[1];
			arrow.int3 = ledArray[2];
			arrow.int4 = ledArray[3];
		}
        });

        socket.on('postscore', function(score){
                board.empty();
                for (var i=0;i<score.length;i++){
                        if(i==0){
                                board.append(''+ score[i][0]+'  :  '+score[i][1]+'
');
                        }else{
                                board.append(score[i][0]+'  :  '+score[i][1]+ '
');
                        }
                }
                board.fadeOut('fast');
                board.fadeIn('fast');
                board.fadeOut('fast');
                board.fadeIn('fast');
        });

        socket.on('disconnect', function() {
                console.log('disconnected');
                chat.html("Disconnected!");
        });

        $("input[name=sendBtn]").click(function(){
                var msg = {type:'chat',message:username + " : " + $("input[name=chatTxt]").val()}
                socket.json.send(msg);
                $("input[name=chatTxt]").val("");
        });

////// EventListeners for joystick canvas
    control_canvas.addEventListener('pointerdown', onPointerDown, false);
    control_canvas.addEventListener('pointermove', onPointerMove, false);
    control_canvas.addEventListener('pointerup', onPointerUp, false);
    control_canvas.addEventListener('pointerout', onPointerUp, false);
    // start drawing joystick loop
    requestAnimFrame(joystick_draw);
}

function joystick_draw() {
    c.clearRect(0, 0, control_canvas.width, control_canvas.height);

    c.beginPath();
    c.moveTo(halfWidth, halfHeight-4);
    c.strokeStyle = "rgba(250, 102, 0, 1)";
    c.lineWidth = 2;
    c.lineTo(halfWidth, halfHeight+4);
    c.stroke();

    c.beginPath();
    c.moveTo(halfWidth+4, halfHeight);
    c.strokeStyle = "rgba(250, 102, 0, 1)";
    c.lineWidth = 2;
    c.lineTo(halfWidth-4, halfHeight);
    c.stroke();

    drawCircles(halfWidth, halfHeight);

        //// mouse event loop
    touches.forEach(function (touch) {
        if (touch.identifier == leftPointerID) {
	// draw the joystick in the control canvas
            var alpha = arrow.trimArrow(leftVector, max_val);

            c.beginPath();
            c.fillStyle = "rgba(250, 102, 0, 1)";
            c.arc(leftPointerPos.x, leftPointerPos.y, 16, 0, Math.PI * 2, true);
            c.fill();

            c.beginPath();
            c.moveTo(leftPointerStartPos.x,leftPointerStartPos.y);
            c.strokeStyle = "rgba(250, 102, 0, 1)";
            c.lineTo(leftPointerStartPos.x+max_val*(arrow.int2-arrow.int4),leftPointerStartPos.y+max_val*(arrow.int1-arrow.int3));
            c.lineWidth = 3;
            c.stroke();

            c.beginPath();
            c.fillStyle = "rgba(255, 255, 255, "+alpha+")";
            c.arc(halfWidth, halfHeight, 16, 0, Math.PI * 2, true);
            c.fill();

            c.beginPath();
            c.fillStyle = "#fff";
            c.fillText(alpha,halfWidth-10, halfHeight-25);

            c.beginPath();
            c.fillStyle = "#dd6600";
            var theta = leftVector.angle();
            c.fillText(theta.toFixed(0),leftPointerPos.x+10, leftPointerPos.y-20);
            // send the input to johnny five

        }
    });

    requestAnimFrame(joystick_draw);
    if(LEDloopON)
    {
        changeLED(1);
    }
}

function givePointerType(event) {
    switch (event.pointerType) {
        case event.POINTER_TYPE_MOUSE:
            return "MOUSE";
            break;
        case event.POINTER_TYPE_PEN:
            return "PEN";
            break;
        case event.POINTER_TYPE_TOUCH:
            return "TOUCH";
            break;
    }
}

function onPointerDown(e) {
    var newPointer = { identifier: e.pointerId, x: e.clientX, y: e.clientY, type: givePointerType(e) };
    leftPointerID = e.pointerId;
    leftPointerStartPos.reset(halfWidth, halfHeight);
    leftPointerPos.copyFrom(leftPointerStartPos);
    leftVector.reset(0, 0);
    joy_arrow.reset(0, 0, 0, 0);
    touches.add(e.pointerId, newPointer);
}

function onPointerMove(e) {
    if (leftPointerID == e.pointerId) {
        leftPointerPos.reset(e.offsetX, e.offsetY);
        leftVector.copyFrom(leftPointerPos);
        leftVector.minusEq(leftPointerStartPos);
        joy_arrow.setArrow(leftVector, max_val);
        LEDloopON = true;
    }
    else {
        if (touches.item(e.pointerId)) {
            touches.item(e.pointerId).x = e.clientX;
            touches.item(e.pointerId).y = e.clientY;
        }
    }
}

function onPointerUp(e) {
    if (leftPointerID == e.pointerId) {
        leftPointerID = -1;
        leftVector.reset(0, 0);
    }
    leftVector.reset(0, 0);
    joy_arrow.reset(0, 0, 0, 0);
    touches.remove(e.pointerId);
    LEDloopON = false; // we are no longer monitoring the mouse input
    changeLED(0); // turn off all LEDs
}

function setupCanvas() {
    control_canvas = document.getElementById('controlCanvas');
    c = control_canvas.getContext('2d');
    resetCanvas();
    c.strokeStyle = "#ffffff";
    c.lineWidth = 2;
}

// Arduino control functions
function changeLED(LEDon) {
    if(LEDon)
    {
	var msg =
	{type:'sendarrow', user:username, led1:joy_arrow.int1, led2:joy_arrow.int2, led3:joy_arrow.int3, led4:joy_arrow.int4};
    	socket.json.send(msg);
    }
    else
    {
	var msg =
	{type:'sendarrow', user:username, led1:0, led2:0, led3:0, led4:0};
    	socket.json.send(msg);
    }
}

function resetCanvas(e) {
    max_val = (document.getElementById("joystickArea").offsetWidth-100)/2;
    console.log('max_val :' + max_val);
    // resize the canvas - but remember - this clears the canvas too.

    control_canvas.width = document.getElementById("joystickArea").offsetWidth-20;
    control_canvas.height = control_canvas.width;
    console.log('canvas w: '+document.getElementById("controlCanvas").offsetWidth-20);
    console.log('canvas h: '+document.getElementById("controlCanvas").offsetHeight-20);
    console.log('canvas x: '+document.getElementById("controlCanvas").offsetX);
    console.log('canvas y: '+document.getElementById("controlCanvas").offsetY);
    halfWidth = (control_canvas.width)/2;
    halfHeight = (control_canvas.height)/2;

    // make sure we scroll to the top left.
    window.scrollTo(0, 0);
}
<commit_msg>joystick debug<commit_after>// main requestAnimFrame for all the animation
window.requestAnimFrame = (function () {
    return window.requestAnimationFrame ||
    window.webkitRequestAnimationFrame ||
    window.mozRequestAnimationFrame ||
    window.oRequestAnimationFrame ||
    window.msRequestAnimationFrame ||
    function (callback) {
        window.setTimeout(callback, 1000 / 30);
    };
})();

//// for drawing the joystick
var control_canvas,
c, // context 2D
halfWidth,
halfHeight,
rect_joy,
leftPointerID = -1,	// variable for mouse left button cursor interactions
leftPointerPos = new Vector2(0, 0),
leftPointerStartPos = new Vector2(0, 0),
leftVector = new Vector2(0, 0);
arrow = new VectorLED(0, 0, 0, 0);	// vector for LED direction
joy_arrow = new VectorLED(0, 0, 0, 0);	// vector used for direction calculations

var touches; // collections of pointers

/////////////////////////////// ARDUINO SETUP

// LED setup
//var led1; //-90 D
//var led2; //0 R
//var led3; //90 U
//var led4; //180=-180 L
var max_val; // threshold radius of the joystick
var LEDloopON = false;

///////////////////////////// ARDUINO SETUP END

var username = "noname";	// for socket.io
var socket;					// for socket.io

document.addEventListener("DOMContentLoaded", init);

window.onorientationchange = resetCanvas;	// resize when you resize the browser
window.onresize = resetCanvas;

function init() {
    setupCanvas();
    setupD3();
    //setupMotionDetection();

    touches = new Collection();

    onReady();
}

function onReady() {
////// jQuery for the socket.io
    // username input
        $('input[name=setUsername]').click(function(){
        	if($('input[name=usernameTxt]').val() != ""){
                username = $('input[name=usernameTxt]').val();
                    var msg = {type:'setUsername', user:username};
                    socket.json.send(msg);
                }
            $('#username').slideUp("slow",function(){
                $('#entergame').slideDown("slow");
            });
        });

        $("input[name=gamestartBtn]").click(function(){
            resetGame();
        });
    // chats and score postings
        socket = new io.connect('http://171.65.102.132:3002');
        var chat = $('#chat');
        var board = $('#board');

        socket.on('connect', function() {
            console.log("Connected!");
            socket.emit('message', {channel:'realtime'});
        });

        socket.on('message', function(message){
		var str = message.split("&&");
		if (Number(str[0]))
		{
			chat.append(str[1] + '
');
		}else{
			var ledArray = str[1].split("^");
			arrow.int1 = ledArray[0];
			arrow.int2 = ledArray[1];
			arrow.int3 = ledArray[2];
			arrow.int4 = ledArray[3];
		}
        });

        socket.on('postscore', function(score){
                board.empty();
                for (var i=0;i<score.length;i++){
                        if(i==0){
                                board.append(''+ score[i][0]+'  :  '+score[i][1]+'
');
                        }else{
                                board.append(score[i][0]+'  :  '+score[i][1]+ '
');
                        }
                }
                board.fadeOut('fast');
                board.fadeIn('fast');
                board.fadeOut('fast');
                board.fadeIn('fast');
        });

        socket.on('disconnect', function() {
                console.log('disconnected');
                chat.html("Disconnected!");
        });

        $("input[name=sendBtn]").click(function(){
                var msg = {type:'chat',message:username + " : " + $("input[name=chatTxt]").val()}
                socket.json.send(msg);
                $("input[name=chatTxt]").val("");
        });

////// EventListeners for joystick canvas
    control_canvas.addEventListener('pointerdown', onPointerDown, false);
    control_canvas.addEventListener('pointermove', onPointerMove, false);
    control_canvas.addEventListener('pointerup', onPointerUp, false);
    control_canvas.addEventListener('pointerout', onPointerUp, false);
    // start drawing joystick loop
    requestAnimFrame(joystick_draw);
}

function joystick_draw() {
    c.clearRect(0, 0, control_canvas.width, control_canvas.height);

    c.beginPath();
    c.moveTo(halfWidth, halfHeight-4);
    c.strokeStyle = "rgba(250, 102, 0, 1)";
    c.lineWidth = 2;
    c.lineTo(halfWidth, halfHeight+4);
    c.stroke();

    c.beginPath();
    c.moveTo(halfWidth+4, halfHeight);
    c.strokeStyle = "rgba(250, 102, 0, 1)";
    c.lineWidth = 2;
    c.lineTo(halfWidth-4, halfHeight);
    c.stroke();

    drawCircles(halfWidth, halfHeight);

        //// mouse event loop
    touches.forEach(function (touch) {
        if (touch.identifier == leftPointerID) {
	// draw the joystick in the control canvas
            var alpha = arrow.trimArrow(leftVector, max_val);

            c.beginPath();
            c.fillStyle = "rgba(250, 102, 0, 1)";
            c.arc(leftPointerPos.x, leftPointerPos.y, 16, 0, Math.PI * 2, true);
            c.fill();

            c.beginPath();
            c.moveTo(leftPointerStartPos.x,leftPointerStartPos.y);
            c.strokeStyle = "rgba(250, 102, 0, 1)";
            c.lineTo(leftPointerStartPos.x+max_val*(arrow.int2-arrow.int4),leftPointerStartPos.y+max_val*(arrow.int1-arrow.int3));
            c.lineWidth = 3;
            c.stroke();

            c.beginPath();
            c.fillStyle = "rgba(255, 255, 255, "+alpha+")";
            c.arc(halfWidth, halfHeight, 16, 0, Math.PI * 2, true);
            c.fill();

            c.beginPath();
            c.fillStyle = "#fff";
            c.fillText(alpha,halfWidth-10, halfHeight-25);

            c.beginPath();
            c.fillStyle = "#dd6600";
            var theta = leftVector.angle();
            c.fillText(theta.toFixed(0),leftPointerPos.x+10, leftPointerPos.y-20);
            // send the input to johnny five

        }
    });

    requestAnimFrame(joystick_draw);
    if(LEDloopON)
    {
        changeLED(1);
    }
}

function givePointerType(event) {
    switch (event.pointerType) {
        case event.POINTER_TYPE_MOUSE:
            return "MOUSE";
            break;
        case event.POINTER_TYPE_PEN:
            return "PEN";
            break;
        case event.POINTER_TYPE_TOUCH:
            return "TOUCH";
            break;
    }
}

function onPointerDown(e) {
    var newPointer = { identifier: e.pointerId, x: e.clientX, y: e.clientY, type: givePointerType(e) };
    leftPointerID = e.pointerId;
    leftPointerStartPos.reset(halfWidth, halfHeight);
    leftPointerPos.copyFrom(leftPointerStartPos);
    leftVector.reset(0, 0);
    joy_arrow.reset(0, 0, 0, 0);
    touches.add(e.pointerId, newPointer);
}

function onPointerMove(e) {
    if (leftPointerID == e.pointerId) {
        leftPointerPos.reset(e.pageX-rect_joy.left, e.pageY-rect_joy.top);
        leftVector.copyFrom(leftPointerPos);
        leftVector.minusEq(leftPointerStartPos);
        joy_arrow.setArrow(leftVector, max_val);
        LEDloopON = true;
    }
    else {
        if (touches.item(e.pointerId)) {
            touches.item(e.pointerId).x = e.clientX;
            touches.item(e.pointerId).y = e.clientY;
        }
    }
}

function onPointerUp(e) {
    if (leftPointerID == e.pointerId) {
        leftPointerID = -1;
        leftVector.reset(0, 0);
    }
    leftVector.reset(0, 0);
    joy_arrow.reset(0, 0, 0, 0);
    touches.remove(e.pointerId);
    LEDloopON = false; // we are no longer monitoring the mouse input
    changeLED(0); // turn off all LEDs
}

function setupCanvas() {
    control_canvas = document.getElementById('controlCanvas');
    c = control_canvas.getContext('2d');
    resetCanvas();
    c.strokeStyle = "#ffffff";
    c.lineWidth = 2;
}

// Arduino control functions
function changeLED(LEDon) {
    if(LEDon)
    {
	var msg =
	{type:'sendarrow', user:username, led1:joy_arrow.int1, led2:joy_arrow.int2, led3:joy_arrow.int3, led4:joy_arrow.int4};
    	socket.json.send(msg);
    }
    else
    {
	var msg =
	{type:'sendarrow', user:username, led1:0, led2:0, led3:0, led4:0};
    	socket.json.send(msg);
    }
}

function resetCanvas(e) {
    max_val = (document.getElementById("joystickArea").offsetWidth-100)/2;
    console.log('max_val :' + max_val);
    // resize the canvas - but remember - this clears the canvas too.

    control_canvas.width = document.getElementById("joystickArea").offsetWidth-20;
    control_canvas.height = control_canvas.width;
    halfWidth = (control_canvas.width)/2;
    halfHeight = (control_canvas.height)/2;

    rect_joy = control_canvas.getBoundingClientRect();

    // make sure we scroll to the top left.
    window.scrollTo(0, 0);
}
<|endoftext|>


<commit_before>// caching frequently-accessed selectors
var navBoxHeader = $('#navBoxHeader');
var welcomeMessage = $('#welcomeMsgArea');
var mainLabel = $('#mainLabel');
var activityIndicator = $('#activityIndicator');
var activityIndicatorTop = Math.floor($(window).height() / 2);

/*
 The purpose of the functions "prepare...ForDevice()" is to establish the
 buttons that can be displayed on the navBar and the function of the buttons
 where they differ.
 The visibility of the welcome/intro message is also controlled at this stage.
*/

function prepareAnswerSpacesListViewForDevice()
{
}

function prepareMasterCategoriesViewForDevice()
{
	$.bbq.removeState();
	categoriesView.find('.welcomeBox').removeClass('hidden');
	navBoxHeader.addClass('hidden');
}

function prepareCategoriesViewForDevice()
{
	var categoriesView = $('#categoriesView');
  if (hasMasterCategories)
  {
		$.bbq.pushState({ m: currentMasterCategory }, 2);
		categoriesView.find('.welcomeBox').addClass('hidden');
		navBoxHeader.removeClass('hidden');
  }
  else
  {
		$.bbq.removeState();
		categoriesView.find('.welcomeBox').removeClass('hidden');
		navBoxHeader.addClass('hidden');
  }
}

function prepareKeywordListViewForDevice(category)
{
	var keywordListView = $('#keywordListView');
	var hashState = {};
	if (hasCategories)
		hashState['c'] = currentCategory;
	if (hasVisualCategories)
	{
		keywordListView.find('.welcomeBox').addClass('hidden');
		navBoxHeader.removeClass('hidden');
	}
  else if (hasMasterCategories)
  {
		keywordListView.find('.welcomeBox').addClass('hidden');
		navBoxHeader.removeClass('hidden');
		hashState['m'] = currentMasterCategory;
  }
  else
  {
		keywordListView.find('.welcomeBox').removeClass('hidden');
		navBoxHeader.addClass('hidden');
  }
	$.bbq.pushState(hashState, 2);
}

function prepareKeywordViewForDevice(oneKeyword, showHelp)
{
	$.bbq.pushState({ k: currentKeyword }, 2);
	if (oneKeyword)
		navBoxHeader.addClass('hidden');
	else
		navBoxHeader.removeClass('hidden');
	if (showHelp)
		navBoxHeader.find('.helpButton').removeClass('hidden');
	else
		navBoxHeader.find('.helpButton').addClass('hidden');
}

function prepareAnswerViewForDevice()
{
	$.bbq.pushState({ a: currentKeyword }, 2);
	if (answerSpaceOneKeyword)
		navBoxHeader.addClass('hidden');
	else
		navBoxHeader.removeClass('hidden');
}

function prepareSecondLevelAnswerViewForDevice(keyword, arg)
{
	$.bbq.pushState({ a2k: keyword, a2a: arg }, 2);
	navBoxHeader.removeClass('hidden');
  navBoxHeader.find('.helpButton').addClass('hidden');
}

function prepareHelpViewForDevice()
{
	$.bbq.pushState({ h: 'H' });
	var helpView = $('#helpView');
	navBoxHeader.removeClass('hidden');
  helpView.find('#backButton').addClass('hidden');
  helpView.find('#helpButton').removeClass('hidden');
}

function prepareLoginViewForDevice()
{
	$.bbq.pushState({ l: 'L' }, 2);
	navBoxHeader.removeClass('hidden');
  navBoxHeader.find('.helpButton').addClass('hidden');
}

function prepareNewLoginViewForDevice()
{
	$.bbq.pushState({ l: 'N' }, 2);
	navBoxHeader.removeClass('hidden');
  navBoxHeader.find('.helpButton').addClass('hidden');
}

function prepareActivateLoginViewForDevice()
{
	$.bbq.pushState({ l: 'A' }, 2);
	navBoxHeader.removeClass('hidden');
  navBoxHeader.find('.helpButton').addClass('hidden');
}

function stopInProgressAnimation()
{
	activityIndicator.addClass('hidden');
}

function startInProgressAnimation()
{
  activityIndicator.removeClass('hidden');
}

function populateTextOnlyCategories(masterCategory)
{
	var order = hasMasterCategories ? siteConfig.master_categories[masterCategory].categories : siteConfig.categories_order;
	var list = siteConfig.categories;
	var select = document.createElement('select');
	$(select).attr('id', 'categoriesList');
	$(select).bind('change', function() {
	 showKeywordListView(this.options[this.selectedIndex].value);
	});
	for (id in order)
	{
		var option = document.createElement('option');
		$(option).attr('value', order[id]);
		if (order[id] == currentCategory)
			$(option).attr('selected', 'true');
		$(option).html(list[order[id]].name);
		$(option).appendTo(select);
	}
	$('#categorySelector').empty().append(select);
	$('#categorySelectorArea').removeClass('hidden');
	//currentCategory = currentCategory ? currentCategory : siteConfig.default_category;
}

function setCurrentView(view, reverseTransition)
{
  console.log('setCurrentView(): ' + view + ' ' + reverseTransition);
	setupParts();
  var entranceDirection = (reverseTransition ? 'left' : 'right');
  var exitDirection = (reverseTransition ? 'right' : 'left');
  var startPosition = (reverseTransition ? 'left' : 'right');
  var currentView = $('#' + $('#stackLayout > .view:visible').attr('id'));
  var newView = $('#' + view);
  if (currentView.size() == 0)
  {
		newView.show();
  }
  else if (currentView.attr('id') == newView.attr('id'))
  {
		newView.hide();
		newView.show('slide', { direction: entranceDirection }, 300);
  }
	else if ((newView.find('#keywordBox > a, #categoriesBox > a, #masterCategoriesBox > a').size() > 0)
					 || (currentView.find('#keywordBox > a, #categoriesBox > a, #masterCategoriesBox > a').size() > 0))
  {
		var zoomEntrance = reverseTransition ? 'zoomingin' : 'zoomingout';
		var zoomExit = reverseTransition ? 'zoomingout' : 'zoomingin';
		currentView.addClass('animating old');
		currentView.addClass(zoomExit);
		newView.addClass(zoomEntrance);
		newView.addClass('animating new');
		newView.removeClass(zoomEntrance);
		newView.show();
		setTimeout(function() {
			currentView.hide();
			currentView.removeClass('animating old ' + zoomExit);
			newView.removeClass('animating new');
		}, 300);
  }
  else
  {
		currentView.hide('slide', { direction: exitDirection }, 300);
		newView.show('slide', { direction: entranceDirection }, 300);
  }
	setTimeout(function() {
		window.scrollTo(0, 1);
	}, 0);
}

/*
 ABOVE: all methods need implementation per device (directly called from main.js)
 BELOW: methods assisting the above methods (NOT directly called from main.js)
*/

function setupParts()
{
}

function showUnreadBulletins()
{
	var bulletins = $.jStore.get('bulletins') || new Array();
	$('#bulletins').find('.bulletin').each(function(index, element) {
		var bulletin = $(element);
		var name = bulletin.attr('id');
		if (bulletins.indexOf(name) == -1)
			bulletin.show('slide', 300).removeClass('hidden');
	});
}

function dismissBulletin()
{
	var bulletin = $(this);
	bulletin.hide('slide', 300);
	var name = bulletin.attr('id');
	var bulletins = $.jStore.get('bulletins') || new Array();
	if (typeof(bulletins) == 'string')
		bulletins = JSON.parse(bulletins);
	bulletins.push(name);
	$.jStore.set('bulletins', JSON.stringify(bulletins));
	return false;
}

function onHashChange(event)
{
	console.log(location.hash);
	console.log(hashStack);
	var hashState = event.getState();
	var hashString = JSON.stringify(hashState);
	if (location.hash.length > 1 && hashStack.indexOf(hashString) == -1)
		hashStack.push(hashString);
	else if (hashStack.length == 0 || location.hash.length <= 1)
		goBackToHome();
	else
	{
		hashStack.pop();
		goBack()
	}
}

/*
 using jQuery BBQ, courtesy of Ben Alman
 storing state in the hash
 m = current master category
 c = current category
 k = current keyword
 a = current answer
 a2k = keyword for second level answer
 a2a = argument for second level answer
 l = Activate | New | Login
 h = Help
*/

<commit_msg>android: fix problem with shout boxes by being more specific with hash changes<commit_after>// caching frequently-accessed selectors
var navBoxHeader = $('#navBoxHeader');
var welcomeMessage = $('#welcomeMsgArea');
var mainLabel = $('#mainLabel');
var activityIndicator = $('#activityIndicator');
var activityIndicatorTop = Math.floor($(window).height() / 2);

/*
 The purpose of the functions "prepare...ForDevice()" is to establish the
 buttons that can be displayed on the navBar and the function of the buttons
 where they differ.
 The visibility of the welcome/intro message is also controlled at this stage.
*/

function prepareAnswerSpacesListViewForDevice()
{
}

function prepareMasterCategoriesViewForDevice()
{
	$.bbq.removeState();
	categoriesView.find('.welcomeBox').removeClass('hidden');
	navBoxHeader.addClass('hidden');
}

function prepareCategoriesViewForDevice()
{
	var categoriesView = $('#categoriesView');
  if (hasMasterCategories)
  {
		$.bbq.pushState({ m: currentMasterCategory }, 2);
		categoriesView.find('.welcomeBox').addClass('hidden');
		navBoxHeader.removeClass('hidden');
  }
  else
  {
		$.bbq.removeState();
		categoriesView.find('.welcomeBox').removeClass('hidden');
		navBoxHeader.addClass('hidden');
  }
}

function prepareKeywordListViewForDevice(category)
{
	var keywordListView = $('#keywordListView');
	var hashState = {};
	if (hasCategories)
		hashState['c'] = currentCategory;
	if (hasVisualCategories)
	{
		keywordListView.find('.welcomeBox').addClass('hidden');
		navBoxHeader.removeClass('hidden');
	}
  else if (hasMasterCategories)
  {
		keywordListView.find('.welcomeBox').addClass('hidden');
		navBoxHeader.removeClass('hidden');
		hashState['m'] = currentMasterCategory;
  }
  else
  {
		keywordListView.find('.welcomeBox').removeClass('hidden');
		navBoxHeader.addClass('hidden');
  }
	$.bbq.pushState(hashState, 2);
}

function prepareKeywordViewForDevice(oneKeyword, showHelp)
{
	$.bbq.pushState({ k: currentKeyword }, 2);
	if (oneKeyword)
		navBoxHeader.addClass('hidden');
	else
		navBoxHeader.removeClass('hidden');
	if (showHelp)
		navBoxHeader.find('.helpButton').removeClass('hidden');
	else
		navBoxHeader.find('.helpButton').addClass('hidden');
}

function prepareAnswerViewForDevice()
{
	$.bbq.pushState({ a: currentKeyword }, 2);
	if (answerSpaceOneKeyword)
		navBoxHeader.addClass('hidden');
	else
		navBoxHeader.removeClass('hidden');
}

function prepareSecondLevelAnswerViewForDevice(keyword, arg)
{
	$.bbq.pushState({ a2k: keyword, a2a: arg }, 2);
	navBoxHeader.removeClass('hidden');
  navBoxHeader.find('.helpButton').addClass('hidden');
}

function prepareHelpViewForDevice()
{
	$.bbq.pushState({ h: 'H' });
	var helpView = $('#helpView');
	navBoxHeader.removeClass('hidden');
  helpView.find('#backButton').addClass('hidden');
  helpView.find('#helpButton').removeClass('hidden');
}

function prepareLoginViewForDevice()
{
	$.bbq.pushState({ l: 'L' }, 2);
	navBoxHeader.removeClass('hidden');
  navBoxHeader.find('.helpButton').addClass('hidden');
}

function prepareNewLoginViewForDevice()
{
	$.bbq.pushState({ l: 'N' }, 2);
	navBoxHeader.removeClass('hidden');
  navBoxHeader.find('.helpButton').addClass('hidden');
}

function prepareActivateLoginViewForDevice()
{
	$.bbq.pushState({ l: 'A' }, 2);
	navBoxHeader.removeClass('hidden');
  navBoxHeader.find('.helpButton').addClass('hidden');
}

function stopInProgressAnimation()
{
	activityIndicator.addClass('hidden');
}

function startInProgressAnimation()
{
  activityIndicator.removeClass('hidden');
}

function populateTextOnlyCategories(masterCategory)
{
	var order = hasMasterCategories ? siteConfig.master_categories[masterCategory].categories : siteConfig.categories_order;
	var list = siteConfig.categories;
	var select = document.createElement('select');
	$(select).attr('id', 'categoriesList');
	$(select).bind('change', function() {
	 showKeywordListView(this.options[this.selectedIndex].value);
	});
	for (id in order)
	{
		var option = document.createElement('option');
		$(option).attr('value', order[id]);
		if (order[id] == currentCategory)
			$(option).attr('selected', 'true');
		$(option).html(list[order[id]].name);
		$(option).appendTo(select);
	}
	$('#categorySelector').empty().append(select);
	$('#categorySelectorArea').removeClass('hidden');
	//currentCategory = currentCategory ? currentCategory : siteConfig.default_category;
}

function setCurrentView(view, reverseTransition)
{
  console.log('setCurrentView(): ' + view + ' ' + reverseTransition);
	setupParts();
  var entranceDirection = (reverseTransition ? 'left' : 'right');
  var exitDirection = (reverseTransition ? 'right' : 'left');
  var startPosition = (reverseTransition ? 'left' : 'right');
  var currentView = $('#' + $('#stackLayout > .view:visible').attr('id'));
  var newView = $('#' + view);
  if (currentView.size() == 0)
  {
		newView.show();
  }
  else if (currentView.attr('id') == newView.attr('id'))
  {
		newView.hide();
		newView.show('slide', { direction: entranceDirection }, 300);
  }
	else if ((newView.find('#keywordBox > a, #categoriesBox > a, #masterCategoriesBox > a').size() > 0)
					 || (currentView.find('#keywordBox > a, #categoriesBox > a, #masterCategoriesBox > a').size() > 0))
  {
		var zoomEntrance = reverseTransition ? 'zoomingin' : 'zoomingout';
		var zoomExit = reverseTransition ? 'zoomingout' : 'zoomingin';
		currentView.addClass('animating old');
		currentView.addClass(zoomExit);
		newView.addClass(zoomEntrance);
		newView.addClass('animating new');
		newView.removeClass(zoomEntrance);
		newView.show();
		setTimeout(function() {
			currentView.hide();
			currentView.removeClass('animating old ' + zoomExit);
			newView.removeClass('animating new');
		}, 300);
  }
  else
  {
		currentView.hide('slide', { direction: exitDirection }, 300);
		newView.show('slide', { direction: entranceDirection }, 300);
  }
	setTimeout(function() {
		window.scrollTo(0, 1);
	}, 0);
}

/*
 ABOVE: all methods need implementation per device (directly called from main.js)
 BELOW: methods assisting the above methods (NOT directly called from main.js)
*/

function setupParts()
{
}

function showUnreadBulletins()
{
	var bulletins = $.jStore.get('bulletins') || new Array();
	$('#bulletins').find('.bulletin').each(function(index, element) {
		var bulletin = $(element);
		var name = bulletin.attr('id');
		if (bulletins.indexOf(name) == -1)
			bulletin.show('slide', 300).removeClass('hidden');
	});
}

function dismissBulletin()
{
	var bulletin = $(this);
	bulletin.hide('slide', 300);
	var name = bulletin.attr('id');
	var bulletins = $.jStore.get('bulletins') || new Array();
	if (typeof(bulletins) == 'string')
		bulletins = JSON.parse(bulletins);
	bulletins.push(name);
	$.jStore.set('bulletins', JSON.stringify(bulletins));
	return false;
}

function onHashChange(event)
{
	var hashState = event.getState();
	var hashString = JSON.stringify(hashState);
	if (location.hash.length > 1 && hashStack.indexOf(hashString) == -1)
		hashStack.push(hashString);
	else if (hashStack.length == 0 || location.hash.length <= 1)
		goBackToHome();
	else if (hashStack[hashStack.length - 2] == hashString)
	{
		hashStack.pop();
		goBack()
	}
}

/*
 using jQuery BBQ, courtesy of Ben Alman
 storing state in the hash
 m = current master category
 c = current category
 k = current keyword
 a = current answer
 a2k = keyword for second level answer
 a2a = argument for second level answer
 l = Activate | New | Login
 h = Help
*/

<|endoftext|>


<commit_before>'use strict';

var core = require('ceci-core');
var cc   = require('ceci-channels');

const OKAY = 0;
const SKIP = 1;
const STOP = 2;

var pipeThrough = function(fn, input, output) {
  var managed = (output == null);
  if (managed)
    output = cc.chan();

  var done = core.go(function*() {
    var arg, res, val, status;

    while (true) {
      if (undefined === (arg = yield cc.pull(input)))
        break;

      res = yield fn(arg);
      val = res[0];
      status = res[1];
      if (status == SKIP)
        continue;

      if (!(yield cc.push(output, (val === undefined ? null : val))))
        break;
      if (status == STOP)
        break;
    }

    if (managed) {
      cc.close(input);
      cc.close(output);
    }

    return output;
  });

  if (managed)
    return output;
  else
    return done;
};

exports.tapWith = function(filter, arg, input) {
  var output = cc.chan();
  core.go(function*() {
    yield filter(arg, input, output);
    cc.close(output);
  });
  return output;
};

exports.source = function(gen, output) {
  var managed = output == null;
  if (managed)
    output = cc.chan();

  core.go(function*() {
    var step;

    while (true) {
      step = gen.next();
      if (step.done)
        break;
      if (!(yield cc.push(output, step.value)))
        break
    }

    if (managed)
      cc.close(output);
  });

  return output;
};

exports.each = function(fn, input) {
  return core.go(function*() {
    var val;
    while (undefined !== (val = yield cc.pull(input)))
      if (fn)
        yield fn(val);
  });
};

exports.map = function(fn, input, output) {
  return pipeThrough(
    function(arg) {
      return core.lift(Array)(fn(arg), OKAY);
    },
    input, output);
};

exports.filter = function(pred, input, output) {
  return pipeThrough(
    function(arg) {
      return [arg, (pred(arg) ? OKAY : SKIP)];
    },
    input, output);
};

exports.reductions = function(fn, start, input, output) {
  var acc = start;
  return pipeThrough(
    function(arg) {
      return [acc = fn(acc, arg), OKAY];
    },
    input, output);
};

exports.take = function(n, input, output) {
  if (n == 0) {
    if (output == null)
      return cc.chan();
  } else {
    var count = 0;
    return pipeThrough(
      function(arg) {
        return [arg, (++count < n ? OKAY : STOP)];
      },
      input, output);
  }
};

exports.takeUntil = function(pred, input, output) {
  return pipeThrough(
    function(arg) {
      return [arg, (pred(arg) ? STOP : OKAY)];
    },
    input, output);
};

exports.takeFor = function(ms, input, output) {
  var t = cc.timeout(ms);

  return pipeThrough(
    function(arg) {
      return core.go(function*() {
        var go = (yield cc.select(t, { default: true })).value;
        return [arg, (go ? OKAY : STOP)];
      });
    },
    input, output);
};

exports.drop = function(n, input, output) {
  var count = false;

  return pipeThrough(
    function(arg) {
      return [arg, (++count <= n ? SKIP : OKAY)];
    },
    input, output);
};

exports.dropWhile = function(pred, input, output) {
  var go = false;

  return pipeThrough(
    function(arg) {
      go = go || !pred(arg);
      return [arg, (go ? OKAY : SKIP)];
    },
    input, output);
};

exports.dropFor = function(ms, input, output) {
  var t = cc.timeout(ms);
  var go = false;

  return pipeThrough(
    function(arg) {
      return core.go(function*() {
        go = go || !(yield cc.select(t, { default: true })).value;
        return [arg, (go ? OKAY : SKIP)];
      });
    },
    input, output);
};

exports.scatter = function(preds, input, outputs) {
  var open = preds.map(function() { return true });
  var nrOpen = preds.length;
  var managed = outputs == null;
  if (managed)
    outputs = preds.map(function() { return cc.chan(); });

  core.go(function*() {
    var val;

    while(nrOpen > 0 && undefined !== (val = yield cc.pull(input))) {
      for (var i = 0; i < preds.length; ++i) {
        if ((preds[i] == true) || preds[i](val)) {
          if (open[i] && !(yield cc.push(outputs[i], val))) {
            --nrOpen;
            open[i] = false;
          }
          break;
        }
      }
    }

    if (managed)
      outputs.forEach(cc.close);
  });

  return outputs;
};

exports.merge = function(inputs, output) {
  var managed = output == null;
  if (managed)
    output = cc.chan();
  var inputs = inputs.slice();

  core.go(function*() {
    var res;
    while (inputs.length > 0) {
      res = yield cc.select.apply(null, inputs);
      if (res.value === undefined)
        inputs.slice(inputs.indexOf(res.channel), 1);
      else if (!(yield cc.push(output, res.value)))
        break;
    }

    if (managed) {
      cc.close(output);
      inputs.forEach(cc.close);
    }
  });

  return output;
};

exports.combine = function(inputs, output) {
  var managed = output == null;
  if (managed)
    output = cc.chan();
  var active = inputs.slice();
  var current = new Array(inputs.length);

  core.go(function*() {
    var res;

    while (active.length > 0) {
      res = yield cc.select.apply(null, active);
      if (res.value === undefined)
        active.slice(active.indexOf(res.channel), 1);
      else {
        current[inputs.indexOf(res.channel)] = res.value;
        if (!(yield cc.push(output, current)))
          break;
      }
    }

    if (managed) {
      cc.close(output);
      inputs.forEach(cc.close);
    }
  });

  return output;
};
<commit_msg>add a new zip implementation and fix some glitches<commit_after>'use strict';

var core = require('ceci-core');
var cc   = require('ceci-channels');

const OKAY = 0;
const SKIP = 1;
const STOP = 2;

var pipeThrough = function(fn, input, output) {
  var managed = (output == null);
  if (managed)
    output = cc.chan();

  var done = core.go(function*() {
    var arg, res, val, status;

    while (true) {
      if (undefined === (arg = yield cc.pull(input)))
        break;

      res = yield fn(arg);
      val = res[0];
      status = res[1];
      if (status == SKIP)
        continue;

      if (!(yield cc.push(output, (val === undefined ? null : val))))
        break;
      if (status == STOP)
        break;
    }

    if (managed) {
      cc.close(input);
      cc.close(output);
    }

    return output;
  });

  if (managed)
    return output;
  else
    return done;
};

exports.tapWith = function(filter, arg, input) {
  var output = cc.chan();
  core.go(function*() {
    yield filter(arg, input, output);
    cc.close(output);
  });
  return output;
};

exports.source = function(gen, output) {
  var managed = output == null;
  if (managed)
    output = cc.chan();

  core.go(function*() {
    var step;

    while (true) {
      step = gen.next();
      if (step.done)
        break;
      if (!(yield cc.push(output, step.value)))
        break
    }

    if (managed)
      cc.close(output);
  });

  return output;
};

exports.each = function(fn, input) {
  return core.go(function*() {
    var val;
    while (undefined !== (val = yield cc.pull(input)))
      if (fn)
        yield fn(val);
  });
};

exports.map = function(fn, input, output) {
  return pipeThrough(
    function(arg) {
      return core.lift(Array)(fn(arg), OKAY);
    },
    input, output);
};

exports.filter = function(pred, input, output) {
  return pipeThrough(
    function(arg) {
      return [arg, (pred(arg) ? OKAY : SKIP)];
    },
    input, output);
};

exports.reductions = function(fn, start, input, output) {
  var acc = start;
  return pipeThrough(
    function(arg) {
      return [acc = fn(acc, arg), OKAY];
    },
    input, output);
};

exports.take = function(n, input, output) {
  if (n == 0) {
    if (output == null)
      return cc.chan();
  } else {
    var count = 0;
    return pipeThrough(
      function(arg) {
        return [arg, (++count < n ? OKAY : STOP)];
      },
      input, output);
  }
};

exports.takeUntil = function(pred, input, output) {
  return pipeThrough(
    function(arg) {
      return [arg, (pred(arg) ? STOP : OKAY)];
    },
    input, output);
};

exports.takeFor = function(ms, input, output) {
  var t = cc.timeout(ms);

  return pipeThrough(
    function(arg) {
      return core.go(function*() {
        var go = (yield cc.select(t, { default: true })).value;
        return [arg, (go ? OKAY : STOP)];
      });
    },
    input, output);
};

exports.drop = function(n, input, output) {
  var count = false;

  return pipeThrough(
    function(arg) {
      return [arg, (++count <= n ? SKIP : OKAY)];
    },
    input, output);
};

exports.dropWhile = function(pred, input, output) {
  var go = false;

  return pipeThrough(
    function(arg) {
      go = go || !pred(arg);
      return [arg, (go ? OKAY : SKIP)];
    },
    input, output);
};

exports.dropFor = function(ms, input, output) {
  var t = cc.timeout(ms);
  var go = false;

  return pipeThrough(
    function(arg) {
      return core.go(function*() {
        go = go || !(yield cc.select(t, { default: true })).value;
        return [arg, (go ? OKAY : SKIP)];
      });
    },
    input, output);
};

exports.scatter = function(preds, input, outputs) {
  var open = preds.map(function() { return true });
  var nrOpen = preds.length;
  var managed = outputs == null;
  if (managed)
    outputs = preds.map(function() { return cc.chan(); });

  core.go(function*() {
    var val;

    while(nrOpen > 0 && undefined !== (val = yield cc.pull(input))) {
      for (var i = 0; i < preds.length; ++i) {
        if ((preds[i] == true) || preds[i](val)) {
          if (open[i] && !(yield cc.push(outputs[i], val))) {
            --nrOpen;
            open[i] = false;
          }
          break;
        }
      }
    }

    if (managed)
      outputs.forEach(cc.close);
  });

  return outputs;
};

exports.merge = function(inputs, output) {
  var managed = output == null;
  if (managed)
    output = cc.chan();
  var inputs = inputs.slice();

  core.go(function*() {
    var res;
    while (inputs.length > 0) {
      res = yield cc.select.apply(null, inputs);
      if (res.value === undefined)
        inputs.splice(inputs.indexOf(res.channel), 1);
      else if (!(yield cc.push(output, res.value)))
        break;
    }

    if (managed) {
      cc.close(output);
      inputs.forEach(cc.close);
    }
  });

  return output;
};

exports.combine = function(inputs, output) {
  var managed = output == null;
  if (managed)
    output = cc.chan();
  var active = inputs.slice();
  var current = new Array(inputs.length);

  core.go(function*() {
    var res;

    while (active.length > 0) {
      res = yield cc.select.apply(null, active);
      if (res.value === undefined)
        active.splice(active.indexOf(res.channel), 1);
      else {
        current[inputs.indexOf(res.channel)] = res.value;
        if (!(yield cc.push(output, current)))
          break;
      }
    }

    if (managed) {
      cc.close(output);
      inputs.forEach(cc.close);
    }
  });

  return output;
};

exports.zip = function(inputs, output) {
  var managed = output == null;
  if (managed)
    output = cc.chan();
  var current = new Array(inputs.length);

  core.go(function*() {
    var done = false;
    var res, pending;

    while (!done) {
      pending = inputs.slice();
      while (pending.length > 0) {
        res = yield cc.select.apply(null, pending);
        if (res.value === undefined) {
          done = true;
          break;
        } else {
          current[inputs.indexOf(res.channel)] = res.value;
          pending.splice(pending.indexOf(res.channel), 1);
        }
      }
      if (!done && !(yield cc.push(output, current.slice())))
        break;
    }

    if (managed) {
      cc.close(output);
      inputs.forEach(cc.close);
    }
  });

  return output;
};
<|endoftext|>


<commit_before>/*
==================================================================================================
  Lowland - JavaScript low level functions
  Copyright (C) 2012 Sebatian Fastner
==================================================================================================
*/

/**
 * #require(ext.sugar.Object)
 */

(function(window) {
  var hasPostMessage = !!window.postMessage;
  var slice = Array.prototype.slice;
  var timeouts = [];
  var messageName = "$$lowland-zero-timeout-message";

  var handleMessage = function() {
    if (event.source == window && event.data == messageName) {
      event.stopPropagation();
      if (timeouts.length > 0) {
        var timeout = timeouts.shift();

        timeout[0].apply(timeout[0], timeout[1]);
      }
    }
  };
  addEventListener("message", handleMessage, true);

  core.Main.addMembers("Function", {

    delay : function(time) {
      var func = this;
      setTimeout(function() {
        func.apply(func, slice.call(arguments, 1));
      }, time, slice.call(arguments, 1));
    },

    /**
     * Based upon work of http://dbaron.org/log/20100309-faster-timeouts
     */
    lazy : function(func) {
      timeouts.push([func, slice.call(arguments,1)]);
      postMessage(messageName, "*");
    }
  });

})(window);<commit_msg>Fix function.delay context setting<commit_after>/*
==================================================================================================
  Lowland - JavaScript low level functions
  Copyright (C) 2012 Sebatian Fastner
==================================================================================================
*/

/**
 * #require(ext.sugar.Object)
 */

(function(window) {
  var hasPostMessage = !!window.postMessage;
  var slice = Array.prototype.slice;
  var timeouts = [];
  var messageName = "$$lowland-zero-timeout-message";

  var handleMessage = function() {
    if (event.source == window && event.data == messageName) {
      event.stopPropagation();
      if (timeouts.length > 0) {
        var timeout = timeouts.shift();

        timeout[0].apply(timeout[0], timeout[1]);
      }
    }
  };
  addEventListener("message", handleMessage, true);

  core.Main.addMembers("Function", {

    delay : function(time, context) {
      var func = this;
      setTimeout(function(context, args) {
        func.apply(context, args);
      }, time, context, slice.call(arguments, 2));
    },

    /**
     * Based upon work of http://dbaron.org/log/20100309-faster-timeouts
     */
    lazy : function(func) {
      timeouts.push([func, slice.call(arguments,1)]);
      postMessage(messageName, "*");
    }
  });

})(window);<|endoftext|>


<commit_before>import { isNaN, isString, isEmpty } from 'lodash';

const SMALL_WORDS = /^(a|an|and|as|at|but|by|en|for|if|in|nor|of|on|or|per|the|to|vs?\.?|via)$/i;
const UUID_REGEX = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/;

export default {
  asPercent(num) {
    return Math.round(num * 100);
  },

  numberWithOneDecimalPlace(num) {
    return parseFloat(Math.round(parseFloat(num) * 10) / 10).toFixed(1);
  },

  numberWithTwoDecimalPlaces(num) {
    return parseFloat(Math.round(parseFloat(num) * 100) / 100).toFixed(2);
  },

  capitalize(string, lowerOthers = true) {
    const other = lowerOthers ? string.substring(1).toLowerCase() : string.substring(1);
    return string.charAt(0).toUpperCase() + other;
  },

  replaceAt(string, index, character) {
    return string.substr(0, index) + character + string.substr(index + character.length);
  },

  insertAt(string, index, character) {
    return string.substr(0, index) + character + string.substr(index);
  },

  removeAt(string, index, length = 1) {
    return string.substr(0, index) + string.substr(index + length);
  },

  getNumberAndStringOrder(string) {
    const parsedInt = parseFloat(string);
    if (isNaN(parsedInt)) { return string.toLowerCase(); } else { return parsedInt; }
  },

  dasherize(string) {
    return String(string)
      .replace(/[A-Z]/g, (char, index) => (index !== 0 ? '-' : '') + char.toLowerCase())
      .replace(/[-_\s]+/g, '-');
  },

  // originated from http://individed.com/code/to-title-case/
  titleize(string = '') {
    return String(string)
      .replace(/_/g, ' ')
      .replace(/[A-Za-z0-9\u00C0-\u00FF]+[^\s-]*/g, function(match, index, title) {
        if ((index > 0) && ((index + match.length) !== title.length) &&
        (match.search(SMALL_WORDS) > -1) &&
        (title.charAt(index - 2) !== ':') &&
        ( (title.charAt(index + match.length) !== '-') || (title.charAt(index - 1) === '-') ) &&
        (title.charAt(index - 1).search(/[^\s-]/) < 0)) {

          return match.toLowerCase();
        }

        if (match.substr(1).search(/[A-Z]|\../) > -1) {
          return match;
        }

        return match.charAt(0).toUpperCase() + match.substr(1);
      });
  },

  toSentence(arry, join = 'and') {
    if (isString(arry)) { arry = arry.split(' '); }
    if (arry.length > 1) {
      return `${arry.slice(0, arry.length - 1).join(', ')} ${join} ${arry.slice(-1)}`;
    } else {
      return arry[0];
    }
  },

  isEmpty(s) {
    return Boolean(
      isEmpty(s) || (isString(s) && !s.match(/\S/))
    );
  },

  isUUID(uuid = '') { return UUID_REGEX.test(uuid); },

  stringToInt(string) {
    const int = parseInt(string);
    if (isNaN(int)) {
      return 0;
    }
    return int;
  },

  countWords(text) {
    if(!text) return 0;
    text = text.replace(/(^\s*)|(\s*$)/gi,'');
    text = text.replace(/[ ]{2,}/gi,' ');
    text = text.replace(/\n/gi,' ');
    return text.split(' ').length;
  },

  stripHTMLTags(text) {
    return isString(text) ? text.replace(/(<([^>]+)>)/ig, '') : text;
  },

  assignmentHeaderText(type) {
    if(type === 'external') return 'external assignment';
    return type;
  },

};
<commit_msg>fix word count<commit_after>import { isNaN, isString, isEmpty } from 'lodash';

const SMALL_WORDS = /^(a|an|and|as|at|but|by|en|for|if|in|nor|of|on|or|per|the|to|vs?\.?|via)$/i;
const UUID_REGEX = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/;

export default {
  asPercent(num) {
    return Math.round(num * 100);
  },

  numberWithOneDecimalPlace(num) {
    return parseFloat(Math.round(parseFloat(num) * 10) / 10).toFixed(1);
  },

  numberWithTwoDecimalPlaces(num) {
    return parseFloat(Math.round(parseFloat(num) * 100) / 100).toFixed(2);
  },

  capitalize(string, lowerOthers = true) {
    const other = lowerOthers ? string.substring(1).toLowerCase() : string.substring(1);
    return string.charAt(0).toUpperCase() + other;
  },

  replaceAt(string, index, character) {
    return string.substr(0, index) + character + string.substr(index + character.length);
  },

  insertAt(string, index, character) {
    return string.substr(0, index) + character + string.substr(index);
  },

  removeAt(string, index, length = 1) {
    return string.substr(0, index) + string.substr(index + length);
  },

  getNumberAndStringOrder(string) {
    const parsedInt = parseFloat(string);
    if (isNaN(parsedInt)) { return string.toLowerCase(); } else { return parsedInt; }
  },

  dasherize(string) {
    return String(string)
      .replace(/[A-Z]/g, (char, index) => (index !== 0 ? '-' : '') + char.toLowerCase())
      .replace(/[-_\s]+/g, '-');
  },

  // originated from http://individed.com/code/to-title-case/
  titleize(string = '') {
    return String(string)
      .replace(/_/g, ' ')
      .replace(/[A-Za-z0-9\u00C0-\u00FF]+[^\s-]*/g, function(match, index, title) {
        if ((index > 0) && ((index + match.length) !== title.length) &&
        (match.search(SMALL_WORDS) > -1) &&
        (title.charAt(index - 2) !== ':') &&
        ( (title.charAt(index + match.length) !== '-') || (title.charAt(index - 1) === '-') ) &&
        (title.charAt(index - 1).search(/[^\s-]/) < 0)) {

          return match.toLowerCase();
        }

        if (match.substr(1).search(/[A-Z]|\../) > -1) {
          return match;
        }

        return match.charAt(0).toUpperCase() + match.substr(1);
      });
  },

  toSentence(arry, join = 'and') {
    if (isString(arry)) { arry = arry.split(' '); }
    if (arry.length > 1) {
      return `${arry.slice(0, arry.length - 1).join(', ')} ${join} ${arry.slice(-1)}`;
    } else {
      return arry[0];
    }
  },

  isEmpty(s) {
    return Boolean(
      isEmpty(s) || (isString(s) && !s.match(/\S/))
    );
  },

  isUUID(uuid = '') { return UUID_REGEX.test(uuid); },

  stringToInt(string) {
    const int = parseInt(string);
    if (isNaN(int)) {
      return 0;
    }
    return int;
  },

  countWords(text) {
    if(!text) return 0;
    return text.match(/\b[-?(\w+)?]+\b/gi).length;
  },

  stripHTMLTags(text) {
    return isString(text) ? text.replace(/(<([^>]+)>)/ig, '') : text;
  },

  assignmentHeaderText(type) {
    if(type === 'external') return 'external assignment';
    return type;
  },

};
<|endoftext|>


<commit_before>/*
 MIT License http://www.opensource.org/licenses/mit-license.php
 Author Zoltan Magyar
 */
const loaderUtils = require("loader-utils");
const esprima = require('esprima');
const escodegen = require('escodegen');
const esUtils = require('esprima-ast-utils');
const chalk = require('chalk');
const Promise = require('bluebird');
const crypto = require("crypto");
const fs = require('fs');

const cacheDir = './.cache';
try {
    fs.statSync(cacheDir);
} catch (e) {
    fs.mkdirSync(cacheDir);
}
module.exports.raw = true;

module.exports = function (content, map) {
    var self = this;
    if (this.cacheable) this.cacheable();
    var callback = this.async();
    var query = loaderUtils.getOptions(this) || {};
    var debug = query.debug;
    var nameSpace = query.nameSpace;
    var pathMap = query.paths || {};

    if (map !== null && typeof map !== "string") {
        map = JSON.stringify(map);
    }

    /**
     * Resolve the given className as a path using the options->paths mapping defined in the config
     *
     * @param className
     * @returns {*}
     */
    function resolveClassFile(className) {
        let fileToLoad = className;
        let retVal = className;
        retVal = [];
        for (var prefix in pathMap) {
            if (pathMap.hasOwnProperty(prefix)) {
                let re = new RegExp('^' + prefix);
                if (className.match(re)) {
                    if (pathMap[prefix] === false) {
                        retVal = [];
                    } else {
                        if (typeof pathMap[prefix].query === 'function') {

                            classes = pathMap[prefix].query(className);
                            if (classes instanceof Array) {
                                retVal = classes.map((className) => {
                                    return className.src;
                                });
                            } else {
                                try {
                                    if (!classes.src) {
                                        console.log(chalk.red(`Required class "${className}" not found in ${self.resourcePath}`));
                                        retVal = [];
                                    } else {
                                        retVal = [classes.src];
                                    }
                                } catch (e) {
                                    console.log(prefix, className);
                                }
                            }
                        } else {
                            retVal = [prefix.replace(prefix, pathMap[prefix]) + className.replace(prefix, '').replace(/\./g, '/') + '.js'];
                        }
                    }
                    break;
                }
            }
        }
        return [...retVal].filter(Boolean);

    }

    try {
        /**
         * Process each possible ways how required files can be referenced in Ext.js
         * The regexp's below are dealing with the following cases:
         * - requires: [...]
         * - controllers: [...]
         * - stores: [...]
         * - controller: '...' (ViewController definition in the View class)
         * - sViewCache - specific to our codebase - sorry :-)
         *
         * In case of stores and controllers the full namespace is automatically added
         * to the require if not full reference is found
         */
        const configMap = {
            requires: {
                remove: true
            },
            mixins: {
                allowObject: true
            },
            override: true,
            extend: true,
            uses: {
                end: true
            },
            stores: {
                prefix: nameSpace + '.store.'
            },
            controllers: {
                prefix: nameSpace + '.controller.'
            },
            // /sViewCache\(['"](.*)['"],\s{/img,
            controller: true
        };

        let updates = [];
        let properties = Object.keys(configMap);

        function addRequire(className, prefix) {
            if (className.indexOf('.') > 0 || prefix != '' || className === 'Ext') {
                var fileToRequire = resolveClassFile(((className.indexOf('.') > 0) ? '' : prefix) + className);
                if (fileToRequire.length > 0) {
                    let reqStr = '';
                    fileToRequire.forEach((req) => {
                        if (debug) console.log(chalk.green('Converting require: ') + className + ' => ' + req);

                        if (typeof req === 'undefined') {
                            console.log(chalk.red('Converting require: ') + className + ' => ' + req);
                        }
                        reqStr += `require(${escodegen.generate({ type: 'Literal', value: req })});\r\n`;
                    });
                    return reqStr;
                }
            }
            return '';
        }

        function sha1(data) {
            return crypto.createHash("sha1").update(data, "binary").digest("hex");
        }

        function findParentExpression(node) {
            if (!node) return null;
            if (node.type === 'ExpressionStatement' || node.type === 'Program') return node;
            return findParentExpression(node.$parent);
        }

        const contentDigest = sha1(content);
        const cacheFile = cacheDir + '/content_' + contentDigest;
        let tree;

        if (fs.existsSync(cacheFile)) {
            const cachedContent = fs.readFileSync(cacheFile, { encoding: 'utf-8' });
            callback(null, cachedContent, map);
            return;
        }
        tree = esprima.parse(content, {
            range: true
        });

        Promise.each(Object.keys(pathMap), function (map) {
            var objVal = pathMap[map];
            if (objVal.use === undefined) {
                return Promise.resolve();
            } else {

                if (objVal.use.ready) {
                    return objVal.use.ready();
                }
                var use = require(objVal.use);

                var ctor = new use(objVal.options);
                pathMap[map].use = ctor;
                debugger;
                return ctor.ready().then(function (list) {
                    let config = pathMap[map];
                    pathMap[map] = ctor;
                    if (Array.isArray(config.options.aliasForNs)) {
                        config.options.aliasForNs.forEach(ns => {
                            pathMap[ns] = ctor;
                        });
                    }
                    return Promise.resolve();
                });
            }
        }).then(() => {
            let ExtParser = pathMap['Ext'];
            let noParse = false;
            if (ExtParser.query) {
                let fileProps = ExtParser.fileMapCache[self.resourcePath];
                if (fileProps && fileProps.requires && fileProps.requires.length > 0) {
                    let requireStr = '';
                    fileProps.requires.forEach((require) => {
                        let result = ExtParser.query(require);
                        if (result instanceof Array) {
                            result.forEach((require) => {
                                requireStr += `require('${require.src}');\n`;
                            });
                        } else {
                            requireStr += `require('${ExtParser.query(require).src}');\n`;
                        }

                    });
                    updates.push({ type: 'add', start: 0, end: 0, data: requireStr });
                }
                if (fileProps && fileProps.overrides && fileProps.overrides.length > 0) {
                    let requireStr = '';
                    fileProps.overrides.forEach((require) => {
                        let result = ExtParser.query(require);
                        if (result instanceof Array) {
                            result.forEach((require) => {
                                requireStr += `require('${require.src}');\n`;
                            });
                        } else {
                            const requireSource = ExtParser.query(require).src || require;
                            if (requireSource) {
                                requireStr += `require('${requireSource}');\n`;
                            }
                        }

                    });
                    updates.push({ type: 'add', start: content.length, end: content.length, data: requireStr });
                }
            }
            esUtils.parentize(tree);
            esUtils.traverse(tree, function (node) {
                let requireStr = '';
                if (node && node.type === 'Property' && node.key && properties.includes(node.key.name)) {
                    const nodeName = node.key.name;

                    if (node && node.value && node.value.type === 'Literal') {
                        if (node.value.value !== null) {
                            requireStr += addRequire(node.value.value, configMap[nodeName].prefix || '');
                        }
                    } else if (node && node.value && node.value.type === 'ArrayExpression') {
                        node.value.elements.forEach(function (element) {
                            requireStr += addRequire(element.value, configMap[nodeName].prefix || '');
                        })
                    } else if (node && node.value && node.value.type === 'ObjectExpression' && node.value.properties && node.value.properties.length > 0 && configMap[node.key.name].allowObject) {
                        node.value.properties.forEach(function (objectNode) {
                            if (objectNode && objectNode.value && objectNode.value.type === 'Literal') {
                                if (objectNode.value !== null) {
                                    requireStr += addRequire(objectNode.value.value, configMap[nodeName].prefix || '');
                                }
                            }
                        })
                    }
                    if (requireStr !== '') {
                        let parent = findParentExpression(node);
                        if (configMap[nodeName].remove === true) {
                            updates.push({ type: 'remove', start: node.range[0], end: node.range[1] });
                        }
                        updates.push({
                            type: 'add',
                            start: parent.range[configMap[nodeName].end ? 1 : 0],
                            end: parent.range[configMap[nodeName].end ? 1 : 0],
                            data: requireStr
                        });
                        //   console.log('Requires by loader', requireStr);
                    }
                }
            });
            updates.sort((a, b) => {
                return b.end - a.end
            }).forEach(updateItem => {
                if (updateItem.type === 'remove') {
                    content = content.slice(0, updateItem.start) + content.slice(updateItem.end).replace(/^\s*,/im, '');
                } else if (updateItem.type === 'add') {
                    content = [content.slice(0, updateItem.start), updateItem.data, content.slice(updateItem.start)].join('');
                }
            });

            /**
             * Some
             */
            try {
                content = content.replace(/Ext.safeCreate\(['"](.*)['"]/img, function (match, offset, string) {
                    const resolvedClasses = resolveClassFile(offset);
                    let className;
                    if (resolvedClasses.length === 0) {
                        throw new Error(`Couldn't resolve class: ${offset}`)
                    } else {
                        className = resolvedClasses[0];
                    }
                    return 'require(' + escodegen.generate({
                        type: 'Literal',
                        value: className
                    }) + ');\r\n' + match;
                });

                fs.writeFileSync(cacheFile, content);
                callback(null, content, map);
            } catch (e) {
                callback(e)
            }
        });

    } catch (e) {
        console.error(chalk.red(`Error parsing ${self.resourcePath}`) + e);
        callback(e);
    }

};
<commit_msg>Extjs7 related changes<commit_after>/*
 MIT License http://www.opensource.org/licenses/mit-license.php
 Author Zoltan Magyar
 */
const loaderUtils = require("loader-utils");
const esprima = require('esprima');
const escodegen = require('escodegen');
const esUtils = require('esprima-ast-utils');
const chalk = require('chalk');
const Promise = require('bluebird');
const crypto = require("crypto");
const fs = require('fs');

const cacheDir = './.cache';
try {
    fs.statSync(cacheDir);
} catch (e) {
    fs.mkdirSync(cacheDir);
}
module.exports.raw = true;

module.exports = function (content, map) {
    var self = this;
    if (this.cacheable) this.cacheable();
    var callback = this.async();
    var query = loaderUtils.getOptions(this) || {};
    var debug = query.debug;
    var nameSpace = query.nameSpace;
    var pathMap = query.paths || {};

    if (map !== null && typeof map !== "string") {
        map = JSON.stringify(map);
    }

    /**
     * Resolve the given className as a path using the options->paths mapping defined in the config
     *
     * @param className
     * @returns {*}
     */
    function resolveClassFile(className) {
        let fileToLoad = className;
        let retVal = className;
        retVal = [];
        for (var prefix in pathMap) {
            if (pathMap.hasOwnProperty(prefix)) {
                let re = new RegExp('^' + prefix);
                if (className.match(re)) {
                    if (pathMap[prefix] === false) {
                        retVal = [];
                    } else {
                        if (typeof pathMap[prefix].query === 'function') {

                            classes = pathMap[prefix].query(className);
                            if (classes instanceof Array) {
                                retVal = classes.map((className) => {
                                    return className.src;
                                });
                            } else {
                                try {
                                    if (!classes.src) {
                                        console.log(chalk.red(`Required class "${className}" not found in ${self.resourcePath}`));
                                        retVal = [];
                                    } else {
                                        retVal = [classes.src];
                                    }
                                } catch (e) {
                                    console.log(prefix, className);
                                }
                            }
                        } else {
                            retVal = [prefix.replace(prefix, pathMap[prefix]) + className.replace(prefix, '').replace(/\./g, '/') + '.js'];
                        }
                    }
                    break;
                }
            }
        }
        return [...retVal].filter(Boolean);

    }

    try {
        /**
         * Process each possible ways how required files can be referenced in Ext.js
         * The regexp's below are dealing with the following cases:
         * - requires: [...]
         * - controllers: [...]
         * - stores: [...]
         * - controller: '...' (ViewController definition in the View class)
         * - sViewCache - specific to our codebase - sorry :-)
         *
         * In case of stores and controllers the full namespace is automatically added
         * to the require if not full reference is found
         */
        const configMap = {
            requires: {
                remove: true
            },
            mixins: {
                allowObject: true
            },
            override: true,
            extend: true,
            uses: {
                end: true
            },
            stores: {
                prefix: nameSpace + '.store.'
            },
            controllers: {
                prefix: nameSpace + '.controller.'
            },
            // /sViewCache\(['"](.*)['"],\s{/img,
            controller: true
        };

        let updates = [];
        let properties = Object.keys(configMap);

        function addRequire(className, prefix) {
            if (className.indexOf('.') > 0 || prefix != '' || className === 'Ext') {
                var fileToRequire = resolveClassFile(((className.indexOf('.') > 0) ? '' : prefix) + className);
                if (fileToRequire.length > 0) {
                    let reqStr = '';
                    fileToRequire.forEach((req) => {
                        if (debug) console.log(chalk.green('Converting require: ') + className + ' => ' + req);

                        if (typeof req === 'undefined') {
                            console.log(chalk.red('Converting require: ') + className + ' => ' + req);
                        }
                        reqStr += `require(${escodegen.generate({ type: 'Literal', value: req })});\r\n`;
                    });
                    return reqStr;
                }
            }
            return '';
        }

        function sha1(data) {
            return crypto.createHash("sha1").update(data, "binary").digest("hex");
        }

        function findParentExpression(node) {
            if (!node) return null;
            if (node.type === 'ExpressionStatement' || node.type === 'Program') return node;
            return findParentExpression(node.$parent);
        }

        const contentDigest = sha1(content);
        const cacheFile = cacheDir + '/content_' + contentDigest;
        let tree;

        if (fs.existsSync(cacheFile)) {
            const cachedContent = fs.readFileSync(cacheFile, { encoding: 'utf-8' });
            callback(null, cachedContent, map);
            return;
        }
        tree = esprima.parse(content, {
            range: true
        });

        Promise.each(Object.keys(pathMap), function (map) {
            var objVal = pathMap[map];
            if (objVal.use === undefined) {
                return Promise.resolve();
            } else {

                if (objVal.use.ready) {
                    return objVal.use.ready();
                }
                var use = require(objVal.use);

                var ctor = new use(objVal.options);
                pathMap[map].use = ctor;
                return ctor.ready().then(function (list) {
                    let config = pathMap[map];
                    pathMap[map] = ctor;
                    if (Array.isArray(config.options.aliasForNs)) {
                        config.options.aliasForNs.forEach(ns => {
                            pathMap[ns] = ctor;
                        });
                    }
                    return Promise.resolve();
                });
            }
        }).then(() => {
            let ExtParser = pathMap['Ext'];
            let noParse = false;
            if (ExtParser.query) {
                let fileProps = ExtParser.fileMapCache[self.resourcePath];
                if (fileProps && fileProps.requires && fileProps.requires.length > 0) {
                    let requireStr = '';
                    fileProps.requires.forEach((require) => {
                        let result = ExtParser.query(require);
                        if (result instanceof Array) {
                            result.forEach((require) => {
                                requireStr += `require('${require.src}');\n`;
                            });
                        } else {
                            requireStr += `require('${ExtParser.query(require).src}');\n`;
                        }

                    });
                    updates.push({ type: 'add', start: 0, end: 0, data: requireStr });
                }
                if (fileProps && fileProps.overrides && fileProps.overrides.length > 0) {
                    let requireStr = '';
                    fileProps.overrides.forEach((require) => {
                        let result = ExtParser.query(require);
                        if (result instanceof Array) {
                            result.forEach((require) => {
                                requireStr += `require('${require.src}');\n`;
                            });
                        } else {
                            const requireSource = ExtParser.query(require).src || require;
                            if (requireSource) {
                                requireStr += `require('${requireSource}');\n`;
                            }
                        }

                    });
                    updates.push({ type: 'add', start: content.length, end: content.length, data: requireStr });
                }
            }
            esUtils.parentize(tree);
            esUtils.traverse(tree, function (node) {
                let requireStr = '';
                if (node && node.type === 'Property' && node.key && properties.includes(node.key.name)) {
                    const nodeName = node.key.name;

                    if (node && node.value && node.value.type === 'Literal') {
                        if (node.value.value !== null) {
                            requireStr += addRequire(node.value.value, configMap[nodeName].prefix || '');
                        }
                    } else if (node && node.value && node.value.type === 'ArrayExpression') {
                        node.value.elements.forEach(function (element) {
                            requireStr += addRequire(element.value, configMap[nodeName].prefix || '');
                        })
                    } else if (node && node.value && node.value.type === 'ObjectExpression' && node.value.properties && node.value.properties.length > 0 && configMap[node.key.name].allowObject) {
                        node.value.properties.forEach(function (objectNode) {
                            if (objectNode && objectNode.value && objectNode.value.type === 'Literal') {
                                if (objectNode.value !== null) {
                                    requireStr += addRequire(objectNode.value.value, configMap[nodeName].prefix || '');
                                }
                            }
                        })
                    }
                    if (requireStr !== '') {
                        let parent = findParentExpression(node);
                        if (configMap[nodeName].remove === true) {
                            updates.push({ type: 'remove', start: node.range[0], end: node.range[1] });
                        }
                        updates.push({
                            type: 'add',
                            start: parent.range[configMap[nodeName].end ? 1 : 0],
                            end: parent.range[configMap[nodeName].end ? 1 : 0],
                            data: requireStr
                        });
                        //   console.log('Requires by loader', requireStr);
                    }
                }
            });
            updates.sort((a, b) => {
                return b.end - a.end
            }).forEach(updateItem => {
                if (updateItem.type === 'remove') {
                    content = content.slice(0, updateItem.start) + content.slice(updateItem.end).replace(/^\s*,/im, '');
                } else if (updateItem.type === 'add') {
                    content = [content.slice(0, updateItem.start), updateItem.data, content.slice(updateItem.start)].join('');
                }
            });

            /**
             * Some
             */
            try {
                content = content.replace(/Ext.safeCreate\(['"](.*)['"]/img, function (match, offset, string) {
                    const resolvedClasses = resolveClassFile(offset);
                    let className;
                    if (resolvedClasses.length === 0) {
                        throw new Error(`Couldn't resolve class: ${offset}`)
                    } else {
                        className = resolvedClasses[0];
                    }
                    return 'require(' + escodegen.generate({
                        type: 'Literal',
                        value: className
                    }) + ');\r\n' + match;
                });

                fs.writeFileSync(cacheFile, content);
                callback(null, content, map);
            } catch (e) {
                callback(e)
            }
        });

    } catch (e) {
        console.error(chalk.red(`Error parsing ${self.resourcePath}`) + e);
        callback(e);
    }

};
<|endoftext|>


<commit_before>describe('quickhull', function () {
	describe('getDistant', function () {
		it('zero distance', function () {
			var bl = [
				{ lat: 0, lng: 0 },
				{ lat: 0, lng: 10 }
			];
			expect(L.QuickHull.getDistant({ lat: 0, lng: 0 }, bl)).to.eql(0);
		});
		it('non-zero distance', function () {
			var bl = [
				{ lat: 0, lng: 0 },
				{ lat: 0, lng: 10 }
			];
			expect(L.QuickHull.getDistant({ lat: 5, lng: 5 }, bl)).to.eql(-50);
		});
	});

	describe('getConvexHull', function () {
        it('creates a hull', function () {
			expect(L.QuickHull.getConvexHull([
                { lat: 0, lng: 0 },
                { lat: 10, lng: 0 },
                { lat: 10, lng: 10 },
                { lat: 0, lng: 10 },
                { lat: 5, lng: 5 },
            ])).to.eql([
                { lat: 0, lng: 10 },
                { lat: 10, lng: 10 },
                { lat: 10, lng: 0 },
                { lat: 0, lng: 0 },
            ]);
        });
    });
});
<commit_msg>Update QuickHullSpec.js<commit_after>describe('quickhull', function () {
	describe('getDistant', function () {
		it('zero distance', function () {
			var bl = [
				{ lat: 0, lng: 0 },
				{ lat: 0, lng: 10 }
			];
			expect(L.QuickHull.getDistant({ lat: 0, lng: 0 }, bl)).to.eql(0);
		});
		it('non-zero distance', function () {
			var bl = [
				{ lat: 0, lng: 0 },
				{ lat: 0, lng: 10 }
			];
			expect(L.QuickHull.getDistant({ lat: 5, lng: 5 }, bl)).to.eql(-50);
		});
	});

	describe('getConvexHull', function () {
		it('creates a hull', function () {
			expect(L.QuickHull.getConvexHull([	{ lat: 0, lng: 0 },
								{ lat: 10, lng: 0 },
								{ lat: 10, lng: 10 },
								{ lat: 0, lng: 10 },
								{ lat: 5, lng: 5 }
							 ])).to.eql([
							 	{ lat: 0, lng: 10 },
							 	{ lat: 10, lng: 10 },
							 	{ lat: 10, lng: 0 },
							 	{ lat: 0, lng: 0 }
							 ]);
		});
		it('creates a hull for vertically-aligned objects', function () {
			expect(L.QuickHull.getConvexHull([	{ lat: 0, lng: 0 },
								{ lat: 5, lng: 0 },
								{ lat: 10, lng: 0 }
							 ])).to.eql([
							 	{ lat: 0, lng: 0 },
							 	{ lat: 10, lng: 0 }
							 ]);
		});
		it('creates a hull for horizontally-aligned objects', function () {
			expect(L.QuickHull.getConvexHull([	{ lat: 0, lng: 0 },
								{ lat: 0, lng: 5 },
								{ lat: 0, lng: 10 }
							 ])).to.eql([
							 	{ lat: 0, lng: 0 },
							 	{ lat: 0, lng: 10 }
							 ]);
		});
	});
});
<|endoftext|>