<commit_before>/*
 *  jquery-boilerplate - v4.0.0
 *  A jump-start for jQuery plugins development.
 *  http://jqueryboilerplate.com
 *
 *  Made by Zeno Rocha
 *  Under MIT License
 */
;( function( $, window, document, undefined ) {

    "use strict";

    // Create the defaults once
    var pluginName = "jqGeojsonField",
        defaults   = {
            inputSelector: "",
            zoom:          13,
            maxzoom:       18,
            lat:           48.856578,
            long:          2.351828,
            polyline:      true,
            polygon:       true,
            marker:        true,
            circle:        false,
            rectangle:     false,
            remove:        true,
            style:         false
        };

    // The actual plugin constructor
    function Plugin ( element, options ) {
        this.element    = element;
        this.settings   = $.extend( {}, defaults, options );
        this._defaults  = defaults;
        this._name      = pluginName;
        this.$input     = $(this.settings.inputSelector);
        this.map        = undefined;
        this.drawnItems = undefined;

        this.init();
    }

    // Avoid Plugin.prototype conflicts
    $.extend( Plugin.prototype, {
        init: function() {
            this.loadSettingsFromDataAttributes();
            this.createMap();
            this.addDrawEditor();

            if (this.settings.style) {
                this.addStyleEditor();
            }
        },
        loadSettingsFromDataAttributes: function() {
            var defaults = $(this.element).data();

            if (defaults.hasOwnProperty('geojsonfieldZoom') )      { this.settings.zoom = defaults.geojsonfieldZoom; }
            if (defaults.hasOwnProperty('geojsonfieldMaxzoom') )   { this.settings.maxzoom = defaults.geojsonfieldMaxzoom; }
            if (defaults.hasOwnProperty('geojsonfieldLat') )       { this.settings.lat = defaults.geojsonfieldLat; }
            if (defaults.hasOwnProperty('geojsonfieldLong') )      { this.settings.long = defaults.geojsonfieldLong; }
            if (defaults.hasOwnProperty('geojsonfieldPolyline') )  { this.settings.polyline = defaults.geojsonfieldPolyline; }
            if (defaults.hasOwnProperty('geojsonfieldPolygon') )   { this.settings.polygon = defaults.geojsonfieldPolygon; }
            if (defaults.hasOwnProperty('geojsonfieldMarker') )    { this.settings.marker = defaults.geojsonfieldMarker; }
            if (defaults.hasOwnProperty('geojsonfieldCircle') )    { this.settings.circle = defaults.geojsonfieldCircle; }
            if (defaults.hasOwnProperty('geojsonfieldRectangle') ) { this.settings.rectangle = defaults.geojsonfieldRectangle; }
            if (defaults.hasOwnProperty('geojsonfieldRemove') )    { this.settings.remove = defaults.geojsonfieldRemove; }
            if (defaults.hasOwnProperty('geojsonfieldStyle') )     { this.settings.style = defaults.geojsonfieldStyle; }
        },
        createMap: function() {
            var osmUrl    = 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
                osmAttrib = '© OpenStreetMap contributors',
                osm       = L.tileLayer(osmUrl, {
                                maxZoom:     this.settings.maxzoom,
                                attribution: osmAttrib
                            }),
                sVal      = this.$input.val();

            this.map      = new L.Map(this.element, {
                                layers: [osm],
                                center: new L.LatLng(this.settings.lat, this.settings.long),
                                zoom:   this.settings.zoom
                            });

            this.map.invalidateSize();

            if (sVal != '') {
                this.drawnItems = L.geoJson(JSON.parse(sVal ) );

                // zoom to show all the features
                this.map.fitBounds(this.drawnItems.getBounds() );
            }
            else {
                this.drawnItems = L.geoJson();
            }
            this.map.addLayer(this.drawnItems);
        },
        addDrawEditor: function() {
            var _this       = this,
                drawControl = new L.Control.Draw({
                    position: 'topright',
                    draw: {
                        polyline:  this.settings.polyline,
                        polygon:   this.settings.polygon,
                        marker:    this.settings.marker,
                        circle:    this.settings.circle,
                        rectangle: this.settings.rectangle
                    },
                    edit: {
                        featureGroup: this.drawnItems,
                        remove:       this.settings.remove
                    }
                });
            this.map.addControl(drawControl);

            this.map.on('draw:created', function (e) {
                _this.drawnItems.addLayer(e.layer);
                _this.saveGeojson();
            });

            this.map.on('draw:edited', function (e) {
                _this.saveGeojson();
            });

            this.map.on('draw:deleted', function (e) {
                _this.drawnItems.removeLayer(e.layer); // required ?
                _this.saveGeojson();
            });
        },
        addStyleEditor: function() {
            var _this = this;

            //Initialize the StyleEditor
            var styleEditor = L.control.styleEditor({
                position:          "topright",
                useGrouping:       false,
                openOnLeafletDraw: false
            });
            this.map.addControl(styleEditor);

            this.map.on('styleeditor:changed', function(e){
                _this.saveGeojson();
            });

            // Prevent to submit bolt record form
            $('.leaflet-styleeditor button').on('click', function(e) {
                e.preventDefault();
            })
        },
        saveGeojson: function() {
            var i       = 0,
                geojson = this.drawnItems.toGeoJSON();

            this.drawnItems.eachLayer(function(layer) {
                var options = layer.options;
                delete options.editing;
                delete options.original;
                delete options._initHooksCalled;
                delete options.clickable;

                geojson.features[i].style = options;

                i++;
            });

            this.$input.val(JSON.stringify(geojson ) );
        }
    } );

    // A really lightweight plugin wrapper around the constructor,
    // preventing against multiple instantiations
    $.fn[ pluginName ] = function( options ) {
        return this.each( function() {
            if ( !$.data( this, "plugin_" + pluginName ) ) {
                $.data( this, "plugin_" +
                    pluginName, new Plugin( this, options ) );
            }
        } );
    };

} )( jQuery, window, document );
<commit_msg>Display tiles on invisible tab<commit_after>/*
 *  jquery-boilerplate - v4.0.0
 *  A jump-start for jQuery plugins development.
 *  http://jqueryboilerplate.com
 *
 *  Made by Zeno Rocha
 *  Under MIT License
 */
;( function( $, window, document, undefined ) {

    "use strict";

    // Create the defaults once
    var pluginName = "jqGeojsonField",
        defaults   = {
            inputSelector: "",
            zoom:          13,
            maxzoom:       18,
            lat:           48.856578,
            long:          2.351828,
            polyline:      true,
            polygon:       true,
            marker:        true,
            circle:        false,
            rectangle:     false,
            remove:        true,
            style:         false
        };

    // The actual plugin constructor
    function Plugin ( element, options ) {
        this.element    = element;
        this.settings   = $.extend( {}, defaults, options );
        this._defaults  = defaults;
        this._name      = pluginName;
        this.$input     = $(this.settings.inputSelector);
        this.map        = undefined;
        this.drawnItems = undefined;

        this.init();
    }

    // Avoid Plugin.prototype conflicts
    $.extend( Plugin.prototype, {
        init: function() {
            this.loadSettingsFromDataAttributes();
            this.createMap();
            this.addDrawEditor();

            if (this.settings.style) {
                this.addStyleEditor();
            }

            this.waitingToShow();
        },
        // Wait until div is visible, to load tiles on every part of the container
        waitingToShow: function() {
            var _this = this;

            if (! $(_this.element).is(':visible') ) {
                window.setTimeout(function(){ _this.waitingToShow(); }, 500);
            } else {
                _this.map.invalidateSize();
            }
        },
        loadSettingsFromDataAttributes: function() {
            var defaults = $(this.element).data();

            if (defaults.hasOwnProperty('geojsonfieldZoom') )      { this.settings.zoom = defaults.geojsonfieldZoom; }
            if (defaults.hasOwnProperty('geojsonfieldMaxzoom') )   { this.settings.maxzoom = defaults.geojsonfieldMaxzoom; }
            if (defaults.hasOwnProperty('geojsonfieldLat') )       { this.settings.lat = defaults.geojsonfieldLat; }
            if (defaults.hasOwnProperty('geojsonfieldLong') )      { this.settings.long = defaults.geojsonfieldLong; }
            if (defaults.hasOwnProperty('geojsonfieldPolyline') )  { this.settings.polyline = defaults.geojsonfieldPolyline; }
            if (defaults.hasOwnProperty('geojsonfieldPolygon') )   { this.settings.polygon = defaults.geojsonfieldPolygon; }
            if (defaults.hasOwnProperty('geojsonfieldMarker') )    { this.settings.marker = defaults.geojsonfieldMarker; }
            if (defaults.hasOwnProperty('geojsonfieldCircle') )    { this.settings.circle = defaults.geojsonfieldCircle; }
            if (defaults.hasOwnProperty('geojsonfieldRectangle') ) { this.settings.rectangle = defaults.geojsonfieldRectangle; }
            if (defaults.hasOwnProperty('geojsonfieldRemove') )    { this.settings.remove = defaults.geojsonfieldRemove; }
            if (defaults.hasOwnProperty('geojsonfieldStyle') )     { this.settings.style = defaults.geojsonfieldStyle; }
        },
        createMap: function() {
            var osmUrl    = 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
                osmAttrib = '© OpenStreetMap contributors',
                osm       = L.tileLayer(osmUrl, {
                                maxZoom:     this.settings.maxzoom,
                                attribution: osmAttrib
                            }),
                sVal      = this.$input.val();

            this.map      = new L.Map(this.element, {
                                layers: [osm],
                                center: new L.LatLng(this.settings.lat, this.settings.long),
                                zoom:   this.settings.zoom
                            });

            this.map.invalidateSize();

            if (sVal != '') {
                this.drawnItems = L.geoJson(JSON.parse(sVal ) );

                // zoom to show all the features
                this.map.fitBounds(this.drawnItems.getBounds() );
            }
            else {
                this.drawnItems = L.geoJson();
            }
            this.map.addLayer(this.drawnItems);
        },
        addDrawEditor: function() {
            var _this       = this,
                drawControl = new L.Control.Draw({
                    position: 'topright',
                    draw: {
                        polyline:  this.settings.polyline,
                        polygon:   this.settings.polygon,
                        marker:    this.settings.marker,
                        circle:    this.settings.circle,
                        rectangle: this.settings.rectangle
                    },
                    edit: {
                        featureGroup: this.drawnItems,
                        remove:       this.settings.remove
                    }
                });
            this.map.addControl(drawControl);

            this.map.on('draw:created', function (e) {
                _this.drawnItems.addLayer(e.layer);
                _this.saveGeojson();
            });

            this.map.on('draw:edited', function (e) {
                _this.saveGeojson();
            });

            this.map.on('draw:deleted', function (e) {
                _this.drawnItems.removeLayer(e.layer); // required ?
                _this.saveGeojson();
            });
        },
        addStyleEditor: function() {
            var _this = this;

            //Initialize the StyleEditor
            var styleEditor = L.control.styleEditor({
                position:          "topright",
                useGrouping:       false,
                openOnLeafletDraw: false
            });
            this.map.addControl(styleEditor);

            this.map.on('styleeditor:changed', function(e){
                _this.saveGeojson();
            });

            // Prevent to submit bolt record form
            $('.leaflet-styleeditor button').on('click', function(e) {
                e.preventDefault();
            })
        },
        saveGeojson: function() {
            var i       = 0,
                geojson = this.drawnItems.toGeoJSON();

            this.drawnItems.eachLayer(function(layer) {
                var options = layer.options;
                delete options.editing;
                delete options.original;
                delete options._initHooksCalled;
                delete options.clickable;

                geojson.features[i].style = options;

                i++;
            });

            this.$input.val(JSON.stringify(geojson ) );
        }
    } );

    // A really lightweight plugin wrapper around the constructor,
    // preventing against multiple instantiations
    $.fn[ pluginName ] = function( options ) {
        return this.each( function() {
            if ( !$.data( this, "plugin_" + pluginName ) ) {
                $.data( this, "plugin_" +
                    pluginName, new Plugin( this, options ) );
            }
        } );
    };

} )( jQuery, window, document );
<|endoftext|>


<commit_before>// Magic scroll things.
// This binds cool animations to the scroll level in such a way that the
// animations' progress can be controlled by scrolling. This does what
// ScrollMagic does except without the bugs.

var backgroundScale = new chroma.scale(["#2d3940", "#fff"]).mode("lab");

var elem = {
  header: document.getElementsByTagName("header")[0],
  headerTitle: document.getElementsByTagName("h1")[0],
  laptop: document.getElementsByClassName("laptop")[0],
  downIndicator: document.getElementsByClassName("down-indicator")[0],
  laptopContent: document.getElementsByClassName("laptop-content")[0],
  body: document.body
};

// HEADER TRANSITION LOGIC ====================================================

function setHeaderElementsPinned(fixed) {
  var elements = [elem.headerTitle, elem.laptop];
  for (var i=0; i<elements.length; i++) {
    elements[i].style.position = fixed ? "fixed" : "absolute";
    elements[i].style.top = fixed ? "50vh" : window.innerHeight + "px";
  }
}

function updateHeaderElements(progress) {

  function tween(a, b) {
    return a + (b - a) * progress;
  }

  whRatio = elem.laptopContent.offsetWidth / elem.laptopContent.offsetHeight;
  elem.header.style.width = tween(
    100,
    (100 * elem.laptopContent.offsetWidth / window.innerWidth)
  ) + "vw";
  elem.header.style.height = tween(
    100 * (window.innerHeight / window.innerWidth),
    (100 * elem.laptopContent.offsetWidth / window.innerWidth) / whRatio
  ) + "vw";

  elem.header.style.top = (progress < 1 ?
    tween(window.innerHeight / 2, elem.laptopContent.offsetTop + elem.laptopContent.offsetHeight) :
    elem.laptopContent.offsetTop + elem.laptopContent.offsetHeight + window.innerHeight / 2) +
  "px";
  elem.header.style.position = progress < 1 ? "fixed" : "absolute";

  elem.downIndicator.style.opacity = 1 - progress;
  elem.body.style.backgroundColor = backgroundScale(progress).hex();

  gol.sizeChanged();
  // TODO: Update canvas pixel size
}

// SCROLL LISTENER ============================================================

document.addEventListener("scroll", function(e) {
  var scroll = window.scrollY;

  // Header

  var headerProgress = scroll / (window.innerHeight / 2);

  switch(true) {
    case (scroll < 5):
      setHeaderElementsPinned(true);
      updateHeaderElements(0);
      break;

    case (scroll < window.innerHeight / 2):
      setHeaderElementsPinned(true);
      updateHeaderElements(headerProgress);
      break;

    default:
      setHeaderElementsPinned(false);
      updateHeaderElements(1);
  }
});
<commit_msg>Properly shrink canvas<commit_after>// Magic scroll things.
// This binds cool animations to the scroll level in such a way that the
// animations' progress can be controlled by scrolling. This does what
// ScrollMagic does except without the bugs.

var backgroundScale = new chroma.scale(["#2d3940", "#fff"]).mode("lab");

var elem = {
  header: document.getElementsByTagName("header")[0],
  headerTitle: document.getElementsByTagName("h1")[0],
  laptop: document.getElementsByClassName("laptop")[0],
  downIndicator: document.getElementsByClassName("down-indicator")[0],
  laptopContent: document.getElementsByClassName("laptop-content")[0],
  body: document.body
};

// HEADER TRANSITION LOGIC ====================================================

function setHeaderElementsPinned(fixed) {
  var elements = [elem.headerTitle, elem.laptop];
  for (var i=0; i<elements.length; i++) {
    elements[i].style.position = fixed ? "fixed" : "absolute";
    elements[i].style.top = fixed ? "50vh" : window.innerHeight + "px";
  }
}

function updateHeaderElements(progress) {

  function tween(a, b) {
    return a + (b - a) * progress;
  }

  whRatio = elem.laptopContent.offsetWidth / elem.laptopContent.offsetHeight;
  elem.header.style.width = tween(
    100,
    (100 * elem.laptopContent.offsetWidth / window.innerWidth)
  ) + "vw";
  elem.header.style.height = tween(
    100 * (window.innerHeight / window.innerWidth),
    (100 * elem.laptopContent.offsetWidth / window.innerWidth) / whRatio
  ) + "vw";

  elem.header.style.top = (progress < 1 ?
    tween(window.innerHeight / 2, elem.laptopContent.offsetTop + elem.laptopContent.offsetHeight) :
    elem.laptopContent.offsetTop + elem.laptopContent.offsetHeight + window.innerHeight / 2) +
  "px";
  elem.header.style.position = progress < 1 ? "fixed" : "absolute";

  elem.downIndicator.style.opacity = 1 - progress;
  elem.body.style.backgroundColor = backgroundScale(progress).hex();

  // Mean of X scale difference and Y scale difference
  var canvasScale = (gol.canvas.offsetWidth / window.innerWidth + gol.canvas.offsetHeight / window.innerHeight) / 2;

  gol.idealCellSize = 20 * canvasScale;
  gol.sizeChanged();
}

// SCROLL LISTENER ============================================================

document.addEventListener("scroll", function(e) {
  var scroll = window.scrollY;

  // Header

  var headerProgress = scroll / (window.innerHeight / 2);

  switch(true) {
    case (scroll < 5):
      setHeaderElementsPinned(true);
      updateHeaderElements(0);
      break;

    case (scroll < window.innerHeight / 2):
      setHeaderElementsPinned(true);
      updateHeaderElements(headerProgress);
      break;

    default:
      setHeaderElementsPinned(false);
      updateHeaderElements(1);
  }
});
<|endoftext|>


<commit_before>$(document).ready(function(){

	$('#setup').hide();
	$('#main').hide();
	$('#settings').hide();
	$('#add').hide();
	$('#save-trigger').hide();

	// If setup is marked as complete
	if (localStorage.getItem("setup") === "completed") {

		// Load todaylist from localStorage

		var todaylist = JSON.parse("[" + localStorage["todaylist"] + "]");
		var tomorrowlist = JSON.parse("[" + localStorage["tomorrowlist"] + "]");

		// Find date

		var d = new Date();
		var month = d.getMonth()+1;
		var day = d.getDate();
		var date = d.getFullYear() + (month<10 ? '0' : '') + month + (day<10 ? '0' : '') + day;
		if (localStorage.getItem("lastopened") === null || localStorage.getItem("lastopened") === "") {
			localStorage["lastopened"] = date;
		}
		if (localStorage.getItem("lastopened") != date) {
			todaylist = tomorrowlist;
			tomorrowlist = JSON.parse("[]");
			localStorage["lastopened"] = date;
		}

		// Weather forecast

		if (localStorage.getItem("weather") === "true") {

			$.simpleWeather({
			location: localStorage['zip'],
			woeid: '',
			unit: 'f',
			success: function(weather) {
				$("#today-weather").append("

It's currently " + weather.temp + "°" + weather.units.temp + " and " + weather.currently +  ".

Weather provided by Yahoo Weather.

");
				$("#tomorrow-weather").append("

It's going to be " + weather.forecast[1].low + "°" + weather.units.temp + "/" + weather.forecast[1].high + "°" + weather.units.temp + " and " + weather.forecast[1].text +  ".

Weather provided by Yahoo Weather.

");
			},
			error: function(error) {
				toast('Error fetching the weather.', 3000, 'rounded');
			}
			});

		}

		// Reload everything after changes

		function reloadData() {

			var todaytemp = "";
			for (var i = 0; i < todaylist.length; ++i) {
				todaytemp += '"' + todaylist[i] + '",';
			}
			var tomorrowtemp = "";
			for (var i = 0; i < tomorrowlist.length; ++i) {
				tomorrowtemp += '"' + tomorrowlist[i] + '",';
			}
			todaytemp = todaytemp.substring(0, todaytemp.length - 1); // Cut off last comma
			tomorrowtemp = tomorrowtemp.substring(0, tomorrowtemp.length - 1); // Cut off last comma
			localStorage["todaylist"] = todaytemp;
			localStorage["tomorrowlist"] = tomorrowtemp;
			var url = new RegExp(/(\b(https?|ftp):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gim);
			// Generate today list
			if($('#todaylist').length > 0) {
				$("#todaylist").empty();
				if(todaylist.length === 0){
					$("#todaylist").append('

Theres nothing here! Add an item by pressing the Add button in the lower-right corner of the screen.

');
				} else {
					for (var i = 0; i < todaylist.length; ++i) {
						$( "#todaylist" ).append('

' + todaylist[i] + '

DismissPush

');
						// Detect links in task
						var result;
						while((result = url.exec(todaylist[i])) !== null) {
							$( ".actions" + i ).append('Open Link');
						}
					}
				}
			}

			// Generate tomorrow list
			if($('#tomorrowlist').length > 0) {
				$("#tomorrowlist").empty();
				if(tomorrowlist.length === 0){
					$("#tomorrowlist").append('

This is where your items pushed to tomorrow appear.

');
				} else {
					for (var i = 0; i < tomorrowlist.length; ++i) {
						$( "#tomorrowlist" ).append('

' + tomorrowlist[i] + '

');
					}
				}
			}

			// Reload variables from updated localStorage sources
			todaylist = JSON.parse("[" + localStorage["todaylist"] + "]");
			tomorrowlist = JSON.parse("[" + localStorage["tomorrowlist"] + "]");

			// Fix for night mode not applying to reloaded cards
			if (localStorage.getItem("night") === "true") {
				$(".card").css("background", "#151515", 'important');
				$("a").css("color", "#FFFFFF", 'important');
			}
		}

		reloadData();

		// Read values of settings from localStorage

		$("#settings-firstname").val(localStorage['firstname']);
		$("#settings-lastname").val(localStorage['lastname']);
		$("#settings-zip").val(localStorage['zip']);
		$("#settings-weather").prop('checked', JSON.parse(localStorage['weather']));
		$("#settings-night").prop('checked', JSON.parse(localStorage['night']));

		// Actions for settings buttons

		$('#settings-trigger').click(function() {
			$('#add').fadeOut( "slow", function() {});
			$('#settings').fadeIn( "slow", function() {});
			$('#save-trigger').fadeIn( "slow", function() {});
		});

		// Actions for save button

		$('#save-trigger').click(function() {
			if( ($("#settings-firstname").val() == 0) || ($("#settings-lastname").val() == 0) || ($("#settings-zip").val() == 0) )
			{
				// Tell user to fill out everything
				toast('Fill out everything before saving!', 3000, 'rounded');
			} else {
				localStorage['firstname'] = $("#settings-firstname").val();
				localStorage['lastname'] = $("#settings-lastname").val();
				localStorage['zip'] = $("#settings-zip").val();
				if ($("#settings-weather").is(":checked")) {
					localStorage['weather'] = "true";
				} else {
					localStorage['weather'] = "false";
				}
				if ($("#settings-night").is(":checked")) {
					localStorage['night'] = "true";
				} else {
					localStorage['night'] = "false";
				}
				location.reload();
			}
		});

		// Actions for dismiss button

		$(document).on('click', ".delete", function() {
			var item = $(this).parent().parent().parent().attr('id');
			// Remove item from today list
			todaylist.splice(item,1);
			$( "#" + item ).fadeOut( 500, function() {
				reloadData();
				toast('Task completed.', 3000, 'rounded');
			});
		});

		// Actions for push button

		$(document).on('click', ".push", function() {
			var item = $(this).parent().parent().parent().attr('id');
			var task = $( ".task" + item ).text();
			console.log("item: " + item);
			console.log("task: " + task);
			todaylist.splice(item,1); // Remove item from today list
			tomorrowlist.unshift(task); // Add item to tomorrow list
			$( "#" + item ).fadeOut( 500, function() {
				$('#confirm').closeModal();
				reloadData();
				toast('Task pushed to tomorrow.', 3000, 'rounded');
			});
		});

		// Actions for floating add button

		$( "#add" ).click(function() {
			$('#new').openModal();
			$('#task').focus();
		});

		// Actions for ENTER keypress in add modal

		$('#task').keypress(function(event){
		 var keycode = (event.keyCode ? event.keyCode : event.which);
		 if(keycode == '13'){
		 	if(document.getElementById("task").value == 0) {
				toast('Enter a task!', 3000, 'rounded');
			} else {
				var task = document.getElementById("task").value;
				if ($('#new-toggle').is(':checked')) {
					// Add item to tomorrow list
					tomorrowlist.unshift(task);
				} else {
					// Add item to today list
					todaylist.unshift(task);
				}
				reloadData();
				document.getElementById("task").value = "";
				$('#new').closeModal();
				toast('Task added.', 3000, 'rounded');
			}
		 }
		});

		// Actions to do after everything is finished loading

		$(window).load(function() {

			// Night mode
			if (localStorage.getItem("night") === "true") {
				$(".navbar").css("background", "#212121", 'important');
				$("#add").css("background", "#424242", 'important');
				$("#settings-trigger").css("background", "#212121", 'important');
				$("#save-trigger").css("background", "#424242", 'important');
				$("#settings").css("background", "#000000", 'important');
				$(".modal").css("background", "#424242", 'important');
				$(".collection-item").css("border-bottom", "#151515", 'important');
				$("#main").css("background", "#000000", 'important');
				$(".card").css("background", "#212121", 'important');
				$(".switch label input[type=checkbox]:first-child:checked+.lever").css("background", "#151515", 'important');
				$("body").css("color", "#FFFFFF", 'important');
				$("a").css("color", "#FFFFFF", 'important');
				$("input").css("color", "#FFFFFF", 'important');
			}

			// Show everything
			$('.preloader-wrapper').fadeOut( "slow", function() {});
			$('#main').fadeIn( "slow", function() {});
			$('#add').fadeIn( "slow", function() {});

		});

	// If setup is not marked as complete
	} else if (localStorage.getItem("setup") != "completed") {

		// Show setup because it's not complete
		$('#setup').show();

		// Actions when 'Get Started' button is pressed on setup
		$('#getstarted').click(function() {
				// Test if any of the text fields are empty
			if( ($("#setup-firstname").val() == 0) || ($("#setup-lastname").val() == 0) || ($("#setup-zip").val() == 0) )
			{
				// Tell user to fill out everything
				toast('Fill out everything and try again!', 3000, 'rounded');
			} else {
				// Save contents of text fields to localStorage
				localStorage['firstname'] = $("#setup-firstname").val();
				localStorage['lastname'] = $("#setup-lastname").val();
				localStorage['zip'] = $("#setup-zip").val();
				localStorage["weather"] = "true";
				localStorage['setup'] = "completed";
				localStorage["todaylist"] = '"This is a sample list item. You can delete these easily by tapping the Dismiss button.","Look what happens when you add a link! http://www.google.com/"';
				localStorage["tomorrowlist"] = "";
				localStorage['night'] = "false";
				location.reload();
			}
		});

	} else {

		localStorage["setup"] = "";
		location.reload();
	}

});
<commit_msg>reset checkbox on new task popup after completed<commit_after>$(document).ready(function(){

	$('#setup').hide();
	$('#main').hide();
	$('#settings').hide();
	$('#add').hide();
	$('#save-trigger').hide();

	// If setup is marked as complete
	if (localStorage.getItem("setup") === "completed") {

		// Load todaylist from localStorage

		var todaylist = JSON.parse("[" + localStorage["todaylist"] + "]");
		var tomorrowlist = JSON.parse("[" + localStorage["tomorrowlist"] + "]");

		// Find date

		var d = new Date();
		var month = d.getMonth()+1;
		var day = d.getDate();
		var date = d.getFullYear() + (month<10 ? '0' : '') + month + (day<10 ? '0' : '') + day;
		if (localStorage.getItem("lastopened") === null || localStorage.getItem("lastopened") === "") {
			localStorage["lastopened"] = date;
		}
		if (localStorage.getItem("lastopened") != date) {
			todaylist = tomorrowlist;
			tomorrowlist = JSON.parse("[]");
			localStorage["lastopened"] = date;
		}

		// Weather forecast

		if (localStorage.getItem("weather") === "true") {

			$.simpleWeather({
			location: localStorage['zip'],
			woeid: '',
			unit: 'f',
			success: function(weather) {
				$("#today-weather").append("

It's currently " + weather.temp + "°" + weather.units.temp + " and " + weather.currently +  ".

Weather provided by Yahoo Weather.

");
				$("#tomorrow-weather").append("

It's going to be " + weather.forecast[1].low + "°" + weather.units.temp + "/" + weather.forecast[1].high + "°" + weather.units.temp + " and " + weather.forecast[1].text +  ".

Weather provided by Yahoo Weather.

");
			},
			error: function(error) {
				toast('Error fetching the weather.', 3000, 'rounded');
			}
			});

		}

		// Reload everything after changes

		function reloadData() {

			var todaytemp = "";
			for (var i = 0; i < todaylist.length; ++i) {
				todaytemp += '"' + todaylist[i] + '",';
			}
			var tomorrowtemp = "";
			for (var i = 0; i < tomorrowlist.length; ++i) {
				tomorrowtemp += '"' + tomorrowlist[i] + '",';
			}
			todaytemp = todaytemp.substring(0, todaytemp.length - 1); // Cut off last comma
			tomorrowtemp = tomorrowtemp.substring(0, tomorrowtemp.length - 1); // Cut off last comma
			localStorage["todaylist"] = todaytemp;
			localStorage["tomorrowlist"] = tomorrowtemp;
			var url = new RegExp(/(\b(https?|ftp):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gim);
			// Generate today list
			if($('#todaylist').length > 0) {
				$("#todaylist").empty();
				if(todaylist.length === 0){
					$("#todaylist").append('

Theres nothing here! Add an item by pressing the Add button in the lower-right corner of the screen.

');
				} else {
					for (var i = 0; i < todaylist.length; ++i) {
						$( "#todaylist" ).append('

' + todaylist[i] + '

DismissPush

');
						// Detect links in task
						var result;
						while((result = url.exec(todaylist[i])) !== null) {
							$( ".actions" + i ).append('Open Link');
						}
					}
				}
			}

			// Generate tomorrow list
			if($('#tomorrowlist').length > 0) {
				$("#tomorrowlist").empty();
				if(tomorrowlist.length === 0){
					$("#tomorrowlist").append('

This is where your items pushed to tomorrow appear.

');
				} else {
					for (var i = 0; i < tomorrowlist.length; ++i) {
						$( "#tomorrowlist" ).append('

' + tomorrowlist[i] + '

');
					}
				}
			}

			// Reload variables from updated localStorage sources
			todaylist = JSON.parse("[" + localStorage["todaylist"] + "]");
			tomorrowlist = JSON.parse("[" + localStorage["tomorrowlist"] + "]");

			// Fix for night mode not applying to reloaded cards
			if (localStorage.getItem("night") === "true") {
				$(".card").css("background", "#151515", 'important');
				$("a").css("color", "#FFFFFF", 'important');
			}
		}

		reloadData();

		// Read values of settings from localStorage

		$("#settings-firstname").val(localStorage['firstname']);
		$("#settings-lastname").val(localStorage['lastname']);
		$("#settings-zip").val(localStorage['zip']);
		$("#settings-weather").prop('checked', JSON.parse(localStorage['weather']));
		$("#settings-night").prop('checked', JSON.parse(localStorage['night']));

		// Actions for settings buttons

		$('#settings-trigger').click(function() {
			$('#add').fadeOut( "slow", function() {});
			$('#settings').fadeIn( "slow", function() {});
			$('#save-trigger').fadeIn( "slow", function() {});
		});

		// Actions for save button

		$('#save-trigger').click(function() {
			if( ($("#settings-firstname").val() == 0) || ($("#settings-lastname").val() == 0) || ($("#settings-zip").val() == 0) )
			{
				// Tell user to fill out everything
				toast('Fill out everything before saving!', 3000, 'rounded');
			} else {
				localStorage['firstname'] = $("#settings-firstname").val();
				localStorage['lastname'] = $("#settings-lastname").val();
				localStorage['zip'] = $("#settings-zip").val();
				if ($("#settings-weather").is(":checked")) {
					localStorage['weather'] = "true";
				} else {
					localStorage['weather'] = "false";
				}
				if ($("#settings-night").is(":checked")) {
					localStorage['night'] = "true";
				} else {
					localStorage['night'] = "false";
				}
				location.reload();
			}
		});

		// Actions for dismiss button

		$(document).on('click', ".delete", function() {
			var item = $(this).parent().parent().parent().attr('id');
			// Remove item from today list
			todaylist.splice(item,1);
			$( "#" + item ).fadeOut( 500, function() {
				reloadData();
				toast('Task completed.', 3000, 'rounded');
			});
		});

		// Actions for push button

		$(document).on('click', ".push", function() {
			var item = $(this).parent().parent().parent().attr('id');
			var task = $( ".task" + item ).text();
			console.log("item: " + item);
			console.log("task: " + task);
			todaylist.splice(item,1); // Remove item from today list
			tomorrowlist.unshift(task); // Add item to tomorrow list
			$( "#" + item ).fadeOut( 500, function() {
				$('#confirm').closeModal();
				reloadData();
				toast('Task pushed to tomorrow.', 3000, 'rounded');
			});
		});

		// Actions for floating add button

		$( "#add" ).click(function() {
			$('#new').openModal();
			$('#task').focus();
		});

		// Actions for ENTER keypress in add modal

		$('#task').keypress(function(event){
		 var keycode = (event.keyCode ? event.keyCode : event.which);
		 if(keycode == '13'){
		 	if(document.getElementById("task").value == 0) {
				toast('Enter a task!', 3000, 'rounded');
			} else {
				var task = document.getElementById("task").value;
				if ($('#new-toggle').is(':checked')) {
					// Add item to tomorrow list
					tomorrowlist.unshift(task);
					// Reset checkbox
					$("#new-toggle").prop('checked', false);
				} else {
					// Add item to today list
					todaylist.unshift(task);
				}
				reloadData();
				document.getElementById("task").value = "";
				$('#new').closeModal();
				toast('Task added.', 3000, 'rounded');
			}
		 }
		});

		// Actions to do after everything is finished loading

		$(window).load(function() {

			// Night mode
			if (localStorage.getItem("night") === "true") {
				$(".navbar").css("background", "#212121", 'important');
				$("#add").css("background", "#424242", 'important');
				$("#settings-trigger").css("background", "#212121", 'important');
				$("#save-trigger").css("background", "#424242", 'important');
				$("#settings").css("background", "#000000", 'important');
				$(".modal").css("background", "#424242", 'important');
				$(".collection-item").css("border-bottom", "#151515", 'important');
				$("#main").css("background", "#000000", 'important');
				$(".card").css("background", "#212121", 'important');
				$(".switch label input[type=checkbox]:first-child:checked+.lever").css("background", "#151515", 'important');
				$("body").css("color", "#FFFFFF", 'important');
				$("a").css("color", "#FFFFFF", 'important');
				$("input").css("color", "#FFFFFF", 'important');
			}

			// Show everything
			$('.preloader-wrapper').fadeOut( "slow", function() {});
			$('#main').fadeIn( "slow", function() {});
			$('#add').fadeIn( "slow", function() {});

		});

	// If setup is not marked as complete
	} else if (localStorage.getItem("setup") != "completed") {

		// Show setup because it's not complete
		$('#setup').show();

		// Actions when 'Get Started' button is pressed on setup
		$('#getstarted').click(function() {
				// Test if any of the text fields are empty
			if( ($("#setup-firstname").val() == 0) || ($("#setup-lastname").val() == 0) || ($("#setup-zip").val() == 0) )
			{
				// Tell user to fill out everything
				toast('Fill out everything and try again!', 3000, 'rounded');
			} else {
				// Save contents of text fields to localStorage
				localStorage['firstname'] = $("#setup-firstname").val();
				localStorage['lastname'] = $("#setup-lastname").val();
				localStorage['zip'] = $("#setup-zip").val();
				localStorage["weather"] = "true";
				localStorage['setup'] = "completed";
				localStorage["todaylist"] = '"This is a sample list item. You can delete these easily by tapping the Dismiss button.","Look what happens when you add a link! http://www.google.com/"';
				localStorage["tomorrowlist"] = "";
				localStorage['night'] = "false";
				location.reload();
			}
		});

	} else {

		localStorage["setup"] = "";
		location.reload();
	}

});
<|endoftext|>


<commit_before>//select id from account
//select id,name from account

//all variables defined in this file are in global scope. Meaning they can be accessed in any of subsequent js files

//initializes the current html to link to angular application by adding ng-app,ng-controller and custom directive
const body = document.getElementsByTagName('body')[0];
body.setAttribute('ng-app', 'workbenchEnhancerApp');
body.setAttribute('ng-controller', 'baseController');
body.setAttribute('ng-cloak', '');

const pathname = window.location.pathname.replace('/', '').replace('.php', '').replace('#', '');

let textarea, queryBtn;

switch (pathname) {
  case 'query':
    textarea = document.getElementById('soql_query_textarea');
    queryBtn = document.getElementsByName('querySubmit')[0];
    break;

  case 'execute':
    textarea = document.getElementById('scriptInput');
    queryBtn = document.getElementsByName('execute')[0];

  case 'search':
    textarea = document.getElementById('sosl_search_textarea');
    queryBtn = document.getElementsByName('searchSubmit')[0];
}

textarea.setAttribute('ng-model', 'allDataObj.textAreaVal');
queryBtn.setAttribute('ng-click', 'allDataObj.addDataToStorage($event)');
queryBtn.setAttribute('update-model', '');

const customDiv = document.createElement('div');
customDiv.setAttribute('main-extension', '');
body.insertBefore(customDiv, document.getElementById('mainBlock'));

//initialize angular application
const app = angular.module('workbenchEnhancerApp', ['ngAnimate', 'ui.bootstrap', 'ngRoute']);

// //clear storage completely
// chrome.storage.local.clear(function(){
//   alert('Cleared storage');
// });

//clear storage for specific key
// chrome.storage.local.remove('08 Jan 2017',function(){
//   alert('Removed');
// })<commit_msg>new line<commit_after>//select id from account
//select id,name from account

//all variables defined in this file are in global scope. Meaning they can be accessed in any of subsequent js files

//initializes the current html to link to angular application by adding ng-app,ng-controller and custom directive
const body = document.getElementsByTagName('body')[0];
body.setAttribute('ng-app', 'workbenchEnhancerApp');
body.setAttribute('ng-controller', 'baseController');
body.setAttribute('ng-cloak', '');

const pathname = window.location.pathname.replace('/', '').replace('.php', '').replace('#', '');

let textarea, queryBtn;

switch (pathname) {
  case 'query':
    textarea = document.getElementById('soql_query_textarea');
    queryBtn = document.getElementsByName('querySubmit')[0];
    break;

  case 'execute':
    textarea = document.getElementById('scriptInput');
    queryBtn = document.getElementsByName('execute')[0];

  case 'search':
    textarea = document.getElementById('sosl_search_textarea');
    queryBtn = document.getElementsByName('searchSubmit')[0];
}

textarea.setAttribute('ng-model', 'allDataObj.textAreaVal');
queryBtn.setAttribute('ng-click', 'allDataObj.addDataToStorage($event)');
queryBtn.setAttribute('update-model', '');

const customDiv = document.createElement('div');
customDiv.setAttribute('main-extension', '');
body.insertBefore(customDiv, document.getElementById('mainBlock'));

//initialize angular application
const app = angular.module('workbenchEnhancerApp', ['ngAnimate', 'ui.bootstrap', 'ngRoute']);

// //clear storage completely
// chrome.storage.local.clear(function(){
//   alert('Cleared storage');
// });

//clear storage for specific key
// chrome.storage.local.remove('08 Jan 2017',function(){
//   alert('Removed');
// })
<|endoftext|>


<commit_before>/*!
 * jQuery Notify Plugin
 *
 * Copyright (c) 2012-2014 David Persson
 *
 * Licensed under the MIT license.
 * http://www.opensource.org/licenses/mit-license.php
 */
(function($) {

  // Global configuration.
  var config = {
    // Selector of the container in which messages will be added.
    container: '#messages',

    // Element used for a message.
    element: '

',

    // Number of maximum pending messages, all other messages
    // will be discarded to prevent flooding.
    maxPending: 2,

    // Base timeout until a message will be removed after it's shown.
    timeout: 2100
  };

  // Our own personal queue.
  var queue = $({});

  // Main plugin function. Allows for adding a notification and
  // configuring the plugin globally.
  $.notify = function(html, options) {
    if (typeof html === 'object') {
      config = $.extend(html, config);
      return;
    }
    options = $.extend(options || {}, {
      level: null,
      sticky: false,
      timeout: config.timeout
    });

    // Prevent flooding; no more than 2 pending messages. We start at
    // zero as this is called before the first item is queued.
    if (queue.queue().length >= config.maxPending) {
      return;
    }
    // Currently only one message at the time. Allowing showing multiple
    // message here will might need a more sophisticated method of managment.
    queue.queue(function(next) {
      render(html, options, next);
    });
  };

  // Renders a message and calls complete callback after doing that.
  function render(html, options, complete) {
    var $m = $(config.element).html(html);

    if (options.level) {
      $m.addClass(level);
    }
    if (options.sticky) {
      $m.addClass('sticky');
    }
    $(config.container).append($m);

    if (options.sticky) {
      $m.click(function(ev) {
        toggle($m).done(function() {
          $m.remove();
          complete();
        });
      });
      return; // Do not continue and probably show next message.
    }

    // Multiply the timeout for complex messages, giving comprehension time.
    // Give 1s per 30 chars over the first 25 chars.
    options.timeout += 1000 * (($($.parseHTML(html)).text().length - 25) / 30);

    // Workaround to enable CSS transitions on dynamically inserted elements.
    // Reading random property to force recalculating styles. Has no effect
    // when transitions aren't used.
    $m.css('top');

    toggle($m).done(function() {
      setTimeout(function() {
        toggle($m).done(function() {
          $m.remove();
          complete(); // Show next message in queue.
        });
      }, options.timeout);
    });
  }

  // Show/hide function used when a message should dis-/appear; must return
  // a promise which should be resolved when i.e. the show animation
  // finished.
  function toggle($m) {
    var dfr = new $.Deferred();

    // Determines if CSS transitions should/can be used.
    if (typeof Modernizr !== 'undefined' && Modernizr.csstransitions) {
      $m.one('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd', dfr.resolve);
    } else {
      dfr.resolve();
    }
    $m.toggleClass('hide');

    return dfr.promise();
  }

})(jQuery);
<commit_msg>Reimplement.<commit_after>/*!
 * jQuery Notify Plugin
 *
 * Copyright (c) 2012-2014 David Persson
 *
 * Licensed under the MIT license.
 * http://www.opensource.org/licenses/mit-license.php
 */
(function($) {

  // All possible transition event names.
  var TRANSITION_EV = 'transitionend mozTransitionEnd webkitTransitionEnd oTransitionEnd MSTransitionEnd';

  // Global configuration.
  var config = {
    // Selector of the container in which messages will be added.
    container: '#messages',

    // The element definition of a message.
    element: '

',

    // Number of maximum pending messages, all other messages
    // will be discarded to prevent flooding.
    maxPending: 2,

    // Base timeout until a message will be removed after it's shown.
    timeout: 2100,

    // Show function used when a message should appear; must return a
    // promise which should be resolved when i.e. the show animation
    // finished.
    show: function($m, $c) {
      var dfr = new $.Deferred();

      if (typeof Modernizr !== 'undefined' && Modernizr.csstransitions) {
        if ($m.css('transition-duration')) {
          $m.one(TRANSITION_EV, dfr.resolve);
        } else if ($c.css('transition-duration')) {
          $c.one(TRANSITION_EV, dfr.resolve);
        } else {
          dfr.resolve();
        }
        $m.removeClass('invisible');
      } else {
        $m.fadeIn(dfr.resolve);
      }
      return dfr.promise();
    },

    // Hide function used when a message should disappear; must return
    // a promise which should be resolved when i.e. the hide animation
    // finished.
    hide: function($m, $c) {
      var dfr = new $.Deferred();

      if (typeof Modernizr !== 'undefined' && Modernizr.csstransitions) {
        if ($m.css('transition-duration')) {
          $m.one(TRANSITION_EV, dfr.resolve);
        } else if ($c.css('transition-duration')) {
          $c.one(TRANSITION_EV, dfr.resolve);
        } else {
          dfr.resolve();
        }
        $m.addClass('invisible');
      } else {
        $m.fadeOut(dfr.resolve);
      }
      return dfr.promise();
    }
  };

  // Our own personal queue.
  var queue = $({});

  // Renders a message and calls complete callback after doing that.
  var render = function(html, options, complete) {
    var $m = $(config.element).html(html);
    var $c = $(config.container);

    if (options.level) {
      $m.addClass(options.level);
    }
    if (options.sticky) {
      $m.addClass('sticky');
    }
    $c.append($m);

    $m.click(function(ev) {
      config.hide($m, $c).done(function() {
        $m.remove();
        complete();
      });
    });

    if (options.sticky) {
      return; // Do not continue and probably show next message.
    }

    // Multiply the timeout for complex messages, giving comprehension time.
    // Give 1s per 30 chars over the first 25 chars.
   var timeout = options.timeout + 1000 * (($($.parseHTML(html)).text().length - 25) / 30);

    // Workaround to enable CSS transitions on dynamically inserted elements.
    // Reading random property to force recalculating styles.
    $m.css('top');

    config.show($m, $c).done(function() {
      setTimeout(function() {
        config.hide($m, $c).done(function() {
          $m.remove();
          complete(); // Show next message in queue.
        });
      }, timeout);
    });
  };

  // Main plugin function. Allows for adding a notification and
  // configuring the plugin globally.
  $.notify = function(html, options) {
    // Allow setting global configuration for this plugin.
    if (typeof html === 'object') {
      config = $.extend(config, html);
      return;
    }
    options = $.extend({
      level: null,
      sticky: false,
      timeout: config.timeout
    }, options || {});

    // Prevent flooding; no more than 2 pending messages. We start at
    // zero as this is called before the first item is queued.
    if (queue.queue().length >= config.maxPending) {
      return;
    }
    // Currently only one message at the time. Allowing showing multiple
    // message here will might need a more sophisticated method of managment.
    queue.queue(function(next) {
      render(html, options, next);
    });
  };

})(jQuery);
<|endoftext|>


<commit_before>/** @jsx React.DOM */
/**
 * Copyright (c) 2014, Tidepool Project
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the associated License, which is identical to the BSD 2-Clause
 * License as published by the Open Source Initiative at opensource.org.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the License for more details.
 *
 * You should have received a copy of the License along with this program; if
 * not, you can obtain one from Tidepool Project at tidepool.org.
 */
var React = require('react');

var TermsOverlay = React.createClass({
  propTypes: {
    onSubmit: React.PropTypes.func,
    trackMetric: React.PropTypes.func.isRequired,
    ages: React.PropTypes.object,
    messages: React.PropTypes.object
  },
  getDefaultProps: function(){
    return {
      ages: {
        OF_AGE : { value: '>=18', label: ' I am 18 years old or older.'},
        WITH_CONSENT : { value: '13-17', label: ' I am between 13 and 17 years old. You\'ll need to have a parent or guardian agree to the terms on the next screen.' },
        NOT_OF_AGE : { value: '<=12', label: ' I am 12 years old or younger.'}
      },
      messages: {
        ACCEPT_OF_AGE : 'I am 18 or older and I accept the terms of the Tidepool Applications Terms of Use and Privacy Policy',
        ACCEPT_ON_BEHALF: 'I agree that my child aged 13 through 17 can use Tidepool Applications and agree that they are also bound to the terms of the Tidepool Applications Terms of Use and Privacy Policy',
        SORRY_NOT_OF_AGE : 'We are really sorry, but you need to be 13 or older in order to create an account and use Tidepool\'s Applications.'
      }
    };
  },
  getInitialState: function() {
    return {
      agreed: false,
      agreedOnBehalf: false,
      ageConfirmed: false,
      ageSelected: this.props.ages.OF_AGE.value //default
    };
  },
  renderAgeConsentStep:function(){
    return (

          <form ref='ageConfirmation' className='terms-overlay-age-form'>

                <input type='radio' name='age'
                  key={this.props.ages.OF_AGE.value}
                  value={this.props.ages.OF_AGE.value}
                  onChange={this.handleAgeChange}
                  defaultChecked={true} />
                {this.props.ages.OF_AGE.label}

                <input type='radio' name='age'
                  key={this.props.ages.WITH_CONSENT.value}
                  value={this.props.ages.WITH_CONSENT.value}
                  onChange={this.handleAgeChange} />
                {this.props.ages.WITH_CONSENT.label}

                <input type='radio' name='age'
                  key={this.props.ages.NOT_OF_AGE.value}
                  value={this.props.ages.NOT_OF_AGE.value}
                  onChange={this.handleAgeChange} />
                {this.props.ages.NOT_OF_AGE.label}

            <button
              className='btn btn-primary js-terms-submit'
              onClick={this.handleAgeSubmit}>Continue</button>
          </form>

    );
  },
  getTermsAndPrivacyButtonState:function(){
    var isDisabled = !this.state.agreed;

    if (this.state.ageSelected === this.props.ages.WITH_CONSENT.value) {
      if (this.state.agreed && this.state.agreedOnBehalf){
        isDisabled = false;
      } else {
        isDisabled = true;
      }
    }
    return isDisabled;
  },
  renderTermsAndPrivacyStep:function(){
    var terms = this.websiteTerms();
    var privacy = this.websitePrivacy();
    var continueBtnDisabled = this.getTermsAndPrivacyButtonState();
    var agreeConfirmation = this.renderAgreeCheckboxes();

    return (

TERMS OF USE

          {terms}

PRIVACY POLICY

          {privacy}
          <form className='terms-overlay-form'>
            {agreeConfirmation}
            <button
              className='btn btn-primary js-terms-submit'
              onClick={this.handleTermsAndPrivacySubmit}
              disabled={continueBtnDisabled}>Continue</button>
          </form>

    );
  },
  renderAgreeCheckboxes:function(){

    var onBehalf;
    if (this.state.ageSelected === this.props.ages.WITH_CONSENT.value) {
      onBehalf = (

          <input
            id='agreedOnBehalf'
            type='checkbox'
            className='js-terms-checkbox'
            checked={this.state.agreedOnBehalf}
            onChange={this.handleOnBehalfAgreementChange} />
          {this.props.messages.ACCEPT_ON_BEHALF}

      );
    }

    return (

          <input
            id='agreed'
            type='checkbox'
            className='js-terms-checkbox'
            checked={this.state.agreed}
            onChange={this.handleAgreementChange} />
          {this.props.messages.ACCEPT_OF_AGE}

        {onBehalf}

    );
  },
  renderSorryMessage:function(){
    return (

{this.props.messages.SORRY_NOT_OF_AGE}

    );
  },
  render: function() {
    if(this.state.ageConfirmed && this.state.ageSelected !== this.props.ages.NOT_OF_AGE.value){
      return this.renderTermsAndPrivacyStep();
    }else if( this.state.ageConfirmed && this.state.ageSelected === this.props.ages.NOT_OF_AGE.value){
      return this.renderSorryMessage();
    }
    return this.renderAgeConsentStep();
  },
  websiteTerms: function() {
    return React.DOM.iframe({
      className         : 'terms-overlay-iframe',
      src               : 'http://developer.tidepool.io/terms-of-use',
      scrolling         : 'yes',
      frameBorder       : '0',
      allowTransparency : 'true'
    });
  },
  websitePrivacy: function() {
    return React.DOM.iframe({
      className         : 'terms-overlay-iframe',
      src               : 'http://developer.tidepool.io/privacy-policy',
      scrolling         : 'yes',
      frameBorder       : '0',
      allowTransparency : 'true'
    });
  },
  handleAgeSubmit: function(e) {
    if (e) {
      e.preventDefault();
    }
    this.setState({ageConfirmed: true });
    this.props.trackMetric('Confirmed age');
  },
  handleAgeChange:function(e){
    this.setState({ ageSelected: e.target.value});
  },
  handleAgreementChange: function() {
    this.setState({agreed: !this.state.agreed});
  },
  handleOnBehalfAgreementChange: function() {
    this.setState({agreedOnBehalf: !this.state.agreedOnBehalf});
  },
  handleTermsAndPrivacySubmit: function(e) {
    if (e) {
      e.preventDefault();
    }

    this.props.trackMetric('Agreed To Terms Of Use');

    var submit = this.props.onSubmit;
    if (submit) {
      submit(this.state.ageSelected);
    }
  }
});

module.exports = TermsOverlay;<commit_msg>temp update to use https T&C from Github<commit_after>/** @jsx React.DOM */
/**
 * Copyright (c) 2014, Tidepool Project
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the associated License, which is identical to the BSD 2-Clause
 * License as published by the Open Source Initiative at opensource.org.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the License for more details.
 *
 * You should have received a copy of the License along with this program; if
 * not, you can obtain one from Tidepool Project at tidepool.org.
 */
var React = require('react');

var TermsOverlay = React.createClass({
  propTypes: {
    onSubmit: React.PropTypes.func,
    trackMetric: React.PropTypes.func.isRequired,
    ages: React.PropTypes.object,
    messages: React.PropTypes.object
  },
  getDefaultProps: function(){
    return {
      ages: {
        OF_AGE : { value: '>=18', label: ' I am 18 years old or older.'},
        WITH_CONSENT : { value: '13-17', label: ' I am between 13 and 17 years old. You\'ll need to have a parent or guardian agree to the terms on the next screen.' },
        NOT_OF_AGE : { value: '<=12', label: ' I am 12 years old or younger.'}
      },
      messages: {
        ACCEPT_OF_AGE : 'I am 18 or older and I accept the terms of the Tidepool Applications Terms of Use and Privacy Policy',
        ACCEPT_ON_BEHALF: 'I agree that my child aged 13 through 17 can use Tidepool Applications and agree that they are also bound to the terms of the Tidepool Applications Terms of Use and Privacy Policy',
        SORRY_NOT_OF_AGE : 'We are really sorry, but you need to be 13 or older in order to create an account and use Tidepool\'s Applications.'
      }
    };
  },
  getInitialState: function() {
    return {
      agreed: false,
      agreedOnBehalf: false,
      ageConfirmed: false,
      ageSelected: this.props.ages.OF_AGE.value //default
    };
  },
  renderAgeConsentStep:function(){
    return (

          <form ref='ageConfirmation' className='terms-overlay-age-form'>

                <input type='radio' name='age'
                  key={this.props.ages.OF_AGE.value}
                  value={this.props.ages.OF_AGE.value}
                  onChange={this.handleAgeChange}
                  defaultChecked={true} />
                {this.props.ages.OF_AGE.label}

                <input type='radio' name='age'
                  key={this.props.ages.WITH_CONSENT.value}
                  value={this.props.ages.WITH_CONSENT.value}
                  onChange={this.handleAgeChange} />
                {this.props.ages.WITH_CONSENT.label}

                <input type='radio' name='age'
                  key={this.props.ages.NOT_OF_AGE.value}
                  value={this.props.ages.NOT_OF_AGE.value}
                  onChange={this.handleAgeChange} />
                {this.props.ages.NOT_OF_AGE.label}

            <button
              className='btn btn-primary js-terms-submit'
              onClick={this.handleAgeSubmit}>Continue</button>
          </form>

    );
  },
  getTermsAndPrivacyButtonState:function(){
    var isDisabled = !this.state.agreed;

    if (this.state.ageSelected === this.props.ages.WITH_CONSENT.value) {
      if (this.state.agreed && this.state.agreedOnBehalf){
        isDisabled = false;
      } else {
        isDisabled = true;
      }
    }
    return isDisabled;
  },
  renderTermsAndPrivacyStep:function(){
    var terms = this.websiteTerms();
    var privacy = this.websitePrivacy();
    var continueBtnDisabled = this.getTermsAndPrivacyButtonState();
    var agreeConfirmation = this.renderAgreeCheckboxes();

    return (

TERMS OF USE

          {terms}

PRIVACY POLICY

          {privacy}
          <form className='terms-overlay-form'>
            {agreeConfirmation}
            <button
              className='btn btn-primary js-terms-submit'
              onClick={this.handleTermsAndPrivacySubmit}
              disabled={continueBtnDisabled}>Continue</button>
          </form>

    );
  },
  renderAgreeCheckboxes:function(){

    var onBehalf;
    if (this.state.ageSelected === this.props.ages.WITH_CONSENT.value) {
      onBehalf = (

          <input
            id='agreedOnBehalf'
            type='checkbox'
            className='js-terms-checkbox'
            checked={this.state.agreedOnBehalf}
            onChange={this.handleOnBehalfAgreementChange} />
          {this.props.messages.ACCEPT_ON_BEHALF}

      );
    }

    return (

          <input
            id='agreed'
            type='checkbox'
            className='js-terms-checkbox'
            checked={this.state.agreed}
            onChange={this.handleAgreementChange} />
          {this.props.messages.ACCEPT_OF_AGE}

        {onBehalf}

    );
  },
  renderSorryMessage:function(){
    return (

{this.props.messages.SORRY_NOT_OF_AGE}

    );
  },
  render: function() {
    if(this.state.ageConfirmed && this.state.ageSelected !== this.props.ages.NOT_OF_AGE.value){
      return this.renderTermsAndPrivacyStep();
    }else if( this.state.ageConfirmed && this.state.ageSelected === this.props.ages.NOT_OF_AGE.value){
      return this.renderSorryMessage();
    }
    return this.renderAgeConsentStep();
  },
  websiteTerms: function() {
    return React.DOM.iframe({
      className         : 'terms-overlay-iframe',
      src               : 'https://github.com/tidepool-org/tidepool-org.github.io/blob/master/_docs/privacy-policy.md',
      scrolling         : 'yes',
      frameBorder       : '0',
      allowTransparency : 'true'
    });
  },
  websitePrivacy: function() {
    return React.DOM.iframe({
      className         : 'terms-overlay-iframe',
      src               : 'https://github.com/tidepool-org/tidepool-org.github.io/blob/master/_docs/privacy-policy.md',
      scrolling         : 'yes',
      frameBorder       : '0',
      allowTransparency : 'true'
    });
  },
  handleAgeSubmit: function(e) {
    if (e) {
      e.preventDefault();
    }
    this.setState({ageConfirmed: true });
    this.props.trackMetric('Confirmed age');
  },
  handleAgeChange:function(e){
    this.setState({ ageSelected: e.target.value});
  },
  handleAgreementChange: function() {
    this.setState({agreed: !this.state.agreed});
  },
  handleOnBehalfAgreementChange: function() {
    this.setState({agreedOnBehalf: !this.state.agreedOnBehalf});
  },
  handleTermsAndPrivacySubmit: function(e) {
    if (e) {
      e.preventDefault();
    }

    this.props.trackMetric('Agreed To Terms Of Use');

    var submit = this.props.onSubmit;
    if (submit) {
      submit(this.state.ageSelected);
    }
  }
});

module.exports = TermsOverlay;<|endoftext|>


<commit_before>'use strict'

import React, {PropTypes} from 'react'
import {NavigationExperimental, StyleSheet} from 'react-native'
import { connect } from 'react-redux'

import First from './First'
import Second from './Second'
import Third from './Third'
import Modal from './Modal'
import { navigatePop } from '../actions'

const {
	CardStack: NavigationCardStack,
	Card: NavigationCard,
	Header: NavigationHeader
} = NavigationExperimental

class AppContainerWithCardStack extends React.Component {
	render() {
		let { navigationState, backAction } = this.props

		return (

			// Redux is handling the reduction of our state for us. We grab the navigationState
			// we have in our Redux store and pass it directly to the <NavigationCardStack />.
			<NavigationCardStack
				navigationState={navigationState}
				onNavigateBack={backAction}
				style={styles.container}
				direction={navigationState.routes[navigationState.index].key === 'Modal' ?
					'vertical' : 'horizontal'
				}
				renderHeader={props => (
					<NavigationHeader
						{...props}
						onNavigateBack={backAction}
						renderTitleComponent={props => {
							const title = props.scene.route.title
							return <NavigationHeader.Title>{title}</NavigationHeader.Title>
						}}
						// When dealing with modals you may also want to override renderLeftComponent...
					/>
				)}
				renderScene={this._renderScene}
			/>
		)
	}

	_renderScene({scene}) {
		const { route } = scene

		switch(route.key) {
		case 'First':
			return <First />
		case 'Second':
			return <Second />
		case 'Third':
			return <Third />
		case 'Modal':
			return <Modal />
		}
	}
}

AppContainerWithCardStack.propTypes = {
	navigationState: PropTypes.object,
	backAction: PropTypes.func.isRequired
}

const styles = StyleSheet.create({
	container: {
		flex: 1
	}
})

export default connect(
	state => ({
		navigationState: state.navigationState
	}),
	dispatch => ({
		backAction: () => {
			dispatch(navigatePop())
		}
	})
)(AppContainerWithCardStack)<commit_msg>{WIP} Removing modal from the app... for now<commit_after>'use strict'

import React, {PropTypes} from 'react'
import {NavigationExperimental, StyleSheet} from 'react-native'
import { connect } from 'react-redux'

import First from './First'
import Second from './Second'
import Third from './Third'
import Modal from './Modal'
import { navigatePop } from '../actions'

const {
	CardStack: NavigationCardStack,
	Card: NavigationCard,
	Header: NavigationHeader
} = NavigationExperimental

class AppContainerWithCardStack extends React.Component {
	render() {
		let { navigationState, backAction } = this.props

		return (

			// Redux is handling the reduction of our state for us. We grab the navigationState
			// we have in our Redux store and pass it directly to the <NavigationCardStack />.
			<NavigationCardStack
				navigationState={navigationState}
				onNavigateBack={backAction}
				style={styles.container}
				renderHeader={props => (
					<NavigationHeader
						{...props}
						onNavigateBack={backAction}
						renderTitleComponent={props => {
							const title = props.scene.route.title
							return <NavigationHeader.Title>{title}</NavigationHeader.Title>
						}}
						// When dealing with modals you may also want to override renderLeftComponent...
					/>
				)}
				renderScene={this._renderScene}
			/>
		)
	}

	_renderScene({scene}) {
		const { route } = scene

		switch(route.key) {
		case 'First':
			return <First />
		case 'Second':
			return <Second />
		case 'Third':
			return <Third />
		case 'Modal':
			return <Modal />
		}
	}
}

AppContainerWithCardStack.propTypes = {
	navigationState: PropTypes.object,
	backAction: PropTypes.func.isRequired
}

const styles = StyleSheet.create({
	container: {
		flex: 1
	}
})

export default connect(
	state => ({
		navigationState: state.navigationState
	}),
	dispatch => ({
		backAction: () => {
			dispatch(navigatePop())
		}
	})
)(AppContainerWithCardStack)
<|endoftext|>


<commit_before>import {
  COMPOSE_MOUNT,
  COMPOSE_UNMOUNT,
  COMPOSE_CHANGE,
  COMPOSE_REPLY,
  COMPOSE_REPLY_CANCEL,
  COMPOSE_MENTION,
  COMPOSE_SUBMIT_REQUEST,
  COMPOSE_SUBMIT_SUCCESS,
  COMPOSE_SUBMIT_FAIL,
  COMPOSE_UPLOAD_REQUEST,
  COMPOSE_UPLOAD_SUCCESS,
  COMPOSE_UPLOAD_FAIL,
  COMPOSE_UPLOAD_UNDO,
  COMPOSE_UPLOAD_PROGRESS,
  COMPOSE_SUGGESTIONS_CLEAR,
  COMPOSE_SUGGESTIONS_READY,
  COMPOSE_SUGGESTION_SELECT,
  COMPOSE_SENSITIVITY_CHANGE,
  COMPOSE_SPOILERNESS_CHANGE,
  COMPOSE_SPOILER_TEXT_CHANGE,
  COMPOSE_VISIBILITY_CHANGE,
  COMPOSE_COMPOSING_CHANGE,
  COMPOSE_EMOJI_INSERT,
} from '../actions/compose';
import { COMPOSE_LOCK_TAG } from '../actions/favourite_tags';
import { TIMELINE_DELETE } from '../actions/timelines';
import { STORE_HYDRATE } from '../actions/store';
import { Map as ImmutableMap, List as ImmutableList, OrderedSet as ImmutableOrderedSet, fromJS } from 'immutable';
import uuid from '../uuid';

const initialState = ImmutableMap({
  mounted: false,
  sensitive: false,
  spoiler: false,
  spoiler_text: '',
  privacy: null,
  text: '',
  focusDate: null,
  preselectDate: null,
  in_reply_to: null,
  is_composing: false,
  is_submitting: false,
  is_uploading: false,
  progress: 0,
  media_attachments: ImmutableList(),
  suggestion_token: null,
  suggestions: ImmutableList(),
  me: null,
  default_privacy: 'public',
  default_sensitive: false,
  resetFileKey: Math.floor((Math.random() * 0x10000)),
  idempotencyKey: null,
  defaultText: '',
});

function statusToTextMentions(state, status) {
  let set = ImmutableOrderedSet([]);
  let me  = state.get('me');

  if (status.getIn(['account', 'id']) !== me) {
    set = set.add(`@${status.getIn(['account', 'acct'])} `);
  }

  return set.union(status.get('mentions').filterNot(mention => mention.get('id') === me).map(mention => `@${mention.get('acct')} `)).join('');
};

function clearAll(state) {
  const defaultText = state.get('defaultText');
  return state.withMutations(map => {
    map.set('text', defaultText === '' ? '' : ` ${defaultText}`);
    map.set('spoiler', false);
    map.set('spoiler_text', '');
    map.set('is_submitting', false);
    map.set('in_reply_to', null);
    map.set('privacy', state.get('default_privacy'));
    map.set('sensitive', false);
    map.update('media_attachments', list => list.clear());
    map.set('idempotencyKey', uuid());
  });
};

function appendMedia(state, media) {
  const prevSize = state.get('media_attachments').size;

  return state.withMutations(map => {
    map.update('media_attachments', list => list.push(media));
    map.set('is_uploading', false);
    map.set('resetFileKey', Math.floor((Math.random() * 0x10000)));
    map.update('text', oldText => `${oldText.trim()} ${media.get('text_url')}`);
    map.set('focusDate', new Date());
    map.set('idempotencyKey', uuid());

    if (prevSize === 0 && (state.get('default_sensitive') || state.get('spoiler'))) {
      map.set('sensitive', true);
    }
  });
};

function removeMedia(state, mediaId) {
  const media    = state.get('media_attachments').find(item => item.get('id') === mediaId);
  const prevSize = state.get('media_attachments').size;

  return state.withMutations(map => {
    map.update('media_attachments', list => list.filterNot(item => item.get('id') === mediaId));
    map.update('text', text => text.replace(media.get('text_url'), '').trim());
    map.set('idempotencyKey', uuid());

    if (prevSize === 1) {
      map.set('sensitive', false);
    }
  });
};

const insertSuggestion = (state, position, token, completion) => {
  return state.withMutations(map => {
    map.update('text', oldText => `${oldText.slice(0, position)}${completion} ${oldText.slice(position + token.length)}`);
    map.set('suggestion_token', null);
    map.update('suggestions', ImmutableList(), list => list.clear());
    map.set('focusDate', new Date());
    map.set('idempotencyKey', uuid());
  });
};

const insertEmoji = (state, position, emojiData) => {
  const emoji = emojiData.unicode.split('-').map(code => String.fromCodePoint(parseInt(code, 16))).join('');

  return state.withMutations(map => {
    map.update('text', oldText => `${oldText.slice(0, position)}${emoji} ${oldText.slice(position)}`);
    map.set('focusDate', new Date());
    map.set('idempotencyKey', uuid());
  });
};

const setDefaultText = (state, text) => {
  const replaceRE = new RegExp(` *${state.get('defaultText')}`);
  return state.withMutations(map => {
    map.update('text', oldText => oldText.replace(replaceRE, '') + (text === '' ? '' : ` ${text}`));
    map.set('defaultText', text);
  });
};

const privacyPreference = (a, b) => {
  if (a === 'direct' || b === 'direct') {
    return 'direct';
  } else if (a === 'private' || b === 'private') {
    return 'private';
  } else if (a === 'unlisted' || b === 'unlisted') {
    return 'unlisted';
  } else {
    return 'public';
  }
};

export default function compose(state = initialState, action) {
  switch(action.type) {
  case STORE_HYDRATE:
    return clearAll(state.merge(action.state.get('compose')));
  case COMPOSE_MOUNT:
    return state.set('mounted', true);
  case COMPOSE_UNMOUNT:
    return state
      .set('mounted', false)
      .set('is_composing', false);
  case COMPOSE_SENSITIVITY_CHANGE:
    return state.withMutations(map => {
      if (!state.get('spoiler')) {
        map.set('sensitive', !state.get('sensitive'));
      }

      map.set('idempotencyKey', uuid());
    });
  case COMPOSE_SPOILERNESS_CHANGE:
    return state.withMutations(map => {
      map.set('spoiler_text', '');
      map.set('spoiler', !state.get('spoiler'));
      map.set('idempotencyKey', uuid());

      if (!state.get('sensitive') && state.get('media_attachments').size >= 1) {
        map.set('sensitive', true);
      }
    });
  case COMPOSE_SPOILER_TEXT_CHANGE:
    return state
      .set('spoiler_text', action.text)
      .set('idempotencyKey', uuid());
  case COMPOSE_VISIBILITY_CHANGE:
    return state
      .set('privacy', action.value)
      .set('idempotencyKey', uuid());
  case COMPOSE_CHANGE:
    return state
      .set('text', action.text)
      .set('idempotencyKey', uuid());
  case COMPOSE_COMPOSING_CHANGE:
    return state.set('is_composing', action.value);
  case COMPOSE_REPLY:
    return state.withMutations(map => {
      map.set('in_reply_to', action.status.get('id'));
      map.set('text', statusToTextMentions(state, action.status));
      map.set('privacy', privacyPreference(action.status.get('visibility'), state.get('default_privacy')));
      map.set('focusDate', new Date());
      map.set('preselectDate', new Date());
      map.set('idempotencyKey', uuid());

      if (action.status.get('spoiler_text').length > 0) {
        map.set('spoiler', true);
        map.set('spoiler_text', action.status.get('spoiler_text'));
      } else {
        map.set('spoiler', false);
        map.set('spoiler_text', '');
      }
    });
  case COMPOSE_REPLY_CANCEL:
    return state.withMutations(map => {
      map.set('in_reply_to', null);
      map.set('text', '');
      map.set('spoiler', false);
      map.set('spoiler_text', '');
      map.set('privacy', state.get('default_privacy'));
      map.set('idempotencyKey', uuid());
    });
  case COMPOSE_SUBMIT_REQUEST:
    return state.set('is_submitting', true);
  case COMPOSE_SUBMIT_SUCCESS:
    return clearAll(state);
  case COMPOSE_SUBMIT_FAIL:
    return state.set('is_submitting', false);
  case COMPOSE_UPLOAD_REQUEST:
    return state.withMutations(map => {
      map.set('is_uploading', true);
    });
  case COMPOSE_UPLOAD_SUCCESS:
    return appendMedia(state, fromJS(action.media));
  case COMPOSE_UPLOAD_FAIL:
    return state.set('is_uploading', false);
  case COMPOSE_UPLOAD_UNDO:
    return removeMedia(state, action.media_id);
  case COMPOSE_UPLOAD_PROGRESS:
    return state.set('progress', Math.round((action.loaded / action.total) * 100));
  case COMPOSE_MENTION:
    return state
      .update('text', text => `${text}@${action.account.get('acct')} `)
      .set('focusDate', new Date())
      .set('idempotencyKey', uuid());
  case COMPOSE_SUGGESTIONS_CLEAR:
    return state.update('suggestions', ImmutableList(), list => list.clear()).set('suggestion_token', null);
  case COMPOSE_SUGGESTIONS_READY:
    return state.set('suggestions', ImmutableList(action.accounts.map(item => item.id))).set('suggestion_token', action.token);
  case COMPOSE_SUGGESTION_SELECT:
    return insertSuggestion(state, action.position, action.token, action.completion);
  case TIMELINE_DELETE:
    if (action.id === state.get('in_reply_to')) {
      return state.set('in_reply_to', null);
    } else {
      return state;
    }
  case COMPOSE_EMOJI_INSERT:
    return insertEmoji(state, action.position, action.emoji);
  case COMPOSE_LOCK_TAG:
    return setDefaultText(state, action.tag)
      .set('privacy', action.tag !== '' ? 'unlisted' : 'public');
  default:
    return state;
  }
};
<commit_msg>revert favourite tag function add privacy change<commit_after>import {
  COMPOSE_MOUNT,
  COMPOSE_UNMOUNT,
  COMPOSE_CHANGE,
  COMPOSE_REPLY,
  COMPOSE_REPLY_CANCEL,
  COMPOSE_MENTION,
  COMPOSE_SUBMIT_REQUEST,
  COMPOSE_SUBMIT_SUCCESS,
  COMPOSE_SUBMIT_FAIL,
  COMPOSE_UPLOAD_REQUEST,
  COMPOSE_UPLOAD_SUCCESS,
  COMPOSE_UPLOAD_FAIL,
  COMPOSE_UPLOAD_UNDO,
  COMPOSE_UPLOAD_PROGRESS,
  COMPOSE_SUGGESTIONS_CLEAR,
  COMPOSE_SUGGESTIONS_READY,
  COMPOSE_SUGGESTION_SELECT,
  COMPOSE_SENSITIVITY_CHANGE,
  COMPOSE_SPOILERNESS_CHANGE,
  COMPOSE_SPOILER_TEXT_CHANGE,
  COMPOSE_VISIBILITY_CHANGE,
  COMPOSE_COMPOSING_CHANGE,
  COMPOSE_EMOJI_INSERT,
} from '../actions/compose';
import { COMPOSE_LOCK_TAG } from '../actions/favourite_tags';
import { TIMELINE_DELETE } from '../actions/timelines';
import { STORE_HYDRATE } from '../actions/store';
import { Map as ImmutableMap, List as ImmutableList, OrderedSet as ImmutableOrderedSet, fromJS } from 'immutable';
import uuid from '../uuid';

const initialState = ImmutableMap({
  mounted: false,
  sensitive: false,
  spoiler: false,
  spoiler_text: '',
  privacy: null,
  text: '',
  focusDate: null,
  preselectDate: null,
  in_reply_to: null,
  is_composing: false,
  is_submitting: false,
  is_uploading: false,
  progress: 0,
  media_attachments: ImmutableList(),
  suggestion_token: null,
  suggestions: ImmutableList(),
  me: null,
  default_privacy: 'public',
  default_sensitive: false,
  resetFileKey: Math.floor((Math.random() * 0x10000)),
  idempotencyKey: null,
  defaultText: '',
});

function statusToTextMentions(state, status) {
  let set = ImmutableOrderedSet([]);
  let me  = state.get('me');

  if (status.getIn(['account', 'id']) !== me) {
    set = set.add(`@${status.getIn(['account', 'acct'])} `);
  }

  return set.union(status.get('mentions').filterNot(mention => mention.get('id') === me).map(mention => `@${mention.get('acct')} `)).join('');
};

function clearAll(state) {
  const defaultText = state.get('defaultText');
  return state.withMutations(map => {
    map.set('text', defaultText === '' ? '' : ` ${defaultText}`);
    map.set('spoiler', false);
    map.set('spoiler_text', '');
    map.set('is_submitting', false);
    map.set('in_reply_to', null);
    map.set('privacy', state.get('default_privacy'));
    map.set('sensitive', false);
    map.update('media_attachments', list => list.clear());
    map.set('idempotencyKey', uuid());
  });
};

function appendMedia(state, media) {
  const prevSize = state.get('media_attachments').size;

  return state.withMutations(map => {
    map.update('media_attachments', list => list.push(media));
    map.set('is_uploading', false);
    map.set('resetFileKey', Math.floor((Math.random() * 0x10000)));
    map.update('text', oldText => `${oldText.trim()} ${media.get('text_url')}`);
    map.set('focusDate', new Date());
    map.set('idempotencyKey', uuid());

    if (prevSize === 0 && (state.get('default_sensitive') || state.get('spoiler'))) {
      map.set('sensitive', true);
    }
  });
};

function removeMedia(state, mediaId) {
  const media    = state.get('media_attachments').find(item => item.get('id') === mediaId);
  const prevSize = state.get('media_attachments').size;

  return state.withMutations(map => {
    map.update('media_attachments', list => list.filterNot(item => item.get('id') === mediaId));
    map.update('text', text => text.replace(media.get('text_url'), '').trim());
    map.set('idempotencyKey', uuid());

    if (prevSize === 1) {
      map.set('sensitive', false);
    }
  });
};

const insertSuggestion = (state, position, token, completion) => {
  return state.withMutations(map => {
    map.update('text', oldText => `${oldText.slice(0, position)}${completion} ${oldText.slice(position + token.length)}`);
    map.set('suggestion_token', null);
    map.update('suggestions', ImmutableList(), list => list.clear());
    map.set('focusDate', new Date());
    map.set('idempotencyKey', uuid());
  });
};

const insertEmoji = (state, position, emojiData) => {
  const emoji = emojiData.unicode.split('-').map(code => String.fromCodePoint(parseInt(code, 16))).join('');

  return state.withMutations(map => {
    map.update('text', oldText => `${oldText.slice(0, position)}${emoji} ${oldText.slice(position)}`);
    map.set('focusDate', new Date());
    map.set('idempotencyKey', uuid());
  });
};

const setDefaultText = (state, text) => {
  const replaceRE = new RegExp(` *${state.get('defaultText')}`);
  return state.withMutations(map => {
    map.update('text', oldText => oldText.replace(replaceRE, '') + (text === '' ? '' : ` ${text}`));
    map.set('defaultText', text);
  });
};

const privacyPreference = (a, b) => {
  if (a === 'direct' || b === 'direct') {
    return 'direct';
  } else if (a === 'private' || b === 'private') {
    return 'private';
  } else if (a === 'unlisted' || b === 'unlisted') {
    return 'unlisted';
  } else {
    return 'public';
  }
};

export default function compose(state = initialState, action) {
  switch(action.type) {
  case STORE_HYDRATE:
    return clearAll(state.merge(action.state.get('compose')));
  case COMPOSE_MOUNT:
    return state.set('mounted', true);
  case COMPOSE_UNMOUNT:
    return state
      .set('mounted', false)
      .set('is_composing', false);
  case COMPOSE_SENSITIVITY_CHANGE:
    return state.withMutations(map => {
      if (!state.get('spoiler')) {
        map.set('sensitive', !state.get('sensitive'));
      }

      map.set('idempotencyKey', uuid());
    });
  case COMPOSE_SPOILERNESS_CHANGE:
    return state.withMutations(map => {
      map.set('spoiler_text', '');
      map.set('spoiler', !state.get('spoiler'));
      map.set('idempotencyKey', uuid());

      if (!state.get('sensitive') && state.get('media_attachments').size >= 1) {
        map.set('sensitive', true);
      }
    });
  case COMPOSE_SPOILER_TEXT_CHANGE:
    return state
      .set('spoiler_text', action.text)
      .set('idempotencyKey', uuid());
  case COMPOSE_VISIBILITY_CHANGE:
    return state
      .set('privacy', action.value)
      .set('idempotencyKey', uuid());
  case COMPOSE_CHANGE:
    return state
      .set('text', action.text)
      .set('idempotencyKey', uuid());
  case COMPOSE_COMPOSING_CHANGE:
    return state.set('is_composing', action.value);
  case COMPOSE_REPLY:
    return state.withMutations(map => {
      map.set('in_reply_to', action.status.get('id'));
      map.set('text', statusToTextMentions(state, action.status));
      map.set('privacy', privacyPreference(action.status.get('visibility'), state.get('default_privacy')));
      map.set('focusDate', new Date());
      map.set('preselectDate', new Date());
      map.set('idempotencyKey', uuid());

      if (action.status.get('spoiler_text').length > 0) {
        map.set('spoiler', true);
        map.set('spoiler_text', action.status.get('spoiler_text'));
      } else {
        map.set('spoiler', false);
        map.set('spoiler_text', '');
      }
    });
  case COMPOSE_REPLY_CANCEL:
    return state.withMutations(map => {
      map.set('in_reply_to', null);
      map.set('text', '');
      map.set('spoiler', false);
      map.set('spoiler_text', '');
      map.set('privacy', state.get('default_privacy'));
      map.set('idempotencyKey', uuid());
    });
  case COMPOSE_SUBMIT_REQUEST:
    return state.set('is_submitting', true);
  case COMPOSE_SUBMIT_SUCCESS:
    return clearAll(state);
  case COMPOSE_SUBMIT_FAIL:
    return state.set('is_submitting', false);
  case COMPOSE_UPLOAD_REQUEST:
    return state.withMutations(map => {
      map.set('is_uploading', true);
    });
  case COMPOSE_UPLOAD_SUCCESS:
    return appendMedia(state, fromJS(action.media));
  case COMPOSE_UPLOAD_FAIL:
    return state.set('is_uploading', false);
  case COMPOSE_UPLOAD_UNDO:
    return removeMedia(state, action.media_id);
  case COMPOSE_UPLOAD_PROGRESS:
    return state.set('progress', Math.round((action.loaded / action.total) * 100));
  case COMPOSE_MENTION:
    return state
      .update('text', text => `${text}@${action.account.get('acct')} `)
      .set('focusDate', new Date())
      .set('idempotencyKey', uuid());
  case COMPOSE_SUGGESTIONS_CLEAR:
    return state.update('suggestions', ImmutableList(), list => list.clear()).set('suggestion_token', null);
  case COMPOSE_SUGGESTIONS_READY:
    return state.set('suggestions', ImmutableList(action.accounts.map(item => item.id))).set('suggestion_token', action.token);
  case COMPOSE_SUGGESTION_SELECT:
    return insertSuggestion(state, action.position, action.token, action.completion);
  case TIMELINE_DELETE:
    if (action.id === state.get('in_reply_to')) {
      return state.set('in_reply_to', null);
    } else {
      return state;
    }
  case COMPOSE_EMOJI_INSERT:
    return insertEmoji(state, action.position, action.emoji);
  case COMPOSE_LOCK_TAG:
    return setDefaultText(state, action.tag);
  default:
    return state;
  }
};
<|endoftext|>


<commit_before>jQuery(function($) {

	var $body = $('body');
	var $doc = $(document);

	// initialize the sound player of each key
	$('.piano-keyboard .key').each(function() {
		var key = $(this);
		var tone = key.data('tone');
		var _tone = encodeURIComponent(tone);
		var toneID = tone.replace('#', '_');
		var player = $('

').appendTo($body);

		player.jPlayer({
			ready: function (event) {
				$(this).jPlayer("setMedia", {
					m4a: "audio/mp3/" + _tone + '.mp3',
					oga: "audio/ogg/" + _tone + '.ogg'
				});
			},
			supplied: "m4a, oga"
		}).on($.jPlayer.event.play, function() {
			setTimeout(function() {
				key.removeClass('pressed');
			}, 300);
		});
	});

	// handler for mousedown/touchstart for each key
	$('.piano-keyboard .key').on('mousedown touchstart', function() {
		var tone = $(this).data('tone');
		var toneID = tone.replace('#', '_');
		var player = $('#' + toneID);
		player.jPlayer('stop').jPlayer('play');
		$(this).addClass('pressed');
	});

	// piano keyboard to computer keyboard key mappings
	var keyMappings = {
		90: 'c4', // Z
		88: 'd4', // X
		67: 'e4', // C
		86: 'f4', // V
		66: 'g4', // B
		78: 'a4', // N
		77: 'b4', // M
		188: 'c5', // ,
		190: 'd5', // .
		191: 'e5', // /

		83: 'c#4', // S
		68: 'd#4', // D
		71: 'f#4', // G
		72: 'g#4', // H
		74: 'a#4', // J
		76: 'c#5', // L
		186: 'd#5', // ;

		81: 'c5', // Q
		87: 'd5', // W
		69: 'e5', // E
		82: 'f5', // R
		84: 'g5', // T
		89: 'a5', // Y
		85: 'b5', // U
		73: 'c6', // I
		79: 'd6', // O
		80: 'e6', // P
		219: 'f6', // [
		221: 'g6', // ]

		50: 'c#5', // 2
		51: 'd#5', // 3
		53: 'f#5', // 5
		54: 'g#5', // 6
		55: 'a#5', // 7
		57: 'c#6', // 9
		48: 'd#6', // 0
		187: 'f#6', // =
	};

	// handle keydown to allow playing with keyboard
	var keyIsDown = {};
	$doc.on('keydown', function(event) {
		var keycode = (event.keyCode ? event.keyCode : event.which);

		// disallow repetitive keydown event
		if ( !keyIsDown[keycode] ) {
			if (typeof keyMappings[keycode] !== 'undefined') {
				$('[data-tone="' + keyMappings[keycode] + '"]').trigger('mousedown');
			}

			keyIsDown[keycode] = true;
		}
	});

	// handle keyup to reset the keydown event flag
	$doc.on('keyup', function(event) {
		var keycode = (event.keyCode ? event.keyCode : event.which);

		keyIsDown[keycode] = false;
	});

});<commit_msg>explaining keyboard mapping<commit_after>jQuery(function($) {

	var $body = $('body');
	var $doc = $(document);

	// initialize the sound player of each key
	$('.piano-keyboard .key').each(function() {
		var key = $(this);
		var tone = key.data('tone');
		var _tone = encodeURIComponent(tone);
		var toneID = tone.replace('#', '_');
		var player = $('

').appendTo($body);

		player.jPlayer({
			ready: function (event) {
				$(this).jPlayer("setMedia", {
					m4a: "audio/mp3/" + _tone + '.mp3',
					oga: "audio/ogg/" + _tone + '.ogg'
				});
			},

			supplied: "m4a, oga"
		}).on($.jPlayer.event.play, function() {
			setTimeout(function() {
				key.removeClass('pressed');
			}, 300);
		});
	});

	// handler for mousedown/touchstart for each key
	$('.piano-keyboard .key').on('mousedown touchstart', function() {
		var tone = $(this).data('tone');
		var toneID = tone.replace('#', '_');
		var player = $('#' + toneID);
		player.jPlayer('stop').jPlayer('play');
		$(this).addClass('pressed');
	});

	// piano keyboard to computer keyboard key mappings
	// starting from lower key rows, going to upper key rows
	// as positioned on a QWERTY keyboard
	var keyMappings = {
		90: 'c4', // Z
		88: 'd4', // X
		67: 'e4', // C
		86: 'f4', // V
		66: 'g4', // B
		78: 'a4', // N
		77: 'b4', // M
		188: 'c5', // ,
		190: 'd5', // .
		191: 'e5', // /

		83: 'c#4', // S
		68: 'd#4', // D
		71: 'f#4', // G
		72: 'g#4', // H
		74: 'a#4', // J
		76: 'c#5', // L
		186: 'd#5', // ;

		81: 'c5', // Q
		87: 'd5', // W
		69: 'e5', // E
		82: 'f5', // R
		84: 'g5', // T
		89: 'a5', // Y
		85: 'b5', // U
		73: 'c6', // I
		79: 'd6', // O
		80: 'e6', // P
		219: 'f6', // [
		221: 'g6', // ]

		50: 'c#5', // 2
		51: 'd#5', // 3
		53: 'f#5', // 5
		54: 'g#5', // 6
		55: 'a#5', // 7
		57: 'c#6', // 9
		48: 'd#6', // 0
		187: 'f#6', // =
	};

	// handle keydown to allow playing with keyboard
	var keyIsDown = {};
	$doc.on('keydown', function(event) {
		var keycode = (event.keyCode ? event.keyCode : event.which);

		// disallow repetitive keydown event
		if ( !keyIsDown[keycode] ) {
			if (typeof keyMappings[keycode] !== 'undefined') {
				$('[data-tone="' + keyMappings[keycode] + '"]').trigger('mousedown');
			}

			keyIsDown[keycode] = true;
		}
	});

	// handle keyup to reset the keydown event flag
	$doc.on('keyup', function(event) {
		var keycode = (event.keyCode ? event.keyCode : event.which);

		keyIsDown[keycode] = false;
	});

});<|endoftext|>