<commit_before>// For tracking where you were before you narrowed.
var persistent_message_id = 0;

// For narrowing based on a particular message
var narrow_target_message_id = 0;

// Narrowing predicate, or 'false' for the home view.
var narrowed = false;

function do_narrow(description, filter_function) {
    narrowed = filter_function;

    // Your pointer isn't changed when narrowed.
    persistent_message_id = selected_message_id;

    // Empty the filtered table right before we fill it again
    clear_table('zfilt');
    add_to_table(message_array, 'zfilt', filter_function, 'bottom');

    // Show the new set of messages.
    $("#zfilt").addClass("focused_table");

    $("#show_all_messages").removeAttr("disabled");
    $(".narrowcontent").show();
    $("#main_div").addClass("narrowed_view");
    $("#currently_narrowed_to").html(description).attr("title", description);
    $("#zhome").removeClass("focused_table");

    // Indicate both which message is persistently selected and which
    // is temporarily selected
    select_and_show_by_id(selected_message_id);
    selected_message_class = "narrowed_selected_message";
    select_and_show_by_id(narrow_target_message_id);
    scroll_to_selected();
}

function target_message_for_narrow(id) {
    narrow_target_message_id = id;
}

function narrow_huddle() {
    var original = message_dict[narrow_target_message_id];
    do_narrow("Huddles with " + original.display_reply_to, function (other) {
        return other.reply_to === original.reply_to;
    });
}

function narrow_all_personals() {
    do_narrow("All huddles with you", function (other) {
        return other.type === "personal" || other.type === "huddle";
    });
}

function narrow_personals() {
    // Narrow to personals with a specific user
    var original = message_dict[narrow_target_message_id];

    do_narrow("Huddles with " + original.display_replay_to, function (other) {
        return (other.type === 'personal') &&
            (((other.display_recipient.email === original.display_recipient.email) && (other.sender_email === original.sender_email)) ||
             ((other.display_recipient.email === original.sender_email) && (other.sender_email === original.display_recipient.email)));
    });

}

function narrow_stream() {
    var original = message_dict[narrow_target_message_id];
    var message = original.display_recipient;
    do_narrow(message, function (other) {
        return (other.type === 'stream' &&
                original.recipient_id === other.recipient_id);
    });
}

function narrow_subject() {
    var original = message_dict[narrow_target_message_id];
    if (original.type !== 'stream')
        return;

    var message = original.display_recipient + " | " + original.subject;
    do_narrow(message, function (other) {
        return (other.type === 'stream' &&
                original.recipient_id === other.recipient_id &&
                original.subject === other.subject);
    });
}

// Called for the 'narrow by stream' hotkey.
function narrow_by_recipient() {
    switch (message_dict[selected_message_id].type) {
        case 'personal': narrow_personals(); break;
        case 'huddle':   narrow_huddle();    break;
        case 'stream':    narrow_stream();     break;
    }
}

function show_all_messages() {
    if (!narrowed) {
        return;
    }
    narrowed = false;

    $("#zfilt").removeClass('focused_table');
    $("#zhome").addClass('focused_table');
    $(".narrowcontent").hide();
    $("#main_div").removeClass('narrowed_view');
    $("#show_all_messages").attr("disabled", "disabled");
    $("#currently_narrowed_to").html("");

    selected_message_class = "selected_message";
    // Includes scrolling.
    select_and_show_by_id(persistent_message_id);

    scroll_to_selected();
}
<commit_msg>Fix narrowing to personals with a specific user<commit_after>// For tracking where you were before you narrowed.
var persistent_message_id = 0;

// For narrowing based on a particular message
var narrow_target_message_id = 0;

// Narrowing predicate, or 'false' for the home view.
var narrowed = false;

function do_narrow(description, filter_function) {
    narrowed = filter_function;

    // Your pointer isn't changed when narrowed.
    persistent_message_id = selected_message_id;

    // Empty the filtered table right before we fill it again
    clear_table('zfilt');
    add_to_table(message_array, 'zfilt', filter_function, 'bottom');

    // Show the new set of messages.
    $("#zfilt").addClass("focused_table");

    $("#show_all_messages").removeAttr("disabled");
    $(".narrowcontent").show();
    $("#main_div").addClass("narrowed_view");
    $("#currently_narrowed_to").html(description).attr("title", description);
    $("#zhome").removeClass("focused_table");

    // Indicate both which message is persistently selected and which
    // is temporarily selected
    select_and_show_by_id(selected_message_id);
    selected_message_class = "narrowed_selected_message";
    select_and_show_by_id(narrow_target_message_id);
    scroll_to_selected();
}

function target_message_for_narrow(id) {
    narrow_target_message_id = id;
}

function narrow_huddle() {
    var original = message_dict[narrow_target_message_id];
    do_narrow("Huddles with " + original.display_reply_to, function (other) {
        return (other.type === "personal" || other.type === "huddle")
            && other.reply_to === original.reply_to;
    });
}

function narrow_all_personals() {
    do_narrow("All huddles with you", function (other) {
        return other.type === "personal" || other.type === "huddle";
    });
}

function narrow_personals() {
    // Narrow to personals with a specific user
    var original = message_dict[narrow_target_message_id];

    do_narrow("Huddles with " + original.display_replay_to, function (other) {
        return (other.type === 'personal') &&
            (((other.display_recipient.email === original.display_recipient.email) && (other.sender_email === original.sender_email)) ||
             ((other.display_recipient.email === original.sender_email) && (other.sender_email === original.display_recipient.email)));
    });

}

function narrow_stream() {
    var original = message_dict[narrow_target_message_id];
    var message = original.display_recipient;
    do_narrow(message, function (other) {
        return (other.type === 'stream' &&
                original.recipient_id === other.recipient_id);
    });
}

function narrow_subject() {
    var original = message_dict[narrow_target_message_id];
    if (original.type !== 'stream')
        return;

    var message = original.display_recipient + " | " + original.subject;
    do_narrow(message, function (other) {
        return (other.type === 'stream' &&
                original.recipient_id === other.recipient_id &&
                original.subject === other.subject);
    });
}

// Called for the 'narrow by stream' hotkey.
function narrow_by_recipient() {
    switch (message_dict[selected_message_id].type) {
        case 'personal': narrow_personals(); break;
        case 'huddle':   narrow_huddle();    break;
        case 'stream':    narrow_stream();     break;
    }
}

function show_all_messages() {
    if (!narrowed) {
        return;
    }
    narrowed = false;

    $("#zfilt").removeClass('focused_table');
    $("#zhome").addClass('focused_table');
    $(".narrowcontent").hide();
    $("#main_div").removeClass('narrowed_view');
    $("#show_all_messages").attr("disabled", "disabled");
    $("#currently_narrowed_to").html("");

    selected_message_class = "selected_message";
    // Includes scrolling.
    select_and_show_by_id(persistent_message_id);

    scroll_to_selected();
}
<|endoftext|>


<commit_before>function Collision_prototype() {
    this.arbres = [];
    this.mushrooms = [];
    this.rivers = [];
    this.nenuphars = [];
}

Collision_prototype.prototype = {

    manage : function() {

        (function manageWaterlily(self) {
            for (var j = 0; j < self.nenuphars.length; j++) {
                if (lib.isClose(self.nenuphars[j], game.player)) {
                    controls.bump();
                }
            }
        })(this);

        (function manageThree (self) {
            for (var j = 0; j < self.arbres.length; j++) {
                if (lib.isClose(self.arbres[j], game.player)) {
                    controls.block();
                }
            }
        })(this);

        (function manageRiver (self) {
            for (var j = 0; j < self.rivers.length; j++) {
                if (game.player.position.y < 22) {
                    if (lib.isOnRiver(self.rivers[j], game.player.position)) {
                        controls.slow();
                    }
                }
            }
        })(this);

        (function manageMushroom (self) {
            for (var i = 0; i < self.mushrooms.length; i++) {
                if (lib.isClose(self.mushrooms[i], game.player)) {
                    if (game.type == TYPE_GAME.MULTIPLAYER) {
                        Arena.pickupMushroom(self.mushrooms[i].position.x, self.mushrooms[i].position.z);

                        if (self.mushrooms[i].megaMushroom) {
                            game.player.boost += 30;
                        } else {
                            game.player.boost += 10;
                        }
                    }
                    if (game.secondes > 0) {
                        if (game.type != 2) {
                            if (self.mushrooms[i].isMegamush) {
                                game.player.points += 5;
                                game.player.boost += 40;
                            } else {
                                game.player.boost += 20;
                                game.player.points++;
                            }
                        }
                        if (game.player.boost > 100) {
                            game.player.boost = 100;
                        }
                        message.updateBoost();
                        message.showScore();
                    }
                    if (game.type == TYPE_GAME.MULTIPLAYER) {
                        elements.removeElementObjectMush(self.mushrooms[i]);
                    } else {
                        elements.moveToRandomPosition(self.mushrooms[i]);
                    }
                    break;
                }
            }
        })(this);
    }
};

var collision = new Collision_prototype();
<commit_msg>Fix collision<commit_after>function Collision_prototype() {
    this.arbres = [];
    this.mushrooms = [];
    this.rivers = [];
    this.nenuphars = [];
}

Collision_prototype.prototype = {

    manage : function() {

        (function manageWaterlily(self) {
            for (var j = 0; j < self.nenuphars.length; j++) {
                if (lib.isClose(self.nenuphars[j], game.player)) {
                    controls.bump();
                }
            }
        })(this);

        (function manageThree (self) {
            for (var j = 0; j < self.arbres.length; j++) {
                if (lib.isClose(self.arbres[j], game.player)) {
                    controls.block();
                }
            }
        })(this);

        (function manageRiver (self) {
            for (var j = 0; j < self.rivers.length; j++) {
                if (game.player.position.y < 22) {
                    if (lib.isOnRiver(self.rivers[j], game.player.position)) {
                        controls.slow();
                    }
                }
            }
        })(this);

        (function manageMushroom (self) {
            if (game.secondes < 0) { return; }

            for (var i = 0; i < self.mushrooms.length; i++) {

                var mushroom = self.mushrooms[i];
                if(mushroom == undefined) console.log("collison mushroom "+i+" is undefined");

                if (lib.isClose(mushroom, game.player)) {

                    if (game.type == TYPE_GAME.MULTIPLAYER) { // notify
                        Arena.pickupMushroom(self.mushrooms[i].position.x, self.mushrooms[i].position.z);
                        elements.removeElementObjectMush(self.mushrooms[i]);
                    } else if (game.type == TYPE_GAME.BOT){
                        elements.moveToRandomPosition(self.mushrooms[i]);
                    }

                    // add boost
                    if (mushroom.isMegamush) {
                        game.player.boost += 30;
                        message.updateBoost();
                    } else {
                        game.player.boost += 10;
                    }
                    if (game.player.boost > 100) {
                        game.player.boost = 100;
                    }
                    message.updateBoost();

                    // add score
                    if (game.type == TYPE_GAME.BOT){
                        if (mushroom.isMegamush) {
                            game.player.points += 5;
                        } else {
                            game.player.points++;
                        }
                        message.showScore();
                    }

                    break;
                }
            }
        })(this);
    }
};

var collision = new Collision_prototype();
<|endoftext|>


<commit_before>CT.trans = {
	_: {
		vender_prefixes: [ "-webkit-", "-moz-", "-ms-", "-o-", ""],
		tswap: { transform: "-webkit-transform" }, // mobile safari transitions
		enames: [ "webkitTransitionEnd", "mozTransitionEnd", "oTransitionEnd", "transitionend"],
		defaults: {
			trans: {
				duration: 500,
				ease: "ease-in-out"
			},
			rotate: {
				degrees: 180,
				duration: 1000,
				property: "transform",
				ease: "linear",
				prefix: true
			},
			translate: {
				duration: 300,
				property: "transform",
				ease: "ease-out",
				prefix: true,
				dx: 0,
				dy: 0,
				dz: 0
			}
		}
	},
	setVenderPrefixed: function(node, property, value) {
	    for (var i = 0; i < CT.trans._.vender_prefixes.length; i++)
	        node.style[CT.trans._.vender_prefixes[i] + property] = value;
	},
	trans: function(opts) {
		// opts: node, property, value, cb, duration, ease prefix
		opts = CT.merge(opts, CT.trans._.defaults.trans);
	    opts.property && opts.node && CT.trans.setVenderPrefixed(opts.node,
	    	"transition", (CT.trans._.tswap[opts.property] || opts.property)
	        + " " + opts.duration + "ms " + (opts.ease || "ease-in-out"));
	    if (opts.cb) {
	        var transTimeout, wrapper = function () {
	            opts.property && CT.trans.setVenderPrefixed(opts.node, "transition", "");
	            clearTimeout(transTimeout);
	            transTimeout = null;
	            if (opts.node) CT.trans._.enames.forEach(function(ename) {
		            opts.node.removeEventListener(ename, wrapper, false);
            	});
	            opts.cb();
	        }
            if (opts.node) CT.trans._.enames.forEach(function(ename) {
	            opts.node.addEventListener(ename, wrapper, false);
        	});
	        transTimeout = setTimeout(wrapper, opts.duration);
	    }
	    if (opts.property) {
	        if (opts.prefix)
	            CT.trans.setVenderPrefixed(opts.node, opts.property, opts.value);
	        else
	            opts.node.style[opts.property] = opts.value;
	    }
	},
	rotate: function(node, opts) {
		// opts may include: duration, degrees, cb, ease, forever
		opts = CT.merge(opts, CT.trans._.defaults.rotate);
		opts.node = node;
		opts.value = "rotate(" + opts.degrees + "deg)";
		if (opts.forever) opts.cb = function() {
			opts.degrees += CT.trans._.defaults.rotate.degrees;
			CT.trans.rotate(node, opts);
		};
		CT.trans.trans(opts);
	},
	translate: function(node, opts) {
		opts = CT.merge(opts, CT.trans._.defaults.translate);
		opts.node = node;
		opts.value = "translate3d(" + opts.dx + "px," + opts.dy + "px," + opts.dz + "px)",
		CT.trans.trans(opts);
	}
};<commit_msg>CT.trans defaults<commit_after>CT.trans = {
	_: {
		vender_prefixes: [ "-webkit-", "-moz-", "-ms-", "-o-", ""],
		tswap: { transform: "-webkit-transform" }, // mobile safari transitions
		enames: [ "webkitTransitionEnd", "mozTransitionEnd", "oTransitionEnd", "transitionend"],
		defaults: {
			trans: {
				duration: 500,
				property: "*",
				ease: "ease-in-out"
			},
			rotate: {
				degrees: 180,
				duration: 1000,
				property: "transform",
				ease: "linear",
				prefix: true
			},
			translate: {
				duration: 300,
				property: "transform",
				ease: "ease-out",
				prefix: true,
				dx: 0,
				dy: 0,
				dz: 0
			}
		}
	},
	setVenderPrefixed: function(node, property, value) {
	    for (var i = 0; i < CT.trans._.vender_prefixes.length; i++)
	        node.style[CT.trans._.vender_prefixes[i] + property] = value;
	},
	trans: function(opts) {
		// opts: node, property, value, cb, duration, ease prefix
		opts = CT.merge(opts, CT.trans._.defaults.trans);
	    opts.node && CT.trans.setVenderPrefixed(opts.node,
	    	"transition", (CT.trans._.tswap[opts.property] || opts.property)
	        + " " + opts.duration + "ms " + opts.ease);
	    if (opts.cb) {
	        var transTimeout, wrapper = function () {
	            opts.property && CT.trans.setVenderPrefixed(opts.node, "transition", "");
	            clearTimeout(transTimeout);
	            transTimeout = null;
	            if (opts.node) CT.trans._.enames.forEach(function(ename) {
		            opts.node.removeEventListener(ename, wrapper, false);
            	});
	            opts.cb();
	        }
            if (opts.node) CT.trans._.enames.forEach(function(ename) {
	            opts.node.addEventListener(ename, wrapper, false);
        	});
	        transTimeout = setTimeout(wrapper, opts.duration);
	    }
	    if (opts.property && opts.property != "*") {
	        if (opts.prefix)
	            CT.trans.setVenderPrefixed(opts.node, opts.property, opts.value);
	        else
	            opts.node.style[opts.property] = opts.value;
	    }
	},
	rotate: function(node, opts) {
		// opts may include: duration, degrees, cb, ease, forever
		opts = CT.merge(opts, CT.trans._.defaults.rotate);
		opts.node = node;
		opts.value = "rotate(" + opts.degrees + "deg)";
		if (opts.forever) opts.cb = function() {
			opts.degrees += CT.trans._.defaults.rotate.degrees;
			CT.trans.rotate(node, opts);
		};
		CT.trans.trans(opts);
	},
	translate: function(node, opts) {
		opts = CT.merge(opts, CT.trans._.defaults.translate);
		opts.node = node;
		opts.value = "translate3d(" + opts.dx + "px," + opts.dy + "px," + opts.dz + "px)",
		CT.trans.trans(opts);
	}
};<|endoftext|>


<commit_before>import ApolloClient, { createNetworkInterface } from "apollo-client";
import { readQueryFromStore } from "apollo-client/lib/src/data/readFromStore";
import { addReducer, addMiddleware } from "../store";

const heighliner = createNetworkInterface("http://localhost:8888/");
const apolloClient = new ApolloClient({
  networkInterface: heighliner,
});

addReducer({
  apollo: apolloClient.reducer(),
});
addMiddleware(apolloClient.middleware());

export {
  apolloClient,
  readQueryFromStore,
};
<commit_msg>explain yo self<commit_after>// apollo client imports need to remain in this file
// apollo client does not like to mingle with other imports
// apollo client has not told me why
// apollo client demands exclusivity?
// apollo client is probably fine and it's webpack
// webpack is evil
import ApolloClient, { createNetworkInterface } from "apollo-client";
import { readQueryFromStore } from "apollo-client/lib/src/data/readFromStore";
import { addReducer, addMiddleware } from "../store";

const heighliner = createNetworkInterface("http://localhost:8888/");
const apolloClient = new ApolloClient({
  networkInterface: heighliner,
});

addReducer({
  apollo: apolloClient.reducer(),
});
addMiddleware(apolloClient.middleware());

export {
  apolloClient,
  readQueryFromStore,
};
<|endoftext|>


<commit_before>/*
*  index.js
*  Bowtie Code
*
*  Functionality for the application
*/

/*
 * TODO: migrate database functionality to 'com.phonegap.plugins.sqlite'
 * @see https://github.com/brodysoft/Cordova-SQLitePlugin
 */
(function () {
    /* yes please */
    'use strict';

    var big;

    /* Structure for a single assginment's attributes */
    var makeAssignment = function (_title, _desc, _due, _notify) {
        // create a new object from the Object prototype
        var that = Object.create(null);
        // add our custom attributes
        that.title = _title;
        that.desc = _desc;
        that.dueDate = _due;        // these two MUST be Date objects!
        that.notifyDate = _notify;  // --^
        // return the extended object
        return that;
    };

    /* Structure for a single class/section/course */
    var makeCourse = function (_name, _title, _instructor, _location, _times) {
        var that = Object.create(null);
        // basic properties
        that.name = _name;
        that.title = _title;
        that.instructor = _instructor;
        that.location = _location;
        that.times = _times;
        // assignments associated with this class
        that.assignments = [];

        /* some private functions */
        // compare two assignments to sort by due date
        function compareTaskDates (t1, t2) {
            var t1d = t1.dueDate.getTime(),
                t2d = t1.dueDate.getTime();
            if (t1d < t2d) {
                return -1;
            }
            else if (t1d > t2d) {
                return 1;
            }
            else {
                return 0;
            }
        }
        // when we create this object, any existing assignments for it from the db
        function initializeTaskList () {
            html5sql.process(
                [{
                    "sql": "Select * from Assignments Where course = ?",
                    "data": [ that.name ],
                    "success": function (transaction, result) {
                        var i = 0, rl = result.rows.length, r, someClass;
                        for (i; i < rl; i += 1) {
                            r = result.rows.item(i);
                            someTask = makeAssignment(r.name, r.description, r.dueDate, r.whenNotify);
                            that.assignments.push(someTask);
                        }
                    }
                }],
                function () {
                    // need gui update here
                },
                app.logSqlError
            );
        }
        initializeTaskList();

        // add some public methods
        that.addTask = function (taskObj) {
            // add to database
            // on success, add to list
        };
        that.editTask = function (taskIndex, newTaskObj) {

        };
        that.deleteTask = function (taskIndex) {

        };
        that.deleteAllTasks = function () {

        };
        that.getTask = function (taskIndex) {

        };

        return that;
    };
    /* this is a constructor, BUT we should only ever call it once.
      It would be nice if it were a true singleton, but that doesn't really work
      because we can only instantiate this object in response to the
      database being successfully initialized.
    */
    var initCourseList = function () {
        var allCourses = {};
        // when we create this singleton, fetch data from the db
        html5sql.process(
            [{
                "sql": "Select * From Classes Where cname != 'none'",
                "data": [],
                "success": function (transaction, result) {
                    var i = 0, rl = result.rows.length, r, someClass;
                    for (i; i < rl; i += 1) {
                        r = result.rows.item(i);
                        someClass = makeCourse(r.cname, r.ctitle, r.instructor, r.location, r.times);
                        allCourses[someClass.name] = someClass;
                    }
                }
            }],
            function () {
                app.domFuncs.updateCourseListDom();
            },
            app.logSqlError
        );
        // return public methods in an object literal
        return {
            /* Given a classSection object, insert to table, add in list,
             * and rebuild the view if all that was successful
             */
            addCourse: function (course) {
                html5sql.process(
                    [{
                        "sql": "Insert or Replace into Classes Values (?, ?, ?, ?, ?)",
                        "data": [ course.name, course.title, course.instructor, course.location, course.times ],
                        "success": function (transaction, results) {} // don't care...
                    }],
                    function () {
                        allCourses[course.name] = course;
                        app.domFuncs.updateCourseListDom();
                    },
                    app.logSqlError
                );
            },
            editCourse: function (courseId, newTitle, newIns, newLoc, newTime) {
                html5sql.process(
                    [{
                        "sql": "Update Table Classes Set ctitle = ?, instructor = ?, location = ?, times = ? Where cname = ?",
                        "data": [ newTitle, newIns, newLoc, newTime, courseId ],
                        "success": function (transaction, results) {}
                    }],
                    function () {
                        // update in list
                        allCourses.courseId.title = newTitle;
                        allCourses.courseId.instructor = newIns;
                        allCourses.courseId.location = newLoc;
                        allCourses.courseId.times = newTime;
                        // trigger dom refresh
                        app.domFuncs.updateCourseListDom();
                    },
                    app.logSqlError
                );
            },
            /* Given a class id, remove that class from memory and db
             * and redraw the class list view
             */
            deleteCourse: function (courseId) {
                html5sql.process(
                    [{
                        "sql": "Delete From Assignments Where course = ?",
                        "data": [ courseId ],
                        "success": function (transaction, results) {}
                    },
                    {
                        "sql": "Delete From Classes Where cname = ?",
                        "data": [ courseId ],
                        "success": function (transaction, results) {}
                    }],
                    function () {
                        delete allCourses[courseId];
                        app.domFuncs.updateCourseListDom();
                    },
                    app.logSqlError
                );
            },
            /* Be careful with this!
             * This will delete every entry in the classes database!
              */
            deleteAllCourses: function () {
                for (var courseId in allCourses) {
                    if (allCourses.hasOwnProperty(courseId)) {
                        courseList.deleteOne(courseId);
                    }
                }
            },
            getCourse: function (courseId) {
                return allCourses[courseId];
            },
            getAllCourses: function () {
                var res = [];
                for (var id in allCourses) {
                    if (allCourses.hasOwnProperty(id)) {
                        res.push(allCourses[id]);
                    }
                }
                return res;
            },
            /* Grab an array of the class id's we are storing in the list
             */
            getCourseIds: function () {
                var id, idArr = [];
                for (id in allCourses) {
                    if (allCourses.hasOwnProperty(id)) {
                        idArr.push(id);
                    }
                }
                return idArr;
            }
        };  // end public courseList methods
    };

    /* Our primary namespace, bound to 'window' so we can access it from in HTML */
    window.app = {
        // Entry point.  This function is called from bottom of HTML page.
        initialize: function () {
            this.bindEvents();
        },
        /* Bind Event Listeners
         * Bind any events that are required on startup. Common events are:
         * 'load', 'deviceready', 'offline', and 'online'.
         * TODO: How to use both jQuery '*ready' events AND the phonegap ready events?
         */
        bindEvents: function () {
            document.addEventListener('deviceready', this.onDeviceReady, false);
            $("#edit-class").on("popupafterclose", this.classPopupOnCloseHandler);
            $("#edit-class-delete").on("click", this.classPopupDeleteHandler);
        },
        /* Initialize the local storage database */
        initializeLDB: function () {
            html5sql.openDatabase("edu.radford.agenda.db", "RU-Agena-DB", 1024 * 1024 * 5);
            html5sql.process(
                [
                    "create table if not exists Classes ( cname TEXT PRIMARY KEY NOT NULL, ctitle TEXT DEFAULT '' NOT NULL, instructor TEXT, location TEXT, times TEXT );",
                    "create table if not exists Assignments ( id INTEGER PRIMARY KEY AUTOINCREMENT, course TEXT NOT NULL REFERENCES Classes(cname) DEFAULT 'none', name TEXT UNIQUE NOT NULL DEFAULT 'Assignment', description TEXT DEFAULT '', dueDate INTEGER, whenNotify  INTEGER );"
                ],
                function () {
                    console.log("Initialized local database tables");
                    big = initCourseList();
                },
                app.logSqlError
            );
        },
        /***********************************************************************
         * Event handlers
         **********************************************************************/
        /* deviceready Event Handler
         * (the phonegap api is not ready until this function is called!)
         * The scope of 'this' is the event. In order to call the 'receivedEvent'
         * function, we must explicity call 'app.receivedEvent(...);'
         */
        onDeviceReady: function () {
            app.initializeLDB();
        },
        /* handler when we tapclick the "Add new class" list item */
        addNewClassHandler: function () {
            // hide the delete/remove button
            $("#edit-class-delete").hide();
            // enable the class title field
            $("#edit-class-id").prop("disabled", false);
            // set the 'legend' text
            $("div#edit-class h3").text("Add a new class");
            // set handler
            $("#edit-class-save").off("click");
            $("#edit-class-save").on("click", app.classPopupAddBtnHandler);
            // now open the popup
            $("#edit-class").popup("open");
        },
        /* handler when we tapclick an existing item in the list of classes */
        editClassHandler: function (event) {
            var lid, cls;
            // show the delete/remove button
            $("#edit-class-delete").show();
            // disable editing the name/id of the class (it's the key)
            $("#edit-class-id").prop("disabled", true);
            // set the 'legend' text
            $("div#edit-class h3").text("Edit class details");
            // need to pre-populate the form w/ values
            lid = event.currentTarget.id;
            cls = big.getCourse(lid);
            $("#edit-class-id").val(cls.name);
            $("#edit-class-title").val(cls.title);
            $("#edit-class-who").val(cls.instructor);
            $("#edit-class-where").val(cls.location);
            $("#edit-class-when").val(cls.times);
            // set handler
            $("#edit-class-save").off("click");
            $("#edit-class-save").on("click", app.classPopupEditBtnHandler);
            // now open the popup
            $("#edit-class").popup("open");
        },
        /* handler for the delete button in the class detail view */
        classPopupDeleteHandler: function () {
            var cid = $("#edit-class-id").val();

            if (cid !== "") {
                big.deleteCourse(cid);
            }

            //if (cid !== "") {
                app.classList.removeClass(cid);
           // }

            $("#edit-class").popup("close");
        },
        /* handler for the save button in the class detail view */
        classPopupAddBtnHandler: function () {
            var section = makeCourse(
                $("#edit-class-id").val(),
                $("#edit-class-title").val(),
                $("#edit-class-who").val(),
                $("#edit-class-where").val(),
                $("#edit-class-when").val()
            );
            /* rudimentary opaque validation, no empty class names */
            if (section.name !== "") {
                big.addCourse(section);
            }
            $("#edit-class").popup("close");
        },
        classPopupEditBtnHandler: function () {
            big.editCourse(
                $("#edit-class-id").val(),
                $("#edit-class-title").val(),
                $("#edit-class-who").val(),
                $("#edit-class-where").val(),
                $("#edit-class-when").val()
            );
            $("#edit-class").popup("close");
        },
        /* clear the text fields in the class detail popup when it closes */
        classPopupOnCloseHandler: function (/*event, ui*/) {
            $("#edit-class :text").val("");
        },
        /***************************************************************************
         * Dev/Debug stuff
         **************************************************************************/
        /* generic and mostly useless SQL error printing callback */
        logSqlError: function (error, statement) {
            console.log(error);
            console.log(statement);
        },
        /* DELETE ME LATER!
         * Creates some sample class rows to query against.
         */
        makeSampleClasses: function () {
            var someClasses = [
                makeCourse("ITEC 110", "Principles of Information Technology", "Dr. Htay", "MG 203", "TR 3:30 - 4:45 PM"),
                makeCourse("ITEC 120", "Principles of Computer Science I", "Dr. Braffitt", "DA 225", "MWRF 11 - 11:50 AM"),
                makeCourse("MATH 151", "Calculus I", "Cabbage", "RU 314", "MWF 1 - 1:50 PM"),
                makeCourse("ART 111", "Art Appreciation", "Pop", "Porterfield", "MWF 9 - 9:50 AM")
            ], i = 0, scl = someClasses.length;
            for (i; i < scl; i += 1) {
                big.addCourse(someClasses[i]);
            }
        },

        /* contains the funcs for updating dom */
        domFuncs: (function () {
            var getCourseListItemHtml = function (cls) {
                var piecesArr = ["
", cls.name, "
",
                    cls.title, "

", cls.instructor, "

",
                    cls.location, "

", cls.times, "

"];
                return piecesArr.join("");
            };
            return {
                // rebuild the displayed jQuery listView in the classes tab
                updateCourseListDom: function () {
                    var id, oneClass, $newBits,
                        allClasses = big.getAllCourses(),
                        $addBtn = $("
Add new class...
");
                    $("ul#classList").empty();
                    for (id in allClasses) {
                        if (allClasses.hasOwnProperty(id)) {
                            oneClass = allClasses[id];
                            $newBits = $(getCourseListItemHtml(oneClass));
                            $("ul#classList").append($newBits);
                        }
                    }
                    $("ul#classList").append($addBtn);
                    $("#add-new-class-btn").on("click", app.addNewClassHandler);
                    $("ul#classList").on("click", "li a.class-list-item", app.editClassHandler);
                    $("ul#classList").listview("refresh");
                }
            };

        }())

    };
}(this));   // end everything
<commit_msg>Fixed editCourse() method<commit_after>/*
*  index.js
*  Bowtie Code
*
*  Functionality for the application
*/

/*
 * TODO: migrate database functionality to 'com.phonegap.plugins.sqlite'
 * @see https://github.com/brodysoft/Cordova-SQLitePlugin
 */
(function () {
    /* yes please */
    'use strict';

    var big;

    /* Structure for a single assginment's attributes */
    var makeAssignment = function (_title, _desc, _due, _notify) {
        // create a new object from the Object prototype
        var that = Object.create(null);
        // add our custom attributes
        that.title = _title;
        that.desc = _desc;
        that.dueDate = _due;        // these two MUST be Date objects!
        that.notifyDate = _notify;  // --^
        // return the extended object
        return that;
    };

    /* Structure for a single class/section/course */
    var makeCourse = function (_name, _title, _instructor, _location, _times) {
        var that = Object.create(null);
        // basic properties
        that.name = _name;
        that.title = _title;
        that.instructor = _instructor;
        that.location = _location;
        that.times = _times;
        // assignments associated with this class
        that.assignments = [];

        /* some private functions */
        // compare two assignments to sort by due date
        function compareTaskDates (t1, t2) {
            var t1d = t1.dueDate.getTime(),
                t2d = t1.dueDate.getTime();
            if (t1d < t2d) {
                return -1;
            }
            else if (t1d > t2d) {
                return 1;
            }
            else {
                return 0;
            }
        }
        // when we create this object, any existing assignments for it from the db
        function initializeTaskList () {
            html5sql.process(
                [{
                    "sql": "Select * from Assignments Where course = ?",
                    "data": [ that.name ],
                    "success": function (transaction, result) {
                        var i = 0, rl = result.rows.length, r, someClass;
                        for (i; i < rl; i += 1) {
                            r = result.rows.item(i);
                            someTask = makeAssignment(r.name, r.description, r.dueDate, r.whenNotify);
                            that.assignments.push(someTask);
                        }
                    }
                }],
                function () {
                    // need gui update here
                },
                app.logSqlError
            );
        }
        initializeTaskList();

        // add some public methods
        that.addTask = function (taskObj) {
            // add to database
            // on success, add to list
        };
        that.editTask = function (taskIndex, newTaskObj) {

        };
        that.deleteTask = function (taskIndex) {

        };
        that.deleteAllTasks = function () {

        };
        that.getTask = function (taskIndex) {

        };

        return that;
    };
    /* this is a constructor, BUT we should only ever call it once.
      It would be nice if it were a true singleton, but that doesn't really work
      because we can only instantiate the object in response to the
      database being successfully initialized.
    */
    var initCourseList = function () {
        var allCourses = {};
        // when we create this singleton, fetch data from the db
        html5sql.process(
            [{
                "sql": "Select * From Classes Where cname != 'none'",
                "data": [],
                "success": function (transaction, result) {
                    var i = 0, rl = result.rows.length, r, someClass;
                    for (i; i < rl; i += 1) {
                        r = result.rows.item(i);
                        someClass = makeCourse(r.cname, r.ctitle, r.instructor, r.location, r.times);
                        allCourses[someClass.name] = someClass;
                    }
                }
            }],
            function () {
                app.domFuncs.updateCourseListDom();
            },
            app.logSqlError
        );
        // return public methods in an object literal
        return {
            /* Given a classSection object, insert to table, add in list,
             * and rebuild the view if all that was successful
             */
            addCourse: function (course) {
                html5sql.process(
                    [{
                        "sql": "Insert or Replace into Classes Values (?, ?, ?, ?, ?)",
                        "data": [ course.name, course.title, course.instructor, course.location, course.times ],
                        "success": function (transaction, results) {} // don't care...
                    }],
                    function () {
                        allCourses[course.name] = course;
                        app.domFuncs.updateCourseListDom();
                    },
                    app.logSqlError
                );
            },
            editCourse: function (courseId, newTitle, newIns, newLoc, newTime) {
                html5sql.process(
                    [{
                        "sql": "Update Classes Set ctitle = ?, instructor = ?, location = ?, times = ? Where cname = ?",
                        "data": [ newTitle, newIns, newLoc, newTime, courseId ],
                        "success": function (transaction, results) {}
                    }],
                    function () {
                        // update in list
                        allCourses[courseId].title = newTitle;
                        allCourses[courseId].instructor = newIns;
                        allCourses[courseId].location = newLoc;
                        allCourses[courseId].times = newTime;
                        // trigger dom refresh
                        app.domFuncs.updateCourseListDom();
                    },
                    app.logSqlError
                );
            },
            /* Given a class id, remove that class from memory and db
             * and redraw the class list view
             */
            deleteCourse: function (courseId) {
                html5sql.process(
                    [{
                        "sql": "Delete From Assignments Where course = ?",
                        "data": [ courseId ],
                        "success": function (transaction, results) {}
                    },
                    {
                        "sql": "Delete From Classes Where cname = ?",
                        "data": [ courseId ],
                        "success": function (transaction, results) {}
                    }],
                    function () {
                        delete allCourses[courseId];
                        app.domFuncs.updateCourseListDom();
                    },
                    app.logSqlError
                );
            },
            /* Be careful with this!
             * This will delete every entry in the classes database!
              */
            deleteAllCourses: function () {
                for (var courseId in allCourses) {
                    if (allCourses.hasOwnProperty(courseId)) {
                        courseList.deleteOne(courseId);
                    }
                }
            },
            getCourse: function (courseId) {
                return allCourses[courseId];
            },
            getAllCourses: function () {
                var res = [];
                for (var id in allCourses) {
                    if (allCourses.hasOwnProperty(id)) {
                        res.push(allCourses[id]);
                    }
                }
                return res;
            },
            /* Grab an array of the class id's we are storing in the list
             */
            getCourseIds: function () {
                var id, idArr = [];
                for (id in allCourses) {
                    if (allCourses.hasOwnProperty(id)) {
                        idArr.push(id);
                    }
                }
                return idArr;
            }
        };  // end public courseList methods
    };

    /* Our primary namespace, bound to 'window' so we can access it from in HTML */
    window.app = {
        // Entry point.  This function is called from bottom of HTML page.
        initialize: function () {
            this.bindEvents();
        },
        /* Bind Event Listeners
         * Bind any events that are required on startup. Common events are:
         * 'load', 'deviceready', 'offline', and 'online'.
         * TODO: How to use both jQuery '*ready' events AND the phonegap ready events?
         */
        bindEvents: function () {
            document.addEventListener('deviceready', this.onDeviceReady, false);
            $("#edit-class").on("popupafterclose", this.classPopupOnCloseHandler);
            $("#edit-class-delete").on("click", this.classPopupDeleteHandler);
        },
        /* Initialize the local storage database */
        initializeLDB: function () {
            html5sql.openDatabase("edu.radford.agenda.db", "RU-Agena-DB", 1024 * 1024 * 5);
            html5sql.process(
                [
                    "create table if not exists Classes ( cname TEXT PRIMARY KEY NOT NULL, ctitle TEXT DEFAULT '' NOT NULL, instructor TEXT, location TEXT, times TEXT );",
                    "create table if not exists Assignments ( id INTEGER PRIMARY KEY AUTOINCREMENT, course TEXT NOT NULL REFERENCES Classes(cname) DEFAULT 'none', name TEXT UNIQUE NOT NULL DEFAULT 'Assignment', description TEXT DEFAULT '', dueDate INTEGER, whenNotify  INTEGER );"
                ],
                function () {
                    console.log("Initialized local database tables");
                    big = initCourseList();
                },
                app.logSqlError
            );
        },
        /***********************************************************************
         * Event handlers
         **********************************************************************/
        /* deviceready Event Handler
         * (the phonegap api is not ready until this function is called!)
         * The scope of 'this' is the event. In order to call the 'receivedEvent'
         * function, we must explicity call 'app.receivedEvent(...);'
         */
        onDeviceReady: function () {
            app.initializeLDB();
        },
        /* handler when we tapclick the "Add new class" list item */
        addNewClassHandler: function () {
            // hide the delete/remove button
            $("#edit-class-delete").hide();
            // enable the class title field
            $("#edit-class-id").prop("disabled", false);
            // set the 'legend' text
            $("div#edit-class h3").text("Add a new class");
            // set handler
            $("#edit-class-save").off("click");
            $("#edit-class-save").on("click", app.classPopupAddBtnHandler);
            // now open the popup
            $("#edit-class").popup("open");
        },
        /* handler when we tapclick an existing item in the list of classes */
        editClassHandler: function (event) {
            var lid, cls;
            // show the delete/remove button
            $("#edit-class-delete").show();
            // disable editing the name/id of the class (it's the key)
            $("#edit-class-id").prop("disabled", true);
            // set the 'legend' text
            $("div#edit-class h3").text("Edit class details");
            // need to pre-populate the form w/ values
            lid = event.currentTarget.id;
            cls = big.getCourse(lid);
            $("#edit-class-id").val(cls.name);
            $("#edit-class-title").val(cls.title);
            $("#edit-class-who").val(cls.instructor);
            $("#edit-class-where").val(cls.location);
            $("#edit-class-when").val(cls.times);
            // set handler
            $("#edit-class-save").off("click");
            $("#edit-class-save").on("click", app.classPopupEditBtnHandler);
            // now open the popup
            $("#edit-class").popup("open");
        },
        /* handler for the delete button in the class detail view */
        classPopupDeleteHandler: function () {
            var cid = $("#edit-class-id").val();

            if (cid !== "") {
                big.deleteCourse(cid);
            }

            //if (cid !== "") {
                app.classList.removeClass(cid);
           // }

            $("#edit-class").popup("close");
        },
        /* handler for the save button in the class detail view */
        classPopupAddBtnHandler: function () {
            var section = makeCourse(
                $("#edit-class-id").val(),
                $("#edit-class-title").val(),
                $("#edit-class-who").val(),
                $("#edit-class-where").val(),
                $("#edit-class-when").val()
            );
            /* rudimentary opaque validation, no empty class names */
            if (section.name !== "") {
                big.addCourse(section);
            }
            $("#edit-class").popup("close");
        },
        classPopupEditBtnHandler: function () {
            big.editCourse(
                $("#edit-class-id").val(),
                $("#edit-class-title").val(),
                $("#edit-class-who").val(),
                $("#edit-class-where").val(),
                $("#edit-class-when").val()
            );
            $("#edit-class").popup("close");
        },
        /* clear the text fields in the class detail popup when it closes */
        classPopupOnCloseHandler: function (/*event, ui*/) {
            $("#edit-class :text").val("");
        },
        /***************************************************************************
         * Dev/Debug stuff
         **************************************************************************/
        /* generic and mostly useless SQL error printing callback */
        logSqlError: function (error, statement) {
            console.log(error);
            console.log(statement);
        },
        /* DELETE ME LATER!
         * Creates some sample class rows to query against.
         */
        makeSampleClasses: function () {
            var someClasses = [
                makeCourse("ITEC 110", "Principles of Information Technology", "Dr. Htay", "MG 203", "TR 3:30 - 4:45 PM"),
                makeCourse("ITEC 120", "Principles of Computer Science I", "Dr. Braffitt", "DA 225", "MWRF 11 - 11:50 AM"),
                makeCourse("MATH 151", "Calculus I", "Cabbage", "RU 314", "MWF 1 - 1:50 PM"),
                makeCourse("ART 111", "Art Appreciation", "Pop", "Porterfield", "MWF 9 - 9:50 AM")
            ], i = 0, scl = someClasses.length;
            for (i; i < scl; i += 1) {
                big.addCourse(someClasses[i]);
            }
        },

        /* contains the funcs for updating dom */
        domFuncs: (function () {
            var getCourseListItemHtml = function (cls) {
                var piecesArr = ["
", cls.name, "
",
                    cls.title, "

", cls.instructor, "

",
                    cls.location, "

", cls.times, "

"];
                return piecesArr.join("");
            };
            return {
                // rebuild the displayed jQuery listView in the classes tab
                updateCourseListDom: function () {
                    var id, oneClass, $newBits,
                        allClasses = big.getAllCourses(),
                        $addBtn = $("
Add new class...
");
                    $("ul#classList").empty();
                    for (id in allClasses) {
                        if (allClasses.hasOwnProperty(id)) {
                            oneClass = allClasses[id];
                            $newBits = $(getCourseListItemHtml(oneClass));
                            $("ul#classList").append($newBits);
                        }
                    }
                    $("ul#classList").append($addBtn);
                    $("#add-new-class-btn").on("click", app.addNewClassHandler);
                    $("ul#classList").on("click", "li a.class-list-item", app.editClassHandler);
                    $("ul#classList").listview("refresh");
                }
            };

        }())

    };
}(this));   // end everything
<|endoftext|>


<commit_before>const Future = Npm.require("fibers/future");

Meteor.methods({
  'graphql.transport': function(query, variables, operationName) {
    check(query, String);
    check(variables, Match.OneOf(Object, undefined, null));
    check(operationName, Match.OneOf(String, undefined, null));

    variables = {...variables, ...{
      mongoId: this.userId
    }}

    const payload = { query, variables, operationName };
    const f = new Future();

    console.log(`Making request to ${Meteor.settings.heighliner}`)
    fetch(Meteor.settings.heighliner, {
        method: "POST",
        headers: {
          'Accept': 'application/json',
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(payload)
      })
      .then((response) => {
        return response.json()
      })
      .then((data) => {
        f.return(data);
      })
      .catch(error => {
        console.error(error)
        f.throw(error);
      });

    return f.wait()

  }
});
<commit_msg>more logs for heighliner debugging<commit_after>const Future = Npm.require("fibers/future");

Meteor.methods({
  'graphql.transport': function(query, variables, operationName) {
    check(query, String);
    check(variables, Match.OneOf(Object, undefined, null));
    check(operationName, Match.OneOf(String, undefined, null));

    variables = {...variables, ...{
      mongoId: this.userId
    }}

    const payload = { query, variables, operationName };
    const f = new Future();

    console.log(`Making request to ${Meteor.settings.heighliner}`, query, variables)
    fetch(Meteor.settings.heighliner, {
        method: "POST",
        headers: {
          'Accept': 'application/json',
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(payload)
      })
      .then((response) => {
        return response.json()
      })
      .then((data) => {
        f.return(data);
      })
      .catch(error => {
        console.error(error)
        f.throw(error);
      });

    return f.wait()

  }
});
<|endoftext|>


<commit_before>import { EmitterMixin } from '../../mixins/EmitterMixin';
import { mixin }        from '../../utils/ObjectUtils';

var automapData = {

    LEFT   : [ 37 ], // arrow left
    RIGHT  : [ 39 ], // arrow right
    UP     : [ 38 ], // arrow up
    DOWN   : [ 40 ], // arrow down

    A      : [ 65, 81 ], // 'A', 'Q'
    B      : [ 90, 87 ], // 'Z', 'W'

    START  : [ 13 ], // enter
    SELECT : [ 32 ]  // space

};

export class KeyboardInput extends mixin( null, EmitterMixin ) {

    constructor( { element = document.body } ) {

        this._map = options.map || this._createAutomap( options.inputs );
        this._element = options.element;

        this._onKeyDown_ = this._onKeyDown.bind( this );
        this._onKeyUp_ = this._onKeyUp.bind( this );

        this._attach( );

    }

    destroy( ) {

        this._detach( );

    }

    _createAutomap( inputs ) {

        var map = { };

        Object.keys( inputs ).forEach( function ( name ) {

            if ( ! automapData[ name ] )
                return ;

            automapData[ name ].forEach( function ( keyCode ) {
                map[ keyCode ] = inputs[ name ];
            } );

        }, this );

        return map;

    }

    _attach( ) {

        this._element.addEventListener( 'keydown', this._onKeyDown_ );
        this._element.addEventListener( 'keyup', this._onKeyUp_ );

    }

    _detach( ) {

        this._element.removeEventListener( 'keydown', this._onKeyDown_ );
        this._element.removeEventListener( 'keyup', this._onKeyUp_ );

    }

    _onKeyDown( e ) {

        if ( typeof this._map[ e.keyCode ] === 'undefined' )
            return ;

        e.preventDefault( );

        this.emit( 'keydown', this._map[ e.keyCode ] );

    }

    _onKeyUp( e ) {

        if ( typeof this._map[ e.keyCode ] === 'undefined' )
            return ;

        this.emit( 'keyup', this._map[ e.keyCode ] );

    }

};
<commit_msg>Fixes KeyboardInput<commit_after>import { EmitterMixin } from '../../mixins/EmitterMixin';
import { mixin }        from '../../utils/ObjectUtils';

var automapData = {

    LEFT   : [ 37 ], // arrow left
    RIGHT  : [ 39 ], // arrow right
    UP     : [ 38 ], // arrow up
    DOWN   : [ 40 ], // arrow down

    A      : [ 65, 81 ], // 'A', 'Q'
    B      : [ 90, 87 ], // 'Z', 'W'

    START  : [ 13 ], // enter
    SELECT : [ 32 ]  // space

};

export class KeyboardInput extends mixin( null, EmitterMixin ) {

    constructor( { map, inputs, element = document.body } ) {

        super( );

        this._map = map || this._createAutomap( inputs );
        this._element = element;

        this._onKeyDown_ = this._onKeyDown.bind( this );
        this._onKeyUp_ = this._onKeyUp.bind( this );

        this._attach( );

    }

    destroy( ) {

        this._detach( );

    }

    _createAutomap( inputs ) {

        var map = { };

        Object.keys( inputs ).forEach( function ( name ) {

            if ( ! automapData[ name ] )
                return ;

            automapData[ name ].forEach( function ( keyCode ) {
                map[ keyCode ] = inputs[ name ];
            } );

        }, this );

        return map;

    }

    _attach( ) {

        this._element.addEventListener( 'keydown', this._onKeyDown_ );
        this._element.addEventListener( 'keyup', this._onKeyUp_ );

    }

    _detach( ) {

        this._element.removeEventListener( 'keydown', this._onKeyDown_ );
        this._element.removeEventListener( 'keyup', this._onKeyUp_ );

    }

    _onKeyDown( e ) {

        if ( e.keyCode === 8 /* backspace */ )
            e.preventDefault( );

        if ( typeof this._map[ e.keyCode ] === 'undefined' )
            return ;

        e.preventDefault( );

        this.emit( 'keydown', this._map[ e.keyCode ] );

    }

    _onKeyUp( e ) {

        if ( typeof this._map[ e.keyCode ] === 'undefined' )
            return ;

        this.emit( 'keyup', this._map[ e.keyCode ] );

    }

};
<|endoftext|>


<commit_before>function addSuppressedException(/*Exception*/sup,/*Exception*/e) {
    if (e.$sups$===undefined) {
        e.$sups$=[];
    }
    if (sup.getT$name === undefined) sup = NativeException(sup);
    e.$sups$.push(sup);
}
exports.addSuppressedException=addSuppressedException;
function suppressedExceptions(/*Exception*/e) {
    return e.$sups$===undefined?getEmpty():e.$sups$;
}
exports.suppressedExceptions=suppressedExceptions;
<commit_msg>retuple for ceylon/ceylon-js#277<commit_after>function addSuppressedException(/*Exception*/sup,/*Exception*/e) {
    if (e.$sups$===undefined) {
        e.$sups$=[];
    }
    if (sup.getT$name === undefined) sup = NativeException(sup);
    e.$sups$.push(sup);
}
exports.addSuppressedException=addSuppressedException;
function suppressedExceptions(/*Exception*/e) {
    return e.$sups$===undefined?getEmpty():e.$sups$;
}
exports.suppressedExceptions=suppressedExceptions;
function $retuple(t) { //receives {t:'T',l:[...]}
  if (t.t!=='T')return t;
  var e;
  var r={t:Empty};
  for (var i=t.l.length-1;i>=0;i--){
    var f=$retuple(t.l[i]);
    var e=(r.a&&r.a.Element)||f;
    if (r.a&&r.a.Element) {
      if (e.l) {
        var l2=[];for(var j=0;j<e.l.length;j++)l2.push(e.l[j]);
        l2.unshift(f);
        e={t:'u',l:l2};
      } else {
        e = {t:'u',l:[f,e]};
      }
    }
    r={t:Tuple,a:{First:f,Element:e,Rest:r}};
  }
  return r;
}
<|endoftext|>


<commit_before>/**
 * znCrop jQuery plugin
 *
 * @author  Zion Ng <zion@intzone.com>
 * @link    https://github.com/zionsg/zn-jquery/tree/master/znCrop
 * @version 1.0.0, 2013-06-25
 */

(function ($) {

    /**
     * Resize and crop <img> children to fill their parent containers
     *
     * @example $('div.thumbnail').znCrop();
     * @param   bool firstLevel Default = true. Flag to restrict to 1st level <img> only.
     * @return  this
     */
    $.fn.znCrop = function (options) {
        // Merge default options with user options
        var config = $.extend({
            firstLevel: true
        }, options);

        this.css('overflow', 'hidden');
        (config.firstLevel ? this.children('img') : this.find('img')).each(function () {
            var naturalWidth  = this.naturalWidth || $(this).css('width', 'auto').width(),
                naturalHeight = this.naturalHeight || $(this).css('height', 'auto').height();
            if (naturalWidth >= naturalHeight) {
                $(this).css('height', '100%').css('width', null);
            } else {
                $(this).css('width', '100%').css('height', null);
            }
        });

        return this;
    };

}(jQuery));
<commit_msg>Apply overflow on parent<commit_after>/**
 * znCrop jQuery plugin
 *
 * @author  Zion Ng <zion@intzone.com>
 * @link    https://github.com/zionsg/zn-jquery/tree/master/znCrop
 * @version 1.0.0, 2013-06-25
 */

(function ($) {

    /**
     * Resize and crop <img> children to fill their parent containers
     *
     * @param   bool firstLevel Default = true. Restrict to 1st level <img> only.
     * @return  this
     */
    $.fn.znCrop = function (options) {
        // Merge default options with user options
        var config = $.extend({
            firstLevel: true
        }, options);

        (config.firstLevel ? this.children('img') : this.find('img')).each(function () {
            // IE8 and lower do not support naturalWidth and naturalHeight
            var naturalWidth  = this.naturalWidth || $(this).css('width', 'auto').width(),
                naturalHeight = this.naturalHeight || $(this).css('height', 'auto').height();

            $(this).parent().css('overflow', 'hidden');
            if (naturalWidth >= naturalHeight) {
                $(this).css('height', '100%').css('width', null);
            } else {
                $(this).css('width', '100%').css('height', null);
            }
        });

        return this;
    };

}(jQuery));
<|endoftext|>


<commit_before>(function( $ ){
	var multiSelectId=-1;
	$.fn.multiSelect=function(options){
		multiSelectId++;
		var settings = {
			'createCallback':false,
			'createText':false,
			'title':this.attr('title'),
			'checked':[],
			'oncheck':false,
			'onuncheck':false,
			'minWidth': 'default;',
		};
		$.extend(settings,options);
		var button=$('
'+settings.title+'▾
');
		var span=$('');
		span.append(button);
		button.data('id',multiSelectId);
		button.selectedItems=[];
		this.hide();
		this.before(span);
		if(settings.minWidth=='default'){
			settings.minWidth=button.width();
		}
		button.css('min-width',settings.minWidth);
		settings.minOuterWidth=button.outerWidth()-2;
		button.data('settings',settings);
		if(settings.checked.length>0){
			button.children('span').first().text(settings.checked.join(', '));
		}

		button.click(function(event){
			var button=$(this);
			if(button.parent().children('ul').length>0){
				button.parent().children('ul').slideUp(400,function(){
					button.parent().children('ul').remove();
					button.removeClass('active');
				});
				return;
			}
			var lists=$('ul.multiselectoptions');
			lists.slideUp(400,function(){
				lists.remove();
				$('div.multiselect').removeClass('active');
				button.addClass('active');
			});
			button.addClass('active');
			event.stopPropagation();
			var options=$(this).parent().next().children().map(function(){return $(this).val();});
			var list=$('
').hide().appendTo($(this).parent());
			function createItem(item,checked){
				var id='ms'+multiSelectId+'-option-'+item;
				var input=$('<input id="'+id+'" type="checkbox"/>');
				var label=$(''+item+'');
				if(settings.checked.indexOf(item)!=-1 || checked){
					input.attr('checked',true);
				}
				if(checked){
					settings.checked.push(item);
				}
				input.change(function(){
					var groupname=$(this).next().text();
					if($(this).is(':checked')){
						settings.checked.push(groupname);
						if(settings.oncheck){
							if(settings.oncheck(groupname)===false){
								$(this).attr('checked', false);
								return;
							}
						}
					}else{
						var index=settings.checked.indexOf(groupname);
						settings.checked.splice(index,1);
						if(settings.onuncheck){
							if(settings.onuncheck(groupname)===false){
								$(this).attr('checked',true);
								return;
							}
						}
					}
					var oldWidth=button.width();
					if(settings.checked.length>0){
						button.children('span').first().text(settings.checked.join(', '));
					}else{
						button.children('span').first().text(settings.title);
					}
					var newOuterWidth=Math.max((button.outerWidth()-2),settings.minOuterWidth)+'px';
					var newWidth=Math.max(button.width(),settings.minWidth);
					var pos=button.position();
					button.css('height',button.height());
					button.css('white-space','nowrap');
					button.css('width',oldWidth);
					button.animate({'width':newWidth},undefined,undefined,function(){
						button.css('width','');
					});
					list.animate({'width':newOuterWidth,'left':pos.left+3});
				});
				var li=$('

');
				li.append(input).append(label);
				return li;
			}
			$.each(options,function(index,item){
				list.append(createItem(item));
			});
			button.parent().data('preventHide',false);
			if(settings.createText){
				var li=$('
+ '+settings.createText+'
');
				li.click(function(event){
					li.empty();
					var input=$('<input class="new">');
					li.append(input);
					input.focus();
					input.css('width',button.width());
					button.parent().data('preventHide',true);
					input.keypress(function(event) {
						if(event.keyCode == 13) {
							event.preventDefault();
							event.stopPropagation();
							var li=$(this).parent();
							$(this).remove();
							li.text('+ '+settings.createText);
							li.before(createItem($(this).val()));
							li.prev().children('input').trigger('click');
							button.parent().data('preventHide',false);
							var select=button.parent().next();
							select.append($('<option value="'+$(this).val()+'">'+$(this).val()+'</option>'));
							if(settings.createCallback){
								settings.createCallback();
							}
						}
					});
					input.blur(function(){
						event.preventDefault();
						event.stopPropagation();
						$(this).remove();
						li.text('+ '+settings.createText);
						setTimeout(function(){
							button.parent().data('preventHide',false);
						},100);
					});
				});
				list.append(li);
			}
			var pos=button.position();
			list.css('top',pos.top+button.outerHeight()-5);
			list.css('left',pos.left+3);
			list.css('width',(button.outerWidth()-2)+'px');
			list.slideDown();
			list.click(function(event){
				event.stopPropagation();
			});
		});
		$(window).click(function(){
			if(!button.parent().data('preventHide')){
				button.parent().children('ul').slideUp(400,function(){
					button.parent().children('ul').remove();
					button.removeClass('active');
				});
			}
		});

		return span;
	};
})( jQuery );<commit_msg>fix inconsitent behaviour when trying to remove yourself from the admin group<commit_after>(function( $ ){
	var multiSelectId=-1;
	$.fn.multiSelect=function(options){
		multiSelectId++;
		var settings = {
			'createCallback':false,
			'createText':false,
			'title':this.attr('title'),
			'checked':[],
			'oncheck':false,
			'onuncheck':false,
			'minWidth': 'default;',
		};
		$.extend(settings,options);
		var button=$('
'+settings.title+'▾
');
		var span=$('');
		span.append(button);
		button.data('id',multiSelectId);
		button.selectedItems=[];
		this.hide();
		this.before(span);
		if(settings.minWidth=='default'){
			settings.minWidth=button.width();
		}
		button.css('min-width',settings.minWidth);
		settings.minOuterWidth=button.outerWidth()-2;
		button.data('settings',settings);
		if(settings.checked.length>0){
			button.children('span').first().text(settings.checked.join(', '));
		}

		button.click(function(event){
			var button=$(this);
			if(button.parent().children('ul').length>0){
				button.parent().children('ul').slideUp(400,function(){
					button.parent().children('ul').remove();
					button.removeClass('active');
				});
				return;
			}
			var lists=$('ul.multiselectoptions');
			lists.slideUp(400,function(){
				lists.remove();
				$('div.multiselect').removeClass('active');
				button.addClass('active');
			});
			button.addClass('active');
			event.stopPropagation();
			var options=$(this).parent().next().children().map(function(){return $(this).val();});
			var list=$('
').hide().appendTo($(this).parent());
			function createItem(item,checked){
				var id='ms'+multiSelectId+'-option-'+item;
				var input=$('<input id="'+id+'" type="checkbox"/>');
				var label=$(''+item+'');
				if(settings.checked.indexOf(item)!=-1 || checked){
					input.attr('checked',true);
				}
				if(checked){
					settings.checked.push(item);
				}
				input.change(function(){
					var groupname=$(this).next().text();
					if($(this).is(':checked')){
						if(settings.oncheck){
							if(settings.oncheck(groupname)===false){
								$(this).attr('checked', false);
								return;
							}
						}
						settings.checked.push(groupname);
					}else{
						var index=settings.checked.indexOf(groupname);
						if(settings.onuncheck){
							if(settings.onuncheck(groupname)===false){
								$(this).attr('checked',true);
								return;
							}
						}
						settings.checked.splice(index,1);
					}
					var oldWidth=button.width();
					if(settings.checked.length>0){
						button.children('span').first().text(settings.checked.join(', '));
					}else{
						button.children('span').first().text(settings.title);
					}
					var newOuterWidth=Math.max((button.outerWidth()-2),settings.minOuterWidth)+'px';
					var newWidth=Math.max(button.width(),settings.minWidth);
					var pos=button.position();
					button.css('height',button.height());
					button.css('white-space','nowrap');
					button.css('width',oldWidth);
					button.animate({'width':newWidth},undefined,undefined,function(){
						button.css('width','');
					});
					list.animate({'width':newOuterWidth,'left':pos.left+3});
				});
				var li=$('

');
				li.append(input).append(label);
				return li;
			}
			$.each(options,function(index,item){
				list.append(createItem(item));
			});
			button.parent().data('preventHide',false);
			if(settings.createText){
				var li=$('
+ '+settings.createText+'
');
				li.click(function(event){
					li.empty();
					var input=$('<input class="new">');
					li.append(input);
					input.focus();
					input.css('width',button.width());
					button.parent().data('preventHide',true);
					input.keypress(function(event) {
						if(event.keyCode == 13) {
							event.preventDefault();
							event.stopPropagation();
							var li=$(this).parent();
							$(this).remove();
							li.text('+ '+settings.createText);
							li.before(createItem($(this).val()));
							li.prev().children('input').trigger('click');
							button.parent().data('preventHide',false);
							var select=button.parent().next();
							select.append($('<option value="'+$(this).val()+'">'+$(this).val()+'</option>'));
							if(settings.createCallback){
								settings.createCallback();
							}
						}
					});
					input.blur(function(){
						event.preventDefault();
						event.stopPropagation();
						$(this).remove();
						li.text('+ '+settings.createText);
						setTimeout(function(){
							button.parent().data('preventHide',false);
						},100);
					});
				});
				list.append(li);
			}
			var pos=button.position();
			list.css('top',pos.top+button.outerHeight()-5);
			list.css('left',pos.left+3);
			list.css('width',(button.outerWidth()-2)+'px');
			list.slideDown();
			list.click(function(event){
				event.stopPropagation();
			});
		});
		$(window).click(function(){
			if(!button.parent().data('preventHide')){
				button.parent().children('ul').slideUp(400,function(){
					button.parent().children('ul').remove();
					button.removeClass('active');
				});
			}
		});

		return span;
	};
})( jQuery );<|endoftext|>


<commit_before>const root = window.root;

console.assert(typeof root.app.config === 'object', 'root.app.config is not an object');

const settings = {
    version: root.app.config.version,
    webroot: root.app.config.webroot,
    name: 'cnc',
    log: {
        level: 'warn', // trace, debug, info, warn, error
        logger: 'console', // console
        prefix: ''
    },
    i18next: {
        lowerCaseLng: true,

        // logs out more info (console)
        debug: false,

        // language to lookup key if not found on set language
        fallbackLng: 'en',

        // string or array of namespaces
        ns: [
            'locale', // locale: language, timezone, ...
            'resource' // default
        ],
        // default namespace used if not passed to translation function
        defaultNS: 'resource',

        whitelist: [
            'en', // default language
            'de',
            'es',
            'fr',
            'it',
            'ja',
            'zh-cn',
            'zh-tw'
        ],

        // array of languages to preload
        preload: [],

        // language codes to lookup, given set language is 'en-US':
        // 'all' --> ['en-US', 'en', 'dev']
        // 'currentOnly' --> 'en-US'
        // 'languageOnly' --> 'en'
        load: 'currentOnly',

        // char to separate keys
        keySeparator: '.',

        // char to split namespace from key
        nsSeparator: ':',

        interpolation: {
            prefix: '{{',
            suffix: '}}'
        },

        // options for language detection
        // https://github.com/i18next/i18next-browser-languageDetector
        detection: {
            // order and from where user language should be detected
            order: ['querystring', 'cookie', 'localStorage'],

            // keys or params to lookup language from
            lookupQuerystring: 'lang',
            lookupCookie: 'lang',
            lookupLocalStorage: 'lang',

            // cache user language on
            caches: ['localStorage', 'cookie']
        },
        // options for backend
        // https://github.com/i18next/i18next-xhr-backend
        backend: {
            // path where resources get loaded from
            loadPath: root.app.config.webroot + 'i18n/{{lng}}/{{ns}}.json',

            // path to post missing resources
            addPath: 'api/i18n/sendMissing/{{lng}}/{{ns}}',

            // your backend server supports multiloading
            // /locales/resources.json?lng=de+en&ns=ns1+ns2
            allowMultiLoading: false,

            // allow cross domain requests
            crossDomain: false
        }
    }
};

export default settings;
<commit_msg>Transform to hash key for url that ends with 'resource.json'<commit_after>import endsWith from 'lodash/endsWith';
import mapKeys from 'lodash/mapKeys';
import sha1 from 'sha1';

const root = window.root;

console.assert(typeof root.app.config === 'object', 'root.app.config is not an object');

const settings = {
    version: root.app.config.version,
    webroot: root.app.config.webroot,
    name: 'cnc',
    log: {
        level: 'warn', // trace, debug, info, warn, error
        logger: 'console', // console
        prefix: ''
    },
    i18next: {
        lowerCaseLng: true,

        // logs out more info (console)
        debug: false,

        // language to lookup key if not found on set language
        fallbackLng: 'en',

        // string or array of namespaces
        ns: [
            'locale', // locale: language, timezone, ...
            'resource' // default
        ],
        // default namespace used if not passed to translation function
        defaultNS: 'resource',

        whitelist: [
            'en', // default language
            'de',
            'es',
            'fr',
            'it',
            'ja',
            'zh-cn',
            'zh-tw'
        ],

        // array of languages to preload
        preload: [],

        // language codes to lookup, given set language is 'en-US':
        // 'all' --> ['en-US', 'en', 'dev']
        // 'currentOnly' --> 'en-US'
        // 'languageOnly' --> 'en'
        load: 'currentOnly',

        // char to separate keys
        keySeparator: '.',

        // char to split namespace from key
        nsSeparator: ':',

        interpolation: {
            prefix: '{{',
            suffix: '}}'
        },

        // options for language detection
        // https://github.com/i18next/i18next-browser-languageDetector
        detection: {
            // order and from where user language should be detected
            order: ['querystring', 'cookie', 'localStorage'],

            // keys or params to lookup language from
            lookupQuerystring: 'lang',
            lookupCookie: 'lang',
            lookupLocalStorage: 'lang',

            // cache user language on
            caches: ['localStorage', 'cookie']
        },
        // options for backend
        // https://github.com/i18next/i18next-xhr-backend
        backend: {
            // path where resources get loaded from
            loadPath: root.app.config.webroot + 'i18n/{{lng}}/{{ns}}.json',

            // path to post missing resources
            addPath: 'api/i18n/sendMissing/{{lng}}/{{ns}}',

            // your backend server supports multiloading
            // /locales/resources.json?lng=de+en&ns=ns1+ns2
            allowMultiLoading: false,

            parse: function(data, url) {
                if (endsWith(url, 'resource.json')) {
                    data = mapKeys(data, (value, key) => {
                        return sha1(key);
                    });
                }

                return data;
            },

            // allow cross domain requests
            crossDomain: false
        }
    }
};

export default settings;
<|endoftext|>


<commit_before>angular.module('admin.troupe.filters', ['filters.setting']);

angular.module('admin.troupe.controllers', ['controllers.http']);

angular.module('directive.troupes', []).
directive('listTroupes', function() {
return {
  restrict: 'E',
  scope: {
    csrf: '='
  },
  controller: ['$scope', 'Troupes', function($scope, Troupes) {
	 $scope.troupesSource = Troupes;
  }],
  link: function(scope, iElement, iAttrs, ctrl) {
      scope.troupes = scope.troupesSource.query();
  },
  templateUrl: '/js/admin/troupes.html'
};
});

angular.module('services.troupes', ['ngResource']).
controller('MyController', ['$scope','Troupes', function ($scope, Troupes) {
	   $scope.callNotify = function(msg) {
		   var troupes = Troupes.query();
		   console.log(troupes);
	   };
	 }]).
factory('Troupes', ['$resource', function($resource){
	return $resource('/admin/troupes/:troupeId', {}, {
		query: {method:'GET', isArray:true}
	});
}]);

angular.module('admin.troupe.directives', ['directive.troupes']);

angular.module('admin.troupe.services', ['services.troupes']);

angular.module('admin.troupe', ['admin.troupe.filters', 'admin.troupe.controllers', 'admin.troupe.directives', 'admin.troupe.services']);<commit_msg>Notify orders directive to refresh via event broadcasting.<commit_after>angular.module('admin.troupe.filters', ['filters.setting']);

angular.module('admin.troupe.controllers', ['controllers.http']);

angular.module('directive.troupes', []).
directive('listTroupes', function() {
return {
  restrict: 'E',
  scope: {
    csrf: '='
  },
  controller: ['$scope', 'Troupes', function($scope, Troupes) {
	 $scope.troupeSource = Troupes;
  }],
  link: function(scope, iElement, iAttrs) {
	  scope.troupes = scope.troupeSource.query();
	  scope.$on('troupesUpdated', function(event) {
		  console.log("directive heard troupes updated " + event);
		  scope.troupes = scope.troupeSource.query();
	  });
  },
  templateUrl: '/js/admin/troupes.html'
};
});

angular.module('services.troupes', ['ngResource']).
controller('MyController', ['$rootScope','Troupes', function ($rootScope, Troupes) {
			$rootScope.$on('troupesUpdated', function(event) {console.log("controller heard troupes updated " + event)});
			$rootScope.callNotify = function(msg) {
	   		   $rootScope.$broadcast('troupesUpdated');
	   		   console.log("notify troupes");
	   	   };
	 }]).
factory('Troupes', ['$resource', function($resource){
	return $resource('/admin/troupes/:troupeId', {}, {
		query: {method:'GET', isArray:true}
	});
}]);

angular.module('admin.troupe.directives', ['directive.troupes']);

angular.module('admin.troupe.services', ['services.troupes']);

angular.module('admin.troupe', ['admin.troupe.filters', 'admin.troupe.controllers', 'admin.troupe.directives', 'admin.troupe.services']);<|endoftext|>


<commit_before>var Promise = require('bluebird');
var webrtcsupport = require('webrtcsupport');
var Helpers = require('../helpers');
var Plugin = require('../plugin');
var MediaDevicesShim = require('./media-devices-shim');

/**
 * @inheritDoc
 *
 * @constructor
 * @extends Plugin
 */
function MediaPlugin(session, name, id) {
  if (!webrtcsupport.support) {
    throw new Error('WebRTC is not supported');
  }
  MediaPlugin.super_.apply(this, arguments);

  this._pcListeners = {};
}

Helpers.inherits(MediaPlugin, Plugin);

/**
 * @see https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/RTCPeerConnection#RTCConfiguration_dictionary
 * @typedef {Object} RTCConfiguration
 */

/**
 * @param {RTCConfiguration} [options]
 * @returns {RTCPeerConnection}
 */
MediaPlugin.prototype.createPeerConnection = function(options) {
  options = Helpers.extend(options || {}, this._session._connection._options.pc);

  var config = {
    iceServers: [{url: 'stun:stun.l.google.com:19302'}]
  };
  var constraints = {
    'optional': [{'DtlsSrtpKeyAgreement': true}]
  };
  if (options.config) {
    Helpers.extend(config, options.config);
  }
  if (options.constraints) {
    Helpers.extend(constraints, options.constraints);
  }

  this._pc = new webrtcsupport.PeerConnection(config, constraints);
  this._addPcEventListeners();
  return this._pc;
};

/**
 * @param {MediaStream} stream
 */
MediaPlugin.prototype.addStream = function(stream) {
  this._pc.addStream(stream);
};

/**
 * @param {MediaStreamConstraints} constraints
 * @returns {Promise}
 * @fulfilled {MediaStream} stream
 */
MediaPlugin.prototype.getLocalMedia = function(constraints) {
  this.emit('consent-dialog:start');
  var self = this;
  var promise = MediaDevicesShim.getUserMedia(constraints);
  return promise
    .then(function(stream) {
      self.emit('consent-dialog:stop', {stream: stream});
      return stream;
    })
    .catch(function(error) {
      self.emit('consent-dialog:stop', {error: error});
      throw error;
    })
    .finally(function() {
      if (promise.isCancelled()) {
        self.emit('consent-dialog:stop');
      }
    });
};

/**
 * @see https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/createOffer#RTCOfferOptions_dictionary
 * @typedef {Object} RTCOfferOptions
 */

/**
 * @param {RTCOfferOptions} [options]
 * @returns {Promise}
 * @fulfilled {@link _createSDP}
 */
MediaPlugin.prototype.createOffer = function(options) {
  return this._createSDP('createOffer', options);
};

/**
 * @see https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/createAnswer#RTCAnswerOptions_dictionary
 * @typedef {Object} RTCAnswerOptions
 */

/**
 * @param {RTCSessionDescription} jsep
 * @param {RTCAnswerOptions} [options]
 * @returns {Promise}
 * @fulfilled {@link _createSDP}
 */
MediaPlugin.prototype.createAnswer = function(jsep, options) {
  var self = this;
  return Promise.try(function() {
    return self.setRemoteSDP(jsep);
  }).then(function() {
    return self._createSDP('createAnswer', options);
  });
};

/**
 * @param {RTCSessionDescription} jsep
 * @returns {Promise}
 */
MediaPlugin.prototype.setRemoteSDP = function(jsep) {
  return this._pc.setRemoteDescription(new webrtcsupport.SessionDescription(jsep));
};

/**
 * @param {string} party
 * @param {RTCAnswerOptions|RTCOfferOptions} [options]
 * @returns {Promise}
 * @fulfilled {RTCSessionDescription} sdp
 */
MediaPlugin.prototype._createSDP = function(party, options) {
  if (!this._pc) {
    throw new Error('Create PeerConnection before creating SDP for it');
  }
  if (['createOffer', 'createAnswer'].indexOf(party) < 0) {
    throw new Error('Unknown party in _createSDP');
  }

  options = options || {};
  var self = this;
  return this._pc[party](options)
    .then(function(description) {
      return self._pc.setLocalDescription(description);
    })
    .then(function() {
      return self._pc.localDescription;
    });
};

MediaPlugin.prototype.processIncomeMessage = function(message) {
  var self = this;
  return Promise.try(function() {
      return MediaPlugin.super_.prototype.processIncomeMessage.call(self, message);
    })
    .then(function(result) {
      if ('trickle' == message['janus']) {
        self._onTrickle(message);
      }
      return result;
    });
};

/**
 * @param {Object} incomeMessage
 */
MediaPlugin.prototype._onTrickle = function(incomeMessage) {
  var candidate = new webrtcsupport.IceCandidate(incomeMessage['candidate']);
  this._pc.addIceCandidate(candidate).catch(function(error) {
    this.emit('pc:error', error);
  }.bind(this));
};

MediaPlugin.prototype.closePeerConnection = function() {
  Object.keys(this._pcListeners)
    .forEach(function(event) {
      this._removePcEventListener(event);
    }.bind(this));
  this._pc.close();
  this._pc = null;
  this.emit('pc:close');
};

MediaPlugin.prototype._addPcEventListeners = function() {
  var self = this;

  this._addPcEventListener('addstream', function(event) {
    self.emit('pc:addstream', event);
  });
  this._addPcEventListener('track', function(event) {
    self.emit('pc:track', event);
  });

  this._addPcEventListener('icecandidate', function(event) {
    if (event.candidate) {
      self.send({janus: 'trickle', candidate: event.candidate});
    } else {
      self.send({janus: 'trickle', candidate: {completed: true}});
      self._removePcEventListener('icecandidate');
    }
  });

  this._addPcEventListener('signalingstatechange', function() {
    if ('closed' == self._pc.signalingState) {
      self.closePeerConnection();
    }
  });

  this._addPcEventListener('iceconnectionstatechange', function() {
    switch (self._pc.iceConnectionState) {
      case 'closed':
      case 'failed':
        self.closePeerConnection();
        break;
    }
  });
};

MediaPlugin.prototype._addPcEventListener = function(event, listener) {
  this._pcListeners[event] = listener;
  this._pc.addEventListener(event, listener);
};

MediaPlugin.prototype._removePcEventListener = function(event) {
  this._pc.removeEventListener(event, this._pcListeners[event]);
  delete this._pcListeners[event];
};

module.exports = MediaPlugin;
<commit_msg>Fix MediaPlugin.detach<commit_after>var Promise = require('bluebird');
var webrtcsupport = require('webrtcsupport');
var Helpers = require('../helpers');
var Plugin = require('../plugin');
var MediaDevicesShim = require('./media-devices-shim');

/**
 * @inheritDoc
 *
 * @constructor
 * @extends Plugin
 */
function MediaPlugin(session, name, id) {
  if (!webrtcsupport.support) {
    throw new Error('WebRTC is not supported');
  }
  MediaPlugin.super_.apply(this, arguments);

  this._pcListeners = {};
}

Helpers.inherits(MediaPlugin, Plugin);

/**
 * @see https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/RTCPeerConnection#RTCConfiguration_dictionary
 * @typedef {Object} RTCConfiguration
 */

/**
 * @param {RTCConfiguration} [options]
 * @returns {RTCPeerConnection}
 */
MediaPlugin.prototype.createPeerConnection = function(options) {
  options = Helpers.extend(options || {}, this._session._connection._options.pc);

  var config = {
    iceServers: [{url: 'stun:stun.l.google.com:19302'}]
  };
  var constraints = {
    'optional': [{'DtlsSrtpKeyAgreement': true}]
  };
  if (options.config) {
    Helpers.extend(config, options.config);
  }
  if (options.constraints) {
    Helpers.extend(constraints, options.constraints);
  }

  this._pc = new webrtcsupport.PeerConnection(config, constraints);
  this._addPcEventListeners();
  return this._pc;
};

/**
 * @param {MediaStream} stream
 */
MediaPlugin.prototype.addStream = function(stream) {
  this._pc.addStream(stream);
};

/**
 * @param {MediaStreamConstraints} constraints
 * @returns {Promise}
 * @fulfilled {MediaStream} stream
 */
MediaPlugin.prototype.getLocalMedia = function(constraints) {
  this.emit('consent-dialog:start');
  var self = this;
  var promise = MediaDevicesShim.getUserMedia(constraints);
  return promise
    .then(function(stream) {
      self.emit('consent-dialog:stop', {stream: stream});
      return stream;
    })
    .catch(function(error) {
      self.emit('consent-dialog:stop', {error: error});
      throw error;
    })
    .finally(function() {
      if (promise.isCancelled()) {
        self.emit('consent-dialog:stop');
      }
    });
};

/**
 * @see https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/createOffer#RTCOfferOptions_dictionary
 * @typedef {Object} RTCOfferOptions
 */

/**
 * @param {RTCOfferOptions} [options]
 * @returns {Promise}
 * @fulfilled {@link _createSDP}
 */
MediaPlugin.prototype.createOffer = function(options) {
  return this._createSDP('createOffer', options);
};

/**
 * @see https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/createAnswer#RTCAnswerOptions_dictionary
 * @typedef {Object} RTCAnswerOptions
 */

/**
 * @param {RTCSessionDescription} jsep
 * @param {RTCAnswerOptions} [options]
 * @returns {Promise}
 * @fulfilled {@link _createSDP}
 */
MediaPlugin.prototype.createAnswer = function(jsep, options) {
  var self = this;
  return Promise.try(function() {
    return self.setRemoteSDP(jsep);
  }).then(function() {
    return self._createSDP('createAnswer', options);
  });
};

/**
 * @param {RTCSessionDescription} jsep
 * @returns {Promise}
 */
MediaPlugin.prototype.setRemoteSDP = function(jsep) {
  return this._pc.setRemoteDescription(new webrtcsupport.SessionDescription(jsep));
};

/**
 * @param {string} party
 * @param {RTCAnswerOptions|RTCOfferOptions} [options]
 * @returns {Promise}
 * @fulfilled {RTCSessionDescription} sdp
 */
MediaPlugin.prototype._createSDP = function(party, options) {
  if (!this._pc) {
    throw new Error('Create PeerConnection before creating SDP for it');
  }
  if (['createOffer', 'createAnswer'].indexOf(party) < 0) {
    throw new Error('Unknown party in _createSDP');
  }

  options = options || {};
  var self = this;
  return this._pc[party](options)
    .then(function(description) {
      return self._pc.setLocalDescription(description);
    })
    .then(function() {
      return self._pc.localDescription;
    });
};

MediaPlugin.prototype.processIncomeMessage = function(message) {
  var self = this;
  return Promise.try(function() {
      return MediaPlugin.super_.prototype.processIncomeMessage.call(self, message);
    })
    .then(function(result) {
      if ('trickle' == message['janus']) {
        self._onTrickle(message);
      }
      return result;
    });
};

/**
 * @param {Object} incomeMessage
 */
MediaPlugin.prototype._onTrickle = function(incomeMessage) {
  var candidate = new webrtcsupport.IceCandidate(incomeMessage['candidate']);
  this._pc.addIceCandidate(candidate).catch(function(error) {
    this.emit('pc:error', error);
  }.bind(this));
};

MediaPlugin.prototype.closePeerConnection = function() {
  if (this._pc) {
    Object.keys(this._pcListeners)
      .forEach(function(event) {
        this._removePcEventListener(event);
      }.bind(this));
    this._pc.close();
    this._pc = null;
    this.emit('pc:close');
  }
};

MediaPlugin.prototype._detach = function(message) {
  this.closePeerConnection();
  return MediaPlugin.super_.prototype._detach.apply(this, arguments);
};

MediaPlugin.prototype._addPcEventListeners = function() {
  var self = this;

  this._addPcEventListener('addstream', function(event) {
    self.emit('pc:addstream', event);
  });
  this._addPcEventListener('track', function(event) {
    self.emit('pc:track', event);
  });

  this._addPcEventListener('icecandidate', function(event) {
    if (event.candidate) {
      self.send({janus: 'trickle', candidate: event.candidate});
    } else {
      self.send({janus: 'trickle', candidate: {completed: true}});
      self._removePcEventListener('icecandidate');
    }
  });

  this._addPcEventListener('signalingstatechange', function() {
    if ('closed' == self._pc.signalingState) {
      self.closePeerConnection();
    }
  });

  this._addPcEventListener('iceconnectionstatechange', function() {
    switch (self._pc.iceConnectionState) {
      case 'closed':
      case 'failed':
        self.closePeerConnection();
        break;
    }
  });
};

MediaPlugin.prototype._addPcEventListener = function(event, listener) {
  this._pcListeners[event] = listener;
  this._pc.addEventListener(event, listener);
};

MediaPlugin.prototype._removePcEventListener = function(event) {
  this._pc.removeEventListener(event, this._pcListeners[event]);
  delete this._pcListeners[event];
};

module.exports = MediaPlugin;
<|endoftext|>