<commit_before>var Template=require('../util/Template');
var advanced_config=require('../../config/advanced-config');
var app_config=require('../../config/application-config');
var map_config=require('../../config/map-config');
var picpilot_config=require('../../config/picpilot-config');

module.exports=function(Marionette,$){

  return Marionette.ItemView.extend({
    template:Template('AppSettingsView'),
    className:'appSettingsView',

    ui:{
      app_settings:'.app-settings',
      save_button:'.save-button',
      discard_button:'discard_button'
    },

    events:{
      "click .save-button": 'saveSettings',
      "click .discard-button":'discardChanges',
      "click .reset-default-button":'resetSettingsToDefault'
    },

    //adds the current settings to the settings object and adds an input for the setting to the screen
    addSettings: function(settings){
      this.settings[settings.file_name]={
      };
      this.original_settings[settings.file_name]=settings;
      for(var key in settings.default_settings){
        if(settings.default_settings.hasOwnProperty(key)){
          this.settings[settings.file_name][key]={
            element: null,
            val: settings.get(key)
          };
          var container=$('

'+key+'

');
          var input=$('<input type="text">');
          input.val(this.settings[settings.file_name][key].val);
          container.append(input);
          this.ui.app_settings.append(container);
          this.settings[settings.file_name][key].element=input;
        }
      }
    },

    initialize: function(){
      this.settings={}; //where all of the settings and newly modified settings will be stored
      this.original_settings={};
    },
    onRender:function(){
      //called right after a render is called on the view (view.render())
      this.ui.app_settings.append('
Advanced Settings
');
      this.addSettings(advanced_config);
      this.ui.app_settings.append('
Application Settings
');
      this.addSettings(app_config);
      this.ui.app_settings.append('
Map Settings
');
      this.addSettings(map_config);
      this.ui.app_settings.append('
Picpilot Settings
');
      this.addSettings(picpilot_config);
    },
    saveSettings: function(){
      for(var filename in this.settings){
        if(this.settings.hasOwnProperty(filename)){ //go to the setting file
          for(var setting_key in this.settings[filename]){
            if(this.settings[filename].hasOwnProperty(setting_key)){ //go to the setting
              console.log(this.settings[filename][setting_key].element);
              console.log(setting_key);
              console.log(this.settings[filename][setting_key].element.val());
              this.original_settings[filename].set(setting_key,this.settings[filename][setting_key].element.val());
            }
          }
        }
      }
    },
    discardChanges:function(){

    },
    resetSettingsToDefault: function(){

    }
  });
};<commit_msg>Integrity of setting types when saving<commit_after>var Template=require('../util/Template');
var advanced_config=require('../../config/advanced-config');
var app_config=require('../../config/application-config');
var map_config=require('../../config/map-config');
var picpilot_config=require('../../config/picpilot-config');

var _=require('underscore');

module.exports=function(Marionette,$){

  return Marionette.ItemView.extend({
    template:Template('AppSettingsView'),
    className:'appSettingsView',

    ui:{
      app_settings:'.app-settings',
      save_button:'.save-button',
      discard_button:'discard_button'
    },

    events:{
      "click .save-button": 'saveSettings',
      "click .discard-button":'discardChanges',
      "click .reset-default-button":'resetSettingsToDefault'
    },

    //adds the current settings to the settings object and adds an input for the setting to the screen
    addSettings: function(settings){
      this.settings[settings.file_name]={};
      this.original_settings[settings.file_name]=settings;
      for(var key in settings.default_settings){
        if(settings.default_settings.hasOwnProperty(key)){
          this.settings[settings.file_name][key]={
            element: null,
            val: settings.get(key)
          };
          var container=$('

'+key+'

');
          var input=$('<input type="text">');
          var setting_val=this.settings[settings.file_name][key].val;
          if(_.isObject(setting_val)){
            input.val(JSON.stringify(setting_val));
          }
          else{
            input.val(setting_val);
          }
          container.append(input);
          this.ui.app_settings.append(container);
          this.settings[settings.file_name][key].element=input;
        }
      }
    },

    initialize: function(){
      this.settings={}; //where all of the settings and newly modified settings will be stored
      this.original_settings={};
    },
    onRender:function(){
      //called right after a render is called on the view (view.render())
      this.ui.app_settings.append('
Advanced Settings
');
      this.addSettings(advanced_config);
      this.ui.app_settings.append('
Application Settings
');
      this.addSettings(app_config);
      this.ui.app_settings.append('
Map Settings
');
      this.addSettings(map_config);
      this.ui.app_settings.append('
Picpilot Settings
');
      this.addSettings(picpilot_config);
    },
    saveSettings: function(){
      for(var filename in this.settings){
        if(this.settings.hasOwnProperty(filename)){ //go to the setting file
          for(var setting_key in this.settings[filename]){
            if(this.settings[filename].hasOwnProperty(setting_key)){ //go to the setting
              var original=this.original_settings[filename].default_settings[setting_key];
              if (_.isObject(original)){ //do a json.parse to store it back as an object
                this.original_settings[filename].set(setting_key,JSON.parse(this.settings[filename][setting_key].element.val()));
              }
              else if (_.isNumber(original)){ //if the original setting is a number store it as a number
                this.original_settings[filename].set(setting_key,Number(this.settings[filename][setting_key].element.val()));
              }
              else { //otherwise just store it as a string
                this.original_settings[filename].set(setting_key,this.settings[filename][setting_key].element.val());
              }
            }
          }
        }
      }
    },
    discardChanges:function(){

    },
    resetSettingsToDefault: function(){

    }
  });
};<|endoftext|>


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

    window.App.videos = [
        {
            title: 'Приключения Паддингтона',
            url: 'http://fs175.www.ex.ua/load/5d4cd54209b5856205c90e19d9493fd1/163586665/Priklucheniya_Paddingtona.2014.avi',
            type: 'vod'
        },
        {
            title: 'Black.Sails.S02E02',
            url: 'http://fs.to/get/dl/5ykw9cc9clxr220r6fhvgjqme.0.521872670.0.1423076519/Black.Sails.S02E02.1080p.rus.LostFilm.TV.mkv',
            type: 'vod'
        },
        {
            title: '3Europa plus',
            url: 'http://europaplus.cdnvideo.ru/europaplus-live/eptv_main.sdp/playlist.m3u8',
            type: 'hls'
        },
        {
            title: '4PIK TV',
            url: 'http://phone.pik-tv.com/live/mp4:piktv3pik3tv/playlist.m3u8',
            type: 'hls'
        },
        {
            title: '5Redbull',
            url: 'http://live.iphone.redbull.de.edgesuite.net/webtvHD.m3u8',
            type: 'hls'
        }
    ];
})();
<commit_msg>Update videos.js<commit_after>(function () {
    "use strict";

    window.App.videos = [
        {
            title: 'Silicon Valley S02E08',
            url: 'http://fs.to/get/dl/6jw62sy7o95w31o0hoe2yr75y.0.521872670.974127405.1433155559/Silicon.Valley.S02E08.1080i.HDTV.DD5.1.H.264.Amedia.ts',
            type: 'vod'
        },
        {
            title: 'Black.Sails.S02E02',
            url: 'http://fs.to/get/dl/5ykw9cc9clxr220r6fhvgjqme.0.521872670.0.1423076519/Black.Sails.S02E02.1080p.rus.LostFilm.TV.mkv',
            type: 'vod'
        },
        {
            title: '3Europa plus',
            url: 'http://europaplus.cdnvideo.ru/europaplus-live/eptv_main.sdp/playlist.m3u8',
            type: 'hls'
        },
        {
            title: '4PIK TV',
            url: 'http://phone.pik-tv.com/live/mp4:piktv3pik3tv/playlist.m3u8',
            type: 'hls'
        },
        {
            title: '5Redbull',
            url: 'http://live.iphone.redbull.de.edgesuite.net/webtvHD.m3u8',
            type: 'hls'
        }
    ];
})();
<|endoftext|>


<commit_before>const OpenBrowserPlugin = require('open-browser-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');
const webpack = require('webpack');

/**
 * --env.production
 * --env.port port
 */

const PAGE_TITLE = "React Planner";
const VENDORS_LIBRARIES = ['immutable', 'react', 'react-dom', 'react-redux', 'redux', 'three'];

module.exports = function (env) {
  let isProduction = env && env.hasOwnProperty('production');
  let port = env && env.hasOwnProperty('port') ? env.port : 8080;

  if (isProduction) console.info('Webpack: Production mode'); else console.info('Webpack: Development mode');

  let config = {
    context: path.resolve(__dirname),
    entry: {
      app: './src/renderer.jsx',
      vendor: VENDORS_LIBRARIES
    },
    output: {
      path: path.join(__dirname, 'dist'),
      filename: '[chunkhash].[name].js',
    },
    performance: {
      hints: isProduction ? 'warning' : false
    },
    devtool: isProduction ? 'source-map' : 'eval',
    devServer: {
      port: port,
      contentBase: path.join(__dirname, './dist'),
    },
    resolve: {
      extensions: ['.js', '.jsx'],
      alias: {
        'react-planner': path.join(__dirname, '../src/index')
      }
    },
    module: {
      rules: [{
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: [{
          loader: 'babel-loader',
          options: {
            "compact": false,
            "plugins": [
              "transform-object-rest-spread"
            ],
            "presets": [
              "es2015-webpack2",
              "react"
            ]
          }

        }]
      }, {
        test: /\.(jpe?g|png|gif|mtl|obj)$/i,
        use: [{
          loader: 'file-loader',
          options: {
            hash: 'sha512',
            digest: 'hex',
            name: '[path][name].[ext]',
            context: 'demo/src'
          }
        }]
      }]
    },
    plugins: [
      new webpack.optimize.CommonsChunkPlugin({
        names: ['vendor', 'manifest'],
        minChunks: Infinity,
        filename: '[chunkhash].[name].js'
      }),

      new HtmlWebpackPlugin({
        title: PAGE_TITLE,
        template: './src/index.html.ejs',
        filename: 'index.html',
        inject: 'body',
      })
    ]
  };

  if (isProduction) {
    config.plugins.push(new webpack.optimize.UglifyJsPlugin());

    config.plugins.push(new webpack.DefinePlugin({
      'process.env': {
        'NODE_ENV': JSON.stringify('production')
      }
    }));
  }

  if (!isProduction) {
    config.plugins.push(new OpenBrowserPlugin({url: `35.166.135.246:${port}`}))
  }

  return config;
};
<commit_msg>Update webpack.config.js<commit_after>const OpenBrowserPlugin = require('open-browser-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');
const webpack = require('webpack');

/**
 * --env.production
 * --env.port port
 */

const PAGE_TITLE = "React Planner";
const VENDORS_LIBRARIES = ['immutable', 'react', 'react-dom', 'react-redux', 'redux', 'three'];

module.exports = function (env) {
  let isProduction = env && env.hasOwnProperty('production');
  let port = env && env.hasOwnProperty('port') ? env.port : 8080;

  if (isProduction) console.info('Webpack: Production mode'); else console.info('Webpack: Development mode');

  let config = {
    context: path.resolve(__dirname),
    entry: {
      app: './src/renderer.jsx',
      vendor: VENDORS_LIBRARIES
    },
    output: {
      path: path.join(__dirname, 'dist'),
      filename: '[chunkhash].[name].js',
    },
    performance: {
      hints: isProduction ? 'warning' : false
    },
    devtool: isProduction ? 'source-map' : 'eval',
    devServer: {
      port: port,
      contentBase: path.join(__dirname, './dist'),
    },
    resolve: {
      extensions: ['.js', '.jsx'],
      alias: {
        'react-planner': path.join(__dirname, '../src/index')
      }
    },
    module: {
      rules: [{
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: [{
          loader: 'babel-loader',
          options: {
            "compact": false,
            "plugins": [
              "transform-object-rest-spread"
            ],
            "presets": [
              "es2015-webpack2",
              "react"
            ]
          }

        }]
      }, {
        test: /\.(jpe?g|png|gif|mtl|obj)$/i,
        use: [{
          loader: 'file-loader',
          options: {
            hash: 'sha512',
            digest: 'hex',
            name: '[path][name].[ext]',
            context: 'demo/src'
          }
        }]
      }]
    },
    plugins: [
      new webpack.optimize.CommonsChunkPlugin({
        names: ['vendor', 'manifest'],
        minChunks: Infinity,
        filename: '[chunkhash].[name].js'
      }),

      new HtmlWebpackPlugin({
        title: PAGE_TITLE,
        template: './src/index.html.ejs',
        filename: 'index.html',
        inject: 'body',
      })
    ]
  };

  if (isProduction) {
    config.plugins.push(new webpack.optimize.UglifyJsPlugin());

    config.plugins.push(new webpack.DefinePlugin({
      'process.env': {
        'NODE_ENV': JSON.stringify('production')
      }
    }));
  }

  if (!isProduction) {
    config.plugins.push(new OpenBrowserPlugin({url: `http://ec2-35-166-135-246.us-west-2.compute.amazonaws.com:${port}`}))
  }

  return config;
};
<|endoftext|>


<commit_before>/*
    ***** BEGIN LICENSE BLOCK *****

    Copyright © 2009 Center for History and New Media
                     George Mason University, Fairfax, Virginia, USA
                     http://zotero.org

    This file is part of Zotero.

    Zotero is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Zotero is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with Zotero.  If not, see <http://www.gnu.org/licenses/>.

    ***** END LICENSE BLOCK *****
*/

Zotero.MIMETypeHandler = new function () {
	var _typeHandlers, _ignoreContentDispositionTypes, _observers;

	/**
	 * Registers URIContentListener to handle MIME types
	 */
	this.init = function() {
		Zotero.debug("Registering URIContentListener");
		// register our nsIURIContentListener and nsIObserver
		Components.classes["@mozilla.org/uriloader;1"].
			getService(Components.interfaces.nsIURILoader).
			registerContentListener(_URIContentListener);
		Components.classes["@mozilla.org/observer-service;1"].
			getService(Components.interfaces.nsIObserverService).
			addObserver(_Observer, "http-on-examine-response", false);
		this.initializeHandlers();
		Zotero.addShutdownListener(function() {
			Components.classes["@mozilla.org/observer-service;1"].
				getService(Components.interfaces.nsIObserverService).
				removeObserver(_Observer, "http-on-examine-response", false);
		});
	}

	/**
	 * Initializes handlers for MIME types
	 */
	this.initializeHandlers = function() {
		_typeHandlers = {};
		_ignoreContentDispositionTypes = [];
		_observers = [];

		if(Zotero.Prefs.get("parseEndNoteMIMETypes")) {
			this.addHandler("application/x-endnote-refer", _importHandler, true);
			this.addHandler("application/x-research-info-systems", _importHandler, true);
			this.addHandler("application/x-inst-for-scientific-info", _importHandler, true);

			this.addHandler("text/x-bibtex", _importHandler, true);
			this.addHandler("application/x-bibtex", _importHandler, true);

			//
			// And some non-standard ones
			//
			this.addHandler("text/x-research-info-systems", _importHandler, true);
			// Nature uses this one
			this.addHandler("text/application/x-research-info-systems", _importHandler, true);
			// Cell uses this one
			this.addHandler("text/ris", _importHandler, true);
			// Not even trying
			this.addHandler("ris", _importHandler, true);
		}
		this.addHandler("application/vnd.citationstyles.style+xml", function(a1, a2) { Zotero.Styles.install(a1, a2) });
		this.addHandler("text/x-csl", function(a1, a2) { Zotero.Styles.install(a1, a2) }); // deprecated
		this.addHandler("application/x-zotero-schema", Zotero.Schema.importSchema);
		this.addHandler("application/x-zotero-settings", Zotero.Prefs.importSettings);
	}

	/**
	 * Adds a handler to handle a specific MIME type
	 * @param {String} type MIME type to handle
	 * @param {Function} fn Function to call to handle type - fn(string, uri)
	 * @param {Boolean} ignoreContentDisposition If true, ignores the Content-Disposition header,
	 *	which is often used to force a file to download rather than let it be handled by the web
	 *	browser
	 */
	this.addHandler = function(type, fn, ignoreContentDisposition) {
		_typeHandlers[type] = fn;
		_ignoreContentDispositionTypes.push(type);
	}

	/**
	 * Adds an observer to inspect and possibly modify page headers
	 */
	this.addObserver = function(fn) {
		_observers.push(fn);
	}

	/**
	 * Handles Refer/RIS/ISI MIME types
	 * @param {String} string The Refer/RIS/ISI formatted records
	 * @param {String} uri The URI from which the Refer/RIS/ISI formatted records were downloaded
	 */
	function _importHandler(string, uri, contentType, channel) {
		var win = channel.notificationCallbacks.getInterface(Components.interfaces.nsIDOMWindow).top;
		if(!win) throw "Attempt to import from a channel without an attached document refused";

		var hostPort = channel.URI.hostPort.replace(";", "_", "g");

		var allowedSitesString = Zotero.Prefs.get("ingester.allowedSites");
		allowedSites = allowedSitesString.split(";");

		if(allowedSites.indexOf(hostPort) === -1) {
			var title = Zotero.getString("ingester.importReferRISDialog.title");
			var text = Zotero.getString("ingester.importReferRISDialog.text", channel.URI.hostPort)+"\n\n";
			var checkMsg = Zotero.getString("ingester.importReferRISDialog.checkMsg");
			var checkValue = {"value":false};

			// make tab-modal dialog (https://developer.mozilla.org/en/Using_tab-modal_prompts)
			var prompt = Components.classes["@mozilla.org/prompter;1"]
				 .getService(Components.interfaces.nsIPromptFactory)
				 .getPrompt(win, Components.interfaces.nsIPrompt);

			var bag = prompt.QueryInterface(Components.interfaces.nsIWritablePropertyBag2);
			bag.setPropertyAsBool("allowTabModal", true);

			var continueDownload = prompt.confirmCheck(title, text, checkMsg, checkValue);
			if(!continueDownload) return;
			if(checkValue.value) {
				// add to allowed sites if desired
				Zotero.Prefs.set("ingester.allowedSites", allowedSitesString+";"+hostPort);
			}
		}

		var frontWindow = Components.classes["@mozilla.org/embedcomp/window-watcher;1"].
			getService(Components.interfaces.nsIWindowWatcher).activeWindow;

		// attempt to import through Zotero.Translate
		var translation = new Zotero.Translate("import");
		translation.setLocation(uri);
		translation.setString(string);

		// attempt to retrieve translators
		var translators = translation.getTranslators();
		if(!translators.length) {
			// we lied. we can't really translate this file.
			throw "No translator found for handled RIS, Refer or ISI file"
		}

		// translate using first available
		translation.setTranslator(translators[0]);
		frontWindow.Zotero_Browser.performTranslation(translation);
	}

	/**
	 * Called to observe a page load
	 */
	var _Observer = new function() {
		this.observe = function(channel) {
			if(Zotero.isConnector) return;

			channel.QueryInterface(Components.interfaces.nsIRequest);
			if(channel.loadFlags & Components.interfaces.nsIHttpChannel.LOAD_DOCUMENT_URI) {
				channel.QueryInterface(Components.interfaces.nsIHttpChannel);
				try {
					// remove content-disposition headers for EndNote, etc.
					var contentType = channel.getResponseHeader("Content-Type").toLowerCase();
					for each(var handledType in _ignoreContentDispositionTypes) {
						if(contentType.length < handledType.length) {
							break;
						} else {
							if(contentType.substr(0, handledType.length) == handledType) {
								channel.setResponseHeader("Content-Disposition", "", false);
								break;
							}
						}
					}
				} catch(e) {}

				for each(var observer in _observers) {
					observer(channel);
				}
			}
		}
	}

	var _URIContentListener = new function() {
		/**
		 * Standard QI definiton
		 */
		this.QueryInterface = function(iid) {
			if  (iid.equals(Components.interfaces.nsISupports)
			   || iid.equals(Components.interfaces.nsISupportsWeakReference)
			   || iid.equals(Components.interfaces.nsIURIContentListener)) {
				return this;
			}
			throw Components.results.NS_ERROR_NO_INTERFACE;
		}

		/**
		 * Called to see if we can handle a content type
		 */
		this.canHandleContent = this.isPreferred = function(contentType, isContentPreferred, desiredContentType) {
			if(Zotero.isConnector) return false;
			return !!_typeHandlers[contentType.toLowerCase()];
		}

		/**
		 * Called to begin handling a content type
		 */
		this.doContent = function(contentType, isContentPreferred, request, contentHandler) {
			Zotero.debug("MIMETypeHandler: handling "+contentType+" from " + request.name);
			contentHandler.value = new _StreamListener(request, contentType.toLowerCase());
			return false;
		}

		/**
		 * Called so that we could stop a load before it happened if we wanted to
		 */
		this.onStartURIOpen = function(URI) {
			return true;
		}
	}

	/**
	 * @class Implements nsIStreamListener and nsIRequestObserver interfaces to download MIME types
	 * 	we've registered ourself as the handler for
	 * @param {nsIRequest} request The request to handle
	 * @param {String} contenType The content type being handled
	 */
	var _StreamListener = function(request, contentType) {
		this._request = request;
		this._contentType = contentType
		this._storageStream = null;
		this._outputStream = null;
		this._binaryInputStream = null;
	}

	/**
	 * Standard QI definiton
	 */
	_StreamListener.prototype.QueryInterface = function(iid) {
		if (iid.equals(Components.interfaces.nsISupports)
		   || iid.equals(Components.interfaces.nsIRequestObserver)
		   || iid.equals(Components.interfaces.nsIStreamListener)) {
			return this;
		}
		throw Components.results.NS_ERROR_NO_INTERFACE;
	}

	/**
	 * Called when the request is started; we ignore this
	 */
	_StreamListener.prototype.onStartRequest = function(channel, context) {}

	/**
	 * Called when there's data available; we collect this data and keep it until the request is
	 * done
	 */
	_StreamListener.prototype.onDataAvailable = function(request, context, inputStream, offset, count) {
		Zotero.debug(count + " bytes available");

		if (!this._storageStream) {
			this._storageStream = Components.classes["@mozilla.org/storagestream;1"].
					createInstance(Components.interfaces.nsIStorageStream);
			this._storageStream.init(4096, 4294967295, null); // PR_UINT32_MAX
			this._outputStream = this._storageStream.getOutputStream(0);

			this._binaryInputStream = Components.classes["@mozilla.org/binaryinputstream;1"].
					createInstance(Components.interfaces.nsIBinaryInputStream);
			this._binaryInputStream.setInputStream(inputStream);
		}

		var bytes = this._binaryInputStream.readBytes(count);
		this._outputStream.write(bytes, count);
	}

	/**
	 * Called when the request is done
	 */
	_StreamListener.prototype.onStopRequest = function(channel, context, status) {
		Zotero.debug("charset is " + channel.contentCharset);

		var inputStream = this._storageStream.newInputStream(0);
		var charset = channel.contentCharset ? channel.contentCharset : "UTF-8";
		const replacementChar = Components.interfaces.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER;
		var convStream = Components.classes["@mozilla.org/intl/converter-input-stream;1"]
					.createInstance(Components.interfaces.nsIConverterInputStream);
		convStream.init(inputStream, charset, 1024, replacementChar);
		var readString = "";
		var str = {};
		while (convStream.readString(4096, str) != 0) {
			readString += str.value;
		}
		convStream.close();
		inputStream.close();

		try {
			_typeHandlers[this._contentType](readString, (this._request.name ? this._request.name : null),
				this._contentType, channel);
		} catch(e) {
			// if there was an error, handle using nsIExternalHelperAppService
			var externalHelperAppService = Components.classes["@mozilla.org/uriloader/external-helper-app-service;1"].
				getService(Components.interfaces.nsIExternalHelperAppService);
			var frontWindow = Components.classes["@mozilla.org/embedcomp/window-watcher;1"].
				getService(Components.interfaces.nsIWindowWatcher).activeWindow;

			var inputStream = this._storageStream.newInputStream(0);
			var streamListener = externalHelperAppService.doContent(this._contentType, this._request, frontWindow, null);
			if (streamListener) {
				streamListener.onStartRequest(channel, context);
				streamListener.onDataAvailable(this._request, context, inputStream, 0, this._storageStream.length);
				streamListener.onStopRequest(channel, context, status);
			}
			this._storageStream.close();

			// then throw our error
			throw e;
		}

		this._storageStream.close();
	}
}
<commit_msg>Update mimeTypeHandler for asynchronous getTranslators<commit_after>/*
    ***** BEGIN LICENSE BLOCK *****

    Copyright © 2009 Center for History and New Media
                     George Mason University, Fairfax, Virginia, USA
                     http://zotero.org

    This file is part of Zotero.

    Zotero is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Zotero is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with Zotero.  If not, see <http://www.gnu.org/licenses/>.

    ***** END LICENSE BLOCK *****
*/

Zotero.MIMETypeHandler = new function () {
	var _typeHandlers, _ignoreContentDispositionTypes, _observers;

	/**
	 * Registers URIContentListener to handle MIME types
	 */
	this.init = function() {
		Zotero.debug("Registering URIContentListener");
		// register our nsIURIContentListener and nsIObserver
		Components.classes["@mozilla.org/uriloader;1"].
			getService(Components.interfaces.nsIURILoader).
			registerContentListener(_URIContentListener);
		Components.classes["@mozilla.org/observer-service;1"].
			getService(Components.interfaces.nsIObserverService).
			addObserver(_Observer, "http-on-examine-response", false);
		this.initializeHandlers();
		Zotero.addShutdownListener(function() {
			Components.classes["@mozilla.org/observer-service;1"].
				getService(Components.interfaces.nsIObserverService).
				removeObserver(_Observer, "http-on-examine-response", false);
		});
	}

	/**
	 * Initializes handlers for MIME types
	 */
	this.initializeHandlers = function() {
		_typeHandlers = {};
		_ignoreContentDispositionTypes = [];
		_observers = [];

		if(Zotero.Prefs.get("parseEndNoteMIMETypes")) {
			this.addHandler("application/x-endnote-refer", _importHandler, true);
			this.addHandler("application/x-research-info-systems", _importHandler, true);
			this.addHandler("application/x-inst-for-scientific-info", _importHandler, true);

			this.addHandler("text/x-bibtex", _importHandler, true);
			this.addHandler("application/x-bibtex", _importHandler, true);

			//
			// And some non-standard ones
			//
			this.addHandler("text/x-research-info-systems", _importHandler, true);
			// Nature uses this one
			this.addHandler("text/application/x-research-info-systems", _importHandler, true);
			// Cell uses this one
			this.addHandler("text/ris", _importHandler, true);
			// Not even trying
			this.addHandler("ris", _importHandler, true);
		}
		this.addHandler("application/vnd.citationstyles.style+xml", function(a1, a2) { Zotero.Styles.install(a1, a2) });
		this.addHandler("text/x-csl", function(a1, a2) { Zotero.Styles.install(a1, a2) }); // deprecated
		this.addHandler("application/x-zotero-schema", Zotero.Schema.importSchema);
		this.addHandler("application/x-zotero-settings", Zotero.Prefs.importSettings);
	}

	/**
	 * Adds a handler to handle a specific MIME type
	 * @param {String} type MIME type to handle
	 * @param {Function} fn Function to call to handle type - fn(string, uri)
	 * @param {Boolean} ignoreContentDisposition If true, ignores the Content-Disposition header,
	 *	which is often used to force a file to download rather than let it be handled by the web
	 *	browser
	 */
	this.addHandler = function(type, fn, ignoreContentDisposition) {
		_typeHandlers[type] = fn;
		_ignoreContentDispositionTypes.push(type);
	}

	/**
	 * Adds an observer to inspect and possibly modify page headers
	 */
	this.addObserver = function(fn) {
		_observers.push(fn);
	}

	/**
	 * Handles Refer/RIS/ISI MIME types
	 * @param {String} string The Refer/RIS/ISI formatted records
	 * @param {String} uri The URI from which the Refer/RIS/ISI formatted records were downloaded
	 */
	function _importHandler(string, uri, contentType, channel) {
		var win = channel.notificationCallbacks.getInterface(Components.interfaces.nsIDOMWindow).top;
		if(!win) throw "Attempt to import from a channel without an attached document refused";

		var hostPort = channel.URI.hostPort.replace(";", "_", "g");

		var allowedSitesString = Zotero.Prefs.get("ingester.allowedSites");
		allowedSites = allowedSitesString.split(";");

		if(allowedSites.indexOf(hostPort) === -1) {
			var title = Zotero.getString("ingester.importReferRISDialog.title");
			var text = Zotero.getString("ingester.importReferRISDialog.text", channel.URI.hostPort)+"\n\n";
			var checkMsg = Zotero.getString("ingester.importReferRISDialog.checkMsg");
			var checkValue = {"value":false};

			// make tab-modal dialog (https://developer.mozilla.org/en/Using_tab-modal_prompts)
			var prompt = Components.classes["@mozilla.org/prompter;1"]
				 .getService(Components.interfaces.nsIPromptFactory)
				 .getPrompt(win, Components.interfaces.nsIPrompt);

			var bag = prompt.QueryInterface(Components.interfaces.nsIWritablePropertyBag2);
			bag.setPropertyAsBool("allowTabModal", true);

			var continueDownload = prompt.confirmCheck(title, text, checkMsg, checkValue);
			if(!continueDownload) return;
			if(checkValue.value) {
				// add to allowed sites if desired
				Zotero.Prefs.set("ingester.allowedSites", allowedSitesString+";"+hostPort);
			}
		}

		var frontWindow = Components.classes["@mozilla.org/embedcomp/window-watcher;1"].
			getService(Components.interfaces.nsIWindowWatcher).activeWindow;

		// attempt to import through Zotero.Translate
		var translation = new Zotero.Translate("import");
		translation.setLocation(uri);
		translation.setString(string);

		// attempt to retrieve translators
		return translation.getTranslators().then(function(translators) {
			if(!translators.length) {
				// we lied. we can't really translate this file.
				throw "No translator found for handled RIS, Refer or ISI file"
			}

			// translate using first available
			translation.setTranslator(translators[0]);
			frontWindow.Zotero_Browser.performTranslation(translation);
		});
	}

	/**
	 * Called to observe a page load
	 */
	var _Observer = new function() {
		this.observe = function(channel) {
			if(Zotero.isConnector) return;

			channel.QueryInterface(Components.interfaces.nsIRequest);
			if(channel.loadFlags & Components.interfaces.nsIHttpChannel.LOAD_DOCUMENT_URI) {
				channel.QueryInterface(Components.interfaces.nsIHttpChannel);
				try {
					// remove content-disposition headers for EndNote, etc.
					var contentType = channel.getResponseHeader("Content-Type").toLowerCase();
					for each(var handledType in _ignoreContentDispositionTypes) {
						if(contentType.length < handledType.length) {
							break;
						} else {
							if(contentType.substr(0, handledType.length) == handledType) {
								channel.setResponseHeader("Content-Disposition", "", false);
								break;
							}
						}
					}
				} catch(e) {}

				for each(var observer in _observers) {
					observer(channel);
				}
			}
		}
	}

	var _URIContentListener = new function() {
		/**
		 * Standard QI definiton
		 */
		this.QueryInterface = function(iid) {
			if  (iid.equals(Components.interfaces.nsISupports)
			   || iid.equals(Components.interfaces.nsISupportsWeakReference)
			   || iid.equals(Components.interfaces.nsIURIContentListener)) {
				return this;
			}
			throw Components.results.NS_ERROR_NO_INTERFACE;
		}

		/**
		 * Called to see if we can handle a content type
		 */
		this.canHandleContent = this.isPreferred = function(contentType, isContentPreferred, desiredContentType) {
			if(Zotero.isConnector) return false;
			return !!_typeHandlers[contentType.toLowerCase()];
		}

		/**
		 * Called to begin handling a content type
		 */
		this.doContent = function(contentType, isContentPreferred, request, contentHandler) {
			Zotero.debug("MIMETypeHandler: handling "+contentType+" from " + request.name);
			contentHandler.value = new _StreamListener(request, contentType.toLowerCase());
			return false;
		}

		/**
		 * Called so that we could stop a load before it happened if we wanted to
		 */
		this.onStartURIOpen = function(URI) {
			return true;
		}
	}

	/**
	 * @class Implements nsIStreamListener and nsIRequestObserver interfaces to download MIME types
	 * 	we've registered ourself as the handler for
	 * @param {nsIRequest} request The request to handle
	 * @param {String} contenType The content type being handled
	 */
	var _StreamListener = function(request, contentType) {
		this._request = request;
		this._contentType = contentType
		this._storageStream = null;
		this._outputStream = null;
		this._binaryInputStream = null;
	}

	/**
	 * Standard QI definiton
	 */
	_StreamListener.prototype.QueryInterface = function(iid) {
		if (iid.equals(Components.interfaces.nsISupports)
		   || iid.equals(Components.interfaces.nsIRequestObserver)
		   || iid.equals(Components.interfaces.nsIStreamListener)) {
			return this;
		}
		throw Components.results.NS_ERROR_NO_INTERFACE;
	}

	/**
	 * Called when the request is started; we ignore this
	 */
	_StreamListener.prototype.onStartRequest = function(channel, context) {}

	/**
	 * Called when there's data available; we collect this data and keep it until the request is
	 * done
	 */
	_StreamListener.prototype.onDataAvailable = function(request, context, inputStream, offset, count) {
		Zotero.debug(count + " bytes available");

		if (!this._storageStream) {
			this._storageStream = Components.classes["@mozilla.org/storagestream;1"].
					createInstance(Components.interfaces.nsIStorageStream);
			this._storageStream.init(16384, 4294967295, null); // PR_UINT32_MAX
			this._outputStream = this._storageStream.getOutputStream(0);

			this._binaryInputStream = Components.classes["@mozilla.org/binaryinputstream;1"].
					createInstance(Components.interfaces.nsIBinaryInputStream);
			this._binaryInputStream.setInputStream(inputStream);
		}

		var bytes = this._binaryInputStream.readBytes(count);
		this._outputStream.write(bytes, count);
	}

	/**
	 * Called when the request is done
	 */
	_StreamListener.prototype.onStopRequest = function(channel, context, status) {
		Zotero.debug("charset is " + channel.contentCharset);

		var inputStream = this._storageStream.newInputStream(0);
		var charset = channel.contentCharset ? channel.contentCharset : "UTF-8";
		const replacementChar = Components.interfaces.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER;
		var convStream = Components.classes["@mozilla.org/intl/converter-input-stream;1"]
					.createInstance(Components.interfaces.nsIConverterInputStream);
		convStream.init(inputStream, charset, 16384, replacementChar);
		var readString = "";
		var str = {};
		while (convStream.readString(16384, str) != 0) {
			readString += str.value;
		}
		convStream.close();
		inputStream.close();

		var me = this;
		Q(_typeHandlers[this._contentType](readString, (this._request.name ? this._request.name : null),
			this._contentType, channel)).fail(function(e) {
				// if there was an error, handle using nsIExternalHelperAppService
				var externalHelperAppService = Components.classes["@mozilla.org/uriloader/external-helper-app-service;1"].
					getService(Components.interfaces.nsIExternalHelperAppService);
				var frontWindow = Components.classes["@mozilla.org/embedcomp/window-watcher;1"].
					getService(Components.interfaces.nsIWindowWatcher).activeWindow;

				var inputStream = me._storageStream.newInputStream(0);
				var streamListener = externalHelperAppService.doContent(me._contentType, me._request, frontWindow, null);
				if (streamListener) {
					streamListener.onStartRequest(channel, context);
					streamListener.onDataAvailable(me._request, context, inputStream, 0, me._storageStream.length);
					streamListener.onStopRequest(channel, context, status);
				}

				// then throw our error
				throw e;
			}).fin(function() {
				me._storageStream.close();
			}).done();
	}
}
<|endoftext|>


<commit_before>//java -jar layout/yuicompressor-2.4.2.jar --type js -o layout/functions.js --line-break 0 layout/functions-orig.js

/**
 * Class to mange general settings and application updates.
 *
 * @author Bion Oren
 * @version 1.0
 */
var lusa = {
    /** STRING - 'student' if this is the student view. */
    student: null,
    /** STRING - 'trad' if this is the trad view. */
    trad: null,
    /** STRING - The currently selected semester. */
    semester: null,
    /** STRING - The currently selected campus. */
    campus: null
};

/**
 * Initializes the application.
 *
 * @return VOID
 */
lusa.init = function() {
    lusa.updateOptions();
    lusa.loadClasses();
    /**
     * Generates a callback function to update the entire application state.
     *
     * @param STRING type The instance variable to be updated by the callback function.
     * @return FUNCTION
     */
    updateFunction = function(type) {
        /**
         * Callback function to update a property and reload the app.
         *
         * @param EVENT Event that triggered the callback.
         * @return VOID
         */
        return function(event) {
            lusa[type] = this.value;
            cookie = lusa.getCookie(lusa.getCookieName());
            document.location = "index.php?"+lusa.getOptions()+"#"+cookie;
        }
    };
    Event.observe($('typeStudent'), 'click', updateFunction("student"));
    Event.observe($('typeProf'), 'click', updateFunction("student"));
    Event.observe($('typeTraditional'), 'click', updateFunction("trad"));
    Event.observe($('typeNonTraditional'), 'click', updateFunction("trad"));
    if($('campusSelect')) {
        Event.observe($('campusSelect'), 'change', updateFunction("campus"));
    }
    Event.observe($('semesterSelect'), 'change', updateFunction("semester"));
};

/**
 * Updates the location in the URL hash and in the cookie.
 *
 * @return VOID
 */
lusa.updateLocation = function() {
    str = lusa.getOptions();
    Dropdown.instances.each(function(dropdown) {
        if(dropdown.course.value && dropdown.course.value != "0") {
            str += "&choice[]="+dropdown.course.value;
        }
    });
    document.location.hash = str;
    date = new Date();
    date.setTime(date.getTime()+(365*24*60*60*1000));
    if(this.student == "student") {
        document.cookie = this.getCookieName()+"="+str+"; expires="+date.toUTCString();
    }
};

/**
 * Updates the schedule preview picture.
 *
 * @return VOID
 */
lusa.updatePreview = function() {
    if($('scheduleImg')) {
        tmp = new Array();
        url = "print.php?sem=2011SP&trad="+lusa.trad+"&classes=";
        Dropdown.classes.each(function(kvp) {
            tmp.push(kvp[1]);
        });
        url += tmp.join("~");
        $('scheduleImg').src = url;
    }
};

/**
 * Updates all the internal variables from their form controls.
 *
 * @return VOID
 */
lusa.updateOptions = function() {
    if($('typeStudent').checked) {
        lusa.student = $('typeStudent').value;
    } else {
        lusa.student = $('typeProf').value;
    }
    if($('typeTraditional').checked) {
        lusa.trad = $('typeTraditional').value;
    } else {
        lusa.trad = $('typeNonTraditional').value;
    }
    if($('campusSelect')) {
        lusa.campus = $('campusSelect').value;
    }
    if(!lusa.campus) {
        lusa.campus = "MAIN";
    }
    lusa.semester = $('semesterSelect').value;
};

/**
 * Returns a list of common options in a URL ready format.
 *
 * @return STRING List of options for a URL.
 */
lusa.getOptions = function() {
    return "role="+lusa.student+"&type="+lusa.trad+"&semester="+lusa.semester+"&campus="+lusa.campus;
};

/**
 * Loads classes from any visible class descriptions and creates a new empty dropdown.
 *
 * @return VOID
 */
lusa.loadClasses = function() {
    if($('classes')) {
        cookie = lusa.getCookie(lusa.getCookieName());
        if(cookie) {
            cookie.split("&").each(function(part) {
                if(part.startsWith("choice[]")) {
                    new Dropdown(part.split("=")[1]);
                }
            });
        }
    }
    //create dropdowns
    if(lusa.student == "student") {
        new Dropdown();
    }
};

/**
 * Returns the contents of the named cookie.
 *
 * @param c_name STRING - Name of the cookie to get data for.
 * @return STRING - Cookie contents.
 */
lusa.getCookie = function(c_name) {
    if (document.cookie.length>0) {
        c_start=document.cookie.indexOf(c_name + "=");
        if (c_start!=-1) {
            c_start=c_start + c_name.length+1;
            c_end=document.cookie.indexOf(";",c_start);
            if (c_end==-1) {
                c_end=document.cookie.length;
            }
            return unescape(document.cookie.substring(c_start,c_end));
        }
    }
    return null;
 };

/**
 * Returns the name of the cookie currently storing user data.
 *
 * @return STRING - cookie name.
 */
lusa.getCookieName = function() {
   return lusa.semester+lusa.trad+lusa.campus;
};

/**
 * Manages class selection dropdowns.
 *
 * @author Bion Oren
 * @version 1.0
 */
var Dropdown = Class.create({
    /**
     * Constructs a new department dropdown in a div container.
     *
     * @param value STRING Optional default value of the form DEPT-####.
     */
    initialize: function(value) {
        /** @var OBJECT - Container div for these options. */
        this.container = document.createElement("div");
        /** @var OBJECT - Reference to the department dropdown. */
        this.dept = document.createElement("select");
        /** @var OBJECT - Reference to the class dropdown. */
        this.course = document.createElement("select");
        /** @var INTEGER - The number of hours the current class is worth. */
        this.hours = 0;
        /** @var COURSE - An object to manage the actual display of course info. */
        this.courseMgr = null;

        $('classDropdowns').appendChild(this.container);
        this.container.appendChild(this.dept);
        this.courseMgr = new Course(this.course);
        option = document.createElement("option");
        option.setAttribute("value", "");
        option.appendChild(document.createTextNode("----"));
        this.dept.appendChild(option);
        if(!lusa.deptCache) {
            new Ajax.Request('postback.php', {
                method: 'post',
                parameters: { mode: 'getDepartmentData', data: lusa.getOptions() },
                onSuccess: function(transport) {
                    data = transport.responseText.evalJSON();
                    lusa.deptCache = data;
                    Object.values(data).each(function(dept) {
                        option = document.createElement("option");
                        option.setAttribute("value", dept);
                        option.appendChild(document.createTextNode(dept));
                        this.dept.appendChild(option);
                    }.bind(this));

                    Event.observe(this.dept, 'change', this.departmentSelected.bind(this));
                }.bind(this),
                onComplete: function() {
                    if(value) {
                        this.dept.value = value.substr(0, 4);
                        this.departmentSelected(value);
                    }
                }.bind(this)
            });
        } else {
            data = lusa.deptCache;
            Object.values(data).each(function(dept) {
                option = document.createElement("option");
                option.setAttribute("value", dept);
                option.appendChild(document.createTextNode(dept));
                this.dept.appendChild(option);
            }.bind(this));

            Event.observe(this.dept, 'change', this.departmentSelected.bind(this));

            if(value) {
                this.dept.value = value.substr(0, 4);
                this.departmentSelected(value);
            }
        }

        Event.observe(this.course, 'change', this.courseSelected.bind(this));

        Dropdown.instances.push(this);
    },

    /**
     * Called when a department dropdown is selected.
     *
     * @param value STRING Optional default value of the form DEPT-####.
     * @return VOID
     */
    departmentSelected: function(value) {
        if(this.dept.value) {
            if(!this.course.firstChild) {
                if(!Object.isString(value)) {
                    d = new Dropdown();
                    $('classDropdowns').appendChild(d.container);
                }
                this.container.appendChild(this.course);
            }
            this.course.value = 0; //reset the course value for each dropdown selection
            lusa.updateLocation();
            this.populateCourse(value);
        } else {
            this.course.value = 0;
            this.courseSelected();
            Element.remove(this.container);
        }
    },

    /**
     * Called when a specific course is selected.
     *
     * @return VOID
     */
    courseSelected: function() {
        //update hours
        hours = this.course.value.substr(-1);
        $('schedHours').innerHTML = parseInt($('schedHours').innerHTML) + parseInt(hours) - this.hours;
        this.hours = hours;

        //update url
        lusa.updateLocation();

        //update class list
        this.courseMgr.reload();
    },

    /**
     * Populates the course dropdown list with the currently selected department.
     *
     * @param value STRING Optional default value of the form DEPT-####.
     * @return VOID
     */
    populateCourse: function(value) {
        new Ajax.Request('postback.php', {
            method: 'post',
            parameters: { mode: 'getCourseData', data: document.location.hash, dept: this.dept.value },
            onSuccess: function(transport) {
                data = transport.responseText.evalJSON();
                if(this.course.children) {
                    $A(this.course.children).each(function(ele) {
                        Element.remove(ele);
                    });
                }
                option = document.createElement("option");
                option.setAttribute("value", 0);
                option.appendChild(document.createTextNode("----"));
                this.course.appendChild(option);
                Object.keys(data).each(function(course) {
                    option = document.createElement("option");
                    option.setAttribute("value", course);
                    if(data[course].error) {
                        option.setAttribute("disabled", "disabled");
                    }
                    option.appendChild(document.createTextNode(data[course]["class"]));
                    this.course.appendChild(option);
                }.bind(this));
                this.course.activate();
            }.bind(this),
            onComplete: function() {
                if(value) {
                    this.course.value = value;
                    this.courseSelected();
                }
            }.bind(this)
        });
    }
});

/** ARRAY List of dropdown class instances. */
Dropdown.instances = new Array();
/** HASH Mapping from courses to their print script query string argument. */
Dropdown.classes = new Hash();

/**
 * Class to manage interactions with class dropdowns and their interactions with the schedule preview and class information table row(s).
 *
 * @author Bion Oren
 * @version 1.0
 */
var Course = Class.create({
    /**
     * Initializes the class.
     *
     * @param OBJECT course Reference to a class dropdown.
     */
    initialize: function(course) {
        this.course = course;
        this.value = this.course.value;
        this.reload();
    },

    /**
     * Reloads the class dropdown with the current department information.
     *
     * @return VOID
     */
    reload: function() {
        if(this.course.value) {
            if(this.value && this.course.value != this.value) {
                Dropdown.classes.unset(this.value);
                lusa.updatePreview();
            }
            new Ajax.Updater('classes', 'postback.php', {
                parameters: { mode: 'updateClasses', data: document.location.hash },
                onSuccess: function(transport) {
                    if(this.value) {
                        $$("."+this.value).each(function(ele) {
                            Element.remove(ele);
                        }.bind(this));
                    }
                }.bind(this),
                onComplete: function(transport) {
                    this.value = this.course.value;
                    Dropdown.instances.each(function(dropdown) {
                        if(dropdown.courseMgr) {
                            dropdown.courseMgr.update();
                        }
                    });
                    lusa.updatePreview();
                }.bind(this)
            });
        }
    },

    /**
     * Updates the Dropdown.classes hash for the course this class is managing.
     *
     * @return VOID
     */
    update: function() {
        if(this.course.value) {
            rows = $$("."+this.course.value);
            if(rows.length == 1 || typeof rows[1].down("input") == "undefined") {
                Dropdown.classes.set(this.value, rows[0].id);
            }
        }
    }
});

/**
 * Toggles the visibility of class sections in the class defined by key.
 *
 * @param key STRING - Class ID of the form DEPT-####
 * @return VOID
 */
Course.toggle = function(key) {
    sections = $$('.'+key);
    sections.shift(); // remove the toggle header from the list
    tmp = sections.first();
    if(tmp.style.visibility == "visible") {
        state = "collapse";
        $(key).innerHTML = "+";
    } else {
        state = "visible";
        $(key).innerHTML = "-";
    }
    sections.each(function(section) {
        if(section.style.cursor != "pointer") {
            section.style.visibility = state;
        }
    });
};

/**
 * Callback for when a class is selected among options.
 *
 * @param STRING name Class name.
 * @param STRING printStr Query parameter for the print script.
 * @return VOID
 */
Course.selected = function(name, printStr) {
    Dropdown.classes.set(name, printStr);
    lusa.updatePreview();
};

/**
 * Callback for when a professor is selected.
 *
 * @param OBJECT Reference to the select list that fired this event.
 * @return VOID
 */
function profSelected(ele) {
    new Ajax.Updater('schedule', 'postback.php', {
        parameters: { mode:'updateClasses', data:lusa.getOptions()+"&prof="+ele.value }
    });
}<commit_msg>Fixed a bug that caused classes to sometimes not update properly on the schedule preview<commit_after>//java -jar layout/yuicompressor-2.4.2.jar --type js -o layout/functions.js --line-break 0 layout/functions-orig.js

/**
 * Class to mange general settings and application updates.
 *
 * @author Bion Oren
 * @version 1.0
 */
var lusa = {
    /** STRING - 'student' if this is the student view. */
    student: null,
    /** STRING - 'trad' if this is the trad view. */
    trad: null,
    /** STRING - The currently selected semester. */
    semester: null,
    /** STRING - The currently selected campus. */
    campus: null
};

/**
 * Initializes the application.
 *
 * @return VOID
 */
lusa.init = function() {
    lusa.updateOptions();
    lusa.loadClasses();
    /**
     * Generates a callback function to update the entire application state.
     *
     * @param STRING type The instance variable to be updated by the callback function.
     * @return FUNCTION
     */
    updateFunction = function(type) {
        /**
         * Callback function to update a property and reload the app.
         *
         * @param EVENT Event that triggered the callback.
         * @return VOID
         */
        return function(event) {
            lusa[type] = this.value;
            cookie = lusa.getCookie(lusa.getCookieName());
            document.location = "index.php?"+lusa.getOptions()+"#"+cookie;
        }
    };
    Event.observe($('typeStudent'), 'click', updateFunction("student"));
    Event.observe($('typeProf'), 'click', updateFunction("student"));
    Event.observe($('typeTraditional'), 'click', updateFunction("trad"));
    Event.observe($('typeNonTraditional'), 'click', updateFunction("trad"));
    if($('campusSelect')) {
        Event.observe($('campusSelect'), 'change', updateFunction("campus"));
    }
    Event.observe($('semesterSelect'), 'change', updateFunction("semester"));
};

/**
 * Updates the location in the URL hash and in the cookie.
 *
 * @return VOID
 */
lusa.updateLocation = function() {
    str = lusa.getOptions();
    Dropdown.instances.each(function(dropdown) {
        if(dropdown.course.value && dropdown.course.value != "0") {
            str += "&choice[]="+dropdown.course.value;
        }
    });
    document.location.hash = str;
    date = new Date();
    date.setTime(date.getTime()+(365*24*60*60*1000));
    if(this.student == "student") {
        document.cookie = this.getCookieName()+"="+str+"; expires="+date.toUTCString();
    }
};

/**
 * Updates the schedule preview picture.
 *
 * @return VOID
 */
lusa.updatePreview = function() {
    if($('scheduleImg')) {
        tmp = new Array();
        url = "print.php?sem=2011SP&trad="+lusa.trad+"&classes=";
        Dropdown.classes.each(function(kvp) {
            tmp.push(kvp[1]);
        });
        url += tmp.join("~");
        $('scheduleImg').src = url;
    }
};

/**
 * Updates all the internal variables from their form controls.
 *
 * @return VOID
 */
lusa.updateOptions = function() {
    if($('typeStudent').checked) {
        lusa.student = $('typeStudent').value;
    } else {
        lusa.student = $('typeProf').value;
    }
    if($('typeTraditional').checked) {
        lusa.trad = $('typeTraditional').value;
    } else {
        lusa.trad = $('typeNonTraditional').value;
    }
    if($('campusSelect')) {
        lusa.campus = $('campusSelect').value;
    }
    if(!lusa.campus) {
        lusa.campus = "MAIN";
    }
    lusa.semester = $('semesterSelect').value;
};

/**
 * Returns a list of common options in a URL ready format.
 *
 * @return STRING List of options for a URL.
 */
lusa.getOptions = function() {
    return "role="+lusa.student+"&type="+lusa.trad+"&semester="+lusa.semester+"&campus="+lusa.campus;
};

/**
 * Loads classes from any visible class descriptions and creates a new empty dropdown.
 *
 * @return VOID
 */
lusa.loadClasses = function() {
    if($('classes')) {
        cookie = lusa.getCookie(lusa.getCookieName());
        if(cookie) {
            cookie.split("&").each(function(part) {
                if(part.startsWith("choice[]")) {
                    new Dropdown(part.split("=")[1]);
                }
            });
        }
    }
    //create dropdowns
    if(lusa.student == "student") {
        new Dropdown();
    }
};

/**
 * Returns the contents of the named cookie.
 *
 * @param c_name STRING - Name of the cookie to get data for.
 * @return STRING - Cookie contents.
 */
lusa.getCookie = function(c_name) {
    if (document.cookie.length>0) {
        c_start=document.cookie.indexOf(c_name + "=");
        if (c_start!=-1) {
            c_start=c_start + c_name.length+1;
            c_end=document.cookie.indexOf(";",c_start);
            if (c_end==-1) {
                c_end=document.cookie.length;
            }
            return unescape(document.cookie.substring(c_start,c_end));
        }
    }
    return null;
 };

/**
 * Returns the name of the cookie currently storing user data.
 *
 * @return STRING - cookie name.
 */
lusa.getCookieName = function() {
   return lusa.semester+lusa.trad+lusa.campus;
};

/**
 * Manages class selection dropdowns.
 *
 * @author Bion Oren
 * @version 1.0
 */
var Dropdown = Class.create({
    /**
     * Constructs a new department dropdown in a div container.
     *
     * @param value STRING Optional default value of the form DEPT-####.
     */
    initialize: function(value) {
        /** @var OBJECT - Container div for these options. */
        this.container = document.createElement("div");
        /** @var OBJECT - Reference to the department dropdown. */
        this.dept = document.createElement("select");
        /** @var OBJECT - Reference to the class dropdown. */
        this.course = document.createElement("select");
        /** @var INTEGER - The number of hours the current class is worth. */
        this.hours = 0;
        /** @var COURSE - An object to manage the actual display of course info. */
        this.courseMgr = null;

        $('classDropdowns').appendChild(this.container);
        this.container.appendChild(this.dept);
        this.courseMgr = new Course(this.course);
        option = document.createElement("option");
        option.setAttribute("value", "");
        option.appendChild(document.createTextNode("----"));
        this.dept.appendChild(option);
        if(!lusa.deptCache) {
            new Ajax.Request('postback.php', {
                method: 'post',
                parameters: { mode: 'getDepartmentData', data: lusa.getOptions() },
                onSuccess: function(transport) {
                    data = transport.responseText.evalJSON();
                    lusa.deptCache = data;
                    Object.values(data).each(function(dept) {
                        option = document.createElement("option");
                        option.setAttribute("value", dept);
                        option.appendChild(document.createTextNode(dept));
                        this.dept.appendChild(option);
                    }.bind(this));

                    Event.observe(this.dept, 'change', this.departmentSelected.bind(this));
                }.bind(this),
                onComplete: function() {
                    if(value) {
                        this.dept.value = value.substr(0, 4);
                        this.departmentSelected(value);
                    }
                }.bind(this)
            });
        } else {
            data = lusa.deptCache;
            Object.values(data).each(function(dept) {
                option = document.createElement("option");
                option.setAttribute("value", dept);
                option.appendChild(document.createTextNode(dept));
                this.dept.appendChild(option);
            }.bind(this));

            Event.observe(this.dept, 'change', this.departmentSelected.bind(this));

            if(value) {
                this.dept.value = value.substr(0, 4);
                this.departmentSelected(value);
            }
        }

        Event.observe(this.course, 'change', this.courseSelected.bind(this));

        Dropdown.instances.push(this);
    },

    /**
     * Called when a department dropdown is selected.
     *
     * @param value STRING Optional default value of the form DEPT-####.
     * @return VOID
     */
    departmentSelected: function(value) {
        if(this.dept.value) {
            if(!this.course.firstChild) {
                if(!Object.isString(value)) {
                    d = new Dropdown();
                    $('classDropdowns').appendChild(d.container);
                }
                this.container.appendChild(this.course);
            }
            this.course.value = 0; //reset the course value for each dropdown selection
            lusa.updateLocation();
            this.populateCourse(value);
        } else {
            this.course.value = 0;
            this.courseSelected();
            Element.remove(this.container);
        }
    },

    /**
     * Called when a specific course is selected.
     *
     * @return VOID
     */
    courseSelected: function() {
        //update hours
        hours = this.course.value.substr(-1);
        $('schedHours').innerHTML = parseInt($('schedHours').innerHTML) + parseInt(hours) - this.hours;
        this.hours = hours;

        //update url
        lusa.updateLocation();

        //update class list
        this.courseMgr.reload();
    },

    /**
     * Populates the course dropdown list with the currently selected department.
     *
     * @param value STRING Optional default value of the form DEPT-####.
     * @return VOID
     */
    populateCourse: function(value) {
        new Ajax.Request('postback.php', {
            method: 'post',
            parameters: { mode: 'getCourseData', data: document.location.hash, dept: this.dept.value },
            onSuccess: function(transport) {
                data = transport.responseText.evalJSON();
                if(this.course.children) {
                    $A(this.course.children).each(function(ele) {
                        Element.remove(ele);
                    });
                }
                option = document.createElement("option");
                option.setAttribute("value", 0);
                option.appendChild(document.createTextNode("----"));
                this.course.appendChild(option);
                Object.keys(data).each(function(course) {
                    option = document.createElement("option");
                    option.setAttribute("value", course);
                    if(data[course].error) {
                        option.setAttribute("disabled", "disabled");
                    }
                    option.appendChild(document.createTextNode(data[course]["class"]));
                    this.course.appendChild(option);
                }.bind(this));
                this.course.activate();
            }.bind(this),
            onComplete: function() {
                if(value) {
                    this.course.value = value;
                    this.courseSelected();
                }
            }.bind(this)
        });
    }
});

/** ARRAY List of dropdown class instances. */
Dropdown.instances = new Array();
/** HASH Mapping from courses to their print script query string argument. */
Dropdown.classes = new Hash();

/**
 * Class to manage interactions with class dropdowns and their interactions with the schedule preview and class information table row(s).
 *
 * @author Bion Oren
 * @version 1.0
 */
var Course = Class.create({
    /**
     * Initializes the class.
     *
     * @param OBJECT course Reference to a class dropdown.
     */
    initialize: function(course) {
        this.course = course;
        this.value = this.course.value;
        this.reload();
    },

    /**
     * Reloads the class dropdown with the current department information.
     *
     * @return VOID
     */
    reload: function() {
        if(this.course.value) {
            if(this.value && this.course.value != this.value) {
                Dropdown.classes.unset(this.value);
                lusa.updatePreview();
            }
            new Ajax.Updater('classes', 'postback.php', {
                parameters: { mode: 'updateClasses', data: document.location.hash },
                onSuccess: function(transport) {
                    if(this.value) {
                        $$("."+this.value).each(function(ele) {
                            Element.remove(ele);
                        }.bind(this));
                    }
                }.bind(this),
                onComplete: function(transport) {
                    this.value = this.course.value;
                    Dropdown.instances.each(function(dropdown) {
                        if(dropdown.courseMgr) {
                            dropdown.courseMgr.update();
                        }
                    });
                    lusa.updatePreview();
                }.bind(this)
            });
        }
    },

    /**
     * Updates the Dropdown.classes hash for the course this class is managing.
     *
     * @return VOID
     */
    update: function() {
        if(this.course.value) {
            rows = $$("."+this.course.value);
            if(rows.length > 0 && (rows.length == 1 || typeof rows[1].down("input") == "undefined")) {
                Dropdown.classes.set(this.value, rows[0].id);
            }
        }
    }
});

/**
 * Toggles the visibility of class sections in the class defined by key.
 *
 * @param key STRING - Class ID of the form DEPT-####
 * @return VOID
 */
Course.toggle = function(key) {
    sections = $$('.'+key);
    sections.shift(); // remove the toggle header from the list
    tmp = sections.first();
    if(tmp.style.visibility == "visible") {
        state = "collapse";
        $(key).innerHTML = "+";
    } else {
        state = "visible";
        $(key).innerHTML = "-";
    }
    sections.each(function(section) {
        if(section.style.cursor != "pointer") {
            section.style.visibility = state;
        }
    });
};

/**
 * Callback for when a class is selected among options.
 *
 * @param STRING name Class name.
 * @param STRING printStr Query parameter for the print script.
 * @return VOID
 */
Course.selected = function(name, printStr) {
    Dropdown.classes.set(name, printStr);
    lusa.updatePreview();
};

/**
 * Callback for when a professor is selected.
 *
 * @param OBJECT Reference to the select list that fired this event.
 * @return VOID
 */
function profSelected(ele) {
    new Ajax.Updater('schedule', 'postback.php', {
        parameters: { mode:'updateClasses', data:lusa.getOptions()+"&prof="+ele.value }
    });
}<|endoftext|>


<commit_before>var sidebarShown = false;

function showSidebar()
{
	if(sidebarShown)
		return;
	sidebarShown = true;

	if ($(document).height() > $(window).height()) {
		var scrollTop = ($('html').scrollTop()) ? $('html').scrollTop() : $('body').scrollTop(); // Works for Chrome, Firefox, IE...
		$('html').addClass('noscroll').css('top',-scrollTop);
	}
	$("#mobile_sidebar").scrollTop(0);
	$("#mobile_sidebar").addClass("shown");
	$("#mobile_overlay").addClass("shown");

	return false;
}

function hideSidebar()
{
	if(!sidebarShown)
		return;

	sidebarShown = false;

	var scrollTop = parseInt($('html').css('top'));
	$('html').removeClass('noscroll');
	$('html,body').scrollTop(-scrollTop);

	$("#mobile_sidebar").removeClass("shown");
	$("#mobile_overlay").removeClass("shown");

	return false;
}

var touchDown = false;
var touchDownX = 0;
var touchDownY = 0;

$(function() {

	$('#mobile_openHeader').bind('click', showSidebar);
	$('#mobile_overlay').bind('click', hideSidebar);

	document.addEventListener('touchstart', function(event) {
		touchDown = true;
		touchDownX = event.touches[0].pageX;
		touchDownY = event.touches[0].pageY;
	}, false);
	document.addEventListener('touchmove', function(event) {
		var dx = event.changedTouches[0].pageX-touchDownX;
		var dy = event.changedTouches[0].pageY-touchDownY;
		if(touchDown && $(window).scrollLeft() == 0 && !sidebarShown && dx > 0 && Math.abs(dx) > Math.abs(dy))
			event.preventDefault();
		else
			touchDown = false;

		$("#lol").text(dx+" "+dy);
		if(dx > 60)
			showSidebar();
	}, false);

	document.addEventListener('scroll', function(event) {
		touchDown = false;
	}, false);

});
<commit_msg>Make slide detector more accurate<commit_after>var sidebarShown = false;

function showSidebar()
{
	if(sidebarShown)
		return;
	sidebarShown = true;

	if ($(document).height() > $(window).height()) {
		var scrollTop = ($('html').scrollTop()) ? $('html').scrollTop() : $('body').scrollTop(); // Works for Chrome, Firefox, IE...
		$('html').addClass('noscroll').css('top',-scrollTop);
	}
	$("#mobile_sidebar").scrollTop(0);
	$("#mobile_sidebar").addClass("shown");
	$("#mobile_overlay").addClass("shown");

	return false;
}

function hideSidebar()
{
	if(!sidebarShown)
		return;

	sidebarShown = false;

	var scrollTop = parseInt($('html').css('top'));
	$('html').removeClass('noscroll');
	$('html,body').scrollTop(-scrollTop);

	$("#mobile_sidebar").removeClass("shown");
	$("#mobile_overlay").removeClass("shown");

	return false;
}

var touchDown = false;
var touchDownX = 0;
var touchDownY = 0;

$(function() {

	$('#mobile_openHeader').bind('click', showSidebar);
	$('#mobile_overlay').bind('click', hideSidebar);

	document.addEventListener('touchstart', function(event) {
		touchDown = true;
		touchDownX = event.touches[0].pageX;
		touchDownY = event.touches[0].pageY;
	}, false);
	document.addEventListener('touchmove', function(event) {
		var dx = event.changedTouches[0].pageX-touchDownX;
		var dy = event.changedTouches[0].pageY-touchDownY;
		if(touchDown && $(window).scrollLeft() == 0 && !sidebarShown && dx > 0 && Math.abs(dx) > Math.abs(dy))
			event.preventDefault();
		else
			touchDown = false;

		$("#lol").text(dx+" "+dy);
		if(dx > 150 && Math.abs(dy) < 20)
			showSidebar();
	}, false);

	document.addEventListener('scroll', function(event) {
		touchDown = false;
	}, false);

});
<|endoftext|>