<commit_before>var webpack = require('webpack')
var path = require('path')
var ExtractTextPlugin = require('extract-text-webpack-plugin')
var StatsPlugin = require('stats-webpack-plugin')
var loadersByExtension = require('./lib/loaders-by-extension')

module.exports = function(opts) {

  var entry = {
    main: opts.prerender ? './app/mainApp' : './app/mainApp'
  }

  var loaders = {
    'jsx': opts.hotComponents ? [ 'react-hot-loader', 'babel-loader?stage=0' ] : 'babel-loader?stage=0',
    'js': {
      loader: 'babel-loader?stage=0',
      include: path.join(__dirname, 'app')
    },
    'json':  'json-loader',
    'txt': 'raw-loader',
    'png|jpg|jpeg|gif|svg': 'url-loader?limit=10000',
    'woff|woff2': 'url-loader?limit=100000',
    'ttf|eot': 'file-loader',
    'wav|mp3': 'file-loader',
    'html': 'html-loader',
    'md|markdown': [ 'html-loader', 'markdown-loader' ]
  }

  var cssLoader = opts.minimize ? 'css-loader' : 'css-loader?localIdentName=[path][name]---[local]---[hash:base64:5]';

  var stylesheetLoaders = {
    'css': cssLoader,
    'less': [ cssLoader, 'less-loader' ],
    'styl': [ cssLoader, 'stylus-loader' ],
    'scss|sass': [ cssLoader, 'sass-loader' ]
  }

  var additionalLoaders = [
    // { test: /some-reg-exp$/, loader: 'any-loader' }
  ]

  var alias = {

  }

  var aliasLoader = {

  }

  var externals = [

  ]

  var modulesDirectories = [ 'node_modules' ]

  var extensions = [ '', '.js', '.jsx', '.json', '.node' ];

  var root = path.join(__dirname, 'app')

  var publicPath = opts.devServer
                 ? 'http://localhost:2992/dist/'
                 : '/dist/'

  var output = {
    path: __dirname + '/dist/',
    filename: 'bundle.js',
    publicPath: 'http://localhost:2992/',
    contentBase: __dirname + '/public/'
  }

  var excludeFromStats = [
    /node_modules[\\\/]react(-router)?[\\\/]/
  ]

  var plugins = [
    new webpack.PrefetchPlugin('react'),
    new webpack.PrefetchPlugin('react/lib/ReactComponentBrowserEnvironment')
  ]

  if (opts.prerender) {
    plugins.push(new StatsPlugin(path.join(__dirname, 'dist', 'stats.prerender.json'), {
      chunkModules: true,
      exclude: excludeFromStats
    }));
    aliasLoader['react-proxy$'] = 'react-proxy/unavailable';
    aliasLoader['react-proxy-loader$'] = 'react-proxy-loader/unavailable';
    externals.push(
      /^react(\/.*)?$/,
      /^reflux(\/.*)?$/,
      'superagent',
      'async'
    );
    plugins.push(new webpack.optimize.LimitChunkCountPlugin({ maxChunks: 1 }));
  } else {
    plugins.push(new StatsPlugin(path.join(__dirname, 'dist', 'stats.json'), {
      chunkModules: true,
      exclude: excludeFromStats
    }));
  }

  if (opts.commonsChunk) {
    plugins.push(new webpack.optimize.CommonsChunkPlugin('commons', 'commons.js' + (opts.longTermCaching && !opts.prerender ? '?[chunkhash]' : '')))
  }

  var asyncLoader = {
    test: require('./app/routes/async').map(function(name) {
      return path.join(__dirname, 'app', 'routes', name);
    }),
    loader: opts.prerender ? 'react-proxy-loader/unavailable' : 'react-proxy-loader'
  }

  Object.keys(stylesheetLoaders).forEach(function(ext) {
    var stylesheetLoader = stylesheetLoaders[ext];
    if(Array.isArray(stylesheetLoader)) stylesheetLoader = stylesheetLoader.join('!');
    if (opts.prerender) {
      stylesheetLoaders[ext] = stylesheetLoader.replace(/^css-loader/, 'css-loader/locals');
    } else if (opts.separateStylesheet) {
      stylesheetLoaders[ext] = ExtractTextPlugin.extract('style-loader', stylesheetLoader);
    } else {
      stylesheetLoaders[ext] = 'style-loader!' + stylesheetLoader;
    }
  })

  if (opts.separateStylesheet && !opts.prerender) {
    plugins.push(new ExtractTextPlugin('[name].css' + (opts.longTermCaching ? '?[contenthash]' : '')));
  }

  if (opts.minimize && !opts.prerender) {
    plugins.push(
      new webpack.optimize.UglifyJsPlugin({
        compressor: {
          warnings: false
        }
      }),
      new webpack.optimize.DedupePlugin()
    )
  }

  if (opts.minimize) {
    plugins.push(
      new webpack.DefinePlugin({
        'process.env': {
          NODE_ENV: "'production'"
        }
      }),
      new webpack.NoErrorsPlugin()
    )
  }

  var nodeModules = fs.readdirSync('node_modules').filter(function(x) { return x !== '.bin' })

  return {
    entry: entry,
    output: output,
    target: 'atom',
    externals: nodeModules,
    module: {
      loaders: [asyncLoader].concat(loadersByExtension(loaders)).concat(loadersByExtension(stylesheetLoaders)).concat(additionalLoaders)
    },
    devtool: opts.devtool,
    debug: opts.debug,
    resolve: {
      root: root,
      modulesDirectories: modulesDirectories,
      extensions: extensions,
      alias: alias
    },
    plugins: plugins,
    devServer: {
      stats: {
        cached: false,
        exclude: excludeFromStats
      }
    }
  }
}
<commit_msg>add missing fs<commit_after>var webpack = require('webpack')
var path = require('path')
var fs = require('fs')
var ExtractTextPlugin = require('extract-text-webpack-plugin')
var StatsPlugin = require('stats-webpack-plugin')
var loadersByExtension = require('./lib/loaders-by-extension')

module.exports = function(opts) {

  var entry = {
    main: opts.prerender ? './app/mainApp' : './app/mainApp'
  }

  var loaders = {
    'jsx': opts.hotComponents ? [ 'react-hot-loader', 'babel-loader?stage=0' ] : 'babel-loader?stage=0',
    'js': {
      loader: 'babel-loader?stage=0',
      include: path.join(__dirname, 'app')
    },
    'json':  'json-loader',
    'txt': 'raw-loader',
    'png|jpg|jpeg|gif|svg': 'url-loader?limit=10000',
    'woff|woff2': 'url-loader?limit=100000',
    'ttf|eot': 'file-loader',
    'wav|mp3': 'file-loader',
    'html': 'html-loader',
    'md|markdown': [ 'html-loader', 'markdown-loader' ]
  }

  var cssLoader = opts.minimize ? 'css-loader' : 'css-loader?localIdentName=[path][name]---[local]---[hash:base64:5]';

  var stylesheetLoaders = {
    'css': cssLoader,
    'less': [ cssLoader, 'less-loader' ],
    'styl': [ cssLoader, 'stylus-loader' ],
    'scss|sass': [ cssLoader, 'sass-loader' ]
  }

  var additionalLoaders = [
    // { test: /some-reg-exp$/, loader: 'any-loader' }
  ]

  var alias = {

  }

  var aliasLoader = {

  }

  var externals = [

  ]

  var modulesDirectories = [ 'node_modules' ]

  var extensions = [ '', '.js', '.jsx', '.json', '.node' ];

  var root = path.join(__dirname, 'app')

  var publicPath = opts.devServer
                 ? 'http://localhost:2992/dist/'
                 : '/dist/'

  var output = {
    path: __dirname + '/dist/',
    filename: 'bundle.js',
    publicPath: 'http://localhost:2992/',
    contentBase: __dirname + '/public/'
  }

  var excludeFromStats = [
    /node_modules[\\\/]react(-router)?[\\\/]/
  ]

  var plugins = [
    new webpack.PrefetchPlugin('react'),
    new webpack.PrefetchPlugin('react/lib/ReactComponentBrowserEnvironment')
  ]

  if (opts.prerender) {
    plugins.push(new StatsPlugin(path.join(__dirname, 'dist', 'stats.prerender.json'), {
      chunkModules: true,
      exclude: excludeFromStats
    }));
    aliasLoader['react-proxy$'] = 'react-proxy/unavailable';
    aliasLoader['react-proxy-loader$'] = 'react-proxy-loader/unavailable';
    externals.push(
      /^react(\/.*)?$/,
      /^reflux(\/.*)?$/,
      'superagent',
      'async'
    );
    plugins.push(new webpack.optimize.LimitChunkCountPlugin({ maxChunks: 1 }));
  } else {
    plugins.push(new StatsPlugin(path.join(__dirname, 'dist', 'stats.json'), {
      chunkModules: true,
      exclude: excludeFromStats
    }));
  }

  if (opts.commonsChunk) {
    plugins.push(new webpack.optimize.CommonsChunkPlugin('commons', 'commons.js' + (opts.longTermCaching && !opts.prerender ? '?[chunkhash]' : '')))
  }

  var asyncLoader = {
    test: require('./app/routes/async').map(function(name) {
      return path.join(__dirname, 'app', 'routes', name);
    }),
    loader: opts.prerender ? 'react-proxy-loader/unavailable' : 'react-proxy-loader'
  }

  Object.keys(stylesheetLoaders).forEach(function(ext) {
    var stylesheetLoader = stylesheetLoaders[ext];
    if(Array.isArray(stylesheetLoader)) stylesheetLoader = stylesheetLoader.join('!');
    if (opts.prerender) {
      stylesheetLoaders[ext] = stylesheetLoader.replace(/^css-loader/, 'css-loader/locals');
    } else if (opts.separateStylesheet) {
      stylesheetLoaders[ext] = ExtractTextPlugin.extract('style-loader', stylesheetLoader);
    } else {
      stylesheetLoaders[ext] = 'style-loader!' + stylesheetLoader;
    }
  })

  if (opts.separateStylesheet && !opts.prerender) {
    plugins.push(new ExtractTextPlugin('[name].css' + (opts.longTermCaching ? '?[contenthash]' : '')));
  }

  if (opts.minimize && !opts.prerender) {
    plugins.push(
      new webpack.optimize.UglifyJsPlugin({
        compressor: {
          warnings: false
        }
      }),
      new webpack.optimize.DedupePlugin()
    )
  }

  if (opts.minimize) {
    plugins.push(
      new webpack.DefinePlugin({
        'process.env': {
          NODE_ENV: "'production'"
        }
      }),
      new webpack.NoErrorsPlugin()
    )
  }

  var nodeModules = fs.readdirSync('node_modules').filter(function(x) { return x !== '.bin' })

  return {
    entry: entry,
    output: output,
    target: 'atom',
    externals: nodeModules,
    module: {
      loaders: [asyncLoader].concat(loadersByExtension(loaders)).concat(loadersByExtension(stylesheetLoaders)).concat(additionalLoaders)
    },
    devtool: opts.devtool,
    debug: opts.debug,
    resolve: {
      root: root,
      modulesDirectories: modulesDirectories,
      extensions: extensions,
      alias: alias
    },
    plugins: plugins,
    devServer: {
      stats: {
        cached: false,
        exclude: excludeFromStats
      }
    }
  }
}
<|endoftext|>


<commit_before>'use strict';

import componentTpl from './<%= componentName %>.html';

function <%= componentNameCamel %>Component($log) {
	'ngInject';

  var component = {
		templateUrl: componentTpl,
		controller: <%= controllerName %>Controller,
		bindings: {}
  };

  return component;

  function <%= controllerName %>Controller ($scope) {
	  $log.debug('Hello from' + '<%= controllerName %>' + 'Controller!');
  }

}

export default <%= componentNameCamel %>Component;
<commit_msg>quick component bug fix<commit_after>'use strict';
import componentTpl from './<%= componentName %>.html';

var <%= componentNameCamel %>Component = {
    templateUrl: componentTpl,
    controller: <%= controllerName %>Controller,
    bindings: {}
};

function <%= controllerName %>Controller($scope, $log) {
    'ngInject';
    $log.debug('Hello from' +
        '<%= controllerName %>' +
        'Controller (component)!');
}

export default <%= componentNameCamel %>Component;
<|endoftext|>


<commit_before>/**
 * The main application viewport, which displays the whole application
 * @extends Ext.Viewport
 */

Ext.require([
    'CF.view.StationSearch',
    'CF.view.StationSearchByFile'
]);

var eventsTabPanel = Ext.create('Ext.TabPanel',{
    region: 'center',
    border: false,
    layout: {
        type: 'vbox',
        align: 'stretch'
    },
    requires: ['CF.view.EventSearchByFile','CF.view.EventSearch'],
    items: [
                {
                    xtype: 'panel',
                    title: 'File',
                    border: false,
                    layout: {
                        type: 'vbox',
                        align: 'stretch'
                    },
                    items: [
                            Ext.create('CF.view.EventSearchByFile'),
                           ]
                },
                {
                    xtype: 'panel',
                    title: 'WS',
                    border: false,
                    layout: {
                        type: 'vbox',
                        align: 'stretch'
                    },
                    items: [
                            Ext.create('CF.view.EventSearch')
                           ]

                }
          ],
    });

var stationsTabPanel = Ext.create('Ext.TabPanel',{
    border: false,
    layout: {
        type: 'vbox',
        align: 'stretch'
    },
    items: [
                {
                    xtype: 'panel',
                    title: 'File',
                    border: false,
                    layout: {
                        type: 'vbox',
                        align: 'stretch'
                    },
                    items: [
                            Ext.create('CF.view.StationSearchByFile')
                           ]
                },
                {
                    xtype: 'panel',
                    title: 'WS',
                    border: false,
                    layout: {
                        type: 'vbox',
                        align: 'stretch'
                    },
                    items: [
                            Ext.create('CF.view.StationSearch')
                           ]

                }
          ]
    });

Ext.define('CF.view.Viewport', {
    extend: 'Ext.Viewport',
    layout: 'fit',
    requires: [
        'Ext.layout.container.Border',
        'Ext.resizer.Splitter',
        'CF.view.Commons',
        'CF.view.ResultsPane',
        'CF.view.Control',
        'CF.view.Map'
    ],

    initComponent: function () {
        var me = this;

        Ext.apply(me, {  id: 'viewport',
            items: [{
                xtype: 'tabpanel',
                border: 'false',
                layout: 'border',
                defaults: {
                    split: true
                },
                items: [
                {
	                title:'Setup',
	                xtype: 'panel',
	                border: 'false',
	                layout: 'border',
	                defaults: {
	                    split: true
                },
                items:[
                    {
                        xtype: 'cf_mappanel'
                    },
                    {
                        xtype: 'tabpanel',		// Search & Upload
                        region: 'center',
                        border: false,
                        id:'tabpanel_principal',
                        name:'tabpanel_principal',
                        layout: {
                            type: 'vbox',
                            align: 'stretch'
                        },
                        items: [
	                                 {
		                                xtype: 'panel',
        				                title: 'Solver',
            				            border: false,
          					              layout: {
                 				           type: 'vbox',
  				                          align: 'stretch'
          					              },
 			                            items: [
 			                                    Ext.create('CF.view.SolverSelect'),
		                             		    Ext.create('CF.view.dataviews.SolverConf')
                                              ]
                   					 },
                   					 {
		                                xtype: 'panel',
		                                title: 'Earthquakes',
		                                id: 'earthquakes',
		                                name: 'earthquakes',
		                                border: false,
		                                disabled: true,
		                                layout: {
		                                    type: 'vbox',
		                                    align: 'stretch'
		                                },
		                                items: [
		                                        eventsTabPanel,
	                                            Ext.create('CF.view.dataviews.EventGrid')
			                                   ]
	                                },
	                                {
	                                    xtype: 'panel',
	                                    title: 'Stations',
		                                id: 'stations',
		                                name: 'stations',
	                                    disabled: true,
	                                    border: false,
	                                    layout: {
	                                        type: 'vbox',
	                                        align: 'stretch'
	                                    },
	                                    items: [
	                                            	stationsTabPanel,
    			                                    Ext.create('CF.view.dataviews.StationGrid')
	                                           ]
	                                },
	                                {
		                                xtype: 'panel',
		                                title: 'Submit',
		                                id: 'submit',
		                                disabled: true,
		                                border: false,
		                                layout: {
		                                    type: 'vbox',
		                                    align: 'stretch'
		                                },
		                                items: [
			                                    Ext.create('CF.view.Submit')
			                                   ]
	                                },
	                                {
		                                xtype: 'panel',
		                                title: 'Control',
		                                border: false,
		                        		layout: 'fit',
		                                items: [Ext.create('CF.view.Control')]
	                                }
			                  ],
		                  listeners: {
		                      'tabchange': function(tabPanel, tab){
		                          if(tab.id=="submit") updateSubmitOverview();
		                      }
		                  }
                    }

                ]
            }
            , {
                xtype: 'panel',	// Earthquake & Station & Common
                title: 'Results',
                region: 'center',
                border: false,
              autoScroll:true,
                layout: {
					           type: 'border',
				            padding: 5
					       },
				       defaults: {
				           split: true
				       },
                items: [	Ext.create('CF.view.ActivityMonitor'),
                        {
							  region: 'center',
					    	  layout: 'border',
					   		  border: false,
					   		  autoScroll:true,
				   	 	  items: [

	                     			Ext.create('CF.view.provenanceGraphsViewer')

	                     			,
	                     			Ext.create('CF.view.ArtifactView')
	                     			]
	                     	}

                      ]
            }
            ]

          }]

        });

        me.callParent(arguments);
    }
});

selectedFile = "";

function updateSubmitOverview() {
	 $("div#submit_overview div#solver").html(gl_solver);
	 $("div#submit_overview div#mesh").html(gl_mesh);
	 $("div#submit_overview div#velmodel").html(gl_velmod);

	 var sEventUrl = gl_eventUrl;
	 if(sEventUrl.indexOf('documents')<0)	sEventUrl=portalUrl+sEventUrl;
	 var linkToUrl = ""+sEventUrl+"";
	 $("div#submit_overview div#eurl").html(linkToUrl);
	 var sStationUrl = gl_stationUrl;
	 if(sStationUrl.indexOf('documents')<0)	sStationUrl=portalUrl+sStationUrl;
	 linkToUrl = ""+sStationUrl+"";
	 $("div#submit_overview div#surl").html(linkToUrl);

	 var selectedStations = Ext.getCmp('gridStations').getSelectionModel().selected;
	 var sStations = "";
	 selectedStations.each(function(item, ind, l)
		{
			if(ind>0)	sStations+= ', ';
			sStations+= '"'+item.get('network')+'.'+item.get('station')+'"';
		});
	 $("div#submit_overview div#ssel").html(sStations);

	 var selectedEvents = Ext.getCmp('gridEvents').getSelectionModel().selected;
	 var sEvents = "";
	 selectedEvents.each(function(item, ind, l)
		{
			if(ind>0)	sEvents+= ', ';
			sEvents+= '"'+item.get('eventId')+'"';
		});
	 $("div#submit_overview div#esel").html(sEvents);

}

function fileSelection(filetype) {
	Ext.Ajax.request({
		url: getListURL,
		params: {
			userSN: userSN,		//user screen name, it is populated in html/init.jsp
			filetype: filetype
		},
		success: function(response){
			showFileSelector(response.responseText, filetype);
		}
	});
}
function showFileSelector(htmlFileList, filetype)
{
    win = Ext.widget('window', {
        title: 'Select existing file',
        closeAction: 'hide',
        width: 300,
        height: 350,
        layout: 'fit',
        modal: true,
        autoScroll: true,
        resizable: false,
        html: htmlFileList,
        buttons: [{
            text: 'Cancel',
            handler: function() {
            	selectedFile = "";
                this.up('window').hide();
            }
        }, {
            text: 'Select',
            handler: function() {
            	parseSelectedFile(this.up('window'), filetype);
            }
        }]
    });
    win.show();
}
function parseSelectedFile(win, filetype)
{
	if(selectedFile==="")
	{
		Ext.Msg.alert("Alert!", "Please, select a file by clicking on it");
	}
	else
	{
		if(filetype===EVENT_TYPE) 	getEvents(ctrl, selectedFile);
		if(filetype===STXML_TYPE || filetype===STPOINTS_TYPE)
			getStations(ctrl, selectedFile, filetype);
		selectedFile = "";
		win.hide();
	}
}
function selectFile(e)
{
	$("li").css('background-color', '');
	selectedFile = e.getAttribute('filePath');
	$(e).css('background-color', '#CED9E7');
}
<commit_msg>minor<commit_after>/**
 * The main application viewport, which displays the whole application
 * @extends Ext.Viewport
 */

Ext.require([
    'CF.view.StationSearch',
    'CF.view.StationSearchByFile'
]);

var eventsTabPanel = Ext.create('Ext.TabPanel',{
    region: 'center',
    border: false,
    layout: {
        type: 'vbox',
        align: 'stretch'
    },
    requires: ['CF.view.EventSearchByFile','CF.view.EventSearch'],
    items: [
                {
                    xtype: 'panel',
                    title: 'File',
                    border: false,
                    layout: {
                        type: 'vbox',
                        align: 'stretch'
                    },
                    items: [
                            Ext.create('CF.view.EventSearchByFile'),
                           ]
                },
                {
                    xtype: 'panel',
                    title: 'WS',
                    border: false,
                    layout: {
                        type: 'vbox',
                        align: 'stretch'
                    },
                    items: [
                            Ext.create('CF.view.EventSearch')
                           ]

                }
          ],
    });

var stationsTabPanel = Ext.create('Ext.TabPanel',{
    border: false,
    layout: {
        type: 'vbox',
        align: 'stretch'
    },
    items: [
                {
                    xtype: 'panel',
                    title: 'File',
                    border: false,
                    layout: {
                        type: 'vbox',
                        align: 'stretch'
                    },
                    items: [
                            Ext.create('CF.view.StationSearchByFile')
                           ]
                },
                {
                    xtype: 'panel',
                    title: 'WS',
                    border: false,
                    layout: {
                        type: 'vbox',
                        align: 'stretch'
                    },
                    items: [
                            Ext.create('CF.view.StationSearch')
                           ]

                }
          ]
    });

Ext.define('CF.view.Viewport', {
    extend: 'Ext.Viewport',
    layout: 'fit',
    requires: [
        'Ext.layout.container.Border',
        'Ext.resizer.Splitter',
        'CF.view.Commons',
        'CF.view.ResultsPane',
        'CF.view.Control',
        'CF.view.Map'
    ],

    initComponent: function () {
        var me = this;

        Ext.apply(me, {  id: 'viewport',
            items: [{
                xtype: 'tabpanel',
                border: 'false',
                layout: 'border',
                defaults: {
                    split: true
                },
                items: [
                {
	                title:'Setup',
	                xtype: 'panel',
	                border: 'false',
	                layout: 'border',
	                defaults: {
	                    split: true
                },
                items:[
                    {
                        xtype: 'cf_mappanel'
                    },
                    {
                        xtype: 'tabpanel',		// Search & Upload
                        region: 'center',
                        border: false,
                        id:'tabpanel_principal',
                        name:'tabpanel_principal',
                        layout: {
                            type: 'vbox',
                            align: 'stretch'
                        },
                        items: [
	                                 {
		                                xtype: 'panel',
        				                title: 'Solver',
            				            border: false,
          					              layout: {
                 				           type: 'vbox',
  				                          align: 'stretch'
          					              },
 			                            items: [
 			                                    Ext.create('CF.view.SolverSelect'),
		                             		    Ext.create('CF.view.dataviews.SolverConf')
                                              ]
                   					 },
                   					 {
		                                xtype: 'panel',
		                                title: 'Earthquakes',
		                                id: 'earthquakes',
		                                name: 'earthquakes',
		                                border: false,
		                                disabled: true,
		                                layout: {
		                                    type: 'vbox',
		                                    align: 'stretch'
		                                },
		                                items: [
		                                        eventsTabPanel,
	                                            Ext.create('CF.view.dataviews.EventGrid')
			                                   ]
	                                },
	                                {
	                                    xtype: 'panel',
	                                    title: 'Stations',
		                                id: 'stations',
		                                name: 'stations',
	                                    disabled: true,
	                                    border: false,
	                                    layout: {
	                                        type: 'vbox',
	                                        align: 'stretch'
	                                    },
	                                    items: [
	                                            	stationsTabPanel,
    			                                    Ext.create('CF.view.dataviews.StationGrid')
	                                           ]
	                                },
	                                {
		                                xtype: 'panel',
		                                title: 'Submit',
		                                id: 'submit',
		                                disabled: true,
		                                border: false,
		                                layout: {
		                                    type: 'vbox',
		                                    align: 'stretch'
		                                },
		                                items: [
			                                    Ext.create('CF.view.Submit')
			                                   ]
	                                },
	                                {
		                                xtype: 'panel',
		                                title: 'Control',
		                                border: false,
		                        		layout: 'fit',
		                                items: [Ext.create('CF.view.Control')]
	                                }
			                  ],
		                  listeners: {
		                      'tabchange': function(tabPanel, tab){
		                          if(tab.id=="submit") updateSubmitOverview();
		                      }
		                  }
                    }

                ]
            }
            , {
                xtype: 'panel',	// Earthquake & Station & Common
                title: 'Results',
                region: 'center',
                border: false,
              autoScroll:true,
                layout: {
					           type: 'border',
				            padding: 5
					       },
				       defaults: {
				           split: true
				       },
                items: [	Ext.create('CF.view.ActivityMonitor'),
                        {
							  region: 'center',
					    	  layout: 'border',
					   		  border: false,
					   		  autoScroll:true,
				   	 	  items: [

	                     			Ext.create('CF.view.provenanceGraphsViewer')

	                     			,
	                     			Ext.create('CF.view.ArtifactView')
	                     			]
	                     	}

                      ]
            }
            ]

          }]

        });

        me.callParent(arguments);
    }
});

selectedFile = "";

function updateSubmitOverview() {
	 $("div#submit_overview div#solver").html(gl_solver);
	 $("div#submit_overview div#mesh").html(gl_mesh);
	 $("div#submit_overview div#velmodel").html(gl_velmod);

	 var sEventUrl = gl_eventUrl;
	 if(sEventUrl.indexOf('documents')<0)	sEventUrl=portalUrl+sEventUrl;
	 var linkToUrl = ""+sEventUrl+"";
	 $("div#submit_overview div#eurl").html(linkToUrl);
	 var sStationUrl = gl_stationUrl;
	 if(sStationUrl.indexOf('documents')<0)	sStationUrl=portalUrl+sStationUrl;
	 linkToUrl = ""+sStationUrl+"";
	 $("div#submit_overview div#surl").html(linkToUrl);

	 var selectedStations = Ext.getCmp('gridStations').getSelectionModel().selected;
	 var sStations = "";
	 selectedStations.each(function(item, ind, l)
		{
			if(ind>0)	sStations+= ', ';
			sStations+= '"'+item.get('network')+'.'+item.get('station')+'"';
		});
	 $("div#submit_overview div#ssel").html(sStations);

	 var selectedEvents = Ext.getCmp('gridEvents').getSelectionModel().selected;
	 var sEvents = "";
	 selectedEvents.each(function(item, ind, l)
		{
			if(ind>0)	sEvents+= ', ';
			sEvents+= '"'+item.get('eventId')+'"';
		});
	 $("div#submit_overview div#esel").html(sEvents);

}

function fileSelection(filetype) {
	Ext.Ajax.request({
		url: getListURL,
		params: {
			userSN: userSN,		//user screen name, it is populated in html/init.jsp
			filetype: filetype
		},
		success: function(response){
			showFileSelector(response.responseText, filetype);
		}
	});
}
function showFileSelector(htmlFileList, filetype)
{
    win = Ext.widget('window', {
        title: 'Select existing file',
        closeAction: 'hide',
        width: 300,
        height: 350,
        layout: 'fit',
        modal: true,
        autoScroll: true,
        resizable: false,
        html: htmlFileList,
        buttons: [{
            text: 'Cancel',
            handler: function() {
            	selectedFile = "";
                this.up('window').hide();
            }
        }, {
            text: 'Select',
            handler: function() {
            	parseSelectedFile(this.up('window'), filetype);
            }
        }]
    });
    win.show();
}
function parseSelectedFile(win, filetype)
{
	if(selectedFile==="")
	{
		Ext.Msg.alert("Alert!", "Please, select a file by clicking on it");
	}
	else
	{
		if(filetype===EVENT_TYPE) 	getEvents(ctrl, selectedFile);
		if(filetype===STXML_TYPE || filetype===STPOINTS_TYPE)
			getStations(ctrl, selectedFile, filetype);
		selectedFile = "";
		win.hide();
	}
}
function selectFile(e)
{
	$("li").css('background-color', '');
	selectedFile = e.getAttribute('filePath');
	$(e).css('background-color', '#CED9E7');
}
<|endoftext|>


<commit_before>'use strict';

var Base = require('../Base');

/**
 * @class
 */
var Registry = Base.extend('Registry', {
    initialize: function() {
        this.items = Object.create(null);
    },

    /**
     * @summary Register an item and return it.
     * @desc Adds an item to the registry using the provided name (or the class name), converted to all lower case.
     * @param {string} [name] - Case-insensitive item key. If not given, fallsback to `item.prototype.$$CLASS_NAME` or `item.prototype.name` or `item.name`.
     * @param [item] - If unregistered or omitted, nothing is added and method returns `undefined`.
     *
     * > Note: `$$CLASS_NAME` is normally set by providing a string as the (optional) first parameter (`alias`) in your {@link https://www.npmjs.com/package/extend-me|extend} call.
     *
     * @returns Newly registered item or `undefined` if unregistered.
     *
     * @memberOf Registry#
     */
    add: function(name, item) {
        if (arguments.length === 1) {
            item = name;
            name = undefined;
        }

        if (!item) {
            return;
        }

        name = name || item.getClassName && item.getClassName();

        if (!name) {
            throw new this.HypergridError('Cannot register ' + this.friendlyName() + ' without a name.');
        }

        this.items[name] = item;

        // update existing keys that differ only in case
        name = name.toLowerCase();
        Object.keys(this.items)
            .filter(function(key) { return key.toLowerCase() === name; })
            .forEach(function(key) { this.items[key] = item; }, this);

        return item;
    },

    /**
     * @summary Register a synonym for an existing item.
     * @param {string} synonymName
     * @param {string} existingName
     * @returns {function|Constructor} The previously registered item this new synonym points to.
     * @memberOf Registry#
     */
    addSynonym: function(synonymName, existingName) {
        return (this.items[synonymName] = this.items[existingName]);
    },

    /**
     * Fetch a registered item.
     * @param {string} [name]
     * @returns {*|undefined} A registered item or `undefined` if unregistered.
     * @memberOf Registry#
     */
    get: function(name) {
        if (!name) {
            return;
        }

        var result = this.items[name]; // for performance reasons, do not convert to lower case

        if (!result) {
            var lowerName = name.toLowerCase(); // name may differ in case only
            var foundName = Object.keys(this.items).find(function(key) { return lowerName === key.toLowerCase(); });

            result = this.items[foundName];

            if (result) {
                // Register name as a synonym for the found name for faster access next
                // time without having to convert to lower case on every get.
                this.addSynonym(name, foundName);
            } else {
                throw new this.HypergridError('Expected "' + name + '" to be a case-insensitive match for a registered ' + this.friendlyName() + '.');
            }
        }

        return result;
    },

    friendlyName: function() {
        if (this.BaseClass) {
            var name = this.BaseClass.getClassName();
            name = name && name.replace(/([A-Z])/g, ' $1').trim().toLowerCase();
        } else {
            name = singularOf(this.getClassName()).toLowerCase();
        }
        name = name || 'item';
        return indefArtOf(name) + ' ' + name;
    }
});

var endings = [
    { plural: /ies$/, singular: 'y' },
    { plural: /s$/, singular: '' }
];

function singularOf(name) {
    endings.find(function(ending) {
        if (ending.plural.test(name)) {
            name = name.replace(ending.plural, ending.singular);
            return true;
        }
    });
    return name;
}

function indefArtOf(name) {
    return /^[aeiou]/.test(name) ? 'an' : 'a';
}

module.exports = Registry;
<commit_msg>add Registry#make<commit_after>'use strict';

var Base = require('../Base');

/**
 * @class
 */
var Registry = Base.extend('Registry', {
    initialize: function() {
        this.items = Object.create(null);
    },

    /**
     * @summary Register an item and return it.
     * @desc Adds an item to the registry using the provided name (or the class name), converted to all lower case.
     * @param {string} [name] - Case-insensitive item key. If not given, fallsback to `item.prototype.$$CLASS_NAME` or `item.prototype.name` or `item.name`.
     * @param [item] - If unregistered or omitted, nothing is added and method returns `undefined`.
     *
     * > Note: `$$CLASS_NAME` is normally set by providing a string as the (optional) first parameter (`alias`) in your {@link https://www.npmjs.com/package/extend-me|extend} call.
     *
     * @returns Newly registered item or `undefined` if unregistered.
     *
     * @memberOf Registry#
     */
    add: function(name, item) {
        if (arguments.length === 1) {
            item = name;
            name = undefined;
        }

        if (!item) {
            return;
        }

        // getClassName defined if new item derived from extend-me
        name = name || item.getClassName && item.getClassName();

        if (!name) {
            throw new this.HypergridError('Cannot register ' + this.friendlyName() + ' without a name.');
        }

        this.items[name] = item;

        // update existing keys that differ only in case
        name = name.toLowerCase();
        Object.keys(this.items)
            .filter(function(key) { return key.toLowerCase() === name; })
            .forEach(function(key) { this.items[key] = item; }, this);

        return item;
    },

    /**
     * @summary Register a synonym for an existing item.
     * @param {string} synonymName
     * @param {string} existingName
     * @returns {function|Constructor} The previously registered item this new synonym points to.
     * @memberOf Registry#
     */
    addSynonym: function(synonymName, existingName) {
        return (this.items[synonymName] = this.items[existingName]);
    },

    /**
     * Create a new item extended from base class. For formal parameters, see {@link Registry#add add}.
     * @memberOf Registry#
     */
    make: function(name, prototype) {
        var last = arguments.length - 1;
        arguments[last] = this.BaseClass.extend(arguments[last]);
        this.add.apply(this, arguments);
    },

    /**
     * Fetch a registered item.
     * @param {string} [name]
     * @returns {*|undefined} A registered item or `undefined` if unregistered.
     * @memberOf Registry#
     */
    get: function(name) {
        if (!name) {
            return;
        }

        var result = this.items[name]; // for performance reasons, do not convert to lower case

        if (!result) {
            var lowerName = name.toLowerCase(); // name may differ in case only
            var foundName = Object.keys(this.items).find(function(key) { return lowerName === key.toLowerCase(); });

            result = this.items[foundName];

            if (result) {
                // Register name as a synonym for the found name for faster access next
                // time without having to convert to lower case on every get.
                this.addSynonym(name, foundName);
            } else {
                throw new this.HypergridError('Expected "' + name + '" to be a case-insensitive match for a registered ' + this.friendlyName() + '.');
            }
        }

        return result;
    },

    friendlyName: function() {
        if (this.BaseClass) {
            var name = this.BaseClass.getClassName();
            name = name && name.replace(/([A-Z])/g, ' $1').trim().toLowerCase();
        } else {
            name = singularOf(this.getClassName()).toLowerCase();
        }
        name = name || 'item';
        return indefArtOf(name) + ' ' + name;
    }
});

var endings = [
    { plural: /ies$/, singular: 'y' },
    { plural: /s$/, singular: '' }
];

function singularOf(name) {
    endings.find(function(ending) {
        if (ending.plural.test(name)) {
            name = name.replace(ending.plural, ending.singular);
            return true;
        }
    });
    return name;
}

function indefArtOf(name) {
    return /^[aeiou]/.test(name) ? 'an' : 'a';
}

module.exports = Registry;
<|endoftext|>


<commit_before>var chai = require('chai');
var expect = chai.expect;
var spies = require('chai-spies');
var HeatingControl = require('../HeatingControl').HeatingControl;

chai.use(spies);

describe("Heating Control", function() {

  function programmeDoubleWithTargetTemperature(targetTemp) {
    return {
      getCurrentTargetTemperature : function() {
        return targetTemp;
      }
    };
  }

  function temperatureProviderDoubleWithCurrentTemperature(currentTemp) {
    return {
      currentTemp : currentTemp,
      getCurrentTemperature : function() {
        return this.currentTemp;
      }
    };
  }

  var onCommandDouble = {
    execute : function() {}
  }
  var offCommandDouble = {
    execute : function() {}
  }
  var onCommandSpy;
  var offCommandSpy;

  beforeEach(function() {
    onCommandSpy = chai.spy.on(onCommandDouble, 'execute');
    offCommandSpy = chai.spy.on(offCommandDouble, 'execute');
  });

  it("should execute ON command on initial interval when current temperature below switching differential high point", function() {
    // arrange
    var heatingControl = new HeatingControl(
      programmeDoubleWithTargetTemperature(20.0),
      temperatureProviderDoubleWithCurrentTemperature(20.49),
      onCommandDouble,
      offCommandDouble);

    // act
    heatingControl.onInterval();

    // assert
    expect(onCommandSpy).to.have.been.called();
    expect(offCommandSpy).to.not.have.been.called();
  });

  it("should execute OFF command on initial interval when current temperature above switching differential high point", function() {
    // arrange
    var heatingControl = new HeatingControl(
      programmeDoubleWithTargetTemperature(20.0),
      temperatureProviderDoubleWithCurrentTemperature(20.5),
      onCommandDouble,
      offCommandDouble
    );

    // act
    heatingControl.onInterval();

    // assert
    expect(onCommandSpy).to.not.have.been.called();
    expect(offCommandSpy).to.have.been.called();
  });

  it("should execute ON command on initial interval when current temperature below switching differential low point", function() {
    // arrange
    var heatingControl = new HeatingControl(
      programmeDoubleWithTargetTemperature(20.0),
      temperatureProviderDoubleWithCurrentTemperature(19.49),
      onCommandDouble,
      offCommandDouble);

    // act
    heatingControl.onInterval();

    // assert
    expect(onCommandSpy).to.have.been.called();
    expect(offCommandSpy).to.not.have.been.called();
  });

  it("should execute ON command on subsequent interval when current temperature rising and below switching differential low point", function() {
    // arrange
    var temperatureProviderDouble = temperatureProviderDoubleWithCurrentTemperature(19.00)
    var heatingControl = new HeatingControl(
      programmeDoubleWithTargetTemperature(20.0),
      temperatureProviderDouble,
      onCommandDouble,
      offCommandDouble);

    // act
    heatingControl.onInterval();
    temperatureProviderDouble.currentTemp = 19.49;
    heatingControl.onInterval();

    // assert
    expect(onCommandSpy).to.have.been.called.twice;
    expect(offCommandSpy).to.not.have.been.called();
  });

  it("should execute ON command on subsequent interval when current temperature rising and within switching differential", function() {
    // arrange
    var temperatureProviderDouble = temperatureProviderDoubleWithCurrentTemperature(19.00)
    var heatingControl = new HeatingControl(
      programmeDoubleWithTargetTemperature(20.0),
      temperatureProviderDouble,
      onCommandDouble,
      offCommandDouble);

      // act
      heatingControl.onInterval();
      temperatureProviderDouble.currentTemp = 20.0;
      heatingControl.onInterval();

      // assert
      expect(onCommandSpy).to.have.been.called.twice;
      expect(offCommandSpy).to.not.have.been.called();
  });

  it("should execute OFF command on subsequent interval when current temperature rising and above switching differential high point", function() {
    // arrange
    var temperatureProviderDouble = temperatureProviderDoubleWithCurrentTemperature(20.00)
    var heatingControl = new HeatingControl(
      programmeDoubleWithTargetTemperature(20.0),
      temperatureProviderDouble,
      onCommandDouble,
      offCommandDouble);

      // act
      heatingControl.onInterval();
      temperatureProviderDouble.currentTemp = 20.50;

      expect(onCommandSpy).to.have.been.called();

      heatingControl.onInterval();

      expect(offCommandSpy).to.have.been.called();
  });

  it("should execute ON command on subsequent interval when current temperature falling and below switching differential low point", function() {
    // arrange
    var temperatureProviderDouble = temperatureProviderDoubleWithCurrentTemperature(21.00)
    var heatingControl = new HeatingControl(
      programmeDoubleWithTargetTemperature(20.0),
      temperatureProviderDouble,
      onCommandDouble,
      offCommandDouble);

      // act
      heatingControl.onInterval();
      temperatureProviderDouble.currentTemp = 19.49;

      expect(offCommandSpy).to.have.been.called();

      heatingControl.onInterval();

      expect(onCommandSpy).to.have.been.called();
  });

  it("should execute OFF command on subsequent interval when current temperature falling into switching differential", function() {
    // arrange
    var temperatureProviderDouble = temperatureProviderDoubleWithCurrentTemperature(21.00)
    var heatingControl = new HeatingControl(
      programmeDoubleWithTargetTemperature(20.0),
      temperatureProviderDouble,
      onCommandDouble,
      offCommandDouble);

      // act
      heatingControl.onInterval();
      temperatureProviderDouble.currentTemp = 20.00;

      expect(offCommandSpy).to.have.been.called();

      heatingControl.onInterval();

      expect(offCommandSpy).to.have.been.called.twice();
  });

  it("should execute OFF command on subsequent interval when current temperature falling and above switching differential high point", function() {
    // arrange
    var temperatureProviderDouble = temperatureProviderDoubleWithCurrentTemperature(22.00)
    var heatingControl = new HeatingControl(
      programmeDoubleWithTargetTemperature(20.0),
      temperatureProviderDouble,
      onCommandDouble,
      offCommandDouble);

      // act
      heatingControl.onInterval();
      temperatureProviderDouble.currentTemp = 21.00;

      expect(offCommandSpy).to.have.been.called();

      heatingControl.onInterval();

      expect(offCommandSpy).to.have.been.called.twice();
  });

  /*
                 | below h low | in h | above h high |
    init         |       X     |   X  |      X       |
    subs rising  |       X     |   X  |      X       |
    subs falling |       X     |   X  |              |
    prog changed |             |      |              |
  */

  // current temp in switching diff (rising)

  // current temp in switching diff (falling)

  // on programme changed
});
<commit_msg>Test prog changed with temp below switching diff<commit_after>var chai = require('chai');
var expect = chai.expect;
var spies = require('chai-spies');
var HeatingControl = require('../HeatingControl').HeatingControl;

chai.use(spies);

describe("Heating Control", function() {

  function programmeDoubleWithTargetTemperature(targetTemp) {
    return {
      getCurrentTargetTemperature : function() {
        return targetTemp;
      }
    };
  }

  function temperatureProviderDoubleWithCurrentTemperature(currentTemp) {
    return {
      currentTemp : currentTemp,
      getCurrentTemperature : function() {
        return this.currentTemp;
      }
    };
  }

  var onCommandDouble = {
    execute : function() {}
  }
  var offCommandDouble = {
    execute : function() {}
  }
  var onCommandSpy;
  var offCommandSpy;

  beforeEach(function() {
    onCommandSpy = chai.spy.on(onCommandDouble, 'execute');
    offCommandSpy = chai.spy.on(offCommandDouble, 'execute');
  });

  it("should execute ON command on initial interval when current temperature below switching differential high point", function() {
    // arrange
    var heatingControl = new HeatingControl(
      programmeDoubleWithTargetTemperature(20.0),
      temperatureProviderDoubleWithCurrentTemperature(20.49),
      onCommandDouble,
      offCommandDouble);

    // act
    heatingControl.onInterval();

    // assert
    expect(onCommandSpy).to.have.been.called();
    expect(offCommandSpy).to.not.have.been.called();
  });

  it("should execute OFF command on initial interval when current temperature above switching differential high point", function() {
    // arrange
    var heatingControl = new HeatingControl(
      programmeDoubleWithTargetTemperature(20.0),
      temperatureProviderDoubleWithCurrentTemperature(20.5),
      onCommandDouble,
      offCommandDouble
    );

    // act
    heatingControl.onInterval();

    // assert
    expect(onCommandSpy).to.not.have.been.called();
    expect(offCommandSpy).to.have.been.called();
  });

  it("should execute ON command on initial interval when current temperature below switching differential low point", function() {
    // arrange
    var heatingControl = new HeatingControl(
      programmeDoubleWithTargetTemperature(20.0),
      temperatureProviderDoubleWithCurrentTemperature(19.49),
      onCommandDouble,
      offCommandDouble);

    // act
    heatingControl.onInterval();

    // assert
    expect(onCommandSpy).to.have.been.called();
    expect(offCommandSpy).to.not.have.been.called();
  });

  it("should execute ON command on subsequent interval when current temperature rising and below switching differential low point", function() {
    // arrange
    var temperatureProviderDouble = temperatureProviderDoubleWithCurrentTemperature(19.00)
    var heatingControl = new HeatingControl(
      programmeDoubleWithTargetTemperature(20.0),
      temperatureProviderDouble,
      onCommandDouble,
      offCommandDouble);

    // act
    heatingControl.onInterval();
    temperatureProviderDouble.currentTemp = 19.49;
    heatingControl.onInterval();

    // assert
    expect(onCommandSpy).to.have.been.called.twice;
    expect(offCommandSpy).to.not.have.been.called();
  });

  it("should execute ON command on subsequent interval when current temperature rising and within switching differential", function() {
    // arrange
    var temperatureProviderDouble = temperatureProviderDoubleWithCurrentTemperature(19.00)
    var heatingControl = new HeatingControl(
      programmeDoubleWithTargetTemperature(20.0),
      temperatureProviderDouble,
      onCommandDouble,
      offCommandDouble);

      // act
      heatingControl.onInterval();
      temperatureProviderDouble.currentTemp = 20.0;
      heatingControl.onInterval();

      // assert
      expect(onCommandSpy).to.have.been.called.twice;
      expect(offCommandSpy).to.not.have.been.called();
  });

  it("should execute OFF command on subsequent interval when current temperature rising and above switching differential high point", function() {
    // arrange
    var temperatureProviderDouble = temperatureProviderDoubleWithCurrentTemperature(20.00)
    var heatingControl = new HeatingControl(
      programmeDoubleWithTargetTemperature(20.0),
      temperatureProviderDouble,
      onCommandDouble,
      offCommandDouble);

      // act
      heatingControl.onInterval();
      temperatureProviderDouble.currentTemp = 20.50;

      expect(onCommandSpy).to.have.been.called();

      heatingControl.onInterval();

      expect(offCommandSpy).to.have.been.called();
  });

  it("should execute ON command on subsequent interval when current temperature falling and below switching differential low point", function() {
    // arrange
    var temperatureProviderDouble = temperatureProviderDoubleWithCurrentTemperature(21.00)
    var heatingControl = new HeatingControl(
      programmeDoubleWithTargetTemperature(20.0),
      temperatureProviderDouble,
      onCommandDouble,
      offCommandDouble);

      // act
      heatingControl.onInterval();
      temperatureProviderDouble.currentTemp = 19.49;

      expect(offCommandSpy).to.have.been.called();

      heatingControl.onInterval();

      expect(onCommandSpy).to.have.been.called();
  });

  it("should execute OFF command on subsequent interval when current temperature falling into switching differential", function() {
    // arrange
    var temperatureProviderDouble = temperatureProviderDoubleWithCurrentTemperature(21.00)
    var heatingControl = new HeatingControl(
      programmeDoubleWithTargetTemperature(20.0),
      temperatureProviderDouble,
      onCommandDouble,
      offCommandDouble);

      // act
      heatingControl.onInterval();
      temperatureProviderDouble.currentTemp = 20.00;

      expect(offCommandSpy).to.have.been.called();

      heatingControl.onInterval();

      expect(offCommandSpy).to.have.been.called.twice();
  });

  it("should execute OFF command on subsequent interval when current temperature falling and above switching differential high point", function() {
    // arrange
    var temperatureProviderDouble = temperatureProviderDoubleWithCurrentTemperature(22.00)
    var heatingControl = new HeatingControl(
      programmeDoubleWithTargetTemperature(20.0),
      temperatureProviderDouble,
      onCommandDouble,
      offCommandDouble);

      // act
      heatingControl.onInterval();
      temperatureProviderDouble.currentTemp = 21.00;

      expect(offCommandSpy).to.have.been.called();

      heatingControl.onInterval();

      expect(offCommandSpy).to.have.been.called.twice();
  });

  it("should execute ON command on progamme changed when current temperature below switching differential low point", function() {
    // arrange
    var temperatureProviderDouble = temperatureProviderDoubleWithCurrentTemperature(20.00)
    var heatingControl = new HeatingControl(
      programmeDoubleWithTargetTemperature(19.0),
      temperatureProviderDouble,
      onCommandDouble,
      offCommandDouble);

      // act
      heatingControl.onInterval();

      expect(offCommandSpy).to.have.been.called();

      heatingControl.onProgrammeChanged(programmeDoubleWithTargetTemperature(21.00));

      expect(offCommandSpy).to.have.been.called.once();
      expect(onCommandSpy).to.have.been.called.once();
  });

  /*
                 | below h low | in h | above h high |
    init         |       X     |   X  |      X       |
    subs rising  |       X     |   X  |      X       |
    subs falling |       X     |   X  |      X       |
    prog changed |       X     |      |              |
  */

  // current temp in switching diff (rising)

  // current temp in switching diff (falling)

  // on programme changed
});
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
 * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
 * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
 * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
 * Code distributed by Google as part of the polymer project is also
 * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
 */
window.HTMLImports.addModule(function(scope) {

// imports
var path = scope.path;
var rootDocument = scope.rootDocument;
var flags = scope.flags;
var isIE = scope.isIE;
var IMPORT_LINK_TYPE = scope.IMPORT_LINK_TYPE;
var IMPORT_SELECTOR = 'link[rel=' + IMPORT_LINK_TYPE + ']';

// importParser
// highlander object to manage parsing of imports
// parses import related elements and ensures proper parse order
// parse order is enforced by crawling the tree and monitoring which elements
// have been parsed;
// elements can be dynamically added to imports. These are maintained in a
// separate queue and parsed after all other elements.
var importParser = {

  // parse selectors for main document elements
  documentSelectors: IMPORT_SELECTOR,

  // parse selectors for import document elements
  importsSelectors: [
    IMPORT_SELECTOR,
    'link[rel=stylesheet]',
    'style',
    'script:not([type])',
    'script[type="application/javascript"]',
    'script[type="text/javascript"]'
  ].join(','),

  map: {
    link: 'parseLink',
    script: 'parseScript',
    style: 'parseStyle'
  },

  dynamicElements: [],

  // try to parse the next import in the tree
  parseNext: function() {
    var next = this.nextToParse();
    if (next) {
      this.parse(next);
    }
  },

  parse: function(elt) {
    if (this.isParsed(elt)) {
      flags.parse && console.log('[%s] is already parsed', elt.localName);
      return;
    }
    var fn = this[this.map[elt.localName]];
    if (fn) {
      this.markParsing(elt);
      fn.call(this, elt);
    }
  },

  // marks an element for dynamic parsing and attempts to parse the next element
  parseDynamic: function(elt, quiet) {
    this.dynamicElements.push(elt);
    if (!quiet) {
      this.parseNext();
    }
  },

  // only 1 element may be parsed at a time; parsing is async so each
  // parsing implementation must inform the system that parsing is complete
  // via markParsingComplete.
  // To prompt the system to parse the next element, parseNext should then be
  // called.
  // Note, parseNext used to be included at the end of markParsingComplete, but
  // we must not do this so that, for example, we can (1) mark parsing complete
  // then (2) fire an import load event, and then (3) parse the next resource.
  markParsing: function(elt) {
    flags.parse && console.log('parsing', elt);
    this.parsingElement = elt;
  },

  markParsingComplete: function(elt) {
    elt.__importParsed = true;
    this.markDynamicParsingComplete(elt);
    if (elt.__importElement) {
      elt.__importElement.__importParsed = true;
      this.markDynamicParsingComplete(elt.__importElement);
    }
    this.parsingElement = null;
    flags.parse && console.log('completed', elt);
  },

  markDynamicParsingComplete: function(elt) {
    var i = this.dynamicElements.indexOf(elt);
    if (i >= 0) {
      this.dynamicElements.splice(i, 1);
    }
  },

  parseImport: function(elt) {
    // TODO(sorvell): consider if there's a better way to do this;
    // expose an imports parsing hook; this is needed, for example, by the
    // CustomElements polyfill.
    if (window.HTMLImports.__importsParsingHook) {
      window.HTMLImports.__importsParsingHook(elt);
    }
    if (elt.import) {
      elt.import.__importParsed = true;
    }
    this.markParsingComplete(elt);
    // fire load event
    if (elt.__resource && !elt.__error) {
      elt.dispatchEvent(new CustomEvent('load', {bubbles: false}));
    } else {
      elt.dispatchEvent(new CustomEvent('error', {bubbles: false}));
    }
    // TODO(sorvell): workaround for Safari addEventListener not working
    // for elements not in the main document.
    if (elt.__pending) {
      var fn;
      while (elt.__pending.length) {
        fn = elt.__pending.shift();
        if (fn) {
          fn({target: elt});
        }
      }
    }
    this.parseNext();
  },

  parseLink: function(linkElt) {
    if (nodeIsImport(linkElt)) {
      this.parseImport(linkElt);
    } else {
      // make href absolute
      linkElt.href = linkElt.href;
      this.parseGeneric(linkElt);
    }
  },

  parseStyle: function(elt) {
    // TODO(sorvell): style element load event can just not fire so clone styles
    var src = elt;
    elt = cloneStyle(elt);
    src.__appliedElement = elt;
    elt.__importElement = src;
    this.parseGeneric(elt);
  },

  parseGeneric: function(elt) {
    this.trackElement(elt);
    this.addElementToDocument(elt);
  },

  rootImportForElement: function(elt) {
    var n = elt;
    while (n.ownerDocument.__importLink) {
      n = n.ownerDocument.__importLink;
    }
    return n;
  },

  addElementToDocument: function(elt) {
    var port = this.rootImportForElement(elt.__importElement || elt);
    port.parentNode.insertBefore(elt, port);
  },

  // tracks when a loadable element has loaded
  trackElement: function(elt, callback) {
    var self = this;
    var done = function(e) {
      if (callback) {
        callback(e);
      }
      self.markParsingComplete(elt);
      self.parseNext();
    };
    elt.addEventListener('load', done);
    elt.addEventListener('error', done);

    // NOTE: IE does not fire "load" event for styles that have already loaded
    // This is in violation of the spec, so we try our hardest to work around it
    if (isIE && elt.localName === 'style') {
      var fakeLoad = false;
      // If there's not @import in the textContent, assume it has loaded
      if (elt.textContent.indexOf('@import') == -1) {
        fakeLoad = true;
      // if we have a sheet, we have been parsed
      } else if (elt.sheet) {
        fakeLoad = true;
        var csr = elt.sheet.cssRules;
        var len = csr ? csr.length : 0;
        // search the rules for @import's
        for (var i = 0, r; (i < len) && (r = csr[i]); i++) {
          if (r.type === CSSRule.IMPORT_RULE) {
            // if every @import has resolved, fake the load
            fakeLoad = fakeLoad && Boolean(r.styleSheet);
          }
        }
      }
      // dispatch a fake load event and continue parsing
      if (fakeLoad) {
        // Fire async, to prevent reentrancy
        setTimeout(function() {
          elt.dispatchEvent(new CustomEvent('load', {bubbles: false}));
        });
      }
    }
  },

  // NOTE: execute scripts by injecting them and watching for the load/error
  // event. Inline scripts are handled via dataURL's because browsers tend to
  // provide correct parsing errors in this case. If this has any compatibility
  // issues, we can switch to injecting the inline script with textContent.
  parseScript: function(scriptElt) {
    var script = document.createElement('script');
    script.__importElement = scriptElt;
    script.src = scriptElt.src ? scriptElt.src :
        generateScriptDataUrl(scriptElt);
    // keep track of executing script to help polyfill `document.currentScript`
    scope.currentScript = scriptElt;
    this.trackElement(script, function(e) {
      script.parentNode.removeChild(script);
      scope.currentScript = null;
    });
    this.addElementToDocument(script);
  },

  // determine the next element in the tree which should be parsed
  // crawl the document tree to find the next unparsed element
  // then process any dynamically added elements (these should process in 'add'
  // order.
  nextToParse: function() {
    this._mayParse = [];
    return !this.parsingElement && (this.nextToParseInDoc(rootDocument) ||
        this.nextToParseDynamic());
  },

  nextToParseInDoc: function(doc, link) {
    // use `marParse` list to avoid looping into the same document again
    // since it could cause an iloop.
    if (doc && this._mayParse.indexOf(doc) < 0) {
      this._mayParse.push(doc);
      var nodes = doc.querySelectorAll(this.parseSelectorsForNode(doc));
      for (var i=0, l=nodes.length, p=0, n; (i<l) && (n=nodes[i]); i++) {
        if (!this.isParsed(n)) {
          if (this.hasResource(n)) {
            return nodeIsImport(n) ? this.nextToParseInDoc(n.import, n) : n;
          } else {
            return;
          }
        }
      }
    }
    // all nodes have been parsed, ready to parse import, if any
    return link;
  },

  // note dynamically added elements are stored in a separate queue
  nextToParseDynamic: function() {
    return this.dynamicElements[0];
  },

  // return the set of parse selectors relevant for this node.
  parseSelectorsForNode: function(node) {
    var doc = node.ownerDocument || node;
    return doc === rootDocument ? this.documentSelectors :
        this.importsSelectors;
  },

  isParsed: function(node) {
    return node.__importParsed;
  },

  needsDynamicParsing: function(elt) {
    return (this.dynamicElements.indexOf(elt) >= 0);
  },

  hasResource: function(node) {
    if (nodeIsImport(node) && (node.import === undefined)) {
      return false;
    }
    return true;
  }

};

function nodeIsImport(elt) {
  return (elt.localName === 'link') && (elt.rel === IMPORT_LINK_TYPE);
}

function generateScriptDataUrl(script) {
  var scriptContent = generateScriptContent(script);
  return 'data:text/javascript;charset=utf-8,' + encodeURIComponent(scriptContent);
}

function generateScriptContent(script) {
  return script.textContent + generateSourceMapHint(script);
}

// calculate source map hint
function generateSourceMapHint(script) {
  var owner = script.ownerDocument;
  owner.__importedScripts = owner.__importedScripts || 0;
  var moniker = script.ownerDocument.baseURI;
  var num = owner.__importedScripts ? '-' + owner.__importedScripts : '';
  owner.__importedScripts++;
  return '\n//# sourceURL=' + moniker + num + '.js\n';
}

// style/stylesheet handling

// clone style with proper path resolution for main document
// NOTE: styles are the only elements that require direct path fixup.
function cloneStyle(style) {
  var clone = style.ownerDocument.createElement('style');
  clone.textContent = style.textContent;
  path.resolveUrlsInStyle(clone);
  return clone;
}

// exports
scope.parser = importParser;
scope.IMPORT_SELECTOR = IMPORT_SELECTOR;

});
<commit_msg>Fix for issue #342. Before removing the script from its parent, check to see its parent exists. It's still unclear why this condition can arise. Nevertheless, if the condition does arise, and the script has no parent, then presumably it's no longer important to remove the script from its parent.<commit_after>/**
 * @license
 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
 * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
 * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
 * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
 * Code distributed by Google as part of the polymer project is also
 * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
 */
window.HTMLImports.addModule(function(scope) {

// imports
var path = scope.path;
var rootDocument = scope.rootDocument;
var flags = scope.flags;
var isIE = scope.isIE;
var IMPORT_LINK_TYPE = scope.IMPORT_LINK_TYPE;
var IMPORT_SELECTOR = 'link[rel=' + IMPORT_LINK_TYPE + ']';

// importParser
// highlander object to manage parsing of imports
// parses import related elements and ensures proper parse order
// parse order is enforced by crawling the tree and monitoring which elements
// have been parsed;
// elements can be dynamically added to imports. These are maintained in a
// separate queue and parsed after all other elements.
var importParser = {

  // parse selectors for main document elements
  documentSelectors: IMPORT_SELECTOR,

  // parse selectors for import document elements
  importsSelectors: [
    IMPORT_SELECTOR,
    'link[rel=stylesheet]',
    'style',
    'script:not([type])',
    'script[type="application/javascript"]',
    'script[type="text/javascript"]'
  ].join(','),

  map: {
    link: 'parseLink',
    script: 'parseScript',
    style: 'parseStyle'
  },

  dynamicElements: [],

  // try to parse the next import in the tree
  parseNext: function() {
    var next = this.nextToParse();
    if (next) {
      this.parse(next);
    }
  },

  parse: function(elt) {
    if (this.isParsed(elt)) {
      flags.parse && console.log('[%s] is already parsed', elt.localName);
      return;
    }
    var fn = this[this.map[elt.localName]];
    if (fn) {
      this.markParsing(elt);
      fn.call(this, elt);
    }
  },

  // marks an element for dynamic parsing and attempts to parse the next element
  parseDynamic: function(elt, quiet) {
    this.dynamicElements.push(elt);
    if (!quiet) {
      this.parseNext();
    }
  },

  // only 1 element may be parsed at a time; parsing is async so each
  // parsing implementation must inform the system that parsing is complete
  // via markParsingComplete.
  // To prompt the system to parse the next element, parseNext should then be
  // called.
  // Note, parseNext used to be included at the end of markParsingComplete, but
  // we must not do this so that, for example, we can (1) mark parsing complete
  // then (2) fire an import load event, and then (3) parse the next resource.
  markParsing: function(elt) {
    flags.parse && console.log('parsing', elt);
    this.parsingElement = elt;
  },

  markParsingComplete: function(elt) {
    elt.__importParsed = true;
    this.markDynamicParsingComplete(elt);
    if (elt.__importElement) {
      elt.__importElement.__importParsed = true;
      this.markDynamicParsingComplete(elt.__importElement);
    }
    this.parsingElement = null;
    flags.parse && console.log('completed', elt);
  },

  markDynamicParsingComplete: function(elt) {
    var i = this.dynamicElements.indexOf(elt);
    if (i >= 0) {
      this.dynamicElements.splice(i, 1);
    }
  },

  parseImport: function(elt) {
    // TODO(sorvell): consider if there's a better way to do this;
    // expose an imports parsing hook; this is needed, for example, by the
    // CustomElements polyfill.
    if (window.HTMLImports.__importsParsingHook) {
      window.HTMLImports.__importsParsingHook(elt);
    }
    if (elt.import) {
      elt.import.__importParsed = true;
    }
    this.markParsingComplete(elt);
    // fire load event
    if (elt.__resource && !elt.__error) {
      elt.dispatchEvent(new CustomEvent('load', {bubbles: false}));
    } else {
      elt.dispatchEvent(new CustomEvent('error', {bubbles: false}));
    }
    // TODO(sorvell): workaround for Safari addEventListener not working
    // for elements not in the main document.
    if (elt.__pending) {
      var fn;
      while (elt.__pending.length) {
        fn = elt.__pending.shift();
        if (fn) {
          fn({target: elt});
        }
      }
    }
    this.parseNext();
  },

  parseLink: function(linkElt) {
    if (nodeIsImport(linkElt)) {
      this.parseImport(linkElt);
    } else {
      // make href absolute
      linkElt.href = linkElt.href;
      this.parseGeneric(linkElt);
    }
  },

  parseStyle: function(elt) {
    // TODO(sorvell): style element load event can just not fire so clone styles
    var src = elt;
    elt = cloneStyle(elt);
    src.__appliedElement = elt;
    elt.__importElement = src;
    this.parseGeneric(elt);
  },

  parseGeneric: function(elt) {
    this.trackElement(elt);
    this.addElementToDocument(elt);
  },

  rootImportForElement: function(elt) {
    var n = elt;
    while (n.ownerDocument.__importLink) {
      n = n.ownerDocument.__importLink;
    }
    return n;
  },

  addElementToDocument: function(elt) {
    var port = this.rootImportForElement(elt.__importElement || elt);
    port.parentNode.insertBefore(elt, port);
  },

  // tracks when a loadable element has loaded
  trackElement: function(elt, callback) {
    var self = this;
    var done = function(e) {
      if (callback) {
        callback(e);
      }
      self.markParsingComplete(elt);
      self.parseNext();
    };
    elt.addEventListener('load', done);
    elt.addEventListener('error', done);

    // NOTE: IE does not fire "load" event for styles that have already loaded
    // This is in violation of the spec, so we try our hardest to work around it
    if (isIE && elt.localName === 'style') {
      var fakeLoad = false;
      // If there's not @import in the textContent, assume it has loaded
      if (elt.textContent.indexOf('@import') == -1) {
        fakeLoad = true;
      // if we have a sheet, we have been parsed
      } else if (elt.sheet) {
        fakeLoad = true;
        var csr = elt.sheet.cssRules;
        var len = csr ? csr.length : 0;
        // search the rules for @import's
        for (var i = 0, r; (i < len) && (r = csr[i]); i++) {
          if (r.type === CSSRule.IMPORT_RULE) {
            // if every @import has resolved, fake the load
            fakeLoad = fakeLoad && Boolean(r.styleSheet);
          }
        }
      }
      // dispatch a fake load event and continue parsing
      if (fakeLoad) {
        // Fire async, to prevent reentrancy
        setTimeout(function() {
          elt.dispatchEvent(new CustomEvent('load', {bubbles: false}));
        });
      }
    }
  },

  // NOTE: execute scripts by injecting them and watching for the load/error
  // event. Inline scripts are handled via dataURL's because browsers tend to
  // provide correct parsing errors in this case. If this has any compatibility
  // issues, we can switch to injecting the inline script with textContent.
  parseScript: function(scriptElt) {
    var script = document.createElement('script');
    script.__importElement = scriptElt;
    script.src = scriptElt.src ? scriptElt.src :
        generateScriptDataUrl(scriptElt);
    // keep track of executing script to help polyfill `document.currentScript`
    scope.currentScript = scriptElt;
    this.trackElement(script, function(e) {
      if (script.parentNode) {
        script.parentNode.removeChild(script);
      }
      scope.currentScript = null;
    });
    this.addElementToDocument(script);
  },

  // determine the next element in the tree which should be parsed
  // crawl the document tree to find the next unparsed element
  // then process any dynamically added elements (these should process in 'add'
  // order.
  nextToParse: function() {
    this._mayParse = [];
    return !this.parsingElement && (this.nextToParseInDoc(rootDocument) ||
        this.nextToParseDynamic());
  },

  nextToParseInDoc: function(doc, link) {
    // use `marParse` list to avoid looping into the same document again
    // since it could cause an iloop.
    if (doc && this._mayParse.indexOf(doc) < 0) {
      this._mayParse.push(doc);
      var nodes = doc.querySelectorAll(this.parseSelectorsForNode(doc));
      for (var i=0, l=nodes.length, p=0, n; (i<l) && (n=nodes[i]); i++) {
        if (!this.isParsed(n)) {
          if (this.hasResource(n)) {
            return nodeIsImport(n) ? this.nextToParseInDoc(n.import, n) : n;
          } else {
            return;
          }
        }
      }
    }
    // all nodes have been parsed, ready to parse import, if any
    return link;
  },

  // note dynamically added elements are stored in a separate queue
  nextToParseDynamic: function() {
    return this.dynamicElements[0];
  },

  // return the set of parse selectors relevant for this node.
  parseSelectorsForNode: function(node) {
    var doc = node.ownerDocument || node;
    return doc === rootDocument ? this.documentSelectors :
        this.importsSelectors;
  },

  isParsed: function(node) {
    return node.__importParsed;
  },

  needsDynamicParsing: function(elt) {
    return (this.dynamicElements.indexOf(elt) >= 0);
  },

  hasResource: function(node) {
    if (nodeIsImport(node) && (node.import === undefined)) {
      return false;
    }
    return true;
  }

};

function nodeIsImport(elt) {
  return (elt.localName === 'link') && (elt.rel === IMPORT_LINK_TYPE);
}

function generateScriptDataUrl(script) {
  var scriptContent = generateScriptContent(script);
  return 'data:text/javascript;charset=utf-8,' + encodeURIComponent(scriptContent);
}

function generateScriptContent(script) {
  return script.textContent + generateSourceMapHint(script);
}

// calculate source map hint
function generateSourceMapHint(script) {
  var owner = script.ownerDocument;
  owner.__importedScripts = owner.__importedScripts || 0;
  var moniker = script.ownerDocument.baseURI;
  var num = owner.__importedScripts ? '-' + owner.__importedScripts : '';
  owner.__importedScripts++;
  return '\n//# sourceURL=' + moniker + num + '.js\n';
}

// style/stylesheet handling

// clone style with proper path resolution for main document
// NOTE: styles are the only elements that require direct path fixup.
function cloneStyle(style) {
  var clone = style.ownerDocument.createElement('style');
  clone.textContent = style.textContent;
  path.resolveUrlsInStyle(clone);
  return clone;
}

// exports
scope.parser = importParser;
scope.IMPORT_SELECTOR = IMPORT_SELECTOR;

});
<|endoftext|>


<commit_before>(function () {
  var ns = $.namespace('pskl.worker.framecolors');

  if (Constants.TRANSPARENT_COLOR !== 'rgba(0, 0, 0, 0)') {
    throw 'Constants.TRANSPARENT_COLOR, please update FrameColorsWorker';
  }

  ns.FrameColorsWorker = function () {

    var TRANSPARENT_COLOR = 'rgba(0, 0, 0, 0)';

    var componentToHex = function (c) {
      var hex = c.toString(16);
      return hex.length == 1 ? '0' + hex : hex;
    };

    var rgbToHex = function (r, g, b) {
      return '#' + componentToHex(r) + componentToHex(g) + componentToHex(b);
    };

    var toHexString_ = function(color) {
      if (color === TRANSPARENT_COLOR) {
        return color;
      } else {
        color = color.replace(/\s/g, '');
        var hexRe = (/^#([a-f0-9]{3}){1,2}$/i);
        var rgbRe = (/^rgb\((\d{1,3}),(\d{1,3}),(\d{1,3})\)$/i);
        if (hexRe.test(color)) {
          return color.toLowerCase();
        } else if (rgbRe.test(color)) {
          var exec = rgbRe.exec(color);
          return rgbToHex(exec[1] * 1, exec[2] * 1, exec[3] * 1);
        }
      }
    };

    var getFrameColors = function (frame) {
      var frameColors = {};
      var transparentColorInt = 0; // TODO: Fix magic number
      for (var i = 0; i < frame.length; i++) {
        var color = frame[i];
        if (color !== transparentColorInt) {
          var hexColor = rgbToHex(color & 0xff, color >> 16 & 0xff, color >> 8 & 0xff);
          frameColors[hexColor] = true;
        }
      }
      return frameColors;
    };

    this.onmessage = function(event) {
      try {
        var frame = event.data;
        var colors = getFrameColors(frame);
        this.postMessage({
          type : 'SUCCESS',
          colors : colors
        });
      } catch (e) {
        this.postMessage({
          type : 'ERROR',
          message : e.message
        });
      }
    };
  };
})();
<commit_msg>Improve frame colors worker perfomance by caching<commit_after>(function () {
  var ns = $.namespace('pskl.worker.framecolors');

  if (Constants.TRANSPARENT_COLOR !== 'rgba(0, 0, 0, 0)') {
    throw 'Constants.TRANSPARENT_COLOR, please update FrameColorsWorker';
  }

  ns.FrameColorsWorker = function () {

    var TRANSPARENT_COLOR = 'rgba(0, 0, 0, 0)';

    var componentToHex = function (c) {
      var hex = c.toString(16);
      return hex.length == 1 ? '0' + hex : hex;
    };

    var rgbToHex = function (r, g, b) {
      return '#' + componentToHex(r) + componentToHex(g) + componentToHex(b);
    };

    var toHexString_ = function(color) {
      if (color === TRANSPARENT_COLOR) {
        return color;
      } else {
        color = color.replace(/\s/g, '');
        var hexRe = (/^#([a-f0-9]{3}){1,2}$/i);
        var rgbRe = (/^rgb\((\d{1,3}),(\d{1,3}),(\d{1,3})\)$/i);
        if (hexRe.test(color)) {
          return color.toLowerCase();
        } else if (rgbRe.test(color)) {
          var exec = rgbRe.exec(color);
          return rgbToHex(exec[1] * 1, exec[2] * 1, exec[3] * 1);
        }
      }
    };

    var intHexCache = {};
    var intToHex = function(int) {
      if (intHexCache[int]) {
        return intHexCache[int];
      }

      var hex = rgbToHex(int & 0xff, int >> 8 & 0xff, int >> 16 & 0xff);
      intHexCache[int] = hex;
      return hex;
    };

    var getFrameColors = function (frame) {
      var frameColors = {};
      var transparentColorInt = 0; // TODO: Fix magic number
      for (var i = 0; i < frame.length; i++) {
        var color = frame[i];
        if (color !== transparentColorInt) {
          var hexColor = intToHex(color);
          frameColors[hexColor] = true;
        }
      }
      return frameColors;
    };

    this.onmessage = function(event) {
      try {
        var frame = event.data;
        var colors = getFrameColors(frame);
        this.postMessage({
          type : 'SUCCESS',
          colors : colors
        });
      } catch (e) {
        this.postMessage({
          type : 'ERROR',
          message : e.message
        });
      }
    };
  };
})();
<|endoftext|>


<commit_before>/**
 * Clean-css - https://github.com/jakubpawlowicz/clean-css
 * Released under the terms of MIT license
 *
 * Copyright (C) 2014 JakubPawlowicz.com
 */

var ColorShortener = require('./colors/shortener');
var ColorHSLToHex = require('./colors/hsl-to-hex');
var ColorRGBToHex = require('./colors/rgb-to-hex');
var ColorLongToShortHex = require('./colors/long-to-short-hex');

var ImportInliner = require('./imports/inliner');
var UrlRebase = require('./images/url-rebase');

var CommentsProcessor = require('./text/comments');
var ExpressionsProcessor = require('./text/expressions');
var FreeTextProcessor = require('./text/free');
var UrlsProcessor = require('./text/urls');
var NameQuotesProcessor = require('./text/name-quotes');
var Splitter = require('./utils/splitter');

var SelectorsOptimizer = require('./selectors/optimizer');

var CleanCSS = module.exports = function CleanCSS(options) {
  options = options || {};

  options.keepBreaks = options.keepBreaks || false;

  //active by default
  if (undefined === options.processImport)
    options.processImport = true;

  this.options = options;
  this.stats = {};
  this.context = {
    errors: [],
    warnings: [],
    debug: options.debug
  };
  this.errors = this.context.errors;
  this.warnings = this.context.warnings;
};

CleanCSS.prototype.minify = function(data, callback) {
  var options = this.options;

  if (Buffer.isBuffer(data))
    data = data.toString();

  if (options.processImport || data.indexOf('@shallow') > 0) {
    // inline all imports
    var self = this;
    var runner = callback ?
      process.nextTick :
      function(callback) { return callback(); };

    return runner(function() {
      return new ImportInliner(self.context, options.inliner).process(data, {
        localOnly: !callback,
        root: options.root || process.cwd(),
        relativeTo: options.relativeTo,
        whenDone: function(data) {
          return minify.call(self, data, callback);
        }
      });
    });
  } else {
    return minify.call(this, data, callback);
  }
};

var minify = function(data, callback) {
  var startedAt;
  var stats = this.stats;
  var options = this.options;
  var context = this.context;

  var commentsProcessor = new CommentsProcessor('keepSpecialComments' in options ? options.keepSpecialComments : '*', options.keepBreaks);
  var expressionsProcessor = new ExpressionsProcessor();
  var freeTextProcessor = new FreeTextProcessor();
  var urlsProcessor = new UrlsProcessor();
  var nameQuotesProcessor = new NameQuotesProcessor();

  if (options.debug) {
    this.startedAt = process.hrtime();
    this.stats.originalSize = data.length;
  }

  var replace = function() {
    if (typeof arguments[0] == 'function')
      arguments[0]();
    else
      data = data.replace.apply(data, arguments);
  };

  // replace function
  if (options.benchmark) {
    var originalReplace = replace;
    replace = function(pattern, replacement) {
      var name = typeof pattern == 'function' ?
        /function (\w+)\(/.exec(pattern.toString())[1] :
        pattern;

      var start = process.hrtime();
      originalReplace(pattern, replacement);

      var itTook = process.hrtime(start);
      console.log('%d ms: ' + name, 1000 * itTook[0] + itTook[1] / 1000000);
    };
  }

  if (options.debug) {
    startedAt = process.hrtime();
    stats.originalSize = data.length;
  }

  replace(function escapeComments() {
    data = commentsProcessor.escape(data);
  });

  // replace all escaped line breaks
  replace(/\\(\r\n|\n)/gm, '');

  // strip parentheses in urls if possible (no spaces inside)
  replace(/url\((['"])([^\)]+)['"]\)/g, function(match, quote, url) {
    var unsafeDataURI = url.indexOf('data:') === 0 && url.match(/data:\w+\/[^;]+;base64,/) === null;
    if (url.match(/[ \t]/g) !== null || unsafeDataURI)
      return 'url(' + quote + url + quote + ')';
    else
      return 'url(' + url + ')';
  });

  // strip parentheses in animation & font names
  replace(function removeQuotes() {
    data = nameQuotesProcessor.process(data);
  });

  // strip parentheses in @keyframes
  replace(/@(\-moz\-|\-o\-|\-webkit\-)?keyframes ([^{]+)/g, function(match, prefix, name) {
    prefix = prefix || '';
    return '@' + prefix + 'keyframes ' + (name.indexOf(' ') > -1 ? name : name.replace(/['"]/g, ''));
  });

  // IE shorter filters, but only if single (IE 7 issue)
  replace(/progid:DXImageTransform\.Microsoft\.(Alpha|Chroma)(\([^\)]+\))([;}'"])/g, function(match, filter, args, suffix) {
    return filter.toLowerCase() + args + suffix;
  });

  replace(function escapeExpressions() {
    data = expressionsProcessor.escape(data);
  });

  // strip parentheses in attribute values
  replace(/\[([^\]]+)\]/g, function(match, content) {
    var eqIndex = content.indexOf('=');
    var singleQuoteIndex = content.indexOf('\'');
    var doubleQuoteIndex = content.indexOf('"');
    if (eqIndex < 0 && singleQuoteIndex < 0 && doubleQuoteIndex < 0)
      return match;
    if (singleQuoteIndex === 0 || doubleQuoteIndex === 0)
      return match;

    var key = content.substring(0, eqIndex);
    var value = content.substring(eqIndex + 1, content.length);

    if (/^['"](?:[a-zA-Z][a-zA-Z\d\-_]+)['"]$/.test(value))
      return '[' + key + '=' + value.substring(1, value.length - 1) + ']';
    else
      return match;
  });

  replace(function escapeFreeText() {
    data = freeTextProcessor.escape(data);
  });

  replace(function escapeUrls() {
    data = urlsProcessor.escape(data);
  });

  // remove invalid special declarations
  replace(/@charset [^;]+;/ig, function (match) {
    return match.indexOf('@charset') > -1 ? match : '';
  });

  // whitespace inside attribute selectors brackets
  replace(/\[([^\]]+)\]/g, function(match) {
    return match.replace(/\s/g, '');
  });

  // line breaks
  replace(/[\r]?\n/g, ' ');

  // multiple whitespace
  replace(/[\t ]+/g, ' ');

  // multiple semicolons (with optional whitespace)
  replace(/;[ ]?;+/g, ';');

  // multiple line breaks to one
  replace(/ (?:\r\n|\n)/g, lineBreak);
  replace(/(?:\r\n|\n)+/g, lineBreak);

  // remove spaces around selectors
  replace(/ ([+~>]) /g, '$1');

  // remove extra spaces inside content
  replace(/([!\(\{\}:;=,\n]) /g, '$1');
  replace(/ ([!\)\{\};=,\n])/g, '$1');
  replace(/(?:\r\n|\n)\}/g, '}');
  replace(/([\{;,])(?:\r\n|\n)/g, '$1');
  replace(/ :([^\{\};]+)([;}])/g, ':$1$2');

  // restore spaces inside IE filters (IE 7 issue)
  replace(/progid:[^(]+\(([^\)]+)/g, function(match) {
    return match.replace(/,/g, ', ');
  });

  // trailing semicolons
  replace(/;\}/g, '}');

  replace(function hsl2Hex() {
    data = new ColorHSLToHex(data).process();
  });

  replace(function rgb2Hex() {
    data = new ColorRGBToHex(data).process();
  });

  replace(function longToShortHex() {
    data = new ColorLongToShortHex(data).process();
  });

  replace(function shortenColors() {
    data = new ColorShortener(data).process();
  });

  // replace font weight with numerical value
  replace(/(font\-weight|font):(normal|bold)([ ;\}!])(\w*)/g, function(match, property, weight, suffix, next) {
    if (suffix == ' ' && (next.indexOf('/') > -1 || next == 'normal' || /[1-9]00/.test(next)))
      return match;

    if (weight == 'normal')
      return property + ':400' + suffix + next;
    else if (weight == 'bold')
      return property + ':700' + suffix + next;
    else
      return match;
  });

  // minus zero to zero
  // repeated twice on purpose as if not it doesn't process rgba(-0,-0,-0,-0) correctly
  var zerosRegexp = /(\s|:|,|\()\-0([^\.])/g;
  replace(zerosRegexp, '$10$2');
  replace(zerosRegexp, '$10$2');

  // zero(s) + value to value
  replace(/(\s|:|,)0+([1-9])/g, '$1$2');

  // round pixels to 2nd decimal place
  var precision = 'roundingPrecision' in options ? options.roundingPrecision : 2;
  var decimalMultiplier = Math.pow(10, precision);
  replace(new RegExp('\\.(\\d{' + (precision + 1) + ',})px', 'g'), function(match, decimalPlaces) {
    return precision === 0 ?
      'px' :
      '.' + Math.round(parseFloat('.' + decimalPlaces) * decimalMultiplier) / decimalMultiplier + 'px';
  });

  // .0 to 0
  // repeated twice on purpose as if not it doesn't process {padding: .0 .0 .0 .0} correctly
  var leadingDecimalRegexp = /(\D)\.0+(\D)/g;
  replace(leadingDecimalRegexp, '$10$2');
  replace(leadingDecimalRegexp, '$10$2');

  // fraction zeros removal
  replace(/\.([1-9]*)0+(\D)/g, function(match, nonZeroPart, suffix) {
    return (nonZeroPart.length > 0 ? '.' : '') + nonZeroPart + suffix;
  });

  // zero + unit to zero
  var units = ['px', 'em', 'ex', 'cm', 'mm', 'in', 'pt', 'pc', '%'];
  if (['ie7', 'ie8'].indexOf(options.compatibility) == -1)
    units.push('rem');

  replace(new RegExp('(\\s|:|,)\\-?0(?:' + units.join('|') + ')', 'g'), '$1' + '0');
  replace(new RegExp('(\\s|:|,)\\-?(\\d+)\\.(\\D)', 'g'), '$1$2$3');
  replace(new RegExp('rect\\(0(?:' + units.join('|') + ')', 'g'), 'rect(0');

  // restore % in rgb/rgba and hsl/hsla
  replace(/(rgb|rgba|hsl|hsla)\(([^\)]+)\)/g, function(match, colorFunction, colorDef) {
    var tokens = colorDef.split(',');
    var applies = colorFunction == 'hsl' || colorFunction == 'hsla' || tokens[0].indexOf('%') > -1;
    if (!applies)
      return match;

    if (tokens[1].indexOf('%') == -1)
      tokens[1] += '%';
    if (tokens[2].indexOf('%') == -1)
      tokens[2] += '%';
    return colorFunction + '(' + tokens.join(',') + ')';
  });

  // transparent rgba/hsla to 'transparent' unless in compatibility mode
  if (!options.compatibility) {
    replace(/:([^;]*)(?:rgba|hsla)\(0,0%?,0%?,0\)/g, function (match, prefix) {
      if (new Splitter(',').split(match).pop().indexOf('gradient(') > -1)
        return match;

      return ':' + prefix + 'transparent';
    });
  }

  // none to 0
  replace(/outline:none/g, 'outline:0');

  // background:none to background:0 0
  replace(/background:(?:none|transparent)([;}])/g, 'background:0 0$1');

  // multiple zeros into one
  replace(/box-shadow:0 0 0 0([^\.])/g, 'box-shadow:0 0$1');
  replace(/:0 0 0 0([^\.])/g, ':0$1');
  replace(/([: ,=\-])0\.(\d)/g, '$1.$2');

  // restore rect(...) zeros syntax for 4 zeros
  replace(/rect\(\s?0(\s|,)0[ ,]0[ ,]0\s?\)/g, 'rect(0$10$10$10)');

  // remove universal selector when not needed (*#id, *.class etc)
  // pending a better fix
  if (options.compatibility != 'ie7') {
    replace(/([^,]?)(\*[^ \+\{]*\+html[^\{]*)(\{[^\}]*\})/g, function (match, prefix, selector, body) {
      var notHackedSelectors = new Splitter(',').split(selector).filter(function (m) {
        return !/^\*[^ \+\{]*\+html/.test(m);
      });

      return notHackedSelectors.length > 0 ?
        prefix + notHackedSelectors.join(',') + body :
        prefix;
    });
    replace(/\*([\.#:\[])/g, '$1');
  }

  // Restore spaces inside calc back
  replace(/calc\([^\}]+\}/g, function(match) {
    return match.replace(/\+/g, ' + ');
  });

  // get rid of IE hacks if not in compatibility mode
  if (!options.compatibility)
    replace(/([;\{])[\*_][\w\-]+:[^;\}]+/g, '$1');

  if (options.noAdvanced) {
    if (options.keepBreaks)
      replace(/\}/g, '}' + lineBreak);
  } else {
    replace(function optimizeSelectors() {
      data = new SelectorsOptimizer(data, context, {
        keepBreaks: options.keepBreaks,
        lineBreak: lineBreak,
        compatibility: options.compatibility,
        aggressiveMerging: !options.noAggressiveMerging
      }).process();
    });
  }

  // replace ' / ' in border-*-radius with '/'
  replace(/(border-\w+-\w+-radius:\S+)\s+\/\s+/g, '$1/');

  // replace same H/V values in border-radius
  replace(/(border-\w+-\w+-radius):([^;\}]+)/g, function (match, property, value) {
    var parts = value.split('/');

    if (parts.length > 1 && parts[0] == parts[1])
      return property + ':' + parts[0];
    else
      return match;
  });

  replace(function restoreUrls() {
    data = urlsProcessor.restore(data);
  });
  replace(function rebaseUrls() {
    data = options.noRebase ? data : new UrlRebase(options, context).process(data);
  });
  replace(function restoreFreeText() {
    data = freeTextProcessor.restore(data);
  });
  replace(function restoreComments() {
    data = commentsProcessor.restore(data);
  });
  replace(function restoreExpressions() {
    data = expressionsProcessor.restore(data);
  });

  // move first charset to the beginning
  replace(function moveCharset() {
    // get first charset in stylesheet
    var match = data.match(/@charset [^;]+;/);
    var firstCharset = match ? match[0] : null;
    if (!firstCharset)
      return;

    // reattach first charset and remove all subsequent
    data = firstCharset +
      (options.keepBreaks ? lineBreak : '') +
      data.replace(new RegExp('@charset [^;]+;(' + lineBreak + ')?', 'g'), '').trim();
  });

  if (options.noAdvanced) {
    replace(function removeEmptySelectors() {
      data = new EmptyRemoval(data).process();
    });
  }

  // trim spaces at beginning and end
  data = data.trim();

  if (options.debug) {
    var elapsed = process.hrtime(startedAt);
    stats.timeSpent = ~~(elapsed[0] * 1e3 + elapsed[1] / 1e6);
    stats.efficiency = 1 - data.length / stats.originalSize;
    stats.minifiedSize = data.length;
  }

  return callback ?
    callback.call(this, this.context.errors.length > 0 ? this.context.errors : null, data) :
    data;
};
<commit_msg>Strips main clean.js transforms to bare minimum.<commit_after>/**
 * Clean-css - https://github.com/jakubpawlowicz/clean-css
 * Released under the terms of MIT license
 *
 * Copyright (C) 2014 JakubPawlowicz.com
 */

var ImportInliner = require('./imports/inliner');
var UrlRebase = require('./images/url-rebase');

var CommentsProcessor = require('./text/comments-processor');
var ExpressionsProcessor = require('./text/expressions-processor');
var FreeTextProcessor = require('./text/free-text-processor');
var UrlsProcessor = require('./text/urls-processor');

var SelectorsOptimizer = require('./selectors/optimizer');

var CleanCSS = module.exports = function CleanCSS(options) {
  options = options || {};

  options.keepBreaks = options.keepBreaks || false;

  //active by default
  if (undefined === options.processImport)
    options.processImport = true;

  this.options = options;
  this.stats = {};
  this.context = {
    errors: [],
    warnings: [],
    debug: options.debug
  };
  this.errors = this.context.errors;
  this.warnings = this.context.warnings;
};

CleanCSS.prototype.minify = function(data, callback) {
  var options = this.options;

  if (Buffer.isBuffer(data))
    data = data.toString();

  if (options.processImport || data.indexOf('@shallow') > 0) {
    // inline all imports
    var self = this;
    var runner = callback ?
      process.nextTick :
      function(callback) { return callback(); };

    return runner(function() {
      return new ImportInliner(self.context, options.inliner).process(data, {
        localOnly: !callback,
        root: options.root || process.cwd(),
        relativeTo: options.relativeTo,
        whenDone: function(data) {
          return minify.call(self, data, callback);
        }
      });
    });
  } else {
    return minify.call(this, data, callback);
  }
};

function minify(data, callback) {
  var startedAt;
  var stats = this.stats;
  var options = this.options;
  var context = this.context;

  var commentsProcessor = new CommentsProcessor('keepSpecialComments' in options ? options.keepSpecialComments : '*', options.keepBreaks);
  var expressionsProcessor = new ExpressionsProcessor();
  var freeTextProcessor = new FreeTextProcessor();
  var urlsProcessor = new UrlsProcessor();

  if (options.debug) {
    this.startedAt = process.hrtime();
    this.stats.originalSize = data.length;
  }

  var replace = function() {
    if (typeof arguments[0] == 'function')
      arguments[0]();
    else
      data = data.replace.apply(data, arguments);
  };

  // replace function
  if (options.benchmark) {
    var originalReplace = replace;
    replace = function(pattern, replacement) {
      var name = typeof pattern == 'function' ?
        /function (\w+)\(/.exec(pattern.toString())[1] :
        pattern;

      var start = process.hrtime();
      originalReplace(pattern, replacement);

      var itTook = process.hrtime(start);
      console.log('%d ms: ' + name, 1000 * itTook[0] + itTook[1] / 1000000);
    };
  }

  if (options.debug) {
    startedAt = process.hrtime();
    stats.originalSize = data.length;
  }

  replace(function escapeComments() {
    data = commentsProcessor.escape(data);
  });

  replace(function escapeExpressions() {
    data = expressionsProcessor.escape(data);
  });

  replace(function escapeFreeText() {
    data = freeTextProcessor.escape(data);
  });

  replace(function escapeUrls() {
    data = urlsProcessor.escape(data);
  });

  replace(function restoreUrls() {
    data = urlsProcessor.restore(data);
  });

  replace(function rebaseUrls() {
    data = options.noRebase ? data : new UrlRebase(options, context).process(data);
  });

  replace(function restoreFreeText() {
    data = freeTextProcessor.restore(data);
  });

  replace(function restoreComments() {
    data = commentsProcessor.restore(data);
  });

  replace(function restoreExpressions() {
    data = expressionsProcessor.restore(data);
  });

  if (options.debug) {
    var elapsed = process.hrtime(startedAt);
    stats.timeSpent = ~~(elapsed[0] * 1e3 + elapsed[1] / 1e6);
    stats.efficiency = 1 - data.length / stats.originalSize;
    stats.minifiedSize = data.length;
  }

  return callback ?
    callback.call(this, this.context.errors.length > 0 ? this.context.errors : null, data) :
    data;
};
<|endoftext|>