<commit_before>/**
 * All the actual functionality of the extension; loads as part of the background page.
 *
 * Active ingredient is enable(), which sets up the webRequest callbacks.
 *
 * */

allFilters = null;

function setFilters(newFilters) {
	allFilters = newFilters;
	localStorage["filters"] = JSON.stringify(newFilters);
}

// magic objects that the webRequest API interprets
// we turn images and iframes into innocuous no-ops, everything else gets outright "cancelled"
blockImagePayload = {redirectUrl: "data:image/gif;,"};
blockPagePayload = {redirectUrl: "about:blank"};
cancelPayload = {cancel: true};

// magic callbacks to deliver the abovementioned magic objects:
function blockImage(details) {
	return blockImagePayload;
}

function blockPage(details) {
	return blockPagePayload;
}

function blockObject(details) {
	return cancelPayload;
}

// types of object and callbacks to remove them:
listenerCallbacks = [
	[["image"], blockImage],
	[["sub_frame"], blockPage],
	[["main_frame", "object", "script", "xmlhttprequest", "stylesheet", "other"], blockObject]
]

// global on/off state
blockingEnabled = false;

// register all callbacks
function enable(icon = true) {
	if (blockingEnabled) {
		return;
	}

	// edge case: enabling with urls == [] will block *all* URLs,
	// rather than none of them
	if (allFilters.length > 0) {
		for (var j in listenerCallbacks) {
			var types = listenerCallbacks[j][0];
			var callback = listenerCallbacks[j][1];
			chrome.webRequest.onBeforeRequest.addListener(
				callback,
				{urls: allFilters, types: types},
				// blocks the request until processed; needed to cancel/redir
				["blocking"]
			);
		}
	}

	blockingEnabled = true;
	if (icon) {
		chrome.browserAction.setIcon({path: "enabled.png"});
	}
}

// unregister all callbacks
function disable(icon = true) {
	for (var j in listenerCallbacks) {
		var callback = listenerCallbacks[j][1];
		chrome.webRequest.onBeforeRequest.removeListener(callback);
	}

	blockingEnabled = false;
	if (icon) {
		chrome.browserAction.setIcon({path: "disabled.png"});
	}
}

// power-cycle
function refreshFilters() {
	// work around some weird Chrome issue. seems like: on first load,
	// if you call setIcon twice in a row, the second call is ignored (?)
	disable(false);
	enable(true);
}

// switch-flip
function toggleEnabled() {
	if (blockingEnabled) {
		disable();
	} else {
		enable();
	}
}

// Initialization.

if (localStorage["filters"] == undefined) {
	console.log("Initializing filters to defaults.");
	setFilters(defaultFilters);
} else {
	allFilters = JSON.parse(localStorage["filters"]);
}

// toggle blocking on-off via the extension icon in the Omnibar
chrome.browserAction.onClicked.addListener(toggleEnabled);

// main screen turn on
enable();
<commit_msg>go back to a 1x1 transparent gif<commit_after>/**
 * All the actual functionality of the extension; loads as part of the background page.
 *
 * Active ingredient is enable(), which sets up the webRequest callbacks.
 *
 * */

allFilters = null;

function setFilters(newFilters) {
	allFilters = newFilters;
	localStorage["filters"] = JSON.stringify(newFilters);
}

// magic objects that the webRequest API interprets
// we turn images and iframes into innocuous no-ops, everything else gets outright "cancelled"
blockImagePayload = {redirectUrl: "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEAAAAALAAAAAABAAEAAAI="};
blockPagePayload = {redirectUrl: "about:blank"};
cancelPayload = {cancel: true};

// magic callbacks to deliver the abovementioned magic objects:
function blockImage(details) {
	return blockImagePayload;
}

function blockPage(details) {
	return blockPagePayload;
}

function blockObject(details) {
	return cancelPayload;
}

// types of object and callbacks to remove them:
listenerCallbacks = [
	[["image"], blockImage],
	[["sub_frame"], blockPage],
	[["main_frame", "object", "script", "xmlhttprequest", "stylesheet", "other"], blockObject]
]

// global on/off state
blockingEnabled = false;

// register all callbacks
function enable(icon = true) {
	if (blockingEnabled) {
		return;
	}

	// edge case: enabling with urls == [] will block *all* URLs,
	// rather than none of them
	if (allFilters.length > 0) {
		for (var j in listenerCallbacks) {
			var types = listenerCallbacks[j][0];
			var callback = listenerCallbacks[j][1];
			chrome.webRequest.onBeforeRequest.addListener(
				callback,
				{urls: allFilters, types: types},
				// blocks the request until processed; needed to cancel/redir
				["blocking"]
			);
		}
	}

	blockingEnabled = true;
	if (icon) {
		chrome.browserAction.setIcon({path: "enabled.png"});
	}
}

// unregister all callbacks
function disable(icon = true) {
	for (var j in listenerCallbacks) {
		var callback = listenerCallbacks[j][1];
		chrome.webRequest.onBeforeRequest.removeListener(callback);
	}

	blockingEnabled = false;
	if (icon) {
		chrome.browserAction.setIcon({path: "disabled.png"});
	}
}

// power-cycle
function refreshFilters() {
	// work around some weird Chrome issue. seems like: on first load,
	// if you call setIcon twice in a row, the second call is ignored (?)
	disable(false);
	enable(true);
}

// switch-flip
function toggleEnabled() {
	if (blockingEnabled) {
		disable();
	} else {
		enable();
	}
}

// Initialization.

if (localStorage["filters"] == undefined) {
	console.log("Initializing filters to defaults.");
	setFilters(defaultFilters);
} else {
	allFilters = JSON.parse(localStorage["filters"]);
}

// toggle blocking on-off via the extension icon in the Omnibar
chrome.browserAction.onClicked.addListener(toggleEnabled);

// main screen turn on
enable();
<|endoftext|>


<commit_before>import _ from 'lodash';
import fs from 'fs';
import createJSON from './_jsonCreator';
import EventEmitter from 'events';

class PlaybackAPI extends EventEmitter {
  constructor() {
    super();

    this.PATH = createJSON('playback');
    this.reset();
    this._save();
    if (Settings.get('enableJSONApi', true)) {
      // DEV: Handle windows users running as admin...
      fs.chmodSync(this.PATH, '777');
    }

    this._hook();
  }

  _hook() {
    Emitter.on('change:track', (event, details) => {
      this._setPlaybackSong(details.title, details.artist, details.album, details.albumArt);
    });

    Emitter.on('playback:isPlaying', this._setPlaying.bind(this, true));
    Emitter.on('playback:isPaused', this._setPlaying.bind(this, false));
    Emitter.on('playback:isStopped', this._setPlaying.bind(this, false));

    Emitter.on('change:playback-time', (event, timeObj) => this._setTime(timeObj.current, timeObj.total));
    // we throttle this function because of a bug in gmusic.js
    // ratings are received multiple times here in a couple of ms
    // to avoid writing the file 5+ times we throttle it to 500ms max
    Emitter.on('change:rating', _.throttle((event, details) => this._setRating(details), 500));
    Emitter.on('change:shuffle', _.throttle((event, mode) => this._setShuffle(mode)), 20);
    Emitter.on('change:repeat', _.throttle((event, mode) => this._setRepeat(mode)), 20);
    Emitter.on('change:playlists', _.throttle((event, playlists) => this._setPlaylists(playlists)), 20);
    Emitter.on('change:queue', _.throttle((event, queue) => this._setQueue(queue)), 20);
    Emitter.on('change:search-results', _.throttle((event, results) => this._setResults(results)), 20);
  }

  reset() {
    this.data = {
      playing: false,
      song: {
        title: null,
        artist: null,
        album: null,
        albumArt: null,
      },
      rating: {
        liked: false,
        disliked: false,
      },
      time: {
        current: 0,
        total: 0,
      },
      songLyrics: null,
      shuffle: 'NO_SHUFFLE',
      repeat: 'NO_REPEAT',
    };
    this._private_data = {
      playlists: [],
      queue: [],
      results: {
        searchText: '',
        artists: [],
        albums: [],
        tracks: [],
      },
    };
    this._save();
  }

  _save() {
    if (Settings.get('enableJSON_API', true)) {
      fs.writeFileSync(this.PATH, JSON.stringify(this.data, null, 4));
    }
  }

  _setPlaying(isPlaying) {
    this.data.playing = isPlaying;
    this._fire('change:state', isPlaying);
    this._save();
  }

  _setPlaybackSong(title, artist, album, albumArt) {
    const fullSizeAlbumArt = albumArt.replace(/=s90-c-e100$/g, '');
    this.data.song = {
      title,
      artist,
      album,
      albumArt: fullSizeAlbumArt,
    };
    this._resetRating();
    this.data.songLyrics = null;
    this._fire('change:track', this.data.song);
    this._fire('change:lyrics', this.data.songLyrics);
    this._save();
  }

  _setPlaylists(playlists) {
    this._private_data.playlists = playlists;
    this._fire('change:playlists', this._private_data.playlists);
  }

  _setQueue(queue) {
    this._private_data.queue = queue;
    this._fire('change:queue', this._private_data.queue);
  }

  _setRating(rating) {
    this.data.rating.liked = rating === '5';
    this.data.rating.disliked = rating === '1';
    this._fire('change:rating', this.data.rating);
    this._save();
  }

  _resetRating() {
    this.data.rating.liked = false;
    this.data.rating.disliked = false;
  }

  _setPlaybackSongLyrics(lyricString) {
    this.data.songLyrics = lyricString;
    this._fire('change:lyrics', this.data.songLyrics);
    this._save();
  }

  _setShuffle(mode) {
    this.data.shuffle = mode;
    this._fire('change:shuffle', this.data.shuffle);
    this._save();
  }

  _setRepeat(mode) {
    this.data.repeat = mode;
    this._fire('change:repeat', this.data.repeat);
    this._save();
  }

  _setResults(results) {
    this._private_data.results = results;
    this._fire('change:search-results', this._private_data.results);
  }

  _setTime(current, total) {
    const totalTime = total || this.data.time.total;
    this.data.time = {
      current,
      total: totalTime,
    };
    this._fire('change:time', this.data.time);
    this._save();
  }

  isPlaying() {
    return this.data.playing;
  }

  currentRepeat() {
    return this.data.repeat;
  }

  currentShuffle() {
    return this.data.shuffle;
  }

  currentSong(force) {
    return (this.data.playing || force) ? this.data.song : null;
  }

  currentSongLyrics(force) {
    return (this.data.playing || force) ? this.data.songLyrics : null;
  }

  currentTime() {
    return this.data.time;
  }

  getPlaylists() {
    return this._private_data.playlists;
  }

  getQueue() {
    return this._private_data.queue;
  }

  getResults() {
    return this._private_data.results;
  }

  _fire(what, arg) {
    this.emit(what, arg);
    Emitter.sendToWindowsOfName('main', `PlaybackAPI:${what}`, arg);
  }
}

export default PlaybackAPI;
<commit_msg>Fix import ordering<commit_after>import _ from 'lodash';
import EventEmitter from 'events';
import fs from 'fs';

import createJSON from './_jsonCreator';

class PlaybackAPI extends EventEmitter {
  constructor() {
    super();

    this.PATH = createJSON('playback');
    this.reset();
    this._save();
    if (Settings.get('enableJSONApi', true)) {
      // DEV: Handle windows users running as admin...
      fs.chmodSync(this.PATH, '777');
    }

    this._hook();
  }

  _hook() {
    Emitter.on('change:track', (event, details) => {
      this._setPlaybackSong(details.title, details.artist, details.album, details.albumArt);
    });

    Emitter.on('playback:isPlaying', this._setPlaying.bind(this, true));
    Emitter.on('playback:isPaused', this._setPlaying.bind(this, false));
    Emitter.on('playback:isStopped', this._setPlaying.bind(this, false));

    Emitter.on('change:playback-time', (event, timeObj) => this._setTime(timeObj.current, timeObj.total));
    // we throttle this function because of a bug in gmusic.js
    // ratings are received multiple times here in a couple of ms
    // to avoid writing the file 5+ times we throttle it to 500ms max
    Emitter.on('change:rating', _.throttle((event, details) => this._setRating(details), 500));
    Emitter.on('change:shuffle', _.throttle((event, mode) => this._setShuffle(mode)), 20);
    Emitter.on('change:repeat', _.throttle((event, mode) => this._setRepeat(mode)), 20);
    Emitter.on('change:playlists', _.throttle((event, playlists) => this._setPlaylists(playlists)), 20);
    Emitter.on('change:queue', _.throttle((event, queue) => this._setQueue(queue)), 20);
    Emitter.on('change:search-results', _.throttle((event, results) => this._setResults(results)), 20);
  }

  reset() {
    this.data = {
      playing: false,
      song: {
        title: null,
        artist: null,
        album: null,
        albumArt: null,
      },
      rating: {
        liked: false,
        disliked: false,
      },
      time: {
        current: 0,
        total: 0,
      },
      songLyrics: null,
      shuffle: 'NO_SHUFFLE',
      repeat: 'NO_REPEAT',
    };
    this._private_data = {
      playlists: [],
      queue: [],
      results: {
        searchText: '',
        artists: [],
        albums: [],
        tracks: [],
      },
    };
    this._save();
  }

  _save() {
    if (Settings.get('enableJSON_API', true)) {
      fs.writeFileSync(this.PATH, JSON.stringify(this.data, null, 4));
    }
  }

  _setPlaying(isPlaying) {
    this.data.playing = isPlaying;
    this._fire('change:state', isPlaying);
    this._save();
  }

  _setPlaybackSong(title, artist, album, albumArt) {
    const fullSizeAlbumArt = albumArt.replace(/=s90-c-e100$/g, '');
    this.data.song = {
      title,
      artist,
      album,
      albumArt: fullSizeAlbumArt,
    };
    this._resetRating();
    this.data.songLyrics = null;
    this._fire('change:track', this.data.song);
    this._fire('change:lyrics', this.data.songLyrics);
    this._save();
  }

  _setPlaylists(playlists) {
    this._private_data.playlists = playlists;
    this._fire('change:playlists', this._private_data.playlists);
  }

  _setQueue(queue) {
    this._private_data.queue = queue;
    this._fire('change:queue', this._private_data.queue);
  }

  _setRating(rating) {
    this.data.rating.liked = rating === '5';
    this.data.rating.disliked = rating === '1';
    this._fire('change:rating', this.data.rating);
    this._save();
  }

  _resetRating() {
    this.data.rating.liked = false;
    this.data.rating.disliked = false;
  }

  _setPlaybackSongLyrics(lyricString) {
    this.data.songLyrics = lyricString;
    this._fire('change:lyrics', this.data.songLyrics);
    this._save();
  }

  _setShuffle(mode) {
    this.data.shuffle = mode;
    this._fire('change:shuffle', this.data.shuffle);
    this._save();
  }

  _setRepeat(mode) {
    this.data.repeat = mode;
    this._fire('change:repeat', this.data.repeat);
    this._save();
  }

  _setResults(results) {
    this._private_data.results = results;
    this._fire('change:search-results', this._private_data.results);
  }

  _setTime(current, total) {
    const totalTime = total || this.data.time.total;
    this.data.time = {
      current,
      total: totalTime,
    };
    this._fire('change:time', this.data.time);
    this._save();
  }

  isPlaying() {
    return this.data.playing;
  }

  currentRepeat() {
    return this.data.repeat;
  }

  currentShuffle() {
    return this.data.shuffle;
  }

  currentSong(force) {
    return (this.data.playing || force) ? this.data.song : null;
  }

  currentSongLyrics(force) {
    return (this.data.playing || force) ? this.data.songLyrics : null;
  }

  currentTime() {
    return this.data.time;
  }

  getPlaylists() {
    return this._private_data.playlists;
  }

  getQueue() {
    return this._private_data.queue;
  }

  getResults() {
    return this._private_data.results;
  }

  _fire(what, arg) {
    this.emit(what, arg);
    Emitter.sendToWindowsOfName('main', `PlaybackAPI:${what}`, arg);
  }
}

export default PlaybackAPI;
<|endoftext|>


<commit_before>/** @jsx React.DOM */

/*
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

/*
 * Copyright (c) 2014, Joyent, Inc.
 */
"use strict";

var Backbone = require('backbone');
var _ = require('underscore');

var React = require('react');

var NicConfigComponent = React.createFactory(require('../components/nic-config'));

var JobProgress = require('./job-progress');

var VMNicForm = Backbone.Marionette.ItemView.extend({
    template: require('../tpl/vm-nic-form.hbs'),
    id: 'vm-nic-form',
    attributes: {
        'class': 'modal'
    },
    events: {
        'click button[type=submit]': 'onSubmit'
    },

    initialize: function(options) {
        if (! this.model) {
            this.model = new Backbone.Model();
        }
        this.vm = options.vm;
    },

    onSubmit: function() {
        var self = this;
        var vm = this.vm;
        var nic = this.nicConfig.getValue();
        nic.uuid = nic.network_uuid;
        delete nic.network_uuid;

        if (! nic.mac) {
            vm.addNics([nic], function(err, job) {
                if (err) {
                    window.alert('Error adding network interface ' + err);
                    return;
                }
                self.$el.modal('hide').remove();
                var view = new JobProgress({ model: job });
                view.show();

                self.listenTo(view, 'execution', function(st) {
                    if (st === 'succeeded') {
                        vm.fetch();
                    }
                });
            });
        } else {
            var nics = vm.get('nics');
            if (nic.primary) {
                nics = nics.map(function(n) {
                    delete n.primary;
                    return n;
                });
            }

            var existingNic = _.findWhere(nics, {mac: nic.mac});

            if (existingNic) {
                _.extend(existingNic, nic);
            } else {
                nics.push(nic);
            }
            nics = nics.map(function(n) {
                delete n.vlan_id;
                delete n.nic_tag;
                delete n.ip;
                delete n.netmask;
                delete n.state;
                delete n.belongs_to_type;
                delete n.belongs_to_uuid;
                delete n.gateway;
                delete n.resolvers;
                delete n.network_uuid;
                delete n.owner_uuid;
                delete n.uuid;
                return n;
            });

            vm.updateNics(nics, function(err, job) {
                if (err) {
                    window.alert('Error updating network interfaces ' + err);
                    return;
                }
                self.$el.modal('hide').remove();
                var view = new JobProgress({
                    model: job
                });
                view.show();
                self.listenTo(view, 'execution', function(st) {
                    if (st === 'succeeded') {
                        vm.fetch();
                    }
                });
            });
        }
    },

    disableButtons: function() {
        this.$('button[type=submit]').prop('disabled', true);
    },

    enableButtons: function() {
        this.$('button[type=submit]').prop('disabled', false);
    },

    onNicPropertyChange: function(prop, value, nic) {
        if (nic.network_uuid) {
            this.enableButtons();
        } else {
            this.disableButtons();
        }
    },

    onRender: function() {
        this.nicConfig = React.render(
            new NicConfigComponent({
                nic: this.model.toJSON(),
                readonlyNetwork: true,
                expandAntispoofOptions: false,
                onPropertyChange: this.onNicPropertyChange.bind(this)
            }),
            this.$('.nic-config-component').get(0));

        this.$el.modal().on('hidden', this.remove.bind(this));
        this.$el.modal('show');
        this.disableButtons();
    }
});

module.exports = VMNicForm;
<commit_msg>ADMINUI-1937 add nic to vm missing networks<commit_after>/** @jsx React.DOM */

/*
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

/*
 * Copyright (c) 2014, Joyent, Inc.
 */
"use strict";

var Backbone = require('backbone');
var _ = require('underscore');

var React = require('react');

var NicConfigComponent = React.createFactory(require('../components/nic-config'));

var JobProgress = require('./job-progress');

var VMNicForm = Backbone.Marionette.ItemView.extend({
    template: require('../tpl/vm-nic-form.hbs'),
    id: 'vm-nic-form',
    attributes: {
        'class': 'modal'
    },
    events: {
        'click button[type=submit]': 'onSubmit'
    },

    initialize: function(options) {
        if (! this.model) {
            this.model = new Backbone.Model();
        }
        this.vm = options.vm;
    },

    onSubmit: function() {
        var self = this;
        var vm = this.vm;
        var nic = this.nicConfig.getValue();
        nic.uuid = nic.network_uuid;
        delete nic.network_uuid;

        if (! nic.mac) {
            vm.addNics([nic], function(err, job) {
                if (err) {
                    window.alert('Error adding network interface ' + err);
                    return;
                }
                self.$el.modal('hide').remove();
                var view = new JobProgress({ model: job });
                view.show();

                self.listenTo(view, 'execution', function(st) {
                    if (st === 'succeeded') {
                        vm.fetch();
                    }
                });
            });
        } else {
            var nics = vm.get('nics');
            if (nic.primary) {
                nics = nics.map(function(n) {
                    delete n.primary;
                    return n;
                });
            }

            var existingNic = _.findWhere(nics, {mac: nic.mac});

            if (existingNic) {
                _.extend(existingNic, nic);
            } else {
                nics.push(nic);
            }
            nics = nics.map(function(n) {
                delete n.vlan_id;
                delete n.nic_tag;
                delete n.ip;
                delete n.netmask;
                delete n.state;
                delete n.belongs_to_type;
                delete n.belongs_to_uuid;
                delete n.gateway;
                delete n.resolvers;
                delete n.network_uuid;
                delete n.owner_uuid;
                delete n.uuid;
                return n;
            });

            vm.updateNics(nics, function(err, job) {
                if (err) {
                    window.alert('Error updating network interfaces ' + err);
                    return;
                }
                self.$el.modal('hide').remove();
                var view = new JobProgress({
                    model: job
                });
                view.show();
                self.listenTo(view, 'execution', function(st) {
                    if (st === 'succeeded') {
                        vm.fetch();
                    }
                });
            });
        }
    },

    disableButtons: function() {
        this.$('button[type=submit]').prop('disabled', true);
    },

    enableButtons: function() {
        this.$('button[type=submit]').prop('disabled', false);
    },

    onNicPropertyChange: function(prop, value, nic) {
        if (nic.network_uuid) {
            this.enableButtons();
        } else {
            this.disableButtons();
        }
    },

    onRender: function() {
        this.nicConfig = React.render(
            new NicConfigComponent({
                nic: this.model.toJSON(),
                readonlyNetwork: !this.model.isNew(),
                expandAntispoofOptions: false,
                onPropertyChange: this.onNicPropertyChange.bind(this)
            }),
            this.$('.nic-config-component').get(0));

        this.$el.modal().on('hidden', this.remove.bind(this));
        this.$el.modal('show');
        this.disableButtons();
    }
});

module.exports = VMNicForm;
<|endoftext|>


<commit_before>if (!window.wps) {
  window.wps = {};
}
var wps = window.wps;

wps.process = function(options) {
  this.client = null;
  this.server = null;
  this.identifier = null;
  this.description = null;
  this.localWPS = 'http://geoserver/wps';
  this.chained = 0;
  for (var prop in options)   {
    if (this.hasOwnProperty(prop)) {
      this[prop] = options[prop];
    }
  }
  this.executeCallbacks = [];
  this.formats = [{
    mimeType: 'application/wkt',
    format: new ol.format.WKT()
  }, {
    mimeType: 'application/json',
    format: new ol.format.GeoJSON()
  }];
};

wps.process.prototype.describe = function(options) {
  options = options || {};
  if (!this.description) {
    this.client.describeProcess(this.server, this.identifier, function(description) {
      if (!this.description) {
        this.parseDescription(description);
      }
      if (options.callback) {
        options.callback.call(options.scope, this.description);
      }
    }, this);
  } else if (options.callback) {
    var description = this.description;
    window.setTimeout(function() {
      options.callback.call(options.scope, description);
    }, 0);
  }
};

// check the values against the required inputs
wps.process.prototype.isComplete = function(values) {
  if (this.description) {
    var hasUndefined = false;
    var inputs = this.description.dataInputs.input;
    for (var i=0, ii=inputs.length; i<ii; ++i) {
      var input = inputs[i];
      // TODO do we have processes where the same input needs more than 1?
      if (input.minOccurs > 0) {
        if (values[input.identifier.value] === undefined) {
          hasUndefined = true;
          break;
        }
      }
    }
    return !hasUndefined;
  } else {
    return false;
  }
};

wps.process.prototype.configure = function(options) {
  this.describe({
    callback: function() {
      var info = {
        name: {
          localPart: "Execute",
          namespaceURI: "http://www.opengis.net/wps/1.0.0"
        },
        value: {
          service: "WPS",
          version: "1.0.0",
          identifier: {
            value: this.description.identifier.value
          },
          dataInputs: {
            input: []
          }
        }
      };
      var description = this.description,
        inputs = options.inputs,
        input, i, ii;
      for (i=0, ii=description.dataInputs.input.length; i<ii; ++i) {
        input = description.dataInputs.input[i];
        if (inputs[input.identifier.value] !== undefined) {
          this.setInputData(info, input, inputs[input.identifier.value]);
        }
      }
      if (options.callback) {
        options.callback.call(options.scope, info);
      }
    },
    scope: this
  });
  return this;
};

wps.process.prototype.execute = function(options) {
  this.configure({
    inputs: options.inputs,
    callback: function(info) {
      var me = this;
      //TODO For now we only deal with a single output
      var outputIndex = this.getOutputIndex(
        me.description.processOutputs.output, options.output);
      me.setResponseForm(info, {outputIndex: outputIndex});
      (function callback() {
        var idx = me.executeCallbacks.indexOf(callback);
        if (idx > -1) {
          me.executeCallbacks.splice(idx, 1);
        }
        if (me.chained !== 0) {
          // need to wait until chained processes have a
          // description and configuration - see chainProcess
          me.executeCallbacks.push(callback);
          return;
        }
        // all chained processes are added as references now, so
        // let's proceed.
        var xmlhttp = new XMLHttpRequest();
        xmlhttp.open('POST', me.client.servers[me.server].url, true);
        xmlhttp.setRequestHeader('Content-type', 'application/xml');
        xmlhttp.onload = function() {
          var output = me.description.processOutputs.output[outputIndex];
          var result;
          if (output.literalOutput) {
            if (output.literalOutput.dataType === "boolean") {
              result = (this.responseText.trim().toLowerCase() === 'true');
            } else if (output.literalOutput.dataType === "double") {
              result = parseFloat(this.responseText);
            } else {
              result = this.responseText;
            }
          } else if (output.complexOutput) {
            var mimeType = me.findMimeType(output.complexOutput.supported.format);
            //TODO For now we assume a spatial output if complexOutput
            for (var i=0, ii=me.formats.length; i<ii; ++i) {
              if (me.formats[i].mimeType === mimeType) {
                result = me.formats[i].format.readFeatures(this.responseText);
                break;
              }
            }
          }
          if (options.success) {
            var outputs = {};
            outputs[options.output || 'result'] = result;
            options.success.call(options.scope, outputs);
          }
        };
        xmlhttp.send(me.client.marshaller.marshalString(info));
      })();
    },
    scope: this
  });
};

wps.process.prototype.output = function(identifier) {
  return new wps.process.chainlink({
    process: this,
    output: identifier
  });
};

wps.process.prototype.parseDescription = function(description) {
  var server = this.client.servers[this.server];
  this.description = this.client.unmarshaller.unmarshalString(
    server.processDescription[this.identifier]).value.processDescription[0];
};

wps.process.prototype.setInputData = function(info, input, data) {
  var inputs = info.value.dataInputs.input;
  if (data instanceof wps.process.chainlink) {
    ++this.chained;
    input.reference = {
      method: 'POST',
      href: data.process.server === this.server ?
        this.localWPS : this.client.servers[data.process.server].url
    };
    data.process.describe({
      callback: function() {
        --this.chained;
        this.chainProcess(info, input, data);
      },
      scope: this
    });
  } else {
    var complexData = input.complexData;
    if (complexData) {
      var format = this.findMimeType(complexData.supported.format);
      var content;
      for (var i=0, ii=this.formats.length; i<ii; ++i) {
        if (this.formats[i].mimeType === format) {
          content = this.formats[i].format.writeFeatures(this.toFeatures(data));
          break;
        }
      }
      inputs.push({
        identifier: {
          value: input.identifier.value
        },
        data: {
          complexData: {
            mimeType: format,
            content: [content]
          }
        }
      });
    } else {
      inputs.push({
        identifier: {
          value: input.identifier.value
        },
        data: {
          literalData: {
            value: data
          }
        }
      });
    }
  }
};

wps.process.prototype.setResponseForm = function(info, options) {
  options = options || {};
  var output = this.description.processOutputs.output[options.outputIndex || 0];
  var mimeType;
  if (output.complexOutput) {
    mimeType = this.findMimeType(output.complexOutput.supported.format, options.supportedFormats);
  }
  info.value.responseForm = {
    rawDataOutput: {
      identifier: {
        value: output.identifier.value
      },
      mimeType: mimeType
    }
  };
};

wps.process.prototype.getOutputIndex = function(outputs, identifier) {
  var output;
  if (identifier) {
    for (var i=outputs.length-1; i>=0; --i) {
      if (outputs[i].identifier.value === identifier) {
        output = i;
        break;
      }
    }
  } else {
    output = 0;
  }
  return output;
};

wps.process.prototype.chainProcess = function(info, input, chainLink) {
  var output = this.getOutputIndex(
    chainLink.process.description.processOutputs.output, chainLink.output);
  input.reference.mimeType = this.findMimeType(
    input.complexData.supported.format,
    chainLink.process.description.processOutputs.output[output].complexOutput.supported.format);
  var formats = {};
  formats[input.reference.mimeType] = true;
  chainLink.process.setResponseForm(info, {
    outputIndex: output,
    supportedFormats: formats
  });
  input.reference.body = chainLink.process.description;
  while (this.executeCallbacks.length > 0) {
    this.executeCallbacks[0]();
  }
};

wps.process.prototype.toFeatures = function(source) {
  var isArray = toString.call(source) === "[object Array]";
  if (!isArray) {
    source = [source];
  }
  return source;
};

wps.process.prototype.findMimeType = function(sourceFormats, targetFormats) {
  targetFormats = targetFormats || this.formats;
  for (var i=0, ii=sourceFormats.length; i<ii; ++i) {
    var f = sourceFormats[i].mimeType;
    for (var j=0, jj=targetFormats.length; j<jj; ++j) {
      if (targetFormats[j].mimeType === f) {
        return f;
      }
    }
  }
  return null;
};

wps.process.chainlink = function(options) {
  this.process = null;
  this.output = null;
  for (var prop in options)   {
    if (this.hasOwnProperty(prop)) {
      this[prop] = options[prop];
    }
  }
};

wps.client = function(options) {
  this.context = new Jsonix.Context([OWS_V_1_1_0, WPS_V_1_0_0]);
  this.unmarshaller = this.context.createUnmarshaller();
  this.marshaller = this.context.createMarshaller();
  this.version = options.version || "1.0.0";
  this.lazy = options.lazy !== undefined ? options.lazy : false;
  this.servers = {};
  for (var s in options.servers) {
    this.servers[s] = typeof options.servers[s] == 'string' ? {
      url: options.servers[s],
      version: this.version,
      processDescription: {}
    } : options.servers[s];
  }
};

wps.client.prototype.execute = function(options) {
  var process = this.getProcess(options.server, options.process);
  process.execute({
    inputs: options.inputs,
    success: options.success,
    scope: options.scope
  });
};

wps.client.prototype.getProcess = function(serverID, processID, options) {
  var process = new wps.process({
    client: this,
    server: serverID,
    identifier: processID
  });
  if (!this.lazy) {
    process.describe(options);
  }
  return process;
};

wps.client.prototype.getGroupedProcesses = function(serverID, callback) {
  var server = this.servers[serverID];
  var xmlhttp = new XMLHttpRequest();
  var url = server.url + '?service=WPS&VERSION=' + server.version + '&request=GetCapabilities';
  var me = this;
  xmlhttp.open("GET", url, true);
  xmlhttp.onload = function() {
    var info = me.unmarshaller.unmarshalDocument(this.responseXML).value;
    var groups = {};
    for (var i=0, ii=info.processOfferings.process.length; i<ii; ++i) {
      var key = info.processOfferings.process[i].identifier.value;
      var names = key.split(':');
      var group = names[0];
      if (!groups[group]) {
        groups[group] = [];
      }
      groups[group].push({name: names[1], value: info.processOfferings.process[i]});
    }
    callback.call(me, groups);
  };
  xmlhttp.send();
};

wps.client.prototype.describeProcess = function(serverID, processID, callback, scope) {
  var server = this.servers[serverID];
  if (!server.processDescription[processID]) {
    if (!(processID in server.processDescription)) {
      // set to null so we know a describeFeature request is pending
      server.processDescription[processID] = null;
      var xmlhttp = new XMLHttpRequest();
      var url = server.url + '?service=WPS&VERSION=' + server.version + '&request=DescribeProcess&identifier=' + processID;
      xmlhttp.open("GET", url, true);
      var me = this;
      xmlhttp.onload = function() {
        server.processDescription[processID] = this.responseText;
        var evt = document.createEvent("Event");
        evt.initEvent("describeprocess", true, false);
        evt.identifier = processID;
        evt.raw = this.responseText;
        // TODO is there a better target than document?
        document.dispatchEvent(evt);
        callback.call(scope, this.responseText);
      };
      xmlhttp.send();
    } else {
      // pending request
      document.addEventListener("describeprocess", function describe(evt) {
        if (evt.identifier === processID) {
          this.events.unregister('describeprocess', this, describe);
          callback.call(scope, evt.raw);
        }
      }, true);
    }
  } else {
    window.setTimeout(function() {
      callback.call(scope, server.processDescription[processID]);
    }, 0);
  }
};

<commit_msg>move Execute part to the execute function (closes #31)<commit_after>if (!window.wps) {
  window.wps = {};
}
var wps = window.wps;

wps.process = function(options) {
  this.client = null;
  this.server = null;
  this.identifier = null;
  this.description = null;
  this.localWPS = 'http://geoserver/wps';
  this.chained = 0;
  for (var prop in options)   {
    if (this.hasOwnProperty(prop)) {
      this[prop] = options[prop];
    }
  }
  this.executeCallbacks = [];
  this.formats = [{
    mimeType: 'application/wkt',
    format: new ol.format.WKT()
  }, {
    mimeType: 'application/json',
    format: new ol.format.GeoJSON()
  }];
};

wps.process.prototype.describe = function(options) {
  options = options || {};
  if (!this.description) {
    this.client.describeProcess(this.server, this.identifier, function(description) {
      if (!this.description) {
        this.parseDescription(description);
      }
      if (options.callback) {
        options.callback.call(options.scope, this.description);
      }
    }, this);
  } else if (options.callback) {
    var description = this.description;
    window.setTimeout(function() {
      options.callback.call(options.scope, description);
    }, 0);
  }
};

// check the values against the required inputs
wps.process.prototype.isComplete = function(values) {
  if (this.description) {
    var hasUndefined = false;
    var inputs = this.description.dataInputs.input;
    for (var i=0, ii=inputs.length; i<ii; ++i) {
      var input = inputs[i];
      // TODO do we have processes where the same input needs more than 1?
      if (input.minOccurs > 0) {
        if (values[input.identifier.value] === undefined) {
          hasUndefined = true;
          break;
        }
      }
    }
    return !hasUndefined;
  } else {
    return false;
  }
};

wps.process.prototype.configure = function(options) {
  this.describe({
    callback: function() {
      var description = this.description,
        inputs = options.inputs,
        values = options.values,
        input, i, ii;
      for (i=0, ii=description.dataInputs.input.length; i<ii; ++i) {
        input = description.dataInputs.input[i];
        if (values[input.identifier.value] !== undefined) {
          this.setInputData(inputs, input, values[input.identifier.value]);
        }
      }
      if (options.callback) {
        options.callback.call(options.scope);
      }
    },
    scope: this
  });
  return this;
};

wps.process.prototype.execute = function(options) {
  var info = {
    name: {
      localPart: "Execute",
      namespaceURI: "http://www.opengis.net/wps/1.0.0"
    },
    value: {
      service: "WPS",
      version: "1.0.0",
      identifier: {
        value: this.description.identifier.value
      },
      dataInputs: {
        input: []
      }
    }
  };
  // unlike the OpenLayers 2 WPS client, we are not modifying this.description here
  // we are creating new config for JSONIX to serialize
  // so we are passing in options.inputs as the values to use
  // and inputs will be added to the array represented by info.value.dataInputs.input
  this.configure({
    inputs: info.value.dataInputs.input,
    values: options.inputs,
    callback: function() {
      var me = this;
      //TODO For now we only deal with a single output
      var outputIndex = this.getOutputIndex(
        me.description.processOutputs.output, options.output);
      me.setResponseForm(info, {outputIndex: outputIndex});
      (function callback() {
        var idx = me.executeCallbacks.indexOf(callback);
        if (idx > -1) {
          me.executeCallbacks.splice(idx, 1);
        }
        if (me.chained !== 0) {
          // need to wait until chained processes have a
          // description and configuration - see chainProcess
          me.executeCallbacks.push(callback);
          return;
        }
        // all chained processes are added as references now, so
        // let's proceed.
        var xmlhttp = new XMLHttpRequest();
        xmlhttp.open('POST', me.client.servers[me.server].url, true);
        xmlhttp.setRequestHeader('Content-type', 'application/xml');
        xmlhttp.onload = function() {
          var output = me.description.processOutputs.output[outputIndex];
          var result;
          if (output.literalOutput) {
            if (output.literalOutput.dataType === "boolean") {
              result = (this.responseText.trim().toLowerCase() === 'true');
            } else if (output.literalOutput.dataType === "double") {
              result = parseFloat(this.responseText);
            } else {
              result = this.responseText;
            }
          } else if (output.complexOutput) {
            var mimeType = me.findMimeType(output.complexOutput.supported.format);
            //TODO For now we assume a spatial output if complexOutput
            for (var i=0, ii=me.formats.length; i<ii; ++i) {
              if (me.formats[i].mimeType === mimeType) {
                result = me.formats[i].format.readFeatures(this.responseText);
                break;
              }
            }
          }
          if (options.success) {
            var outputs = {};
            outputs[options.output || 'result'] = result;
            options.success.call(options.scope, outputs);
          }
        };
        xmlhttp.send(me.client.marshaller.marshalString(info));
      })();
    },
    scope: this
  });
};

wps.process.prototype.output = function(identifier) {
  return new wps.process.chainlink({
    process: this,
    output: identifier
  });
};

wps.process.prototype.parseDescription = function(description) {
  var server = this.client.servers[this.server];
  this.description = this.client.unmarshaller.unmarshalString(
    server.processDescription[this.identifier]).value.processDescription[0];
};

wps.process.prototype.setInputData = function(inputs, input, data) {
  if (data instanceof wps.process.chainlink) {
    ++this.chained;
    // TODO we should be pushing here to inputs not modifying input itself
    input.reference = {
      method: 'POST',
      href: data.process.server === this.server ?
        this.localWPS : this.client.servers[data.process.server].url
    };
    data.process.describe({
      callback: function() {
        --this.chained;
        this.chainProcess(info, input, data);
      },
      scope: this
    });
  } else {
    var complexData = input.complexData;
    if (complexData) {
      var format = this.findMimeType(complexData.supported.format);
      var content;
      for (var i=0, ii=this.formats.length; i<ii; ++i) {
        if (this.formats[i].mimeType === format) {
          content = this.formats[i].format.writeFeatures(this.toFeatures(data));
          break;
        }
      }
      inputs.push({
        identifier: {
          value: input.identifier.value
        },
        data: {
          complexData: {
            mimeType: format,
            content: [content]
          }
        }
      });
    } else {
      inputs.push({
        identifier: {
          value: input.identifier.value
        },
        data: {
          literalData: {
            value: data
          }
        }
      });
    }
  }
};

wps.process.prototype.setResponseForm = function(info, options) {
  options = options || {};
  var output = this.description.processOutputs.output[options.outputIndex || 0];
  var mimeType;
  if (output.complexOutput) {
    mimeType = this.findMimeType(output.complexOutput.supported.format, options.supportedFormats);
  }
  info.value.responseForm = {
    rawDataOutput: {
      identifier: {
        value: output.identifier.value
      },
      mimeType: mimeType
    }
  };
};

wps.process.prototype.getOutputIndex = function(outputs, identifier) {
  var output;
  if (identifier) {
    for (var i=outputs.length-1; i>=0; --i) {
      if (outputs[i].identifier.value === identifier) {
        output = i;
        break;
      }
    }
  } else {
    output = 0;
  }
  return output;
};

wps.process.prototype.chainProcess = function(info, input, chainLink) {
  var output = this.getOutputIndex(
    chainLink.process.description.processOutputs.output, chainLink.output);
  input.reference.mimeType = this.findMimeType(
    input.complexData.supported.format,
    chainLink.process.description.processOutputs.output[output].complexOutput.supported.format);
  var formats = {};
  formats[input.reference.mimeType] = true;
  chainLink.process.setResponseForm(info, {
    outputIndex: output,
    supportedFormats: formats
  });
  input.reference.body = chainLink.process.description;
  while (this.executeCallbacks.length > 0) {
    this.executeCallbacks[0]();
  }
};

wps.process.prototype.toFeatures = function(source) {
  var isArray = toString.call(source) === "[object Array]";
  if (!isArray) {
    source = [source];
  }
  return source;
};

wps.process.prototype.findMimeType = function(sourceFormats, targetFormats) {
  targetFormats = targetFormats || this.formats;
  for (var i=0, ii=sourceFormats.length; i<ii; ++i) {
    var f = sourceFormats[i].mimeType;
    for (var j=0, jj=targetFormats.length; j<jj; ++j) {
      if (targetFormats[j].mimeType === f) {
        return f;
      }
    }
  }
  return null;
};

wps.process.chainlink = function(options) {
  this.process = null;
  this.output = null;
  for (var prop in options)   {
    if (this.hasOwnProperty(prop)) {
      this[prop] = options[prop];
    }
  }
};

wps.client = function(options) {
  this.context = new Jsonix.Context([OWS_V_1_1_0, WPS_V_1_0_0]);
  this.unmarshaller = this.context.createUnmarshaller();
  this.marshaller = this.context.createMarshaller();
  this.version = options.version || "1.0.0";
  this.lazy = options.lazy !== undefined ? options.lazy : false;
  this.servers = {};
  for (var s in options.servers) {
    this.servers[s] = typeof options.servers[s] == 'string' ? {
      url: options.servers[s],
      version: this.version,
      processDescription: {}
    } : options.servers[s];
  }
};

wps.client.prototype.execute = function(options) {
  var process = this.getProcess(options.server, options.process);
  process.execute({
    inputs: options.inputs,
    success: options.success,
    scope: options.scope
  });
};

wps.client.prototype.getProcess = function(serverID, processID, options) {
  var process = new wps.process({
    client: this,
    server: serverID,
    identifier: processID
  });
  if (!this.lazy) {
    process.describe(options);
  }
  return process;
};

wps.client.prototype.getGroupedProcesses = function(serverID, callback) {
  var server = this.servers[serverID];
  var xmlhttp = new XMLHttpRequest();
  var url = server.url + '?service=WPS&VERSION=' + server.version + '&request=GetCapabilities';
  var me = this;
  xmlhttp.open("GET", url, true);
  xmlhttp.onload = function() {
    var info = me.unmarshaller.unmarshalDocument(this.responseXML).value;
    var groups = {};
    for (var i=0, ii=info.processOfferings.process.length; i<ii; ++i) {
      var key = info.processOfferings.process[i].identifier.value;
      var names = key.split(':');
      var group = names[0];
      if (!groups[group]) {
        groups[group] = [];
      }
      groups[group].push({name: names[1], value: info.processOfferings.process[i]});
    }
    callback.call(me, groups);
  };
  xmlhttp.send();
};

wps.client.prototype.describeProcess = function(serverID, processID, callback, scope) {
  var server = this.servers[serverID];
  if (!server.processDescription[processID]) {
    if (!(processID in server.processDescription)) {
      // set to null so we know a describeFeature request is pending
      server.processDescription[processID] = null;
      var xmlhttp = new XMLHttpRequest();
      var url = server.url + '?service=WPS&VERSION=' + server.version + '&request=DescribeProcess&identifier=' + processID;
      xmlhttp.open("GET", url, true);
      var me = this;
      xmlhttp.onload = function() {
        server.processDescription[processID] = this.responseText;
        var evt = document.createEvent("Event");
        evt.initEvent("describeprocess", true, false);
        evt.identifier = processID;
        evt.raw = this.responseText;
        // TODO is there a better target than document?
        document.dispatchEvent(evt);
        callback.call(scope, this.responseText);
      };
      xmlhttp.send();
    } else {
      // pending request
      document.addEventListener("describeprocess", function describe(evt) {
        if (evt.identifier === processID) {
          this.events.unregister('describeprocess', this, describe);
          callback.call(scope, evt.raw);
        }
      }, true);
    }
  } else {
    window.setTimeout(function() {
      callback.call(scope, server.processDescription[processID]);
    }, 0);
  }
};

<|endoftext|>


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

  domready(function() {

    var scrollElements = document.querySelectorAll('[data-scroll-element]');

    emailFormHandler();
    facebookHandler();
    twitterHandler();
    emailHandler();

    var inValidRange = function(offset, limit) {
      return offset >= 0 && offset < limit;
    };

    var setVisibility = function(element, nextOffset, limit) {
      if(inValidRange(nextOffset, limit)) {
        my_removeClass(element, 'disabled');
      } else {
        my_addClass(element, 'disabled');
      }
    };

    var setVisibilityAll = function(elements, newOffset) {
      var
        scrollElement,
        increment,
        nextOffset,
        limit;

      each(elements, function(el) {
        scrollElement = document.querySelector(el.dataset.scrollElement);
        increment  = parseInt(el.dataset.scrollIncrement);
        nextOffset = newOffset + increment;
        limit      = parseInt(scrollElement.dataset.scrollLimit);

        setVisibility(el, nextOffset, limit);
      });
    };

    var resetScroll = function(element) {
      element.scrollTop = 0;
      element.dataset.scrollOffset = 0;
    };

    each(document.querySelectorAll('[data-clipboard-target]'), function(el) {
      var clipboard = new Clipboard(el);
      var notification;

      var notify = function(clipboardNotification, notificationText) {
        notification = document.getElementById(clipboardNotification.slice(1));
        notification.textContent = notificationText;
        my_addClass(notification, 'in');
        setTimeout(function() {
          my_removeClass(notification, 'in');
        }, 1400);
      };

      var notifySuccess = function(e) {
        notify(e.trigger.dataset.clipboardNotification, "Copied!");
      };

      var notifyFailure = function(e) {
        //if the copy function failed the text should still be selected, so just ask the user to hit ctrl+c
        notify(e.trigger.dataset.clipboardNotification, "Press Ctrl+C to copy");
      };

      clipboard.on('success', notifySuccess);
      clipboard.on('error', notifyFailure);
      handleClicks(el, function(e) {
        if (window.frameElement && window.frameElement.squatchJsApi) {
          window.frameElement.squatchJsApi._shareEvent(window.squatch, 'DIRECT');
        }
      });
    });

    each(scrollElements, function(el) {
      var element = document.querySelector(el.dataset.scrollElement);
      var increment = parseInt(el.dataset.scrollIncrement);
      var limit     = parseInt(element.dataset.scrollLimit.valueOf());
      var offset    = parseInt(element.dataset.scrollOffset.valueOf());
      var newOffset;

      element.dataset.scrollLimit = limit;

      var nextOffset = offset + increment;

      setVisibility(el, nextOffset, limit);

      // Force IE to forget previous scroll top value
      resetScroll(element);

      listenToClick(el, 'click', function() {
        offset = parseInt(element.dataset.scrollOffset);

        newOffset = offset + increment;

        if (inValidRange(newOffset, limit)) {
          scrollTop(element, document.getElementById(newOffset).offsetTop, 400);
          element.dataset.scrollOffset = newOffset;

          setVisibilityAll(scrollElements, newOffset);
        }
      });
    });

    each(document.querySelectorAll('[data-moment]'), function(el) {
      var time = moment(parseInt(el.textContent));
      el.textContent = time.fromNow();
    });

    each(document.getElementsByClassName('squatch-header-close'), function(el) {
      handleClicks(el, function(e) {
        if (window.frameElement && window.frameElement.squatchJsApi) {
          window.frameElement.squatchJsApi.close();
        }
      });
    });

    // Popup stuff
    each(document.querySelectorAll('[data-open-panel]'), function(el) {
      var element = document.getElementById(el.dataset.openPanel.slice(1));

      if (element) {
        el.onclick = function() {
          my_addClass(element, 'open');
        };
      }
    });

    each(document.querySelectorAll('[data-close-panel]'), function(el) {
      var element = document.getElementById(el.dataset.closePanel.slice(1));

      if (element) {
        el.onclick = function() {
          my_removeClass(element, 'open');
        };
      }
    });

    var setContainerHeight = function(containerEl) {
      var bodyEl           = document.getElementsByClassName('squatch-body')[0];
      var titleEl          = document.getElementsByClassName('squatch-title')[0];
      var titleStyle       = getComputedStyle(titleEl);
      var panelEl          = document.getElementById('squatch-panel');
      var referralsEl      = document.getElementsByClassName('squatch-referrals')[0];
      var referralsTitleEl = document.getElementsByClassName('squatch-referrals-title')[0];

      console.log('the panel', panelEl);

      var bodyHeight = bodyEl.offsetHeight;
      var bodyHeightWithoutTitle = bodyHeight - titleEl.offsetHeight - parseInt(titleStyle.marginTop || '0') - parseInt(titleStyle.marginBottom || '0') - titleEl.offsetTop;
      var panelHeight = panelEl ? panelEl.offsetHeight : 0;

      console.log('body height with no title', bodyHeightWithoutTitle);

      if (referralsEl && referralsEl.style.display !== 'none') {
        panelHeight -= referralsEl.offsetHeight;
      }

      if (referralsTitleEl && referralsTitleEl.style.display !== 'none') {
        panelHeight -= referralsTitleEl.offsetHeight;
      }

      console.log('the panel height', panelHeight);
      console.log('the body height', bodyHeight);

      containerEl.style.height = bodyHeight + panelHeight + "px";

      console.log('container Height', containerEl.style.height);

      var stylesheet = document.createElement('style');
      stylesheet.type = 'text/css';

      var css = '#squatch-panel.open {' +
        '-webkit-transform: translate(0, -' + bodyHeightWithoutTitle + 'px);' +
        '-ms-transform: translate(0, -' + bodyHeightWithoutTitle + 'px);' +
        '-o-transform: translate(0, -' + bodyHeightWithoutTitle + 'px);' +
        'transform: translate(0, -' + bodyHeightWithoutTitle + 'px);' +
        '}' +
        'html.lt-ie9 #squatch-panel.open {' +
        'top: -' + bodyHeightWithoutTitle + 'px;' +
        '}';

      if (stylesheet.styleSheet){
        // IE
        stylesheet.styleSheet.cssText = css;
      } else {
        // W3C Standard
        stylesheet.appendChild(document.createTextNode(css));
      }

      document.querySelector('head').appendChild(stylesheet);
    };

    var containerEl = document.getElementsByClassName('squatch-container-popup')[0];

    if (containerEl) {
     window.onload = function() {
       setContainerHeight(containerEl);
     }

    }
  });

})();
<commit_msg>Debugging<commit_after>(function() {
  'use strict';

  domready(function() {

    var scrollElements = document.querySelectorAll('[data-scroll-element]');

    emailFormHandler();
    facebookHandler();
    twitterHandler();
    emailHandler();

    var inValidRange = function(offset, limit) {
      return offset >= 0 && offset < limit;
    };

    var setVisibility = function(element, nextOffset, limit) {
      if(inValidRange(nextOffset, limit)) {
        my_removeClass(element, 'disabled');
      } else {
        my_addClass(element, 'disabled');
      }
    };

    var setVisibilityAll = function(elements, newOffset) {
      var
        scrollElement,
        increment,
        nextOffset,
        limit;

      each(elements, function(el) {
        scrollElement = document.querySelector(el.dataset.scrollElement);
        increment  = parseInt(el.dataset.scrollIncrement);
        nextOffset = newOffset + increment;
        limit      = parseInt(scrollElement.dataset.scrollLimit);

        setVisibility(el, nextOffset, limit);
      });
    };

    var resetScroll = function(element) {
      element.scrollTop = 0;
      element.dataset.scrollOffset = 0;
    };

    each(document.querySelectorAll('[data-clipboard-target]'), function(el) {
      var clipboard = new Clipboard(el);
      var notification;

      var notify = function(clipboardNotification, notificationText) {
        notification = document.getElementById(clipboardNotification.slice(1));
        notification.textContent = notificationText;
        my_addClass(notification, 'in');
        setTimeout(function() {
          my_removeClass(notification, 'in');
        }, 1400);
      };

      var notifySuccess = function(e) {
        notify(e.trigger.dataset.clipboardNotification, "Copied!");
      };

      var notifyFailure = function(e) {
        //if the copy function failed the text should still be selected, so just ask the user to hit ctrl+c
        notify(e.trigger.dataset.clipboardNotification, "Press Ctrl+C to copy");
      };

      clipboard.on('success', notifySuccess);
      clipboard.on('error', notifyFailure);
      handleClicks(el, function(e) {
        if (window.frameElement && window.frameElement.squatchJsApi) {
          window.frameElement.squatchJsApi._shareEvent(window.squatch, 'DIRECT');
        }
      });
    });

    each(scrollElements, function(el) {
      var element = document.querySelector(el.dataset.scrollElement);
      var increment = parseInt(el.dataset.scrollIncrement);
      var limit     = parseInt(element.dataset.scrollLimit.valueOf());
      var offset    = parseInt(element.dataset.scrollOffset.valueOf());
      var newOffset;

      element.dataset.scrollLimit = limit;

      var nextOffset = offset + increment;

      setVisibility(el, nextOffset, limit);

      // Force IE to forget previous scroll top value
      resetScroll(element);

      listenToClick(el, 'click', function() {
        offset = parseInt(element.dataset.scrollOffset);

        newOffset = offset + increment;

        if (inValidRange(newOffset, limit)) {
          scrollTop(element, document.getElementById(newOffset).offsetTop, 400);
          element.dataset.scrollOffset = newOffset;

          setVisibilityAll(scrollElements, newOffset);
        }
      });
    });

    each(document.querySelectorAll('[data-moment]'), function(el) {
      var time = moment(parseInt(el.textContent));
      el.textContent = time.fromNow();
    });

    each(document.getElementsByClassName('squatch-header-close'), function(el) {
      handleClicks(el, function(e) {
        if (window.frameElement && window.frameElement.squatchJsApi) {
          window.frameElement.squatchJsApi.close();
        }
      });
    });

    // Popup stuff
    each(document.querySelectorAll('[data-open-panel]'), function(el) {
      var element = document.getElementById(el.dataset.openPanel.slice(1));

      if (element) {
        el.onclick = function() {
          my_addClass(element, 'open');
        };
      }
    });

    each(document.querySelectorAll('[data-close-panel]'), function(el) {
      var element = document.getElementById(el.dataset.closePanel.slice(1));

      if (element) {
        el.onclick = function() {
          my_removeClass(element, 'open');
        };
      }
    });

    var setContainerHeight = function(containerEl) {
      var bodyEl           = document.getElementsByClassName('squatch-body')[0];
      var titleEl          = document.getElementsByClassName('squatch-title')[0];
      var titleStyle       = getComputedStyle(titleEl);
      var panelEl          = document.getElementById('squatch-panel');
      var referralsEl      = document.getElementsByClassName('squatch-referrals')[0];
      var referralsTitleEl = document.getElementsByClassName('squatch-referrals-title')[0];

      console.log('the panel', panelEl);

      var bodyHeight = bodyEl.offsetHeight;
      var bodyHeightWithoutTitle = bodyHeight - titleEl.offsetHeight - parseInt(titleStyle.marginTop || '0') - parseInt(titleStyle.marginBottom || '0') - titleEl.offsetTop;
      var panelHeight = panelEl ? panelEl.offsetHeight : 0;

      console.log('body height with no title', bodyHeightWithoutTitle);

      if (referralsEl && referralsEl.style.display !== 'none') {
        panelHeight -= referralsEl.offsetHeight;
      }

      if (referralsTitleEl && referralsTitleEl.style.display !== 'none') {
        panelHeight -= referralsTitleEl.offsetHeight;
      }

      console.log('the panel height', panelHeight);
      console.log('the body height', bodyHeight);

      containerEl.style.height = bodyHeight + panelHeight + "px";

      console.log('container Height', containerEl.style.height);
      console.log('bodyHeightWithoutTitle', bodyHeightWithoutTitle);

      var stylesheet = document.createElement('style');
      stylesheet.type = 'text/css';

      var css = '#squatch-panel.open {' +
        '-webkit-transform: translate(0, -' + bodyHeightWithoutTitle + 'px);' +
        '-ms-transform: translate(0, -' + bodyHeightWithoutTitle + 'px);' +
        '-o-transform: translate(0, -' + bodyHeightWithoutTitle + 'px);' +
        'transform: translate(0, -' + bodyHeightWithoutTitle + 'px);' +
        '}' +
        'html.lt-ie9 #squatch-panel.open {' +
        'top: -' + bodyHeightWithoutTitle + 'px;' +
        '}';

      if (stylesheet.styleSheet){
        // IE
        stylesheet.styleSheet.cssText = css;
      } else {
        // W3C Standard
        stylesheet.appendChild(document.createTextNode(css));
      }

      document.querySelector('head').appendChild(stylesheet);
    };

    var containerEl = document.getElementsByClassName('squatch-container-popup')[0];

    if (containerEl) {
     window.onload = function() {
       setContainerHeight(containerEl);
     }

    }
  });

})();
<|endoftext|>


<commit_before>/**
 * @since 150722 11:34
 * @author vivaxy
 */
var RefererKiller = function () {
    this.refererKillerIframeId = 0;
};

RefererKiller.prototype.convert = function () {
    var _this = this,
        images = document.querySelectorAll('img[referer-killer-src]');
    Array.prototype.forEach.call(images, function (img) {
        var iframe = document.createElement('iframe');
        iframe.id = 'referer-killer-id-' + _this.refererKillerIframeId++;
        iframe.style.border = 'none';
        // cannot use `data:text/html,`
        // because iframe used `parent` to get parent window, which causes cross origin
        iframe.src = 'javascript: \'<!DOCTYPE html>' +
            '' +
            '' +
            '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">' +
            '<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0">' +
            '' +
            '' +
            '' +
            '' +
            '' +
            '' +
            '\'';
        img.parentNode.replaceChild(iframe, img);
    });
};
<commit_msg>add reference<commit_after>/**
 * @since 150722 11:34
 * @author vivaxy
 */
// https://github.com/jpgerek/referrer-killer
var RefererKiller = function () {
    this.refererKillerIframeId = 0;
};

RefererKiller.prototype.convert = function () {
    var _this = this,
        images = document.querySelectorAll('img[referer-killer-src]');
    Array.prototype.forEach.call(images, function (img) {
        var iframe = document.createElement('iframe');
        iframe.id = 'referer-killer-id-' + _this.refererKillerIframeId++;
        iframe.style.border = 'none';
        // cannot use `data:text/html,`
        // because iframe used `parent` to get parent window, which causes cross origin
        iframe.src = 'javascript: \'<!DOCTYPE html>' +
            '' +
            '' +
            '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">' +
            '<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0">' +
            '' +
            '' +
            '' +
            '' +
            '' +
            '' +
            '\'';
        img.parentNode.replaceChild(iframe, img);
    });
};
<|endoftext|>


<commit_before>var _ = require('underscore'),
  pexec = require('../utils/command_line').pexec,
  path = require('path'),
  templates = require('./docker_templates');

var controllers = module.exports = {};

var build = function(options){
  console.log('build', options);
  var imageName = options.userName + '/' + options.repoName;
  var cmd = 'docker build -t ' + imageName + ' .';
  pexec(cmd, {
    cwd: path.join(__dirname, '..' ,'/temp', options.repoName)
  });
};

controllers.buildImage = function(options){
  templates.node(options);
  build(options);
};<commit_msg>split<commit_after>var _ = require('underscore'),
  pexec = require('../utils/command_line').pexec,
  path = require('path'),
  templates = require('./docker_templates');

var controllers = module.exports = {};

var build = function(options){
  console.log('build', options);
  var imageName = options.userName + '/' + options.repoName;
  var cmd = 'docker build -t ' + imageName + ' .';
  pexec(cmd, {
    cwd: path.join(__dirname, '..' ,'/temp', options.repoName)
  });
};

controllers.buildImage = function(imageName){
  var options = {
    userName: imageName.split('/')[0],
    repoName: imageName.split('/')[1]
  };
  templates.node(options);
  build(options);
};<|endoftext|>


<commit_before>import React, {Component, PropTypes} from 'react';
import ReactDOM from 'react-dom';
import transitions from '../styles/transitions';
import DropDownArrow from '../svg-icons/navigation/arrow-drop-down';
import Menu from '../Menu/Menu';
import ClearFix from '../internal/ClearFix';
import Popover from '../Popover/Popover';
import PopoverAnimationVertical from '../Popover/PopoverAnimationVertical';
import keycode from 'keycode';
import Events from '../utils/events';
import IconButton from '../IconButton';

const anchorOrigin = {
  vertical: 'top',
  horizontal: 'left',
};

function getStyles(props, context) {
  const {disabled} = props;
  const spacing = context.muiTheme.baseTheme.spacing;
  const palette = context.muiTheme.baseTheme.palette;
  const accentColor = context.muiTheme.dropDownMenu.accentColor;
  return {
    control: {
      cursor: disabled ? 'not-allowed' : 'pointer',
      height: '100%',
      position: 'relative',
      width: '100%',
    },
    icon: {
      fill: accentColor,
      position: 'absolute',
      right: spacing.desktopGutterLess,
      top: (spacing.iconSize - 24) / 2 + spacing.desktopGutterMini / 2,
    },
    iconChildren: {
      fill: 'inherit',
    },
    label: {
      color: disabled ? palette.disabledColor : palette.textColor,
      lineHeight: `${spacing.desktopToolbarHeight}px`,
      overflow: 'hidden',
      opacity: 1,
      position: 'relative',
      paddingLeft: spacing.desktopGutter,
      paddingRight: spacing.iconSize * 2 + spacing.desktopGutterMini,
      textOverflow: 'ellipsis',
      top: 0,
      whiteSpace: 'nowrap',
    },
    labelWhenOpen: {
      opacity: 0,
      top: (spacing.desktopToolbarHeight / 8),
    },
    root: {
      display: 'inline-block',
      fontSize: spacing.desktopDropDownMenuFontSize,
      height: spacing.desktopSubheaderHeight,
      fontFamily: context.muiTheme.baseTheme.fontFamily,
      outline: 'none',
      position: 'relative',
      transition: transitions.easeOut(),
    },
    rootWhenOpen: {
      opacity: 1,
    },
    underline: {
      borderTop: `solid 1px ${accentColor}`,
      bottom: 1,
      left: 0,
      margin: `-1px ${spacing.desktopGutter}px`,
      right: 0,
      position: 'absolute',
    },
  };
}

class DropDownMenu extends Component {
  static muiName = 'DropDownMenu';

  // The nested styles for drop-down-menu are modified by toolbar and possibly
  // other user components, so it will give full access to its js styles rather
  // than just the parent.
  static propTypes = {
    /**
     * If true, the popover will apply transitions when
     * it gets added to the DOM.
     */
    animated: PropTypes.bool,
    /**
     * Override the default animation component used.
     */
    animation: PropTypes.func,
    /**
     * The width will automatically be set according to the items inside the menu.
     * To control this width in css instead, set this prop to `false`.
     */
    autoWidth: PropTypes.bool,
    /**
     * The `MenuItem`s to populate the `Menu` with. If the `MenuItems` have the
     * prop `label` that value will be used to render the representation of that
     * item within the field.
     */
    children: PropTypes.node,
    /**
     * The css class name of the root element.
     */
    className: PropTypes.string,
    /**
     * Disables the menu.
     */
    disabled: PropTypes.bool,
    /**
     * Overrides default `SvgIcon` dropdown arrow component.
     */
    iconButton: PropTypes.node,
    /**
     * Overrides the styles of icon element.
     */
    iconStyle: PropTypes.object,
    /**
     * Overrides the styles of label when the `DropDownMenu` is inactive.
     */
    labelStyle: PropTypes.object,
    /**
     * The style object to use to override underlying list style.
     */
    listStyle: PropTypes.object,
    /**
     * The maximum height of the `Menu` when it is displayed.
     */
    maxHeight: PropTypes.number,
    /**
     * Override the inline-styles of menu items.
     */
    menuItemStyle: PropTypes.object,
    /**
     * Overrides the styles of `Menu` when the `DropDownMenu` is displayed.
     */
    menuStyle: PropTypes.object,
    /**
     * Callback function fired when a menu item is clicked, other than the one currently selected.
     *
     * @param {object} event TouchTap event targeting the menu item that was clicked.
     * @param {number} key The index of the clicked menu item in the `children` collection.
     * @param {any} payload The `value` prop of the clicked menu item.
     */
    onChange: PropTypes.func,
    /**
     * Callback function fired when the menu is closed.
     */
    onClose: PropTypes.func,
    /**
     * Set to true to have the `DropDownMenu` automatically open on mount.
     */
    openImmediately: PropTypes.bool,
    /**
     * Override the inline-styles of selected menu items.
     */
    selectedMenuItemStyle: PropTypes.object,
    /**
     * Override the inline-styles of the root element.
     */
    style: PropTypes.object,
    /**
     * Overrides the inline-styles of the underline.
     */
    underlineStyle: PropTypes.object,
    /**
     * The value that is currently selected.
     */
    value: PropTypes.any,
  };

  static defaultProps = {
    animated: true,
    autoWidth: true,
    disabled: false,
    iconButton: <DropDownArrow />,
    openImmediately: false,
    maxHeight: 500,
  };

  static contextTypes = {
    muiTheme: PropTypes.object.isRequired,
  };

  state = {
    open: false,
  };

  componentDidMount() {
    if (this.props.autoWidth) {
      this.setWidth();
    }
    if (this.props.openImmediately) {
      // TODO: Temporary fix to make openImmediately work with popover.
      /* eslint-disable react/no-did-mount-set-state */
      setTimeout(() => this.setState({
        open: true,
        anchorEl: this.rootNode,
      }), 0);
      /* eslint-enable react/no-did-mount-set-state */
    }
  }

  componentWillReceiveProps() {
    if (this.props.autoWidth) {
      this.setWidth();
    }
  }

  rootNode = undefined;
  arrowNode = undefined;

  /**
   * This method is deprecated but still here because the TextField
   * need it in order to work. TODO: That will be addressed later.
   */
  getInputNode() {
    const rootNode = this.rootNode;

    rootNode.focus = () => {
      if (!this.props.disabled) {
        this.setState({
          open: !this.state.open,
          anchorEl: this.rootNode,
        });
      }
    };

    return rootNode;
  }

  setWidth() {
    const el = this.rootNode;
    if (!this.props.style || !this.props.style.hasOwnProperty('width')) {
      el.style.width = 'auto';
    }
  }

  handleTouchTapControl = (event) => {
    event.preventDefault();
    if (!this.props.disabled) {
      this.setState({
        open: !this.state.open,
        anchorEl: this.rootNode,
      });
    }
  };

  handleRequestCloseMenu = () => {
    this.close(false);
  };

  handleEscKeyDownMenu = () => {
    this.close(true);
  };

  handleKeyDown = (event) => {
    switch (keycode(event)) {
      case 'up':
      case 'down':
      case 'space':
      case 'enter':
        event.preventDefault();
        this.setState({
          open: true,
          anchorEl: this.rootNode,
        });
        break;
    }
  };

  handleItemTouchTap = (event, child, index) => {
    event.persist();
    this.setState({
      open: false,
    }, () => {
      if (this.props.onChange) {
        this.props.onChange(event, index, child.props.value);
      }

      this.close(Events.isKeyboard(event));
    });
  };

  close = (isKeyboard) => {
    this.setState({
      open: false,
    }, () => {
      if (this.props.onClose) {
        this.props.onClose();
      }

      if (isKeyboard) {
        const dropArrow = this.arrowNode;
        const dropNode = ReactDOM.findDOMNode(dropArrow);
        dropNode.focus();
        dropArrow.setKeyboardFocus(true);
      }
    });
  }

  render() {
    const {
      animated,
      animation,
      autoWidth,
      children,
      className,
      iconStyle,
      labelStyle,
      listStyle,
      maxHeight,
      menuStyle: menuStyleProp,
      onClose, // eslint-disable-line no-unused-vars
      openImmediately, // eslint-disable-line no-unused-vars
      menuItemStyle,
      selectedMenuItemStyle,
      style,
      underlineStyle,
      value,
      iconButton,
      ...other
    } = this.props;

    const {
      anchorEl,
      open,
    } = this.state;

    const {prepareStyles} = this.context.muiTheme;
    const styles = getStyles(this.props, this.context);

    let displayValue = '';
    React.Children.forEach(children, (child) => {
      if (child && value === child.props.value) {
        // This will need to be improved (in case primaryText is a node)
        displayValue = child.props.label || child.props.primaryText;
      }
    });

    let menuStyle;
    if (anchorEl && !autoWidth) {
      menuStyle = Object.assign({
        width: anchorEl.clientWidth,
      }, menuStyleProp);
    } else {
      menuStyle = menuStyleProp;
    }

    return (

 {
          this.rootNode = node;
        }}
        className={className}
        style={prepareStyles(Object.assign({}, styles.root, open && styles.rootWhenOpen, style))}
      >
        <ClearFix style={styles.control} onTouchTap={this.handleTouchTapControl}>

            {displayValue}

          <IconButton
            tabIndex={this.props.disabled ? -1 : undefined}
            onKeyDown={this.handleKeyDown}
            ref={(node) => {
              this.arrowNode = node;
            }}
            style={Object.assign({}, styles.icon, iconStyle)}
            iconStyle={styles.iconChildren}
          >
            {iconButton}
          </IconButton>

        </ClearFix>
        <Popover
          anchorOrigin={anchorOrigin}
          anchorEl={anchorEl}
          animation={animation || PopoverAnimationVertical}
          open={open}
          animated={animated}
          onRequestClose={this.handleRequestCloseMenu}
        >
          <Menu
            maxHeight={maxHeight}
            desktop={true}
            value={value}
            onEscKeyDown={this.handleEscKeyDownMenu}
            style={menuStyle}
            listStyle={listStyle}
            onItemTouchTap={this.handleItemTouchTap}
            menuItemStyle={menuItemStyle}
            selectedMenuItemStyle={selectedMenuItemStyle}
          >
            {children}
          </Menu>
        </Popover>

    );
  }
}

export default DropDownMenu;
<commit_msg>[DropDownMenu] Add disableIconTouchRipple prop<commit_after>import React, {Component, PropTypes} from 'react';
import ReactDOM from 'react-dom';
import transitions from '../styles/transitions';
import DropDownArrow from '../svg-icons/navigation/arrow-drop-down';
import Menu from '../Menu/Menu';
import ClearFix from '../internal/ClearFix';
import Popover from '../Popover/Popover';
import PopoverAnimationVertical from '../Popover/PopoverAnimationVertical';
import keycode from 'keycode';
import Events from '../utils/events';
import IconButton from '../IconButton';

const anchorOrigin = {
  vertical: 'top',
  horizontal: 'left',
};

function getStyles(props, context) {
  const {disabled} = props;
  const spacing = context.muiTheme.baseTheme.spacing;
  const palette = context.muiTheme.baseTheme.palette;
  const accentColor = context.muiTheme.dropDownMenu.accentColor;
  return {
    control: {
      cursor: disabled ? 'not-allowed' : 'pointer',
      height: '100%',
      position: 'relative',
      width: '100%',
    },
    icon: {
      fill: accentColor,
      position: 'absolute',
      right: spacing.desktopGutterLess,
      top: (spacing.iconSize - 24) / 2 + spacing.desktopGutterMini / 2,
    },
    iconChildren: {
      fill: 'inherit',
    },
    label: {
      color: disabled ? palette.disabledColor : palette.textColor,
      lineHeight: `${spacing.desktopToolbarHeight}px`,
      overflow: 'hidden',
      opacity: 1,
      position: 'relative',
      paddingLeft: spacing.desktopGutter,
      paddingRight: spacing.iconSize * 2 + spacing.desktopGutterMini,
      textOverflow: 'ellipsis',
      top: 0,
      whiteSpace: 'nowrap',
    },
    labelWhenOpen: {
      opacity: 0,
      top: (spacing.desktopToolbarHeight / 8),
    },
    root: {
      display: 'inline-block',
      fontSize: spacing.desktopDropDownMenuFontSize,
      height: spacing.desktopSubheaderHeight,
      fontFamily: context.muiTheme.baseTheme.fontFamily,
      outline: 'none',
      position: 'relative',
      transition: transitions.easeOut(),
    },
    rootWhenOpen: {
      opacity: 1,
    },
    underline: {
      borderTop: `solid 1px ${accentColor}`,
      bottom: 1,
      left: 0,
      margin: `-1px ${spacing.desktopGutter}px`,
      right: 0,
      position: 'absolute',
    },
  };
}

class DropDownMenu extends Component {
  static muiName = 'DropDownMenu';

  // The nested styles for drop-down-menu are modified by toolbar and possibly
  // other user components, so it will give full access to its js styles rather
  // than just the parent.
  static propTypes = {
    /**
     * If true, the popover will apply transitions when
     * it gets added to the DOM.
     */
    animated: PropTypes.bool,
    /**
     * Override the default animation component used.
     */
    animation: PropTypes.func,
    /**
     * The width will automatically be set according to the items inside the menu.
     * To control this width in css instead, set this prop to `false`.
     */
    autoWidth: PropTypes.bool,
    /**
     * The `MenuItem`s to populate the `Menu` with. If the `MenuItems` have the
     * prop `label` that value will be used to render the representation of that
     * item within the field.
     */
    children: PropTypes.node,
    /**
     * The css class name of the root element.
     */
    className: PropTypes.string,
    /**
     * Disables the menu.
     */
    disabled: PropTypes.bool,
    /**
     * If true, the icon element's ripple effect will be disabled
     */
    disableIconTouchRipple: PropTypes.bool,
    /**
     * Overrides default `SvgIcon` dropdown arrow component.
     */
    iconButton: PropTypes.node,
    /**
     * Overrides the styles of icon element.
     */
    iconStyle: PropTypes.object,
    /**
     * Overrides the styles of label when the `DropDownMenu` is inactive.
     */
    labelStyle: PropTypes.object,
    /**
     * The style object to use to override underlying list style.
     */
    listStyle: PropTypes.object,
    /**
     * The maximum height of the `Menu` when it is displayed.
     */
    maxHeight: PropTypes.number,
    /**
     * Override the inline-styles of menu items.
     */
    menuItemStyle: PropTypes.object,
    /**
     * Overrides the styles of `Menu` when the `DropDownMenu` is displayed.
     */
    menuStyle: PropTypes.object,
    /**
     * Callback function fired when a menu item is clicked, other than the one currently selected.
     *
     * @param {object} event TouchTap event targeting the menu item that was clicked.
     * @param {number} key The index of the clicked menu item in the `children` collection.
     * @param {any} payload The `value` prop of the clicked menu item.
     */
    onChange: PropTypes.func,
    /**
     * Callback function fired when the menu is closed.
     */
    onClose: PropTypes.func,
    /**
     * Set to true to have the `DropDownMenu` automatically open on mount.
     */
    openImmediately: PropTypes.bool,
    /**
     * Override the inline-styles of selected menu items.
     */
    selectedMenuItemStyle: PropTypes.object,
    /**
     * Override the inline-styles of the root element.
     */
    style: PropTypes.object,
    /**
     * Overrides the inline-styles of the underline.
     */
    underlineStyle: PropTypes.object,
    /**
     * The value that is currently selected.
     */
    value: PropTypes.any,
  };

  static defaultProps = {
    animated: true,
    autoWidth: true,
    disabled: false,
    iconButton: <DropDownArrow />,
    openImmediately: false,
    maxHeight: 500,
  };

  static contextTypes = {
    muiTheme: PropTypes.object.isRequired,
  };

  state = {
    open: false,
  };

  componentDidMount() {
    if (this.props.autoWidth) {
      this.setWidth();
    }
    if (this.props.openImmediately) {
      // TODO: Temporary fix to make openImmediately work with popover.
      /* eslint-disable react/no-did-mount-set-state */
      setTimeout(() => this.setState({
        open: true,
        anchorEl: this.rootNode,
      }), 0);
      /* eslint-enable react/no-did-mount-set-state */
    }
  }

  componentWillReceiveProps() {
    if (this.props.autoWidth) {
      this.setWidth();
    }
  }

  rootNode = undefined;
  arrowNode = undefined;

  /**
   * This method is deprecated but still here because the TextField
   * need it in order to work. TODO: That will be addressed later.
   */
  getInputNode() {
    const rootNode = this.rootNode;

    rootNode.focus = () => {
      if (!this.props.disabled) {
        this.setState({
          open: !this.state.open,
          anchorEl: this.rootNode,
        });
      }
    };

    return rootNode;
  }

  setWidth() {
    const el = this.rootNode;
    if (!this.props.style || !this.props.style.hasOwnProperty('width')) {
      el.style.width = 'auto';
    }
  }

  handleTouchTapControl = (event) => {
    event.preventDefault();
    if (!this.props.disabled) {
      this.setState({
        open: !this.state.open,
        anchorEl: this.rootNode,
      });
    }
  };

  handleRequestCloseMenu = () => {
    this.close(false);
  };

  handleEscKeyDownMenu = () => {
    this.close(true);
  };

  handleKeyDown = (event) => {
    switch (keycode(event)) {
      case 'up':
      case 'down':
      case 'space':
      case 'enter':
        event.preventDefault();
        this.setState({
          open: true,
          anchorEl: this.rootNode,
        });
        break;
    }
  };

  handleItemTouchTap = (event, child, index) => {
    event.persist();
    this.setState({
      open: false,
    }, () => {
      if (this.props.onChange) {
        this.props.onChange(event, index, child.props.value);
      }

      this.close(Events.isKeyboard(event));
    });
  };

  close = (isKeyboard) => {
    this.setState({
      open: false,
    }, () => {
      if (this.props.onClose) {
        this.props.onClose();
      }

      if (isKeyboard) {
        const dropArrow = this.arrowNode;
        const dropNode = ReactDOM.findDOMNode(dropArrow);
        dropNode.focus();
        dropArrow.setKeyboardFocus(true);
      }
    });
  }

  render() {
    const {
      animated,
      animation,
      autoWidth,
      children,
      className,
      disableIconTouchRipple,
      iconStyle,
      labelStyle,
      listStyle,
      maxHeight,
      menuStyle: menuStyleProp,
      onClose, // eslint-disable-line no-unused-vars
      openImmediately, // eslint-disable-line no-unused-vars
      menuItemStyle,
      selectedMenuItemStyle,
      style,
      underlineStyle,
      value,
      iconButton,
      ...other
    } = this.props;

    const {
      anchorEl,
      open,
    } = this.state;

    const {prepareStyles} = this.context.muiTheme;
    const styles = getStyles(this.props, this.context);

    let displayValue = '';
    React.Children.forEach(children, (child) => {
      if (child && value === child.props.value) {
        // This will need to be improved (in case primaryText is a node)
        displayValue = child.props.label || child.props.primaryText;
      }
    });

    let menuStyle;
    if (anchorEl && !autoWidth) {
      menuStyle = Object.assign({
        width: anchorEl.clientWidth,
      }, menuStyleProp);
    } else {
      menuStyle = menuStyleProp;
    }

    return (

 {
          this.rootNode = node;
        }}
        className={className}
        style={prepareStyles(Object.assign({}, styles.root, open && styles.rootWhenOpen, style))}
      >
        <ClearFix style={styles.control} onTouchTap={this.handleTouchTapControl}>

            {displayValue}

          <IconButton
            disableTouchRipple={disableIconTouchRipple}
            tabIndex={this.props.disabled ? -1 : undefined}
            onKeyDown={this.handleKeyDown}
            ref={(node) => {
              this.arrowNode = node;
            }}
            style={Object.assign({}, styles.icon, iconStyle)}
            iconStyle={styles.iconChildren}
          >
            {iconButton}
          </IconButton>

        </ClearFix>
        <Popover
          anchorOrigin={anchorOrigin}
          anchorEl={anchorEl}
          animation={animation || PopoverAnimationVertical}
          open={open}
          animated={animated}
          onRequestClose={this.handleRequestCloseMenu}
        >
          <Menu
            maxHeight={maxHeight}
            desktop={true}
            value={value}
            onEscKeyDown={this.handleEscKeyDownMenu}
            style={menuStyle}
            listStyle={listStyle}
            onItemTouchTap={this.handleItemTouchTap}
            menuItemStyle={menuItemStyle}
            selectedMenuItemStyle={selectedMenuItemStyle}
          >
            {children}
          </Menu>
        </Popover>

    );
  }
}

export default DropDownMenu;
<|endoftext|>


<commit_before>// Copyright 2014 Volker Sorge
//
// 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.

/**
 * @fileoverview Testcases for ChromeVox's speech rules.
 *     Abstract superclass that provides facilities to parameterize the speech
 *     rule engine and to execute rule tests on math expressions.
 * @author Volker.Sorge@gmail.com (Volker Sorge)
 */

goog.provide('sre.AbstractRuleTest');

goog.require('sre.AbstractExamples');

/**
 * @constructor
 * @extends {sre.AbstractExamples}
 */
sre.AbstractRuleTest = function() {
  goog.base(this);

  /**
   * @type {string}
   */
  this.style = 'default';

  /**
   * @type {string}
   */
  this.domain = 'default';

  /**
   * @type {boolean}
   */
  this.semantics = false;
};
goog.inherits(sre.AbstractRuleTest, sre.AbstractExamples);

/**
 * Tests if for speech translation of a given html snippet is equal to the
 * answer provided.
 * @param {string} mml Snippet of a MathML expression.
 * @param {string} answer Expected speech translation of MathML expression.
 * @param {string=} opt_style Mathspeak style for translation.
 */
sre.AbstractRuleTest.prototype.executeRuleTest = function(mml, answer,
                                                          opt_style) {
  opt_style = opt_style || this.style;
  var mathMl = '<math xmlns="http://www.w3.org/1998/Math/MathML">' +
          mml + '</math>';
  this.appendExamples(mathMl);
  sre.SpeechRuleEngine.getInstance().clearCache();
  sre.System.getInstance().setupEngine(
      {semantics: this.semantics, domain: this.domain, style: opt_style});
  var result = sre.System.getInstance().toSpeech(mathMl);
  this.assert.equal(result, answer);
};

<commit_msg>Allow for rule set customisation in speech rule tests.<commit_after>// Copyright 2014 Volker Sorge
//
// 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.

/**
 * @fileoverview Testcases for ChromeVox's speech rules.
 *     Abstract superclass that provides facilities to parameterize the speech
 *     rule engine and to execute rule tests on math expressions.
 * @author Volker.Sorge@gmail.com (Volker Sorge)
 */

goog.provide('sre.AbstractRuleTest');

goog.require('sre.AbstractExamples');

/**
 * @constructor
 * @extends {sre.AbstractExamples}
 */
sre.AbstractRuleTest = function() {
  goog.base(this);

  /**
   * @type {string}
   */
  this.style = 'default';

  /**
   * @type {string}
   */
  this.domain = 'default';

  /**
   * @type {boolean}
   */
  this.semantics = false;

  /**
   * Specify particular rule sets for a test. By default all available rule sets
   * are used.
   * @type {Array.<string>}
   */
  this.rules = null;

};
goog.inherits(sre.AbstractRuleTest, sre.AbstractExamples);

/**
 * Tests if for speech translation of a given html snippet is equal to the
 * answer provided.
 * @param {string} mml Snippet of a MathML expression.
 * @param {string} answer Expected speech translation of MathML expression.
 * @param {string=} opt_style Mathspeak style for translation.
 */
sre.AbstractRuleTest.prototype.executeRuleTest = function(mml, answer,
                                                          opt_style) {
  opt_style = opt_style || this.style;
  var mathMl = '<math xmlns="http://www.w3.org/1998/Math/MathML">' +
          mml + '</math>';
  this.appendExamples(mathMl);
  sre.SpeechRuleEngine.getInstance().clearCache();
  sre.System.getInstance().setupEngine(
    {semantics: this.semantics, domain: this.domain, style: opt_style,
     rules: this.rules});
  var result = sre.System.getInstance().toSpeech(mathMl);
  this.assert.equal(result, answer);
};

<|endoftext|>


<commit_before>// jQuery creates it's own event object, and it doesn't have a
// dataTransfer property yet. This adds dataTransfer to the event object.
$.event.props.push("dataTransfer");
$(function() {
    "use strict";
    var dump;
    dump = function (file) {
        var spinner, worker, reader, optionFirstLineHasFieldNames, optionDelimiter;
        spinner = $("#spinner");
        spinner.show();
        if (file) {
            worker = new Worker("scripts/crumbs-worker.js");
            optionFirstLineHasFieldNames = $("#optionFirstLineHasFieldNames").is(":checked");
            optionDelimiter = $("#optionDelimiter").val();
            reader = new FileReader();
            reader.onload = function (event) {
                var payload;
                payload = {
                    data: event.target.result,
                    options: {
                        firstLineHasFieldNames: optionFirstLineHasFieldNames,
                        delimiter: optionDelimiter
                    }
                };
                worker.onmessage = function (message) {
                    if (message.data === 0) {
                        alert("Import complete.");
                    } else {
                        alert("Something went wrong.");
                    }
                    spinner.hide();
                };
                worker.postMessage(payload);
            };
            reader.readAsText(file);
        } else {
            spinner.hide();
            alert("Please provide a CSV file.");
        }
    };
    // Button handlers.
    $("#button").click(function () {
        var file;
        file = $("#picker").get(0).files[0];
        dump(file);
    });
    // Drag-and-Drop handlers.
    $("#dropzone").bind("dragover", function (e) {
        e.preventDefault();
        $(this).css("background", "red");
    });
    $("#dropzone").bind("dragleave", function (e) {
        e.preventDefault();
        $(this).css("background", "white");
    });
    $("#dropzone").bind("drop", function (e) {
        var file;
        e.preventDefault();
        $(this).css("background", "white");
        file = e.dataTransfer.files[0];
        dump(file);
    });
});
<commit_msg>Fix typo in comment.<commit_after>// jQuery creates its own event object, and it doesn't have a
// dataTransfer property yet. This adds dataTransfer to the event object.
$.event.props.push("dataTransfer");
$(function() {
    "use strict";
    var dump;
    dump = function (file) {
        var spinner, worker, reader, optionFirstLineHasFieldNames, optionDelimiter;
        spinner = $("#spinner");
        spinner.show();
        if (file) {
            worker = new Worker("scripts/crumbs-worker.js");
            optionFirstLineHasFieldNames = $("#optionFirstLineHasFieldNames").is(":checked");
            optionDelimiter = $("#optionDelimiter").val();
            reader = new FileReader();
            reader.onload = function (event) {
                var payload;
                payload = {
                    data: event.target.result,
                    options: {
                        firstLineHasFieldNames: optionFirstLineHasFieldNames,
                        delimiter: optionDelimiter
                    }
                };
                worker.onmessage = function (message) {
                    if (message.data === 0) {
                        alert("Import complete.");
                    } else {
                        alert("Something went wrong.");
                    }
                    spinner.hide();
                };
                worker.postMessage(payload);
            };
            reader.readAsText(file);
        } else {
            spinner.hide();
            alert("Please provide a CSV file.");
        }
    };
    // Button handlers.
    $("#button").click(function () {
        var file;
        file = $("#picker").get(0).files[0];
        dump(file);
    });
    // Drag-and-Drop handlers.
    $("#dropzone").bind("dragover", function (e) {
        e.preventDefault();
        $(this).css("background", "red");
    });
    $("#dropzone").bind("dragleave", function (e) {
        e.preventDefault();
        $(this).css("background", "white");
    });
    $("#dropzone").bind("drop", function (e) {
        var file;
        e.preventDefault();
        $(this).css("background", "white");
        file = e.dataTransfer.files[0];
        dump(file);
    });
});
<|endoftext|>