<commit_before>
////////////////////////
// GLOBAL VARS
var whichPage;

var titles;
var descriptions;

var showAbout = false;
var showContact = false;
var trans = false;

var workDest = "work.html"
var procDest = "process/"
var homeDest = "index.html"

var paneFade = "slow"
var $container;
var pageBg;

var whichThumbs = "all";
var sorting = false;

////////////////////////
// SETUP ON READY

$(document).ready(function() {

    if (document.getElementById("fullBg") !== null && document.getElementById("fullBg") !== undefined) {
        //alert("Home Page");
        whichPage = "home";
        $("body").addClass("homePage");
        pageBg = $("#fullBg");
        pageBg.backstretch(["img/main/1.jpg"],{duration: 3500, fade: 3000});
        resizeBg(pageBg);
    } else if (document.getElementById("workBg") !== null && document.getElementById("workBg") !== undefined) {
        //alert("Work Page");
        whichPage = "work";
        $("body").addClass("workPage");
        pageBg = $("#workBg");
        pageBg.backstretch(["img/work/mesh.jpg"],{duration: 6500, fade: 3000});
        paneFade = 10;
        resizeThumbs();
        $container = $('#projContainer');
        // initialize
        $container.masonry({
            "columnWidth": ".projThumb",
            "gutter": ".gutter",
            "itemSelector": '.activeThumb',
            "isResizeBound": false
        });
        $container.masonry( 'on', 'layoutComplete', expandThumbBgs);
        resizeBg(pageBg);
    };

    if (whichPage === "home") {
        titles = ["001",
                  "002",
                  "003",
                  "004",
                  "005",
                  "006",
                  "007",
                  "008",
                  "009",
                  "010"];

        descriptions = ["Description description content description stuff",
                        "stuff stuff stuff describing things that are real",
                        "Description description content description stuff",
                        "stuff stuff stuff describing things that are real",
                        "Description description content description stuff",
                        "stuff stuff stuff describing things that are real",
                        "Description description content description stuff",
                        "stuff stuff stuff describing things that are real",
                        "Description description content description stuff",
                        "stuff stuff stuff describing things that are real"]
    };

    //$("#projName").html(titles[0]);
    //$("#projDesc").html(descriptions[0]);

    var Menu;
    if (Modernizr.csstransitions && Modernizr.csstransforms) {
        Menu = {
            el: {
                ham: $('.menu'),
                menuTop: $('.menu-top'),
                menuMiddle: $('.menu-middle'),
                menuBottom: $('.menu-bottom')
            },
            init: function() {
                Menu.bindUIactions();
            },
            bindUIactions: function() {
                Menu.el.ham
                .on('click',
                    function(event) {
                    Menu.activateMenu(event);
                    event.preventDefault();
                    $("#my-menu").trigger("open.mm");
                    }
                );
            },
            activateMenu: function() {
                Menu.el.menuTop.toggleClass('menu-top-click');
                Menu.el.menuMiddle.toggleClass('menu-middle-click');
                Menu.el.menuBottom.toggleClass('menu-bottom-click');
            }
        };
        Menu.init();
    } else {

    };

    $("#my-menu").mmenu({
        offCanvas: {
           position  : "right"
        }
     }).on( "closing.mm", function() {
        Menu.el.menuTop.removeClass('menu-top-click');
        Menu.el.menuMiddle.removeClass('menu-middle-click');
        Menu.el.menuBottom.removeClass('menu-bottom-click');
     }).css("visibility","visible");

    //$("body").addClass("good");

});

////////////////////////
// EVENTS

$( window ).load(function() {
    if (jQuery.browser.mobile == true) {
        //isMobile = true;
        $("body").addClass("isMobile");
    } else {
        $("body").addClass("isNotMobile");
    };
    if (whichPage === "home") {
        var bgArray = pageBg.data('backstretch');
        for (var i = 2; i <= 11; i++) {
            bgArray.images.push('img/main/' + i + '.jpg');
        };
    };
});

$(window).on("backstretch.before", function (e, instance, index) {
    $("#projName, #projDesc").fadeOut(1500,function(){
        $("#projName").html(titles[index]);
        $("#projDesc").html(descriptions[index]);
        $("#projName, #projDesc").fadeIn(1500);
    });

    if (whichPage === "work" && Modernizr.opacity) {
        $("#projMargin").fadeTo(2000,1.0);
    };
});

$(window).on("backstretch.after", function (e, instance, index) {
});

$(".mediaButton").click(function(){
    var what = $(this).attr("data-control");
    pageBg.backstretch(what);
    if (what == "pause") {
        //alert(what);
        $(this).attr("data-control","resume");
        $(this).addClass("play");
    } else if (what == "resume") {
        //alert(what);
        $(this).attr("data-control","pause");
        $(this).removeClass("play");
    };
});

$(".navLink").click(function(event){
    event.preventDefault();
    var dest = $(this).attr("data-dest");
    var active = $(this).index();
    $(".navLink").each(function(){
        $(this).removeClass("underlined");
    })

    if (dest == "work") {
        if (whichPage === "work") {
            hideOver();
        } else {
            $("#container").fadeOut(1000,function(){
                document.location.href = workDest;
            })
        };
    } else if (dest == "process") {
        if (whichPage === "process") {
            hideOver();
        } else {
            $("#container").fadeOut(1000,function(){
                document.location.href = procDest;
            })
        };
    } else {
        overlay(dest,active);
    };
});

$(".mmenuLink").click(function(event){
    event.preventDefault();
    var dest = $(this).attr("data-dest");

    if (dest == "work") {
        if (whichPage === "work") {
            hideOver();
            $("#my-menu").trigger("close.mm");
        } else {
            document.location.href = workDest;
        };
    } else if (dest == "process") {
        if (whichPage === "process") {
            hideOver();
            $("#my-menu").trigger("close.mm");
        } else {
            document.location.href = procDest;
        };
    } else if (dest == "home") {
        if (whichPage === "home") {
            hideOver();
            $("#my-menu").trigger("close.mm");
        } else {
            document.location.href = homeDest;
        };
    } else {
        $("#my-menu").trigger("close.mm");
        overlay(dest,99);
    };
});

$(".tagLink").click(function(event){
    event.preventDefault();
    var filter = $(this).attr("data-filter");

    if (filter === whichThumbs) {
        //alert("This IS active");
        // Do nothing
    } else if (filter === "all") {
        //alert("Will show All")
        sorting = true;
        whichThumbs = filter;

        $(".projThumb").each(function(index){
            // console.log(index);
            var outer = $(this);
            outer.addClass("activeThumb");
            outer.removeClass("projHidden");

            setTimeout(function() {
                //alert("woo")
                resizeThumbs();
                $container.masonry('reloadItems').masonry();
            }, 50);
        });
    } else {
        sorting = true;
        whichThumbs = filter;
        var amt = $('.projThumb').length;
        //alert(amt);
        $(".projThumb").each(function(index){
            // console.log(index);
            var outer = $(this);
            if ($(this).hasClass(filter)) {
                outer.addClass("activeThumb");
                outer.removeClass("projHidden");
            } else {
                $("p",this).fadeOut();
                $(".innerImage", this).animate({
                    height: "0px"
                  }, 500, function() {
                    outer.removeClass("activeThumb");
                    outer.addClass("projHidden");
                    //$container.masonry('reloadItems').masonry();
                  }
                );
            }
            if (index == amt-1) {
                setTimeout(function() {
                    //alert("woo")
                    resizeThumbs();
                    $container.masonry('reloadItems').masonry();
                }, 600);
            };
        });
    }
});

$(".closeOver").click(function(){
    hideOver();
});

$("#logoTop, #antaresName").click(function(){
    // if (showAbout || showContact) {
    //     hideOver();
    // };
    if (whichPage !== "home") {
        $("#container").fadeOut(1000,function(){
            document.location.href = "index.html";
        })
    };
});

$(document).keyup(function(e) {
    if (e.keyCode == 27) {            // ESC
        hideOver();
    }
});

on_resize(function() {
    //Throttled on-resize handler

})();

$( window ).resize(function() {
    //Normal on-resize handler

    if (whichPage === "work" && $container != undefined) {
        resizeThumbs();
        $container.masonry();
    };
    resizeBg(pageBg);
});

////////////////////////
// CUSTOM FUNCTIONS

function hideOver(){
    if (showAbout && !trans) {
        trans = true;
        $("#aboutInfo").fadeOut("slow",function(){
            $("#headerbg").animate({height: "100%"},function(){
                fadeRGBA($("#headerbg"),0.75);
                $("#labelPane").fadeIn(paneFade,function(){
                    showAbout = false;
                    trans = false;
                });
            });
        });
    } else if (showContact && !trans) {
        trans = true;
        $("#contactInfo").fadeOut("slow",function(){
            $("#headerbg").animate({height: "100%"},function(){
                fadeRGBA($("#headerbg"),0.75);
                $("#labelPane").fadeIn(paneFade,function(){
                    showContact = false;
                    trans = false;
                });
            });
        });
    };
    if (whichPage === "work") {
        $(".navLink:eq(0)").addClass("underlined");
    };
};

function fadeRGBA(thing, target) {
    if (Modernizr.rgba) {
        thing.animate({backgroundColor: jQuery.Color( "rgba(0,0,0," + target + ")" )});
    };
};

function overlay(dest,active) {
    var winHeight = window.innerHeight;

    if (dest == "about" && !trans) {
        if (!showAbout && !showContact) {
            trans = true;
            $("#labelPane").fadeOut( paneFade);
            $("#headerbg").animate({height: winHeight +"px"}, function(){
                fadeRGBA($("#headerbg"),0.9);
                $("#aboutInfo").fadeIn("slow",function(){
                    showAbout = true;
                    $(".navLink:eq(" + active + ")").addClass("underlined");
                    trans = false;
                });
            });
        } else if (showAbout && !showContact) {
            trans = true;
            $("#aboutInfo").fadeOut("slow",function(){
                $("#headerbg").animate({height: "100%"},function(){
                    fadeRGBA($("#headerbg"),0.75);
                    $("#labelPane").fadeIn(paneFade,function(){
                        showAbout = false;
                        if (whichPage === "work") {
                            $(".navLink:eq(0)").addClass("underlined");
                        };
                        trans = false;
                    });
                });
            });
        } else if (!showAbout && showContact) {
            trans = true;
            $("#contactInfo").fadeOut(function(){
                showContact = false;
                $("#aboutInfo").fadeIn("slow",function(){
                    showAbout = true;
                    $(".navLink:eq(" + active + ")").addClass("underlined");
                    trans = false;
                });
            });
        };

    } else if (dest == "contact" && !trans) {
        if (!showContact && !showAbout) {
            trans = true;
            $("#labelPane").fadeOut( paneFade);
            $("#headerbg").animate({height: winHeight +"px"}, function(){
                fadeRGBA($("#headerbg"),0.9);
                $("#contactInfo").fadeIn("slow",function(){
                    showContact = true;
                    $(".navLink:eq(" + active + ")").addClass("underlined");
                    trans = false;
                });
            });
        } else if (showContact && !showAbout) {
            trans = true;
            $("#contactInfo").fadeOut("slow",function(){
                $("#headerbg").animate({height: "100%"},function(){
                    fadeRGBA($("#headerbg"),0.75);
                    $("#labelPane").fadeIn(paneFade,function(){
                        showContact = false;
                        if (whichPage === "work") {
                            $(".navLink:eq(0)").addClass("underlined");
                        };
                        trans = false;
                    });
                });
            });
        } else if (!showContact && showAbout) {
            trans = true;
            $("#aboutInfo").fadeOut(function(){
                showAbout = false;
                $("#contactInfo").fadeIn("slow",function(){
                    showContact = true;
                    $(".navLink:eq(" + active + ")").addClass("underlined");
                    trans = false;
                });
            });
        };
    };
}

function resizeThumbs(){
    $(".projThumb").css("margin-bottom", $(".gutter").width()+"px");
    $(".projThumb").each(function(){
        var w = $(this).width();
        if ($(this).hasClass("vertThumb")) {
            $(this).css("height", (w * 1.5) + "px");
        } else {
            $(this).css("height", w + "px");
        };
    });
}

function resizeBg(bg) {
    //bg.height(jQuery(window).height());
    if (bg !== undefined) {
        bg.height(jQuery(window).height()+60);
    };
    //resizeBg(pageBg);
}

function expandThumbBgs(target) {
    if (sorting) {
        //alert("Expanded");
        $(".projThumb").each(function(){
            if ($(this).hasClass(whichThumbs) || whichThumbs === "all") {
                $(".innerImage", this).animate({
                    width: "100%",
                    height: "100%"
                  }, 500);
                $("p",this).fadeIn();
            }
        });
        sorting = false;
    };
}

////////////////////////
// UTILITIES

// debulked onresize handler
function on_resize(c,t){onresize=function(){clearTimeout(t);t=setTimeout(c,150)};return c};

// Avoid `console` errors in browsers that lack a console.
(function() {
    var method;
    var noop = function () {};
    var methods = [
        'assert', 'clear', 'count', 'debug', 'dir', 'dirxml', 'error',
        'exception', 'group', 'groupCollapsed', 'groupEnd', 'info', 'log',
        'markTimeline', 'profile', 'profileEnd', 'table', 'time', 'timeEnd',
        'timeline', 'timelineEnd', 'timeStamp', 'trace', 'warn'
    ];
    var length = methods.length;
    var console = (window.console = window.console || {});

    while (length--) {
        method = methods[length];

        // Only stub undefined methods.
        if (!console[method]) {
            console[method] = noop;
        }
    }
}());

/*
event.preventDefault();
var items = $container.masonry('getItemElements');
//$container.masonry( 'remove', item[1] );
//$container.masonry( 'remove', document.getElementById("firstThumb") ).masonry();
var item = $container.masonry( 'getItem', items[0] );
console.log(item);
$container.masonry( 'remove', items[0] );
*/

<commit_msg>speed<commit_after>
////////////////////////
// GLOBAL VARS
var whichPage;

var titles;
var descriptions;

var showAbout = false;
var showContact = false;
var trans = false;

var workDest = "work.html"
var procDest = "process/"
var homeDest = "index.html"

var paneFade = "slow"
var $container;
var pageBg;

var whichThumbs = "all";
var sorting = false;

////////////////////////
// SETUP ON READY

$(document).ready(function() {

    if (document.getElementById("fullBg") !== null && document.getElementById("fullBg") !== undefined) {
        //alert("Home Page");
        whichPage = "home";
        $("body").addClass("homePage");
        pageBg = $("#fullBg");
        pageBg.backstretch(["img/main/1.jpg"],{duration: 2500, fade: 3000});
        resizeBg(pageBg);
    } else if (document.getElementById("workBg") !== null && document.getElementById("workBg") !== undefined) {
        //alert("Work Page");
        whichPage = "work";
        $("body").addClass("workPage");
        pageBg = $("#workBg");
        pageBg.backstretch(["img/work/mesh.jpg"],{duration: 6500, fade: 3000});
        paneFade = 10;
        resizeThumbs();
        $container = $('#projContainer');
        // initialize
        $container.masonry({
            "columnWidth": ".projThumb",
            "gutter": ".gutter",
            "itemSelector": '.activeThumb',
            "isResizeBound": false
        });
        $container.masonry( 'on', 'layoutComplete', expandThumbBgs);
        resizeBg(pageBg);
    };

    if (whichPage === "home") {
        titles = ["001",
                  "002",
                  "003",
                  "004",
                  "005",
                  "006",
                  "007",
                  "008",
                  "009",
                  "010"];

        descriptions = ["Description description content description stuff",
                        "stuff stuff stuff describing things that are real",
                        "Description description content description stuff",
                        "stuff stuff stuff describing things that are real",
                        "Description description content description stuff",
                        "stuff stuff stuff describing things that are real",
                        "Description description content description stuff",
                        "stuff stuff stuff describing things that are real",
                        "Description description content description stuff",
                        "stuff stuff stuff describing things that are real"]
    };

    //$("#projName").html(titles[0]);
    //$("#projDesc").html(descriptions[0]);

    var Menu;
    if (Modernizr.csstransitions && Modernizr.csstransforms) {
        Menu = {
            el: {
                ham: $('.menu'),
                menuTop: $('.menu-top'),
                menuMiddle: $('.menu-middle'),
                menuBottom: $('.menu-bottom')
            },
            init: function() {
                Menu.bindUIactions();
            },
            bindUIactions: function() {
                Menu.el.ham
                .on('click',
                    function(event) {
                    Menu.activateMenu(event);
                    event.preventDefault();
                    $("#my-menu").trigger("open.mm");
                    }
                );
            },
            activateMenu: function() {
                Menu.el.menuTop.toggleClass('menu-top-click');
                Menu.el.menuMiddle.toggleClass('menu-middle-click');
                Menu.el.menuBottom.toggleClass('menu-bottom-click');
            }
        };
        Menu.init();
    } else {

    };

    $("#my-menu").mmenu({
        offCanvas: {
           position  : "right"
        }
     }).on( "closing.mm", function() {
        Menu.el.menuTop.removeClass('menu-top-click');
        Menu.el.menuMiddle.removeClass('menu-middle-click');
        Menu.el.menuBottom.removeClass('menu-bottom-click');
     }).css("visibility","visible");

    //$("body").addClass("good");

});

////////////////////////
// EVENTS

$( window ).load(function() {
    if (jQuery.browser.mobile == true) {
        //isMobile = true;
        $("body").addClass("isMobile");
    } else {
        $("body").addClass("isNotMobile");
    };
    if (whichPage === "home") {
        var bgArray = pageBg.data('backstretch');
        for (var i = 2; i <= 11; i++) {
            bgArray.images.push('img/main/' + i + '.jpg');
        };
    };
});

$(window).on("backstretch.before", function (e, instance, index) {
    $("#projName, #projDesc").fadeOut(1500,function(){
        $("#projName").html(titles[index]);
        $("#projDesc").html(descriptions[index]);
        $("#projName, #projDesc").fadeIn(1500);
    });

    if (whichPage === "work" && Modernizr.opacity) {
        $("#projMargin").fadeTo(2000,1.0);
    };
});

$(window).on("backstretch.after", function (e, instance, index) {
});

$(".mediaButton").click(function(){
    var what = $(this).attr("data-control");
    pageBg.backstretch(what);
    if (what == "pause") {
        //alert(what);
        $(this).attr("data-control","resume");
        $(this).addClass("play");
    } else if (what == "resume") {
        //alert(what);
        $(this).attr("data-control","pause");
        $(this).removeClass("play");
    };
});

$(".navLink").click(function(event){
    event.preventDefault();
    var dest = $(this).attr("data-dest");
    var active = $(this).index();
    $(".navLink").each(function(){
        $(this).removeClass("underlined");
    })

    if (dest == "work") {
        if (whichPage === "work") {
            hideOver();
        } else {
            $("#container").fadeOut(1000,function(){
                document.location.href = workDest;
            })
        };
    } else if (dest == "process") {
        if (whichPage === "process") {
            hideOver();
        } else {
            $("#container").fadeOut(1000,function(){
                document.location.href = procDest;
            })
        };
    } else {
        overlay(dest,active);
    };
});

$(".mmenuLink").click(function(event){
    event.preventDefault();
    var dest = $(this).attr("data-dest");

    if (dest == "work") {
        if (whichPage === "work") {
            hideOver();
            $("#my-menu").trigger("close.mm");
        } else {
            document.location.href = workDest;
        };
    } else if (dest == "process") {
        if (whichPage === "process") {
            hideOver();
            $("#my-menu").trigger("close.mm");
        } else {
            document.location.href = procDest;
        };
    } else if (dest == "home") {
        if (whichPage === "home") {
            hideOver();
            $("#my-menu").trigger("close.mm");
        } else {
            document.location.href = homeDest;
        };
    } else {
        $("#my-menu").trigger("close.mm");
        overlay(dest,99);
    };
});

$(".tagLink").click(function(event){
    event.preventDefault();
    var filter = $(this).attr("data-filter");

    if (filter === whichThumbs) {
        //alert("This IS active");
        // Do nothing
    } else if (filter === "all") {
        //alert("Will show All")
        sorting = true;
        whichThumbs = filter;

        $(".projThumb").each(function(index){
            // console.log(index);
            var outer = $(this);
            outer.addClass("activeThumb");
            outer.removeClass("projHidden");

            setTimeout(function() {
                //alert("woo")
                resizeThumbs();
                $container.masonry('reloadItems').masonry();
            }, 50);
        });
    } else {
        sorting = true;
        whichThumbs = filter;
        var amt = $('.projThumb').length;
        //alert(amt);
        $(".projThumb").each(function(index){
            // console.log(index);
            var outer = $(this);
            if ($(this).hasClass(filter)) {
                outer.addClass("activeThumb");
                outer.removeClass("projHidden");
            } else {
                $("p",this).fadeOut();
                $(".innerImage", this).animate({
                    height: "0px"
                  }, 500, function() {
                    outer.removeClass("activeThumb");
                    outer.addClass("projHidden");
                    //$container.masonry('reloadItems').masonry();
                  }
                );
            }
            if (index == amt-1) {
                setTimeout(function() {
                    //alert("woo")
                    resizeThumbs();
                    $container.masonry('reloadItems').masonry();
                }, 600);
            };
        });
    }
});

$(".closeOver").click(function(){
    hideOver();
});

$("#logoTop, #antaresName").click(function(){
    // if (showAbout || showContact) {
    //     hideOver();
    // };
    if (whichPage !== "home") {
        $("#container").fadeOut(1000,function(){
            document.location.href = "index.html";
        })
    };
});

$(document).keyup(function(e) {
    if (e.keyCode == 27) {            // ESC
        hideOver();
    }
});

on_resize(function() {
    //Throttled on-resize handler

})();

$( window ).resize(function() {
    //Normal on-resize handler

    if (whichPage === "work" && $container != undefined) {
        resizeThumbs();
        $container.masonry();
    };
    resizeBg(pageBg);
});

////////////////////////
// CUSTOM FUNCTIONS

function hideOver(){
    if (showAbout && !trans) {
        trans = true;
        $("#aboutInfo").fadeOut("slow",function(){
            $("#headerbg").animate({height: "100%"},function(){
                fadeRGBA($("#headerbg"),0.75);
                $("#labelPane").fadeIn(paneFade,function(){
                    showAbout = false;
                    trans = false;
                });
            });
        });
    } else if (showContact && !trans) {
        trans = true;
        $("#contactInfo").fadeOut("slow",function(){
            $("#headerbg").animate({height: "100%"},function(){
                fadeRGBA($("#headerbg"),0.75);
                $("#labelPane").fadeIn(paneFade,function(){
                    showContact = false;
                    trans = false;
                });
            });
        });
    };
    if (whichPage === "work") {
        $(".navLink:eq(0)").addClass("underlined");
    };
};

function fadeRGBA(thing, target) {
    if (Modernizr.rgba) {
        thing.animate({backgroundColor: jQuery.Color( "rgba(0,0,0," + target + ")" )});
    };
};

function overlay(dest,active) {
    var winHeight = window.innerHeight;

    if (dest == "about" && !trans) {
        if (!showAbout && !showContact) {
            trans = true;
            $("#labelPane").fadeOut( paneFade);
            $("#headerbg").animate({height: winHeight +"px"}, function(){
                fadeRGBA($("#headerbg"),0.9);
                $("#aboutInfo").fadeIn("slow",function(){
                    showAbout = true;
                    $(".navLink:eq(" + active + ")").addClass("underlined");
                    trans = false;
                });
            });
        } else if (showAbout && !showContact) {
            trans = true;
            $("#aboutInfo").fadeOut("slow",function(){
                $("#headerbg").animate({height: "100%"},function(){
                    fadeRGBA($("#headerbg"),0.75);
                    $("#labelPane").fadeIn(paneFade,function(){
                        showAbout = false;
                        if (whichPage === "work") {
                            $(".navLink:eq(0)").addClass("underlined");
                        };
                        trans = false;
                    });
                });
            });
        } else if (!showAbout && showContact) {
            trans = true;
            $("#contactInfo").fadeOut(function(){
                showContact = false;
                $("#aboutInfo").fadeIn("slow",function(){
                    showAbout = true;
                    $(".navLink:eq(" + active + ")").addClass("underlined");
                    trans = false;
                });
            });
        };

    } else if (dest == "contact" && !trans) {
        if (!showContact && !showAbout) {
            trans = true;
            $("#labelPane").fadeOut( paneFade);
            $("#headerbg").animate({height: winHeight +"px"}, function(){
                fadeRGBA($("#headerbg"),0.9);
                $("#contactInfo").fadeIn("slow",function(){
                    showContact = true;
                    $(".navLink:eq(" + active + ")").addClass("underlined");
                    trans = false;
                });
            });
        } else if (showContact && !showAbout) {
            trans = true;
            $("#contactInfo").fadeOut("slow",function(){
                $("#headerbg").animate({height: "100%"},function(){
                    fadeRGBA($("#headerbg"),0.75);
                    $("#labelPane").fadeIn(paneFade,function(){
                        showContact = false;
                        if (whichPage === "work") {
                            $(".navLink:eq(0)").addClass("underlined");
                        };
                        trans = false;
                    });
                });
            });
        } else if (!showContact && showAbout) {
            trans = true;
            $("#aboutInfo").fadeOut(function(){
                showAbout = false;
                $("#contactInfo").fadeIn("slow",function(){
                    showContact = true;
                    $(".navLink:eq(" + active + ")").addClass("underlined");
                    trans = false;
                });
            });
        };
    };
}

function resizeThumbs(){
    $(".projThumb").css("margin-bottom", $(".gutter").width()+"px");
    $(".projThumb").each(function(){
        var w = $(this).width();
        if ($(this).hasClass("vertThumb")) {
            $(this).css("height", (w * 1.5) + "px");
        } else {
            $(this).css("height", w + "px");
        };
    });
}

function resizeBg(bg) {
    //bg.height(jQuery(window).height());
    if (bg !== undefined) {
        bg.height(jQuery(window).height()+60);
    };
    //resizeBg(pageBg);
}

function expandThumbBgs(target) {
    if (sorting) {
        //alert("Expanded");
        $(".projThumb").each(function(){
            if ($(this).hasClass(whichThumbs) || whichThumbs === "all") {
                $(".innerImage", this).animate({
                    width: "100%",
                    height: "100%"
                  }, 500);
                $("p",this).fadeIn();
            }
        });
        sorting = false;
    };
}

////////////////////////
// UTILITIES

// debulked onresize handler
function on_resize(c,t){onresize=function(){clearTimeout(t);t=setTimeout(c,150)};return c};

// Avoid `console` errors in browsers that lack a console.
(function() {
    var method;
    var noop = function () {};
    var methods = [
        'assert', 'clear', 'count', 'debug', 'dir', 'dirxml', 'error',
        'exception', 'group', 'groupCollapsed', 'groupEnd', 'info', 'log',
        'markTimeline', 'profile', 'profileEnd', 'table', 'time', 'timeEnd',
        'timeline', 'timelineEnd', 'timeStamp', 'trace', 'warn'
    ];
    var length = methods.length;
    var console = (window.console = window.console || {});

    while (length--) {
        method = methods[length];

        // Only stub undefined methods.
        if (!console[method]) {
            console[method] = noop;
        }
    }
}());

/*
event.preventDefault();
var items = $container.masonry('getItemElements');
//$container.masonry( 'remove', item[1] );
//$container.masonry( 'remove', document.getElementById("firstThumb") ).masonry();
var item = $container.masonry( 'getItem', items[0] );
console.log(item);
$container.masonry( 'remove', items[0] );
*/

<|endoftext|>


<commit_before>/**
 * Chiffon
 *
 * @description  A very small ECMAScript parser, tokenizer and minify written in JavaScript
 * @fileoverview JavaScript parser, tokenizer and minify library
 * @version      1.1.2
 * @date         2015-10-06
 * @link         https://github.com/polygonplanet/Chiffon
 * @copyright    Copyright (c) 2015 polygon planet <polygon.planet.aqua@gmail.com>
 * @license      Licensed under the MIT license.
 */

/*jshint bitwise:false, eqnull:true */
(function(name, context, factory) {

  // Supports UMD. AMD, CommonJS/Node.js and browser context
  if (typeof exports !== 'undefined') {
    if (typeof module !== 'undefined' && module.exports) {
      module.exports = factory();
    } else {
      exports[name] = factory();
    }
  } else if (typeof define === 'function' && define.amd) {
    define(factory);
  } else {
    context[name] = factory();
  }

}('Chiffon', this, function() {
  'use strict';

  var Chiffon = {};

  var hasOwnProperty = Object.prototype.hasOwnProperty;

  var Keywords = makeDict(
    // ECMA-262 11.6.2.1 Keywords
    'break do in typeof case else instanceof var ' +
    'catch export new void class extends return while const finally ' +
    'super with continue for switch yield debugger function this default ' +
    'if throw delete import try ' +
    'arguments eval ' +
    // ECMA-262 11.6.2.2 Future Reserved Words
    'enum await ' +
    'implements package protected interface private public'
  );

  var TokenName = {
    2: 'Comment',
    3: 'Comment',
    4: 'LineTerminator',
    5: 'Comment',
    6: 'Template',
    7: 'String',
    8: 'Punctuator',
    9: 'LineTerminator',
    10: 'RegularExpression',
    11: 'Punctuator',
    12: 'Numeric',
    13: 'UnicodeEscapeSequence',
    14: 'LineTerminator',
    15: 'Identifier',
    Null: 'Null',
    Boolean: 'Boolean',
    Keyword: 'Keyword'
  };

  var lineTerminator = '\\r\\n\\u2028\\u2029';
  var lineTerminatorSequence = '(?:\\r\\n|[' + lineTerminator + '])';
  var whiteSpace = '(?:(?![' + lineTerminator + '])\\s)+';
  var regexpFlags = makeRegExpFlagPattern('gimuy');
  var literalSuffix = '(?=' +
    '\\s*' +
    '(?:' + '(?!\\s*[/\\\\<>*+%`^"\'\\w$-])' +
            '[^/\\\\<>*+%`^\'"({[\\w$-]' +
      '|' + '[!=]==?' +
      '|' + '[|][|]' +
      '|' + '[&][&]' +
      '|' + '/(?:[*]|/)' +
      '|' + '[,.;:!?)}\\]' + lineTerminator + ']' +
      '|' + '$' +
    ')' +
  ')';

  var tokenizePattern = new RegExp(
    '(' + // (2) multiline comment
          '(/[*][\\s\\S]*?[*]/)' +
          // (3) single line comment
    '|' + '(' + '//[^' + lineTerminator + ']*' +
          '|' + '<!--[^' + lineTerminator + ']*' +
          ')' +
          // (4) line terminators
    '|' + '(?:^|(' + lineTerminatorSequence + '))' +
          '(?:' + whiteSpace + '|)' +
          // (5) single line comment
          '(' + '-->[^' + lineTerminator + ']*' +
          ')' +
          // (6) template literal
    '|' + '(' + '`(?:\\\\[\\s\\S]|[^`\\\\])*`' +
          ')' + literalSuffix +
          // (7) string literal
    '|' + '(' + '"(?:\\\\[\\s\\S]|[^"' + lineTerminator + '\\\\])*"' +
          '|' + "'(?:\\\\[\\s\\S]|[^'" + lineTerminator + "\\\\])*'" +
          ')' +
          // (8) regexp literal prefix
    '|' + '(' + '^' +
          '|' + '[-!%&*+,/:;<=>?[{(^|~]' +
          ')' +
          '(?:' + whiteSpace +
          // (9) line terminators
          '|' + '(' + lineTerminatorSequence + ')' +
          ')?' +
          '(?:' +
            // (10) regular expression literal
            '(' +
                '(?:/(?![*])(?:\\\\.|[^/' + lineTerminator + '\\\\])+/)' +
                '(?:' + regexpFlags + '|)' +
            ')' + literalSuffix +
          ')' +
          // (11) operators
    '|' + '(' + '>>>=?|[.][.][.]|<<=|===|!==|>>=' +
          '|' + '[+][+](?=[+])|[-][-](?=[-])' +
          '|' + '[=!<>*%+/&|^-]=' +
          '|' + '[&][&]|[|][|]|[+][+]|[-][-]|<<|>>|=>' +
          '|' + '[-+*/%<>=&|^~!?:;,.()[\\]{}]' +
          ')' +
          // (12) numeric literal
    '|' + '(' + '0(?:' + '[xX][0-9a-fA-F]+' +
                   '|' + '[oO]?[0-7]+' +
                   '|' + '[bB][01]+' +
                   ')' +
          '|' + '\\d+(?:[.]\\d+)?(?:[eE][+-]?\\d+)?' +
          '|' + '[1-9]\\d*' +
          ')' +
          // (13) unicode character
    '|' + '(' + '\\\\u[0-9a-fA-F]{4}' +
          ')' +
    '|' + whiteSpace +
          // (14) line terminators
    '|' + '(' + lineTerminatorSequence + ')' +
          // (15) identifier
    '|' + '(' + '[^\\s+/%*=&|^~<>!?:;,.()[\\]{}\'"`-]+' +
          ')' +
    ')',
    'g'
  );

  function makeRegExpFlagPattern(flags) {
    flags = flags.split('');

    var len = flags.length;
    var patterns = {};
    var i, j, k, l, m;
    var c, c2, c3, c4, c5;

    var add = function(f) {
      if (!/(.).*\1/.test(f)) {
        patterns[f] = 1;
      }
    };

    for (i = 0; i < len; i++) {
      c = flags[i];
      patterns[c] = 1;

      for (j = 0; j < len; j++) {
        c2 = flags[j];
        add(c + c2);

        for (k = 0; k < len; k++) {
          c3 = flags[k];
          add(c + c2 + c3);

          for (l = 0; l < len; l++) {
            c4 = flags[l];
            add(c + c2 + c3 + c4);

            for (m = 0; m < len; m++) {
              c5 = flags[m];
              add(c + c2 + c3 + c4 + c5);
            }
          }
        }
      }
    }

    return '(?:' + getKeys(patterns).join('|') + ')';
  }

  function parseMatches(match, options) {
    var tokens = [];
    var tokenKeys = getKeys(TokenName);

    for (var i = 0, len = tokenKeys.length; i < len; i++) {
      var key = tokenKeys[i];
      var value = match[key];
      if (!value) {
        continue;
      }

      var name = TokenName[key];
      if ((name === 'Comment' && !options.comment) ||
          (name === 'LineTerminator' && !options.lineTerminator)) {
        continue;
      }

      var type = name;
      if (name === 'Identifier') {
        if (value === 'null') {
          type = TokenName.Null;
        } else if (value === 'true' || value === 'false') {
          type = TokenName.Boolean;
        } else if (hasOwnProperty.call(Keywords, value)) {
          type = TokenName.Keyword;
        }
      }

      tokens[tokens.length] = {
        type: type,
        value: value
      };
    }

    return tokens;
  }

  function tokenize(code, options) {
    options = options || {};

    var results = [];
    var m;

    tokenizePattern.lastIndex = 0;
    while ((m = tokenizePattern.exec(code)) != null) {
      var tokens = parseMatches(m, options);
      for (var i = 0, len = tokens.length; i < len; i++) {
        results[results.length] = tokens[i];
      }
    }

    return results;
  }

  /**
   * Tokenize a string code.
   *
   * @param {string} code Target code.
   * @param {Object} [options] Tokenize options.
   *   - comment: {boolean} (default=false)
   *     true = Keep comment tokens.
   *   - lineTerminator: {boolean} (default=false)
   *     true = Keep line feed tokens.
   * @return {string} Return an array of the parsed tokens.
   */
  Chiffon.tokenize = tokenize;

  function untokenize(tokens) {
    var ident = /[^\s+\/%*=&|^~<>!?:;,.()[\]{}'"`-]/;
    var sign = /[+-]/;
    var LT = 'LineTerminator';

    var results = [];
    var prev;

    for (var i = 0, len = tokens.length; i < len; prev = tokens[i++]) {
      var token = tokens[i];

      if (!prev) {
        if (token.type !== LT) {
          results[results.length] = token.value;
        }
        continue;
      }

      if (prev.type === LT && token.type === LT) {
        continue;
      }

      var space = '';
      if ((sign.test(token.value) && sign.test(prev.value)) ||
          (ident.test(prev.value.slice(-1)) && ident.test(token.value.charAt(0)))) {
        space = ' ';
      }

      results[results.length] = space + token.value;
    }

    return results.join('');
  }

  /**
   * Concatenate to string from the parsed tokens.
   *
   * @param {Array} tokens An array of the parsed tokens.
   * @return {string} Return a concatenated string.
   */
  Chiffon.untokenize = untokenize;

  function minify(code) {
    return untokenize(tokenize(code, { lineTerminator: true }));
  }

  /**
   * Minify JavaScript code.
   *
   * @param {string} code Target code.
   * @return {string} Return a minified code.
   */
  Chiffon.minify = minify;

  function getKeys(object) {
    if (Object.keys) {
      return Object.keys(object);
    }

    var keys = [];
    for (var key in object) {
      if (hasOwnProperty.call(object, key)) {
        keys[keys.length] = key;
      }
    }
    return keys;
  }

  function makeDict(string) {
    var dict = {};
    var words = string.split(/\s+/);
    for (var i = 0, len = words.length; i < len; i++) {
      dict[words[i]] = true;
    }
    return dict;
  }

  return Chiffon;
}));
<commit_msg>Optimize patterns<commit_after>/**
 * Chiffon
 *
 * @description  A very small ECMAScript parser, tokenizer and minify written in JavaScript
 * @fileoverview JavaScript parser, tokenizer and minify library
 * @version      1.1.3
 * @date         2015-10-06
 * @link         https://github.com/polygonplanet/Chiffon
 * @copyright    Copyright (c) 2015 polygon planet <polygon.planet.aqua@gmail.com>
 * @license      Licensed under the MIT license.
 */

/*jshint bitwise:false, eqnull:true */
(function(name, context, factory) {

  // Supports UMD. AMD, CommonJS/Node.js and browser context
  if (typeof exports !== 'undefined') {
    if (typeof module !== 'undefined' && module.exports) {
      module.exports = factory();
    } else {
      exports[name] = factory();
    }
  } else if (typeof define === 'function' && define.amd) {
    define(factory);
  } else {
    context[name] = factory();
  }

}('Chiffon', this, function() {
  'use strict';

  var Chiffon = {};

  var hasOwnProperty = Object.prototype.hasOwnProperty;

  var Keywords = (function(words) {
    words = words.split(/\s+/);
    var kw = {};
    for (var i = 0, len = words.length; i < len; i++) {
      kw[words[i]] = 1;
    }
    return kw;
  }(
    // ECMA-262 11.6.2.1 Keywords
    'break do in typeof case else instanceof var ' +
    'catch export new void class extends return while const finally ' +
    'super with continue for switch yield debugger function this default ' +
    'if throw delete import try ' +
    'arguments eval ' +
    // ECMA-262 11.6.2.2 Future Reserved Words
    'enum await ' +
    'implements package protected interface private public'
  ));

  var _Comment = 'Comment',
      _LineTerminator = 'LineTerminator',
      _Template = 'Template',
      _String = 'String',
      _Punctuator = 'Punctuator',
      _RegularExpression = 'RegularExpression',
      _Numeric = 'Numeric',
      _UnicodeEscapeSequence = 'UnicodeEscapeSequence',
      _Identifier = 'Identifier',
      _Null = 'Null',
      _Boolean = 'Boolean',
      _Keyword = 'Keyword';

  var TokenName = {
    2: _Comment,
    3: _Comment,
    4: _LineTerminator,
    5: _Comment,
    6: _Template,
    7: _String,
    8: _Punctuator,
    9: _LineTerminator,
    10: _RegularExpression,
    11: _Punctuator,
    12: _Numeric,
    13: _UnicodeEscapeSequence,
    14: _LineTerminator,
    15: _Identifier
  };

  var lineTerminator = '\\r\\n\\u2028\\u2029';
  var lineTerminatorSequence = '(?:\\r\\n|[' + lineTerminator + '])';
  var whiteSpace = '(?:(?![' + lineTerminator + '])\\s)+';
  var regexpFlags = makeRegExpFlagPattern('gimuy');
  var literalSuffix = '(?=' +
    '\\s*' +
    '(?:' + '(?!\\s*[/\\\\<>*+%`^"\'\\w$-])' +
            '[^/\\\\<>*+%`^\'"({[\\w$-]' +
      '|' + '[!=]==?' +
      '|' + '[|][|]' +
      '|' + '&&' +
      '|' + '/(?:[*]|/)' +
      '|' + '[,.;:!?)}\\]' + lineTerminator + ']' +
      '|' + '$' +
    ')' +
  ')';

  var tokenizePattern = new RegExp(
    '(' + // (2) multiline comment
          '(/[*][\\s\\S]*?[*]/)' +
          // (3) single line comment
    '|' + '(' + '//[^' + lineTerminator + ']*' +
          '|' + '<!--[^' + lineTerminator + ']*' +
          ')' +
          // (4) line terminators
    '|' + '(?:^|(' + lineTerminatorSequence + '))' +
          '(?:' + whiteSpace + '|)' +
          // (5) single line comment
          '(' + '-->[^' + lineTerminator + ']*' +
          ')' +
          // (6) template literal
    '|' + '(' + '`(?:\\\\[\\s\\S]|[^`\\\\])*`' +
          ')' + literalSuffix +
          // (7) string literal
    '|' + '(' + '"(?:\\\\[\\s\\S]|[^"' + lineTerminator + '\\\\])*"' +
          '|' + "'(?:\\\\[\\s\\S]|[^'" + lineTerminator + "\\\\])*'" +
          ')' +
          // (8) regexp literal prefix
    '|' + '(' + '^' +
          '|' + '[-!%&*+,/:;<=>?[{(^|~]' +
          ')' +
          '(?:' + whiteSpace +
          // (9) line terminators
          '|' + '(' + lineTerminatorSequence + ')' +
          ')?' +
          '(?:' +
            // (10) regular expression literal
            '(' +
                '(?:/(?![*])(?:\\\\.|[^/' + lineTerminator + '\\\\])+/)' +
                '(?:' + regexpFlags + '|)' +
            ')' + literalSuffix +
          ')' +
          // (11) operators
    '|' + '(' + '>>>=?|[.][.][.]|<<=|===|!==|>>=' +
          '|' + '[+][+](?=[+])|--(?=-)' +
          '|' + '[=!<>*%+/&|^-]=' +
          '|' + '&&|[|][|]|[+][+]|--|<<|>>|=>' +
          '|' + '[-+*/%<>=&|^~!?:;,.()[\\]{}]' +
          ')' +
          // (12) numeric literal
    '|' + '(' + '0(?:' + '[xX][0-9a-fA-F]+' +
                   '|' + '[oO]?[0-7]+' +
                   '|' + '[bB][01]+' +
                   ')' +
          '|' + '\\d+(?:[.]\\d+)?(?:[eE][+-]?\\d+)?' +
          '|' + '[1-9]\\d*' +
          ')' +
          // (13) unicode character
    '|' + '(' + '\\\\u[0-9a-fA-F]{4}' +
          ')' +
    '|' + whiteSpace +
          // (14) line terminators
    '|' + '(' + lineTerminatorSequence + ')' +
          // (15) identifier
    '|' + '(' + '[^\\s+/%*=&|^~<>!?:;,.()[\\]{}\'"`-]+' +
          ')' +
    ')',
    'g'
  );

  function makeRegExpFlagPattern(flags) {
    flags = flags.split('');

    var len = flags.length;
    var patterns = {};
    var i, j, k, l, m;
    var c, c2, c3, c4, c5;

    var add = function(f) {
      if (!/(.).*\1/.test(f)) {
        patterns[f] = 1;
      }
    };

    for (i = 0; i < len; i++) {
      c = flags[i];
      patterns[c] = 1;

      for (j = 0; j < len; j++) {
        c2 = flags[j];
        add(c + c2);

        for (k = 0; k < len; k++) {
          c3 = flags[k];
          add(c + c2 + c3);

          for (l = 0; l < len; l++) {
            c4 = flags[l];
            add(c + c2 + c3 + c4);

            for (m = 0; m < len; m++) {
              c5 = flags[m];
              add(c + c2 + c3 + c4 + c5);
            }
          }
        }
      }
    }

    return '(?:' + getKeys(patterns).join('|') + ')';
  }

  function parseMatches(match, options) {
    var tokens = [];
    var tokenKeys = getKeys(TokenName);

    for (var i = 0, len = tokenKeys.length; i < len; i++) {
      var key = tokenKeys[i];
      var value = match[key];
      if (!value) {
        continue;
      }

      var name = TokenName[key];
      if ((name === _Comment && !options.comment) ||
          (name === _LineTerminator && !options.lineTerminator)) {
        continue;
      }

      var type = name;
      if (name === _Identifier) {
        if (value === 'null') {
          type = _Null;
        } else if (value === 'true' || value === 'false') {
          type = _Boolean;
        } else if (hasOwnProperty.call(Keywords, value)) {
          type = _Keyword;
        }
      }

      tokens[tokens.length] = {
        type: type,
        value: value
      };
    }

    return tokens;
  }

  function tokenize(code, options) {
    options = options || {};

    var results = [];
    var m;

    tokenizePattern.lastIndex = 0;
    while ((m = tokenizePattern.exec(code)) != null) {
      var tokens = parseMatches(m, options);
      for (var i = 0, len = tokens.length; i < len; i++) {
        results[results.length] = tokens[i];
      }
    }

    return results;
  }

  /**
   * Tokenize a string code.
   *
   * @param {string} code Target code.
   * @param {Object} [options] Tokenize options.
   *   - comment: {boolean} (default=false)
   *     true = Keep comment tokens.
   *   - lineTerminator: {boolean} (default=false)
   *     true = Keep line feed tokens.
   * @return {string} Return an array of the parsed tokens.
   */
  Chiffon.tokenize = tokenize;

  function untokenize(tokens) {
    var ident = /[^\s+\/%*=&|^~<>!?:;,.()[\]{}'"`-]/;
    var sign = /[+-]/;

    var results = [];
    var prev;

    for (var i = 0, len = tokens.length; i < len; prev = tokens[i++]) {
      var token = tokens[i];

      if (!prev) {
        if (token.type !== _LineTerminator) {
          results[results.length] = token.value;
        }
        continue;
      }

      if (prev.type === _LineTerminator && token.type === _LineTerminator) {
        continue;
      }

      var space = '';
      if ((sign.test(token.value) && sign.test(prev.value)) ||
          (ident.test(prev.value.slice(-1)) && ident.test(token.value.charAt(0)))) {
        space = ' ';
      }

      results[results.length] = space + token.value;
    }

    return results.join('');
  }

  /**
   * Concatenate to string from the parsed tokens.
   *
   * @param {Array} tokens An array of the parsed tokens.
   * @return {string} Return a concatenated string.
   */
  Chiffon.untokenize = untokenize;

  function minify(code) {
    return untokenize(tokenize(code, { lineTerminator: true }));
  }

  /**
   * Minify JavaScript code.
   *
   * @param {string} code Target code.
   * @return {string} Return a minified code.
   */
  Chiffon.minify = minify;

  function getKeys(object) {
    if (Object.keys) {
      return Object.keys(object);
    }

    var keys = [];
    for (var key in object) {
      if (hasOwnProperty.call(object, key)) {
        keys[keys.length] = key;
      }
    }
    return keys;
  }

  return Chiffon;
}));
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2014 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

CLASS({
  name: 'BusyStatus',
  documentation: '
Sets an output property to true when any "process" is ' +
      'active. Any code that needs to indicate a busy state can call ' +
      '$$DOC{ref:".start"}, which returns a completion function. When the ' +
      'long-running process is finished, call the completion function.
' +
      '
This will set $$DOC{ref:".busy"} to true when these rules ' +
      'are met:
' +
      '
At least one process has been created.
' +
      '
The $$DOC{ref:".minPreSpinnerWait"} timer has expired.
' +
      '
 and will set it back to false when the rules are met:
' +
      '
All processes have been completed.
' +
      '
The $$DOC{ref:".minSpinnerShowTime"} has elapsed.
' +
      '

',

  imports: [
    'clearTimeout',
    'setTimeout'
  ],

  properties: [
    {
      name: 'busy',
      documentation: 'Set when the logic indicates a spinner should be shown.',
      defaultValue: false
    },
    {
      name: 'minPreSpinnerWait',
      documentation: 'Minimum wait time before showing a spinner.',
      units: 'ms',
      defaultValue: 500
    },
    {
      name: 'minSpinnerShowTime',
      documentation: 'Minimum time to show a spinner. (Seems strange, but it ' +
          'is perceived as glitchy to see a spinner for only an instant.)',
      units: 'ms',
      defaultValue: 500
    },
    // Internal below here.
    {
      name: 'waiting_',
      hidden: true,
      getter: function() { return Object.keys(this.processes_).length > 0; }
    },
    {
      name: 'processes_',
      factory: function() { return {}; }
    },
    {
      name: 'nextProcessId_',
      defaultValue: 0
    },
    {
      name: 'timer_'
    }
  ],

  methods: {
    start: function() {
      var alreadyWaiting = this.waiting_;
      var pid = this.nextProcessId_++;
      this.processes_[pid] = true;

      var completeFunc = this.done_.bind(this, pid);

      // If there were already things waiting, nothing more to do.
      if ( alreadyWaiting ) return completeFunc;

      // But if this is the first topic, we start the pre-spinner timer.
      // Clear the minimum spinner timer if it's already running.
      if ( this.timer_ ) this.clearTimeout(this.timer_);
      this.timer_ = this.setTimeout(this.onTimer, this.minPreSpinnerWait);
      return completeFunc;
    },
    done_: function(pid) {
      if ( ! this.processes_[pid] ) return; // Unrecognized topic; bail.
      delete this.processes_[pid];

      // If there are still things waiting, do nothing further.
      if ( this.waiting_ ) return;

      if ( this.timer_ && ! this.busy ) {
        // Pre-spinner timer is still running. Cancel it and we're done.
        this.clearTimeout(this.timer_);
        this.timer_ = '';
      } else if ( this.busy ) {
        // Spinner is up, and the minimum spinner timer has expired.
        this.busy = false;
      }
      // The final case is that the minimum spinner timer is still running,
      // in which case we just let it expire.
    }
  },

  listeners: [
    {
      name: 'onTimer',
      code: function() {
        var waiting = this.waiting_;
        this.timer_ = '';
        if ( this.busy && ! waiting ) {
          // Minimum spinner timer just expired, and we're done waiting.
          this.busy = false;
        } else if ( ! this.busy && waiting ) {
          // Topics are waiting and we're not already busy., so this is the
          // pre-spinner timer that just expired. Set busy.
          this.busy = true;
        }
        // Otherwise, either:
        // - The minimum spinner time expired and things are still waiting, or
        // - The pre-spinner timer just expired but the wait is already over.
        // Either way, nothing to do.
      }
    }
  ]
});
<commit_msg>Add BusyFlagTracker, a client of BusyStatus which will track a boolean value and start/stop the busy status as necessary.<commit_after>/**
 * @license
 * Copyright 2014 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

CLASS({
  name: 'BusyStatus',
  documentation: '
Sets an output property to true when any "process" is ' +
      'active. Any code that needs to indicate a busy state can call ' +
      '$$DOC{ref:".start"}, which returns a completion function. When the ' +
      'long-running process is finished, call the completion function.
' +
      '
This will set $$DOC{ref:".busy"} to true when these rules ' +
      'are met:
' +
      '
At least one process has been created.
' +
      '
The $$DOC{ref:".minPreSpinnerWait"} timer has expired.
' +
      '
 and will set it back to false when the rules are met:
' +
      '
All processes have been completed.
' +
      '
The $$DOC{ref:".minSpinnerShowTime"} has elapsed.
' +
      '

',

  imports: [
    'clearTimeout',
    'setTimeout'
  ],

  properties: [
    {
      name: 'busy',
      documentation: 'Set when the logic indicates a spinner should be shown.',
      defaultValue: false
    },
    {
      name: 'minPreSpinnerWait',
      documentation: 'Minimum wait time before showing a spinner.',
      units: 'ms',
      defaultValue: 500
    },
    {
      name: 'minSpinnerShowTime',
      documentation: 'Minimum time to show a spinner. (Seems strange, but it ' +
          'is perceived as glitchy to see a spinner for only an instant.)',
      units: 'ms',
      defaultValue: 500
    },
    // Internal below here.
    {
      name: 'waiting_',
      hidden: true,
      getter: function() { return Object.keys(this.processes_).length > 0; }
    },
    {
      name: 'processes_',
      factory: function() { return {}; }
    },
    {
      name: 'nextProcessId_',
      defaultValue: 0
    },
    {
      name: 'timer_'
    }
  ],

  methods: {
    start: function() {
      var alreadyWaiting = this.waiting_;
      var pid = this.nextProcessId_++;
      this.processes_[pid] = true;

      var completeFunc = this.done_.bind(this, pid);

      // If there were already things waiting, nothing more to do.
      if ( alreadyWaiting ) return completeFunc;

      // But if this is the first topic, we start the pre-spinner timer.
      // Clear the minimum spinner timer if it's already running.
      if ( this.timer_ ) this.clearTimeout(this.timer_);
      this.timer_ = this.setTimeout(this.onTimer, this.minPreSpinnerWait);
      return completeFunc;
    },
    done_: function(pid) {
      if ( ! this.processes_[pid] ) return; // Unrecognized topic; bail.
      delete this.processes_[pid];

      // If there are still things waiting, do nothing further.
      if ( this.waiting_ ) return;

      if ( this.timer_ && ! this.busy ) {
        // Pre-spinner timer is still running. Cancel it and we're done.
        this.clearTimeout(this.timer_);
        this.timer_ = '';
      } else if ( this.busy ) {
        // Spinner is up, and the minimum spinner timer has expired.
        this.busy = false;
      }
      // The final case is that the minimum spinner timer is still running,
      // in which case we just let it expire.
    }
  },

  listeners: [
    {
      name: 'onTimer',
      code: function() {
        var waiting = this.waiting_;
        this.timer_ = '';
        if ( this.busy && ! waiting ) {
          // Minimum spinner timer just expired, and we're done waiting.
          this.busy = false;
        } else if ( ! this.busy && waiting ) {
          // Topics are waiting and we're not already busy., so this is the
          // pre-spinner timer that just expired. Set busy.
          this.busy = true;
        }
        // Otherwise, either:
        // - The minimum spinner time expired and things are still waiting, or
        // - The pre-spinner timer just expired but the wait is already over.
        // Either way, nothing to do.
      }
    }
  ]
});

CLASS({
  name: 'BusyFlagTracker',
  properties: [
    'busyStatus',
    {
      name: 'target',
      postSet: function(oldTarget, newTarget) {
        if ( this.callback ) {
          this.callback();
          this.callback = null;
        }

        if ( oldTarget ) oldTarget.remoteListener(this.onChange);
        newTarget.addListener(this.onChange);
      }
    },
    'callback'
  ],
  listeners: [
    {
      name: 'onChange',
      code: function(_, _, oldValue, newValue) {
        if ( newValue ) {
          if ( this.callback ) this.callback();
          this.callback = this.busyStatus.start();
        } else {
          this.callback();
          this.callback = null;
        }
      }
    }
  ]
});
<|endoftext|>


<commit_before>/* qml.core javascript code */

if (!_globals.core)
	_globals.core = {}

_globals.core.Object = function(parent) {
	this.parent = parent;
	this._local = {}
	this._changedHandlers = {}
}

_globals.core.Object.prototype._update = function(name, value) {
	if (name in this._changedHandlers) {
		var handlers = this._changedHandlers[name];
		handlers.forEach(function(callback) { callback(value); });
	}
}

_globals.core.Object.prototype._setId = function (name) {
	var p = this;
	while(p) {
		p._local[name] = this;
		p = p.parent;
	}
}

_globals.core.Object.prototype.onChanged = function (name, callback) {
	if (name in this._changedHandlers)
		this._changedHandlers[name].push(callback);
	else
		this._changedHandlers[name] = [callback];
}

_globals.core.Object.prototype.get = function (name) {
	if (name in this._local)
		return this._local[name];
	if (this.hasOwnProperty(name))
		return this[name];
	console.log(name, this);
	throw ("invalid property requested: '" + name + "' in context of " + this);
}

function setup(context) {
	_globals.core.Item.prototype.children = []

	_globals.core.Item.prototype.toScreen = function() {
		var item = this;
		var x = 0, y = 0;
		while(item) {
			x += item.x;
			y += item.y;
			item = item.parent;
		}
		return [x, y, x + this.width, y + this.height];
	}

	_globals.core.Border.prototype._update = function(name, value) {
		switch(name) {
			case 'width': this.parent.element.css('border-width', value); break;
			case 'color': this.parent.element.css('border-color', value); break;
		}
		_globals.core.Object.prototype._update.apply(this, arguments);
	}

	_globals.core.Item.prototype._update = function(name, value) {
		switch(name) {
			case 'width': 	this.element.css('width', value); this.right.value = this.x + value; break;
			case 'height':	this.element.css('height', value); this.bottom.value = this.y + value; break;
			case 'x':		this.element.css('left', value); this.left.value = value; this.right.value = value + this.width; break;
			case 'y':		this.element.css('top', value); this.top.value = value; this.bottom.value = value + this.height; break;
			case 'radius':	this.element.css('border-radius', value); break;
		}
		_globals.core.Object.prototype._update.apply(this, arguments);
	}

	_globals.core.AnchorLine.prototype._update = function(name, value) {
		_globals.core.Object.prototype._update.apply(this, arguments);
	}

	_globals.core.Anchors.prototype._update = function(name, line) {
		var self = this.parent;
		var target = line.parent;
		var anchors = this;
		var lm = anchors.leftMargin || anchors.margins;
		var rm = anchors.rightMargin || anchors.margins;
		var tm = anchors.topMargin || anchors.margins;
		var bm = anchors.bottomMargin || anchors.margins;

		var update_left = function() {
			var target_box = target.toScreen();
			var parent_box = self.parent.toScreen();
			//console.log(target_box, parent_box);
			self.x = target_box[0] + lm - parent_box[0];
			if (anchors.right) {
				var right_target_box = anchors.right.parent.toScreen();
				self.width = (right_target_box[2] - parent_box[0]) - self.x - rm ;
			}
		};

		var update_right = function() {
			var target_box = target.toScreen();
			var parent_box = self.parent.toScreen();
			//console.log(target_box, parent_box);
			if (anchors.left) {
				var left_target_box = anchors.left.parent.toScreen();
				self.width = target_box[2] - left_target_box[0] - lm - rm;
			}
			self.x = (target_box[2] - parent_box[0] - self.width) + lm;
		};

		var update_top = function() {
			var target_box = target.toScreen();
			var parent_box = self.parent.toScreen();
			//console.log(target_box, parent_box);
			self.y = target_box[1] + tm - parent_box[1];
			if (anchors.bottom) {
				var bottom_target_box = anchors.bottom.parent.toScreen();
				self.height = (bottom_target_box[3] - parent_box[1]) - self.y - bm;
			}
		};

		var update_bottom = function() {
			var target_box = target.toScreen();
			var parent_box = self.parent.toScreen();
			//console.log(target_box, parent_box);
			if (anchors.top) {
				var top_target_box = anchors.top.parent.toScreen();
				self.height = target_box[3] - top_target_box[1] - tm - bm;
			}
			self.y = (target_box[3] - parent_box[1] - self.height) + tm;
		};

		switch(name) {
			case 'left':
				update_left();
				target.left.onChanged('value', update_left);
				break;

			case 'right':
				update_right();
				target.right.onChanged('value', update_right);
				break;

			case 'top':
				update_top();
				target.top.onChanged('value', update_top);
				break;

			case 'bottom':
				update_bottom();
				target.bottom.onChanged('value', update_bottom);
				break;
		}
		_globals.core.Object.prototype._update.apply(this, arguments);
	}

	_globals.core.Font.prototype._update = function(name, value) {
		switch(name) {
			case 'pointSize': this.parent.element.css('font-size', value + "pt"); break;
			case 'pixelSize': this.parent.element.css('font-size', value + "px"); break;
			case 'italic': this.parent.element.css('font-style', value? 'italic': 'normal'); break;
		}
		_globals.core.Object.prototype._update.apply(this, arguments);
	}

	_globals.core.Text.prototype._update = function(name, value) {
		switch(name) {
			case 'text': this.element.text(value); break;
		}
		_globals.core.Item.prototype._update.apply(this, arguments);
	}

	_globals.core.Rectangle.prototype._update = function(name, value) {
		switch(name) {
			case 'color': this.element.css('background-color', value); break;
		}
		_globals.core.Item.prototype._update.apply(this, arguments);
	}
}

exports.Context = function() {
	_globals.core.Object.apply(this, null);

	var w = $(window).width();
	var h = $(window).height();
	console.log("window size: " + w + "x" + h);

	var body = $('body');
	var div = $("

");
	body.append(div)

	exports.addProperty(this, 'int', 'x');
	exports.addProperty(this, 'int', 'y');
	exports.addProperty(this, 'int', 'width');
	exports.addProperty(this, 'int', 'height');

	this.element = div
	this.element.css({width: w, height: h});
	this.width = w;
	this.height = h;

	console.log("context created");
	setup(this);
}

exports.Context.prototype = Object.create(_globals.core.Object.prototype);
exports.Context.prototype.constructor = exports.Context;

exports.Context.prototype.start = function(name) {
	var proto;
	if (typeof name == 'string') {
		console.log('creating component...', name);
		var path = name.split('.');
		proto = _globals;
		for (var i = 0; i < path.length; ++i)
			proto = proto[path[i]]
	}
	else
		proto = name;
	var instance = Object.create(proto.prototype);
	proto.apply(instance, [this]);
	return instance;
}

exports.addProperty = function(self, type, name) {
	var value;
	switch(type) {
		case 'int':			value = 0; break;
		case 'bool':		value = false; break;
		case 'real':		value = 0.0; break;
		default: if (type[0].toUpperCase() == type[0]) value = null; break;
	}
	Object.defineProperty(self, name, {
		get: function() {
			return value;
		},
		set: function(newValue) {
			oldValue = value;
			if (oldValue != newValue) {
				value = newValue;
				self._update(name, newValue, oldValue);
			}
		}
	});
}

exports._bootstrap = function(self, name) {
	switch(name) {
		case 'core.Item':
			if (self.element)
				throw "double ctor call";
			self.element = $('
');
			self.parent.element.append(self.element);
			break;
	}
}
<commit_msg>added z handling<commit_after>/* qml.core javascript code */

if (!_globals.core)
	_globals.core = {}

_globals.core.Object = function(parent) {
	this.parent = parent;
	this._local = {}
	this._changedHandlers = {}
}

_globals.core.Object.prototype._update = function(name, value) {
	if (name in this._changedHandlers) {
		var handlers = this._changedHandlers[name];
		handlers.forEach(function(callback) { callback(value); });
	}
}

_globals.core.Object.prototype._setId = function (name) {
	var p = this;
	while(p) {
		p._local[name] = this;
		p = p.parent;
	}
}

_globals.core.Object.prototype.onChanged = function (name, callback) {
	if (name in this._changedHandlers)
		this._changedHandlers[name].push(callback);
	else
		this._changedHandlers[name] = [callback];
}

_globals.core.Object.prototype.get = function (name) {
	if (name in this._local)
		return this._local[name];
	if (this.hasOwnProperty(name))
		return this[name];
	console.log(name, this);
	throw ("invalid property requested: '" + name + "' in context of " + this);
}

function setup(context) {
	_globals.core.Item.prototype.children = []

	_globals.core.Item.prototype.toScreen = function() {
		var item = this;
		var x = 0, y = 0;
		while(item) {
			x += item.x;
			y += item.y;
			item = item.parent;
		}
		return [x, y, x + this.width, y + this.height];
	}

	_globals.core.Border.prototype._update = function(name, value) {
		switch(name) {
			case 'width': this.parent.element.css('border-width', value); break;
			case 'color': this.parent.element.css('border-color', value); break;
		}
		_globals.core.Object.prototype._update.apply(this, arguments);
	}

	_globals.core.Item.prototype._update = function(name, value) {
		switch(name) {
			case 'width': 	this.element.css('width', value); this.right.value = this.x + value; break;
			case 'height':	this.element.css('height', value); this.bottom.value = this.y + value; break;
			case 'x':		this.element.css('left', value); this.left.value = value; this.right.value = value + this.width; break;
			case 'y':		this.element.css('top', value); this.top.value = value; this.bottom.value = value + this.height; break;
			case 'z':		this.element.css('z-index', value); break;
			case 'radius':	this.element.css('border-radius', value); break;
		}
		_globals.core.Object.prototype._update.apply(this, arguments);
	}

	_globals.core.AnchorLine.prototype._update = function(name, value) {
		_globals.core.Object.prototype._update.apply(this, arguments);
	}

	_globals.core.Anchors.prototype._update = function(name, line) {
		var self = this.parent;
		var target = line.parent;
		var anchors = this;
		var lm = anchors.leftMargin || anchors.margins;
		var rm = anchors.rightMargin || anchors.margins;
		var tm = anchors.topMargin || anchors.margins;
		var bm = anchors.bottomMargin || anchors.margins;

		var update_left = function() {
			var target_box = target.toScreen();
			var parent_box = self.parent.toScreen();
			//console.log(target_box, parent_box);
			self.x = target_box[0] + lm - parent_box[0];
			if (anchors.right) {
				var right_target_box = anchors.right.parent.toScreen();
				self.width = (right_target_box[2] - parent_box[0]) - self.x - rm ;
			}
		};

		var update_right = function() {
			var target_box = target.toScreen();
			var parent_box = self.parent.toScreen();
			//console.log(target_box, parent_box);
			if (anchors.left) {
				var left_target_box = anchors.left.parent.toScreen();
				self.width = target_box[2] - left_target_box[0] - lm - rm;
			}
			self.x = (target_box[2] - parent_box[0] - self.width) + lm;
		};

		var update_top = function() {
			var target_box = target.toScreen();
			var parent_box = self.parent.toScreen();
			//console.log(target_box, parent_box);
			self.y = target_box[1] + tm - parent_box[1];
			if (anchors.bottom) {
				var bottom_target_box = anchors.bottom.parent.toScreen();
				self.height = (bottom_target_box[3] - parent_box[1]) - self.y - bm;
			}
		};

		var update_bottom = function() {
			var target_box = target.toScreen();
			var parent_box = self.parent.toScreen();
			//console.log(target_box, parent_box);
			if (anchors.top) {
				var top_target_box = anchors.top.parent.toScreen();
				self.height = target_box[3] - top_target_box[1] - tm - bm;
			}
			self.y = (target_box[3] - parent_box[1] - self.height) + tm;
		};

		switch(name) {
			case 'left':
				update_left();
				target.left.onChanged('value', update_left);
				break;

			case 'right':
				update_right();
				target.right.onChanged('value', update_right);
				break;

			case 'top':
				update_top();
				target.top.onChanged('value', update_top);
				break;

			case 'bottom':
				update_bottom();
				target.bottom.onChanged('value', update_bottom);
				break;
		}
		_globals.core.Object.prototype._update.apply(this, arguments);
	}

	_globals.core.Font.prototype._update = function(name, value) {
		switch(name) {
			case 'pointSize': this.parent.element.css('font-size', value + "pt"); break;
			case 'pixelSize': this.parent.element.css('font-size', value + "px"); break;
			case 'italic': this.parent.element.css('font-style', value? 'italic': 'normal'); break;
		}
		_globals.core.Object.prototype._update.apply(this, arguments);
	}

	_globals.core.Text.prototype._update = function(name, value) {
		switch(name) {
			case 'text': this.element.text(value); break;
		}
		_globals.core.Item.prototype._update.apply(this, arguments);
	}

	_globals.core.Rectangle.prototype._update = function(name, value) {
		switch(name) {
			case 'color': this.element.css('background-color', value); break;
		}
		_globals.core.Item.prototype._update.apply(this, arguments);
	}
}

exports.Context = function() {
	_globals.core.Object.apply(this, null);

	var w = $(window).width();
	var h = $(window).height();
	console.log("window size: " + w + "x" + h);

	var body = $('body');
	var div = $("

");
	body.append(div)

	exports.addProperty(this, 'int', 'x');
	exports.addProperty(this, 'int', 'y');
	exports.addProperty(this, 'int', 'width');
	exports.addProperty(this, 'int', 'height');

	this.element = div
	this.element.css({width: w, height: h});
	this.width = w;
	this.height = h;

	console.log("context created");
	setup(this);
}

exports.Context.prototype = Object.create(_globals.core.Object.prototype);
exports.Context.prototype.constructor = exports.Context;

exports.Context.prototype.start = function(name) {
	var proto;
	if (typeof name == 'string') {
		console.log('creating component...', name);
		var path = name.split('.');
		proto = _globals;
		for (var i = 0; i < path.length; ++i)
			proto = proto[path[i]]
	}
	else
		proto = name;
	var instance = Object.create(proto.prototype);
	proto.apply(instance, [this]);
	return instance;
}

exports.addProperty = function(self, type, name) {
	var value;
	switch(type) {
		case 'int':			value = 0; break;
		case 'bool':		value = false; break;
		case 'real':		value = 0.0; break;
		default: if (type[0].toUpperCase() == type[0]) value = null; break;
	}
	Object.defineProperty(self, name, {
		get: function() {
			return value;
		},
		set: function(newValue) {
			oldValue = value;
			if (oldValue != newValue) {
				value = newValue;
				self._update(name, newValue, oldValue);
			}
		}
	});
}

exports._bootstrap = function(self, name) {
	switch(name) {
		case 'core.Item':
			if (self.element)
				throw "double ctor call";
			self.element = $('
');
			self.parent.element.append(self.element);
			break;
	}
}
<|endoftext|>


<commit_before>/*global require: false, module: false */
'use strict';

var Rx = require('rx');
require('rx-dom');
var _ = require('underscore');
var qs = require('qs');

// XXX Need a config mechanism for this. For now, uncomment the localhost
// setting when working locally.
 var databaseUrl = "http://brcaexchange.cloudapp.net/backend";
//var databaseUrl = "http://localhost:8000";

var transpose = a => _.zip.apply(_, a);

// URIs have a 2083 character size limit and some search terms exceed that.
// Limit the length and cut at a semicolon if possible to ensure the search works
function trimSearchTerm(search) {
    if (search.length > 50) {
        search = search.slice(0, 50);
        var lastColonPosition = search.lastIndexOf(":");
        if (lastColonPosition !== -1) {
            search = search.slice(0, lastColonPosition);
        }
    }
    return search;
}

// XXX these defaults might produce odd user experience, since they
// are not reflected in the UI.
function url(opts) {
    var {
        format = 'json',
        filterValues = {},
        sortBy: {prop = 'Gene_Symbol', order = 'ascending'} = {},
        pageLength = 100,
        page = 0,
        search = '',
        source
        } = opts,

        [filter, filterValue] = transpose(_.pairs(_.pick(filterValues, v => v)));
    search = trimSearchTerm(search);

    return `${databaseUrl}/data/?${qs.stringify(_.pick({
        format,
        filter,
        filterValue,
        'order_by': prop,
        direction: order,
        'page_size': pageLength,
        'page_num': page,
        'search_term': search,
        'source': source
    }, v => v != null), {arrayFormat: 'repeat'})}`;
}

function data(opts) {
    return Rx.DOM.get(url(opts)).map(xhr => JSON.parse(xhr.responseText));
}

module.exports = {
    data,
    url,
    trimSearchTerm,
    databaseUrl
};
<commit_msg>change localhost to be the default backend<commit_after>/*global require: false, module: false */
'use strict';

var Rx = require('rx');
require('rx-dom');
var _ = require('underscore');
var qs = require('qs');

// XXX Need a config mechanism for this.
//var databaseUrl = "http://brcaexchange.cloudapp.net/backend";
var databaseUrl = "http://localhost:8000";

var transpose = a => _.zip.apply(_, a);

// URIs have a 2083 character size limit and some search terms exceed that.
// Limit the length and cut at a semicolon if possible to ensure the search works
function trimSearchTerm(search) {
    if (search.length > 50) {
        search = search.slice(0, 50);
        var lastColonPosition = search.lastIndexOf(":");
        if (lastColonPosition !== -1) {
            search = search.slice(0, lastColonPosition);
        }
    }
    return search;
}

// XXX these defaults might produce odd user experience, since they
// are not reflected in the UI.
function url(opts) {
    var {
        format = 'json',
        filterValues = {},
        sortBy: {prop = 'Gene_Symbol', order = 'ascending'} = {},
        pageLength = 100,
        page = 0,
        search = '',
        source
        } = opts,

        [filter, filterValue] = transpose(_.pairs(_.pick(filterValues, v => v)));
    search = trimSearchTerm(search);

    return `${databaseUrl}/data/?${qs.stringify(_.pick({
        format,
        filter,
        filterValue,
        'order_by': prop,
        direction: order,
        'page_size': pageLength,
        'page_num': page,
        'search_term': search,
        'source': source
    }, v => v != null), {arrayFormat: 'repeat'})}`;
}

function data(opts) {
    return Rx.DOM.get(url(opts)).map(xhr => JSON.parse(xhr.responseText));
}

module.exports = {
    data,
    url,
    trimSearchTerm,
    databaseUrl
};
<|endoftext|>


<commit_before>// Copyright 2016 Documize Inc. <legal@documize.com>. All rights reserved.
//
// This software (Documize Community Edition) is licensed under
// GNU AGPL v3 http://www.gnu.org/licenses/agpl-3.0.en.html
//
// You can operate outside the AGPL restrictions by purchasing
// Documize Enterprise Edition and obtaining a commercial license
// by contacting <sales@documize.com>.
//
// https://documize.com

import { computed } from '@ember/object';
import { notEmpty } from '@ember/object/computed';
import { inject as service } from '@ember/service';
import Modals from '../../mixins/modal';
import Notifier from '../../mixins/notifier';
import Component from '@ember/component';

export default Component.extend(Modals, Notifier, {
	classNames: ["document-meta", ' non-printable'],
	documentService: service('document'),
	browserSvc: service('browser'),
	appMeta: service(),
	session: service(),
	hasAttachments: notEmpty('files'),
	canEdit: computed('permissions.documentEdit', 'document.protection', function() {
		return this.get('document.protection') !== this.get('constants').ProtectionType.Lock && this.get('permissions.documentEdit');
	}),
	showDialog: false,
	downloadQuery: '',

	didReceiveAttrs() {
		this._super(...arguments);
		this.getAttachments();
	},

	didInsertElement() {
		this._super(...arguments);

		// For authenticated users we send server auth token.
		let qry = '';
		if (this.get('session.hasSecureToken')) {
			qry = '?secure=' + this.get('session.secureToken');
		} else if (this.get('session.authenticated')) {
			qry = '?token=' + this.get('session.authToken');
		}
		this.set('downloadQuery', qry);

		if (!this.get('permissions.documentEdit') || this.get('document.protection') === this.get('constants').ProtectionType.Lock) {
			return;
		}

		let self = this;
		let documentId = this.get('document.id');
		let url = this.get('appMeta.endpoint');
		let uploadUrl = `${url}/documents/${documentId}/attachments`;

		// Handle upload clicks on button and anything inside that button.
		let sel = ['#upload-document-files ', '#upload-document-files  > i'];
		for (var i=0; i < 2; i++) {
			let dzone = new Dropzone(sel[i], {
				headers: {
					'Authorization': 'Bearer ' + self.get('session.authToken')
				},
				url: uploadUrl,
				method: "post",
				paramName: 'attachment',
				clickable: true,
				maxFilesize: 250,
				parallelUploads: 5,
				uploadMultiple: false,
				addRemoveLinks: false,
				autoProcessQueue: true,

				init: function () {
					this.on("success", function (/*file, response*/ ) {
					});

					this.on("queuecomplete", function () {
						self.notifySuccess('Uploaded file');
						self.getAttachments();
					});

					this.on("addedfile", function ( /*file*/ ) {
					});

					this.on("error", function (error, msg) {
						self.notifyError(msg);
						self.notifyError(error);
					});
				}
			});

			dzone.on("complete", function (file) {
				dzone.removeFile(file);
			});
		}
	},

	getAttachments() {
		this.get('documentService').getAttachments(this.get('document.id')).then((files) => {
			this.set('files', files);
		});
	},

	actions: {
		onDelete(attachment) {
			this.get('documentService').deleteAttachment(this.get('document.id'), attachment.id).then(() => {
				this.notifySuccess('File deleted');
				this.getAttachments();
			});
		}
	}
});
<commit_msg>Ensure only change approvers can change doc level attachments<commit_after>// Copyright 2016 Documize Inc. <legal@documize.com>. All rights reserved.
//
// This software (Documize Community Edition) is licensed under
// GNU AGPL v3 http://www.gnu.org/licenses/agpl-3.0.en.html
//
// You can operate outside the AGPL restrictions by purchasing
// Documize Enterprise Edition and obtaining a commercial license
// by contacting <sales@documize.com>.
//
// https://documize.com

import { computed } from '@ember/object';
import { notEmpty } from '@ember/object/computed';
import { inject as service } from '@ember/service';
import Modals from '../../mixins/modal';
import Notifier from '../../mixins/notifier';
import Component from '@ember/component';

export default Component.extend(Modals, Notifier, {
	classNames: ["document-meta", ' non-printable'],
	documentService: service('document'),
	browserSvc: service('browser'),
	appMeta: service(),
	session: service(),
	hasAttachments: notEmpty('files'),
	canEdit: computed('permissions.{documentApprove,documentEdit}', 'document.protection', function() {
		// Check to see if specific scenarios prevent us from changing doc level attachments.
		if (this.get('document.protection') == this.get('constants').ProtectionType.Lock) return false;
		if (!this.get('permissions.documentEdit')) return false;
		if (this.get('document.protection') == this.get('constants').ProtectionType.Review && !this.get('permissions.documentApprove')) return false;

		// By default, we can edit/upload attachments that sit at the document level.
		return true;
	}),
	showDialog: false,
	downloadQuery: '',

	didReceiveAttrs() {
		this._super(...arguments);
		this.getAttachments();
	},

	didInsertElement() {
		this._super(...arguments);

		// For authenticated users we send server auth token.
		let qry = '';
		if (this.get('session.hasSecureToken')) {
			qry = '?secure=' + this.get('session.secureToken');
		} else if (this.get('session.authenticated')) {
			qry = '?token=' + this.get('session.authToken');
		}
		this.set('downloadQuery', qry);

		if (!this.get('permissions.documentEdit') || this.get('document.protection') === this.get('constants').ProtectionType.Lock) {
			return;
		}

		let self = this;
		let documentId = this.get('document.id');
		let url = this.get('appMeta.endpoint');
		let uploadUrl = `${url}/documents/${documentId}/attachments`;

		// Handle upload clicks on button and anything inside that button.
		let sel = ['#upload-document-files ', '#upload-document-files  > i'];
		for (var i=0; i < 2; i++) {
			let dzone = new Dropzone(sel[i], {
				headers: {
					'Authorization': 'Bearer ' + self.get('session.authToken')
				},
				url: uploadUrl,
				method: "post",
				paramName: 'attachment',
				clickable: true,
				maxFilesize: 250,
				parallelUploads: 5,
				uploadMultiple: false,
				addRemoveLinks: false,
				autoProcessQueue: true,

				init: function () {
					this.on("success", function (/*file, response*/ ) {
					});

					this.on("queuecomplete", function () {
						self.notifySuccess('Uploaded file');
						self.getAttachments();
					});

					this.on("addedfile", function ( /*file*/ ) {
					});

					this.on("error", function (error, msg) {
						self.notifyError(msg);
						self.notifyError(error);
					});
				}
			});

			dzone.on("complete", function (file) {
				dzone.removeFile(file);
			});
		}
	},

	getAttachments() {
		this.get('documentService').getAttachments(this.get('document.id')).then((files) => {
			this.set('files', files);
		});
	},

	actions: {
		onDelete(attachment) {
			this.get('documentService').deleteAttachment(this.get('document.id'), attachment.id).then(() => {
				this.notifySuccess('File deleted');
				this.getAttachments();
			});
		}
	}
});
<|endoftext|>


<commit_before>import { inject as service } from '@ember/service';
import Adapter from '@ember-data/adapter';
import {
  AdapterError,
  AbortError,
  TimeoutError,
  ServerError,
  UnauthorizedError,
  ForbiddenError,
  NotFoundError,
  ConflictError,
  InvalidError,
} from '@ember-data/adapter/error';

// TODO These are now exactly the same, apart from the fact that one uses
// `serialized, unserialized` and the other just `query`
// they could actually be one function now, but would be nice to think about
// the naming of things (serialized vs query etc)
const read = function(adapter, modelName, type, query = {}) {
  return adapter.rpc(
    function(adapter, request, query) {
      return adapter[`requestFor${type}`](request, query);
    },
    function(serializer, respond, query) {
      return serializer[`respondFor${type}`](respond, query);
    },
    query,
    modelName
  );
};
const write = function(adapter, modelName, type, snapshot) {
  return adapter.rpc(
    function(adapter, request, serialized, unserialized) {
      return adapter[`requestFor${type}`](request, serialized, unserialized);
    },
    function(serializer, respond, serialized, unserialized) {
      return serializer[`respondFor${type}`](respond, serialized, unserialized);
    },
    snapshot,
    modelName
  );
};
export default class HttpAdapter extends Adapter {
  @service('client/http') client;

  rpc(req, resp, obj, modelName) {
    const client = this.client;
    const store = this.store;
    const adapter = this;

    let unserialized, serialized;
    const serializer = store.serializerFor(modelName);
    // workable way to decide whether this is a snapshot
    // essentially 'is attributable'.
    // Snapshot is private so we can't do instanceof here
    // and using obj.constructor.name gets changed/minified
    // during compilation so you can't rely on it
    // checking for `attributes` being a function is more
    // reliable as that is the thing we need to call
    if (typeof obj.attributes === 'function') {
      unserialized = obj.attributes();
      serialized = serializer.serialize(obj, {});
    } else {
      unserialized = obj;
      serialized = unserialized;
    }

    return client
      .request(function(request) {
        return req(adapter, request, serialized, unserialized);
      })
      .catch(function(e) {
        return adapter.error(e);
      })
      .then(function(respond) {
        // TODO: When HTTPAdapter:responder changes, this will also need to change
        return resp(serializer, respond, serialized, unserialized);
      });
    // TODO: Potentially add specific serializer errors here
    // .catch(function(e) {
    //   return Promise.reject(e);
    // });
  }

  error(err) {
    if (err instanceof TypeError) {
      throw err;
    }
    const errors = [
      {
        status: `${err.statusCode}`,
        title: 'The backend responded with an error',
        detail: err.message,
      },
    ];
    let error;
    const detailedMessage = '';
    try {
      switch (err.statusCode) {
        case 0:
          error = new AbortError();
          error.errors[0].status = '0';
          break;
        case 401:
          error = new UnauthorizedError(errors, detailedMessage);
          break;
        case 403:
          error = new ForbiddenError(errors, detailedMessage);
          break;
        case 404:
          error = new NotFoundError(errors, detailedMessage);
          break;
        case 408:
          error = new TimeoutError();
          break;
        case 409:
          error = new ConflictError(errors, detailedMessage);
          break;
        case 422:
          error = new InvalidError(errors); //payload.errors
          break;
        default:
          if (err.statusCode >= 500) {
            error = new ServerError(errors, detailedMessage);
          } else {
            error = new AdapterError(errors, detailedMessage);
          }
      }
    } catch (e) {
      error = e;
    }
    // TODO: This comes originates from ember-data
    // This can be confusing if you need to use this with Promise.reject
    // Consider changing this to return the error and then
    // throw from the call site instead
    throw error;
  }

  query(store, type, query) {
    return read(this, type.modelName, 'Query', query);
  }

  queryRecord(store, type, query) {
    return read(this, type.modelName, 'QueryRecord', query);
  }

  findAll(store, type) {
    return read(this, type.modelName, 'FindAll');
  }

  createRecord(store, type, snapshot) {
    return write(this, type.modelName, 'CreateRecord', snapshot);
  }

  updateRecord(store, type, snapshot) {
    return write(this, type.modelName, 'UpdateRecord', snapshot);
  }

  deleteRecord(store, type, snapshot) {
    return write(this, type.modelName, 'DeleteRecord', snapshot);
  }
}
<commit_msg>ui: Correct AdapterError import (#9147)<commit_after>import { inject as service } from '@ember/service';
import Adapter from '@ember-data/adapter';
import AdapterError, {
  AbortError,
  TimeoutError,
  ServerError,
  UnauthorizedError,
  ForbiddenError,
  NotFoundError,
  ConflictError,
  InvalidError,
} from '@ember-data/adapter/error';

// TODO These are now exactly the same, apart from the fact that one uses
// `serialized, unserialized` and the other just `query`
// they could actually be one function now, but would be nice to think about
// the naming of things (serialized vs query etc)
const read = function(adapter, modelName, type, query = {}) {
  return adapter.rpc(
    function(adapter, request, query) {
      return adapter[`requestFor${type}`](request, query);
    },
    function(serializer, respond, query) {
      return serializer[`respondFor${type}`](respond, query);
    },
    query,
    modelName
  );
};
const write = function(adapter, modelName, type, snapshot) {
  return adapter.rpc(
    function(adapter, request, serialized, unserialized) {
      return adapter[`requestFor${type}`](request, serialized, unserialized);
    },
    function(serializer, respond, serialized, unserialized) {
      return serializer[`respondFor${type}`](respond, serialized, unserialized);
    },
    snapshot,
    modelName
  );
};
export default class HttpAdapter extends Adapter {
  @service('client/http') client;

  rpc(req, resp, obj, modelName) {
    const client = this.client;
    const store = this.store;
    const adapter = this;

    let unserialized, serialized;
    const serializer = store.serializerFor(modelName);
    // workable way to decide whether this is a snapshot
    // essentially 'is attributable'.
    // Snapshot is private so we can't do instanceof here
    // and using obj.constructor.name gets changed/minified
    // during compilation so you can't rely on it
    // checking for `attributes` being a function is more
    // reliable as that is the thing we need to call
    if (typeof obj.attributes === 'function') {
      unserialized = obj.attributes();
      serialized = serializer.serialize(obj, {});
    } else {
      unserialized = obj;
      serialized = unserialized;
    }

    return client
      .request(function(request) {
        return req(adapter, request, serialized, unserialized);
      })
      .catch(function(e) {
        return adapter.error(e);
      })
      .then(function(respond) {
        // TODO: When HTTPAdapter:responder changes, this will also need to change
        return resp(serializer, respond, serialized, unserialized);
      });
    // TODO: Potentially add specific serializer errors here
    // .catch(function(e) {
    //   return Promise.reject(e);
    // });
  }

  error(err) {
    if (err instanceof TypeError) {
      throw err;
    }
    const errors = [
      {
        status: `${err.statusCode}`,
        title: 'The backend responded with an error',
        detail: err.message,
      },
    ];
    let error;
    const detailedMessage = '';
    try {
      switch (err.statusCode) {
        case 0:
          error = new AbortError();
          error.errors[0].status = '0';
          break;
        case 401:
          error = new UnauthorizedError(errors, detailedMessage);
          break;
        case 403:
          error = new ForbiddenError(errors, detailedMessage);
          break;
        case 404:
          error = new NotFoundError(errors, detailedMessage);
          break;
        case 408:
          error = new TimeoutError();
          break;
        case 409:
          error = new ConflictError(errors, detailedMessage);
          break;
        case 422:
          error = new InvalidError(errors); //payload.errors
          break;
        default:
          if (err.statusCode >= 500) {
            error = new ServerError(errors, detailedMessage);
          } else {
            error = new AdapterError(errors, detailedMessage);
          }
      }
    } catch (e) {
      error = e;
    }
    // TODO: This comes originates from ember-data
    // This can be confusing if you need to use this with Promise.reject
    // Consider changing this to return the error and then
    // throw from the call site instead
    throw error;
  }

  query(store, type, query) {
    return read(this, type.modelName, 'Query', query);
  }

  queryRecord(store, type, query) {
    return read(this, type.modelName, 'QueryRecord', query);
  }

  findAll(store, type) {
    return read(this, type.modelName, 'FindAll');
  }

  createRecord(store, type, snapshot) {
    return write(this, type.modelName, 'CreateRecord', snapshot);
  }

  updateRecord(store, type, snapshot) {
    return write(this, type.modelName, 'UpdateRecord', snapshot);
  }

  deleteRecord(store, type, snapshot) {
    return write(this, type.modelName, 'DeleteRecord', snapshot);
  }
}
<|endoftext|>