<commit_before>/*
 * Gulpfile
 * Author: Mattijs Bliek
 *
 * IMPORTANT:
 * Gulp needs to be installed globally on your system before
 * you're able to run tasks. This can be done by running:
 * `npm install -g gulp`
 *
 * -------------------------------------------------------------
 *
 * DESCRIPTION:
 * Gulp is used to manage and generate front-end assets, such as
 * css, javascript, and compressed images. You can run gulp from
 * the command line with the commands below.
 *
 * -------------------------------------------------------------
 *
 * TODO:
 * - CSS sourcemaps are not rendering properly
 * - Either concat libs.js and main.js for production, or employ a module
 *   loader to generate various builds
 *
 * -------------------------------------------------------------
 *
 * COMMANDS:
 *
 * Generate a build for an environment:
 * `gulp`
 *
 * Arguments:
 * --e=environment (development|staging|production)
 * --skipImages (don't build compressed images)
 *
 * Generate images for an environment:
 * `gulp images`
 *
 * Watch files and run a server (use for development only):
 * `gulp watch`
 *
 * -------------------------------------------------------------
 */

var gulp           = require('gulp'),
	autoprefixer   = require('gulp-autoprefixer'),
	gutil          = require('gulp-util'),
	concat         = require('gulp-concat'),
	jshint         = require('gulp-jshint'),
	jshintStylish  = require('jshint-stylish'),
	imagemin       = require('gulp-imagemin'),
    minifycss      = require('gulp-minify-css'),
    urlAdjuster    = require('gulp-css-url-adjuster'),
	pxtorem        = require('gulp-pxtorem'),
	modernizr      = require('gulp-modernizr'),
	sass           = require('gulp-sass'),
	browserSync    = require('browser-sync'),
	mainBowerFiles = require('main-bower-files'),
	uglify         = require('gulp-uglify'),
	sourcemaps     = require('gulp-sourcemaps'),
	scsslint       = require('gulp-scss-lint'),
	gulpif         = require('gulp-if'),
	argv           = require('yargs').argv,
	sh             = require('execSync');

var semver;
var paths = {};
var ENV = argv.e ? argv.e : 'development';

function getShellOutput(command) {
	result = sh.exec(command);
    if (result.stderr) {
		handleError('Error getting shell output: ' + result.stderr);
        gutil.beep();
    }
    // Do a replace because of newline in shell output
    return result.stdout.replace(/\s?$/, '');
};

function getConfigValue(value) {
	if (!value) {
		handleError('Can\'t get undefined config value');
		return;
	}
	var command = 'php ' + __dirname + '/../golem/scripts/golem.php config get ' + value + ' --e=' + ENV;
	return getShellOutput(command);
}

function constructPaths() {
	paths.public      = 'public';

	paths.js          = paths.public + '/js';
	paths.jsSrc       = paths.js     + '/src';
	paths.jsBuild     = paths.public + getConfigValue('assets.js.root') + '/' + semver;

	paths.css         = paths.public + '/css';
	paths.cssSrc      = paths.public + getConfigValue('assets.sass.root');
	paths.cssBuild    = paths.public + getConfigValue('assets.css.root') + '/' + semver;

	paths.imgSrc      = paths.css      + '/img';
	paths.imgBuild    = paths.cssBuild + '/img';
	paths.cdn         = getConfigValue('cdn.domain');
	paths.cdnCss      = getConfigValue('assets.css.root') + '/' + semver;

	return paths;
};

function handleError (error) {
	gutil.log(gutil.colors.red(error.toString()));
	this.emit('end');
}

gulp.task('init', function() {
	semver = getShellOutput('semver');
	domain = getConfigValue('app.domain');
	cdnType  = getConfigValue('cdn.type');
	paths  = constructPaths();

	gutil.log(gutil.colors.green('-----------------'));
	gutil.log(gutil.colors.green('Semver: ' + semver));
	gutil.log(gutil.colors.green('Environment: ' + ENV));
	gutil.log(gutil.colors.green('-----------------'));
});

gulp.task('browser-sync', ['sass-ie', 'sass-cms', 'sass', 'javascript'], function() {
	if (!domain) {
		handleError('Could not get ' + ENV + ' domain from application/configs/app.ini');
	}
	browserSync({
		proxy: domain,
		open: false,
		notify: {
		     styles: [
				"display: none",
				"padding: 15px",
				"font-family: sans-serif",
				"position: fixed",
				"font-size: 0.9em",
				"z-index: 9999",
				"right: 0px",
				"bottom: 0px",
				"border-top-left-radius: 5px",
				"background-color: rgb(27, 32, 50)",
				"margin: 0",
				"color: white",
				"text-align: center"
	        ]
	    }
	});
});

gulp.task('sass', ['scss-lint'], function () {

	var pxtoremOptions = {
		root_value: 10,
		unit_precision: 5,
		prop_white_list: [
			'font',
			'font-size',
		],
		replace: false,
		media_query: false
	},
	postcssOptions = {
		map: true
	};

    gutil.log(gutil.colors.green('Building css to ' + paths.cssBuild));
    return gulp.src([paths.cssSrc + '/base.scss'])
		.pipe(sass({
			onError: browserSync.notify
		})).on('error', handleError)
		.pipe(pxtorem(pxtoremOptions, postcssOptions))
		.pipe(autoprefixer('>5%', 'last 3 versions', 'safari 5', 'ie 9', 'opera 12.1'))
		.pipe(gulpif(ENV != 'development' && cdnType != 'local', urlAdjuster({
			// hacky slashes are necessary because one slash is stripped by urlAdjuster
			prepend: 'http:///' + paths.cdn + paths.cdnCss + '/',
			append: '?v=' + semver
		})))
		.pipe(gulpif(ENV != 'development', minifycss()))
        .pipe(gulp.dest(paths.cssBuild))
		.pipe(browserSync.reload({stream:true}))
});

gulp.task('sass-cms', function() {
    return gulp.src(paths.cssSrc + '/cms.scss')
		.pipe(sass()).on('error', handleError)
		.pipe(gulpif(ENV != 'development', minifycss()))
		.pipe(gulp.dest(paths.cssBuild));
});

gulp.task('sass-ie', function() {
    return gulp.src(paths.cssSrc + '/ie-old.scss')
		.pipe(sass()).on('error', handleError)
		.pipe(gulpif(ENV != 'development', minifycss()))
		.pipe(gulp.dest(paths.cssBuild));
});

gulp.task('scss-lint', function() {
	gulp.src(paths.cssSrc + '/**/*.scss')
		.pipe(scsslint({'config': __dirname + '/.scss-lint.yml'})).on('error', handleError);
});

gulp.task('javascript', ['jshint', 'bower-concat'], function() {
    gutil.log(gutil.colors.green('Building js to ' + paths.jsBuild));
    return gulp.src([
			paths.jsSrc + '/../garp/front/styling.js',
			paths.jsSrc + '/../garp/front/flashmessage.js',
			paths.jsSrc + '/../garp/front/cookies.js',
			paths.jsSrc + '/**/*.js',
		])
		.pipe(gulpif(ENV == 'development', sourcemaps.init()))
		.pipe(concat('main.js'))
		.pipe(gulpif(ENV != 'development', uglify())).on('error', handleError)
		.pipe(gulpif(ENV == 'development', sourcemaps.write()))
		.pipe(gulp.dest(paths.jsBuild))
		.pipe(browserSync.reload({stream:true}))
    ;
});

gulp.task('javascript-cms', function() {
    return gulp.src(require('./garp/public/js/cmsBuildStack.js').stack)
		.pipe(concat('cms.js'))
		.pipe(gulpif(ENV != 'development', uglify())).on('error', handleError)
		.pipe(gulp.dest(paths.jsBuild))
    ;
});

gulp.task('javascript-models', function() {
    return gulp.src([
			paths.jsSrc + '/../garp/models/*.js',
			paths.jsSrc + '/../models/*.js',
		])
		.pipe(concat('extended-models.js'))
		.pipe(uglify()).on('error', handleError)
		.pipe(gulp.dest(paths.jsBuild))
    ;
});

gulp.task('bower-concat', function() {
	if (mainBowerFiles().length == 0) {
		gutil.log('No bower dependencies');
		return;
	}
    return gulp.src(mainBowerFiles())
    .pipe(concat('libs.js'))
    .pipe(uglify())
    .pipe(gulp.dest(paths.jsBuild));
});

gulp.task('jshint', function () {
    gulp.src(paths.jsSrc + '/**/*.js')
        .pipe(jshint('.jshintrc'))
        .pipe(jshint.reporter('jshint-stylish'));
});

gulp.task('modernizr', ['sass', 'javascript'], function() {
  return gulp.src([paths.cssBuild + '/base.css', paths.jsBuild + '/main.js'])
    .pipe(modernizr('modernizr.js')).on('error', handleError)
    .pipe(uglify())
    .pipe(gulp.dest(paths.jsBuild))
});

gulp.task('images', ['init'], function () {
	if (argv.skipImages) {
		return;
	}
	gutil.log(gutil.colors.green('Building images to ' + paths.imgBuild));
    return gulp.src(paths.imgSrc + '/*.{png,gif,jpg,svg}')
        .pipe(imagemin({
            progressive: true,
            svgoPlugins: [{removeViewBox: false}]
        })).on('error', handleError)
        .pipe(gulp.dest(paths.imgBuild));
});

gulp.task('watch', ['default', 'browser-sync'], function() {
	gulp.watch([paths.cssSrc + '/**/*.scss', '!**/cms.scss'], ['sass']);
	gulp.watch(paths.cssSrc + '/**/cms.scss', ['sass-cms']);
	gulp.watch(paths.jsSrc + '/**/*.js', ['javascript']);
	gulp.watch(paths.imgSrc + '/**/*.{gif,jpg,svg,png}', ['images']);
    gulp.watch('application/modules/default/**/*.{phtml, php}', browserSync.reload);
});

gulp.task('default', [
	'init',
	'sass-ie',
	'sass-cms',
	'sass',
	'javascript-cms',
	'javascript-models',
	'javascript',
	'images',
	'modernizr'
]);
<commit_msg>Added CDN type to Gulp output;<commit_after>/*
 * Gulpfile
 * Author: Mattijs Bliek
 *
 * IMPORTANT:
 * Gulp needs to be installed globally on your system before
 * you're able to run tasks. This can be done by running:
 * `npm install -g gulp`
 *
 * -------------------------------------------------------------
 *
 * DESCRIPTION:
 * Gulp is used to manage and generate front-end assets, such as
 * css, javascript, and compressed images. You can run gulp from
 * the command line with the commands below.
 *
 * -------------------------------------------------------------
 *
 * TODO:
 * - CSS sourcemaps are not rendering properly
 * - Either concat libs.js and main.js for production, or employ a module
 *   loader to generate various builds
 *
 * -------------------------------------------------------------
 *
 * COMMANDS:
 *
 * Generate a build for an environment:
 * `gulp`
 *
 * Arguments:
 * --e=environment (development|staging|production)
 * --skipImages (don't build compressed images)
 *
 * Generate images for an environment:
 * `gulp images`
 *
 * Watch files and run a server (use for development only):
 * `gulp watch`
 *
 * -------------------------------------------------------------
 */

var gulp           = require('gulp'),
	autoprefixer   = require('gulp-autoprefixer'),
	gutil          = require('gulp-util'),
	concat         = require('gulp-concat'),
	jshint         = require('gulp-jshint'),
    jshintStylish  = require('jshint-stylish'),
    imagemin       = require('gulp-imagemin'),
    minifycss      = require('gulp-minify-css'),
    urlAdjuster    = require('gulp-css-url-adjuster'),
	pxtorem        = require('gulp-pxtorem'),
	modernizr      = require('gulp-modernizr'),
	sass           = require('gulp-sass'),
	browserSync    = require('browser-sync'),
	mainBowerFiles = require('main-bower-files'),
	uglify         = require('gulp-uglify'),
	sourcemaps     = require('gulp-sourcemaps'),
	scsslint       = require('gulp-scss-lint'),
	gulpif         = require('gulp-if'),
	argv           = require('yargs').argv,
	sh             = require('execSync');

var semver;
var paths = {};
var ENV = argv.e ? argv.e : 'development';

function getShellOutput(command) {
	result = sh.exec(command);
    if (result.stderr) {
		handleError('Error getting shell output: ' + result.stderr);
        gutil.beep();
    }
    // Do a replace because of newline in shell output
    return result.stdout.replace(/\s?$/, '');
};

function getConfigValue(value) {
	if (!value) {
		handleError('Can\'t get undefined config value');
		return;
	}
	var command = 'php ' + __dirname + '/../golem/scripts/golem.php config get ' + value + ' --e=' + ENV;
	return getShellOutput(command);
}

function constructPaths() {
	paths.public      = 'public';

	paths.js          = paths.public + '/js';
	paths.jsSrc       = paths.js     + '/src';
	paths.jsBuild     = paths.public + getConfigValue('assets.js.root') + '/' + semver;

	paths.css         = paths.public + '/css';
	paths.cssSrc      = paths.public + getConfigValue('assets.sass.root');
	paths.cssBuild    = paths.public + getConfigValue('assets.css.root') + '/' + semver;

	paths.imgSrc      = paths.css      + '/img';
	paths.imgBuild    = paths.cssBuild + '/img';
	paths.cdn         = getConfigValue('cdn.domain');
	paths.cdnCss      = getConfigValue('assets.css.root') + '/' + semver;

	return paths;
};

function handleError (error) {
	gutil.log(gutil.colors.red(error.toString()));
	this.emit('end');
}

gulp.task('init', function() {
	semver = getShellOutput('semver');
	domain = getConfigValue('app.domain');
	cdnType  = getConfigValue('cdn.type');
	paths  = constructPaths();

	gutil.log(gutil.colors.green('-----------------'));
	gutil.log(gutil.colors.green('Semver: ' + semver));
	gutil.log(gutil.colors.green('Environment: ' + ENV));
	gutil.log(gutil.colors.green('CDN type: ' + cdnType));
	gutil.log(gutil.colors.green('-----------------'));
});

gulp.task('browser-sync', ['sass-ie', 'sass-cms', 'sass', 'javascript'], function() {
	if (!domain) {
		handleError('Could not get ' + ENV + ' domain from application/configs/app.ini');
	}
	browserSync({
		proxy: domain,
		open: false,
		notify: {
		     styles: [
				"display: none",
				"padding: 15px",
				"font-family: sans-serif",
				"position: fixed",
				"font-size: 0.9em",
				"z-index: 9999",
				"right: 0px",
				"bottom: 0px",
				"border-top-left-radius: 5px",
				"background-color: rgb(27, 32, 50)",
				"margin: 0",
				"color: white",
				"text-align: center"
	        ]
	    }
	});
});

gulp.task('sass', ['scss-lint'], function () {

	var pxtoremOptions = {
		root_value: 10,
		unit_precision: 5,
		prop_white_list: [
			'font',
			'font-size',
		],
		replace: false,
		media_query: false
	},
	postcssOptions = {
		map: true
	};

    gutil.log(gutil.colors.green('Building css to ' + paths.cssBuild));
    return gulp.src([paths.cssSrc + '/base.scss'])
		.pipe(sass({
			onError: browserSync.notify
		})).on('error', handleError)
		.pipe(pxtorem(pxtoremOptions, postcssOptions))
		.pipe(autoprefixer('>5%', 'last 3 versions', 'safari 5', 'ie 9', 'opera 12.1'))
		.pipe(gulpif(ENV != 'development' && cdnType != 'local', urlAdjuster({
			// hacky slashes are necessary because one slash is stripped by urlAdjuster
			prepend: 'http:///' + paths.cdn + paths.cdnCss + '/',
			append: '?v=' + semver
		})))
		.pipe(gulpif(ENV != 'development', minifycss()))
        .pipe(gulp.dest(paths.cssBuild))
		.pipe(browserSync.reload({stream:true}))
});

gulp.task('sass-cms', function() {
    return gulp.src(paths.cssSrc + '/cms.scss')
		.pipe(sass()).on('error', handleError)
		.pipe(gulpif(ENV != 'development', minifycss()))
		.pipe(gulp.dest(paths.cssBuild));
});

gulp.task('sass-ie', function() {
    return gulp.src(paths.cssSrc + '/ie-old.scss')
		.pipe(sass()).on('error', handleError)
		.pipe(gulpif(ENV != 'development', minifycss()))
		.pipe(gulp.dest(paths.cssBuild));
});

gulp.task('scss-lint', function() {
	gulp.src(paths.cssSrc + '/**/*.scss')
		.pipe(scsslint({'config': __dirname + '/.scss-lint.yml'})).on('error', handleError);
});

gulp.task('javascript', ['jshint', 'bower-concat'], function() {
    gutil.log(gutil.colors.green('Building js to ' + paths.jsBuild));
    return gulp.src([
			paths.jsSrc + '/../garp/front/styling.js',
			paths.jsSrc + '/../garp/front/flashmessage.js',
			paths.jsSrc + '/../garp/front/cookies.js',
			paths.jsSrc + '/**/*.js',
		])
		.pipe(gulpif(ENV == 'development', sourcemaps.init()))
		.pipe(concat('main.js'))
		.pipe(gulpif(ENV != 'development', uglify())).on('error', handleError)
		.pipe(gulpif(ENV == 'development', sourcemaps.write()))
		.pipe(gulp.dest(paths.jsBuild))
		.pipe(browserSync.reload({stream:true}))
    ;
});

gulp.task('javascript-cms', function() {
    return gulp.src(require('./garp/public/js/cmsBuildStack.js').stack)
		.pipe(concat('cms.js'))
		.pipe(gulpif(ENV != 'development', uglify())).on('error', handleError)
		.pipe(gulp.dest(paths.jsBuild))
    ;
});

gulp.task('javascript-models', function() {
    return gulp.src([
			paths.jsSrc + '/../garp/models/*.js',
			paths.jsSrc + '/../models/*.js',
		])
		.pipe(concat('extended-models.js'))
		.pipe(uglify()).on('error', handleError)
		.pipe(gulp.dest(paths.jsBuild))
    ;
});

gulp.task('bower-concat', function() {
	if (mainBowerFiles().length == 0) {
		gutil.log('No bower dependencies');
		return;
	}
    return gulp.src(mainBowerFiles())
    .pipe(concat('libs.js'))
    .pipe(uglify())
    .pipe(gulp.dest(paths.jsBuild));
});

gulp.task('jshint', function () {
    gulp.src(paths.jsSrc + '/**/*.js')
        .pipe(jshint('.jshintrc'))
        .pipe(jshint.reporter('jshint-stylish'));
});

gulp.task('modernizr', ['sass', 'javascript'], function() {
  return gulp.src([paths.cssBuild + '/base.css', paths.jsBuild + '/main.js'])
    .pipe(modernizr('modernizr.js')).on('error', handleError)
    .pipe(uglify())
    .pipe(gulp.dest(paths.jsBuild))
});

gulp.task('images', ['init'], function () {
	if (argv.skipImages) {
		return;
	}
	gutil.log(gutil.colors.green('Building images to ' + paths.imgBuild));
    return gulp.src(paths.imgSrc + '/*.{png,gif,jpg,svg}')
        .pipe(imagemin({
            progressive: true,
            svgoPlugins: [{removeViewBox: false}]
        })).on('error', handleError)
        .pipe(gulp.dest(paths.imgBuild));
});

gulp.task('watch', ['default', 'browser-sync'], function() {
	gulp.watch([paths.cssSrc + '/**/*.scss', '!**/cms.scss'], ['sass']);
	gulp.watch(paths.cssSrc + '/**/cms.scss', ['sass-cms']);
	gulp.watch(paths.jsSrc + '/**/*.js', ['javascript']);
	gulp.watch(paths.imgSrc + '/**/*.{gif,jpg,svg,png}', ['images']);
    gulp.watch('application/modules/default/**/*.{phtml, php}', browserSync.reload);
});

gulp.task('default', [
	'init',
	'sass-ie',
	'sass-cms',
	'sass',
	'javascript-cms',
	'javascript-models',
	'javascript',
	'images',
	'modernizr'
]);
<|endoftext|>


<commit_before>/**
 * @class  	WebAlloy
 * @author  Flavio De Stefano <flavio.destefano@caffeinalab.com>
 *
 * This is an entire µ-web-framework to write Titanium-Alloy apps in HTML/CSS/JS, without native objects.
 *
 * The unique method `WebAlloy.createView` create a WebView with static html inside.
 *
 * In this **special** webview, you have some *helpers* that helps you to achieve the final results:
 *
 * * **underscore** template system
 * * **jQuery** as a DOM lib.
 *
 * To work with WebAlloy, you have to replicate the exact structure in the app directory (Alloy).
 *
 * ### Globals
 *
 * #### app.css
 * Global CSS included in each view.
 *
 * #### app.jslocal
 * Global JS included in each view.
 *
 * ### MVC specific
 *
 *	#### controllers/foo.jslocal
 *	Javascript file included in the specific controller, after app.jslocal and jquery.jslocal
 *
 * #### views/foo.tpl
 * HTML/TPL (underscore templating system) file that is parsed and written in the static HTML.
 *
 * #### styles/foo.css
 * CSS file included in the specific controller.
 *
 * When you have replicated this structure, you can just call:
 *
 * ```
 * WebAlloy.createView({
 * 	name: 'foo',
 * 	webdata: { ... },
 * 	...
 * });
 * ```
 *
 * The **name** arg is to specific the files to load.
 *
 * The **webdata** object is passed to the HTML file and rendered.
 *
 *	All the other arguments are Ti-UI specific for the classic WebView.
 *
 * ### HTML output
 *
 * So, the final result is an HTML string passed to the WebView, like this:
 *
 * ```
 * <!DOCTYPE html>
 * <html>
 * 	<head>
 * 		... metas ...
 * 		<style>{{ app.css }}</style>
 * 		<style>{{ your_controller.css }}</style>
 * 	</head>
 * 	<body>
 * 		<div id="main">
 * 			{{ controller.tpl (rendered with webdata argument) }}
 * 		</div>
 * 		<script>{{ jquery.jslocal }}</script>
 * 		<script>{{ app.jslocal }}</script>
 * 		<script>{{ controller.jslocal }}</script>
 * 	</body>
 * </html>
 * ```
 *
 * ### WebView additional method
 *
 * Basically, you can interact with DOM elements with `evalJS`.
 *
 * There are some proxy methods designed to interact directly:
 *
 * #### render({ data })
 *
 * Re-render the template with new data passed.
 *
 * #### call(...)
 *
 * Call a function in the WebView.
 *
 * For example, `$.wv.call('foo', 1, 2, {x:1})` will be converted to js in `foo(1, 2, {x:1})`.
 *
 * #### $(selector).call(...)
 *
 * Call a function in a DOM-RAW object.
 *
 * #### $(selector).get(...)
 *
 * Get a property of a DOM-RAW object.
 *
 * #### $(selector).set(...)
 *
 * Set a property of a DOM-RAW object.
 *
 */

function embedCSS(f) {
	var file = Ti.Filesystem.getFile(f);
	if (!file.exists()) return '';
	var read = file.read().text; file = null;
	return '';
}

function embedJS(f) {
	var file = Ti.Filesystem.getFile(f);
	if (!file.exists()) return '';
	var read = file.read().text; file = null;
	return '';
}

/**
 * @method createView
 * @param  {Object} args Arguments for the view.
 * @return {Ti.UI.WebView}
 */
exports.createView = function(args) {
	var $ui = Ti.UI.createWebView(_.extend({
		disableBounce: true,
		backgroundColor: "transparent"
	}, args));

	var html = '<!DOCTYPE html>';
	html += '<meta charset="utf-8" /><meta name="viewport" content="initial-scale=1.0; maximum-scale=1.0; user-scalable=no;" />';
	html += embedCSS('web/app.css') + embedCSS('web/styles/'+args.name+'.css');
	html += '
';

	$ui.tpl = _.template(Ti.Filesystem.getFile('web/views/'+args.name+'.tpl').read().text);
	html += $ui.tpl(args.webdata);

	html += '
';
	html += embedJS('web/jquery.jslocal') + embedJS('web/app.jslocal') + embedJS('web/controllers/'+args.name+'.jslocal');
	html += '';

	$ui.setHtml(html);
	html = null;

	$ui._ = function(js) {
		return $ui.evalJS(js);
	};

	$ui.call = function() {
		var args = _.map(Array.prototype.slice.call(arguments, 1), function(a) { return JSON.stringify(a); });
		return $ui._( arguments[0] + '(' + args.join(',') + ')' );
	};

	$ui.$ = function(selector) {
		return {
			call: function() {
				var args = _.map(Array.prototype.slice.call(arguments, 1), function(a) { return JSON.stringify(a); });
				return $ui._( 'document.querySelector("' + selector + '").' + arguments[0] + '(' + args.join(',') + ')' );
			},
			get: function(name) {
				return $ui._( 'document.querySelector("' + selector + '").' + name );
			},
			set: function(name, value) {
				return $ui._( 'document.querySelector("' + selector + '").' + name + ' = ' + JSON.stringify(value) );
			}
		};
	};

	$ui.render = function(data) {
		$ui.$('#main').set('innerHTML', $ui.tpl(data));
	};

	return $ui;
};<commit_msg>libs/**<commit_after>/**
 * @class  	WebAlloy
 * @author  Flavio De Stefano <flavio.destefano@caffeinalab.com>
 *
 * This is an entire µ-web-framework to write Titanium-Alloy apps in HTML/CSS/JS, without native objects.
 *
 * The unique method `WebAlloy.createView` create a WebView with static html inside.
 *
 * To work with WebAlloy, you have to replicate the exact structure in the app directory (Alloy).
 *
 * ### Globals
 *
 * #### app.css
 * Global CSS included in each view.
 *
 * #### app.jslocal
 * Global JS included in each view.
 *
 *	#### controllers/foo.jslocal
 *	Javascript file included in the specific controller, after app.jslocal and jquery.jslocal
 *
 * #### views/foo.tpl
 * HTML/TPL (underscore templating system) file that is parsed and written in the static HTML.
 *
 * #### styles/foo.css
 * CSS file included in the specific controller.
 *
 * ### lib/**.jslocal
 * Put your jslocal files here, they are automatically appended at the end of the HTML.
 *
 * When you have replicated this structure, you can just call:
 *
 * ```
 * WebAlloy.createView({
 * 	name: 'foo',
 * 	webdata: { ... },
 * 	...
 * });
 * ```
 *
 * The **name** arg is to specific the files to load.
 *
 * The **webdata** object is passed to the HTML file and rendered with the Undescore template system.
 *
 *	All the other arguments are Ti-UI specific for the classic WebView.
 *
 * ### HTML output
 *
 * So, the final result is an HTML string passed to the WebView, like this:
 *
 * ```
 * <!DOCTYPE html>
 * <html>
 * 	<head>
 * 		... metas ...
 * 		<style>{{ app.css }}</style>
 * 		<style>{{ your_controller.css }}</style>
 * 	</head>
 * 	<body>
 * 		<div id="main">
 * 			{{ controller.tpl (rendered in undescore with webdata argument) }}
 * 		</div>
 * 		<script>{{ lib/**.jslocal }}</script>
 * 		<script>{{ app.jslocal }}</script>
 * 		<script>{{ controller.jslocal }}</script>
 * 	</body>
 * </html>
 * ```
 *
 * ### WebView additional method
 *
 * Basically, you can interact with DOM elements with `evalJS`.
 *
 * There are some proxy methods designed to interact directly:
 *
 * #### render({ data })
 *
 * Re-render the template with new data passed.
 *
 * #### call(...)
 *
 * Call a function in the WebView.
 *
 * For example, `$.wv.call('foo', 1, 2, {x:1})` will be converted to js in `foo(1, 2, {x:1})`.
 *
 * #### $(selector).call(...)
 *
 * Call a function in a DOM-RAW object.
 *
 * #### $(selector).get(...)
 *
 * Get a property of a DOM-RAW object.
 *
 * #### $(selector).set(...)
 *
 * Set a property of a DOM-RAW object.
 *
 */

/**
 * * **minify**: Minify all CSS/JS. Default: ENV_PRODUCTION
 * @type {Object}
 */
var config = _.extend({
	minify: ENV_PRODUCTION
}, Alloy.CFG.T.weballoy);
exports.config = config;

var libDir = [];

function minify(content) {
	if (!config.minify) {
		return content;
	}

	content = content.replace( /\/\*(?:(?!\*\/)[\s\S])*\*\/|[\r\n\t]+/g, '' );
	content = content.replace( / {2,}/g, ' ' );
	content = content.replace( / ([{:}]) /g, '$1' );
	content = content.replace( /([;,]) /g, '$1' );
	content = content.replace( / !/g, '!' );
	return content;
}

function embedCSS(f) {
	var file = Ti.Filesystem.getFile(f);
	if (!file.exists()) return '';
	var read = minify(file.read().text);
	file = null;
	return '';
}

function embedJS(f) {
	var file = Ti.Filesystem.getFile(f);
	if (!file.exists()) return '';
	var read = minify(file.read().text);
	file = null;
	return '';
}

/**
 * @method createView
 * @param  {Object} args Arguments for the view.
 * @return {Ti.UI.WebView}
 */
exports.createView = function(args) {
	var $ui = Ti.UI.createWebView(_.extend({
		disableBounce: true,
		backgroundColor: "transparent"
	}, args));

	// Include head (styles)
	var html = '<!DOCTYPE html>';
	html += '';
	html += '<meta charset="utf-8" />';
	html += '<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=no;" />';

	html += embedCSS('web/app.css');
	html += embedCSS('web/styles/'+args.name+'.css');

	html += '';

	// Include template
	html += '
';
	var tplf = Ti.Filesystem.getFile('web/views/'+args.name+'.tpl');
	if (tplf.exists()) {
		$ui.tpl = _.template(tplf.read().text);
		html += $ui.tpl(args.webdata);
	} else {
		Ti.API.warn("WebAlloy: no view found ["+args.name+"]");
	}
	tplf = null;
	html += '
';

	// Include libs
	_.each(libDir, function(js) {
		html += embedJS(js);
	});

	// Include footer
	html += embedJS('web/app.jslocal');
	html += embedJS('web/controllers/'+args.name+'.jslocal');
	html += '';

	$ui.setHtml(html);
	html = null;

	$ui._ = function(js) {
		return $ui.evalJS(js);
	};

	$ui.call = function() {
		var args = _.map(Array.prototype.slice.call(arguments, 1), function(a) { return JSON.stringify(a); });
		return $ui._( arguments[0] + '(' + args.join(',') + ')' );
	};

	$ui.$ = function(selector) {
		return {
			call: function() {
				var args = _.map(Array.prototype.slice.call(arguments, 1), function(a) { return JSON.stringify(a); });
				return $ui._( 'document.querySelector("' + selector + '").' + arguments[0] + '(' + args.join(',') + ')' );
			},
			get: function(name) {
				return $ui._( 'document.querySelector("' + selector + '").' + name );
			},
			set: function(name, value) {
				return $ui._( 'document.querySelector("' + selector + '").' + name + ' = ' + JSON.stringify(value) );
			}
		};
	};

	$ui.render = function(data) {
		$ui.$('#main').set('innerHTML', $ui.tpl(data));
	};

	return $ui;
};

(function init() {

	_.each(Ti.Filesystem.getFile('web/lib').getDirectoryListing(), function(js) {
		libDir.push('web/lib/'+js);
	});

})();<|endoftext|>


<commit_before>/**
 * Crowi context class for client
 */

import axios from 'axios'
import io from 'socket.io-client'

export default class Crowi {
  constructor(context, window) {
    this.context = context
    this.config = {}
    this.csrfToken = context.csrfToken
    this.setUser(context.user)

    this.window = window
    this.location = window.location || {}
    this.document = window.document || {}
    this.localStorage = window.localStorage || {}

    this.fetchUsers = this.fetchUsers.bind(this)
    this.apiGet = this.apiGet.bind(this)
    this.apiPost = this.apiPost.bind(this)
    this.apiRequest = this.apiRequest.bind(this)

    this.users = []
    this.userByName = {}
    this.userById = {}
    this.draft = {}

    this.recoverData()

    this.socket = io({
      transports: ['websocket'],
    })
  }

  getContext() {
    return context
  }

  setConfig(config) {
    this.config = config
  }

  getConfig() {
    return this.config
  }

  setUser(user) {
    const { id = '', name = '' } = user || {}
    this.user = { id, name }
  }

  getUser() {
    return this.user
  }

  getWebSocket() {
    return this.socket
  }

  recoverData() {
    const keys = ['userByName', 'userById', 'users', 'draft']

    keys.forEach(key => {
      if (this.localStorage[key]) {
        try {
          this[key] = JSON.parse(this.localStorage[key])
        } catch (e) {
          this.localStorage.removeItem(key)
        }
      }
    })
  }

  fetchUsers() {
    const interval = 1000 * 60 * 15 // 15min
    const currentTime = new Date()
    if (this.localStorage.lastFetched && interval > currentTime - new Date(this.localStorage.lastFetched)) {
      return
    }

    this.apiGet('/users.list', {})
      .then(data => {
        this.users = data.users
        this.localStorage.users = JSON.stringify(data.users)

        let userByName = {}
        let userById = {}
        for (let i = 0; i < data.users.length; i++) {
          const user = data.users[i]
          userByName[user.username] = user
          userById[user._id] = user
        }
        this.userByName = userByName
        this.localStorage.userByName = JSON.stringify(userByName)

        this.userById = userById
        this.localStorage.userById = JSON.stringify(userById)

        this.localStorage.lastFetched = new Date()
      })
      .catch(err => {
        this.localStorage.removeItem('lastFetched')
        // ignore errors
      })
  }

  clearDraft(path) {
    delete this.draft[path]
    this.localStorage.draft = JSON.stringify(this.draft)
  }

  saveDraft(path, body) {
    this.draft[path] = body
    this.localStorage.draft = JSON.stringify(this.draft)
  }

  findDraft(path) {
    if (this.draft && this.draft[path]) {
      return this.draft[path]
    }

    return null
  }

  findUserById(userId) {
    if (this.userById && this.userById[userId]) {
      return this.userById[userId]
    }

    return null
  }

  findUserByIds(userIds) {
    let users = []
    for (let userId of userIds) {
      let user = this.findUserById(userId)
      if (user) {
        users.push(user)
      }
    }

    return users
  }

  findUser(username) {
    if (this.userByName && this.userByName[username]) {
      return this.userByName[username]
    }

    return null
  }

  async apiGet(path, params = {}) {
    return this.apiRequest('get', path, { params })
  }

  async apiPost(path, params = {}) {
    if (!params._csrf) {
      params._csrf = this.csrfToken
    }

    return this.apiRequest('post', path, params)
  }

  async apiRequest(method, path, params) {
    const createError = (message, info = {}) => {
      let error = new Error(message)
      error.info = info
      return error
    }
    const { data } = await axios[method](`/_api${path}`, params).catch(function() {
      throw createError('Error')
    })
    const { ok, error, info } = data
    if (ok) {
      return data
    }
    throw createError(error, info)
  }

  static escape(html, encode) {
    return html
      .replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&')
      .replace(/</g, '<')
      .replace(/>/g, '>')
      .replace(/"/g, '"')
      .replace(/'/g, ''')
  }

  static unescape(html) {
    return html.replace(/&([#\w]+);/g, function(_, n) {
      n = n.toLowerCase()
      if (n === 'colon') return ':'
      if (n.charAt(0) === '#') {
        return n.charAt(1) === 'x' ? String.fromCharCode(parseInt(n.substring(2), 16)) : String.fromCharCode(+n.substring(1))
      }
      return ''
    })
  }
}
<commit_msg>Fix a lint error<commit_after>/**
 * Crowi context class for client
 */

import axios from 'axios'
import io from 'socket.io-client'

export default class Crowi {
  constructor(context, window) {
    this.context = context
    this.config = {}
    this.csrfToken = context.csrfToken
    this.setUser(context.user)

    this.window = window
    this.location = window.location || {}
    this.document = window.document || {}
    this.localStorage = window.localStorage || {}

    this.fetchUsers = this.fetchUsers.bind(this)
    this.apiGet = this.apiGet.bind(this)
    this.apiPost = this.apiPost.bind(this)
    this.apiRequest = this.apiRequest.bind(this)

    this.users = []
    this.userByName = {}
    this.userById = {}
    this.draft = {}

    this.recoverData()

    this.socket = io({
      transports: ['websocket'],
    })
  }

  getContext() {
    return this.context
  }

  setConfig(config) {
    this.config = config
  }

  getConfig() {
    return this.config
  }

  setUser(user) {
    const { id = '', name = '' } = user || {}
    this.user = { id, name }
  }

  getUser() {
    return this.user
  }

  getWebSocket() {
    return this.socket
  }

  recoverData() {
    const keys = ['userByName', 'userById', 'users', 'draft']

    keys.forEach(key => {
      if (this.localStorage[key]) {
        try {
          this[key] = JSON.parse(this.localStorage[key])
        } catch (e) {
          this.localStorage.removeItem(key)
        }
      }
    })
  }

  fetchUsers() {
    const interval = 1000 * 60 * 15 // 15min
    const currentTime = new Date()
    if (this.localStorage.lastFetched && interval > currentTime - new Date(this.localStorage.lastFetched)) {
      return
    }

    this.apiGet('/users.list', {})
      .then(data => {
        this.users = data.users
        this.localStorage.users = JSON.stringify(data.users)

        let userByName = {}
        let userById = {}
        for (let i = 0; i < data.users.length; i++) {
          const user = data.users[i]
          userByName[user.username] = user
          userById[user._id] = user
        }
        this.userByName = userByName
        this.localStorage.userByName = JSON.stringify(userByName)

        this.userById = userById
        this.localStorage.userById = JSON.stringify(userById)

        this.localStorage.lastFetched = new Date()
      })
      .catch(err => {
        this.localStorage.removeItem('lastFetched')
        // ignore errors
      })
  }

  clearDraft(path) {
    delete this.draft[path]
    this.localStorage.draft = JSON.stringify(this.draft)
  }

  saveDraft(path, body) {
    this.draft[path] = body
    this.localStorage.draft = JSON.stringify(this.draft)
  }

  findDraft(path) {
    if (this.draft && this.draft[path]) {
      return this.draft[path]
    }

    return null
  }

  findUserById(userId) {
    if (this.userById && this.userById[userId]) {
      return this.userById[userId]
    }

    return null
  }

  findUserByIds(userIds) {
    let users = []
    for (let userId of userIds) {
      let user = this.findUserById(userId)
      if (user) {
        users.push(user)
      }
    }

    return users
  }

  findUser(username) {
    if (this.userByName && this.userByName[username]) {
      return this.userByName[username]
    }

    return null
  }

  async apiGet(path, params = {}) {
    return this.apiRequest('get', path, { params })
  }

  async apiPost(path, params = {}) {
    if (!params._csrf) {
      params._csrf = this.csrfToken
    }

    return this.apiRequest('post', path, params)
  }

  async apiRequest(method, path, params) {
    const createError = (message, info = {}) => {
      let error = new Error(message)
      error.info = info
      return error
    }
    const { data } = await axios[method](`/_api${path}`, params).catch(function() {
      throw createError('Error')
    })
    const { ok, error, info } = data
    if (ok) {
      return data
    }
    throw createError(error, info)
  }

  static escape(html, encode) {
    return html
      .replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&')
      .replace(/</g, '<')
      .replace(/>/g, '>')
      .replace(/"/g, '"')
      .replace(/'/g, ''')
  }

  static unescape(html) {
    return html.replace(/&([#\w]+);/g, function(_, n) {
      n = n.toLowerCase()
      if (n === 'colon') return ':'
      if (n.charAt(0) === '#') {
        return n.charAt(1) === 'x' ? String.fromCharCode(parseInt(n.substring(2), 16)) : String.fromCharCode(+n.substring(1))
      }
      return ''
    })
  }
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2011 - present Instructure, Inc.
 *
 * This file is part of Canvas.
 *
 * Canvas is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License as published by the Free
 * Software Foundation, version 3 of the License.
 *
 * Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Affero General Public License along
 * with this program. If not, see <http://www.gnu.org/licenses/>.
 */

/*
will make the element semi-transparent and disable any :inputs untill a defferred completes.
example:

$('#some_form').disableWhileLoading($.ajaxJSON(...), {buttons: ['.send_button' : 'Sending...'}});

or

var promise = $.ajaxJSON(...);
$('#form').disableWhileLoading(promise, {
  buttons: {
    '.send_button' : 'Sending...'
  }
});

*/
import I18n from 'i18n!disableWhileLoading'
import $ from 'jquery'
import './jquery.ajaxJSON'
import 'spin.js/jquery.spin'

function eraseFromArray(array, victim) {
  array.forEach((prospect, index) => {
    if (prospect === victim) array.splice(index, 1)
  })
}

$.fn.disableWhileLoading = function(deferred, options) {
  return this.each(function() {
    const opts = $.extend(true, {}, $.fn.disableWhileLoading.defaults, options),
      $this = $(this),
      data = $this.data(),
      thingsToWaitOn =
        data.disabledWhileLoadingDeferreds || (data.disabledWhileLoadingDeferreds = []),
      myDeferred = $.Deferred()

    $.when.apply($, thingsToWaitOn).done(function() {
      let dataKey = 'disabled_' + $.guid++,
        $disabledArea = $this.add($this.nextAll('.ui-dialog-buttonpane')),
        //  todo: replace .andSelf with .addBack when JQuery is upgraded.
        $inputsToDisable = $disabledArea
          .find('*')
          .andSelf()
          .filter(':input')
          .not(':disabled,[type=file]'),
        $foundSpinHolder = $this.find('.spin_holder'),
        $spinHolder = $foundSpinHolder.length ? $foundSpinHolder : $this,
        previousSpinHolderDisplay = $spinHolder.css('display'),
        disabled = false

      const disabler = setTimeout(function() {
        disabled = true
        $inputsToDisable.prop('disabled', true)
        $spinHolder.show().spin(options)
        $($spinHolder.data().spinner.el).css({'max-width': '100px'})
        $disabledArea.css('opacity', function(i, currentOpacity) {
          $(this).data(dataKey + 'opacityBefore', this.style.opacity || 1)
          return opts.opacity
        })
        $.each(opts.buttons, function(selector, text) {
          // if you pass an array to $.each the first arg is indexInArray, we need second arg
          if ($.isArray(opts.buttons)) {
            selector = text
            text = null
          }
          $disabledArea.find(selector).text(function(i, currentText) {
            $(this).data(dataKey, currentText)
            return (
              text ||
              $(this).data('textWhileLoading') ||
              ($(this).is('.ui-button-text') &&
                $(this)
                  .closest('.ui-button')
                  .data('textWhileLoading')) ||
              // if nothing was passed in as the text value or if they pass an array for opts.buttons,
              // just use a default loading... text.
              I18n.t('loading', 'Loading...')
            )
          })
        })
      }, 13)

      $.when(deferred).always(function() {
        clearTimeout(disabler)
        if (disabled) {
          $spinHolder.css('display', previousSpinHolderDisplay).spin(false) // stop spinner
          $disabledArea.css('opacity', function() {
            return $(this).data(dataKey + 'opacityBefore') || 1
          })
          $inputsToDisable.prop('disabled', false)
          $.each(opts.buttons, function(selector, text) {
            if (typeof selector === 'number') selector = '' + this // for arrays
            $disabledArea.find(selector).text(function() {
              return $(this).data(dataKey)
            })
          })
          eraseFromArray(thingsToWaitOn, myDeferred) // speed up so that $.when doesn't have to look at myDeferred any more
          myDeferred.resolve()
          if (opts.onComplete) {
            opts.onComplete()
          }
        }
      })
    })
    thingsToWaitOn.push(myDeferred)
  })
}
$.fn.disableWhileLoading.defaults = {
  opacity: 0.5,
  buttons: ['button[type="submit"], .ui-dialog-buttonpane .ui-button .ui-button-text']
}
<commit_msg>perf: avoid a “Recalculate Style” in disableWhileLoading<commit_after>/*
 * Copyright (C) 2011 - present Instructure, Inc.
 *
 * This file is part of Canvas.
 *
 * Canvas is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License as published by the Free
 * Software Foundation, version 3 of the License.
 *
 * Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Affero General Public License along
 * with this program. If not, see <http://www.gnu.org/licenses/>.
 */

/*
will make the element semi-transparent and disable any :inputs untill a defferred completes.
example:

$('#some_form').disableWhileLoading($.ajaxJSON(...), {buttons: ['.send_button' : 'Sending...'}});

or

var promise = $.ajaxJSON(...);
$('#form').disableWhileLoading(promise, {
  buttons: {
    '.send_button' : 'Sending...'
  }
});

*/
import I18n from 'i18n!disableWhileLoading'
import $ from 'jquery'
import './jquery.ajaxJSON'
import 'spin.js/jquery.spin'

function eraseFromArray(array, victim) {
  array.forEach((prospect, index) => {
    if (prospect === victim) array.splice(index, 1)
  })
}

$.fn.disableWhileLoading = function(deferred, options) {
  return this.each(function() {
    const opts = $.extend(true, {}, $.fn.disableWhileLoading.defaults, options)
    const $this = $(this)
    const data = $this.data()
    const thingsToWaitOn =
      data.disabledWhileLoadingDeferreds || (data.disabledWhileLoadingDeferreds = [])
    const myDeferred = $.Deferred()

    $.when(...thingsToWaitOn).done(() => {
      let dataKey
      let $disabledArea
      let $inputsToDisable
      let $spinHolder
      let previousSpinHolderDisplay
      let disabled = false

      const disabler = setTimeout(() => {
        dataKey = 'disabled_' + $.guid++
        $disabledArea = $this.add($this.nextAll('.ui-dialog-buttonpane'))
        disabled = true
        //  todo: replace .andSelf with .addBack when JQuery is upgraded.
        $inputsToDisable = $disabledArea
          .find('*')
          .andSelf()
          .filter(':input')
          .not(':disabled,[type=file]')
        const $foundSpinHolder = $this.find('.spin_holder')
        $spinHolder = $foundSpinHolder.length ? $foundSpinHolder : $this
        previousSpinHolderDisplay = $spinHolder.css('display')

        $inputsToDisable.prop('disabled', true)
        $spinHolder.show().spin(options)
        $($spinHolder.data().spinner.el).css({'max-width': '100px'})
        $disabledArea.css('opacity', function(i, currentOpacity) {
          $(this).data(dataKey + 'opacityBefore', this.style.opacity || 1)
          return opts.opacity
        })
        $.each(opts.buttons, function(selector, text) {
          // if you pass an array to $.each the first arg is indexInArray, we need second arg
          if ($.isArray(opts.buttons)) {
            selector = text
            text = null
          }
          $disabledArea.find(selector).text(function(i, currentText) {
            $(this).data(dataKey, currentText)
            return (
              text ||
              $(this).data('textWhileLoading') ||
              ($(this).is('.ui-button-text') &&
                $(this)
                  .closest('.ui-button')
                  .data('textWhileLoading')) ||
              // if nothing was passed in as the text value or if they pass an array for opts.buttons,
              // just use a default loading... text.
              I18n.t('loading', 'Loading...')
            )
          })
        })
      }, 13)

      $.when(deferred).always(function() {
        clearTimeout(disabler)
        if (disabled) {
          $spinHolder.css('display', previousSpinHolderDisplay).spin(false) // stop spinner
          $disabledArea.css('opacity', function() {
            return $(this).data(dataKey + 'opacityBefore') || 1
          })
          $inputsToDisable.prop('disabled', false)
          $.each(opts.buttons, function(selector, text) {
            if (typeof selector === 'number') selector = '' + this // for arrays
            $disabledArea.find(selector).text(function() {
              return $(this).data(dataKey)
            })
          })
          eraseFromArray(thingsToWaitOn, myDeferred) // speed up so that $.when doesn't have to look at myDeferred any more
          myDeferred.resolve()
          if (opts.onComplete) {
            opts.onComplete()
          }
        }
      })
    })
    thingsToWaitOn.push(myDeferred)
  })
}
$.fn.disableWhileLoading.defaults = {
  opacity: 0.5,
  buttons: ['button[type="submit"], .ui-dialog-buttonpane .ui-button .ui-button-text']
}
<|endoftext|>


<commit_before>'use strict';

angular.module('venueApp')
  .controller('InstructorEventsCtrl', ($scope, $routeParams, User, Auth) => {

    $scope.user = {};
    $scope.events = [];

    Auth.getCurrentUser((user) => {
      $scope.user = user;
      User.get({id: user._id, withSections:true, withEvents: true, withSectionsCourse:true}, (usr) => {
        $scope.user = usr;
        $scope.events = usr.events;
        console.log(usr.events)
      });
    });

  });
<commit_msg>Update events.controller.js<commit_after>'use strict';

angular.module('venueApp')
  .controller('InstructorEventsCtrl', ($scope, $routeParams, User, Auth) => {

    $scope.user = {};
    $scope.events = [];

    Auth.getCurrentUser((user) => {
      $scope.user = user;
      User.get({id: user._id, withSections:true, withEvents: true, withSectionsCourse:true}, (usr) => {
        $scope.user = usr;
        $scope.events = usr.events;
      });
    });

  });
<|endoftext|>


<commit_before>angular
    .module('material.components.tabs')
    .controller('MdTabsController', MdTabsController);

/**
 * @ngInject
 */
function MdTabsController ($scope, $element, $window, $timeout, $mdConstant, $mdTabInkRipple,
                           $mdUtil, $animate) {
  var ctrl     = this,
      locked   = false,
      elements = getElements(),
      queue    = [];

  ctrl.scope = $scope;
  ctrl.parent = $scope.$parent;
  ctrl.tabs = [];
  ctrl.lastSelectedIndex = null;
  ctrl.focusIndex = 0;
  ctrl.offsetLeft = 0;
  ctrl.hasContent = false;
  ctrl.hasFocus = false;
  ctrl.lastClick = true;

  ctrl.redirectFocus = redirectFocus;
  ctrl.attachRipple = attachRipple;
  ctrl.shouldStretchTabs = shouldStretchTabs;
  ctrl.shouldPaginate = shouldPaginate;
  ctrl.shouldCenterTabs = shouldCenterTabs;
  ctrl.insertTab = insertTab;
  ctrl.removeTab = removeTab;
  ctrl.select = select;
  ctrl.scroll = scroll;
  ctrl.nextPage = nextPage;
  ctrl.previousPage = previousPage;
  ctrl.keydown = keydown;
  ctrl.canPageForward = canPageForward;
  ctrl.canPageBack = canPageBack;
  ctrl.refreshIndex = refreshIndex;
  ctrl.incrementSelectedIndex = incrementSelectedIndex;
  ctrl.updateInkBarStyles = updateInkBarStyles;
  ctrl.updateTabOrder = $mdUtil.debounce(updateTabOrder, 100);

  init();

  function init () {
    $scope.$watch('selectedIndex', handleSelectedIndexChange);
    $scope.$watch('$mdTabsCtrl.focusIndex', handleFocusIndexChange);
    $scope.$watch('$mdTabsCtrl.offsetLeft', handleOffsetChange);
    $scope.$watch('$mdTabsCtrl.hasContent', handleHasContent);
    angular.element($window).on('resize', function () { $scope.$apply(handleWindowResize); });
    $timeout(updateInkBarStyles, 0, false);
    $timeout(updateHeightFromContent, 0, false);
  }

  function handleHasContent (hasContent) {
    $element[hasContent ? 'removeClass' : 'addClass']('md-no-tab-content');
  }

  function getElements () {
    var elements      = {};

    //-- gather tab bar elements
    elements.wrapper  = $element[0].getElementsByTagName('md-tabs-wrapper')[0];
    elements.canvas   = elements.wrapper.getElementsByTagName('md-tabs-canvas')[0];
    elements.paging   = elements.canvas.getElementsByTagName('md-pagination-wrapper')[0];
    elements.tabs     = elements.paging.getElementsByTagName('md-tab-item');
    elements.dummies  = elements.canvas.getElementsByTagName('md-dummy-tab');
    elements.inkBar   = elements.paging.getElementsByTagName('md-ink-bar')[0];

    //-- gather tab content elements
    elements.contentsWrapper = $element[0].getElementsByTagName('md-tabs-content-wrapper')[0];
    elements.contents = elements.contentsWrapper.getElementsByTagName('md-tab-content');

    return elements;
  }

  function keydown (event) {
    switch (event.keyCode) {
      case $mdConstant.KEY_CODE.LEFT_ARROW:
        event.preventDefault();
        incrementSelectedIndex(-1, true);
        break;
      case $mdConstant.KEY_CODE.RIGHT_ARROW:
        event.preventDefault();
        incrementSelectedIndex(1, true);
        break;
      case $mdConstant.KEY_CODE.SPACE:
      case $mdConstant.KEY_CODE.ENTER:
        event.preventDefault();
        if (!locked) $scope.selectedIndex = ctrl.focusIndex;
        break;
    }
    ctrl.lastClick = false;
  }

  function updateTabOrder () {
    var selectedItem = ctrl.tabs[$scope.selectedIndex],
        focusItem = ctrl.tabs[ctrl.focusIndex];
    ctrl.tabs = ctrl.tabs.sort(function (a, b) {
      return a.index - b.index;
    });
    $scope.selectedIndex = ctrl.tabs.indexOf(selectedItem);
    ctrl.focusIndex = ctrl.tabs.indexOf(focusItem);
    $timeout(updateInkBarStyles, 0, false);
  }

  function incrementSelectedIndex (inc, focus) {
    var newIndex,
        index = focus ? ctrl.focusIndex : $scope.selectedIndex;
    for (newIndex = index + inc;
         ctrl.tabs[newIndex] && ctrl.tabs[newIndex].scope.disabled;
         newIndex += inc) {}
    if (ctrl.tabs[newIndex]) {
      if (focus) ctrl.focusIndex = newIndex;
      else $scope.selectedIndex = newIndex;
    }
  }

  function handleOffsetChange (left) {
    var newValue = shouldCenterTabs() ? '' : '-' + left + 'px';
    angular.element(elements.paging).css('transform', 'translate3d(' + newValue + ', 0, 0)');
    $scope.$broadcast('$mdTabsPaginationChanged');
  }

  function handleFocusIndexChange (newIndex, oldIndex) {
    if (newIndex === oldIndex) return;
    if (!elements.tabs[newIndex]) return;
    adjustOffset();
    redirectFocus();
  }

  function redirectFocus () {
    elements.dummies[ctrl.focusIndex].focus();
  }

  function adjustOffset () {
    if (shouldCenterTabs()) return;
    var tab = elements.tabs[ctrl.focusIndex],
        left = tab.offsetLeft,
        right = tab.offsetWidth + left;
    ctrl.offsetLeft = Math.max(ctrl.offsetLeft, fixOffset(right - elements.canvas.clientWidth));
    ctrl.offsetLeft = Math.min(ctrl.offsetLeft, fixOffset(left));
  }

  function handleWindowResize () {
    ctrl.lastSelectedIndex = $scope.selectedIndex;
    ctrl.offsetLeft = fixOffset(ctrl.offsetLeft);
    $timeout(updateInkBarStyles, 0, false);
  }

  function processQueue () {
    queue.forEach(function (func) { $timeout(func); });
    queue = [];
  }

  function insertTab (tabData, index) {
    var proto = {
          getIndex: function () { return ctrl.tabs.indexOf(tab); },
          isActive: function () { return this.getIndex() === $scope.selectedIndex; },
          isLeft:   function () { return this.getIndex() < $scope.selectedIndex; },
          isRight:  function () { return this.getIndex() > $scope.selectedIndex; },
          hasFocus: function () { return !ctrl.lastClick && ctrl.hasFocus && this.getIndex() === ctrl.focusIndex; },
          id:       $mdUtil.nextUid()
        },
        tab = angular.extend(proto, tabData);
    if (angular.isDefined(index)) {
      ctrl.tabs.splice(index, 0, tab);
    } else {
      ctrl.tabs.push(tab);
    }
    processQueue();
    updateHasContent();
    return tab;
  }

  function updateHasContent () {
    var hasContent = false;
    angular.forEach(ctrl.tabs, function (tab) {
      if (tab.template) hasContent = true;
    });
    ctrl.hasContent = hasContent;
  }

  function removeTab (tabData) {
    ctrl.tabs.splice(tabData.getIndex(), 1);
    refreshIndex();
    $timeout(function () {
      updateInkBarStyles();
      ctrl.offsetLeft = fixOffset(ctrl.offsetLeft);
    });
  }

  function refreshIndex () {
    $scope.selectedIndex = getNearestSafeIndex($scope.selectedIndex);
    ctrl.focusIndex = getNearestSafeIndex(ctrl.focusIndex);
  }

  function handleSelectedIndexChange (newValue, oldValue) {
    if (newValue === oldValue) return;

    $scope.selectedIndex = getNearestSafeIndex(newValue);
    ctrl.lastSelectedIndex = oldValue;
    updateInkBarStyles();
    updateHeightFromContent();
    $scope.$broadcast('$mdTabsChanged');
    ctrl.tabs[oldValue] && ctrl.tabs[oldValue].scope.deselect();
    ctrl.tabs[newValue] && ctrl.tabs[newValue].scope.select();
  }

  function handleResizeWhenVisible () {
    //-- if there is already a watcher waiting for resize, do nothing
    if (handleResizeWhenVisible.watcher) return;
    //-- otherwise, we will abuse the $watch function to check for visible
    handleResizeWhenVisible.watcher = $scope.$watch(function () {
      //-- since we are checking for DOM size, we use $timeout to wait for after the DOM updates
      $timeout(function () {
        //-- if the watcher has already run (ie. multiple digests in one cycle), do nothing
        if (!handleResizeWhenVisible.watcher) return;

        if ($element.prop('offsetParent')) {
          handleResizeWhenVisible.watcher();
          handleResizeWhenVisible.watcher = null;

          //-- we have to trigger our own $apply so that the DOM bindings will update
          $scope.$apply(handleWindowResize);
        }
      }, 0, false);
    });
  }

  function updateHeightFromContent () {
    if (!$scope.dynamicHeight) return $element.css('height', '');
    if (!ctrl.tabs.length) return queue.push(updateHeightFromContent);
    var tabContent    = elements.contents[$scope.selectedIndex],
        contentHeight = tabContent ? tabContent.offsetHeight : 0,
        tabsHeight    = elements.wrapper.offsetHeight,
        newHeight     = contentHeight + tabsHeight,
        currentHeight = $element.prop('clientHeight');
    if (currentHeight === newHeight) return;
    locked = true;
    $animate
        .animate(
          $element,
          { height: currentHeight + 'px' },
          { height: newHeight + 'px'}
        )
        .then(function () {
          $element.css('height', '');
          locked = false;
        });
  }

  function updateInkBarStyles () {
    if (!ctrl.tabs.length) return queue.push(updateInkBarStyles);
    //-- if the element is not visible, we will not be able to calculate sizes until it is
    //-- we should treat that as a resize event rather than just updating the ink bar
    if (!$element.prop('offsetParent')) return handleResizeWhenVisible();
    var index = $scope.selectedIndex,
        totalWidth = elements.paging.offsetWidth,
        tab = elements.tabs[index],
        left = tab.offsetLeft,
        right = totalWidth - left - tab.offsetWidth;
    updateInkBarClassName();
    angular.element(elements.inkBar).css({ left: left + 'px', right: right + 'px' });
  }

  function updateInkBarClassName () {
    var newIndex = $scope.selectedIndex,
        oldIndex = ctrl.lastSelectedIndex,
        ink = angular.element(elements.inkBar);
    ink.removeClass('md-left md-right');
    if (!angular.isNumber(oldIndex)) return;
    if (newIndex < oldIndex) {
      ink.addClass('md-left');
    } else if (newIndex > oldIndex) {
      ink.addClass('md-right');
    }
  }

  function getNearestSafeIndex(newIndex) {
    var maxOffset = Math.max(ctrl.tabs.length - newIndex, newIndex),
        i, tab;
    for (i = 0; i <= maxOffset; i++) {
      tab = ctrl.tabs[newIndex + i];
      if (tab && (tab.scope.disabled !== true)) return tab.getIndex();
      tab = ctrl.tabs[newIndex - i];
      if (tab && (tab.scope.disabled !== true)) return tab.getIndex();
    }
    return newIndex;
  }

  function shouldStretchTabs () {
    switch ($scope.stretchTabs) {
      case 'always': return true;
      case 'never':  return false;
      default:       return !shouldPaginate() && $window.matchMedia('(max-width: 600px)').matches;
    }
  }

  function shouldCenterTabs () {
    return $scope.centerTabs && !shouldPaginate();
  }

  function shouldPaginate () {
    if ($scope.noPagination) return false;
    var canvasWidth = $element.prop('clientWidth');
    angular.forEach(elements.tabs, function (tab) { canvasWidth -= tab.offsetWidth; });
    return canvasWidth < 0;
  }

  function select (index) {
    if (!locked) ctrl.focusIndex = $scope.selectedIndex = index;
    ctrl.lastClick = true;
  }

  function scroll (event) {
    if (!shouldPaginate()) return;
    event.preventDefault();
    ctrl.offsetLeft = fixOffset(ctrl.offsetLeft - event.wheelDelta);
  }

  function fixOffset (value) {
    if (!elements.tabs.length || !shouldPaginate()) return 0;
    var lastTab = elements.tabs[elements.tabs.length - 1],
        totalWidth = lastTab.offsetLeft + lastTab.offsetWidth;
    value = Math.max(0, value);
    value = Math.min(totalWidth - elements.canvas.clientWidth, value);
    return value;
  }

  function nextPage () {
    var viewportWidth = elements.canvas.clientWidth,
        totalWidth = viewportWidth + ctrl.offsetLeft,
        i, tab;
    for (i = 0; i < elements.tabs.length; i++) {
      tab = elements.tabs[i];
      if (tab.offsetLeft + tab.offsetWidth > totalWidth) break;
    }
    ctrl.offsetLeft = fixOffset(tab.offsetLeft);
  }

  function previousPage () {
    var i, tab;
    for (i = 0; i < elements.tabs.length; i++) {
      tab = elements.tabs[i];
      if (tab.offsetLeft + tab.offsetWidth >= ctrl.offsetLeft) break;
    }
    ctrl.offsetLeft = fixOffset(tab.offsetLeft + tab.offsetWidth - elements.canvas.clientWidth);
  }

  function canPageBack () {
    return ctrl.offsetLeft > 0;
  }

  function canPageForward () {
    var lastTab = elements.tabs[elements.tabs.length - 1];
    return lastTab && lastTab.offsetLeft + lastTab.offsetWidth > elements.canvas.clientWidth + ctrl.offsetLeft;
  }

  function attachRipple (scope, element) {
    var options = { colorElement: angular.element(elements.inkBar) };
    $mdTabInkRipple.attach(scope, element, options);
  }
}
<commit_msg>fix(tabs): initial state will now scroll to selected tab<commit_after>angular
    .module('material.components.tabs')
    .controller('MdTabsController', MdTabsController);

/**
 * @ngInject
 */
function MdTabsController ($scope, $element, $window, $timeout, $mdConstant, $mdTabInkRipple,
                           $mdUtil, $animate) {
  var ctrl     = this,
      locked   = false,
      elements = getElements(),
      queue    = [];

  ctrl.scope = $scope;
  ctrl.parent = $scope.$parent;
  ctrl.tabs = [];
  ctrl.lastSelectedIndex = null;
  ctrl.focusIndex = $scope.selectedIndex || 0;
  ctrl.offsetLeft = 0;
  ctrl.hasContent = false;
  ctrl.hasFocus = false;
  ctrl.lastClick = true;

  ctrl.redirectFocus = redirectFocus;
  ctrl.attachRipple = attachRipple;
  ctrl.shouldStretchTabs = shouldStretchTabs;
  ctrl.shouldPaginate = shouldPaginate;
  ctrl.shouldCenterTabs = shouldCenterTabs;
  ctrl.insertTab = insertTab;
  ctrl.removeTab = removeTab;
  ctrl.select = select;
  ctrl.scroll = scroll;
  ctrl.nextPage = nextPage;
  ctrl.previousPage = previousPage;
  ctrl.keydown = keydown;
  ctrl.canPageForward = canPageForward;
  ctrl.canPageBack = canPageBack;
  ctrl.refreshIndex = refreshIndex;
  ctrl.incrementSelectedIndex = incrementSelectedIndex;
  ctrl.updateInkBarStyles = updateInkBarStyles;
  ctrl.updateTabOrder = $mdUtil.debounce(updateTabOrder, 100);

  init();

  function init () {
    $scope.$watch('selectedIndex', handleSelectedIndexChange);
    $scope.$watch('$mdTabsCtrl.focusIndex', handleFocusIndexChange);
    $scope.$watch('$mdTabsCtrl.offsetLeft', handleOffsetChange);
    $scope.$watch('$mdTabsCtrl.hasContent', handleHasContent);
    angular.element($window).on('resize', function () { $scope.$apply(handleWindowResize); });
    $timeout(updateInkBarStyles, 0, false);
    $timeout(updateHeightFromContent, 0, false);
    $timeout(adjustOffset);
  }

  function handleHasContent (hasContent) {
    $element[hasContent ? 'removeClass' : 'addClass']('md-no-tab-content');
  }

  function getElements () {
    var elements      = {};

    //-- gather tab bar elements
    elements.wrapper  = $element[0].getElementsByTagName('md-tabs-wrapper')[0];
    elements.canvas   = elements.wrapper.getElementsByTagName('md-tabs-canvas')[0];
    elements.paging   = elements.canvas.getElementsByTagName('md-pagination-wrapper')[0];
    elements.tabs     = elements.paging.getElementsByTagName('md-tab-item');
    elements.dummies  = elements.canvas.getElementsByTagName('md-dummy-tab');
    elements.inkBar   = elements.paging.getElementsByTagName('md-ink-bar')[0];

    //-- gather tab content elements
    elements.contentsWrapper = $element[0].getElementsByTagName('md-tabs-content-wrapper')[0];
    elements.contents = elements.contentsWrapper.getElementsByTagName('md-tab-content');

    return elements;
  }

  function keydown (event) {
    switch (event.keyCode) {
      case $mdConstant.KEY_CODE.LEFT_ARROW:
        event.preventDefault();
        incrementSelectedIndex(-1, true);
        break;
      case $mdConstant.KEY_CODE.RIGHT_ARROW:
        event.preventDefault();
        incrementSelectedIndex(1, true);
        break;
      case $mdConstant.KEY_CODE.SPACE:
      case $mdConstant.KEY_CODE.ENTER:
        event.preventDefault();
        if (!locked) $scope.selectedIndex = ctrl.focusIndex;
        break;
    }
    ctrl.lastClick = false;
  }

  function updateTabOrder () {
    var selectedItem = ctrl.tabs[$scope.selectedIndex],
        focusItem = ctrl.tabs[ctrl.focusIndex];
    ctrl.tabs = ctrl.tabs.sort(function (a, b) {
      return a.index - b.index;
    });
    $scope.selectedIndex = ctrl.tabs.indexOf(selectedItem);
    ctrl.focusIndex = ctrl.tabs.indexOf(focusItem);
    $timeout(updateInkBarStyles, 0, false);
  }

  function incrementSelectedIndex (inc, focus) {
    var newIndex,
        index = focus ? ctrl.focusIndex : $scope.selectedIndex;
    for (newIndex = index + inc;
         ctrl.tabs[newIndex] && ctrl.tabs[newIndex].scope.disabled;
         newIndex += inc) {}
    if (ctrl.tabs[newIndex]) {
      if (focus) ctrl.focusIndex = newIndex;
      else $scope.selectedIndex = newIndex;
    }
  }

  function handleOffsetChange (left) {
    var newValue = shouldCenterTabs() ? '' : '-' + left + 'px';
    angular.element(elements.paging).css('transform', 'translate3d(' + newValue + ', 0, 0)');
    $scope.$broadcast('$mdTabsPaginationChanged');
  }

  function handleFocusIndexChange (newIndex, oldIndex) {
    if (newIndex === oldIndex) return;
    if (!elements.tabs[newIndex]) return;
    adjustOffset();
    redirectFocus();
  }

  function redirectFocus () {
    elements.dummies[ctrl.focusIndex].focus();
  }

  function adjustOffset () {
    if (shouldCenterTabs()) return;
    var tab = elements.tabs[ctrl.focusIndex],
        left = tab.offsetLeft,
        right = tab.offsetWidth + left;
    ctrl.offsetLeft = Math.max(ctrl.offsetLeft, fixOffset(right - elements.canvas.clientWidth));
    ctrl.offsetLeft = Math.min(ctrl.offsetLeft, fixOffset(left));
  }

  function handleWindowResize () {
    ctrl.lastSelectedIndex = $scope.selectedIndex;
    ctrl.offsetLeft = fixOffset(ctrl.offsetLeft);
    $timeout(updateInkBarStyles, 0, false);
  }

  function processQueue () {
    queue.forEach(function (func) { $timeout(func); });
    queue = [];
  }

  function insertTab (tabData, index) {
    var proto = {
          getIndex: function () { return ctrl.tabs.indexOf(tab); },
          isActive: function () { return this.getIndex() === $scope.selectedIndex; },
          isLeft:   function () { return this.getIndex() < $scope.selectedIndex; },
          isRight:  function () { return this.getIndex() > $scope.selectedIndex; },
          hasFocus: function () { return !ctrl.lastClick && ctrl.hasFocus && this.getIndex() === ctrl.focusIndex; },
          id:       $mdUtil.nextUid()
        },
        tab = angular.extend(proto, tabData);
    if (angular.isDefined(index)) {
      ctrl.tabs.splice(index, 0, tab);
    } else {
      ctrl.tabs.push(tab);
    }
    processQueue();
    updateHasContent();
    return tab;
  }

  function updateHasContent () {
    var hasContent = false;
    angular.forEach(ctrl.tabs, function (tab) {
      if (tab.template) hasContent = true;
    });
    ctrl.hasContent = hasContent;
  }

  function removeTab (tabData) {
    ctrl.tabs.splice(tabData.getIndex(), 1);
    refreshIndex();
    $timeout(function () {
      updateInkBarStyles();
      ctrl.offsetLeft = fixOffset(ctrl.offsetLeft);
    });
  }

  function refreshIndex () {
    $scope.selectedIndex = getNearestSafeIndex($scope.selectedIndex);
    ctrl.focusIndex = getNearestSafeIndex(ctrl.focusIndex);
  }

  function handleSelectedIndexChange (newValue, oldValue) {
    if (newValue === oldValue) return;

    $scope.selectedIndex = getNearestSafeIndex(newValue);
    ctrl.lastSelectedIndex = oldValue;
    updateInkBarStyles();
    updateHeightFromContent();
    $scope.$broadcast('$mdTabsChanged');
    ctrl.tabs[oldValue] && ctrl.tabs[oldValue].scope.deselect();
    ctrl.tabs[newValue] && ctrl.tabs[newValue].scope.select();
  }

  function handleResizeWhenVisible () {
    //-- if there is already a watcher waiting for resize, do nothing
    if (handleResizeWhenVisible.watcher) return;
    //-- otherwise, we will abuse the $watch function to check for visible
    handleResizeWhenVisible.watcher = $scope.$watch(function () {
      //-- since we are checking for DOM size, we use $timeout to wait for after the DOM updates
      $timeout(function () {
        //-- if the watcher has already run (ie. multiple digests in one cycle), do nothing
        if (!handleResizeWhenVisible.watcher) return;

        if ($element.prop('offsetParent')) {
          handleResizeWhenVisible.watcher();
          handleResizeWhenVisible.watcher = null;

          //-- we have to trigger our own $apply so that the DOM bindings will update
          $scope.$apply(handleWindowResize);
        }
      }, 0, false);
    });
  }

  function updateHeightFromContent () {
    if (!$scope.dynamicHeight) return $element.css('height', '');
    if (!ctrl.tabs.length) return queue.push(updateHeightFromContent);
    var tabContent    = elements.contents[$scope.selectedIndex],
        contentHeight = tabContent ? tabContent.offsetHeight : 0,
        tabsHeight    = elements.wrapper.offsetHeight,
        newHeight     = contentHeight + tabsHeight,
        currentHeight = $element.prop('clientHeight');
    if (currentHeight === newHeight) return;
    locked = true;
    $animate
        .animate(
          $element,
          { height: currentHeight + 'px' },
          { height: newHeight + 'px'}
        )
        .then(function () {
          $element.css('height', '');
          locked = false;
        });
  }

  function updateInkBarStyles () {
    if (!ctrl.tabs.length) return queue.push(updateInkBarStyles);
    //-- if the element is not visible, we will not be able to calculate sizes until it is
    //-- we should treat that as a resize event rather than just updating the ink bar
    if (!$element.prop('offsetParent')) return handleResizeWhenVisible();
    var index = $scope.selectedIndex,
        totalWidth = elements.paging.offsetWidth,
        tab = elements.tabs[index],
        left = tab.offsetLeft,
        right = totalWidth - left - tab.offsetWidth;
    updateInkBarClassName();
    angular.element(elements.inkBar).css({ left: left + 'px', right: right + 'px' });
  }

  function updateInkBarClassName () {
    var newIndex = $scope.selectedIndex,
        oldIndex = ctrl.lastSelectedIndex,
        ink = angular.element(elements.inkBar);
    ink.removeClass('md-left md-right');
    if (!angular.isNumber(oldIndex)) return;
    if (newIndex < oldIndex) {
      ink.addClass('md-left');
    } else if (newIndex > oldIndex) {
      ink.addClass('md-right');
    }
  }

  function getNearestSafeIndex(newIndex) {
    var maxOffset = Math.max(ctrl.tabs.length - newIndex, newIndex),
        i, tab;
    for (i = 0; i <= maxOffset; i++) {
      tab = ctrl.tabs[newIndex + i];
      if (tab && (tab.scope.disabled !== true)) return tab.getIndex();
      tab = ctrl.tabs[newIndex - i];
      if (tab && (tab.scope.disabled !== true)) return tab.getIndex();
    }
    return newIndex;
  }

  function shouldStretchTabs () {
    switch ($scope.stretchTabs) {
      case 'always': return true;
      case 'never':  return false;
      default:       return !shouldPaginate() && $window.matchMedia('(max-width: 600px)').matches;
    }
  }

  function shouldCenterTabs () {
    return $scope.centerTabs && !shouldPaginate();
  }

  function shouldPaginate () {
    if ($scope.noPagination) return false;
    var canvasWidth = $element.prop('clientWidth');
    angular.forEach(elements.tabs, function (tab) { canvasWidth -= tab.offsetWidth; });
    return canvasWidth < 0;
  }

  function select (index) {
    if (!locked) ctrl.focusIndex = $scope.selectedIndex = index;
    ctrl.lastClick = true;
  }

  function scroll (event) {
    if (!shouldPaginate()) return;
    event.preventDefault();
    ctrl.offsetLeft = fixOffset(ctrl.offsetLeft - event.wheelDelta);
  }

  function fixOffset (value) {
    if (!elements.tabs.length || !shouldPaginate()) return 0;
    var lastTab = elements.tabs[elements.tabs.length - 1],
        totalWidth = lastTab.offsetLeft + lastTab.offsetWidth;
    value = Math.max(0, value);
    value = Math.min(totalWidth - elements.canvas.clientWidth, value);
    return value;
  }

  function nextPage () {
    var viewportWidth = elements.canvas.clientWidth,
        totalWidth = viewportWidth + ctrl.offsetLeft,
        i, tab;
    for (i = 0; i < elements.tabs.length; i++) {
      tab = elements.tabs[i];
      if (tab.offsetLeft + tab.offsetWidth > totalWidth) break;
    }
    ctrl.offsetLeft = fixOffset(tab.offsetLeft);
  }

  function previousPage () {
    var i, tab;
    for (i = 0; i < elements.tabs.length; i++) {
      tab = elements.tabs[i];
      if (tab.offsetLeft + tab.offsetWidth >= ctrl.offsetLeft) break;
    }
    ctrl.offsetLeft = fixOffset(tab.offsetLeft + tab.offsetWidth - elements.canvas.clientWidth);
  }

  function canPageBack () {
    return ctrl.offsetLeft > 0;
  }

  function canPageForward () {
    var lastTab = elements.tabs[elements.tabs.length - 1];
    return lastTab && lastTab.offsetLeft + lastTab.offsetWidth > elements.canvas.clientWidth + ctrl.offsetLeft;
  }

  function attachRipple (scope, element) {
    var options = { colorElement: angular.element(elements.inkBar) };
    $mdTabInkRipple.attach(scope, element, options);
  }
}
<|endoftext|>


<commit_before>if(self.location.protocol === "file:"){
	alert("The documentation is not going to work properly if accessed from a file system. You should use a webserver instead.");
}

luga.namespace("luga.docs");

luga.docs.initMainNav = function(rootNode, url, response){
	jQuery("a", rootNode).each(function(index, item){
		if((index > 0) && luga.docs.belongsToCurrentSection(jQuery(item).attr("href"))){
			jQuery(item).parent().addClass("current");
		}
	});
};

luga.docs.belongsToCurrentSection = function(href){
	var tokens = href.split("/");
	var section = tokens[2];
	return location.href.indexOf(section) > 0;
};

luga.docs.initLocalNav = function(rootNode, url, response){
	jQuery("a", rootNode).each(function(index, item){
		if(luga.docs.isCurrentPage(jQuery(item).attr("href"))){
			jQuery(item).parent().addClass("current");
		}
	});
};

luga.docs.isCurrentPage = function(href){
	var tokens = href.split("/");
	var destination = tokens[tokens.length -2] + "/" + tokens[tokens.length -1];
	return location.href.indexOf(destination) > 0;
};

<commit_msg>Docs: Removed redundant .js file<commit_after><|endoftext|>


<commit_before>// This module defines the Angular controller that renders the Chord Diagram.
define(function(require) {

  // Load D3 v4 via our custom bundle build output.
  var d3 = require("../d3/d3.min");

  // Load the module that defines the Chord Diagram using D3.
  var ChordDiagram = require("./chordDiagram");

  // Load the module that defines the HTML Table using D3.
  var Table = require("./table");

  // Access the Kibana plugin Angular module.
  var module = require("ui/modules").get("kibana-chord");

  // Create a time formatter for the timestamp in the table.
  var formatTime = d3.timeFormat("%b %d, %y %X");

  // Register the controller with the Kibana plugin Angular module.
  module.controller("ChordController", function($scope, $rootScope, Private, $element, $http) {

    // Inject the tabify utility from Kibana internals.
    var tabifyAggResponse = Private(require("ui/agg_response/tabify/tabify"));

    // Access the DOM element provided by Angular's dependency injection.
    var div = $element[0];

    // Construct a Bootstrap Grid to position the Chord Diagram and Table.
    var container = d3.select(div).style("width", "100%")
          .append("div").attr("class", "container-fluid")
          .append("div").attr("class", "row"),
        chordContainer = container.append("div")
          .attr("class", "col-md-6"),
        rightPanel = container.append("div")
          .attr("class", "col-md-6"),
        tableContainer = rightPanel.append("div"),
        moreButton = rightPanel.append("div")
            .style("text-align", "center")
          .append("button")
            .text("More")
            .style("display", "none");

    // Construct an instance of the Chord Diagram.
    var chordDiagram = ChordDiagram(chordContainer.node());

    // Construct an instance of the HTML Table.
    var table = Table(tableContainer.node());

    // Converts hierarchical result set from ElasticSearch into a tabular form.
    // Returns an array of row objects, similar to the format returned by d3.csv.
    function tabify(response){

      var tabified = tabifyAggResponse($scope.vis, response, {
        asAggConfigResults: true
      });

      // Handle the case of a filter being applied in "Split Chart",
      // which yields a nested data structure with the table one level deeper.
      if("tables" in tabified.tables[0]){
        tabified = tabified.tables[0];
      }

      return tabified.tables[0].rows.map(function (array){
        var row = {};
        array.forEach(function (entry){
          row[entry.aggConfig.id] = entry.value;
        });
        return row;
      });
    }

    // Update the visualization with new data as the query response changes.
    $scope.$watch("esResponse", function(response) {

      // Guard against undefined value, which always occurs
      // after the plugin is loaded and before the data gets loaded.
      if(response){

        // Tabify the response.
        var data = tabify(response);

        // Pass the fresh data into the Chord Diagram.
        chordDiagram.data(data);

        // Render the Chord Diagram.
        chordDiagram();

        // Update the table (if a ribbon is currently selected).
        // This is invoked here to handle the case of auto-refresh.
        if(chordDiagram.selectedRibbon()){
          updateTable();
        }
      }
    });

    // Updates the details table based on the selected chord.
    function updateTable(){

      // Get the currently selected ribbon.
      var selectedRibbon = chordDiagram.selectedRibbon();

      if(selectedRibbon){

        var tableTitle = (
          "Flows between " + selectedRibbon.source +
          " and " + selectedRibbon.destination
        );

        // Extract the time interval from the global timeFilter.
        var timeBounds = $rootScope.timefilter.getBounds();

        // Construct the HTTP POST payload for the query middleware.
        var options = {
          source: selectedRibbon.source,
          destination: selectedRibbon.destination,
          index: $scope.vis.indexPattern.id,
          time: {
            gte: timeBounds.min.toDate().getTime(),
            lte: timeBounds.max.toDate().getTime(),
            format: "epoch_millis"
          }
        };

        // Invoke the query middleware, then render it into the table.
        $http
          .post("/api/kibana-chord", options)
          .then(function successCallback(response){
            var data = parseResponseHits(response);

            // Render the HTML Table.
            var columns = [
              { title: "Source IP", property: "sourceip" },
              { title: "Dest IP", property: "destinationip" },
              { title: "Source PG", property: "source" },
              { title: "Dest PG", property: "dest" },
              { title: "Type", property: "type" },
              { title: "Timestamp", property: "timestamp" },
              { title: "Packets", property: "packets" }
            ];

            table
              .data(data)
              .columns(columns)
              .title(tableTitle)
              ();

            moreButton.style("display", "inline-block");

            moreButton.on("click", function (){
              var options = {
                scrollId: response.data._scroll_id,
                scroll: "30s"
              };

              // Invoke the scroll middleware, then append it into the table.
              $http
                .post("/api/kibana-chord-scroll", options)
                .then(function successCallback(response){
                  console.log(response);
                });
            });

          }, function errorCallback(response){
            throw response;
          });

      // If there is no selected ribbon, then
      } else {

        // clear the existing table.
        table
          .data([])
          .columns([])
          .title("")
          ();
        moreButton.style("display", "none");

      }
    }

    // Invoke our custom middleware for querying ElasticSearch
    // when the user clicks on the ribbon.
    chordDiagram.onSelectedRibbonChange(updateTable);
  });

  function parseResponseHits(response){

    // Transform the response data into a form the table can use.
    return response.data.hits.hits.map(function (d){
      d = d._source;

      // Format timestamp as human-readable date.
      d.timestamp = formatTime(new Date(d.timestamp));

      // Add source and dest attribute to be used in table
      d.source = d.nuage_metadata.sourcepolicygroups;
      d.dest = d.nuage_metadata.destinationpolicygroups;

      return d;
    });
  }
});
<commit_msg>Update table with scroll data. Closes #34<commit_after>// This module defines the Angular controller that renders the Chord Diagram.
define(function(require) {

  // Load D3 v4 via our custom bundle build output.
  var d3 = require("../d3/d3.min");

  // Load the module that defines the Chord Diagram using D3.
  var ChordDiagram = require("./chordDiagram");

  // Load the module that defines the HTML Table using D3.
  var Table = require("./table");

  // Access the Kibana plugin Angular module.
  var module = require("ui/modules").get("kibana-chord");

  // Create a time formatter for the timestamp in the table.
  var formatTime = d3.timeFormat("%b %d, %y %X");

  // Register the controller with the Kibana plugin Angular module.
  module.controller("ChordController", function($scope, $rootScope, Private, $element, $http) {

    // Inject the tabify utility from Kibana internals.
    var tabifyAggResponse = Private(require("ui/agg_response/tabify/tabify"));

    // Access the DOM element provided by Angular's dependency injection.
    var div = $element[0];

    // Construct a Bootstrap Grid to position the Chord Diagram and Table.
    var container = d3.select(div).style("width", "100%")
          .append("div").attr("class", "container-fluid")
          .append("div").attr("class", "row"),
        chordContainer = container.append("div")
          .attr("class", "col-md-6"),
        rightPanel = container.append("div")
          .attr("class", "col-md-6"),
        tableContainer = rightPanel.append("div"),
        moreButton = rightPanel.append("div")
            .style("text-align", "center")
          .append("button")
            .text("More")
            .style("display", "none");

    // Construct an instance of the Chord Diagram.
    var chordDiagram = ChordDiagram(chordContainer.node());

    // Construct an instance of the HTML Table.
    var table = Table(tableContainer.node());

    // Converts hierarchical result set from ElasticSearch into a tabular form.
    // Returns an array of row objects, similar to the format returned by d3.csv.
    function tabify(response){

      var tabified = tabifyAggResponse($scope.vis, response, {
        asAggConfigResults: true
      });

      // Handle the case of a filter being applied in "Split Chart",
      // which yields a nested data structure with the table one level deeper.
      if("tables" in tabified.tables[0]){
        tabified = tabified.tables[0];
      }

      return tabified.tables[0].rows.map(function (array){
        var row = {};
        array.forEach(function (entry){
          row[entry.aggConfig.id] = entry.value;
        });
        return row;
      });
    }

    // Update the visualization with new data as the query response changes.
    $scope.$watch("esResponse", function(response) {

      // Guard against undefined value, which always occurs
      // after the plugin is loaded and before the data gets loaded.
      if(response){

        // Tabify the response.
        var data = tabify(response);

        // Pass the fresh data into the Chord Diagram.
        chordDiagram.data(data);

        // Render the Chord Diagram.
        chordDiagram();

        // Update the table (if a ribbon is currently selected).
        // This is invoked here to handle the case of auto-refresh.
        if(chordDiagram.selectedRibbon()){
          updateTable();
        }
      }
    });

    // Updates the details table based on the selected chord.
    function updateTable(){

      // Get the currently selected ribbon.
      var selectedRibbon = chordDiagram.selectedRibbon();

      if(selectedRibbon){

        var tableTitle = (
          "Flows between " + selectedRibbon.source +
          " and " + selectedRibbon.destination
        );

        // Extract the time interval from the global timeFilter.
        var timeBounds = $rootScope.timefilter.getBounds();

        // Construct the HTTP POST payload for the query middleware.
        var options = {
          source: selectedRibbon.source,
          destination: selectedRibbon.destination,
          index: $scope.vis.indexPattern.id,
          time: {
            gte: timeBounds.min.toDate().getTime(),
            lte: timeBounds.max.toDate().getTime(),
            format: "epoch_millis"
          }
        };

        // Invoke the query middleware, then render it into the table.
        $http
          .post("/api/kibana-chord", options)
          .then(function successCallback(response){
            var data = parseResponseHits(response);

            // Render the HTML Table.
            var columns = [
              { title: "Source IP", property: "sourceip" },
              { title: "Dest IP", property: "destinationip" },
              { title: "Source PG", property: "source" },
              { title: "Dest PG", property: "dest" },
              { title: "Type", property: "type" },
              { title: "Timestamp", property: "timestamp" },
              { title: "Packets", property: "packets" }
            ];

            table
              .data(data)
              .columns(columns)
              .title(tableTitle)
              ();

            moreButton.style("display", "inline-block");

            moreButton.on("click", function (){
              var options = {
                scrollId: response.data._scroll_id,
                scroll: "30s"
              };

              // Invoke the scroll middleware, then append it into the table.
              $http
                .post("/api/kibana-chord-scroll", options)
                .then(function successCallback(response){
                  var newData = parseResponseHits(response);
                  var oldData = table.data();
                  var data = oldData.concat(newData);
                  table.data(data);
                  table();
                });
            });

          }, function errorCallback(response){
            throw response;
          });

      // If there is no selected ribbon, then
      } else {

        // clear the existing table.
        table
          .data([])
          .columns([])
          .title("")
          ();
        moreButton.style("display", "none");

      }
    }

    // Invoke our custom middleware for querying ElasticSearch
    // when the user clicks on the ribbon.
    chordDiagram.onSelectedRibbonChange(updateTable);
  });

  function parseResponseHits(response){

    // Transform the response data into a form the table can use.
    return response.data.hits.hits.map(function (d){
      d = d._source;

      // Format timestamp as human-readable date.
      d.timestamp = formatTime(new Date(d.timestamp));

      // Add source and dest attribute to be used in table
      d.source = d.nuage_metadata.sourcepolicygroups;
      d.dest = d.nuage_metadata.destinationpolicygroups;

      return d;
    });
  }
});
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import ImageGallery from './shutterstock/components/ImageGallery.js'
import baguetteBox from 'baguettebox.js';
import Banner from './shutterstock/components/Banner.js'

class App extends Component {
    componentDidMount() {
        baguetteBox.run('.cards-gallery', { animation: 'slideIn'});
    }
  render() {
    return (

 Welcome to my awesome photo gallery powered by Shutterstock.

                <ImageGallery/>

    );
  }
}

export default App;
<commit_msg>[TASK] add jumbotron<commit_after>import React, { Component } from 'react';
import './App.css';
import ImageGallery from './shutterstock/components/ImageGallery.js'
import baguetteBox from 'baguettebox.js';
import Banner from './shutterstock/components/Banner.js'

class App extends Component {
    componentDidMount() {
        baguetteBox.run('.cards-gallery', { animation: 'slideIn'});
    }
  render() {
    return (

My Photo Gallery

Welcome to my awesome photo gallery powered by Shutterstock.

                <ImageGallery/>

    );
  }
}

export default App;
<|endoftext|>