<commit_before>const path = require('path');
const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');

let og_image_url = process.env.RIOT_OG_IMAGE_URL;
if (!og_image_url) og_image_url = 'https://riot.im/app/themes/riot/img/logos/riot-im-logo-1.png';

module.exports = {
    entry: {
        // Load babel-polyfill first to avoid issues where some imports (namely react)
        // are potentially loaded before babel-polyfill.
        "bundle": ["babel-polyfill", "./src/vector/index.js"],
        "indexeddb-worker": "./src/vector/indexeddb-worker.js",

        "mobileguide": "./src/vector/mobile_guide/index.js",

        // CSS themes
        "theme-light":  "./node_modules/matrix-react-sdk/res/themes/light/css/light.scss",
        "theme-dark":   "./node_modules/matrix-react-sdk/res/themes/dark/css/dark.scss",
        "theme-dharma": "./node_modules/matrix-react-sdk/res/themes/dharma/css/dharma.scss",
        "theme-status": "./res/themes/status/css/status.scss",
    },
    module: {
        rules: [
            { enforce: 'pre', test: /\.js$/, use: "source-map-loader", exclude: /node_modules/, },
            { test: /\.js$/, use: "babel-loader", include: path.resolve(__dirname, 'src') },
            {
                test: /\.scss$/,
                // 1. postcss-loader turns the SCSS into normal CSS.
                // 2. css-loader turns the CSS into a JS module whose default
                //    export is a string containing the CSS, while also adding
                //    the images and fonts from CSS as Webpack inputs.
                // 3. ExtractTextPlugin turns that string into a separate asset.
                use: ExtractTextPlugin.extract({
                    use: [
                        "css-loader",
                        {
                            loader: 'postcss-loader',
                            options: {
                                config: {
                                    path: './postcss.config.js',
                                },
                            },
                        },
                    ],
                }),
            },
            {
                // this works similarly to the scss case, without postcss.
                test: /\.css$/,
                use: ExtractTextPlugin.extract({
                    use: "css-loader",
                }),
            },
            {
                test: /\.(gif|png|svg|ttf)$/,
                // Use a content-based hash in the name so that we can set a long cache
                // lifetime for assets while still delivering changes quickly.
                oneOf: [
                    {
                        // Images referenced in HTML files
                        issuer: /\.html$/,
                        loader: 'file-loader',
                        options: {
                            name: '[name].[hash:7].[ext]',
                            outputPath: getImgOutputPath,
                        },
                    },
                    {
                        // Images referenced in JS and CSS files
                        loader: 'file-loader',
                        options: {
                            name: '[name].[hash:7].[ext]',
                            outputPath: getImgOutputPath,
                            publicPath: function(url, resourcePath) {
                                // JS and CSS image usages end up the `bundles/[hash]` output
                                // directory, so we adjust the final path to navigate up twice.
                                return path.join("../..", getImgOutputPath(url, resourcePath));
                            },
                        },
                    },
                ],
            },
        ],
        noParse: [
            // for cross platform compatibility use [\\\/] as the path separator
            // this ensures that the regex trips on both Windows and *nix

            // don't parse the languages within highlight.js. They cause stack
            // overflows (https://github.com/webpack/webpack/issues/1721), and
            // there is no need for webpack to parse them - they can just be
            // included as-is.
            /highlight\.js[\\\/]lib[\\\/]languages/,

            // olm takes ages for webpack to process, and it's already heavily
            // optimised, so there is little to gain by us uglifying it.
            /olm[\\\/](javascript[\\\/])?olm\.js$/,
        ],
    },
    output: {
        path: path.join(__dirname, "webapp"),

        // The generated JS (and CSS, from the ExtractTextPlugin) are put in a
        // unique subdirectory for the build. There will only be one such
        // 'bundle' directory in the generated tarball; however, hosting
        // servers can collect 'bundles' from multiple versions into one
        // directory and symlink it into place - this allows users who loaded
        // an older version of the application to continue to access webpack
        // chunks even after the app is redeployed.
        filename: "bundles/[hash]/[name].js",
        chunkFilename: "bundles/[hash]/[name].js",
        devtoolModuleFilenameTemplate: function(info) {
            // Reading input source maps gives only relative paths here for
            // everything. Until I figure out how to fix this, this is a
            // workaround.
            // We use the relative resource path with any '../'s on the front
            // removed which gives a tree with matrix-react-sdk and vector
            // trees smashed together, but this fixes everything being under
            // various levels of '.' and '..'
            // Also, sometimes the resource path is absolute.
            return path.relative(process.cwd(), info.resourcePath).replace(/^[\/\.]*/, '');
        },
    },
    resolve: {
        alias: {
            // alias any requires to the react module to the one in our path, otherwise
            // we tend to get the react source included twice when using npm link.
            "react": path.resolve('./node_modules/react'),
            "react-dom": path.resolve('./node_modules/react-dom'),
            "react-addons-perf": path.resolve('./node_modules/react-addons-perf'),

            // same goes for js-sdk
            "matrix-js-sdk": path.resolve('./node_modules/matrix-js-sdk'),
        },
    },
    plugins: [
        new webpack.DefinePlugin({
            'process.env': {
                NODE_ENV: JSON.stringify(process.env.NODE_ENV),
            },
        }),

        new ExtractTextPlugin("bundles/[hash]/[name].css", {
            allChunks: true,
        }),

        new HtmlWebpackPlugin({
            template: './src/vector/index.html',

            // we inject the links ourselves via the template, because
            // HtmlWebpackPlugin wants to put the script tags either at the
            // bottom of <head> or the bottom of <body>, and I'm a bit scared
            // about moving them.
            inject: false,
            excludeChunks: ['mobileguide'],
            vars: {
                og_image_url: og_image_url,
            },
        }),
        new HtmlWebpackPlugin({
            template: './src/vector/mobile_guide/index.html',
            filename: 'mobile_guide/index.html',
            chunks: ['mobileguide'],
        }),
    ],
    devtool: 'source-map',

    // configuration for the webpack-dev-server
    devServer: {
        // serve unwebpacked assets from webapp.
        contentBase: './webapp',

        stats: {
            // don't fill the console up with a mahoosive list of modules
            chunks: false,
        },

        // hot mdule replacement doesn't work (I think we'd need react-hot-reload?)
        // so webpack-dev-server reloads the page on every update which is quite
        // tedious in Riot since that can take a while.
        hot: false,
        inline: false,
    },
};

/**
 * Merge assets found via CSS and imports into a single tree, while also preserving
 * directories under `res`.
 *
 * @param {string} url The adjusted name of the file, such as `warning.1234567.svg`.
 * @param {string} resourcePath The absolute path to the source file with unmodified name.
 * @return {string} The returned paths will look like `img/warning.1234567.svg`.
 */
function getImgOutputPath(url, resourcePath) {
    const prefix = /^.*\/res\//;
    const outputDir = path.dirname(resourcePath).replace(prefix, "");
    return path.join(outputDir, path.basename(url));
}
<commit_msg>Fix some path math on Windows<commit_after>const path = require('path');
const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');

let og_image_url = process.env.RIOT_OG_IMAGE_URL;
if (!og_image_url) og_image_url = 'https://riot.im/app/themes/riot/img/logos/riot-im-logo-1.png';

module.exports = {
    entry: {
        // Load babel-polyfill first to avoid issues where some imports (namely react)
        // are potentially loaded before babel-polyfill.
        "bundle": ["babel-polyfill", "./src/vector/index.js"],
        "indexeddb-worker": "./src/vector/indexeddb-worker.js",

        "mobileguide": "./src/vector/mobile_guide/index.js",

        // CSS themes
        "theme-light":  "./node_modules/matrix-react-sdk/res/themes/light/css/light.scss",
        "theme-dark":   "./node_modules/matrix-react-sdk/res/themes/dark/css/dark.scss",
        "theme-dharma": "./node_modules/matrix-react-sdk/res/themes/dharma/css/dharma.scss",
        "theme-status": "./res/themes/status/css/status.scss",
    },
    module: {
        rules: [
            { enforce: 'pre', test: /\.js$/, use: "source-map-loader", exclude: /node_modules/, },
            { test: /\.js$/, use: "babel-loader", include: path.resolve(__dirname, 'src') },
            {
                test: /\.scss$/,
                // 1. postcss-loader turns the SCSS into normal CSS.
                // 2. css-loader turns the CSS into a JS module whose default
                //    export is a string containing the CSS, while also adding
                //    the images and fonts from CSS as Webpack inputs.
                // 3. ExtractTextPlugin turns that string into a separate asset.
                use: ExtractTextPlugin.extract({
                    use: [
                        "css-loader",
                        {
                            loader: 'postcss-loader',
                            options: {
                                config: {
                                    path: './postcss.config.js',
                                },
                            },
                        },
                    ],
                }),
            },
            {
                // this works similarly to the scss case, without postcss.
                test: /\.css$/,
                use: ExtractTextPlugin.extract({
                    use: "css-loader",
                }),
            },
            {
                test: /\.(gif|png|svg|ttf)$/,
                // Use a content-based hash in the name so that we can set a long cache
                // lifetime for assets while still delivering changes quickly.
                oneOf: [
                    {
                        // Images referenced in HTML files
                        issuer: /\.html$/,
                        loader: 'file-loader',
                        options: {
                            name: '[name].[hash:7].[ext]',
                            outputPath: getImgOutputPath,
                        },
                    },
                    {
                        // Images referenced in JS and CSS files
                        loader: 'file-loader',
                        options: {
                            name: '[name].[hash:7].[ext]',
                            outputPath: getImgOutputPath,
                            publicPath: function(url, resourcePath) {
                                // JS and CSS image usages end up the `bundles/[hash]` output
                                // directory, so we adjust the final path to navigate up twice.
                                return path.join("../..", getImgOutputPath(url, resourcePath));
                            },
                        },
                    },
                ],
            },
        ],
        noParse: [
            // for cross platform compatibility use [\\\/] as the path separator
            // this ensures that the regex trips on both Windows and *nix

            // don't parse the languages within highlight.js. They cause stack
            // overflows (https://github.com/webpack/webpack/issues/1721), and
            // there is no need for webpack to parse them - they can just be
            // included as-is.
            /highlight\.js[\\\/]lib[\\\/]languages/,

            // olm takes ages for webpack to process, and it's already heavily
            // optimised, so there is little to gain by us uglifying it.
            /olm[\\\/](javascript[\\\/])?olm\.js$/,
        ],
    },
    output: {
        path: path.join(__dirname, "webapp"),

        // The generated JS (and CSS, from the ExtractTextPlugin) are put in a
        // unique subdirectory for the build. There will only be one such
        // 'bundle' directory in the generated tarball; however, hosting
        // servers can collect 'bundles' from multiple versions into one
        // directory and symlink it into place - this allows users who loaded
        // an older version of the application to continue to access webpack
        // chunks even after the app is redeployed.
        filename: "bundles/[hash]/[name].js",
        chunkFilename: "bundles/[hash]/[name].js",
        devtoolModuleFilenameTemplate: function(info) {
            // Reading input source maps gives only relative paths here for
            // everything. Until I figure out how to fix this, this is a
            // workaround.
            // We use the relative resource path with any '../'s on the front
            // removed which gives a tree with matrix-react-sdk and vector
            // trees smashed together, but this fixes everything being under
            // various levels of '.' and '..'
            // Also, sometimes the resource path is absolute.
            return path.relative(process.cwd(), info.resourcePath).replace(/^[\/\.]*/, '');
        },
    },
    resolve: {
        alias: {
            // alias any requires to the react module to the one in our path, otherwise
            // we tend to get the react source included twice when using npm link.
            "react": path.resolve('./node_modules/react'),
            "react-dom": path.resolve('./node_modules/react-dom'),
            "react-addons-perf": path.resolve('./node_modules/react-addons-perf'),

            // same goes for js-sdk
            "matrix-js-sdk": path.resolve('./node_modules/matrix-js-sdk'),
        },
    },
    plugins: [
        new webpack.DefinePlugin({
            'process.env': {
                NODE_ENV: JSON.stringify(process.env.NODE_ENV),
            },
        }),

        new ExtractTextPlugin("bundles/[hash]/[name].css", {
            allChunks: true,
        }),

        new HtmlWebpackPlugin({
            template: './src/vector/index.html',

            // we inject the links ourselves via the template, because
            // HtmlWebpackPlugin wants to put the script tags either at the
            // bottom of <head> or the bottom of <body>, and I'm a bit scared
            // about moving them.
            inject: false,
            excludeChunks: ['mobileguide'],
            vars: {
                og_image_url: og_image_url,
            },
        }),
        new HtmlWebpackPlugin({
            template: './src/vector/mobile_guide/index.html',
            filename: 'mobile_guide/index.html',
            chunks: ['mobileguide'],
        }),
    ],
    devtool: 'source-map',

    // configuration for the webpack-dev-server
    devServer: {
        // serve unwebpacked assets from webapp.
        contentBase: './webapp',

        stats: {
            // don't fill the console up with a mahoosive list of modules
            chunks: false,
        },

        // hot mdule replacement doesn't work (I think we'd need react-hot-reload?)
        // so webpack-dev-server reloads the page on every update which is quite
        // tedious in Riot since that can take a while.
        hot: false,
        inline: false,
    },
};

/**
 * Merge assets found via CSS and imports into a single tree, while also preserving
 * directories under `res`.
 *
 * @param {string} url The adjusted name of the file, such as `warning.1234567.svg`.
 * @param {string} resourcePath The absolute path to the source file with unmodified name.
 * @return {string} The returned paths will look like `img/warning.1234567.svg`.
 */
function getImgOutputPath(url, resourcePath) {
    const prefix = /^.*[/\\]res[/\\]/;
    const outputDir = path.dirname(resourcePath).replace(prefix, "");
    return path.join(outputDir, path.basename(url));
}
<|endoftext|>


<commit_before>(function () {
    $('#upload_button').click(function () {
        $('#uploader').modal();
    });

    // generate socket connection
    function socketClient() {
        var socket = io.connect('127.0.0.1:3000');
        socket.send('client message');
        socket.on('message', function (time) {
            console.log('received server timestamp:' + time);
        });
        return socket;
    }

    //HTML File detection
    window.addEventListener('load', ready);

    function ready() {
        if (window.File && window.FileReader) {
            var socket = socketClient();

            $('#choose-button').click(function () {
                $('#choose-file').click();
            });

            var fileTarget = null;

            $('#choose-file').on('change', function () {
                var file = document.getElementById('choose-file').files[0];
                if (file) {
                    $('#fileName').val(file.name);
                    var fileReader = new FileReader();
                    fileReader.onload = function (evnt) {
                        socket.emit('upload', { 'Name': file.name, 'Segment': evnt.target.result, 'SessionId': $.cookie('session_id')});
                    };
                    socket.emit('start', {'Name': file.name, 'Size': file.size, 'SessionId': $.cookie('session_id')});

                    socket.on('moreData', function (data) { // more data in progress
                        console.log('moreData: ' + JSON.stringify(data));
                        updateProgressBar(data.percent);
                        var position = data.position * 524288;
                        var newFile = null;
                        if(file.slice)
                            newFile = file.slice(position, position + Math.min(524288, file.size - position));
                        else if (file.webkitSlice)
                            newFile = file.webkitSlice(position, position + Math.min(524288, file.size - position));
                        else if(file.mozSlice)
                            newFile = file.mozSlice(position, position + Math.min(524288, file.size - position));
                        if(newFile)
                            fileReader.readAsBinaryString(newFile); // trigger upload event
                    });

                    socket.on('done', function(data){
                        console.log('[done]: ' + JSON.stringify(data));
                        $('#fileName').val('');
                        updateProgressBar(100);
                    });
                }
            });
        } else {
            $("#fileName").html('Your browser does not support the File API. please change a newer browser.');
        }
    }

    function updateProgressBar(percent){
        $('#progressBar').val(percent);
    }
})();<commit_msg>uploading accomplished.<commit_after>(function () {
    $('#upload_button').click(function () {
        $('#uploader').modal();
    });

    // generate socket connection
    function socketClient() {
        var socket = io.connect('127.0.0.1:3000');
        socket.send('client message');
        socket.on('message', function (time) {
            console.log('received server timestamp:' + time);
        });
        return socket;
    }

    //HTML File detection
    window.addEventListener('load', ready);

    function ready() {
        if (window.File && window.FileReader) {
            var socket = socketClient();

            $('#choose-button').click(function () {
                $('#choose-file').click();
            });

            $('#choose-file').on('change', function () {
                var file = document.getElementById('choose-file').files[0];
                if (file) {
                    $('#fileName').val(file.name);
                    var fileReader = new FileReader();
                    fileReader.onload = function (evnt) {
                        socket.emit('upload', { 'Name': file.name, 'Segment': evnt.target.result, 'SessionId': $.cookie('session_id')});
                    };
                    socket.emit('start', {'Name': file.name, 'Size': file.size, 'SessionId': $.cookie('session_id')});

                    socket.on('moreData', function (data) { // more data in progress
                        console.log('moreData: ' + JSON.stringify(data));
                        updateProgressBar(data.percent);
                        var position = data.position * 524288;
                        var newFile = null;
                        if(file.slice)
                            newFile = file.slice(position, position + Math.min(524288, file.size - position));
                        else if (file.webkitSlice)
                            newFile = file.webkitSlice(position, position + Math.min(524288, file.size - position));
                        else if(file.mozSlice)
                            newFile = file.mozSlice(position, position + Math.min(524288, file.size - position));
                        if(newFile)
                            fileReader.readAsBinaryString(newFile); // trigger upload event
                    });

                    socket.on('done', function(data){
                        console.log('[done]: ' + JSON.stringify(data));
                        $('#fileName').val('');
                        delete fileReader;
                        updateProgressBar(100);
                    });
                }
            });
        } else {
            $("#fileName").html('Your browser does not support the File API. please change a newer browser.');
        }
    }

    function updateProgressBar(percent){
        $('#progressBar').val(percent);
    }
})();<|endoftext|>


<commit_before>'use strict';

var path = require('path');
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');

var isProd = process.env.NODE_ENV === 'production';

module.exports = (function makeWebpackConfig() {
	var config = {};

	/**
	 * Configuration begins here
	 * Reference: http://webpack.github.io/docs/configuration.html
	 */

	// Cache generated modules and chunks to improve performance for multiple incremental builds.
	// Reference: http://webpack.github.io/docs/configuration.html#cache
	config.cache = true;

	// Mapping entry point
	// More: https://github.com/webpack/webpack/issues/1189
	config.entry = {
		// This will map entry point to destination path related to output.path
		'dist/app': './src/app/app.js'
	};

	// Options affecting the output of the compilation.
	// Reference: http://webpack.github.io/docs/configuration.html#output
	// Additional notes:
	// http://webpack.github.io/docs/long-term-caching.html
	// https://medium.com/@okonetchnikov/long-term-caching-of-static-assets-with-webpack-1ecb139adb95
	config.output = {
		path: path.resolve(__dirname, 'dist'),
		publicPath: './',
		filename: isProd ? '[name].[chunkhash].js' : '[name].bundle.js',
		// This is probably a bug, since chunks doesn't respect entry mapping in config
		chunkFilename: isProd ? 'dist/[name].[chunkhash].js' : 'dist/[name].bundle.js'
	};

	// Choose a developer tool to enhance debugging.
	// Reference: http://webpack.github.io/docs/configuration.html#devtool
	config.devtool = 'source-map';

	/**
	 * Loaders definition
	 * Reference: http://webpack.github.io/docs/configuration.html#module-loaders
	 * List: http://webpack.github.io/docs/list-of-loaders.html
	 * This handles most of the magic responsible for converting modules
	 */

	config.module = {
		preLoaders: [],
		loaders: [{
			// JS LOADER
			// Reference: https://github.com/babel/babel-loader
			// Transpile .js files using babel-loader (compile ES6 and ES7 into ES5 code)
			test: /\.js$/,
			exclude: /node_modules/,
			// We may use ng-annotate module later
			// Reference: https://github.com/jeffling/ng-annotate-webpack-plugin
			loader: 'babel',
			query: {
				// By default Babel is injecting helpers into each file that requires it.
				// Require the babel runtime as a separate module to avoid the duplication.
				// Reference: https://github.com/babel/babel-loader#babel-is-injecting-helpers-into-each-file-and-bloating-my-code
				plugins: ['transform-runtime']
			}
		},
		{
			test: /\.scss$/,
			// STYLE LOADER
			// Reference: https://github.com/webpack-contrib/style-loader
			// CSS LOADER
			// Reference: https://github.com/webpack-contrib/css-loader
			// SASS LOADER
			// Reference: https://github.com/webpack-contrib/sass-loader
			loader: 'style-loader!css-loader!sass-loader'
		},
		{
			test: /\.css$/,
			// STYLE LOADER
			// Reference: https://github.com/webpack-contrib/style-loader
			// CSS LOADER
			// Reference: https://github.com/webpack-contrib/css-loader
			loader: 'style-loader!css-loader'
		},
		{
			// HTML LOADER
			// Reference: https://github.com/webpack/raw-loader
			// Allow loading html through js
			test: /\.html$/,
			exclude: /node_modules/,
			loader: 'raw'
		}]
	};

	/**
	 * Add additional plugins to the compiler
	 * Reference: http://webpack.github.io/docs/configuration.html#plugins
	 * List: http://webpack.github.io/docs/list-of-plugins.html
	 */

	config.plugins = [];

	// HtmlWebpackPlugin
	// Injects bundles in your main file instead of wiring all manually.
	// Reference: https://github.com/ampedandwired/html-webpack-plugin
	config.plugins.push(
		new HtmlWebpackPlugin({
			filename: 'index.html',
			inject: 'head'
		})
	);

	// Automatically move all modules defined outside of application directory to vendor bundle.
	// If you are using more complicated project structure, consider to specify common chunks manually.
	// Reference: http://webpack.github.io/docs/list-of-plugins.html#commonschunkplugin
	config.plugins.push(
		new webpack.optimize.CommonsChunkPlugin({
			// Destination path (entry config) mapping is also needed here
			name: 'dist/vendor',
			minChunks: function (module, count) {
				return module.resource && (
					module.resource.indexOf(path.resolve(__dirname, 'src', 'app')) === -1
				);
			}
		})
	);

	if (isProd) {
		config.plugins.push(
			// http://webpack.github.io/docs/list-of-plugins.html#noerrorsplugin
			new webpack.NoErrorsPlugin(),
			// Search for equal or similar files and deduplicate them in the output.
			// This comes with some overhead for the entry chunk, but can reduce file size effectively.
			// Reference: http://webpack.github.io/docs/list-of-plugins.html#dedupeplugin
			new webpack.optimize.DedupePlugin(),
			// Minimize all JavaScript output of chunks. Loaders are switched into minimizing mode.
			// Reference: http://webpack.github.io/docs/list-of-plugins.html#uglifyjsplugin
			new webpack.optimize.UglifyJsPlugin({
				mangle: false
			})
		);
	}

	return config;
}());
<commit_msg>Make use of extract-text-webpack-plugin webpack plugin.<commit_after>'use strict';

var path = require('path');
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');

var isProd = process.env.NODE_ENV === 'production';

module.exports = (function makeWebpackConfig() {
	var config = {};

	/**
	 * Configuration begins here
	 * Reference: http://webpack.github.io/docs/configuration.html
	 */

	// Cache generated modules and chunks to improve performance for multiple incremental builds.
	// Reference: http://webpack.github.io/docs/configuration.html#cache
	config.cache = true;

	// Mapping entry point
	// More: https://github.com/webpack/webpack/issues/1189
	config.entry = {
		// This will map entry point to destination path related to output.path
		'dist/app': './src/app/app.js'
	};

	// Options affecting the output of the compilation.
	// Reference: http://webpack.github.io/docs/configuration.html#output
	// Additional notes:
	// http://webpack.github.io/docs/long-term-caching.html
	// https://medium.com/@okonetchnikov/long-term-caching-of-static-assets-with-webpack-1ecb139adb95
	config.output = {
		path: path.resolve(__dirname, 'dist'),
		publicPath: './',
		filename: isProd ? '[name].[chunkhash].js' : '[name].bundle.js',
		// This is probably a bug, since chunks doesn't respect entry mapping in config
		chunkFilename: isProd ? 'dist/[name].[chunkhash].js' : 'dist/[name].bundle.js'
	};

	// Choose a developer tool to enhance debugging.
	// Reference: http://webpack.github.io/docs/configuration.html#devtool
	config.devtool = 'source-map';

	/**
	 * Loaders definition
	 * Reference: http://webpack.github.io/docs/configuration.html#module-loaders
	 * List: http://webpack.github.io/docs/list-of-loaders.html
	 * This handles most of the magic responsible for converting modules
	 */

	config.module = {
		preLoaders: [],
		loaders: [{
			// JS LOADER
			// Reference: https://github.com/babel/babel-loader
			// Transpile .js files using babel-loader (compile ES6 and ES7 into ES5 code)
			test: /\.js$/,
			exclude: /node_modules/,
			// We may use ng-annotate module later
			// Reference: https://github.com/jeffling/ng-annotate-webpack-plugin
			loader: 'babel',
			query: {
				// By default Babel is injecting helpers into each file that requires it.
				// Require the babel runtime as a separate module to avoid the duplication.
				// Reference: https://github.com/babel/babel-loader#babel-is-injecting-helpers-into-each-file-and-bloating-my-code
				plugins: ['transform-runtime']
			}
		},
		{
			test: /\.scss$/,
			// STYLE LOADER
			// Reference: https://github.com/webpack-contrib/style-loader
			// CSS LOADER
			// Reference: https://github.com/webpack-contrib/css-loader
			// SASS LOADER
			// Reference: https://github.com/webpack-contrib/sass-loader
			loader: 'style-loader!css-loader!sass-loader'
		},
		{
			test: /\.css$/,
			// STYLE LOADER
			// Reference: https://github.com/webpack-contrib/style-loader
			// CSS LOADER
			// Reference: https://github.com/webpack-contrib/css-loader
			loader: ExtractTextPlugin.extract('style-loader', 'css-loader?sourceMap')
		},
		{
			// HTML LOADER
			// Reference: https://github.com/webpack/raw-loader
			// Allow loading html through js
			test: /\.html$/,
			exclude: /node_modules/,
			loader: 'raw'
		}]
	};

	/**
	 * Add additional plugins to the compiler
	 * Reference: http://webpack.github.io/docs/configuration.html#plugins
	 * List: http://webpack.github.io/docs/list-of-plugins.html
	 */

	config.plugins = [];

	// HtmlWebpackPlugin
	// Injects bundles in your main file instead of wiring all manually.
	// Reference: https://github.com/ampedandwired/html-webpack-plugin
	config.plugins.push(
		new HtmlWebpackPlugin({
			filename: 'index.html',
			inject: 'head'
		})
	);

	// ExtractTextPlugin
	//
	// Reference: https://github.com/webpack-contrib/extract-text-webpack-plugin/blob/webpack-1/README.md
	config.plugins.push(
		new ExtractTextPlugin('styles.css')
	);

	// Automatically move all modules defined outside of application directory to vendor bundle.
	// If you are using more complicated project structure, consider to specify common chunks manually.
	// Reference: http://webpack.github.io/docs/list-of-plugins.html#commonschunkplugin
	config.plugins.push(
		new webpack.optimize.CommonsChunkPlugin({
			// Destination path (entry config) mapping is also needed here
			name: 'dist/vendor',
			minChunks: function (module, count) {
				return module.resource && (
					module.resource.indexOf(path.resolve(__dirname, 'src', 'app')) === -1
				);
			}
		})
	);

	if (isProd) {
		config.plugins.push(
			// http://webpack.github.io/docs/list-of-plugins.html#noerrorsplugin
			new webpack.NoErrorsPlugin(),
			// Search for equal or similar files and deduplicate them in the output.
			// This comes with some overhead for the entry chunk, but can reduce file size effectively.
			// Reference: http://webpack.github.io/docs/list-of-plugins.html#dedupeplugin
			new webpack.optimize.DedupePlugin(),
			// Minimize all JavaScript output of chunks. Loaders are switched into minimizing mode.
			// Reference: http://webpack.github.io/docs/list-of-plugins.html#uglifyjsplugin
			new webpack.optimize.UglifyJsPlugin({
				mangle: false
			})
		);
	}

	return config;
}());
<|endoftext|>


<commit_before>var templateHTML = '
\

\

\

\

	\

	\

	\

\

\

\

\
      \

\
      	\

\

\

\

\

	\

	\

	\

\

\

\

\

\

\

#{title}
\

#{message}
\

';

var growl4rails_template = new Template(templateHTML);

var growl4rails_instance_count = 0;
var growl4rails_current_showing = 0;
var growl4rails_queue = [];
var growl4rails_limit_reached = false;
var growl4rails_timer_hash = new Hash();

var Growl4Rails = Class.create();

Growl4Rails.showGrowl = function(arguments) {
  //if we're not showing maximum number of growls then show it, otherwise queue it up
  if(growl4rails_current_showing >= growl4rails_max_showing)
    growl4rails_limit_reached = true;

  //generate a unique id for this growl
  var growl_cell_id = $H(arguments).get('growl_id');
  if(growl_cell_id == null)
    growl_cell_id = 'growl4rails_cell_' + (growl4rails_instance_count++);

  if(!growl4rails_limit_reached) {
    growl4rails_current_showing++;

    //add it to the document

    //IE6 PNG fix for icons
    var img_path = $H(arguments).get('image_path');
    var is_png = (img_path.substring(img_path.length-3, img_path.length).toUpperCase() == "PNG")
    var img_style = 'background-image:url(' + img_path + ');background-repeat: no-repeat;';
    if (Prototype.Browser.IE && navigator.userAgent.match(/MSIE [456]/) && is_png) {
      img_style = 'filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' + img_path + '\');';
    }
    var data = {
      id:growl_cell_id,
      title:$H(arguments).get('title'),
      img_style:img_style,
      message:$H(arguments).get('message')
    };

    //get the other growls before we add this one so we can position
    var other_growls = $$('.growl4rails_cell');

    Element.insert(document.body, growl4rails_template.evaluate(data));

    //position the growl
    var top_offset = 0;
    var left_offset = document.viewport.getWidth() - 400;
    $(growl_cell_id).style.left = left_offset + 'px';

    if(other_growls.length > 0) {
      var top_position = 0;
      other_growls.each(function(growl) {
        top_position += growl.getHeight();
      });
      top_offset = document.viewport.getScrollOffsets().top + top_position + 10;
    } else {
      top_offset = document.viewport.getScrollOffsets().top + 10;
    }
    $(growl_cell_id).style.top = top_offset + 'px';

    //position the text and image
    $('growl4rails_info_' + growl_cell_id).style.top = (top_offset + 28) + 'px';
    $('growl4rails_info_' + growl_cell_id).style.left = left_offset + 28 + 'px';

    //wire up the growl mouse events
    $(growl_cell_id).observe('mouseover', Growl4Rails.mouseOver);
    $(growl_cell_id).observe('mouseout', Growl4Rails.mouseOut);
    $(growl_cell_id).observe('click', Growl4Rails.click);
    $('growl4rails_info_' + growl_cell_id).observe('click', Growl4Rails.click);

    //Temporary until we've got better support for opacity and alpha transparency
    if(Prototype.Browser.IE) {
      $('growl4rails_info_' + growl_cell_id).show();
      $(growl_cell_id).show();
    } else {
      Effect.Appear('growl4rails_info_' + growl_cell_id);
      Effect.Appear(growl_cell_id);
    }

    $('growl4rails_body_' + growl_cell_id).style.height = ($('growl4rails_info_' + growl_cell_id).getDimensionsPatched().height - 20) + 'px';

    //set it up to disappear
    var timer = setTimeout("Growl4Rails.hideGrowl('" + growl_cell_id + "')", growl4rails_duration);
    growl4rails_timer_hash.set(growl_cell_id, timer);
  } else {
    growl4rails_queue.push($H({
      growl_id:growl_cell_id,
      image_path:$H(arguments).get('image_path'),
      title:$H(arguments).get('title'),
      message:$H(arguments).get('message')
    }));
  }
  return growl_cell_id;
}

Growl4Rails.hideGrowl = function(growl_cell_id) {
  growl4rails_timer_hash.unset(growl_cell_id);
  if(Prototype.Browser.IE) {
    if($('growl4rails_info_' + growl_cell_id))
      $('growl4rails_info_' + growl_cell_id).hide();

    if($(growl_cell_id))
      $(growl_cell_id).hide();
  } else {
    if($('growl4rails_info_' + growl_cell_id))
      Effect.Fade('growl4rails_info_' + growl_cell_id, { duration: 1.0 });

    if($(growl_cell_id))
      Effect.Fade(growl_cell_id, { duration: 1.0 });
  }

  setTimeout("Growl4Rails.removeGrowl('" + growl_cell_id + "')", 1000);
};

Growl4Rails.removeGrowl = function(growl_cell_id) {
  growl4rails_current_showing--;
  if($('growl4rails_info_' + growl_cell_id))
    $('growl4rails_info_' + growl_cell_id).remove();

  if($(growl_cell_id))
    $(growl_cell_id).remove();

  //if this is the last growl, fire an event so we can show more, if there are any
  if(growl4rails_current_showing == 0) {
    growl4rails_limit_reached = false;
    document.fire('growl4rails:lastgrowlshown');
  }
};

var mouseOverClasses = ['growl4rails_corner_ul', 'growl4rails_top', 'growl4rails_corner_ur',
          'growl4rails_body', 'growl4rails_corner_ll', 'growl4rails_bottom', 'growl4rails_corner_lr'];

Growl4Rails.mouseOver = function(event) {
  //bunch of hoo-ha to make sure we're not handling bubbled mouseover events.
  var relatedTarget = event.relatedTarget;
  var currentTarget = event.currentTarget ? event.currentTarget : event.srcElement;
  if (relatedTarget && relatedTarget.nodeType == Node.TEXT_NODE) relatedTarget = relatedTarget.parentNode;
  if (relatedTarget && relatedTarget != currentTarget && !Element.descendantOf(relatedTarget, currentTarget) && !relatedTarget.ancestors().any(function(n) { return n.hasClassName('growl4rails_info'); })) {
    growl_cell = Growl4Rails.findGrowlIdByDescendant(Event.findElement(event));
    mouseOverClasses.each(function(item) {
     $$('#' + growl_cell.id + ' .' + item)[0].toggleClassName(item + '_hi');
    });
    timer = growl4rails_timer_hash.get(growl_cell.id);
    clearTimeout(timer);
  }
};

Growl4Rails.mouseOut = function(event) {
  //bunch of hoo-ha to make sure we're not handling bubbled mouseover events.
  var relatedTarget = event.relatedTarget;
  var currentTarget = event.currentTarget ? event.currentTarget : event.srcElement;
  if (relatedTarget && relatedTarget.nodeType == Node.TEXT_NODE) relatedTarget = relatedTarget.parentNode;
  if (relatedTarget && relatedTarget != currentTarget && !Element.descendantOf(relatedTarget, currentTarget) && !relatedTarget.ancestors().any(function(n) { return n.hasClassName('growl4rails_info'); })) {
    growl_cell = Growl4Rails.findGrowlIdByDescendant(Event.findElement(event));
    mouseOverClasses.each(function(item) {
     $$('#' + growl_cell.id + ' .' + item)[0].toggleClassName(item + '_hi');
    });
    var timer = setTimeout("Growl4Rails.hideGrowl('" + growl_cell.id + "')", growl4rails_duration);
    growl4rails_timer_hash.set(growl_cell.id, timer);
  }
};

Growl4Rails.click = function(event) {
  growl_cell = Growl4Rails.findGrowlIdByDescendant(Event.findElement(event));
  Growl4Rails.hideGrowl(growl_cell.id);
  growl_cell.fire(growl_cell.id + ':clicked');
};

Growl4Rails.findGrowlIdByDescendant = function(descendant) {
  //Thanks IE!!!
  if(descendant.className == 'growl4rails_cell')
    return descendant;

  var growl_cell = descendant.ancestors().find(function(ancestor){ return ancestor.hasClassName('growl4rails_cell'); });

  if(!growl_cell) {
    growl_info = descendant.ancestors().find(function(ancestor){ return ancestor.hasClassName('growl4rails_info'); });
    if(growl_info)
      growl_cell = $(growl_info.id.sub('growl4rails_info_', ''));
  }
  return growl_cell
};

document.observe('growl4rails:lastgrowlshown', function(event) {
  var i = 0;
  while(growl4rails_queue.length != 0 && i < growl4rails_max_showing) {
    Growl4Rails.showGrowl(growl4rails_queue.shift());
    i++;
  }
});

//Patch for getDimensions where parent is hidden, therefore can't get child dimensions:
Element.addMethods({
  getDimensionsPatched: function (element) {
      element = $(element);
      var dimensions = {width: element.clientWidth, height: element.clientHeight};

      if ((dimensions.width || dimensions.height) == 0) {
        // All *Width and *Height properties give 0 on elements with display none,
        // or when ancestors have display none, so enable those temporarily
        var restore = element.ancestors(function(element) { return !element.visible() }),
        styles = [];
        restore.push(element);

        restore.each(function(r) {
          styles.push({
            display: r.getStyle('display'),
            position: r.getStyle('position'),
            visibility: r.getStyle('visibility')
          });
          r.setStyle({display: 'block', position: 'absolute', visibility: 'visible'});
        });

        dimensions = {width: element.clientWidth, height: element.clientHeight};
        restore.each(function(r, index) {
          r.setStyle(styles[index]);
        });
      }
      return dimensions;
  }//getDimensions
});
<commit_msg>toggling classnames has issues with finnicky bubbling mouseover events.  Just adding on mouseover and removing on mouseout will be best.<commit_after>var templateHTML = '
\

\

\

\

	\

	\

	\

\

\

\

\
      \

\
      	\

\

\

\

\

	\

	\

	\

\

\

\

\

\

\

#{title}
\

#{message}
\

';

var growl4rails_template = new Template(templateHTML);

var growl4rails_instance_count = 0;
var growl4rails_current_showing = 0;
var growl4rails_queue = [];
var growl4rails_limit_reached = false;
var growl4rails_timer_hash = new Hash();

var Growl4Rails = Class.create();

Growl4Rails.showGrowl = function(arguments) {
  //if we're not showing maximum number of growls then show it, otherwise queue it up
  if(growl4rails_current_showing >= growl4rails_max_showing)
    growl4rails_limit_reached = true;

  //generate a unique id for this growl
  var growl_cell_id = $H(arguments).get('growl_id');
  if(growl_cell_id == null)
    growl_cell_id = 'growl4rails_cell_' + (growl4rails_instance_count++);

  if(!growl4rails_limit_reached) {
    growl4rails_current_showing++;

    //add it to the document

    //IE6 PNG fix for icons
    var img_path = $H(arguments).get('image_path');
    var is_png = (img_path.substring(img_path.length-3, img_path.length).toUpperCase() == "PNG")
    var img_style = 'background-image:url(' + img_path + ');background-repeat: no-repeat;';
    if (Prototype.Browser.IE && navigator.userAgent.match(/MSIE [456]/) && is_png) {
      img_style = 'filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' + img_path + '\');';
    }
    var data = {
      id:growl_cell_id,
      title:$H(arguments).get('title'),
      img_style:img_style,
      message:$H(arguments).get('message')
    };

    //get the other growls before we add this one so we can position
    var other_growls = $$('.growl4rails_cell');

    Element.insert(document.body, growl4rails_template.evaluate(data));

    //position the growl
    var top_offset = 0;
    var left_offset = document.viewport.getWidth() - 400;
    $(growl_cell_id).style.left = left_offset + 'px';

    if(other_growls.length > 0) {
      var top_position = 0;
      other_growls.each(function(growl) {
        top_position += growl.getHeight();
      });
      top_offset = document.viewport.getScrollOffsets().top + top_position + 10;
    } else {
      top_offset = document.viewport.getScrollOffsets().top + 10;
    }
    $(growl_cell_id).style.top = top_offset + 'px';

    //position the text and image
    $('growl4rails_info_' + growl_cell_id).style.top = (top_offset + 28) + 'px';
    $('growl4rails_info_' + growl_cell_id).style.left = left_offset + 28 + 'px';

    //wire up the growl mouse events
    $(growl_cell_id).observe('mouseover', Growl4Rails.mouseOver);
    $(growl_cell_id).observe('mouseout', Growl4Rails.mouseOut);
    $(growl_cell_id).observe('click', Growl4Rails.click);
    $('growl4rails_info_' + growl_cell_id).observe('click', Growl4Rails.click);

    //Temporary until we've got better support for opacity and alpha transparency
    if(Prototype.Browser.IE) {
      $('growl4rails_info_' + growl_cell_id).show();
      $(growl_cell_id).show();
    } else {
      Effect.Appear('growl4rails_info_' + growl_cell_id);
      Effect.Appear(growl_cell_id);
    }

    $('growl4rails_body_' + growl_cell_id).style.height = ($('growl4rails_info_' + growl_cell_id).getDimensionsPatched().height - 20) + 'px';

    //set it up to disappear
    var timer = setTimeout("Growl4Rails.hideGrowl('" + growl_cell_id + "')", growl4rails_duration);
    growl4rails_timer_hash.set(growl_cell_id, timer);
  } else {
    growl4rails_queue.push($H({
      growl_id:growl_cell_id,
      image_path:$H(arguments).get('image_path'),
      title:$H(arguments).get('title'),
      message:$H(arguments).get('message')
    }));
  }
  return growl_cell_id;
}

Growl4Rails.hideGrowl = function(growl_cell_id) {
  growl4rails_timer_hash.unset(growl_cell_id);
  if(Prototype.Browser.IE) {
    if($('growl4rails_info_' + growl_cell_id))
      $('growl4rails_info_' + growl_cell_id).hide();

    if($(growl_cell_id))
      $(growl_cell_id).hide();
  } else {
    if($('growl4rails_info_' + growl_cell_id))
      Effect.Fade('growl4rails_info_' + growl_cell_id, { duration: 1.0 });

    if($(growl_cell_id))
      Effect.Fade(growl_cell_id, { duration: 1.0 });
  }

  setTimeout("Growl4Rails.removeGrowl('" + growl_cell_id + "')", 1000);
};

Growl4Rails.removeGrowl = function(growl_cell_id) {
  growl4rails_current_showing--;
  if($('growl4rails_info_' + growl_cell_id))
    $('growl4rails_info_' + growl_cell_id).remove();

  if($(growl_cell_id))
    $(growl_cell_id).remove();

  //if this is the last growl, fire an event so we can show more, if there are any
  if(growl4rails_current_showing == 0) {
    growl4rails_limit_reached = false;
    document.fire('growl4rails:lastgrowlshown');
  }
};

var mouseOverClasses = ['growl4rails_corner_ul', 'growl4rails_top', 'growl4rails_corner_ur',
          'growl4rails_body', 'growl4rails_corner_ll', 'growl4rails_bottom', 'growl4rails_corner_lr'];

Growl4Rails.mouseOver = function(event) {
  //bunch of hoo-ha to make sure we're not handling bubbled mouseover events.
  var relatedTarget = event.relatedTarget;
  var currentTarget = event.currentTarget ? event.currentTarget : event.srcElement;
  if (relatedTarget && relatedTarget.nodeType == Node.TEXT_NODE) relatedTarget = relatedTarget.parentNode;
  if (relatedTarget && relatedTarget != currentTarget && !Element.descendantOf(relatedTarget, currentTarget) && !relatedTarget.ancestors().any(function(n) { return n.hasClassName('growl4rails_info'); })) {
    growl_cell = Growl4Rails.findGrowlIdByDescendant(Event.findElement(event));
    mouseOverClasses.each(function(item) {
     $$('#' + growl_cell.id + ' .' + item)[0].addClassName(item + '_hi');
    });
    timer = growl4rails_timer_hash.get(growl_cell.id);
    clearTimeout(timer);
  }
};

Growl4Rails.mouseOut = function(event) {
  //bunch of hoo-ha to make sure we're not handling bubbled mouseover events.
  var relatedTarget = event.relatedTarget;
  var currentTarget = event.currentTarget ? event.currentTarget : event.srcElement;
  if (relatedTarget && relatedTarget.nodeType == Node.TEXT_NODE) relatedTarget = relatedTarget.parentNode;
  if (relatedTarget && relatedTarget != currentTarget && !Element.descendantOf(relatedTarget, currentTarget) && !relatedTarget.ancestors().any(function(n) { return n.hasClassName('growl4rails_info'); })) {
    growl_cell = Growl4Rails.findGrowlIdByDescendant(Event.findElement(event));
    mouseOverClasses.each(function(item) {
     $$('#' + growl_cell.id + ' .' + item)[0].removeClassName(item + '_hi');
    });
    var timer = setTimeout("Growl4Rails.hideGrowl('" + growl_cell.id + "')", growl4rails_duration);
    growl4rails_timer_hash.set(growl_cell.id, timer);
  }
};

Growl4Rails.click = function(event) {
  growl_cell = Growl4Rails.findGrowlIdByDescendant(Event.findElement(event));
  Growl4Rails.hideGrowl(growl_cell.id);
  growl_cell.fire(growl_cell.id + ':clicked');
};

Growl4Rails.findGrowlIdByDescendant = function(descendant) {
  //Thanks IE!!!
  if(descendant.className == 'growl4rails_cell')
    return descendant;

  var growl_cell = descendant.ancestors().find(function(ancestor){ return ancestor.hasClassName('growl4rails_cell'); });

  if(!growl_cell) {
    growl_info = descendant.ancestors().find(function(ancestor){ return ancestor.hasClassName('growl4rails_info'); });
    if(growl_info)
      growl_cell = $(growl_info.id.sub('growl4rails_info_', ''));
  }
  return growl_cell
};

document.observe('growl4rails:lastgrowlshown', function(event) {
  var i = 0;
  while(growl4rails_queue.length != 0 && i < growl4rails_max_showing) {
    Growl4Rails.showGrowl(growl4rails_queue.shift());
    i++;
  }
});

//Patch for getDimensions where parent is hidden, therefore can't get child dimensions:
Element.addMethods({
  getDimensionsPatched: function (element) {
      element = $(element);
      var dimensions = {width: element.clientWidth, height: element.clientHeight};

      if ((dimensions.width || dimensions.height) == 0) {
        // All *Width and *Height properties give 0 on elements with display none,
        // or when ancestors have display none, so enable those temporarily
        var restore = element.ancestors(function(element) { return !element.visible() }),
        styles = [];
        restore.push(element);

        restore.each(function(r) {
          styles.push({
            display: r.getStyle('display'),
            position: r.getStyle('position'),
            visibility: r.getStyle('visibility')
          });
          r.setStyle({display: 'block', position: 'absolute', visibility: 'visible'});
        });

        dimensions = {width: element.clientWidth, height: element.clientHeight};
        restore.each(function(r, index) {
          r.setStyle(styles[index]);
        });
      }
      return dimensions;
  }//getDimensions
});
<|endoftext|>


<commit_before>require('es6-promise').polyfill(); // https://github.com/webpack/css-loader/issues/144

module.exports = {
  devtool: 'inline-source-map',
  entry: __dirname + '/src/js/index.js',
  output: {
    path: __dirname + '/dist',
    publicPath: '/',
    filename: 'tripleo_ui.js',
    sourceMapFilename: 'tripleo_ui.js.map'
  },
  module: {
    loaders: [
      // Javascript
      {
        test: /\.js$/,
        include: /src/,
        exclude: /src\/js\/workers/,
        loader: 'babel'
      },

      // Shared Workers
      {
        test: /\.js$/,
        include: /src\/js\/workers/,
        loader: 'shared-worker!babel'
      },

      // Images
      {
        test: /\.(png|jpg|gif)(\?v=\d+\.\d+\.\d+)?$/,
        loader: 'url-loader',
        query: {
          limit: 8192, // inline base64 URLs for <=8k images, direct URLs for the rest
          name: '[name].[ext]'
        }
      },

      // Fonts and svg images
      {
        test: /\.(woff|woff2)(\?v=\d+\.\d+\.\d+)?$/,
        loader: 'url',
        query: {
          limit: 8192,
          mimetype: 'application/font-woff',
          name: '[name].[ext]'
        }
      },
      {
        test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
        loader: 'url',
        query: {
          limit: 8192,
          mimetype: 'application/octet-stream',
          name: '[name].[ext]'
        }
      },
      {
        test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
        loader: 'file',
        query: { name: '[name].[ext]' }
      },
      {
        test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
        loader: 'url',
        query: {
          limit: 8192,
          mimetype: 'image/svg+xml',
          name: '[name].[ext]'
        }
      },

      // Plain CSS files
      {
        test: /\.css$/,
        loader: 'style!css'
      },

      // Less
      {
        test: /\.less$/,
        loader: 'style!css!less?sourceMap'
      },

      {
        loader: __dirname + '/src/js/loaders/version.js',
        test: /src\/js\/index.js$/
      }
    ]
  },
  devServer: {
    contentBase: './dist',
    port: 3000,
    colors: true,
    historyApiFallback: true,
    inline: true
  }
};
<commit_msg>Have dev server listen everywhere instead of just local<commit_after>require('es6-promise').polyfill(); // https://github.com/webpack/css-loader/issues/144

module.exports = {
  devtool: 'inline-source-map',
  entry: __dirname + '/src/js/index.js',
  output: {
    path: __dirname + '/dist',
    publicPath: '/',
    filename: 'tripleo_ui.js',
    sourceMapFilename: 'tripleo_ui.js.map'
  },
  module: {
    loaders: [
      // Javascript
      {
        test: /\.js$/,
        include: /src/,
        exclude: /src\/js\/workers/,
        loader: 'babel'
      },

      // Shared Workers
      {
        test: /\.js$/,
        include: /src\/js\/workers/,
        loader: 'shared-worker!babel'
      },

      // Images
      {
        test: /\.(png|jpg|gif)(\?v=\d+\.\d+\.\d+)?$/,
        loader: 'url-loader',
        query: {
          limit: 8192, // inline base64 URLs for <=8k images, direct URLs for the rest
          name: '[name].[ext]'
        }
      },

      // Fonts and svg images
      {
        test: /\.(woff|woff2)(\?v=\d+\.\d+\.\d+)?$/,
        loader: 'url',
        query: {
          limit: 8192,
          mimetype: 'application/font-woff',
          name: '[name].[ext]'
        }
      },
      {
        test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
        loader: 'url',
        query: {
          limit: 8192,
          mimetype: 'application/octet-stream',
          name: '[name].[ext]'
        }
      },
      {
        test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
        loader: 'file',
        query: { name: '[name].[ext]' }
      },
      {
        test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
        loader: 'url',
        query: {
          limit: 8192,
          mimetype: 'image/svg+xml',
          name: '[name].[ext]'
        }
      },

      // Plain CSS files
      {
        test: /\.css$/,
        loader: 'style!css'
      },

      // Less
      {
        test: /\.less$/,
        loader: 'style!css!less?sourceMap'
      },

      {
        loader: __dirname + '/src/js/loaders/version.js',
        test: /src\/js\/index.js$/
      }
    ]
  },
  devServer: {
    contentBase: './dist',
    host: '0.0.0.0',
    port: 3000,
    colors: true,
    historyApiFallback: true,
    inline: true
  }
};
<|endoftext|>


<commit_before>var width = 1000,
    height = 900,
    color = d3.scale.category20(), //random color palette maybe?
    toggle = false;

d3.json("/javascripts/data/abp1415-min.json", function(error, json) {

    if (error) return console.warn(error);

    var nodesData = _.each(json, function(item) {
        item.radius = item["AveragePoints"]/50;
    item.fontsize = 5 + item.radius/5;
  })

    // the physics
    var force = d3.layout.force()
                .gravity(0.045)
                .charge(function(d, i) { return i ? 0 : -2000; })
                .nodes(nodesData)
                .size([width, height]);

    force.start();

    var svgContainer = d3.select("body").append("svg")
                    .attr("width", width)
                    .attr("height", height);

    var tip = d3.tip()
        .attr("class", "d3-tip")
        .offset([-10, 0])
        .html(function(d) {
            return "Module Title:  "
            + d["ModuleTitle"] + ""
            + "
"
            + "Average Bid Points: "
            + ""
            + d["AveragePoints"] + "
";
        });

    var vis = d3.select("body")
        .append("svg")
        .call(tip);

    var elem = svgContainer.selectAll("g")
        .data(nodesData);

    var elemEnter = elem.enter()
        .append("g")
        .on('mouseover', tip.show)
        .on('mousedown', tip.hide)
        .on('mouseout', tip.hide);

    var circle = elemEnter.append("circle")
        .attr("r", function(d) {return d.radius;})
        .style("fill", function(d, i) { return color(i % 20);})
        .call(force.drag);

    var text = elemEnter.append("text")
        .attr("text-anchor", "middle")
        .attr("font-family", "sans-serif")
        .attr("font-size", function(d) {return d.fontsize;})
        .attr("fill", "black")
        .text(function(d) {return d["ModuleCode"];});

   // circle.on('click', moduleDetail);

  //what occurs in every step of the animation
    force.on("tick", function() {
        var q = d3.geom.quadtree(nodesData), //q is a quadtree factory
            i = 0,
            n = nodesData.length; //number of nodes

        while (++i < n)
            q.visit(collide(nodesData[i])); //visit each node in quad tree

        circle.attr("cx", function(d) { return d.x; })
            .attr("cy", function(d) { return d.y; });

        text.attr("x", function(d) {return d.x;})
            .attr("y", function(d) {return d.y;});

  });

    function moduleDetail() {
        if (!toggle) {
            //Reduce opacity of other nodes
   //         d = d3.select(this)

        } else {

        }
    }

    //Collision detection function.
    //without it, nodes would overlap
    function collide(node) {
        var r = node.radius + 25, //add buffer distance for collision
        nx1 = node.x - r,
        nx2 = node.x + r,
        ny1 = node.y - r,
        ny2 = node.y + r;

    return function(quad, x1, y1, x2, y2) {
      if (quad.point && (quad.point !== node)) {
        var x = node.x - quad.point.x,
            y = node.y - quad.point.y,
            l = Math.sqrt(x * x + y * y), //distance between two points
            r = node.radius + quad.point.radius;
        if (l < r) {
          l = (l - r) / l * .5;
          node.x -= x *= l;
          node.y -= y *= l;
          quad.point.x += x;
          quad.point.y += y; //move nodes apart
        }
      }
      //if return true, children not visited
      return x1 > nx2 || x2 < nx1 || y1 > ny2 || y2 < ny1;
    };
  }

});

<commit_msg>minor graph aesthetic changes<commit_after>var width = 1000,
    height = 900,
    color = d3.scale.category20(),
    toggle = false;

d3.json("/javascripts/data/abp1415-min.json", function(error, json) {

    if (error) return console.warn(error);

    var nodesData = _.each(json, function(item) {
        item.radius = item.AveragePoints/50;
        item.fontsize = 5 + item.radius/5;
  })

    // the physics
    var force = d3.layout.force()
                .gravity(0.045)
                .charge(function(d, i) { return i ? 0 : -2000; })
                .nodes(nodesData)
                .size([width, height]);

    force.start();

    var svgContainer = d3.select("body").append("svg")
                    .attr("width", width)
                    .attr("height", height);

    var tip = d3.tip()
        .attr("class", "d3-tip")
        .offset([-10, 0])
        .html(function(d) {
            return "Module Title:  "
            + d.ModuleTitle + ""
            + "
"
            + "Average Bid Points: "
            + ""
            + d.AveragePoints + "
";
        });

    var vis = d3.select("body")
        .append("svg")
        .call(tip);

    var elem = svgContainer.selectAll("g")
        .data(nodesData);

    var elemEnter = elem.enter()
        .append("g")
        .on('mouseover', tip.show)
        .on('mousedown', tip.hide)
        .on('mouseout', tip.hide);

    var circle = elemEnter.append("circle")
        .attr("r", function(d) {return d.radius;})
        .style("fill", function(d, i) { return color(i % 10);})
        .call(force.drag);

    var text = elemEnter.append("text")
        .attr("text-anchor", "middle")
        .attr("font-family", "sans-serif")
        .attr("font-size", function(d) {return d.fontsize;})
        .attr("fill", "black")
        .text(function(d) {return d.ModuleCode;});

   // circle.on('click', moduleDetail);

  //what occurs in every step of the animation
    force.on("tick", function() {
        var q = d3.geom.quadtree(nodesData), //q is a quadtree factory
            i = 0,
            n = nodesData.length; //number of nodes

        while (++i < n)
            q.visit(collide(nodesData[i])); //visit each node in quad tree

        circle.attr("cx", function(d) { return d.x; })
            .attr("cy", function(d) { return d.y; });

        text.attr("x", function(d) {return d.x;})
            .attr("y", function(d) {return d.y;});

  });

    function moduleDetail() {
        if (!toggle) {

        } else {

        }
    }

    //Collision detection function.
    //without it, nodes would overlap
    function collide(node) {
        var r = node.radius + 25, //add buffer distance for collision
        nx1 = node.x - r,
        nx2 = node.x + r,
        ny1 = node.y - r,
        ny2 = node.y + r;

    return function(quad, x1, y1, x2, y2) {
      if (quad.point && (quad.point !== node)) {
        var x = node.x - quad.point.x,
            y = node.y - quad.point.y,
            l = Math.sqrt(x * x + y * y), //distance between two points
            r = node.radius + quad.point.radius;
        if (l < r) {
          l = (l - r) / l * .5;
          node.x -= x *= l;
          node.y -= y *= l;
          quad.point.x += x;
          quad.point.y += y; //move nodes apart
        }
      }
      //if return true, children not visited
      return x1 > nx2 || x2 < nx1 || y1 > ny2 || y2 < ny1;
    };
  }

});

<|endoftext|>


<commit_before>function showSubTree(parent, children, dontAnimate) {
    var childrenSpan = $(this).parent().children("span");
    var totalLength = $(this).parent().width();
    var nodeChildrenSize = $(this).siblings('ul').children().size();
    var heightDiff;
    var heightBefore = parent.height();
    if(nodeChildrenSize> 0){
        var leftHeight = (nodeChildrenSize+1)*38;
        parent.height(leftHeight);
        heightDiff = leftHeight-heightBefore;
    } else {
        parent.height(28);
        heightDiff = 28 -heightBefore;
    }

    ($(parent).parents("li.parent_li")).each(function(index, grandParent){
        $(grandParent).height($(grandParent).height()+heightDiff);
    });

    var rightHeight = $(this).siblings(".data").height();
    $(this).siblings('ul').css("position","relative");

    $(this).siblings('ul').css("top", +(20-rightHeight)+"px");
    var toFill = totalLength;
    for (var i = 0; i < childrenSpan.length; i++) {
        if(!$(childrenSpan[i]).hasClass("line")){
        toFill -= $(childrenSpan[i]).outerWidth();
        }
    }
    if(dontAnimate){
        $(this).siblings(".line").width(toFill + "px");
    }else {
        $(this).siblings(".line").animate({width: toFill + "px"}).fadeIn();
    }
    $(this).siblings(".data").fadeIn();
    parent.addClass("open");

    children.show('fast');

    $(this).attr('title', 'Collapse this branch').find('> i').addClass('glyphicon-minus').removeClass('glyphicon-plus');
}
function hideSubTree(parent, children, correctHeights, possibleChild) {
    var heightBefore = $(parent).height();
    var childrenSpan = $(this).siblings("span");
    for (var i = 0; i < childrenSpan.length; i++) {
        $(childrenSpan[i]).hide();
    }
    var openChildren = $(children).filter(".open");
    for(var i = 0; i< openChildren.length; i++){
        var toClose = $(openChildren[i]).children("span.title");
        hideSubTree.call(toClose,openChildren[i],$(openChildren[i]).find(' > ul > li'), false);
    }

    $(parent).css("height","");
    $(this).siblings(".line").stop().width("0px");
    $(parent).removeClass("open");
    $(parent).next().removeClass("after-open");
    if(!possibleChild || parent.has(possibleChild).length==0 ){
        var childrenCount = children.length;
        children.hide('fast', function(){
            if(childrenCount==1) {
                if (correctHeights) {
                    var heightDiff = heightBefore - $(parent).height();
                    ($(parent).parents("li.parent_li")).each(function (index, grandParent) {
                        $(grandParent).height($(grandParent).height() - heightDiff);
                    });
                }
            }
            childrenCount --;
        });
        $(this).attr('title', 'Expand this branch').find('> i').addClass('glyphicon-plus').removeClass('glyphicon-minus');
    }

}
function nodeHover(args){
    var parent = $(this).parent('li.parent_li');
    parent.children('span.data, span.title').addClass('hovered');
    parent.children('ul').find('li > span.title').addClass('hovered');
    $(parent).children('span.title_edit_button').animate({"margin-left":"-5px"}, 100);
}
function nodeHoverOut(args) {
    var parent = $(this).parent('li.parent_li');
    parent.children('span').removeClass('hovered');
    parent.children('ul').find('li > span.title').removeClass('hovered');
    if(($(parent).find(args.relatedTarget).length==0 || !$(args.relatedTarget).is("span"))
        || $(parent).is(args.relatedTarget)) {
        $(parent).children('span.title_edit_button').animate({"margin-left": "-35px"}, 300);
    }
}
function editHoverOut(args){
    var parent = $(this).parent('li.parent_li');
    if($(parent).find(args.relatedTarget).length==0){
        $(parent).children('span.title_edit_button').animate({"margin-left": "-35px"}, 300);
    }

}
function resizeViewport() {
    currentlyOpens = $('.tree li.parent_li > span');
    for(var currentlyOpen in currentlyOpens) {
        var parent = $(currentlyOpen).parent('li.parent_li');
        var children = parent.find(' > ul > li');
        showSubTree.call(currentlyOpen, parent, children, true);
    }
}
function onNodeClick(e) {
    var parent = $(this).parent('li.parent_li');
    var children = parent.find(' > ul > li');
    if (children.is(":visible")) {

        hideSubTree.call(this, parent, children, true);
    } else {
        if ($(parent).hasClass('open')) {
            hideSubTree.call(this, parent, children, true);
        } else {
            showSubTree.call(this, parent, children);
        }
    }
    e.stopPropagation();
}
function onEditClick(e) {
    e.stopPropagation();
    $(this).siblings('span.title').editable({
        type: 'text',
        placement: 'top',
        title: 'Enter username'
    });
    $(this).siblings('span.title').attr('title','Enter node name');
    $($(this).siblings('span.title')[0]).editable('show');
}
$(function () {

    $('.tree li').addClass('parent_li').find('> span').attr('title', 'Collapse this branch');
    $('.tree li.parent_li > span.title').on('click', onNodeClick);
    $('.tree li.parent_li > span.title_edit_button').on('click',onEditClick);
    $('.tree li.parent_li > span').parent('li.parent_li').find('> ul > li').hide('fast');
    $(window).resize(resizeViewport);
    $('.tree li.parent_li > span.title').hover(nodeHover, nodeHoverOut);
    $('.tree li.parent_li > span.title_edit_button').hover(function(){}, editHoverOut)
});<commit_msg>fixing some aspects of the horizontal node expansion<commit_after>function showSubTree(parent, children, dontAnimate) {
    var childrenSpan = $(this).parent().children("span");
    var totalLength = $(this).parent().width();
    var nodeChildrenSize = $(this).siblings('ul').children().size();
    var heightDiff;
    var heightBefore = parent.height();
    if(nodeChildrenSize> 0){
        var leftHeight = (nodeChildrenSize+1)*38;
        parent.height(leftHeight);
        heightDiff = leftHeight-heightBefore;
    } else {
        parent.height(28);
        heightDiff = 28 -heightBefore;
    }

    ($(parent).parents("li.parent_li")).each(function(index, grandParent){
        $(grandParent).height($(grandParent).height()+heightDiff);
    });

    var rightHeight = $(this).siblings(".data").height();
    $(this).siblings('ul').css("position","relative");

    $(this).siblings('ul').css("top", +(20-rightHeight)+"px");
    var toFill = totalLength;
    for (var i = 0; i < childrenSpan.length; i++) {
        if(!$(childrenSpan[i]).hasClass("line")){
            toFill -= $(childrenSpan[i]).outerWidth();
        }
    }
    if(dontAnimate){
        $(this).siblings(".line").width(toFill + "px");
    }else {
        $(this).siblings(".line").animate({width: toFill + "px"}).fadeIn();
    }
    $(this).siblings(".data").fadeIn();
    parent.addClass("open");

    children.show('fast');

    $(this).attr('title', 'Collapse this branch').find('> i').addClass('glyphicon-minus').removeClass('glyphicon-plus');
}
function hideSubTree(parent, children, correctHeights, possibleChild) {
    var heightBefore = $(parent).height();
    var childrenSpan = $(this).siblings("span");
    for (var i = 0; i < childrenSpan.length; i++) {
        $(childrenSpan[i]).hide();
    }
    var openChildren = $(children).filter(".open");
    for(var i = 0; i< openChildren.length; i++){
        var toClose = $(openChildren[i]).children("span.title");
        hideSubTree.call(toClose,openChildren[i],$(openChildren[i]).find(' > ul > li'), false);
    }

    $(parent).css("height","");
    $(this).siblings(".line").stop().width("0px");
    $(parent).removeClass("open");
    $(parent).next().removeClass("after-open");
    if(!possibleChild || parent.has(possibleChild).length==0 ){
        var childrenCount = children.length;
        children.hide('fast', function(){
            if(childrenCount==1) {
                if (correctHeights) {
                    var heightDiff = heightBefore - $(parent).height();
                    ($(parent).parents("li.parent_li")).each(function (index, grandParent) {
                        $(grandParent).height($(grandParent).height() - heightDiff);
                    });
                }
            }
            childrenCount --;
        });
        $(this).attr('title', 'Expand this branch').find('> i').addClass('glyphicon-plus').removeClass('glyphicon-minus');
    }

}
function nodeHover(args){
    var parent = $(this).parent('li.parent_li');
    parent.children('span.data, span.title').addClass('hovered');
    parent.children('ul').find('li > span.title').addClass('hovered');
    var currentWidth = $(parent).children("span.line").data("oldWidth") || $(parent).children("span.line").width();
    if(parent.children('span.data:visible').length != 0) {
        var lineWidth = currentWidth - 30;
        $(parent).children("span.line:visible").stop().animate({"width":lineWidth},{duration: 100, queue: false , complete:function(){
            $(this).data("oldWidth", lineWidth);
        }});
    }
    $(parent).children('span.title_edit_button').show().stop().animate({"margin-left": "-5px"}, { duration: 100, queue: false });
}
function nodeHoverOut(args) {
    var parent = $(this).parent('li.parent_li');
    parent.children('span').removeClass('hovered');
    parent.children('ul').find('li > span.title').removeClass('hovered');
    if(($(parent).find(args.relatedTarget).length==0 || !$(args.relatedTarget).is("span"))
        || $(parent).is(args.relatedTarget)) {
        var currentWidth = $(parent).children("span.line").data("oldWidth") || $(parent).children("span.line").width();
        if(parent.children('span.data:visible').length != 0) {
            var lineWidth = currentWidth + 30;
            $(parent).children("span.line:visible").stop().animate({"width": lineWidth}, {duration: 300, queue: false,complete:function(){
                $(this).data("oldWidth", lineWidth);
            }});
        }
        $(parent).children('span.title_edit_button').stop().animate({"margin-left": "-35px"}, { duration: 300, queue: false });
    }
}
function editHoverOut(args){
    var parent = $(this).parent('li.parent_li');
    if($(parent).find(args.relatedTarget).length==0){
        $(parent).children('span.title_edit_button').animate({"margin-left": "-35px"}, 300);
    }

}
function resizeViewport() {
    currentlyOpens = $('.tree li.parent_li > span');
    for(var currentlyOpen in currentlyOpens) {
        var parent = $(currentlyOpen).parent('li.parent_li');
        var children = parent.find(' > ul > li');
        showSubTree.call(currentlyOpen, parent, children, true);
    }
}
function onNodeClick(e) {
    var parent = $(this).parent('li.parent_li');
    var children = parent.find(' > ul > li');
    if (children.is(":visible")) {

        hideSubTree.call(this, parent, children, true);
    } else {
        if ($(parent).hasClass('open')) {
            hideSubTree.call(this, parent, children, true);
        } else {
            showSubTree.call(this, parent, children);
        }
    }
    e.stopPropagation();
}
function onEditClick(e) {
    e.stopPropagation();
    $(this).siblings('span.title').editable({
        type: 'text',
        placement: 'top',
        title: 'Enter username'
    });
    $(this).siblings('span.title').attr('title','Enter node name');
    $($(this).siblings('span.title')[0]).editable('show');
}
$(function () {

    $('.tree li').addClass('parent_li').find('> span').attr('title', 'Collapse this branch');
    $('.tree li.parent_li > span.title').on('click', onNodeClick);
    $('.tree li.parent_li > span.title_edit_button').on('click',onEditClick);
    $('.tree li.parent_li > span').parent('li.parent_li').find('> ul > li').hide('fast');
    $(window).resize(resizeViewport);
    $('.tree li.parent_li > span.title').hover(nodeHover, nodeHoverOut);
    $('.tree li.parent_li > span.title_edit_button').hover(function(){}, editHoverOut)
});<|endoftext|>


<commit_before>'use strict';

const deepcopy = require('deepcopy'),
      webpack = require('webpack');

const ExtractTextPlugin = require('extract-text-webpack-plugin');

// eslint-disable-next-line no-unused-vars
module.exports = function(env) {
  const baseConfig = {
    context: __dirname,
  };

  return [
    Object.assign({}, deepcopy(baseConfig), {
      entry: {
        'manifest': `${__dirname}/src/manifest.js`
      },
      module: {
        rules: [
          {
            exclude: /node_modules/,
            test: /manifest.js$/,
            use: ExtractTextPlugin.extract({
              use: [
                { loader: 'raw-loader' },
                { loader: 'val-loader' },
              ],
            }),
          },
        ],
      },
      output: {
        filename: '[name].json',
        path: `${__dirname}/ext/`,
        publicPath: './',
      },
      plugins: [
        new ExtractTextPlugin('manifest.json'),
      ],
    }),
    Object.assign({}, deepcopy(baseConfig), {
      entry: {
        'background': `${__dirname}/src/background.js`,
        'options': `${__dirname}/src/options.js`,
        'vendor': [
          'mustache',
          'sprintf-js',
        ],
      },
      module: {
        rules: [
          {
            exclude: /node_modules/,
            include: /options\.js/,
            test: /\.js$/,
            use: [
              { loader: 'babel-loader' },
            ],
          },
        ],
      },
      output: {
        chunkFilename: 'chunk-[id]-[hash].js',
        filename: '[name].js',
        path: `${__dirname}/ext/`,
        publicPath: './',
      },
      target: 'web',
      plugins: [
        new webpack.optimize.CommonsChunkPlugin({
          name: 'vendor',
          minChunks: Infinity,
        }),
        new webpack.BannerPlugin({
          banner: [
            '@license Copyright(c) 2017 sasa+1',
            'Released under the MIT license.',
          ].join('\n'),
          entryOnly: true,
          raw: false,
        }),
      ],
    }),
  ];
};
<commit_msg>added URI to banner<commit_after>'use strict';

const deepcopy = require('deepcopy'),
      webpack = require('webpack');

const ExtractTextPlugin = require('extract-text-webpack-plugin');

// eslint-disable-next-line no-unused-vars
module.exports = function(env) {
  const baseConfig = {
    context: __dirname,
  };

  return [
    Object.assign({}, deepcopy(baseConfig), {
      entry: {
        'manifest': `${__dirname}/src/manifest.js`
      },
      module: {
        rules: [
          {
            exclude: /node_modules/,
            test: /manifest.js$/,
            use: ExtractTextPlugin.extract({
              use: [
                { loader: 'raw-loader' },
                { loader: 'val-loader' },
              ],
            }),
          },
        ],
      },
      output: {
        filename: '[name].json',
        path: `${__dirname}/ext/`,
        publicPath: './',
      },
      plugins: [
        new ExtractTextPlugin('manifest.json'),
      ],
    }),
    Object.assign({}, deepcopy(baseConfig), {
      entry: {
        'background': `${__dirname}/src/background.js`,
        'options': `${__dirname}/src/options.js`,
        'vendor': [
          'mustache',
          'sprintf-js',
        ],
      },
      module: {
        rules: [
          {
            exclude: /node_modules/,
            include: /options\.js/,
            test: /\.js$/,
            use: [
              { loader: 'babel-loader' },
            ],
          },
        ],
      },
      output: {
        chunkFilename: 'chunk-[id]-[hash].js',
        filename: '[name].js',
        path: `${__dirname}/ext/`,
        publicPath: './',
      },
      target: 'web',
      plugins: [
        new webpack.optimize.CommonsChunkPlugin({
          name: 'vendor',
          minChunks: Infinity,
        }),
        new webpack.BannerPlugin({
          banner: [
            '@license Copyright(c) 2017 sasa+1',
            'https://github.com/chocolateorange/new-post.crx',
            'Released under the MIT license.',
          ].join('\n'),
          entryOnly: true,
          raw: false,
        }),
      ],
    }),
  ];
};
<|endoftext|>


<commit_before>/*ConnextCMS pluginView.js - This file loads plugins at run-time.*/
define([
	'jQuery-2.1.4.min',
	'underscore_1.3.3',
	'backbone_0.9.2',
  'text!../../../js/app/templates/pluginTemplate.html'
], function ($, _, Backbone, PluginTemplate) {
	'use strict';

	var PostsView = Backbone.View.extend({

		tagName:  'div',

    el: '#pluginDiv',

		template: _.template(PluginTemplate),

		// The DOM events specific to an item.
		events: {

		},

		initialize: function () {
      this.loadedPlugins = []; //An array containing all the loaded plugins and their Backbone constructs.
      this.pluginData = []; //An array containing the contents of the pluginSettings.json file (the metadata) for each plugin.
		},

    render: function () {
      //debugger;

      var thisView = this;

      this.$el.html(this.template);

      $.get('/api/plugins/list', '', function(data) {
        //debugger;

        //Error Handling
        if( (!data.success) || (data.plugins.length == 0) ) {
          return;
        }

        //Save the pluginSettings.json data
        thisView.pluginData = data.plugins; //Copy the plugin data (for all plugins) to the Plugin View
        var pluginData = data.plugins;      //Also copy the plugin data to a local variable.

        //Loop through each PLUGIN
        for(var i=0; i < pluginData.length; i++) {

          //Add a div to the DOM. This will be the div for the current plugin.
          thisView.$el.find('#pluginParentDiv').append('

');

          //Tell the plugin which div belongs to it.
          thisView.pluginData[i].divId = '#plugin'+i;

          //Prep the loadedPlugins object for this plugin with an empty object.
          var tmpObj = {};
          tmpObj.views = [];
          tmpObj.models = [];
          tmpObj.collections = [];
          thisView.loadedPlugins[i] = tmpObj;

          //Load the Backbone Views, Models, and Collections associated with this plugin.
          thisView.loadConstructs(i);

          thisView.loadModels(i);
        }

      });

			return this;
		},

    //This function instantiates the Backbone Views, Models, and Collections associated with a plugin.
    //It expects the plugin metadata to be passed into it. This is the data stored in the pluginSettings.json
    loadConstructs: function(pluginIndex) {
      //debugger;

      //Get local handles to view-level objects.
      var thisView = this;                                //Get a handle on this View.
      var thisPluginData = this.pluginData[pluginIndex];  //Plugin Metadata
      var thisPlugin = this.loadedPlugins[pluginIndex];   //Will hold the plugins Backbone constructs.

      // ---BEGIN BACKBONE VIEWS---

      //Loop through each of the backbone views for this plugin.
      //Have to use an async for loop since we making async calls to $.getScript().
      global.async.eachOf(thisPluginData.backboneViewFiles, function(value, key, callback) {
        //debugger;

        try {

          var pluginDir = '/plugins/'+thisPluginData.pluginDirName+'/';

          //Load the individual views for this plugin. Generate a promise for each view.
          var scriptPromise = $.getScript(pluginDir+value, function(data, textStatus, jqxhr) {
            //debugger;

          })
          .fail(function( jqxhr, settings, exception ) {
            debugger;

            console.error('Problem with pluginView.js/loadConstructs() when trying load Backbone Views: '+exception);
          });

          //When the promise resolves:
          scriptPromise.then(function(results) {
            //debugger;

            //Scope is lost at the point and a handle needs to be established on the current plugin.
            var thisPluginIndex = global.pluginView.getPluginIndex('backboneViewNames', results);
            if(thisPluginIndex == null) {
              console.error('Could not find plugin.');
              return;
            } else {
              var thisPluginData = global.pluginView.pluginData[thisPluginIndex];
              var thisPlugin = global.pluginView.loadedPlugins[thisPluginIndex];
            }

            //Create the new view.
            var constructor = "new "+thisPluginData.backboneViewNames[key]+"({el: $(thisPluginData.divId), pluginData: thisPluginData, pluginHandle: thisPlugin })";
            var thisView = eval(constructor);

            //Add this view to the loadedPlugins.views[] array.
            thisPlugin.views.push(thisView);

            //Create a global reference to the primary view that should be loaded when the user
            //clicks on the left menu entry for this plugin.
            if(thisPluginData.primaryViewConstructor == thisPluginData.backboneViewNames[key]) {

              var pluginViewReference = "global.pluginView."+thisPluginData.primaryViewInstance;
              var evalStr = pluginViewReference+" = thisPlugin.views["+key+"]";
              eval(evalStr);

              //Add a menu item for this primary view.
              var tmpLi = '
 '+thisPluginData.primaryViewLabel+'
';
              var pluginLi = global.leftMenuView.$el.find('#plugin-link');
              pluginLi.parent().append(tmpLi);
            }

            //debugger;
            //loadModels();
            //callback();

          }, function(error) {
            debugger;
            callback(error);
          });

        } catch(err) {
          callback(err);
        }

      }, function(err) {
        debugger;

        if(err) {
          debugger;
          console.error('Problem with pluginView.js/loadConstructs() when trying to load Backbone Views: '+err);
        } else {
          debugger;

          //Views have been loaded. Next, load the models.
          //global.pluginView.loadModels();
        }

      });
      // ---END BACKBONE VIEWS---

    },

    //This function is called after plugin Views have been loaded. It's purpose is to load the
    //Backbone models associated with this plugin.
    loadModels: function(pluginIndex) {
      debugger;

    },

    // ---BEGIN UTILITY FUNCTIONS---

    //Dev note: I don't think this function is used any more.
    //This function returns a pointer to the global.pluginView.loadedPlugins[] element
    //that matches the directory name stored in that plugins metadata. It's useful for
    //getting the plugin constructs in a function without any scope.
    //If the loaded plugin can not be found, then this functioin returns false.
    getHandle: function(dirName) {
      try {
        debugger;

        for(var i=0; i < global.pluginView.pluginData.length; i++) {
          if(dirName == global.pluginView.pluginData[i].pluginDirName) {
            return global.pluginView.loadedPlugins[i];
          }
        }

        return false;

      } catch(err) {
          console.error('Problem in pluginView.js/getHandle(): '+err);
      }
    },

    //This function is used to retrieve the plugin index -e.g. which plugin inside
    //global.pluginView.pluginData that we're trying to deal with. It returns
    //the element inside the global.pluginView.pluginData array that matches the
    //key and script. If no match is found, it returns null.
    //This function is used to regain scope on the currently targeted plugin.
    //
    //Since this function uses text matching, it can cause a false positive when
    //text in the Backbone files are copied from the template. If this because
    //a serious issue, I might want to think of ways to refine this function.
    getPluginIndex: function(key, script) {
      //debugger;

      try {
        var thisPluginIndex = null;

        //Loop through each plugin's metadata.
        for(var i=0; i < global.pluginView.pluginData.length; i++) {

          //Loop through each element in the key field.
          var keyArray = eval('global.pluginView.pluginData[i].'+key);

          for(var j=0; j < keyArray.length; j++) {
            if(script.indexOf(keyArray[j]) > -1) {
              console.log('pluginView.js/getPluginIndex() found a match with '+keyArray[j]);
              thisPluginIndex = i;
              return thisPluginIndex;
            }
          }
        }

        if(thisPluginIndex == null) {
          debugger;
          console.error('Problem in pluginView.js/getPluginIndex(). Could not identify the view and could not find the plugin index. key = '+key+' script = '+script);
          return null;
        }

      } catch(err) {
        debugger;
        console.log('Error in getPluginIndex(): '+err);
        return null;
      }
    }

    // ---END UTILITY FUNCTIONS---

	});

  //debugger;
	return PostsView;
});<commit_msg>Importing pluginLoader.js code into pluginView.js<commit_after>/*ConnextCMS pluginView.js - This file loads plugins at run-time.*/
define([
	'jQuery-2.1.4.min',
	'underscore_1.3.3',
	'backbone_0.9.2',
  'text!../../../js/app/templates/pluginTemplate.html'
], function ($, _, Backbone, PluginTemplate) {
	'use strict';

	var PostsView = Backbone.View.extend({

		tagName:  'div',

    el: '#pluginDiv',

		template: _.template(PluginTemplate),

		// The DOM events specific to an item.
		events: {

		},

		initialize: function () {
      this.loadedPlugins = []; //An array containing all the loaded plugins and their Backbone constructs.
      this.pluginData = []; //An array containing the contents of the pluginSettings.json file (the metadata) for each plugin.
		},

    render: function () {
      //debugger;

      var thisView = this;

      this.$el.html(this.template);

      $.get('/api/plugins/list', '', function(data) {
        //debugger;

        //Error Handling
        if( (!data.success) || (data.plugins.length == 0) ) {
          return;
        }

        //Save the pluginSettings.json data
        thisView.pluginData = data.plugins; //Copy the plugin data (for all plugins) to the Plugin View
        var pluginData = data.plugins;      //Also copy the plugin data to a local variable.

        //Loop through each PLUGIN
        for(var i=0; i < pluginData.length; i++) {

          //Add a div to the DOM. This will be the div for the current plugin.
          thisView.$el.find('#pluginParentDiv').append('

');

          //Tell the plugin which div belongs to it.
          thisView.pluginData[i].divId = '#plugin'+i;

          //Prep the loadedPlugins object for this plugin with an empty object.
          var tmpObj = {};
          tmpObj.views = [];
          tmpObj.models = [];
          tmpObj.collections = [];
          thisView.loadedPlugins[i] = tmpObj;

          //Load the Backbone Views, Models, and Collections associated with this plugin.
          thisView.loadViews(i);

          thisView.loadModels(i);
        }

      });

			return this;
		},

    //This function instantiates the Backbone Views, Models, and Collections associated with a plugin.
    //It expects the plugin metadata to be passed into it. This is the data stored in the pluginSettings.json
    loadViews: function(pluginIndex) {
      //debugger;

      //Get local handles to view-level objects.
      var thisView = this;                                //Get a handle on this View.
      var thisPluginData = this.pluginData[pluginIndex];  //Plugin Metadata
      var thisPlugin = this.loadedPlugins[pluginIndex];   //Will hold the plugins Backbone constructs.

      // ---BEGIN BACKBONE VIEWS---

      //Loop through each of the backbone views for this plugin.
      //Have to use an async for loop since we making async calls to $.getScript().
      global.async.eachOf(thisPluginData.backboneViewFiles, function(value, key, callback) {
        //debugger;

        try {

          var pluginDir = '/plugins/'+thisPluginData.pluginDirName+'/';

          //Load the individual views for this plugin. Generate a promise for each view.
          var scriptPromise = $.getScript(pluginDir+value, function(data, textStatus, jqxhr) {
            //debugger;

          })
          .fail(function( jqxhr, settings, exception ) {
            debugger;

            console.error('Problem with pluginView.js/loadViews() when trying load Backbone Views: '+exception);
          });

          //When the promise resolves:
          scriptPromise.then(function(results) {
            //debugger;

            //Scope is lost at the point and a handle needs to be established on the current plugin.
            var thisPluginIndex = global.pluginView.getPluginIndex('backboneViewNames', results);
            if(thisPluginIndex == null) {
              console.error('Could not find plugin.');
              return;
            } else {
              var thisPluginData = global.pluginView.pluginData[thisPluginIndex];
              var thisPlugin = global.pluginView.loadedPlugins[thisPluginIndex];
            }

            //Create the new view.
            var constructor = "new "+thisPluginData.backboneViewNames[key]+"({el: $(thisPluginData.divId), pluginData: thisPluginData, pluginHandle: thisPlugin })";
            var thisView = eval(constructor);

            //Add this view to the loadedPlugins.views[] array.
            thisPlugin.views.push(thisView);

            //Create a global reference to the primary view that should be loaded when the user
            //clicks on the left menu entry for this plugin.
            if(thisPluginData.primaryViewConstructor == thisPluginData.backboneViewNames[key]) {

              var pluginViewReference = "global.pluginView."+thisPluginData.primaryViewInstance;
              var evalStr = pluginViewReference+" = thisPlugin.views["+key+"]";
              eval(evalStr);

              //Add a menu item for this primary view.
              var tmpLi = '
 '+thisPluginData.primaryViewLabel+'
';
              var pluginLi = global.leftMenuView.$el.find('#plugin-link');
              pluginLi.parent().append(tmpLi);
            }

            //debugger;
            //loadModels();
            //callback();

          }, function(error) {
            debugger;
            callback(error);
          });

        } catch(err) {
          callback(err);
        }

      }, function(err) {
        debugger;

        if(err) {
          debugger;
          console.error('Problem with pluginView.js/loadViews() when trying to load Backbone Views: '+err);
        } else {
          debugger;

          //Views have been loaded. Next, load the models.
          //global.pluginView.loadModels();
        }

      });
      // ---END BACKBONE VIEWS---

    },

    // ---BEGIN BACKBONE MODELS---

    //This function is called in parallel with loadViews(). It's purpose is to load the
    //Backbone models associated with this plugin.
    loadModels: function(pluginIndex) {
      debugger;

      //Get local handles to view-level objects.
      var thisView = this;                                //Get a handle on this View.
      var thisPluginData = this.pluginData[pluginIndex];  //Plugin Metadata
      var thisPlugin = this.loadedPlugins[pluginIndex];   //Will hold the plugins Backbone constructs.

      //Loop through each of the backbone views for this plugin.
      //Have to use an async for loop since we making async calls to $.getScript().
      global.async.eachOf(thisPluginData.backboneModelFiles, function(value, key, callback) {
        try {

          var pluginDir = '/plugins/'+thisPluginData.pluginDirName+'/';

          //Load the individual views for this plugin. Generate a promise for each view.
          var scriptPromise = $.getScript(pluginDir+value, function(data, textStatus, jqxhr) {
            debugger;

            //Scope is lost at the point and a handle needs to be established on the current plugin.
            var thisPluginIndex = global.pluginView.getPluginIndex('backboneViewNames', results);
            if(thisPluginIndex == null) {
              console.error('Could not find plugin.');
              return;
            } else {
              var thisPluginData = global.pluginView.pluginData[thisPluginIndex];
              var thisPlugin = global.pluginView.loadedPlugins[thisPluginIndex];
            }

            var constructor = "new "+thisPluginData.modelNames[key]+"(null,{pluginData: thisPluginData, pluginHandle: thisPlugin })";
            var thisModel = eval(constructor);

            thisPlugin.models.push(thisModel);

          })
          .fail(function( jqxhr, settings, exception ) {
            debugger;

            console.error('Problem with pluginView.js/loadModels() when trying load Backbone Models: '+exception);
            callback(exception);
          });

          //When the promise resolves:
          scriptPromise.then(function(results) {

        } catch(err) {
          callback(err);
        }

      }, function(err) {
        debugger;

        if(err) {
          debugger;
          console.error('Problem with pluginView.js/loadModels() when trying to load Backbone Models: '+err);
        } else {
          debugger;

          //Views have been loaded. Next, load the models.
          //global.pluginView.loadModels();
        }

      });
    },

    // ---END BACKBONE MODELS---

    // ---BEGIN UTILITY FUNCTIONS---

    //Dev note: I don't think this function is used any more.
    //This function returns a pointer to the global.pluginView.loadedPlugins[] element
    //that matches the directory name stored in that plugins metadata. It's useful for
    //getting the plugin constructs in a function without any scope.
    //If the loaded plugin can not be found, then this functioin returns false.
    getHandle: function(dirName) {
      try {
        debugger;

        for(var i=0; i < global.pluginView.pluginData.length; i++) {
          if(dirName == global.pluginView.pluginData[i].pluginDirName) {
            return global.pluginView.loadedPlugins[i];
          }
        }

        return false;

      } catch(err) {
          console.error('Problem in pluginView.js/getHandle(): '+err);
      }
    },

    //This function is used to retrieve the plugin index -e.g. which plugin inside
    //global.pluginView.pluginData that we're trying to deal with. It returns
    //the element inside the global.pluginView.pluginData array that matches the
    //key and script. If no match is found, it returns null.
    //This function is used to regain scope on the currently targeted plugin.
    //
    //Since this function uses text matching, it can cause a false positive when
    //text in the Backbone files are copied from the template. If this because
    //a serious issue, I might want to think of ways to refine this function.
    getPluginIndex: function(key, script) {
      //debugger;

      try {
        var thisPluginIndex = null;

        //Loop through each plugin's metadata.
        for(var i=0; i < global.pluginView.pluginData.length; i++) {

          //Loop through each element in the key field.
          var keyArray = eval('global.pluginView.pluginData[i].'+key);

          for(var j=0; j < keyArray.length; j++) {
            if(script.indexOf(keyArray[j]) > -1) {
              console.log('pluginView.js/getPluginIndex() found a match with '+keyArray[j]);
              thisPluginIndex = i;
              return thisPluginIndex;
            }
          }
        }

        if(thisPluginIndex == null) {
          debugger;
          console.error('Problem in pluginView.js/getPluginIndex(). Could not identify the view and could not find the plugin index. key = '+key+' script = '+script);
          return null;
        }

      } catch(err) {
        debugger;
        console.log('Error in getPluginIndex(): '+err);
        return null;
      }
    }

    // ---END UTILITY FUNCTIONS---

	});

  //debugger;
	return PostsView;
});<|endoftext|>