<commit_before>'use strict';

    var callButton = document.getElementById('callButton');
    //var hangupButton = document.getElementById('hangupButton');
    callButton.disabled = false;
    //hangupButton.disabled = true;
    callButton.onclick = call;
    //hangupButton.onclick = hangup;

    var startTime;
    var localVideo = document.getElementById('localVideo');
    var remoteVideo = document.getElementById('remoteVideo');

    var localStream;
    var connection;

    var sdpConstraints = {
        'mandatory': {
            'OfferToReceiveAudio': false,
            'OfferToReceiveVideo': true
        }
    };

    localVideo.addEventListener('loadedmetadata', function () {
        trace('Local video currentSrc: ' + this.currentSrc +
          ', videoWidth: ' + this.videoWidth +
          'px,  videoHeight: ' + this.videoHeight + 'px');
    });

    remoteVideo.addEventListener('loadedmetadata', function () {
        trace('Remote video currentSrc: ' + this.currentSrc +
          ', videoWidth: ' + this.videoWidth +
          'px,  videoHeight: ' + this.videoHeight + 'px');
    });

    remoteVideo.onresize = function () {
        trace('Remote video size changed to ' +
          remoteVideo.videoWidth + 'x' + remoteVideo.videoHeight);
        // We'll use the first onsize callback as an indication that video has started playing out.
        if (startTime) {
            var elapsedTime = window.performance.now() - startTime;
            trace('Setup time: ' + elapsedTime.toFixed(3) + 'ms');
            startTime = null;
        }
    };

function start() {
  // Call into getUserMedia via the polyfill (adapter.js).
  getUserMedia({
      audio: true,
      video: true
    }, gotStream,
    function(e) {
        //alert('getUserMedia() error: ' + e.name);
        alert('Sorry, you web cam is absent or unavailable');
        callButton.disabled = true;
    });
  var servers = null;
  connection = new RTCPeerConnection(servers);
  trace('Created connection object');
  connection.onicecandidate = function (e) {
      chat.server.iceCandidate(JSON.stringify({ "candidate": e.candidate }));
  };
  connection.onaddstream = function (e) {
      // Call the polyfill wrapper to attach the media stream to this element.
      attachMediaStream(remoteVideo, e.stream);
      trace('received remote stream');
  };
}

function call() {
  callButton.disabled = true;
  //hangupButton.disabled = false;
  trace('Starting call');
  startTime = window.performance.now();
  var videoTracks = localStream.getVideoTracks();
  var audioTracks = localStream.getAudioTracks();
  if (videoTracks.length > 0) {
    trace('Using video device: ' + videoTracks[0].label);
  }
  if (audioTracks.length > 0) {
    trace('Using audio device: ' + audioTracks[0].label);
  }

  if (localStream != null) {
      connection.addStream(localStream);
      trace('Added local stream to connection');
  }

  trace('connection createOffer start');
  connection.createOffer(onCreateOfferSuccess, onCreateSessionDescriptionError);
}

function answer(message) {
    trace('send answer ' + message.sdp);
    connection.setRemoteDescription(new RTCSessionDescription(message.sdp), function () {
        trace('setRemoteDescription');
        if (localStream != null) {
            connection.addStream(localStream);
        }
            connection.createAnswer(function (desc) {
                connection.setLocalDescription(desc, function () {
                    chat.server.answer(JSON.stringify({ "sdp": desc}));
                });
            });
    });
}

function addIceCandidate(message) {
    if (message.candidate != null) {
        trace('add ice candidate');
        connection.addIceCandidate(new RTCIceCandidate(message.candidate));
    }
}

function getAnswer(message) {
    if (message.sdp != null) {
        trace('get answer');
        connection.setRemoteDescription(new RTCSessionDescription(message.sdp));
    }
}

function gotStream(stream) {
    trace('Received local stream');
    // Call the polyfill wrapper to attach the media stream to this element.
    attachMediaStream(localVideo, stream);
    localStream = stream;
    callButton.disabled = false;
}

function onCreateSessionDescriptionError(error) {
  trace('Failed to create session description: ' + error.toString());
}

function onCreateOfferSuccess(desc) {
    trace('Offer created');
  trace('setLocalDescription start');
  connection.setLocalDescription(desc, function () {
    chat.server.offer(JSON.stringify({ "sdp": desc }));
    onSetLocalSuccess(connection);
  });
}

function onSetLocalSuccess(connection) {
  trace(' setLocalDescription complete');
}

function onSetRemoteSuccess(connection) {
  trace(' setRemoteDescription complete');
}

function onCreateAnswerSuccess(desc) {
    trace('Answer from pc2:\n' + desc.sdp);
    trace('pc1 setRemoteDescription start');
  trace('pc2 setLocalDescription start');
  connection.setLocalDescription(desc, function () {
      onSetLocalSuccess(connection);
  });
}

function onAddIceCandidateSuccess(connection) {
  trace(' addIceCandidate success');
}

function onAddIceCandidateError(connection, error) {
  trace(' failed to add ICE Candidate: ' + error.toString());
}

//function hangup() {
//  trace('Ending call');
//  connection.close();
//  connection = null;
//  hangupButton.disabled = true;
//  callButton.disabled = false;
//}
<commit_msg>stun server<commit_after>'use strict';

    var callButton = document.getElementById('callButton');
    //var hangupButton = document.getElementById('hangupButton');
    callButton.disabled = false;
    //hangupButton.disabled = true;
    callButton.onclick = call;
    //hangupButton.onclick = hangup;

    var startTime;
    var localVideo = document.getElementById('localVideo');
    var remoteVideo = document.getElementById('remoteVideo');

    var localStream;
    var connection;

    var sdpConstraints = {
        'mandatory': {
            'OfferToReceiveAudio': false,
            'OfferToReceiveVideo': true
        }
    };

    localVideo.addEventListener('loadedmetadata', function () {
        trace('Local video currentSrc: ' + this.currentSrc +
          ', videoWidth: ' + this.videoWidth +
          'px,  videoHeight: ' + this.videoHeight + 'px');
    });

    remoteVideo.addEventListener('loadedmetadata', function () {
        trace('Remote video currentSrc: ' + this.currentSrc +
          ', videoWidth: ' + this.videoWidth +
          'px,  videoHeight: ' + this.videoHeight + 'px');
    });

    remoteVideo.onresize = function () {
        trace('Remote video size changed to ' +
          remoteVideo.videoWidth + 'x' + remoteVideo.videoHeight);
        // We'll use the first onsize callback as an indication that video has started playing out.
        if (startTime) {
            var elapsedTime = window.performance.now() - startTime;
            trace('Setup time: ' + elapsedTime.toFixed(3) + 'ms');
            startTime = null;
        }
    };

function start() {
  // Call into getUserMedia via the polyfill (adapter.js).
  getUserMedia({
      audio: true,
      video: true
    }, gotStream,
    function(e) {
        //alert('getUserMedia() error: ' + e.name);
        alert('Sorry, you web cam is absent or unavailable');
        callButton.disabled = true;
    });
  //var servers = null;
  //var servers = { 'iceServers': [{ 'url': 'stun:stun.l.google.com:19302' }] };
  var servers = { 'iceServers': [{ 'url': 'stun:74.125.142.127:19302' }] };
  //var  _iceServers = [{ url: 'stun:74.125.142.127:19302' }], // stun.l.google.com - Firefox does not support DNS names.
  connection = new RTCPeerConnection(servers);
  //connection = new RTCPeerConnection({ iceServers: _iceServers });
  trace('Created connection object');
  connection.onicecandidate = function (e) {
      chat.server.iceCandidate(JSON.stringify({ "candidate": e.candidate }));
  };
  connection.onaddstream = function (e) {
      // Call the polyfill wrapper to attach the media stream to this element.
      attachMediaStream(remoteVideo, e.stream);
      trace('received remote stream');
  };
}

function call() {
  callButton.disabled = true;
  //hangupButton.disabled = false;
  trace('Starting call');
  startTime = window.performance.now();
  var videoTracks = localStream.getVideoTracks();
  var audioTracks = localStream.getAudioTracks();
  if (videoTracks.length > 0) {
    trace('Using video device: ' + videoTracks[0].label);
  }
  if (audioTracks.length > 0) {
    trace('Using audio device: ' + audioTracks[0].label);
  }

  if (localStream != null) {
      connection.addStream(localStream);
      trace('Added local stream to connection');
  }

  trace('connection createOffer start');
  connection.createOffer(onCreateOfferSuccess, onCreateSessionDescriptionError);
}

function answer(message) {
    trace('send answer ' + message.sdp);
    connection.setRemoteDescription(new RTCSessionDescription(message.sdp), function () {
        trace('setRemoteDescription');
        if (localStream != null) {
            connection.addStream(localStream);
        }
            connection.createAnswer(function (desc) {
                connection.setLocalDescription(desc, function () {
                    chat.server.answer(JSON.stringify({ "sdp": desc}));
                });
            });
    });
}

function addIceCandidate(message) {
    if (message.candidate != null) {
        trace('add ice candidate');
        connection.addIceCandidate(new RTCIceCandidate(message.candidate));
    }
}

function getAnswer(message) {
    if (message.sdp != null) {
        trace('get answer');
        connection.setRemoteDescription(new RTCSessionDescription(message.sdp));
    }
}

function gotStream(stream) {
    trace('Received local stream');
    // Call the polyfill wrapper to attach the media stream to this element.
    attachMediaStream(localVideo, stream);
    localStream = stream;
    callButton.disabled = false;
}

function onCreateSessionDescriptionError(error) {
  trace('Failed to create session description: ' + error.toString());
}

function onCreateOfferSuccess(desc) {
    trace('Offer created');
  trace('setLocalDescription start');
  connection.setLocalDescription(desc, function () {
    chat.server.offer(JSON.stringify({ "sdp": desc }));
    onSetLocalSuccess(connection);
  });
}

function onSetLocalSuccess(connection) {
  trace(' setLocalDescription complete');
}

function onSetRemoteSuccess(connection) {
  trace(' setRemoteDescription complete');
}

function onCreateAnswerSuccess(desc) {
    trace('Answer from pc2:\n' + desc.sdp);
    trace('pc1 setRemoteDescription start');
  trace('pc2 setLocalDescription start');
  connection.setLocalDescription(desc, function () {
      onSetLocalSuccess(connection);
  });
}

function onAddIceCandidateSuccess(connection) {
  trace(' addIceCandidate success');
}

function onAddIceCandidateError(connection, error) {
  trace(' failed to add ICE Candidate: ' + error.toString());
}

//function hangup() {
//  trace('Ending call');
//  connection.close();
//  connection = null;
//  hangupButton.disabled = true;
//  callButton.disabled = false;
//}
<|endoftext|>


<commit_before>module.exports = function (context, myTimer) {
    var timeStamp = new Date().toISOString();

    if(myTimer.isPastDue)
    {
        context.log('Node.js is running late!');
    }
    context.log('Node.js timer trigger function ran!', timeStamp);

    context.done();
};<commit_msg>notify rainfall forecast<commit_after>
var http = require("http");
var https = require("https");
var querystring = require("querystring");
var url = require("url");

function make_url(lon, lat)
{
    var yahoo_weather_api_url = "http://weather.olp.yahooapis.jp/v1/place?"
    var params = {
        "output"      : "json",
        "past"        : "1",
        "interval"    : "5",
        "coordinates" : lon + "," + lat,
        "appid"       : process.env.YAHOO_APP_ID
    };
    return yahoo_weather_api_url + querystring.stringify(params);
}

function get_yahoo_weather_data(lon, lat) {
    return new Promise((resolve, reject) => {
        http.get(make_url(lon, lat), res => {
            var body = '';
            res.on('data', chunk => {
                body += chunk;
            });
            res.on('end', () => {
                resolve(JSON.parse(body));
            });
        }).on('error', e => {
            reject(e);
        });
    });
}

function get_rainfall_data(data) {
    return data.Feature[0].Property.WeatherList.Weather;
}

function get_rainfall_last_result(data) {
    var w = data.filter(w => w["Type"] == "observation");
    return w[w.length - 1];
}

function make_readable_date(date)
{
    return parseInt(date.slice(8, 10)) + ":" + date.slice(10, 12);
}

function make_line_rainfall_forecast_message(weather)
{
    return weather["Rainfall"] ? [
        {
            "type" : "text",
            "text" : [make_readable_date(weather.Date) + " 雨が降りそうです(" + weather["Rainfall"] + "mm/h)", "yjweather://Yahoo!天気を開く"].join("\n")
        }
    ] : [
        {
            "type" : "text",
            "text" : [make_readable_date(weather.Date) + " 雨が止みそうです", "yjweather://Yahoo!天気を開く"].join("\n")
        }
    ];
}

function push_line(to, messages)
{
    return new Promise((resolve,reject) => {
        var post_data = JSON.stringify({
            "to" : to,
            "messages" : messages
        });

        var parse_url = url.parse("https://api.line.me/v2/bot/message/push");
        var post_options = {
            host: parse_url.host,
            path: parse_url.path,
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'Authorization' : 'Bearer {' + process.env.LINE_CHANNEL_ACCESS_TOKEN + '}',
                'Content-Length': Buffer.byteLength(post_data)
            }
        };

        var post_req = https.request(post_options, res => {
            var body = "";
            res.setEncoding('utf8');
            res.on('data', chunk => {
                body += chunk;
            });
            res.on('end', () => {
                resolve(body);
            })
            res.on('error', err => {
                reject(err);
            })
        });

        post_req.write(post_data);
        post_req.end();
    });
}

function is_rainfall_now(data)
{
    var observation = data.filter(w => w["Type"] == "observation" );
    return observation[observation.length - 1]["Rainfall"] != 0 ? true : false;
}

function will_start_rainfall(data)
{
    var forecast = data.filter(w => w["Type"] == "forecast" );
    for (var i = 1; i < 7; i++) {
        if (forecast[i]["Rainfall"]) return forecast[i];
    }
    return null;
}

function will_stop_rainfall(data)
{
    var forecast = data.filter(w => w["Type"] == "forecast" );
    var rain_stop = null;
    for (var i = 6; i > 0; i--) {
        if (forecast[i]["Rainfall"] == 0) rain_stop = forecast[i];
    }
    return rain_stop;
}

module.exports = function (context, myTimer) {
    var timeStamp = new Date().toISOString();

    if(myTimer.isPastDue)
    {
        context.log('Node.js is running late!');
    }
    context.log('Node.js timer trigger function ran!', timeStamp);

    var lon = process.env.LONGITUDE;
    var lat = process.env.LATITUDE;

    get_yahoo_weather_data(lon, lat).then(data => {
        return get_rainfall_data(data);
    }).then(data => {
        return is_rainfall_now(data) ? will_stop_rainfall(data) : will_start_rainfall(data);
    }).then(data => {
        return data ? make_line_rainfall_forecast_message(data) : null
    }).then(messages => {
        return (messages && messages.length) ? push_line(process.env.LINE_PUSH_TO, messages) : null;
    }).then(result => {
        context.log(result);
        context.done();
    }).catch(err => {
        context.log(err);
        context.done();
    });
};

if (require.main === module) {

    var lon = "139.753945";
    var lat = "35.683801";

    var context = {
        log : console.log,
        done: () => {}
    };

    get_yahoo_weather_data(lon, lat).then(data => {
        return get_rainfall_data(data);
    }).then(data => {
//      data = make_dummy_rainfall_data(0, 1);
//      data = make_dummy_rainfall_data(1, 0);
        if (is_rainfall_now(data)) {
            return will_stop_rainfall(data);
        }
        else {
            return will_start_rainfall(data);
        }
    }).then(data => {
        return data ? make_line_rainfall_forecast_message(data) : null
    }).then(messages => {
        return (messages && messages.length) ? push_line(process.env.LINE_PUSH_TO, messages) : null;
    }).then(result => {
        context.log(result);
        context.done();
    }).catch(err => {
        context.log(err);
        context.done();
    });

    context.log(is_rainfall_now(make_dummy_rainfall_data(0, 0)) == false);
    context.log(is_rainfall_now(make_dummy_rainfall_data(1, 0)) == true);

    context.log(will_start_rainfall(make_dummy_rainfall_data(0, 0)) == null);
    context.log(will_start_rainfall(make_dummy_rainfall_data(0, 1)) != null);

    context.log(will_stop_rainfall(make_dummy_rainfall_data(1, 1)) == null);
    context.log(will_stop_rainfall(make_dummy_rainfall_data(1, 0)) != null);

    var rain_fall = will_start_rainfall(make_dummy_rainfall_data(0, 1));
    context.log(make_line_rainfall_forecast_message(rain_fall));

    var rain_fall = will_stop_rainfall(make_dummy_rainfall_data(1, 0));
    context.log(make_line_rainfall_forecast_message(rain_fall));
}

function make_dummy_rainfall_data(a, b)
{
    return [
        { Type: 'observation', Date: '201610240000', Rainfall: 0 },
        { Type: 'observation', Date: '201610240005', Rainfall: 0 },
        { Type: 'observation', Date: '201610240010', Rainfall: 0 },
        { Type: 'observation', Date: '201610240015', Rainfall: 0 },
        { Type: 'observation', Date: '201610240020', Rainfall: 0 },
        { Type: 'observation', Date: '201610240025', Rainfall: 0 },
        { Type: 'observation', Date: '201610240030', Rainfall: 0 },
        { Type: 'observation', Date: '201610240035', Rainfall: 0 },
        { Type: 'observation', Date: '201610240040', Rainfall: 0 },
        { Type: 'observation', Date: '201610240045', Rainfall: 0 },
        { Type: 'observation', Date: '201610240050', Rainfall: 0 },
        { Type: 'observation', Date: '201610240055', Rainfall: 0 },
        { Type: 'observation', Date: '201610240100', Rainfall: a },
        { Type: 'forecast', Date: '201610240105', Rainfall: b },
        { Type: 'forecast', Date: '201610240110', Rainfall: b },
        { Type: 'forecast', Date: '201610240115', Rainfall: b },
        { Type: 'forecast', Date: '201610240120', Rainfall: b },
        { Type: 'forecast', Date: '201610240125', Rainfall: b },
        { Type: 'forecast', Date: '201610240130', Rainfall: b },
        { Type: 'forecast', Date: '201610240135', Rainfall: b },
        { Type: 'forecast', Date: '201610240140', Rainfall: b },
        { Type: 'forecast', Date: '201610240145', Rainfall: b },
        { Type: 'forecast', Date: '201610240150', Rainfall: b },
        { Type: 'forecast', Date: '201610240155', Rainfall: b },
        { Type: 'forecast', Date: '201610240200', Rainfall: b }
    ];
}
<|endoftext|>


<commit_before>Ext4.define('Kwf.Ext4.ViewController.EditWindow', {
    extend: 'Kwf.Ext4.ViewController.Abstract',
    uses: [ 'Kwf.Ext4.Data.StoreSyncQueue' ],

    focusOnEditSelector: 'field',
    bindable: null,
    autoSync: false,

    optionalControl: {

        saveButton: {
            selector: '> toolbar > button#save',
            listeners: {
                click: 'onSave'
            }
        },

        deleteButton: {
            selector: '> toolbar > button#delete'
        },

        cancelButton: {
            selector: '> toolbar > button#cancel',
            listeners: {
                click: 'onCancel'
            }
        }

    },
    init: function()
    {
        if (!this.view) Ext4.Error.raise('view is required');
        if (!(this.view instanceof Ext4.window.Window)) Ext4.Error.raise('view needs to be a Ext.window.Window');

        if (!this.bindable) {
            //by default (most common case) get form
            this.bindable = this.view.down('> form');
        }
        if (!this.bindable) Ext4.Error.raise('bindable config is required');
        if (!this.bindable.isBindableController && this.bindable.getController) {
            this.bindable = this.bindable.getController();
        }
        if (!this.bindable.isBindableController) {
            Ext4.Error.raise('bindable config needs to be a Kwf.Ext4.Controller.Bindable.Interface');
        }

        this.view.on('beforeclose', function() {
            this.onCancel();
            return false;
        }, this);
    },

    //store is optional, used for sync
    openEditWindow: function(row, store)
    {
        this._loadedStore = store;
        if (row.phantom) {
            this.view.setTitle(trlKwf('Add'));
        } else {
            this.view.setTitle(trlKwf('Edit'));
        }
        this.view.show();
        this.bindable.load(row);
        if (this.focusOnEditSelector) {
            this.view.down(this.focusOnEditSelector).focus();
        }
    },

    validateAndSubmit: function(options)
    {
        return this.bindable.validateAndSubmit(options);
    },

    doSave: function()
    {
        if (!this.bindable.isValid()) {
            Ext4.Msg.alert(trlKwf('Save'),
                trlKwf("Can't save, please fill all red underlined fields correctly."));
            return false;
        }

        var row = this.bindable.getLoadedRecord();
        if (row.phantom && this._loadedStore
            && this._loadedStore.indexOf(row) == -1
        ) {
            this._loadedStore.add(row);
        }

        if (this.autoSync) {
            if (this._loadedStore) {
                var syncQueue = new Kwf.Ext4.Data.StoreSyncQueue();
                syncQueue.add(this._loadedStore); //sync store first
                this.bindable.save(syncQueue);    //then bindables (so bindable grid is synced second)
                                                  //bindable forms can still update the row as the sync is not yet started
                syncQueue.start({
                    success: function() {
                        this.fireViewEvent('savesuccess');
                    },
                    scope: this
                });
            } else {
                this.bindable.save();
                this.bindable.getLoadedRecord().save({
                    callback: function(records, operation, success) {
                        if (success) this.fireViewEvent('savesuccess');
                    },
                    scope: this
                });
            }
        } else {
            this.bindable.save();
        }
        this.fireViewEvent('save');

        return true;
    },

    onSave: function()
    {
        if (this.doSave() !== false) {
            this.closeWindow();
        }
    },

    onCancel: function()
    {
        if (this.bindable.isDirty()) {
            Ext4.Msg.show({
                title: trl('Speichern'),
                msg: trl('Wollen Sie die Änderungen speichern?'),
                icon: Ext4.MessageBox.QUESTION,
                buttons: Ext4.Msg.YESNOCANCEL,
                fn: function(btn) {
                    if (btn == 'no') {
                        this.closeWindow();
                    } else if (btn == 'yes') {
                        if (this.doSave() !== false) {
                            this.closeWindow();
                        }
                    }
                },
                scope: this
            });
        } else {
            this.closeWindow();
        }
    },

    closeWindow: function()
    {
        this.bindable.reset();
        this.view.hide();
    },

    getLoadedRecord: function()
    {
        if (this.bindable) {
            return this.bindable.getLoadedRecord();
        } else {
            return null;
        }
    }

});
<commit_msg>Ext4: reset after hiding window, allows accessing loaded record in hide event<commit_after>Ext4.define('Kwf.Ext4.ViewController.EditWindow', {
    extend: 'Kwf.Ext4.ViewController.Abstract',
    uses: [ 'Kwf.Ext4.Data.StoreSyncQueue' ],

    focusOnEditSelector: 'field',
    bindable: null,
    autoSync: false,

    optionalControl: {

        saveButton: {
            selector: '> toolbar > button#save',
            listeners: {
                click: 'onSave'
            }
        },

        deleteButton: {
            selector: '> toolbar > button#delete'
        },

        cancelButton: {
            selector: '> toolbar > button#cancel',
            listeners: {
                click: 'onCancel'
            }
        }

    },
    init: function()
    {
        if (!this.view) Ext4.Error.raise('view is required');
        if (!(this.view instanceof Ext4.window.Window)) Ext4.Error.raise('view needs to be a Ext.window.Window');

        if (!this.bindable) {
            //by default (most common case) get form
            this.bindable = this.view.down('> form');
        }
        if (!this.bindable) Ext4.Error.raise('bindable config is required');
        if (!this.bindable.isBindableController && this.bindable.getController) {
            this.bindable = this.bindable.getController();
        }
        if (!this.bindable.isBindableController) {
            Ext4.Error.raise('bindable config needs to be a Kwf.Ext4.Controller.Bindable.Interface');
        }

        this.view.on('beforeclose', function() {
            this.onCancel();
            return false;
        }, this);
    },

    //store is optional, used for sync
    openEditWindow: function(row, store)
    {
        this._loadedStore = store;
        if (row.phantom) {
            this.view.setTitle(trlKwf('Add'));
        } else {
            this.view.setTitle(trlKwf('Edit'));
        }
        this.view.show();
        this.bindable.load(row);
        if (this.focusOnEditSelector) {
            this.view.down(this.focusOnEditSelector).focus();
        }
    },

    validateAndSubmit: function(options)
    {
        return this.bindable.validateAndSubmit(options);
    },

    doSave: function()
    {
        if (!this.bindable.isValid()) {
            Ext4.Msg.alert(trlKwf('Save'),
                trlKwf("Can't save, please fill all red underlined fields correctly."));
            return false;
        }

        var row = this.bindable.getLoadedRecord();
        if (row.phantom && this._loadedStore
            && this._loadedStore.indexOf(row) == -1
        ) {
            this._loadedStore.add(row);
        }

        if (this.autoSync) {
            if (this._loadedStore) {
                var syncQueue = new Kwf.Ext4.Data.StoreSyncQueue();
                syncQueue.add(this._loadedStore); //sync store first
                this.bindable.save(syncQueue);    //then bindables (so bindable grid is synced second)
                                                  //bindable forms can still update the row as the sync is not yet started
                syncQueue.start({
                    success: function() {
                        this.fireViewEvent('savesuccess');
                    },
                    scope: this
                });
            } else {
                this.bindable.save();
                this.bindable.getLoadedRecord().save({
                    callback: function(records, operation, success) {
                        if (success) this.fireViewEvent('savesuccess');
                    },
                    scope: this
                });
            }
        } else {
            this.bindable.save();
        }
        this.fireViewEvent('save');

        return true;
    },

    onSave: function()
    {
        if (this.doSave() !== false) {
            this.closeWindow();
        }
    },

    onCancel: function()
    {
        if (this.bindable.isDirty()) {
            Ext4.Msg.show({
                title: trl('Speichern'),
                msg: trl('Wollen Sie die Änderungen speichern?'),
                icon: Ext4.MessageBox.QUESTION,
                buttons: Ext4.Msg.YESNOCANCEL,
                fn: function(btn) {
                    if (btn == 'no') {
                        this.closeWindow();
                    } else if (btn == 'yes') {
                        if (this.doSave() !== false) {
                            this.closeWindow();
                        }
                    }
                },
                scope: this
            });
        } else {
            this.closeWindow();
        }
    },

    closeWindow: function()
    {
        this.view.hide();
        this.bindable.reset();
    },

    getLoadedRecord: function()
    {
        if (this.bindable) {
            return this.bindable.getLoadedRecord();
        } else {
            return null;
        }
    }

});
<|endoftext|>


<commit_before>Ext.namespace('Vpc.ListSwitch');

Vpc.ListSwitch.View = function(componentWrapper) {
    this.componentWrapper = Ext.get(componentWrapper);
    this.init();
};

Vpc.ListSwitch.View.prototype = {
    previewElements: [],
    activePreviewLink: null,

    init: function() {
        this.previousEl = this.componentWrapper.down('.listSwitchLargeWrapper a.listSwitchPrevious');
        this.nextEl = this.componentWrapper.down('.listSwitchLargeWrapper a.listSwitchNext');

        this.previousEl.on('click', this.showPrevious, this);
        this.nextEl.on('click', this.showNext, this);

        var switchItems = Ext.DomQuery.select(
            'div.listSwitchItem',
            this.componentWrapper.down('.listSwitchPreviewWrapper').dom
        );
        Ext.each(switchItems, function(si) {
            var previewLink = Ext.get(si).down('a.previewLink');
            previewLink.largeContent = Ext.get(si).down('.largeContent').dom;
            previewLink.switchIndex = this.previewElements.length;
            previewLink.on('click', function(ev, el, cfg) {
                this.setLarge(cfg.linkEl);
                ev.stopEvent();
            }, this, { linkEl: previewLink });
            this.previewElements.push(previewLink);
        }, this);

        if (this.previewElements.length && this.previewElements[0]) {
            this.setLarge(this.previewElements[0]);
        }
    },

    setLarge: function(previewEl) {
        if (this.activePreviewLink)  {
            this.activePreviewLink.largeContent.style.display = 'none';
        } else {
            this.componentWrapper.down('.listSwitchLargeWrapper .listSwitchLargeContent').dom.innerHTML = '';
        }
        previewEl.largeContent.style.display = 'block';
        this.componentWrapper.down('.listSwitchLargeWrapper .listSwitchLargeContent').dom.appendChild(previewEl.largeContent);
        if (this.activePreviewLink) {
            this.activePreviewLink.removeClass('active');
        }
        this.activePreviewLink = previewEl;
        this.activePreviewLink.addClass('active');

        this.previousEl.setDisplayed(this.activePreviewLink.switchIndex == 0 ? false : true);
        this.nextEl.setDisplayed(
            this.activePreviewLink.switchIndex >= (this.previewElements.length -1) ? false : true
        );
    },

    showNext: function(ev) {
        if (this.previewElements[this.activePreviewLink.switchIndex+1]) {
            this.setLarge(this.previewElements[this.activePreviewLink.switchIndex+1]);
        }
        ev.stopEvent();
    },

    showPrevious: function(ev) {
        if (this.activePreviewLink.switchIndex >= 1) {
            this.setLarge(this.previewElements[this.activePreviewLink.switchIndex-1]);
        }
        ev.stopEvent();
    }
};

Vps.onContentReady(function() {
    var switches = Ext.DomQuery.select('div.vpsListSwitch');
    Ext.each(switches, function(sw) {
        var list = new Vpc.ListSwitch.View(sw);
    });
});

<commit_msg>bugfix: list switch wird im backend eventuell oefter initialisiert und kackt dann ab<commit_after>Ext.namespace('Vpc.ListSwitch');

Vpc.ListSwitch.View = function(componentWrapper) {
    this.componentWrapper = Ext.get(componentWrapper);
    this.init();
};

Vpc.ListSwitch.View.prototype = {
    previewElements: [],
    activePreviewLink: null,

    init: function() {
        if (this.componentWrapper.initDone) return;

        this.previousEl = this.componentWrapper.down('.listSwitchLargeWrapper a.listSwitchPrevious');
        this.nextEl = this.componentWrapper.down('.listSwitchLargeWrapper a.listSwitchNext');

        this.previousEl.on('click', this.showPrevious, this);
        this.nextEl.on('click', this.showNext, this);

        var switchItems = Ext.DomQuery.select(
            'div.listSwitchItem',
            this.componentWrapper.down('.listSwitchPreviewWrapper').dom
        );
        Ext.each(switchItems, function(si) {
            var previewLink = Ext.get(si).down('a.previewLink');
            previewLink.largeContent = Ext.get(si).down('.largeContent').dom;
            previewLink.switchIndex = this.previewElements.length;
            previewLink.on('click', function(ev, el, cfg) {
                this.setLarge(cfg.linkEl);
                ev.stopEvent();
            }, this, { linkEl: previewLink });
            this.previewElements.push(previewLink);
        }, this);

        if (this.previewElements.length && this.previewElements[0]) {
            this.setLarge(this.previewElements[0]);
        }

        this.componentWrapper.initDone = true;
    },

    setLarge: function(previewEl) {
        if (this.activePreviewLink)  {
            this.activePreviewLink.largeContent.style.display = 'none';
        } else {
            this.componentWrapper.down('.listSwitchLargeWrapper .listSwitchLargeContent').dom.innerHTML = '';
        }
        previewEl.largeContent.style.display = 'block';
        this.componentWrapper.down('.listSwitchLargeWrapper .listSwitchLargeContent').dom.appendChild(previewEl.largeContent);
        if (this.activePreviewLink) {
            this.activePreviewLink.removeClass('active');
        }
        this.activePreviewLink = previewEl;
        this.activePreviewLink.addClass('active');

        this.previousEl.setDisplayed(this.activePreviewLink.switchIndex == 0 ? false : true);
        this.nextEl.setDisplayed(
            this.activePreviewLink.switchIndex >= (this.previewElements.length -1) ? false : true
        );
    },

    showNext: function(ev) {
        if (this.previewElements[this.activePreviewLink.switchIndex+1]) {
            this.setLarge(this.previewElements[this.activePreviewLink.switchIndex+1]);
        }
        ev.stopEvent();
    },

    showPrevious: function(ev) {
        if (this.activePreviewLink.switchIndex >= 1) {
            this.setLarge(this.previewElements[this.activePreviewLink.switchIndex-1]);
        }
        ev.stopEvent();
    }
};

Vps.onContentReady(function() {
    var switches = Ext.DomQuery.select('div.vpsListSwitch');
    Ext.each(switches, function(sw) {
        var list = new Vpc.ListSwitch.View(sw);
    });
});

<|endoftext|>


<commit_before>Ext.namespace('Vps.Auto');
Vps.Auto.SyncTreePanel = Ext.extend(Vps.Binding.AbstractPanel, {

    layout: 'fit',

    initComponent : function()
    {
        if (this.autoLoad !== false) {
            this.autoLoad = true;
        } else {
            delete this.autoLoad;
        }

        this.addEvents(
            'selectionchange',
            'editaction',
            'addaction'
        );
        this.actions['delete'] = new Ext.Action({
            text    : trlVps('Delete'),
            handler : this.onDelete,
            cls     : 'x-btn-text-icon',
            disabled: true,
            scope   : this
        });
        this.actions.add = new Ext.Action({
            text    : trlVps('Add'),
            handler : this.onAdd,
            cls     : 'x-btn-text-icon',
            scope   : this
        });
        this.actions.edit = new Ext.Action({
            text    : trlVps('Edit'),
            handler : this.onEdit,
            cls     : 'x-btn-text-icon',
            disabled: true,
            scope   : this
        });
        this.actions.invisible = new Ext.Action({
            text    : trlVps('Toggle Visibility'),
            handler : this.onVisible,
            cls     : 'x-btn-text-icon',
            disabled: true,
            scope   : this
        });
        this.actions.reload = new Ext.Action({
            text    : '',
            handler : function () { this.tree.getRootNode().reload(); },
            icon    : '/assets/silkicons/arrow_rotate_clockwise.png',
            cls     : 'x-btn-icon',
            tooltip : trlVps('Reload'),
            scope   : this
        });

        Vps.Auto.SyncTreePanel.superclass.initComponent.call(this);
    },
    doAutoLoad : function()
    {
        //autoLoad kann in der zwischenzeit abgeschaltet werden, zB wenn
        //wir in einem Binding sind
        if (!this.autoLoad) return;
        this.loadMeta();
    },

    loadMeta: function()
    {
        Ext.Ajax.request({
            mask: true,
            url: this.controllerUrl + '/json-meta',
            params: this.baseParams,
            success: this.onMetaChange,
            scope: this
        });
    },

    onMetaChange: function(response) {
        var meta = Ext.decode(response.responseText);
        this.icons = meta.icons;
        for (var i in this.icons) {
            if (i in this.actions) {
                this.actions[i].initialConfig.icon = this.icons[i];
            }
        }

        // Toolbar
        if (meta.buttons.each == undefined) { // Abfrage nötig, falls keine Buttons geliefert
            var tbar = [];
            for (var button in meta.buttons) {
                tbar.add(this.getAction(button));
            }
        }

        // Tree
        baseParams = this.baseParams != undefined ? this.baseParams : {};
        if (this.openedId != undefined) { baseParams.openedId = this.openedId; }
        this.tree = new Ext.tree.TreePanel({
            border      : false,
//            animate     : true,
            loader      : new Ext.tree.TreeLoader({
                baseParams  : baseParams,
                dataUrl     : this.controllerUrl + '/json-data'
            }),
            enableDD    : meta.enableDD,
            autoScroll: true,
            rootVisible : meta.rootVisible,
            tbar        : tbar,
            dropConfig  : meta.dropConfig
        });

        this.tree.setRootNode(
            new Ext.tree.AsyncTreeNode({
                text: meta.rootText,
                id: '0',
                allowDrag: false
            })
        );

        this.tree.getSelectionModel().on('selectionchange', this.onSelectionchange, this);
        this.tree.getSelectionModel().on('beforeselect', function(selModel, newNode, oldNode) {
            return this.fireEvent('beforeselectionchange', newNode.attributes.id);
        }, this);
        this.tree.on('beforenodedrop', this.onMove, this);
        this.tree.on('collapsenode', this.onCollapseNode, this);
        this.tree.on('expandnode', this.onExpandNode, this);

        this.tree.on('load', function(node) {
            if (this.openedId == node.id) {
                node.select();
            }
            return true;
        }, this);

        this.relayEvents(this.tree, ['click', 'dblclick']);

        this.add(this.tree);
        this.doLayout();

        this.tree.getRootNode().expand();
        if (meta.rootVisible) {
            this.tree.getRootNode().ui.iconNode.style.backgroundImage = 'url(' + meta.icons.root + ')';
            this.tree.getRootNode().select();
        }

        if (!this.editDialog && meta.editDialog) {
            this.editDialog = meta.editDialog;
        }
        if (this.editDialog && !(this.editDialog instanceof Vps.Auto.Form.Window)) {
            this.editDialog = new Vps.Auto.Form.Window(meta.editDialog);
        }
        if (this.editDialog) {
            this.editDialog.on('datachange', function(o) {
                if (o.data.addedId != undefined) {
                    id = o.data.addedId;
                } else {
                    id = this.tree.getSelectionModel().getSelectedNode().id;
                }
                this.onSave(id);
            }, this);
            this.tree.on('dblclick', function(grid, rowIndex) {
                this.onEdit();
            }, this);
            if (this.editDialog.applyBaseParams) {
                this.editDialog.applyBaseParams(this.getBaseParams());
            }
        }

        this.fireEvent('loaded', this.tree);
    },

    onEdit : function (o, e) {
        if (this.editDialog != undefined) {
            node = this.tree.getSelectionModel().getSelectedNode();
            this.editDialog.showEdit(node.id);
        } else {
            this.fireEvent('editaction', this.tree.getSelectionModel().getSelectedNode());
        }
    },

    onAdd: function (o, e) {
        if (this.editDialog != undefined) {
            this.editDialog.getAutoForm().applyBaseParams({
                parent_id: this.getSelectedId()
            });
            this.editDialog.showAdd();
        } else {
            this.fireEvent('addaction', this.tree.getSelectionModel().getSelectedNode());
        }
    },

    onSave : function (id)
    {
        Ext.Ajax.request({
            url: this.controllerUrl + '/json-node-data',
            params: Ext.apply({node:id}, this.getBaseParams()),
            success: function(r) {
                this.onSaved(Ext.decode(r.responseText).data);
            },
            scope: this
        })
    },

    onSelectionchange: function (selModel, node) {
        if (node && node.id != 0) {
            this.getAction('edit').enable();
            this.getAction('invisible').enable();
            this.getAction('delete').enable();
        } else {
            this.getAction('edit').disable();
            this.getAction('invisible').disable();
            this.getAction('delete').disable();
        }
        this.fireEvent('selectionchange', node);
    },

    onDelete: function (o, e) {
        Ext.MessageBox.confirm(trlVps('Delete'), trlVps('Do you really want to delete this entry:\n\n"') + this.tree.getSelectionModel().getSelectedNode().text + '"',
            function  (button) {
                if (button == 'yes') {
                    Ext.Ajax.request({
                        url: this.controllerUrl + '/json-delete',
                        params: {
                            id: this.tree.getSelectionModel().getSelectedNode().id
                        },
                        success: function(r) {
                            this.onDeleted(Ext.decode(r.responseText));
                        },
                        scope: this
                    });
                }
            },
            this
        );
    },

    onMove : function(dropEvent){
        Ext.Ajax.request({
            url: this.controllerUrl + '/json-move',
            params: {
                source: dropEvent.dropNode.id,
                target: dropEvent.target.id,
                point: dropEvent.point
            },
            success: function(r) {
                response = Ext.decode(r.responseText);
                var parent = this.tree.getNodeById(response.parent);
                var node = this.tree.getNodeById(response.node);
                var before = this.tree.getNodeById(response.before);
                parent.insertBefore(node, before);
                parent.expand();
            },
            failure: function(r) {
                this.tree.getRootNode().reload();
            },
            scope: this
        });
        dropEvent.dropStatus = true;
        dropEvent.cancel = true;
        return true;
    },

    onCollapseNode : function(node) {
        Ext.Ajax.request({
            url: this.controllerUrl + '/json-collapse',
            params: {id: node.id}
        });
    },

    onExpandNode : function(node) {
        if (node.attributes.children && node.attributes.children.length > 0) {
            Ext.Ajax.request({
                url: this.controllerUrl + '/json-expand',
                params: {id: node.id}
            });
        }
    },

    onVisible : function (o, e) {
        Ext.Ajax.request({
            url: this.controllerUrl + '/json-visible',
            params: {
                id: this.tree.getSelectionModel().getSelectedNode().id
            },
            success: function(r) {
                response = Ext.decode(r.responseText);
                node = this.tree.getNodeById(response.id);
                node.attributes.visible = response.visible;
                this.setVisible(node);
            },
            scope: this
        })
    },

    setVisible : function (node) {
        if (node.attributes.visible) {
            node.ui.iconNode.style.backgroundImage = 'url(' + this.icons['default'] + ')';
        } else {
            node.ui.iconNode.style.backgroundImage = 'url(' + this.icons['invisible'] + ')';
        }
    },

    getTree : function() {
        return this.tree;
    },
    getSelectionModel : function() {
        if (!this.getTree()) return null;
        return this.getTree().getSelectionModel();
    },
    getSelectedNode : function() {
        if (!this.getSelectionModel()) return null;
        return this.getSelectionModel().getSelectedNode();
    },

    //für AbstractPanel
    getSelectedId: function() {
        var s = this.getSelectedNode();
        if (s) return s.id;
        return null;
    },

    //für AbstractPanel
    selectId: function(id) {
        if (id) {
            if (this.getTree()) {
                var n = this.getTree().getNodeById(id);
                if (n) {
                    n.select();
                }
            } else {
                this.openedId = id;
            }
        } else {
            var m = this.getSelectionModel();
            if (m) m.clearSelections();
        }
    },

    onSaved : function (response)
    {
        this.tree.getRootNode().reload();
    },

    onDeleted: function (response) {
        this.tree.getRootNode().reload();
    },

    setBaseParams : function(baseParams) {
        Vps.Auto.SyncTreePanel.superclass.setBaseParams.apply(this, arguments);
        if (this.editDialog && this.editDialog.setBaseParams) {
            this.editDialog.setBaseParams(baseParams);
        }
    },
    applyBaseParams : function(baseParams) {
        Vps.Auto.SyncTreePanel.superclass.applyBaseParams.apply(this, arguments);
        if (this.editDialog && this.editDialog.applyBaseParams) {
            this.editDialog.applyBaseParams(baseParams);
        }
    }

});
Ext.reg('vps.autotreesync', Vps.Auto.SyncTreePanel);
<commit_msg>Tree verbesserungen: - bei allen requests die gemacht werden baseParams mitschicken (um die component_id zu haben die für  berechtigungsüberprüfung verwendet wird) - bei Ext.Ajax.request kommt als 3. parameter schon result mit - muss nicht nochmal Ext.decode verwendet werden<commit_after>Ext.namespace('Vps.Auto');
Vps.Auto.SyncTreePanel = Ext.extend(Vps.Binding.AbstractPanel, {

    layout: 'fit',

    initComponent : function()
    {
        if (this.autoLoad !== false) {
            this.autoLoad = true;
        } else {
            delete this.autoLoad;
        }

        this.addEvents(
            'selectionchange',
            'editaction',
            'addaction'
        );
        this.actions['delete'] = new Ext.Action({
            text    : trlVps('Delete'),
            handler : this.onDelete,
            cls     : 'x-btn-text-icon',
            disabled: true,
            scope   : this
        });
        this.actions.add = new Ext.Action({
            text    : trlVps('Add'),
            handler : this.onAdd,
            cls     : 'x-btn-text-icon',
            scope   : this
        });
        this.actions.edit = new Ext.Action({
            text    : trlVps('Edit'),
            handler : this.onEdit,
            cls     : 'x-btn-text-icon',
            disabled: true,
            scope   : this
        });
        this.actions.invisible = new Ext.Action({
            text    : trlVps('Toggle Visibility'),
            handler : this.onVisible,
            cls     : 'x-btn-text-icon',
            disabled: true,
            scope   : this
        });
        this.actions.reload = new Ext.Action({
            text    : '',
            handler : function () { this.tree.getRootNode().reload(); },
            icon    : '/assets/silkicons/arrow_rotate_clockwise.png',
            cls     : 'x-btn-icon',
            tooltip : trlVps('Reload'),
            scope   : this
        });

        Vps.Auto.SyncTreePanel.superclass.initComponent.call(this);
    },
    doAutoLoad : function()
    {
        //autoLoad kann in der zwischenzeit abgeschaltet werden, zB wenn
        //wir in einem Binding sind
        if (!this.autoLoad) return;
        this.loadMeta();
    },

    loadMeta: function()
    {
        Ext.Ajax.request({
            mask: true,
            url: this.controllerUrl + '/json-meta',
            params: this.baseParams,
            success: this.onMetaChange,
            scope: this
        });
    },

    onMetaChange: function(response, options, meta) {
        this.icons = meta.icons;
        for (var i in this.icons) {
            if (i in this.actions) {
                this.actions[i].initialConfig.icon = this.icons[i];
            }
        }

        // Toolbar
        if (meta.buttons.each == undefined) { // Abfrage nötig, falls keine Buttons geliefert
            var tbar = [];
            for (var button in meta.buttons) {
                tbar.add(this.getAction(button));
            }
        }

        // Tree
        var baseParams = this.baseParams != undefined ? this.baseParams : {};
        if (this.openedId != undefined) { baseParams.openedId = this.openedId; }
        this.tree = new Ext.tree.TreePanel({
            border      : false,
//            animate     : true,
            loader      : new Ext.tree.TreeLoader({
                baseParams  : baseParams,
                dataUrl     : this.controllerUrl + '/json-data'
            }),
            enableDD    : meta.enableDD,
            autoScroll: true,
            rootVisible : meta.rootVisible,
            tbar        : tbar,
            dropConfig  : meta.dropConfig
        });

        this.tree.setRootNode(
            new Ext.tree.AsyncTreeNode({
                text: meta.rootText,
                id: '0',
                allowDrag: false
            })
        );

        this.tree.getSelectionModel().on('selectionchange', this.onSelectionchange, this);
        this.tree.getSelectionModel().on('beforeselect', function(selModel, newNode, oldNode) {
            return this.fireEvent('beforeselectionchange', newNode.attributes.id);
        }, this);
        this.tree.on('beforenodedrop', this.onMove, this);
        this.tree.on('collapsenode', this.onCollapseNode, this);
        this.tree.on('expandnode', this.onExpandNode, this);

        this.tree.on('load', function(node) {
            if (this.openedId == node.id) {
                node.select();
            }
            return true;
        }, this);

        this.relayEvents(this.tree, ['click', 'dblclick']);

        this.add(this.tree);
        this.doLayout();

        this.tree.getRootNode().expand();
        if (meta.rootVisible) {
            this.tree.getRootNode().ui.iconNode.style.backgroundImage = 'url(' + meta.icons.root + ')';
            this.tree.getRootNode().select();
        }

        if (!this.editDialog && meta.editDialog) {
            this.editDialog = meta.editDialog;
        }
        if (this.editDialog && !(this.editDialog instanceof Vps.Auto.Form.Window)) {
            this.editDialog = new Vps.Auto.Form.Window(meta.editDialog);
        }
        if (this.editDialog) {
            this.editDialog.on('datachange', function(o) {
                if (o.data.addedId != undefined) {
                    id = o.data.addedId;
                } else {
                    id = this.tree.getSelectionModel().getSelectedNode().id;
                }
                this.onSave(id);
            }, this);
            this.tree.on('dblclick', function(grid, rowIndex) {
                this.onEdit();
            }, this);
            if (this.editDialog.applyBaseParams) {
                this.editDialog.applyBaseParams(this.getBaseParams());
            }
        }

        this.fireEvent('loaded', this.tree);
    },

    onEdit : function (o, e) {
        var node = this.tree.getSelectionModel().getSelectedNode();
        if (!node.id) return;
        if (this.editDialog != undefined) {
            this.editDialog.showEdit(node.id);
        } else {
            this.fireEvent('editaction', node);
        }
    },

    onAdd: function (o, e) {
        if (this.editDialog != undefined) {
            this.editDialog.getAutoForm().applyBaseParams({
                parent_id: this.getSelectedId()
            });
            this.editDialog.showAdd();
        } else {
            this.fireEvent('addaction', this.tree.getSelectionModel().getSelectedNode());
        }
    },

    onSave : function (id)
    {
        Ext.Ajax.request({
            url: this.controllerUrl + '/json-node-data',
            params: Ext.apply({node:id}, this.getBaseParams()),
            success: function(response, options, result) {
                this.onSaved(result.data);
            },
            scope: this
        })
    },

    onSelectionchange: function (selModel, node) {
        if (node && node.id != 0) {
            this.getAction('edit').enable();
            this.getAction('invisible').enable();
            this.getAction('delete').enable();
        } else {
            this.getAction('edit').disable();
            this.getAction('invisible').disable();
            this.getAction('delete').disable();
        }
        this.fireEvent('selectionchange', node);
    },

    onDelete: function (o, e) {
        Ext.MessageBox.confirm(trlVps('Delete'), trlVps('Do you really want to delete this entry:\n\n"') + this.tree.getSelectionModel().getSelectedNode().text + '"',
            function  (button) {
                if (button == 'yes') {
                    Ext.Ajax.request({
                        url: this.controllerUrl + '/json-delete',
                        params: Ext.apply({id:this.getSelectedId()}, this.getBaseParams()),
                        success: function(response, options, result) {
                            this.onDeleted(result);
                        },
                        scope: this
                    });
                }
            },
            this
        );
    },

    onMove : function(dropEvent){
        var params = this.getBaseParams()
        params.source = dropEvent.dropNode.id;
        params.target = dropEvent.target.id;
        params.point = dropEvent.point;
        Ext.Ajax.request({
            url: this.controllerUrl + '/json-move',
            params: params,
            success: function(response, options, result) {
                var parent = this.tree.getNodeById(result.parent);
                var node = this.tree.getNodeById(result.node);
                var before = this.tree.getNodeById(result.before);
                parent.insertBefore(node, before);
                parent.expand();
            },
            failure: function(r) {
                this.tree.getRootNode().reload();
            },
            scope: this
        });
        dropEvent.dropStatus = true;
        dropEvent.cancel = true;
        return true;
    },

    onCollapseNode : function(node) {
        Ext.Ajax.request({
            url: this.controllerUrl + '/json-collapse',
            params: Ext.apply({id:node.id}, this.getBaseParams())
        });
    },

    onExpandNode : function(node) {
        if (node.attributes.children && node.attributes.children.length > 0) {
            Ext.Ajax.request({
                url: this.controllerUrl + '/json-expand',
                params: Ext.apply({id:node.id}, this.getBaseParams())
            });
        }
    },

    onVisible : function (o, e) {
        Ext.Ajax.request({
            url: this.controllerUrl + '/json-visible',
            params: Ext.apply({id:this.getSelectedId()}, this.getBaseParams()),
            success: function(response, options, result) {
                node = this.tree.getNodeById(result.id);
                node.attributes.visible = result.visible;
                this.setVisible(node);
            },
            scope: this
        })
    },

    setVisible : function (node) {
        if (node.attributes.visible) {
            node.ui.iconNode.style.backgroundImage = 'url(' + this.icons['default'] + ')';
        } else {
            node.ui.iconNode.style.backgroundImage = 'url(' + this.icons['invisible'] + ')';
        }
    },

    getTree : function() {
        return this.tree;
    },
    getSelectionModel : function() {
        if (!this.getTree()) return null;
        return this.getTree().getSelectionModel();
    },
    getSelectedNode : function() {
        if (!this.getSelectionModel()) return null;
        return this.getSelectionModel().getSelectedNode();
    },

    //für AbstractPanel
    getSelectedId: function() {
        var s = this.getSelectedNode();
        if (s) return s.id;
        return null;
    },

    //für AbstractPanel
    selectId: function(id) {
        if (id) {
            if (this.getTree()) {
                var n = this.getTree().getNodeById(id);
                if (n) {
                    n.select();
                }
            } else {
                this.openedId = id;
            }
        } else {
            var m = this.getSelectionModel();
            if (m) m.clearSelections();
        }
    },

    onSaved : function (response)
    {
        this.tree.getRootNode().reload();
    },

    onDeleted: function (response) {
        this.tree.getRootNode().reload();
    },

    setBaseParams : function(baseParams) {
        Vps.Auto.SyncTreePanel.superclass.setBaseParams.apply(this, arguments);
        if (this.editDialog && this.editDialog.setBaseParams) {
            this.editDialog.setBaseParams(baseParams);
        }
    },
    applyBaseParams : function(baseParams) {
        Vps.Auto.SyncTreePanel.superclass.applyBaseParams.apply(this, arguments);
        if (this.editDialog && this.editDialog.applyBaseParams) {
            this.editDialog.applyBaseParams(baseParams);
        }
    }

});
Ext.reg('vps.autotreesync', Vps.Auto.SyncTreePanel);
<|endoftext|>


<commit_before>Ext.namespace('Vps.FrontendForm');
Vps.FrontendForm.Field = function(fieldEl) {
    Vps.FrontendForm.Field.superclass.constructor.call(this);
    this.el = fieldEl;
    this.el.enableDisplayMode();
    this.initField();
    this.addEvents('change');
};
Ext.extend(Vps.FrontendForm.Field, Ext.util.Observable, {
    initField: function() {
        var inp = this.el.child('input');
        if (inp) {
            inp.on('change', function() {
                this.fireEvent('change', this.getValue());
            }, this);
        }
    },
    getFieldName: function() {
        var inp = this.el.child('input');
        if (!inp) return null;
        return inp.dom.name;
    },
    getValue: function() {
        var inp = this.el.child('input');
        if (!inp) return null;
        return inp.dom.value;
    },
    hide: function() {
        this.el.hide();
    },
    show: function() {
        this.el.show();
    }
});

Vps.FrontendForm.fields['vpsField'] = Vps.FrontendForm.Field;
<commit_msg>initialize fields<commit_after>Ext.namespace('Vps.FrontendForm');
Vps.FrontendForm.Field = function(fieldEl) {
    Vps.FrontendForm.Field.superclass.constructor.call(this);
    this.el = fieldEl;
    this.el.enableDisplayMode();
    this.initField();
    this.addEvents('change');
};
Ext.extend(Vps.FrontendForm.Field, Ext.util.Observable, {
    initField: function() {
        var inp = this.el.child('input');
        if (inp) {
            inp.on('change', function() {
                this.fireEvent('change', this.getValue());
            }, this);
        }
    },
    getFieldName: function() {
        var inp = this.el.child('input');
        if (!inp) return null;
        return inp.dom.name;
    },
    getValue: function() {
        var inp = this.el.child('input');
        if (!inp) return null;
        return inp.dom.value;
    },
    hide: function() {
        this.el.hide();
    },
    show: function() {
        this.el.show();
    }
});

Vps.FrontendForm.fields = {};
Vps.FrontendForm.fields['vpsField'] = Vps.FrontendForm.Field;
<|endoftext|>


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

	$("#ClickCamera").click( function () {
		// Grab elements, create settings, etc.
		var video = document.getElementById('video');

		// Get access to the camera!
		navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia || navigator.oGetUserMedia;
		if(navigator.getUserMedia) {
		    // Not adding `{ audio: true }` since we only want video now
		    navigator.getUserMedia({video: true}, function (stream){
		    	video.src = window.URL.createObjectURL(stream);
		    	video.play();
		    }, function () {

		    });
		} else {
			console.log('false video', navigator.mediaDevices, navigator.getUserMedia);
		}
	});
	$("#SnapPhoto").click(function () {
		var video = document.getElementById('video');
		var photo = document.getElementById('photo').getContext('2d');
		$("#dphoto").show();
		photo.drawImage(video, 0, 0, 580, 480);
		$(video).hide();
		$('#SnapPhoto').text("Отправить фото").addClass("SEND_PHOTO");
	});

	$("body").on('click', '.SEND_PHOTO', function () {
		var photo = document.getElementById('photo');
		var data = photo.toDataURL();
		console.log(data);

	    $.ajax({
	        url: "/run_base64",
	        type: 'POST',
	        data: {
	        	imgBase64: data
	        },
	        success: function (data) {
	            console.log(data)
			    var img = new Image();
			    img.src="/result?filename="+data.filename+'.jpg';
			    img.onload = function () {
			        $("#Result").append($(img));
			    }
	        }
	    });
	});

	$("body").on("click", ".btn_route", function (evt) {
		var route = $(evt.target).attr('route');
		console.log(route);

		$('.windows').hide(400);
		$('#window_'+route).show(400);
	});

	// Перехват субмита форма
	$("#MainForm").submit( function (event) {

		console.log("Submit form!");

		var formData = new FormData($(this)[0]);
	    $.ajax({
	        url: "/run",
	        type: 'POST',
	        data: formData,
	        async: false,
	        success: function (data) {
	        	$("#window_FileUpload").hide();
	        	$("#Result").removeClass("deactive");
	            console.log(data)
			    var img = new Image();
			    img.src="/result?filename="+data.filename;
			    img.onload = function () {
			        $("#Result").append($(img));
			    }
	        },
	        cache: false,
	        contentType: false,
	        processData: false
	    });

		return false;
	});

	$('.myUploader .simform').click(function () {
		console.log('ok');
		$('.myUploader input[type=file]').trigger('click');
		return false;
	});

	$('.myUploader .simform').on("dragenter dragstart dragend dragleave dragover drag drop", function (e) {
	    e.preventDefault();
	});

	var area = $('.myUploader .simform').get(0);
	area.ondragover = function () {
		$(area).addClass('hover');
		console.log('ondragover');
	}
	area.ondragleave = function () {
		$(area).removeClass('hover');
	}
	area.ondrop = function (event) {
		console.log('DROP');
		$(area).removeClass('hover');
		var file = event.dataTransfer.files[0];
		console.log(file)

		var formData = new FormData();
		formData.append("file", file);
	    $.ajax({
	        url: "/run",
	        type: 'POST',
	        data: formData,
	        async: false,
	        success: function (data) {
	        	$("#window_FileUpload").hide();
	        	$("#Result").removeClass("deactive");
	            console.log(data)
			    var img = new Image();
			    img.src="/result?filename="+data.filename;
			    img.onload = function () {
			        $("#Result").append($(img));
			    }
	        },
	        cache: false,
	        contentType: false,
	        processData: false
	    });
	}

	$("#InputFile").change( function (evt) {
		console.log("Change!");
		var formData = new FormData($("#UploadFileForm")[0]);
	    $.ajax({
	        url: "/run",
	        type: 'POST',
	        data: formData,
	        async: false,
	        success: function (data) {
	        	$("#window_FileUpload").hide();
	        	$("#Result").removeClass("deactive");
	            console.log(data)
			    var img = new Image();
			    img.src="/result?filename="+data.filename;
			    img.onload = function () {
			        $("#Result").append($(img));
			    }
	        },
	        cache: false,
	        contentType: false,
	        processData: false
	    });

		return false;
	})

});<commit_msg>asldhasld<commit_after>
$( document ).ready( function () {

	$("#ClickCamera").click( function () {
		// Grab elements, create settings, etc.
		var video = document.getElementById('video');

		// Get access to the camera!
		navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia || navigator.oGetUserMedia;
		if(navigator.getUserMedia) {
		    // Not adding `{ audio: true }` since we only want video now
		    navigator.getUserMedia({video: true}, function (stream){
		    	video.src = window.URL.createObjectURL(stream);
		    	video.play();
		    }, function () {

		    });
		} else {
			console.log('false video', navigator.mediaDevices, navigator.getUserMedia);
		}
	});
	$("#SnapPhoto").click(function () {
		var video = document.getElementById('video');
		var photo = document.getElementById('photo').getContext('2d');
		$("#dphoto").show();
		photo.drawImage(video, 0, 0, 580, 480);
		$(video).hide();
		$('#SnapPhoto').text("Отправить фото").addClass("SEND_PHOTO");
	});

	$("body").on('click', '.SEND_PHOTO', function () {
		var photo = document.getElementById('photo');
		var data = photo.toDataURL();
		console.log(data);

	    $.ajax({
	        url: "/run_base64",
	        type: 'POST',
	        data: {
	        	imgBase64: data
	        },
	        success: function (data) {
	        	$("#window_FileUpload").hide();
	        	$("#Result").removeClass("deactive");
	            console.log(data)
			    var img = new Image();
			    img.src="/result?filename="+data.filename+'.jpg';
			    img.onload = function () {
			        $("#Result").append($(img));
			    }
	        }
	    });
	});

	$("body").on("click", ".btn_route", function (evt) {
		var route = $(evt.target).attr('route');
		console.log(route);

		$('.windows').hide(400);
		$('#window_'+route).show(400);
	});

	// Перехват субмита форма
	$("#MainForm").submit( function (event) {

		console.log("Submit form!");

		var formData = new FormData($(this)[0]);
	    $.ajax({
	        url: "/run",
	        type: 'POST',
	        data: formData,
	        async: false,
	        success: function (data) {
	        	$("#window_FileUpload").hide();
	        	$("#Result").removeClass("deactive");
	            console.log(data)
			    var img = new Image();
			    img.src="/result?filename="+data.filename;
			    img.onload = function () {
			        $("#Result").append($(img));
			    }
	        },
	        cache: false,
	        contentType: false,
	        processData: false
	    });

		return false;
	});

	$('.myUploader .simform').click(function () {
		console.log('ok');
		$('.myUploader input[type=file]').trigger('click');
		return false;
	});

	$('.myUploader .simform').on("dragenter dragstart dragend dragleave dragover drag drop", function (e) {
	    e.preventDefault();
	});

	var area = $('.myUploader .simform').get(0);
	area.ondragover = function () {
		$(area).addClass('hover');
		console.log('ondragover');
	}
	area.ondragleave = function () {
		$(area).removeClass('hover');
	}
	area.ondrop = function (event) {
		console.log('DROP');
		$(area).removeClass('hover');
		var file = event.dataTransfer.files[0];
		console.log(file)

		var formData = new FormData();
		formData.append("file", file);
	    $.ajax({
	        url: "/run",
	        type: 'POST',
	        data: formData,
	        async: false,
	        success: function (data) {
	        	$("#window_FileUpload").hide();
	        	$("#Result").removeClass("deactive");
	            console.log(data)
			    var img = new Image();
			    img.src="/result?filename="+data.filename;
			    img.onload = function () {
			        $("#Result").append($(img));
			    }
	        },
	        cache: false,
	        contentType: false,
	        processData: false
	    });
	}

	$("#InputFile").change( function (evt) {
		console.log("Change!");
		var formData = new FormData($("#UploadFileForm")[0]);
	    $.ajax({
	        url: "/run",
	        type: 'POST',
	        data: formData,
	        async: false,
	        success: function (data) {
	        	$("#window_FileUpload").hide();
	        	$("#Result").removeClass("deactive");
	            console.log(data)
			    var img = new Image();
			    img.src="/result?filename="+data.filename;
			    img.onload = function () {
			        $("#Result").append($(img));
			    }
	        },
	        cache: false,
	        contentType: false,
	        processData: false
	    });

		return false;
	})

});<|endoftext|>


<commit_before>const { fromBuildIdentifier } = require('../../../src/api');

module.exports = {
  buildIdentifier: 'beta',
  makers: [],
  publishers: [],
  packagerConfig: { foo: 'bar', baz: {} },
  s3: {},
  electronReleaseServer: {},
  magicFn: () => 'magic result',
  topLevelProp: fromBuildIdentifier({ beta: 'foo' }),
  topLevelUndef: fromBuildIdentifier({ stable: 'heya' }),
  sub: {
    prop: {
      inArray: [
        fromBuildIdentifier({ beta: 'arr' }),
        'natural',
        'array',
      ],
      deep: {
        prop: fromBuildIdentifier({ beta: 'bar' }),
      },
    },
  },
};
<commit_msg>fix(core): fromBuildIdentifier moved to the utils object<commit_after>const { utils: { fromBuildIdentifier } } = require('../../../src/api');

module.exports = {
  buildIdentifier: 'beta',
  makers: [],
  publishers: [],
  packagerConfig: { foo: 'bar', baz: {} },
  s3: {},
  electronReleaseServer: {},
  magicFn: () => 'magic result',
  topLevelProp: fromBuildIdentifier({ beta: 'foo' }),
  topLevelUndef: fromBuildIdentifier({ stable: 'heya' }),
  sub: {
    prop: {
      inArray: [
        fromBuildIdentifier({ beta: 'arr' }),
        'natural',
        'array',
      ],
      deep: {
        prop: fromBuildIdentifier({ beta: 'bar' }),
      },
    },
  },
};
<|endoftext|>


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

/*
 * Contains functionality used to display a context menu in the chart in eventResultDashboard/showAll
 */

//= require bower_components/jQuery-contextMenu/dist/jquery.contextMenu.min.js

// context menu on all dots of all graphs
$(function () {
    $.contextMenu({
        selector: '.chart-context-menu',

        callback: function (key) {
            // rickshawGraphBuilder is in the global namespace and
            // nearestPoint is set in the update method of Rickshaw.Graph.HoverDetail
            var nearestPoint = rickshawGraphBuilder.graph.nearestPoint;

            // default action to be executed; open wpt of the dot/measurement in the corresponding view
            window.open(buildWptUrl(key, nearestPoint));
        },

        items: {
            "summary": {name: "Summary", icon: "fa-file-text-o"},
            "waterfallView": {name: "Waterfall", icon: "fa-bars"},
            "performanceReview": {name: "Performance Review", icon: "fa-check"},
            "contentBreakdown": {name: "Content Breakdown", icon: "fa-pie-chart"},
            "domains": {name: "Domains", icon: "fa-list"},
            "screenshot": {name: "Screen Shot", icon: "fa-picture-o"},
            "filmstrip": {name: "Filmstrip", icon: "fa-film"},
            "compare": {
                name: "Compare Filmstrips", icon: "fa-columns",
                // show only if at least one point is already selected
                visible: function () {
                    return rickshawGraphBuilder.graph.selectedPoints.length > 0;
                },
                callback: function (itemKey) {
                    // if current point is not selected yet, do it and then open the comparison view
                    if (isNotSelected(rickshawGraphBuilder.graph.nearestPoint)) {
                        selectPoint(rickshawGraphBuilder.graph.nearestPoint);
                    }
                    window.open(buildWptUrl(itemKey, rickshawGraphBuilder.graph.nearestPoint));
                }
            },
            separator: "-----",
            "selectPoint": {
                name: "Select Point", icon: "fa-dot-circle-o",
                // show only if point is not selected yet
                visible: function () {
                    return isNotSelected(rickshawGraphBuilder.graph.nearestPoint);
                },
                callback: function () {
                    selectPoint(rickshawGraphBuilder.graph.nearestPoint);
                }
            },
            "deselectPoint": {
                name: "Deselect Point", icon: "fa-trash-o",
                // show only if point is already selected
                visible: function () {
                    return !isNotSelected(rickshawGraphBuilder.graph.nearestPoint);
                },
                callback: function () {
                    deselectPoint(rickshawGraphBuilder.graph.nearestPoint);
                }
            }
        }
    });
});

// context menu on the rickshaw chart
$(function () {
    $.contextMenu({
        selector: '#rickshaw_chart',

        items: {
            "comparePoints": {
                name: "Compare Filmstrips",
                icon: "fa-columns",
                // show only if at least one point is already saved
                visible: function () {
                    return rickshawGraphBuilder.graph.selectedPoints.length > 1;
                },
                callback: function () {
                    window.open(buildWptUrl());
                }
            },
            "deselectAllPoints": {
                name: "Deselect all Points",
                icon: "fa-trash-o",
                // show only if at least one point is already saved
                visible: function () {
                    return rickshawGraphBuilder.graph.selectedPoints.length > 0;
                },
                callback: function () {
                    deselectAllPoints();
                }
            }
        }
    });
});

function buildWptUrl(wptView = null, nearestPoint = null) {
    var url = null;
    if (!nearestPoint || !wptView) {
        // build url for the comparison view launched from the chart context menu
        url = rickshawGraphBuilder.graph.selectedPoints[0].value.wptResultInfo.wptServerBaseurl.toString() +
            "video/compare.php?tests=" + comparingPartOfFilmstripsURL();
    } else {
        // build url for the comparison view launched from a aspecific point

        // get the wpt infos of the corresponding data point
        var wptServerBaseurl = nearestPoint.value.wptResultInfo.wptServerBaseurl.toString();
        var testId = nearestPoint.value.wptResultInfo.testId.toString();
        var numberOfWptRun = nearestPoint.value.wptResultInfo.numberOfWptRun.toString();
        var cachedView = nearestPoint.value.wptResultInfo.cachedView;
        var cached = null;
        var oneBaseStepIndexInJourney = nearestPoint.value.wptResultInfo.oneBaseStepIndexInJourney.toString();

        // build the url
        if (wptView == "compare") {
            url = wptServerBaseurl + "video/compare.php?tests=" + comparingPartOfFilmstripsURL();
        } else if (wptView == "filmstrip") {
            cached = cachedView ? "1" : "0";

            url = wptServerBaseurl + "video/compare.php?tests=" +
                testId +
                "-r:" + numberOfWptRun +
                "-c:" + cached +
                "-s:" + oneBaseStepIndexInJourney;
        } else {
            cached = cachedView ? "cached/" : "";

            url = wptServerBaseurl + "result/" + testId + "/" + cached;

            if (wptView == "summary") url += "#run";

            url += numberOfWptRun;

            switch (wptView) {
                case "summary":
                    url += "_step";
                    break;
                case "waterfallView":
                    url += "/details/#waterfall_view_step";
                    break;
                case "performanceReview":
                    url += "/performance_optimization/#review_step";
                    break;
                case "contentBreakdown":
                    url += "/breakdown/#breakdown_fv_step";
                    break;
                case "domains":
                    url += "/domains/#breakdown_fv_step";
                    break;
                case "screenshot":
                    url += "/screen_shot/#step_";
                    break;
                default:
                    alert("URL could not be configured. Please try again.");
                    return;
            }

            url += oneBaseStepIndexInJourney;
        }
    }

    return url;
}

function comparingPartOfFilmstripsURL() {
    var urlPart = "";
    rickshawGraphBuilder.graph.selectedPoints.forEach(function (point) {
        var testId = point.value.wptResultInfo.testId.toString();
        var numberOfWptRun = point.value.wptResultInfo.numberOfWptRun.toString();
        var cached = point.value.wptResultInfo.cachedView ? "1" : "0";
        var oneBaseStepIndexInJourney = point.value.wptResultInfo.oneBaseStepIndexInJourney.toString();

        urlPart += testId +
            "-r:" + numberOfWptRun +
            "-c:" + cached +
            "-s:" + oneBaseStepIndexInJourney + ",";
    });

    // return this part of the url, but delete the last unnecessary comma
    return urlPart.slice(0, -1);
}

function selectPoint(nearestPoint) {
    // selection is only possible if same server was used
    if (rickshawGraphBuilder.graph.selectedPoints.length > 0) {
        var server = rickshawGraphBuilder.graph.selectedPoints[0].value.wptResultInfo.wptServerBaseurl;

        if (server != nearestPoint.value.wptResultInfo.wptServerBaseurl) {
            alert("Multiple selection is only possible for measurements on the same server.");
            return;
        }
    }

    // create and save the html id for the dot in the 'rickshawGraphBuilder.graph.selectedPoints' datastructure
    var html_id = nearestPoint.html_id = "selected_dot_" + (rickshawGraphBuilder.graph.selectedPoints.length + 1).toString();
    // add the point to the datastructure
    rickshawGraphBuilder.graph.selectedPoints.push(nearestPoint);

    // create the html:
    // get the current dot and mark it as saved
    var activeDot = $('.dot.active')[0];
    $(activeDot).addClass('saved');
    // set an id for the ability to delete it individually
    $(activeDot).attr('id', html_id);

    // create the new dot and copy the styles of the active dot
    var newSavedDot = $(activeDot).clone();
    // get the distance to the left side
    var detailElement = $('.detail')[0];
    var left = $(detailElement).css("left");
    $(newSavedDot).css("left", left);

    // display the new saved dot in the chart
    var chart = $('#rickshaw_chart');
    $(chart).append(newSavedDot);
}

function isNotSelected(point) {
    var isNotSaved = true;
    rickshawGraphBuilder.graph.selectedPoints.forEach(function (savedPoint) {
        if (point.formattedXValue == savedPoint.formattedXValue &&
            point.formattedYValue == savedPoint.formattedYValue &&
            point.name == savedPoint.name) {
            isNotSaved = false;
        }
    });

    return isNotSaved;
}

function deselectPoint(point) {
    var itemToRemove = null;
    // get the current item in the datastructure
    rickshawGraphBuilder.graph.selectedPoints.forEach(function (savedPoint) {
        if (point.formattedXValue == savedPoint.formattedXValue &&
            point.formattedYValue == savedPoint.formattedYValue &&
            point.name == savedPoint.name) {
            itemToRemove = savedPoint;
        }
    });
    // delete the element from the datastructure
    rickshawGraphBuilder.graph.selectedPoints.splice(itemToRemove, 1);

    // remove the dot from the DOM
    var dot = document.getElementById(itemToRemove.html_id);
    dot.parentNode.removeChild(dot);
}

function deselectAllPoints() {
    // reset the point datastructure
    rickshawGraphBuilder.graph.selectedPoints = [];
    // delete the DOM elements
    var savedDots = document.getElementsByClassName('saved');
    while (savedDots[0]) {
        savedDots[0].parentNode.removeChild(savedDots[0]);
    }
}<commit_msg>[IT-1308] Select/deselect points on the graph with metaKey + click<commit_after>/*
 * OpenSpeedMonitor (OSM)
 * Copyright 2014 iteratec GmbH
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * 	http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * Contains functionality used to display a context menu in the chart in eventResultDashboard/showAll
 */

//= require bower_components/jQuery-contextMenu/dist/jquery.contextMenu.min.js

// context menu on all dots of all graphs
$(function () {
    $.contextMenu({
        selector: '.chart-context-menu',

        callback: function (key) {
            // rickshawGraphBuilder is in the global namespace and
            // nearestPoint is set in the update method of Rickshaw.Graph.HoverDetail
            var nearestPoint = rickshawGraphBuilder.graph.nearestPoint;

            // default action to be executed; open wpt of the dot/measurement in the corresponding view
            window.open(buildWptUrl(key, nearestPoint));
        },

        items: {
            "summary": {name: "Summary", icon: "fa-file-text-o"},
            "waterfallView": {name: "Waterfall", icon: "fa-bars"},
            "performanceReview": {name: "Performance Review", icon: "fa-check"},
            "contentBreakdown": {name: "Content Breakdown", icon: "fa-pie-chart"},
            "domains": {name: "Domains", icon: "fa-list"},
            "screenshot": {name: "Screen Shot", icon: "fa-picture-o"},
            "filmstrip": {name: "Filmstrip", icon: "fa-film"},
            "compare": {
                name: "Compare Filmstrips", icon: "fa-columns",
                // show only if at least one point is already selected
                visible: function () {
                    return rickshawGraphBuilder.graph.selectedPoints.length > 0;
                },
                callback: function (itemKey) {
                    // if current point is not selected yet, do it and then open the comparison view
                    if (isNotSelected(rickshawGraphBuilder.graph.nearestPoint)) {
                        selectPoint(rickshawGraphBuilder.graph.nearestPoint);
                    }
                    window.open(buildWptUrl(itemKey, rickshawGraphBuilder.graph.nearestPoint));
                }
            },
            separator: "-----",
            "selectPoint": {
                name: "Select Point", icon: "fa-dot-circle-o",
                // show only if point is not selected yet
                visible: function () {
                    return isNotSelected(rickshawGraphBuilder.graph.nearestPoint);
                },
                callback: function () {
                    selectPoint(rickshawGraphBuilder.graph.nearestPoint);
                }
            },
            "deselectPoint": {
                name: "Deselect Point", icon: "fa-trash-o",
                // show only if point is already selected
                visible: function () {
                    return !isNotSelected(rickshawGraphBuilder.graph.nearestPoint);
                },
                callback: function () {
                    deselectPoint(rickshawGraphBuilder.graph.nearestPoint);
                }
            }
        }
    });
});

// context menu on the rickshaw chart
$(function () {
    $.contextMenu({
        selector: '#rickshaw_chart',

        items: {
            "comparePoints": {
                name: "Compare Filmstrips",
                icon: "fa-columns",
                // show only if at least one point is already saved
                visible: function () {
                    return rickshawGraphBuilder.graph.selectedPoints.length > 1;
                },
                callback: function () {
                    window.open(buildWptUrl());
                }
            },
            "deselectAllPoints": {
                name: "Deselect all Points",
                icon: "fa-trash-o",
                // show only if at least one point is already saved
                visible: function () {
                    return rickshawGraphBuilder.graph.selectedPoints.length > 0;
                },
                callback: function () {
                    deselectAllPoints();
                }
            }
        }
    });
});

// select/deselect points on the graph with meta-key+click
$(function () {
    $('#rickshaw_main').on('click', '.chart-context-menu', function (event) {
        if (event.metaKey) {
            var nearestPoint = rickshawGraphBuilder.graph.nearestPoint;

            if (isNotSelected(nearestPoint)) {
                selectPoint(nearestPoint);
            } else {
                deselectPoint(nearestPoint)
            }

            event.preventDefault();
            return false;
        }
    });
});

function buildWptUrl(wptView = null, nearestPoint = null) {
    var url = null;
    if (!nearestPoint || !wptView) {
        // build url for the comparison view launched from the chart context menu
        url = rickshawGraphBuilder.graph.selectedPoints[0].value.wptResultInfo.wptServerBaseurl.toString() +
            "video/compare.php?tests=" + comparingPartOfFilmstripsURL();
    } else {
        // build url for the comparison view launched from a aspecific point

        // get the wpt infos of the corresponding data point
        var wptServerBaseurl = nearestPoint.value.wptResultInfo.wptServerBaseurl.toString();
        var testId = nearestPoint.value.wptResultInfo.testId.toString();
        var numberOfWptRun = nearestPoint.value.wptResultInfo.numberOfWptRun.toString();
        var cachedView = nearestPoint.value.wptResultInfo.cachedView;
        var cached = null;
        var oneBaseStepIndexInJourney = nearestPoint.value.wptResultInfo.oneBaseStepIndexInJourney.toString();

        // build the url
        if (wptView == "compare") {
            url = wptServerBaseurl + "video/compare.php?tests=" + comparingPartOfFilmstripsURL();
        } else if (wptView == "filmstrip") {
            cached = cachedView ? "1" : "0";

            url = wptServerBaseurl + "video/compare.php?tests=" +
                testId +
                "-r:" + numberOfWptRun +
                "-c:" + cached +
                "-s:" + oneBaseStepIndexInJourney;
        } else {
            cached = cachedView ? "cached/" : "";

            url = wptServerBaseurl + "result/" + testId + "/" + cached;

            if (wptView == "summary") url += "#run";

            url += numberOfWptRun;

            switch (wptView) {
                case "summary":
                    url += "_step";
                    break;
                case "waterfallView":
                    url += "/details/#waterfall_view_step";
                    break;
                case "performanceReview":
                    url += "/performance_optimization/#review_step";
                    break;
                case "contentBreakdown":
                    url += "/breakdown/#breakdown_fv_step";
                    break;
                case "domains":
                    url += "/domains/#breakdown_fv_step";
                    break;
                case "screenshot":
                    url += "/screen_shot/#step_";
                    break;
                default:
                    alert("URL could not be configured. Please try again.");
                    return;
            }

            url += oneBaseStepIndexInJourney;
        }
    }

    return url;
}

function comparingPartOfFilmstripsURL() {
    var urlPart = "";
    rickshawGraphBuilder.graph.selectedPoints.forEach(function (point) {
        var testId = point.value.wptResultInfo.testId.toString();
        var numberOfWptRun = point.value.wptResultInfo.numberOfWptRun.toString();
        var cached = point.value.wptResultInfo.cachedView ? "1" : "0";
        var oneBaseStepIndexInJourney = point.value.wptResultInfo.oneBaseStepIndexInJourney.toString();

        urlPart += testId +
            "-r:" + numberOfWptRun +
            "-c:" + cached +
            "-s:" + oneBaseStepIndexInJourney + ",";
    });

    // return this part of the url, but delete the last unnecessary comma
    return urlPart.slice(0, -1);
}

function selectPoint(nearestPoint) {
    // selection is only possible if same server was used
    if (rickshawGraphBuilder.graph.selectedPoints.length > 0) {
        var server = rickshawGraphBuilder.graph.selectedPoints[0].value.wptResultInfo.wptServerBaseurl;

        if (server != nearestPoint.value.wptResultInfo.wptServerBaseurl) {
            alert("Multiple selection is only possible for measurements on the same server.");
            return;
        }
    }

    // create and save the html id for the dot in the 'rickshawGraphBuilder.graph.selectedPoints' datastructure
    var html_id = nearestPoint.html_id = "selected_dot_" + (rickshawGraphBuilder.graph.selectedPoints.length + 1).toString();
    // add the point to the datastructure
    rickshawGraphBuilder.graph.selectedPoints.push(nearestPoint);

    // create the html:
    // get the current dot and mark it as saved
    var activeDot = $('.dot.active')[0];
    $(activeDot).addClass('saved');
    // set an id for the ability to delete it individually
    $(activeDot).attr('id', html_id);

    // create the new dot and copy the styles of the active dot
    var newSavedDot = $(activeDot).clone();
    // get the distance to the left side
    var detailElement = $('.detail')[0];
    var left = $(detailElement).css("left");
    $(newSavedDot).css("left", left);

    // display the new saved dot in the chart
    var chart = $('#rickshaw_chart');
    $(chart).append(newSavedDot);
}

function isNotSelected(point) {
    var isNotSaved = true;
    rickshawGraphBuilder.graph.selectedPoints.forEach(function (savedPoint) {
        if (point.formattedXValue == savedPoint.formattedXValue &&
            point.formattedYValue == savedPoint.formattedYValue &&
            point.name == savedPoint.name) {
            isNotSaved = false;
        }
    });

    return isNotSaved;
}

function deselectPoint(point) {
    var itemToRemove = null;
    // get the current item in the datastructure
    rickshawGraphBuilder.graph.selectedPoints.forEach(function (savedPoint) {
        if (point.formattedXValue == savedPoint.formattedXValue &&
            point.formattedYValue == savedPoint.formattedYValue &&
            point.name == savedPoint.name) {
            itemToRemove = savedPoint;
        }
    });
    // delete the element from the datastructure
    rickshawGraphBuilder.graph.selectedPoints.splice(itemToRemove, 1);

    // remove the dot from the DOM
    var dot = document.getElementById(itemToRemove.html_id);
    dot.parentNode.removeChild(dot);
}

function deselectAllPoints() {
    // reset the point datastructure
    rickshawGraphBuilder.graph.selectedPoints = [];
    // delete the DOM elements
    var savedDots = document.getElementsByClassName('saved');
    while (savedDots[0]) {
        savedDots[0].parentNode.removeChild(savedDots[0]);
    }
}<|endoftext|>