<commit_before>var SwipeTable = function(dataProviderUrl, tableKeys, elem){
	"use strict";
	/**
	 * Config
	 *
	 * Use the following format to call SwipeTable
	 *----------------------------------------
	 *	(function(root){
	 *
   *		var restApiUrl = '/api';
   *		var keys = [
   *		    "id", // this is the 'pinned' column
   *		    "time",
   *		    "time2",
   *		    "location",
   *		    "location2"
   *		];
   *		var stElem = document.getElementsByClassName('swipe-table')[0];
	 *
   *		root.SwipeTable = new SwipeTable(restApiUrl, keys, stElem);
	 *
   *	}(this));
	 *----------------------------------------
	 */

	//=== Variables ===
	var dataProvider     = dataProviderUrl;
	var keys             = tableKeys;
	var elementReference = elem;
	var swipeReference;

	//TODO: configure table class height via call or test
	var tableClass = 'table';
	var rowHeight = 39;
	tableClass += ' table-condensed'; rowHeight = 33;

	var doneTables    = 0;
	var totalTables   = 0;
	var pageSize      = 1;
	var sortAscending = true;
	var sortColumn;

	//=== Functions ===

	/**
	 * Fetch the viewport size and set the
	 * pageSize(num of rows) based on rowHeight
	 */
	var init = function(){
		// responsejs.com/labs/dimensions/
		var matchMedia = window.matchMedia || window.msMatchMedia;
		var viewportH = (function(win, docElem, mM) {
			var client = docElem.clientHeight,
			    inner = win.innerHeight;
			if (mM && client < inner && true === mM('(min-height:' + inner + 'px)').matches){
				return win.innerHeight;
			}
			else{
				return docElem.clientHeight;
			}
		}(window, document.documentElement, matchMedia));

		// Remove one rowHeight for the header;
		viewportH -= rowHeight;
		pageSize = Math.floor(viewportH / rowHeight);
	};

	/**
	 * Takes an object that contains:
	 * REQ* server: address of the API
	 * REQ* pageSize
	 * REQ* table: container to attach the results to
	 *    * page
	 *    * timestamp
	 *    * sortField
	 *    * sortAsc
	 * Items marked with REQ are required or the request will fail.
	 *
	 * Fetches according to parameters given
	 * and gives results + table to parseResponse.
	 * @param {Object}queries Object containing quieries
	 */
	var makeRequest = function (queries){
		if(!queries.server){
			console.log("No server provided to makeRequest, not making request");
			return;
		}
		console.log("Making request to "+ queries.server+ ".");
		if(queries.timestamp){
			if(queries.sortField || queries.sortAsc){
				if(!queries.sortField || !queries.sortAsc){
					console.log("Missing sort parameter");
					return;
				}

				if(queries.page){
					executeRequest("GET",
					                queries.server +
					                  "?p=" + queries.page +
					                  "&ps=" + pageSize +
					                  "&ts=" + queries.timestamp +
					                  "&sort[field]=" + queries.sortField +
					                  "&sort[asc]=" + queries.sortAsc,
					                queries.table);
				}
				else{
					executeRequest("GET",
					                queries.server +
					                  "?ps=" + pageSize +
					                  "&ts=" + queries.timestamp +
					                  "&sort[field]=" + queries.sortField +
					                  "&sort[asc]=" + queries.sortAsc,
					                queries.table);
				}
			}
			else{
				if(!queries.page){
					console.log("Missing page, not according to spec.");
					return;
				}
				// No sorting, must be page request
				executeRequest("GET",
				                queries.server +
				                  "?p=" + queries.page +
				                  "&ps=" + pageSize +
				                  "&ts=" + queries.timestamp,
				                queries.table);
			}
		}
		else{
			// No timestamp, fresh request
			executeRequest("GET",
			                queries.server +
			                  "?ps=" + pageSize,
			                queries.table);
		}
	};

	/**
	 * Executes a request with method, parameters and the table give to next function
	 * @param  {String} method Valid HTTP method eg. GET, POST
	 * @param  {String} url Complete url string (server + parameters)
	 * @param  {Object} table Partial table object
	 */
	var executeRequest = function(method, url, table){
		var r = new XMLHttpRequest();
		r.open(method, url, true);
		r.onreadystatechange = function(){
			if(r.readyState !== 4 || r.status !== 200){
				console.log("Request went sour");
				return;
			}
			console.log("Request successful.");
			parseResponse(table, r.responseText);
		};
		r.send(null);
	};

	// parseResponse(table, response)
	//  Calls fillTable with table and JSON.parse
	//TODO: Work parseResponse into appropriate function
	var parseResponse = function(table, response){
		console.log("Parsing response.");
		fillTable(table, JSON.parse(response));
	};

	/**
	 * Creates a table with appropriate headers(thead).
	 *
	 * Increments totalTables.
	 *
	 * Returns a partial table.
	 */
	var createTable = (function(){
		console.log("Creating Table.");
		var tableInstance;
		return function(){
			if(tableInstance){
				console.log("Giving table instance");
				totalTables += 1;
				var copy = tableInstance.cloneNode(true);
				return copy;
			}
			else{
				console.log("Creating new Table");
				var i = 0;
				var table = document.createElement("table");
				table.className = tableClass;
				var thead = document.createElement("thead");
				var tr = document.createElement("tr");

				for (i; i < keys.length; i+=1){
					var th = document.createElement("th");
					th.appendChild(document.createTextNode(keys[i]));
					tr.appendChild(th);
				}

				thead.appendChild(tr);
				table.appendChild(thead);
				console.log("Table created.");
				tableInstance = table.cloneNode(true);
				totalTables += 1;
				return table;
			}
		};
	}());

	/**
	 * Goes through dataSet and attaches rows to
	 * the table reference, then attaches the
	 * table to the container in the DOM.
	 *
	 * Calls tableDone() when done.
	 * @param table Partial table to fill
	 * @param dataSet Parsed data to fill with
	 */
	var fillTable = function(table, dataSet){
		console.log("Filling table.");

		var numRows = dataSet.length;
		if(numRows === 0){
			return;
		}

		var tbody = document.createElement("tbody");
		table.appendChild(tbody);

		var i = 0;
		while (i < numRows){
			var col = dataSet[i];
			var tr = document.createElement("tr");
			var colCells = Object.keys(col).length;

			var j = 0;
			while (j < colCells)
			{
				var td = document.createElement("td");
				td.appendChild(document.createTextNode(col[keys[j]]));
				tr.appendChild(td);
				j+=1;
			}

			tbody.appendChild(tr);
			i+=1;
		}
		var container = elementReference.getElementsByClassName('st-wrap')[0];
		var tableContainer = document.createElement('div');
		var scrollableContainer = tableContainer.cloneNode(true);
		var pinnedContainer = tableContainer.cloneNode(true);
		tableContainer.className = 'st-table-wrap';
		scrollableContainer.className = 'st-scrollable';
		pinnedContainer.className = 'st-pinned';
		var cloned = table.cloneNode(true);
		scrollableContainer.appendChild(table);
		pinnedContainer.appendChild(cloned);
		tableContainer.appendChild(scrollableContainer);
		tableContainer.appendChild(pinnedContainer);
		if(swipeReference !== undefined){
			swipeReference.prepareForAddition(tableContainer);
		}
		container.appendChild(tableContainer);
		tableDone();
	};

	/**
	 *  Increments doneTables and executes if equal to totalTables.
	 *  Checks if mySwipe is made and if it isn't,
	 *  makes it and gives arguments to mySwipe.
	 *  If it's the first table to be finished,
	 *  sets up the next one to be fetched and placed,
	 *  also updates the header.
	 *
	 *  If mySwipe was already made, calls mySwipe.setup.
	 */
	var tableDone = function(){
		doneTables += 1;
		if (doneTables === totalTables){
			if(swipeReference === undefined){
				/* global Swipe */
				var doNextPage = nextPage.bind(this);
				var doUpdateHeader = updateHeader.bind(this);
				swipeReference = new Swipe(elementReference,{
					continuous:false,
					callback: function(currentIndex, element){
						if (currentIndex === element.parentNode.childNodes.length - 1){
							console.log("fetching next item");
							doNextPage();
						}
					},
					transitionEnd: function(currentIndex, element){
						doUpdateHeader(element);
					}
				});
				if(doneTables === 1){
					nextPage();
					updateHeader(document.getElementsByClassName('st-table-wrap')[0]);
				}
				/* global -Swipe */
			}
			else {
				swipeReference.setup();
			}
		}
	};

	/**
	 * Gets position from mySwipe.
	 *
	 * Calls createTable(), passes it to makeRequest.
	 */
	var nextPage = function(){
		var pos = swipeReference.getPos() + 1;

		var table = createTable();
		if(sortColumn === undefined){
			makeRequest({
				table: table ,
				server: dataProvider,
				page: pos + 1,
				timestamp: 10
			});
		}
		else{
			makeRequest({
				table: table,
				server: dataProvider,
				page: pos + 1,
				sortField: sortColumn,
				sortAsc: sortAscending
			});
		}
	};

	/**
	 * Copy the given element,
	 * paste it in the header container and attach onscroll listener,
	 * execute updateScroll calls when appropriate to update positions.
	 * @param element
	 */
	var updateHeader = function(element){
		var copy = element.cloneNode(true);
		var header = elementReference.getElementsByClassName('st-header')[0];
		header.innerHTML = '';
		copy.removeAttribute('style');
		copy.removeAttribute('data-index');
		header.appendChild(copy);

		var scrollable = header.getElementsByClassName('st-scrollable')[0];
		if (scrollable){
			scrollable.onscroll = function(){
				console.log("Scrolling is happening!");
				SwipeTable.setScrollPosition(this.scrollLeft);
				SwipeTable.updateScrollables();
			};

			var pos = SwipeTable.getScrollPosition();
			if (pos !== undefined){
				scrollable.scrollLeft = pos;
				SwipeTable.updateScrollables();
			}
			else{
				SwipeTable.setScrollPosition(0);
			}
		}
	};

	/**
	 * Exposes scroll positions to the outside
	 * and function to update all scrollables.
	 */
	var updateScroll = (function(){
		var position;
		console.log("Entered updateScroll");

		return {
			getPosition : function(){
				console.log("Getting position " + position);
				return position;
			},
			setPosition : function(newPos){
				console.log("Setting position " + newPos);
				position = newPos;
			},
			updateScrollables : function(){
				console.log("Updating scrollables");
				var targets = document.getElementsByClassName('st-wrap')[0].getElementsByClassName('st-scrollable');
				var i = 0;
				for(i;i<targets.length;i+=1){
					targets[i].scrollLeft = position;
				}
			}
		};
	}());

	//=== Logic ===
	init();

	var dataTable = createTable();
	console.log("dataProvider === " + dataProvider);
	makeRequest({
		table: dataTable,
		server: dataProvider
	});
	updateHeader(dataTable);

	var methods = {
		nextPage : nextPage,
		updateHeader : updateHeader,
		getScrollPosition : updateScroll.getPosition,
		setScrollPosition : updateScroll.setPosition,
		updateScrollables : updateScroll.updateScrollables
	};

	return methods;
};
<commit_msg>Expose Swipe's next() and prev()<commit_after>var SwipeTable = function(dataProviderUrl, tableKeys, elem){
	"use strict";
	/**
	 * Config
	 *
	 * Use the following format to call SwipeTable
	 *----------------------------------------
	 *	(function(root){
	 *
   *		var restApiUrl = '/api';
   *		var keys = [
   *		    "id", // this is the 'pinned' column
   *		    "time",
   *		    "time2",
   *		    "location",
   *		    "location2"
   *		];
   *		var stElem = document.getElementsByClassName('swipe-table')[0];
	 *
   *		root.SwipeTable = new SwipeTable(restApiUrl, keys, stElem);
	 *
   *	}(this));
	 *----------------------------------------
	 */

	//=== Variables ===
	var dataProvider     = dataProviderUrl;
	var keys             = tableKeys;
	var elementReference = elem;
	var swipeReference;

	//TODO: configure table class height via call or test
	var tableClass = 'table';
	var rowHeight = 39;
	tableClass += ' table-condensed'; rowHeight = 33;

	var doneTables    = 0;
	var totalTables   = 0;
	var pageSize      = 1;
	var sortAscending = true;
	var sortColumn;

	//=== Functions ===

	/**
	 * Fetch the viewport size and set the
	 * pageSize(num of rows) based on rowHeight
	 */
	var init = function(){
		// responsejs.com/labs/dimensions/
		var matchMedia = window.matchMedia || window.msMatchMedia;
		var viewportH = (function(win, docElem, mM) {
			var client = docElem.clientHeight,
			    inner = win.innerHeight;
			if (mM && client < inner && true === mM('(min-height:' + inner + 'px)').matches){
				return win.innerHeight;
			}
			else{
				return docElem.clientHeight;
			}
		}(window, document.documentElement, matchMedia));

		// Remove one rowHeight for the header;
		viewportH -= rowHeight;
		pageSize = Math.floor(viewportH / rowHeight);
	};

	/**
	 * Takes an object that contains:
	 * REQ* server: address of the API
	 * REQ* pageSize
	 * REQ* table: container to attach the results to
	 *    * page
	 *    * timestamp
	 *    * sortField
	 *    * sortAsc
	 * Items marked with REQ are required or the request will fail.
	 *
	 * Fetches according to parameters given
	 * and gives results + table to parseResponse.
	 * @param {Object}queries Object containing quieries
	 */
	var makeRequest = function (queries){
		if(!queries.server){
			console.log("No server provided to makeRequest, not making request");
			return;
		}
		console.log("Making request to "+ queries.server+ ".");
		if(queries.timestamp){
			if(queries.sortField || queries.sortAsc){
				if(!queries.sortField || !queries.sortAsc){
					console.log("Missing sort parameter");
					return;
				}

				if(queries.page){
					executeRequest("GET",
					                queries.server +
					                  "?p=" + queries.page +
					                  "&ps=" + pageSize +
					                  "&ts=" + queries.timestamp +
					                  "&sort[field]=" + queries.sortField +
					                  "&sort[asc]=" + queries.sortAsc,
					                queries.table);
				}
				else{
					executeRequest("GET",
					                queries.server +
					                  "?ps=" + pageSize +
					                  "&ts=" + queries.timestamp +
					                  "&sort[field]=" + queries.sortField +
					                  "&sort[asc]=" + queries.sortAsc,
					                queries.table);
				}
			}
			else{
				if(!queries.page){
					console.log("Missing page, not according to spec.");
					return;
				}
				// No sorting, must be page request
				executeRequest("GET",
				                queries.server +
				                  "?p=" + queries.page +
				                  "&ps=" + pageSize +
				                  "&ts=" + queries.timestamp,
				                queries.table);
			}
		}
		else{
			// No timestamp, fresh request
			executeRequest("GET",
			                queries.server +
			                  "?ps=" + pageSize,
			                queries.table);
		}
	};

	/**
	 * Executes a request with method, parameters and the table give to next function
	 * @param  {String} method Valid HTTP method eg. GET, POST
	 * @param  {String} url Complete url string (server + parameters)
	 * @param  {Object} table Partial table object
	 */
	var executeRequest = function(method, url, table){
		var r = new XMLHttpRequest();
		r.open(method, url, true);
		r.onreadystatechange = function(){
			if(r.readyState !== 4 || r.status !== 200){
				console.log("Request went sour");
				return;
			}
			console.log("Request successful.");
			parseResponse(table, r.responseText);
		};
		r.send(null);
	};

	// parseResponse(table, response)
	//  Calls fillTable with table and JSON.parse
	//TODO: Work parseResponse into appropriate function
	var parseResponse = function(table, response){
		console.log("Parsing response.");
		fillTable(table, JSON.parse(response));
	};

	/**
	 * Creates a table with appropriate headers(thead).
	 *
	 * Increments totalTables.
	 *
	 * Returns a partial table.
	 */
	var createTable = (function(){
		console.log("Creating Table.");
		var tableInstance;
		return function(){
			if(tableInstance){
				console.log("Giving table instance");
				totalTables += 1;
				var copy = tableInstance.cloneNode(true);
				return copy;
			}
			else{
				console.log("Creating new Table");
				var i = 0;
				var table = document.createElement("table");
				table.className = tableClass;
				var thead = document.createElement("thead");
				var tr = document.createElement("tr");

				for (i; i < keys.length; i+=1){
					var th = document.createElement("th");
					th.appendChild(document.createTextNode(keys[i]));
					tr.appendChild(th);
				}

				thead.appendChild(tr);
				table.appendChild(thead);
				console.log("Table created.");
				tableInstance = table.cloneNode(true);
				totalTables += 1;
				return table;
			}
		};
	}());

	/**
	 * Goes through dataSet and attaches rows to
	 * the table reference, then attaches the
	 * table to the container in the DOM.
	 *
	 * Calls tableDone() when done.
	 * @param table Partial table to fill
	 * @param dataSet Parsed data to fill with
	 */
	var fillTable = function(table, dataSet){
		console.log("Filling table.");

		var numRows = dataSet.length;
		if(numRows === 0){
			return;
		}

		var tbody = document.createElement("tbody");
		table.appendChild(tbody);

		var i = 0;
		while (i < numRows){
			var col = dataSet[i];
			var tr = document.createElement("tr");
			var colCells = Object.keys(col).length;

			var j = 0;
			while (j < colCells)
			{
				var td = document.createElement("td");
				td.appendChild(document.createTextNode(col[keys[j]]));
				tr.appendChild(td);
				j+=1;
			}

			tbody.appendChild(tr);
			i+=1;
		}
		var container = elementReference.getElementsByClassName('st-wrap')[0];
		var tableContainer = document.createElement('div');
		var scrollableContainer = tableContainer.cloneNode(true);
		var pinnedContainer = tableContainer.cloneNode(true);
		tableContainer.className = 'st-table-wrap';
		scrollableContainer.className = 'st-scrollable';
		pinnedContainer.className = 'st-pinned';
		var cloned = table.cloneNode(true);
		scrollableContainer.appendChild(table);
		pinnedContainer.appendChild(cloned);
		tableContainer.appendChild(scrollableContainer);
		tableContainer.appendChild(pinnedContainer);
		if(swipeReference !== undefined){
			swipeReference.prepareForAddition(tableContainer);
		}
		container.appendChild(tableContainer);
		tableDone();
	};

	/**
	 *  Increments doneTables and executes if equal to totalTables.
	 *  Checks if mySwipe is made and if it isn't,
	 *  makes it and gives arguments to mySwipe.
	 *  If it's the first table to be finished,
	 *  sets up the next one to be fetched and placed,
	 *  also updates the header.
	 *
	 *  If mySwipe was already made, calls mySwipe.setup.
	 */
	var tableDone = function(){
		doneTables += 1;
		if (doneTables === totalTables){
			if(swipeReference === undefined){
				/* global Swipe */
				var doNextPage = nextPage.bind(this);
				var doUpdateHeader = updateHeader.bind(this);
				swipeReference = new Swipe(elementReference,{
					continuous:false,
					callback: function(currentIndex, element){
						if (currentIndex === element.parentNode.childNodes.length - 1){
							console.log("fetching next item");
							doNextPage();
						}
					},
					transitionEnd: function(currentIndex, element){
						doUpdateHeader(element);
					}
				});
				if(doneTables === 1){
					nextPage();
					updateHeader(document.getElementsByClassName('st-table-wrap')[0]);
				}
				/* global -Swipe */
			}
			else {
				swipeReference.setup();
			}
		}
	};

	/**
	 * Gets position from mySwipe.
	 *
	 * Calls createTable(), passes it to makeRequest.
	 */
	var nextPage = function(){
		var pos = swipeReference.getPos() + 1;

		var table = createTable();
		if(sortColumn === undefined){
			makeRequest({
				table: table ,
				server: dataProvider,
				page: pos + 1,
				timestamp: 10
			});
		}
		else{
			makeRequest({
				table: table,
				server: dataProvider,
				page: pos + 1,
				sortField: sortColumn,
				sortAsc: sortAscending
			});
		}
	};

	/**
	 * Copy the given element,
	 * paste it in the header container and attach onscroll listener,
	 * execute updateScroll calls when appropriate to update positions.
	 * @param element
	 */
	var updateHeader = function(element){
		var copy = element.cloneNode(true);
		var header = elementReference.getElementsByClassName('st-header')[0];
		header.innerHTML = '';
		copy.removeAttribute('style');
		copy.removeAttribute('data-index');
		header.appendChild(copy);

		var scrollable = header.getElementsByClassName('st-scrollable')[0];
		if (scrollable){
			scrollable.onscroll = function(){
				console.log("Scrolling is happening!");
				SwipeTable.setScrollPosition(this.scrollLeft);
				SwipeTable.updateScrollables();
			};

			var pos = SwipeTable.getScrollPosition();
			if (pos !== undefined){
				scrollable.scrollLeft = pos;
				SwipeTable.updateScrollables();
			}
			else{
				SwipeTable.setScrollPosition(0);
			}
		}
	};

	/**
	 * Exposes scroll positions to the outside
	 * and function to update all scrollables.
	 */
	var updateScroll = (function(){
		var position;
		console.log("Entered updateScroll");

		return {
			getPosition : function(){
				console.log("Getting position " + position);
				return position;
			},
			setPosition : function(newPos){
				console.log("Setting position " + newPos);
				position = newPos;
			},
			updateScrollables : function(){
				console.log("Updating scrollables");
				var targets = document.getElementsByClassName('st-wrap')[0].getElementsByClassName('st-scrollable');
				var i = 0;
				for(i;i<targets.length;i+=1){
					targets[i].scrollLeft = position;
				}
			}
		};
	}());

	var swipeFunc = {
		next : function(){
			if (swipeReference !== undefined)
			{
				swipeReference.next();
			}
		},
		prev : function(){
			if (swipeReference !== undefined)
			{
				swipeReference.prev();
			}
		}
	};

	//=== Logic ===
	init();

	var dataTable = createTable();
	console.log("dataProvider === " + dataProvider);
	makeRequest({
		table: dataTable,
		server: dataProvider
	});
	updateHeader(dataTable);

	var methods = {
		nextPage : nextPage,
		updateHeader : updateHeader,
		getScrollPosition : updateScroll.getPosition,
		setScrollPosition : updateScroll.setPosition,
		updateScrollables : updateScroll.updateScrollables,
		next : swipeFunc.next,
		prev : swipeFunc.prev
	};

	return methods;
};
<|endoftext|>


<commit_before>'use strict';

var gulp = require('gulp'),
  merge = require('merge-stream'),
  modRewrite = require('connect-modrewrite'),
  BannerPlugin = require('gulp-webpack/node_modules/webpack/lib/BannerPlugin'),
  UglifyJsPlugin = require('gulp-webpack/node_modules/webpack/lib/optimize/UglifyJsPlugin'),

  meta = require('./package.json'),
  languages = require('./l10n/languages.json').active,
  languageCodes = languages.map(function(i) { return i.code; }).join(' ');

var $ = require('gulp-load-plugins')({
  pattern: ['gulp-*', 'del', 'browser-sync']
});

var buildDirPath = 'build';

require('events').EventEmitter.prototype._maxListeners = 100;

// Clean the build folder
gulp.task('clean:dev', function () {
  $.del.sync([buildDirPath + '/dev/*']);
});

gulp.task('clean:dist', function () {
  $.del.sync([buildDirPath + '/dist/*']);
});

gulp.task('bower', function() {
  return $.bower();
});

// Webpack
gulp.task('webpack:dev', function() {
  // TODO jshint
  // TODO move to js/entry.js
  return gulp.src('src/js/entry/web.js')
    .pipe($.webpack({
      module: {
        loaders: [
          { test: /\.jade$/, loader: "jade-loader" },
          { test: /\.json$/, loader: "json-loader" }
        ]
      },
      output: {
        filename: "app.js"
      },
      cache: true,
      debug: true,
      devtool: 'eval'
    }))
    .pipe(gulp.dest(buildDirPath + '/dev/js/'))
    .pipe($.browserSync.reload({stream:true}));
});

gulp.task('webpack:dist', function() {
  var pack = gulp.src('src/js/entry/web.js');

  // Build languages
  languages.forEach(function(language){
    pack
      .pipe($.webpack({
        module: {
          loaders: [
            { test: /\.jade$/, loader: "jade-l10n-loader?languageFile=l10n/" + language.code + "/messages.po" },
            { test: /\.json$/, loader: "json-loader" }
          ]
        },
        output: {
          filename: "app-" + language.code + ".js"
        },
        plugins: [
          new BannerPlugin('Ripple Client v' + meta.version + '\nCopyright (c) ' + new Date().getFullYear() + ' ' + meta.author.name + '\nLicensed under the ' + meta.license + ' license.'),
          new UglifyJsPlugin({
            compress: {
              warnings: false
            }
          })
        ],
        debug: false
      }))
      .pipe(gulp.dest(buildDirPath + '/dist/js/'));
  });

  return pack;
});

// TODO SASS
// Less
gulp.task('less', function () {
  return gulp.src('src/less/ripple/web.less')
    .pipe($.less({
      paths: ['src/less']
    }))
    .pipe(gulp.dest(buildDirPath + '/dev/css'))
    .pipe($.browserSync.reload({stream:true}));
});

// Static server
gulp.task('serve:dev', function() {
  $.browserSync({
    server: {
      baseDir: [".", buildDirPath + "/dev", buildDirPath, buildDirPath + "/dist", "./res", "./deps/js"],
      middleware: [
        modRewrite([
          '!\\.html|\\.js|\\.css|\\.png|\\.jpg|\\.gif|\\.svg|\\.txt|\\.eot|\\.woff|\\.woff2|\\.ttf$ /index.html [L]'
        ])
      ]
    }
  });
});

gulp.task('serve:dist', function() {
  $.browserSync({
    server: {
      baseDir: [buildDirPath + "/dist"],
      middleware: [
        modRewrite([
          '!\\.html|\\.js|\\.css|\\.png|\\.jpg|\\.gif|\\.svg|\\.txt|\\.eot|\\.woff|\\.woff2|\\.ttf$ /index.html [L]'
        ])
      ]
    }
  });
});

// Static files
gulp.task('static', function() {
  // Ripple.txt and mixpanel script
  var rpl = gulp.src(['ripple.txt', 'deps/js/mixpanel.js'])
    .pipe(gulp.dest(buildDirPath + '/dist/'));

  // Fonts and icons
  var fontsIcons = gulp.src(['res/**/*'])
    .pipe(gulp.dest(buildDirPath + '/dist/'));

  // Images
  var images = gulp.src('img/**/*')
    .pipe(gulp.dest(buildDirPath + '/dist/img/'));

  return merge(rpl, fontsIcons, images);
});

// Version branch
gulp.task('gitVersion', function (cb) {
  require('child_process').exec('git rev-parse --abbrev-ref HEAD', function(err, stdout) {
    meta.gitVersionBranch = stdout.replace(/\n$/, '');

    require('child_process').exec('git describe --tags --always --dirty', function(err, stdout) {
      meta.gitVersion = stdout.replace(/\n$/, '');

      cb(err)
    })
  })
});

// Preprocess
gulp.task('preprocess:dev', ['gitVersion'], function() {
  gulp.src('src/index.html')
    .pipe($.preprocess({
      context: {
        MODE: 'dev',
        VERSION: meta.gitVersion,
        VERSIONBRANCH: meta.gitVersionBranch,
        LANGUAGES: languageCodes
      }
    }))
    .pipe(gulp.dest(buildDirPath + '/dev/'))
    .pipe($.browserSync.reload({stream:true}))
});

gulp.task('preprocess:dist', ['gitVersion'], function() {
  gulp.src('src/index.html')
    .pipe($.preprocess({
      context: {
        MODE: 'dist',
        VERSION: meta.gitVersion,
        VERSIONBRANCH: meta.gitVersionBranch,
        LANGUAGES: languageCodes
      }
    }))
    .pipe(gulp.dest(buildDirPath + '/dist/'))
});

// Default Task (Dev environment)
gulp.task('default', ['dev', 'serve:dev'], function() {
  // Webpack
  gulp.watch(['src/js/**/*.js', 'src/jade/**/*.jade'], ['webpack:dev']);

  // Htmls
  gulp.watch('src/*.html', ['preprocess:dev']);

  // TODO Config

  gulp.watch('src/less/**/*', ['less']);
});

// Development
gulp.task('dev', ['clean:dev', 'bower', 'webpack:dev', 'less', 'preprocess:dev']);

// Distribution
gulp.task('dist', ['clean:dist', 'dev', 'webpack:dist', 'preprocess:dist', 'static'], function () {
  var assets = $.useref.assets();

  return gulp.src([buildDirPath + '/dist/index.html', 'src/includes.html'])
    // Concatenates asset files from the build blocks inside the HTML
    .pipe(assets)
    // Appends hash to extracted files app.css → app-098f6bcd.css
    .pipe($.rev())
    // Adds AngularJS dependency injection annotations
    // We don't need this, cuz the app doesn't go thru this anymore
    //.pipe($.if('*.js', $.ngAnnotate()))
    // Uglifies js files
    .pipe($.if('*.js', $.uglify()))
    // Minifies css files
    .pipe($.if('*.css', $.csso()))
    // Brings back the previously filtered HTML files
    .pipe(assets.restore())
    // Parses build blocks in html to replace references to non-optimized scripts or stylesheets
    .pipe($.useref())
    // Rewrites occurences of filenames which have been renamed by rev
    .pipe($.revReplace())
    // Minifies html
    .pipe($.if('*.html', $.minifyHtml({
      empty: true,
      spare: true,
      quotes: true
    })))
    // Creates the actual files
    .pipe(gulp.dest(buildDirPath + '/dist/'))
    // Print the file sizes
    .pipe($.size({ title: buildDirPath + '/dist/', showFiles: true }));
});<commit_msg>[FIX] Gulp: Dev env<commit_after>'use strict';

var gulp = require('gulp'),
  merge = require('merge-stream'),
  modRewrite = require('connect-modrewrite'),
  BannerPlugin = require('gulp-webpack/node_modules/webpack/lib/BannerPlugin'),
  UglifyJsPlugin = require('gulp-webpack/node_modules/webpack/lib/optimize/UglifyJsPlugin'),

  meta = require('./package.json'),
  languages = require('./l10n/languages.json').active,
  languageCodes = languages.map(function(i) { return i.code; }).join(' ');

var $ = require('gulp-load-plugins')({
  pattern: ['gulp-*', 'del', 'browser-sync']
});

var buildDirPath = 'build';

require('events').EventEmitter.prototype._maxListeners = 100;

// Clean the build folder
gulp.task('clean:dev', function () {
  $.del.sync([buildDirPath + '/dev/*']);
});

gulp.task('clean:dist', function () {
  $.del.sync([buildDirPath + '/dist/*']);
});

gulp.task('bower', function() {
  return $.bower();
});

// Webpack
gulp.task('webpack:dev', function() {
  // TODO jshint
  // TODO move to js/entry.js
  return gulp.src('src/js/entry/web.js')
    .pipe($.webpack({
      module: {
        loaders: [
          { test: /\.jade$/, loader: "jade-loader" },
          { test: /\.json$/, loader: "json-loader" }
        ]
      },
      output: {
        filename: "app-en.js"
      },
      cache: true,
      debug: true,
      devtool: 'eval'
    }))
    .pipe(gulp.dest(buildDirPath + '/dev/js/'))
    .pipe($.browserSync.reload({stream:true}));
});

gulp.task('webpack:dist', function() {
  var pack = gulp.src('src/js/entry/web.js');

  // Build languages
  languages.forEach(function(language){
    pack
      .pipe($.webpack({
        module: {
          loaders: [
            { test: /\.jade$/, loader: "jade-l10n-loader?languageFile=l10n/" + language.code + "/messages.po" },
            { test: /\.json$/, loader: "json-loader" }
          ]
        },
        output: {
          filename: "app-" + language.code + ".js"
        },
        plugins: [
          new BannerPlugin('Ripple Client v' + meta.version + '\nCopyright (c) ' + new Date().getFullYear() + ' ' + meta.author.name + '\nLicensed under the ' + meta.license + ' license.'),
          new UglifyJsPlugin({
            compress: {
              warnings: false
            }
          })
        ],
        debug: false
      }))
      .pipe(gulp.dest(buildDirPath + '/dist/js/'));
  });

  return pack;
});

// TODO SASS
// Less
gulp.task('less', function () {
  return gulp.src('src/less/ripple/web.less')
    .pipe($.less({
      paths: ['src/less']
    }))
    .pipe(gulp.dest(buildDirPath + '/dev/css'))
    .pipe($.browserSync.reload({stream:true}));
});

// Static server
gulp.task('serve:dev', function() {
  $.browserSync({
    server: {
      baseDir: [".", buildDirPath + "/dev", buildDirPath, buildDirPath + "/dist", "./res", "./deps/js"],
      middleware: [
        modRewrite([
          '!\\.html|\\.js|\\.css|\\.png|\\.jpg|\\.gif|\\.svg|\\.txt|\\.eot|\\.woff|\\.woff2|\\.ttf$ /index.html [L]'
        ])
      ]
    }
  });
});

gulp.task('serve:dist', function() {
  $.browserSync({
    server: {
      baseDir: [buildDirPath + "/dist"],
      middleware: [
        modRewrite([
          '!\\.html|\\.js|\\.css|\\.png|\\.jpg|\\.gif|\\.svg|\\.txt|\\.eot|\\.woff|\\.woff2|\\.ttf$ /index.html [L]'
        ])
      ]
    }
  });
});

// Static files
gulp.task('static', function() {
  // Ripple.txt and mixpanel script
  var rpl = gulp.src(['ripple.txt', 'deps/js/mixpanel.js'])
    .pipe(gulp.dest(buildDirPath + '/dist/'));

  // Fonts and icons
  var fontsIcons = gulp.src(['res/**/*'])
    .pipe(gulp.dest(buildDirPath + '/dist/'));

  // Images
  var images = gulp.src('img/**/*')
    .pipe(gulp.dest(buildDirPath + '/dist/img/'));

  return merge(rpl, fontsIcons, images);
});

// Version branch
gulp.task('gitVersion', function (cb) {
  require('child_process').exec('git rev-parse --abbrev-ref HEAD', function(err, stdout) {
    meta.gitVersionBranch = stdout.replace(/\n$/, '');

    require('child_process').exec('git describe --tags --always --dirty', function(err, stdout) {
      meta.gitVersion = stdout.replace(/\n$/, '');

      cb(err)
    })
  })
});

// Preprocess
gulp.task('preprocess:dev', ['gitVersion'], function() {
  gulp.src('src/index.html')
    .pipe($.preprocess({
      context: {
        MODE: 'dev',
        VERSION: meta.gitVersion,
        VERSIONBRANCH: meta.gitVersionBranch,
        LANGUAGES: languageCodes
      }
    }))
    .pipe(gulp.dest(buildDirPath + '/dev/'))
    .pipe($.browserSync.reload({stream:true}))
});

gulp.task('preprocess:dist', ['gitVersion'], function() {
  gulp.src('src/index.html')
    .pipe($.preprocess({
      context: {
        MODE: 'dist',
        VERSION: meta.gitVersion,
        VERSIONBRANCH: meta.gitVersionBranch,
        LANGUAGES: languageCodes
      }
    }))
    .pipe(gulp.dest(buildDirPath + '/dist/'))
});

// Default Task (Dev environment)
gulp.task('default', ['dev', 'serve:dev'], function() {
  // Webpack
  gulp.watch(['src/js/**/*.js', 'src/jade/**/*.jade'], ['webpack:dev']);

  // Htmls
  gulp.watch('src/*.html', ['preprocess:dev']);

  // TODO Config

  gulp.watch('src/less/**/*', ['less']);
});

// Development
gulp.task('dev', ['clean:dev', 'bower', 'webpack:dev', 'less', 'preprocess:dev']);

// Distribution
gulp.task('dist', ['clean:dist', 'dev', 'webpack:dist', 'preprocess:dist', 'static'], function () {
  var assets = $.useref.assets();

  return gulp.src([buildDirPath + '/dist/index.html', 'src/includes.html'])
    // Concatenates asset files from the build blocks inside the HTML
    .pipe(assets)
    // Appends hash to extracted files app.css → app-098f6bcd.css
    .pipe($.rev())
    // Adds AngularJS dependency injection annotations
    // We don't need this, cuz the app doesn't go thru this anymore
    //.pipe($.if('*.js', $.ngAnnotate()))
    // Uglifies js files
    .pipe($.if('*.js', $.uglify()))
    // Minifies css files
    .pipe($.if('*.css', $.csso()))
    // Brings back the previously filtered HTML files
    .pipe(assets.restore())
    // Parses build blocks in html to replace references to non-optimized scripts or stylesheets
    .pipe($.useref())
    // Rewrites occurences of filenames which have been renamed by rev
    .pipe($.revReplace())
    // Minifies html
    .pipe($.if('*.html', $.minifyHtml({
      empty: true,
      spare: true,
      quotes: true
    })))
    // Creates the actual files
    .pipe(gulp.dest(buildDirPath + '/dist/'))
    // Print the file sizes
    .pipe($.size({ title: buildDirPath + '/dist/', showFiles: true }));
});<|endoftext|>


<commit_before>/**
 * @requires OpenLayers/Control.js
 * @requires OpenLayers/Util/hideFromOldIE.js
 */
OpenLayers.Control.Transformations =
    OpenLayers.Class(OpenLayers.Control, {

    // remember that suffixes are added to this class: ItemActive or ItemInactive
    btnClass: 'olControlButtonTransformations',
    title: null,
    widget: null,
    cnt: null,
    sosiCodes: null,

    initialize: function(options) {
        OpenLayers.Control.prototype.initialize.apply(this, [options]);

        this.type = OpenLayers.Control.TYPE_BUTTON;
        OpenLayers.Util.extend(OpenLayers.Lang.nb, {
            'Transformations': 'Transformasjoner',
            'Transform coordinates': 'Transformer koordinater',
            'Select input coordinate system': 'Velg input-koordinatsystem',
            'Select output coordinate system': 'Velg output-koordinatsystem',
            'Fill out the coordinate fields or select in the map': 'Skriv inn koordinater eller velg i kart',
            'Help': 'Hjelp',
            'East coordinate': 'Øst-koordinat (lengdegrad)',
            'North coordinate': 'Nord-koordinat (breddegrad)',
            'Show coordinates': 'Vis koordinater'
        });

        this.title = OpenLayers.Lang.translate('Transformations');
        this.sosiCodes = [
            {'ESRI': 27391, 'EPSG': 27391, 'SOSI': 1, 'name': 'NGO1948 Gauss-K. Akse 1'},
            {'ESRI': 27392, 'EPSG': 27392, 'SOSI': 2, 'name': 'NGO1948 Gauss-K. Akse 2'},
            {'ESRI': 27393, 'EPSG': 27393, 'SOSI': 3, 'name': 'NGO1948 Gauss-K. Akse 3'},
            {'ESRI': 27394, 'EPSG': 27394, 'SOSI': 4, 'name': 'NGO1948 Gauss-K. Akse 4'},
            {'ESRI': 27395, 'EPSG': 27395, 'SOSI': 5, 'name': 'NGO1948 Gauss-K. Akse 5'},
            {'ESRI': 27396, 'EPSG': 27396, 'SOSI': 6, 'name': 'NGO1948 Gauss-K. Akse 6'},
            {'ESRI': 27397, 'EPSG': 27397, 'SOSI': 7, 'name': 'NGO1948 Gauss-K. Akse 7'},
            {'ESRI': 27398, 'EPSG': 27398, 'SOSI': 8, 'name': 'NGO1948 Gauss-K. Akse 8'},
            {'ESRI': null, 'EPSG': null, 'SOSI': 9, 'name': 'NGO1948, datum NGO1948, Geografisk Ingen projeksjon, enhet:sekunder'},
            {'ESRI': 32631, 'EPSG': 32631, 'SOSI': 21, 'name': 'UTM sone 31 basert på EUREF89/WGS84'},
            {'ESRI': 32632, 'EPSG': 32632, 'SOSI': 22, 'name': 'UTM sone 32 basert på EUREF89/WGS84'},
            {'ESRI': 32633, 'EPSG': 32633, 'SOSI': 23, 'name': 'UTM sone 33 basert på EUREF89/WGS84'},
            {'ESRI': 32634, 'EPSG': 32634, 'SOSI': 24, 'name': 'UTM sone 34 basert på EUREF89/WGS84'},
            {'ESRI': 32635, 'EPSG': 32635, 'SOSI': 25, 'name': 'UTM sone 35 basert på EUREF89/WGS84'},
            {'ESRI': 32636, 'EPSG': 32636, 'SOSI': 26, 'name': 'UTM sone 36 basert på EUREF89/WGS84'},
            {'ESRI': 23031, 'EPSG': 23031, 'SOSI': 31, 'name': 'UTM sone 31 basert på ED50'},
            {'ESRI': 23032, 'EPSG': 23032, 'SOSI': 32, 'name': 'UTM sone 32 basert på ED50'},
            {'ESRI': 23033, 'EPSG': 23033, 'SOSI': 33, 'name': 'UTM sone 33 basert på ED50'},
            {'ESRI': 23034, 'EPSG': 23034, 'SOSI': 34, 'name': 'UTM sone 34 basert på ED50'},
            {'ESRI': 23035, 'EPSG': 23035, 'SOSI': 35, 'name': 'UTM sone 35 basert på ED50'},
            {'ESRI': 23036, 'EPSG': 23036, 'SOSI': 36, 'name': 'UTM sone 36 basert på ED50'},
            {'ESRI': null, 'EPSG': null, 'SOSI': 41, 'name': 'Lokalt nett, uspesifisert'},
            {'ESRI': null, 'EPSG': null, 'SOSI': 42, 'name': 'Lokalt nett, uspesifisert'},
            {'ESRI': null, 'EPSG': null, 'SOSI': 50, 'name': 'ED 50 Geografisk, ingen projeksjon, enhet:sekunder'},
            {'ESRI': null, 'EPSG': null, 'SOSI': 51, 'name': 'NGO-56A basert på NGO1948.Benyttet for Møre'},
            {'ESRI': null, 'EPSG': null, 'SOSI': 52, 'name': 'NGO-56B basert på NGO1948.Benyttet for Møre'},
            {'ESRI': null, 'EPSG': null, 'SOSI': 53, 'name': 'NGO-64A basert på NGO1948.Benyttet for Møre'},
            {'ESRI': null, 'EPSG': null, 'SOSI': 54, 'name': 'NGO-64B basert på NGO1948.Benyttet for Møre'},
            {'ESRI': null, 'EPSG': null, 'SOSI': 72, 'name': 'WGS72 Geografisk, ingen projeksjon,enhet:sekunder'},
            {'ESRI': null, 'EPSG': null, 'SOSI': 84, 'name': 'EUREF89/WGS84 Geografisk Ingen projeksjon,enhet:sekunder'},
            {'ESRI': null, 'EPSG': null, 'SOSI': 87, 'name': 'ED 87 Geografisk Ingen projeksjon,enhet:sekunder'},
            {'ESRI': null, 'EPSG': null, 'SOSI': 99, 'name': 'Egendefinert.Benytter TRANSSYS for å angi transformasjonsparametre fra lokalt over til et kjent koordinatsystem'},
            {'ESRI': null, 'EPSG': null, 'SOSI': 101, 'name': 'Lokalt nett, Oslo'},
            {'ESRI': null, 'EPSG': null, 'SOSI': 102, 'name': 'Lokalt nett, Bærum'},
            {'ESRI': null, 'EPSG': null, 'SOSI': 103, 'name': 'Lokalt nett, Asker'},
            {'ESRI': null, 'EPSG': null, 'SOSI': 104, 'name': 'Lokalt nett, Lillehammer'},
            {'ESRI': null, 'EPSG': null, 'SOSI': 105, 'name': 'Lokalt nett, Drammen'},
            {'ESRI': null, 'EPSG': null, 'SOSI': 106, 'name': 'Lokalt nett, Bergen/Askøy'},
            {'ESRI': null, 'EPSG': null, 'SOSI': 107, 'name': 'Lokalt nett, Trondheim'},
            {'ESRI': null, 'EPSG': null, 'SOSI': 108, 'name': 'Lokalt nett, Bodø'},
            {'ESRI': null, 'EPSG': null, 'SOSI': 109, 'name': 'Lokalt nett, Kristiansund'},
            {'ESRI': 4230, 'EPSG': 4230, 'SOSI': 4230, 'name': 'ED 50 Geografisk, ingen projeksjon, enhet:grader'},
            {'ESRI': 4231, 'EPSG': null, 'SOSI': 4231, 'name': 'ED 87 Geografisk Ingen projeksjon ,enhet:grader'},
            {'ESRI': 4273, 'EPSG': 4273, 'SOSI': 4273, 'name': 'NGO1948 , datum NGO1948, Geografisk Ingen projeksjon, enhet:grader'},
            {'ESRI': null, 'EPSG': 4322, 'SOSI': 4322, 'name': 'WGS72 Geografisk, ingen projeksjon,enhet:grader'},
            {'ESRI': 4326, 'EPSG': 4326, 'SOSI': 4326, 'name': 'EUREF89/WGS84 Geografisk Ingen projeksjon, enhet:grader'}
        ];
    }, // initialize

    draw: function () {
        var self = this,
            cName = 'Transformations-button nkButton',
            mapped,
            btn,
            toolElement,
            panel;

	    mapped = 'OpenLayers_Control_Transformations' + self.map.id;
        btn    = OpenLayers.Util.createButton( mapped, null, null, null, 'static');

        OpenLayers.Event.observe(btn, 'click',
            OpenLayers.Function.bind(self.toggleWidget, self)
        );

        btn.title = self.title;
        btn.className = btn.className === "" ? cName : btn.className + " " + cName;
        btn.innerHTML = OpenLayers.Util.hideFromOldIE('<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" width="28px" height="26px" viewBox="0 0 28 26" preserveAspectRatio="xMidYMid meet" class="icon transformations"><path d="M19.678,13.156l7.323-6.078l-7.323-6.078v3.965H4.611v4.225h15.066V13.156z M8.323,12.844L1,18.922l7.323,6.077v-3.966h15.032v-4.225H8.323V12.844z"/></svg>');

        if (self.div == null) {
            self.div = btn;
        } else {
            if (OpenLayers.Element.hasClass(self.div, 'panel')) {
                panel = self.div;
                toolElement = document.createElement('div');
                OpenLayers.Element.addClass(toolElement, 'tool');
                OpenLayers.Element.addClass(toolElement, 'transformations');
                toolElement.appendChild(btn);
                panel.appendChild(toolElement);
                self.div = toolElement;
            } else {
                self.div.appendChild(btn);
            }
        }

    	self.cnt = document.createElement("div");
        OpenLayers.Element.addClass(self.cnt, "cnt");

        self.widget = OpenLayers.Util.createWidget( self.cnt, 1 );
        self.div.appendChild( self.widget );

        return self.div;
    }, // draw

    hideControls: function () {
    	OpenLayers.Element.removeClass( this.div, 'active' );
    }, //hideControls

    showControls: function () {
        var html,
            i,
            j,
            sosiCode,
            selected;

        html = '
' + OpenLayers.Lang.translate('Transform coordinates') + '
';
        html += '' + OpenLayers.Lang.translate('Select input coordinate system') + '';
        html += '<select id="transformations-input-coordinate-system">';
        for (i = 0, j = this.sosiCodes.length; i < j; i += 1) {
            sosiCode = this.sosiCodes[i];
            selected = (sosiCode.SOSI === 23) ? ' selected="selected"' : '';
            html += '<option value="' + sosiCode.SOSI + '"' + selected + '>' + sosiCode.name + '</option>';
        }
        html += '</select>';
    	this.cnt.innerHTML = html;
    	OpenLayers.Element.addClass( this.div, 'active' );
    }, // showControls

    enable: function () {
    }, // enable

    disable: function () {
    }, // disable

    toggleWidget: function () {
    	OpenLayers.Element.hasClass( this.div, 'active' ) ? this.hideControls() : this.showControls();
    }, // toggleGetURL

    toggleControls: function () {
	   var self = this;
    },//togglecontrols

    CLASS_NAME: "OpenLayers.Control.Transformations"
}); // OpenLayers.Control.Transformations
<commit_msg>43616-80 removed some unused coordinate systems<commit_after>/**
 * @requires OpenLayers/Control.js
 * @requires OpenLayers/Util/hideFromOldIE.js
 */
OpenLayers.Control.Transformations =
    OpenLayers.Class(OpenLayers.Control, {

    // remember that suffixes are added to this class: ItemActive or ItemInactive
    btnClass: 'olControlButtonTransformations',
    title: null,
    widget: null,
    cnt: null,
    sosiCodes: null,

    initialize: function(options) {
        OpenLayers.Control.prototype.initialize.apply(this, [options]);

        this.type = OpenLayers.Control.TYPE_BUTTON;
        OpenLayers.Util.extend(OpenLayers.Lang.nb, {
            'Transformations': 'Transformasjoner',
            'Transform coordinates': 'Transformer koordinater',
            'Select input coordinate system': 'Velg input-koordinatsystem',
            'Select output coordinate system': 'Velg output-koordinatsystem',
            'Fill out the coordinate fields or select in the map': 'Skriv inn koordinater eller velg i kart',
            'Help': 'Hjelp',
            'East coordinate': 'Øst-koordinat (lengdegrad)',
            'North coordinate': 'Nord-koordinat (breddegrad)',
            'Show coordinates': 'Vis koordinater'
        });

        this.title = OpenLayers.Lang.translate('Transformations');
        this.sosiCodes = [
            {'ESRI': 27391, 'EPSG': 27391, 'SOSI': 1, 'name': 'NGO1948, Gauss-K. Akse 1'},
            {'ESRI': 27392, 'EPSG': 27392, 'SOSI': 2, 'name': 'NGO1948, Gauss-K. Akse 2'},
            {'ESRI': 27393, 'EPSG': 27393, 'SOSI': 3, 'name': 'NGO1948, Gauss-K. Akse 3'},
            {'ESRI': 27394, 'EPSG': 27394, 'SOSI': 4, 'name': 'NGO1948, Gauss-K. Akse 4'},
            {'ESRI': 27395, 'EPSG': 27395, 'SOSI': 5, 'name': 'NGO1948, Gauss-K. Akse 5'},
            {'ESRI': 27396, 'EPSG': 27396, 'SOSI': 6, 'name': 'NGO1948, Gauss-K. Akse 6'},
            {'ESRI': 27397, 'EPSG': 27397, 'SOSI': 7, 'name': 'NGO1948, Gauss-K. Akse 7'},
            {'ESRI': 27398, 'EPSG': 27398, 'SOSI': 8, 'name': 'NGO1948, Gauss-K. Akse 8'},
            {'ESRI': 32631, 'EPSG': 32631, 'SOSI': 21, 'name': 'EU89, UTM-sone 31'},
            {'ESRI': 32632, 'EPSG': 32632, 'SOSI': 22, 'name': 'EU89, UTM-sone 32'},
            {'ESRI': 32633, 'EPSG': 32633, 'SOSI': 23, 'name': 'EU89, UTM-sone 33'},
            {'ESRI': 32634, 'EPSG': 32634, 'SOSI': 24, 'name': 'EU89, UTM-sone 34'},
            {'ESRI': 32635, 'EPSG': 32635, 'SOSI': 25, 'name': 'EU89, UTM-sone 35'},
            {'ESRI': 32636, 'EPSG': 32636, 'SOSI': 26, 'name': 'EU89, UTM-sone 36'},
            {'ESRI': 23031, 'EPSG': 23031, 'SOSI': 31, 'name': 'ED50, UTM-sone 31'},
            {'ESRI': 23032, 'EPSG': 23032, 'SOSI': 32, 'name': 'ED50, UTM-sone 32'},
            {'ESRI': 23033, 'EPSG': 23033, 'SOSI': 33, 'name': 'ED50, UTM-sone 33'},
            {'ESRI': 23034, 'EPSG': 23034, 'SOSI': 34, 'name': 'ED50, UTM-sone 34'},
            {'ESRI': 23035, 'EPSG': 23035, 'SOSI': 35, 'name': 'ED50, UTM-sone 35'},
            {'ESRI': 23036, 'EPSG': 23036, 'SOSI': 36, 'name': 'ED50, UTM-sone 36'},
            {'ESRI': null, 'EPSG': null, 'SOSI': 50, 'name': 'ED50, Geografisk'},
            {'ESRI': null, 'EPSG': null, 'SOSI': 53, 'name': 'Møre-A'},
            {'ESRI': null, 'EPSG': null, 'SOSI': 54, 'name': 'Møre-B'},
            {'ESRI': null, 'EPSG': null, 'SOSI': 84, 'name': 'EU89, Geografisk, enhet:sekunder'},
            {'ESRI': 4230, 'EPSG': 4230, 'SOSI': 4230, 'name': 'ED50 Geografisk, enhet:grader'},
            {'ESRI': 4231, 'EPSG': null, 'SOSI': 4231, 'name': 'ED87 Geografisk, enhet:grader'},
            {'ESRI': 4273, 'EPSG': 4273, 'SOSI': 4273, 'name': 'NGO1948 Geografisk, enhet:grader'},
            {'ESRI': null, 'EPSG': 4322, 'SOSI': 4322, 'name': 'WGS72 Geografisk, enhet:grader'},
            {'ESRI': 4326, 'EPSG': 4326, 'SOSI': 4326, 'name': 'EU89/WGS84 Geografisk, enhet:grader'}
        ];
    }, // initialize

    draw: function () {
        var self = this,
            cName = 'Transformations-button nkButton',
            mapped,
            btn,
            toolElement,
            panel;

	    mapped = 'OpenLayers_Control_Transformations' + self.map.id;
        btn    = OpenLayers.Util.createButton( mapped, null, null, null, 'static');

        OpenLayers.Event.observe(btn, 'click',
            OpenLayers.Function.bind(self.toggleWidget, self)
        );

        btn.title = self.title;
        btn.className = btn.className === "" ? cName : btn.className + " " + cName;
        btn.innerHTML = OpenLayers.Util.hideFromOldIE('<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" width="28px" height="26px" viewBox="0 0 28 26" preserveAspectRatio="xMidYMid meet" class="icon transformations"><path d="M19.678,13.156l7.323-6.078l-7.323-6.078v3.965H4.611v4.225h15.066V13.156z M8.323,12.844L1,18.922l7.323,6.077v-3.966h15.032v-4.225H8.323V12.844z"/></svg>');

        if (self.div == null) {
            self.div = btn;
        } else {
            if (OpenLayers.Element.hasClass(self.div, 'panel')) {
                panel = self.div;
                toolElement = document.createElement('div');
                OpenLayers.Element.addClass(toolElement, 'tool');
                OpenLayers.Element.addClass(toolElement, 'transformations');
                toolElement.appendChild(btn);
                panel.appendChild(toolElement);
                self.div = toolElement;
            } else {
                self.div.appendChild(btn);
            }
        }

    	self.cnt = document.createElement("div");
        OpenLayers.Element.addClass(self.cnt, "cnt");

        self.widget = OpenLayers.Util.createWidget( self.cnt, 1 );
        self.div.appendChild( self.widget );

        return self.div;
    }, // draw

    hideControls: function () {
    	OpenLayers.Element.removeClass( this.div, 'active' );
    }, //hideControls

    showControls: function () {
        var html,
            i,
            j,
            sosiCode,
            selected;

        html = '
' + OpenLayers.Lang.translate('Transform coordinates') + '
';
        html += '' + OpenLayers.Lang.translate('Select input coordinate system') + '';
        html += '<select id="transformations-input-coordinate-system">';
        for (i = 0, j = this.sosiCodes.length; i < j; i += 1) {
            sosiCode = this.sosiCodes[i];
            selected = (sosiCode.SOSI === 23) ? ' selected="selected"' : '';
            html += '<option value="' + sosiCode.SOSI + '"' + selected + '>' + sosiCode.name + '</option>';
        }
        html += '</select>';
    	this.cnt.innerHTML = html;
    	OpenLayers.Element.addClass( this.div, 'active' );
    }, // showControls

    enable: function () {
    }, // enable

    disable: function () {
    }, // disable

    toggleWidget: function () {
    	OpenLayers.Element.hasClass( this.div, 'active' ) ? this.hideControls() : this.showControls();
    }, // toggleGetURL

    toggleControls: function () {
	   var self = this;
    },//togglecontrols

    CLASS_NAME: "OpenLayers.Control.Transformations"
}); // OpenLayers.Control.Transformations
<|endoftext|>


<commit_before>/**!
 * AjaxEdit v0.0.1
 *
 * Lightweight jQuery plugin used to edit HTML regions without reloading
 * the page.
 *
 * Author: Baptiste Fontaine
 * Licence: MIT
 * Repository: github.com/bfontaine/AjaxEdit
 *
 **/
;(function( $ ) {

    var defaultOptions = {

            /* Define when the element will be set to editable mode.
             * Possible values:
             *      - 'hoverButton': A button labelled "Edit" will appear
             *                       when the user put the cursor over the
             *                       element. If they click on the button,
             *                       the element will become editable. This
             *                       is the default.
             *
             *      - Any other value will be threated as an event on the
             *        element, e.g. "dblclick".
             *
             * This can be a list with multiple values.
             */
            editOn: 'hoverButton',

            /* This option allows you to have different names for the fields
             * in your API.
             */
            fields: {
                html: 'html', // the name of the field for HTML
                text: 'text'  // the name of the field for text/markup
            },

            // buttons' labels
            buttons: {
                edit:   'Edit',
                save:   'Save',
                cancel: 'Cancel'
            },

            // if this is set to true, the fields' text values will
            // be preloaded. If this is set to false, their text values
            // will be loaded only if the user try to edit them.
            prefetch: false // #NotImplemented

        },

        // This Error is raised when no URL is provided for
        // GETting/POSTing the content
        noURLException = new Error( 'No URL provided.' ),

        // random key used for unique class attributes
        key = '__' + (0|Math.random()*1000) + 'k' + +new Date(),

        // button class (internal usage only)
        button_class = key + '_button',
        // editor div class (internal usage only)
        editor_class = key + '_editor',

        // the button base which will be used for all buttons
        // .ajaxedit-button class is added for the user
        $baseButton = $( '<input>' )
                        .attr( 'type', 'button' )
                        .addClass([ 'ajaxedit-button', button_class ]),

        // the editor base which will be used for all editors (divs)
        $baseEditor = $( '

' )
                        .attr( 'contenteditable', true )
                        .addClass( editor_class );

    // attach an "Edit" button to the element, which will be made
    // visible when the user move their mouse over the element
    function attachHoverButton( $el, label, callback ) {

        var $editButton = $baseButton.clone()
                            .attr( 'value', label )
                            .click( callback );

        $el.hover(

            function() {

                if ( !$el.data( 'edited' ) ) {

                    addButton( $el, $editButton );

                }

            },

            function() { removeButton( $el, $editButton ); }
        );

    }

    // Add a button on an element
    function addButton( $el, $button ) {

        $button.appendTo( $el );

    }

    // Remove a button which is on an element
    function removeButton( $el, $button ) {

        $button.detach();

    }

    // called when the user click the "Save" button on an element
    // (return a callback)
    function saveEdit( opts, $el ) {

        return function( ev ) {

            //TODO

        };

    }

    // called when the user cancel an edit on an element
    // (return a callback)
    function cancelEdit( opts, $el ) {

        return function( ev ) {

            $el.find( button_class ).remove().end()
               .find( editor_class ).remove().end()
               .data( 'edited', false )
               .trigger( 'EditCanceled' )
               .html( $el.data( 'html' ) || '' );

        };

    }

    // called when the user try to edit an element
    // (return a callback)
    function edited( opts, $el ) {

        return function() {

            if ( $el.data( 'edited' ) ) { return; }

            $el.trigger( 'EditInit' )
               .data( 'edited', true );

            fetch( opts )( $el,

                 // called with the data from the server
                 function( data ) {

                     var text;

                     if ( !$el.data( 'edited' ) ) { return; }

                     text = data[ $el.data( 'name' ) ][ opts.fields.text ];

                     $el.trigger( 'EditOk' )
                        .text( '' )
                        .data( 'html',
                               data[$el.data( 'name' )][opts.fields.html] );

                     // "Cancel" button
                     addButton( $el, $baseButton.clone()
                                       .attr( 'value', opts.buttons.cancel )
                                       .click( cancelEdit( opts, $el ) ) );

                     // "Save" button
                     addButton( $el, $baseButton.clone()
                                       .attr( 'value', opts.buttons.save )
                                       .click( saveEdit( opts, $el ) ) );

                     $el.append( $baseEditor.clone().text( text ) );

                 },
                 // called if there's an error
                 function( err ) {

                    if ( !$el.data( 'edited' ) ) { return; }

                    $el.data( 'edited', false )
                       .trigger('EditError');

                    //TODO callback?

                 }
            );
        };
    }

    // fetch $el's data from the server and pass it to
    // the callback function
    // (return a callback)
    function fetch( opts ) {

        return function( $el, successCallback, errorCallback ) {

            // optional additional parameters
            var params = $el.data( 'params' ) || {};

            $.ajax( opts.url, {

                data: params,
                context: $el,
                success: successCallback,
                error: errorCallback

            });

        };

    }

    // AjaxEdit main function
    $.fn.ajaxedit = function( opts ) {

        if ( arguments.length === 0 ) {

            throw noURLException;

        }

        // if the argument is a string, we assume that
        // this is the API endpoint (URL)
        if ( typeof opts === 'string' ) {

            opts = $.extend( true, {}, defaultOptions, { url: opts } );

        }
        // else, this is an object where keys/values are options
        else if ( typeof opts === 'object' ) {

            opts = $.extend( true, {}, defaultOptions, opts );

        }

        if ( !opts.hasOwnProperty('url') || !opts['url'] ) {

            throw noURLException;

        }

        var fields = [];

        if ( this.length === 1 && this.attr('data-name') ) {

            fields.push( this );

        }
        else {

            this.each( function( i, e ) {

                var $e = $(e);

                if ( $e.attr( 'data-name' ) ) {

                    // if this element is editable, don't search for fields in it
                    fields.push($e);

                }
                else {

                    // otherwise, pick its children
                    fields = fields.concat( $e.find( '[data-name]' ) );

                }

            });

        }

        // if there is no editable elements, don't do anything
        if ( fields.length === 0 ) { return this; }

        // List of events triggered when the user wants to edit an element
        var editOn = ( $.type( opts.editOn ) === 'array' ) ?
                            opts.editOn :
                                [ opts.editOn ];

        $.each( fields, function( i, $field ) {

            // For each 'edit' event, bind the event to the callback
            $.each( editOn, function( i, ev ) {

                // special 'event': The "Edit" button
                if ( ev === 'hoverButton' ) {

                    attachHoverButton( $field, opts.buttons.edit, edited(opts, $field) );

                }
                else {

                    $field.bind( ev, edited(opts, $field) );

                }

            });

            // The field is ready to be edited
            $field
                .attr( 'contenteditable', false )
                .trigger( 'EditReady' );
        });

        return this;

    };

})( jQuery );
<commit_msg>minor syntax change.<commit_after>/**!
 * AjaxEdit v0.0.1
 *
 * Lightweight jQuery plugin used to edit HTML regions without reloading
 * the page.
 *
 * Author: Baptiste Fontaine
 * Licence: MIT
 * Repository: github.com/bfontaine/AjaxEdit
 *
 **/
;(function( $ ) {

    var defaultOptions = {

            /* Define when the element will be set to editable mode.
             * Possible values:
             *      - 'hoverButton': A button labelled "Edit" will appear
             *                       when the user put the cursor over the
             *                       element. If they click on the button,
             *                       the element will become editable. This
             *                       is the default.
             *
             *      - Any other value will be threated as an event on the
             *        element, e.g. "dblclick".
             *
             * This can be a list with multiple values.
             */
            editOn: 'hoverButton',

            /* This option allows you to have different names for the fields
             * in your API.
             */
            fields: {
                html: 'html', // the name of the field for HTML
                text: 'text'  // the name of the field for text/markup
            },

            // buttons' labels
            buttons: {
                edit:   'Edit',
                save:   'Save',
                cancel: 'Cancel'
            },

            // if this is set to true, the fields' text values will
            // be preloaded. If this is set to false, their text values
            // will be loaded only if the user try to edit them.
            prefetch: false // #NotImplemented

        },

        // This Error is raised when no URL is provided for
        // getting/posting the content
        noURLException = new Error( 'No URL provided.' ),

        // random key used for unique class attributes
        key = '__' + ( 0|Math.random() * 1000 ) + 'k' + +new Date(),

        // button class (internal usage only)
        button_class = key + '_button',
        // editor div class (internal usage only)
        editor_class = key + '_editor',

        // the button base which will be used for all buttons
        // .ajaxedit-button class is added for the user
        $baseButton = $( '<input>' )
                        .attr( 'type', 'button' )
                        .addClass([ 'ajaxedit-button', button_class ]),

        // the editor base which will be used for all editors (divs)
        $baseEditor = $( '

' )
                        .attr( 'contenteditable', true )
                        .addClass( editor_class );

    // attach an "Edit" button to the element, which will be made
    // visible when the user move their mouse over the element
    function attachHoverButton( $el, label, callback ) {

        var $editButton = $baseButton.clone()
                            .attr( 'value', label )
                            .click( callback );

        $el.hover(

            function() {

                if ( !$el.data( 'edited' ) ) {

                    addButton( $el, $editButton );

                }

            },

            function() { removeButton( $el, $editButton ); }
        );

    }

    // Add a button on an element
    function addButton( $el, $button ) {

        $button.appendTo( $el );

    }

    // Remove a button which is on an element
    function removeButton( $el, $button ) {

        $button.detach();

    }

    // called when the user click the "Save" button on an element
    // (return a callback)
    function saveEdit( opts, $el ) {

        return function( ev ) {

            //TODO

        };

    }

    // called when the user cancel an edit on an element
    // (return a callback)
    function cancelEdit( opts, $el ) {

        return function( ev ) {

            $el.find( button_class ).remove().end()
               .find( editor_class ).remove().end()
               .data( 'edited', false )
               .trigger( 'EditCanceled' )
               .html( $el.data( 'html' ) || '' );

        };

    }

    // called when the user try to edit an element
    // (return a callback)
    function edited( opts, $el ) {

        return function() {

            if ( $el.data( 'edited' ) ) { return; }

            $el.trigger( 'EditInit' )
               .data( 'edited', true );

            fetch( opts )( $el,

                 // called with the data from the server
                 function( data ) {

                     var text;

                     if ( !$el.data( 'edited' ) ) { return; }

                     text = data[ $el.data( 'name' ) ][ opts.fields.text ];

                     $el.trigger( 'EditOk' )
                        .text( '' )
                        .data( 'html',
                               data[$el.data( 'name' )][opts.fields.html] );

                     // "Cancel" button
                     addButton( $el, $baseButton.clone()
                                       .attr( 'value', opts.buttons.cancel )
                                       .click( cancelEdit( opts, $el ) ) );

                     // "Save" button
                     addButton( $el, $baseButton.clone()
                                       .attr( 'value', opts.buttons.save )
                                       .click( saveEdit( opts, $el ) ) );

                     $el.append( $baseEditor.clone().text( text ) );

                 },
                 // called if there's an error
                 function( err ) {

                    if ( !$el.data( 'edited' ) ) { return; }

                    $el.data( 'edited', false )
                       .trigger('EditError');

                    //TODO callback?

                 }
            );
        };
    }

    // fetch $el's data from the server and pass it to
    // the callback function
    // (return a callback)
    function fetch( opts ) {

        return function( $el, successCallback, errorCallback ) {

            // optional additional parameters
            var params = $el.data( 'params' ) || {};

            $.ajax( opts.url, {

                data: params,
                context: $el,
                success: successCallback,
                error: errorCallback

            });

        };

    }

    // AjaxEdit main function
    $.fn.ajaxedit = function( opts ) {

        if ( arguments.length === 0 ) {

            throw noURLException;

        }

        // if the argument is a string, we assume that
        // this is the API endpoint (URL)
        if ( typeof opts === 'string' ) {

            opts = $.extend( true, {}, defaultOptions, { url: opts } );

        }
        // else, this is an object where keys/values are options
        else if ( typeof opts === 'object' ) {

            opts = $.extend( true, {}, defaultOptions, opts );

        }

        if ( !opts.hasOwnProperty('url') || !opts['url'] ) {

            throw noURLException;

        }

        var fields = [];

        if ( this.length === 1 && this.attr('data-name') ) {

            fields.push( this );

        }
        else {

            this.each( function( i, e ) {

                var $e = $(e);

                if ( $e.attr( 'data-name' ) ) {

                    // if this element is editable, don't search for fields in it
                    fields.push($e);

                }
                else {

                    // otherwise, pick its children
                    fields = fields.concat( $e.find( '[data-name]' ) );

                }

            });

        }

        // if there is no editable elements, don't do anything
        if ( fields.length === 0 ) { return this; }

        // List of events triggered when the user wants to edit an element
        var editOn = ( $.type( opts.editOn ) === 'array' ) ?
                            opts.editOn :
                                [ opts.editOn ];

        $.each( fields, function( i, $field ) {

            // For each 'edit' event, bind the event to the callback
            $.each( editOn, function( i, ev ) {

                // special 'event': The "Edit" button
                if ( ev === 'hoverButton' ) {

                    attachHoverButton( $field, opts.buttons.edit, edited(opts, $field) );

                }
                else {

                    $field.bind( ev, edited(opts, $field) );

                }

            });

            // The field is ready to be edited
            $field
                .attr( 'contenteditable', false )
                .trigger( 'EditReady' );
        });

        return this;

    };

})( jQuery );
<|endoftext|>


<commit_before>// module:
//		dui/tests/boilerplate
// description:
//		A <script src="boilerplate.js"> on your test page will:
//
//		- load claro or a specified theme
//		- load the loader (i.e. define the require() method)
//
//		By URL flags you can specify the theme,
//		and optionally enable RTL (right to left) mode, and/or dj_a11y (high-
//		contrast/image off emulation) ... probably not a genuine test for a11y.
//
//		You should NOT be using this in a production environment.  Include
//		your css and set your classes manually:
//
//		<style type="text/css">
//			@import "dui/themes/claro/document.css";
//		</style>
//		<link id="themeStyles" rel="stylesheet" href="dui/themes/claro/claro.css"/>
//		<script type="text/javascript" src="dojo/dojo.js"></script>
//		...
//		<body class="claro">

var dir = "",
	theme = "",
	testMode = null;

dojoConfig = {
	async: true,
	isDebug: true,
	locale: "en-us"
};

// Parse the URL, get parameters
if(window.location.href.indexOf("?") > -1){
	var str = window.location.href.substr(window.location.href.indexOf("?")+1).split(/#/);
	var ary  = str[0].split(/&/);
	for(var i = 0; i < ary.length; i++){
		var split = ary[i].split("="),
			key = split[0],
			value = (split[1]||'').replace(/[^\w]/g, "");	// replace() to prevent XSS attack
		switch(key){
			case "locale":
				// locale string | null
				dojoConfig.locale = value;
				break;
			case "dir":
				// rtl | null
				dir = value;
				break;
			case "theme":
				// tundra | soria | nihilo | claro | null
				theme = /null|none/.test(value) ? null : value;
				break;
			case "a11y":
				if(value){ testMode = "dj_a11y"; }
				break;
		}
	}
}

// Find the <script src="boilerplate.js"> tag, to get test directory and data-dojo-config argument
var scripts = document.getElementsByTagName("script"), script;	// testDir is global
for(i = 0; script = scripts[i]; i++){
	var src = script.getAttribute("src"),
		match = src && src.match(/(.*|^)boilerplate\.js/i);
	if(match){
		// Sniff location of dui/tests directory relative to this test file.   testDir will be an empty string if it's
		// the same directory, or a string including a slash, ex: "../", if the test is in a subdirectory.
		testDir = match[1];

		// Sniff configuration on attribute in script element.
		// Allows syntax like <script src="boilerplate.js data-dojo-config="parseOnLoad: true">, where the settings
		// specified override the default settings.
		var attr = script.getAttribute("data-dojo-config");
		if(attr){
			var overrides = eval("({ " + attr + " })");
			for(var key in overrides){
				dojoConfig[key] = overrides[key];
			}
		}
		break;
	}
}

// Output the boilerplate text to load the theme CSS
if(theme){
	var themeDir = testDir + "../themes/" + theme + "/";
	document.write([
		'<style type="text/css">',
			theme == "claro" ? '@import "' + themeDir + 'document.css";' : "",
			'@import "' + testDir + 'css/dijitTests.css";',
		'</style>',
		'<link id="themeStyles" rel="stylesheet" href="' + themeDir + theme + '.css"/>'
	].join("\n"));
}

// Setup configuration options for the loader
require = {
	baseUrl: testDir + "../../",
	packages: [
		{name:'dojo', location:'dojo'},
		{name:'dijit', location:'dijit'},
		{name:'dojox', location:'dojox'},
		{name:'doh', location:'util/doh'}
	]
};

// Output the boilerplate text to load the loader.
document.write('<script type="text/javascript" src="' + testDir + '../../dojo/requirejs/require.js"></script>');

// On IE9 the following inlined script will run before dojo has finished loading, leading to an error because require()
// isn't defined yet.  Workaround it by putting the code in a separate file.
//document.write('<script type="text/javascript">require(["dojo/domReady!"], boilerplateOnLoad);</script>');
document.write('<script type="text/javascript" src="' + testDir + 'boilerplateOnload.js"></script>');

function boilerplateOnLoad(){
	// This function is the first registered domReady() callback, allowing us to setup
	// theme stuff etc. before the widgets start instantiating.

	// theme (claro, tundra, etc.)
	if(theme){
		// Set <body> to point to the specified theme
		document.body.className = theme;
	}

	// a11y (flag for faux high-contrast testing)
	if(testMode){
		document.body.className += " " + testMode;
	}

	// BIDI
	if(dir == "rtl"){
		// set dir=rtl on <html> node
		document.body.parentNode.setAttribute("dir", "rtl");

		require(["dojo/query!css2", "dojo/NodeList-dom"], function(query){
			// pretend all the labels are in an RTL language, because
			// that affects how they lay out relative to inline form widgets
			query("label").attr("dir", "rtl");
		});
	}

	// parseOnLoad: true requires that the parser itself be loaded.
	if(dojoConfig.parseOnLoad){
		require(["dojo/parser"]);
	}
}
<commit_msg>Load claro theme by default. It's needed for infrastructure classes like dijitPopup.<commit_after>// module:
//		dui/tests/boilerplate
// description:
//		A <script src="boilerplate.js"> on your test page will:
//
//		- load claro or a specified theme
//		- load the loader (i.e. define the require() method)
//
//		By URL flags you can specify the theme,
//		and optionally enable RTL (right to left) mode, and/or dj_a11y (high-
//		contrast/image off emulation) ... probably not a genuine test for a11y.
//
//		You should NOT be using this in a production environment.  Include
//		your css and set your classes manually:
//
//		<style type="text/css">
//			@import "dui/themes/claro/document.css";
//		</style>
//		<link id="themeStyles" rel="stylesheet" href="dui/themes/claro/claro.css"/>
//		<script type="text/javascript" src="dojo/dojo.js"></script>
//		...
//		<body class="claro">

var dir = "",
	theme = "claro",
	testMode = null;

dojoConfig = {
	async: true,
	isDebug: true,
	locale: "en-us"
};

// Parse the URL, get parameters
if(window.location.href.indexOf("?") > -1){
	var str = window.location.href.substr(window.location.href.indexOf("?")+1).split(/#/);
	var ary  = str[0].split(/&/);
	for(var i = 0; i < ary.length; i++){
		var split = ary[i].split("="),
			key = split[0],
			value = (split[1]||'').replace(/[^\w]/g, "");	// replace() to prevent XSS attack
		switch(key){
			case "locale":
				// locale string | null
				dojoConfig.locale = value;
				break;
			case "dir":
				// rtl | null
				dir = value;
				break;
			case "theme":
				// tundra | soria | nihilo | claro | null
				theme = /null|none/.test(value) ? null : value;
				break;
			case "a11y":
				if(value){ testMode = "dj_a11y"; }
				break;
		}
	}
}

// Find the <script src="boilerplate.js"> tag, to get test directory and data-dojo-config argument
var scripts = document.getElementsByTagName("script"), script;	// testDir is global
for(i = 0; script = scripts[i]; i++){
	var src = script.getAttribute("src"),
		match = src && src.match(/(.*|^)boilerplate\.js/i);
	if(match){
		// Sniff location of dui/tests directory relative to this test file.   testDir will be an empty string if it's
		// the same directory, or a string including a slash, ex: "../", if the test is in a subdirectory.
		testDir = match[1];

		// Sniff configuration on attribute in script element.
		// Allows syntax like <script src="boilerplate.js data-dojo-config="parseOnLoad: true">, where the settings
		// specified override the default settings.
		var attr = script.getAttribute("data-dojo-config");
		if(attr){
			var overrides = eval("({ " + attr + " })");
			for(var key in overrides){
				dojoConfig[key] = overrides[key];
			}
		}
		break;
	}
}

// Output the boilerplate text to load the theme CSS
if(theme){
	// Temporary: get theme from dijit/ or mobile/ directory.
	// Eventually there should be a shared theme in dui/themes.
	var themeDir = testDir + "../" + (theme == "claro" ? "dijit" : "mobile") + "/themes/" + theme + "/";
	document.write([
		'<style type="text/css">',
			theme == "claro" ? '@import "' + themeDir + 'document.css";' : "",
		'</style>',
		'<link id="themeStyles" rel="stylesheet" href="' + themeDir + theme + '.css"/>'
	].join("\n"));
}

// Setup configuration options for the loader
require = {
	baseUrl: testDir + "../../",
	packages: [
		{name:'dojo', location:'dojo'},
		{name:'dijit', location:'dijit'},
		{name:'dojox', location:'dojox'},
		{name:'doh', location:'util/doh'}
	]
};

// Output the boilerplate text to load the loader.
document.write('<script type="text/javascript" src="' + testDir + '../../dojo/requirejs/require.js"></script>');

// On IE9 the following inlined script will run before dojo has finished loading, leading to an error because require()
// isn't defined yet.  Workaround it by putting the code in a separate file.
//document.write('<script type="text/javascript">require(["dojo/domReady!"], boilerplateOnLoad);</script>');
document.write('<script type="text/javascript" src="' + testDir + 'boilerplateOnload.js"></script>');

function boilerplateOnLoad(){
	// This function is the first registered domReady() callback, allowing us to setup
	// theme stuff etc. before the widgets start instantiating.

	// theme (claro, tundra, etc.)
	if(theme){
		// Set <body> to point to the specified theme
		document.body.className = theme;
	}

	// a11y (flag for faux high-contrast testing)
	if(testMode){
		document.body.className += " " + testMode;
	}

	// BIDI
	if(dir == "rtl"){
		// set dir=rtl on <html> node
		document.body.parentNode.setAttribute("dir", "rtl");

		require(["dojo/query!css2", "dojo/NodeList-dom"], function(query){
			// pretend all the labels are in an RTL language, because
			// that affects how they lay out relative to inline form widgets
			query("label").attr("dir", "rtl");
		});
	}

	// parseOnLoad: true requires that the parser itself be loaded.
	if(dojoConfig.parseOnLoad){
		require(["dojo/parser"]);
	}
}
<|endoftext|>


<commit_before>(function($, window, document, undefined) {
    'use strict';

    var Diamonds = function(customOptions) {
        this.options = {
            wrapElement : null,
            itemSelector : ".item",
            size : 250,
            gap : 0.5,
            autoRedraw : true,
            hideIncompleteRow : false,
            scrollbarWidth : null,
            minDiamondsPerRow : 2,
            itemWrap : $('

'),
            rowWrap : $('

'),
            rowUpperWrap : $('

'),
            rowLowerWrap : $('

'),
            diamondWrap : $('

'),
            overrideCss : '.diamonds-{{guid}} .diamond-box-wrap { width: {{size}}px; height: {{size}}px; } .diamonds-{{guid}} .diamond-box { border-width: {{gap}}px }'
        };
        this.setOptions(customOptions);

        this.itemElements = $(this.options.itemSelector, this.options.wrapElement);

        this.guid = this._createGuid();

        // Create override css
        this.styleElement = this._createOverrideCss();

        // Initial draw
        this.draw();

        // Auto redraw
        this.startAutoRedraw();
    };

    Diamonds.prototype._createGuid = function() {
        return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {var r = Math.random()*16|0,v=c=='x'?r:r&0x3|0x8;return v.toString(16);});
    };

    Diamonds.prototype.destroy = function() {
        this._removeOverrideCss();
        this.stopAutoRedraw();
        this._emptyElement(this.options.wrapElement);
        this.options.wrapElement.append(this.itemElements);
        this.options.wrapElement.removeData("diamonds");
    };

    Diamonds.prototype._createOverrideCss = function() {
        var css = this.options.overrideCss;
        var data = {
            "size" : this.options.size,
            "gap" : this.options.gap,
            "guid" : this.guid
        }
        for(var key in data) {
            if(data.hasOwnProperty(key)) {
                css = css.replace(new RegExp("{{" + key + "}}", 'g'), data[key]);
            }
        }

        var style = $('');
        style.html(css);

        $("head").append(style);
        return style;
    };

    Diamonds.prototype._removeOverrideCss = function() {
        this.styleElement.remove();
    };

    Diamonds.prototype.stopAutoRedraw = function() {
        window.clearInterval(this.redrawer);
    };

    Diamonds.prototype.startAutoRedraw = function() {
        this.stopAutoRedraw(); // Stop previous
        var lastWidth = this.options.wrapElement.width();
        if(this.options.autoRedraw) {
            this.redrawer = window.setInterval(function() {
                var curWidth = this.options.wrapElement.width();
                if(curWidth !== lastWidth) {
                    lastWidth = curWidth;
                    this.draw();
                }
            }.bind(this), 50);
        }
    };

    Diamonds.prototype.setOptions = function(customOptions) {
        if(customOptions !== null && typeof customOptions === "object") {
            $.extend(true, this.options, customOptions);
        }
    };

    Diamonds.prototype._getScrollbarWidth = function() {
        if(isNaN(this.options.scrollbarWidth) && this.options.scrollbarWidth >= 0) return this.scrollbarWidth;
        var $inner = $('
test
'),
            $outer = $('

').append($inner),
            inner = $inner[0],
            outer = $outer[0];

        $('body').append(outer);
        var width1 = inner.offsetWidth;
        $outer.css('overflow', 'scroll');
        var width2 = outer.clientWidth;
        $outer.remove();

        return this.scrollbarWidth = (width1 - width2);
    };

    Diamonds.prototype._emptyElement = function(element) {
        $("*", element).detach();
    };

    Diamonds.prototype._groupIntoRows = function(items, maxDiamondsPerRow, hideIncompleteRow) {
        // Max number of diamonds per row
        maxDiamondsPerRow = Math.max(this.options.minDiamondsPerRow, maxDiamondsPerRow);

        // Draw rows
        var rows = new Array();
        for(var i = 0; i < items.length; i++) {
            var item = items[i];
            // Append or create new row?
            var max = rows.length % 2 === 0 ? maxDiamondsPerRow - 1 : maxDiamondsPerRow;
            if(!rows.hasOwnProperty(rows.length - 1) || rows[rows.length - 1].length == max) {
                rows.push(new Array());
            }
            rows[rows.length - 1].push(item);
        }

        // Hide incomplete rows
        if(hideIncompleteRow) {
            if(rows.hasOwnProperty(rows.length - 1) && rows[rows.length - 1].length < rows.length % 2 === 0 ? maxDiamondsPerRow - 1 : maxDiamondsPerRow) {
                rows.pop();
            }
        }

        return rows;
    };

    Diamonds.prototype._renderHtml = function(rows) {
        var wrap = this.options.diamondWrap.clone();
        wrap.addClass("diamonds-" + this.guid);
        for(var i = 0; i < rows.length; i += 2) {
            var row = this.options.rowWrap.clone();
            var upper = this.options.rowUpperWrap.clone();
            var lower = this.options.rowLowerWrap.clone();
            row.append(upper).append(lower);
            wrap.append(row);

            for(var j = 0; j < rows[i].length; j++) {
                upper.append(rows[i][j]);
                $(rows[i][j]).wrap(this.options.itemWrap);
            }
            if(!rows.hasOwnProperty(i + 1)) break;
            for(var j = 0; j < rows[i + 1].length; j++) {
                lower.append(rows[i + 1][j]);
                $(rows[i + 1][j]).wrap(this.options.itemWrap);
            }
        }

        wrap.css("min-width", this.options.minDiamondsPerRow * this.options.size);

        return wrap;
    };

    Diamonds.prototype.draw = function() {
        this._emptyElement(this.options.wrapElement);

        var width = this.options.wrapElement.innerWidth() - this._getScrollbarWidth();

        var rows = this._groupIntoRows(this.itemElements,
            Math.floor(width / this.options.size),
            this.options.hideIncompleteRow);

        var html = this._renderHtml(rows);

        this.options.wrapElement.append(html);
    };

    // jQuery stuff
    $.fn.diamonds = function(method) {

        // Initialize
        if(method === undefined || $.isPlainObject(method)) {
            method = method || {};
            method.wrapElement = this;
            this.data("diamonds", new Diamonds(method));
            return this;
        }

        // Call method
        var inst = this.data("diamonds");
        if(inst == null) throw new Error("Diamonds not initialized on this element.");

        if(Diamonds.prototype.hasOwnProperty(method)) {
            var args = Array.prototype.slice.call(arguments);
            args.shift();
            var ret = Diamonds.prototype[method].apply(inst, args);
            return ret === undefined ? this : ret;
        }
    };
})(jQuery, window, document);<commit_msg>Refactor to redraw when options change.<commit_after>(function($, window, document, undefined) {
    'use strict';

    var Diamonds = function(customOptions) {
        this.options = {
            wrapElement : null,
            itemSelector : ".item",
            size : 250,
            gap : 0.5,
            autoRedraw : true,
            hideIncompleteRow : false,
            scrollbarWidth : null,
            minDiamondsPerRow : 2,
            itemWrap : $('

'),
            rowWrap : $('

'),
            rowUpperWrap : $('

'),
            rowLowerWrap : $('

'),
            diamondWrap : $('

'),
            overrideCss : '.diamonds-{{guid}} .diamond-box-wrap { width: {{size}}px; height: {{size}}px; } .diamonds-{{guid}} .diamond-box { border-width: {{gap}}px }'
        };
        this.setOptions(customOptions);

        this.itemElements = $(this.options.itemSelector, this.options.wrapElement);

        this.guid = this._createGuid();

        // Create override css
        this.styleElement = this._createOverrideCss();

        // Initial draw
        this.draw();

        // Auto redraw
        this.startAutoRedraw();
    };

    Diamonds.prototype._createGuid = function() {
        return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {var r = Math.random()*16|0,v=c=='x'?r:r&0x3|0x8;return v.toString(16);});
    };

    Diamonds.prototype.destroy = function() {
        this._removeOverrideCss();
        this.stopAutoRedraw();
        this._emptyElement(this.options.wrapElement);
        this.options.wrapElement.append(this.itemElements);
        this.options.wrapElement.removeData("diamonds");
    };

    Diamonds.prototype._createOverrideCss = function() {
        var css = this.options.overrideCss;
        var data = {
            "size" : this.options.size,
            "gap" : this.options.gap,
            "guid" : this.guid
        }
        for(var key in data) {
            if(data.hasOwnProperty(key)) {
                css = css.replace(new RegExp("{{" + key + "}}", 'g'), data[key]);
            }
        }

        var style = $('');
        style.html(css);

        $("head").append(style);
        return style;
    };

    Diamonds.prototype._removeOverrideCss = function() {
        this.styleElement.remove();
    };

    Diamonds.prototype._updateOverrideCss = function() {
        this._removeOverrideCss();
        this._createOverrideCss();
    };

    Diamonds.prototype.stopAutoRedraw = function() {
        window.clearInterval(this.redrawer);
    };

    Diamonds.prototype.startAutoRedraw = function() {
        this.stopAutoRedraw(); // Stop previous
        var lastWidth = this.options.wrapElement.width();
        if(this.options.autoRedraw) {
            this.redrawer = window.setInterval(function() {
                var curWidth = this.options.wrapElement.width();
                if(curWidth !== lastWidth) {
                    lastWidth = curWidth;
                    this.draw();
                }
            }.bind(this), 50);
        }
    };

    Diamonds.prototype.setOptions = function(customOptions) {
        if(customOptions !== null && typeof customOptions === "object") {
            $.extend(true, this.options, customOptions);

            this._updateOverrideCss();
            this.draw();
        }
    };

    Diamonds.prototype._getScrollbarWidth = function() {
        if(isNaN(this.options.scrollbarWidth) && this.options.scrollbarWidth >= 0) return this.scrollbarWidth;
        var $inner = $('
test
'),
            $outer = $('

').append($inner),
            inner = $inner[0],
            outer = $outer[0];

        $('body').append(outer);
        var width1 = inner.offsetWidth;
        $outer.css('overflow', 'scroll');
        var width2 = outer.clientWidth;
        $outer.remove();

        return this.scrollbarWidth = (width1 - width2);
    };

    Diamonds.prototype._emptyElement = function(element) {
        $("*", element).detach();
    };

    Diamonds.prototype._groupIntoRows = function(items, maxDiamondsPerRow, hideIncompleteRow) {
        // Max number of diamonds per row
        maxDiamondsPerRow = Math.max(this.options.minDiamondsPerRow, maxDiamondsPerRow);

        // Draw rows
        var rows = new Array();
        for(var i = 0; i < items.length; i++) {
            var item = items[i];
            // Append or create new row?
            var max = rows.length % 2 === 0 ? maxDiamondsPerRow - 1 : maxDiamondsPerRow;
            if(!rows.hasOwnProperty(rows.length - 1) || rows[rows.length - 1].length == max) {
                rows.push(new Array());
            }
            rows[rows.length - 1].push(item);
        }

        // Hide incomplete rows
        if(hideIncompleteRow) {
            if(rows.hasOwnProperty(rows.length - 1) && rows[rows.length - 1].length < rows.length % 2 === 0 ? maxDiamondsPerRow - 1 : maxDiamondsPerRow) {
                rows.pop();
            }
        }

        return rows;
    };

    Diamonds.prototype._renderHtml = function(rows) {
        var wrap = this.options.diamondWrap.clone();
        wrap.addClass("diamonds-" + this.guid);
        for(var i = 0; i < rows.length; i += 2) {
            var row = this.options.rowWrap.clone();
            var upper = this.options.rowUpperWrap.clone();
            var lower = this.options.rowLowerWrap.clone();
            row.append(upper).append(lower);
            wrap.append(row);

            for(var j = 0; j < rows[i].length; j++) {
                upper.append(rows[i][j]);
                $(rows[i][j]).wrap(this.options.itemWrap);
            }
            if(!rows.hasOwnProperty(i + 1)) break;
            for(var j = 0; j < rows[i + 1].length; j++) {
                lower.append(rows[i + 1][j]);
                $(rows[i + 1][j]).wrap(this.options.itemWrap);
            }
        }

        wrap.css("min-width", this.options.minDiamondsPerRow * this.options.size);

        return wrap;
    };

    Diamonds.prototype.draw = function() {
        this._emptyElement(this.options.wrapElement);

        var width = this.options.wrapElement.innerWidth() - this._getScrollbarWidth();

        var rows = this._groupIntoRows(this.itemElements,
            Math.floor(width / this.options.size),
            this.options.hideIncompleteRow);

        var html = this._renderHtml(rows);

        this.options.wrapElement.append(html);
    };

    // jQuery stuff
    $.fn.diamonds = function(method) {

        // Initialize
        if(method === undefined || $.isPlainObject(method)) {
            method = method || {};
            method.wrapElement = this;
            this.data("diamonds", new Diamonds(method));
            return this;
        }

        // Call method
        var inst = this.data("diamonds");
        if(inst == null) throw new Error("Diamonds not initialized on this element.");

        if(Diamonds.prototype.hasOwnProperty(method)) {
            var args = Array.prototype.slice.call(arguments);
            args.shift();
            var ret = Diamonds.prototype[method].apply(inst, args);
            return ret === undefined ? this : ret;
        }
    };
})(jQuery, window, document);<|endoftext|>


<commit_before>var gulp = require('gulp');
var uglify = require('gulp-uglify');
var rename = require('gulp-rename');
var sass = require('gulp-ruby-sass');
var jshint = require('gulp-jshint');

gulp.task('default', ['compress', 'sass']);

gulp.task('watch', function() {
    gulp.watch('./src/*.js', ['lint']);
})

gulp.task('sass', function() {
    gulp.src('./src/*.scss')
        .pipe(sass({compass: true}))
        .pipe(gulp.dest('./src'));
    gulp.src('./src/*.scss')
        .pipe(sass({compass: true, style: 'compressed'}))
        .pipe(gulp.dest('./dist'));
});

gulp.task('compress', function() {
    gulp.src('./src/talaria.js')
        .pipe(uglify({outSourceMap: true}))
        .pipe(rename('talaria.min.js'))
        .pipe(gulp.dest('./dist'));
});

gulp.task('lint', function() {
    gulp.src('./src/*.js')
        .pipe(jshint())
        .pipe(jshint.reporter('default'));
});
<commit_msg>Adds a gulp task to copy the non-minimized talaria.js to /dist.<commit_after>var gulp = require('gulp');
var uglify = require('gulp-uglify');
var rename = require('gulp-rename');
var sass = require('gulp-ruby-sass');
var jshint = require('gulp-jshint');

gulp.task('default', ['compress', 'copy', 'sass']);

gulp.task('watch', function() {
    gulp.watch('./src/*.js', ['lint']);
})

gulp.task('sass', function() {
    gulp.src('./src/*.scss')
        .pipe(sass({compass: true}))
        .pipe(gulp.dest('./src'));
    gulp.src('./src/*.scss')
        .pipe(sass({compass: true, style: 'compressed'}))
        .pipe(gulp.dest('./dist'));
});

gulp.task('compress', function() {
    gulp.src('./src/talaria.js')
        .pipe(uglify({outSourceMap: true}))
        .pipe(rename('talaria.min.js'))
        .pipe(gulp.dest('./dist'));
});

gulp.task('copy', function() {
    gulp.src('./src/talaria.js')
        .pipe(gulp.dest('./dist'));
});

gulp.task('lint', function() {
    gulp.src('./src/*.js')
        .pipe(jshint())
        .pipe(jshint.reporter('default'));
});
<|endoftext|>