<commit_before>var gulp = require('gulp'),
  minifyCss = require('gulp-minify-css'),
  nodemon = require('gulp-nodemon'),
  gutil = require('gulp-util'),
  bower = require('gulp-bower'),
  sass = require('gulp-sass'),
  jade = require('gulp-jade'),
  mocha = require('gulp-mocha'),
  Server = require('karma').Server,
  imagemin = require('gulp-imagemin'),
  notify = require('gulp-notify'),
  browserify = require('browserify'),
  source = require('vinyl-source-stream'),

  path = {
    public: 'public/',
    app: {
      js: 'app/**/*.js',
      sass: 'app/sass/*.scss',
      jade: ['app/*.jade', '!app/shared/**', 'app/**/*.jade'],
      img: 'app/img/*.*',
      staticFiles: [
        '!app/**/*.+(scss|css|js|jade)',
        '!app/img/**/*',
        'app/**/*.*'
      ]
    },
    serverTests: ['./spec/server/**/*.spec.js'],
    unitTests: [
      'public/lib/angular/angular.js',
      'public/lib/angular-ui-router/release/angular-ui-router.min.js',
      'public/lib/angular-aria/angular-aria.min.js',
      'public/lib/angular-route/angular-route.min.js',
      'public/lib/angular-mocks/angular-mocks.js',
      'public/lib/angular-sanitize/angular-sanitize.min.js',
      'public/lib/angular-animate/angular-animate.min.js',
      'public/lib/angular-material/angular-material.min.js',
      'public/lib/angular-resource/angular-resource.min.js',
      'public/lib/ng-file-upload/ng-file-upload-shim.js',
      'public/lib/lodash/lodash.js',
      'public/lib/cloudinary-core/cloudinary-core.js',
      'public/lib/cloudinary_ng/js/angular.cloudinary.js',
      'public/lib/ng-file-upload/ng-file-upload.js',
      'public/lib/angular-material-data-table/dist/md-data-table.min.js',

      //tinyMCE script
      'public/lib/tinymce-dist/tinymce.js',
      'public/lib/angular-ui-tinymce/src/tinymce.js',

      // Font Awesome dependency
      'public/lib/font-awesome/css/font-awesome.css',
      'public/js/application.js',
      'spec/unit/client/**/*.js'
    ]
  };

/**
 * [task to convert jade files to html]
 * @param  {[.jade]} 'jade' [files written in jade]
 * @return {[html]}        [files converted to html]
 */
gulp.task('jade', function() {
  return gulp.src(path.app.jade)
    .pipe(jade())
    .pipe(gulp.dest('./public/'))
    .pipe(notify('Gulp-jade Done!'));
});

/**
 * [task to convert sass files to css]
 * @param  {[.scss]} 'sass' [files written in scss]
 * @return {[css]}        [files converted to css]
 */
gulp.task('sass', function() {
  return gulp.src(path.app.sass)
    .pipe(sass())
    .pipe(gulp.dest('./public/css'))
    .pipe(notify('Gulp-sass Done!'));
});

/**
 * [task to minify images]
 * @param  {[.jpg, .png]} 'images' [images]
 * @return {[.jpg, .png]}          [minified image]
 */
gulp.task('images', function() {
  return gulp.src(path.app.img)
    .pipe(imagemin({
      optimizationLevel: 3,
      progressive: true,
      interlaced: true
    }))
    .pipe(gulp.dest('./public/img'))
    .pipe(notify('Gulp-imagemin Done!'));
});

/**
 * [task to minify css files]
 * @param  {[.css]} 'minCss' [files to be minified]
 * @return {[.css]}          [minified css file]
 */
gulp.task('minCss', function() {
  return gulp.src('public/css/*.css')
    .pipe(minifyCss())
    .pipe(gulp.dest('./public/css'))
    .pipe(notify('Gulp-minify-css Done!'));
});

/**
 * [task to enable bower components install dependencies]
 */
gulp.task('bower', function() {
  return bower()
    .pipe(gulp.dest('./public/lib/'));
});

/**
 * [task to start the api server]
 */
gulp.task('server', function() {
  nodemon({
      script: 'server.js',
      ext: 'js html',
      env: {
        'NODE_ENV': 'development'
      },
      ignore: ['public/**', 'client/**', 'node_modules/**']
    })
    .on('restart', ['jade', 'sass'], function() {
      console.log('Server restarted!');
    });
});

/**
 * [task to handle static files]
 */
gulp.task('static-files', function() {
  return gulp.src(path.app.staticFiles)
    .pipe(gulp.dest('public/'));
});

gulp.task('browserify', function() {
  return browserify('./app/js/app.js').bundle()
    .on('success', gutil.log.bind(gutil, 'Browserify Rebundled'))
    .on('error', gutil.log.bind(gutil, 'Browserify ' +
      'Error: in browserify gulp task'))
    // vinyl-source-stream makes the bundle compatible with gulp
    .pipe(source('application.js')) // Desired filename
    // Output the file
    .pipe(gulp.dest('./public/js/'))
    .pipe(notify('Browserify Done!'));
});

gulp.task('test:fend', ['build'], function(done) {
  // Be sure to return the stream
  return new Server({
    configFile: __dirname + '/karma.conf.js',
    singleRun: true
  },done()).start();
});

gulp.task('test:bend', ['test:fend'], function() {
  return gulp.src(path.serverTests)
    .pipe(mocha({
      reporter: 'spec'
    }))
    .once('error', function(err) {
      throw err;
    });
});

/**
 * [task to watch for changes]
 */
gulp.task('watchers', function() {
  // gulp.watch(path.app.js,['minify']);
  gulp.watch(path.app.sass, ['sass']);
  gulp.watch(path.app.jade, ['jade']);
  gulp.watch(path.app.js, ['browserify']);
});

gulp.task('build', ['jade', 'sass', 'static-files', 'images',
  'browserify', 'bower'
]);

gulp.task('dev', ['watchers']);
gulp.task('production', ['minifyJs', 'minifyCss']);
gulp.task('default', ['server', 'watchers', 'build']);
<commit_msg>Redesign Admin view [Fixes #114650271]<commit_after>var gulp = require('gulp'),
  minifyCss = require('gulp-minify-css'),
  nodemon = require('gulp-nodemon'),
  gutil = require('gulp-util'),
  bower = require('gulp-bower'),
  sass = require('gulp-sass'),
  jade = require('gulp-jade'),
  mocha = require('mocha'),
  Server = require('karma').Server,
  imagemin = require('gulp-imagemin'),
  notify = require('gulp-notify'),
  browserify = require('browserify'),
  source = require('vinyl-source-stream'),

  path = {
    public: 'public/',
    app: {
      js: 'app/**/*.js',
      sass: 'app/sass/*.scss',
      jade: ['app/*.jade', '!app/shared/**', 'app/**/*.jade'],
      img: 'app/img/*.*',
      staticFiles: [
        '!app/**/*.+(scss|css|js|jade)',
        '!app/img/**/*',
        'app/**/*.*'
      ]
    },
    serverTests: ['./spec/server/**/*.spec.js'],
    unitTests: [
      'public/lib/angular/angular.js',
      'public/lib/angular-ui-router/release/angular-ui-router.min.js',
      'public/lib/angular-aria/angular-aria.min.js',
      'public/lib/angular-route/angular-route.min.js',
      'public/lib/angular-mocks/angular-mocks.js',
      'public/lib/angular-sanitize/angular-sanitize.min.js',
      'public/lib/angular-animate/angular-animate.min.js',
      'public/lib/angular-material/angular-material.min.js',
      'public/lib/angular-resource/angular-resource.min.js',
      'public/lib/ng-file-upload/ng-file-upload-shim.js',
      'public/lib/lodash/lodash.js',
      'public/lib/cloudinary-core/cloudinary-core.js',
      'public/lib/cloudinary_ng/js/angular.cloudinary.js',
      'public/lib/ng-file-upload/ng-file-upload.js',
      'public/lib/angular-material-data-table/dist/md-data-table.min.js',

      //tinyMCE script
      'public/lib/tinymce-dist/tinymce.js',
      'public/lib/angular-ui-tinymce/src/tinymce.js',

      // Font Awesome dependency
      'public/lib/font-awesome/css/font-awesome.css',
      'public/js/application.js',
      'spec/unit/client/**/*.js'
    ]
  };

/**
 * [task to convert jade files to html]
 * @param  {[.jade]} 'jade' [files written in jade]
 * @return {[html]}        [files converted to html]
 */
gulp.task('jade', function() {
  return gulp.src(path.app.jade)
    .pipe(jade())
    .pipe(gulp.dest('./public/'))
    .pipe(notify('Gulp-jade Done!'));
});

/**
 * [task to convert sass files to css]
 * @param  {[.scss]} 'sass' [files written in scss]
 * @return {[css]}        [files converted to css]
 */
gulp.task('sass', function() {
  return gulp.src(path.app.sass)
    .pipe(sass())
    .pipe(gulp.dest('./public/css'))
    .pipe(notify('Gulp-sass Done!'));
});

/**
 * [task to minify images]
 * @param  {[.jpg, .png]} 'images' [images]
 * @return {[.jpg, .png]}          [minified image]
 */
gulp.task('images', function() {
  return gulp.src(path.app.img)
    .pipe(imagemin({
      optimizationLevel: 3,
      progressive: true,
      interlaced: true
    }))
    .pipe(gulp.dest('./public/img'))
    .pipe(notify('Gulp-imagemin Done!'));
});

/**
 * [task to minify css files]
 * @param  {[.css]} 'minCss' [files to be minified]
 * @return {[.css]}          [minified css file]
 */
gulp.task('minCss', function() {
  return gulp.src('public/css/*.css')
    .pipe(minifyCss())
    .pipe(gulp.dest('./public/css'))
    .pipe(notify('Gulp-minify-css Done!'));
});

/**
 * [task to enable bower components install dependencies]
 */
gulp.task('bower', function() {
  return bower()
    .pipe(gulp.dest('./public/lib/'));
});

/**
 * [task to start the api server]
 */
gulp.task('server', function() {
  nodemon({
      script: 'server.js',
      ext: 'js html',
      env: {
        'NODE_ENV': 'development'
      },
      ignore: ['public/**', 'client/**', 'node_modules/**']
    })
    .on('restart', ['jade', 'sass'], function() {
      console.log('Server restarted!');
    });
});

/**
 * [task to handle static files]
 */
gulp.task('static-files', function() {
  return gulp.src(path.app.staticFiles)
    .pipe(gulp.dest('public/'));
});

gulp.task('browserify', function() {
  return browserify('./app/js/app.js').bundle()
    .on('success', gutil.log.bind(gutil, 'Browserify Rebundled'))
    .on('error', gutil.log.bind(gutil, 'Browserify ' +
      'Error: in browserify gulp task'))
    // vinyl-source-stream makes the bundle compatible with gulp
    .pipe(source('application.js')) // Desired filename
    // Output the file
    .pipe(gulp.dest('./public/js/'))
    .pipe(notify('Browserify Done!'));
});

gulp.task('test:fend', ['build'], function(done) {
  // Be sure to return the stream
  return new Server({
    configFile: __dirname + '/karma.conf.js',
    singleRun: true
  },done()).start();
});

gulp.task('test:bend', ['test:fend'], function() {
  return gulp.src(path.serverTests)
    .pipe(mocha({
      reporter: 'spec'
    }))
    .once('error', function(err) {
      throw err;
    });
});

/**
 * [task to watch for changes]
 */
gulp.task('watchers', function() {
  // gulp.watch(path.app.js,['minify']);
  gulp.watch(path.app.sass, ['sass']);
  gulp.watch(path.app.jade, ['jade']);
  gulp.watch(path.app.js, ['browserify']);
});

gulp.task('build', ['jade', 'sass', 'static-files', 'images',
  'browserify', 'bower'
]);

gulp.task('dev', ['watchers']);
gulp.task('production', ['minifyJs', 'minifyCss']);
gulp.task('default', ['server', 'watchers', 'build']);
<|endoftext|>


<commit_before>/*
 * IDBWrapper - A cross-browser wrapper for IndexedDB
 * Copyright (c) 2011 Jens Arps
 * http://jensarps.de/
 *
 * Licensed under the MIT (X11) license
 */

(function(name, definition, global){
	if (typeof define === 'function'){
		define(definition);
	} else {
		global[name] = definition();
	}
})('IDBStore', function(){

	var IDBStore;

	var defaults = {
		dbName: 'IDB',
		storeName: 'Store',
		dbVersion: '1.0',
		keyPath: 'id',
		autoIncrement: true,
		onStoreReady: function(){}
	};

	IDBStore = function(kwArgs, onStoreReady){
		mixin(this, defaults);
		mixin(this, kwArgs);
		onStoreReady && (this.onStoreReady = onStoreReady);
		this.idb = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.msIndexedDB;
		this.consts = window.IDBTransaction || window.webkitIDBTransaction || window.msIndexedDB;
		this.openDB();
	};

	IDBStore.prototype = {

		db: null,

		dbName: null,

		dbDescription: null,

		dbVersion: null,

		store: null,

		storeName: null,

		keyPath: null,

		autoIncrement: null,

		features: null,

		onStoreReady: null,

		openDB: function(){
			var openRequest = this.idb.open(this.dbName, this.dbDescription);
			openRequest.onerror = function(error){ console.error('Could not open database.', error); };
			openRequest.onsuccess = hitch(this, function(event){
				this.db = event.target.result;
				this.checkVersion(hitch(this, function(){
					this.getObjectStore(hitch(this, function(){
						this.testFeatures(this.onStoreReady)
					}));
				}));
			});
		},

		testFeatures: function(callback){
			var features = this.features = {};

			// In Chrome, there's no getAll method (getAll is not part of the spec, but handy)
			var getAllTransaction = this.db.transaction([this.storeName], this.consts.READ_ONLY);
			features.hasGetAll = !!getAllTransaction.objectStore(this.storeName).getAll;
			getAllTransaction.abort();

			// In FF, autoIncrement doesn't work.
			// We won't test for that, as testing
			// sometimes fails in Chrome (it's a long
			// story).
			features.hasAutoIncrement = !window.mozIndexedDB;

			callback && callback();
		},

		/**************
		 * versioning *
		 **************/

		checkVersion: function(onSuccess, onError){
			if(this.getVersion() != this.dbVersion){
				this.setVersion(onSuccess, onError);
			}else{
				onSuccess && onSuccess();
			}
		},

		getVersion: function(){
			return this.db.version;
		},

		setVersion: function(onSuccess, onError){
			onError || (onError = function(error){ console.error('Failed to set version.', error); });
			var versionRequest = this.db.setVersion(this.dbVersion);
			versionRequest.onerror = onError;
			versionRequest.onblocked = onError;
			versionRequest.onsuccess = onSuccess;
		},

		/*************************
		 * object store handling *
		 *************************/

		getObjectStore: function(onSuccess, onError){
			if(this.hasObjectStore()){
				this.openExistingObjectStore(onSuccess, onError);
			}else{
				this.createNewObjectStore(onSuccess, onError);
			}
		},

		hasObjectStore: function(){
			return this.db.objectStoreNames.contains(this.storeName);
		},

		createNewObjectStore: function(onSuccess, onError){
			this.setVersion(hitch(this, function(){
				this.store = this.db.createObjectStore(this.storeName, { keyPath: this.keyPath, autoIncrement: this.autoIncrement});
				onSuccess && onSuccess(this.store);
			}), onError);
		},

		openExistingObjectStore: function(onSuccess, onError){
			var emptyTransaction = this.db.transaction([], this.consts.READ_ONLY, 0);
			this.store = emptyTransaction.objectStore(this.storeName);
			onSuccess && onSuccess(this.store);
		},

		deleteObjectStore: function(onSuccess, onError){
			onError || (onError = function(error){ console.error('Failed to delete objectStore.', error); });
			this.setVersion(hitch(this, function(){
				this.db.deleteObjectStore(this.storeName);
				var success = !this.hasObjectStore();
				onSuccess && success && onSuccess();
				onError && !success && onError();
			}), onError);
		},

		/*********************
		 * data manipulation *
		 *********************/

		put: function(dataObj, onSuccess, onError){
			onError || (onError = function(error) { console.error('Could not write data.', error); });
			onSuccess || (onSuccess = noop);
			if(typeof dataObj[this.keyPath] == 'undefined' && !this.features.hasAutoIncrement){
				dataObj[this.keyPath] = this._getUID();
			}
			var putTransaction = this.db.transaction([this.storeName], this.consts.READ_WRITE, 1000);
			var putRequest = putTransaction.objectStore(this.storeName).put(dataObj);
			putRequest.onsuccess = function(event){ onSuccess(event.target.result); };
			putRequest.onerror = onError;
		},

		get: function(key, onSuccess, onError){
			onError || (onError = function(error) { console.error('Could not read data.', error); });
			onSuccess || (onSuccess = noop);
			var getTransaction = this.db.transaction([this.storeName], this.consts.READ_ONLY, 1000);
			var getRequest = getTransaction.objectStore(this.storeName).get(key);
			getRequest.onsuccess = function(event){ onSuccess(event.target.result); };
			getRequest.onerror = onError;
		},

		remove: function(key, onSuccess, onError){
			onError || (onError = function(error) { console.error('Could not remove data.', error); });
			onSuccess || (onSuccess = noop);
			var removeTransaction = this.db.transaction([this.storeName], this.consts.READ_WRITE);
			var deleteRequest = removeTransaction.objectStore(this.storeName).delete(key);
			deleteRequest.onsuccess = function(event){ onSuccess(event.target.result); };
			deleteRequest.onerror = onError;
		},

		getAll: function(onSuccess, onError){
			onError || (onError = function(error) { console.error('Could not read data.', error); });
			onSuccess || (onSuccess = noop);
			var getAllTransaction = this.db.transaction([this.storeName], this.consts.READ_ONLY);
			if(this.features.hasGetAll){
				var getAllRequest = getAllTransaction.objectStore(this.storeName).getAll();
				getAllRequest.onsuccess = function(event){ onSuccess(event.target.result); };
				getAllRequest.onerror = onError;
			}else{
				this._getAllCursor(getAllTransaction, onSuccess, onError);
			}
		},

		_getAllCursor: function(tr, onSuccess, onError){
			var all = [];
			var store = tr.objectStore(this.storeName);
			var cursorRequest = store.openCursor();

			cursorRequest.onsuccess = function(event) {
				var cursor = event.target.result;
				if (cursor) {
					all.push(cursor.value);
					cursor.continue();
				}
				else {
					onSuccess(all);
				}
			};
			cursorRequest.onError = onError;
		},

		clear: function(onSuccess, onError){
			onError || (onError = function(error) { console.error('Could not clear store.', error); });
			onSuccess || (onSuccess = noop);
			var clearTransaction = this.db.transaction([this.storeName], this.consts.READ_WRITE);
			var clearRequest = clearTransaction.objectStore(this.storeName).clear();
			clearRequest.onsuccess = function(event){ onSuccess(event.target.result); };
			clearRequest.onerror = onError;
		},

		_getUID: function(){
			// FF bails at times on non-numeric ids. So we take an even
			// worse approach now, using current time as id. Sigh.
			return +new Date();
		},

		/************
		 * indexing *
		 ************/

		createIndex: function(indexName, propertyName, isUnique, onSuccess, onError){
			onError || (onError = function(error) { console.error('Could not create index.', error); });
			onSuccess || (onSuccess = noop);
			propertyName || (propertyName = indexName);
			this.setVersion(hitch(this, function(evt){
				var index = evt.target.result.objectStore(this.storeName).createIndex(indexName, propertyName, { unique: !!isUnique });
				onSuccess(index);
			}), onError);
		},

		getIndex: function(indexName){
			return this.store.index(indexName);
		},

		getIndexList: function(){
			return this.store.indexNames;
		},

		hasIndex: function(indexName){
			return this.store.indexNames.contains(indexName);
		},

		removeIndex: function(indexName, onSuccess, onError){
			onError || (onError = function(error) { console.error('Could not remove index.', error); });
			onSuccess || (onSuccess = noop);
			this.setVersion(hitch(this, function(evt){
				evt.target.result.objectStore(this.storeName).deleteIndex(indexName);
				onSuccess();
			}), onError);
		},

		/* key ranges / cursors */
		// TODO: implement

	};

	/** helpers **/

	var noop = function(){};
	var empty = {};
	var mixin = function(target, source){
		var name, s;
		for(name in source){
			s = source[name];
			if(s !== empty[name] && s !== target[name]){
				target[name] = s;
			}
		}
		return target;
	};
	var hitch = function (scope, method){
		if(!method){ method = scope; scope = null; }
		if(typeof method == "string"){
			scope = scope || window;
			if(!scope[method]){ throw(['method not found']); }
			return function(){ return scope[method].apply(scope, arguments || []); };
		}
		return !scope ? method : function(){ return method.apply(scope, arguments || []); };
	};

	return IDBStore;

}, this);<commit_msg>Timeouts have been removed from spec.<commit_after>/*
 * IDBWrapper - A cross-browser wrapper for IndexedDB
 * Copyright (c) 2011 Jens Arps
 * http://jensarps.de/
 *
 * Licensed under the MIT (X11) license
 */

(function(name, definition, global){
	if (typeof define === 'function'){
		define(definition);
	} else {
		global[name] = definition();
	}
})('IDBStore', function(){

	var IDBStore;

	var defaults = {
		dbName: 'IDB',
		storeName: 'Store',
		dbVersion: '1.0',
		keyPath: 'id',
		autoIncrement: true,
		onStoreReady: function(){}
	};

	IDBStore = function(kwArgs, onStoreReady){
		mixin(this, defaults);
		mixin(this, kwArgs);
		onStoreReady && (this.onStoreReady = onStoreReady);
		this.idb = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.msIndexedDB;
		this.consts = window.IDBTransaction || window.webkitIDBTransaction || window.msIndexedDB;
		this.openDB();
	};

	IDBStore.prototype = {

		db: null,

		dbName: null,

		dbDescription: null,

		dbVersion: null,

		store: null,

		storeName: null,

		keyPath: null,

		autoIncrement: null,

		features: null,

		onStoreReady: null,

		openDB: function(){
			var openRequest = this.idb.open(this.dbName, this.dbDescription);
			openRequest.onerror = function(error){ console.error('Could not open database.', error); };
			openRequest.onsuccess = hitch(this, function(event){
				this.db = event.target.result;
				this.checkVersion(hitch(this, function(){
					this.getObjectStore(hitch(this, function(){
						this.testFeatures(this.onStoreReady)
					}));
				}));
			});
		},

		testFeatures: function(callback){
			var features = this.features = {};

			// In Chrome, there's no getAll method (getAll is not part of the spec, but handy)
			var getAllTransaction = this.db.transaction([this.storeName], this.consts.READ_ONLY);
			features.hasGetAll = !!getAllTransaction.objectStore(this.storeName).getAll;
			getAllTransaction.abort();

			// In FF, autoIncrement doesn't work.
			// We won't test for that, as testing
			// sometimes fails in Chrome (it's a long
			// story).
			features.hasAutoIncrement = !window.mozIndexedDB;

			callback && callback();
		},

		/**************
		 * versioning *
		 **************/

		checkVersion: function(onSuccess, onError){
			if(this.getVersion() != this.dbVersion){
				this.setVersion(onSuccess, onError);
			}else{
				onSuccess && onSuccess();
			}
		},

		getVersion: function(){
			return this.db.version;
		},

		setVersion: function(onSuccess, onError){
			onError || (onError = function(error){ console.error('Failed to set version.', error); });
			var versionRequest = this.db.setVersion(this.dbVersion);
			versionRequest.onerror = onError;
			versionRequest.onblocked = onError;
			versionRequest.onsuccess = onSuccess;
		},

		/*************************
		 * object store handling *
		 *************************/

		getObjectStore: function(onSuccess, onError){
			if(this.hasObjectStore()){
				this.openExistingObjectStore(onSuccess, onError);
			}else{
				this.createNewObjectStore(onSuccess, onError);
			}
		},

		hasObjectStore: function(){
			return this.db.objectStoreNames.contains(this.storeName);
		},

		createNewObjectStore: function(onSuccess, onError){
			this.setVersion(hitch(this, function(){
				this.store = this.db.createObjectStore(this.storeName, { keyPath: this.keyPath, autoIncrement: this.autoIncrement});
				onSuccess && onSuccess(this.store);
			}), onError);
		},

		openExistingObjectStore: function(onSuccess, onError){
			var emptyTransaction = this.db.transaction([], this.consts.READ_ONLY);
			this.store = emptyTransaction.objectStore(this.storeName);
			onSuccess && onSuccess(this.store);
		},

		deleteObjectStore: function(onSuccess, onError){
			onError || (onError = function(error){ console.error('Failed to delete objectStore.', error); });
			this.setVersion(hitch(this, function(){
				this.db.deleteObjectStore(this.storeName);
				var success = !this.hasObjectStore();
				onSuccess && success && onSuccess();
				onError && !success && onError();
			}), onError);
		},

		/*********************
		 * data manipulation *
		 *********************/

		put: function(dataObj, onSuccess, onError){
			onError || (onError = function(error) { console.error('Could not write data.', error); });
			onSuccess || (onSuccess = noop);
			if(typeof dataObj[this.keyPath] == 'undefined' && !this.features.hasAutoIncrement){
				dataObj[this.keyPath] = this._getUID();
			}
			var putTransaction = this.db.transaction([this.storeName], this.consts.READ_WRITE);
			var putRequest = putTransaction.objectStore(this.storeName).put(dataObj);
			putRequest.onsuccess = function(event){ onSuccess(event.target.result); };
			putRequest.onerror = onError;
		},

		get: function(key, onSuccess, onError){
			onError || (onError = function(error) { console.error('Could not read data.', error); });
			onSuccess || (onSuccess = noop);
			var getTransaction = this.db.transaction([this.storeName], this.consts.READ_ONLY);
			var getRequest = getTransaction.objectStore(this.storeName).get(key);
			getRequest.onsuccess = function(event){ onSuccess(event.target.result); };
			getRequest.onerror = onError;
		},

		remove: function(key, onSuccess, onError){
			onError || (onError = function(error) { console.error('Could not remove data.', error); });
			onSuccess || (onSuccess = noop);
			var removeTransaction = this.db.transaction([this.storeName], this.consts.READ_WRITE);
			var deleteRequest = removeTransaction.objectStore(this.storeName).delete(key);
			deleteRequest.onsuccess = function(event){ onSuccess(event.target.result); };
			deleteRequest.onerror = onError;
		},

		getAll: function(onSuccess, onError){
			onError || (onError = function(error) { console.error('Could not read data.', error); });
			onSuccess || (onSuccess = noop);
			var getAllTransaction = this.db.transaction([this.storeName], this.consts.READ_ONLY);
			if(this.features.hasGetAll){
				var getAllRequest = getAllTransaction.objectStore(this.storeName).getAll();
				getAllRequest.onsuccess = function(event){ onSuccess(event.target.result); };
				getAllRequest.onerror = onError;
			}else{
				this._getAllCursor(getAllTransaction, onSuccess, onError);
			}
		},

		_getAllCursor: function(tr, onSuccess, onError){
			var all = [];
			var store = tr.objectStore(this.storeName);
			var cursorRequest = store.openCursor();

			cursorRequest.onsuccess = function(event) {
				var cursor = event.target.result;
				if (cursor) {
					all.push(cursor.value);
					cursor.continue();
				}
				else {
					onSuccess(all);
				}
			};
			cursorRequest.onError = onError;
		},

		clear: function(onSuccess, onError){
			onError || (onError = function(error) { console.error('Could not clear store.', error); });
			onSuccess || (onSuccess = noop);
			var clearTransaction = this.db.transaction([this.storeName], this.consts.READ_WRITE);
			var clearRequest = clearTransaction.objectStore(this.storeName).clear();
			clearRequest.onsuccess = function(event){ onSuccess(event.target.result); };
			clearRequest.onerror = onError;
		},

		_getUID: function(){
			// FF bails at times on non-numeric ids. So we take an even
			// worse approach now, using current time as id. Sigh.
			return +new Date();
		},

		/************
		 * indexing *
		 ************/

		createIndex: function(indexName, propertyName, isUnique, onSuccess, onError){
			onError || (onError = function(error) { console.error('Could not create index.', error); });
			onSuccess || (onSuccess = noop);
			propertyName || (propertyName = indexName);
			this.setVersion(hitch(this, function(evt){
				var index = evt.target.result.objectStore(this.storeName).createIndex(indexName, propertyName, { unique: !!isUnique });
				onSuccess(index);
			}), onError);
		},

		getIndex: function(indexName){
			return this.store.index(indexName);
		},

		getIndexList: function(){
			return this.store.indexNames;
		},

		hasIndex: function(indexName){
			return this.store.indexNames.contains(indexName);
		},

		removeIndex: function(indexName, onSuccess, onError){
			onError || (onError = function(error) { console.error('Could not remove index.', error); });
			onSuccess || (onSuccess = noop);
			this.setVersion(hitch(this, function(evt){
				evt.target.result.objectStore(this.storeName).deleteIndex(indexName);
				onSuccess();
			}), onError);
		},

		/* key ranges / cursors */
		// TODO: implement

	};

	/** helpers **/

	var noop = function(){};
	var empty = {};
	var mixin = function(target, source){
		var name, s;
		for(name in source){
			s = source[name];
			if(s !== empty[name] && s !== target[name]){
				target[name] = s;
			}
		}
		return target;
	};
	var hitch = function (scope, method){
		if(!method){ method = scope; scope = null; }
		if(typeof method == "string"){
			scope = scope || window;
			if(!scope[method]){ throw(['method not found']); }
			return function(){ return scope[method].apply(scope, arguments || []); };
		}
		return !scope ? method : function(){ return method.apply(scope, arguments || []); };
	};

	return IDBStore;

}, this);<|endoftext|>


<commit_before>var fs = require('fs')
  , path = require('path')
  , VERSION = fs.readFileSync(path.join(process.cwd() + '/VERSION'), 'utf-8')

function concat(fileList, destPath) {
  var out = fileList.map(function (filePath) {
    var file = fs.readFileSync(filePath, 'utf-8')
    file = file.replace(/@VERSION/g, VERSION)
    return file
  })
  fs.writeFileSync(destPath, out.join('\n'))
}

function colorize(str, color) {
  var colors =
    { 'blue': '34m'
    , 'cyan': '36m'
    , 'green': '01;32m'
    , 'magenta': '35m'
    , 'red': '31m'
    , 'yellow': '33m'
    }

  return colors[color] ? '\033[' + colors[color] + str + '\033[39m' : str
}

desc('Lint all js files')
task('lint', [], function () {
  jake.Task['lint:all'].invoke();
}, {async: true})

namespace('lint', function () {
  var cwd = process.cwd()
    , jakefile = path.join(cwd + '/Jakefile.js')
    , jshintrc = path.join(cwd + '/.jshintrc')
    , editor = path.join(cwd + '/src/editor.js')
    , spec = path.join(cwd + '/spec/spec.js')
    , docs = path.join(cwd + '/docs/js/main.js')

  task('all', ['lint:editor', 'lint:docs', 'lint:spec', 'lint:util'], function () {
    complete()
  }, {async: true})

  desc('Lint core EpicEditor: src/editor.js')
  task('editor', [], function () {
    console.log(colorize('--> Linting editor', 'yellow'))
    var cwd = process.cwd()
      , files = [ editor ]
      , cmds = ['jshint ' + files.join(' ') + ' --config .jshintrc']

    jake.exec(cmds, function () {
      console.log(colorize('  √ ok', 'green'))
      complete()
    }, {stdout: true})
  }, {async: true})

  desc('Lint doc related js: docs/js/main.js')
  task('docs', [], function () {
    console.log(colorize('--> Linting docs', 'yellow'))
    var cwd = process.cwd()
      , files = [ docs ]
      , cmds = ['jshint ' + files.join(' ') + ' --config .jshintrc']

    jake.exec(cmds, function () {
      console.log(colorize('  √ ok', 'green'))
      complete()
    }, {stdout: true})
  }, {async: true})

  desc('Lint test related js: spec/spec.js')
  task('spec', [], function () {
    console.log(colorize('--> Linting specs', 'yellow'))
    var cwd = process.cwd()
      , files = [ spec ]
      , cmds = ['jshint ' + files.join(' ') + ' --config .jshintrc']

    jake.exec(cmds, function () {
      console.log(colorize('  √ ok', 'green'))
      complete()
    }, {stdout: true})
  }, {async: true})

  desc('Lint utility and config js files')
  task('util', [], function () {
    console.log(colorize('--> Linting utils', 'yellow'))
    var cwd = process.cwd()
      , files = [ jshintrc, jakefile ]
      , cmds = ['jshint ' + files.join(' ') + ' --config .jshintrc --extra-ext .jshintrc']

    jake.exec(cmds, function () {
      console.log(colorize('  √ ok', 'green'))
      complete()
    }, {stdout: true})
  }, {async: true})
})

desc('Build epiceditor.js and minify to epiceditor.min.js')
task('build', ['lint:editor'], function () {
  console.log(colorize('--> Building', 'yellow'))
  var destDir = path.join(process.cwd() + '/epiceditor/js/')
    , srcDir = path.join(process.cwd() + '/src/')
    , parser = process.env.parser ? process.env.parser : srcDir + 'marked/lib/marked.js'
    , srcPaths =
      [ srcDir + 'editor.js'
      , parser
      ]
    , destPath = destDir + 'epiceditor.js'
    , destPathMin = destDir + 'epiceditor.min.js'
    , cmds = ['git submodule update --init', 'uglifyjs ' + destPath + ' > ' + destPathMin]

  // If the destination directory does not exist, create it
  jake.mkdirP('epiceditor/js')

  if (!path.existsSync(parser)) {
    fail("Parser path not found.")
  }

  concat(srcPaths, destPath)

  // Minify
  jake.exec(cmds, function () {
    console.log(colorize('  √ ok', 'green'))
    complete()
  }, {stdout: true})
}, {async: true})

namespace('build', function () {
  desc('Force build epiceditor.js and epiceditor.min.js skipping pre-reqs')
  task('force', [], function () {
    console.log(colorize('--> Warning: Force build skips build pre-reqs. This build should not be commited.', 'magenta'))
    jake.Task['build'].execute()
  })
})

desc('Build index.html from the README')
task('docs', ['lint:docs'], function () {
  console.log(colorize('--> Building docs', 'yellow'))
  var destDir = path.join(process.cwd() + '/')
    , srcDir = path.join(process.cwd() + '/docs/')
    , readmePath = destDir + 'README.md'
    , tempPath = srcDir + 'README.html'
    , destPath = destDir + 'index.html'
    , srcPaths =
      [ srcDir + 'header.html'
      , tempPath
      , srcDir + 'footer.html'
      ]
    , cmds = ['marked -o ' + tempPath + ' -i ' + readmePath + ' --gfm']

  jake.exec(cmds, function () {
    concat(srcPaths, destPath)
    // remove temporary README.html
    fs.unlink(tempPath)
    console.log(colorize('  √ ok', 'green'))
    complete()
  }, {stdout: true})
}, {async: true})

desc('Test code against specs')
task('test', ['lint:spec'], function () {
  console.log(colorize('--> Test suite is now running (CTRL+C to quit)', 'magenta'))
  console.log(colorize('--> http://localhost:5057/spec/runner.html', 'yellow'))
  jake.exec(['foounit serve'], function () {
    complete()
  }, {stdout: false})
}, {async: true})

var pkg = new jake.PackageTask('EpicEditor', 'v' + VERSION, function () {
  var fileList = [ 'epiceditor']
  this.packageDir = "docs/downloads"
  this.packageFiles.include(fileList);
  this.needZip = true;
})

desc('Kick out some ascii')
task('ascii', [], function () {
  var epicAscii = "" +
      "                                           \n" +
      "                               ',          \n" +
      "                    .eee.     .'           \n" +
      "                  .eeEEEEEe.               \n" +
      " EEEEEEEEEEEE'  .E'   `eEE'  .EEEEEEEEEEE  \n" +
      " EE           .E'    eEE`  .E          EE  \n" +
      " EE         .E'    eEE`    EE          EE  \n" +
      " EE       .E'    eEE`      EE              \n" +
      " EE     .E'    eEE`        EEEEEEEEEE      \n" +
      " EE          eEE`          EE              \n" +
      " EE   .    `eE`            EE              \n" +
      " EE   Ee'                  EE          EE  \n" +
      " EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE  \n"
  console.log(colorize(epicAscii, 'yellow'))
  console.log(colorize('EpicEditor - An Embeddable JavaScript Markdown Editor', 'yellow'))
})<commit_msg>ensure submodule init before parser check<commit_after>var fs = require('fs')
  , path = require('path')
  , VERSION = fs.readFileSync(path.join(process.cwd() + '/VERSION'), 'utf-8')

function concat(fileList, destPath) {
  var out = fileList.map(function (filePath) {
    var file = fs.readFileSync(filePath, 'utf-8')
    file = file.replace(/@VERSION/g, VERSION)
    return file
  })
  fs.writeFileSync(destPath, out.join('\n'))
}

function colorize(str, color) {
  var colors =
    { 'blue': '34m'
    , 'cyan': '36m'
    , 'green': '01;32m'
    , 'magenta': '35m'
    , 'red': '31m'
    , 'yellow': '33m'
    }

  return colors[color] ? '\033[' + colors[color] + str + '\033[39m' : str
}

desc('Lint all js files')
task('lint', [], function () {
  jake.Task['lint:all'].invoke();
}, {async: true})

namespace('lint', function () {
  var cwd = process.cwd()
    , jakefile = path.join(cwd + '/Jakefile.js')
    , jshintrc = path.join(cwd + '/.jshintrc')
    , editor = path.join(cwd + '/src/editor.js')
    , spec = path.join(cwd + '/spec/spec.js')
    , docs = path.join(cwd + '/docs/js/main.js')

  task('all', ['lint:editor', 'lint:docs', 'lint:spec', 'lint:util'], function () {
    complete()
  }, {async: true})

  desc('Lint core EpicEditor: src/editor.js')
  task('editor', [], function () {
    console.log(colorize('--> Linting editor', 'yellow'))
    var cwd = process.cwd()
      , files = [ editor ]
      , cmds = ['jshint ' + files.join(' ') + ' --config .jshintrc']

    jake.exec(cmds, function () {
      console.log(colorize('  √ ok', 'green'))
      complete()
    }, {stdout: true})
  }, {async: true})

  desc('Lint doc related js: docs/js/main.js')
  task('docs', [], function () {
    console.log(colorize('--> Linting docs', 'yellow'))
    var cwd = process.cwd()
      , files = [ docs ]
      , cmds = ['jshint ' + files.join(' ') + ' --config .jshintrc']

    jake.exec(cmds, function () {
      console.log(colorize('  √ ok', 'green'))
      complete()
    }, {stdout: true})
  }, {async: true})

  desc('Lint test related js: spec/spec.js')
  task('spec', [], function () {
    console.log(colorize('--> Linting specs', 'yellow'))
    var cwd = process.cwd()
      , files = [ spec ]
      , cmds = ['jshint ' + files.join(' ') + ' --config .jshintrc']

    jake.exec(cmds, function () {
      console.log(colorize('  √ ok', 'green'))
      complete()
    }, {stdout: true})
  }, {async: true})

  desc('Lint utility and config js files')
  task('util', [], function () {
    console.log(colorize('--> Linting utils', 'yellow'))
    var cwd = process.cwd()
      , files = [ jshintrc, jakefile ]
      , cmds = ['jshint ' + files.join(' ') + ' --config .jshintrc --extra-ext .jshintrc']

    jake.exec(cmds, function () {
      console.log(colorize('  √ ok', 'green'))
      complete()
    }, {stdout: true})
  }, {async: true})
})

desc('Build epiceditor.js and minify to epiceditor.min.js')
task('build', ['build:init', 'lint:editor'], function () {
  console.log(colorize('--> Building', 'yellow'))
  var destDir = path.join(process.cwd() + '/epiceditor/js/')
    , srcDir = path.join(process.cwd() + '/src/')
    , parser = process.env.parser ? process.env.parser : srcDir + 'marked/lib/marked.js'
    , srcPaths =
      [ srcDir + 'editor.js'
      , parser
      ]
    , destPath = destDir + 'epiceditor.js'
    , destPathMin = destDir + 'epiceditor.min.js'
    , cmds = ['uglifyjs ' + destPath + ' > ' + destPathMin]

  // If the destination directory does not exist, create it
  jake.mkdirP('epiceditor/js')

  if (!path.existsSync(parser)) {
    fail("Parser path not found.")
  }

  concat(srcPaths, destPath)

  // Minify
  jake.exec(cmds, function () {
    console.log(colorize('  √ ok', 'green'))
    complete()
  }, {stdout: true})
}, {async: true})

namespace('build', function () {
  desc('Force build epiceditor.js and epiceditor.min.js skipping pre-reqs')
  task('force', [], function () {
    console.log(colorize('--> Warning: Force build skips build pre-reqs. This build should not be commited.', 'magenta'))
    jake.Task['build'].execute()
  })

  task('init', [], function () {
    jake.exec(['git submodule update --init'], function () {
      complete();
    }, {stdout: true})
  }, {async: true})
})

desc('Build index.html from the README')
task('docs', ['lint:docs'], function () {
  console.log(colorize('--> Building docs', 'yellow'))
  var destDir = path.join(process.cwd() + '/')
    , srcDir = path.join(process.cwd() + '/docs/')
    , readmePath = destDir + 'README.md'
    , tempPath = srcDir + 'README.html'
    , destPath = destDir + 'index.html'
    , srcPaths =
      [ srcDir + 'header.html'
      , tempPath
      , srcDir + 'footer.html'
      ]
    , cmds = ['marked -o ' + tempPath + ' -i ' + readmePath + ' --gfm']

  jake.exec(cmds, function () {
    concat(srcPaths, destPath)
    // remove temporary README.html
    fs.unlink(tempPath)
    console.log(colorize('  √ ok', 'green'))
    complete()
  }, {stdout: true})
}, {async: true})

desc('Test code against specs')
task('test', ['lint:spec'], function () {
  console.log(colorize('--> Test suite is now running (CTRL+C to quit)', 'magenta'))
  console.log(colorize('--> http://localhost:5057/spec/runner.html', 'yellow'))
  jake.exec(['foounit serve'], function () {
    complete()
  }, {stdout: false})
}, {async: true})

var pkg = new jake.PackageTask('EpicEditor', 'v' + VERSION, function () {
  var fileList = [ 'epiceditor']
  this.packageDir = "docs/downloads"
  this.packageFiles.include(fileList);
  this.needZip = true;
})

desc('Kick out some ascii')
task('ascii', [], function () {
  var epicAscii = "" +
      "                                           \n" +
      "                               ',          \n" +
      "                    .eee.     .'           \n" +
      "                  .eeEEEEEe.               \n" +
      " EEEEEEEEEEEE'  .E'   `eEE'  .EEEEEEEEEEE  \n" +
      " EE           .E'    eEE`  .E          EE  \n" +
      " EE         .E'    eEE`    EE          EE  \n" +
      " EE       .E'    eEE`      EE              \n" +
      " EE     .E'    eEE`        EEEEEEEEEE      \n" +
      " EE          eEE`          EE              \n" +
      " EE   .    `eE`            EE              \n" +
      " EE   Ee'                  EE          EE  \n" +
      " EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE  \n"
  console.log(colorize(epicAscii, 'yellow'))
  console.log(colorize('EpicEditor - An Embeddable JavaScript Markdown Editor', 'yellow'))
})<|endoftext|>


<commit_before>var fs = require('fs');
var sys = require('sys');
var path = require('path');

var utils = require('./build/utils');
var mkjs = require('./build/mkjs');
var mkswf = require('./build/mkswf');
var mkxap = require('./build/mkxap');
var wiki = require('./build/wiki');
var tools = require('./build/tools');

var copyright = [
	"/**",
	" * mOxie - multi-runtime File API & XMLHttpRequest L2 Polyfill",
	" * v@@version@@",
	" *",
	" * Copyright 2013, Moxiecode Systems AB",
	" * Released under GPL License.",
	" *",
	" * License: http://www.plupload.com/license",
	" * Contributing: http://www.plupload.com/contributing",
	" *",
	" * Date: @@releasedate@@",
	" */"
].join("\n");

task("default", ["mkjs", "mkswf", "mkxap", "docs"], function (params) {});

desc("Build release package");
task("release", ["default", "package"], function (params) {});

desc("Runs JSHint on source files");
task("jshint", [], function (params) {
	jshint("src", {
		curly: true
	});
});

desc("Compile JS");
task("mkjs", [], function () {
	var amdlc = require('amdlc');
	var baseDir = "src/javascript", targetDir = "bin/js";

	var options = {
		compress: {
			unused: false,
			global_defs: {
				MXI_DEBUG: false
			}
		},
		baseDir: baseDir,
		rootNS: "moxie",
		expose: "public",
		verbose: true,
		outputSource: targetDir + "/moxie.js",
		outputMinified: targetDir + "/moxie.min.js",
		outputDev: targetDir + "/moxie.dev.js",
		outputCoverage: targetDir + "/moxie.cov.js"
	};

	var resolvedModules, modules = [].slice.call(arguments);
	if (!modules.length) {
		modules = ["file/FileInput", "file/FileDrop", "file/FileReader", "xhr/XMLHttpRequest", "image/Image"];
	}

	// resolve dependencies
	resolvedModules = mkjs.resolveModules(modules, options);

	// start fresh
	if (fs.existsSync(targetDir)) {
		jake.rmRf(targetDir);
	}
	jake.mkdirP(targetDir);

	amdlc.compileMinified(resolvedModules, options);
	amdlc.compileSource(resolvedModules, options);

	// for dev and cov versions expose all modules to be able to test them properly
	options.expose = 'all';
	options.force = true;
	resolvedModules = mkjs.resolveModules(modules, options);
	amdlc.compileDevelopment(resolvedModules, options);
	amdlc.compileCoverage(resolvedModules, options);

	var info = require('./package.json');
	info.copyright = copyright;
	tools.addReleaseDetailsTo(targetDir, info);

	// add debug constant to dev source
	mkjs.addDebug(targetDir + "/moxie.js");
	mkjs.addDebug(targetDir + "/moxie.dev.js");

	// add compatibility
	if (process.env.compat !== 'no') {
		mkjs.addCompat({
			baseDir: baseDir,
			targetDir: targetDir
		});
	}
});

desc("Compile SWF");
task("mkswf", [], function() {
	var targetDir = "bin/flash";

	// start fresh
	if (fs.existsSync(targetDir)) {
		jake.rmRf(targetDir);
	}
	jake.mkdirP(targetDir);

	// compile both
	utils.inSeries([
		function(cb) {
			mkswf({
				src: "./src/flash/src",
				input: "./src/flash/src/Moxie.as",
				output: targetDir + "/Moxie.swf",
				extra: "-define=MXI::IncludeImageLibs,true -define=MXI::EnableCSS,false -debug=false -optimize=true -swf-version=16"
			}, cb);
		},
		function(cb) {
			mkswf({
				src: "./src/flash/src",
				input: "./src/flash/src/Moxie.as",
				output: targetDir + "/Moxie.cdn.swf",
				extra: "-define=MXI::IncludeImageLibs,true -define=MXI::EnableCSS,true -debug=false -optimize=true -swf-version=16"
			}, cb);
		},
		function(cb) {
			// we do not require any fancy stuff in this one, so target FP 11.2 (last version supported by linux)
			mkswf({
				src: "./src/flash/src",
				input: "./src/flash/src/Moxie.as",
				output: targetDir + "/Moxie.min.swf",
				extra: "-define=MXI::IncludeImageLibs,false -define=MXI::EnableCSS,false -debug=false -optimize=true -swf-version=15"
			}, cb);
		}
	], complete);
}, true);

desc("Compile XAP");
task("mkxap", [], function() {
	var targetDir = "bin\\silverlight\\";

	// start fresh
	if (fs.existsSync(targetDir)) {
		jake.rmRf(targetDir);
	}
	jake.mkdirP(targetDir);

	// compile both
	utils.inSeries([
		function(cb) {
			mkxap({
				input: ".\\src\\silverlight\\Moxie.csproj",
				output: "/p:IncludeImageLibs=TRUE,XapFilename=Moxie.xap,OutputDir=..\\..\\" + targetDir
			}, cb);
		},
		function(cb) {
			mkxap({
				input: ".\\src\\silverlight\\Moxie.csproj",
				output: "/p:IncludeImageLibs=TRUE,EnableCSS=TRUE,XapFilename=Moxie.cdn.xap,OutputDir=..\\..\\" + targetDir
			}, cb);
		},
		function(cb) {
			mkxap({
				input: ".\\src\\silverlight\\Moxie.csproj",
				output: "/p:IncludeImageLibs=FALSE,XapFilename=Moxie.min.xap,OutputDir=..\\..\\" + targetDir
			}, cb);
		}
	], complete);
}, true);

desc("Generate documentation using YUIDoc");
task("docs", [], function (params) {
	var baseDir = "src/javascript"
	, exclude = [
		"runtime/flash",
		"runtime/silverlight",
		"runtime/html5",
		"runtime/html4"
	];

	tools.yuidoc(baseDir, "docs", {
		exclude: exclude.map(function(filePath) { return baseDir + "/" + filePath; }).join(",")
	});
}, true);

desc("Generate wiki pages");
task("wiki", ["docs"], function() {
	wiki("git@github.com:moxiecode/moxie.wiki.git", "wiki", "docs");
});

desc("Package library");
task("package", [], function (params) {
	var zip = tools.zip;
	var info = require("./package.json");

	var tmpDir = "./tmp";
	if (fs.existsSync(tmpDir)) {
		jake.rmRf(tmpDir);
	}
	fs.mkdirSync(tmpDir, 0755);

	var suffix = info.version.replace(/\./g, '_');
	if (/(?:beta|alpha)/.test(suffix)) {
		var dateFormat = require('dateformat');
		// If some public test build, append build number
		suffix += "." + dateFormat(new Date(), "yymmddHHMM", true);
	}

	zip([
		"bin/**/*",
		"README.md",
		"LICENSE.txt"
	], path.join(tmpDir, utils.format("moxie_%s.zip", suffix)), complete);
}, true);

desc("Run tests");
task("test", [], function() {
	var baseDir = 'tests/auto';
	var suite = eval('(' + fs.readFileSync(baseDir + '/tests.js').toString() + ')');
	var tests = suite.tests.map(function(test) {  return baseDir + '/' + test.url; });

	var config = {
		  hub: "http://localhost:9000"
		, farm: 'saucelabs'
		, saucelabs: {
			  user: process.env.SAUCE_USERNAME
			, pass: process.env.SAUCE_ACCESS_KEY
			, slots: 1
		}
		, args: tests
		, browsers: [
			  { id: 'ie', version: 10, osId: 'win' }
			, { id: 'chrome', version: 28, osId: 'mac' }
			//, { id: 'firefox', version: 16, osId: 'mac' }
		]

		, verbose: true
		, wait: true
	};

	require('./node_modules/bunyip/lib/bunyip').main(config);

}, true);

<commit_msg>Build: Coverage version requires MXI_DEBUG.<commit_after>var fs = require('fs');
var sys = require('sys');
var path = require('path');

var utils = require('./build/utils');
var mkjs = require('./build/mkjs');
var mkswf = require('./build/mkswf');
var mkxap = require('./build/mkxap');
var wiki = require('./build/wiki');
var tools = require('./build/tools');

var copyright = [
	"/**",
	" * mOxie - multi-runtime File API & XMLHttpRequest L2 Polyfill",
	" * v@@version@@",
	" *",
	" * Copyright 2013, Moxiecode Systems AB",
	" * Released under GPL License.",
	" *",
	" * License: http://www.plupload.com/license",
	" * Contributing: http://www.plupload.com/contributing",
	" *",
	" * Date: @@releasedate@@",
	" */"
].join("\n");

task("default", ["mkjs", "mkswf", "mkxap", "docs"], function (params) {});

desc("Build release package");
task("release", ["default", "package"], function (params) {});

desc("Runs JSHint on source files");
task("jshint", [], function (params) {
	jshint("src", {
		curly: true
	});
});

desc("Compile JS");
task("mkjs", [], function () {
	var amdlc = require('amdlc');
	var baseDir = "src/javascript", targetDir = "bin/js";

	var options = {
		compress: {
			unused: false,
			global_defs: {
				MXI_DEBUG: false
			}
		},
		baseDir: baseDir,
		rootNS: "moxie",
		expose: "public",
		verbose: true,
		outputSource: targetDir + "/moxie.js",
		outputMinified: targetDir + "/moxie.min.js",
		outputDev: targetDir + "/moxie.dev.js",
		outputCoverage: targetDir + "/moxie.cov.js"
	};

	var resolvedModules, modules = [].slice.call(arguments);
	if (!modules.length) {
		modules = ["file/FileInput", "file/FileDrop", "file/FileReader", "xhr/XMLHttpRequest", "image/Image"];
	}

	// resolve dependencies
	resolvedModules = mkjs.resolveModules(modules, options);

	// start fresh
	if (fs.existsSync(targetDir)) {
		jake.rmRf(targetDir);
	}
	jake.mkdirP(targetDir);

	amdlc.compileMinified(resolvedModules, options);
	amdlc.compileSource(resolvedModules, options);

	// for dev and cov versions expose all modules to be able to test them properly
	options.expose = 'all';
	options.force = true;
	resolvedModules = mkjs.resolveModules(modules, options);
	amdlc.compileDevelopment(resolvedModules, options);
	amdlc.compileCoverage(resolvedModules, options);

	var info = require('./package.json');
	info.copyright = copyright;
	tools.addReleaseDetailsTo(targetDir, info);

	// add debug constant to dev source
	mkjs.addDebug(targetDir + "/moxie.js");
	mkjs.addDebug(targetDir + "/moxie.dev.js");
	mkjs.addDebug(targetDir + "/moxie.cov.js");

	// add compatibility
	if (process.env.compat !== 'no') {
		mkjs.addCompat({
			baseDir: baseDir,
			targetDir: targetDir
		});
	}
});

desc("Compile SWF");
task("mkswf", [], function() {
	var targetDir = "bin/flash";

	// start fresh
	if (fs.existsSync(targetDir)) {
		jake.rmRf(targetDir);
	}
	jake.mkdirP(targetDir);

	// compile both
	utils.inSeries([
		function(cb) {
			mkswf({
				src: "./src/flash/src",
				input: "./src/flash/src/Moxie.as",
				output: targetDir + "/Moxie.swf",
				extra: "-define=MXI::IncludeImageLibs,true -define=MXI::EnableCSS,false -debug=false -optimize=true -swf-version=16"
			}, cb);
		},
		function(cb) {
			mkswf({
				src: "./src/flash/src",
				input: "./src/flash/src/Moxie.as",
				output: targetDir + "/Moxie.cdn.swf",
				extra: "-define=MXI::IncludeImageLibs,true -define=MXI::EnableCSS,true -debug=false -optimize=true -swf-version=16"
			}, cb);
		},
		function(cb) {
			// we do not require any fancy stuff in this one, so target FP 11.2 (last version supported by linux)
			mkswf({
				src: "./src/flash/src",
				input: "./src/flash/src/Moxie.as",
				output: targetDir + "/Moxie.min.swf",
				extra: "-define=MXI::IncludeImageLibs,false -define=MXI::EnableCSS,false -debug=false -optimize=true -swf-version=15"
			}, cb);
		}
	], complete);
}, true);

desc("Compile XAP");
task("mkxap", [], function() {
	var targetDir = "bin\\silverlight\\";

	// start fresh
	if (fs.existsSync(targetDir)) {
		jake.rmRf(targetDir);
	}
	jake.mkdirP(targetDir);

	// compile both
	utils.inSeries([
		function(cb) {
			mkxap({
				input: ".\\src\\silverlight\\Moxie.csproj",
				output: "/p:IncludeImageLibs=TRUE,XapFilename=Moxie.xap,OutputDir=..\\..\\" + targetDir
			}, cb);
		},
		function(cb) {
			mkxap({
				input: ".\\src\\silverlight\\Moxie.csproj",
				output: "/p:IncludeImageLibs=TRUE,EnableCSS=TRUE,XapFilename=Moxie.cdn.xap,OutputDir=..\\..\\" + targetDir
			}, cb);
		},
		function(cb) {
			mkxap({
				input: ".\\src\\silverlight\\Moxie.csproj",
				output: "/p:IncludeImageLibs=FALSE,XapFilename=Moxie.min.xap,OutputDir=..\\..\\" + targetDir
			}, cb);
		}
	], complete);
}, true);

desc("Generate documentation using YUIDoc");
task("docs", [], function (params) {
	var baseDir = "src/javascript"
	, exclude = [
		"runtime/flash",
		"runtime/silverlight",
		"runtime/html5",
		"runtime/html4"
	];

	tools.yuidoc(baseDir, "docs", {
		exclude: exclude.map(function(filePath) { return baseDir + "/" + filePath; }).join(",")
	});
}, true);

desc("Generate wiki pages");
task("wiki", ["docs"], function() {
	wiki("git@github.com:moxiecode/moxie.wiki.git", "wiki", "docs");
});

desc("Package library");
task("package", [], function (params) {
	var zip = tools.zip;
	var info = require("./package.json");

	var tmpDir = "./tmp";
	if (fs.existsSync(tmpDir)) {
		jake.rmRf(tmpDir);
	}
	fs.mkdirSync(tmpDir, 0755);

	var suffix = info.version.replace(/\./g, '_');
	if (/(?:beta|alpha)/.test(suffix)) {
		var dateFormat = require('dateformat');
		// If some public test build, append build number
		suffix += "." + dateFormat(new Date(), "yymmddHHMM", true);
	}

	zip([
		"bin/**/*",
		"README.md",
		"LICENSE.txt"
	], path.join(tmpDir, utils.format("moxie_%s.zip", suffix)), complete);
}, true);

desc("Run tests");
task("test", [], function() {
	var baseDir = 'tests/auto';
	var suite = eval('(' + fs.readFileSync(baseDir + '/tests.js').toString() + ')');
	var tests = suite.tests.map(function(test) {  return baseDir + '/' + test.url; });

	var config = {
		  hub: "http://localhost:9000"
		, farm: 'saucelabs'
		, saucelabs: {
			  user: process.env.SAUCE_USERNAME
			, pass: process.env.SAUCE_ACCESS_KEY
			, slots: 1
		}
		, args: tests
		, browsers: [
			  { id: 'ie', version: 10, osId: 'win' }
			, { id: 'chrome', version: 28, osId: 'mac' }
			//, { id: 'firefox', version: 16, osId: 'mac' }
		]

		, verbose: true
		, wait: true
	};

	require('./node_modules/bunyip/lib/bunyip').main(config);

}, true);

<|endoftext|>


<commit_before>/*jslint sloppy:true, node:true*/
/*globals freedom,console,FileReaderSync,exports*/

// For use in unit testing
if (typeof Promise === 'undefined' && typeof require === 'function') {
  var Promise = require('es6-promise').Promise;
}

/*
 * Peer 2 Peer transport provider.
 *
 */
var WebRTCTransportProvider = function (dispatchEvent) {
  this.dispatchEvent = dispatchEvent;
  this.name = null;
  this._setup = false;
  this.pc = freedom['core.peerconnection']();
  this.pc.on('onReceived', this.onData.bind(this));
  this.pc.on('onClose', this.onClose.bind(this));
  this.pc.on('onOpenDataChannel', this.onNewTag.bind(this));
  this._tags = [];
  // Maps tags to booleans. The boolean corresponding to a given tag
  // is true if this WebRTCTransportProvider is currently sending out
  // chunks of a message for that tag.
  this._sending = {};
  // Maps tags to lists of whole outgoing messages that are waiting to
  // be sent over the wire. Messages must be sent one at a time to
  // prevent the interleaving of chunks from two or messages.
  this._queuedMessages = {};
  // Entries in this dictionary map tags to arrays containing chunks
  // of incoming messages. If there is no entry for a tag in the
  // dictionary, then we have not received the first chunk of the next
  // message.
  this._chunks = {};
  // Messages may be limited to a 16KB length
  // http://tools.ietf.org/html/draft-ietf-rtcweb-data-channel-07#section-6.6
  this._chunkSize = 15000;
  // The maximum amount of bytes we should allow to get queued up in
  // peerconnection, any more and we start queueing ourself.
  this._pcQueueLimit = 1024 * 250;
  // Javascript has trouble representing integers larger than 2^53 exactly
  this._maxMessageSize = Math.pow(2, 53);
};

WebRTCTransportProvider.stun_servers = [
  "stun:stun.l.google.com:19302",
  "stun:stun1.l.google.com:19302",
  "stun:stun2.l.google.com:19302",
  "stun:stun3.l.google.com:19302",
  "stun:stun4.l.google.com:19302"
];

// The argument |signallingChannelId| is a freedom communication channel id to
// use to open a peer connection.
WebRTCTransportProvider.prototype.setup = function(name, signallingChannelId,
                                                   continuation) {
  this.name = name;
  var promise = this.pc.setup(signallingChannelId, name,
                              WebRTCTransportProvider.stun_servers, false);
  this._setup = true;
  promise.then(continuation).catch(function(err) {
    console.error('Error setting up peerconnection');

    continuation(undefined, {
      "errcode": "FAILED",
      "message": 'Error setting up peerconnection'
    });
  });
};

WebRTCTransportProvider.prototype.send = function(tag, data, continuation) {
  // console.log("TransportProvider.send." + this.name);
  if(!this._setup) {
    continuation(undefined, {
      "errcode": "NOTREADY",
      "message": "send called before setup"
    });
    throw new Error("send called before setup in WebRTCTransportProvider");
  }
  if (this._tags.indexOf(tag) >= 0) {
    if (this._sending[tag]) {
      // A message is currently being sent. Queue this message to
      // prevent message interleaving.
      this._queuedMessages[tag].push({tag: tag,
                                      data: data,
                                      continuation: continuation});
      return;
    }
    var buffers = this._chunk(data);
    this._sending[tag] = true;
    this._waitSend(tag, buffers).then(function afterSending() {
      this._sending[tag] = false;
      if ((typeof this._queuedMessages[tag] !== "undefined") &&
          this._queuedMessages[tag].length > 0) {
        var next = this._queuedMessages[tag].shift();
        this.send(next.tag, next.data, next.continuation);
      }
    }.bind(this)).then(continuation);
  } else {
    this.pc.openDataChannel(tag).then(function(){
      this._tags.push(tag);
      this._sending[tag] = false;
      this._queuedMessages[tag] = [];

      this.send(tag, data, continuation);
    }.bind(this));
  }
};

/**
 * Chunk a single ArrayBuffer into multiple ArrayBuffers of
 * this._chunkSize length.
 * @param {ArrayBuffer} data - Data to chunk.
 * @return {Array} - Array of ArrayBuffer objects such that the
 * concatenation of all array buffer objects equals the data
 * parameter.
 */
WebRTCTransportProvider.prototype._chunk = function(data) {
  // The first 8 bytes of the first chunk of a message encodes the
  // number of bytes in the message.
  var dataView = new Uint8Array(data);
  var buffers = [];
  var size = data.byteLength;
  var lowerBound = 0; // exclusive range
  var upperBound;

  // lowerBound points to the byte after the last byte to be chunked
  // from the original data buffer.  It should be the case that
  // lowerBound < upperBound.
  // Buffer: [------------------------------------------------]
  //          ^              ^              ^
  //          lB_0           uB_0/lB_1      uB_1/lB_2 ...    ^uB_n

  var sizeBuffer = this._sizeToBuffer(size);
  var firstBuffer = new Uint8Array(Math.min(this._chunkSize,
                                             size + sizeBuffer.byteLength));

  firstBuffer.set(sizeBuffer, 0);
  upperBound = Math.min(this._chunkSize - sizeBuffer.byteLength,
                        firstBuffer.byteLength);
  firstBuffer.set(dataView.subarray(0, upperBound), sizeBuffer.byteLength);
  buffers.push(firstBuffer.buffer);
  lowerBound = upperBound;

  while (lowerBound < size) {
    upperBound = lowerBound + this._chunkSize;
    buffers.push(data.slice(lowerBound, upperBound));
    lowerBound = upperBound;
  }

  return buffers;
};

WebRTCTransportProvider.prototype._waitSend = function(tag, buffers) {
  var bufferBound = 0; // upper bound on the # of bytes buffered

  var sendBuffers = function() {
    var promises = [];
    while(bufferBound + this._chunkSize <= this._pcQueueLimit &&
          buffers.length > 0) {
      var nextBuffer = buffers.shift();
      promises.push(this.pc.send({"channelLabel": tag,
                                  "buffer": nextBuffer}));
      bufferBound += nextBuffer.byteLength;
    }

    var allSends = Promise.all(promises);
    if (buffers.length === 0) {
      return allSends;
    }
    return allSends.then(checkBufferedAmount);
  }.bind(this);

  var checkBufferedAmount = function() {
    return this.pc.getBufferedAmount(tag).then(function(bufferedAmount) {
      bufferBound = bufferedAmount;
      if (bufferedAmount + this._chunkSize > this._pcQueueLimit) {
        return new Promise(function(resolve) {
          setTimeout(function() {
            resolve(checkBufferedAmount());
          }, 100);
        });
      } else {
        return sendBuffers();
      }
    });
  }.bind(this);
  // Check first, in case there is data in the pc buffer from another message.
  return checkBufferedAmount();
};

WebRTCTransportProvider.prototype.close = function(continuation) {
  // TODO: Close data channels.
  this._tags = [];
  this._sending = {};
  this._queuedMessages = {};
  this._chunks = {};
  this.pc.close().then(continuation);
};

// Called when the peer-connection receives data, it then passes it here.
WebRTCTransportProvider.prototype.onData = function(msg) {
  //console.log("TransportProvider.prototype.message: Got Message:" + JSON.stringify(msg));
  if (msg.buffer) {
    this._handleData(msg.channelLabel, msg.buffer);
  } else if (msg.binary) {
    if (typeof FileReaderSync === 'undefined') {
      var fileReader = new FileReader();
      fileReader.onload = (function(handleData, channelLabel) {
        return function(e) {
          handleData(channelLabel, e.target.result);
        };
      }(this._handleData.bind(this), msg.channelLabel));
      fileReader.readAsArrayBuffer(msg.binary);
    } else {
      var fileReaderSync = new FileReaderSync();
      var arrayBuffer = fileReaderSync.readAsArrayBuffer(msg.binary);
      this._handleData(msg.channelLabel, arrayBuffer);
    }
  } else if (msg.text) {
    console.error("Strings not supported.");
  }  else {
    console.error('message called without a valid data field');
  }
};

WebRTCTransportProvider.prototype._handleData = function(tag, buffer) {
  var currentTag;
  if (tag in this._chunks) {
    currentTag = this._chunks[tag];
    currentTag.buffers.push(buffer);
    currentTag.currentByteCount += buffer.byteLength;
  } else {
    currentTag = {buffers: [],
                  currentByteCount: 0,
                  totalByteCount: 0};
    this._chunks[tag] = currentTag;
    var size = this._bufferToSize(buffer.slice(0, 8));
    if (size > this._maxMessageSize) {
      console.warn("Incomming message is larger than maximum message size");
    }
    currentTag.totalByteCount = size;
    currentTag.buffers.push(buffer.slice(8));
    currentTag.currentByteCount += buffer.byteLength - 8;
  }

  if(currentTag.currentByteCount === currentTag.totalByteCount) {
    var returnBuffer = this._assembleBuffers(tag);
    this.dispatchEvent('onData', {
      "tag": tag,
      "data": returnBuffer
    });
    delete this._chunks[tag];
  } else if(currentTag.currentByteCount > currentTag.totalByteCount) {
    console.warn("Received more bytes for message than expected, something has gone seriously wrong");
    delete this._chunks[tag];
  }

};

WebRTCTransportProvider.prototype.onNewTag = function(event) {
  this._tags.push(event.channelId);
};

WebRTCTransportProvider.prototype.onClose = function() {
  this._tags = [];
  this._sending = {};
  this._queuedMessages = {};
  this._chunks = {};
  this.dispatchEvent('onClose', null);
};

WebRTCTransportProvider.prototype._sizeToBuffer = function(size) {
  // Bit shifts have overflow issues for any integers with more than
  // 32 bits, so use division.
  var buffer = new ArrayBuffer(8);
  var view = new Uint8Array(buffer);
  for (var index = 0; index < 8; index++) {
    /*jslint bitwise:true*/
    var currentByte = (size & 0xff);
    /*jslint bitwise:false*/
    view [ index ] = currentByte;
    size = (size - currentByte) / 256 ;
  }
  return view;
};

WebRTCTransportProvider.prototype._bufferToSize = function(buffer) {
  var view = new Uint8Array(buffer);
  var number = 0;
  for ( var i = view.byteLength - 1; i >= 0; i--) {
    number = (number * 256) + view[i];
  }

  return number;
};

/*
 * Reassemble the buffers for the given tag into a single ArrayBuffer object.
 * @param {String}
 * @return {ArrayBuffer} Result of concatenating all buffers for tag
 */
WebRTCTransportProvider.prototype._assembleBuffers = function(tag) {
  var size = this._chunks[tag].totalByteCount;
  var bytesCopied = 0;
  var result = new ArrayBuffer(size);
  var view = new Uint8Array(result);
  this._chunks[tag].buffers.forEach(function(buffer) {

    view.set(new Uint8Array(buffer), bytesCopied);
    bytesCopied += buffer.byteLength;
  });
  return result;
};

/** REGISTER PROVIDER **/
if (typeof freedom !== 'undefined') {
  freedom().provideAsynchronous(WebRTCTransportProvider);
}

if (typeof exports !== 'undefined') {
  exports.provider = WebRTCTransportProvider;
  exports.name = 'transport';
}
<commit_msg>remove jshint warning.<commit_after>/*jslint sloppy:true, node:true*/
/*globals freedom,console,FileReaderSync,exports*/

// For use in unit testing
if (typeof Promise === 'undefined' && typeof require === 'function') {
  /*jslint -W079 */
  var Promise = require('es6-promise').Promise;
  /*jslint +W079 */
}

/*
 * Peer 2 Peer transport provider.
 *
 */
var WebRTCTransportProvider = function (dispatchEvent) {
  this.dispatchEvent = dispatchEvent;
  this.name = null;
  this._setup = false;
  this.pc = freedom['core.peerconnection']();
  this.pc.on('onReceived', this.onData.bind(this));
  this.pc.on('onClose', this.onClose.bind(this));
  this.pc.on('onOpenDataChannel', this.onNewTag.bind(this));
  this._tags = [];
  // Maps tags to booleans. The boolean corresponding to a given tag
  // is true if this WebRTCTransportProvider is currently sending out
  // chunks of a message for that tag.
  this._sending = {};
  // Maps tags to lists of whole outgoing messages that are waiting to
  // be sent over the wire. Messages must be sent one at a time to
  // prevent the interleaving of chunks from two or messages.
  this._queuedMessages = {};
  // Entries in this dictionary map tags to arrays containing chunks
  // of incoming messages. If there is no entry for a tag in the
  // dictionary, then we have not received the first chunk of the next
  // message.
  this._chunks = {};
  // Messages may be limited to a 16KB length
  // http://tools.ietf.org/html/draft-ietf-rtcweb-data-channel-07#section-6.6
  this._chunkSize = 15000;
  // The maximum amount of bytes we should allow to get queued up in
  // peerconnection, any more and we start queueing ourself.
  this._pcQueueLimit = 1024 * 250;
  // Javascript has trouble representing integers larger than 2^53 exactly
  this._maxMessageSize = Math.pow(2, 53);
};

WebRTCTransportProvider.stun_servers = [
  "stun:stun.l.google.com:19302",
  "stun:stun1.l.google.com:19302",
  "stun:stun2.l.google.com:19302",
  "stun:stun3.l.google.com:19302",
  "stun:stun4.l.google.com:19302"
];

// The argument |signallingChannelId| is a freedom communication channel id to
// use to open a peer connection.
WebRTCTransportProvider.prototype.setup = function(name, signallingChannelId,
                                                   continuation) {
  this.name = name;
  var promise = this.pc.setup(signallingChannelId, name,
                              WebRTCTransportProvider.stun_servers, false);
  this._setup = true;
  promise.then(continuation).catch(function(err) {
    console.error('Error setting up peerconnection');

    continuation(undefined, {
      "errcode": "FAILED",
      "message": 'Error setting up peerconnection'
    });
  });
};

WebRTCTransportProvider.prototype.send = function(tag, data, continuation) {
  // console.log("TransportProvider.send." + this.name);
  if(!this._setup) {
    continuation(undefined, {
      "errcode": "NOTREADY",
      "message": "send called before setup"
    });
    throw new Error("send called before setup in WebRTCTransportProvider");
  }
  if (this._tags.indexOf(tag) >= 0) {
    if (this._sending[tag]) {
      // A message is currently being sent. Queue this message to
      // prevent message interleaving.
      this._queuedMessages[tag].push({tag: tag,
                                      data: data,
                                      continuation: continuation});
      return;
    }
    var buffers = this._chunk(data);
    this._sending[tag] = true;
    this._waitSend(tag, buffers).then(function afterSending() {
      this._sending[tag] = false;
      if ((typeof this._queuedMessages[tag] !== "undefined") &&
          this._queuedMessages[tag].length > 0) {
        var next = this._queuedMessages[tag].shift();
        this.send(next.tag, next.data, next.continuation);
      }
    }.bind(this)).then(continuation);
  } else {
    this.pc.openDataChannel(tag).then(function(){
      this._tags.push(tag);
      this._sending[tag] = false;
      this._queuedMessages[tag] = [];

      this.send(tag, data, continuation);
    }.bind(this));
  }
};

/**
 * Chunk a single ArrayBuffer into multiple ArrayBuffers of
 * this._chunkSize length.
 * @param {ArrayBuffer} data - Data to chunk.
 * @return {Array} - Array of ArrayBuffer objects such that the
 * concatenation of all array buffer objects equals the data
 * parameter.
 */
WebRTCTransportProvider.prototype._chunk = function(data) {
  // The first 8 bytes of the first chunk of a message encodes the
  // number of bytes in the message.
  var dataView = new Uint8Array(data);
  var buffers = [];
  var size = data.byteLength;
  var lowerBound = 0; // exclusive range
  var upperBound;

  // lowerBound points to the byte after the last byte to be chunked
  // from the original data buffer.  It should be the case that
  // lowerBound < upperBound.
  // Buffer: [------------------------------------------------]
  //          ^              ^              ^
  //          lB_0           uB_0/lB_1      uB_1/lB_2 ...    ^uB_n

  var sizeBuffer = this._sizeToBuffer(size);
  var firstBuffer = new Uint8Array(Math.min(this._chunkSize,
                                             size + sizeBuffer.byteLength));

  firstBuffer.set(sizeBuffer, 0);
  upperBound = Math.min(this._chunkSize - sizeBuffer.byteLength,
                        firstBuffer.byteLength);
  firstBuffer.set(dataView.subarray(0, upperBound), sizeBuffer.byteLength);
  buffers.push(firstBuffer.buffer);
  lowerBound = upperBound;

  while (lowerBound < size) {
    upperBound = lowerBound + this._chunkSize;
    buffers.push(data.slice(lowerBound, upperBound));
    lowerBound = upperBound;
  }

  return buffers;
};

WebRTCTransportProvider.prototype._waitSend = function(tag, buffers) {
  var bufferBound = 0; // upper bound on the # of bytes buffered

  var sendBuffers = function() {
    var promises = [];
    while(bufferBound + this._chunkSize <= this._pcQueueLimit &&
          buffers.length > 0) {
      var nextBuffer = buffers.shift();
      promises.push(this.pc.send({"channelLabel": tag,
                                  "buffer": nextBuffer}));
      bufferBound += nextBuffer.byteLength;
    }

    var allSends = Promise.all(promises);
    if (buffers.length === 0) {
      return allSends;
    }
    return allSends.then(checkBufferedAmount);
  }.bind(this);

  var checkBufferedAmount = function() {
    return this.pc.getBufferedAmount(tag).then(function(bufferedAmount) {
      bufferBound = bufferedAmount;
      if (bufferedAmount + this._chunkSize > this._pcQueueLimit) {
        return new Promise(function(resolve) {
          setTimeout(function() {
            resolve(checkBufferedAmount());
          }, 100);
        });
      } else {
        return sendBuffers();
      }
    });
  }.bind(this);
  // Check first, in case there is data in the pc buffer from another message.
  return checkBufferedAmount();
};

WebRTCTransportProvider.prototype.close = function(continuation) {
  // TODO: Close data channels.
  this._tags = [];
  this._sending = {};
  this._queuedMessages = {};
  this._chunks = {};
  this.pc.close().then(continuation);
};

// Called when the peer-connection receives data, it then passes it here.
WebRTCTransportProvider.prototype.onData = function(msg) {
  //console.log("TransportProvider.prototype.message: Got Message:" + JSON.stringify(msg));
  if (msg.buffer) {
    this._handleData(msg.channelLabel, msg.buffer);
  } else if (msg.binary) {
    if (typeof FileReaderSync === 'undefined') {
      var fileReader = new FileReader();
      fileReader.onload = (function(handleData, channelLabel) {
        return function(e) {
          handleData(channelLabel, e.target.result);
        };
      }(this._handleData.bind(this), msg.channelLabel));
      fileReader.readAsArrayBuffer(msg.binary);
    } else {
      var fileReaderSync = new FileReaderSync();
      var arrayBuffer = fileReaderSync.readAsArrayBuffer(msg.binary);
      this._handleData(msg.channelLabel, arrayBuffer);
    }
  } else if (msg.text) {
    console.error("Strings not supported.");
  }  else {
    console.error('message called without a valid data field');
  }
};

WebRTCTransportProvider.prototype._handleData = function(tag, buffer) {
  var currentTag;
  if (tag in this._chunks) {
    currentTag = this._chunks[tag];
    currentTag.buffers.push(buffer);
    currentTag.currentByteCount += buffer.byteLength;
  } else {
    currentTag = {buffers: [],
                  currentByteCount: 0,
                  totalByteCount: 0};
    this._chunks[tag] = currentTag;
    var size = this._bufferToSize(buffer.slice(0, 8));
    if (size > this._maxMessageSize) {
      console.warn("Incomming message is larger than maximum message size");
    }
    currentTag.totalByteCount = size;
    currentTag.buffers.push(buffer.slice(8));
    currentTag.currentByteCount += buffer.byteLength - 8;
  }

  if(currentTag.currentByteCount === currentTag.totalByteCount) {
    var returnBuffer = this._assembleBuffers(tag);
    this.dispatchEvent('onData', {
      "tag": tag,
      "data": returnBuffer
    });
    delete this._chunks[tag];
  } else if(currentTag.currentByteCount > currentTag.totalByteCount) {
    console.warn("Received more bytes for message than expected, something has gone seriously wrong");
    delete this._chunks[tag];
  }

};

WebRTCTransportProvider.prototype.onNewTag = function(event) {
  this._tags.push(event.channelId);
};

WebRTCTransportProvider.prototype.onClose = function() {
  this._tags = [];
  this._sending = {};
  this._queuedMessages = {};
  this._chunks = {};
  this.dispatchEvent('onClose', null);
};

WebRTCTransportProvider.prototype._sizeToBuffer = function(size) {
  // Bit shifts have overflow issues for any integers with more than
  // 32 bits, so use division.
  var buffer = new ArrayBuffer(8);
  var view = new Uint8Array(buffer);
  for (var index = 0; index < 8; index++) {
    /*jslint bitwise:true*/
    var currentByte = (size & 0xff);
    /*jslint bitwise:false*/
    view [ index ] = currentByte;
    size = (size - currentByte) / 256 ;
  }
  return view;
};

WebRTCTransportProvider.prototype._bufferToSize = function(buffer) {
  var view = new Uint8Array(buffer);
  var number = 0;
  for ( var i = view.byteLength - 1; i >= 0; i--) {
    number = (number * 256) + view[i];
  }

  return number;
};

/*
 * Reassemble the buffers for the given tag into a single ArrayBuffer object.
 * @param {String}
 * @return {ArrayBuffer} Result of concatenating all buffers for tag
 */
WebRTCTransportProvider.prototype._assembleBuffers = function(tag) {
  var size = this._chunks[tag].totalByteCount;
  var bytesCopied = 0;
  var result = new ArrayBuffer(size);
  var view = new Uint8Array(result);
  this._chunks[tag].buffers.forEach(function(buffer) {

    view.set(new Uint8Array(buffer), bytesCopied);
    bytesCopied += buffer.byteLength;
  });
  return result;
};

/** REGISTER PROVIDER **/
if (typeof freedom !== 'undefined') {
  freedom().provideAsynchronous(WebRTCTransportProvider);
}

if (typeof exports !== 'undefined') {
  exports.provider = WebRTCTransportProvider;
  exports.name = 'transport';
}
<|endoftext|>


<commit_before>define([], function(){
  //TODO Optimisation memoise (area of valid camera, full result,...) or use a state object

  var zmax = function(area, tanAngle) {
    var m = function(min, max, tanAngle) {
      return (max - min) / (2 * tanAngle);
    };
    return Math.min(m(area.xmin, area.xmax, tanAngle), m(area.ymin, area.ymax, tanAngle));
  };

  /**
   * @param {{x : {Number}, y : {Number}} target
   * @param {Number} distance
   * @param {Camera} camera
   * @param {{xmin : {Number}, xmax : {Number}, ymin : {Number}, ymax : {Number}}} area
   */
  var follow = function(target, distance, camera, area){
    var tanAngle = Math.abs(Math.tan(camera.fov * Math.PI /(180 * 2 ))); // half of the fov
    var z = Math.max(0, Math.min(zmax(area, tanAngle), camera.position.z));
    var margin = z * tanAngle;
    var x = Math.max( area.xmin + margin, Math.min(area.xmax - margin, target.x));
    var y = Math.max( area.ymin + margin, Math.min(area.ymax - margin, target.y));
    camera.position.x = x;
    camera.position.y = y;
    camera.position.z = z;
    camera.lookAt({x : x, y :y, z: 0});
  };
  return follow;
});
<commit_msg>camera: fix computation of mode2d<commit_after>define([], function(){
  //TODO Optimisation memoise (area of valid camera, full result,...) or use a state object

  var zmax = function(area, tanAngle, aspect) {
    var m = function(lg, tanAngle) {
      return lg / (2 * tanAngle);
    };
    return Math.min(m((area.xmax - area.xmin)/aspect, tanAngle), m((area.ymax - area.ymin), tanAngle));
  };

  /**
   * @param {{x : {Number}, y : {Number}} target
   * @param {Number} distance
   * @param {Camera} camera
   * @param {{xmin : {Number}, xmax : {Number}, ymin : {Number}, ymax : {Number}}} area
   */
  var follow = function(target, distance, camera, area){
    var tanAngle = Math.abs(Math.tan(camera.fov * Math.PI /(180 * 2 ))); // half of the fov
    var z = Math.max(0, Math.min(zmax(area, tanAngle, camera.aspect), camera.position.z));
    var xmargin = (z * tanAngle) * camera.aspect * camera.scale.x;
    var ymargin = z * tanAngle * camera.scale.y;
    var x = Math.max( area.xmin + xmargin, Math.min(area.xmax - xmargin, target.x));
    var y = Math.max( area.ymin + ymargin, Math.min(area.ymax - ymargin, target.y));
    camera.position.x = x;
    camera.position.y = y;
    camera.position.z = z;
    camera.lookAt({x : x, y :y, z: 0});
  };
  return follow;
});
<|endoftext|>


<commit_before>/*** MQTT Z-Way odule *******************************************
 Version: 1.0.0
 -----------------------------------------------------------------------------
 Author: David Uebelacker <david@uebelacker.ch>
 ******************************************************************************/

function ZWayMqttBridge(id, controller) {
    ZWayMqttBridge.super_.call(this, id, controller);
}

inherits(ZWayMqttBridge, AutomationModule);

_module = ZWayMqttBridge;

ZWayMqttBridge.prototype.init = function (config) {
    ZWayMqttBridge.super_.prototype.init.call(this, config);

    var self = this;

    this.log = function(message) {
        console.log('ZWayMqttBridge: ' + message);
    };

    if (!self.config.host || !self.config.port) {
        this.log('Host or port not configured! will not start!')
    };

    this.reconnect = function () {
        self.connected = false;
        self.mqttBridge = null;
        self.log('Will try to reconnect to Mqtt Bridge in 10 seconds ...');
        setTimeout(function () {
            self.connect();
        }, 10000);
    };

    this.connect = function () {
        self.log('Connecting to Mqtt Bridge ....');

        this.mqttBridge = new sockets.tcp();
        this.mqttBridge.onrecv = function (data) {
            self.log('Connecting to Mqtt Bridge established!');
            self.connected = true;
        };

        this.mqttBridge.onclose = function () {
            self.log('Mqtt Bridge connection was closed!');
            self.reconnect();
        };

        if (this.mqttBridge.connect(self.config.host, parseInt(self.config.port))) {
            setTimeout(function () {
                if (self.mqttBridge && !self.connected) {
                    self.log('Mqtt Bridge connection timeout!');
                    self.reconnect();
                }
            }, 5000);
        } else {
            self.log('Could not connect to Mqtt Bridge!');
            self.reconnect();
        }
    };

    this.findRoom = function(id) {
        var locations = self.controller.locations;
        if (locations) {
            for (var i = 0; i < locations.length; i++) {
                if (locations[i].id == id) {
                    return locations[i];
                }
            }
        }
        return null;
    };

    this.createTopic = function(device) {
        var room = self.findRoom(device.get('location'));
        topic += self.config.topic_prefix;
        topic += '/';
        topic += self.normalizeTopicToken(room.title);
        topic += '/';
        topic += self.normalizeTopicToken(device.get('metrics:title'));
        return topic;
    };

    this.normalizeTopicToken = function(token) {
        token = token.toLowerCase();
        token = token.replace(/[^0-9a-z_]/g, '_');
        return token;
    };

    this.deviceUpdate = function (device) {
        if (self.mqttBridge) {
            var message = {
                'topic': self.createTopic(device),
                'payload': device.get('metric:level')
            };

            var str = JSON.stringify(message);
            self.log('Sending update to bridge:' + str);
            var buf = new ArrayBuffer(str.length); // 2 bytes for each char
            var bufView = new Uint8Array(buf);

            for (var i=0; i < str.length; i++) {
                bufView[i] = str.charCodeAt(i);
            }

            self.mqttBridge.send(buf);
        }
    };

    this.connect();
    this.controller.devices.on('change:metrics:level', self.deviceUpdate);
};

<commit_msg>devel<commit_after>/*** MQTT Z-Way odule *******************************************
 Version: 1.0.0
 -----------------------------------------------------------------------------
 Author: David Uebelacker <david@uebelacker.ch>
 ******************************************************************************/

function ZWayMqttBridge(id, controller) {
    ZWayMqttBridge.super_.call(this, id, controller);
}

inherits(ZWayMqttBridge, AutomationModule);

_module = ZWayMqttBridge;

ZWayMqttBridge.prototype.init = function (config) {
    ZWayMqttBridge.super_.prototype.init.call(this, config);

    var self = this;

    this.log = function(message) {
        console.log('ZWayMqttBridge: ' + message);
    };

    if (!self.config.host || !self.config.port) {
        this.log('Host or port not configured! will not start!')
    };

    this.reconnect = function () {
        self.connected = false;
        self.mqttBridge = null;
        self.log('Will try to reconnect to Mqtt Bridge in 10 seconds ...');
        setTimeout(function () {
            self.connect();
        }, 10000);
    };

    this.connect = function () {
        self.log('Connecting to Mqtt Bridge ....');

        this.mqttBridge = new sockets.tcp();
        this.mqttBridge.onrecv = function (data) {
            self.log('Connecting to Mqtt Bridge established!');
            self.connected = true;
        };

        this.mqttBridge.onclose = function () {
            self.log('Mqtt Bridge connection was closed!');
            self.reconnect();
        };

        if (this.mqttBridge.connect(self.config.host, parseInt(self.config.port))) {
            setTimeout(function () {
                if (self.mqttBridge && !self.connected) {
                    self.log('Mqtt Bridge connection timeout!');
                    self.reconnect();
                }
            }, 5000);
        } else {
            self.log('Could not connect to Mqtt Bridge!');
            self.reconnect();
        }
    };

    this.findRoom = function(id) {
        var locations = self.controller.locations;
        if (locations) {
            for (var i = 0; i < locations.length; i++) {
                if (locations[i].id == id) {
                    return locations[i];
                }
            }
        }
        return null;
    };

    this.createTopic = function(device) {
        var room = self.findRoom(device.get('location'));
        var topic = self.config.topic_prefix;
        topic += '/';
        topic += self.normalizeTopicToken(room.title);
        topic += '/';
        topic += self.normalizeTopicToken(device.get('metrics:title'));
        return topic;
    };

    this.normalizeTopicToken = function(token) {
        token = token.toLowerCase();
        token = token.replace(/[^0-9a-z_]/g, '_');
        return token;
    };

    this.deviceUpdate = function (device) {
        if (self.mqttBridge) {
            var message = {
                'topic': self.createTopic(device),
                'payload': device.get('metric:level')
            };

            var str = JSON.stringify(message);
            self.log('Sending update to bridge:' + str);
            var buf = new ArrayBuffer(str.length); // 2 bytes for each char
            var bufView = new Uint8Array(buf);

            for (var i=0; i < str.length; i++) {
                bufView[i] = str.charCodeAt(i);
            }

            self.mqttBridge.send(buf);
        }
    };

    this.connect();
    this.controller.devices.on('change:metrics:level', self.deviceUpdate);
};

<|endoftext|>


<commit_before>var node;
var i = 1;
var ucount = 1;
var removedNode;
var cutNode;
var copyNode;
var sqlScripts = "createnew";
var jsContextPath = "${pageContext.request.contextPath}";
var sqls = [];
var sqlidx = 0;
var groupid = 0;
var curgroup = 0;
$(document).ready(function() {
	$.ajaxSettings.cache = false;
	$("#example").treeview( {
		toggle : function() {
			// alert ("toggle "+$(this).attr("id"));
	},
	animated : "fast",
	collapsed : true,
	control : "#treecontrol"
	});

});

// need to modify this for questionnaire
// $(document).ready(function(){

//$("#save").click(function() {
//	var qname = $('#newQuestionnaire\\.name').attr("value");
//	var qnaireid = $('#newQuestionnaire\\.questionnaireId').attr("value");
//	var qdescription = $('#newQuestionnaire\\.description').attr("value");
//	var qisfinal = $('#newQuestionnaire\\.isFinal').attr("checked");
//	// alert
//		// ("save"+qname+qdescription+$('#newQuestionnaire\\.isFinal').attr("checked"));
//		if (qname == '') {
//			alert("Questionnaire Name is required");
//		} else if (qdescription == '') {
//			alert("Questionnaire description is required");
//		} else {
//			// TODO : FF seems to have trouble with "#;#"
//
//			if (sqlScripts.indexOf("#;#") > 1) {
//				// if current sqlScripts is not in array yet
//				// 10 should be fine to use as check
//				sqls[sqlidx++] = sqlScripts;
//			}
//			// TODO : problem with '&' in string will in name or description
//			qname = qname.replace(/&/g, ";amp");
//			qdescription = qdescription.replace(/&/g, ";amp");
//
//			var desc1 = "";
//			var saveok = 'true';
//			if (qdescription.length > 1800) {
//				// TODO : 1800 should be ok
//				desc1 = qdescription.substring(1800);
//				qdescription = qdescription.substring(0, 1800);
//			}
//
//			// Save new questionnaire bo
//			$.ajax( {
//				url : 'questionnaireAjax.do',
//				type : 'GET',
//				dataType : 'html',
//				cache : false,
//				data : 'action=savebo&newQuestionnaire.name=' + qname
//						+ '&newQuestionnaire.questionnaireId=' + qnaireid
//						+ '&newQuestionnaire.description=' + qdescription
//						+ '&newQuestionnaire.isFinal=' + qisfinal,
//				async : false,
//				timeout : 1000,
//				error : function() {
//					// alert('Error loading XML document');
//				jumpToAnchor('topOfForm');
//				$('').css("color", "red").html(
//						"Error when save Questionnaire").appendTo(
//						$("#headermsg"))
//				$('
').appendTo($("#headermsg"));
//				saveok = 'false';
//			},
//			success : function(xml) {
//				// sqlScripts="createnew";
//				$(xml).find('h3').each(function() {
//					// var item_text = $(this).text();
//						$('#newQuestionnaire\\.questionnaireId').attr("value",
//								$(this).text().substring(9));
//						$('').css("color", "black").html(
//								"Questionnaire saved successfully").appendTo(
//								$("#headermsg"));
//						$('
').appendTo($("#headermsg"));
//						jumpToAnchor('topOfForm');
//					});
//			}
//			});// .ajax
//
//			if (desc1 != '' && saveok == 'true') {
//				// if description is really long cause the query string more
//				// than 2000 characters
//				$.ajax( {
//					url : 'questionnaireAjax.do',
//					type : 'GET',
//					dataType : 'html',
//					cache : false,
//					data : 'action=savebo1&newQuestionnaire.name=' + qname
//							+ '&newQuestionnaire.questionnaireId='
//							+ questionnaireId
//							+ '&newQuestionnaire.description=' + desc1
//							+ '&newQuestionnaire.isFinal=' + qisfinal,
//					async : false,
//					timeout : 1000,
//					error : function() {
//						// alert('Error loading XML document');
//					jumpToAnchor('topOfForm');
//					$('').css("color", "red").html(
//							"Error when save Questionnaire").appendTo(
//							$("#headermsg"))
//					$('
').appendTo($("#headermsg"));
//				},
//				success : function(xml) {
//					// sqlScripts="createnew";
//					$(xml).find('h3').each(function() {
//						// var item_text = $(this).text();
//							$('#newQuestionnaire\\.questionnaireId').attr(
//									"value", $(this).text().substring(9));
//						});
//				}
//				});// .ajax
//
//			}
//
//			for ( var k = 0; k < sqls.length; k++) {
//				sqlScripts = sqls[k];
//				sqlScripts = sqlScripts.replace(/#;#/g, ";;;");
//				qnaireid = $('#newQuestionnaire\\.questionnaireId').attr(
//						"value");
//				// alert(sqls.length+"-"+k)
//				// TODO : should consider to send newquestionnaire itself to
//				// save.
//				// need to resend newquestionnaire because it might be changed.
//				// also need to deal with 'description' which is varchar2(2000)
//				// we can not assume that is is not over 2000, so need to think
//				// about it.
//				$.ajax( {
//					url : 'questionnaireAjax.do',
//					type : 'GET',
//					dataType : 'html',
//					cache : false,
//					data : 'action=new&sqlScripts=' + sqlScripts
//							+ '&newQuestionnaire.questionnaireId=' + qnaireid,
//					async : false,
//					timeout : 1000,
//					error : function() {
//						alert('error when saving');
//					},
//					success : function(xml) {
//						sqlScripts = "createnew";
//						$(xml).find('h3').each(function() {
//							// var item_text = $(this).text();
//								// $('#newQuestionnaire\\.questionnaireId').attr("value",$(this).text().substring(9));
//							});
//					}
//				});// .ajax
//			} // end for
//			sqlidx = 0;
//		} // if-then-else
//		return false;
//	});

// }
	$("#nextGroup").hide();
	$("#prevGroup").hide();

<commit_msg>KCIRB-371<commit_after>var node;
var i = 1;
var ucount = 1;
var removedNode;
var maxCopyNodeIdx = 0;
var cutNode;
var copyNode;
var sqlScripts = "createnew";
var jsContextPath = "${pageContext.request.contextPath}";
var sqls = [];
var sqlidx = 0;
var groupid = 0;
var curgroup = 0;
$(document).ready(function() {
	$.ajaxSettings.cache = false;
	$("#example").treeview( {
		toggle : function() {
			// alert ("toggle "+$(this).attr("id"));
	},
	animated : "fast",
	collapsed : true,
	control : "#treecontrol"
	});

});

// need to modify this for questionnaire
// $(document).ready(function(){

//$("#save").click(function() {
//	var qname = $('#newQuestionnaire\\.name').attr("value");
//	var qnaireid = $('#newQuestionnaire\\.questionnaireId').attr("value");
//	var qdescription = $('#newQuestionnaire\\.description').attr("value");
//	var qisfinal = $('#newQuestionnaire\\.isFinal').attr("checked");
//	// alert
//		// ("save"+qname+qdescription+$('#newQuestionnaire\\.isFinal').attr("checked"));
//		if (qname == '') {
//			alert("Questionnaire Name is required");
//		} else if (qdescription == '') {
//			alert("Questionnaire description is required");
//		} else {
//			// TODO : FF seems to have trouble with "#;#"
//
//			if (sqlScripts.indexOf("#;#") > 1) {
//				// if current sqlScripts is not in array yet
//				// 10 should be fine to use as check
//				sqls[sqlidx++] = sqlScripts;
//			}
//			// TODO : problem with '&' in string will in name or description
//			qname = qname.replace(/&/g, ";amp");
//			qdescription = qdescription.replace(/&/g, ";amp");
//
//			var desc1 = "";
//			var saveok = 'true';
//			if (qdescription.length > 1800) {
//				// TODO : 1800 should be ok
//				desc1 = qdescription.substring(1800);
//				qdescription = qdescription.substring(0, 1800);
//			}
//
//			// Save new questionnaire bo
//			$.ajax( {
//				url : 'questionnaireAjax.do',
//				type : 'GET',
//				dataType : 'html',
//				cache : false,
//				data : 'action=savebo&newQuestionnaire.name=' + qname
//						+ '&newQuestionnaire.questionnaireId=' + qnaireid
//						+ '&newQuestionnaire.description=' + qdescription
//						+ '&newQuestionnaire.isFinal=' + qisfinal,
//				async : false,
//				timeout : 1000,
//				error : function() {
//					// alert('Error loading XML document');
//				jumpToAnchor('topOfForm');
//				$('').css("color", "red").html(
//						"Error when save Questionnaire").appendTo(
//						$("#headermsg"))
//				$('
').appendTo($("#headermsg"));
//				saveok = 'false';
//			},
//			success : function(xml) {
//				// sqlScripts="createnew";
//				$(xml).find('h3').each(function() {
//					// var item_text = $(this).text();
//						$('#newQuestionnaire\\.questionnaireId').attr("value",
//								$(this).text().substring(9));
//						$('').css("color", "black").html(
//								"Questionnaire saved successfully").appendTo(
//								$("#headermsg"));
//						$('
').appendTo($("#headermsg"));
//						jumpToAnchor('topOfForm');
//					});
//			}
//			});// .ajax
//
//			if (desc1 != '' && saveok == 'true') {
//				// if description is really long cause the query string more
//				// than 2000 characters
//				$.ajax( {
//					url : 'questionnaireAjax.do',
//					type : 'GET',
//					dataType : 'html',
//					cache : false,
//					data : 'action=savebo1&newQuestionnaire.name=' + qname
//							+ '&newQuestionnaire.questionnaireId='
//							+ questionnaireId
//							+ '&newQuestionnaire.description=' + desc1
//							+ '&newQuestionnaire.isFinal=' + qisfinal,
//					async : false,
//					timeout : 1000,
//					error : function() {
//						// alert('Error loading XML document');
//					jumpToAnchor('topOfForm');
//					$('').css("color", "red").html(
//							"Error when save Questionnaire").appendTo(
//							$("#headermsg"))
//					$('
').appendTo($("#headermsg"));
//				},
//				success : function(xml) {
//					// sqlScripts="createnew";
//					$(xml).find('h3').each(function() {
//						// var item_text = $(this).text();
//							$('#newQuestionnaire\\.questionnaireId').attr(
//									"value", $(this).text().substring(9));
//						});
//				}
//				});// .ajax
//
//			}
//
//			for ( var k = 0; k < sqls.length; k++) {
//				sqlScripts = sqls[k];
//				sqlScripts = sqlScripts.replace(/#;#/g, ";;;");
//				qnaireid = $('#newQuestionnaire\\.questionnaireId').attr(
//						"value");
//				// alert(sqls.length+"-"+k)
//				// TODO : should consider to send newquestionnaire itself to
//				// save.
//				// need to resend newquestionnaire because it might be changed.
//				// also need to deal with 'description' which is varchar2(2000)
//				// we can not assume that is is not over 2000, so need to think
//				// about it.
//				$.ajax( {
//					url : 'questionnaireAjax.do',
//					type : 'GET',
//					dataType : 'html',
//					cache : false,
//					data : 'action=new&sqlScripts=' + sqlScripts
//							+ '&newQuestionnaire.questionnaireId=' + qnaireid,
//					async : false,
//					timeout : 1000,
//					error : function() {
//						alert('error when saving');
//					},
//					success : function(xml) {
//						sqlScripts = "createnew";
//						$(xml).find('h3').each(function() {
//							// var item_text = $(this).text();
//								// $('#newQuestionnaire\\.questionnaireId').attr("value",$(this).text().substring(9));
//							});
//					}
//				});// .ajax
//			} // end for
//			sqlidx = 0;
//		} // if-then-else
//		return false;
//	});

// }
	$("#nextGroup").hide();
	$("#prevGroup").hide();

<|endoftext|>