Source: LAF/widgets/back_gesture.js

/*jshint loopfunc: true */
/**
 * Back gesture for LAF
 *
 * The browser goes back if a circle gesture is swiped left to right
 *
 * @name Lens.LAF.BackGesture
 * @namespace
 */
define([ "lib/jquery", "lib/underscore", "common/util/dom_utils",
         "ARCore/contour_search"],
function( $,            _,                DOMUtils,
          ContourSearch) {

    "use strict";

    /// which contours exist in a verticle strip of screen
    // list (num elements = num segments) which contains an
    // object full of contour ids. Acts like a hashset of which
    // contours are in each segment and still viable for back
    var contoursInSegment = [];

    // how many verticle strips to segment the screen into
    var segments = 4;
    var segmentsArray = [];
    for (var s = 0; s < segments; s++) {
        segmentsArray[s] = s;
    }
    var contourSearches = [];

    var enabled = true;

    var BackGesture = /** @lends Lens.LAF.BackGesture */ {
        /**
         * Enables gesture
         */
        enable: function() {
            enabled = true;
            gestureSearch(enabled);
        },

        /**
         * Disables gesture
         */
        disable: function() {
            enabled = false;
            gestureSearch(enabled);
        },

        /**
         * Returns true if this LAF module is enabled
         * @return Boolean
         * @memberOf Lens.LAF.BackGesture
         */
        enabled: function() {
            return enabled;
        }
    };

    // turn gesture on or off
    function gestureSearch(enabled){
        if(!enabled) {
            for (var i = 0; i < segments; i++) {
                if (contourSearches[i] !== undefined) {
                    contourSearches[i].stop();
                    delete contourSearches[i];
                }
                delete contoursInSegment[i];
            }
            return;
        }

        for (var j = 0; j < segments-1; j++) {
            if (contoursInSegment[j] === undefined){
                contoursInSegment[j] = {};
            }
        }

        var colWidth = window.innerWidth/segments;

        segmentsArray.forEach(function(k) {
            if (k === 0) {
                // allow the first contour to not be a circle
                contourSearches[k] = Lens.ContourSearch({
                    x: [colWidth*(segments-k-1), colWidth*(segments-k)]
                });

                // only first contour cares about appeared
                contourSearches[k].appeared(function(c) {
                    contoursInSegment[k][c.id] = true;
                });
            }
            else {
                contourSearches[k] = Lens.ContourSearch({
                    x: [colWidth*(segments-k-0.5), colWidth*(segments-k+0.5)],
                    classification: ContourSearch.CLASSIFICATION_CIRCLE
                });

                contourSearches[k].moved(function(c){
                // if a contour is in the previous segment, move it
                    if (k!==0 && contoursInSegment[k-1][c.id]) {
                        delete contoursInSegment[k-1][c.id];
                        if (k === segments-1){
                            window.history.back();
                        }
                        else {
                            contoursInSegment[k][c.id] = true;
                        }
                    }
                });

                contourSearches[k].disappeared(function(c) {
                    // removes a contour from all lists if it disappeared
                    if (k < segments - 1) {
                        if (contoursInSegment[k][c.id] !== undefined) {
                            delete contoursInSegment[k][c.id];
                        }
                    }
                });
            }
        });
    }

    BackGesture.enable();

    Lens._addMember(BackGesture, "BackGesture", Lens.LAF);
    return BackGesture;
});