<commit_before>function ScatterplotDialog(column) {
    this._column = column;
    this._plot_method = "lin";
    this._createDialog();
}

ScatterplotDialog.prototype._createDialog = function() {
    var self = this;
    var frame = DialogSystem.createDialog();
    frame.width("1100px");

    var header = $('

').addClass("dialog-header").text('Scatterplot Matrix' + ((typeof this._column == "undefined") ? "" : " (focusing on '" + this._column + "')")).appendTo(frame);
    var body = $('

').addClass("dialog-body").appendTo(frame);
    var footer = $(
        '
' +
           '

' +
             '	' +
             '	' +
           '

' +
        '
'
    ).appendTo(frame);

    var html = $(
        '

' +
            '
' +
                '' +
                    'Plot type: <select bind="plotSelector">' +
                        '<option selected="true" value="lin">linear</option>' +
                        '<option value="log">log-log</option>' +
                    '</select>' +
                    'Plot Size: <input bind="plotSize" type="test" size="2" value=""> px' +
                    'Dot Size: <input bind="dotSize" type="test" size="2" value=""> px' +
                    'Rotation: <select bind="rotationSelector">' +
                    '<option selected="true" value="none">none</option>' +
                    '<option value="cw">45° clockwise</option>' +
                    '<option value="ccw">45° counter-clockwise</option>' +
                '</select>' +
                '	' +
            '
' +
            '
' +
                '' +
                    '

' +
                '	' +
            '
' +
        '

'
    ).appendTo(body);

    this._elmts = DOM.bind(html);

    this._elmts.plotSelector.change(function() {
        self._plot_method = $(this).find("option:selected").attr("value");
        self._renderMatrix();
    });

    this._elmts.rotationSelector.change(function() {
        self._rotation = $(this).find("option:selected").attr("value");
        self._renderMatrix();
    });

    this._elmts.plotSize.change(function() {
        try {
            self._plot_size = parseInt($(this).val())
            self._renderMatrix();
        } catch (e) {
            alert("Must be a number");
        }
    });

    this._elmts.dotSize.change(function() {
        try {
            self._dot_size = parseFloat($(this).val())
            self._renderMatrix();
        } catch (e) {
            alert("Must be a number");
        }
    });

    var left_footer = footer.find(".left");

    var right_footer = footer.find(".right");
    $('<button></button>').text("Done").click(function() { self._dismiss(); }).appendTo(right_footer);

    this._level = DialogSystem.showDialog(frame);
    this._renderMatrix();
};

ScatterplotDialog.prototype._renderMatrix = function() {
    var self = this;

    var container = this._elmts.tableContainer.html(
        '
Processing...
'
    );

    if (theProject.columnModel.columns.length > 0) {
        var params = {
            project: theProject.id
        };
        $.getJSON("/command/get-columns-info?" + $.param(params),function(data) {
            if (data == null || typeof data.length == 'undefined') {
                container.html("Error calling 'get-columns-info'");
                return;
            }

            var columns = [];
            for (var i = 0; i < data.length; i++) {
                if (data[i].is_numeric) {
                    columns.push(data[i]);
                }
            }

            if (typeof self._plot_size == 'undefined') {
                self._plot_size = Math.max(Math.floor(500 / columns.length / 5) * 5,20);
                self._dot_size = 0.4;
                self._elmts.plotSize.val(self._plot_size);
                self._elmts.dotSize.val(self._dot_size);
            }

            var table = '

';

            var createScatterplot = function(cx, cy) {
                var title = cx + ' (x) vs. ' + cy + ' (y)';
                var link = '';
                var plotter_params = {
                    'cx' : cx,
                    'cy' : cy,
                    'l' : self._plot_size,
                    'dot': self._dot_size,
                    'dim_x': self._plot_method,
                    'dim_y': self._plot_method,
                    'r': self._rotation
                };
                var params = {
                    project: theProject.id,
                    engine: JSON.stringify(ui.browsingEngine.getJSON()),
                    plotter: JSON.stringify(plotter_params)
                };
                var url = "/command/get-scatterplot?" + $.param(params);
                return link + '';
            };

            for (var i = 0; i < columns.length; i++) {
                table += '
';
                var div_class = "column_header";
                if (columns[i].name == self._column) div_class += " current_column";
                table += '' + columns[i].name + '	'
                for (var j = i + 1; j < columns.length; j++) {
                    var cx = columns[i].name;
                    var cy = columns[j].name;

                    var div_class = "scatterplot";
                    if (cx == self._column || cy == self._column) div_class += " current_column";
                    table += '
' + createScatterplot(cx,cy) + '
	';
                }
                table += '
';
            }

            table += "

";

            var width = container.width();
            container.empty().css("width", width + "px").append($(table));

            container.find("a").click(function() {
                var options = {
                    "name" : $(this).attr("title"),
                    "cx" : $(this).attr("cx"),
                    "cy" : $(this).attr("cy"),
                    "l" : 120,
                    "ex" : "value",
                    "ey" : "value",
                    "dot" : self._dot_size,
                    "dim_x" : self._plot_method,
                    "dim_y" : self._plot_method,
                    'r': self._rotation
                };
                ui.browsingEngine.addFacet("scatterplot", options);
                //self._dismiss();
            });

            container.find(".scatterplot").hover(
                function() {
                    $(this).find('img').addClass("hover");
                } , function() {
                    $(this).find('img').removeClass("hover");
                }
            );
        });
    } else {
        container.html(
            '

There are no columns in this dataset

'
        );
    }

};

ScatterplotDialog.prototype._dismiss = function() {
    DialogSystem.dismissUntil(this._level - 1);
};

<commit_msg>Made non-current scatter plots in scatter plot dialog render only on hover.<commit_after>function ScatterplotDialog(column) {
    this._column = column;
    this._plot_method = "lin";
    this._createDialog();
}

ScatterplotDialog.prototype._createDialog = function() {
    var self = this;
    var frame = DialogSystem.createDialog();
    frame.width("1100px");

    var header = $('

').addClass("dialog-header").text('Scatterplot Matrix' + ((typeof this._column == "undefined") ? "" : " (focusing on '" + this._column + "')")).appendTo(frame);
    var body = $('

').addClass("dialog-body").appendTo(frame);
    var footer = $(
        '
' +
           '

' +
             '	' +
             '	' +
           '

' +
        '
'
    ).appendTo(frame);

    var html = $(
        '

' +
            '
' +
                '' +
                    'Plot type: <select bind="plotSelector">' +
                        '<option selected="true" value="lin">linear</option>' +
                        '<option value="log">log-log</option>' +
                    '</select>' +
                    'Plot Size: <input bind="plotSize" type="test" size="2" value=""> px' +
                    'Dot Size: <input bind="dotSize" type="test" size="2" value=""> px' +
                    'Rotation: <select bind="rotationSelector">' +
                    '<option selected="true" value="none">none</option>' +
                    '<option value="cw">45° clockwise</option>' +
                    '<option value="ccw">45° counter-clockwise</option>' +
                '</select>' +
                '	' +
            '
' +
            '
' +
                '' +
                    '

' +
                '	' +
            '
' +
        '

'
    ).appendTo(body);

    this._elmts = DOM.bind(html);

    this._elmts.plotSelector.change(function() {
        self._plot_method = $(this).find("option:selected").attr("value");
        self._renderMatrix();
    });

    this._elmts.rotationSelector.change(function() {
        self._rotation = $(this).find("option:selected").attr("value");
        self._renderMatrix();
    });

    this._elmts.plotSize.change(function() {
        try {
            self._plot_size = parseInt($(this).val())
            self._renderMatrix();
        } catch (e) {
            alert("Must be a number");
        }
    });

    this._elmts.dotSize.change(function() {
        try {
            self._dot_size = parseFloat($(this).val())
            self._renderMatrix();
        } catch (e) {
            alert("Must be a number");
        }
    });

    var left_footer = footer.find(".left");

    var right_footer = footer.find(".right");
    $('<button></button>').text("Done").click(function() { self._dismiss(); }).appendTo(right_footer);

    this._level = DialogSystem.showDialog(frame);
    this._renderMatrix();
};

ScatterplotDialog.prototype._renderMatrix = function() {
    var self = this;

    var container = this._elmts.tableContainer.html(
        '
Processing...
'
    );

    if (theProject.columnModel.columns.length > 0) {
        var params = {
            project: theProject.id
        };
        $.getJSON("/command/get-columns-info?" + $.param(params),function(data) {
            if (data == null || typeof data.length == 'undefined') {
                container.html("Error calling 'get-columns-info'");
                return;
            }

            var columns = [];
            for (var i = 0; i < data.length; i++) {
                if (data[i].is_numeric) {
                    columns.push(data[i]);
                }
            }

            if (typeof self._plot_size == 'undefined') {
                self._plot_size = Math.max(Math.floor(500 / columns.length / 5) * 5,20);
                self._dot_size = 0.4;
                self._elmts.plotSize.val(self._plot_size);
                self._elmts.dotSize.val(self._dot_size);
            }

            var table = '

';

            var createScatterplot = function(cx, cy, current) {
                var title = cx + ' (x) vs. ' + cy + ' (y)';
                var link = '';
                var plotter_params = {
                    'cx' : cx,
                    'cy' : cy,
                    'l' : self._plot_size,
                    'dot': self._dot_size,
                    'dim_x': self._plot_method,
                    'dim_y': self._plot_method,
                    'r': self._rotation
                };
                var params = {
                    project: theProject.id,
                    engine: JSON.stringify(ui.browsingEngine.getJSON()),
                    plotter: JSON.stringify(plotter_params)
                };
                var h = '<img';

                var attrs = [
                    'width="' + self._plot_size + '"',
                    'height="' + self._plot_size + '"'
                ];

                var url = "/command/get-scatterplot?" + $.param(params);
                attrs.push((current ? 'src="' : 'src2="') + url + '"');

                return link + '';
            };

            for (var i = 0; i < columns.length; i++) {
                table += '
';
                var div_class = "column_header";
                if (columns[i].name == self._column) div_class += " current_column";
                table += '' + columns[i].name + '	'
                for (var j = i + 1; j < columns.length; j++) {
                    var cx = columns[i].name;
                    var cy = columns[j].name;

                    var div_class = "scatterplot";
                    var current = cx == self._column || cy == self._column;
                    if (current) div_class += " current_column";
                    table += '
' + createScatterplot(cx,cy,current) + '
	';
                }
                table += '
';
            }

            table += "

";

            var width = container.width();
            container.empty().css("width", width + "px").html(table);

            container.find("a").click(function() {
                var options = {
                    "name" : $(this).attr("title"),
                    "cx" : $(this).attr("cx"),
                    "cy" : $(this).attr("cy"),
                    "l" : 120,
                    "ex" : "value",
                    "ey" : "value",
                    "dot" : self._dot_size,
                    "dim_x" : self._plot_method,
                    "dim_y" : self._plot_method,
                    'r': self._rotation
                };
                ui.browsingEngine.addFacet("scatterplot", options);
                //self._dismiss();
            });

            container.find(".scatterplot img").hover(
                function() {
                    var elmt = $(this);
                    elmt.addClass("hover");

                    var src2= elmt.attr("src2");
                    if (src2) {
                        elmt.attr("src", src2);
                        elmt.attr("src2", "");
                    }
                }, function() {
                    $(this).removeClass("hover");
                }
            );
        });
    } else {
        container.html(
            '

There are no columns in this dataset

'
        );
    }

};

ScatterplotDialog.prototype._dismiss = function() {
    DialogSystem.dismissUntil(this._level - 1);
};

<|endoftext|>


<commit_before>/*
 * grunt-seajs-concat
 * https://github.com/chenliangyu/grunt-seajs-concat
 *
 * Copyright (c) 2015 binavid chen
 * abc
 */

'use strict';

module.exports = function(grunt) {

  // Project configuration.
  grunt.initConfig({
    jshint: {
      all: [
        'Gruntfile.js',
        'tasks/**/*.js'
      ],
      options: {
        jshintrc: '.jshintrc'
      }
    },

    // Before generating any new files, remove any previously-created files.
    clean: {
      example: ['tmp']
    },

    // Configuration to be run (and then tested).
    seajs_concat: {
        options : {
            base : "example"
        },
        common : {
            src : "example/common/common-*.js",
            dest : "tmp/common/common.js"
        },
        main : {
             options:{
                excludeDependencies : ["common/common"]
             },
             files : {
                 "tmp/page/index.js" : ["example/page/index/index.js"],
                 "tmp/page/inside.js" : ["example/page/inside/inside.js"]
             }
        }
    }
  });

  // Actually load this plugin's task(s).
  grunt.loadTasks('tasks');

  // These plugins provide necessary tasks.
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('jasmine');

  // Whenever the "test" task is run, first clean the "tmp" dir, then run this
  // plugin's task(s), then test the result.
  grunt.registerTask('test', ['clean','specs']);

  // By default, lint and run all tests.
  grunt.registerTask('default', ['jshint', 'test','seajs_concat']);

};
<commit_msg>#26 test webhook test<commit_after>/*
 * grunt-seajs-concat
 * https://github.com/chenliangyu/grunt-seajs-concat
 *
 * Copyright (c) 2015 binavid chen
 * abc
 */

'use strict';

module.exports = function(grunt) {

  // Project configuration
  grunt.initConfig({
    jshint: {
      all: [
        'Gruntfile.js',
        'tasks/**/*.js'
      ],
      options: {
        jshintrc: '.jshintrc'
      }
    },

    // Before generating any new files, remove any previously-created files.
    clean: {
      example: ['tmp']
    },

    // Configuration to be run (and then tested).
    seajs_concat: {
        options : {
            base : "example"
        },
        common : {
            src : "example/common/common-*.js",
            dest : "tmp/common/common.js"
        },
        main : {
             options:{
                excludeDependencies : ["common/common"]
             },
             files : {
                 "tmp/page/index.js" : ["example/page/index/index.js"],
                 "tmp/page/inside.js" : ["example/page/inside/inside.js"]
             }
        }
    }
  });

  // Actually load this plugin's task(s).
  grunt.loadTasks('tasks');

  // These plugins provide necessary tasks.
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('jasmine');

  // Whenever the "test" task is run, first clean the "tmp" dir, then run this
  // plugin's task(s), then test the result.
  grunt.registerTask('test', ['clean','specs']);

  // By default, lint and run all tests.
  grunt.registerTask('default', ['jshint', 'test','seajs_concat']);

};
<|endoftext|>


<commit_before>// TODO: Consider using nodegit instead
import childProcess from 'child_process'

const GIT_PREFIX = 'git'

async function _exec(cmd, options = { timeout: 1000 }) {
  return new Promise((resolve, reject) => {
    childProcess.exec(cmd, options, (err, stdout) => {
      if (err) {
        reject(err)
      } else {
        resolve(stdout.trim())
      }
    })
  })
}

export default class ServerlessGitVariables {
  constructor(serverless, options) {
    this.serverless = serverless
    this.resolvedValues = {}
    const delegate = serverless.variables.getValueFromSource.bind(serverless.variables)

    serverless.variables.getValueFromSource = (variableString) => {
      if (variableString.startsWith(`${GIT_PREFIX}:`)) {
        const variable = variableString.split(`${GIT_PREFIX}:`)[1]
        return this._getValue(variable)
      }

      return delegate(variableString)
    }
    this.hooks = {
      'after:package:initialize': this.exportGitVariables.bind(this),
      'before:offline:start': this.exportGitVariables.bind(this),
      'before:offline:start:init': this.exportGitVariables.bind(this)
    }
  }

  async _getValue(variable) {
    if (this.resolvedValues[variable]) {
      return Promise.resolve(this.resolvedValues[variable])
    }

    return this._getValueFromGit(variable)
  }

  async _getValueFromGit(variable) {
    let value = null
    switch (variable) {
      case 'describe':
        value = await _exec('git describe --always')
        break
      case 'sha1':
        value = await _exec('git rev-parse --short HEAD')
        break
      case 'commit':
        value = await _exec('git rev-parse HEAD')
        break
      case 'branch':
        value = await _exec('git rev-parse --abbrev-ref HEAD')
        break
      case 'message':
        value = await _exec('git log -1 --pretty=%B')
        break
      case 'isDirty':
        const writeTree = await _exec('git write-tree')
        const changes = await _exec(`git diff-index ${writeTree} --`)
        value = `${changes.length > 0}`
        break
      default:
        throw new Error(`Git variable ${variable} is unknown. Candidates are 'describe', 'sha1', 'commit', 'branch', 'message'`)
    }

    // TODO: Figure out why if I don't log, the deasync promise
    // never resolves. Catching it in the debugger or logging
    // causes it to work fine.
    process.stdout.write('')

    // Cache before returning
    this.resolvedValues[variable] = value
    return value
  }

  exportGitVariables() {
    const exportGitVariables = this.serverless.service.custom && this.serverless.service.custom.exportGitVariables
    if (exportGitVariables === false) {
      return Promise.resolve()
    }

    const promises = this.serverless.service.getAllFunctions().map((functionName) => {
      return Promise.all([
        this._getValue('sha1'),
        this._getValue('commit'),
        this._getValue('branch'),
        this._getValue('isDirty')
      ]).then(([sha1, commit, branch, isDirty]) => {
        const func = this.serverless.service.getFunction(functionName)
        this.exportGitVariable(func, 'GIT_COMMIT_SHORT', sha1)
        this.exportGitVariable(func, 'GIT_COMMIT_LONG', commit)
        this.exportGitVariable(func, 'GIT_BRANCH', branch)
        this.exportGitVariable(func, 'GIT_IS_DIRTY', isDirty)
      })
    })
    return Promise.all(promises)
  }

  exportGitVariable(func, variableName, gitValue) {
    if (!func.environment[variableName]) {
      func.environment[variableName] = gitValue
    }

    if (!func.tags) {
      func.tags = {}
    }

    if (!func.tags[variableName]) {
      func.tags[variableName] = gitValue
    }
  }
}
<commit_msg>Initialize `func.environment` if unset<commit_after>// TODO: Consider using nodegit instead
import childProcess from 'child_process'

const GIT_PREFIX = 'git'

async function _exec(cmd, options = { timeout: 1000 }) {
  return new Promise((resolve, reject) => {
    childProcess.exec(cmd, options, (err, stdout) => {
      if (err) {
        reject(err)
      } else {
        resolve(stdout.trim())
      }
    })
  })
}

export default class ServerlessGitVariables {
  constructor(serverless, options) {
    this.serverless = serverless
    this.resolvedValues = {}
    const delegate = serverless.variables.getValueFromSource.bind(serverless.variables)

    serverless.variables.getValueFromSource = (variableString) => {
      if (variableString.startsWith(`${GIT_PREFIX}:`)) {
        const variable = variableString.split(`${GIT_PREFIX}:`)[1]
        return this._getValue(variable)
      }

      return delegate(variableString)
    }
    this.hooks = {
      'after:package:initialize': this.exportGitVariables.bind(this),
      'before:offline:start': this.exportGitVariables.bind(this),
      'before:offline:start:init': this.exportGitVariables.bind(this)
    }
  }

  async _getValue(variable) {
    if (this.resolvedValues[variable]) {
      return Promise.resolve(this.resolvedValues[variable])
    }

    return this._getValueFromGit(variable)
  }

  async _getValueFromGit(variable) {
    let value = null
    switch (variable) {
      case 'describe':
        value = await _exec('git describe --always')
        break
      case 'sha1':
        value = await _exec('git rev-parse --short HEAD')
        break
      case 'commit':
        value = await _exec('git rev-parse HEAD')
        break
      case 'branch':
        value = await _exec('git rev-parse --abbrev-ref HEAD')
        break
      case 'message':
        value = await _exec('git log -1 --pretty=%B')
        break
      case 'isDirty':
        const writeTree = await _exec('git write-tree')
        const changes = await _exec(`git diff-index ${writeTree} --`)
        value = `${changes.length > 0}`
        break
      default:
        throw new Error(`Git variable ${variable} is unknown. Candidates are 'describe', 'sha1', 'commit', 'branch', 'message'`)
    }

    // TODO: Figure out why if I don't log, the deasync promise
    // never resolves. Catching it in the debugger or logging
    // causes it to work fine.
    process.stdout.write('')

    // Cache before returning
    this.resolvedValues[variable] = value
    return value
  }

  exportGitVariables() {
    const exportGitVariables = this.serverless.service.custom && this.serverless.service.custom.exportGitVariables
    if (exportGitVariables === false) {
      return Promise.resolve()
    }

    const promises = this.serverless.service.getAllFunctions().map((functionName) => {
      return Promise.all([
        this._getValue('sha1'),
        this._getValue('commit'),
        this._getValue('branch'),
        this._getValue('isDirty')
      ]).then(([sha1, commit, branch, isDirty]) => {
        const func = this.serverless.service.getFunction(functionName)
        this.exportGitVariable(func, 'GIT_COMMIT_SHORT', sha1)
        this.exportGitVariable(func, 'GIT_COMMIT_LONG', commit)
        this.exportGitVariable(func, 'GIT_BRANCH', branch)
        this.exportGitVariable(func, 'GIT_IS_DIRTY', isDirty)
      })
    })
    return Promise.all(promises)
  }

  exportGitVariable(func, variableName, gitValue) {
    if (!func.environment) {
      func.environment = {}
    }

    if (!func.environment[variableName]) {
      func.environment[variableName] = gitValue
    }

    if (!func.tags) {
      func.tags = {}
    }

    if (!func.tags[variableName]) {
      func.tags[variableName] = gitValue
    }
  }
}
<|endoftext|>


<commit_before>    ////////////////////////////////////////////////
    // remove temporary photo files in iOS
    // code from:
    // https://software.intel.com/en-us/articles/phonegap-camera-api-capture-a-photo-using-a-device-camera-and-edit-zoom-and-crop-the
    /////////////////////////////////////////////////

    // Removes all temporary files created by application. Is to be used when temporary files are not intended to be operated with further
function removeTemporaryFiles() {
    if (isIOS()) {
        navigator.camera.cleanup(onSuccess, onError);
    }
    function onSuccess() {  }
    function onError(message) {  }
}
// Determines whether the current device is running iOS
function isIOS() {
    var iDevices = ["iPad", "iPhone", "iPod"];
    for (var i = 0; i < iDevices.length ; i++ ) {
        if( navigator.platform.indexOf(iDevices[i]) !== -1){
            return true;
        }
    }
    return false;
}
    // Get current position
	//
	function currentPosition(){
		var flag = new Boolean();

		if(navigator.geolocation){
			flag = true;

			//get current location
			navigator.geolocation.getCurrentPosition(function(pos){
				return pos;
			}, function(){
				//has GPS but not working...
				errorGeolocation(flag);
			});
		}
		else {
			//device has no GPS
			flag = false;
			errorGeolocation(flag);
		}

		function errorGeolocation(errFlag){
			if (errFlag == true)
			{
				alert("Geolocation service failed.");
			}
			else
			{
				alert("Your device does not support geolocation.");
			}
		}
		alert('return null');
		return '';
	}

    ////////////////////////////////////////////////
    // phonegap camera code template from
    // http://docs.phonegap.com/en/2.5.0/cordova_camera_camera.md.html
    // API: https://github.com/apache/cordova-plugin-camera/blob/master/doc/index.md
    ////////////////////////////////////////////////

    // Wait for Cordova to connect with the device
    //
    document.addEventListener("deviceready",onDeviceReady,false);

	var photoURI;
    var options;
    // Cordova is ready to be used!
    //
    function onDeviceReady() {
        options = { quality: 50,
			destinationType : Camera.DestinationType.FILE_URI,
			sourceType : Camera.PictureSourceType.CAMERA,
			targetWidth: 500,
			targetHeight: 500,
			allowEdit: true,
			correctOrientation: true,
			encodingType: Camera.EncodingType.JPG,
			saveToPhotoAlbum: true };

		photoURI = null;
	//capturePhoto();

    }

	// display photo on the page
	function showPhoto(imageURI){

      // Get image handle
      //
      var largeImage = document.getElementById('largeImage');

      // Unhide image elements
      //
      largeImage.style.display = 'block';

      // Show the captured photo
      // The inline CSS rules are used to resize the image
      //
      largeImage.src = imageURI;

	}

	// Retrieve and save current GPS location to the given photo
	//
	function savePhotoData(imageURI,shared){
		//retrieve saved photo coords
		var photos = window.localStorage.getItem("photos");
		var lastmoddate;
		window.resolveLocalFileSystemURI(imageURI, function(entry){
			entry.getMetadata(function (metadata){
				lastmoddate = metadata.modificationTime;
			},null);
		}, function(message){
			console.log('resolveFileSystemURI failed: '+getFileErrMsg(message.code));
		});
		if(photos!=''){
			photos = JSON.parse(photos);
		}
		else{
			photos = {};
		}

		//get current GPS location
		var pos = currentPosition();
		if(pos!=''){
			var d = new Date();

			photos[imageURI].coords = pos;
			photos[imageURI].posDate = d.getTime();
		}
		else{
			photos[imageURI].coords = '';
		}

		photos[imageURI].URI = imageURI;
		photos[imageURI].shared = shared;

		if(lastmoddate!=null){
			alert('lastmodDate '+lastmoddate);
			photos[imageURI].modDate = lastmoddate;
		}
		window.localStorage.setItem("photos",JSON.stringify(photos));
	}

    // Called when a photo is successfully retrieved
    //
    function onTakePhotoSuccess(imageURI) {
		alert('GET!! '+imageURI);
		photoURI = imageURI;

		//display photo
		$('#imgContainer').show();
		$('#share').show();
		$('#del').hide();

		showPhoto(imageURI);

		//save photo coords
		savePhotoData(imageURI,false);

    }

	function onGetPhotoSuccess(imageURI){
		alert('Get!!! '+imageURI);
		photoURI = imageURI;

		//display photo
		$('#imgContainer').show();
		$('#share').show();
		$('#del').show();
		showPhoto(imageURI);

	}
    // A button will call this function
    //
    function capturePhoto() {
      // Take picture using device camera and retrieve image as base64-encoded string
      options.sourceType = Camera.PictureSourceType.CAMERA;
	  options.saveToPhotoAlbum = true;
	  options.allowEdit=true;
	  options.targetWidth = 500;
	  options.targetHeight = 500;
      navigator.camera.getPicture(onTakePhotoSuccess, onFail, options);
    }

    // A button will call this function
    //
    function getPhoto() {
      // Retrieve image file location from specified source
      options.sourceType = Camera.PictureSourceType.SAVEDPHOTOALBUM;
	  options.saveToPhotoAlbum = false;
	  options.allowEdit = false;
	  delete options.targetWidth;
	  delete options.targetHeight;
      navigator.camera.getPicture(onGetPhotoSuccess, onFail, options);
    }

    // Called if something bad happens.
    //
    function onFail(message) {
      alert('Failed because: ' + message);
	  delete photoURI;
    }

	//delete image
	function deletePhoto(){
		if(photoURI != null && photoURI != ''){
			alert('deleting photo '+photoURI);
			var photoEntry;
			window.resolveLocalFileSystemURI(photoURI, function (fileEntry) {
				alert('deleting file '+fileEntry.fullPath);
				alert('file url '+fileEntry.toURL());
				photoEntry = fileEntry;
				fileEntry.remove(function (entry) {
					alert('image deleted');

				},function(message){
					alert('image delete failed: '+getFileErrMsg(message.code));
				});
				delete photoURI;
				$('#imgContainer').hide();
				$('#share').hide();
				$('#del').hide();

				// somehow the removeSuccess (or removeFail for that matter)
				// does not fire despite that the file is successfully removed
				// so the associated photo data is deleted here, at URI resolve success

				//get photo data collection from localStorage
				  var photos = window.localStorage.getItem("photos");
				  if(photos!=null && photos!=''){
					photos = JSON.parse(photos);
					alert('delete localstorage');
					//get last mod date from metadata
					var entryLastMod;
					photoEntry.getMetadata(function (metadata){
						entryLastMod = metadata.modificationTime;
						alert('entrylastmod '+entryLastMod.getTime());
					},null);

					if(entryLastMod!=null && entryLastMod!=''){
						//find the photo with the same last mod time and delete
						var pURI;
						for(p in photos){
						alert('for '+p.URI);
							if(p.modDate.getTime() == entryLastMod.getTime()){
								pURI = p;
								break;
							}
						}

						if(pURI !=null && pURI!= ''){
						alert('del local');
							delete photos[pURI.URI];
							window.localStorage.setItem("photos",JSON.stringify(photos));
						}
					}
				  }
			}, function (message){
				console.log('resolveFileSystemURI failed: '+getFileErrMsg(message.code));
				alert('resolveFileSystemURI failed: '+getFileErrMsg(message.code));
			});
		}
	}

	function resSuccess(fileEntry){
		alert('deleting file '+fileEntry.fullPath);
		fileEntry.remove(rmSuccess,rmFail);
		delete photoURI;
	}

	function resFail(message){
		console.log('resolveFileSystemURI failed: '+getFileErrMsg(message.code));
	}

	function rmSuccess(){
		  alert('image deleted');
		  //remove photo coords from localStorage
		  var photos = window.localStorage.getItem("photos");
		  if(photos!=''){
			photos = JSON.parse(photos);
			if(photos[photoURI]!=''){
				delete photos[photoURI];
				window.localStorage.setItem("photos",JSON.stringify(photos));
			}
		  }

		  // Get image handle
		  //
		  // var largeImage = document.getElementById('largeImage');

		  // hide image elements
		  //
		  // largeImage.style.display = 'none';
			$('#imgContainer').hide();
			$('#share').hide();
			$('#del').hide();
		  //reset values
		  // largeImage.src = '';
		  //photoURI = null;
	}

	function rmFail(message){
		alert('image delete failed: '+getFileErrMsg(message.code));
		//photoURI=null;
	}

	function getFileErrMsg(code){
		var msg = '';
		switch (code)
		{
		case FileError.QUOTA_EXCEEDED_ERR:
		msg = 'QUOTA_EXCEEDED_ERR';
		break;
        case FileError.NOT_FOUND_ERR:
		msg = 'NOT_FOUND_ERR';
		break;
        case FileError.SECURITY_ERR:
		msg = 'SECURITY_ERR';
		break;
        case FileError.INVALID_MODIFICATION_ERR:
		msg = 'INVALID_MODIFICATION_ERR';
		break;
        case FileError.INVALID_STATE_ERR:
		msg = 'INVALID_STATE_ERR';
		break;
		case FileError.ABORT_ERR:
		msg = 'ABORT_ERR';
		break;
		case FileError.NOT_READABLE_ERR:
		msg = 'NOT_READABLE_ERR';
		break;
		case FileError.ENCODING_ERR:
		msg = 'ENCODING_ERR';
		break;
        case FileError.SYNTAX_ERR:
		msg = 'SYNTAX_ERR';
		break;
		case FileError.TYPE_MISMATCH_ERR:
		msg = 'TYPE_MISMATCH_ERR';
		break;
        case FileError.PATH_EXISTS_ERR:
		msg = 'PATH_EXISTS_ERR';
		break;
        default:
		msg = code;
        break;
		}
	}

	function shareOnMap(){
		if(photoURI != null && photoURI != ''){
			alert('sharing photo '+photoURI);
			var photoEntry;
			window.resolveLocalFileSystemURI(photoURI, function (fileEntry) {

				photoEntry = fileEntry;

			}, function (message){
				console.log('resolveFileSystemURI failed: '+getFileErrMsg(message.code));
			});

			var photos = window.localStorage.getItem("photos");
			  if(photos!=null && photos!=''){
				photos = JSON.parse(photos);

				//get last mod date from metadata
				var entryLastMod;
				photoEntry.getMetadata(function (metadata){
					entryLastMod = metadata.modificationTime;
				},null);

				if(entryLastMod!=null && entryLastMod!=''){
					//find the photo with the same last mod time
					var pURI;
					for(p in photos){
						if(p.modDate.getTime() == entryLastMod.getTime()){
							pURI = p;
							break;
						}
					}

					if(pURI !=null && pURI!= ''){
						var sharing = false;

						//check for photo's coord, if none, get the current one
						if(pURI.coords == null || pURI.coords ==''){
							alert('getting coords');
							var pos = currentPosition();

							//save new coords to photo data
							if(pos!=null && pos!= ''){
								pURI.coords = pos;
								sharing = true;
								pURI.shared = true;

							}
							else{

								sharing = false;
							}
						}
						//coords already in photo data
						else{
							sharing = true;
							pURI.shared = true;
						}

						if(sharing == true){
							photos[pURI.URI] = pURI;
							window.localStorage.setItem("photos",JSON.stringify(photos));

							//save to local storage to load on map
							var sharedPhotos = window.localStorage.getItem("sharedPhotos");
							if(sharedPhotos == null || sharedPhotos == ''){
								sharedPhotos = {};
							}
							else{
								sharedPhotos = JSON.parse(sharedPhotos);
							}
							sharedPhotos[pURI.URI] = pURI;
							window.localStorage.setItem("sharedPhotos",JSON.stringify(sharedPhotos));

							//upload to server
							//uploadPhoto();
						}
						else{
							alert('share failed, no coords found');
						}

					}
					else{
						alert('sharing failed: photo data not found');
					}

				}
				else{
					alert('sharing failed: photo last date invalid');
				}

			}
			else{
				alert('sharing failed: photo data collection invalid');
			}
		}
		else{
			alert('sharing failed: photoURI invalid');
		}
	}

	/////////////////////////////////////////////////////
	// upload photo code template from:
	// http://docs.phonegap.com/en/3.1.0/cordova_file_file.md.html#FileTransfer
	/////////////////////////////////////////////////////
	function uploadPhoto(){
		if(photoURI!='' && photoURI!=null){
			//get photoURI's photo coords, if any
			var photos = window.localStorage.getItem("photos");
			photos = JSON.parse(photos);

			var pos = photos[photoURI];
			if(pos == ''){
				//try to get current position
				pos = currentPosition();
				if(pos!=''){
					//save photo coords
					savePhotoData(photoURI,true);
				}
				else{
					alert('upload photo error, no geolocation available!');
					return;
				}
			}
			//set upload options
			var uploadOptions = new FileUploadOptions();
			uploadOptions.fileKey="file";
			//uploadOptions.fileName=photoURI.substr(photoURI.lastIndexOf('/')+1);
			uploadOptions.mimeType="image/jpeg";
			var params = {};
			params.coords = pos;
			//params.value2 = "param";
			uploadOptions.params = params;
			var ft = new FileTransfer();
			ft.upload(photoURI, encodeURI("http://some.server.com/upload.php"), win, fail, uploadOptions);

		}
	}
	function win(r) {
	console.log("Code = " + r.responseCode);
	console.log("Response = " + r.response);
	console.log("Sent = " + r.bytesSent);
	}
	function fail(error) {
	alert("An error has occurred: Code = " + error.code);
	console.log("upload error source " + error.source);
	console.log("upload error target " + error.target);
	}

	//delete from server
	function deleteFromServer(){

	}
<commit_msg>fix delete photos bug<commit_after>    ////////////////////////////////////////////////
    // remove temporary photo files in iOS
    // code from:
    // https://software.intel.com/en-us/articles/phonegap-camera-api-capture-a-photo-using-a-device-camera-and-edit-zoom-and-crop-the
    /////////////////////////////////////////////////

    // Removes all temporary files created by application. Is to be used when temporary files are not intended to be operated with further
function removeTemporaryFiles() {
    if (isIOS()) {
        navigator.camera.cleanup(onSuccess, onError);
    }
    function onSuccess() {  }
    function onError(message) {  }
}
// Determines whether the current device is running iOS
function isIOS() {
    var iDevices = ["iPad", "iPhone", "iPod"];
    for (var i = 0; i < iDevices.length ; i++ ) {
        if( navigator.platform.indexOf(iDevices[i]) !== -1){
            return true;
        }
    }
    return false;
}
    // Get current position
	//
	function currentPosition(){
		var flag = new Boolean();

		if(navigator.geolocation){
			flag = true;

			//get current location
			navigator.geolocation.getCurrentPosition(function(pos){
				return pos;
			}, function(){
				//has GPS but not working...
				errorGeolocation(flag);
			});
		}
		else {
			//device has no GPS
			flag = false;
			errorGeolocation(flag);
		}

		function errorGeolocation(errFlag){
			if (errFlag == true)
			{
				alert("Geolocation service failed.");
			}
			else
			{
				alert("Your device does not support geolocation.");
			}
		}
		alert('return null');
		return '';
	}

    ////////////////////////////////////////////////
    // phonegap camera code template from
    // http://docs.phonegap.com/en/2.5.0/cordova_camera_camera.md.html
    // API: https://github.com/apache/cordova-plugin-camera/blob/master/doc/index.md
    ////////////////////////////////////////////////

    // Wait for Cordova to connect with the device
    //
    document.addEventListener("deviceready",onDeviceReady,false);

	var photoURI;
    var options;
    // Cordova is ready to be used!
    //
    function onDeviceReady() {
        options = { quality: 50,
			destinationType : Camera.DestinationType.FILE_URI,
			sourceType : Camera.PictureSourceType.CAMERA,
			targetWidth: 500,
			targetHeight: 500,
			allowEdit: true,
			correctOrientation: true,
			encodingType: Camera.EncodingType.JPG,
			saveToPhotoAlbum: true };

		photoURI = null;
	//capturePhoto();

    }

	// display photo on the page
	function showPhoto(imageURI){

      // Get image handle
      //
      var largeImage = document.getElementById('largeImage');

      // Unhide image elements
      //
      largeImage.style.display = 'block';

      // Show the captured photo
      // The inline CSS rules are used to resize the image
      //
      largeImage.src = imageURI;

	}

	// Retrieve and save current GPS location to the given photo
	//
	function savePhotoData(imageURI,shared){
		//retrieve saved photo coords
		var photos = window.localStorage.getItem("photos");
		var lastmoddate;
		window.resolveLocalFileSystemURI(imageURI, function(entry){
			entry.getMetadata(function (metadata){
				lastmoddate = metadata.modificationTime;
			},null);
		}, function(message){
			console.log('resolveFileSystemURI failed: '+getFileErrMsg(message.code));
		});
		if(photos!=''){
			photos = JSON.parse(photos);
		}
		else{
			photos = {};
		}

		//get current GPS location
		var pos = currentPosition();
		if(pos!=''){
			var d = new Date();

			photos[imageURI].coords = pos;
			photos[imageURI].posDate = d.getTime();
		}
		else{
			photos[imageURI].coords = '';
		}

		photos[imageURI].URI = imageURI;
		photos[imageURI].shared = shared;

		if(lastmoddate!=null){
			alert('lastmodDate '+lastmoddate);
			photos[imageURI].modDate = lastmoddate;
		}
		window.localStorage.setItem("photos",JSON.stringify(photos));
	}

    // Called when a photo is successfully retrieved
    //
    function onTakePhotoSuccess(imageURI) {
		alert('GET!! '+imageURI);
		photoURI = imageURI;

		//display photo
		$('#imgContainer').show();
		$('#share').show();
		$('#del').hide();

		showPhoto(imageURI);

		//save photo coords
		savePhotoData(imageURI,false);

    }

	function onGetPhotoSuccess(imageURI){
		alert('Get!!! '+imageURI);
		photoURI = imageURI;

		//display photo
		$('#imgContainer').show();
		$('#share').show();
		$('#del').show();
		showPhoto(imageURI);

	}
    // A button will call this function
    //
    function capturePhoto() {
      // Take picture using device camera and retrieve image as base64-encoded string
      options.sourceType = Camera.PictureSourceType.CAMERA;
	  options.saveToPhotoAlbum = true;
	  options.allowEdit=true;
	  options.targetWidth = 500;
	  options.targetHeight = 500;
      navigator.camera.getPicture(onTakePhotoSuccess, onFail, options);
    }

    // A button will call this function
    //
    function getPhoto() {
      // Retrieve image file location from specified source
      options.sourceType = Camera.PictureSourceType.SAVEDPHOTOALBUM;
	  options.saveToPhotoAlbum = false;
	  options.allowEdit = false;
	  delete options.targetWidth;
	  delete options.targetHeight;
      navigator.camera.getPicture(onGetPhotoSuccess, onFail, options);
    }

    // Called if something bad happens.
    //
    function onFail(message) {
      alert('Failed because: ' + message);
	  delete photoURI;
    }

	//delete image
	function deletePhoto(){
		if(photoURI != null && photoURI != ''){
			alert('deleting photo '+photoURI);
			var photoEntry;
			window.resolveLocalFileSystemURI(photoURI, function (fileEntry) {
				alert('deleting file '+fileEntry.fullPath);
				alert('file url '+fileEntry.toURL());
				photoEntry = fileEntry;
				fileEntry.remove(function (entry) {
					alert('image deleted');

				},function(message){
					alert('image delete failed: '+getFileErrMsg(message.code));
				});
				delete photoURI;
				$('#imgContainer').hide();
				$('#share').hide();
				$('#del').hide();

				// somehow the removeSuccess (or removeFail for that matter)
				// does not fire despite that the file is successfully removed
				// so the associated photo data is deleted here, at URI resolve success

				//get photo data collection from localStorage
				  var photos = window.localStorage.getItem("photos");
				  if(photos!=null && photos!=''){
					photos = JSON.parse(photos);
					alert('delete localstorage');
					//get last mod date from metadata
					var entryLastMod;
					photoEntry.getMetadata(function (metadata){
						entryLastMod = metadata.modificationTime;
						alert('entrylastmod '+entryLastMod.getTime());
					},null);

					if(entryLastMod!=null && entryLastMod!=''){
						//find the photo with the same last mod time and delete
						var pURI;
						for(p in photos){
						alert('for '+p.URI);
							if(p.modDate.getTime() == entryLastMod.getTime()){
								pURI = p;
								break;
							}
						}

						if(pURI !=null && pURI!= ''){
						alert('del local');
							delete photos[pURI.URI];
							window.localStorage.setItem("photos",JSON.stringify(photos));
						}
					}
				  }
			}, function (message){
				console.log('resolveFileSystemURI failed: '+getFileErrMsg(message.code));
				alert('resolveFileSystemURI failed: '+getFileErrMsg(message.code));
			});
		}
	}

	function resSuccess(fileEntry){
		alert('deleting file '+fileEntry.fullPath);
		fileEntry.remove(rmSuccess,rmFail);
		delete photoURI;
	}

	function resFail(message){
		console.log('resolveFileSystemURI failed: '+getFileErrMsg(message.code));
	}

	function rmSuccess(){
		  alert('image deleted');
		  //remove photo coords from localStorage
		  var photos = window.localStorage.getItem("photos");
		  if(photos!=''){
			photos = JSON.parse(photos);
			if(photos[photoURI]!=''){
				delete photos[photoURI];
				window.localStorage.setItem("photos",JSON.stringify(photos));
			}
		  }

		  // Get image handle
		  //
		  // var largeImage = document.getElementById('largeImage');

		  // hide image elements
		  //
		  // largeImage.style.display = 'none';
			$('#imgContainer').hide();
			$('#share').hide();
			$('#del').hide();
		  //reset values
		  // largeImage.src = '';
		  //photoURI = null;
	}

	function rmFail(message){
		alert('image delete failed: '+getFileErrMsg(message.code));
		//photoURI=null;
	}

	function getFileErrMsg(code){
		var msg = '';
		switch (code)
		{
		case FileError.QUOTA_EXCEEDED_ERR:
		msg = 'QUOTA_EXCEEDED_ERR';
		break;
        case FileError.NOT_FOUND_ERR:
		msg = 'NOT_FOUND_ERR';
		break;
        case FileError.SECURITY_ERR:
		msg = 'SECURITY_ERR';
		break;
        case FileError.INVALID_MODIFICATION_ERR:
		msg = 'INVALID_MODIFICATION_ERR';
		break;
        case FileError.INVALID_STATE_ERR:
		msg = 'INVALID_STATE_ERR';
		break;
		case FileError.ABORT_ERR:
		msg = 'ABORT_ERR';
		break;
		case FileError.NOT_READABLE_ERR:
		msg = 'NOT_READABLE_ERR';
		break;
		case FileError.ENCODING_ERR:
		msg = 'ENCODING_ERR';
		break;
        case FileError.SYNTAX_ERR:
		msg = 'SYNTAX_ERR';
		break;
		case FileError.TYPE_MISMATCH_ERR:
		msg = 'TYPE_MISMATCH_ERR';
		break;
        case FileError.PATH_EXISTS_ERR:
		msg = 'PATH_EXISTS_ERR';
		break;
        default:
		msg = code;
        break;
		}
		return msg;
	}

	function shareOnMap(){
		if(photoURI != null && photoURI != ''){
			alert('sharing photo '+photoURI);
			var photoEntry;
			window.resolveLocalFileSystemURI(photoURI, function (fileEntry) {

				photoEntry = fileEntry;

			}, function (message){
				console.log('resolveFileSystemURI failed: '+getFileErrMsg(message.code));
			});

			var photos = window.localStorage.getItem("photos");
			  if(photos!=null && photos!=''){
				photos = JSON.parse(photos);

				//get last mod date from metadata
				var entryLastMod;
				photoEntry.getMetadata(function (metadata){
					entryLastMod = metadata.modificationTime;
				},null);

				if(entryLastMod!=null && entryLastMod!=''){
					//find the photo with the same last mod time
					var pURI;
					for(p in photos){
						if(p.modDate.getTime() == entryLastMod.getTime()){
							pURI = p;
							break;
						}
					}

					if(pURI !=null && pURI!= ''){
						var sharing = false;

						//check for photo's coord, if none, get the current one
						if(pURI.coords == null || pURI.coords ==''){
							alert('getting coords');
							var pos = currentPosition();

							//save new coords to photo data
							if(pos!=null && pos!= ''){
								pURI.coords = pos;
								sharing = true;
								pURI.shared = true;

							}
							else{

								sharing = false;
							}
						}
						//coords already in photo data
						else{
							sharing = true;
							pURI.shared = true;
						}

						if(sharing == true){
							photos[pURI.URI] = pURI;
							window.localStorage.setItem("photos",JSON.stringify(photos));

							//save to local storage to load on map
							var sharedPhotos = window.localStorage.getItem("sharedPhotos");
							if(sharedPhotos == null || sharedPhotos == ''){
								sharedPhotos = {};
							}
							else{
								sharedPhotos = JSON.parse(sharedPhotos);
							}
							sharedPhotos[pURI.URI] = pURI;
							window.localStorage.setItem("sharedPhotos",JSON.stringify(sharedPhotos));

							//upload to server
							//uploadPhoto();
						}
						else{
							alert('share failed, no coords found');
						}

					}
					else{
						alert('sharing failed: photo data not found');
					}

				}
				else{
					alert('sharing failed: photo last date invalid');
				}

			}
			else{
				alert('sharing failed: photo data collection invalid');
			}
		}
		else{
			alert('sharing failed: photoURI invalid');
		}
	}

	/////////////////////////////////////////////////////
	// upload photo code template from:
	// http://docs.phonegap.com/en/3.1.0/cordova_file_file.md.html#FileTransfer
	/////////////////////////////////////////////////////
	function uploadPhoto(){
		if(photoURI!='' && photoURI!=null){
			//get photoURI's photo coords, if any
			var photos = window.localStorage.getItem("photos");
			photos = JSON.parse(photos);

			var pos = photos[photoURI];
			if(pos == ''){
				//try to get current position
				pos = currentPosition();
				if(pos!=''){
					//save photo coords
					savePhotoData(photoURI,true);
				}
				else{
					alert('upload photo error, no geolocation available!');
					return;
				}
			}
			//set upload options
			var uploadOptions = new FileUploadOptions();
			uploadOptions.fileKey="file";
			//uploadOptions.fileName=photoURI.substr(photoURI.lastIndexOf('/')+1);
			uploadOptions.mimeType="image/jpeg";
			var params = {};
			params.coords = pos;
			//params.value2 = "param";
			uploadOptions.params = params;
			var ft = new FileTransfer();
			ft.upload(photoURI, encodeURI("http://some.server.com/upload.php"), win, fail, uploadOptions);

		}
	}
	function win(r) {
	console.log("Code = " + r.responseCode);
	console.log("Response = " + r.response);
	console.log("Sent = " + r.bytesSent);
	}
	function fail(error) {
	alert("An error has occurred: Code = " + error.code);
	console.log("upload error source " + error.source);
	console.log("upload error target " + error.target);
	}

	//delete from server
	function deleteFromServer(){

	}
<|endoftext|>


<commit_before>// Generated on 2015-03-28 using generator-angular 0.11.1
'use strict';

// # Globbing
// for performance reasons we're only matching one level down:
// 'test/spec/{,*/}*.js'
// use this if you want to recursively match all subfolders:
// 'test/spec/**/*.js'

module.exports = function (grunt) {

  // Load grunt tasks automatically
  require('load-grunt-tasks')(grunt);

  // Time how long tasks take. Can help when optimizing build times
  require('time-grunt')(grunt);

  // Configurable paths for the application
  var appConfig = {
    app: require('./bower.json').appPath || 'app',
    dist: 'dist',
    raw: '.raw',
    repo: 'git@github.com:cloudfleet/blimp-cockpit.git',
    repo_branch: 'production'
  };

  // Define the configuration for all the tasks
  grunt.initConfig({

    // Project settings
    yeoman: appConfig,

    // Watches files for changes and runs tasks based on the changed files
    watch: {
      bower: {
        files: ['bower.json'],
        tasks: ['wiredep']
      },
      js: {
        files: ['<%= yeoman.app %>/scripts/{,*/}*.js'],
        tasks: ['newer:jshint:all'],
        options: {
          livereload: '<%= connect.options.livereload %>'
        }
      },
      jsTest: {
        files: ['test/spec/{,*/}*.js'],
        tasks: ['newer:jshint:test', 'karma']
      },
      compass: {
        files: ['<%= yeoman.app %>/styles/{,*/}*.{scss,sass}'],
        tasks: ['compass:server', 'autoprefixer']
      },
      gruntfile: {
        files: ['Gruntfile.js']
      },
      livereload: {
        options: {
          livereload: '<%= connect.options.livereload %>'
        },
        files: [
          '<%= yeoman.app %>/{,*/}*.html',
          '.tmp/styles/{,*/}*.css',
          '<%= yeoman.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}'
        ]
      }
    },

    // The actual grunt server settings
    connect: {
      options: {
        port: 9000,
        // Change this to '0.0.0.0' to access the server from outside.
        hostname: 'localhost',
        livereload: 35729
      },
      livereload: {
        options: {
          open: true,
          middleware: function (connect) {
            return [
              connect.static('.tmp'),
              connect().use(
                '/bower_components',
                connect.static('./bower_components')
              ),
              connect().use(
                '/app/styles',
                connect.static('./app/styles')
              ),
              connect.static(appConfig.app)
            ];
          }
        }
      },
      test: {
        options: {
          port: 9001,
          middleware: function (connect) {
            return [
              connect.static('.tmp'),
              connect.static('test'),
              connect().use(
                '/bower_components',
                connect.static('./bower_components')
              ),
              connect.static(appConfig.app)
            ];
          }
        }
      },
      dist: {
        options: {
          open: true,
          base: '<%= yeoman.dist %>'
        }
      }
    },

    // Make sure code styles are up to par and there are no obvious mistakes
    jshint: {
      options: {
        jshintrc: '.jshintrc',
        reporter: require('jshint-stylish')
      },
      all: {
        src: [
          'Gruntfile.js',
          '<%= yeoman.app %>/scripts/{,*/}*.js'
        ]
      },
      test: {
        options: {
          jshintrc: 'test/.jshintrc'
        },
        src: ['test/spec/{,*/}*.js']
      }
    },

    // Empties folders to start fresh
    clean: {
      dist: {
        files: [{
          dot: true,
          src: [
            '.tmp',
            '<%= yeoman.dist %>/{,*/}*',
            '!<%= yeoman.dist %>/.git{,*/}*'
          ]
        }]
      },
      server: '.tmp'
    },

    // Add vendor prefixed styles
    autoprefixer: {
      options: {
        browsers: ['last 1 version']
      },
      server: {
        options: {
          map: true,
        },
        files: [{
          expand: true,
          cwd: '.tmp/styles/',
          src: '{,*/}*.css',
          dest: '.tmp/styles/'
        }]
      },
      dist: {
        files: [{
          expand: true,
          cwd: '.tmp/styles/',
          src: '{,*/}*.css',
          dest: '.tmp/styles/'
        }]
      }
    },

    // Automatically inject Bower components into the app
    wiredep: {
      app: {
        src: ['<%= yeoman.app %>/index.html'],
        ignorePath:  /\.\.\//
      },
      test: {
        devDependencies: true,
        src: '<%= karma.unit.configFile %>',
        ignorePath:  /\.\.\//,
        fileTypes:{
          js: {
            block: /(([\s\t]*)\/{2}\s*?bower:\s*?(\S*))(\n|\r|.)*?(\/{2}\s*endbower)/gi,
              detect: {
                js: /'(.*\.js)'/gi
              },
              replace: {
                js: '\'{{filePath}}\','
              }
            }
          }
      },
      sass: {
        src: ['<%= yeoman.app %>/styles/{,*/}*.{scss,sass}'],
        ignorePath: /(\.\.\/){1,2}bower_components\//
      }
    },

    // Compiles Sass to CSS and generates necessary files if requested
    compass: {
      options: {
        sassDir: '<%= yeoman.app %>/styles',
        cssDir: '.tmp/styles',
        generatedImagesDir: '.tmp/images/generated',
        imagesDir: '<%= yeoman.app %>/images',
        javascriptsDir: '<%= yeoman.app %>/scripts',
        fontsDir: '<%= yeoman.app %>/styles/fonts',
        importPath: './bower_components',
        httpImagesPath: '/images',
        httpGeneratedImagesPath: '/images/generated',
        httpFontsPath: '/styles/fonts',
        relativeAssets: false,
        assetCacheBuster: false,
        raw: 'Sass::Script::Number.precision = 10\n'
      },
      dist: {
        options: {
          generatedImagesDir: '<%= yeoman.dist %>/images/generated'
        }
      },
      server: {
        options: {
          sourcemap: true
        }
      }
    },

    // Renames files for browser caching purposes
    filerev: {
      dist: {
        src: [
          '<%= yeoman.dist %>/scripts/{,*/}*.js',
          '<%= yeoman.dist %>/styles/{,*/}*.css',
          '<%= yeoman.dist %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}',
          '<%= yeoman.dist %>/styles/fonts/*'
        ]
      }
    },

    // Reads HTML for usemin blocks to enable smart builds that automatically
    // concat, minify and revision files. Creates configurations in memory so
    // additional tasks can operate on them
    useminPrepare: {
      html: '<%= yeoman.app %>/index.html',
      options: {
        dest: '<%= yeoman.dist %>',
        flow: {
          html: {
            steps: {
              js: ['concat', 'uglifyjs'],
              css: ['cssmin']
            },
            post: {}
          }
        }
      }
    },

    // Performs rewrites based on filerev and the useminPrepare configuration
    usemin: {
      html: ['<%= yeoman.dist %>/{,*/}*.html'],
      css: ['<%= yeoman.dist %>/styles/{,*/}*.css'],
      options: {
        assetsDirs: [
          '<%= yeoman.dist %>',
          '<%= yeoman.dist %>/images',
          '<%= yeoman.dist %>/styles'
        ]
      }
    },

    // The following *-min tasks will produce minified files in the dist folder
    // By default, your `index.html`'s <!-- Usemin block --> will take care of
    // minification. These next options are pre-configured if you do not wish
    // to use the Usemin blocks.
    cssmin: {
      dist: {
        files: {
          '<%= yeoman.dist %>/styles/main.css': [
            '.tmp/styles/{,*/}*.css'
          ]
        }
      },
      options: {
        sourceMap: true
      }
    },
    uglify: {
      dist: {
        files: {
          '<%= yeoman.dist %>/scripts/scripts.js': [
            '<%= yeoman.dist %>/scripts/scripts.js'
          ]
        }
      },
      options: {
        sourceMap: true,
        sourceMapIn: function(uglifySource) {
          return uglifySource + '.map';
        },
        sourceMapIncludeSources: true
      }
    },
    concat: {
      dist: {},
      options: {
        sourceMap: true
      }
    },

    imagemin: {
      dist: {
        files: [{
          expand: true,
          cwd: '<%= yeoman.app %>/images',
          src: '{,*/}*.{png,jpg,jpeg,gif}',
          dest: '<%= yeoman.dist %>/images'
        }]
      }
    },

    svgmin: {
      dist: {
        files: [{
          expand: true,
          cwd: '<%= yeoman.app %>/images',
          src: '{,*/}*.svg',
          dest: '<%= yeoman.dist %>/images'
        }]
      }
    },

    htmlmin: {
      dist: {
        options: {
          collapseWhitespace: true,
          conservativeCollapse: true,
          collapseBooleanAttributes: true,
          removeCommentsFromCDATA: true,
          removeOptionalTags: true
        },
        files: [{
          expand: true,
          cwd: '<%= yeoman.dist %>',
          src: ['*.html', 'views/{,*/}*.html'],
          dest: '<%= yeoman.dist %>'
        }]
      }
    },

    // ng-annotate tries to make the code safe for minification automatically
    // by using the Angular long form for dependency injection.
    ngAnnotate: {
      dist: {
        files: [{
          expand: true,
          cwd: '.tmp/concat/scripts',
          src: '*.js',
          dest: '.tmp/concat/scripts'
        }]
      }
    },

    // Copies remaining files to places other tasks can use
    copy: {
      dist: {
        files: [{
          expand: true,
          dot: true,
          cwd: '<%= yeoman.app %>',
          dest: '<%= yeoman.dist %>',
          src: [
            '*.{ico,png,txt}',
            '.htaccess',
            'Dockerfile', // the production Dockerfile
            '*.html',
            'views/{,*/}*.html',
            'images/{,*/}*.{webp}',
            'styles/fonts/{,*/}*.*',
            'scripts/l10n/{,*/}*.*'
          ]
        }, {
          expand: true,
          cwd: '.tmp/images',
          dest: '<%= yeoman.dist %>/images',
          src: ['generated/*']
        }, {
          expand: true,
          cwd: '.',
          src: 'bower_components/bootstrap-sass-official/assets/fonts/bootstrap/*',
          dest: '<%= yeoman.dist %>'
        }, {
          expand: true,
          cwd: '.',
          src: 'bower_components/**',
          dest: '<%= yeoman.dist %>'
        }, {
          expand: true,
          cwd: 'bower_components/font-awesome/fonts',
          src: '**',
          dest: '<%= yeoman.dist %>/fonts'
        }]
      },
      /* copy in original scripts to .raw/
      so that lazy loading can use them */
      raw1: {
        files: [{
          expand: true,
          dot: true,
          cwd: '<%= yeoman.app %>',
          dest: '<%= yeoman.raw %>',
          src: [
            'scripts/{,*/}*.*'
          ]
        }]
      },
      /* copy in original scripts from .raw/
       to dist/, so that lazy loading can use them */
      raw2: {
        files: [{
          expand: true,
          dot: true,
          cwd: '<%= yeoman.raw %>',
          dest: '<%= yeoman.dist %>',
          src: [
            'scripts/{,*/}*.*'
          ]
        }]
      },
      styles: {
        expand: true,
        cwd: '<%= yeoman.app %>/styles',
        dest: '.tmp/styles/',
        src: '{,*/}*.css'
      }
    },

    // Run some tasks in parallel to speed up the build process
    concurrent: {
      server: [
        'compass:server'
      ],
      test: [
        'compass'
      ],
      dist: [
        'compass:dist',
        'imagemin',
        'svgmin'
      ]
    },

    // Test settings
    karma: {
      unit: {
        configFile: 'test/karma.conf.js',
        singleRun: true
      }
    },

    // Deploy to production branch
    buildcontrol: {
      options: {
        dir: '<%= yeoman.dist %>',
        commit: true,
        push: true,
        message: 'Built %sourceName% from commit %sourceCommit% on branch %sourceBranch%'
      },
      production: {
        options: {
          remote: '<%= yeoman.repo %>',
          branch: '<%= yeoman.repo_branch %>'
        }
      }
    }

  });

  grunt.registerTask('serve', 'Compile then start a connect web server', function (target) {
    if (target === 'dist') {
      return grunt.task.run(['build', 'connect:dist:keepalive']);
    }

    grunt.task.run([
      'clean:server',
      'wiredep',
      'concurrent:server',
      'autoprefixer:server',
      'connect:livereload',
      'watch'
    ]);
  });

  grunt.registerTask('server', 'DEPRECATED TASK. Use the "serve" task instead', function (target) {
    grunt.log.warn('The `server` task has been deprecated. Use `grunt serve` to start a server.');
    grunt.task.run(['serve:' + target]);
  });

  grunt.registerTask('test', [
    'clean:server',
    'wiredep',
    'concurrent:test',
    'autoprefixer',
    'connect:test',
    'karma'
  ]);

  grunt.registerTask('build', [
    'clean:dist',
    'copy:raw1', // for lazy loading
    'wiredep',
    'useminPrepare',
    'concurrent:dist',
    'autoprefixer',
    'concat',
    'ngAnnotate',
    'copy:dist',
    'cssmin',
    'uglify',
    'filerev',
    'usemin',
    'htmlmin',
    'copy:raw2' // for lazy loading
  ]);

  grunt.registerTask('deploy', [
    'build',
    'buildcontrol:production'
  ]);

  grunt.registerTask('default', [
    'newer:jshint',
    'test',
    'build'
  ]);
};
<commit_msg>add copy stanza for simple-line-icons fonts<commit_after>// Generated on 2015-03-28 using generator-angular 0.11.1
'use strict';

// # Globbing
// for performance reasons we're only matching one level down:
// 'test/spec/{,*/}*.js'
// use this if you want to recursively match all subfolders:
// 'test/spec/**/*.js'

module.exports = function (grunt) {

  // Load grunt tasks automatically
  require('load-grunt-tasks')(grunt);

  // Time how long tasks take. Can help when optimizing build times
  require('time-grunt')(grunt);

  // Configurable paths for the application
  var appConfig = {
    app: require('./bower.json').appPath || 'app',
    dist: 'dist',
    raw: '.raw',
    repo: 'git@github.com:cloudfleet/blimp-cockpit.git',
    repo_branch: 'production'
  };

  // Define the configuration for all the tasks
  grunt.initConfig({

    // Project settings
    yeoman: appConfig,

    // Watches files for changes and runs tasks based on the changed files
    watch: {
      bower: {
        files: ['bower.json'],
        tasks: ['wiredep']
      },
      js: {
        files: ['<%= yeoman.app %>/scripts/{,*/}*.js'],
        tasks: ['newer:jshint:all'],
        options: {
          livereload: '<%= connect.options.livereload %>'
        }
      },
      jsTest: {
        files: ['test/spec/{,*/}*.js'],
        tasks: ['newer:jshint:test', 'karma']
      },
      compass: {
        files: ['<%= yeoman.app %>/styles/{,*/}*.{scss,sass}'],
        tasks: ['compass:server', 'autoprefixer']
      },
      gruntfile: {
        files: ['Gruntfile.js']
      },
      livereload: {
        options: {
          livereload: '<%= connect.options.livereload %>'
        },
        files: [
          '<%= yeoman.app %>/{,*/}*.html',
          '.tmp/styles/{,*/}*.css',
          '<%= yeoman.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}'
        ]
      }
    },

    // The actual grunt server settings
    connect: {
      options: {
        port: 9000,
        // Change this to '0.0.0.0' to access the server from outside.
        hostname: 'localhost',
        livereload: 35729
      },
      livereload: {
        options: {
          open: true,
          middleware: function (connect) {
            return [
              connect.static('.tmp'),
              connect().use(
                '/bower_components',
                connect.static('./bower_components')
              ),
              connect().use(
                '/app/styles',
                connect.static('./app/styles')
              ),
              connect.static(appConfig.app)
            ];
          }
        }
      },
      test: {
        options: {
          port: 9001,
          middleware: function (connect) {
            return [
              connect.static('.tmp'),
              connect.static('test'),
              connect().use(
                '/bower_components',
                connect.static('./bower_components')
              ),
              connect.static(appConfig.app)
            ];
          }
        }
      },
      dist: {
        options: {
          open: true,
          base: '<%= yeoman.dist %>'
        }
      }
    },

    // Make sure code styles are up to par and there are no obvious mistakes
    jshint: {
      options: {
        jshintrc: '.jshintrc',
        reporter: require('jshint-stylish')
      },
      all: {
        src: [
          'Gruntfile.js',
          '<%= yeoman.app %>/scripts/{,*/}*.js'
        ]
      },
      test: {
        options: {
          jshintrc: 'test/.jshintrc'
        },
        src: ['test/spec/{,*/}*.js']
      }
    },

    // Empties folders to start fresh
    clean: {
      dist: {
        files: [{
          dot: true,
          src: [
            '.tmp',
            '<%= yeoman.dist %>/{,*/}*',
            '!<%= yeoman.dist %>/.git{,*/}*'
          ]
        }]
      },
      server: '.tmp'
    },

    // Add vendor prefixed styles
    autoprefixer: {
      options: {
        browsers: ['last 1 version']
      },
      server: {
        options: {
          map: true,
        },
        files: [{
          expand: true,
          cwd: '.tmp/styles/',
          src: '{,*/}*.css',
          dest: '.tmp/styles/'
        }]
      },
      dist: {
        files: [{
          expand: true,
          cwd: '.tmp/styles/',
          src: '{,*/}*.css',
          dest: '.tmp/styles/'
        }]
      }
    },

    // Automatically inject Bower components into the app
    wiredep: {
      app: {
        src: ['<%= yeoman.app %>/index.html'],
        ignorePath:  /\.\.\//
      },
      test: {
        devDependencies: true,
        src: '<%= karma.unit.configFile %>',
        ignorePath:  /\.\.\//,
        fileTypes:{
          js: {
            block: /(([\s\t]*)\/{2}\s*?bower:\s*?(\S*))(\n|\r|.)*?(\/{2}\s*endbower)/gi,
              detect: {
                js: /'(.*\.js)'/gi
              },
              replace: {
                js: '\'{{filePath}}\','
              }
            }
          }
      },
      sass: {
        src: ['<%= yeoman.app %>/styles/{,*/}*.{scss,sass}'],
        ignorePath: /(\.\.\/){1,2}bower_components\//
      }
    },

    // Compiles Sass to CSS and generates necessary files if requested
    compass: {
      options: {
        sassDir: '<%= yeoman.app %>/styles',
        cssDir: '.tmp/styles',
        generatedImagesDir: '.tmp/images/generated',
        imagesDir: '<%= yeoman.app %>/images',
        javascriptsDir: '<%= yeoman.app %>/scripts',
        fontsDir: '<%= yeoman.app %>/styles/fonts',
        importPath: './bower_components',
        httpImagesPath: '/images',
        httpGeneratedImagesPath: '/images/generated',
        httpFontsPath: '/styles/fonts',
        relativeAssets: false,
        assetCacheBuster: false,
        raw: 'Sass::Script::Number.precision = 10\n'
      },
      dist: {
        options: {
          generatedImagesDir: '<%= yeoman.dist %>/images/generated'
        }
      },
      server: {
        options: {
          sourcemap: true
        }
      }
    },

    // Renames files for browser caching purposes
    filerev: {
      dist: {
        src: [
          '<%= yeoman.dist %>/scripts/{,*/}*.js',
          '<%= yeoman.dist %>/styles/{,*/}*.css',
          '<%= yeoman.dist %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}',
          '<%= yeoman.dist %>/styles/fonts/*'
        ]
      }
    },

    // Reads HTML for usemin blocks to enable smart builds that automatically
    // concat, minify and revision files. Creates configurations in memory so
    // additional tasks can operate on them
    useminPrepare: {
      html: '<%= yeoman.app %>/index.html',
      options: {
        dest: '<%= yeoman.dist %>',
        flow: {
          html: {
            steps: {
              js: ['concat', 'uglifyjs'],
              css: ['cssmin']
            },
            post: {}
          }
        }
      }
    },

    // Performs rewrites based on filerev and the useminPrepare configuration
    usemin: {
      html: ['<%= yeoman.dist %>/{,*/}*.html'],
      css: ['<%= yeoman.dist %>/styles/{,*/}*.css'],
      options: {
        assetsDirs: [
          '<%= yeoman.dist %>',
          '<%= yeoman.dist %>/images',
          '<%= yeoman.dist %>/styles'
        ]
      }
    },

    // The following *-min tasks will produce minified files in the dist folder
    // By default, your `index.html`'s <!-- Usemin block --> will take care of
    // minification. These next options are pre-configured if you do not wish
    // to use the Usemin blocks.
    cssmin: {
      dist: {
        files: {
          '<%= yeoman.dist %>/styles/main.css': [
            '.tmp/styles/{,*/}*.css'
          ]
        }
      },
      options: {
        sourceMap: true
      }
    },
    uglify: {
      dist: {
        files: {
          '<%= yeoman.dist %>/scripts/scripts.js': [
            '<%= yeoman.dist %>/scripts/scripts.js'
          ]
        }
      },
      options: {
        sourceMap: true,
        sourceMapIn: function(uglifySource) {
          return uglifySource + '.map';
        },
        sourceMapIncludeSources: true
      }
    },
    concat: {
      dist: {},
      options: {
        sourceMap: true
      }
    },

    imagemin: {
      dist: {
        files: [{
          expand: true,
          cwd: '<%= yeoman.app %>/images',
          src: '{,*/}*.{png,jpg,jpeg,gif}',
          dest: '<%= yeoman.dist %>/images'
        }]
      }
    },

    svgmin: {
      dist: {
        files: [{
          expand: true,
          cwd: '<%= yeoman.app %>/images',
          src: '{,*/}*.svg',
          dest: '<%= yeoman.dist %>/images'
        }]
      }
    },

    htmlmin: {
      dist: {
        options: {
          collapseWhitespace: true,
          conservativeCollapse: true,
          collapseBooleanAttributes: true,
          removeCommentsFromCDATA: true,
          removeOptionalTags: true
        },
        files: [{
          expand: true,
          cwd: '<%= yeoman.dist %>',
          src: ['*.html', 'views/{,*/}*.html'],
          dest: '<%= yeoman.dist %>'
        }]
      }
    },

    // ng-annotate tries to make the code safe for minification automatically
    // by using the Angular long form for dependency injection.
    ngAnnotate: {
      dist: {
        files: [{
          expand: true,
          cwd: '.tmp/concat/scripts',
          src: '*.js',
          dest: '.tmp/concat/scripts'
        }]
      }
    },

    // Copies remaining files to places other tasks can use
    copy: {
      dist: {
        files: [{
          expand: true,
          dot: true,
          cwd: '<%= yeoman.app %>',
          dest: '<%= yeoman.dist %>',
          src: [
            '*.{ico,png,txt}',
            '.htaccess',
            'Dockerfile', // the production Dockerfile
            '*.html',
            'views/{,*/}*.html',
            'images/{,*/}*.{webp}',
            'styles/fonts/{,*/}*.*',
            'scripts/l10n/{,*/}*.*'
          ]
        }, {
          expand: true,
          cwd: '.tmp/images',
          dest: '<%= yeoman.dist %>/images',
          src: ['generated/*']
        }, {
          expand: true,
          cwd: '.',
          src: 'bower_components/bootstrap-sass-official/assets/fonts/bootstrap/*',
          dest: '<%= yeoman.dist %>'
        }, {
          expand: true,
          cwd: '.',
          src: 'bower_components/**',
          dest: '<%= yeoman.dist %>'
        }, {
          expand: true,
          cwd: 'bower_components/font-awesome/fonts',
          src: '**',
          dest: '<%= yeoman.dist %>/fonts'
        }, {
          expand: true,
          cwd: 'bower_components/simple-line-icons/fonts',
          src: '**',
          dest: '<%= yeoman.dist %>/fonts'
        }]
      },
      /* copy in original scripts to .raw/
      so that lazy loading can use them */
      raw1: {
        files: [{
          expand: true,
          dot: true,
          cwd: '<%= yeoman.app %>',
          dest: '<%= yeoman.raw %>',
          src: [
            'scripts/{,*/}*.*'
          ]
        }]
      },
      /* copy in original scripts from .raw/
       to dist/, so that lazy loading can use them */
      raw2: {
        files: [{
          expand: true,
          dot: true,
          cwd: '<%= yeoman.raw %>',
          dest: '<%= yeoman.dist %>',
          src: [
            'scripts/{,*/}*.*'
          ]
        }]
      },
      styles: {
        expand: true,
        cwd: '<%= yeoman.app %>/styles',
        dest: '.tmp/styles/',
        src: '{,*/}*.css'
      }
    },

    // Run some tasks in parallel to speed up the build process
    concurrent: {
      server: [
        'compass:server'
      ],
      test: [
        'compass'
      ],
      dist: [
        'compass:dist',
        'imagemin',
        'svgmin'
      ]
    },

    // Test settings
    karma: {
      unit: {
        configFile: 'test/karma.conf.js',
        singleRun: true
      }
    },

    // Deploy to production branch
    buildcontrol: {
      options: {
        dir: '<%= yeoman.dist %>',
        commit: true,
        push: true,
        message: 'Built %sourceName% from commit %sourceCommit% on branch %sourceBranch%'
      },
      production: {
        options: {
          remote: '<%= yeoman.repo %>',
          branch: '<%= yeoman.repo_branch %>'
        }
      }
    }

  });

  grunt.registerTask('serve', 'Compile then start a connect web server', function (target) {
    if (target === 'dist') {
      return grunt.task.run(['build', 'connect:dist:keepalive']);
    }

    grunt.task.run([
      'clean:server',
      'wiredep',
      'concurrent:server',
      'autoprefixer:server',
      'connect:livereload',
      'watch'
    ]);
  });

  grunt.registerTask('server', 'DEPRECATED TASK. Use the "serve" task instead', function (target) {
    grunt.log.warn('The `server` task has been deprecated. Use `grunt serve` to start a server.');
    grunt.task.run(['serve:' + target]);
  });

  grunt.registerTask('test', [
    'clean:server',
    'wiredep',
    'concurrent:test',
    'autoprefixer',
    'connect:test',
    'karma'
  ]);

  grunt.registerTask('build', [
    'clean:dist',
    'copy:raw1', // for lazy loading
    'wiredep',
    'useminPrepare',
    'concurrent:dist',
    'autoprefixer',
    'concat',
    'ngAnnotate',
    'copy:dist',
    'cssmin',
    'uglify',
    'filerev',
    'usemin',
    'htmlmin',
    'copy:raw2' // for lazy loading
  ]);

  grunt.registerTask('deploy', [
    'build',
    'buildcontrol:production'
  ]);

  grunt.registerTask('default', [
    'newer:jshint',
    'test',
    'build'
  ]);
};
<|endoftext|>


<commit_before>import styled, { css } from 'styled-components'

import DefaultButton from './Default'

const RedButton = styled(DefaultButton)`
  border-color: var(--red-70);

  &:not(:disabled):hover {
    border-color: var(--red-80);
  }

  ${props =>
    props.outlined
      ? css`
          color: var(--red-70);

          &:hover {
            color: var(--red-80);
          }
        `
      : css`
          background-color: var(--red-70);
          color: var(--white);

          &:hover {
            background-color: var(--red-80);
          }
        `}
`

export default RedButton
<commit_msg>Remove unused class<commit_after><|endoftext|>


<commit_before>/*
 * notifIt! by @naoxink
 */
function notif(config) {
    var to = null;
    var defaults = {
        type: "info",
        width: 400,
        height: 60,
        position: "right",
        autohide: 1,
        msg: "This is my default message",
        opacity: 1,
        multiline: 0,
        fade: 0,
        bgcolor: "",
        color: "",
        timeout: 5000,
        zindex: null,
        offset: 0
    };
    jQuery.extend(defaults, config);

    position = defaults.position;

    if (defaults.width > 0) {
        defaults.width = defaults.width;
    } else if (defaults.width === "all") {
        defaults.width = screen.width - 60;
    }

    if (defaults.height < 100 && defaults.height > 0) {
        height = defaults.height;
    }

    var div = "

" + defaults.msg + "

";
    jQuery("#ui_notifIt").remove();
    clearInterval(to);
    jQuery("body").append(div);

    if ( defaults.zindex ) {
        jQuery("#ui_notifIt").css("z-index", defaults.zindex);
    }

    if (defaults.multiline) {
        jQuery("#ui_notifIt").css("padding", 15);
    } else {
        jQuery("#ui_notifIt").css("height", height);
        jQuery("#ui_notifIt p").css("line-height", height + "px");
    }

    jQuery("#ui_notifIt").css("width", defaults.width);

    jQuery("#ui_notifIt").css("opacity", defaults.opacity);

    switch (defaults.type) {
        case "error":
            jQuery("#ui_notifIt").addClass("error");
            break;
        case "success":
            jQuery("#ui_notifIt").addClass("success");
            break;
        case "info":
            jQuery("#ui_notifIt").addClass("info");
            break;
        case "warning":
            jQuery("#ui_notifIt").addClass("warning");
            break;
        default:
            jQuery("#ui_notifIt").addClass("default");
            break;
    }

    jQuery("#ui_notifIt").css("background-color", defaults.bgcolor);

    jQuery("#ui_notifIt").css("color", defaults.color);

    switch (defaults.position) {
        case "left":
            jQuery("#ui_notifIt").css("left", parseInt(0 - (defaults.width + 10)));
            jQuery("#ui_notifIt").css("left", parseInt(0 - (defaults.width * 2)));
            jQuery("#ui_notifIt").animate({left: parseInt(10 + defaults.offset)});
            break;
        case "right":
            jQuery("#ui_notifIt").css("right", parseInt(0 - (defaults.width + 10)));
            jQuery("#ui_notifIt").css("right", parseInt(0 - (defaults.width * 2)));
            jQuery("#ui_notifIt").animate({right: parseInt(10 + defaults.offset)});
            break;
        case "center":
            var mid = (window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth) / 2;
            jQuery("#ui_notifIt").css("top", parseInt(0 - (defaults.height + 10)));
            jQuery("#ui_notifIt").css("left", mid - parseInt(defaults.width / 2));
            jQuery("#ui_notifIt").animate({top: parseInt(10 + defaults.offset)});
            break;
        case "bottom":
            var mid = (window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth) / 2;
            jQuery("#ui_notifIt").css("top", 'auto');
            jQuery("#ui_notifIt").css("bottom", parseInt(0 - (defaults.height + 10)));
            jQuery("#ui_notifIt").css("left", mid - parseInt(defaults.width / 2));
            jQuery("#ui_notifIt").animate({bottom: parseInt(10 + defaults.offset)});
            break;
        default:
            var mid = (window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth) / 2;
            jQuery("#ui_notifIt").css("right", parseInt(0 - (defaults.width + 10)));
            jQuery("#ui_notifIt").css("left", mid - parseInt(defaults.width / 2));
            jQuery("#ui_notifIt").animate({right: parseInt(10 + defaults.offset)});
            break;
    }

    jQuery("#ui_notifIt").click(function() {
        notifit_dismiss(to, defaults);
    });

    if (defaults.autohide) {
            if (!isNaN(defaults.timeout)) { // Take the timeout if is a number
                to = setTimeout(function() {
                    jQuery("#ui_notifIt").click();
                }, defaults.timeout);
            }

    }
}

function notifit_dismiss(to, config) {
    clearInterval(to);
    if (!config.fade) {
        switch(config.position){
            case "center":
                jQuery("#ui_notifIt").animate({
                    top: parseInt(config.height - (config.height / 2))
                }, 100, function() {
                    jQuery("#ui_notifIt").animate({
                        top: parseInt(0 - (config.height * 2))
                    }, 100, function() {
                        jQuery("#ui_notifIt").remove();
                    });
                });
            break;
            case "bottom":
                jQuery("#ui_notifIt").animate({
                    bottom: parseInt(config.height - (config.height / 2))
                }, 100, function() {
                    jQuery("#ui_notifIt").animate({
                        bottom: parseInt(0 - (config.height * 2))
                    }, 100, function() {
                        jQuery("#ui_notifIt").remove();
                    });
                });
            break;
            case "right":
                jQuery("#ui_notifIt").animate({
                    right: parseFloat(config.width - (config.width * 0.9))
                }, 100, function() {
                    jQuery("#ui_notifIt").animate({
                        right: parseInt(0 - (config.width * 2))
                    }, 100, function() {
                        jQuery("#ui_notifIt").remove();
                    });
                });
            break;
            case "left":
                jQuery("#ui_notifIt").animate({
                    left: parseFloat(config.width - (config.width * 0.9))
                }, 100, function() {
                    jQuery("#ui_notifIt").animate({
                        left: parseInt(0 - (config.width * 2))
                    }, 100, function() {
                        jQuery("#ui_notifIt").remove();
                    });
                });
            break;
        }
    } else {
        jQuery("#ui_notifIt").fadeOut("slow", function() {
            jQuery("#ui_notifIt").remove();
        });
    }
}
<commit_msg>Added callback support<commit_after>/*
 * notifIt! by @naoxink
 */
function notif(config) {
    var to = null;
    var defaults = {
        type: "info",
        width: 400,
        height: 60,
        position: "right",
        autohide: 1,
        msg: "This is my default message",
        opacity: 1,
        multiline: 0,
        fade: 0,
        bgcolor: "",
        color: "",
        timeout: 5000,
        zindex: null,
        offset: 0,
		callback: null
    };
    jQuery.extend(defaults, config);

	if(typeof defaults.callback !== 'function'){
		defaults.callback = null;
	}

    position = defaults.position;

    if (defaults.width > 0) {
        defaults.width = defaults.width;
    } else if (defaults.width === "all") {
        defaults.width = screen.width - 60;
    }

    if (defaults.height < 100 && defaults.height > 0) {
        height = defaults.height;
    }

    var div = "

" + defaults.msg + "

";
    jQuery("#ui_notifIt").remove();
    clearInterval(to);
    jQuery("body").append(div);

    if ( defaults.zindex ) {
        jQuery("#ui_notifIt").css("z-index", defaults.zindex);
    }

    if (defaults.multiline) {
        jQuery("#ui_notifIt").css("padding", 15);
    } else {
        jQuery("#ui_notifIt").css("height", height);
        jQuery("#ui_notifIt p").css("line-height", height + "px");
    }

    jQuery("#ui_notifIt").css("width", defaults.width);

    jQuery("#ui_notifIt").css("opacity", defaults.opacity);

    switch (defaults.type) {
        case "error":
            jQuery("#ui_notifIt").addClass("error");
            break;
        case "success":
            jQuery("#ui_notifIt").addClass("success");
            break;
        case "info":
            jQuery("#ui_notifIt").addClass("info");
            break;
        case "warning":
            jQuery("#ui_notifIt").addClass("warning");
            break;
        default:
            jQuery("#ui_notifIt").addClass("default");
            break;
    }

    jQuery("#ui_notifIt").css("background-color", defaults.bgcolor);

    jQuery("#ui_notifIt").css("color", defaults.color);

    switch (defaults.position) {
        case "left":
            jQuery("#ui_notifIt").css("left", parseInt(0 - (defaults.width + 10)));
            jQuery("#ui_notifIt").css("left", parseInt(0 - (defaults.width * 2)));
            jQuery("#ui_notifIt").animate({left: parseInt(10 + defaults.offset)});
            break;
        case "right":
            jQuery("#ui_notifIt").css("right", parseInt(0 - (defaults.width + 10)));
            jQuery("#ui_notifIt").css("right", parseInt(0 - (defaults.width * 2)));
            jQuery("#ui_notifIt").animate({right: parseInt(10 + defaults.offset)});
            break;
        case "center":
            var mid = (window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth) / 2;
            jQuery("#ui_notifIt").css("top", parseInt(0 - (defaults.height + 10)));
            jQuery("#ui_notifIt").css("left", mid - parseInt(defaults.width / 2));
            jQuery("#ui_notifIt").animate({top: parseInt(10 + defaults.offset)});
            break;
        case "bottom":
            var mid = (window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth) / 2;
            jQuery("#ui_notifIt").css("top", 'auto');
            jQuery("#ui_notifIt").css("bottom", parseInt(0 - (defaults.height + 10)));
            jQuery("#ui_notifIt").css("left", mid - parseInt(defaults.width / 2));
            jQuery("#ui_notifIt").animate({bottom: parseInt(10 + defaults.offset)});
            break;
        default:
            var mid = (window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth) / 2;
            jQuery("#ui_notifIt").css("right", parseInt(0 - (defaults.width + 10)));
            jQuery("#ui_notifIt").css("left", mid - parseInt(defaults.width / 2));
            jQuery("#ui_notifIt").animate({right: parseInt(10 + defaults.offset)});
            break;
    }

    jQuery("#ui_notifIt").click(function() {
        notifit_dismiss(to, defaults);
    });

    if (defaults.autohide) {
            if (!isNaN(defaults.timeout)) { // Take the timeout if is a number
                to = setTimeout(function() {
                    jQuery("#ui_notifIt").click();
                }, defaults.timeout);
            }

    }
}

function notifit_dismiss(to, config) {
    clearInterval(to);
    if (!config.fade) {
		var animation1 = {},
			animation2 = {};
        switch(config.position){
            case "center":
				animation1 = {
                    top: parseInt(config.height - (config.height / 2))
                };
				animation2 = {
                    top: parseInt(0 - (config.height * 2))
                };
            break;
            case "bottom":
				animation1 = {
                    bottom: parseInt(config.height - (config.height / 2))
                };
				animation2 = {
                    bottom: parseInt(0 - (config.height * 2))
                };
            break;
            case "right":
				animation1 = {
                    right: parseFloat(config.width - (config.width * 0.9))
                };
				animation2 = {
                    right: parseInt(0 - (config.width * 2))
                };
            break;
            case "left":
				animation1 = {
                    left: parseFloat(config.width - (config.width * 0.9))
                };
				animation2 = {
                    left: parseInt(0 - (config.width * 2))
                };
            break;
        }
		// Execute animations
        jQuery("#ui_notifIt").animate(animation1, 100, function() {
            jQuery("#ui_notifIt").animate(animation2, 100, function() {
                jQuery("#ui_notifIt").remove();
				if(config.callback){
					config.callback();
				}
            });
        });
    } else {
        jQuery("#ui_notifIt").fadeOut("slow", function() {
            jQuery("#ui_notifIt").remove();
			if(config.callback){
				config.callback();
			}
        });
    }
}
<|endoftext|>