<commit_before>/**
* @overview
* This is the controller file for the ToDoList View. The todolist view loads data from
* a model (sqlite), and derives a Sectioned and Indexed (iOS) ListView displaying all items.
* The todolist has one ListView Template for showing list item.
* Also, the ToDoList View have search bar to seaerch item.
*/
var _args = arguments[0] || {}, // Any passed in arguments will fall into this property
	moment = require('alloy/moment'),
	status = 'Pending',
	flag = false;

var colToDoList = Alloy.Collections.instance('todolist');

/**
 * Appcelerator Analytics Call
 */
var title = _args.title ? _args.title.toLowerCase() : "todolist";
Ti.Analytics.featureEvent(Ti.Platform.osname+"."+title+".viewed");

/**
 * This function handles the click events for the rows in the ListView.
 * We want to capture the list property associated with the row, and pass
 * it into the next View
 *
 * @param {Object} Event data passed to the function
 */
function onItemClick(e){
	console.log("e ==> " + JSON.stringify(e));
	if(!flag) {
		flag = true;
		return;
	}
	/**
	 * Appcelerator Analytics Call
	 */
	Ti.Analytics.featureEvent(Ti.Platform.osname+"."+title+".contact.clicked");

	/**
	 * Get the Item that was clicked
	 */
	var item = $.listView.sections[e.sectionIndex].items[e.itemIndex];

	/**
	 * Open the profile view, and pass in the user data for this contact
	 */
	var data = colToDoList.toJSON();

	_.each(data, function(value, key) {
		if(value.id === item.todo.id) {
			Alloy.Globals.Navigator.open("todoform", {obj: value});
		}
	});
}

/**
 * This code is only relevant to iOS - to make it cleaner, we are declaring variables, and
 * then assigning them to functions within an iOS Block. On MobileWeb, Android, etc this code block will not
 * exist
 */
var onSearchChange, onSearchFocus, onSearchCancel;

if(OS_IOS){

	/**
	 * Handles the SearchBar OnChange event
	 *
	 * @description On iOS we want the search bar to always be on top, so we use the onchange event to tie it back
	 * 				to the ListView
	 *
	 * @param {Object} Event data passed to the function
	 */
	onSearchChange = function onChange(e){
		$.listView.searchText = $.searchBar.value;
	};

	/**
	 * Updates the UI when the SearchBar gains focus. Shows
	 * the Cancel button.
	 *
	 * @description We used the focus event to show the Cancel button.
	 *
	 * @param {Object} Event data passed to the function
	 */
	onSearchFocus = function onFocus(e){
		$.searchBar.showCancel = true;
	};

	/**
	 * Updates the UI when the Cancel button is clicked within the search bar. Hides the Cancel button.
	 *
	 * @param {Object} Event data passed to the function
	 */
	onSearchCancel = function onCancel(e){
		$.searchBar.showCancel = false;
		$.searchBar.blur();
	};
}
else if(OS_ANDROID){
	/**
	 * Handles the SearchBar OnChange event
	 *
	 * @description On iOS we want the search bar to always be on top, so we use the onchange event to tie it back
	 * 				to the ListView
	 *
	 * @param {Object} Event data passed to the function
	 */
	onSearchChange = function onChange(e){
		if($.searchBar.value !==''){
			$.closeBtn.visible = true;
		}
		else{
			$.closeBtn.visible = false;
		}

		$.listView.searchText = $.searchBar.value;
	};
	/**
	 * Hides the keyboard when the cancel button is clicked
	 *
	 * @param {Object} Event data passed to the function
	 */
	onSearchCancel = function onCancel(e){
		$.closeBtn.visible = false;
		$.searchBar.value = '';
		$.searchBar.blur();
	};
}

function onWinFocus() {
	if(status === "Pending") {
		$.btnPending.fireEvent("click");
	} else {
		$.btnCompleted.fireEvent("click");
	}
}

function init() {
	colToDoList.fetch({query: "SELECT * FROM todolist ORDER BY dt_modified DESC"});
	// while (colToDoList.length > 0)
		// colToDoList.at(0).destroy();
}

function doTransform(model) {
    // Need to convert the model to a JSON object
    var transform = model.toJSON();
    transform.dt_modified = moment(transform.dt_modified).fromNow();
    return transform;
}

function addToDoItem() {
	Alloy.Globals.Navigator.open("todoform");
	return;
}

function filterOutput(collection) {
	return collection.where({status: status});
}

function emlShare(e) {
	flag = false; // Just a hack since bubbleParent is not working.
	var item = $.listView.sections[e.sectionIndex].items[e.itemIndex];
	var data = colToDoList.toJSON();

	_.each(data, function(value, key) {
		if(value.id === item.todo.id) {
			var emailDialog = Ti.UI.createEmailDialog();
			emailDialog.subject = "To Do List";
			emailDialog.toRecipients = ['pablo.guevara@propelics.com', 'carolina.lopez@propelics.com', 'cesar.cavazos@propelics.com'];
			emailDialog.messageBody = 'Task - ' + value.content + '
Status - ' + value.status + '';
			if(value.image && value.image != "") {
				emailDialog.addAttachment(value.image);
			}
			emailDialog.open();
		}
	});
}

function smsShare(e) {
	flag = false; // Just a hack since bubbleParent is not working.
	var item = $.listView.sections[e.sectionIndex].items[e.itemIndex];
	var data = colToDoList.toJSON();

	_.each(data, function(value, key) {
		if(value.id === item.todo.id) {
			if(OS_IOS) {
				sendSMS("+91 1234567890", value.content + "\n" + value.status, value.image);
			} else {
				openSMSIntent("+91 1234567890", value.content, value.status);
			}
		}
	});
}

function openSMSIntent(phone, content, status) {
	var intent = Ti.Android.createIntent({
		action: Ti.Android.ACTION_SENDTO,
		data: 'smsto:' + phone
	});
	intent.putExtra('sms_body', "Task - " + content + "\nStauts - " + status);
	Ti.Android.currentActivity.startActivity(intent);
}

function sendSMS(phone, content, imageBlob) {
    var module = require('com.omorandi');
    Ti.API.info("module is => " + module);

    //create the smsDialog object
    var smsDialog = module.createSMSDialog();
    //check if the feature is available on the device at hand
    if (!smsDialog.isSupported()) {
        //falls here when executed on iOS versions < 4.0 and in the emulator
        var a = Ti.UI.createAlertDialog({title: 'warning', message: 'the required feature is not available on your device'});
        a.show();
    }
    else
    {
        //pre-populate the dialog with the info provided in the following properties
        smsDialog.recipients = phone ? ['+14151234567'] : [phone];
        smsDialog.messageBody = content;

        //set the color of the title-bar
        smsDialog.barColor = '#E5E4E2';

        //add attachments if supported
        if (smsDialog.canSendAttachments()) {
            Ti.API.info('We can send attachments');
            //add an attachment as a file path
            //smsDialog.addAttachment('images/01.jpg', 'image1.jpg');
			if(imageBlob) {
				var fileName = "" + ".png";
	            smsDialog.addAttachment(imageBlob, filename);
			}
        }
        else {
            Ti.API.info('We cannot send attachments');
        }

        //add an event listener for the 'complete' event, in order to be notified about the result of the operation
        smsDialog.addEventListener('complete', function(e){
            Ti.API.info("Result: " + e.resultMessage);
            var a = Ti.UI.createAlertDialog({title: 'complete', message: 'Result: ' + e.resultMessage});
            a.show();
            if (e.result == smsDialog.SENT)
            {
                //do something
            }
            else if (e.result == smsDialog.FAILED)
            {
               //do something else
            }
            else if (e.result == smsDialog.CANCELLED)
            {
               //don't bother
            }
        });

        //open the SMS dialog window with slide-up animation
        smsDialog.open({animated: true});
    }

}

function sortData(e) {
	status = e.source.title;
	$.addClass(e.source, "fontBold");
	if(status === "Pending") {
		$.removeClass($.btnCompleted, "fontBold");
	} else {
		$.removeClass($.btnPending, "fontBold");
	}
	init();
}

function delRow(e) {
	/**
	 * Get the Item that was clicked
	 */
	var item = $.listView.sections[e.sectionIndex].items[e.itemIndex];
	var model = Alloy.createModel('todolist', {id: item.todo.id});
	model.destroy();
}

function openPic(e) {
	flag = false;
	Alloy.Globals.Navigator.open("taskpic", {image: e.source.image});
}
<commit_msg>Formted email smae as SMS.<commit_after>/**
* @overview
* This is the controller file for the ToDoList View. The todolist view loads data from
* a model (sqlite), and derives a Sectioned and Indexed (iOS) ListView displaying all items.
* The todolist has one ListView Template for showing list item.
* Also, the ToDoList View have search bar to seaerch item.
*/
var _args = arguments[0] || {}, // Any passed in arguments will fall into this property
	moment = require('alloy/moment'),
	status = 'Pending',
	flag = false;

var colToDoList = Alloy.Collections.instance('todolist');

/**
 * Appcelerator Analytics Call
 */
var title = _args.title ? _args.title.toLowerCase() : "todolist";
Ti.Analytics.featureEvent(Ti.Platform.osname+"."+title+".viewed");

/**
 * This function handles the click events for the rows in the ListView.
 * We want to capture the list property associated with the row, and pass
 * it into the next View
 *
 * @param {Object} Event data passed to the function
 */
function onItemClick(e){
	console.log("e ==> " + JSON.stringify(e));
	if(!flag) {
		flag = true;
		return;
	}
	/**
	 * Appcelerator Analytics Call
	 */
	Ti.Analytics.featureEvent(Ti.Platform.osname+"."+title+".contact.clicked");

	/**
	 * Get the Item that was clicked
	 */
	var item = $.listView.sections[e.sectionIndex].items[e.itemIndex];

	/**
	 * Open the profile view, and pass in the user data for this contact
	 */
	var data = colToDoList.toJSON();

	_.each(data, function(value, key) {
		if(value.id === item.todo.id) {
			Alloy.Globals.Navigator.open("todoform", {obj: value});
		}
	});
}

/**
 * This code is only relevant to iOS - to make it cleaner, we are declaring variables, and
 * then assigning them to functions within an iOS Block. On MobileWeb, Android, etc this code block will not
 * exist
 */
var onSearchChange, onSearchFocus, onSearchCancel;

if(OS_IOS){

	/**
	 * Handles the SearchBar OnChange event
	 *
	 * @description On iOS we want the search bar to always be on top, so we use the onchange event to tie it back
	 * 				to the ListView
	 *
	 * @param {Object} Event data passed to the function
	 */
	onSearchChange = function onChange(e){
		$.listView.searchText = $.searchBar.value;
	};

	/**
	 * Updates the UI when the SearchBar gains focus. Shows
	 * the Cancel button.
	 *
	 * @description We used the focus event to show the Cancel button.
	 *
	 * @param {Object} Event data passed to the function
	 */
	onSearchFocus = function onFocus(e){
		$.searchBar.showCancel = true;
	};

	/**
	 * Updates the UI when the Cancel button is clicked within the search bar. Hides the Cancel button.
	 *
	 * @param {Object} Event data passed to the function
	 */
	onSearchCancel = function onCancel(e){
		$.searchBar.showCancel = false;
		$.searchBar.blur();
	};
}
else if(OS_ANDROID){
	/**
	 * Handles the SearchBar OnChange event
	 *
	 * @description On iOS we want the search bar to always be on top, so we use the onchange event to tie it back
	 * 				to the ListView
	 *
	 * @param {Object} Event data passed to the function
	 */
	onSearchChange = function onChange(e){
		if($.searchBar.value !==''){
			$.closeBtn.visible = true;
		}
		else{
			$.closeBtn.visible = false;
		}

		$.listView.searchText = $.searchBar.value;
	};
	/**
	 * Hides the keyboard when the cancel button is clicked
	 *
	 * @param {Object} Event data passed to the function
	 */
	onSearchCancel = function onCancel(e){
		$.closeBtn.visible = false;
		$.searchBar.value = '';
		$.searchBar.blur();
	};
}

function onWinFocus() {
	if(status === "Pending") {
		$.btnPending.fireEvent("click");
	} else {
		$.btnCompleted.fireEvent("click");
	}
}

function init() {
	colToDoList.fetch({query: "SELECT * FROM todolist ORDER BY dt_modified DESC"});
	// while (colToDoList.length > 0)
		// colToDoList.at(0).destroy();
}

function doTransform(model) {
    // Need to convert the model to a JSON object
    var transform = model.toJSON();
    transform.dt_modified = moment(transform.dt_modified).fromNow();
    return transform;
}

function addToDoItem() {
	Alloy.Globals.Navigator.open("todoform");
	return;
}

function filterOutput(collection) {
	return collection.where({status: status});
}

function emlShare(e) {
	flag = false; // Just a hack since bubbleParent is not working.
	var item = $.listView.sections[e.sectionIndex].items[e.itemIndex];
	var data = colToDoList.toJSON();

	_.each(data, function(value, key) {
		if(value.id === item.todo.id) {
			var emailDialog = Ti.UI.createEmailDialog();
			emailDialog.subject = "To Do List";
			emailDialog.toRecipients = ['pablo.guevara@propelics.com', 'carolina.lopez@propelics.com', 'cesar.cavazos@propelics.com'];
			emailDialog.messageBody = 'Task - ' + value.content + '\nStatus - ' + value.status;
			if(value.image && value.image != "") {
				emailDialog.addAttachment(value.image);
			}
			emailDialog.open();
		}
	});
}

function smsShare(e) {
	flag = false; // Just a hack since bubbleParent is not working.
	var item = $.listView.sections[e.sectionIndex].items[e.itemIndex];
	var data = colToDoList.toJSON();

	_.each(data, function(value, key) {
		if(value.id === item.todo.id) {
			if(OS_IOS) {
				sendSMS("+91 1234567890", value.content + "\n" + value.status, value.image);
			} else {
				openSMSIntent("+91 1234567890", value.content, value.status);
			}
		}
	});
}

function openSMSIntent(phone, content, status) {
	var intent = Ti.Android.createIntent({
		action: Ti.Android.ACTION_SENDTO,
		data: 'smsto:' + phone
	});
	intent.putExtra('sms_body', "Task - " + content + "\nStauts - " + status);
	Ti.Android.currentActivity.startActivity(intent);
}

function sendSMS(phone, content, imageBlob) {
    var module = require('com.omorandi');
    Ti.API.info("module is => " + module);

    //create the smsDialog object
    var smsDialog = module.createSMSDialog();
    //check if the feature is available on the device at hand
    if (!smsDialog.isSupported()) {
        //falls here when executed on iOS versions < 4.0 and in the emulator
        var a = Ti.UI.createAlertDialog({title: 'warning', message: 'the required feature is not available on your device'});
        a.show();
    }
    else
    {
        //pre-populate the dialog with the info provided in the following properties
        smsDialog.recipients = phone ? ['+14151234567'] : [phone];
        smsDialog.messageBody = content;

        //set the color of the title-bar
        smsDialog.barColor = '#E5E4E2';

        //add attachments if supported
        if (smsDialog.canSendAttachments()) {
            Ti.API.info('We can send attachments');
            //add an attachment as a file path
            //smsDialog.addAttachment('images/01.jpg', 'image1.jpg');
			if(imageBlob) {
				var fileName = "" + ".png";
	            smsDialog.addAttachment(imageBlob, filename);
			}
        }
        else {
            Ti.API.info('We cannot send attachments');
        }

        //add an event listener for the 'complete' event, in order to be notified about the result of the operation
        smsDialog.addEventListener('complete', function(e){
            Ti.API.info("Result: " + e.resultMessage);
            var a = Ti.UI.createAlertDialog({title: 'complete', message: 'Result: ' + e.resultMessage});
            a.show();
            if (e.result == smsDialog.SENT)
            {
                //do something
            }
            else if (e.result == smsDialog.FAILED)
            {
               //do something else
            }
            else if (e.result == smsDialog.CANCELLED)
            {
               //don't bother
            }
        });

        //open the SMS dialog window with slide-up animation
        smsDialog.open({animated: true});
    }

}

function sortData(e) {
	status = e.source.title;
	$.addClass(e.source, "fontBold");
	if(status === "Pending") {
		$.removeClass($.btnCompleted, "fontBold");
	} else {
		$.removeClass($.btnPending, "fontBold");
	}
	init();
}

function delRow(e) {
	/**
	 * Get the Item that was clicked
	 */
	var item = $.listView.sections[e.sectionIndex].items[e.itemIndex];
	var model = Alloy.createModel('todolist', {id: item.todo.id});
	model.destroy();
}

function openPic(e) {
	flag = false;
	Alloy.Globals.Navigator.open("taskpic", {image: e.source.image});
}
<|endoftext|>


<commit_before>(function () {
    'use strict';

    // Define object config of properties for this chart directive
    var BarChartDefaults = {
        plotWidth: 800,
        plotHeight: 200,
        transitionMillis: 500,
        lazyLoad: true,
        binType: 'temporal'
    };

    /**
     * ngInject
     */
    function barChart (CartoConfig, BarChartDefaults) {

        var PLOT_CLASS = 'mos-barchart';

        // Begin directive module definition
        var module = {};

        module.restrict = 'EA';
        module.templateUrl = 'scripts/charting/barchart-partial.html';
        module.controller = 'ChartingController';

        module.scope = {
            data: '=',              // Required
            id: '@',                // Required
            plotWidth: '@',
            selectedY: '=',
            selectLabel: '=',
            selectUnit: '=',
            plotHeight: '@',
            margin: '&',
            binType: '@',
            lazyLoad: '@',
            transitionMillis: '@'
        };

        // This is a helper function for transforming api data into percentiles based on sqft
        function binBySqFt(data, groups) {
            data = _.filter(data, function(d) { return d.sqfeet > 0; });
            _.forEach(data, function(d) {
                d.log = Math.log10(d.sqfeet);
            });
            var maxLog = _.max(data, function(d) { return d.log; }).log;
            var binnedBySqFt = {};
            var binSize = maxLog / groups;
            var getBinSize =  function(d) {
                return binSize * i < d.log && (binSize * i) + binSize >= d.log;
            };
            for (var i = 0; i < groups; i++) {
                binnedBySqFt[i] = _.filter(data, getBinSize);
            }
            var output = [];
            _.forEach(binnedBySqFt, function(d, i) {
                // Naive count
                var kCount = d.length;
                // Special counts for fair avging
                var nEnergystar = _.filter(d, function(e) { return !isNaN(e.energystar) && e.energystar > 0; }).length;
                var nEUI = _.filter(d, function(e) { return !isNaN(e.eui) && e.eui > 0; }).length;
                // The bin boundaries
                var lowBound = Math.round(Math.pow(10, (i * binSize))).toLocaleString();
                var highBound = Math.round(Math.pow(10, (i * binSize) + binSize)).toLocaleString();
                // Min and max sq ft
                var minsqft = _.min(d, function(val) { return val.sqfeet; }).sqfeet;
                var maxsqft = _.max(d, function(val) { return val.sqfeet; }).sqfeet;
                output = output.concat({
                    totalemissions: _.reduce(d, function(memo, val) { return val.emissions + memo; }, 0),
                    avgenergystar: nEnergystar > 0 ? _.reduce(d, function(memo, val) { return val.energystar + memo; }, 0) / nEnergystar : 0,
                    avgeui: nEUI > 0 ? _.reduce(d, function(memo, val) { return val.eui + memo; }, 0) / nEUI : 0,
                    minsqft: minsqft ? minsqft : 0,
                    maxsqft: maxsqft ? maxsqft : 0,
                    avgsqft: _.reduce(d, function(memo, val) { return val.sqfeet + memo; }, 0) / kCount,
                    totalsqft: _.reduce(d, function(memo, val) { return val.sqfeet + memo; }, 0),
                    totalenergy: _.reduce(d, function(memo, val) { return (val.sqfeet * val.eui) + memo; }, 0),
                    count: kCount,
                    key: lowBound + '-' + highBound,
                    yearRange: _.min(d, function(d) { return d.yearbuilt; }).yearbuilt +
                        '-' + _.max(d, function(d) { return d.yearbuilt; }).yearbuilt
                });
            });
            return _.rest(output, function(d) { return d.count === 0; }).reverse(); // Prune empty head
        }

        // Helper function for transforming unshaped data into data binned and aggregated over 5 year periods
        function binByYears(data) {
            var filteredData = _.filter(data, function(d) { return d.yearbuilt > 1849; });
            var dateRanges = _.zip(_.range(1849, 2015, 5), _.range(1853, 2019, 5));
            var rolledData =
                d3.nest()
                    .key(function(d) {
                        var years = _.find(dateRanges, function(range) {
                            return range[0] <= d.yearbuilt && d.yearbuilt <= range[1];
                        });
                        return years[0]+'-'+years[1];
                    })
                    .rollup(function(d) {
                        return {
                            totalsqft: d3.mean(d, function(e) { return e.sqfeet; }),
                            avgeui: d3.mean(d, function(e) { return e.eui; }),
                            totalemissions: d3.mean(d, function(e) { return e.emissions; }),
                            avgenergystar: d3.mean(d, function(e) { return e.energystar; }),
                            count: d3.sum(d, function() { return 1; }),
                            totalenergy: d3.sum(d, function(e) { return e.eui * e.sqfeet; })
                        };
                    })
                    .entries(filteredData);
            return _.chain(rolledData)
                    .sortBy(function(d) { return d.key; })
                    .map(function(d) {
                        var obj = d.values;
                        obj.key = d.key;
                        obj.avgenergystar = isNaN(obj.avgenergystar) ? 0 : obj.avgenergystar;
                        return obj;
                    })
                    .reverse()
                    .value();
        }

        module.link = function ($scope, element, attrs) {
            $scope.configure(BarChartDefaults);
            var config = $scope.config;
            config.margin.left = 0;

            // D3 margin, sizing, and spacing code
            element.addClass(PLOT_CLASS);
            var chart = d3.select('#' + attrs.id + ' .chart')
                    .attr('width', config.plotWidth);

            // Overridden ChartingController method
            $scope.plot = function(data) {
                // The dimension of choice for representation along Y
                var yAttr = $scope.selectedY;
                // Chart height
                chart.attr('height', config.plotHeight);

                // Choose appropriate binning algorithm
                if (config.binType === 'temporal') {
                    data = binByYears(data);
                } else if (config.binType === 'area') {
                    data = binBySqFt(data, 62); // 62 is the magic number for generating a
                                                // logarithmically generated set of bins which
                                                // have  32 after pruning the empty head (30 removed)
                }

                // Axes and scales
                var x = d3.scale.ordinal()
                    .domain(data.map(function(d) { return d.key; }))
                    .rangeRoundBands([config.plotWidth-config.margin.left-config.margin.right, 0], 0.05);
                var y = d3.scale.linear()
                    .domain([0, d3.max(data, function(d) { return d[yAttr]; })])
                    .range([config.plotHeight-config.margin.bottom-config.margin.top, 0]);
                var bottomAxis = d3.svg.axis()
                    .orient('bottom')
                    .scale(x)
                    .tickSize(3,1)
                    .tickValues([]);
                chart.append('g')
                    .attr('class', 'x axis')
                    .attr('transform', 'translate(' +config.margin.left + ',' + (config.plotHeight - config.margin.bottom) + ')')
                    .call(bottomAxis);

                // Axes should have custom labels to prevent cluttering; tooltips can handle detail
                var labelStart = chart.append('text')
                    .attr('class', 'x startLabel')
                    .attr('text-anchor', 'start')
                    .attr('y', config.plotHeight-config.margin.top);
                var labelEnd = chart.append('text')
                    .attr('class', 'x endLabel')
                    .attr('text-anchor', 'end')
                    .attr('x', config.plotWidth-config.margin.right)
                    .attr('y', config.plotHeight-config.margin.top);
                // Depending on bin type, our axis labeling should look rather different
                if (config.binType === 'temporal') {
                    labelStart.text('1850');
                    labelEnd.text('2013');
                } else if (config.binType === 'area') {
                    labelStart.text(Math.round(data[data.length - 1].minsqft / 1000).toLocaleString() + 'k');
                    labelEnd.text(Math.round(data[0].maxsqft / 1000).toLocaleString() + 'k');
                }

                // Tooltips
                var tip = d3.tip()
                  .attr('class', 'd3-tip')
                  .offset([-10, 0])
                  .html(function(d) {
                    var dataLabel = d.key + (config.binType === 'area' ? ' Sq Ft' : '');
                    return '
' + dataLabel + '
' +
                           '
' + $scope.selectLabel + ': ' + Math.round(d[yAttr]).toLocaleString() + ' ' + $scope.selectUnit + '
';
                  });
                chart.call(tip);

                // Bars
                chart.selectAll('bar')
                    .data(data)
                    .enter().append('rect')
                    .attr('transform', function(d) { return 'translate(' + (x(d.key) + config.margin.left).toString() + ',0)'; })
                    .attr('y', config.plotHeight - config.margin.bottom)
                    // Height of zero initially so it can be animated on load
                    .attr('height', 0)
                    .attr('width', x.rangeBand())
                    .attr('opacity', function(d, i) { return 1 - (i / data.length) * 0.3; })
                    .attr('rx', 3) // Rounding of corners
                    .attr('ry', 3)
                    .on('mouseover', tip.show)
                    .on('mouseout', tip.hide);

                // Perform the initial animation
                refreshData();

                // Animation functions
                function refreshScale() {
                    y.domain([0, d3.max(data, function(d) { return d[yAttr]; })]);
                }

                function refreshData() {
                    var transitionMillis = config.transitionMillis;
                    refreshScale();
                    chart.selectAll('rect')
                        .transition()
                        .ease('linear')
                        .duration(transitionMillis)
                        .attr('class', config.binType)
                        .attr('y', function(d) {
                            var val = isNaN(d[yAttr]) ? 0 : y(d[yAttr]);
                            return val - 10 + config.margin.top; })
                        .attr('height', function(d) {
                            var val = isNaN(d[yAttr]) ? 0 : y(d[yAttr]);
                            return config.plotHeight - val - config.margin.top - config.margin.bottom;
                        });
                }

                $scope.$watch('selectedY', function(newValue) {
                    yAttr = newValue;
                    refreshData();
                });
            };
        };

        return module;
    }

    angular.module('mos.charting')
      .constant('BarChartDefaults', BarChartDefaults)
      .directive('mosBarchart', barChart);

})();
<commit_msg>Cleanup barchart tooltip<commit_after>(function () {
    'use strict';

    // Define object config of properties for this chart directive
    var BarChartDefaults = {
        plotWidth: 800,
        plotHeight: 200,
        transitionMillis: 500,
        lazyLoad: true,
        binType: 'temporal'
    };

    /**
     * ngInject
     */
    function barChart (CartoConfig, BarChartDefaults) {

        var PLOT_CLASS = 'mos-barchart';

        // Begin directive module definition
        var module = {};

        module.restrict = 'EA';
        module.templateUrl = 'scripts/charting/barchart-partial.html';
        module.controller = 'ChartingController';

        module.scope = {
            data: '=',              // Required
            id: '@',                // Required
            plotWidth: '@',
            selectedY: '=',
            selectLabel: '=',
            selectUnit: '=',
            plotHeight: '@',
            margin: '&',
            binType: '@',
            lazyLoad: '@',
            transitionMillis: '@'
        };

        // This is a helper function for transforming api data into percentiles based on sqft
        function binBySqFt(data, groups) {
            data = _.filter(data, function(d) { return d.sqfeet > 0; });
            _.forEach(data, function(d) {
                d.log = Math.log10(d.sqfeet);
            });
            var maxLog = _.max(data, function(d) { return d.log; }).log;
            var binnedBySqFt = {};
            var binSize = maxLog / groups;
            var getBinSize =  function(d) {
                return binSize * i < d.log && (binSize * i) + binSize >= d.log;
            };
            for (var i = 0; i < groups; i++) {
                binnedBySqFt[i] = _.filter(data, getBinSize);
            }
            var output = [];
            _.forEach(binnedBySqFt, function(d, i) {
                // Naive count
                var kCount = d.length;
                // Special counts for fair avging
                var nEnergystar = _.filter(d, function(e) { return !isNaN(e.energystar) && e.energystar > 0; }).length;
                var nEUI = _.filter(d, function(e) { return !isNaN(e.eui) && e.eui > 0; }).length;
                // The bin boundaries
                var lowBound = Math.round(Math.pow(10, (i * binSize))).toLocaleString();
                var highBound = Math.round(Math.pow(10, (i * binSize) + binSize)).toLocaleString();
                // Min and max sq ft
                var minsqft = _.min(d, function(val) { return val.sqfeet; }).sqfeet;
                var maxsqft = _.max(d, function(val) { return val.sqfeet; }).sqfeet;
                output = output.concat({
                    totalemissions: _.reduce(d, function(memo, val) { return val.emissions + memo; }, 0),
                    avgenergystar: nEnergystar > 0 ? _.reduce(d, function(memo, val) { return val.energystar + memo; }, 0) / nEnergystar : 0,
                    avgeui: nEUI > 0 ? _.reduce(d, function(memo, val) { return val.eui + memo; }, 0) / nEUI : 0,
                    minsqft: minsqft ? minsqft : 0,
                    maxsqft: maxsqft ? maxsqft : 0,
                    avgsqft: _.reduce(d, function(memo, val) { return val.sqfeet + memo; }, 0) / kCount,
                    totalsqft: _.reduce(d, function(memo, val) { return val.sqfeet + memo; }, 0),
                    totalenergy: _.reduce(d, function(memo, val) { return (val.sqfeet * val.eui) + memo; }, 0),
                    count: kCount,
                    key: lowBound + ' - ' + highBound,
                    yearRange: _.min(d, function(d) { return d.yearbuilt; }).yearbuilt +
                        '-' + _.max(d, function(d) { return d.yearbuilt; }).yearbuilt
                });
            });
            return _.rest(output, function(d) { return d.count === 0; }).reverse(); // Prune empty head
        }

        // Helper function for transforming unshaped data into data binned and aggregated over 5 year periods
        function binByYears(data) {
            var filteredData = _.filter(data, function(d) { return d.yearbuilt > 1849; });
            var dateRanges = _.zip(_.range(1849, 2015, 5), _.range(1853, 2019, 5));
            var rolledData =
                d3.nest()
                    .key(function(d) {
                        var years = _.find(dateRanges, function(range) {
                            return range[0] <= d.yearbuilt && d.yearbuilt <= range[1];
                        });
                        return years[0]+' - '+years[1];
                    })
                    .rollup(function(d) {
                        return {
                            totalsqft: d3.mean(d, function(e) { return e.sqfeet; }),
                            avgeui: d3.mean(d, function(e) { return e.eui; }),
                            totalemissions: d3.mean(d, function(e) { return e.emissions; }),
                            avgenergystar: d3.mean(d, function(e) { return e.energystar; }),
                            count: d3.sum(d, function() { return 1; }),
                            totalenergy: d3.sum(d, function(e) { return e.eui * e.sqfeet; })
                        };
                    })
                    .entries(filteredData);
            return _.chain(rolledData)
                    .sortBy(function(d) { return d.key; })
                    .map(function(d) {
                        var obj = d.values;
                        obj.key = d.key;
                        obj.avgenergystar = isNaN(obj.avgenergystar) ? 0 : obj.avgenergystar;
                        return obj;
                    })
                    .reverse()
                    .value();
        }

        module.link = function ($scope, element, attrs) {
            $scope.configure(BarChartDefaults);
            var config = $scope.config;
            config.margin.left = 0;

            // D3 margin, sizing, and spacing code
            element.addClass(PLOT_CLASS);
            var chart = d3.select('#' + attrs.id + ' .chart')
                    .attr('width', config.plotWidth);

            // Overridden ChartingController method
            $scope.plot = function(data) {
                // The dimension of choice for representation along Y
                var yAttr = $scope.selectedY;
                // Chart height
                chart.attr('height', config.plotHeight);

                // Choose appropriate binning algorithm
                if (config.binType === 'temporal') {
                    data = binByYears(data);
                } else if (config.binType === 'area') {
                    data = binBySqFt(data, 62); // 62 is the magic number for generating a
                                                // logarithmically generated set of bins which
                                                // have  32 after pruning the empty head (30 removed)
                }

                // Axes and scales
                var x = d3.scale.ordinal()
                    .domain(data.map(function(d) { return d.key; }))
                    .rangeRoundBands([config.plotWidth-config.margin.left-config.margin.right, 0], 0.05);
                var y = d3.scale.linear()
                    .domain([0, d3.max(data, function(d) { return d[yAttr]; })])
                    .range([config.plotHeight-config.margin.bottom-config.margin.top, 0]);
                var bottomAxis = d3.svg.axis()
                    .orient('bottom')
                    .scale(x)
                    .tickSize(3,1)
                    .tickValues([]);
                var leftAxis = d3.svg.axis()
                    .orient('left')
                    .scale(y);
                chart.append('g')
                    .attr('class', 'x axis')
                    .attr('transform', 'translate(' +config.margin.left + ',' + (config.plotHeight - config.margin.bottom) + ')')
                    .call(bottomAxis);
                //chart.append('g')
                    //.attr('class', 'y axis')
                    //.attr('transform', 'translate(' + config.margin.left + ', 0)')
                    //.call(leftAxis);

                // Axes should have custom labels to prevent cluttering; tooltips can handle detail
                var labelStart = chart.append('text')
                    .attr('class', 'x startLabel')
                    .attr('text-anchor', 'start')
                    .attr('x', config.margin.left)
                    .attr('y', config.plotHeight-config.margin.top);
                var labelEnd = chart.append('text')
                    .attr('class', 'x endLabel')
                    .attr('text-anchor', 'end')
                    .attr('x', config.plotWidth-config.margin.right)
                    .attr('y', config.plotHeight-config.margin.top);
                // Depending on bin type, our axis labeling should look rather different
                if (config.binType === 'temporal') {
                    labelStart.text('1850');
                    labelEnd.text('2013');
                } else if (config.binType === 'area') {
                    labelStart.text(Math.round(data[data.length - 1].minsqft / 1000).toLocaleString() + 'k');
                    labelEnd.text(Math.round(data[0].maxsqft / 1000).toLocaleString() + 'k');
                }

                // Tooltips
                var tip = d3.tip()
                  .attr('class', 'd3-tip')
                  .offset([-10, 0])
                  .html(function(d) {
                    var dataLabel = d.key + (config.binType === 'area' ? ' Sq Ft' : '');
                    return '
' + dataLabel + '

' +
                           '
' + $scope.selectLabel + ':
' +
                           '
' + Math.round(d[yAttr]).toLocaleString() + ' ' + $scope.selectUnit + '
';
                  });
                chart.call(tip);

                // Bars
                chart.selectAll('bar')
                    .data(data)
                    .enter().append('rect')
                    .attr('transform', function(d) { return 'translate(' + (x(d.key) + config.margin.left).toString() + ',0)'; })
                    .attr('y', config.plotHeight - config.margin.bottom)
                    // Height of zero initially so it can be animated on load
                    .attr('height', 0)
                    .attr('width', x.rangeBand())
                    .attr('opacity', function(d, i) { return 1 - (i / data.length) * 0.3; })
                    .attr('rx', 3) // Rounding of corners
                    .attr('ry', 3)
                    .on('mouseover', tip.show)
                    .on('mouseout', tip.hide);

                // Perform the initial animation
                refreshData();

                // Animation functions
                function refreshScale() {
                    y.domain([0, d3.max(data, function(d) { return d[yAttr]; })]);
                }

                function refreshData() {
                    var transitionMillis = config.transitionMillis;
                    refreshScale();
                    chart.selectAll('rect')
                        .transition()
                        .ease('linear')
                        .duration(transitionMillis)
                        .attr('class', config.binType)
                        .attr('y', function(d) {
                            var val = isNaN(d[yAttr]) ? 0 : y(d[yAttr]);
                            return val - 10 + config.margin.top; })
                        .attr('height', function(d) {
                            var val = isNaN(d[yAttr]) ? 0 : y(d[yAttr]);
                            return config.plotHeight - val - config.margin.top - config.margin.bottom;
                        });
                }

                $scope.$watch('selectedY', function(newValue) {
                    yAttr = newValue;
                    refreshData();
                });
            };
        };

        return module;
    }

    angular.module('mos.charting')
      .constant('BarChartDefaults', BarChartDefaults)
      .directive('mosBarchart', barChart);

})();
<|endoftext|>


<commit_before>
/*
 * vim: ts=4:sw=4:expandtab
 */
;(function() {
    'use strict';
    window.Whisper = window.Whisper || {};

    function destroyExpiredMessages() {
        // Load messages that have expired and destroy them
        var expired = new Whisper.MessageCollection();
        expired.on('add', function(message) {
            console.log('message', message.get('sent_at'), 'expired');
            message.getConversation().trigger('expired', message);

            // We delete after the trigger to allow the conversation time to process
            //   the expiration before the message is removed from the database.
            message.destroy();
        });
        expired.on('reset', checkExpiringMessages);

        expired.fetchExpired();
    }

    var timeout;
    function checkExpiringMessages() {
        // Look up the next expiring message and set a timer to destroy it
        var expiring = new Whisper.MessageCollection();
        expiring.once('add', function(next) {
            var expires_at = next.get('expires_at');
            console.log('next message expires', new Date(expires_at).toISOString());

            var wait = expires_at - Date.now();
            if (wait < 0) { wait = 0; }

            clearTimeout(timeout);
            timeout = setTimeout(destroyExpiredMessages, wait);
        });
        expiring.fetchNextExpiring();
    }

    Whisper.ExpiringMessagesListener = {
        init: function(events) {
            checkExpiringMessages();
            events.on('timetravel', checkExpiringMessages);
        },
        update: checkExpiringMessages
    };

    var TimerOption = Backbone.Model.extend({
      getName: function() {
        return i18n([
          'timerOption', this.get('time'), this.get('unit'),
        ].join('_')) || moment.duration(this.get('time'), this.get('unit')).humanize();
      },
      getAbbreviated: function() {
        return i18n([
          'timerOption', this.get('time'), this.get('unit'), 'abbreviated'
        ].join('_'));
      }
    });
    Whisper.ExpirationTimerOptions = new (Backbone.Collection.extend({
      model: TimerOption,
      getName: function(seconds) {
        if (!seconds) {
          seconds = 0;
        }
        var o = this.findWhere({seconds: seconds});
        if (o) { return o.getName(); }
        else {
          return [seconds, 'seconds'].join(' ');
        }
      },
      getAbbreviated: function(seconds) {
        if (!seconds) {
          seconds = 0;
        }
        var o = this.findWhere({seconds: seconds});
        if (o) { return o.getAbbreviated(); }
        else {
          return [seconds, 's'].join('');
        }
      }
    }))([
        [ 0,  'seconds'  ],
        [ 5,  'seconds'  ],
        [ 10, 'seconds'  ],
        [ 30, 'seconds'  ],
        [ 1,  'minute'   ],
        [ 5,  'minutes'  ],
        [ 30, 'minutes'  ],
        [ 1,  'hour'     ],
        [ 6,  'hours'    ],
        [ 12, 'hours'    ],
        [ 1,  'day'      ],
        [ 1,  'week'     ],
    ].map(function(o) {
      var duration = moment.duration(o[0], o[1]); // 5, 'seconds'
      return {
        time: o[0],
        unit: o[1],
        seconds: duration.asSeconds()
      };
    }));

})();
<commit_msg>Throttle expiring messages data query and deletion<commit_after>
/*
 * vim: ts=4:sw=4:expandtab
 */
;(function() {
    'use strict';
    window.Whisper = window.Whisper || {};

    function destroyExpiredMessages() {
        // Load messages that have expired and destroy them
        var expired = new Whisper.MessageCollection();
        expired.on('add', function(message) {
            console.log('message', message.get('sent_at'), 'expired');
            message.getConversation().trigger('expired', message);

            // We delete after the trigger to allow the conversation time to process
            //   the expiration before the message is removed from the database.
            message.destroy();
        });
        expired.on('reset', throttledCheckExpiringMessages);

        expired.fetchExpired();
    }

    var timeout;
    function checkExpiringMessages() {
        // Look up the next expiring message and set a timer to destroy it
        var expiring = new Whisper.MessageCollection();
        expiring.once('add', function(next) {
            var expires_at = next.get('expires_at');
            console.log('next message expires', new Date(expires_at).toISOString());

            var wait = expires_at - Date.now();
            if (wait < 0) { wait = 0; }

            clearTimeout(timeout);
            timeout = setTimeout(destroyExpiredMessages, wait);
        });
        expiring.fetchNextExpiring();
    }
    var throttledCheckExpiringMessages = _.throttle(checkExpiringMessages, 1000);

    Whisper.ExpiringMessagesListener = {
        init: function(events) {
            checkExpiringMessages();
            events.on('timetravel', throttledCheckExpiringMessages);
        },
        update: throttledCheckExpiringMessages
    };

    var TimerOption = Backbone.Model.extend({
      getName: function() {
        return i18n([
          'timerOption', this.get('time'), this.get('unit'),
        ].join('_')) || moment.duration(this.get('time'), this.get('unit')).humanize();
      },
      getAbbreviated: function() {
        return i18n([
          'timerOption', this.get('time'), this.get('unit'), 'abbreviated'
        ].join('_'));
      }
    });
    Whisper.ExpirationTimerOptions = new (Backbone.Collection.extend({
      model: TimerOption,
      getName: function(seconds) {
        if (!seconds) {
          seconds = 0;
        }
        var o = this.findWhere({seconds: seconds});
        if (o) { return o.getName(); }
        else {
          return [seconds, 'seconds'].join(' ');
        }
      },
      getAbbreviated: function(seconds) {
        if (!seconds) {
          seconds = 0;
        }
        var o = this.findWhere({seconds: seconds});
        if (o) { return o.getAbbreviated(); }
        else {
          return [seconds, 's'].join('');
        }
      }
    }))([
        [ 0,  'seconds'  ],
        [ 5,  'seconds'  ],
        [ 10, 'seconds'  ],
        [ 30, 'seconds'  ],
        [ 1,  'minute'   ],
        [ 5,  'minutes'  ],
        [ 30, 'minutes'  ],
        [ 1,  'hour'     ],
        [ 6,  'hours'    ],
        [ 12, 'hours'    ],
        [ 1,  'day'      ],
        [ 1,  'week'     ],
    ].map(function(o) {
      var duration = moment.duration(o[0], o[1]); // 5, 'seconds'
      return {
        time: o[0],
        unit: o[1],
        seconds: duration.asSeconds()
      };
    }));

})();
<|endoftext|>


<commit_before>(function () {
    'use strict';
    /** @ngInject */
    function npMediaElementDirective($log) {
        $log.debug('\nnpReveal mediaelementDirective::Init\n');
        var Directive = function () {
            this.restrict = 'A';
            this.link = function (scope, element, attrs, controller) {
            };
        };
        return new Directive();
    }
    angular
            .module('newplayer.component')
            .controller('npRevealController',
                    function ($log, $scope, $sce, $element) {
                        var cmpData = $scope.component.data,
                                revealItems = $scope.component.revealItems,
                                revealItemsIndex = $scope.component.idx,
                                revealItemsButtonImage = $scope.component.revealItems.buttonImage;
                        var buttonData = $scope.feedback || {};
                        this.revealItems = $scope.component.revealItems;
                        this.revealItemComponent = $scope.component.revealItems[0];
                        this.revealItemComponents = $scope.component.revealItems;
                        this.revealItemVideoType = $scope.component.baseURL;
                        this.id = cmpData.id;
                        this.baseURL = cmpData.baseURL;
                        this.src = cmpData.image;
                        $scope.feedback = this.feedback = cmpData.feedback;
                        $scope.image = this.image = cmpData.image;
                        $log.debug('npReveal::data', cmpData, buttonData);
                        //////////////////////////////////////////////////////////////////////////////////////
                        //get ready
                        //////////////////////////////////////////////////////////////////////////////////////
                        setTimeout(function () {
                            $scope.$apply(function () {
                                //////////////////////////////////////////////////////////////////////////////////////
                                //on ready set states
                                //////////////////////////////////////////////////////////////////////////////////////
                                var maxHeight = 0;
                                $(".reveal-wrapper").each(function () {
                                    if ($(this).outerHeight() > maxHeight) {
                                        maxHeight = ($(this).outerHeight() + 500);
                                    }
                                });
                                $(".np-reveal").height(maxHeight);
                                TweenMax.to($(".reveal-object"), 0, {
                                    opacity: 0
                                });
                                TweenMax.set($(".reveal-button"), {
                                    opacity: 0,
                                    scale: 0.25,
                                    force3D: true
                                });
                                //////////////////////////////////////////////////////////////////////////////////////
                                //build init state
                                //////////////////////////////////////////////////////////////////////////////////////
                                TweenMax.to($(".button-screen"), 1.5, {
                                    autoAlpha: 0.75,
                                    ease: Power4.easeOut
                                });
                                TweenMax.staggerTo($(".reveal-button"), 2, {
                                    scale: 1,
                                    opacity: 1,
                                    delay: 0.25,
                                    ease: Power4.easeOut,
                                    force3D: true
                                }, 0.2);
                                TweenMax.to($(".button-screen"), 1.5, {
                                    autoAlpha: 0.65,
                                    ease: Power4.easeOut
                                });
                                TweenMax.to($(".button-screen")[0], 1.75, {
                                    autoAlpha: 0,
                                    delay: 1.75,
                                    ease: Power4.easeOut
                                });
                                TweenMax.to($(".reveal-object")[0], 1.75, {
                                    autoAlpha: 1,
                                    delay: 1.75,
                                    ease: Power4.easeOut
//                                    onComplete: function () {
//
//                                    }
                                });
                            });
                        });
                        this.update = function (button) {
                            var idx = this.revealItems.indexOf(button);
                            //////////////////////////////////////////////////////////////////////////////////////
                            //on navigation change stop and reset all video files
                            //////////////////////////////////////////////////////////////////////////////////////
                            $('video').each(function () {
                                this.pause();
                                this.currentTime = 0;
                                this.load();
                            });
                            //////////////////////////////////////////////////////////////////////////////////////
                            //on navigation change cross fade items
                            //////////////////////////////////////////////////////////////////////////////////////
                            TweenMax.to($(".button-screen"), 1.5, {
                                autoAlpha: 0.75,
                                ease: Power4.easeOut
                            });
                            TweenMax.to($(".button-screen")[idx], 1.75, {
                                autoAlpha: 0,
                                ease: Power4.easeOut
                            });
                            TweenMax.to($(".reveal-object"), 1.5, {
                                autoAlpha: 0,
                                ease: Power4.easeOut
                            });
                            TweenMax.to($(".reveal-object")[idx], 1.75, {
                                autoAlpha: 1,
                                ease: Power4.easeOut
                            });
                        };
                    }
            )
            .directive('mediaelement', npMediaElementDirective)
            /** @ngInject */
            .run(
                    function ($log, $rootScope) {
                        $log.debug('npReveal::component loaded!');
                    }
            );
})();
<commit_msg>next button updates height fixes<commit_after>(function () {
    'use strict';
    /** @ngInject */
    function npMediaElementDirective($log) {
        $log.debug('\nnpReveal mediaelementDirective::Init\n');
        var Directive = function () {
            this.restrict = 'A';
            this.link = function (scope, element, attrs, controller) {
            };
        };
        return new Directive();
    }
    angular
            .module('newplayer.component')
            .controller('npRevealController',
                    function ($log, $scope, $sce, $element) {
                        var cmpData = $scope.component.data,
                                revealItems = $scope.component.revealItems,
                                revealItemsIndex = $scope.component.idx,
                                revealItemsButtonImage = $scope.component.revealItems.buttonImage;
                        var buttonData = $scope.feedback || {};
                        this.revealItems = $scope.component.revealItems;
                        this.revealItemComponent = $scope.component.revealItems[0];
                        this.revealItemComponents = $scope.component.revealItems;
                        this.revealItemVideoType = $scope.component.baseURL;
                        this.id = cmpData.id;
                        this.baseURL = cmpData.baseURL;
                        this.src = cmpData.image;
                        $scope.feedback = this.feedback = cmpData.feedback;
                        $scope.image = this.image = cmpData.image;
                        $log.debug('npReveal::data', cmpData, buttonData);
                        //////////////////////////////////////////////////////////////////////////////////////
                        //get ready
                        //////////////////////////////////////////////////////////////////////////////////////
                        setTimeout(function () {
                            $scope.$apply(function () {
                                //////////////////////////////////////////////////////////////////////////////////////
                                //on ready set states
                                //////////////////////////////////////////////////////////////////////////////////////
                                TweenMax.set($(".reveal-object"), {
                                    autoAlpha: 0
                                });
                                TweenMax.set($(".reveal-button"), {
                                    opacity: 0,
                                    scale: 0.25,
                                    force3D: true
                                });
                                //////////////////////////////////////////////////////////////////////////////////////
                                //get actuall height
                                //////////////////////////////////////////////////////////////////////////////////////
                                imagesLoaded(document.querySelector('.reveal-object'), function (instance) {
                                    var maxHeight = Math.max.apply(null, $('.reveal-wrapper').map(function () {
                                        return $(this).outerHeight(true);
                                    }).get());
                                    var outsidePaddingHeight = $('.np_outside-padding').outerHeight(true);
                                    TweenMax.set($('.reveal-wrapper'), {
                                        height: maxHeight
                                    });
                                    TweenMax.set($('.np_outside-padding'), {
                                        height: maxHeight
                                    });
                                    console.log(
                                            '\n::::::::::::::::::::::::::::::::::::::npFlashCards::maxHeight:::::::::::::::::::::::::::::::::::::::::::::::::',
                                            '\n::maxHeight:', maxHeight,
                                            '\n::outsidePaddingHeight:', outsidePaddingHeight,
                                            '\n::maxHeight + outsidePaddingHeight:', maxHeight + outsidePaddingHeight,
                                            '\n:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::'
                                            );
                                    //////////////////////////////////////////////////////////////////////////////////////
                                    //build init state
                                    //////////////////////////////////////////////////////////////////////////////////////
                                    TweenMax.to($(".button-screen"), 1.5, {
                                        autoAlpha: 0.75,
                                        ease: Power4.easeOut
                                    });
                                    TweenMax.staggerTo($(".reveal-button"), 2, {
                                        scale: 1,
                                        opacity: 1,
                                        delay: 0.25,
                                        ease: Power4.easeOut,
                                        force3D: true
                                    }, 0.2);
                                    TweenMax.to($(".button-screen"), 1.5, {
                                        autoAlpha: 0.65,
                                        ease: Power4.easeOut
                                    });
                                    TweenMax.to($(".button-screen")[0], 1.75, {
                                        autoAlpha: 0,
                                        delay: 1.75,
                                        ease: Power4.easeOut
                                    });
                                    TweenMax.to($(".reveal-object")[0], 1.75, {
                                        autoAlpha: 1,
                                        delay: 1.75,
                                        ease: Power4.easeOut
                                    });
                                });
                            });
                        });
                        this.update = function (button) {
                            var idx = this.revealItems.indexOf(button);
                            //////////////////////////////////////////////////////////////////////////////////////
                            //on navigation change stop and reset all video files
                            //////////////////////////////////////////////////////////////////////////////////////
                            $('video').each(function () {
                                this.pause();
                                this.currentTime = 0;
                                this.load();
                            });
                            //////////////////////////////////////////////////////////////////////////////////////
                            //on navigation change cross fade items
                            //////////////////////////////////////////////////////////////////////////////////////
                            TweenMax.to($(".button-screen"), 1.5, {
                                autoAlpha: 0.75,
                                ease: Power4.easeOut
                            });
                            TweenMax.to($(".button-screen")[idx], 1.75, {
                                autoAlpha: 0,
                                ease: Power4.easeOut
                            });
                            TweenMax.to($(".reveal-object"), 1.5, {
                                autoAlpha: 0,
                                ease: Power4.easeOut
                            });
                            TweenMax.to($(".reveal-object")[idx], 1.75, {
                                autoAlpha: 1,
                                ease: Power4.easeOut
                            });
                        };
                    }
            )
            .directive('mediaelement', npMediaElementDirective)
            /** @ngInject */
            .run(
                    function ($log, $rootScope) {
                        $log.debug('npReveal::component loaded!');
                    }
            );
})();
<|endoftext|>


<commit_before>import parseLocationHash from 'javascript/utility/parseLocationHash';
import setLocationHash from 'javascript/utility/setLocationHash';

import assign from 'lodash/assign'

const DEFAULT_CONFIG = {
  x_min: -2.0,
  x_max:  2.0,
  y_min: -1.25,
  y_max:  1.25,

  brightness: 4.0
};

const Config = {
  currentConfig: {},
  getConfig(locationHash = parseLocationHash()) {
    Config.currentConfig = assign({}, DEFAULT_CONFIG, locationHash);

    return Config.currentConfig;
  },
  setConfig(configChanges) {
    const newConfig = assign({}, Config.getConfig(), configChanges);

    setLocationHash(newConfig);
  }
};

export default Config;
<commit_msg>up the default brightness of the rendering<commit_after>import parseLocationHash from 'javascript/utility/parseLocationHash';
import setLocationHash from 'javascript/utility/setLocationHash';

import assign from 'lodash/assign'

const DEFAULT_CONFIG = {
  x_min: -2.0,
  x_max:  2.0,
  y_min: -1.25,
  y_max:  1.25,

  brightness: 8.0
};

const Config = {
  currentConfig: {},
  getConfig(locationHash = parseLocationHash()) {
    Config.currentConfig = assign({}, DEFAULT_CONFIG, locationHash);

    return Config.currentConfig;
  },
  setConfig(configChanges) {
    const newConfig = assign({}, Config.getConfig(), configChanges);

    setLocationHash(newConfig);
  }
};

export default Config;
<|endoftext|>


<commit_before>/**
 * Sticky module.
 * @module foundation.sticky
 * @requires foundation.util.triggers
 * @requires foundation.util.mediaQuery
 */
!function($, Foundation){
  'use strict';

  /**
   * Creates a new instance of a sticky thing.
   * @class
   * @param {jQuery} element - jQuery object to make sticky.
   * @param {Object} options - options object passed when creating the element programmatically.
   */
  function Sticky(element, options){
    this.$element = element;
    this.options = $.extend({}, Sticky.defaults, this.$element.data(), options);

    this._init();

    Foundation.registerPlugin(this, 'Sticky');
  }
  Sticky.defaults = {
    /**
     * Customizable container template. Add your own classes for styling and sizing.
     * @option
     * @example '

'
     */
    container: '

',
    /**
     * Location in the view the element sticks to.
     * @option
     * @example 'top'
     */
    stickTo: 'top',
    /**
     * If anchored to a single element, the id of that element.
     * @option
     * @example 'exampleId'
     */
    anchor: '',
    /**
     * If using more than one element as anchor points, the id of the top anchor.
     * @option
     * @example 'exampleId:top'
     */
    topAnchor: '',
    /**
     * If using more than one element as anchor points, the id of the bottom anchor.
     * @option
     * @example 'exampleId:bottom'
     */
    btmAnchor: '',
    /**
     * Margin, in `em`'s to apply to the top of the element when it becomes sticky.
     * @option
     * @example 1
     */
    marginTop: 1,
    /**
     * Margin, in `em`'s to apply to the bottom of the element when it becomes sticky.
     * @option
     * @example 1
     */
    marginBottom: 1,
    /**
     * Breakpoint string that is the minimum screen size an element should become sticky.
     * @option
     * @example 'medium'
     */
    stickyOn: 'medium',
    /**
     * Class applied to sticky element, and removed on destruction. Foundation defaults to `sticky`.
     * @option
     * @example 'sticky'
     */
    stickyClass: 'sticky',
    /**
     * Class applied to sticky container. Foundation defaults to `sticky-container`.
     * @option
     * @example 'sticky-container'
     */
    containerClass: 'sticky-container',
    /**
     * Number of scroll events between the plugin's recalculating sticky points. Setting it to `0` will cause it to recalc every scroll event, setting it to `-1` will prevent recalc on scroll.
     * @option
     * @example 50
     */
    checkEvery: -1
  };

  /**
   * Initializes the sticky element by adding classes, getting/setting dimensions, breakpoints and attributes
   * @function
   * @private
   */
  Sticky.prototype._init = function(){
    var $parent = this.$element.parent('[data-sticky-container]'),
        id = this.$element[0].id || Foundation.GetYoDigits(6, 'sticky'),
        _this = this;

    if(!$parent.length){
      this.wasWrapped = true;
    }
    this.$container = $parent.length ? $parent : $(this.options.container).wrapInner(this.$element);
    this.$container.addClass(this.options.containerClass);

    this.$element.addClass(this.options.stickyClass)
                 .attr({'data-resize': id});

    this.scrollCount = this.options.checkEvery;
    this.isStuck = false;

    if(this.options.anchor !== ''){
      this.$anchor = $(`#${this.options.anchor}`);
    }else{
      this._parsePoints();
    }

    this._setSizes(function(){
      _this._calc(false);
    });
    this._events(id.split('-').reverse().join('-'));
  };
  /**
   * If using multiple elements as anchors, calculates the top and bottom pixel values the sticky thing should stick and unstick on.
   * @function
   * @private
   */
  Sticky.prototype._parsePoints = function(){
    var top = this.options.topAnchor,
        btm = this.options.btmAnchor,
        pts = [top, btm],
        breaks = {};
    if(top && btm){

      for(var i = 0, len = pts.length; i < len && pts[i]; i++){
        var pt;
        if(typeof pts[i] === 'number'){
          pt = pts[i];
        }else{
          var place = pts[i].split(':'),
              anchor = $(`#${place[0]}`);

          pt = anchor.offset().top;
          if(place[1] && place[1].toLowerCase() === 'bottom'){
            pt += anchor[0].getBoundingClientRect().height;
          }
        }
        breaks[i] = pt;
      }
    }else{
      breaks = {0: 1, 1: document.documentElement.scrollHeight};
    }

    this.points = breaks;
    return;
  };

  /**
   * Adds event handlers for the scrolling element.
   * @private
   * @param {String} id - psuedo-random id for unique scroll event listener.
   */
  Sticky.prototype._events = function(id){
    var _this = this,
        scrollListener = this.scrollListener = `scroll.zf.${id}`;
    if(this.isOn){ return; }
    if(this.canStick){
      this.isOn = true;
      $(window).off(scrollListener)
               .on(scrollListener, function(e){
                 if(_this.scrollCount === 0){
                   _this.scrollCount = _this.options.checkEvery;
                   _this._setSizes(function(){
                     _this._calc(false, window.pageYOffset);
                   });
                 }else{
                   _this.scrollCount--;
                   _this._calc(false, window.pageYOffset);
                 }
              });
    }

    this.$element.off('resizeme.zf.trigger')
                 .on('resizeme.zf.trigger', function(e, el){
                     _this._setSizes(function(){
                       _this._calc(false);
                       if(_this.canStick){
                         if(!_this.isOn){
                           _this._events(id);
                         }
                       }else if(_this.isOn){
                         _this._pauseListeners(scrollListener);
                       }
                     });
    });
  };

  /**
   * Removes event handlers for scroll and change events on anchor.
   * @fires Sticky#pause
   * @param {String} scrollListener - unique, namespaced scroll listener attached to `window`
   */
  Sticky.prototype._pauseListeners = function(scrollListener){
    this.isOn = false;
    $(window).off(scrollListener);

    /**
     * Fires when the plugin is paused due to resize event shrinking the view.
     * @event Sticky#pause
     * @private
     */
     this.$element.trigger('pause.zf.sticky');
  };

  /**
   * Called on every `scroll` event and on `_init`
   * fires functions based on booleans and cached values
   * @param {Boolean} checkSizes - true if plugin should recalculate sizes and breakpoints.
   * @param {Number} scroll - current scroll position passed from scroll event cb function. If not passed, defaults to `window.pageYOffset`.
   */
  Sticky.prototype._calc = function(checkSizes, scroll){
    if(checkSizes){ this._setSizes(); }

    if(!this.canStick){
      if(this.isStuck){
        this._removeSticky(true);
      }
      return false;
    }

    if(!scroll){ scroll = window.pageYOffset; }

    if(scroll >= this.topPoint){
      if(scroll <= this.bottomPoint){
        if(!this.isStuck){
          this._setSticky();
        }
      }else{
        if(this.isStuck){
          this._removeSticky(false);
        }
      }
    }else{
      if(this.isStuck){
        this._removeSticky(true);
      }
    }
  };
  /**
   * Causes the $element to become stuck.
   * Adds `position: fixed;`, and helper classes.
   * @fires Sticky#stuckto
   * @function
   * @private
   */
  Sticky.prototype._setSticky = function(){
    var stickTo = this.options.stickTo,
        mrgn = stickTo === 'top' ? 'marginTop' : 'marginBottom',
        notStuckTo = stickTo === 'top' ? 'bottom' : 'top',
        css = {};

    css[mrgn] = `${this.options[mrgn]}em`;
    css[stickTo] = 0;
    css[notStuckTo] = 'auto';
    css['left'] = this.$container.offset().left + parseInt(window.getComputedStyle(this.$container[0])["padding-left"], 10);
    this.isStuck = true;
    this.$element.removeClass(`is-anchored is-at-${notStuckTo}`)
                 .addClass(`is-stuck is-at-${stickTo}`)
                 .css(css)
                 /**
                  * Fires when the $element has become `position: fixed;`
                  * Namespaced to `top` or `bottom`.
                  * @event Sticky#stuckto
                  */
                 .trigger(`sticky.zf.stuckto:${stickTo}`);
  };

  /**
   * Causes the $element to become unstuck.
   * Removes `position: fixed;`, and helper classes.
   * Adds other helper classes.
   * @param {Boolean} isTop - tells the function if the $element should anchor to the top or bottom of its $anchor element.
   * @fires Sticky#unstuckfrom
   * @private
   */
  Sticky.prototype._removeSticky = function(isTop){
    var stickTo = this.options.stickTo,
        stickToTop = stickTo === 'top',
        css = {},
        anchorPt = (this.points ? this.points[1] - this.points[0] : this.anchorHeight) - this.elemHeight,
        mrgn = stickToTop ? 'marginTop' : 'marginBottom',
        notStuckTo = stickToTop ? 'bottom' : 'top',
        topOrBottom = isTop ? 'top' : 'bottom';

    css[mrgn] = 0;

    if((isTop && !stickToTop) || (stickToTop && !isTop)){
      css[stickTo] = anchorPt;
      css[notStuckTo] = 0;
    }else{
      css[stickTo] = 0;
      css[notStuckTo] = anchorPt;
    }

    css['left'] = '';
    this.isStuck = false;
    this.$element.removeClass(`is-stuck is-at-${stickTo}`)
                 .addClass(`is-anchored is-at-${topOrBottom}`)
                 .css(css)
                 /**
                  * Fires when the $element has become anchored.
                  * Namespaced to `top` or `bottom`.
                  * @event Sticky#unstuckfrom
                  */
                 .trigger(`sticky.zf.unstuckfrom:${topOrBottom}`);
  };

  /**
   * Sets the $element and $container sizes for plugin.
   * Calls `_setBreakPoints`.
   * @param {Function} cb - optional callback function to fire on completion of `_setBreakPoints`.
   * @private
   */
  Sticky.prototype._setSizes = function(cb){
    this.canStick = Foundation.MediaQuery.atLeast(this.options.stickyOn);
    if(!this.canStick){ cb(); }
    var _this = this,
        newElemWidth = this.$container[0].getBoundingClientRect().width,
        comp = window.getComputedStyle(this.$container[0]),
        pdng = parseInt(comp['padding-right'], 10);

    if(this.$anchor && this.$anchor.length){
      this.anchorHeight = this.$anchor[0].getBoundingClientRect().height;
    }else{
      this._parsePoints();
    }

    this.$element.css({
      'max-width': `${newElemWidth - pdng}px`
    });

    var newContainerHeight = this.$element[0].getBoundingClientRect().height || this.containerHeight;
    this.containerHeight = newContainerHeight;
    this.$container.css({
      height: newContainerHeight
    });
    this.elemHeight = newContainerHeight;

  	if (this.isStuck) {
  		this.$element.css({"left":this.$container.offset().left + parseInt(comp['padding-left'], 10)});
  	}

    this._setBreakPoints(newContainerHeight, function(){
      if(cb){ cb(); }
    });

  };
  /**
   * Sets the upper and lower breakpoints for the element to become sticky/unsticky.
   * @param {Number} elemHeight - px value for sticky.$element height, calculated by `_setSizes`.
   * @param {Function} cb - optional callback function to be called on completion.
   * @private
   */
  Sticky.prototype._setBreakPoints = function(elemHeight, cb){
    if(!this.canStick){
      if(cb){ cb(); }
      else{ return false; }
    }
    var mTop = emCalc(this.options.marginTop),
        mBtm = emCalc(this.options.marginBottom),
        topPoint = this.points ? this.points[0] : this.$anchor.offset().top,
        bottomPoint = this.points ? this.points[1] : topPoint + this.anchorHeight,
        // topPoint = this.$anchor.offset().top || this.points[0],
        // bottomPoint = topPoint + this.anchorHeight || this.points[1],
        winHeight = window.innerHeight;

    if(this.options.stickTo === 'top'){
      topPoint -= mTop;
      bottomPoint -= (elemHeight + mTop);
    }else if(this.options.stickTo === 'bottom'){
      topPoint -= (winHeight - (elemHeight + mBtm));
      bottomPoint -= (winHeight - mBtm);
    }else{
      //this would be the stickTo: both option... tricky
    }

    this.topPoint = topPoint;
    this.bottomPoint = bottomPoint;

    if(cb){ cb(); }
  };

  /**
   * Destroys the current sticky element.
   * Resets the element to the top position first.
   * Removes event listeners, JS-added css properties and classes, and unwraps the $element if the JS added the $container.
   * @function
   */
  Sticky.prototype.destroy = function(){
    this._removeSticky(true);

    this.$element.removeClass(`${this.options.stickyClass} is-anchored is-at-top`)
                 .css({
                   height: '',
                   top: '',
                   bottom: '',
                   'max-width': ''
                 })
                 .off('resizeme.zf.trigger');

    this.$anchor.off('change.zf.sticky');
    $(window).off(this.scrollListener);

    if(this.wasWrapped){
      this.$element.unwrap();
    }else{
      this.$container.removeClass(this.options.containerClass)
                     .css({
                       height: ''
                     });
    }
    Foundation.unregisterPlugin(this);
  };
  /**
   * Helper function to calculate em values
   * @param Number {em} - number of em's to calculate into pixels
   */
  function emCalc(em){
    return parseInt(window.getComputedStyle(document.body, null).fontSize, 10) * em;
  }
  Foundation.plugin(Sticky, 'Sticky');
}(jQuery, window.Foundation);
<commit_msg>Convert sticky to ES6 class<commit_after>'use strict';

/**
 * Sticky module.
 * @module foundation.sticky
 * @requires foundation.util.triggers
 * @requires foundation.util.mediaQuery
 */

export default class Sticky {
  /**
   * Creates a new instance of a sticky thing.
   * @class
   * @param {jQuery} element - jQuery object to make sticky.
   * @param {Object} options - options object passed when creating the element programmatically.
   */
  constructor(element, options) {
    this.$element = element;
    this.options = $.extend({}, Sticky.defaults, this.$element.data(), options);

    this._init();

    Foundation.registerPlugin(this, 'Sticky');
  }

  /**
   * Initializes the sticky element by adding classes, getting/setting dimensions, breakpoints and attributes
   * @function
   * @private
   */
  _init() {
    var $parent = this.$element.parent('[data-sticky-container]'),
        id = this.$element[0].id || Foundation.GetYoDigits(6, 'sticky'),
        _this = this;

    if (!$parent.length) {
      this.wasWrapped = true;
    }
    this.$container = $parent.length ? $parent : $(this.options.container).wrapInner(this.$element);
    this.$container.addClass(this.options.containerClass);

    this.$element.addClass(this.options.stickyClass)
                 .attr({'data-resize': id});

    this.scrollCount = this.options.checkEvery;
    this.isStuck = false;

    if (this.options.anchor !== '') {
      this.$anchor = $(`#${this.options.anchor}`);
    } else {
      this._parsePoints();
    }

    this._setSizes(function() {
      _this._calc(false);
    });
    this._events(id.split('-').reverse().join('-'));
  }

  /**
   * If using multiple elements as anchors, calculates the top and bottom pixel values the sticky thing should stick and unstick on.
   * @function
   * @private
   */
  _parsePoints() {
    var top = this.options.topAnchor,
        btm = this.options.btmAnchor,
        pts = [top, btm],
        breaks = {};
    if (top && btm) {

      for (var i = 0, len = pts.length; i < len && pts[i]; i++) {
        var pt;
        if (typeof pts[i] === 'number') {
          pt = pts[i];
        } else {
          var place = pts[i].split(':'),
              anchor = $(`#${place[0]}`);

          pt = anchor.offset().top;
          if (place[1] && place[1].toLowerCase() === 'bottom') {
            pt += anchor[0].getBoundingClientRect().height;
          }
        }
        breaks[i] = pt;
      }
    } else {
      breaks = {0: 1, 1: document.documentElement.scrollHeight};
    }

    this.points = breaks;
    return;
  }

  /**
   * Adds event handlers for the scrolling element.
   * @private
   * @param {String} id - psuedo-random id for unique scroll event listener.
   */
  _events(id) {
    var _this = this,
        scrollListener = this.scrollListener = `scroll.zf.${id}`;
    if (this.isOn) { return; }
    if (this.canStick) {
      this.isOn = true;
      $(window).off(scrollListener)
               .on(scrollListener, function(e) {
                 if (_this.scrollCount === 0) {
                   _this.scrollCount = _this.options.checkEvery;
                   _this._setSizes(function() {
                     _this._calc(false, window.pageYOffset);
                   });
                 } else {
                   _this.scrollCount--;
                   _this._calc(false, window.pageYOffset);
                 }
              });
    }

    this.$element.off('resizeme.zf.trigger')
                 .on('resizeme.zf.trigger', function(e, el) {
                     _this._setSizes(function() {
                       _this._calc(false);
                       if (_this.canStick) {
                         if (!_this.isOn) {
                           _this._events(id);
                         }
                       } else if (_this.isOn) {
                         _this._pauseListeners(scrollListener);
                       }
                     });
    });
  }

  /**
   * Removes event handlers for scroll and change events on anchor.
   * @fires Sticky#pause
   * @param {String} scrollListener - unique, namespaced scroll listener attached to `window`
   */
  _pauseListeners(scrollListener) {
    this.isOn = false;
    $(window).off(scrollListener);

    /**
     * Fires when the plugin is paused due to resize event shrinking the view.
     * @event Sticky#pause
     * @private
     */
     this.$element.trigger('pause.zf.sticky');
  }

  /**
   * Called on every `scroll` event and on `_init`
   * fires functions based on booleans and cached values
   * @param {Boolean} checkSizes - true if plugin should recalculate sizes and breakpoints.
   * @param {Number} scroll - current scroll position passed from scroll event cb function. If not passed, defaults to `window.pageYOffset`.
   */
  _calc(checkSizes, scroll) {
    if (checkSizes) { this._setSizes(); }

    if (!this.canStick) {
      if (this.isStuck) {
        this._removeSticky(true);
      }
      return false;
    }

    if (!scroll) { scroll = window.pageYOffset; }

    if (scroll >= this.topPoint) {
      if (scroll <= this.bottomPoint) {
        if (!this.isStuck) {
          this._setSticky();
        }
      } else {
        if (this.isStuck) {
          this._removeSticky(false);
        }
      }
    } else {
      if (this.isStuck) {
        this._removeSticky(true);
      }
    }
  }

  /**
   * Causes the $element to become stuck.
   * Adds `position: fixed;`, and helper classes.
   * @fires Sticky#stuckto
   * @function
   * @private
   */
  _setSticky() {
    var stickTo = this.options.stickTo,
        mrgn = stickTo === 'top' ? 'marginTop' : 'marginBottom',
        notStuckTo = stickTo === 'top' ? 'bottom' : 'top',
        css = {};

    css[mrgn] = `${this.options[mrgn]}em`;
    css[stickTo] = 0;
    css[notStuckTo] = 'auto';
    css['left'] = this.$container.offset().left + parseInt(window.getComputedStyle(this.$container[0])["padding-left"], 10);
    this.isStuck = true;
    this.$element.removeClass(`is-anchored is-at-${notStuckTo}`)
                 .addClass(`is-stuck is-at-${stickTo}`)
                 .css(css)
                 /**
                  * Fires when the $element has become `position: fixed;`
                  * Namespaced to `top` or `bottom`.
                  * @event Sticky#stuckto
                  */
                 .trigger(`sticky.zf.stuckto:${stickTo}`);
  }

  /**
   * Causes the $element to become unstuck.
   * Removes `position: fixed;`, and helper classes.
   * Adds other helper classes.
   * @param {Boolean} isTop - tells the function if the $element should anchor to the top or bottom of its $anchor element.
   * @fires Sticky#unstuckfrom
   * @private
   */
  _removeSticky(isTop) {
    var stickTo = this.options.stickTo,
        stickToTop = stickTo === 'top',
        css = {},
        anchorPt = (this.points ? this.points[1] - this.points[0] : this.anchorHeight) - this.elemHeight,
        mrgn = stickToTop ? 'marginTop' : 'marginBottom',
        notStuckTo = stickToTop ? 'bottom' : 'top',
        topOrBottom = isTop ? 'top' : 'bottom';

    css[mrgn] = 0;

    if ((isTop && !stickToTop) || (stickToTop && !isTop)) {
      css[stickTo] = anchorPt;
      css[notStuckTo] = 0;
    } else {
      css[stickTo] = 0;
      css[notStuckTo] = anchorPt;
    }

    css['left'] = '';
    this.isStuck = false;
    this.$element.removeClass(`is-stuck is-at-${stickTo}`)
                 .addClass(`is-anchored is-at-${topOrBottom}`)
                 .css(css)
                 /**
                  * Fires when the $element has become anchored.
                  * Namespaced to `top` or `bottom`.
                  * @event Sticky#unstuckfrom
                  */
                 .trigger(`sticky.zf.unstuckfrom:${topOrBottom}`);
  }

  /**
   * Sets the $element and $container sizes for plugin.
   * Calls `_setBreakPoints`.
   * @param {Function} cb - optional callback function to fire on completion of `_setBreakPoints`.
   * @private
   */
  _setSizes(cb) {
    this.canStick = Foundation.MediaQuery.atLeast(this.options.stickyOn);
    if (!this.canStick) { cb(); }
    var _this = this,
        newElemWidth = this.$container[0].getBoundingClientRect().width,
        comp = window.getComputedStyle(this.$container[0]),
        pdng = parseInt(comp['padding-right'], 10);

    if (this.$anchor && this.$anchor.length) {
      this.anchorHeight = this.$anchor[0].getBoundingClientRect().height;
    } else {
      this._parsePoints();
    }

    this.$element.css({
      'max-width': `${newElemWidth - pdng}px`
    });

    var newContainerHeight = this.$element[0].getBoundingClientRect().height || this.containerHeight;
    this.containerHeight = newContainerHeight;
    this.$container.css({
      height: newContainerHeight
    });
    this.elemHeight = newContainerHeight;

  	if (this.isStuck) {
  		this.$element.css({"left":this.$container.offset().left + parseInt(comp['padding-left'], 10)});
  	}

    this._setBreakPoints(newContainerHeight, function() {
      if (cb) { cb(); }
    });
  }

  /**
   * Sets the upper and lower breakpoints for the element to become sticky/unsticky.
   * @param {Number} elemHeight - px value for sticky.$element height, calculated by `_setSizes`.
   * @param {Function} cb - optional callback function to be called on completion.
   * @private
   */
  _setBreakPoints(elemHeight, cb) {
    if (!this.canStick) {
      if (cb) { cb(); }
      else { return false; }
    }
    var mTop = emCalc(this.options.marginTop),
        mBtm = emCalc(this.options.marginBottom),
        topPoint = this.points ? this.points[0] : this.$anchor.offset().top,
        bottomPoint = this.points ? this.points[1] : topPoint + this.anchorHeight,
        // topPoint = this.$anchor.offset().top || this.points[0],
        // bottomPoint = topPoint + this.anchorHeight || this.points[1],
        winHeight = window.innerHeight;

    if (this.options.stickTo === 'top') {
      topPoint -= mTop;
      bottomPoint -= (elemHeight + mTop);
    } else if (this.options.stickTo === 'bottom') {
      topPoint -= (winHeight - (elemHeight + mBtm));
      bottomPoint -= (winHeight - mBtm);
    } else {
      //this would be the stickTo: both option... tricky
    }

    this.topPoint = topPoint;
    this.bottomPoint = bottomPoint;

    if (cb) { cb(); }
  }

  /**
   * Destroys the current sticky element.
   * Resets the element to the top position first.
   * Removes event listeners, JS-added css properties and classes, and unwraps the $element if the JS added the $container.
   * @function
   */
  destroy() {
    this._removeSticky(true);

    this.$element.removeClass(`${this.options.stickyClass} is-anchored is-at-top`)
                 .css({
                   height: '',
                   top: '',
                   bottom: '',
                   'max-width': ''
                 })
                 .off('resizeme.zf.trigger');

    this.$anchor.off('change.zf.sticky');
    $(window).off(this.scrollListener);

    if (this.wasWrapped) {
      this.$element.unwrap();
    } else {
      this.$container.removeClass(this.options.containerClass)
                     .css({
                       height: ''
                     });
    }
    Foundation.unregisterPlugin(this);
  }
}

Sticky.defaults = {
  /**
   * Customizable container template. Add your own classes for styling and sizing.
   * @option
   * @example '

'
   */
  container: '

',
  /**
   * Location in the view the element sticks to.
   * @option
   * @example 'top'
   */
  stickTo: 'top',
  /**
   * If anchored to a single element, the id of that element.
   * @option
   * @example 'exampleId'
   */
  anchor: '',
  /**
   * If using more than one element as anchor points, the id of the top anchor.
   * @option
   * @example 'exampleId:top'
   */
  topAnchor: '',
  /**
   * If using more than one element as anchor points, the id of the bottom anchor.
   * @option
   * @example 'exampleId:bottom'
   */
  btmAnchor: '',
  /**
   * Margin, in `em`'s to apply to the top of the element when it becomes sticky.
   * @option
   * @example 1
   */
  marginTop: 1,
  /**
   * Margin, in `em`'s to apply to the bottom of the element when it becomes sticky.
   * @option
   * @example 1
   */
  marginBottom: 1,
  /**
   * Breakpoint string that is the minimum screen size an element should become sticky.
   * @option
   * @example 'medium'
   */
  stickyOn: 'medium',
  /**
   * Class applied to sticky element, and removed on destruction. Foundation defaults to `sticky`.
   * @option
   * @example 'sticky'
   */
  stickyClass: 'sticky',
  /**
   * Class applied to sticky container. Foundation defaults to `sticky-container`.
   * @option
   * @example 'sticky-container'
   */
  containerClass: 'sticky-container',
  /**
   * Number of scroll events between the plugin's recalculating sticky points. Setting it to `0` will cause it to recalc every scroll event, setting it to `-1` will prevent recalc on scroll.
   * @option
   * @example 50
   */
  checkEvery: -1
};

/**
 * Helper function to calculate em values
 * @param Number {em} - number of em's to calculate into pixels
 */
function emCalc(em) {
  return parseInt(window.getComputedStyle(document.body, null).fontSize, 10) * em;
}

// Window exports
if (window.Foundation) {
  window.Foundation.plugin(Sticky, 'Sticky');
}
<|endoftext|>


<commit_before>'use strict';

/*
 * Controllers for development topics management.
 * Pay attention to injection of dependencies (factories, entities and Angular objects).
 */
angular.module('appverseClientIncubatorApp')
  .controller('TopicsController',
      function ($scope,   $state,   topics,   utils) {
                // Add a 'topics' field in this abstract parent's scope, so that all
                // child state views can access it in their scopes. Please note: scope
                // inheritance is not due to nesting of states, but rather choosing to
                // nest the templates of those states. It's normal scope inheritance.
                $scope.topics = topics;

                $scope.goToRandom = function () {
                  var randId = utils.newRandomKey($scope.topics, "id", $state.params.topicId);
                  // $state.go() can be used as a high level convenience method
                  // for activating a state programmatically.
                  $state.go('topics.detail', { topicId: randId });
                };
  })
 .controller('TopicDetailsController',
      function (  $scope,   $stateParams,   utils) {
                    $scope.topic = utils.findById($scope.topics, $stateParams.topicId);
                })
 .controller('TopicDetailsItemController',
      function (  $scope,   $stateParams,   $state,   utils) {
                    $scope.item = utils.findById($scope.topic.items, $stateParams.itemId);

                    $scope.edit = function () {
                      // Here we show off go's ability to navigate to a relative state. Using '^' to go upwards
                      // and '.' to go down, you can navigate to any relative state (ancestor or descendant).
                      // Here we are going down to the child state 'edit' (full name of 'topics.detail.item.edit')
                      $state.go('.edit', $stateParams);
                    };
                  })
.controller('TopicDetailsItemEditController',
     function (  $scope,   $stateParams,   $state,   utils) {
                    $scope.item = utils.findById($scope.topic.items, $stateParams.itemId);
                    $scope.done = function () {
                      // Go back up. '^' means up one. '^.^' would be up twice, to the grandparent.
                      $state.go('^', $stateParams);
                    };
                  });<commit_msg>- Added controller for the translation state<commit_after>'use strict';

/*
 * Controllers for development topics management.
 * Pay attention to injection of dependencies (factories, entities and Angular objects).
 */
angular.module('appverseClientIncubatorApp')
  .controller('TopicsController',
      function ($scope,   $state,   topics,   utils) {
                // Add a 'topics' field in this abstract parent's scope, so that all
                // child state views can access it in their scopes. Please note: scope
                // inheritance is not due to nesting of states, but rather choosing to
                // nest the templates of those states. It's normal scope inheritance.
                $scope.topics = topics;

                $scope.goToRandom = function () {
                  var randId = utils.newRandomKey($scope.topics, "id", $state.params.topicId);
                  // $state.go() can be used as a high level convenience method
                  // for activating a state programmatically.
                  $state.go('topics.detail', { topicId: randId });
                };
  })
 .controller('TopicDetailsController',
      function (  $scope,   $stateParams,   utils) {
                    $scope.topic = utils.findById($scope.topics, $stateParams.topicId);
                })
 .controller('TopicDetailsItemController',
      function (  $scope,   $stateParams,   $state,   utils) {
                    $scope.item = utils.findById($scope.topic.items, $stateParams.itemId);

                    $scope.edit = function () {
                      // Here we show off go's ability to navigate to a relative state. Using '^' to go upwards
                      // and '.' to go down, you can navigate to any relative state (ancestor or descendant).
                      // Here we are going down to the child state 'edit' (full name of 'topics.detail.item.edit')
                      $state.go('.edit', $stateParams);
                    };
                  })
.controller('TopicDetailsItemEditController',
     function (  $scope,   $stateParams,   $state,   utils) {
                    $scope.item = utils.findById($scope.topic.items, $stateParams.itemId);
                    $scope.done = function () {
                      // Go back up. '^' means up one. '^.^' would be up twice, to the grandparent.
                      $state.go('^', $stateParams);
                    };
                  })

.controller('translationController', ['$scope', '$translate',
     function ( $scope, $translate ) {

                    $scope.now = new Date();
                    $scope.name = 'Alex';
                    $scope.age = '20';

                    $scope.setLocale = function(locale) {
                        $translate.uses(locale);
                    };
                  }]);
<|endoftext|>