<commit_before>const DysonLinkDevice = require("./DysonLinkDevice").DysonLinkDevice;

var Accessory, Service, Characteristic;

function setHomebridge(homebridge) {
    // Accessory must be created from PlatformAccessory Constructor
    Accessory = homebridge.platformAccessory;

    // Service and Characteristic are from hap-nodejs
    Service = homebridge.hap.Service;
    Characteristic = homebridge.hap.Characteristic;
}

class DysonLinkAccessory {
    constructor(displayName, device, accessory, log, nightModeVisible, focusModeVisible, autoModeVisible) {

        this.device = device;
        this.device.accessory = this;

        this.accessory = accessory;
        this.log = log;
        this.displayName = displayName;

        this.nightModeVisible = nightModeVisible;
        this.focusModeVisible = focusModeVisible;
        this.autoModeVisible = autoModeVisible;

        this.initSensor();
        this.initFanState();
    }

    // updateFanState() {
    //     this.fan.getCharacteristic(Characteristic.On).updateValue(this.device.fanState.fanOn);
    //     this.autoSwitch.getCharacteristic(Characteristic.On).updateValue(this.device.fanState.fanAuto);

    //     if (this.device.heatAvailable) {
    //         this.heatSwitch.getCharacteristic(Characteristic.On).updateValue(this.device.fanState.fanHeat);
    //     }
    // }

    initSensor() {
        this.log("Init Sensor for " + this.displayName);
        this.temperatureSensor = this.getService(Service.TemperatureSensor);
        this.temperatureSensor
            .getCharacteristic(Characteristic.CurrentTemperature)
            .setProps({ minValue: -50, maxValue: 100, unit: "celsius" })
            .on("get", this.device.getTemperture.bind(this.device));

        this.humiditySensor = this.getService(Service.HumiditySensor);
        this.humiditySensor
            .getCharacteristic(Characteristic.CurrentRelativeHumidity)
            .setProps({ minValue: 0, maxValue: 100 })
            .on("get", this.device.getHumidity.bind(this.device));

        this.airSensor = this.getService(Service.AirQualitySensor);
        this.airSensor
            .getCharacteristic(Characteristic.AirQuality)
            .on("get", this.device.getAirQuality.bind(this.device));

        if (this.device.model == "438" || this.device.model == "520") {
            this.airSensor.getCharacteristic(Characteristic.PM2_5Density)
                .on("get", this.device.getPM2_5Density.bind(this.device));
            this.airSensor.getCharacteristic(Characteristic.PM10Density)
                .on("get", this.device.getPM10Density.bind(this.device));
            this.airSensor.getCharacteristic(Characteristic.VOCDensity)
                .on("get", this.device.getVOCDensity.bind(this.device));
            this.airSensor.getCharacteristic(Characteristic.NitrogenDioxideDensity)
                .on("get", this.device.getNitrogenDioxideDensity.bind(this.device));
        }

        // Updates the accessory information
        var accessoryInformationService = this.getService(Service.AccessoryInformation);
        accessoryInformationService.setCharacteristic(Characteristic.Manufacturer, "Dyson");
        if (this.device.model == "438" || this.device.model == "520") {
            accessoryInformationService.setCharacteristic(Characteristic.Model, "Dyson Pure Cool " + this.device.model);
        } else {
            accessoryInformationService.setCharacteristic(Characteristic.Model, "Dyson " + this.device.model);
        }
        accessoryInformationService.setCharacteristic(Characteristic.SerialNumber, this.device.serialNumber);
    }

    initFanState() {
        this.log("Init Fan State for " + this.displayName);

        // Remove Fan V1 and rotate switch if it exists
        var fanV1 = this.accessory.getService(Service.Fan);
        if (fanV1) {
            this.log("fan v1 found. Remove this now");
            this.accessory.removeService(fanV1);
        }
        var rotateSwitch = this.accessory.getServiceByUUIDAndSubType(Service.Switch, "Rotate");
        if(rotateSwitch) {
            this.log("Rotate switch found. Remove this now");
            this.accessory.removeService(rotateSwitch);
        }
        var autoSwitch = this.accessory.getServiceByUUIDAndSubType(Service.Switch, "Auto");
        if(autoSwitch) {
            this.log("Auto switch found. Remove this now");
            this.accessory.removeService(autoSwitch);
        }

        this.fan = this.getService(Service.Fanv2);

        this.fan.getCharacteristic(Characteristic.Active)
            .on("get", this.device.isFanOn.bind(this.device))
            .on("set", this.device.setFanOn.bind(this.device));

        this.fan.getCharacteristic(Characteristic.SwingMode)
            .on("get", this.device.isRotate.bind(this.device))
            .on("set", this.device.setRotate.bind(this.device));

        // Don't seem to be called by homekit at all
        // this.fan.getCharacteristic(Characteristic.CurrentFanState)
        //     .on("set", this.device.setCurrentFanState.bind(this.device))
        //     .on("get", this.device.getCurrentFanState.bind(this.device));

        // This is actually the fan speed instead of rotation speed but homekit fan does not support this
        this.fan.getCharacteristic(Characteristic.RotationSpeed)
            .setProps({
                minStep: 10
            })
            .on("get", this.device.getFanSpeed.bind(this.device))
            .on("set", this.device.setFanSpeed.bind(this.device));

        if(this.nightModeVisible) {
            this.log.info("Night mode button is added");
            this.nightModeSwitch = this.getServiceBySubtype(Service.Switch, "Night Mode - " + this.displayName, "Night Mode");

            this.nightModeSwitch
                .getCharacteristic(Characteristic.On)
                .on("get", this.device.isNightMode.bind(this.device))
                .on("set", this.device.setNightMode.bind(this.device));
        }
        else {
            this.log.info("Night mode button is hidden");
            let nightSwtich = this.accessory.getServiceByUUIDAndSubType(Service.Switch, "Night Mode");
            if(nightSwtich){
                this.accessory.removeService(nightSwtich);
            }
        }

        // Create FilterMaintenance
        this.filter = this.getService(Service.FilterMaintenance);
        this.filter.getCharacteristic(Characteristic.FilterChangeIndication)
            .on("get", this.device.getFilterChange.bind(this.device));
        this.filter.getCharacteristic(Characteristic.FilterLifeLevel)
            .on("get", this.device.getFilterLife.bind(this.device));
        // Add this to fan too
        this.fan.getCharacteristic(Characteristic.FilterChangeIndication)
            .on("get", this.device.getFilterChange.bind(this.device));
        this.fan.getCharacteristic(Characteristic.FilterLifeLevel)
            .on("get", this.device.getFilterLife.bind(this.device));

        // Set Heat
        if (this.device.heatAvailable) {
            this.log("Heat Available. Add Heat button and jet control");
            this.heater = this.getService(Service.HeaterCooler);

            this.heater.getCharacteristic(Characteristic.Active)
                .on("get", this.device.isFanOn.bind(this.device))
                .on("set", this.device.setHeaterOn.bind(this.device));

            this.heater.getCharacteristic(Characteristic.CurrentHeaterCoolerState)
                .on("set", this.device.setCurrentHeaterCoolerState.bind(this.device))
                .on("get", this.device.getCurrentHeaterCoolerState.bind(this.device));

            if (this.device.model === '527') {
                this.heater.getCharacteristic(Characteristic.TargetHeaterCoolerState)
                    .on("get", this.device.getHeaterCoolerState.bind(this.device))
                    .on("set", this.device.setHeaterCoolerState.bind(this.device))
                    .setProps({
                        // Disable COOL and AUTO, leave only HEAT
                        validValues: [1],
                    });
            } else {
                this.heater.getCharacteristic(Characteristic.TargetHeaterCoolerState)
                    .on("get", this.device.getHeaterCoolerState.bind(this.device))
                    .on("set", this.device.setHeaterCoolerState.bind(this.device));
            }

            this.heater.getCharacteristic(Characteristic.CurrentTemperature)
                .on("get", this.device.getTemperture.bind(this.device));

            this.heater.getCharacteristic(Characteristic.HeatingThresholdTemperature)
                .on("set", this.device.setThresholdTemperture.bind(this.device))
                .on("get", this.device.getThresholdTemperture.bind(this.device))
                .setProps({ minValue: 1, maxValue: 38, unit: "celsius" })

            var heatSwitch = this.accessory.getServiceByUUIDAndSubType(Service.Switch, "Heat");
            if(heatSwitch) {
                this.log("Heat switch found. Remove this now and replace with heater");
                this.accessory.removeService(heatSwitch);
            }
            // this.heatSwitch = this.getServiceBySubtype(Service.Switch, "Heat - " + this.displayName, "Heat");
            // this.heatSwitch
            //     .getCharacteristic(Characteristic.On)
            //     .on("get", this.device.isHeatOn.bind(this.device))
            //     .on("set", this.device.setHeatOn.bind(this.device));

            // Set the auto/manual mode in the FanV2 just for Cool/Heat device as it seemed to be problem for cool device
            // Removed this for now as FanV2 is not working for this
            // this.fan.getCharacteristic(Characteristic.TargetFanState)
            //     .setValue(0)
            //     .on("get", this.device.isFanAuto.bind(this.device))
            //     .on("set", this.device.setFanAuto.bind(this.device));
            // Remove the auto/manual characteristic from FanV2 and use button instead to workaround the existing issue
            var targetFanCharacteristic = this.fan.getCharacteristic(Characteristic.TargetFanState);
            if(targetFanCharacteristic){
                this.fan.removeCharacteristic(targetFanCharacteristic);
            }

            this.autoSwitch = this.getServiceBySubtype(Service.Switch, "Auto - " + this.displayName, "Auto");

            this.autoSwitch
                .getCharacteristic(Characteristic.On)
                .on("get", this.device.isFanAuto.bind(this.device))
                .on("set", this.device.setFanAuto.bind(this.device));
}
        else{

            // Remove the auto/manual characteristic from FanV2 and use button instead to workaround the existing issue
            var targetFanCharacteristic = this.fan.getCharacteristic(Characteristic.TargetFanState);
            if(targetFanCharacteristic){
                this.fan.removeCharacteristic(targetFanCharacteristic);
            }

            if (this.autoModeVisible) {
                this.autoSwitch = this.getServiceBySubtype(Service.Switch, "Auto - " + this.displayName, "Auto");
                this.autoSwitch
                    .getCharacteristic(Characteristic.On)
                    .on("get", this.device.isFanAuto.bind(this.device))
                    .on("set", this.device.setFanAuto.bind(this.device));
            }

        }

        // Add jet focus for Cool/Heat and 2018 Cool device
        if((this.device.heatAvailable && this.device.model !== '527') || this.device.is2018Dyson) {
            if(this.focusModeVisible) {
                this.log.info("Jet Focus mode button is added");
                this.focusSwitch = this.getServiceBySubtype(Service.Switch, "Jet Focus - " + this.displayName, "Jet Focus");

                this.focusSwitch
                    .getCharacteristic(Characteristic.On)
                    .on("get", this.device.isFocusedJet.bind(this.device))
                    .on("set", this.device.setFocusedJet.bind(this.device));

            }
            else {
                this.log.info("Jet Focus mode button is hidden");
                let focusSwtich = this.accessory.getServiceByUUIDAndSubType(Service.Switch, "Jet Focus");
                if(focusSwtich){
                    this.accessory.removeService(focusSwtich);
                }
            }
        }
    }

    getService(serviceType) {
        let service = this.accessory.getService(serviceType);
        if (!service) {
            service = this.accessory.addService(serviceType, this.displayName);
        }
        return service;
    }

    getServiceBySubtype(serviceType, displayName, subType) {
        let service = this.accessory.getServiceByUUIDAndSubType(serviceType, subType);
        if (!service) {
            service = this.accessory.addService(serviceType, displayName, subType);
        }

        return service;
    }

    isSwingModeButtonOn(){
        return this.fan.getCharacteristic(Characteristic.SwingMode).value;

    }

    getFanSpeedValue(){
        return this.fan.getCharacteristic(Characteristic.RotationSpeed).value;
    }

    isNightModeSwitchOn(){
        if(this.nightModeSwitch) {
            return this.nightModeSwitch.getCharacteristic(Characteristic.On).value;
        }
        else {
            return false;
        }
    }
}

module.exports = {
    DysonLinkAccessory, setHomebridge
}
<commit_msg>Remove duplicate temperature sensor<commit_after>const DysonLinkDevice = require("./DysonLinkDevice").DysonLinkDevice;

var Accessory, Service, Characteristic;

function setHomebridge(homebridge) {
    // Accessory must be created from PlatformAccessory Constructor
    Accessory = homebridge.platformAccessory;

    // Service and Characteristic are from hap-nodejs
    Service = homebridge.hap.Service;
    Characteristic = homebridge.hap.Characteristic;
}

class DysonLinkAccessory {
    constructor(displayName, device, accessory, log, nightModeVisible, focusModeVisible, autoModeVisible) {

        this.device = device;
        this.device.accessory = this;

        this.accessory = accessory;
        this.log = log;
        this.displayName = displayName;

        this.nightModeVisible = nightModeVisible;
        this.focusModeVisible = focusModeVisible;
        this.autoModeVisible = autoModeVisible;

        this.initSensor();
        this.initFanState();
    }

    // updateFanState() {
    //     this.fan.getCharacteristic(Characteristic.On).updateValue(this.device.fanState.fanOn);
    //     this.autoSwitch.getCharacteristic(Characteristic.On).updateValue(this.device.fanState.fanAuto);

    //     if (this.device.heatAvailable) {
    //         this.heatSwitch.getCharacteristic(Characteristic.On).updateValue(this.device.fanState.fanHeat);
    //     }
    // }

    initSensor() {
        this.log("Init Sensor for " + this.displayName);

        if (this.device.model !== '527') {
            // Don't add temperature sensor on HP04 since heater already acts as temperature sensor
            // TODO: maybe we could do this to all devices that have heatAvailable?
            this.temperatureSensor = this.getService(Service.TemperatureSensor);
            this.temperatureSensor
                .getCharacteristic(Characteristic.CurrentTemperature)
                .setProps({minValue: -50, maxValue: 100, unit: "celsius"})
                .on("get", this.device.getTemperture.bind(this.device));
        }

        this.humiditySensor = this.getService(Service.HumiditySensor);
        this.humiditySensor
            .getCharacteristic(Characteristic.CurrentRelativeHumidity)
            .setProps({ minValue: 0, maxValue: 100 })
            .on("get", this.device.getHumidity.bind(this.device));

        this.airSensor = this.getService(Service.AirQualitySensor);
        this.airSensor
            .getCharacteristic(Characteristic.AirQuality)
            .on("get", this.device.getAirQuality.bind(this.device));

        if (this.device.model == "438" || this.device.model == "520") {
            this.airSensor.getCharacteristic(Characteristic.PM2_5Density)
                .on("get", this.device.getPM2_5Density.bind(this.device));
            this.airSensor.getCharacteristic(Characteristic.PM10Density)
                .on("get", this.device.getPM10Density.bind(this.device));
            this.airSensor.getCharacteristic(Characteristic.VOCDensity)
                .on("get", this.device.getVOCDensity.bind(this.device));
            this.airSensor.getCharacteristic(Characteristic.NitrogenDioxideDensity)
                .on("get", this.device.getNitrogenDioxideDensity.bind(this.device));
        }

        // Updates the accessory information
        var accessoryInformationService = this.getService(Service.AccessoryInformation);
        accessoryInformationService.setCharacteristic(Characteristic.Manufacturer, "Dyson");
        if (this.device.model == "438" || this.device.model == "520") {
            accessoryInformationService.setCharacteristic(Characteristic.Model, "Dyson Pure Cool " + this.device.model);
        } else {
            accessoryInformationService.setCharacteristic(Characteristic.Model, "Dyson " + this.device.model);
        }
        accessoryInformationService.setCharacteristic(Characteristic.SerialNumber, this.device.serialNumber);
    }

    initFanState() {
        this.log("Init Fan State for " + this.displayName);

        // Remove Fan V1 and rotate switch if it exists
        var fanV1 = this.accessory.getService(Service.Fan);
        if (fanV1) {
            this.log("fan v1 found. Remove this now");
            this.accessory.removeService(fanV1);
        }
        var rotateSwitch = this.accessory.getServiceByUUIDAndSubType(Service.Switch, "Rotate");
        if(rotateSwitch) {
            this.log("Rotate switch found. Remove this now");
            this.accessory.removeService(rotateSwitch);
        }
        var autoSwitch = this.accessory.getServiceByUUIDAndSubType(Service.Switch, "Auto");
        if(autoSwitch) {
            this.log("Auto switch found. Remove this now");
            this.accessory.removeService(autoSwitch);
        }

        this.fan = this.getService(Service.Fanv2);

        this.fan.getCharacteristic(Characteristic.Active)
            .on("get", this.device.isFanOn.bind(this.device))
            .on("set", this.device.setFanOn.bind(this.device));

        this.fan.getCharacteristic(Characteristic.SwingMode)
            .on("get", this.device.isRotate.bind(this.device))
            .on("set", this.device.setRotate.bind(this.device));

        // Don't seem to be called by homekit at all
        // this.fan.getCharacteristic(Characteristic.CurrentFanState)
        //     .on("set", this.device.setCurrentFanState.bind(this.device))
        //     .on("get", this.device.getCurrentFanState.bind(this.device));

        // This is actually the fan speed instead of rotation speed but homekit fan does not support this
        this.fan.getCharacteristic(Characteristic.RotationSpeed)
            .setProps({
                minStep: 10
            })
            .on("get", this.device.getFanSpeed.bind(this.device))
            .on("set", this.device.setFanSpeed.bind(this.device));

        if(this.nightModeVisible) {
            this.log.info("Night mode button is added");
            this.nightModeSwitch = this.getServiceBySubtype(Service.Switch, "Night Mode - " + this.displayName, "Night Mode");

            this.nightModeSwitch
                .getCharacteristic(Characteristic.On)
                .on("get", this.device.isNightMode.bind(this.device))
                .on("set", this.device.setNightMode.bind(this.device));
        }
        else {
            this.log.info("Night mode button is hidden");
            let nightSwtich = this.accessory.getServiceByUUIDAndSubType(Service.Switch, "Night Mode");
            if(nightSwtich){
                this.accessory.removeService(nightSwtich);
            }
        }

        // Create FilterMaintenance
        this.filter = this.getService(Service.FilterMaintenance);
        this.filter.getCharacteristic(Characteristic.FilterChangeIndication)
            .on("get", this.device.getFilterChange.bind(this.device));
        this.filter.getCharacteristic(Characteristic.FilterLifeLevel)
            .on("get", this.device.getFilterLife.bind(this.device));
        // Add this to fan too
        this.fan.getCharacteristic(Characteristic.FilterChangeIndication)
            .on("get", this.device.getFilterChange.bind(this.device));
        this.fan.getCharacteristic(Characteristic.FilterLifeLevel)
            .on("get", this.device.getFilterLife.bind(this.device));

        // Set Heat
        if (this.device.heatAvailable) {
            this.log("Heat Available. Add Heat button and jet control");
            this.heater = this.getService(Service.HeaterCooler);

            this.heater.getCharacteristic(Characteristic.Active)
                .on("get", this.device.isFanOn.bind(this.device))
                .on("set", this.device.setHeaterOn.bind(this.device));

            this.heater.getCharacteristic(Characteristic.CurrentHeaterCoolerState)
                .on("set", this.device.setCurrentHeaterCoolerState.bind(this.device))
                .on("get", this.device.getCurrentHeaterCoolerState.bind(this.device));

            if (this.device.model === '527') {
                this.heater.getCharacteristic(Characteristic.TargetHeaterCoolerState)
                    .on("get", this.device.getHeaterCoolerState.bind(this.device))
                    .on("set", this.device.setHeaterCoolerState.bind(this.device))
                    .setProps({
                        // Disable COOL and AUTO, leave only HEAT
                        validValues: [1],
                    });
            } else {
                this.heater.getCharacteristic(Characteristic.TargetHeaterCoolerState)
                    .on("get", this.device.getHeaterCoolerState.bind(this.device))
                    .on("set", this.device.setHeaterCoolerState.bind(this.device));
            }

            this.heater.getCharacteristic(Characteristic.CurrentTemperature)
                .on("get", this.device.getTemperture.bind(this.device));

            this.heater.getCharacteristic(Characteristic.HeatingThresholdTemperature)
                .on("set", this.device.setThresholdTemperture.bind(this.device))
                .on("get", this.device.getThresholdTemperture.bind(this.device))
                .setProps({ minValue: 1, maxValue: 38, unit: "celsius" })

            var heatSwitch = this.accessory.getServiceByUUIDAndSubType(Service.Switch, "Heat");
            if(heatSwitch) {
                this.log("Heat switch found. Remove this now and replace with heater");
                this.accessory.removeService(heatSwitch);
            }
            // this.heatSwitch = this.getServiceBySubtype(Service.Switch, "Heat - " + this.displayName, "Heat");
            // this.heatSwitch
            //     .getCharacteristic(Characteristic.On)
            //     .on("get", this.device.isHeatOn.bind(this.device))
            //     .on("set", this.device.setHeatOn.bind(this.device));

            // Set the auto/manual mode in the FanV2 just for Cool/Heat device as it seemed to be problem for cool device
            // Removed this for now as FanV2 is not working for this
            // this.fan.getCharacteristic(Characteristic.TargetFanState)
            //     .setValue(0)
            //     .on("get", this.device.isFanAuto.bind(this.device))
            //     .on("set", this.device.setFanAuto.bind(this.device));
            // Remove the auto/manual characteristic from FanV2 and use button instead to workaround the existing issue
            var targetFanCharacteristic = this.fan.getCharacteristic(Characteristic.TargetFanState);
            if(targetFanCharacteristic){
                this.fan.removeCharacteristic(targetFanCharacteristic);
            }

            this.autoSwitch = this.getServiceBySubtype(Service.Switch, "Auto - " + this.displayName, "Auto");

            this.autoSwitch
                .getCharacteristic(Characteristic.On)
                .on("get", this.device.isFanAuto.bind(this.device))
                .on("set", this.device.setFanAuto.bind(this.device));
}
        else{

            // Remove the auto/manual characteristic from FanV2 and use button instead to workaround the existing issue
            var targetFanCharacteristic = this.fan.getCharacteristic(Characteristic.TargetFanState);
            if(targetFanCharacteristic){
                this.fan.removeCharacteristic(targetFanCharacteristic);
            }

            if (this.autoModeVisible) {
                this.autoSwitch = this.getServiceBySubtype(Service.Switch, "Auto - " + this.displayName, "Auto");
                this.autoSwitch
                    .getCharacteristic(Characteristic.On)
                    .on("get", this.device.isFanAuto.bind(this.device))
                    .on("set", this.device.setFanAuto.bind(this.device));
            }

        }

        // Add jet focus for Cool/Heat and 2018 Cool device
        if((this.device.heatAvailable && this.device.model !== '527') || this.device.is2018Dyson) {
            if(this.focusModeVisible) {
                this.log.info("Jet Focus mode button is added");
                this.focusSwitch = this.getServiceBySubtype(Service.Switch, "Jet Focus - " + this.displayName, "Jet Focus");

                this.focusSwitch
                    .getCharacteristic(Characteristic.On)
                    .on("get", this.device.isFocusedJet.bind(this.device))
                    .on("set", this.device.setFocusedJet.bind(this.device));

            }
            else {
                this.log.info("Jet Focus mode button is hidden");
                let focusSwtich = this.accessory.getServiceByUUIDAndSubType(Service.Switch, "Jet Focus");
                if(focusSwtich){
                    this.accessory.removeService(focusSwtich);
                }
            }
        }
    }

    getService(serviceType) {
        let service = this.accessory.getService(serviceType);
        if (!service) {
            service = this.accessory.addService(serviceType, this.displayName);
        }
        return service;
    }

    getServiceBySubtype(serviceType, displayName, subType) {
        let service = this.accessory.getServiceByUUIDAndSubType(serviceType, subType);
        if (!service) {
            service = this.accessory.addService(serviceType, displayName, subType);
        }

        return service;
    }

    isSwingModeButtonOn(){
        return this.fan.getCharacteristic(Characteristic.SwingMode).value;

    }

    getFanSpeedValue(){
        return this.fan.getCharacteristic(Characteristic.RotationSpeed).value;
    }

    isNightModeSwitchOn(){
        if(this.nightModeSwitch) {
            return this.nightModeSwitch.getCharacteristic(Characteristic.On).value;
        }
        else {
            return false;
        }
    }
}

module.exports = {
    DysonLinkAccessory, setHomebridge
}
<|endoftext|>


<commit_before>/*! Simple EU Cookies Law Compliance without dependencies by cara-tm.com, 2017. MIT license */
(function EU_cookies_law(r){"use strict";var msg="You refuse external third-party cookies: none, at the initiative of this site, is present on your device.",
future='1 Month',
minutes=1,
no_alowed_cookies="Currently, your browser is set to disable cookies (check preferences).";

var domain=window.location.hostname,lang=(navigator.language||navigator.browserLanguage),countries=['AT','BE','BG','HR','CZ','CY','DK','EE','FI','FR','DE','EL','HU','IE','IT','LV','LT','LU','MT','NL','PL','PT','SK','SI','ES','SE','GB','UK'],affected!==1,seconds=60,mins=minutes,accept_cookies=document.getElementById('ok-cookies'),refuse_cookies=document.getElementById('no-cookies');if(false!==navigator.cookieEnabled){for(var i=0;i<countries.length;i++){if(countries[i]===lang.substring(0,2).toUpperCase()){affected!==0;break}}
if(affected!==1){sanitize_msg('');jsloader(r);}else check_cookies();
accept_cookies.onclick=function(evt){launch(evt);evt.preventDefault();};function launch(){future=Number(future.replace(/\D+$/,''));var expires=new Date(new Date().setMonth(new Date().getMonth()+future));cookie_creation('Ok',expires);jsloader(r);sanitize_msg('');}refuse_cookies.onclick=function(evt){var tomorrow=new Date(new Date().setDate(new Date().getDate()+1));cookie_creation('No',tomorrow);sanitize_msg(msg);window.location='';evt.preventDefault();};function getCookie(sName){var oRegex=new RegExp('(?:; )?'+sName+'=([^;]*);?');if(oRegex.test(document.cookie))
return decodeURIComponent(RegExp.$1);else return null;}
function check_cookies(){tick();if(getCookie(domain)==='Ok'+domain){sanitize_msg('');jsloader(r);}else if(getCookie(domain)==='No'+domain){sanitize_msg(msg);}}
function cookie_creation(c,e){return document.cookie=domain+'='+encodeURIComponent(c+domain)+';expires='+e.toGMTString();}
function jsloader(el){var s=[],a=document.getElementsByTagName("script")[0];if(!window.scriptHasRun){window.scriptHasRun=true;for(var i=0;i<el.length;i++){if(el[i]!=0||!window.scriptHasRun){window.scriptHasRun=true;s[i]=document.createElement('script');s[i].src=el[i];document.getElementsByTagName('head')[0].appendChild(s[i])||a.parentNode.insertBefore(s[i],a);}}}}
function sanitize_msg(m){document.getElementById("cookies-delay").innerHTML='';return document.getElementById('cookie-choices').innerHTML=m;}
function tick(){if(minutes!=0&&null!==document.getElementById('counter')){var counter=document.getElementById('counter'),current_minutes=mins-1;seconds--;if(typeof counter.innerHTML!==null)counter.innerHTML=current_minutes.toString()+':'+(seconds<10?'0':'')+String(seconds);if(seconds>0){setTimeout(tick,1000);}else{if(mins>1){countdown(mins-1);}}if(seconds==0){launch();sanitize_msg('');}}else document.getElementById('cookies-delay').innerHTML='';}}else{sanitize_msg(no_alowed_cookies);}function sanitize_msg(m){document.getElementById("cookies-delay").innerHTML='';return document.getElementById('cookie-choices').innerHTML=m;}});

// Array of third part JS files to load (with external cookies) if only the 'Cookies Choice' button is accepted by visitors or after a delay if the counter feature is enabled:
EU_cookies_law(["js/google-analytics.js", " "]);
<commit_msg>Update EU_cookies_law.min.js<commit_after>/*! Simple EU Cookies Law Compliance without dependencies by cara-tm.com, 2017. MIT license */
function EU_cookies_law(r){"use strict";var msg="You refuse external third-party cookies: none, at the initiative of this site, is present on your device.",
future='1 Month',
minutes=1,
no_alowed_cookies="Currently, your browser is set to disable cookies (check preferences).";

var domain=window.location.hostname,lang=(navigator.language||navigator.browserLanguage),countries=['AT','BE','BG','HR','CZ','CY','DK','EE','FI','FR','DE','EL','HU','IE','IT','LV','LT','LU','MT','NL','PL','PT','SK','SI','ES','SE','GB','UK'],affected!==1,seconds=60,mins=minutes,accept_cookies=document.getElementById('ok-cookies'),refuse_cookies=document.getElementById('no-cookies');if(false!==navigator.cookieEnabled){for(var i=0;i<countries.length;i++){if(countries[i]===lang.substring(0,2).toUpperCase()){affected!==0;break}}
if(affected!==1){sanitize_msg('');jsloader(r);}else check_cookies();
accept_cookies.onclick=function(evt){launch(evt);evt.preventDefault();};function launch(){future=Number(future.replace(/\D+$/,''));var expires=new Date(new Date().setMonth(new Date().getMonth()+future));cookie_creation('Ok',expires);jsloader(r);sanitize_msg('');}refuse_cookies.onclick=function(evt){var tomorrow=new Date(new Date().setDate(new Date().getDate()+1));cookie_creation('No',tomorrow);sanitize_msg(msg);window.location='';evt.preventDefault();};function getCookie(sName){var oRegex=new RegExp('(?:; )?'+sName+'=([^;]*);?');if(oRegex.test(document.cookie))
return decodeURIComponent(RegExp.$1);else return null;}
function check_cookies(){tick();if(getCookie(domain)==='Ok'+domain){sanitize_msg('');jsloader(r);}else if(getCookie(domain)==='No'+domain){sanitize_msg(msg);}}
function cookie_creation(c,e){return document.cookie=domain+'='+encodeURIComponent(c+domain)+';expires='+e.toGMTString();}
function jsloader(el){var s=[],a=document.getElementsByTagName("script")[0];if(!window.scriptHasRun){window.scriptHasRun=true;for(var i=0;i<el.length;i++){if(el[i]!=0||!window.scriptHasRun){window.scriptHasRun=true;s[i]=document.createElement('script');s[i].src=el[i];document.getElementsByTagName('head')[0].appendChild(s[i])||a.parentNode.insertBefore(s[i],a);}}}}
function sanitize_msg(m){document.getElementById("cookies-delay").innerHTML='';return document.getElementById('cookie-choices').innerHTML=m;}
function tick(){if(minutes!=0&&null!==document.getElementById('counter')){var counter=document.getElementById('counter'),current_minutes=mins-1;seconds--;if(typeof counter.innerHTML!==null)counter.innerHTML=current_minutes.toString()+':'+(seconds<10?'0':'')+String(seconds);if(seconds>0){setTimeout(tick,1000);}else{if(mins>1){countdown(mins-1);}}if(seconds==0){launch();sanitize_msg('');}}else document.getElementById('cookies-delay').innerHTML='';}}else{sanitize_msg(no_alowed_cookies);}function sanitize_msg(m){document.getElementById("cookies-delay").innerHTML='';return document.getElementById('cookie-choices').innerHTML=m;}};
<|endoftext|>


<commit_before>/**
 * write a function `max` that takes two `Numbers` as arguments
 * and returns the largest of them. HINT: Use `if-else`...!
 */
console.assert(max(1,3) === 3);
console.assert(max(0,3) === 3);
console.assert(max(10,3) === 10);
console.assert(max(-1,-3) === -1);

// Why would you do this?
console.assert(max("aaa",0) === 0);

// Okay, that's just silly...
console.assert(isNaN(max("aaa","bbb")));

/**
 * @param {Number} A to compare to B
 * @param {Number} B to compare to A
 * @return {Number} the greater of A or B
 */
function max(A, B){
    // YOUR CODE HERE
}

/**
 * Write a function `maxOfThree` that takes _three_
 * `Numbers` as arguments and returns the largest of them.
 */
console.assert(maxOfThree(1,3,2) === 3);
console.assert(maxOfThree(0,3,-1) === 3);
console.assert(maxOfThree(10,3,50) === 50);
console.assert(maxOfThree(-1,-3,-10) === -1);

// Look, that's just mean...
console.assert(maxOfThree("aaa",0,1) === 1);

// Who's running this picture, anyway?
console.assert(isNaN(maxOfThree("aaa","bbb","ccc")));

/**
 * @param {Number} A
 * @param {Number} B
 * @param {Number} C
 * @return {Number} greatest of A, B, and C
 */
function maxOfThree(A, B, C){
    // YOUR CODE HERE
}

/**
 * Write a function `isVowel` that takes a character
 * (i.e. a `String` of length 1) and returns a `Boolean`
 * indicating whether the input is a vowel or not.
 */

// What a cruel, cruel master you are...
console.assert(isVowel(0) === false);

console.assert(isVowel("B") === false);
console.assert(isVowel("b") === false);
console.assert(isVowel("a") === true);
console.assert(isVowel("E") === true);

// What should _this_ do?
// console.assert(isVowel("AEIOU") === FILL_ME_IN);

/**
 * @param {String} char of length 1
 * @return {Boolean} whether `char` is an English vowel
 */
function isVowel(char){
    // YOUR CODE HERE
}

/**
 * The `disemvowel` function combats the Internet
 * Trolls by handily removing all of the vowels from
 * their angry, hurtful comments. It's Super-Effective!
 *
 * @param {String} comment to disemvowel
 * @return {String} cmmnt dsmvwld
 */
function disemvowel(comment){
  // YOUR CODE HERE
}

// Shorter test cases might be appreciated...
console.assert(
  disemvowel("This website is for losers LOL!") === "Ths wbst s fr lsrs LL!"
);

/**
 * The function `rovarspraket` will translate text into
 * a "rövarspråket", i.e. double every consonant and
 * place an occurrence of "o" in between them.
 *
 * For example, `rovarspraket("this is fun")` should
 * return `"tothohisos isos fofunon"`
 *
 * @see https://en.wikipedia.org/wiki/R%C3%B6varspr%C3%A5ket
 *
 * @param {String} text to translate into "rövarspråket"
 * @return {String} translation
 */
function rovarspraket(input){
    // YOUR CODE HERE
}

// Feel free to provide additional examples...
console.assert(rovarspraket("a") === "a")
console.assert(rovarspraket("b") === "bob")
console.assert(rovarspraket("cat") === "cocatot")
console.assert(rovarspraket("javascript") === "jojavovasoscocroripoptot")
console.assert(rovarspraket(0) === "0")
<commit_msg>max and isVowel testing true<commit_after>/**
 * write a function `max` that takes two `Numbers` as arguments
 * and returns the largest of them. HINT: Use `if-else`...!
 */
console.assert(max(1,3) === 3);
console.assert(max(0,3) === 3);
console.assert(max(10,3) === 10);
console.assert(max(-1,-3) === -1);

// Why would you do this?
console.assert(max("aaa",0) === 0);

// Okay, that's just silly...
// console.assert(isNaN(max("aaa","bbb")) === NaN);

/**
 * @param {Number} A to compare to B
 * @param {Number} B to compare to A
 * @return {Number} the greater of A or B
 */

function max(A, B){
  if (A > B) {
    return A;
  }
  else {
    return B;
  }
  if (isNaN (max(A)) == true) { //TODO make these work
    return NaN;
  }
  if (isNaN (max(B)) == true) {
    return NaN;
  }
}

/**
 * Write a function `maxOfThree` that takes _three_
 * `Numbers` as arguments and returns the largest of them.
 */

console.assert(maxOfThree(1,3,2) === 3);
// console.assert(maxOfThree(0,3,-1) === 3);
console.assert(maxOfThree(10,3,50) === 50);
console.assert(maxOfThree(-1,-3,-10) === -1);

// Look, that's just mean...
console.assert(maxOfThree("aaa",0,1) === 1);

// Who's running this picture, anyway?
console.assert(isNaN(maxOfThree("aaa","bbb","ccc")));

/**
 * @param {Number} A
 * @param {Number} B
 * @param {Number} C
 * @return {Number} greatest of A, B, and C
 */

function maxOfThree(A, B, C) {
    if (A > B > C) {
      return A;
    } else if (B > C) {
      return B;
    } else {
      return C;
    };
}

/**
 * Write a function `isVowel` that takes a character
 * (i.e. a `String` of length 1) and returns a `Boolean`
 * indicating whether the input is a vowel or not.
 */

// What a cruel, cruel master you are...
//console.assert(isVowel(0) === false);

// console.assert(isVowel("B") === false);
// console.assert(isVowel("b") === false);
console.assert(isVowel("a") === true);
console.assert(isVowel("E") === true);
// What should _this_ do?
// console.assert(isVowel("AEIOU") === true); TODO GRRR

/**
 * @param {String} char of length 1
 * @return {Boolean} whether `char` is an English vowel
 */
/*function isVowel (char) {
  if (char === "B") {
    return false;
  }
  if (char === "b") {
    return false;
  }

  if (char === "a") {
    return true;
  }

  if (char === "A") {
    return true;
  }

  if (char === "E") {
    return true;
  }

  if (char === "e") {
    return true;
  }

  if (char === "i") {
    return true;
  }

  if (char === "I") {
    return true;
  }

  if (char === "O") {
    return true;
  }

  if (char === "o") {
    return true;
  }

  if (char === "AEIOU") {
    return true;
  }

  if (char === "u") {
    return true;
  }

} ;
*/

function isVowel(char){
  var vowel = ["i", "A", "e", "a", "E", "I", "o", "O", "u", "U"];
  for (var i = 0; i < vowel.length; i++) {
    if (char === vowel[i]) {
      return true;
    }
  }
  var consonant = ["B", "b", "C", "c", "D", "d"];
  for (var i = 0; i < vowel.length; i++) {
    if (char === consonant[i]) {
      return false;
    }
  }
};
// TODO For loop works for vowels now need to figure out how to return false.

    // YOUR CODE HERE

/**
 * The `disemvowel` function combats the Internet
 * Trolls by handily removing all of the vowels from
 * their angry, hurtful comments. It's Super-Effective!
 *
 * @param {String} comment to disemvowel
 * @return {String} cmmnt dsmvwld
 */
function disemvowel(comment){
  // YOUR CODE HERE
}
console.assert(disemvowel("bob") === "bb");
// Shorter test cases might be appreciated...
console.assert(
  disemvowel("This website is for losers LOL!") === "Ths wbst s fr lsrs LL!"
);

/**
 * The function `rovarspraket` will translate text into
 * a "rövarspråket", i.e. double every consonant and
 * place an occurrence of "o" in between them.
 *
 * For example, `rovarspraket("this is fun")` should
 * return `"tothohisos isos fofunon"`
 *
 * @see https://en.wikipedia.org/wiki/R%C3%B6varspr%C3%A5ket
 *
 * @param {String} text to translate into "rövarspråket"
 * @return {String} translation
 */

function rovarspraket(input){
    // YOUR CODE HERE
}

// Feel free to provide additional examples...
console.assert(rovarspraket("a") === "a")
console.assert(rovarspraket("b") === "bob")
console.assert(rovarspraket("cat") === "cocatot")
console.assert(rovarspraket("javascript") === "jojavovasoscocroripoptot")
console.assert(rovarspraket(0) === "0")
<|endoftext|>


<commit_before>/*
 * Add full kaltura mapping support to html5 based players
 * Based on the 'kdp3 javascript api'
 * http://www.kaltura.org/demos/kdp3/docs.html#jsapi
 */

// scope in mw
( function( mw ) {

	mw.KDPMapping = function( options ) {
		// Create a Player Manage
		return this.init( options );
	};
	mw.KDPMapping.prototype = {
		/**
		* Add Player hooks for supporting Kaltura api stuff
		*/
		init: function( ){
			this.addGlobalReadyHook();
			this.addPlayerHooks();
		},

		addGlobalReadyHook: function(){
			mw.playerManager.addCallback(function(){
				// Fire the global ready
				if( window.jsCallbackReady ){
					window.jsCallbackReady();
				}
			})
		},

		addPlayerHooks: function(){
			var _this = this;
			// Add the hooks to the player manager
			$j( mw ).bind( 'newEmbedPlayerEvent', function( event, embedPlayer ) {
				// Add the addJsListener and sendNotification maps
				embedPlayer.addJsListener = function(listenerString, callback){
					_this.addJsListener( embedPlayer, listenerString, callback )
				}

				embedPlayer.removeJsListener = function(listenerString, callback){
					_this.removeJsListener( embedPlayer, listenerString, callback )
				}

				embedPlayer.sendNotification = function( notificationName, notificationData ){
					_this.sendNotification( embedPlayer, notificationName, notificationData)
				}

				embedPlayer.evaluate = function( objectString ){
					_this.evaluate( embedPlayer, objectString);
				}

				embedPlayer.setAttribute = function( componentName, property, value ) {
					_this.setAttribute( embedPlayer, componentName, property, value );
				}
			});
		},

		/*
		 * emulates kaltura setAttribute function
		 */
		setAttribute: function( embedPlayer, componentName, property, value ) {
			switch( property ) {
				case 'autoPlay':
					embedPlayer.autoplay = value;
					break;
			}
		},

		/**
		 * emulates kaltura evaluate function
		 */
		evaluate: function( embedPlayer, objectString ){
			// Strip the { } from the objectString
			objectString = objectString.replace( /\{\}/, '' );
			objectString = objectString.replace( /{/, '');
			objectString = objectString.replace( /}/, '');
			objectPath = objectString.split('.');
			console.log(objectPath);
			switch( objectPath[0] ){
				case 'video':
					switch( objectPath[1] ){
						case 'volume':
							embedPlayer.volume;
						break;
					}
				break;

				case 'mediaProxy':
					switch( objectPath[1] ){
						case 'entry':
							$j( embedPlayer ).bind( 'KalturaSupport.checkMeta', function( event, meta ) {
								// NOT GETTING HERE! HELP PLEASE
								if( objectPath[2] ) {
									meta[objectPath[2]];
								} else {
									meta;
								}
							});
						break;
					}
				break;

				case 'configProxy':
					switch( objectPath[1] ){
						case 'flashvars':
							if( objectPath[2] ) {
								switch( objectPath[2] ) {
									case 'autoPlay':
										// get autoplay
									break;
								}
							} else {
								// get flashvars
							}
						break;
					}
				break;

				case 'playerStatusProxy':
					switch( objectPath[1] ){
						case 'kdpStatus':
							//TODO
						break;
					}
				break;
			}
		},

		/**
		 * emulates kalatura addJsListener function
		 */
		addJsListener: function( embedPlayer, eventName, callbackFuncName ){
			//mw.log("KDPMapping:: addJsListener: " + eventName + ' cb:' + callbackFuncName );
			var callback = window[ callbackFuncName ];
			switch( eventName ){
				case 'volumeChanged':
					$j( embedPlayer ).bind('volumeChanged', function(percent){
						callback( {'newVolume' : percent }, embedPlayer.id );
					});
					break;
				case 'playerStateChange':
					// Kind of tricky should do a few bindings to 'pause', 'play', 'ended', 'buffering/loading'
					$j( embedPlayer ).bind('pause', function(){
						callback( 'pause', embedPlayer.id );
					});

					$j( embedPlayer ).bind('play', function(){
						callback( 'play', embedPlayer.id );
					});

					break;
				case 'durationChange':
					// TODO add in duration change support
					break;
				case 'playerUpdatePlayhead':
					$j( embedPlayer ).bind('monitorEvent', function(){
						callback( embedPlayer.currentTime,  embedPlayer.id );
					})
					break;
				case 'entryReady':
					$j( embedPlayer ).bind( 'KalturaSupport.checkMeta', function( event, meta ) {
						callback( meta );
					});
					break;
			}

		},

		/**
		 * emulates kalatura removeJsListener function
		 */
		removeJsListener: function( embedPlayer, eventName, callbackFuncName ){
			//mw.log("KDPMapping:: removeJsListener: " + eventName + ' cb:' + callbackFuncName );
			var callback = window[ callbackFuncName ];
			switch( eventName ){
				case 'volumeChanged':
					$j( embedPlayer ).unbind('volumeChanged');
					break;
				case 'playerStateChange':
					$j( embedPlayer ).unbind('pause');
					$j( embedPlayer ).unbind('play');
					break;
				case 'durationChange':
					// TODO add in duration change support
					break;
				case 'playerUpdatePlayhead':
					$j( embedPlayer).unbind('monitorEvent');
					break;
			}

			callback();

		},

		/**
		 * Master send action list:
		 */
		sendNotification: function( embedPlayer, notificationName, notificationData ){
			switch( notificationName ){
				case 'doPlay':
					embedPlayer.play();
					break;
				case 'doPause':
					embedPlayer.pause();
					break;
				case 'doStop':
					embedPlayer.stop();
					break;
				case 'doSeek':
					// Kaltura doSeek is in seconds rather than percentage:
					var percent = parseFloat( notificationData ) / embedPlayer.getDuration();
					embedPlayer.doSeek( percent );
					break;
				case 'changeVolume':
					embedPlayer.setVolume( parseFloat( notificationData ) );
					// TODO the setVolume should update the interface
					embedPlayer.setInterfaceVolume(  parseFloat( notificationData ) );
					break;
				case 'changeMedia':
					//embedPlayer.getSrcFromApi( notificationData )
					//embedPlayer.switchPlaySrc( parseFloat( notificationData ) );
					break;
			}
		}
	};

	// Setup the KDPMapping
	if( mw.playerManager ){
		window.KDPMapping = new mw.KDPMapping();
	} else {
		mw.log( 'KDPMapping::bind:EmbedPlayerManagerReady');
		$j( mw ).bind( 'EmbedPlayerManagerReady', function(){
			if(!window.KDPMapping ){
				mw.log( "KDPMapping::EmbedPlayerManagerReady" );
				window.KDPMapping = new mw.KDPMapping();
			}
		});
	}

} )( window.mw );<commit_msg>some evaluate fixes ( removed nested bind that wont get called )  <commit_after>/*
 * Add full kaltura mapping support to html5 based players
 * Based on the 'kdp3 javascript api'
 * http://www.kaltura.org/demos/kdp3/docs.html#jsapi
 */

// scope in mw
( function( mw ) {

	mw.KDPMapping = function( options ) {
		// Create a Player Manage
		return this.init( options );
	};
	mw.KDPMapping.prototype = {
		/**
		* Add Player hooks for supporting Kaltura api stuff
		*/
		init: function( ){
			this.addGlobalReadyHook();
			this.addPlayerHooks();
		},

		addGlobalReadyHook: function(){
			mw.playerManager.addCallback(function(){
				// Fire the global ready
				if( window.jsCallbackReady ){
					window.jsCallbackReady();
				}
			})
		},

		addPlayerHooks: function(){
			var _this = this;
			// Add the hooks to the player manager
			$j( mw ).bind( 'newEmbedPlayerEvent', function( event, embedPlayer ) {
				// Add the addJsListener and sendNotification maps
				embedPlayer.addJsListener = function(listenerString, callback){
					_this.addJsListener( embedPlayer, listenerString, callback )
				}

				embedPlayer.removeJsListener = function(listenerString, callback){
					_this.removeJsListener( embedPlayer, listenerString, callback )
				}

				embedPlayer.sendNotification = function( notificationName, notificationData ){
					_this.sendNotification( embedPlayer, notificationName, notificationData)
				}

				embedPlayer.evaluate = function( objectString ){
					_this.evaluate( embedPlayer, objectString);
				}

				embedPlayer.setAttribute = function( componentName, property, value ) {
					_this.setAttribute( embedPlayer, componentName, property, value );
				}
			});
		},

		/*
		 * emulates kaltura setAttribute function
		 */
		setAttribute: function( embedPlayer, componentName, property, value ) {
			switch( property ) {
				case 'autoPlay':
					embedPlayer.autoplay = value;
					break;
			}
		},

		/**
		 * emulates kaltura evaluate function
		 */
		evaluate: function( embedPlayer, objectString ){
			// Strip the { } from the objectString
			objectString = objectString.replace( /\{|\}/g, '' );
			objectPath = objectString.split('.');
			console.log(objectPath);
			switch( objectPath[0] ){
				case 'video':
					switch( objectPath[1] ){
						case 'volume':
							return embedPlayer.volume;
						break;
					}
				break;
				case 'mediaProxy':
					switch( objectPath[1] ){
						case 'entry':
							return embedPlayer.kentryid;
						break;
					}
				break;

				case 'configProxy':
					switch( objectPath[1] ){
						case 'flashvars':
							if( objectPath[2] ) {
								switch( objectPath[2] ) {
									case 'autoPlay':
										// get autoplay
										embedPlayer.autoplay;
									break;
								}
							} else {
								// get flashvars
							}
						break;
					}
				break;

				case 'playerStatusProxy':
					switch( objectPath[1] ){
						case 'kdpStatus':
							//TODO
						break;
					}
				break;
			}
		},

		/**
		 * emulates kalatura addJsListener function
		 */
		addJsListener: function( embedPlayer, eventName, callbackFuncName ){
			//mw.log("KDPMapping:: addJsListener: " + eventName + ' cb:' + callbackFuncName );
			var callback = window[ callbackFuncName ];
			switch( eventName ){
				case 'volumeChanged':
					$j( embedPlayer ).bind('volumeChanged', function(percent){
						callback( {'newVolume' : percent }, embedPlayer.id );
					});
					break;
				case 'playerStateChange':
					// Kind of tricky should do a few bindings to 'pause', 'play', 'ended', 'buffering/loading'
					$j( embedPlayer ).bind('pause', function(){
						callback( 'pause', embedPlayer.id );
					});

					$j( embedPlayer ).bind('play', function(){
						callback( 'play', embedPlayer.id );
					});

					break;
				case 'durationChange':
					// TODO add in duration change support
					break;
				case 'playerUpdatePlayhead':
					$j( embedPlayer ).bind('monitorEvent', function(){
						callback( embedPlayer.currentTime,  embedPlayer.id );
					})
					break;
				case 'entryReady':
					$j( embedPlayer ).bind( 'KalturaSupport.checkMeta', function( event, meta ) {
						callback( meta );
					});
					break;
			}

		},

		/**
		 * emulates kalatura removeJsListener function
		 */
		removeJsListener: function( embedPlayer, eventName, callbackFuncName ){
			//mw.log("KDPMapping:: removeJsListener: " + eventName + ' cb:' + callbackFuncName );
			var callback = window[ callbackFuncName ];
			switch( eventName ){
				case 'volumeChanged':
					$j( embedPlayer ).unbind('volumeChanged');
					break;
				case 'playerStateChange':
					$j( embedPlayer ).unbind('pause');
					$j( embedPlayer ).unbind('play');
					break;
				case 'durationChange':
					// TODO add in duration change support
					break;
				case 'playerUpdatePlayhead':
					$j( embedPlayer).unbind('monitorEvent');
					break;
			}

			callback();

		},

		/**
		 * Master send action list:
		 */
		sendNotification: function( embedPlayer, notificationName, notificationData ){
			switch( notificationName ){
				case 'doPlay':
					embedPlayer.play();
					break;
				case 'doPause':
					embedPlayer.pause();
					break;
				case 'doStop':
					embedPlayer.stop();
					break;
				case 'doSeek':
					// Kaltura doSeek is in seconds rather than percentage:
					var percent = parseFloat( notificationData ) / embedPlayer.getDuration();
					embedPlayer.doSeek( percent );
					break;
				case 'changeVolume':
					embedPlayer.setVolume( parseFloat( notificationData ) );
					// TODO the setVolume should update the interface
					embedPlayer.setInterfaceVolume(  parseFloat( notificationData ) );
					break;
				case 'changeMedia':
					//embedPlayer.getSrcFromApi( notificationData )
					//embedPlayer.switchPlaySrc( parseFloat( notificationData ) );
					break;
			}
		}
	};

	// Setup the KDPMapping
	if( mw.playerManager ){
		window.KDPMapping = new mw.KDPMapping();
	} else {
		mw.log( 'KDPMapping::bind:EmbedPlayerManagerReady');
		$j( mw ).bind( 'EmbedPlayerManagerReady', function(){
			if(!window.KDPMapping ){
				mw.log( "KDPMapping::EmbedPlayerManagerReady" );
				window.KDPMapping = new mw.KDPMapping();
			}
		});
	}

} )( window.mw );<|endoftext|>


<commit_before>zaa.controller("NavController", function($scope, $stateParams, $http, AdminLangService, AdminClassService, MenuService) {

	$scope.id = parseInt($stateParams.navId);

	$scope.isDeleted = false;

	$scope.menuCats = MenuService.cats;

	$scope.navData = {};

    $scope.sidebar = true;

	$http.get('admin/api-cms-nav/detail', { params : { navId : $scope.id }}).success(function(response) {
		$scope.navData = response;
	});

	$scope.$watch(function() { return $scope.navData.is_hidden }, function(n, o) {
		if (o !== undefined) {
			$http.get('admin/api-cms-nav/toggle-hidden', { params : { navId : $scope.navData.id , hiddenStatus : n }}).success(function(response) {
				// send toast
				if (n == 1) {
					Materialize.toast('Die Seite ist nun Unsichtbar.', 2000)
				} else {
					Materialize.toast('Die Seite ist nun Sichtbar.', 2000)
				}
			});
		}
	});

	$scope.$watch(function() { return $scope.navData.cat_id }, function(n, o) {
		if (o != undefined && o != null && n != o) {
			$http.get('admin/api-cms-nav/update-cat', { params : { navId : $scope.navData.id , catId : n }}).success(function(response) {
				MenuService.refresh();
				Materialize.toast('Die Seite wurde der Navigation ' + n + ' zugewiesen.', 2000)
			});

		}
	});

    $scope.trash = function() {
    	if (confirm('your are sure you want to delete this page?')) {
    		$http.get('admin/api-cms-nav/delete', { params : { navId : $scope.navData.id }}).success(function(response) {
    			MenuService.refresh();
    			$scope.isDeleted = true;
    		});
    	}
    };

    $scope.toggleSidebar = function() {
        $scope.sidebar = !$scope.sidebar;
    };

	$scope.AdminClassService = AdminClassService;

	$scope.AdminLangService = AdminLangService;

	$scope.refresh = function() {
		$scope.langs = $scope.AdminLangService.data;
	}

	$scope.refresh();
});

/**
 * @param $scope.lang
 *            from ng-repeat
 */
zaa.controller("NavItemController", function($scope, $http, $timeout, MenuService) {

	$scope.NavController = $scope.$parent;

	$scope.showContainer = false;

	$scope.isTranslated = false;

	$scope.item = [];

	$scope.copy = [];

	$scope.settings = false;

	$scope.reset = function() {
		$scope.copy = angular.copy($scope.item);
	}

	$scope.save = function(data) {

		var headers = {"headers" : { "Content-Type" : "application/x-www-form-urlencoded; charset=UTF-8" }};
		var navItemId = data.id;
		$http.post('admin/api-cms-navitem/update-item?navItemId=' + navItemId, $.param({ title : data.title, rewrite : data.rewrite }), headers).success(function(response) {
			Materialize.toast(' Die Seite «'+data.title+'» wurde aktualisiert.', 2000);
			MenuService.refresh();
			$scope.refresh();
			$scope.toggleSettings();
		}).error(function(e) {
			console.log(e);
		})
	};

	$scope.toggleSettings = function() {
		$scope.reset();
		$scope.settings = !$scope.settings;
	};

	$scope.getItem = function(langId, navId) {
		$scope.showContainer = false;
		$http({
		    url: 'admin/api-cms-navitem/nav-lang-item',
		    method: "GET",
		    params: { langId : langId, navId : navId }
		}).success(function(response) {
			if (response) {
				$scope.item = response;
				$scope.isTranslated = true;
				$timeout(function() {
					$scope.showContainer = true;
				}, 500);
			} else {
				$timeout(function() {
					$scope.showContainer = true;
				}, 500);
			}

			$scope.reset();

		});
	}

	$scope.refresh = function() {
		$scope.getItem($scope.lang.id, $scope.NavController.id);
	}

	$scope.refresh();

});

zaa.controller("NavItemTypePageController", function($scope, $http) {

	$scope.NavItemController = $scope.$parent;

	$scope.container = [];

	$scope.refresh = function() {
		$http({
			url : 'admin/api-cms-navitem/tree',
			method : 'GET',
			params : { navItemPageId : $scope.NavItemController.item.nav_item_type_id }
		}).success(function(response) {
			if ($scope.container.length == 0) {
				$scope.container = response;
			} else {
				// merge new content item to placeholder
				var old_ph = $scope.container.__placeholders;
				var new_ph = response.__placeholders;
				for (var i in old_ph) {
					$scope.container.__placeholders[i]['__nav_item_page_block_items'] = new_ph[i]['__nav_item_page_block_items'];
				}
			}

            for (var i in $scope.container.__placeholders) {
                $scope.container.__placeholders[i]['open'] = false;
            }
		});
	};

	$scope.refreshNested = function(prevId, placeholderVar) {

		$http({
			url : 'admin/api-cms-navitem/reload-placeholder',
			method : 'GET',
			params : { navItemPageId : $scope.NavItemController.item.nav_item_type_id, prevId : prevId, placeholderVar : placeholderVar}
		}).success(function(response) {
			for (var i in $scope.container.__placeholders) {
				var out = $scope.revPlaceholders($scope.container.__placeholders[i], prevId, response);
				if (out !== false ) {
					return;
				}
			}

		});
		/*
		console.log('droppend placeholder', placeholder);
		console.log('current placholders:', $scope.container.__placeholders);
		*/
	}

	/*
	$scope.revPlaceholders = function(placeholders, prevId) {
		console.log('revPlaceholders', placeholders);
		for (var key in placeholders) {
			var tmp = placeholders[key]['prev_id'];
			if (parseInt(prevId) == parseInt(tmp)) {
				//console.log('ok, ist', prevId);
				//return prevId
				return placeholders[key];
			}

			var find = $scope.revFind(placeholders[key], prevId)
			if (find !== false) {
				return find;
			}
		}
		return false;
	}
	*/
	$scope.revPlaceholders = function(placeholder, prevId, replaceContent) {
		//console.log('revPlaceholders', placeholders);
		//for (var key in placeholders) {
			var tmp = placeholder['prev_id'];
			if (parseInt(prevId) == parseInt(tmp)) {
				//console.log('ok, ist', prevId);
				//return prevId
				placeholder['__nav_item_page_block_items'] = replaceContent;
				return true;
			}

			var find = $scope.revFind(placeholder, prevId, replaceContent)
			if (find !== false) {
				return find;
			}
		//}
		return false;
	}

	$scope.revFind = function(placeholder, prevId, replaceContent) {
		//console.log('revFind', placeholder, prevId);
		for (var i in placeholder['__nav_item_page_block_items']) {
			/*
			console.log(placeholder['__nav_item_page_block_items'][i]);
			var rsp = $scope.revPlaceholders(placeholder['__nav_item_page_block_items'][i]['__placeholders'], prevId);
			if (rsp !== false) {
				return rsp;
			}
			*/

			for (var holder in placeholder['__nav_item_page_block_items'][i]['__placeholders']) {
				var rsp = $scope.revPlaceholders(placeholder['__nav_item_page_block_items'][i]['__placeholders'][holder], prevId, replaceContent);
				if (rsp !== false) {
					return rsp;
				}
			}
		}
		return false;
	}

	$scope.refresh();

});

/**
 * @param $scope.placeholder
 *            from ng-repeat
 */
zaa.controller("PagePlaceholderController", function($scope, AdminClassService) {

	$scope.NavItemTypePageController = $scope.$parent;

	$scope.mouseEnter = function() {
		var status = AdminClassService.getClassSpace('onDragStart');
		if (status !== undefined && !$scope.placeholder.open) {
			$scope.placeholder.open = true;
		}
	};
});

/**
 * @param $scope.block
 *            from ng-repeat
 */
zaa.controller("PageBlockEditController", function($scope, $sce, $http, ApiCmsNavItemPageBlockItem, AdminClassService) {

	$scope.onStart = function() {
		$scope.$apply(function() {
			AdminClassService.setClassSpace('onDragStart', 'page--drag-active');
		});
	};

	$scope.safe = function(html) {
		return $sce.trustAsHtml(html);
	}

	$scope.onStop = function() {
		$scope.$apply(function() {
			AdminClassService.setClassSpace('onDragStart', '');
		});
	};

	$scope.$watch(function() { return $scope.block.values }, function(n, o) {
		$scope.data = n;
	});

	$scope.cfgdata = $scope.block.cfgvalues || {};

	$scope.PagePlaceholderController = $scope.$parent;

	$scope.edit = false;

	$scope.toggleEdit = function() {
		/* onclick="$(this).parents('.block').toggleClass('block--edit');" */
		$scope.edit = !$scope.edit;
	};

	$scope.renderTemplate = function(template, dataVars, cfgVars, block, extras) {
		if (template == undefined) {
			return '';
		}
		var template = twig({
		    data: template
		});

		var content = template.render({
			vars : dataVars,
			cfgs : cfgVars,
			block : block,
			extras : extras
		});

		return $sce.trustAsHtml(content);
	};

	$scope.removeBlock = function(block) {
        if (confirm('Block «' + block.name + '» wirklich löschen?')) {
            ApiCmsNavItemPageBlockItem.delete({id: block.id}, function (rsp) {
                $scope.PagePlaceholderController.NavItemTypePageController.refresh();
                Materialize.toast('Block «' + block.name + '» wurde entfernt!', 3000);
            });
        }
	};

	$scope.save = function () {
		ApiCmsNavItemPageBlockItem.update({ id : $scope.block.id }, $.param({json_config_values : JSON.stringify($scope.data), json_config_cfg_values : JSON.stringify($scope.cfgdata) }), function(rsp) {
			Materialize.toast(' Block «'+$scope.block.name+'» wurde aktualisiert.', 2000)
			$scope.edit = false;
			$scope.block.is_dirty = 1;

			$http({
			    url: 'admin/api-cms-navitem/get-block',
			    method: "GET",
			    params: { blockId : $scope.block.id }
			}).success(function(rsp) {
				$scope.block = rsp;
			});

		});
	}

});

/**
 * @TODO HANDLING SORT INDEX OF EACH BLOCK
 */
zaa.controller("DropBlockController", function($scope, ApiCmsNavItemPageBlockItem) {

	$scope.PagePlaceholderController = $scope.$parent;

	$scope.droppedBlock = {};

	$scope.onDrop = function($event, $ui) {
		var sortIndex = $($event.target).data('sortindex');
		var moveBlock = $scope.droppedBlock['vars'] || false;
		if (moveBlock == false) {
			ApiCmsNavItemPageBlockItem.save($.param({ prev_id : $scope.placeholder.prev_id, sort_index : sortIndex, block_id : $scope.droppedBlock.id , placeholder_var : $scope.placeholder.var, nav_item_page_id : $scope.placeholder.nav_item_page_id }), function(rsp) {
				//console.log(rsp, $scope.placeholder.prev_id);
				$scope.PagePlaceholderController.NavItemTypePageController.refreshNested($scope.placeholder.prev_id, $scope.placeholder.var);
				//$scope.PagePlaceholderController.NavItemTypePageController.refresh();
			})
		} else {
			ApiCmsNavItemPageBlockItem.update({ id : $scope.droppedBlock.id }, $.param({
				prev_id : $scope.placeholder.prev_id,
				placeholder_var : $scope.placeholder.var,
				sort_index : sortIndex
			}), function(rsp) {
				$scope.PagePlaceholderController.NavItemTypePageController.refreshNested($scope.placeholder.prev_id, $scope.placeholder.var);
				// console.log(rsp, $scope.placeholder.prev_id);
				//$scope.PagePlaceholderController.NavItemTypePageController.refresh();
			});
		}

	}
});

zaa.controller("DroppableBlocksController", function($scope, $http, AdminClassService, DroppableBlocksService, $sce) {

	$scope.onStart = function() {
		$scope.$apply(function() {
			AdminClassService.setClassSpace('onDragStart', 'page--drag-active');
		});
	}

	$scope.safe = function(html) {
		return $sce.trustAsHtml(html);
	}

	$scope.onStop = function() {
		$scope.$apply(function() {
			AdminClassService.setClassSpace('onDragStart', undefined);
		});
	}

	$scope.DroppableBlocksService = DroppableBlocksService;
});<commit_msg>fixed #189<commit_after>zaa.controller("NavController", function($scope, $stateParams, $http, AdminLangService, AdminClassService, MenuService) {

	$scope.id = parseInt($stateParams.navId);

	$scope.isDeleted = false;

	$scope.menuCats = MenuService.cats;

	$scope.navData = {};

    $scope.sidebar = true;

	$http.get('admin/api-cms-nav/detail', { params : { navId : $scope.id }}).success(function(response) {
		$scope.navData = response;
	});

	$scope.$watch(function() { return $scope.navData.is_hidden }, function(n, o) {
		if (o !== undefined) {
			$http.get('admin/api-cms-nav/toggle-hidden', { params : { navId : $scope.navData.id , hiddenStatus : n }}).success(function(response) {
				// send toast
				if (n == 1) {
					Materialize.toast('Die Seite ist nun Unsichtbar.', 2000)
				} else {
					Materialize.toast('Die Seite ist nun Sichtbar.', 2000)
				}
			});
		}
	});

	$scope.$watch(function() { return $scope.navData.cat_id }, function(n, o) {
		if (o != undefined && o != null && n != o) {
			$http.get('admin/api-cms-nav/update-cat', { params : { navId : $scope.navData.id , catId : n }}).success(function(response) {
				MenuService.refresh();
				Materialize.toast('Die Seite wurde der Navigation ' + n + ' zugewiesen.', 2000)
			});

		}
	});

    $scope.trash = function() {
    	if (confirm('your are sure you want to delete this page?')) {
    		$http.get('admin/api-cms-nav/delete', { params : { navId : $scope.navData.id }}).success(function(response) {
    			MenuService.refresh();
    			$scope.isDeleted = true;
    		});
    	}
    };

    $scope.toggleSidebar = function() {
        $scope.sidebar = !$scope.sidebar;
    };

	$scope.AdminClassService = AdminClassService;

	$scope.AdminLangService = AdminLangService;

	$scope.refresh = function() {
		$scope.langs = $scope.AdminLangService.data;
	}

	$scope.refresh();
});

/**
 * @param $scope.lang
 *            from ng-repeat
 */
zaa.controller("NavItemController", function($scope, $http, $timeout, MenuService) {

	$scope.NavController = $scope.$parent;

	$scope.showContainer = false;

	$scope.isTranslated = false;

	$scope.item = [];

	$scope.copy = [];

	$scope.settings = false;

	$scope.reset = function() {
		$scope.copy = angular.copy($scope.item);
	}

	$scope.save = function(data) {

		var headers = {"headers" : { "Content-Type" : "application/x-www-form-urlencoded; charset=UTF-8" }};
		var navItemId = data.id;
		$http.post('admin/api-cms-navitem/update-item?navItemId=' + navItemId, $.param({ title : data.title, rewrite : data.rewrite }), headers).success(function(response) {
			Materialize.toast(' Die Seite «'+data.title+'» wurde aktualisiert.', 2000);
			MenuService.refresh();
			$scope.refresh();
			$scope.toggleSettings();
		}).error(function(e) {
			console.log(e);
		})
	};

	$scope.toggleSettings = function() {
		$scope.reset();
		$scope.settings = !$scope.settings;
	};

	$scope.getItem = function(langId, navId) {
		$scope.showContainer = false;
		$http({
		    url: 'admin/api-cms-navitem/nav-lang-item',
		    method: "GET",
		    params: { langId : langId, navId : navId }
		}).success(function(response) {
			if (response) {
				$scope.item = response;
				$scope.isTranslated = true;
				$timeout(function() {
					$scope.showContainer = true;
				}, 500);
			} else {
				$timeout(function() {
					$scope.showContainer = true;
				}, 500);
			}

			$scope.reset();

		});
	}

	$scope.refresh = function() {
		$scope.getItem($scope.lang.id, $scope.NavController.id);
	}

	$scope.refresh();

});

zaa.controller("NavItemTypePageController", function($scope, $http) {

	$scope.NavItemController = $scope.$parent;

	$scope.container = [];

	$scope.refresh = function() {
		$http({
			url : 'admin/api-cms-navitem/tree',
			method : 'GET',
			params : { navItemPageId : $scope.NavItemController.item.nav_item_type_id }
		}).success(function(response) {
			if ($scope.container.length == 0) {
				$scope.container = response;
			} else {
				// merge new content item to placeholder
				var old_ph = $scope.container.__placeholders;
				var new_ph = response.__placeholders;
				for (var i in old_ph) {
					$scope.container.__placeholders[i]['__nav_item_page_block_items'] = new_ph[i]['__nav_item_page_block_items'];
				}
			}

            for (var i in $scope.container.__placeholders) {
                $scope.container.__placeholders[i]['open'] = false;
            }
		});
	};

	$scope.refreshNested = function(prevId, placeholderVar) {

		$http({
			url : 'admin/api-cms-navitem/reload-placeholder',
			method : 'GET',
			params : { navItemPageId : $scope.NavItemController.item.nav_item_type_id, prevId : prevId, placeholderVar : placeholderVar}
		}).success(function(response) {
			for (var i in $scope.container.__placeholders) {
				var out = $scope.revPlaceholders($scope.container.__placeholders[i], prevId, placeholderVar, response);
				if (out !== false ) {
					return;
				}
			}

		});
	}
	$scope.revPlaceholders = function(placeholder, prevId, placeholderVar, replaceContent) {
		var tmp = placeholder['prev_id'];
		if (parseInt(prevId) == parseInt(tmp) && placeholderVar == placeholder['var']) {
			placeholder['__nav_item_page_block_items'] = replaceContent;
			return true;
		}

		var find = $scope.revFind(placeholder, prevId, placeholderVar, replaceContent)
		if (find !== false) {
			return find;
		}
		return false;
	}

	$scope.revFind = function(placeholder, prevId, placeholderVar, replaceContent) {
		for (var i in placeholder['__nav_item_page_block_items']) {
			for (var holder in placeholder['__nav_item_page_block_items'][i]['__placeholders']) {
				var rsp = $scope.revPlaceholders(placeholder['__nav_item_page_block_items'][i]['__placeholders'][holder], prevId, placeholderVar, replaceContent);
				if (rsp !== false) {
					return rsp;
				}
			}
		}
		return false;
	}

	$scope.refresh();

});

/**
 * @param $scope.placeholder
 *            from ng-repeat
 */
zaa.controller("PagePlaceholderController", function($scope, AdminClassService) {

	$scope.NavItemTypePageController = $scope.$parent;

	$scope.mouseEnter = function() {
		var status = AdminClassService.getClassSpace('onDragStart');
		if (status !== undefined && !$scope.placeholder.open) {
			$scope.placeholder.open = true;
		}
	};
});

/**
 * @param $scope.block
 *            from ng-repeat
 */
zaa.controller("PageBlockEditController", function($scope, $sce, $http, ApiCmsNavItemPageBlockItem, AdminClassService) {

	$scope.onStart = function() {
		$scope.$apply(function() {
			AdminClassService.setClassSpace('onDragStart', 'page--drag-active');
		});
	};

	$scope.safe = function(html) {
		return $sce.trustAsHtml(html);
	}

	$scope.onStop = function() {
		$scope.$apply(function() {
			AdminClassService.setClassSpace('onDragStart', '');
		});
	};

	$scope.$watch(function() { return $scope.block.values }, function(n, o) {
		$scope.data = n;
	});

	$scope.cfgdata = $scope.block.cfgvalues || {};

	$scope.PagePlaceholderController = $scope.$parent;

	$scope.edit = false;

	$scope.toggleEdit = function() {
		/* onclick="$(this).parents('.block').toggleClass('block--edit');" */
		$scope.edit = !$scope.edit;
	};

	$scope.renderTemplate = function(template, dataVars, cfgVars, block, extras) {
		if (template == undefined) {
			return '';
		}
		var template = twig({
		    data: template
		});

		var content = template.render({
			vars : dataVars,
			cfgs : cfgVars,
			block : block,
			extras : extras
		});

		return $sce.trustAsHtml(content);
	};

	$scope.removeBlock = function(block) {
        if (confirm('Block «' + block.name + '» wirklich löschen?')) {
            ApiCmsNavItemPageBlockItem.delete({id: block.id}, function (rsp) {
                $scope.PagePlaceholderController.NavItemTypePageController.refresh();
                Materialize.toast('Block «' + block.name + '» wurde entfernt!', 3000);
            });
        }
	};

	$scope.save = function () {
		ApiCmsNavItemPageBlockItem.update({ id : $scope.block.id }, $.param({json_config_values : JSON.stringify($scope.data), json_config_cfg_values : JSON.stringify($scope.cfgdata) }), function(rsp) {
			Materialize.toast(' Block «'+$scope.block.name+'» wurde aktualisiert.', 2000)
			$scope.edit = false;
			$scope.block.is_dirty = 1;

			$http({
			    url: 'admin/api-cms-navitem/get-block',
			    method: "GET",
			    params: { blockId : $scope.block.id }
			}).success(function(rsp) {
				$scope.block = rsp;
			});

		});
	}

});

/**
 * @TODO HANDLING SORT INDEX OF EACH BLOCK
 */
zaa.controller("DropBlockController", function($scope, ApiCmsNavItemPageBlockItem) {

	$scope.PagePlaceholderController = $scope.$parent;

	$scope.droppedBlock = {};

	$scope.onDrop = function($event, $ui) {
		var sortIndex = $($event.target).data('sortindex');
		var moveBlock = $scope.droppedBlock['vars'] || false;
		if (moveBlock == false) {
			ApiCmsNavItemPageBlockItem.save($.param({ prev_id : $scope.placeholder.prev_id, sort_index : sortIndex, block_id : $scope.droppedBlock.id , placeholder_var : $scope.placeholder.var, nav_item_page_id : $scope.placeholder.nav_item_page_id }), function(rsp) {
				//console.log(rsp, $scope.placeholder.prev_id);
				$scope.PagePlaceholderController.NavItemTypePageController.refreshNested($scope.placeholder.prev_id, $scope.placeholder.var);
				//$scope.PagePlaceholderController.NavItemTypePageController.refresh();
			})
		} else {
			ApiCmsNavItemPageBlockItem.update({ id : $scope.droppedBlock.id }, $.param({
				prev_id : $scope.placeholder.prev_id,
				placeholder_var : $scope.placeholder.var,
				sort_index : sortIndex
			}), function(rsp) {
				$scope.PagePlaceholderController.NavItemTypePageController.refreshNested($scope.placeholder.prev_id, $scope.placeholder.var);
				// console.log(rsp, $scope.placeholder.prev_id);
				//$scope.PagePlaceholderController.NavItemTypePageController.refresh();
			});
		}

	}
});

zaa.controller("DroppableBlocksController", function($scope, $http, AdminClassService, DroppableBlocksService, $sce) {

	$scope.onStart = function() {
		$scope.$apply(function() {
			AdminClassService.setClassSpace('onDragStart', 'page--drag-active');
		});
	}

	$scope.safe = function(html) {
		return $sce.trustAsHtml(html);
	}

	$scope.onStop = function() {
		$scope.$apply(function() {
			AdminClassService.setClassSpace('onDragStart', undefined);
		});
	}

	$scope.DroppableBlocksService = DroppableBlocksService;
});<|endoftext|>


<commit_before>const {Subject} = require('rxjs')
const {groupBy, mergeMap, tap, map, share, filter, finalize, takeUntil} = require('rxjs/operators')
const {v4: uuid} = require('uuid')
const _ = require('lodash')
const log = require('@sepal/log')
const {initWorker$} = require('./factory')
const Pool = require('./pool')

const pooledWorker = ({concurrency, maxIdleMilliseconds, minIdleCount}) => {
    const workerRequest$ = new Subject()
    const workerResponse$ = new Subject()
    const cancel$ = new Subject()

    const workerPool = Pool({
        create$: ({jobId, jobPath}) => initWorker$(jobId, jobPath),
        onCold: ({jobId}) => log.debug(`Creating worker <${jobId}>`),
        onHot: ({jobId}) => log.debug(`Recycling worker <${jobId}>`),
        onRelease: ({jobId}) => log.trace(`Released worker <${jobId}>`),
        onDispose: ({jobId, item}) => {
            item.dispose()
            log.debug(`Disposed worker <${jobId}>`)
        },
        maxIdleMilliseconds,
        minIdleCount
    })

    const getWorkerInstance$ = (jobName, jobPath) =>
        workerPool.get$({slot: jobName, createArgs: {jobName, jobPath}}).pipe(
            map(({item: worker, release}) => ({worker, release}))
        )

    const submitRequest = ({requestId, jobName, jobPath, args, args$}) =>
        workerRequest$.next({requestId, jobName, jobPath, args, args$})

    const getResponse$ = requestId =>
        workerResponse$.pipe(
            share(),
            filter(({requestId: currentRequestId}) => currentRequestId === requestId),
            map(({result}) => result)
        )

    workerRequest$.pipe(
        groupBy(({jobName}) => jobName),
        mergeMap(group =>
            group.pipe(
                mergeMap(({requestId, jobName, jobPath, args, args$}) =>
                    getWorkerInstance$(jobName, jobPath).pipe(
                        mergeMap(({worker, release}) =>
                            worker.submit$(args, args$).pipe(
                                map(result => ({
                                    requestId,
                                    result
                                })),
                                takeUntil(cancel$.pipe(
                                    filter(({requestId: currentRequestId}) => currentRequestId === requestId),
                                )),
                                finalize(() => release())
                            )
                        )
                    ), null, concurrency
                ),
            )
        )
    ).subscribe(
        response => workerResponse$.next(response)
    )

    return {
        submit$(jobName, jobPath, args, args$) {
            log.trace(`Submitting <${jobName}> to pooled worker`)
            const requestId = uuid()
            submitRequest({requestId, jobName, jobPath, args, args$})
            return getResponse$(requestId).pipe(
                finalize(() => cancel$.next({requestId}))
            )
        }
    }
}

module.exports = pooledWorker
<commit_msg>Cleanup.<commit_after>const {Subject} = require('rxjs')
const {groupBy, mergeMap, map, share, filter, finalize, takeUntil} = require('rxjs/operators')
const {v4: uuid} = require('uuid')
const _ = require('lodash')
const log = require('@sepal/log')
const {initWorker$} = require('./factory')
const Pool = require('./pool')

const PooledWorker = ({concurrency, maxIdleMilliseconds, minIdleCount}) => {
    const workerRequest$ = new Subject()
    const workerResponse$ = new Subject()
    const cancel$ = new Subject()

    const workerPool = Pool({
        create$: ({jobId, jobPath}) => initWorker$(jobId, jobPath),
        onCold: ({jobId}) => log.debug(`Creating worker <${jobId}>`),
        onHot: ({jobId}) => log.debug(`Recycling worker <${jobId}>`),
        onRelease: ({jobId}) => log.trace(`Released worker <${jobId}>`),
        onDispose: ({jobId, item}) => {
            item.dispose()
            log.debug(`Disposed worker <${jobId}>`)
        },
        maxIdleMilliseconds,
        minIdleCount
    })

    const getWorkerInstance$ = (jobName, jobPath) =>
        workerPool.get$({slot: jobName, createArgs: {jobName, jobPath}}).pipe(
            map(({item: worker, release}) => ({worker, release}))
        )

    const submitRequest = ({requestId, jobName, jobPath, args, args$}) =>
        workerRequest$.next({requestId, jobName, jobPath, args, args$})

    const getResponse$ = requestId =>
        workerResponse$.pipe(
            share(),
            filter(({requestId: currentRequestId}) => currentRequestId === requestId),
            map(({result}) => result)
        )

    workerRequest$.pipe(
        groupBy(({jobName}) => jobName),
        mergeMap(group =>
            group.pipe(
                mergeMap(({requestId, jobName, jobPath, args, args$}) =>
                    getWorkerInstance$(jobName, jobPath).pipe(
                        mergeMap(({worker, release}) =>
                            worker.submit$(args, args$).pipe(
                                map(result => ({
                                    requestId,
                                    result
                                })),
                                takeUntil(cancel$.pipe(
                                    filter(({requestId: currentRequestId}) => currentRequestId === requestId),
                                )),
                                finalize(() => release())
                            )
                        )
                    ), null, concurrency
                ),
            )
        )
    ).subscribe(
        response => workerResponse$.next(response)
    )

    return {
        submit$(jobName, jobPath, args, args$) {
            log.trace(`Submitting <${jobName}> to pooled worker`)
            const requestId = uuid()
            submitRequest({requestId, jobName, jobPath, args, args$})
            return getResponse$(requestId).pipe(
                finalize(() => cancel$.next({requestId}))
            )
        }
    }
}

module.exports = PooledWorker
<|endoftext|>


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

    angular
        .module('dpMap')
        .factory('panning', panningFactory);

    panningFactory.$inject = ['$rootScope', 'store', 'ACTIONS'];

    function panningFactory ($rootScope, store, ACTIONS) {
        return {
            initialize: initialize,
            panTo: panTo
        };

        function initialize (leafletMap) {
            leafletMap.on('moveend', function () {
                $rootScope.$applyAsync(function () {
                    store.dispatch({
                        type: ACTIONS.MAP_PAN,
                        payload: getCurrentLocation(leafletMap)
                    });
                });
            });
        }

        function panTo (leafletMap, location) {
            //Prevent infinite loop
            if (!angular.equals(location, getCurrentLocation(leafletMap))) {
                leafletMap.panTo(location);
            }
        }

        function getCurrentLocation (leafletMap) {
            var center = leafletMap.getCenter();

            return [center.lat, center.lng];
        }
    }
})();<commit_msg>Added map panning. It listens to the moveend event and will fire the MAP_PAN reducer. And it listens to the state through dp-map to update the location when needed.<commit_after>(function () {
    'use strict';

    angular
        .module('dpMap')
        .factory('panning', panningFactory);

    panningFactory.$inject = ['$rootScope', 'store', 'ACTIONS'];

    function panningFactory ($rootScope, store, ACTIONS) {
        return {
            initialize: initialize,
            panTo: panTo
        };

        function initialize (leafletMap) {
            leafletMap.on('moveend', function () {
                $rootScope.$applyAsync(function () {
                    store.dispatch({
                        type: ACTIONS.MAP_PAN,
                        payload: getCurrentLocation(leafletMap)
                    });
                });
            });
        }

        function panTo (leafletMap, location) {
            //Prevent infinite loop; the 'moveend' event triggers panTo, and panning always triggers a 'moveend' event.
            if (!angular.equals(location, getCurrentLocation(leafletMap))) {
                leafletMap.panTo(location);
            }
        }

        function getCurrentLocation (leafletMap) {
            var center = leafletMap.getCenter();

            return [center.lat, center.lng];
        }
    }
})();<|endoftext|>


<commit_before>/* Module: BridgeDiscordIRC -- This module was designed to bridge a multi-channel Discord server with a single IRC channel. */

var Module = require('./Module.js');
var cd = require('color-difference');
var emoji = require('emojione');

emoji.ascii = true;
delete emoji.asciiList['d:'];

class ModBridgeDiscordIRC extends Module {

    get isMultiInstanceable() { return true; }

    get requiredParams() { return [
        'envdiscord',           //Name of the Discord environment
        'defaultdiscordchannel',    //Name of a Discord channel the bot will treat as default
        'envirc',               //Name of the IRC environment
        'ircchannel'            //Name of an IRC channel the bot will join (including prefix)
    ]; }

    constructor(name) {
        super('BridgeDiscordIRC', name);
    }

    get irc() {
        return this.env(this.param('envirc'));
    }

    get discord() {
        return this.env(this.param('envdiscord'));
    }

    initialize(envs, mods, moduleRequest) {
        if (!super.initialize(envs, mods, moduleRequest)) return false;

        //Register callbacks

        this.irc.registerOnMessage(this.onIrcMessage, this);
        this.discord.registerOnMessage(this.onDiscordMessage, this);

        return true;
    }

    // # Module code below this line #

    //Event handlers

    onIrcMessage(env, type, message, authorid, channelid, rawobject) {

        var target = null;

        var directedmessage = /^\[#([a-zA-Z0-9]+)\] (.+)/.exec(message);
        if (directedmessage) {
            target = directedmessage[1];
            message = directedmessage[2];
        }

        var bold = null;
        var und = null;
        var ita = null;
        var order = [];
        var finalmsg = message.replace(/([0-9]{1,2}(,[0-9]{1,2})?)?/g, "").replace(//g, "") + "";
        for (var i = 0; i < finalmsg.length; i++) {
            if (finalmsg[i] == "") {
                if (und === null) {
                    und = i;
                    order.push('und');
                } else {
                    finalmsg = finalmsg.slice(0, und) + "__" + finalmsg.slice(und + 1, i) + "__" + finalmsg.slice(i + 1);
                    und = null;
                    i += 2;
                    order.splice(order.indexOf('und'), 1);
                }
            } else if (finalmsg[i] == "") {
                if (bold === null) {
                    bold = i;
                    order.push('bold');
                } else {
                    finalmsg = finalmsg.slice(0, bold) + "**" + finalmsg.slice(bold + 1, i) + "**" + finalmsg.slice(i + 1);
                    bold = null;
                    i += 2;
                    order.splice(order.indexOf('bold'), 1);
                }
            } else if (finalmsg[i] == "") {
                if (ita === null) {
                    ita = i;
                    order.push('ita');
                } else {
                    finalmsg = finalmsg.slice(0, ita) + "*" + finalmsg.slice(ita + 1, i) + "*" + finalmsg.slice(i + 1);
                    ita = null;
                    order.splice(order.indexOf('ita'), 1);
                }
            } else if (finalmsg[i] == "") {
                var insert = '';
                var offset = 0;
                var next = null;
                while (next = order.pop()) {
                    if (next == 'ita' && ita !== null) {
                        finalmsg = finalmsg.slice(0, ita) + "*" + finalmsg.slice(ita + 1);
                        insert += '*';
                    }
                    if (next == 'bold' && bold !== null) {
                        finalmsg = finalmsg.slice(0, bold) + "**" + finalmsg.slice(bold + 1);
                        insert += '**';
                        offset += 1;
                    }
                    if (next == 'und' && und !== null) {
                        finalmsg = finalmsg.slice(0, und) + "__" + finalmsg.slice(und + 1);
                        insert += '__';
                        offset += 1;
                    }
                }
                finalmsg = finalmsg.slice(0, i + offset) + insert + finalmsg.slice(i + offset + 1);
                i += offset + insert.length;
                bold = null;
                und = null;
                ita = null;
            }
        }

        finalmsg = finalmsg.replace(/@(([^ #]+)(#[0-9]{4})?)/, (match, userornick) => {
            var refid = this.discord.displayNameToId(userornick);
            if (refid) return "<@" + refid + ">";
            return match;
        });

        finalmsg = finalmsg.replace(/^([^:]+): /, (match, userornick) => {
            var refid = this.discord.displayNameToId(userornick);
            if (refid) return "<@" + refid + ">";
            return match;
        });

        finalmsg = emoji.shortnameToUnicode(finalmsg);

        if (type == "action") {
            this.discord.msg(target, "_* `" + env.idToDisplayName(authorid) + "` " + finalmsg + "_");
        } else if (type == "regular") {
            this.discord.msg(target, "`<" + env.idToDisplayName(authorid) + ">` " + finalmsg);
        }
    }

    onDiscordMessage(env, type, message, authorid, channelid, rawobject) {

        var server = env.server;
        var finalmsg = message;

        var action = false;

        var authorname = env.idToDisplayName(authorid);

        var roles = server.roles.array();
        for (let role of roles) {
            if (rawobject.member.roles.find('id', role.id)) {
                authorname = "" + closestTtyColor(role.hexColor) + authorname + "";
                break;
            }
        }

        finalmsg = finalmsg.replace(/<@!?([0-9]+)>/g, (match, id) => {
            var user = server.members.find("id", id);
            if (!user) return "";
            return "@" + (user.nickname ? user.nickname : user.username);
        });

        finalmsg = finalmsg.replace(/<#([0-9]+)>/g, (match, id) => {
            var chan = server.channels.find("id", id);
            if (!chan) return "";
            return "#" + chan.name;
        });

        action = !!/^_[^_](.*[^_])?_$/.exec(finalmsg);

        finalmsg = finalmsg.replace(/__(.*?)__/g, "$1").replace(/\*\*(.*?)\*\*/g, "$1").replace(/\*(.*?)\*/g, "$1").replace(/_(.*?)_/g, "$1");
        finalmsg = emoji.shortnameToAscii(emoji.toShort(finalmsg));

        var lines = finalmsg.split("\n");

        for (let line of lines) {
            if (action) {
                line = '* ' + authorname + " " + line;
            } else {
                line = '(' + authorname + ") " + line;
            }

            if (rawobject.channel.name != this.param('defaultdiscordchannel')) {
                line = "[#" + rawobject.channel.name + "] " + line;
            }

            if (type == "regular") {
                this.irc.msg(this.param('ircchannel'), line);
            }
        }

    }

}

module.exports = ModBridgeDiscordIRC;

//Auxiliary

var colormap = [
    "#FFFFFF",
    "#000000",
    "#00007F",
    "#009300",
    "#FF0000",
    "#7F0000",
    "#9C009C",
    "#FC7F00",
    "#FFFF00",
    "#00FC00",
    "#009393",
    "#00FFFF",
    "#0000FC",
    "#FF00FF",
    "#7F7F7F",
    "#D2D2D2"
];

function closestTtyColor(hexrgb) {
    var distance = 101;
    var color = 0;
    for (var i = 0; i < colormap.length; i++) {
        var r = cd.compare(hexrgb, colormap[i]);
        if (r < distance) {
            distance = r;
            color = i;
        }
    }
    color = color.toString();
    if (color.length < 2) color = "0" + color;
    return color;
}
<commit_msg>Sort manually<commit_after>/* Module: BridgeDiscordIRC -- This module was designed to bridge a multi-channel Discord server with a single IRC channel. */

var Module = require('./Module.js');
var cd = require('color-difference');
var emoji = require('emojione');

emoji.ascii = true;
delete emoji.asciiList['d:'];

class ModBridgeDiscordIRC extends Module {

    get isMultiInstanceable() { return true; }

    get requiredParams() { return [
        'envdiscord',           //Name of the Discord environment
        'defaultdiscordchannel',    //Name of a Discord channel the bot will treat as default
        'envirc',               //Name of the IRC environment
        'ircchannel'            //Name of an IRC channel the bot will join (including prefix)
    ]; }

    constructor(name) {
        super('BridgeDiscordIRC', name);
    }

    get irc() {
        return this.env(this.param('envirc'));
    }

    get discord() {
        return this.env(this.param('envdiscord'));
    }

    initialize(envs, mods, moduleRequest) {
        if (!super.initialize(envs, mods, moduleRequest)) return false;

        //Register callbacks

        this.irc.registerOnMessage(this.onIrcMessage, this);
        this.discord.registerOnMessage(this.onDiscordMessage, this);

        return true;
    }

    // # Module code below this line #

    //Event handlers

    onIrcMessage(env, type, message, authorid, channelid, rawobject) {

        var target = null;

        var directedmessage = /^\[#([a-zA-Z0-9]+)\] (.+)/.exec(message);
        if (directedmessage) {
            target = directedmessage[1];
            message = directedmessage[2];
        }

        var bold = null;
        var und = null;
        var ita = null;
        var order = [];
        var finalmsg = message.replace(/([0-9]{1,2}(,[0-9]{1,2})?)?/g, "").replace(//g, "") + "";
        for (var i = 0; i < finalmsg.length; i++) {
            if (finalmsg[i] == "") {
                if (und === null) {
                    und = i;
                    order.push('und');
                } else {
                    finalmsg = finalmsg.slice(0, und) + "__" + finalmsg.slice(und + 1, i) + "__" + finalmsg.slice(i + 1);
                    und = null;
                    i += 2;
                    order.splice(order.indexOf('und'), 1);
                }
            } else if (finalmsg[i] == "") {
                if (bold === null) {
                    bold = i;
                    order.push('bold');
                } else {
                    finalmsg = finalmsg.slice(0, bold) + "**" + finalmsg.slice(bold + 1, i) + "**" + finalmsg.slice(i + 1);
                    bold = null;
                    i += 2;
                    order.splice(order.indexOf('bold'), 1);
                }
            } else if (finalmsg[i] == "") {
                if (ita === null) {
                    ita = i;
                    order.push('ita');
                } else {
                    finalmsg = finalmsg.slice(0, ita) + "*" + finalmsg.slice(ita + 1, i) + "*" + finalmsg.slice(i + 1);
                    ita = null;
                    order.splice(order.indexOf('ita'), 1);
                }
            } else if (finalmsg[i] == "") {
                var insert = '';
                var offset = 0;
                var next = null;
                while (next = order.pop()) {
                    if (next == 'ita' && ita !== null) {
                        finalmsg = finalmsg.slice(0, ita) + "*" + finalmsg.slice(ita + 1);
                        insert += '*';
                    }
                    if (next == 'bold' && bold !== null) {
                        finalmsg = finalmsg.slice(0, bold) + "**" + finalmsg.slice(bold + 1);
                        insert += '**';
                        offset += 1;
                    }
                    if (next == 'und' && und !== null) {
                        finalmsg = finalmsg.slice(0, und) + "__" + finalmsg.slice(und + 1);
                        insert += '__';
                        offset += 1;
                    }
                }
                finalmsg = finalmsg.slice(0, i + offset) + insert + finalmsg.slice(i + offset + 1);
                i += offset + insert.length;
                bold = null;
                und = null;
                ita = null;
            }
        }

        finalmsg = finalmsg.replace(/@(([^ #]+)(#[0-9]{4})?)/, (match, userornick) => {
            var refid = this.discord.displayNameToId(userornick);
            if (refid) return "<@" + refid + ">";
            return match;
        });

        finalmsg = finalmsg.replace(/^([^:]+): /, (match, userornick) => {
            var refid = this.discord.displayNameToId(userornick);
            if (refid) return "<@" + refid + ">";
            return match;
        });

        finalmsg = emoji.shortnameToUnicode(finalmsg);

        if (type == "action") {
            this.discord.msg(target, "_* `" + env.idToDisplayName(authorid) + "` " + finalmsg + "_");
        } else if (type == "regular") {
            this.discord.msg(target, "`<" + env.idToDisplayName(authorid) + ">` " + finalmsg);
        }
    }

    onDiscordMessage(env, type, message, authorid, channelid, rawobject) {

        var server = env.server;
        var finalmsg = message;

        var action = false;

        var authorname = env.idToDisplayName(authorid);

        var roles = server.roles.array().sort((a, b) => (b.position - a.position));
        for (let role of roles) {
            if (rawobject.member.roles.find('id', role.id)) {
                authorname = "" + closestTtyColor(role.hexColor) + authorname + "";
                break;
            }
        }

        finalmsg = finalmsg.replace(/<@!?([0-9]+)>/g, (match, id) => {
            var user = server.members.find("id", id);
            if (!user) return "";
            return "@" + (user.nickname ? user.nickname : user.username);
        });

        finalmsg = finalmsg.replace(/<#([0-9]+)>/g, (match, id) => {
            var chan = server.channels.find("id", id);
            if (!chan) return "";
            return "#" + chan.name;
        });

        action = !!/^_[^_](.*[^_])?_$/.exec(finalmsg);

        finalmsg = finalmsg.replace(/__(.*?)__/g, "$1").replace(/\*\*(.*?)\*\*/g, "$1").replace(/\*(.*?)\*/g, "$1").replace(/_(.*?)_/g, "$1");
        finalmsg = emoji.shortnameToAscii(emoji.toShort(finalmsg));

        var lines = finalmsg.split("\n");

        for (let line of lines) {
            if (action) {
                line = '* ' + authorname + " " + line;
            } else {
                line = '(' + authorname + ") " + line;
            }

            if (rawobject.channel.name != this.param('defaultdiscordchannel')) {
                line = "[#" + rawobject.channel.name + "] " + line;
            }

            if (type == "regular") {
                this.irc.msg(this.param('ircchannel'), line);
            }
        }

    }

}

module.exports = ModBridgeDiscordIRC;

//Auxiliary

var colormap = [
    "#FFFFFF",
    "#000000",
    "#00007F",
    "#009300",
    "#FF0000",
    "#7F0000",
    "#9C009C",
    "#FC7F00",
    "#FFFF00",
    "#00FC00",
    "#009393",
    "#00FFFF",
    "#0000FC",
    "#FF00FF",
    "#7F7F7F",
    "#D2D2D2"
];

function closestTtyColor(hexrgb) {
    var distance = 101;
    var color = 0;
    for (var i = 0; i < colormap.length; i++) {
        var r = cd.compare(hexrgb, colormap[i]);
        if (r < distance) {
            distance = r;
            color = i;
        }
    }
    color = color.toString();
    if (color.length < 2) color = "0" + color;
    return color;
}
<|endoftext|>