<commit_before>define([
    'knockout',
    'underscore',
    'viewmodels/widget',
    'leaflet',
    'knockout-mapping',
    'uuid',
    'arches',
    'leaflet-iiif',
    'leaflet-draw',
    'leaflet-draw-local',
    'bindings/leaflet'
], function(ko, _, WidgetViewModel, L, koMapping, uuid, arches) {
    return ko.components.register('iiif-widget', {
        viewModel: function(params) {
            var self = this;
            var canvasLayer = null;
            params.configKeys = ['nameLabel', 'placeholder', 'typeLabel'];
            WidgetViewModel.apply(this, [params]);

            this.displayValue = ko.computed(function() {
                var val = ko.unwrap(self.value);
                if (!val) {
                    return val;
                }
                return val.manifestLabel;
            });

            var features = self.value.features ? koMapping.toJS(self.value.features) : [];
            var ignoreFeatureClick = false;
            this.hoverData = ko.observable(null);
            this.clickData = ko.observable(null);
            this.clickName = ko.pureComputed({
                read: function() {
                    return self.clickData() ? self.clickData().name : '';
                },
                write: function(val) {
                    if (self.clickData()) {
                        self.clickData().name = val;
                        updateFeatures();
                    }
                },
                owner: this
            });
            this.clickType = ko.pureComputed({
                read: function() {
                    return self.clickData() ? self.clickData().type : null;
                },
                write: function(val) {
                    if (self.clickData()) {
                        self.clickData().type = val;
                        updateFeatures();
                    }
                },
                owner: this
            });
            this.hoverType = ko.pureComputed(function() {
                return self.hoverData() ? self.hoverData().type : null;
            });
            this.popupData = ko.computed(function() {
                var hoverData = self.hoverData();
                return hoverData ? hoverData : self.clickData();
            });

            var highlightedFeature;
            var highlightedFeatureStyle;
            var largeIcon = new L.Icon.Default();
            largeIcon.options.iconSize = [33, 54]
            largeIcon.options.iconAnchor = [16, 54]
            largeIcon.options.shadowSize =  [54, 54];
            var highlightFeature = function(layer) {
                highlightedFeatureStyle = _.clone(layer.options);
                if (highlightedFeatureStyle.icon) {
                    layer.setIcon(largeIcon);
                } else {
                    layer.setStyle({
                        weight: 7,
                        color: '#2a3fff',
                        fillOpacity: 0.7
                    });

                    if (!L.Browser.ie && !L.Browser.opera && !L.Browser.edge) {
                        layer.bringToFront();
                    }
                }

                highlightedFeature = layer;
            };

            this.clickData.subscribe(function(clickData) {
                if (highlightedFeature) {
                    if (highlightedFeatureStyle.icon) {
                        highlightedFeature.setIcon(highlightedFeatureStyle.icon);
                    } else {
                        highlightedFeature.setStyle(highlightedFeatureStyle);
                    }
                    highlightedFeature = null;
                    highlightedFeatureStyle = null;
                }
            });

            var addLayerListeners = function(layer) {
                layer.on({
                    mouseover: function(e) {
                        self.hoverData(layer.feature.properties);
                    },
                    mouseout: function(e) {
                        self.hoverData(null);
                    },
                    click: function(e) {
                        if (!ignoreFeatureClick) {
                            self.clickData(layer.feature.properties);
                            highlightFeature(layer);
                        }
                    }
                });
            }
            var drawnItems = new L.geoJson({
                type: 'FeatureCollection',
                features: features
            }, {
                onEachFeature: function(feature, layer) {
                    addLayerListeners(layer)
                }
            });
            var drawControl = new L.Control.Draw({
                edit: {
                    featureGroup: drawnItems
                },
                draw: {
                    circle: false
                }
            });

            this.expandControls = ko.observable(false);

            var manifestId;
            var canvasId;
            if (self.value.manifestId !== undefined) {
                manifestId = ko.unwrap(self.value.manifestId);
            }
            if (self.value.canvasId !== undefined) {
                canvasId = ko.unwrap(self.value.canvasId);
            }
            this.selectedManifest = ko.observable(null);
            this.selectedCanvas = ko.observable(null);
            var updateSelections = function(manifest) {
                var selectedCanvas;
                var selectedManifest;
                if (manifest.data()['@id'] === manifestId) {
                    selectedManifest = manifest;
                    _.find(manifest.data().sequences, function(sequence) {
                        var canvas = _.find(sequence.canvases, function(canvas) {
                            return canvas['@id'] === canvasId;
                        });
                        if (canvas) {
                            selectedCanvas = canvas;
                        }
                        return canvas;
                    });
                }
                if (selectedManifest) {
                    self.selectedManifest(selectedManifest);
                }
                if (selectedCanvas) {
                    self.selectedCanvas(selectedCanvas);
                }
            }
            _.each(arches.iiifManifests, function(manifest) {
                if (!manifest.data) {
                    manifest.data = ko.observable(null);
                    $.get(manifest.url, function(data) {
                        manifest.data(data);
                    });
                }
                if (manifest.data()) {
                    updateSelections(manifest);
                } else {
                    manifest.data.subscribe(function() {
                        updateSelections(manifest);
                    })
                }
            });
            this.manifests = ko.observableArray(arches.iiifManifests);

            var updateFeatures = function() {
                var features = drawnItems.toGeoJSON().features;
                if (self.value.features !== undefined) {
                    self.value.features(features);
                } else {
                    var value = self.value();
                    if (!value) {
                        value = {
                            canvasId: null,
                            canvasLabel: null,
                            manifestId: null,
                            manifestLabel: null,
                            attribution: null,
                            url: null
                        };
                    }
                    value.features = features;
                    self.value(value)
                }
            }
            this.map = null;
            this.mapConfig = {
                center: [0, 0],
                crs: L.CRS.Simple,
                zoom: 0,
                afterRender: function(map) {
                    var url;
                    var attribution;
                    if (self.value.url !== undefined) {
                        url = ko.unwrap(self.value.url);
                    }
                    if (self.value.attribution !== undefined) {
                        attribution = ko.unwrap(self.value.manifestLabel) + ', ' +
                            ko.unwrap(self.value.canvasLabel) + ', ' +
                            ko.unwrap(self.value.attribution);
                    }
                    self.map = map;
                    self.map.addLayer(drawnItems);
                    map.on('preclick', function(e) {
                        self.clickData(null);
                    });

                    if (url) {
                        canvasLayer = L.tileLayer.iiif(
                            url, {
                                attribution: attribution
                            }
                        ).addTo(self.map);
                    }

                    if (self.state !== 'report') {
                        self.map.addControl(drawControl);
                        map.on('draw:deletestart', function(e) {
                            ignoreFeatureClick = true;
                        });
                        map.on('draw:deletestop', function(e) {
                            ignoreFeatureClick = false;
                        })
                    } else {
                        self.map.addLayer(drawnItems);
                    }

                    self.map.on(L.Draw.Event.CREATED, function(e) {
                        var type = e.layerType
                        var layer = e.layer;
                        layer.feature = {
                            type: "Feature",
                            properties: {
                                id: uuid.generate(),
                                name: '',
                                type: null
                            }
                        };

                        addLayerListeners(layer);

                        drawnItems.addLayer(layer);

                        updateFeatures()
                    });
                    self.map.on(L.Draw.Event.EDITED, updateFeatures);
                    self.map.on(L.Draw.Event.DELETED, updateFeatures);

                    self.expanded.subscribe(function () {
                        console.log(self.tile.tileid())
                        _.defer(function () {
                            self.map.invalidateSize();
                        }, 500);
                    });
                }
            };

            this.selectedCanvas.subscribe(function(canvas) {
                var url;
                var manifest = self.selectedManifest() ? self.selectedManifest().data() : {
                    '@id': null,
                    'label': null,
                    'attribution': null
                };
                if (self.map && canvasLayer && self.map.hasLayer(canvasLayer)) {
                    self.map.removeLayer(canvasLayer);
                    canvasLayer = null;
                }
                if (canvas) {
                    if (canvas.images.length > 0) {
                        url = canvas.images[0].resource.service['@id'] + '/info.json';
                    }
                    if (self.map) {
                        self.map.removeLayer(drawnItems);
                        if (canvas.images.length > 0) {
                            canvasLayer = L.tileLayer.iiif(
                                canvas.images[0].resource.service['@id'] + '/info.json', {
                                    attribution: manifest['label'] + ', ' + canvas['label'] + ', ' + manifest['attribution']
                                }
                            ).addTo(self.map);
                        }
                        self.map.addLayer(drawnItems);
                    }
                } else {
                    canvas = {
                        '@id': null,
                        'label': null
                    };
                    url = null;
                }
                if (self.value.canvasId !== undefined) {
                    self.value.canvasId(canvas['@id']);
                    self.value.canvasLabel(canvas['label']);
                    self.value.manifestId(manifest['@id']);
                    self.value.manifestLabel(manifest['label']);
                    self.value.attribution(manifest['attribution']);
                    self.value.url(url);
                    self.value.features(drawnItems.toGeoJSON().features);
                } else {
                    var value = self.value();
                    if (canvas['@id']) {
                        if (!value) {
                            value = {};
                        }
                        value.canvasId = canvas['@id'];
                        value.canvasLabel = canvas['label'];
                        value.manifestId = manifest['@id'];
                        value.manifestLabel = manifest['label'];
                        value.attribution = manifest['attribution'];
                        value.url = url;
                        value.features = drawnItems.toGeoJSON().features;
                    }
                    self.value(value)
                }
            });

            if (this.form) {
                this.form.on('after-update', function(req, tile) {
                    self.clickData(null);
                    if (!ko.unwrap(self.value)) {
                        drawnItems.clearLayers();
                        self.selectedManifest(null);
                        self.selectedCanvas(null);
                    }
                });
                this.form.on('tile-reset', function(tile) {
                    self.clickData(null);
                    drawnItems.clearLayers();
                    var features = self.value.features ? koMapping.toJS(self.value.features) : [];
                    drawnItems.addData({
                        type: 'FeatureCollection',
                        features: features
                    });
                    var manifestId;
                    var canvasId;
                    if (self.value.manifestId !== undefined) {
                        manifestId = ko.unwrap(self.value.manifestId);
                    }
                    if (self.value.canvasId !== undefined) {
                        canvasId = ko.unwrap(self.value.canvasId);
                    }
                    var selectedManifest = _.find(self.manifests(), function(manifest) {
                        return manifest.data()['@id'] === manifestId
                    });
                    var selectedCanvas = null;
                    if (selectedManifest) {
                        _.find(selectedManifest.data().sequences, function(sequence) {
                            var canvas = _.find(sequence.canvases, function(canvas) {
                                return canvas['@id'] === canvasId;
                            });
                            if (canvas) {
                                selectedCanvas = canvas;
                            }
                            return canvas;
                        });
                    }
                    var currentCanvasId = self.selectedCanvas() ? self.selectedCanvas()['@id'] : null;
                    var selectedCanvasId = selectedCanvas ? selectedCanvas['@id'] : null;
                    if (currentCanvasId !== selectedCanvasId) {
                        self.selectedCanvas(selectedCanvas);
                    }
                    self.selectedManifest(selectedManifest);
                });
            }
        },
        template: {
            require: 'text!widget-templates/iiif'
        }
    });
});
<commit_msg>removing console.log re: #2006<commit_after>define([
    'knockout',
    'underscore',
    'viewmodels/widget',
    'leaflet',
    'knockout-mapping',
    'uuid',
    'arches',
    'leaflet-iiif',
    'leaflet-draw',
    'leaflet-draw-local',
    'bindings/leaflet'
], function(ko, _, WidgetViewModel, L, koMapping, uuid, arches) {
    return ko.components.register('iiif-widget', {
        viewModel: function(params) {
            var self = this;
            var canvasLayer = null;
            params.configKeys = ['nameLabel', 'placeholder', 'typeLabel'];
            WidgetViewModel.apply(this, [params]);

            this.displayValue = ko.computed(function() {
                var val = ko.unwrap(self.value);
                if (!val) {
                    return val;
                }
                return val.manifestLabel;
            });

            var features = self.value.features ? koMapping.toJS(self.value.features) : [];
            var ignoreFeatureClick = false;
            this.hoverData = ko.observable(null);
            this.clickData = ko.observable(null);
            this.clickName = ko.pureComputed({
                read: function() {
                    return self.clickData() ? self.clickData().name : '';
                },
                write: function(val) {
                    if (self.clickData()) {
                        self.clickData().name = val;
                        updateFeatures();
                    }
                },
                owner: this
            });
            this.clickType = ko.pureComputed({
                read: function() {
                    return self.clickData() ? self.clickData().type : null;
                },
                write: function(val) {
                    if (self.clickData()) {
                        self.clickData().type = val;
                        updateFeatures();
                    }
                },
                owner: this
            });
            this.hoverType = ko.pureComputed(function() {
                return self.hoverData() ? self.hoverData().type : null;
            });
            this.popupData = ko.computed(function() {
                var hoverData = self.hoverData();
                return hoverData ? hoverData : self.clickData();
            });

            var highlightedFeature;
            var highlightedFeatureStyle;
            var largeIcon = new L.Icon.Default();
            largeIcon.options.iconSize = [33, 54]
            largeIcon.options.iconAnchor = [16, 54]
            largeIcon.options.shadowSize =  [54, 54];
            var highlightFeature = function(layer) {
                highlightedFeatureStyle = _.clone(layer.options);
                if (highlightedFeatureStyle.icon) {
                    layer.setIcon(largeIcon);
                } else {
                    layer.setStyle({
                        weight: 7,
                        color: '#2a3fff',
                        fillOpacity: 0.7
                    });

                    if (!L.Browser.ie && !L.Browser.opera && !L.Browser.edge) {
                        layer.bringToFront();
                    }
                }

                highlightedFeature = layer;
            };

            this.clickData.subscribe(function(clickData) {
                if (highlightedFeature) {
                    if (highlightedFeatureStyle.icon) {
                        highlightedFeature.setIcon(highlightedFeatureStyle.icon);
                    } else {
                        highlightedFeature.setStyle(highlightedFeatureStyle);
                    }
                    highlightedFeature = null;
                    highlightedFeatureStyle = null;
                }
            });

            var addLayerListeners = function(layer) {
                layer.on({
                    mouseover: function(e) {
                        self.hoverData(layer.feature.properties);
                    },
                    mouseout: function(e) {
                        self.hoverData(null);
                    },
                    click: function(e) {
                        if (!ignoreFeatureClick) {
                            self.clickData(layer.feature.properties);
                            highlightFeature(layer);
                        }
                    }
                });
            }
            var drawnItems = new L.geoJson({
                type: 'FeatureCollection',
                features: features
            }, {
                onEachFeature: function(feature, layer) {
                    addLayerListeners(layer)
                }
            });
            var drawControl = new L.Control.Draw({
                edit: {
                    featureGroup: drawnItems
                },
                draw: {
                    circle: false
                }
            });

            this.expandControls = ko.observable(false);

            var manifestId;
            var canvasId;
            if (self.value.manifestId !== undefined) {
                manifestId = ko.unwrap(self.value.manifestId);
            }
            if (self.value.canvasId !== undefined) {
                canvasId = ko.unwrap(self.value.canvasId);
            }
            this.selectedManifest = ko.observable(null);
            this.selectedCanvas = ko.observable(null);
            var updateSelections = function(manifest) {
                var selectedCanvas;
                var selectedManifest;
                if (manifest.data()['@id'] === manifestId) {
                    selectedManifest = manifest;
                    _.find(manifest.data().sequences, function(sequence) {
                        var canvas = _.find(sequence.canvases, function(canvas) {
                            return canvas['@id'] === canvasId;
                        });
                        if (canvas) {
                            selectedCanvas = canvas;
                        }
                        return canvas;
                    });
                }
                if (selectedManifest) {
                    self.selectedManifest(selectedManifest);
                }
                if (selectedCanvas) {
                    self.selectedCanvas(selectedCanvas);
                }
            }
            _.each(arches.iiifManifests, function(manifest) {
                if (!manifest.data) {
                    manifest.data = ko.observable(null);
                    $.get(manifest.url, function(data) {
                        manifest.data(data);
                    });
                }
                if (manifest.data()) {
                    updateSelections(manifest);
                } else {
                    manifest.data.subscribe(function() {
                        updateSelections(manifest);
                    })
                }
            });
            this.manifests = ko.observableArray(arches.iiifManifests);

            var updateFeatures = function() {
                var features = drawnItems.toGeoJSON().features;
                if (self.value.features !== undefined) {
                    self.value.features(features);
                } else {
                    var value = self.value();
                    if (!value) {
                        value = {
                            canvasId: null,
                            canvasLabel: null,
                            manifestId: null,
                            manifestLabel: null,
                            attribution: null,
                            url: null
                        };
                    }
                    value.features = features;
                    self.value(value)
                }
            }
            this.map = null;
            this.mapConfig = {
                center: [0, 0],
                crs: L.CRS.Simple,
                zoom: 0,
                afterRender: function(map) {
                    var url;
                    var attribution;
                    if (self.value.url !== undefined) {
                        url = ko.unwrap(self.value.url);
                    }
                    if (self.value.attribution !== undefined) {
                        attribution = ko.unwrap(self.value.manifestLabel) + ', ' +
                            ko.unwrap(self.value.canvasLabel) + ', ' +
                            ko.unwrap(self.value.attribution);
                    }
                    self.map = map;
                    self.map.addLayer(drawnItems);
                    map.on('preclick', function(e) {
                        self.clickData(null);
                    });

                    if (url) {
                        canvasLayer = L.tileLayer.iiif(
                            url, {
                                attribution: attribution
                            }
                        ).addTo(self.map);
                    }

                    if (self.state !== 'report') {
                        self.map.addControl(drawControl);
                        map.on('draw:deletestart', function(e) {
                            ignoreFeatureClick = true;
                        });
                        map.on('draw:deletestop', function(e) {
                            ignoreFeatureClick = false;
                        })
                    } else {
                        self.map.addLayer(drawnItems);
                    }

                    self.map.on(L.Draw.Event.CREATED, function(e) {
                        var type = e.layerType
                        var layer = e.layer;
                        layer.feature = {
                            type: "Feature",
                            properties: {
                                id: uuid.generate(),
                                name: '',
                                type: null
                            }
                        };

                        addLayerListeners(layer);

                        drawnItems.addLayer(layer);

                        updateFeatures()
                    });
                    self.map.on(L.Draw.Event.EDITED, updateFeatures);
                    self.map.on(L.Draw.Event.DELETED, updateFeatures);

                    self.expanded.subscribe(function () {
                        _.defer(function () {
                            self.map.invalidateSize();
                        }, 500);
                    });
                }
            };

            this.selectedCanvas.subscribe(function(canvas) {
                var url;
                var manifest = self.selectedManifest() ? self.selectedManifest().data() : {
                    '@id': null,
                    'label': null,
                    'attribution': null
                };
                if (self.map && canvasLayer && self.map.hasLayer(canvasLayer)) {
                    self.map.removeLayer(canvasLayer);
                    canvasLayer = null;
                }
                if (canvas) {
                    if (canvas.images.length > 0) {
                        url = canvas.images[0].resource.service['@id'] + '/info.json';
                    }
                    if (self.map) {
                        self.map.removeLayer(drawnItems);
                        if (canvas.images.length > 0) {
                            canvasLayer = L.tileLayer.iiif(
                                canvas.images[0].resource.service['@id'] + '/info.json', {
                                    attribution: manifest['label'] + ', ' + canvas['label'] + ', ' + manifest['attribution']
                                }
                            ).addTo(self.map);
                        }
                        self.map.addLayer(drawnItems);
                    }
                } else {
                    canvas = {
                        '@id': null,
                        'label': null
                    };
                    url = null;
                }
                if (self.value.canvasId !== undefined) {
                    self.value.canvasId(canvas['@id']);
                    self.value.canvasLabel(canvas['label']);
                    self.value.manifestId(manifest['@id']);
                    self.value.manifestLabel(manifest['label']);
                    self.value.attribution(manifest['attribution']);
                    self.value.url(url);
                    self.value.features(drawnItems.toGeoJSON().features);
                } else {
                    var value = self.value();
                    if (canvas['@id']) {
                        if (!value) {
                            value = {};
                        }
                        value.canvasId = canvas['@id'];
                        value.canvasLabel = canvas['label'];
                        value.manifestId = manifest['@id'];
                        value.manifestLabel = manifest['label'];
                        value.attribution = manifest['attribution'];
                        value.url = url;
                        value.features = drawnItems.toGeoJSON().features;
                    }
                    self.value(value)
                }
            });

            if (this.form) {
                this.form.on('after-update', function(req, tile) {
                    self.clickData(null);
                    if (!ko.unwrap(self.value)) {
                        drawnItems.clearLayers();
                        self.selectedManifest(null);
                        self.selectedCanvas(null);
                    }
                });
                this.form.on('tile-reset', function(tile) {
                    self.clickData(null);
                    drawnItems.clearLayers();
                    var features = self.value.features ? koMapping.toJS(self.value.features) : [];
                    drawnItems.addData({
                        type: 'FeatureCollection',
                        features: features
                    });
                    var manifestId;
                    var canvasId;
                    if (self.value.manifestId !== undefined) {
                        manifestId = ko.unwrap(self.value.manifestId);
                    }
                    if (self.value.canvasId !== undefined) {
                        canvasId = ko.unwrap(self.value.canvasId);
                    }
                    var selectedManifest = _.find(self.manifests(), function(manifest) {
                        return manifest.data()['@id'] === manifestId
                    });
                    var selectedCanvas = null;
                    if (selectedManifest) {
                        _.find(selectedManifest.data().sequences, function(sequence) {
                            var canvas = _.find(sequence.canvases, function(canvas) {
                                return canvas['@id'] === canvasId;
                            });
                            if (canvas) {
                                selectedCanvas = canvas;
                            }
                            return canvas;
                        });
                    }
                    var currentCanvasId = self.selectedCanvas() ? self.selectedCanvas()['@id'] : null;
                    var selectedCanvasId = selectedCanvas ? selectedCanvas['@id'] : null;
                    if (currentCanvasId !== selectedCanvasId) {
                        self.selectedCanvas(selectedCanvas);
                    }
                    self.selectedManifest(selectedManifest);
                });
            }
        },
        template: {
            require: 'text!widget-templates/iiif'
        }
    });
});
<|endoftext|>


<commit_before>/*global Backbone, jQuery, _, ENTER_KEY, ESC_KEY */
var app = app || {};

(function ($) {
	'use strict';

	// Todo Item View
	// --------------

	// The DOM element for a todo item...
	app.TodoView = Backbone.View.extend({
		//... is a list tag.
		tagName:  'li',

		// Cache the template function for a single item.
		template: _.template($('#item-template').html()),

		// The DOM events specific to an item.
		events: {
			'click .toggle': 'toggleCompleted',
			'dblclick label': 'edit',
			'click .destroy': 'clear',
			'keypress .edit': 'updateOnEnter',
			'keydown .edit': 'revertOnEscape',
			'blur .edit': 'close'
		},

		// The TodoView listens for changes to its model, re-rendering. Since
		// there's a one-to-one correspondence between a **Todo** and a
		// **TodoView** in this app, we set a direct reference on the model for
		// convenience.
		initialize: function () {
			this.listenTo(this.model, 'change', this.render);
			this.listenTo(this.model, 'destroy', this.remove);
			this.listenTo(this.model, 'visible', this.toggleVisible);
		},

		// Re-render the titles of the todo item.
		render: function () {
			// Backbone LocalStorage is adding `id` attribute instantly after
			// creating a model.  This causes our TodoView to render twice. Once
			// after creating a model and once on `id` change.  We want to
			// filter out the second redundant render, which is caused by this
			// `id` change.  It's known Backbone LocalStorage bug, therefore
			// we've to create a workaround.
			// https://github.com/tastejs/todomvc/issues/469
			if (this.model.changed.id !== undefined) {
				return;
			}

			this.$el.html(this.template(this.model.toJSON()));
			this.$el.toggleClass('completed', this.model.get('completed'));
			this.toggleVisible();
			this.$input = this.$('.edit');
			return this;
		},

		toggleVisible: function () {
			this.$el.toggleClass('hidden', this.isHidden());
		},

		isHidden: function () {
			var isCompleted = this.model.get('completed');
			return (// hidden cases only
				(!isCompleted && app.TodoFilter === 'completed') ||
				(isCompleted && app.TodoFilter === 'active')
			);
		},

		// Toggle the `"completed"` state of the model.
		toggleCompleted: function () {
			this.model.toggle();
		},

		// Switch this view into `"editing"` mode, displaying the input field.
		edit: function () {
			this.$el.addClass('editing');
			this.$input.focus();
		},

		// Close the `"editing"` mode, saving changes to the todo.
		close: function () {
			var value = this.$input.val();
			var trimmedValue = value.trim();

			// We don't want to handle blur events from an item that is no
			// longer being edited. Relying on the CSS class here has the
			// benefit of us not having to maintain state in the DOM and the
			// JavaScript logic.
			if (!this.$el.hasClass('editing')) {
				return;
			}

			if (trimmedValue) {
				this.model.save({ title: trimmedValue });

				if (value !== trimmedValue) {
					// Model values changes consisting of whitespaces only are
					// not causing change to be triggered Therefore we've to
					// compare untrimmed version with a trimmed one to check
					// whether anything changed
					// And if yes, we've to trigger change event ourselves
					this.model.trigger('change');
				}
			} else {
				this.clear();
			}

			this.$el.removeClass('editing');
		},

		// If you hit `enter`, we're through editing the item.
		updateOnEnter: function (e) {
			if (e.which === ENTER_KEY) {
				this.close();
			}
		},

		// If you're pressing `escape` we revert your change by simply leaving
		// the `editing` state.
		revertOnEscape: function (e) {
			if (e.which === ESC_KEY) {
				this.$el.removeClass('editing');
			}
		},

		// Remove the item, destroy the model from *localStorage* and delete its view.
		clear: function () {
			this.model.destroy();
		}
	});
})(jQuery);
<commit_msg>Backbone: Reset input on revert<commit_after>/*global Backbone, jQuery, _, ENTER_KEY, ESC_KEY */
var app = app || {};

(function ($) {
	'use strict';

	// Todo Item View
	// --------------

	// The DOM element for a todo item...
	app.TodoView = Backbone.View.extend({
		//... is a list tag.
		tagName:  'li',

		// Cache the template function for a single item.
		template: _.template($('#item-template').html()),

		// The DOM events specific to an item.
		events: {
			'click .toggle': 'toggleCompleted',
			'dblclick label': 'edit',
			'click .destroy': 'clear',
			'keypress .edit': 'updateOnEnter',
			'keydown .edit': 'revertOnEscape',
			'blur .edit': 'close'
		},

		// The TodoView listens for changes to its model, re-rendering. Since
		// there's a one-to-one correspondence between a **Todo** and a
		// **TodoView** in this app, we set a direct reference on the model for
		// convenience.
		initialize: function () {
			this.listenTo(this.model, 'change', this.render);
			this.listenTo(this.model, 'destroy', this.remove);
			this.listenTo(this.model, 'visible', this.toggleVisible);
		},

		// Re-render the titles of the todo item.
		render: function () {
			// Backbone LocalStorage is adding `id` attribute instantly after
			// creating a model.  This causes our TodoView to render twice. Once
			// after creating a model and once on `id` change.  We want to
			// filter out the second redundant render, which is caused by this
			// `id` change.  It's known Backbone LocalStorage bug, therefore
			// we've to create a workaround.
			// https://github.com/tastejs/todomvc/issues/469
			if (this.model.changed.id !== undefined) {
				return;
			}

			this.$el.html(this.template(this.model.toJSON()));
			this.$el.toggleClass('completed', this.model.get('completed'));
			this.toggleVisible();
			this.$input = this.$('.edit');
			return this;
		},

		toggleVisible: function () {
			this.$el.toggleClass('hidden', this.isHidden());
		},

		isHidden: function () {
			var isCompleted = this.model.get('completed');
			return (// hidden cases only
				(!isCompleted && app.TodoFilter === 'completed') ||
				(isCompleted && app.TodoFilter === 'active')
			);
		},

		// Toggle the `"completed"` state of the model.
		toggleCompleted: function () {
			this.model.toggle();
		},

		// Switch this view into `"editing"` mode, displaying the input field.
		edit: function () {
			this.$el.addClass('editing');
			this.$input.focus();
		},

		// Close the `"editing"` mode, saving changes to the todo.
		close: function () {
			var value = this.$input.val();
			var trimmedValue = value.trim();

			// We don't want to handle blur events from an item that is no
			// longer being edited. Relying on the CSS class here has the
			// benefit of us not having to maintain state in the DOM and the
			// JavaScript logic.
			if (!this.$el.hasClass('editing')) {
				return;
			}

			if (trimmedValue) {
				this.model.save({ title: trimmedValue });

				if (value !== trimmedValue) {
					// Model values changes consisting of whitespaces only are
					// not causing change to be triggered Therefore we've to
					// compare untrimmed version with a trimmed one to check
					// whether anything changed
					// And if yes, we've to trigger change event ourselves
					this.model.trigger('change');
				}
			} else {
				this.clear();
			}

			this.$el.removeClass('editing');
		},

		// If you hit `enter`, we're through editing the item.
		updateOnEnter: function (e) {
			if (e.which === ENTER_KEY) {
				this.close();
			}
		},

		// If you're pressing `escape` we revert your change by simply leaving
		// the `editing` state.
		revertOnEscape: function (e) {
			if (e.which === ESC_KEY) {
				this.$el.removeClass('editing');
				// Also reset the hidden input back to the original value.
				this.$input.val(this.model.get('title'));
			}
		},

		// Remove the item, destroy the model from *localStorage* and delete its view.
		clear: function () {
			this.model.destroy();
		}
	});
})(jQuery);
<|endoftext|>


<commit_before>'use strict';

var _ = require('lodash');

/**@ngInject*/
function UserOrderController($scope, orders) {
  this.orders = this.getOrderStatus(orders);
}

UserOrderController.prototype.getOrders = function() {
  return this.orders;
};

UserOrderController.prototype.getOrderStatus = function(orders) {
  // this enumeration of statuses is not consistent with the API's enumeration.
  var provision_status_map = { ok: 0, pending: 1, unknown: 2, warning: 3, critical: 4, retired: 5 };
  _.each(orders, function(order)
  {
    order.provision_status = "ok";
    var retiredCount = 0;
    _.each(order.order_items, function(order_item)
    {
      if (typeof order_item.provision_status === "undefined") {
        order_item.provision_status = "unknown";
      }
      // if an order_item's status is of higher concern than the order's current status
      if (provision_status_map[order.provision_status] < provision_status_map[order_item.provision_status]) {
        if (order_item.provision_status === "retired") {
          retiredCount++;
        }
        // unknown is considered a warning for the order
        else if (order_item.provision_status === "unknown") {
          order.provision_status = "warning";
        }
        else {
          order.provision_status = order_item.provision_status;
        }
      }
    });
    // not retired unless all order_items are retired
    if (retiredCount === order.order_items.length)
    {
      if (retiredCount > 0) {
        order.provision_status = "retired";
      }
      else {
        order.provision_status = "";
      }
    }
  });
  return orders;
};

UserOrderController.resolve = {
  /**@ngInject*/
  orders: function(UserOrders, currentUser) {
    return UserOrders.query({staff_id: currentUser.id}).$promise;
  }
};

module.exports = UserOrderController;<commit_msg>Rebuilt based upon Stack's suggestions<commit_after>'use strict';

var _ = require('lodash');

/**@ngInject*/
function UserOrderController($scope, orders) {
  this.orders = this.getOrderStatus(orders);
}

function _reduceItemStatus(status, order_item) {
  var itemStatus = null;
  var provision_status_map = { ok: 0, pending: 1, unknown: 2, warning: 3, critical: 4, retired: 5 };
  // undefined status and 'unknown' statuses are set to 'warning' for order status
  if ((typeof order_item.provision_status === "undefined") || (order_item.provision_status === "unknown")) {
    itemStatus = "warning";
  } else {
    itemStatus = order_item.provision_status;
  }
  // Compare levels of the statuses - the higher status should represent the status of the order (except retired)
  if ((provision_status_map[itemStatus] > provision_status_map[status]) && (itemStatus !== "retired")) {
    return itemStatus;
  } else {
    // Return existing status
    return status;
  }
}

UserOrderController.prototype.getOrders = function() {
  return this.orders;
};

UserOrderController.prototype.getOrderStatus = function(orders) {
  _.each(orders, function(order)
  {
    if (_.every(order.order_items, function(order_item){return order_item.provision_status === "retired";})) {
      order.provision_status = "retired";
    }
    else {
      order.provision_status = _.reduce(order.order_items, _reduceItemStatus, "ok");
    }
  });
  return orders;
};

UserOrderController.resolve = {
  /**@ngInject*/
  orders: function(UserOrders, currentUser) {
    return UserOrders.query({staff_id: currentUser.id}).$promise;
  }
};

module.exports = UserOrderController;<|endoftext|>


<commit_before>/**
 * core/modules data store: module info.
 *
 * Site Kit by Google, Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * External dependencies
 */
import invariant from 'invariant';

/**
 * WordPress dependencies
 */
import { createRegistryControl } from '@wordpress/data';

/**
 * Internal dependencies
 */
import API from 'googlesitekit-api';
import Data from 'googlesitekit-data';
import { STORE_NAME } from './constants';
import { STORE_NAME as CORE_USER_STORE_NAME } from '../../datastore/user/constants';

const { createRegistrySelector } = Data;

// Actions
const START_FETCH_SET_MODULE_ACTIVATION = 'START_FETCH_SET_MODULE_ACTIVATION';
const FETCH_SET_MODULE_ACTIVATION = 'FETCH_SET_MODULE_ACTIVATION';
const FINISH_FETCH_SET_MODULE_ACTIVATION = 'FINISH_FETCH_SET_MODULE_ACTIVATION';
const CATCH_FETCH_SET_MODULE_ACTIVATION = 'CATCH_FETCH_SET_MODULE_ACTIVATION';
const START_FETCH_MODULES = 'START_FETCH_MODULES';
const FETCH_MODULES = 'FETCH_MODULES';
const FINISH_FETCH_MODULES = 'FINISH_FETCH_MODULES';
const CATCH_FETCH_MODULES = 'CATCH_FETCH_MODULES';
const RECEIVE_MODULES = 'RECEIVE_MODULES';
const REFETCH_AUTHENICATION = 'REFETCH_AUTHENICATION';

export const INITIAL_STATE = {
	modules: undefined,
	isFetchingSetModuleActivation: {},
	isFetchingModules: false,
};

export const actions = {
	/**
	 * Activate a module on the server.
	 *
	 * Activate a module (based on the slug provided).
	 *
	 * @since 1.8.0
	 *
	 * @param  {string} slug Slug of the module to activate.
	 * @return {Object}      Object with {response, error}
	 */
	*activateModule( slug ) {
		const { response, error } = yield actions.setModuleActivation( slug, true );

		yield {
			payload: {},
			type: REFETCH_AUTHENICATION,
		};

		return { response, error };
	},

	/**
	 * Dectivate a module on the server.
	 *
	 * Dectivate a module (based on the slug provided).
	 *
	 * @since 1.8.0
	 *
	 * @param  {string} slug Slug of the module to activate.
	 * @return {Object}      Object with {response, error}
	 */
	*deactivateModule( slug ) {
		const { response, error } = yield actions.setModuleActivation( slug, false );

		yield {
			payload: {},
			type: REFETCH_AUTHENICATION,
		};

		return { response, error };
	},

	/**
	 * (De)activate a module on the server.
	 *
	 * POSTs to the `core/modules/activation` endpoint to set the `active` status
	 * supplied for the give `slug`.
	 *
	 * @since 1.8.0
	 * @private
	 *
	 * @param  {string}  slug   Slug of the module to activate/deactivate.
	 * @param  {boolean} active `true` to activate; `false` to deactivate.
	 * @return {Object}         Object with {response, error}
	 */
	*setModuleActivation( slug, active ) {
		invariant( slug, 'slug is required.' );
		invariant( active !== undefined, 'active is required.' );

		let response, error;

		const params = { active, slug };

		yield {
			payload: { params },
			type: START_FETCH_SET_MODULE_ACTIVATION,
		};

		try {
			response = yield {
				payload: { params },
				type: FETCH_SET_MODULE_ACTIVATION,
			};

			if ( response.success === true ) {
				// Fetch (or re-fetch) all modules, with their updated status.
				yield actions.fetchModules();
			}

			yield {
				payload: { params },
				type: FINISH_FETCH_SET_MODULE_ACTIVATION,
			};
		} catch ( e ) {
			error = e;
			yield {
				payload: { params, error },
				type: CATCH_FETCH_SET_MODULE_ACTIVATION,
			};
		}

		return { response, error };
	},

	/**
	 * Dispatches an action that creates an HTTP request.
	 *
	 * Requests the `core/modules/list` endpoint.
	 *
	 * @since 1.8.0
	 * @private
	 *
	 * @return {Object} Object with {response, error}
	 */
	*fetchModules() {
		let response, error;

		yield {
			payload: {},
			type: START_FETCH_MODULES,
		};

		try {
			response = yield {
				payload: {},
				type: FETCH_MODULES,
			};

			yield actions.receiveModules( response );

			yield {
				payload: {},
				type: FINISH_FETCH_MODULES,
			};
		} catch ( e ) {
			error = e;
			yield {
				payload: { error },
				type: CATCH_FETCH_MODULES,
			};
		}

		return { response, error };
	},

	/**
	 * Stores modules received from the REST API.
	 *
	 * @since 1.5.0
	 * @private
	 *
	 * @param {Array} modules Modules from the API.
	 * @return {Object} Redux-style action.
	 */
	receiveModules( modules ) {
		invariant( modules, 'modules is required.' );

		return {
			payload: { modules },
			type: RECEIVE_MODULES,
		};
	},
};

export const controls = {
	[ FETCH_SET_MODULE_ACTIVATION ]: ( { payload: { params } } ) => {
		return API.set( 'core', 'modules', 'activation', params );
	},
	[ FETCH_MODULES ]: () => {
		return API.get( 'core', 'modules', 'list', null, { useCache: false } );
	},
	[ REFETCH_AUTHENICATION ]: createRegistryControl( ( registry ) => () => {
		registry.dispatch( CORE_USER_STORE_NAME ).fetchAuthentication();
	} ),
};

export const reducer = ( state, { type, payload } ) => {
	switch ( type ) {
		case START_FETCH_SET_MODULE_ACTIVATION: {
			const { slug } = payload.params;

			return {
				...state,
				isFetchingSetModuleActivation: {
					...state.isFetchingSetModuleActivation,
					[ slug ]: true,
				},
			};
		}

		case FINISH_FETCH_SET_MODULE_ACTIVATION: {
			const { slug } = payload.params;

			return {
				...state,
				isFetchingSetModuleActivation: {
					...state.isFetchingSetModuleActivation,
					[ slug ]: false,
				},
			};
		}

		case CATCH_FETCH_SET_MODULE_ACTIVATION: {
			const { slug } = payload.params;

			return {
				...state,
				error: payload.error,
				isFetchingSetModuleActivation: {
					...state.isFetchingSetModuleActivation,
					[ slug ]: false,
				},
			};
		}

		case START_FETCH_MODULES: {
			return {
				...state,
				isFetchingModules: true,
			};
		}

		case RECEIVE_MODULES: {
			const { modules } = payload;

			return {
				...state,
				modules: modules.reduce( ( acc, module ) => {
					return { ...acc, [ module.slug ]: module };
				}, {} ),
			};
		}

		case FINISH_FETCH_MODULES: {
			return {
				...state,
				isFetchingModules: false,
			};
		}

		case CATCH_FETCH_MODULES: {
			return {
				...state,
				error: payload.error,
				isFetchingModules: false,
			};
		}

		default: {
			return { ...state };
		}
	}
};

export const resolvers = {
	*getModules() {
		const registry = yield Data.commonActions.getRegistry();

		const existingModules = registry.select( STORE_NAME ).getModules();

		if ( ! existingModules ) {
			yield actions.fetchModules();
		}
	},
};

export const selectors = {
	/**
	 * Get the list of modules registered for use with Site Kit.
	 *
	 * A module is a section of Site Kit that relates to a particular service,
	 * like Google Analytics or Google PageSpeed modules. They can provide
	 * admin-only features (like PageSpeed Insights), frontend-only features,
	 * or both (eg. Analytics, which can install Analytics <script> tags in the
	 * frontend, and show dashboards in the WordPress Admin).
	 *
	 * Returns an Object/map of objects, keyed by slug, with the following shape when successful:
	 * ```
	 * slug: {
	 *   "slug": "tagmanager",
	 *   "name": "Tag Manager",
	 *   "description": "Tag Manager creates an easy to manage way to create tags on your site without updating code.",
	 *   "homepage": "https://tagmanager.google.com/",
	 *   "internal": false,
	 *   "active": false,
	 *   "connected": false,
	 *   "dependencies": [
	 *     "analytics"
	 *   ],
	 *   "dependants": []
	 * }
	 * ```
	 *
	 * @since 1.8.0
	 *
	 * @param {Object} state Data store's state.
	 * @return {(Object|undefined)} Modules available on the site.
	 */
	getModules( state ) {
		const { modules } = state;

		return modules;
	},

	/**
	 * Get a specific module by slug.
	 *
	 * Returns a specific module by its slug.
	 * Returns `undefined` if state is still loading or if said module doesn't exist.
	 *
	 * @since 1.8.0
	 *
	 * @param {Object} state Data store's state.
	 * @param {string} slug  Module slug.
	 * @return {(Object|undefined)} A specific module object; `undefined` if state is still loading or if said module doesn't exist.
	 */
	getModule: createRegistrySelector( ( select ) => ( state, slug ) => {
		const modules = select( STORE_NAME ).getModules();

		// Return `undefined` if modules haven't been loaded yet.
		if ( modules === undefined ) {
			return undefined;
		}

		// A module with this slug couldn't be found; return `null` to signify the
		// "not found" state.
		if ( modules[ slug ] === undefined ) {
			return null;
		}

		// This module exists, so let's return it.
		return modules[ slug ];
	} ),

	/**
	 * Check a module's activation status.
	 *
	 * Returns `true` if the module exists and is active.
	 * Returns `false` if the module exists but is not active.
	 * Returns `undefined` if state is still loading or if no module with that slug exists.
	 *
	 * @since 1.8.0
	 *
	 * @param {Object} state Data store's state.
	 * @param {string} slug  Module slug.
	 * @return {(Object|undefined)} A specific module object; `undefined` if state is still loading or if said module doesn't exist.
	 */
	isModuleActive: createRegistrySelector( ( select ) => ( state, slug ) => {
		const module = select( STORE_NAME ).getModule( slug );

		// Return `undefined` if modules haven't been loaded yet.
		if ( module === undefined ) {
			return undefined;
		}

		// A module with this slug couldn't be found; return `null` to signify the
		// "not found" state.
		if ( module === null ) {
			return null;
		}

		return module.active;
	} ),

	/**
	 * Check if a module's status is changing.
	 *
	 * Returns `true` if the module exists and is changing its `active` flag.
	 * Returns `false` if the module exists but is not changing its `active` flag.
	 * Returns `undefined` if state is still loading or if no module with that slug exists.
	 *
	 * @since 1.8.0
	 *
	 * @param {Object} state Data store's state.
	 * @param {string} slug  Module slug.
	 * @return {(boolean|undefined)} Activation change status; `undefined` if state is still loading or if no module with that slug exists.
	 */
	isSettingModuleActivation: ( state, slug ) => {
		return state.isFetchingSetModuleActivation[ slug ];
	},
};

export default {
	INITIAL_STATE,
	actions,
	controls,
	reducer,
	resolvers,
	selectors,
};
<commit_msg>Move API call into REFETCH_AUTHENTICATION and add timestamp param.<commit_after>/**
 * core/modules data store: module info.
 *
 * Site Kit by Google, Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * External dependencies
 */
import invariant from 'invariant';

/**
 * Internal dependencies
 */
import API from 'googlesitekit-api';
import Data from 'googlesitekit-data';
import { STORE_NAME } from './constants';

const { createRegistrySelector } = Data;

// Actions
const START_FETCH_SET_MODULE_ACTIVATION = 'START_FETCH_SET_MODULE_ACTIVATION';
const FETCH_SET_MODULE_ACTIVATION = 'FETCH_SET_MODULE_ACTIVATION';
const FINISH_FETCH_SET_MODULE_ACTIVATION = 'FINISH_FETCH_SET_MODULE_ACTIVATION';
const CATCH_FETCH_SET_MODULE_ACTIVATION = 'CATCH_FETCH_SET_MODULE_ACTIVATION';
const START_FETCH_MODULES = 'START_FETCH_MODULES';
const FETCH_MODULES = 'FETCH_MODULES';
const FINISH_FETCH_MODULES = 'FINISH_FETCH_MODULES';
const CATCH_FETCH_MODULES = 'CATCH_FETCH_MODULES';
const RECEIVE_MODULES = 'RECEIVE_MODULES';
const REFETCH_AUTHENICATION = 'REFETCH_AUTHENICATION';

export const INITIAL_STATE = {
	modules: undefined,
	isFetchingSetModuleActivation: {},
	isFetchingModules: false,
};

export const actions = {
	/**
	 * Activate a module on the server.
	 *
	 * Activate a module (based on the slug provided).
	 *
	 * @since 1.8.0
	 *
	 * @param  {string} slug Slug of the module to activate.
	 * @return {Object}      Object with {response, error}
	 */
	*activateModule( slug ) {
		const { response, error } = yield actions.setModuleActivation( slug, true );

		yield {
			payload: {},
			type: REFETCH_AUTHENICATION,
		};

		return { response, error };
	},

	/**
	 * Dectivate a module on the server.
	 *
	 * Dectivate a module (based on the slug provided).
	 *
	 * @since 1.8.0
	 *
	 * @param  {string} slug Slug of the module to activate.
	 * @return {Object}      Object with {response, error}
	 */
	*deactivateModule( slug ) {
		const { response, error } = yield actions.setModuleActivation( slug, false );

		yield {
			payload: {},
			type: REFETCH_AUTHENICATION,
		};

		return { response, error };
	},

	/**
	 * (De)activate a module on the server.
	 *
	 * POSTs to the `core/modules/activation` endpoint to set the `active` status
	 * supplied for the give `slug`.
	 *
	 * @since 1.8.0
	 * @private
	 *
	 * @param  {string}  slug   Slug of the module to activate/deactivate.
	 * @param  {boolean} active `true` to activate; `false` to deactivate.
	 * @return {Object}         Object with {response, error}
	 */
	*setModuleActivation( slug, active ) {
		invariant( slug, 'slug is required.' );
		invariant( active !== undefined, 'active is required.' );

		let response, error;

		const params = { active, slug };

		yield {
			payload: { params },
			type: START_FETCH_SET_MODULE_ACTIVATION,
		};

		try {
			response = yield {
				payload: { params },
				type: FETCH_SET_MODULE_ACTIVATION,
			};

			if ( response.success === true ) {
				// Fetch (or re-fetch) all modules, with their updated status.
				yield actions.fetchModules();
			}

			yield {
				payload: { params },
				type: FINISH_FETCH_SET_MODULE_ACTIVATION,
			};
		} catch ( e ) {
			error = e;
			yield {
				payload: { params, error },
				type: CATCH_FETCH_SET_MODULE_ACTIVATION,
			};
		}

		return { response, error };
	},

	/**
	 * Dispatches an action that creates an HTTP request.
	 *
	 * Requests the `core/modules/list` endpoint.
	 *
	 * @since 1.8.0
	 * @private
	 *
	 * @return {Object} Object with {response, error}
	 */
	*fetchModules() {
		let response, error;

		yield {
			payload: {},
			type: START_FETCH_MODULES,
		};

		try {
			response = yield {
				payload: {},
				type: FETCH_MODULES,
			};

			yield actions.receiveModules( response );

			yield {
				payload: {},
				type: FINISH_FETCH_MODULES,
			};
		} catch ( e ) {
			error = e;
			yield {
				payload: { error },
				type: CATCH_FETCH_MODULES,
			};
		}

		return { response, error };
	},

	/**
	 * Stores modules received from the REST API.
	 *
	 * @since 1.5.0
	 * @private
	 *
	 * @param {Array} modules Modules from the API.
	 * @return {Object} Redux-style action.
	 */
	receiveModules( modules ) {
		invariant( modules, 'modules is required.' );

		return {
			payload: { modules },
			type: RECEIVE_MODULES,
		};
	},
};

export const controls = {
	[ FETCH_SET_MODULE_ACTIVATION ]: ( { payload: { params } } ) => {
		return API.set( 'core', 'modules', 'activation', params );
	},
	[ FETCH_MODULES ]: () => {
		return API.get( 'core', 'modules', 'list', null, { useCache: false } );
	},
	[ REFETCH_AUTHENICATION ]: () => {
		return API.get( 'core', 'user', 'authentication', null, { useCache: false, timestamp: Date.now() } );
	},
};

export const reducer = ( state, { type, payload } ) => {
	switch ( type ) {
		case START_FETCH_SET_MODULE_ACTIVATION: {
			const { slug } = payload.params;

			return {
				...state,
				isFetchingSetModuleActivation: {
					...state.isFetchingSetModuleActivation,
					[ slug ]: true,
				},
			};
		}

		case FINISH_FETCH_SET_MODULE_ACTIVATION: {
			const { slug } = payload.params;

			return {
				...state,
				isFetchingSetModuleActivation: {
					...state.isFetchingSetModuleActivation,
					[ slug ]: false,
				},
			};
		}

		case CATCH_FETCH_SET_MODULE_ACTIVATION: {
			const { slug } = payload.params;

			return {
				...state,
				error: payload.error,
				isFetchingSetModuleActivation: {
					...state.isFetchingSetModuleActivation,
					[ slug ]: false,
				},
			};
		}

		case START_FETCH_MODULES: {
			return {
				...state,
				isFetchingModules: true,
			};
		}

		case RECEIVE_MODULES: {
			const { modules } = payload;

			return {
				...state,
				modules: modules.reduce( ( acc, module ) => {
					return { ...acc, [ module.slug ]: module };
				}, {} ),
			};
		}

		case FINISH_FETCH_MODULES: {
			return {
				...state,
				isFetchingModules: false,
			};
		}

		case CATCH_FETCH_MODULES: {
			return {
				...state,
				error: payload.error,
				isFetchingModules: false,
			};
		}

		default: {
			return { ...state };
		}
	}
};

export const resolvers = {
	*getModules() {
		const registry = yield Data.commonActions.getRegistry();

		const existingModules = registry.select( STORE_NAME ).getModules();

		if ( ! existingModules ) {
			yield actions.fetchModules();
		}
	},
};

export const selectors = {
	/**
	 * Get the list of modules registered for use with Site Kit.
	 *
	 * A module is a section of Site Kit that relates to a particular service,
	 * like Google Analytics or Google PageSpeed modules. They can provide
	 * admin-only features (like PageSpeed Insights), frontend-only features,
	 * or both (eg. Analytics, which can install Analytics <script> tags in the
	 * frontend, and show dashboards in the WordPress Admin).
	 *
	 * Returns an Object/map of objects, keyed by slug, with the following shape when successful:
	 * ```
	 * slug: {
	 *   "slug": "tagmanager",
	 *   "name": "Tag Manager",
	 *   "description": "Tag Manager creates an easy to manage way to create tags on your site without updating code.",
	 *   "homepage": "https://tagmanager.google.com/",
	 *   "internal": false,
	 *   "active": false,
	 *   "connected": false,
	 *   "dependencies": [
	 *     "analytics"
	 *   ],
	 *   "dependants": []
	 * }
	 * ```
	 *
	 * @since 1.8.0
	 *
	 * @param {Object} state Data store's state.
	 * @return {(Object|undefined)} Modules available on the site.
	 */
	getModules( state ) {
		const { modules } = state;

		return modules;
	},

	/**
	 * Get a specific module by slug.
	 *
	 * Returns a specific module by its slug.
	 * Returns `undefined` if state is still loading or if said module doesn't exist.
	 *
	 * @since 1.8.0
	 *
	 * @param {Object} state Data store's state.
	 * @param {string} slug  Module slug.
	 * @return {(Object|undefined)} A specific module object; `undefined` if state is still loading or if said module doesn't exist.
	 */
	getModule: createRegistrySelector( ( select ) => ( state, slug ) => {
		const modules = select( STORE_NAME ).getModules();

		// Return `undefined` if modules haven't been loaded yet.
		if ( modules === undefined ) {
			return undefined;
		}

		// A module with this slug couldn't be found; return `null` to signify the
		// "not found" state.
		if ( modules[ slug ] === undefined ) {
			return null;
		}

		// This module exists, so let's return it.
		return modules[ slug ];
	} ),

	/**
	 * Check a module's activation status.
	 *
	 * Returns `true` if the module exists and is active.
	 * Returns `false` if the module exists but is not active.
	 * Returns `undefined` if state is still loading or if no module with that slug exists.
	 *
	 * @since 1.8.0
	 *
	 * @param {Object} state Data store's state.
	 * @param {string} slug  Module slug.
	 * @return {(Object|undefined)} A specific module object; `undefined` if state is still loading or if said module doesn't exist.
	 */
	isModuleActive: createRegistrySelector( ( select ) => ( state, slug ) => {
		const module = select( STORE_NAME ).getModule( slug );

		// Return `undefined` if modules haven't been loaded yet.
		if ( module === undefined ) {
			return undefined;
		}

		// A module with this slug couldn't be found; return `null` to signify the
		// "not found" state.
		if ( module === null ) {
			return null;
		}

		return module.active;
	} ),

	/**
	 * Check if a module's status is changing.
	 *
	 * Returns `true` if the module exists and is changing its `active` flag.
	 * Returns `false` if the module exists but is not changing its `active` flag.
	 * Returns `undefined` if state is still loading or if no module with that slug exists.
	 *
	 * @since 1.8.0
	 *
	 * @param {Object} state Data store's state.
	 * @param {string} slug  Module slug.
	 * @return {(boolean|undefined)} Activation change status; `undefined` if state is still loading or if no module with that slug exists.
	 */
	isSettingModuleActivation: ( state, slug ) => {
		return state.isFetchingSetModuleActivation[ slug ];
	},
};

export default {
	INITIAL_STATE,
	actions,
	controls,
	reducer,
	resolvers,
	selectors,
};
<|endoftext|>


<commit_before>/**
 * Widget component.
 *
 * Site Kit by Google, Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * External dependencies
 */
import classnames from 'classnames';
import { node, func, string, bool } from 'prop-types';

const Widget = ( {
	children,
	className,
	slug,
	noPadding,
	header: Header,
	footer: Footer,
} ) => {
	return (
		<div
			className={ classnames(
				'googlesitekit-widget',
				`googlesitekit-widget--${ slug }`,
				{ 'googlesitekit-widget--no-padding': noPadding },
				className
			) }
		>
			{ Header && (

			) }

				{ children }

			{ Footer && (

			) }

	);
};

Widget.defaultProps = {
	children: undefined,
	noPadding: false,
};

Widget.propTypes = {
	children: node,
	slug: string.isRequired,
	noPadding: bool,
	header: func,
	footer: func,
};

export default Widget;
<commit_msg>Fix expected prop type for Widget header and footer.<commit_after>/**
 * Widget component.
 *
 * Site Kit by Google, Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * External dependencies
 */
import classnames from 'classnames';
import { node, elementType, string, bool } from 'prop-types';

const Widget = ( {
	children,
	className,
	slug,
	noPadding,
	header: Header,
	footer: Footer,
} ) => {
	return (
		<div
			className={ classnames(
				'googlesitekit-widget',
				`googlesitekit-widget--${ slug }`,
				{ 'googlesitekit-widget--no-padding': noPadding },
				className
			) }
		>
			{ Header && (

			) }

				{ children }

			{ Footer && (

			) }

	);
};

Widget.defaultProps = {
	children: undefined,
	noPadding: false,
};

Widget.propTypes = {
	children: node,
	slug: string.isRequired,
	noPadding: bool,
	header: elementType,
	footer: elementType,
};

export default Widget;
<|endoftext|>


<commit_before>'use strict'
const slapp = require('../slackSetup.js').slapp
const getRadius = require('../radius.js').getRadius
//db imports
const firebase    = require('../firebaseSetup.js'),
      db = firebase.db,
      snaps = firebase.snaps,
      tags = firebase.tags,
      users = firebase.users

let test = function() {
  let randomNum = 0;

  slapp.command('/test', (msg, text) => {
    randomNum = (Math.floor(Math.random() * 1400) + 200)

    msg
      .say({
        text: '',
        attachments: [{
          text: 'Where do you want to Jaywalk to?',
          fallback: 'Where to today?',
          callback_id: 'doit_confirm_callback',
          actions: [{
              name: 'answer',
              text: 'Suprise Me!',
              type: 'button',
              value: randomNum
            }
            // { name: 'answer', text: 'Random Tag', type: 'button', value: Math.floor(Math.random() * 44) }
          ]
        }]
      })

  })
  .route('getid', (msg, state) => {
    console.log(randomNum)
    var randSnap = msg.body.actions[0].value || ''
    var randTag = msg.body.actions[0].value || ''

    // user may not have typed text as their next action, ask again and re-route
    if (!randSnap || !randTag) {
      return msg
        .say("Whoops, you just have to pick a button...")
        .say('Click a button!')
        .route('getid1', state)
    }
    let body
    let testSnapLocation = getRadius(39.752764, -104.877743) //test: snap #1055
    let snapLat = snaps
      .orderByChild('lat')
      .startAt(testSnapLocation[5].lat + "-") // "-"makes a string for query
      .endAt(testSnapLocation[1].lat + "-")
      .once('value')
      .then(function(snap) {
        snap.forEach(function(data) {
          if (data.val().lng <= testSnapLocation[0].lng && data.val().lng >= testSnapLocation[3].lng) {
            console.log(data.val().title)
            let body = data.val()
            msg.say(`I found a deal for you: ${body.title}\n${body.description}\n${body.picture}\n${body.address}\n`)
          }
        })
      })
    })
}
module.exports = {
  test:test()
}

<commit_msg>turns out that was a useful route...<commit_after>'use strict'
const slapp = require('../slackSetup.js').slapp
const getRadius = require('../radius.js').getRadius
//db imports
const firebase    = require('../firebaseSetup.js'),
      db = firebase.db,
      snaps = firebase.snaps,
      tags = firebase.tags,
      users = firebase.users

let test = function() {
  let randomNum = 0;

  slapp.command('/test', (msg, text) => {
    randomNum = (Math.floor(Math.random() * 1400) + 200)

    msg
      .say({
        text: '',
        attachments: [{
          text: 'Where do you want to Jaywalk to?',
          fallback: 'Where to today?',
          callback_id: 'doit_confirm_callback',
          actions: [{
              name: 'answer',
              text: 'Suprise Me!',
              type: 'button',
              value: randomNum
            }
            // { name: 'answer', text: 'Random Tag', type: 'button', value: Math.floor(Math.random() * 44) }
          ]
        }]
      })
      .route('getid', {
        id: text
      })
  })
  .route('requestToDatabase', (msg, state) => {
    console.log(randomNum)
    var randSnap = msg.body.actions[0].value || ''
    var randTag = msg.body.actions[0].value || ''

    // user may not have typed text as their next action, ask again and re-route
    if (!randSnap || !randTag) {
      return msg
        .say("Whoops, you just have to pick a button...")
        .say('Click a button!')
        .route('requestToDatabase', state)
    }
    let body
    let testSnapLocation = getRadius(39.752764, -104.877743) //test: snap #1055
    let snapLat = snaps
      .orderByChild('lat')
      .startAt(testSnapLocation[5].lat + "-") // "-"makes a string for query
      .endAt(testSnapLocation[1].lat + "-")
      .once('value')
      .then(function(snap) {
        snap.forEach(function(data) {
          if (data.val().lng <= testSnapLocation[0].lng && data.val().lng >= testSnapLocation[3].lng) {
            console.log(data.val().title)
            let body = data.val()
            msg.say(`I found a deal for you: ${body.title}\n${body.description}\n${body.picture}\n${body.address}\n`)
          }
        })
      })
    })
}
module.exports = {
  test:test()
}

<|endoftext|>


<commit_before>/**
 * Created by kintesh on 17/02/15.
 */

var Slides = (function($) {

    var TYPES = {
        SLIDE: 1,
        ELEM: 2
    };

    var CSS_SLIDES = "./slides_assets/css/slides.css",
        CSS_FONTAWESOME = "./slides_assets/css/font-awesome.css",
        JS_MATHJAX = "./slides_assets/js/MathJax/MathJax.js?config=TeX-AMS-MML_HTMLorMML";

    var list = [], curr = -1, slides, currSlide, sBar,
        rawSlides, currRawSlide = -1, slidesConsoleWindow, consoleCurrView, consoleNextView,
        startTime, currSlideStartTime, helpMenu;

    function init() {
        setupProgressbar();
        setupControls();
        setupHelp();
        setupSlides();
        //console.log("list length: " + list.length);
        startTime = Date.now();
        nextItem();
    }

    function setupSlides() {
        rawSlides = $(".slide").clone();
        slides = $(".slide").addClass("slide_hidden");
        slides.each(function(e) {
            list.push({
                type: TYPES.SLIDE,
                slide: slides[e]
            });
            var cList = $(slides[e]).find(".controlElem");
            cList.each(function(ce) {
                var nextElem = $(cList[ce]).next(),
                    nextElemChildren = nextElem.find("li"),
                    props = JSON.parse(cList[ce].innerHTML);
                if (props.hasOwnProperty("visibility")) {
                    props.visibility = "";
                    processCElemReveal(nextElem, nextElemChildren, props);
                } else {
                    processCElem(nextElem, nextElemChildren, props);
                }
            });
        });
    }

    function processCElemReveal(nextElem, nextElemChildren, props) {
        if (nextElemChildren.length != 0) {
            nextElemChildren.each(function(ch) {
                list.push({
                    type: TYPES.ELEM,
                    elem: $(nextElemChildren[ch]).addClass("controlled_elem hide_elem"),
                    props: props
                });
            });
        } else {
            list.push({
                type: TYPES.ELEM,
                elem: nextElem.addClass("controlled_elem hide_elem"),
                props: props
            });
        }
    }

    function processCElem(nextElem, nextElemChildren, props) {
        if (nextElemChildren.length != 0) {
            nextElemChildren.each(function(ch) {
                list.push({
                    type: TYPES.ELEM,
                    elem: $(nextElemChildren[ch]).addClass("controlled_elem"),
                    props: props
                });
            });
        } else {
            list.push({
                type: TYPES.ELEM,
                elem: nextElem.addClass("controlled_elem"),
                props: props
            });
        }
    }

    function nextItem() {
        if(curr+1 < list.length) {
            var temp = list[curr+1];
            if(temp.type === TYPES.SLIDE) {
                showSlide(curr+1);
            } else if(temp.type === TYPES.ELEM) {
                revealElem(temp);
            }
            curr++;
        }
    }

    function previousItem() {
        if(curr-1 > -1) {
            var temp = list[curr-1];
            if(temp.type === TYPES.SLIDE) {
                if(list[curr].type !== TYPES.ELEM) {
                    showSlide(curr-1);
                } else {
                    hideElem(list[curr])
                }
            } else if(temp.type === TYPES.ELEM) {
                var parentSlide = getElemSlide(curr-1);
                if(parentSlide != currSlide) {
                    showSlide(parentSlide);
                } else {
                    hideElem(list[curr])
                }
            }
            curr--;
        }
    }

    function showSlide(index) {
        var prev = getPreviousSlide(index-1),
            next = getNextSlide(index+1);
        //console.log("Curr: "+ curr +"SLIDE:" + index + "  Previous:" + prev + "  Next:" + next);
        slides.removeClass("slide_previous slide_next")
            .addClass("slide_hidden");
        if(prev != undefined) {
            $(list[prev].slide).removeClass("slide_hidden slide_previous slide_current slide_next")
                .addClass("slide_previous");
        }
        if(next != undefined) {
            $(list[next].slide).removeClass("slide_hidden slide_previous slide_current slide_next")
                .addClass("slide_next");
        }
        $(list[index].slide).removeClass("slide_hidden slide_previous slide_current slide_next")
            .addClass("slide_current");
        $("body").css("background-color", list[index].slide.style.backgroundColor);
        updateCurrRawSlide(index);
        currSlide = index;
        currSlideStartTime = Date.now();
    }

    function revealElem(cElem) {
        if(cElem.props.hasOwnProperty("visibility")) {
            $(cElem.elem).removeClass("hide_elem")
                .addClass("reveal_elem")
                .css(cElem.props);
        } else {
            $(cElem.elem).css(cElem.props);
        }
    }

    function hideElem(cElem) {
        if(cElem.props.hasOwnProperty("visibility")) {
            $(cElem.elem).removeClass("reveal_elem")
                .addClass("hide_elem")
                .css(cElem.props);
        } else {
            var nProps = {};
            $.each(cElem.props, function(prop) {
                nProps[prop] = "";
            });
            $(cElem.elem).css(nProps);
        }
    }

    function getElemSlide(index) {
        for (;index>=0;index--) {
            if(list[index].type == TYPES.SLIDE) {
                return index;
            }
        }
    }

    function getPreviousSlide(index) {
        for (;index>=0;index--) {
            if(list[index].type == TYPES.SLIDE) {
                return index;
            }
        }
    }

    function getNextSlide(index) {
        for (;index<list.length;++index) {
            if(list[index].type == TYPES.SLIDE) {
                return index;
            }
        }
    }

    function setupProgressbar() {
        $("

").appendTo("body");
        sBar = $("#sBar");
    }

    function updateProgressbar() {
        sBar.width(((curr)/(list.length-1))*100 + "vw");
    }

    function setupControls() {
        $("
\n" +
        "
Previous
" +
        "
Next
" +
        "
Full Screen
" +
        "
Console
" +
        "
Help
" +
        "
").appendTo("body").animate({opacity:"0"}, 2000);

        $("#cBtn_Previous" ).click(function() {
            previous();
        });

        $("#cBtn_Next" ).click(function() {
            next();
        });

        $("#cBtn_Screen" ).click(function() {
            toggleFullScreen();
        });

        $("#cBtn_Console" ).click(function() {
            openConsole();
        });

        $("#cBtn_Help" ).click(function() {
            toggleHelp();
        });
    }

    function setupHelp() {
        helpMenu = $("
" +
        "Use keybord to navigate.
" +
        "
").appendTo("body").delay(2000).fadeOut("slow");

        $("#hBtn_close").click(function() {
            toggleHelp();
        });
    }

    function toggleHelp() {
        helpMenu.fadeToggle("slow");
    }

    function next() {
        nextItem();
        updateProgressbar();
    }

    function previous() {
        previousItem();
        updateProgressbar();
    }

    /**
     * Slides Console
     */
    function updateCurrRawSlide(index) {
        if(currSlide == undefined)
            currRawSlide++;
        else {
            if (index > currSlide)
                currRawSlide++;
            else
                currRawSlide--;
        }
        updateConsole();
    }

    function openConsole() {
        var consoleWindowHTML = "" +
            "<!DOCTYPE html><title>Slides Console</title><meta charset=\"UTF-8\">" +
            "<link rel=\"stylesheet\" href="+CSS_SLIDES+">" +
            "<link rel=\"stylesheet\" href="+CSS_FONTAWESOME+">" +
            "" +
            "
 Loading...
"+
            "
"+
            "
"+
            "
Previous
" +
            "
"+
            "
"+
            "
Next
" +
            "
"+
            "
"+
            "
" +
            "Current Slide"+
            "Next Slide"+
            "
"+
            "
" +
            "
Wednesday, 18 February 2015
" +
            "
" +
            "
--:--:--
Slide
"+
            "
--:--:--
Total
" +
            "
"+
            "
"+
            "";

        slidesConsoleWindow = window.open("","Slides Console","width=880,height=500");
        slidesConsoleWindow.document.open();
        slidesConsoleWindow.document.write(consoleWindowHTML);
        slidesConsoleWindow.document.close();

        var slideT, totalT;

        $(slidesConsoleWindow.document).ready(function () {
            $("#btn_prev", slidesConsoleWindow.document).click(function() {
                previous();
            });

            $("#btn_next", slidesConsoleWindow.document).click(function() {
                next();
            });

            setInterval(function() {
                $("#today", slidesConsoleWindow.document).html(new Date().toGMTString().slice(0, -4));
                slideT = new Date(Date.now() - currSlideStartTime);
                totalT = new Date(Date.now() - startTime);
                $("#dur_slide", slidesConsoleWindow.document).html(
                    (slideT.getUTCHours()<10 ? "0"+slideT.getUTCHours() : slideT.getUTCHours()) + ":" +
                    (slideT.getUTCMinutes()<10 ? "0"+slideT.getUTCMinutes() : slideT.getUTCMinutes()) + ":" +
                    (slideT.getUTCSeconds()<10 ? "0"+slideT.getUTCSeconds() : slideT.getUTCSeconds()));
                $("#dur_total", slidesConsoleWindow.document).html(
                    (totalT.getUTCHours()<10 ? "0"+totalT.getUTCHours() : totalT.getUTCHours()) + ":" +
                    (totalT.getUTCMinutes()<10 ? "0"+totalT.getUTCMinutes() : totalT.getUTCMinutes()) + ":" +
                    (totalT.getUTCSeconds()<10 ? "0"+totalT.getUTCSeconds() : totalT.getUTCSeconds()));
            }, 1000);

            consoleCurrView = $("#view_curr", slidesConsoleWindow.document);
            consoleNextView = $("#view_next", slidesConsoleWindow.document);
            updateConsole();
            setTimeout(function refresh() {
                $("#block", slidesConsoleWindow.document).fadeOut("slow");
            }, 1000);
        });
    }

    function updateConsole() {
        if(consoleCurrView != undefined && consoleNextView != undefined) {
            if (currRawSlide != undefined && currRawSlide < rawSlides.length) {
                consoleCurrView.prop("srcdoc", getIFrameSrcdoc(rawSlides[currRawSlide]))
            }
            if (currRawSlide != undefined && currRawSlide + 1 < rawSlides.length) {
                consoleNextView.prop("srcdoc", getIFrameSrcdoc(rawSlides[currRawSlide + 1]))
            }
        }
    }

    function getIFrameSrcdoc(slide) {
        return "<!DOCTYPE html><meta charset=\"UTF-8\">" +
            "<link rel=\"stylesheet\" href=" + CSS_SLIDES + ">" +
            "" +
            ""+slide.outerHTML+"";
    }

    /**
     * Events
     */
    $( document ).keypress(function( event ) {
        //console.log("keyCode: " + event.keyCode + " | which:" + event.which + " | key:" + event.key);
        // Left:37  Up:38  Right:39  Down:40  13:Return
        if(event.keyCode == 39 || event.keyCode == 40) {
            next();
        } else if (event.keyCode == 37 || event.keyCode == 38) {
            previous();
        } else if (event.keyCode == 13) {
            toggleFullScreen();
        } else if(event.which == 67 || event.which == 99) {
            openConsole();
        } else if(event.which == 72 || event.which == 104) {
            toggleHelp();
        }
    });

    /**
     * From https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Using_full_screen_mode
     */
    function toggleFullScreen() {
        if (!document.fullscreenElement &&          // alternative standard method
            !document.mozFullScreenElement &&       //--\
            !document.webkitFullscreenElement &&    //   | current working methods
            !document.msFullscreenElement ) {       //--/
            if (document.documentElement.requestFullscreen) {
                document.documentElement.requestFullscreen();
            } else if (document.documentElement.msRequestFullscreen) {
                document.documentElement.msRequestFullscreen();
            } else if (document.documentElement.mozRequestFullScreen) {
                document.documentElement.mozRequestFullScreen();
            } else if (document.documentElement.webkitRequestFullscreen) {
                document.documentElement.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT);
            }
            $("#cBtn_Screen").html("Restore");
        } else {
            if (document.exitFullscreen) {
                document.exitFullscreen();
            } else if (document.msExitFullscreen) {
                document.msExitFullscreen();
            } else if (document.mozCancelFullScreen) {
                document.mozCancelFullScreen();
            } else if (document.webkitExitFullscreen) {
                document.webkitExitFullscreen();
            }
            $("#cBtn_Screen").html("Full Screen");
        }
    }

    return {
        init: init,
        next: next,
        previous: previous
    }

})(jQuery);

$( document ).ready(function() {
    Slides.init();
});

<commit_msg>updated.<commit_after>/**
 * Created by kintesh on 17/02/15.
 */

var Slides = (function($) {

    var TYPES = {
        SLIDE: 1,
        ELEM: 2
    };

    var CSS_SLIDES = "./slides_assets/css/slides.css",
        CSS_FONTAWESOME = "./slides_assets/css/font-awesome.css",
        JS_MATHJAX = "./slides_assets/js/MathJax/MathJax.js?config=TeX-AMS-MML_HTMLorMML";

    var list = [], curr = -1, slides, currSlide, sBar,
        rawSlides, currRawSlide = -1, slidesConsoleWindow, consoleCurrView, consoleNextView,
        startTime, currSlideStartTime, helpMenu;

    function init() {
        setupProgressbar();
        setupControls();
        setupHelp();
        setupSlides();
        //console.log("list length: " + list.length);
        startTime = Date.now();
        nextItem();
    }

    function setupSlides() {
        rawSlides = $(".slide").clone();
        slides = $(".slide").addClass("slide_hidden");
        slides.each(function(e) {
            list.push({
                type: TYPES.SLIDE,
                slide: slides[e]
            });
            var cList = $(slides[e]).find(".controlElem");
            cList.each(function(ce) {
                var nextElem = $(cList[ce]).next(),
                    nextElemChildren = nextElem.find("li"),
                    props = JSON.parse(cList[ce].innerHTML);
                if (props.hasOwnProperty("visibility")) {
                    props.visibility = "";
                    processCElemReveal(nextElem, nextElemChildren, props);
                } else {
                    processCElem(nextElem, nextElemChildren, props);
                }
            });
        });
    }

    function processCElemReveal(nextElem, nextElemChildren, props) {
        if (nextElemChildren.length != 0) {
            nextElemChildren.each(function(ch) {
                list.push({
                    type: TYPES.ELEM,
                    elem: $(nextElemChildren[ch]).addClass("controlled_elem hide_elem"),
                    props: props
                });
            });
        } else {
            list.push({
                type: TYPES.ELEM,
                elem: nextElem.addClass("controlled_elem hide_elem"),
                props: props
            });
        }
    }

    function processCElem(nextElem, nextElemChildren, props) {
        if (nextElemChildren.length != 0) {
            nextElemChildren.each(function(ch) {
                list.push({
                    type: TYPES.ELEM,
                    elem: $(nextElemChildren[ch]).addClass("controlled_elem"),
                    props: props
                });
            });
        } else {
            list.push({
                type: TYPES.ELEM,
                elem: nextElem.addClass("controlled_elem"),
                props: props
            });
        }
    }

    function nextItem() {
        if(curr+1 < list.length) {
            var temp = list[curr+1];
            if(temp.type === TYPES.SLIDE) {
                showSlide(curr+1);
            } else if(temp.type === TYPES.ELEM) {
                revealElem(temp);
            }
            curr++;
        }
    }

    function previousItem() {
        if(curr-1 > -1) {
            var temp = list[curr-1];
            if(temp.type === TYPES.SLIDE) {
                if(list[curr].type !== TYPES.ELEM) {
                    showSlide(curr-1);
                } else {
                    hideElem(list[curr])
                }
            } else if(temp.type === TYPES.ELEM) {
                var parentSlide = getElemSlide(curr-1);
                if(parentSlide != currSlide) {
                    showSlide(parentSlide);
                } else {
                    hideElem(list[curr])
                }
            }
            curr--;
        }
    }

    function showSlide(index) {
        var prev = getPreviousSlide(index-1),
            next = getNextSlide(index+1);
        //console.log("Curr: "+ curr +"SLIDE:" + index + "  Previous:" + prev + "  Next:" + next);
        slides.removeClass("slide_previous slide_next")
            .addClass("slide_hidden");
        if(prev != undefined) {
            $(list[prev].slide).removeClass("slide_hidden slide_previous slide_current slide_next")
                .addClass("slide_previous");
        }
        if(next != undefined) {
            $(list[next].slide).removeClass("slide_hidden slide_previous slide_current slide_next")
                .addClass("slide_next");
        }
        $(list[index].slide).removeClass("slide_hidden slide_previous slide_current slide_next")
            .addClass("slide_current");
        $("body").css("background-color", list[index].slide.style.backgroundColor);
        updateCurrRawSlide(index);
        currSlide = index;
        currSlideStartTime = Date.now();
    }

    function revealElem(cElem) {
        if(cElem.props.hasOwnProperty("visibility")) {
            $(cElem.elem).removeClass("hide_elem")
                .addClass("reveal_elem")
                .css(cElem.props);
        } else {
            $(cElem.elem).css(cElem.props);
        }
    }

    function hideElem(cElem) {
        if(cElem.props.hasOwnProperty("visibility")) {
            $(cElem.elem).removeClass("reveal_elem")
                .addClass("hide_elem")
                .css(cElem.props);
        } else {
            var nProps = {};
            $.each(cElem.props, function(prop) {
                nProps[prop] = "";
            });
            $(cElem.elem).css(nProps);
        }
    }

    function getElemSlide(index) {
        for (;index>=0;index--) {
            if(list[index].type == TYPES.SLIDE) {
                return index;
            }
        }
    }

    function getPreviousSlide(index) {
        for (;index>=0;index--) {
            if(list[index].type == TYPES.SLIDE) {
                return index;
            }
        }
    }

    function getNextSlide(index) {
        for (;index<list.length;++index) {
            if(list[index].type == TYPES.SLIDE) {
                return index;
            }
        }
    }

    function setupProgressbar() {
        $("

").appendTo("body");
        sBar = $("#sBar");
    }

    function updateProgressbar() {
        sBar.width(((curr)/(list.length-1))*100 + "vw");
    }

    function setupControls() {
        $("
\n" +
        "
Previous
" +
        "
Next
" +
        "
Full Screen
" +
        "
Console
" +
        "
Help
" +
        "
").appendTo("body").animate({opacity:"0"}, 2000);

        $("#cBtn_Previous" ).click(function() {
            previous();
        });

        $("#cBtn_Next" ).click(function() {
            next();
        });

        $("#cBtn_Screen" ).click(function() {
            toggleFullScreen();
        });

        $("#cBtn_Console" ).click(function() {
            openConsole();
        });

        $("#cBtn_Help" ).click(function() {
            toggleHelp();
        });
    }

    function setupHelp() {
        helpMenu = $("
" +
        "Use keybord to navigate.
" +
        "
").appendTo("body").delay(2000).fadeOut("slow");

        $("#hBtn_close").click(function() {
            toggleHelp();
        });
    }

    function toggleHelp() {
        helpMenu.fadeToggle("slow");
    }

    function next() {
        nextItem();
        updateProgressbar();
    }

    function previous() {
        previousItem();
        updateProgressbar();
    }

    /**
     * Slides Console
     */
    function updateCurrRawSlide(index) {
        if(currSlide == undefined)
            currRawSlide++;
        else {
            if (index > currSlide)
                currRawSlide++;
            else
                currRawSlide--;
        }
        updateConsole();
    }

    function openConsole() {
        var consoleWindowHTML = "" +
            "<!DOCTYPE html><title>Slides Console</title><meta charset=\"UTF-8\">" +
            "<link rel=\"stylesheet\" href="+CSS_SLIDES+">" +
            "<link rel=\"stylesheet\" href="+CSS_FONTAWESOME+">" +
            "" +
            "
 Loading...
"+
            "
"+
            "
"+
            "
Previous
" +
            "
"+
            "
"+
            "
Next
" +
            "
"+
            "
"+
            "
" +
            "Current Slide"+
            "Next Slide"+
            "
"+
            "
" +
            "
Wednesday, 18 February 2015
" +
            "
" +
            "
--:--:--
Slide
"+
            "
--:--:--
Total
" +
            "
"+
            "
"+
            "";

        slidesConsoleWindow = window.open("","Slides Console","width=880,height=500");
        slidesConsoleWindow.document.open();
        slidesConsoleWindow.document.write(consoleWindowHTML);
        slidesConsoleWindow.document.close();

        var slideT, totalT;

        $(slidesConsoleWindow.document).ready(function () {
            $("#btn_prev", slidesConsoleWindow.document).click(function() {
                previous();
            });

            $("#btn_next", slidesConsoleWindow.document).click(function() {
                next();
            });

            setInterval(function() {
                $("#today", slidesConsoleWindow.document).html(new Date().toGMTString().slice(0, -4));
                slideT = new Date(Date.now() - currSlideStartTime);
                totalT = new Date(Date.now() - startTime);
                $("#dur_slide", slidesConsoleWindow.document).html(
                    (slideT.getUTCHours()<10 ? "0"+slideT.getUTCHours() : slideT.getUTCHours()) + ":" +
                    (slideT.getUTCMinutes()<10 ? "0"+slideT.getUTCMinutes() : slideT.getUTCMinutes()) + ":" +
                    (slideT.getUTCSeconds()<10 ? "0"+slideT.getUTCSeconds() : slideT.getUTCSeconds()));
                $("#dur_total", slidesConsoleWindow.document).html(
                    (totalT.getUTCHours()<10 ? "0"+totalT.getUTCHours() : totalT.getUTCHours()) + ":" +
                    (totalT.getUTCMinutes()<10 ? "0"+totalT.getUTCMinutes() : totalT.getUTCMinutes()) + ":" +
                    (totalT.getUTCSeconds()<10 ? "0"+totalT.getUTCSeconds() : totalT.getUTCSeconds()));
            }, 1000);

            consoleCurrView = $("#view_curr", slidesConsoleWindow.document);
            consoleNextView = $("#view_next", slidesConsoleWindow.document);
            updateConsole();
            setTimeout(function refresh() {
                $("#block", slidesConsoleWindow.document).fadeOut("slow");
            }, 1000);
        });
    }

    function updateConsole() {
        if(consoleCurrView != undefined && consoleNextView != undefined) {
            if (currRawSlide != undefined && currRawSlide < rawSlides.length) {
                consoleCurrView.prop("srcdoc", getIFrameSrcdoc(rawSlides[currRawSlide]))
            }
            if (currRawSlide != undefined && currRawSlide + 1 < rawSlides.length) {
                consoleNextView.prop("srcdoc", getIFrameSrcdoc(rawSlides[currRawSlide + 1]))
            }
        }
    }

    function getIFrameSrcdoc(slide) {
        return "<!DOCTYPE html><meta charset=\"UTF-8\">" +
            "<link rel=\"stylesheet\" href=" + CSS_SLIDES + ">" +
            "" +
            ""+slide.outerHTML+"";
    }

    /**
     * Events
     */
    $( document ).keypress(function( event ) {
        //console.log("keyCode: " + event.keyCode + " | which:" + event.which + " | key:" + event.key);
        // Left:37  Up:38  Right:39  Down:40  13:Return
        if(event.keyCode == 39 || event.keyCode == 40 || event.keyCode == 46) {
            next();
        } else if (event.keyCode == 37 || event.keyCode == 38 || event.keyCode == 44) {
            previous();
        } else if (event.keyCode == 13) {
            toggleFullScreen();
        } else if(event.which == 67 || event.which == 99) {
            openConsole();
        } else if(event.which == 72 || event.which == 104) {
            toggleHelp();
        }
    });

    /**
     * From https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Using_full_screen_mode
     */
    function toggleFullScreen() {
        if (!document.fullscreenElement &&          // alternative standard method
            !document.mozFullScreenElement &&       //--\
            !document.webkitFullscreenElement &&    //   | current working methods
            !document.msFullscreenElement ) {       //--/
            if (document.documentElement.requestFullscreen) {
                document.documentElement.requestFullscreen();
            } else if (document.documentElement.msRequestFullscreen) {
                document.documentElement.msRequestFullscreen();
            } else if (document.documentElement.mozRequestFullScreen) {
                document.documentElement.mozRequestFullScreen();
            } else if (document.documentElement.webkitRequestFullscreen) {
                document.documentElement.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT);
            }
            $("#cBtn_Screen").html("Restore");
        } else {
            if (document.exitFullscreen) {
                document.exitFullscreen();
            } else if (document.msExitFullscreen) {
                document.msExitFullscreen();
            } else if (document.mozCancelFullScreen) {
                document.mozCancelFullScreen();
            } else if (document.webkitExitFullscreen) {
                document.webkitExitFullscreen();
            }
            $("#cBtn_Screen").html("Full Screen");
        }
    }

    return {
        init: init,
        next: next,
        previous: previous
    }

})(jQuery);

$( document ).ready(function() {
    Slides.init();
});

<|endoftext|>