<commit_before>app.controller(
    'UploadController',
    [
        '$scope',
        '$controller',
        '$modal',
        'ModelService',
        function ($scope, ModelService) {
            // file reader stuff
            $scope.fileReaderSupported = window.FileReader != null;
            $scope.hasUploader = function (index) {
                return $scope.upload[index] != null;
            };
            $scope.abort = function (index) {
                $scope.upload[index].abort();
                $scope.upload[index] = null;
            };

            $scope.onFileSelect = function ($files) {
                $scope.file_name = null;
                $scope.csv_data = null;
                $scope.csv_errors = [];
                if ($files.length != 1) {
                    $scope.csv_errors.push('Please drag only one file at a time.');
                } else {
                    parseCSV($files[0])
                }
            };

            function parseCSV(file) {
                    $scope.file_name = file.name;

                    // parse CSV file
                    Papa.parse(file, {
                        header: true,
                        complete: function (results) {
                            validateData(results.data);
                            $scope.csv_data = results.data;
                            $scope.$apply();
                        }
                    });
            }

            function validateData(data) {
                var distinct_cohorts = [];
                var distinct_notebooks_tmp = [];  // array of strings (name)
                $scope.distinct_notebooks = [];  // array of objects
                var distinct_networks = [];  // array of strings (name)
                var distinct_participants_tmp = [];  // array of strings (name)
                $scope.distinct_participants = [];  // array of objects

                var distinct_analytes_tmp = [];  // array of strings (name)
                $scope.distinct_analytes = [];  // array of objects

                // analyte regex pattern to strip optional bead number
                var analyte_pattern = /^.*(?=\s\(\d+\)$)/;
                var analyte_result;

                var distinct_isotypes_tmp = [];  // array of strings (name)
                $scope.distinct_isotypes = [];  // array of objects

                var distinct_conjugates_tmp = [];  // array of strings (name)
                $scope.distinct_conjugates = [];  // array of objects

                // gather validation data for every data point
                data.forEach(function (d) {
                    // get distinct cohorts, must be only one and must match
                    // the current cohort
                    if (typeof(d.Cohort) == "undefined") {
                        $scope.csv_errors.push("Cohort field is required");
                    } else {
                        if (distinct_cohorts.indexOf(d.Cohort) == -1) {
                            distinct_cohorts.push(d.Cohort);
                        }
                    }

                    // get distinct notebooks. this field is required but there
                    // are no additional rules for this one
                    // but we will show the new ones to the user
                    if (typeof(d['Notebook Number']) == "undefined") {
                        $scope.csv_errors.push("Notebook field is required");
                    } else {
                        if (distinct_notebooks_tmp.indexOf(d['Notebook Number']) == -1) {
                            distinct_notebooks_tmp.push(d['Notebook Number']);
                        }
                    }

                    // get distinct networks (required)
                    if (typeof(d['Network']) == "undefined") {
                        $scope.csv_errors.push("Network field is required");
                    } else {
                        if (distinct_networks.indexOf(d['Network']) == -1) {
                            distinct_networks.push(d['Network']);
                        }
                    }

                    // get distinct participants (required)
                    if (typeof(d['Participant ID']) == "undefined") {
                        $scope.csv_errors.push("Participant ID field is required");
                    } else {
                        if (distinct_participants_tmp.indexOf(d['Participant ID']) == -1) {
                            distinct_participants_tmp.push(d['Participant ID']);

                            // determine if any new participants are present
                            var existing_participant_idx = null;

                            for (var i= 0, len = $scope.participants.length; i < len; i++) {
                                if ($scope.participants[i].code == d['Participant ID']) {
                                    existing_participant_idx = i;
                                    break;
                                }
                            }

                            if (existing_participant_idx != null) {
                                // existing participant:
                                // verify species matches this record.
                                // this is done only for this first encountered
                                // record, all others will be assumed to be the
                                // same, checking this would potentially be
                                // quite expensive
                                if (d['Species'] != $scope.participants[existing_participant_idx].species_name) {
                                    $scope.csv_errors.push("Species for participant " + d['Participant ID'] + " does not match the server");
                                }
                            }

                            $scope.distinct_participants.push(
                                {
                                    code: d['Participant ID'],
                                    new: existing_participant_idx == null
                                }
                            );
                        }
                    }

                    // get distinct analytes (required)
                    if (typeof(d['Analyte']) == "undefined") {
                        $scope.csv_errors.push("Analyte field is required");
                    } else {
                        // need to strip the bead number off analyte string
                        // if present
                        analyte_result = analyte_pattern.exec(d['Analyte']);
                        if (analyte_result == null) {
                            // doesn't contain a trailing bead number
                            analyte_result = d['Analyte'];
                        } else {
                            // contains a bead number, get everything but bead
                            analyte_result = analyte_result[0];
                        }

                        if (distinct_analytes_tmp.indexOf(analyte_result) == -1) {
                            distinct_analytes_tmp.push(analyte_result);

                            // determine if any new analytes are present
                            var existing_analyte_idx = null;

                            for (var i= 0, len = $scope.analytes.length; i < len; i++) {
                                if ($scope.analytes[i].name == analyte_result) {
                                    existing_analyte_idx = i;
                                    break;
                                }
                            }

                            if (existing_analyte_idx == null) {
                                // analyte doesn't exist, uh, that's a problem
                                $scope.csv_errors.push("Analyte \"" + analyte_result + "\" does not exist on the server");
                            }

                            $scope.distinct_analytes.push(
                                {
                                    name: analyte_result,
                                    new: existing_analyte_idx == null
                                }
                            );
                        }
                    }

                    // get distinct isotypes (required)
                    if (typeof(d['Isotype']) == "undefined") {
                        $scope.csv_errors.push("Isotype field is required");
                    } else {
                        if (distinct_isotypes_tmp.indexOf(d['Isotype']) == -1) {
                            distinct_isotypes_tmp.push(d['Isotype']);

                            // determine if any new isotypes are present
                            var existing_isotype_idx = null;

                            for (var i= 0, len = $scope.isotypes.length; i < len; i++) {
                                if ($scope.isotypes[i].name == d['Isotype']) {
                                    existing_isotype_idx = i;
                                    break;
                                }
                            }

                            if (existing_isotype_idx == null) {
                                // isotype doesn't exist, uh, that's a problem
                                $scope.csv_errors.push("Isotype \"" + d['Isotype'] + "\" does not exist on the server");
                            }

                            $scope.distinct_isotypes.push(
                                {
                                    name: d['Isotype'],
                                    new: existing_isotype_idx == null
                                }
                            );
                        }
                    }

                    // get distinct conjugates (required)
                    if (typeof(d['Conjugate']) == "undefined") {
                        $scope.csv_errors.push("Conjugate field is required");
                    } else {
                        if (distinct_conjugates_tmp.indexOf(d['Conjugate']) == -1) {
                            distinct_conjugates_tmp.push(d['Conjugate']);

                            // determine if any new conjugates are present
                            var existing_conjugate_idx = null;

                            for (var i= 0, len = $scope.conjugates.length; i < len; i++) {
                                if ($scope.conjugates[i].name == d['Conjugate']) {
                                    existing_conjugate_idx = i;
                                    break;
                                }
                            }

                            if (existing_conjugate_idx == null) {
                                // conjugate doesn't exist, uh, that's a problem
                                $scope.csv_errors.push("Conjugate \"" + d['Conjugate'] + "\" does not exist on the server");
                            }

                            $scope.distinct_conjugates.push(
                                {
                                    name: d['Conjugate'],
                                    new: existing_conjugate_idx == null
                                }
                            );
                        }
                    }

                    // validate dilution is present and a positive number
                    if (typeof(d['Dilution']) == "undefined") {
                        $scope.csv_errors.push("Dilution field is required");
                    } else if (isNaN(d['Dilution'])) {
                        $scope.csv_errors.push("Dilution value must be a positive number. Found: " + d['Dilution']);
                    } else if (parseFloat(d['Dilution']) <= 0) {
                        $scope.csv_errors.push("Dilution value must be a positive number. Found: " + d['Dilution']);
                    }
                });

                // Now check all our validation data

                // only one cohort should be present
                if (distinct_cohorts.length > 1) {
                    $scope.csv_errors.push("Multiple cohorts found in CSV file. Data can only be uploaded for one cohort at a time");
                }

                // cohort must match current cohort
                if (distinct_cohorts[0] != $scope.current_cohort.name) {
                    $scope.csv_errors.push("Cohort in CSV file doesn't match this cohort");
                }

                // only one network should be present and should match the
                // cohort's network
                if (distinct_networks.length > 1) {
                    $scope.csv_errors.push("Multiple networks found in CSV file. Data can only be uploaded for one network at a time");
                }

                // cohort must match current cohort
                if (distinct_networks[0] != $scope.current_cohort.network_name) {
                    $scope.csv_errors.push("Network in CSV file doesn't match this cohort's network");
                }

                // determine if any new notebooks are present
                distinct_notebooks_tmp.forEach(function (n) {
                    var new_nb = false;
                    if ($scope.notebooks.indexOf(n) == -1) {
                        new_nb = true;
                    }
                    $scope.distinct_notebooks.push(
                        {
                            name: n,
                            new: new_nb
                        }
                    );
                });
            }
        }
    ]
);<commit_msg>validate FI-Bkgd is a number<commit_after>app.controller(
    'UploadController',
    [
        '$scope',
        '$controller',
        '$modal',
        'ModelService',
        function ($scope, ModelService) {
            // file reader stuff
            $scope.fileReaderSupported = window.FileReader != null;
            $scope.hasUploader = function (index) {
                return $scope.upload[index] != null;
            };
            $scope.abort = function (index) {
                $scope.upload[index].abort();
                $scope.upload[index] = null;
            };

            $scope.onFileSelect = function ($files) {
                $scope.file_name = null;
                $scope.csv_data = null;
                $scope.csv_errors = [];
                if ($files.length != 1) {
                    $scope.csv_errors.push('Please drag only one file at a time.');
                } else {
                    parseCSV($files[0])
                }
            };

            function parseCSV(file) {
                    $scope.file_name = file.name;

                    // parse CSV file
                    Papa.parse(file, {
                        header: true,
                        complete: function (results) {
                            validateData(results.data);
                            $scope.csv_data = results.data;
                            $scope.$apply();
                        }
                    });
            }

            function validateData(data) {
                var distinct_cohorts = [];
                var distinct_notebooks_tmp = [];  // array of strings (name)
                $scope.distinct_notebooks = [];  // array of objects
                var distinct_networks = [];  // array of strings (name)
                var distinct_participants_tmp = [];  // array of strings (name)
                $scope.distinct_participants = [];  // array of objects

                var distinct_analytes_tmp = [];  // array of strings (name)
                $scope.distinct_analytes = [];  // array of objects

                // analyte regex pattern to strip optional bead number
                var analyte_pattern = /^.*(?=\s\(\d+\)$)/;
                var analyte_result;

                var distinct_isotypes_tmp = [];  // array of strings (name)
                $scope.distinct_isotypes = [];  // array of objects

                var distinct_conjugates_tmp = [];  // array of strings (name)
                $scope.distinct_conjugates = [];  // array of objects

                // gather validation data for every data point
                data.forEach(function (d) {
                    // get distinct cohorts, must be only one and must match
                    // the current cohort
                    if (typeof(d.Cohort) == "undefined") {
                        $scope.csv_errors.push("Cohort field is required");
                    } else {
                        if (distinct_cohorts.indexOf(d.Cohort) == -1) {
                            distinct_cohorts.push(d.Cohort);
                        }
                    }

                    // get distinct notebooks. this field is required but there
                    // are no additional rules for this one
                    // but we will show the new ones to the user
                    if (typeof(d['Notebook Number']) == "undefined") {
                        $scope.csv_errors.push("Notebook field is required");
                    } else {
                        if (distinct_notebooks_tmp.indexOf(d['Notebook Number']) == -1) {
                            distinct_notebooks_tmp.push(d['Notebook Number']);
                        }
                    }

                    // get distinct networks (required)
                    if (typeof(d['Network']) == "undefined") {
                        $scope.csv_errors.push("Network field is required");
                    } else {
                        if (distinct_networks.indexOf(d['Network']) == -1) {
                            distinct_networks.push(d['Network']);
                        }
                    }

                    // get distinct participants (required)
                    if (typeof(d['Participant ID']) == "undefined") {
                        $scope.csv_errors.push("Participant ID field is required");
                    } else {
                        if (distinct_participants_tmp.indexOf(d['Participant ID']) == -1) {
                            distinct_participants_tmp.push(d['Participant ID']);

                            // determine if any new participants are present
                            var existing_participant_idx = null;

                            for (var i= 0, len = $scope.participants.length; i < len; i++) {
                                if ($scope.participants[i].code == d['Participant ID']) {
                                    existing_participant_idx = i;
                                    break;
                                }
                            }

                            if (existing_participant_idx != null) {
                                // existing participant:
                                // verify species matches this record.
                                // this is done only for this first encountered
                                // record, all others will be assumed to be the
                                // same, checking this would potentially be
                                // quite expensive
                                if (d['Species'] != $scope.participants[existing_participant_idx].species_name) {
                                    $scope.csv_errors.push("Species for participant " + d['Participant ID'] + " does not match the server");
                                }
                            }

                            $scope.distinct_participants.push(
                                {
                                    code: d['Participant ID'],
                                    new: existing_participant_idx == null
                                }
                            );
                        }
                    }

                    // get distinct analytes (required)
                    if (typeof(d['Analyte']) == "undefined") {
                        $scope.csv_errors.push("Analyte field is required");
                    } else {
                        // need to strip the bead number off analyte string
                        // if present
                        analyte_result = analyte_pattern.exec(d['Analyte']);
                        if (analyte_result == null) {
                            // doesn't contain a trailing bead number
                            analyte_result = d['Analyte'];
                        } else {
                            // contains a bead number, get everything but bead
                            analyte_result = analyte_result[0];
                        }

                        if (distinct_analytes_tmp.indexOf(analyte_result) == -1) {
                            distinct_analytes_tmp.push(analyte_result);

                            // determine if any new analytes are present
                            var existing_analyte_idx = null;

                            for (var i= 0, len = $scope.analytes.length; i < len; i++) {
                                if ($scope.analytes[i].name == analyte_result) {
                                    existing_analyte_idx = i;
                                    break;
                                }
                            }

                            if (existing_analyte_idx == null) {
                                // analyte doesn't exist, uh, that's a problem
                                $scope.csv_errors.push("Analyte \"" + analyte_result + "\" does not exist on the server");
                            }

                            $scope.distinct_analytes.push(
                                {
                                    name: analyte_result,
                                    new: existing_analyte_idx == null
                                }
                            );
                        }
                    }

                    // get distinct isotypes (required)
                    if (typeof(d['Isotype']) == "undefined") {
                        $scope.csv_errors.push("Isotype field is required");
                    } else {
                        if (distinct_isotypes_tmp.indexOf(d['Isotype']) == -1) {
                            distinct_isotypes_tmp.push(d['Isotype']);

                            // determine if any new isotypes are present
                            var existing_isotype_idx = null;

                            for (var i= 0, len = $scope.isotypes.length; i < len; i++) {
                                if ($scope.isotypes[i].name == d['Isotype']) {
                                    existing_isotype_idx = i;
                                    break;
                                }
                            }

                            if (existing_isotype_idx == null) {
                                // isotype doesn't exist, uh, that's a problem
                                $scope.csv_errors.push("Isotype \"" + d['Isotype'] + "\" does not exist on the server");
                            }

                            $scope.distinct_isotypes.push(
                                {
                                    name: d['Isotype'],
                                    new: existing_isotype_idx == null
                                }
                            );
                        }
                    }

                    // get distinct conjugates (required)
                    if (typeof(d['Conjugate']) == "undefined") {
                        $scope.csv_errors.push("Conjugate field is required");
                    } else {
                        if (distinct_conjugates_tmp.indexOf(d['Conjugate']) == -1) {
                            distinct_conjugates_tmp.push(d['Conjugate']);

                            // determine if any new conjugates are present
                            var existing_conjugate_idx = null;

                            for (var i= 0, len = $scope.conjugates.length; i < len; i++) {
                                if ($scope.conjugates[i].name == d['Conjugate']) {
                                    existing_conjugate_idx = i;
                                    break;
                                }
                            }

                            if (existing_conjugate_idx == null) {
                                // conjugate doesn't exist, uh, that's a problem
                                $scope.csv_errors.push("Conjugate \"" + d['Conjugate'] + "\" does not exist on the server");
                            }

                            $scope.distinct_conjugates.push(
                                {
                                    name: d['Conjugate'],
                                    new: existing_conjugate_idx == null
                                }
                            );
                        }
                    }

                    // validate dilution is present and a positive number
                    if (typeof(d['Dilution']) == "undefined") {
                        $scope.csv_errors.push("Dilution field is required");
                    } else if (isNaN(d['Dilution'])) {
                        $scope.csv_errors.push("Dilution value must be a positive number. Found: " + d['Dilution']);
                    } else if (parseFloat(d['Dilution']) <= 0) {
                        $scope.csv_errors.push("Dilution value must be a positive number. Found: " + d['Dilution']);
                    }

                    // validate FI-Bkgd is present and a number
                    if (typeof(d['FI-Bkgd']) == "undefined") {
                        $scope.csv_errors.push("FI-Bkgd field is required");
                    } else if (isNaN(d['FI-Bkgd'])) {
                        $scope.csv_errors.push("FI-Bkgd value must be a number. Found: " + d['FI-Bkgd']);
                    }
                });

                // Now check all our validation data

                // only one cohort should be present
                if (distinct_cohorts.length > 1) {
                    $scope.csv_errors.push("Multiple cohorts found in CSV file. Data can only be uploaded for one cohort at a time");
                }

                // cohort must match current cohort
                if (distinct_cohorts[0] != $scope.current_cohort.name) {
                    $scope.csv_errors.push("Cohort in CSV file doesn't match this cohort");
                }

                // only one network should be present and should match the
                // cohort's network
                if (distinct_networks.length > 1) {
                    $scope.csv_errors.push("Multiple networks found in CSV file. Data can only be uploaded for one network at a time");
                }

                // cohort must match current cohort
                if (distinct_networks[0] != $scope.current_cohort.network_name) {
                    $scope.csv_errors.push("Network in CSV file doesn't match this cohort's network");
                }

                // determine if any new notebooks are present
                distinct_notebooks_tmp.forEach(function (n) {
                    var new_nb = false;
                    if ($scope.notebooks.indexOf(n) == -1) {
                        new_nb = true;
                    }
                    $scope.distinct_notebooks.push(
                        {
                            name: n,
                            new: new_nb
                        }
                    );
                });
            }
        }
    ]
);<|endoftext|>


<commit_before>/*
Copyright (c) 2015 Simon Cullen, http://github.com/cullens

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/
'use strict';

/**
 * @class Tasker
 * @mixes $thing.Base
 * @memberOf $thing
 */
$thing.Tasker = new ($thing.Base.inherit({

	doWake: function(container) {
    	var now = $thing.getMicroTime();

    	if (!container.nextWakeTime || now >= container.nextWakeTime) {

        	var selector = new $thing.Selector(
        			container,
            	    [['Behaviour', 'and', 'Waker']],
                	['container:0:0', '$thing'],
                	false
            	)
            	;

        	if (selector.length === 0) {
            	selector.release();
            	selector = undefined;
        	}
        	else {
            	selector.dispatch(
                	{   filters: $thing.Filter.ALL,
                    	method: 'action',
                    	args: []
                	},
                	function(cbNext) {
                    	cbNext();
                	},
                	function() {
                    	selector.release();
                    	selector = undefined;
                	}
            	);
        	}

        	container.nextWakeTime =
            	now + $thing.WAKE_MIN_PERIOD - (now % $thing.WAKE_MIN_PERIOD);
    	}

	},

	doAction: function(container) {
    	var self = this;

    	if (container.isActionTaskQueued) return;
    	container.isActionTaskQueued = true;

    	$thing.async.setImmediate(function() {
        	var selector = new $thing.Selector(
        			container,
            	    [['Behaviour', 'not', 'Waker']],
                	['container:0:0', '$thing'],
                	false
            	)
            	;

        	if (selector.length === 0) {
            	selector.release();
            	selector = undefined;
            	container.isActionTaskQueued = false;
        	}
        	else {
            	selector.dispatch(
                	{   filters: $thing.Filter.ALL,
                    	method: 'action',
                    	args: []
                	},
                	function(cbNext) {
                    	cbNext();
                	},
                	function() {
                    	selector.release();
                    	selector = undefined;
                    	container.isActionTaskQueued = false;
                    	self.doAction(container);
                	}
            	);
        	}

    	});

	},

	thread: function() {
		var container = $thing.getContainer($thing.getBacktrace());

		this.doWake(container);
		this.doAction(container);
	}

}))();<commit_msg>Fixed formatting<commit_after>/*
Copyright (c) 2015 Simon Cullen, http://github.com/cullens

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/
'use strict';

/**
 * @class Tasker
 * @mixes $thing.Base
 * @memberOf $thing
 */
$thing.Tasker = new ($thing.Base.inherit({

    doWake: function(container) {
        var now = $thing.getMicroTime();

        if (!container.nextWakeTime || now >= container.nextWakeTime) {

            var selector = new $thing.Selector(
                    container,
                    [['Behaviour', 'and', 'Waker']],
                    ['container:0:0', '$thing'],
                    false
                )
                ;

            if (selector.length === 0) {
                selector.release();
                selector = undefined;
            }
            else {
                selector.dispatch(
                    {   filters: $thing.Filter.ALL,
                        method: 'action',
                        args: []
                    },
                    function(cbNext) {
                        cbNext();
                    },
                    function() {
                        selector.release();
                        selector = undefined;
                    }
                );
            }

            container.nextWakeTime =
                now + $thing.WAKE_MIN_PERIOD - (now % $thing.WAKE_MIN_PERIOD);
        }

    },

    doAction: function(container) {
        var self = this;

        if (container.isActionTaskQueued) return;
        container.isActionTaskQueued = true;

        $thing.async.setImmediate(function() {
            var selector = new $thing.Selector(
                    container,
                    [['Behaviour', 'not', 'Waker']],
                    ['container:0:0', '$thing'],
                    false
                )
                ;

            if (selector.length === 0) {
                selector.release();
                selector = undefined;
                container.isActionTaskQueued = false;
            }
            else {
                selector.dispatch(
                    {   filters: $thing.Filter.ALL,
                        method: 'action',
                        args: []
                    },
                    function(cbNext) {
                        cbNext();
                    },
                    function() {
                        selector.release();
                        selector = undefined;
                        container.isActionTaskQueued = false;
                        self.doAction(container);
                    }
                );
            }

        });

    },

    thread: function() {
        var container = $thing.getContainer($thing.getBacktrace());

        this.doWake(container);
        this.doAction(container);
    }

}))();<|endoftext|>


<commit_before>$(document).ready(function() {
 var events = eventModule()
 events.dropDown()
 events.bindFadeCardAnnimation()
});

// Nav DropDown
(function() {

  var dropDown = function() {

  "use strict";

    var $menuContainer = $('.dropdown-container');
    var $eventTrigger = $('#dropdown-listener');

    function displayMenu() {
      $menuContainer.css('display', 'block');
    };

    function hideMenu() {
      $menuContainer.css('display', 'none');
    }

    function triggerDisplay() {
      $eventTrigger.mouseenter(displayMenu);
      $menuContainer.mouseleave(hideMenu);
    };

    triggerDisplay()

  };

  //  Play Screen Card Annimation On Hover

  var bindFadeCardAnnimation = function() {

    "use strict";

    var $triggerContainer = $(".start-container");
    var $cardContainer = $(".play-card-container")

    function cardsFadeIn() {
      $cardContainer.fadeIn("slow");
    };

    function cardsFadeOut() {
      $cardContainer.fadeOut("slow");
    }

    function triggerCardFade() {
      $triggerContainer.mouseenter(cardsFadeIn);
    };

    function triggerCardFadeOut() {
      $triggerContainer.mouseleave(cardsFadeOut);
    }

    $cardContainer.fadeOut("slow")
    triggerCardFadeOut()
    triggerCardFade()

  };

  this.eventModule = function() {
    return {
      dropDown: dropDown,
      bindFadeCardAnnimation: bindFadeCardAnnimation
    }
  }

})();

// OO

 // function Card() {
 //    this.name = undefined,
 //    this.value = undefined,
 //    this.img_url = undefined,
 //    this.id = undefined,
 // }

 // Card.prototype.loadAttr = function() {
 //   // Recieve JSON object and assign attributes to card object
 // };

 // function Game() {
 //  this.id = undefined,
 // }

  // sudo JS

  // needs

    // Objects
    // Cards - Store attributes in DATA HTML

    // Game
    // Deck?

    // routes/api

    // Hit - Dynamic card retrieval
    // Stay - Start dealer action phase

  // Nav Bar

  // Modular
  // bind events
  // event listeners on hover
  // toggle slide dropdown

<commit_msg>jQuery fix<commit_after>$(document).ready(function() {
 var events = eventModule()
 events.dropDown()
 events.bindFadeCardAnnimation()
});

// Nav DropDown
(function($) {

  var dropDown = function() {

  "use strict";

    var $menuContainer = $('.dropdown-container');
    var $eventTrigger = $('#dropdown-listener');

    function displayMenu() {
      $menuContainer.css('display', 'block');
    };

    function hideMenu() {
      $menuContainer.css('display', 'none');
    }

    function triggerDisplay() {
      $eventTrigger.mouseenter(displayMenu);
      $menuContainer.mouseleave(hideMenu);
    };

    triggerDisplay()

  };

  //  Play Screen Card Annimation On Hover

  var bindFadeCardAnnimation = function() {

    "use strict";

    var $triggerContainer = $(".start-container");
    var $cardContainer = $(".play-card-container")

    function cardsFadeIn() {
      $cardContainer.fadeIn("slow");
    };

    function cardsFadeOut() {
      $cardContainer.fadeOut("slow");
    }

    function triggerCardFade() {
      $triggerContainer.mouseenter(cardsFadeIn);
    };

    function triggerCardFadeOut() {
      $triggerContainer.mouseleave(cardsFadeOut);
    }

    $cardContainer.fadeOut("slow")
    triggerCardFadeOut()
    triggerCardFade()

  };

  this.eventModule = function() {
    return {
      dropDown: dropDown,
      bindFadeCardAnnimation: bindFadeCardAnnimation
    }
  }

})($);

// OO

 // function Card() {
 //    this.name = undefined,
 //    this.value = undefined,
 //    this.img_url = undefined,
 //    this.id = undefined,
 // }

 // Card.prototype.loadAttr = function() {
 //   // Recieve JSON object and assign attributes to card object
 // };

 // function Game() {
 //  this.id = undefined,
 // }

  // sudo JS

  // needs

    // Objects
    // Cards - Store attributes in DATA HTML

    // Game
    // Deck?

    // routes/api

    // Hit - Dynamic card retrieval
    // Stay - Start dealer action phase

  // Nav Bar

  // Modular
  // bind events
  // event listeners on hover
  // toggle slide dropdown

<|endoftext|>


<commit_before>'use strict';
/**
 * Created by Adrian on 03-Apr-16.
 * The Thorin Intent class is used to defined incoming events or actions.
 * Transports will then match intents based on their actions and
 * validate them.
 */
module.exports = function init(thorin) {
  const input = Symbol(),
    rawInput = Symbol(),
    data = Symbol(),
    client = Symbol(),
    error = Symbol(),
    authorization = Symbol(),
    onSend = Symbol(),
    rootData = Symbol(),
    rawResult = Symbol(),
    timeStart = Symbol(),
    timeEnd = Symbol(),
    events = Symbol(),
    eventsFired = Symbol(),
    resultHeaders = Symbol(),
    result = Symbol();

  const INTENT_EVENTS = {
    END: 'end'
  };

  class ThorinIntent {

    constructor(actionType, rawInputData, onIntentSend) {
      this.completed = false;
      // this.transport is set at the transport layer, the source transport
      this.proxied = false; // if the default onIntentSend callback was changed.
      this.action = actionType;
      this[rawInput] = rawInputData;
      this[rawResult] = false;  // raw results will not send an object, with {result:}, but the actual value of .result()
      this[events] = {};    // this is our mini event handler. with only .on('event', oneFunctionCall)
      this[eventsFired] = {}; // a hash of {eventName:true}
      this[timeStart] = Date.now();
      this[timeEnd] = null;
      this[data] = {};  // we can attach data to it.
      this[input] = {}; // input data
      this[result] = null;  // output data
      this[rootData] = null;  // pagination data
      this[error] = null;   // error info
      this[authorization] = null; // authorization data
      this[client] = {};  // incoming client data.
      this[onSend] = onIntentSend;
      this[resultHeaders] = null; // a hash of headers to send back
    }

    /* Sets the authorization information for this intent.
     * The authorization information is set at the transport level, depending
     * on the source of it.
     * As an example, HTTP transports may place the Authorization: "Bearer {token}" header value
     * as the authorization data.
     * */
    set authorization(val) {
      if (this[authorization] != null) {
        console.error('Thorin.Intent: authorization information already set for intent on action ' + this.action);
        return;
      }
      this[authorization] = val;
    }

    get authorization() {
      return this[authorization];
    }

    get rawInput() {
      return this[rawInput];
    }

    /*
     * An intent's send() function can be proxied, going through another callback
     * before actually calling the send() function. You can look at this like a
     * call that will be called before the send() function. This proxy function can alter
     * errors or results of the intent.
     * WARNING: When proxying an intent, you MUST call the send() of that intent, otherwise
     * it will not send the response to the client.
     * For example:
     *   intentObj.proxy(function(obj) {
     *     console.log("PROXY WITH", obj);
     *     this.send({something: "else"});
     *   });
     *
     *   /////
     *   intentObj.send({some: "object"})
     * */
    proxy(proxyFn) {
      if(this.proxied) {
        console.warn('Thorin.Intent: intent for action ' + this.action + ' is already proxied.');
        return this;
      }
      this.proxied = true;
      let oldSend = this[onSend];
      this[onSend] = function ProxySend() {
        this[onSend] = oldSend;
        try {
          proxyFn.apply(this, arguments);
        } catch(e) {
          console.error('Thorin.intent: proxy function on intent action ' + this.action + ' threw an error.');
          this.error(thorin.error(e));
          this.send();
        }
      }.bind(this);
      this.proxied = true;
      return this;
    }

    /*
     * When an intent is triggered by the dispatcher, this function gets called asynchronously,
     * in order to asynchronously initiate the intent.
     * A plugin or anybody can override this function to insert itself
     * into it, BEFORE it is actually run through its stack.
     * NOTE:
     *   when overriding it, the function MUST call the callback function with (err|null)
     * */
    runCreate(fn) {
      fn();
    }

    /*
     * This will set some specific headers to be sent to the transport layer.
     * */
    resultHeaders(name, _val) {
      if(typeof name === 'object' && name) {
        if(typeof this[resultHeaders] !== 'object' || this[resultHeaders] == null) this[resultHeaders] = {};
        Object.keys(name).forEach((key) => {
          this[resultHeaders][key] = name[key];
        });
        return this;
      }
      if (typeof name === 'undefined') return this[resultHeaders];
      if (typeof name === 'string' && typeof _val === 'undefined') {
        return this[resultHeaders][name] || null;
      }
      if (typeof name === 'string' && typeof _val !== 'undefined') {
        if(typeof this[resultHeaders] !== 'object' || !this[resultHeaders]) this[resultHeaders] = {};
        this[resultHeaders][name] = _val;
        return this;
      }
      return null;
    }

    /* Event handler ON: will call the function only once. */
    on(eventName, fn) {
      if (typeof fn !== 'function') {
        console.error('Thorin.intent: .on(eventName, fn), fn is not a function.');
        return this;
      }
      if (this[eventsFired][eventName]) {
        try {
          fn();
        } catch (e) {
          console.error('Thorin.Intent: triggered event ' + eventName + ' on callback function threw an exception.');
          console.error(e);
        }
        return this;
      }
      if (typeof this[events][eventName] === 'undefined') this[events][eventName] = [];
      this[events][eventName].push(fn);
      return this;
    }

    /*
     * Sets/gets specific client information.
     * */
    client(key, val) {
      if (typeof key === 'object' && key) {
        Object.keys(key).forEach((a) => {
          this.client(a, key[a]);
        });
        return this;
      }
      if (typeof key === 'undefined') return this[client];
      if (typeof key === 'string' && typeof val === 'undefined') return (typeof this[client][key] === 'undefined' ? null : this[client][key]);
      this[client][key] = val;
      return this;
    }

    /*
     * Get/Set additional data to it.
     * */
    data(name, _val) {
      if (typeof name !== 'string') return this[data];
      if (typeof name === 'string' && typeof _val === 'udnefined') return this[data][name] || null;
      this[data][name] = _val;
      return this;
    }

    /*
     * Getter/setter for input data.
     * */
    input(name, _val) {
      if (typeof name === 'undefined') return this[input];
      if (typeof name === 'string' && typeof _val === 'undefined') {
        return this[input][name] || null;
      }
      if (typeof name === 'string' && typeof _val !== 'undefined') {
        this[input][name] = _val;
        return this;
      }
      return null;
    }

    /* Checks if the intent is an error yet. */
    hasError() {
      return (this[error] != null);
    }

    /* Checks if we have any result */
    hasResult() {
      return (this[result] != null);
    }

    hasRawResult() {
      return (this[rawResult] === true);
    }

    /*
     * Sets the raw result of the intent. Raw results will send the result as is,
     * without wrapping it into an object.
     * */
    rawResult(val) {
      if(typeof val === 'undefined') return;
      this[rawResult] = true;
      this[result] = val;
      return this;
    }

    /*
     * Get/set result information
     * */
    result(name, val) {
      if(name instanceof Array) {
        this[result] = name;
        return this;
      }
      if (typeof name === 'object' && name) {
        if(typeof name.getDataValue === 'function') { // ignore objects that have toJSON, as the transport will take care of it.
          this[result] = name;
          return this;
        }
        Object.keys(name).forEach((key) => {
          this.result(key, name[key]);
        });
        return this;
      }
      if (typeof name === 'string' && !(this[result] instanceof Array)) {
        if (typeof val === 'undefined') {
          return (typeof this[result][name] === 'undefined' ? null : this[result][name]);
        }
        if (this[result] == null) this[result] = {};
        this[result][name] = val;
        return this;
      }
      if(typeof name === 'undefined') {
        return this[result];
      }
      return this;
    }

    /*
     * Sets pagination data or other information that will be used in the root object.. The pagination data will be included in the base response,
     * right next to id and result.
     * TODO: this should work with a thorin.Pagination
     * */
    rootData(data, val) {
      if (typeof data === 'object') {
        Object.keys(data).forEach((k) => {
          this.rootData(k, data[k]);
        });
        return this;
      }
      if (typeof data === 'string') {
        if (typeof val === 'undefined') {
          return (typeof this[rootData][data] === 'undefined' ? null : this[rootData][data]);
        }
        if (this[rootData] == null) this[rootData] = {};
        this[rootData][data] = val;
        return this;
      }
      return this;
    };

    /*
     * Marks the intent as error. We can set the error only once.
     * */
    error(err) {
      if (typeof err === 'undefined') return this[error];
      if (this[error]) return this;
      if (err instanceof Error && err.name.indexOf('Thorin') !== 0) {
        err = thorin.error(err);
      }
      this[error] = err;
      return this;
    }

    /*
     * Returns the number of ms it took for the intent to end.
     * */
    get took() {
      if (!this[timeEnd]) return 0;
      return this[timeEnd] - this[timeStart];
    }

    /*
     * Ends the current intent, responding with the result back to the transport layer.
     * */
    send(obj) {
      if(this.proxied) {
        this.proxied = false;
        this[onSend].apply(this, arguments);  // proxy the send.
        return;
      }
      if (this.completed) {
        console.error('Thorin.intent: already completed for action ' + this.action);
        return this;
      }
      if (!this[rawResult] && typeof obj === 'object' && obj != null) {
        if (obj instanceof Error && !this.hasError()) {
          this.error(obj);
        } else if (!this.hasResult()) {
          this.result(obj);
        }
      }
      this[timeEnd] = Date.now();
      this.completed = true;
      const intentResult = {
        "action": this.action
      };
      if (this.hasError()) {
        intentResult.error = this.error();
        triggerEvent.call(this, INTENT_EVENTS.END);
        if (typeof this[onSend] === 'function') {
          this[onSend](true, intentResult, this);
          this.destroy();
        } else {
          this.destroy();
          return intentResult;
        }
      } else {
        // IF we have a raw result, we just send it.
        if(this[rawResult] === true) {
          triggerEvent.call(this, INTENT_EVENTS.END);
          if (typeof this[onSend] === 'function') {
            this[onSend](false, this[result], this);
            this.destroy();
          } else {
            this.destroy();
            return this[result];
          }
          return;
        }

        // set any pagination data.
        if (this[rootData] != null) {
          Object.keys(this[rootData]).forEach((k) => {
            if(k === 'result' || k === "action") return;
            if (typeof intentResult[k] !== 'undefined') return;
            intentResult[k] = this[rootData][k];
          });
        }
        if (this.hasResult()) {
          intentResult.result = this.result();
        }
        triggerEvent.call(this, INTENT_EVENTS.END);
        if (typeof this[onSend] === 'function') {
          this[onSend](false, intentResult, this);
          this.destroy();
        } else {
          this.destroy();
          return intentResult;
        }
      }
    }

    /*
     * Intent destructor
     * */
    destroy() {
      this[data] = null;
      this[rawInput] = null;
      this[input] = null;
      this[result] = null;
      this[error] = null;
      this[authorization] = null;
      this[client] = null;
      this[rootData] = null;
      this[events] = {};
      this[eventsFired] = {};
      delete this[resultHeaders];
      delete this[onSend];
    }
  }
  ThorinIntent.EVENT = INTENT_EVENTS;

  /*
   * This is called by the intent to trigger an event
   * Event triggering is only for the intent to fire.
   * */
  function triggerEvent(eventName, _args) {
    if (typeof this[events][eventName] === 'undefined') return;
    for (let i = 0; i < this[events][eventName].length; i++) {
      try {
        this[events][eventName][i](_args);
      } catch (e) {
        console.error('Thorin.Intent: triggered event ' + eventName + ' on callback function threw an exception.');
        console.error(e);
      }
    }
    this[eventsFired][eventName] = true;
    delete this[events][eventName];
  }

  return ThorinIntent;
};<commit_msg>intent now has a _setAuthorization function and exposes the authorizationSource<commit_after>'use strict';
/**
 * Created by Adrian on 03-Apr-16.
 * The Thorin Intent class is used to defined incoming events or actions.
 * Transports will then match intents based on their actions and
 * validate them.
 */
module.exports = function init(thorin) {
  const input = Symbol(),
    rawInput = Symbol(),
    data = Symbol(),
    client = Symbol(),
    error = Symbol(),
    authorization = Symbol(),
    authorizationSource = Symbol(),
    onSend = Symbol(),
    rootData = Symbol(),
    rawResult = Symbol(),
    timeStart = Symbol(),
    timeEnd = Symbol(),
    events = Symbol(),
    eventsFired = Symbol(),
    resultHeaders = Symbol(),
    result = Symbol();

  const INTENT_EVENTS = {
    END: 'end'
  };

  class ThorinIntent {

    constructor(actionType, rawInputData, onIntentSend) {
      this.completed = false;
      // this.transport is set at the transport layer, the source transport
      this.proxied = false; // if the default onIntentSend callback was changed.
      this.action = actionType;
      this[rawInput] = rawInputData;
      this[rawResult] = false;  // raw results will not send an object, with {result:}, but the actual value of .result()
      this[events] = {};    // this is our mini event handler. with only .on('event', oneFunctionCall)
      this[eventsFired] = {}; // a hash of {eventName:true}
      this[timeStart] = Date.now();
      this[timeEnd] = null;
      this[data] = {};  // we can attach data to it.
      this[input] = {}; // input data
      this[result] = null;  // output data
      this[rootData] = null;  // pagination data
      this[error] = null;   // error info
      this[authorization] = null; // authorization data
      //this[authorizationSource] = null; // the authorization source. Where did it come from / what is it?
      this[client] = {};  // incoming client data.
      this[onSend] = onIntentSend;
      this[resultHeaders] = null; // a hash of headers to send back
    }

    /* Sets the authorization information for this intent.
     * The authorization information is set at the transport level, depending
     * on the source of it.
     * As an example, HTTP transports may place the Authorization: "Bearer {token}" header value
     * as the authorization data.
     * */
    _setAuthorization(authSource, authId) {
      if(typeof authSource !== 'string' || !authSource) {
        console.error('Thorin.Intent: _setAuthorization(source, id) must contain a valid authorization source');
        return this;
      }
      if(typeof authId === 'undefined') {
        console.error('Thorin.Intent: _setAuthorization(source, id) must have an authorization id.');
        return this;
      }
      this[authorization] = authId;
      this[authorizationSource] = authSource;
      return this;
    }

    get authorization() {
      return this[authorization];
    }
    set authorization(v) {
      console.error('Thorin.Intent: please use _setAuthorization(source, id) in stead of direct set.');
    }

    get authorizationSource() {
      return this[authorizationSource] || null;
    }

    get rawInput() {
      return this[rawInput];
    }

    /*
     * An intent's send() function can be proxied, going through another callback
     * before actually calling the send() function. You can look at this like a
     * call that will be called before the send() function. This proxy function can alter
     * errors or results of the intent.
     * WARNING: When proxying an intent, you MUST call the send() of that intent, otherwise
     * it will not send the response to the client.
     * For example:
     *   intentObj.proxy(function(obj) {
     *     console.log("PROXY WITH", obj);
     *     this.send({something: "else"});
     *   });
     *
     *   /////
     *   intentObj.send({some: "object"})
     * */
    proxy(proxyFn) {
      if(this.proxied) {
        console.warn('Thorin.Intent: intent for action ' + this.action + ' is already proxied.');
        return this;
      }
      this.proxied = true;
      let oldSend = this[onSend];
      this[onSend] = function ProxySend() {
        this[onSend] = oldSend;
        try {
          proxyFn.apply(this, arguments);
        } catch(e) {
          console.error('Thorin.intent: proxy function on intent action ' + this.action + ' threw an error.');
          this.error(thorin.error(e));
          this.send();
        }
      }.bind(this);
      this.proxied = true;
      return this;
    }

    /*
     * When an intent is triggered by the dispatcher, this function gets called asynchronously,
     * in order to asynchronously initiate the intent.
     * A plugin or anybody can override this function to insert itself
     * into it, BEFORE it is actually run through its stack.
     * NOTE:
     *   when overriding it, the function MUST call the callback function with (err|null)
     * */
    runCreate(fn) {
      fn();
    }

    /*
     * This will set some specific headers to be sent to the transport layer.
     * */
    resultHeaders(name, _val) {
      if(typeof name === 'object' && name) {
        if(typeof this[resultHeaders] !== 'object' || this[resultHeaders] == null) this[resultHeaders] = {};
        Object.keys(name).forEach((key) => {
          this[resultHeaders][key] = name[key];
        });
        return this;
      }
      if (typeof name === 'undefined') return this[resultHeaders];
      if (typeof name === 'string' && typeof _val === 'undefined') {
        return this[resultHeaders][name] || null;
      }
      if (typeof name === 'string' && typeof _val !== 'undefined') {
        if(typeof this[resultHeaders] !== 'object' || !this[resultHeaders]) this[resultHeaders] = {};
        this[resultHeaders][name] = _val;
        return this;
      }
      return null;
    }

    /* Event handler ON: will call the function only once. */
    on(eventName, fn) {
      if (typeof fn !== 'function') {
        console.error('Thorin.intent: .on(eventName, fn), fn is not a function.');
        return this;
      }
      if (this[eventsFired][eventName]) {
        try {
          fn();
        } catch (e) {
          console.error('Thorin.Intent: triggered event ' + eventName + ' on callback function threw an exception.');
          console.error(e);
        }
        return this;
      }
      if (typeof this[events][eventName] === 'undefined') this[events][eventName] = [];
      this[events][eventName].push(fn);
      return this;
    }

    /*
     * Sets/gets specific client information.
     * */
    client(key, val) {
      if (typeof key === 'object' && key) {
        Object.keys(key).forEach((a) => {
          this.client(a, key[a]);
        });
        return this;
      }
      if (typeof key === 'undefined') return this[client];
      if (typeof key === 'string' && typeof val === 'undefined') return (typeof this[client][key] === 'undefined' ? null : this[client][key]);
      this[client][key] = val;
      return this;
    }

    /*
     * Get/Set additional data to it.
     * */
    data(name, _val) {
      if (typeof name !== 'string') return this[data];
      if (typeof name === 'string' && typeof _val === 'udnefined') return this[data][name] || null;
      this[data][name] = _val;
      return this;
    }

    /*
     * Getter/setter for input data.
     * */
    input(name, _val) {
      if (typeof name === 'undefined') return this[input];
      if (typeof name === 'string' && typeof _val === 'undefined') {
        return this[input][name] || null;
      }
      if (typeof name === 'string' && typeof _val !== 'undefined') {
        this[input][name] = _val;
        return this;
      }
      return null;
    }

    /* Checks if the intent is an error yet. */
    hasError() {
      return (this[error] != null);
    }

    /* Checks if we have any result */
    hasResult() {
      return (this[result] != null);
    }

    hasRawResult() {
      return (this[rawResult] === true);
    }

    /*
     * Sets the raw result of the intent. Raw results will send the result as is,
     * without wrapping it into an object.
     * */
    rawResult(val) {
      if(typeof val === 'undefined') return;
      this[rawResult] = true;
      this[result] = val;
      return this;
    }

    /*
     * Get/set result information
     * */
    result(name, val) {
      if(name instanceof Array) {
        this[result] = name;
        return this;
      }
      if (typeof name === 'object' && name) {
        if(typeof name.getDataValue === 'function') { // ignore objects that have toJSON, as the transport will take care of it.
          this[result] = name;
          return this;
        }
        Object.keys(name).forEach((key) => {
          this.result(key, name[key]);
        });
        return this;
      }
      if (typeof name === 'string' && !(this[result] instanceof Array)) {
        if (typeof val === 'undefined') {
          return (typeof this[result][name] === 'undefined' ? null : this[result][name]);
        }
        if (this[result] == null) this[result] = {};
        this[result][name] = val;
        return this;
      }
      if(typeof name === 'undefined') {
        return this[result];
      }
      return this;
    }

    /*
     * Sets pagination data or other information that will be used in the root object.. The pagination data will be included in the base response,
     * right next to id and result.
     * TODO: this should work with a thorin.Pagination
     * */
    rootData(data, val) {
      if (typeof data === 'object') {
        Object.keys(data).forEach((k) => {
          this.rootData(k, data[k]);
        });
        return this;
      }
      if (typeof data === 'string') {
        if (typeof val === 'undefined') {
          return (typeof this[rootData][data] === 'undefined' ? null : this[rootData][data]);
        }
        if (this[rootData] == null) this[rootData] = {};
        this[rootData][data] = val;
        return this;
      }
      return this;
    };

    /*
     * Marks the intent as error. We can set the error only once.
     * */
    error(err) {
      if (typeof err === 'undefined') return this[error];
      if (this[error]) return this;
      if (err instanceof Error && err.name.indexOf('Thorin') !== 0) {
        err = thorin.error(err);
      }
      this[error] = err;
      return this;
    }

    /*
     * Returns the number of ms it took for the intent to end.
     * */
    get took() {
      if (!this[timeEnd]) return 0;
      return this[timeEnd] - this[timeStart];
    }

    /*
     * Ends the current intent, responding with the result back to the transport layer.
     * */
    send(obj) {
      if(this.proxied) {
        this.proxied = false;
        this[onSend].apply(this, arguments);  // proxy the send.
        return;
      }
      if (this.completed) {
        console.error('Thorin.intent: already completed for action ' + this.action);
        return this;
      }
      if (!this[rawResult] && typeof obj === 'object' && obj != null) {
        if (obj instanceof Error && !this.hasError()) {
          this.error(obj);
        } else if (!this.hasResult()) {
          this.result(obj);
        }
      }
      this[timeEnd] = Date.now();
      this.completed = true;
      const intentResult = {
        "action": this.action
      };
      if (this.hasError()) {
        intentResult.error = this.error();
        triggerEvent.call(this, INTENT_EVENTS.END);
        if (typeof this[onSend] === 'function') {
          this[onSend](true, intentResult, this);
          this.destroy();
        } else {
          this.destroy();
          return intentResult;
        }
      } else {
        // IF we have a raw result, we just send it.
        if(this[rawResult] === true) {
          triggerEvent.call(this, INTENT_EVENTS.END);
          if (typeof this[onSend] === 'function') {
            this[onSend](false, this[result], this);
            this.destroy();
          } else {
            this.destroy();
            return this[result];
          }
          return;
        }

        // set any pagination data.
        if (this[rootData] != null) {
          Object.keys(this[rootData]).forEach((k) => {
            if(k === 'result' || k === "action") return;
            if (typeof intentResult[k] !== 'undefined') return;
            intentResult[k] = this[rootData][k];
          });
        }
        if (this.hasResult()) {
          intentResult.result = this.result();
        }
        triggerEvent.call(this, INTENT_EVENTS.END);
        if (typeof this[onSend] === 'function') {
          this[onSend](false, intentResult, this);
          this.destroy();
        } else {
          this.destroy();
          return intentResult;
        }
      }
    }

    /*
     * Intent destructor
     * */
    destroy() {
      this[data] = null;
      this[rawInput] = null;
      this[input] = null;
      this[result] = null;
      this[error] = null;
      this[authorization] = null;
      this[client] = null;
      this[rootData] = null;
      this[events] = {};
      this[eventsFired] = {};
      delete this[resultHeaders];
      delete this[onSend];
    }
  }
  ThorinIntent.EVENT = INTENT_EVENTS;

  /*
   * This is called by the intent to trigger an event
   * Event triggering is only for the intent to fire.
   * */
  function triggerEvent(eventName, _args) {
    if (typeof this[events][eventName] === 'undefined') return;
    for (let i = 0; i < this[events][eventName].length; i++) {
      try {
        this[events][eventName][i](_args);
      } catch (e) {
        console.error('Thorin.Intent: triggered event ' + eventName + ' on callback function threw an exception.');
        console.error(e);
      }
    }
    this[eventsFired][eventName] = true;
    delete this[events][eventName];
  }

  return ThorinIntent;
};<|endoftext|>


<commit_before>function BrainCanvas(canvas) {
  var that  = this;
  var context = canvas.getContext("2d");
  var loader = new Loader();

  var cursor = {
    x: [0,0],
    y: [0,0],
    z: [0,0]
  };
  //Holds the slice numbers
  that.slices = {};

  var spectrum = loader.loadSpectrumFromUrl("/spectrum/spectral.txt");

  this.initCanvas = function(width,heigth) {
    canvas.width = width;
    canvas.height = heigth;

    context.fillStyle = "#000000";
    context.fillRect(0,0,width,heigth);

  };

  this.update_space = function(axis, number, minc,time) {
    var slice = minc.getScaledSlice(axis,number,time,null);

    //get the area of canvas to insert image into
    //Make sure that area uses the step of the axises
    var slice_image_data = context.createImageData(
      minc[axis].length*Math.abs(minc[minc[axis].length_space].step),
      minc[axis].height*Math.abs(minc[minc[axis].height_space].step));

    slice_image_data.data = createColorMap(spectrum,slice_image_data.data,slice,minc.min,minc.max,true);

    return slice_image_data;
  };

  function drawCrosshair(x,y) {
    context.fillStyle = "#FF0000";
    context.fillRect(x-2,y-2,4,4);
  };

  this.updateXSpace = function(number,minc,time) {
    that.slices.xspace = number;
    var xslice_image_data = that.update_space("xspace", number,minc,time);
    context.putImageData(xslice_image_data,0,0);
  };

  this.updateYSpace = function(number,minc,time) {
    that.slices.yspace = number;
    var yslice_image_data = that.update_space("yspace", number,minc,time);

    context.putImageData(yslice_image_data,0,minc.xspace.height*Math.abs(minc.xspace.step));

  };

  this.updateZSpace = function(number,minc,time) {
    that.slices.zspace = number;
    var zslice_image_data = that.update_space("zspace", number,minc,time);
    context.putImageData(zslice_image_data,0,minc.xspace.height*Math.abs(minc.xspace.step)+minc.yspace.height*Math.abs(minc.yspace.step));

  };

  this.updateSlices = function(event,time){
    if(event) {
      var slice_numbers = that.getSliceNumbersFromPosition(getCursorPosition(event));
    }else {
      var slice_numbers = {
	x: that.slices.xspace,
	y: that.slices.yspace,
	z: that.slices.zspace
      };
    }
    //clear canvas
    that.initCanvas(canvas.width, canvas.height);

    //insert slices
    that.updateXSpace(slice_numbers.x,that.current_minc,time);
    that.updateYSpace(slice_numbers.y,that.current_minc,time);
    that.updateZSpace(slice_numbers.z,that.current_minc,time);

    //draw x or square whatever
    drawCrosshair(that.slices[that.current_minc.xspace.length_space]*Math.abs(that.current_minc.xspace.step),
		  that.slices[that.current_minc.xspace.height_space]*Math.abs(that.current_minc.xspace.step));
    drawCrosshair(that.slices[that.current_minc.yspace.length_space]*Math.abs(that.current_minc.xspace.step),
		  that.slices[that.current_minc.yspace.height_space]*Math.abs(that.current_minc.xspace.step)+that.current_minc.xspace.height*Math.abs(that.current_minc.xspace.step));
    drawCrosshair(that.slices[that.current_minc.zspace.length_space]*Math.abs(that.current_minc.xspace.step),
		  that.slices[that.current_minc.zspace.height_space]*Math.abs(that.current_minc.xspace.step)
		  +that.current_minc.xspace.height*Math.abs(that.current_minc.xspace.step)
		  +that.current_minc.yspace.height*Math.abs(that.current_minc.xspace.step));

  };

  this.showMinc=function(minc){
    $(canvas).siblings("#mincinfo").append("Minc Information:
"+
			  "order: "+ minc.order +
			  "
xspace.height: " + minc.xspace.height + " yspace.height: " + minc.yspace.height + " zspace.height: " + minc.zspace.height +
			  "
 xspace.length: " + minc.xspace.length + " yspace.length: " + minc.yspace.length + " zspace.length: " + minc.zspace.length + "xspace step: " + minc.xspace.step + "yspace step: " + minc.yspace.step + "zspace step: " + minc.zspace.step);

    that.slices.xspace = 100;
    that.slices.yspace = 100;
    that.slices.zspace = 100;
    that.updateXSpace(that.slices.xspace,minc);
    that.updateYSpace(that.slices.yspace,minc);
    that.updateZSpace(that.slices.zspace,minc);

    drawCrosshair(that.slices[that.current_minc.xspace.length_space]*Math.abs(that.current_minc.xspace.step),
		  that.slices[that.current_minc.xspace.height_space]*Math.abs(that.current_minc.xspace.step));
    drawCrosshair(that.slices[that.current_minc.yspace.length_space]*Math.abs(that.current_minc.xspace.step),
		  that.slices[that.current_minc.yspace.height_space]*Math.abs(that.current_minc.xspace.step)+that.current_minc.xspace.height*Math.abs(that.current_minc.xspace.step));
    drawCrosshair(that.slices[that.current_minc.zspace.length_space]*Math.abs(that.current_minc.xspace.step),
		  that.slices[that.current_minc.zspace.height_space]*Math.abs(that.current_minc.xspace.step)
		  +that.current_minc.xspace.height*Math.abs(that.current_minc.xspace.step)
		  +that.current_minc.yspace.height*Math.abs(that.current_minc.xspace.step));

   //alert("Typeof xlsice: " + typeof xslice + " Lenght of xslice: " + xslice.length + " xslice max: " + minc.max + " xslice.min: " + minc.min + " xslice[5000]: " + xslice[5000] + " xslice[20000]: " + xslice[20000] + " xslice_image_data.data[10000*4]: "   + " " + xslice_image_data.data[2] );

    //var yslice = Minc.slice('yspace',1);
    //var zslice = Minc.slice('zspace',1);

  };

  function getCursorPosition(e){
    var x;
    var y;
    if (e.pageX != undefined && e.pageY != undefined) {
	x = e.pageX;
	y = e.pageY;
    }
    else {
	x = e.clientX + document.body.scrollLeft +
            document.documentElement.scrollLeft;
	y = e.clientY + document.body.scrollTop +
            document.documentElement.scrollTop;
    }

    x -= canvas.offsetLeft;
    y -= canvas.offsetTop;

    return {x: x,y: y};
  }

  this.getSliceNumbersFromPosition = function(position){
    that.position = position;
    if(position.y/Math.abs(that.current_minc.xspace.step) < that.current_minc.xspace.height) {
      var slices = {
	x: that.slices.xspace
      };
      if(that.current_minc.xspace.height_space == "yspace") {
	slices.y = parseInt(position.y/Math.abs(that.current_minc.yspace.step));
	slices.z = parseInt(position.x/Math.abs(that.current_minc.zspace.step));
      }else {
        slices.y = parseInt(position.x/Math.abs(that.current_minc.yspace.step));
	slices.z = parseInt(position.y/Math.abs(that.current_minc.zspace.step));

      }

    }else if(position.y/Math.abs(that.current_minc.yspace.step) < that.current_minc.xspace.height + that.current_minc.yspace.height){
      var slices = {
	y: that.slices.yspace
      };

      if(that.current_minc.yspace.height_space == "zspace"){

	slices.x = parseInt(position.x/Math.abs(that.current_minc.xspace.step));
	slices.z = parseInt(position.y/Math.abs(that.current_minc.zspace.step)) -  that.current_minc.xspace.height;
      } else {
        slices.z = parseInt(position.x/Math.abs(that.current_minc.zspace.step));
	slices.x = parseInt(position.y/Math.abs(that.current_minc.yspace.step)) -  that.current_minc.xspace.height;
      }

    }else {
      var slices =
	{
	  z: that.slices.zspace,
	  x:parseInt(position.x/Math.abs(that.current_minc.xspace.step)),
	  y:parseInt(position.y/Math.abs(that.current_minc.ypace.step)) - that.current_minc.xspace.height - that.current_minc.yspace.height
	};

    }

  return slices;

  };

  this.addListeners = function() {
    canvas.onmousedown = function(event) {
      that.drag = true;
    };

    canvas.onmouseup = function(event) {
      that.drag = false;
    };

    canvas.onmousemove = function(event) {
      if(that.drag){
	that.updateSlices(event);
      }
    };
  };

  this.showTime = function() {
    var div = $(canvas).parent();
    $("<input type='text' name='time' value=\"0\" size=4>").appendTo(div);
    $("

").slider({
						  value: 0,
						  min: 0,
						  max: that.current_minc.time.space_length,
						  step: 1,
	                                          slide: function(event,ui) {
					           that.updateSlices(null,ui.value);
						  }
						}).appendTo(div);
  };

  this.openFile =function(filename) {
    this.current_minc = new Minc(filename, null,function(minc,extraArgs){
				   var height = minc.xspace.height*Math.abs(minc.xspace.step)+minc.yspace.height*Math.abs(minc.yspace.step)+minc.yspace.height*Math.abs(minc.zspace.step);
				   var length = Math.max(minc.xspace.length*Math.abs(minc.xspace.step),minc.yspace.length*Math.abs(minc.yspace.step),minc.zspace.length*Math.abs(minc.zspace.step));

				   that.initCanvas(length,height);
				   that.showMinc(minc);
				   that.addListeners();
				   if(minc.time) {
				     that.showTime();
				   }
				   ;});
  };

};
<commit_msg>fixed typo<commit_after>function BrainCanvas(canvas) {
  var that  = this;
  var context = canvas.getContext("2d");
  var loader = new Loader();

  var cursor = {
    x: [0,0],
    y: [0,0],
    z: [0,0]
  };
  //Holds the slice numbers
  that.slices = {};

  var spectrum = loader.loadSpectrumFromUrl("/spectrum/spectral.txt");

  this.initCanvas = function(width,heigth) {
    canvas.width = width;
    canvas.height = heigth;

    context.fillStyle = "#000000";
    context.fillRect(0,0,width,heigth);

  };

  this.update_space = function(axis, number, minc,time) {
    var slice = minc.getScaledSlice(axis,number,time,null);

    //get the area of canvas to insert image into
    //Make sure that area uses the step of the axises
    var slice_image_data = context.createImageData(
      minc[axis].length*Math.abs(minc[minc[axis].length_space].step),
      minc[axis].height*Math.abs(minc[minc[axis].height_space].step));

    slice_image_data.data = createColorMap(spectrum,slice_image_data.data,slice,minc.min,minc.max,true);

    return slice_image_data;
  };

  function drawCrosshair(x,y) {
    context.fillStyle = "#FF0000";
    context.fillRect(x-2,y-2,4,4);
  };

  this.updateXSpace = function(number,minc,time) {
    that.slices.xspace = number;
    var xslice_image_data = that.update_space("xspace", number,minc,time);
    context.putImageData(xslice_image_data,0,0);
  };

  this.updateYSpace = function(number,minc,time) {
    that.slices.yspace = number;
    var yslice_image_data = that.update_space("yspace", number,minc,time);

    context.putImageData(yslice_image_data,0,minc.xspace.height*Math.abs(minc.xspace.step));

  };

  this.updateZSpace = function(number,minc,time) {
    that.slices.zspace = number;
    var zslice_image_data = that.update_space("zspace", number,minc,time);
    context.putImageData(zslice_image_data,0,minc.xspace.height*Math.abs(minc.xspace.step)+minc.yspace.height*Math.abs(minc.yspace.step));

  };

  this.updateSlices = function(event,time){
    if(event) {
      var slice_numbers = that.getSliceNumbersFromPosition(getCursorPosition(event));
    }else {
      var slice_numbers = {
	x: that.slices.xspace,
	y: that.slices.yspace,
	z: that.slices.zspace
      };
    }
    //clear canvas
    that.initCanvas(canvas.width, canvas.height);

    //insert slices
    that.updateXSpace(slice_numbers.x,that.current_minc,time);
    that.updateYSpace(slice_numbers.y,that.current_minc,time);
    that.updateZSpace(slice_numbers.z,that.current_minc,time);

    //draw x or square whatever
    drawCrosshair(that.slices[that.current_minc.xspace.length_space]*Math.abs(that.current_minc.xspace.step),
		  that.slices[that.current_minc.xspace.height_space]*Math.abs(that.current_minc.xspace.step));
    drawCrosshair(that.slices[that.current_minc.yspace.length_space]*Math.abs(that.current_minc.xspace.step),
		  that.slices[that.current_minc.yspace.height_space]*Math.abs(that.current_minc.xspace.step)+that.current_minc.xspace.height*Math.abs(that.current_minc.xspace.step));
    drawCrosshair(that.slices[that.current_minc.zspace.length_space]*Math.abs(that.current_minc.xspace.step),
		  that.slices[that.current_minc.zspace.height_space]*Math.abs(that.current_minc.xspace.step)
		  +that.current_minc.xspace.height*Math.abs(that.current_minc.xspace.step)
		  +that.current_minc.yspace.height*Math.abs(that.current_minc.xspace.step));

  };

  this.showMinc=function(minc){
    $(canvas).siblings("#mincinfo").append("Minc Information:
"+
			  "order: "+ minc.order +
			  "
xspace.height: " + minc.xspace.height + " yspace.height: " + minc.yspace.height + " zspace.height: " + minc.zspace.height +
			  "
 xspace.length: " + minc.xspace.length + " yspace.length: " + minc.yspace.length + " zspace.length: " + minc.zspace.length + "xspace step: " + minc.xspace.step + "yspace step: " + minc.yspace.step + "zspace step: " + minc.zspace.step);

    that.slices.xspace = 100;
    that.slices.yspace = 100;
    that.slices.zspace = 100;
    that.updateXSpace(that.slices.xspace,minc);
    that.updateYSpace(that.slices.yspace,minc);
    that.updateZSpace(that.slices.zspace,minc);

    drawCrosshair(that.slices[that.current_minc.xspace.length_space]*Math.abs(that.current_minc.xspace.step),
		  that.slices[that.current_minc.xspace.height_space]*Math.abs(that.current_minc.xspace.step));
    drawCrosshair(that.slices[that.current_minc.yspace.length_space]*Math.abs(that.current_minc.xspace.step),
		  that.slices[that.current_minc.yspace.height_space]*Math.abs(that.current_minc.xspace.step)+that.current_minc.xspace.height*Math.abs(that.current_minc.xspace.step));
    drawCrosshair(that.slices[that.current_minc.zspace.length_space]*Math.abs(that.current_minc.xspace.step),
		  that.slices[that.current_minc.zspace.height_space]*Math.abs(that.current_minc.xspace.step)
		  +that.current_minc.xspace.height*Math.abs(that.current_minc.xspace.step)
		  +that.current_minc.yspace.height*Math.abs(that.current_minc.xspace.step));

   //alert("Typeof xlsice: " + typeof xslice + " Lenght of xslice: " + xslice.length + " xslice max: " + minc.max + " xslice.min: " + minc.min + " xslice[5000]: " + xslice[5000] + " xslice[20000]: " + xslice[20000] + " xslice_image_data.data[10000*4]: "   + " " + xslice_image_data.data[2] );

    //var yslice = Minc.slice('yspace',1);
    //var zslice = Minc.slice('zspace',1);

  };

  function getCursorPosition(e){
    var x;
    var y;
    if (e.pageX != undefined && e.pageY != undefined) {
	x = e.pageX;
	y = e.pageY;
    }
    else {
	x = e.clientX + document.body.scrollLeft +
            document.documentElement.scrollLeft;
	y = e.clientY + document.body.scrollTop +
            document.documentElement.scrollTop;
    }

    x -= canvas.offsetLeft;
    y -= canvas.offsetTop;

    return {x: x,y: y};
  }

  this.getSliceNumbersFromPosition = function(position){
    that.position = position;
    if(position.y/Math.abs(that.current_minc.xspace.step) < that.current_minc.xspace.height) {
      var slices = {
	x: that.slices.xspace
      };
      if(that.current_minc.xspace.height_space == "yspace") {
	slices.y = parseInt(position.y/Math.abs(that.current_minc.yspace.step));
	slices.z = parseInt(position.x/Math.abs(that.current_minc.zspace.step));
      }else {
        slices.y = parseInt(position.x/Math.abs(that.current_minc.yspace.step));
	slices.z = parseInt(position.y/Math.abs(that.current_minc.zspace.step));

      }

    }else if(position.y/Math.abs(that.current_minc.yspace.step) < that.current_minc.xspace.height + that.current_minc.yspace.height){
      var slices = {
	y: that.slices.yspace
      };

      if(that.current_minc.yspace.height_space == "zspace"){

	slices.x = parseInt(position.x/Math.abs(that.current_minc.xspace.step));
	slices.z = parseInt(position.y/Math.abs(that.current_minc.zspace.step)) -  that.current_minc.xspace.height;
      } else {
        slices.z = parseInt(position.x/Math.abs(that.current_minc.zspace.step));
	slices.x = parseInt(position.y/Math.abs(that.current_minc.yspace.step)) -  that.current_minc.xspace.height;
      }

    }else {
      var slices =
	{
	  z: that.slices.zspace,
	  x:parseInt(position.x/Math.abs(that.current_minc.xspace.step)),
	  y:parseInt(position.y/Math.abs(that.current_minc.yspace.step)) - that.current_minc.xspace.height - that.current_minc.yspace.height
	};

    }

  return slices;

  };

  this.addListeners = function() {
    canvas.onmousedown = function(event) {
      that.drag = true;
    };

    canvas.onmouseup = function(event) {
      that.drag = false;
    };

    canvas.onmousemove = function(event) {
      if(that.drag){
	that.updateSlices(event);
      }
    };
  };

  this.showTime = function() {
    var div = $(canvas).parent();
    $("<input type='text' name='time' value=\"0\" size=4>").appendTo(div);
    $("

").slider({
						  value: 0,
						  min: 0,
						  max: that.current_minc.time.space_length,
						  step: 1,
	                                          slide: function(event,ui) {
					           that.updateSlices(null,ui.value);
						  }
						}).appendTo(div);
  };

  this.openFile =function(filename) {
    this.current_minc = new Minc(filename, null,function(minc,extraArgs){
				   var height = minc.xspace.height*Math.abs(minc.xspace.step)+minc.yspace.height*Math.abs(minc.yspace.step)+minc.yspace.height*Math.abs(minc.zspace.step);
				   var length = Math.max(minc.xspace.length*Math.abs(minc.xspace.step),minc.yspace.length*Math.abs(minc.yspace.step),minc.zspace.length*Math.abs(minc.zspace.step));

				   that.initCanvas(length,height);
				   that.showMinc(minc);
				   that.addListeners();
				   if(minc.time) {
				     that.showTime();
				   }
				   ;});
  };

};
<|endoftext|>