Source: widgets/SpwTimeTravel.js

Retour à la documentation
/**
 * @class spw.widgets.SpwTimeTravel
 */
define([
        "dojo/_base/declare", "spw/api/SpwBaseTemplatedWidget", "dojo/text!./templates/SpwTimeTravel.html",
        "dojo/i18n!./nls/SpwTimeTravel", "dijit/form/HorizontalSlider", "dijit/form/HorizontalRuleLabels",
        "dijit/form/HorizontalRule", "dojo/_base/array", "dojo/on", "dojo/_base/lang", "dojo/dom-construct",
        "dijit/Dialog", "dojo/dom-style", "dojo/dom-class", "dojo/dom-geometry",

        "dijit/layout/ContentPane", "dijit/form/Button"
    ],
    function(declare, SpwBaseTemplatedWidget, template, labels, HorizontalSlider, HorizontalRuleLabels,
             HorizontalRule, array, on, lang, domConstruct, Dialog, domStyle, domClass, domGeom) {

        return declare("spw.widgets.SpwTimeTravel", [SpwBaseTemplatedWidget], {

            templateString: template,
            labels: labels,

            // basemap selected
            basemap: null,
            service: null,
            // mapservices for the basemap
            services: [],
            // selectedservice (the most opaque)
            selectedService: null,

            spwViewer: null,

            // slider elements
            horizontalRule: null,
            horizontalRuleLabels: null,
            slider: null,

            // pause/play information
            startValue: 0,
            isPlaying: false,
            stepPlaying: 1,
            playingSpeed: 300,

            // widget options
            widgetId: "SpwTimeTravelBaseMapId",
            widgetTitle: labels.widgetTitle,
            position: "panel-light",
            bottom: "15px",
            right: "15px",

            minimum: 0,
            maximum: 100,

            constructor: function() {
                this.inherited(arguments);
            },

            getTimer: function(){
                return this.basemap || this.service;
            },

            postCreate: function() {
                this.inherited(arguments);

                // without basemap...we can't do more
                if (!this.getTimer()) {
                    return;
                }

                // handle play/pause click
                this.own(
                    on(this.playNode, 'click', lang.hitch(this, this.pausePlayClicked))
                );

                // get alpha start value
                var step = 1 / this.getTimer().services.length;
                this.offset = step / 2;
                this.startValue = this.offset;

                this.minimum = this.offset * 100;
                this.maximum = (1 - this.offset) * 100;

                // get map services
                if(this.basemap){
                    this.services = array.map(this.getTimer().services, lang.hitch(this, function(s, i) {
                        if (s.selected && this.startValue === this.offset) {
                            this.startValue = (i * step) + ((1 - (s.alphaTimer == null ? 1 : Math.abs(s.alphaTimer))) * step);

                            if (i > 0 || s.alphaTimer == null || s.alphaTimer >= 0) {
                                this.startValue += this.offset;
                            }

                            if (this.startValue > 1) {
                                this.startValue = 1;
                            }
                        }
                        return this.spwViewer.get('spwMap').getMapServiceById(s.serviceId);
                    }));
                } else {
                    this.services = this.getTimer().mapServices;
                }
                // build slider
                var timerCount = this.services.length;

                array.forEach(this.services, lang.hitch(this, function(s, idx) {
                    var li = domConstruct.create('li', {
                        'class': 'imgHolder',
                        style: 'width: ' + (100 / this.services.length) + '%'
                    }, this.labelsList);

                    var icon = s.imagePath || 'noRuleIcon.png';

                    var img = domConstruct.create('div', {
                        //src: this.imagesPath + icon,
                        'class': 'img',
                        'style': 'background-image: url(\'' + icon + '\');'
                    }, li);

                    var handleClick = lang.hitch(this, function() {
                        var value = (idx * step);

                        value = (value * 100) + this.offset;

                        this.slider.set('value', this.correctValue(value));
                    });

                    var span = domConstruct.create('span', {
                        innerHTML: s.ruleLabel,
                        style: 'cursor: ' + (s.metadataUrl ? 'pointer' : 'default')
                    }, li);

                    this.own(on(img, 'click', handleClick), on(span, 'click', lang.hitch(this, handleClick/*this.handleOnMetadataClick*/, s)));

                    li.img = img;
                    s.ruleLi = li;
                }));

                this.slider = new HorizontalSlider({
                    name: "slider",
                    value: 0,
                    minimum: this.minimum,
                    maximum: this.maximum,
                    discreteValues: 100,
                    intermediateChanges: true,
                    style: "margin: 0 auto; width: " + (100 - (100 / this.services.length)) + "%;"
                    // style: "margin: 0 auto; width: 100%;"
                }, this.sliderNode);

                // handle slider value changes
                this.own(
                    on(this.slider, 'change', lang.hitch(this, this.setAlpha))
                );

                this.offset *= 100;

                // if startValue != slider value, we can set it and event will be triggered
                if (this.startValue !== this.slider.get('value')) {
                    this.slider.set('value', this.correctValue(this.startValue * 100));
                }
                // if not, we have to call setAlpha manually
                else {
                    this.setAlpha(this.startValue * 100);
                }
            },

            correctValue: function(v) {
                if (v < this.minimum) {
                    return this.minimum;
                }

                if (v > this.maximum) {
                    return this.maximum;
                }

                return v;
            },

            /**
             * Handle pause/play action
             */
            pausePlayClicked: function() {
                // function called every XXX ms
                function playing() {
                    // if is paused
                    if (!this.isPlaying) {
                        // enable slider and change image
                        this.slider.set('disabled', false);
                        domClass.remove(this.playNode, 'pause');
                        return;
                    }

                    // get new value
                    var newVal = this.slider.get('value') + this.stepPlaying;
                    var maxReached = false;

                    // if max reached, stop playing
                    if (newVal >= this.slider.get('maximum')) {
                        newVal = this.slider.get('maximum');
                        this.isPlaying = false;
                    }

                    this.slider.set('value', this.correctValue(newVal));
                    // next call
                    this.timeOutId = setTimeout(lang.hitch(this, playing), this.playingSpeed);
                }

                // pause if currently playing
                if (this.isPlaying) {
                    this.isPlaying = false;
                }
                else {
                    // reset slider value if max reached
                    if (this.slider.get('value') === this.slider.get('maximum')) {
                        this.slider.set('value', this.slider.get('minimum'));
                    }

                    domClass.add(this.playNode, 'pause');

                    // disable slider and start playing
                    this.slider.set('disabled', true);
                    this.isPlaying = true;
                    this.timeOutId = setTimeout(lang.hitch(this, playing), this.playingSpeed);
                }
            },

            setAlpha: function(value) {
                if (!this.services || !this.services.length) {
                    return;
                }

                // get data to compute alphas for each service
                var delta = 100;

                var nbrOfLayers = this.services.length;
                var stepSize = delta / nbrOfLayers;

                var stepNumber = (value + this.offset) / stepSize;
                var stepNumberRounded = Math.round(stepNumber);
                var isAfter = stepNumberRounded <= stepNumber;

                stepNumberRounded -= 1;

                if (stepNumberRounded < 0) {
                    stepNumberRounded = 0;
                    isAfter = false;
                }
                else if (stepNumberRounded >= this.services.length) {
                    stepNumberRounded = this.services.length - 1;
                    isAfter = true;
                }

                for(var i = 0; i < this.services.length; i++) {
                    if(i === stepNumberRounded) {
                        // keep alpha value so BaseMapChooser can use it when global alpha is modified
                        var first = this.services[i].alphaTimer = isAfter ? (-stepNumber + i + 2) : (i - stepNumber);

                        /*if (first < 0) {
                            first = this.services[i].alphaTimer = 0;
                        }
                        else */if (first > 1) {
                            first = this.services[i].alphaTimer = first - 1;
                        }

                        this.selectedService = this.services[i];

                        this.services[i].set('alpha', Math.abs(this.services[i].alphaTimer * this.getTimer().alpha));

                        var idxBefore = i - 1;

                        if (!isAfter && idxBefore >= 0) {
                            var before = this.services[idxBefore].alphaTimer = 1 - Math.abs(first);

                            this.services[idxBefore].set('alpha', Math.abs(this.services[idxBefore].alphaTimer * this.getTimer().alpha));
                            this.setScaleImg(this.services[idxBefore].ruleLi.img, 1 + Math.abs(before / 4));
                        }

                        var idxAfter = i + 1;

                        if (isAfter && idxAfter < this.services.length) {
                            var after = this.services[idxAfter].alphaTimer = 1 - Math.abs(first);

                            if (after < 0) {
                                after = this.services[idxAfter].alphaTimer = 0;
                            }

                            this.services[idxAfter].set('alpha', this.services[idxAfter].alphaTimer * this.getTimer().alpha);
                            i += 1;

                            domClass.remove(this.services[idxAfter].ruleLi, 'selected');
                            this.setScaleImg(this.services[idxAfter].ruleLi.img, 1 + (after / 4));
                        }

                        // show description and disable metadata button is necessary
                        this.descriptionNode.innerHTML = this.selectedService.description ? this.selectedService.description : this.labels.noDescription;
                        domStyle.set(this.metadataButton.domNode, 'display', this.selectedService.metadataUrl ? '' : 'none');
                        this.metadataButton.set('disabled', !this.selectedService.metadataUrl);

                        domClass.add(this.selectedService.ruleLi, 'selected');
                        this.setScaleImg(this.selectedService.ruleLi.img, 1 + Math.abs(first / 4));
                    }
                    else {
                        this.services[i].alphaTimer = 0;
                        this.services[i].set('alpha', 0);
                        domClass.remove(this.services[i].ruleLi, 'selected');
                        this.setScaleImg(this.services[i].ruleLi.img, 1);
                    }
                }
            },

            setScaleImg: function(node, value) {
                domStyle.set(node, '-webkit-transform', 'scale(' + value + ')');
                domStyle.set(node, '-moz-transform', 'scale(' + value + ')');
                domStyle.set(node, '-ms-transform', 'scale(' + value + ')');
                domStyle.set(node, '-o-transform', 'scale(' + value + ')');
                domStyle.set(node, 'transform', 'scale(' + value + ')');
            },

            handleOnMetadataClick: function(service) {
                if (service instanceof Event) {
                    service = this.selectedService;
                }

                if (service && service.metadataUrl) {
                    if(service.metadataPopup){
                        var width = service.metadataPopup.width != null ? service.metadataPopup.width : "750px";
                        var height = service.metadataPopup.height != null ? service.metadataPopup.height : "800px";

                        new Dialog({
                            title: "",
                            content: "<iframe width=\""+width+"\" height=\""+height+"\" src=\""+service.metadataUrl+"\"></iframe>"
                        }).show();
                    }
                    else {
                        window.open(service.metadataUrl, '_blank');
                    }
                }
            }
        });

    });