<commit_before>!(function(e, t) {
	if ("object" == typeof exports && "object" == typeof module)
		module.exports = t();
	else if ("function" == typeof define && define.amd) define([], t);
	else {
		var o = t();
		for (var r in o) ("object" == typeof exports ? exports : e)[r] = o[r];
	}
})(window, function() {
	return (function(e) {
		var t = {};
		function o(r) {
			if (t[r]) return t[r].exports;
			var a = (t[r] = { i: r, l: !1, exports: {} });
			return e[r].call(a.exports, a, a.exports, o), (a.l = !0), a.exports;
		}
		return (
			(o.m = e),
			(o.c = t),
			(o.d = function(e, t, r) {
				o.o(e, t) || Object.defineProperty(e, t, { enumerable: !0, get: r });
			}),
			(o.r = function(e) {
				"undefined" != typeof Symbol &&
					Symbol.toStringTag &&
					Object.defineProperty(e, Symbol.toStringTag, { value: "Module" }),
					Object.defineProperty(e, "__esModule", { value: !0 });
			}),
			(o.t = function(e, t) {
				if ((1 & t && (e = o(e)), 8 & t)) return e;
				if (4 & t && "object" == typeof e && e && e.__esModule) return e;
				var r = Object.create(null);
				if (
					(o.r(r),
					Object.defineProperty(r, "default", { enumerable: !0, value: e }),
					2 & t && "string" != typeof e)
				)
					for (var a in e)
						o.d(
							r,
							a,
							function(t) {
								return e[t];
							}.bind(null, a)
						);
				return r;
			}),
			(o.n = function(e) {
				var t =
					e && e.__esModule
						? function() {
								return e.default;
						  }
						: function() {
								return e;
						  };
				return o.d(t, "a", t), t;
			}),
			(o.o = function(e, t) {
				return Object.prototype.hasOwnProperty.call(e, t);
			}),
			(o.p = ""),
			o((o.s = 0))
		);
	})([
		function(e, t, o) {
			e.exports = o(1);
		},
		function(e, t, o) {
			"use strict";
			Object.defineProperty(t, "__esModule", { value: !0 }),
				(t.default = void 0);
			var r = {
				h: {
					locale: "es-ES",
					common: {
						cancel: "Cancelar",
						confirm: "Confirmar",
						clear: "Limpiar",
						nullOptionText: "Seleccione",
						empty: "Vacío",
						any: "Alguno"
					},
					confirm: { title: "Confirmar" },
					checkbox: {
						limitSize: "Puede seleccionar hasta {limitSize} elementos."
					},
					select: {
						nullOptionText: "Seleccione",
						placeholder: "Seleccione",
						emptyContent: "No se han encontrado resultados",
						searchPlaceHolder: "buscar",
						limitSize: "Puede seleccionar hasta {limitSize} elementos."
					},
					category: { placeholder: "Seleccione" },
					cascader: { placeholder: "Seleccione" },
					categoryModal: {
						limitWords: "Puede seleccionar hasta {size} elementos.",
						emptyContent: "No se han encontrado resultados",
						total: "total"
					},
					categoryPicker: {
						nullOptionText: "Seleccione",
						placeholder: "Seleccione",
						total: "total",
						limitSize: "Puede seleccionar hasta {0} elementos."
					},
					autoComplate: {
						placeholder: "Buscar",
						emptyContent: "No se han encontrado resultados"
					},
					validation: {
						base: {
							required: " no puede estar vacío",
							maxLen: " la longitud del texto no puede exceder {value} carácteres",
							minLen: " la longitud del texto no puede ser menor que {value} carácteres",
							max: " no puede ser mayor que {value}",
							min: " no puede ser menor que {value}"
						},
						type: {
							int: " no es el formato correcto de número entero",
							number: " no es el formato numérico correcto",
							email: " no es el formato correcto de correo electrónico",
							url: " no es el formato correcto de URL",
							tel: " no es el formato correcto de número de teléfono",
							mobile: " no es el formato correcto de número de teléfono móvil",
							globalmobile: " no es el formato correcto de número de teléfono móvil internacional"
						}
					},
					date: {
						today: "Hoy",
						yesterday: "Ayer",
						year: "Año",
						month: "Mes",
						week: "Semana",
						quarter: "trimestre",
						day: "Día",
						header: { year: "", month: "", day: "" },
						show: {
							week: "{year} {weeknum}th semana {daystart} - {dayend}",
							weekInput: "{year} {week}th semana",
							quarter: "{year} {quarter}th trimestre"
						},
						months: {
							january: "Enero",
							february: "Febrero",
							march: "Marzo",
							april: "Abril",
							may: "Mayo",
							june: "Junio",
							july: "Julio",
							august: "Agosto",
							september: "Septiembre",
							october: "Octubre",
							november: "Noviembre",
							december: "Diciembre"
						},
						weeks: {
							monday: "Lunes",
							tuesday: "Martes",
							wednesday: "Miércoles",
							thursday: "Jueves",
							friday: "Viernes",
							saturday: "Sábado",
							sunday: "Domingo"
						}
					},
					datepicker: {
						placeholder: "Seleccione la fecha",
						startTime: "Inicio",
						endTime: "Fin",
						customize: "Personalizar",
						start: "Inicio",
						end: "Fin"
					},
					wordlimit: { warn: "Estás limitado a {0} palabras" },
					wordcount: { warn: "Te has excedido {0} palabras" },
					treepicker: {
						selectDesc: "Ha seleccionado {0} elementos",
						placeholder: "Seleccione"
					},
					search: { placeholder: "Buscando...", searchText: "Buscar" },
					taginput: { limitWords: "Has superado el límite" },
					table: { empty: "No se han encontrado resultados" },
					uploader: { upload: "Subir", reUpload: "Subir otra vez" },
					pagination: {
						incorrectFormat:
							"El formato del valor que ingresaste es incorrecto.",
						overSize: "El valor que ingresaste excede el rango",
						totalBefore: "Total",
						totalAfter: "Elementos",
						sizeOfPage: "{size} elementos/página"
					}
				}
			};
			t.default = r;
		}
	]).default;
});
<commit_msg>fix(Lang): fix Spanish language<commit_after>export default {
  h: {
    locale: 'es-ES',
    common: {
      cancel: 'Cancelar',
      confirm: 'Confirmar',
      clear: 'Limpiar',
      nullOptionText: 'Seleccione',
      empty: 'Vacío',
      any: 'Alguno'
    },
    confirm: { title: 'Confirmar' },
    checkbox: {
      limitSize: 'Puede seleccionar hasta {limitSize} elementos.'
    },
    select: {
      nullOptionText: 'Seleccione',
      placeholder: 'Seleccione',
      emptyContent: 'No se han encontrado resultados',
      searchPlaceHolder: 'buscar',
      limitSize: 'Puede seleccionar hasta {limitSize} elementos.'
    },
    category: { placeholder: 'Seleccione' },
    cascader: { placeholder: 'Seleccione' },
    categoryModal: {
      limitWords: 'Puede seleccionar hasta {size} elementos.',
      emptyContent: 'No se han encontrado resultados',
      total: 'total'
    },
    categoryPicker: {
      nullOptionText: 'Seleccione',
      placeholder: 'Seleccione',
      total: 'total',
      limitSize: 'Puede seleccionar hasta {0} elementos.'
    },
    autoComplate: {
      placeholder: 'Buscar',
      emptyContent: 'No se han encontrado resultados'
    },
    validation: {
      base: {
        required: ' no puede estar vacío',
        maxLen: ' la longitud del texto no puede exceder {value} carácteres',
        minLen: ' la longitud del texto no puede ser menor que {value} carácteres',
        max: ' no puede ser mayor que {value}',
        min: ' no puede ser menor que {value}'
      },
      type: {
        int: ' no es el formato correcto de número entero',
        number: ' no es el formato numérico correcto',
        email: ' no es el formato correcto de correo electrónico',
        url: ' no es el formato correcto de URL',
        tel: ' no es el formato correcto de número de teléfono',
        mobile: ' no es el formato correcto de número de teléfono móvil',
        globalmobile: ' no es el formato correcto de número de teléfono móvil internacional'
      }
    },
    date: {
      today: 'Hoy',
      yesterday: 'Ayer',
      year: 'Año',
      month: 'Mes',
      week: 'Semana',
      quarter: 'trimestre',
      day: 'Día',
      header: { year: '', month: '', day: '' },
      show: {
        week: '{year} {weeknum}th semana {daystart} - {dayend}',
        weekInput: '{year} {week}th semana',
        quarter: '{year} {quarter}th trimestre'
      },
      months: {
        january: 'Enero',
        february: 'Febrero',
        march: 'Marzo',
        april: 'Abril',
        may: 'Mayo',
        june: 'Junio',
        july: 'Julio',
        august: 'Agosto',
        september: 'Septiembre',
        october: 'Octubre',
        november: 'Noviembre',
        december: 'Diciembre'
      },
      weeks: {
        monday: 'Lunes',
        tuesday: 'Martes',
        wednesday: 'Miércoles',
        thursday: 'Jueves',
        friday: 'Viernes',
        saturday: 'Sábado',
        sunday: 'Domingo'
      }
    },
    datepicker: {
      placeholder: 'Seleccione la fecha',
      startTime: 'Inicio',
      endTime: 'Fin',
      customize: 'Personalizar',
      start: 'Inicio',
      end: 'Fin'
    },
    wordlimit: { warn: 'Estás limitado a {0} palabras' },
    wordcount: { warn: 'Te has excedido {0} palabras' },
    treepicker: {
      selectDesc: 'Ha seleccionado {0} elementos',
      placeholder: 'Seleccione'
    },
    search: { placeholder: 'Buscando...', searchText: 'Buscar' },
    taginput: { limitWords: 'Has superado el límite' },
    table: { empty: 'No se han encontrado resultados' },
    uploader: { upload: 'Subir', reUpload: 'Subir otra vez' },
    pagination: {
      incorrectFormat: 'El formato del valor que ingresaste es incorrecto.',
      overSize: 'El valor que ingresaste excede el rango',
      totalBefore: 'Total',
      totalAfter: 'Elementos',
      sizeOfPage: '{size} elementos/página'
    }
  }
};
<|endoftext|>


<commit_before>'use strict';

process.env.NODE_ENV = 'production'; // Drastically increase performances

const path     = require('path');
const os       = require('os');
const electron = require('electron');

const IpcManager         = require('./ipc');             // Manages IPC evens
const TrayManager        = require('./tray');            // Manages Tray
const ConfigManager      = require('./config');          // Handles config
const PowerMonitor       = require('./power-monitor');   // Handle power events
const IntegrationManager = require('./integration');     // Applies various integrations

const app           = electron.app;              // Module to control application life.
const nativeImage   = electron.nativeImage;
const BrowserWindow = electron.BrowserWindow;    // Module to create native browser window.

const appRoot = path.resolve(__dirname, '../..'); // app/ directory
const srcPath = path.join(appRoot, 'src'); // app/src/ directory

// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the javascript object is GCed.
let mainWindow = null;

// Make the app a single-instance app (to avoid Database concurrency)
const shouldQuit = app.makeSingleInstance(() => {
    // Someone tried to run a second instance, we should focus our window.
    if(mainWindow) {
        if(mainWindow.isMinimized()) mainWindow.restore();
        mainWindow.show();
        mainWindow.focus();
    }
});

if (shouldQuit) {
    app.quit();
}

// Quit when all windows are closed
app.on('window-all-closed', () => {
    if (process.platform !== 'darwin')
        app.quit();
});

// This method will be called when Electron has done everything
// initialization and ready for creating browser windows.
app.on('ready', () => {
    const configManager = new ConfigManager(app);
    const { useNativeFrame } = configManager.getConfig();
    let { bounds } = configManager.getConfig();

    bounds = checkBounds(bounds);

    const logosPath = path.join(appRoot, 'src', 'images', 'logos');
    const museeksIcons = {
        '256': nativeImage.createFromPath(path.join(logosPath, 'museeks.png')),
        '128': nativeImage.createFromPath(path.join(logosPath, 'museeks-128.png')),
        '64': nativeImage.createFromPath(path.join(logosPath, 'museeks-64.png')),
        '48': nativeImage.createFromPath(path.join(logosPath, 'museeks-48.png')),
        '32': nativeImage.createFromPath(path.join(logosPath, 'museeks-32.png')),
        'ico': nativeImage.createFromPath(path.join(logosPath, 'museeks.ico')),
        'tray': nativeImage.createFromPath(path.join(logosPath, 'museeks-tray.png')).resize({ width: 24, height: 24 }),
        'tray-ico': nativeImage.createFromPath(path.join(logosPath, 'museeks-tray.ico')).resize({ width: 24, height: 24 }),
    };

    // Browser Window options
    const mainWindowOption = {
        title     : 'Museeks',
        icon      :  os.platform() === 'win32' ? museeksIcons['ico'] : museeksIcons['256'],
        x         :  bounds.x,
        y         :  bounds.y,
        width     :  bounds.width,
        height    :  bounds.height,
        minWidth  :  900,
        minHeight :  550,
        frame     :  useNativeFrame,
        show      :  false,
    };

    // Create the browser window
    mainWindow = new BrowserWindow(mainWindowOption);

    // ... and load our html page
    mainWindow.loadURL(`file://${srcPath}/app.html#/library`);
    mainWindow.openDevTools();
    mainWindow.on('closed', () => {
        // Dereference the window object
        mainWindow = null;
    });

    mainWindow.on('ready-to-show', () => {
        mainWindow.show();
    });

    // IPC events
    const ipcManager = new IpcManager(mainWindow);
    ipcManager.bindEvents();

    // Power monitor
    const powerMonitor = new PowerMonitor(mainWindow);
    powerMonitor.enable();

    // Tray manager
    const trayIcon = os.platform() === 'win32.' ? museeksIcons['tray-ico'] : museeksIcons['tray'];
    const trayManager = new TrayManager(mainWindow, trayIcon);
    trayManager.bindEvents();
    trayManager.show();

    // integrations
    const integrations = new IntegrationManager(mainWindow);
    integrations.enable();
});

/*
|--------------------------------------------------------------------------
| Utils
|--------------------------------------------------------------------------
*/

function checkBounds(bounds) {
    // check if the browser window is offscreen
    const display = electron.screen.getDisplayNearestPoint(bounds).workArea;

    const onScreen = bounds.x >= display.x
        && bounds.x + bounds.width <= display.x + display.width
        && bounds.y >= display.y
        && bounds.y + bounds.height <= display.y + display.height;

    if(!onScreen) {
        delete bounds.x;
        delete bounds.y;
        bounds.width = 900;
        bounds.height = 550;
    }

    return bounds;
}
<commit_msg>Remove openDevTools on startup<commit_after>'use strict';

process.env.NODE_ENV = 'production'; // Drastically increase performances

const path     = require('path');
const os       = require('os');
const electron = require('electron');

const IpcManager         = require('./ipc');             // Manages IPC evens
const TrayManager        = require('./tray');            // Manages Tray
const ConfigManager      = require('./config');          // Handles config
const PowerMonitor       = require('./power-monitor');   // Handle power events
const IntegrationManager = require('./integration');     // Applies various integrations

const app           = electron.app;              // Module to control application life.
const nativeImage   = electron.nativeImage;
const BrowserWindow = electron.BrowserWindow;    // Module to create native browser window.

const appRoot = path.resolve(__dirname, '../..'); // app/ directory
const srcPath = path.join(appRoot, 'src'); // app/src/ directory

// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the javascript object is GCed.
let mainWindow = null;

// Make the app a single-instance app (to avoid Database concurrency)
const shouldQuit = app.makeSingleInstance(() => {
    // Someone tried to run a second instance, we should focus our window.
    if(mainWindow) {
        if(mainWindow.isMinimized()) mainWindow.restore();
        mainWindow.show();
        mainWindow.focus();
    }
});

if (shouldQuit) {
    app.quit();
}

// Quit when all windows are closed
app.on('window-all-closed', () => {
    if (process.platform !== 'darwin')
        app.quit();
});

// This method will be called when Electron has done everything
// initialization and ready for creating browser windows.
app.on('ready', () => {
    const configManager = new ConfigManager(app);
    const { useNativeFrame } = configManager.getConfig();
    let { bounds } = configManager.getConfig();

    bounds = checkBounds(bounds);

    const logosPath = path.join(appRoot, 'src', 'images', 'logos');
    const museeksIcons = {
        '256': nativeImage.createFromPath(path.join(logosPath, 'museeks.png')),
        '128': nativeImage.createFromPath(path.join(logosPath, 'museeks-128.png')),
        '64': nativeImage.createFromPath(path.join(logosPath, 'museeks-64.png')),
        '48': nativeImage.createFromPath(path.join(logosPath, 'museeks-48.png')),
        '32': nativeImage.createFromPath(path.join(logosPath, 'museeks-32.png')),
        'ico': nativeImage.createFromPath(path.join(logosPath, 'museeks.ico')),
        'tray': nativeImage.createFromPath(path.join(logosPath, 'museeks-tray.png')).resize({ width: 24, height: 24 }),
        'tray-ico': nativeImage.createFromPath(path.join(logosPath, 'museeks-tray.ico')).resize({ width: 24, height: 24 }),
    };

    // Browser Window options
    const mainWindowOption = {
        title     : 'Museeks',
        icon      :  os.platform() === 'win32' ? museeksIcons['ico'] : museeksIcons['256'],
        x         :  bounds.x,
        y         :  bounds.y,
        width     :  bounds.width,
        height    :  bounds.height,
        minWidth  :  900,
        minHeight :  550,
        frame     :  useNativeFrame,
        show      :  false,
    };

    // Create the browser window
    mainWindow = new BrowserWindow(mainWindowOption);

    // ... and load our html page
    mainWindow.loadURL(`file://${srcPath}/app.html#/library`);

    mainWindow.on('closed', () => {
        // Dereference the window object
        mainWindow = null;
    });

    mainWindow.on('ready-to-show', () => {
        mainWindow.show();
    });

    // IPC events
    const ipcManager = new IpcManager(mainWindow);
    ipcManager.bindEvents();

    // Power monitor
    const powerMonitor = new PowerMonitor(mainWindow);
    powerMonitor.enable();

    // Tray manager
    const trayIcon = os.platform() === 'win32.' ? museeksIcons['tray-ico'] : museeksIcons['tray'];
    const trayManager = new TrayManager(mainWindow, trayIcon);
    trayManager.bindEvents();
    trayManager.show();

    // integrations
    const integrations = new IntegrationManager(mainWindow);
    integrations.enable();
});

/*
|--------------------------------------------------------------------------
| Utils
|--------------------------------------------------------------------------
*/

function checkBounds(bounds) {
    // check if the browser window is offscreen
    const display = electron.screen.getDisplayNearestPoint(bounds).workArea;

    const onScreen = bounds.x >= display.x
        && bounds.x + bounds.width <= display.x + display.width
        && bounds.y >= display.y
        && bounds.y + bounds.height <= display.y + display.height;

    if(!onScreen) {
        delete bounds.x;
        delete bounds.y;
        bounds.width = 900;
        bounds.height = 550;
    }

    return bounds;
}
<|endoftext|>


<commit_before>// Copyright (c) 2015-2016 Yuya Ochiai
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
'use strict';

import EventEmitter from 'events';

import simpleSpellChecker from 'simple-spellchecker';

/// Following approach for contractions is derived from electron-spellchecker.

// NB: This is to work around electron/electron#1005, where contractions
// are incorrectly marked as spelling errors. This lets people get away with
// incorrectly spelled contracted words, but it's the best we can do for now.
const contractions = [
  "ain't", "aren't", "can't", "could've", "couldn't", "couldn't've", "didn't", "doesn't", "don't", "hadn't",
  "hadn't've", "hasn't", "haven't", "he'd", "he'd've", "he'll", "he's", "how'd", "how'll", "how's", "I'd",
  "I'd've", "I'll", "I'm", "I've", "isn't", "it'd", "it'd've", "it'll", "it's", "let's", "ma'am", "mightn't",
  "mightn't've", "might've", "mustn't", "must've", "needn't", "not've", "o'clock", "shan't", "she'd", "she'd've",
  "she'll", "she's", "should've", "shouldn't", "shouldn't've", "that'll", "that's", "there'd", "there'd've",
  "there're", "there's", "they'd", "they'd've", "they'll", "they're", "they've", "wasn't", "we'd", "we'd've",
  "we'll", "we're", "we've", "weren't", "what'll", "what're", "what's", "what've", "when's", "where'd",
  "where's", "where've", "who'd", "who'll", "who're", "who's", "who've", "why'll", "why're", "why's", "won't",
  "would've", "wouldn't", "wouldn't've", "y'all", "y'all'd've", "you'd", "you'd've", "you'll", "you're", "you've",
];

const contractionMap = contractions.reduce((acc, word) => {
  acc[word.replace(/'.*/, '')] = true;
  return acc;
}, {});

/// End: derived from electron-spellchecker.

export default class SpellChecker extends EventEmitter {
  constructor(locale, dictDir, callback) {
    super();
    this.dict = null;
    this.locale = locale;
    simpleSpellChecker.getDictionary(locale, dictDir, (err, dict) => {
      if (err) {
        this.emit('error', err);
        if (callback) {
          callback(err);
        }
      } else {
        this.dict = dict;
        this.emit('ready');
        if (callback) {
          callback(null, this);
        }
      }
    });
  }

  isReady() {
    return this.dict !== null;
  }

  spellCheck(word) {
    if (word.toLowerCase() === 'mattermost') {
      return true;
    }
    if (isFinite(word)) { // Numerals are not included in the dictionary
      return true;
    }
    if (this.locale.match(/^en-?/) && contractionMap[word]) {
      return true;
    }
    return this.dict.spellCheck(word);
  }

  getSuggestions(word, maxSuggestions) {
    return this.dict.getSuggestions(word, maxSuggestions);
  }
}

SpellChecker.getSpellCheckerLocale = (electronLocale) => {
  if (electronLocale.match(/^en-?/)) {
    return 'en-US';
  }
  if (electronLocale.match(/^fr-?/)) {
    return 'fr-FR';
  }
  if (electronLocale.match(/^de-?/)) {
    return 'de-DE';
  }
  if (electronLocale.match(/^es-?/)) {
    return 'es-ES';
  }
  if (electronLocale.match(/^nl-?/)) {
    return 'nl-NL';
  }
  if (electronLocale.match(/^pt-?/)) {
    return 'pt-BR';
  }
  return 'en-US';
};
<commit_msg>Preserve case of first letter in spell check, fixes #562<commit_after>// Copyright (c) 2015-2016 Yuya Ochiai
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
'use strict';

import EventEmitter from 'events';

import simpleSpellChecker from 'simple-spellchecker';

/// Following approach for contractions is derived from electron-spellchecker.

// NB: This is to work around electron/electron#1005, where contractions
// are incorrectly marked as spelling errors. This lets people get away with
// incorrectly spelled contracted words, but it's the best we can do for now.
const contractions = [
  "ain't", "aren't", "can't", "could've", "couldn't", "couldn't've", "didn't", "doesn't", "don't", "hadn't",
  "hadn't've", "hasn't", "haven't", "he'd", "he'd've", "he'll", "he's", "how'd", "how'll", "how's", "I'd",
  "I'd've", "I'll", "I'm", "I've", "isn't", "it'd", "it'd've", "it'll", "it's", "let's", "ma'am", "mightn't",
  "mightn't've", "might've", "mustn't", "must've", "needn't", "not've", "o'clock", "shan't", "she'd", "she'd've",
  "she'll", "she's", "should've", "shouldn't", "shouldn't've", "that'll", "that's", "there'd", "there'd've",
  "there're", "there's", "they'd", "they'd've", "they'll", "they're", "they've", "wasn't", "we'd", "we'd've",
  "we'll", "we're", "we've", "weren't", "what'll", "what're", "what's", "what've", "when's", "where'd",
  "where's", "where've", "who'd", "who'll", "who're", "who's", "who've", "why'll", "why're", "why's", "won't",
  "would've", "wouldn't", "wouldn't've", "y'all", "y'all'd've", "you'd", "you'd've", "you'll", "you're", "you've",
];

const contractionMap = contractions.reduce((acc, word) => {
  acc[word.replace(/'.*/, '')] = true;
  return acc;
}, {});

/// End: derived from electron-spellchecker.

export default class SpellChecker extends EventEmitter {
  constructor(locale, dictDir, callback) {
    super();
    this.dict = null;
    this.locale = locale;
    simpleSpellChecker.getDictionary(locale, dictDir, (err, dict) => {
      if (err) {
        this.emit('error', err);
        if (callback) {
          callback(err);
        }
      } else {
        this.dict = dict;
        this.emit('ready');
        if (callback) {
          callback(null, this);
        }
      }
    });
  }

  isReady() {
    return this.dict !== null;
  }

  spellCheck(word) {
    if (word.toLowerCase() === 'mattermost') {
      return true;
    }
    if (isFinite(word)) { // Numerals are not included in the dictionary
      return true;
    }
    if (this.locale.match(/^en-?/) && contractionMap[word]) {
      return true;
    }
    return this.dict.spellCheck(word);
  }

  getSuggestions(word, maxSuggestions) {
    const suggestions = this.dict.getSuggestions(word, maxSuggestions);

    const firstCharWord = word.charAt(0);
    let i;
    for (i = 0; i < suggestions.length; i++) {
      if (suggestions[i].charAt(0).toUpperCase() === firstCharWord.toUpperCase()) {
        suggestions[i] = firstCharWord + suggestions[i].slice(1);
      }
    }

    const uniqueSuggestions = suggestions.reduce((a, b) => {
      if (a.indexOf(b) < 0) {
        a.push(b);
      }
      return a;
    }, []);

    return uniqueSuggestions;
  }
}

SpellChecker.getSpellCheckerLocale = (electronLocale) => {
  if (electronLocale.match(/^en-?/)) {
    return 'en-US';
  }
  if (electronLocale.match(/^fr-?/)) {
    return 'fr-FR';
  }
  if (electronLocale.match(/^de-?/)) {
    return 'de-DE';
  }
  if (electronLocale.match(/^es-?/)) {
    return 'es-ES';
  }
  if (electronLocale.match(/^nl-?/)) {
    return 'nl-NL';
  }
  if (electronLocale.match(/^pt-?/)) {
    return 'pt-BR';
  }
  return 'en-US';
};
<|endoftext|>


<commit_before>angular
  .module('lift-ng', [])
  .service('promiseInjector', ['$q', function($q){
    return {};
  }])
  .service('liftProxy', ['$http', '$q', function ($http, $q) {
    var svc = {
      callbacks: {},
      request: function (requestData) {
        var random = function() {
          var text = "";
          var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

          for( var i=0; i < 20; i++ )
            text += possible.charAt(Math.floor(Math.random() * possible.length));

          return text;
        };

        var q = $q.defer();
        var id = random();
        var req = requestData.name+'='+encodeURIComponent(JSON.stringify({id:id, data:requestData.data}));
        var cleanup = function() {delete svc.callbacks[id];};

        var responseToQ = function(data) {
          if (data.success) {
            if (data.data) {
              q.resolve(data.data);
            }
            else {
              q.resolve();
            }
          } else {
            q.reject(data.msg)
          }
          cleanup();
        };

        svc.callbacks[id] = responseToQ;

        var returnQ = function(response) {
          var data = response.data;
          if(!data.future) {
            responseToQ(data)
          }
          return q.promise;
        };

        return $http.post(net_liftmodules_ng.endpoint(), req, {
          headers : {
            'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
          }
        }).then(returnQ);
      },
      response: function(response) {
        // The callback won't exist in the case of multiple apps on one page.
        var cb = svc.callbacks[response.id];
        if(typeof cb !== "undefined" && cb !== null)
          cb(response);
      }
    };

    return svc;
  }
]);<commit_msg>Pulled the lift-ng proxy callbacks collection out to a separate service<commit_after>angular
  .module('lift-ng', [])
  .service('callbacks', function(){
    return {
      callbacks: []
    }
  })
  .service('promiseInjector', ['$q', function($q){
    return {};
  }])
  .service('liftProxy', ['$http', '$q', 'callbacks', function ($http, $q, callbacks) {
    var svc = {
      request: function (requestData) {
        var random = function() {
          var text = "";
          var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

          for( var i=0; i < 20; i++ )
            text += possible.charAt(Math.floor(Math.random() * possible.length));

          return text;
        };

        var q = $q.defer();
        var id = random();
        var req = requestData.name+'='+encodeURIComponent(JSON.stringify({id:id, data:requestData.data}));
        var cleanup = function() {delete callbacks.callbacks[id];};

        var responseToQ = function(data) {
          if (data.success) {
            if (data.data) {
              q.resolve(data.data);
            }
            else {
              q.resolve();
            }
          } else {
            q.reject(data.msg)
          }
          cleanup();
        };

        callbacks.callbacks[id] = responseToQ;

        var returnQ = function(response) {
          var data = response.data;
          if(!data.future) {
            responseToQ(data)
          }
          return q.promise;
        };

        return $http.post(net_liftmodules_ng.endpoint(), req, {
          headers : {
            'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
          }
        }).then(returnQ);
      },
      response: function(response) {
        // The callback won't exist in the case of multiple apps on one page.
        var cb = callbacks.callbacks[response.id];
        if(typeof cb !== "undefined" && cb !== null)
          cb(response);
      }
    };

    return svc;
  }
]);<|endoftext|>


<commit_before>import Map from './Map';
import CollisionIndex from '../core/CollisionIndex';

Map.include(/** @lends Map.prototype */ {
    /**
     * Get map scope collision index
     * @returns {CollisionIndex} collision index
     */
    getCollisionIndex() {
        if (!this._collisionIndex) {
            this.createCollisionIndex();
        }
        return this._collisionIndex || this.createCollisionIndex();
    },

    /**
     * Create a new collisionIndex
     * @returns {CollisionIndex} new collision index
     */
    createCollisionIndex() {
        this.clearCollisionIndex();
        this._collisionIndex = new CollisionIndex();
        return this._collisionIndex;
    },

    /**
     * Clear collision index
     * @returns {Map} this
     */
    clearCollisionIndex() {
        if (this._collisionIndex) {
            this._collisionIndex.clear();
        }
        return this;
    }
});
<commit_msg>reset collisionFrameTime in clearCollisionIndex<commit_after>import Map from './Map';
import CollisionIndex from '../core/CollisionIndex';

Map.include(/** @lends Map.prototype */ {
    /**
     * Get map scope collision index
     * @returns {CollisionIndex} collision index
     */
    getCollisionIndex() {
        if (!this._collisionIndex) {
            this.createCollisionIndex();
        }
        return this._collisionIndex || this.createCollisionIndex();
    },

    /**
     * Create a new collisionIndex
     * @returns {CollisionIndex} new collision index
     */
    createCollisionIndex() {
        this.clearCollisionIndex();
        this._collisionIndex = new CollisionIndex();
        return this._collisionIndex;
    },

    /**
     * Clear collision index
     * @returns {Map} this
     */
    clearCollisionIndex() {
        this.collisionFrameTime = 0;
        if (this._collisionIndex) {
            this._collisionIndex.clear();
        }
        return this;
    }
});
<|endoftext|>


<commit_before>var MarkdownContents,
    Contents = require('contents');

/**
 * @param {string} markdown
 */
MarkdownContents = function MarkdownContents (markdown) {
    var markdownContents;

    if (!(this instanceof MarkdownContents)) {
        return new MarkdownContents(markdown);
    }

    markdownContents = this;

    /**
     * Generate flat index of the headings.
     *
     * @return {Array}
     */
    markdownContents.articles = function () {
        var articles = [],
            headings;

        markdown.replace(/^(#+)(.*$)/mg, function (match, level, name) {
            level = level.length;
            name = name.trim();

            articles.push({
                level: level,
                id: name.toLowerCase().replace(/[^\w]+/g, '-'),
                name: name
            });
        });

        return articles;
    };

    /**
     * Generates hierarchical index of the headings from a flat index.
     *
     * @return {Array}
     */
    markdownContents.tree = function () {
        var articles,
            tree;

        articles = markdownContents.articles();
        tree = MarkdownContents.tree(articles);

        return tree;
    };

    markdownContents.markdown = function () {
        return MarkdownContents.treeToMarkdown(markdownContents.tree());
    };
};

/**
 * Generate markdown contents for an array of contents object definition.
 *
 * @param {Array} tree [{id: '', name: '', descendants: []}]
 * @return {String} markdown
 */
MarkdownContents.treeToMarkdown = function (tree, level) {
    var markdown = '',
        offset = '';

    level = level || 0;

    if (level) {
        offset = new Array(level * 4).join(' ') + ' ';
    }

    tree.forEach(function (article) {
        markdown += offset + '* [' + article.name + '](#' + article.id + ')\n';

        if (article.descendants) {
            markdown += MarkdownContents.treeToMarkdown(article.descendants, level + 1);
        }
    });

    return markdown;
};

/**
 * Makes hierarchical index of the articles from a flat index.
 *
 * @param {Array} articles Generated using Contents.articles.
 * @return {Array}
 */
MarkdownContents.tree = function (articles) {
    return Contents.tree(articles, []);
};

module.exports = MarkdownContents;<commit_msg>Default to no unique IDs.<commit_after>var MarkdownContents,
    Contents = require('contents');

/**
 * @param {string} markdown
 */
MarkdownContents = function MarkdownContents (markdown) {
    var markdownContents;

    if (!(this instanceof MarkdownContents)) {
        return new MarkdownContents(markdown);
    }

    markdownContents = this;

    /**
     * Generate flat index of the headings.
     *
     * @return {Array}
     */
    markdownContents.articles = function () {
        var articles = [],
            headings;

        markdown.replace(/^(#+)(.*$)/mg, function (match, level, name) {
            level = level.length;
            name = name.trim();

            articles.push({
                level: level,
                id: name.toLowerCase().replace(/[^\w]+/g, '-'),
                name: name
            });
        });

        return articles;
    };

    /**
     * Generates hierarchical index of the headings from a flat index.
     *
     * @return {Array}
     */
    markdownContents.tree = function () {
        var articles,
            tree;

        articles = markdownContents.articles();
        tree = MarkdownContents.tree(articles);

        return tree;
    };

    markdownContents.markdown = function () {
        return MarkdownContents.treeToMarkdown(markdownContents.tree());
    };
};

/**
 * Generate markdown contents for an array of contents object definition.
 *
 * @param {Array} tree [{id: '', name: '', descendants: []}]
 * @return {String} markdown
 */
MarkdownContents.treeToMarkdown = function (tree, level) {
    var markdown = '',
        offset = '';

    level = level || 0;

    if (level) {
        offset = new Array(level * 4).join(' ') + ' ';
    }

    tree.forEach(function (article) {
        markdown += offset + '* [' + article.name + '](#' + article.id + ')\n';

        if (article.descendants) {
            markdown += MarkdownContents.treeToMarkdown(article.descendants, level + 1);
        }
    });

    return markdown;
};

/**
 * Makes hierarchical index of the articles from a flat index.
 *
 * @param {Array} articles Generated using Contents.articles.
 * @return {Array}
 */
MarkdownContents.tree = function (articles) {
    return Contents.tree(articles, false);
};

module.exports = MarkdownContents;<|endoftext|>


<commit_before>var Acetate_all = L.tileLayer('http://a{s}.acetate.geoiq.com/tiles/acetate-hillshading/{z}/{x}/{y}.png', {
	attribution: '©2012 Esri & Stamen, Data from OSM and Natural Earth',
	subdomains: '0123',
	minZoom: 2,
	maxZoom: 18
})

var Hydda_Full = L.tileLayer('http://{s}.tile.openstreetmap.se/hydda/full/{z}/{x}/{y}.png', {
  minZoom: 0,
  maxZoom: 18,
  attribution: 'Tiles courtesy of OpenStreetMap Sweden — Map data © OpenStreetMap contributors, CC-BY-SA'
});

var Stamen_TonerLite = L.tileLayer('http://{s}.tile.stamen.com/toner-lite/{z}/{x}/{y}.png', {
  attribution: 'Map tiles by Stamen Design, CC BY 3.0 — Map data © OpenStreetMap contributors, CC-BY-SA',
  subdomains: 'abcd',
  minZoom: 0,
  maxZoom: 20
});
var Esri_WorldImagery = L.tileLayer('http://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', {
  attribution: 'Tiles © Esri — Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community'
});

 var crimeLayer = L.layerGroup();
 var crimeMarker = [];

 var planningLayer = L.layerGroup();
 var planningMarker = [];

 var propertyLayer = L.layerGroup();
 var propertyMarker = [];

 var floodLayer = L.layerGroup();
 var floodArea = [];

 var bounds = new L.LatLngBounds();
 var layersOnMap = [];

 var clusterLayer = new L.MarkerClusterGroup({
    maxClusterRadius: 1,
    spiderfyOnMaxZoom: true,
    showCoverageOnHover: false,
    zoomToBoundsOnClick: true,
    animateAddingMarkers: true
  });

planningIcon  = L.AwesomeMarkers.icon({icon: 'fa-file-text', markerColor: 'red', prefix: 'fa'})
crimeIcon     = L.AwesomeMarkers.icon({icon: 'fa-gavel', markerColor: 'blue', prefix: 'fa'})
propertyIcon  = L.AwesomeMarkers.icon({icon: 'fa-gbp', markerColor: 'green', prefix: 'fa'})
postcodeIcon  = L.AwesomeMarkers.icon({icon: 'fa-home', markerColor: 'orange', prefix: 'fa'})
clusterIcon   = L.AwesomeMarkers.icon({icon: 'fa-home', markerColor: 'purple', prefix: 'fa'})

$.each(floodData.ProximityFloodAlerts, function(i, feature){
    var floodAlertBounds = [[feature.Bounds.BottomRight.Latitude, feature.Bounds.BottomRight.Longitude], [feature.Bounds.TopLeft.Latitude, feature.Bounds.TopLeft.Longitude]];
    floodArea[i] =  L.rectangle(floodAlertBounds, {
                                  color: "#E0753C",
                                  fillColor: "#E0753C",
                                  fillOpacity: 0.2,
                                  weight: 3,
                                  dashArray:10
                                })
                      .bindPopup("Environment Agency Flood Alert"
                                +"
Date Issued: " + feature.FloodAlert.Raised.substring(0, 10)
                                +"
Location: " + feature.FloodAlert.AreaDescription
                                +"
Severity: " + feature.FloodAlert.Severity
                          )
                      .addTo(floodLayer);
    layersOnMap.push(floodLayer);

})

$.each(planningData, function(i, feature) {
    planningMarker[i] = L.marker([feature.location.latitude, feature.location.longitude], {icon: planningIcon})
                    .bindPopup('Date Submitted: '+feature.casedate.substring(0,10)
                              +'
Reference: '+feature.casereference
                              +'
Description: '+feature.casetext
                              +'
Location: '+feature.locationtext
                              +'
Status: '+feature.banesstatus
                            )
                    .addTo(planningLayer);
    bounds.extend([feature.location.latitude, feature.location.longitude]);
    layersOnMap.push(planningLayer);
    clusterLayer.addLayer(planningLayer);
});

$.each(crimeData, function(i, feature) {
  //console.log(crime.location.latitude)
    crimeMarker[i] = L.marker([feature.location.latitude, feature.location.longitude], {icon: crimeIcon})
                    .bindPopup('Date: '+feature.month.substring(0, 7)
                              +'
Crime Type: '+toTitleCase(feature.crime_category).split('-').join(' ')
                              +'
'+'Location: '+feature.street_name)
                    .addTo(crimeLayer);
    bounds.extend([feature.location.latitude, feature.location.longitude]);
    layersOnMap.push(crimeLayer);
    clusterLayer.addLayer(crimeLayer);
});

$.each(houseData, function(i, feature) {
    propertyMarker[i] = L.marker([feature.location.latitude, feature.location.longitude], {icon: propertyIcon})
                    .bindPopup('Date of sale: '+feature.date_of_transfer.substring(0, 10)
                                +'
Price: £'+numberWithCommas(feature.price)
                                +'
Type of property: ' + typeOfProperty(feature.property_type)
                                +'
Address: ' + (feature.primary_addressable_object_name ? toTitleCase(feature.primary_addressable_object_name) + ', ' : '')
                                                        + (feature.secondary_addressable_object_name ? toTitleCase(feature.secondary_addressable_object_name) + ', ' : '')
                                                        + (feature.locality ? toTitleCase(feature.locality) + ', ' : '')
                                                        + (feature.town_city ? toTitleCase(feature.town_city) + ', ' : '')
                                                        + (feature.district ? toTitleCase(feature.district) + ', ' : '')
                                                        + feature.postcode
                              )
                    .addTo(propertyLayer);
    bounds.extend([feature.location.latitude, feature.location.longitude]);
    layersOnMap.push(propertyLayer);
    clusterLayer.addLayer(propertyLayer);
});

var map = L.map('map',{
    attributionControl: false,
    maxZoom: 18,
    layers: Hydda_Full
  }).setView([51.477106,-2.690277], 10);
  map.addLayer(clusterLayer);
   var dummyCrimeLayer = L.layerGroup().addTo(map);
   var dummyPlanningLayer = L.layerGroup().addTo(map);
   var dummyPropertyLayer = L.layerGroup().addTo(map);
/*

    var map = L.map('map', {
        layers: layersOnMap
    });

    */

    var baseLayers = {
        //"Acetate": Acetate_all,
        "Road Map": Hydda_Full,
        //"Satmen Toner Lite": Stamen_TonerLite,
        "Satellite Imagery": Esri_WorldImagery

    };

    var overlays = {
        "Crimes": dummyCrimeLayer,
        "Planning Applications": dummyPlanningLayer,
        "Property Sales": dummyPropertyLayer,
        "Flood Alerts": floodLayer
    };
   var drawnItems = new L.FeatureGroup();
   var postcodeRadius = L.circle([searchedForPostcode[1],searchedForPostcode[0]], 500, {
                                color: 'red',
                                fillColor:'red',
                                fillOpacity: 0.1,
                                opacity: 1,
                               // dashArray: '20',
                                zIndexOffset: 9999
                              }).addTo(drawnItems);

    L.control.layers(baseLayers, overlays).addTo(map);
    var postcodeMarker = L.marker([searchedForPostcode[1],searchedForPostcode[0]], {icon: postcodeIcon, zIndexOffset:999}).bindPopup('Your location').addTo(map);
    bounds.extend([searchedForPostcode[1],searchedForPostcode[0]]);
    map.fitBounds(bounds);
   // map.addLayer(clusterLayer);

// toggle email/list checkboxes when map layer control is changed.
map.on("overlayadd", function(e) {
  if (e.layer === dummyCrimeLayer) {
    clusterLayer.addLayer(crimeLayer);
    //console.log('dummylayer crime added')
    $('#crimes_check').prop('checked', true);
  }
  if (e.layer === dummyPlanningLayer) {
    //console.log('dummylayer plan added')
    clusterLayer.addLayer(planningLayer);
    $('#planning-applications_check').prop('checked', true);
  }
  if (e.layer === dummyPropertyLayer) {
    //console.log('dummylayer prop added')
    clusterLayer.addLayer(propertyLayer);
    $('#house-sales_check').prop('checked', true);
  }
});
map.on("overlayremove", function(e) {
  if (e.layer === dummyCrimeLayer) {
    //console.log('dummylayer crime removed');
    clusterLayer.removeLayer(crimeLayer);
    $('#crimes_check').prop('checked', false);
  }
  if (e.layer === dummyPlanningLayer) {
    //console.log('dummylayer planning removed')
    clusterLayer.removeLayer(planningLayer);
    $('#planning-applications_check').prop('checked', false);
  }
  if (e.layer === dummyPropertyLayer) {
   // console.log('dummylayer property removed')
    clusterLayer.removeLayer(propertyLayer);
    $('#house-sales_check').prop('checked', false);
  }
});

//Change map content when email/list checkboxes are changed
$('#crimes_check').on('change', function(){
  if ($('#crimes_check').prop('checked')){
    clusterLayer.addLayer(crimeLayer)
  }else{
    clusterLayer.removeLayer(crimeLayer)
  }
})
$('#planning-applications_check').on('change', function(){
  if ($('#planning-applications_check').prop('checked')){
    clusterLayer.addLayer(planningLayer)
  }else{
    clusterLayer.removeLayer(planningLayer)
  }
})
$('#house-sales_check').on('change', function(){
  if ($('#house-sales_check').prop('checked')){
    clusterLayer.addLayer(propertyLayer)
  }else{
    clusterLayer.removeLayer(propertyLayer)
  }
})
$('#flood-risk_check').on('change', function(){
  if ($('#flood-risk_check').prop('checked')){
    map.addLayer(floodLayer);
  }else{
    map.removeLayer(floodLayer);
  }
})

$('#custom-search-button').on("click", function(){
  if ($('#custom-search-button').html() === "Change"){
    setCustomRadius();
    $('#custom-search-button').html("Update map content");
  }else{
    saveCustomRadius();
    $('#custom-search-button').html("Loading content...");
    map.removeLayer(clusterLayer);
    map.removeLayer(floodLayer);
  }

})

var editing_radius;
map.on("zoomend", function(e) {
 if (editing_radius === true)  {
   // map.addLayer(clusterLayer);
      setTimeout(function() {
               $('.awesome-marker, .leaflet-shadow-pane, .marker-cluster').addClass('fade-markers');
      }, 1);
  }
});
map.on("zoomstart", function(e) {
 if (editing_radius === true)  {
     // map.removeLayer(clusterLayer);
      setTimeout(function() {
               $('.awesome-marker, .leaflet-shadow-pane, .marker-cluster').addClass('fade-markers');
      }, 1);
  }
});

map.on("mouseup", function(e) {
  if (editing_radius === true)  {
    $('#user-radius').val(Math.round(drawnItems.getLayers()[0]._mRadius))
    $('#user-lat-hidden').val(drawnItems.getLayers()[0]._latlng.lat)
    $('#user-long-hidden').val(drawnItems.getLayers()[0]._latlng.lng)
    postcodeMarker.setLatLng([drawnItems.getLayers()[0]._latlng.lat,drawnItems.getLayers()[0]._latlng.lng]);
    console.log("Radius of drawn circle: " + Math.round(drawnItems.getLayers()[0]._mRadius) + "m around "+drawnItems.getLayers()[0]._latlng.lat+','+drawnItems.getLayers()[0]._latlng.lng)

  }
});

function setCustomRadius(){
   //$('.awesome-marker, .leaflet-shadow-pane').css({'opacity':'0.2'});
    $('.awesome-marker, .leaflet-shadow-pane, .marker-cluster').addClass('fade-markers');
    postcodeRadius.editing.enable();
    postcodeMarker.closePopup();
    map.addLayer(drawnItems);
    $('.leaflet-editing-icon').addClass('radiusDragPoints');
    editing_radius = true;
}

function saveCustomRadius(){
  //$('.awesome-marker, .leaflet-shadow-pane').css({'opacity':'1'});
  $('.awesome-marker, .leaflet-shadow-pane, .marker-cluster').removeClass('fade-markers');
  postcodeRadius.editing.disable();
  map.removeLayer(drawnItems);
  console.log("Radius of drawn circle: " + Math.round(drawnItems.getLayers()[0]._mRadius) + "m around "+drawnItems.getLayers()[0]._latlng.lat+','+drawnItems.getLayers()[0]._latlng.lng)
  $('#user-radius').val(Math.round(drawnItems.getLayers()[0]._mRadius))
  $('#user-lat-hidden').val(drawnItems.getLayers()[0]._latlng.lat)
  $('#user-long-hidden').val(drawnItems.getLayers()[0]._latlng.lng)
  postcodeMarker.setLatLng([drawnItems.getLayers()[0]._latlng.lat,drawnItems.getLayers()[0]._latlng.lng]);
  postcodeMarker.unbindPopup().bindPopup("Your custom location");
  //window.location = "/report/" + drawnItems.getLayers()[0]._latlng.lat + ',' + drawnItems.getLayers()[0]._latlng.lng;
  editing_radius = false;
  $('form').submit();
}

// functions to clean up popup text
function toTitleCase(str){
    return str.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
}
function numberWithCommas(x) {
    return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}

function typeOfProperty(type){
  switch (type) {
    case "D":
        fullType = "Detached house";
        break;
    case "S":
        fullType = "Semi-detached house";
        break;
    case "T":
        fullType = "Terrace";
        break;
    case "F":
        fullType = "Flat";
        break;
  }
  return fullType;
}

<commit_msg>added spinning icon when loading new content<commit_after>var Acetate_all = L.tileLayer('http://a{s}.acetate.geoiq.com/tiles/acetate-hillshading/{z}/{x}/{y}.png', {
	attribution: '©2012 Esri & Stamen, Data from OSM and Natural Earth',
	subdomains: '0123',
	minZoom: 2,
	maxZoom: 18
})

var Hydda_Full = L.tileLayer('http://{s}.tile.openstreetmap.se/hydda/full/{z}/{x}/{y}.png', {
  minZoom: 0,
  maxZoom: 18,
  attribution: 'Tiles courtesy of OpenStreetMap Sweden — Map data © OpenStreetMap contributors, CC-BY-SA'
});

var Stamen_TonerLite = L.tileLayer('http://{s}.tile.stamen.com/toner-lite/{z}/{x}/{y}.png', {
  attribution: 'Map tiles by Stamen Design, CC BY 3.0 — Map data © OpenStreetMap contributors, CC-BY-SA',
  subdomains: 'abcd',
  minZoom: 0,
  maxZoom: 20
});
var Esri_WorldImagery = L.tileLayer('http://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', {
  attribution: 'Tiles © Esri — Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community'
});

 var crimeLayer = L.layerGroup();
 var crimeMarker = [];

 var planningLayer = L.layerGroup();
 var planningMarker = [];

 var propertyLayer = L.layerGroup();
 var propertyMarker = [];

 var floodLayer = L.layerGroup();
 var floodArea = [];

 var bounds = new L.LatLngBounds();
 var layersOnMap = [];

 var clusterLayer = new L.MarkerClusterGroup({
    maxClusterRadius: 1,
    spiderfyOnMaxZoom: true,
    showCoverageOnHover: false,
    zoomToBoundsOnClick: true,
    animateAddingMarkers: true
  });

planningIcon  = L.AwesomeMarkers.icon({icon: 'fa-file-text', markerColor: 'red', prefix: 'fa'})
crimeIcon     = L.AwesomeMarkers.icon({icon: 'fa-gavel', markerColor: 'blue', prefix: 'fa'})
propertyIcon  = L.AwesomeMarkers.icon({icon: 'fa-gbp', markerColor: 'green', prefix: 'fa'})
postcodeIcon  = L.AwesomeMarkers.icon({icon: 'fa-home', markerColor: 'orange', prefix: 'fa'})
loadingIcon   = L.AwesomeMarkers.icon({icon: 'fa-refresh', markerColor: 'orange', prefix: 'fa', spin: true})

$.each(floodData.ProximityFloodAlerts, function(i, feature){
    var floodAlertBounds = [[feature.Bounds.BottomRight.Latitude, feature.Bounds.BottomRight.Longitude], [feature.Bounds.TopLeft.Latitude, feature.Bounds.TopLeft.Longitude]];
    floodArea[i] =  L.rectangle(floodAlertBounds, {
                                  color: "#E0753C",
                                  fillColor: "#E0753C",
                                  fillOpacity: 0.2,
                                  weight: 3,
                                  dashArray:10
                                })
                      .bindPopup("Environment Agency Flood Alert"
                                +"
Date Issued: " + feature.FloodAlert.Raised.substring(0, 10)
                                +"
Location: " + feature.FloodAlert.AreaDescription
                                +"
Severity: " + feature.FloodAlert.Severity
                          )
                      .addTo(floodLayer);
    layersOnMap.push(floodLayer);

})

$.each(planningData, function(i, feature) {
    planningMarker[i] = L.marker([feature.location.latitude, feature.location.longitude], {icon: planningIcon})
                    .bindPopup('Date Submitted: '+feature.casedate.substring(0,10)
                              +'
Reference: '+feature.casereference
                              +'
Description: '+feature.casetext
                              +'
Location: '+feature.locationtext
                              +'
Status: '+feature.banesstatus
                            )
                    .addTo(planningLayer);
    bounds.extend([feature.location.latitude, feature.location.longitude]);
    layersOnMap.push(planningLayer);
    clusterLayer.addLayer(planningLayer);
});

$.each(crimeData, function(i, feature) {
  //console.log(crime.location.latitude)
    crimeMarker[i] = L.marker([feature.location.latitude, feature.location.longitude], {icon: crimeIcon})
                    .bindPopup('Date: '+feature.month.substring(0, 7)
                              +'
Crime Type: '+toTitleCase(feature.crime_category).split('-').join(' ')
                              +'
'+'Location: '+feature.street_name)
                    .addTo(crimeLayer);
    bounds.extend([feature.location.latitude, feature.location.longitude]);
    layersOnMap.push(crimeLayer);
    clusterLayer.addLayer(crimeLayer);
});

$.each(houseData, function(i, feature) {
    propertyMarker[i] = L.marker([feature.location.latitude, feature.location.longitude], {icon: propertyIcon})
                    .bindPopup('Date of sale: '+feature.date_of_transfer.substring(0, 10)
                                +'
Price: £'+numberWithCommas(feature.price)
                                +'
Type of property: ' + typeOfProperty(feature.property_type)
                                +'
Address: ' + (feature.primary_addressable_object_name ? toTitleCase(feature.primary_addressable_object_name) + ', ' : '')
                                                        + (feature.secondary_addressable_object_name ? toTitleCase(feature.secondary_addressable_object_name) + ', ' : '')
                                                        + (feature.locality ? toTitleCase(feature.locality) + ', ' : '')
                                                        + (feature.town_city ? toTitleCase(feature.town_city) + ', ' : '')
                                                        + (feature.district ? toTitleCase(feature.district) + ', ' : '')
                                                        + feature.postcode
                              )
                    .addTo(propertyLayer);
    bounds.extend([feature.location.latitude, feature.location.longitude]);
    layersOnMap.push(propertyLayer);
    clusterLayer.addLayer(propertyLayer);
});

var map = L.map('map',{
    attributionControl: false,
    maxZoom: 18,
    layers: Hydda_Full
  }).setView([51.477106,-2.690277], 10);
  map.addLayer(clusterLayer);
   var dummyCrimeLayer = L.layerGroup().addTo(map);
   var dummyPlanningLayer = L.layerGroup().addTo(map);
   var dummyPropertyLayer = L.layerGroup().addTo(map);
/*

    var map = L.map('map', {
        layers: layersOnMap
    });

    */

    var baseLayers = {
        //"Acetate": Acetate_all,
        "Road Map": Hydda_Full,
        //"Satmen Toner Lite": Stamen_TonerLite,
        "Satellite Imagery": Esri_WorldImagery

    };

    var overlays = {
        "Crimes": dummyCrimeLayer,
        "Planning Applications": dummyPlanningLayer,
        "Property Sales": dummyPropertyLayer,
        "Flood Alerts": floodLayer
    };
   var drawnItems = new L.FeatureGroup();
   var postcodeRadius = L.circle([searchedForPostcode[1],searchedForPostcode[0]], 500, {
                                color: 'red',
                                fillColor:'red',
                                fillOpacity: 0.1,
                                opacity: 1,
                               // dashArray: '20',
                                zIndexOffset: 9999
                              }).addTo(drawnItems);

    L.control.layers(baseLayers, overlays).addTo(map);
    var postcodeMarker = L.marker([searchedForPostcode[1],searchedForPostcode[0]], {icon: postcodeIcon, zIndexOffset:999}).bindPopup('Your location').addTo(map);
    bounds.extend([searchedForPostcode[1],searchedForPostcode[0]]);
    map.fitBounds(bounds);
   // map.addLayer(clusterLayer);

// toggle email/list checkboxes when map layer control is changed.
map.on("overlayadd", function(e) {
  if (e.layer === dummyCrimeLayer) {
    clusterLayer.addLayer(crimeLayer);
    //console.log('dummylayer crime added')
    $('#crimes_check').prop('checked', true);
  }
  if (e.layer === dummyPlanningLayer) {
    //console.log('dummylayer plan added')
    clusterLayer.addLayer(planningLayer);
    $('#planning-applications_check').prop('checked', true);
  }
  if (e.layer === dummyPropertyLayer) {
    //console.log('dummylayer prop added')
    clusterLayer.addLayer(propertyLayer);
    $('#house-sales_check').prop('checked', true);
  }
});
map.on("overlayremove", function(e) {
  if (e.layer === dummyCrimeLayer) {
    //console.log('dummylayer crime removed');
    clusterLayer.removeLayer(crimeLayer);
    $('#crimes_check').prop('checked', false);
  }
  if (e.layer === dummyPlanningLayer) {
    //console.log('dummylayer planning removed')
    clusterLayer.removeLayer(planningLayer);
    $('#planning-applications_check').prop('checked', false);
  }
  if (e.layer === dummyPropertyLayer) {
   // console.log('dummylayer property removed')
    clusterLayer.removeLayer(propertyLayer);
    $('#house-sales_check').prop('checked', false);
  }
});

//Change map content when email/list checkboxes are changed
$('#crimes_check').on('change', function(){
  if ($('#crimes_check').prop('checked')){
    clusterLayer.addLayer(crimeLayer)
  }else{
    clusterLayer.removeLayer(crimeLayer)
  }
})
$('#planning-applications_check').on('change', function(){
  if ($('#planning-applications_check').prop('checked')){
    clusterLayer.addLayer(planningLayer)
  }else{
    clusterLayer.removeLayer(planningLayer)
  }
})
$('#house-sales_check').on('change', function(){
  if ($('#house-sales_check').prop('checked')){
    clusterLayer.addLayer(propertyLayer)
  }else{
    clusterLayer.removeLayer(propertyLayer)
  }
})
$('#flood-risk_check').on('change', function(){
  if ($('#flood-risk_check').prop('checked')){
    map.addLayer(floodLayer);
  }else{
    map.removeLayer(floodLayer);
  }
})

$('#custom-search-button').on("click", function(){
  if ($('#custom-search-button').html() === "Change"){
    setCustomRadius();
    $('#custom-search-button').html("Update map content");
  }else{
    saveCustomRadius();
    $('#custom-search-button').html("Loading content...");
    postcodeMarker.setIcon(loadingIcon);
    map.removeLayer(clusterLayer);
    map.removeLayer(floodLayer);
    bounds = [];
  }

})

var editing_radius;
map.on("zoomend", function(e) {
 if (editing_radius === true)  {
   // map.addLayer(clusterLayer);
      setTimeout(function() {
               $('.awesome-marker, .leaflet-shadow-pane, .marker-cluster').addClass('fade-markers');
      }, 1);
  }
});
map.on("zoomstart", function(e) {
 if (editing_radius === true)  {
     // map.removeLayer(clusterLayer);
      setTimeout(function() {
               $('.awesome-marker, .leaflet-shadow-pane, .marker-cluster').addClass('fade-markers');
      }, 1);
  }
});

map.on("mouseup", function(e) {
  if (editing_radius === true)  {
    $('#user-radius').val(Math.round(drawnItems.getLayers()[0]._mRadius))
    $('#user-lat-hidden').val(drawnItems.getLayers()[0]._latlng.lat)
    $('#user-long-hidden').val(drawnItems.getLayers()[0]._latlng.lng)
    postcodeMarker.setLatLng([drawnItems.getLayers()[0]._latlng.lat,drawnItems.getLayers()[0]._latlng.lng]);
    console.log("Radius of drawn circle: " + Math.round(drawnItems.getLayers()[0]._mRadius) + "m around "+drawnItems.getLayers()[0]._latlng.lat+','+drawnItems.getLayers()[0]._latlng.lng)

  }
});

function setCustomRadius(){
   //$('.awesome-marker, .leaflet-shadow-pane').css({'opacity':'0.2'});
    $('.awesome-marker, .leaflet-shadow-pane, .marker-cluster').addClass('fade-markers');
    postcodeRadius.editing.enable();
    postcodeMarker.closePopup();
    map.addLayer(drawnItems);
    $('.leaflet-editing-icon').addClass('radiusDragPoints');
    editing_radius = true;
}

function saveCustomRadius(){
  //$('.awesome-marker, .leaflet-shadow-pane').css({'opacity':'1'});
  $('.awesome-marker, .leaflet-shadow-pane, .marker-cluster').removeClass('fade-markers');
  postcodeRadius.editing.disable();
  map.removeLayer(drawnItems);
  console.log("Radius of drawn circle: " + Math.round(drawnItems.getLayers()[0]._mRadius) + "m around "+drawnItems.getLayers()[0]._latlng.lat+','+drawnItems.getLayers()[0]._latlng.lng)
  $('#user-radius').val(Math.round(drawnItems.getLayers()[0]._mRadius))
  $('#user-lat-hidden').val(drawnItems.getLayers()[0]._latlng.lat)
  $('#user-long-hidden').val(drawnItems.getLayers()[0]._latlng.lng)
  postcodeMarker.setLatLng([drawnItems.getLayers()[0]._latlng.lat,drawnItems.getLayers()[0]._latlng.lng]);
  postcodeMarker.unbindPopup().bindPopup("Your custom location");
  //window.location = "/report/" + drawnItems.getLayers()[0]._latlng.lat + ',' + drawnItems.getLayers()[0]._latlng.lng;
  editing_radius = false;
  $('form').submit();
}

// functions to clean up popup text
function toTitleCase(str){
    return str.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
}
function numberWithCommas(x) {
    return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}

function typeOfProperty(type){
  switch (type) {
    case "D":
        fullType = "Detached house";
        break;
    case "S":
        fullType = "Semi-detached house";
        break;
    case "T":
        fullType = "Terrace";
        break;
    case "F":
        fullType = "Flat";
        break;
  }
  return fullType;
}

<|endoftext|>


<commit_before>import t from 'tcomb';

const ApiService = t.struct({
	getInitialAuthContext: t.Function,
	initializeAuth: t.Function,
	login: t.Function,
	logout: t.Function,
	getEntityDescriptors: t.Function,
	getEntityIndex: t.Function,
	getEntity: t.Function,
	persistEntity: t.Function,
	deleteEntity: t.Function
});

export const ApiContext = t.struct({
	host: t.maybe(t.struct({
		name: t.String,
		ssl: t.Boolean
	})),
	service: ApiService
});
<commit_msg>chore(api/types): export ApiService type<commit_after>import t from 'tcomb';

export const ApiService = t.struct({
	getInitialAuthContext: t.Function,
	initializeAuth: t.Function,
	login: t.Function,
	logout: t.Function,
	getEntityDescriptors: t.Function,
	getEntityIndex: t.Function,
	getEntity: t.Function,
	persistEntity: t.Function,
	deleteEntity: t.Function
});

export const ApiContext = t.struct({
	host: t.maybe(t.struct({
		name: t.String,
		ssl: t.Boolean
	})),
	service: ApiService
});
<|endoftext|>


<commit_before>'use strict';
const CliTable = require('cli-table');
const chalk = require('chalk');
const tradePairs = require('./tradePairs');
const tradePairParser = require('./tradePairParser');
const formatter = require('./formatter');

class TableData {

  constructor() {
    this.tradePairs = [];
  }

  init() {
    this.tradePairs = tradePairs.getTradePairs();
  }

  getTable() {
    return new Promise((resolve, reject) => {
      let table = new CliTable({
        head: this.getHead()
      });

      this.fillContent(table)
        .then(table => resolve(table))
        .catch(error => reject(error));
    });
  }

  getHead() {
    return [
      chalk.cyan.bold('name'),
      chalk.cyan.bold('ll'),
      chalk.cyan.bold('stat'),
      chalk.cyan.bold('oo?'),
      chalk.cyan.bold('coins'),
      chalk.cyan.bold('in BTC'),
      chalk.cyan.bold('change'),
      chalk.cyan.bold('pr2Buy'),
      chalk.cyan.bold('pr2Sell'),
      chalk.cyan.bold('lastPrice'),
      chalk.cyan.bold('price diff'),
      chalk.cyan.bold('price is'),
      chalk.cyan.bold('# buys'),
      chalk.cyan.bold('1/6/12/24/+'),
      chalk.cyan.bold('# sells'),
      chalk.cyan.bold('1/6/12/24/+'),
      chalk.cyan.bold('profit'),
      chalk.cyan.bold('last error')
    ];
  }

  fillContent(table) {
    return new Promise((resolve, reject) => {
      let dataPromises = [];
      for (let market of Object.keys(this.tradePairs)) {
        if (this.tradePairs[market].length === 0) {
          continue;
        }

        for (let tradePair of this.tradePairs[market]) {
          dataPromises.push(tradePairParser.getData(tradePair, market));
        }
      }

      Promise.all(dataPromises)
        .then(values => {

          let totalBTCValue = 0.0;
          let totalProfit = 0.0;

          for (let data of values) {
            if (data === undefined || data.lastTimeStamp === undefined) {
              continue;
            }

            if(!isNaN(parseFloat(formatter.btcValue(data.coins, data.lastPriceInBTC)))) {
              totalBTCValue += parseFloat(formatter.btcValue(data.coins, data.lastPriceInBTC));
            }

            if(!isNaN(parseFloat(data.profit))) {
              totalProfit += parseFloat(data.profit);
            }

            table.push([
              formatter.tradePair(data.tradePair),
              formatter.timeSince(data.lastTimeStamp),
              formatter.timeToStatus(data.lastTimeStamp),
              formatter.openOrders(data.openOrders || data.noOpenOrders),
              formatter.coins(data.coins),
              formatter.btcValue(data.coins, data.lastPriceInBTC),
              formatter.currentProfit(data.coins, data.boughtPrice, data.lastPriceInBTC),
              formatter.price(data.buyPrice),
              formatter.price(data.sellPrice),
              formatter.lastPrice(data.lastPrice, data.tendency),
              formatter.priceDiff(data.priceStatusBuy || data.priceStatusSell, data.buyPrice, data.sellPrice, data.lastPrice),
              formatter.buySellMessage(data.priceStatusBuy || data.priceStatusSell || data.priceStatusSweet),
              formatter.trades(data.buyCounter, data.lastTimeStampBuy),
              formatter.tradesInTimeSlots(data.buys),
              formatter.trades(data.sellCounter, data.lastTimeStampSell),
              formatter.tradesInTimeSlots(data.sells),
              formatter.price(data.profit),
              formatter.errorCode(data.lastErrorCode, data.lastErrorTimeStamp)
            ]);
          }

          table.push([
            formatter.tradePair('TOTAL'),
            '',
            '',
            '',
            '',
            formatter.price(totalBTCValue),
            '',
            '',
            '',
            '',
            '',
            '',
            '',
            '',
            '',
            '',
            formatter.price(totalProfit),
            ''
          ]);
          resolve(table);
        })
        .catch(error => reject(error));
    });
  }

}

module.exports = new TableData();
<commit_msg>Typo.<commit_after>'use strict';
const CliTable = require('cli-table');
const chalk = require('chalk');
const tradePairs = require('./tradePairs');
const tradePairParser = require('./tradePairParser');
const formatter = require('./formatter');

class TableData {

  constructor() {
    this.tradePairs = [];
  }

  init() {
    this.tradePairs = tradePairs.getTradePairs();
  }

  getTable() {
    return new Promise((resolve, reject) => {
      let table = new CliTable({
        head: this.getHead()
      });

      this.fillContent(table)
        .then(table => resolve(table))
        .catch(error => reject(error));
    });
  }

  getHead() {
    return [
      chalk.cyan.bold('name'),
      chalk.cyan.bold('ll'),
      chalk.cyan.bold('stat'),
      chalk.cyan.bold('oo?'),
      chalk.cyan.bold('coins'),
      chalk.cyan.bold('in BTC'),
      chalk.cyan.bold('change'),
      chalk.cyan.bold('pr2Buy'),
      chalk.cyan.bold('pr2Sell'),
      chalk.cyan.bold('lastPrice'),
      chalk.cyan.bold('price diff'),
      chalk.cyan.bold('price is'),
      chalk.cyan.bold('# buys'),
      chalk.cyan.bold('1/6/12/24/+'),
      chalk.cyan.bold('# sells'),
      chalk.cyan.bold('1/6/12/24/+'),
      chalk.cyan.bold('profit'),
      chalk.cyan.bold('last error')
    ];
  }

  fillContent(table) {
    return new Promise((resolve, reject) => {
      let dataPromises = [];
      for (let market of Object.keys(this.tradePairs)) {
        if (this.tradePairs[market].length === 0) {
          continue;
        }

        for (let tradePair of this.tradePairs[market]) {
          dataPromises.push(tradePairParser.getData(tradePair, market));
        }
      }

      Promise.all(dataPromises)
        .then(values => {
          let totalBTCValue = 0.0;
          let totalProfit = 0.0;

          for (let data of values) {
            if (data === undefined || data.lastTimeStamp === undefined) {
              continue;
            }

            if (!isNaN(parseFloat(formatter.btcValue(data.coins, data.lastPriceInBTC)))) {
              totalBTCValue += parseFloat(formatter.btcValue(data.coins, data.lastPriceInBTC));
            }

            if (!isNaN(parseFloat(data.profit))) {
              totalProfit += parseFloat(data.profit);
            }

            table.push([
              formatter.tradePair(data.tradePair),
              formatter.timeSince(data.lastTimeStamp),
              formatter.timeToStatus(data.lastTimeStamp),
              formatter.openOrders(data.openOrders || data.noOpenOrders),
              formatter.coins(data.coins),
              formatter.btcValue(data.coins, data.lastPriceInBTC),
              formatter.currentProfit(data.coins, data.boughtPrice, data.lastPriceInBTC),
              formatter.price(data.buyPrice),
              formatter.price(data.sellPrice),
              formatter.lastPrice(data.lastPrice, data.tendency),
              formatter.priceDiff(data.priceStatusBuy || data.priceStatusSell, data.buyPrice, data.sellPrice, data.lastPrice),
              formatter.buySellMessage(data.priceStatusBuy || data.priceStatusSell || data.priceStatusSweet),
              formatter.trades(data.buyCounter, data.lastTimeStampBuy),
              formatter.tradesInTimeSlots(data.buys),
              formatter.trades(data.sellCounter, data.lastTimeStampSell),
              formatter.tradesInTimeSlots(data.sells),
              formatter.price(data.profit),
              formatter.errorCode(data.lastErrorCode, data.lastErrorTimeStamp)
            ]);
          }

          table.push([
            formatter.tradePair('TOTAL'),
            '',
            '',
            '',
            '',
            formatter.price(totalBTCValue),
            '',
            '',
            '',
            '',
            '',
            '',
            '',
            '',
            '',
            '',
            formatter.price(totalProfit),
            ''
          ]);
          resolve(table);
        })
        .catch(error => reject(error));
    });
  }

}

module.exports = new TableData();
<|endoftext|>


<commit_before>'use strict';

var nullFormCtrl = {
  $addControl: noop,
  $removeControl: noop,
  $setValidity: noop,
  $setDirty: noop
}

/**
 * @ngdoc object
 * @name angular.module.ng.$compileProvider.directive.form.FormController
 *
 * @property {boolean} $pristine True if user has not interacted with the form yet.
 * @property {boolean} $dirty True if user has already interacted with the form.
 * @property {boolean} $valid True if all of the containg forms and controls are valid.
 * @property {boolean} $invalid True if at least one containing control or form is invalid.
 *
 * @property {Object} $error Is an object hash, containing references to all invalid controls or
 *  forms, where:
 *
 *  - keys are validation tokens (error names) — such as `REQUIRED`, `URL` or `EMAIL`),
 *  - values are arrays of controls or forms that are invalid with given error.
 *
 * @description
 * `FormController` keeps track of all its controls and nested forms as well as state of them,
 * such as being valid/invalid or dirty/pristine.
 *
 * Each {@link angular.module.ng.$compileProvider.directive.form form} directive creates an instance
 * of `FormController`.
 *
 */
FormController.$inject = ['$element', '$attrs'];
function FormController(element, attrs) {
  var form = this,
      parentForm = element.parent().controller('form') || nullFormCtrl,
      invalidCount = 0, // used to easily determine if we are valid
      errors = form.$error = {};

  // init state
  form.$name = attrs.name;
  form.$dirty = false;
  form.$pristine = true;
  form.$valid = true;
  form.$invalid = false;

  parentForm.$addControl(form);

  // Setup initial state of the control
  element.addClass(PRISTINE_CLASS);
  toggleValidCss(true);

  // convenience method for easy toggling of classes
  function toggleValidCss(isValid, validationErrorKey) {
    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';
    element.
      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).
      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);
  }

  form.$addControl = function(control) {
    if (control.$name && !form.hasOwnProperty(control.$name)) {
      form[control.$name] = control;
    }
  };

  form.$removeControl = function(control) {
    if (control.$name && form[control.$name] === control) {
      delete form[control.$name];
    }
    forEach(errors, cleanupControlErrors, control);
  };

  form.$setValidity = function(validationToken, isValid, control) {
    if (isValid) {
      cleanupControlErrors(errors[validationToken], validationToken, control);

      if (!invalidCount) {
        toggleValidCss(isValid);
        form.$valid = true;
        form.$invalid = false;
      }
    } else {
      if (!invalidCount) {
        toggleValidCss(isValid);
      }
      addControlError(validationToken, control);

      form.$valid = false;
      form.$invalid = true;
    }
  };

  form.$setDirty = function() {
    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);
    form.$dirty = true;
    form.$pristine = false;
  };

  function cleanupControlErrors(queue, validationToken, control) {
    if (queue) {
      control = control || this; // so that we can be used in forEach;
      arrayRemove(queue, control);
      if (!queue.length) {
        invalidCount--;
        errors[validationToken] = false;
        toggleValidCss(true, validationToken);
        parentForm.$setValidity(validationToken, true, form);
      }
    }
  }

  function addControlError(validationToken, control) {
    var queue = errors[validationToken];
    if (queue) {
      if (includes(queue, control)) return;
    } else {
      errors[validationToken] = queue = [];
      invalidCount++;
      toggleValidCss(false, validationToken);
      parentForm.$setValidity(validationToken, false, form);
    }
    queue.push(control);
  }
}

/**
 * @ngdoc directive
 * @name angular.module.ng.$compileProvider.directive.ng-form
 * @restrict EAC
 *
 * @description
 * Nestable alias of {@link angular.module.ng.$compileProvider.directive.form `form`} directive. HTML
 * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a
 * sub-group of controls needs to be determined.
 *
 * @param {string=} ng-form|name Name of the form. If specified, the form controller will be published into
 *                       related scope, under this name.
 *
 */

 /**
 * @ngdoc directive
 * @name angular.module.ng.$compileProvider.directive.form
 * @restrict E
 *
 * @description
 * Directive that instantiates
 * {@link angular.module.ng.$compileProvider.directive.form.FormController FormController}.
 *
 * If `name` attribute is specified, the form controller is published onto the current scope under
 * this name.
 *
 * # Alias: {@link angular.module.ng.$compileProvider.directive.ng-form `ng-form`}
 *
 * In angular forms can be nested. This means that the outer form is valid when all of the child
 * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this
 * reason angular provides {@link angular.module.ng.$compileProvider.directive.ng-form `ng-form`} alias
 * which behaves identical to `<form>` but allows form nesting.
 *
 *
 * # CSS classes
 *  - `ng-valid` Is set if the form is valid.
 *  - `ng-invalid` Is set if the form is invalid.
 *  - `ng-pristine` Is set if the form is pristine.
 *  - `ng-dirty` Is set if the form is dirty.
 *
 *
 * # Submitting a form and preventing default action
 *
 * Since the role of forms in client-side Angular applications is different than in classical
 * roundtrip apps, it is desirable for the browser not to translate the form submission into a full
 * page reload that sends the data to the server. Instead some javascript logic should be triggered
 * to handle the form submission in application specific way.
 *
 * For this reason, Angular prevents the default action (form submission to the server) unless the
 * `<form>` element has an `action` attribute specified.
 *
 * You can use one of the following two ways to specify what javascript method should be called when
 * a form is submitted:
 *
 * - ng-submit on the form element (add link to ng-submit)
 * - ng-click on the first button or input field of type submit (input[type=submit])
 *
 * To prevent double execution of the handler, use only one of ng-submit or ng-click. This is
 * because of the following form submission rules coming from the html spec:
 *
 * - If a form has only one input field then hitting enter in this field triggers form submit
 * (`ng-submit`)
 * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter
 * doesn't trigger submit
 * - if a form has one or more input fields and one or more buttons or input[type=submit] then
 * hitting enter in any of the input fields will trigger the click handler on the *first* button or
 * input[type=submit] (`ng-click`) *and* a submit handler on the enclosing form (`ng-submit`)
 *
 * @param {string=} name Name of the form. If specified, the form controller will be published into
 *                       related scope, under this name.
 *
 * @example
    <doc:example>
      <doc:source>

       <form name="myForm" ng-controller="Ctrl">
         userType: <input name="input" ng-model="userType" required>
         Required!

         <tt>userType = {{userType}}</tt>

         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt>

         <tt>myForm.input.$error = {{myForm.input.$error}}</tt>

         <tt>myForm.$valid = {{myForm.$valid}}</tt>

         <tt>myForm.$error.REQUIRED = {{!!myForm.$error.REQUIRED}}</tt>

        </form>
      </doc:source>
      <doc:scenario>
        it('should initialize to model', function() {
         expect(binding('userType')).toEqual('guest');
         expect(binding('myForm.input.$valid')).toEqual('true');
        });

        it('should be invalid if empty', function() {
         input('userType').enter('');
         expect(binding('userType')).toEqual('');
         expect(binding('myForm.input.$valid')).toEqual('false');
        });
      </doc:scenario>
    </doc:example>
 */
var formDirectiveDir = {
  name: 'form',
  restrict: 'E',
  controller: FormController,
  compile: function() {
    return {
      pre: function(scope, formElement, attr, controller) {
        if (!attr.action) {
          formElement.bind('submit', function(event) {
            event.preventDefault();
          });
        }

        var parentFormCtrl = formElement.parent().controller('form'),
            alias = attr.name || attr.ngForm;

        if (alias) {
          scope[alias] = controller;
        }
        if (parentFormCtrl) {
          formElement.bind('$destroy', function() {
            parentFormCtrl.$removeControl(controller);
            if (alias) {
              scope[alias] = undefined;
            }
            extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards
          });
        }
      }
    };
  }
};

var formDirective = valueFn(formDirectiveDir);
var ngFormDirective = valueFn(extend(copy(formDirectiveDir), {restrict: 'EAC'}));
<commit_msg>fix(FormController): ask for  dependency to fool the  BC module<commit_after>'use strict';

var nullFormCtrl = {
  $addControl: noop,
  $removeControl: noop,
  $setValidity: noop,
  $setDirty: noop
}

/**
 * @ngdoc object
 * @name angular.module.ng.$compileProvider.directive.form.FormController
 *
 * @property {boolean} $pristine True if user has not interacted with the form yet.
 * @property {boolean} $dirty True if user has already interacted with the form.
 * @property {boolean} $valid True if all of the containg forms and controls are valid.
 * @property {boolean} $invalid True if at least one containing control or form is invalid.
 *
 * @property {Object} $error Is an object hash, containing references to all invalid controls or
 *  forms, where:
 *
 *  - keys are validation tokens (error names) — such as `REQUIRED`, `URL` or `EMAIL`),
 *  - values are arrays of controls or forms that are invalid with given error.
 *
 * @description
 * `FormController` keeps track of all its controls and nested forms as well as state of them,
 * such as being valid/invalid or dirty/pristine.
 *
 * Each {@link angular.module.ng.$compileProvider.directive.form form} directive creates an instance
 * of `FormController`.
 *
 */
//asks for $scope to fool the BC controller module
FormController.$inject = ['$element', '$attrs', '$scope'];
function FormController(element, attrs) {
  var form = this,
      parentForm = element.parent().controller('form') || nullFormCtrl,
      invalidCount = 0, // used to easily determine if we are valid
      errors = form.$error = {};

  // init state
  form.$name = attrs.name;
  form.$dirty = false;
  form.$pristine = true;
  form.$valid = true;
  form.$invalid = false;

  parentForm.$addControl(form);

  // Setup initial state of the control
  element.addClass(PRISTINE_CLASS);
  toggleValidCss(true);

  // convenience method for easy toggling of classes
  function toggleValidCss(isValid, validationErrorKey) {
    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';
    element.
      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).
      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);
  }

  form.$addControl = function(control) {
    if (control.$name && !form.hasOwnProperty(control.$name)) {
      form[control.$name] = control;
    }
  };

  form.$removeControl = function(control) {
    if (control.$name && form[control.$name] === control) {
      delete form[control.$name];
    }
    forEach(errors, cleanupControlErrors, control);
  };

  form.$setValidity = function(validationToken, isValid, control) {
    if (isValid) {
      cleanupControlErrors(errors[validationToken], validationToken, control);

      if (!invalidCount) {
        toggleValidCss(isValid);
        form.$valid = true;
        form.$invalid = false;
      }
    } else {
      if (!invalidCount) {
        toggleValidCss(isValid);
      }
      addControlError(validationToken, control);

      form.$valid = false;
      form.$invalid = true;
    }
  };

  form.$setDirty = function() {
    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);
    form.$dirty = true;
    form.$pristine = false;
  };

  function cleanupControlErrors(queue, validationToken, control) {
    if (queue) {
      control = control || this; // so that we can be used in forEach;
      arrayRemove(queue, control);
      if (!queue.length) {
        invalidCount--;
        errors[validationToken] = false;
        toggleValidCss(true, validationToken);
        parentForm.$setValidity(validationToken, true, form);
      }
    }
  }

  function addControlError(validationToken, control) {
    var queue = errors[validationToken];
    if (queue) {
      if (includes(queue, control)) return;
    } else {
      errors[validationToken] = queue = [];
      invalidCount++;
      toggleValidCss(false, validationToken);
      parentForm.$setValidity(validationToken, false, form);
    }
    queue.push(control);
  }
}

/**
 * @ngdoc directive
 * @name angular.module.ng.$compileProvider.directive.ng-form
 * @restrict EAC
 *
 * @description
 * Nestable alias of {@link angular.module.ng.$compileProvider.directive.form `form`} directive. HTML
 * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a
 * sub-group of controls needs to be determined.
 *
 * @param {string=} ng-form|name Name of the form. If specified, the form controller will be published into
 *                       related scope, under this name.
 *
 */

 /**
 * @ngdoc directive
 * @name angular.module.ng.$compileProvider.directive.form
 * @restrict E
 *
 * @description
 * Directive that instantiates
 * {@link angular.module.ng.$compileProvider.directive.form.FormController FormController}.
 *
 * If `name` attribute is specified, the form controller is published onto the current scope under
 * this name.
 *
 * # Alias: {@link angular.module.ng.$compileProvider.directive.ng-form `ng-form`}
 *
 * In angular forms can be nested. This means that the outer form is valid when all of the child
 * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this
 * reason angular provides {@link angular.module.ng.$compileProvider.directive.ng-form `ng-form`} alias
 * which behaves identical to `<form>` but allows form nesting.
 *
 *
 * # CSS classes
 *  - `ng-valid` Is set if the form is valid.
 *  - `ng-invalid` Is set if the form is invalid.
 *  - `ng-pristine` Is set if the form is pristine.
 *  - `ng-dirty` Is set if the form is dirty.
 *
 *
 * # Submitting a form and preventing default action
 *
 * Since the role of forms in client-side Angular applications is different than in classical
 * roundtrip apps, it is desirable for the browser not to translate the form submission into a full
 * page reload that sends the data to the server. Instead some javascript logic should be triggered
 * to handle the form submission in application specific way.
 *
 * For this reason, Angular prevents the default action (form submission to the server) unless the
 * `<form>` element has an `action` attribute specified.
 *
 * You can use one of the following two ways to specify what javascript method should be called when
 * a form is submitted:
 *
 * - ng-submit on the form element (add link to ng-submit)
 * - ng-click on the first button or input field of type submit (input[type=submit])
 *
 * To prevent double execution of the handler, use only one of ng-submit or ng-click. This is
 * because of the following form submission rules coming from the html spec:
 *
 * - If a form has only one input field then hitting enter in this field triggers form submit
 * (`ng-submit`)
 * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter
 * doesn't trigger submit
 * - if a form has one or more input fields and one or more buttons or input[type=submit] then
 * hitting enter in any of the input fields will trigger the click handler on the *first* button or
 * input[type=submit] (`ng-click`) *and* a submit handler on the enclosing form (`ng-submit`)
 *
 * @param {string=} name Name of the form. If specified, the form controller will be published into
 *                       related scope, under this name.
 *
 * @example
    <doc:example>
      <doc:source>

       <form name="myForm" ng-controller="Ctrl">
         userType: <input name="input" ng-model="userType" required>
         Required!

         <tt>userType = {{userType}}</tt>

         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt>

         <tt>myForm.input.$error = {{myForm.input.$error}}</tt>

         <tt>myForm.$valid = {{myForm.$valid}}</tt>

         <tt>myForm.$error.REQUIRED = {{!!myForm.$error.REQUIRED}}</tt>

        </form>
      </doc:source>
      <doc:scenario>
        it('should initialize to model', function() {
         expect(binding('userType')).toEqual('guest');
         expect(binding('myForm.input.$valid')).toEqual('true');
        });

        it('should be invalid if empty', function() {
         input('userType').enter('');
         expect(binding('userType')).toEqual('');
         expect(binding('myForm.input.$valid')).toEqual('false');
        });
      </doc:scenario>
    </doc:example>
 */
var formDirectiveDir = {
  name: 'form',
  restrict: 'E',
  controller: FormController,
  compile: function() {
    return {
      pre: function(scope, formElement, attr, controller) {
        if (!attr.action) {
          formElement.bind('submit', function(event) {
            event.preventDefault();
          });
        }

        var parentFormCtrl = formElement.parent().controller('form'),
            alias = attr.name || attr.ngForm;

        if (alias) {
          scope[alias] = controller;
        }
        if (parentFormCtrl) {
          formElement.bind('$destroy', function() {
            parentFormCtrl.$removeControl(controller);
            if (alias) {
              scope[alias] = undefined;
            }
            extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards
          });
        }
      }
    };
  }
};

var formDirective = valueFn(formDirectiveDir);
var ngFormDirective = valueFn(extend(copy(formDirectiveDir), {restrict: 'EAC'}));
<|endoftext|>


<commit_before>'use strict';

/**
 * @ngdoc filter
 * @name orderBy
 * @kind function
 *
 * @description
 * Orders a specified `array` by the `expression` predicate. It is ordered alphabetically
 * for strings and numerically for numbers. Note: if you notice numbers are not being sorted
 * correctly, make sure they are actually being saved as numbers and not strings.
 *
 * @param {Array} array The array to sort.
 * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be
 *    used by the comparator to determine the order of elements.
 *
 *    Can be one of:
 *
 *    - `function`: Getter function. The result of this function will be sorted using the
 *      `<`, `=`, `>` operator.
 *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'
 *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control
 *      ascending or descending sort order (for example, +name or -name).
 *    - `Array`: An array of function or string predicates. The first predicate in the array
 *      is used for sorting, but when two items are equivalent, the next predicate is used.
 *
 * @param {boolean=} reverse Reverse the order of the array.
 * @returns {Array} Sorted copy of the source array.
 *
 * @example
   <example>
     <file name="index.html">

Sorting predicate = {{predicate}}; reverse = {{reverse}}

         [ unsorted ]

             Name
                 (^)
             Phone Number
             Age

             {{friend.name}}
             {{friend.phone}}
             {{friend.age}}

     </file>
   </example>
 *
 * It's also possible to call the orderBy filter manually, by injecting `$filter`, retrieving the
 * filter routine with `$filter('orderBy')`, and calling the returned filter routine with the
 * desired parameters.
 *
 * Example:
 *
 * @example
  <example>
    <file name="index.html">

            Name
              (^)
            Phone Number
            Age

            {{friend.name}}
            {{friend.phone}}
            {{friend.age}}

    </file>

    <file name="script.js">
      function Ctrl($scope, $filter) {
        var orderBy = $filter('orderBy');
        $scope.friends = [
          { name: 'John',    phone: '555-1212',    age: 10 },
          { name: 'Mary',    phone: '555-9876',    age: 19 },
          { name: 'Mike',    phone: '555-4321',    age: 21 },
          { name: 'Adam',    phone: '555-5678',    age: 35 },
          { name: 'Julie',   phone: '555-8765',    age: 29 }
        ];

        $scope.order = function(predicate, reverse) {
          $scope.friends = orderBy($scope.friends, predicate, reverse);
        };
        $scope.order('-age',false);
      }
    </file>
</example>
 */
orderByFilter.$inject = ['$parse'];
function orderByFilter($parse){
  return function(array, sortPredicate, reverseOrder) {
    if (!isArray(array)) return array;
    if (!sortPredicate) return array;
    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];
    sortPredicate = map(sortPredicate, function(predicate){
      var descending = false, get = predicate || identity;
      if (isString(predicate)) {
        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {
          descending = predicate.charAt(0) == '-';
          predicate = predicate.substring(1);
        }
        get = $parse(predicate);
        if (get.constant) {
          var key = get();
          return reverseComparator(function(a,b) {
            return compare(a[key], b[key]);
          }, descending);
        }
      }
      return reverseComparator(function(a,b){
        return compare(get(a),get(b));
      }, descending);
    });
    var arrayCopy = [];
    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }
    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));

    function comparator(o1, o2){
      for ( var i = 0; i < sortPredicate.length; i++) {
        var comp = sortPredicate[i](o1, o2);
        if (comp !== 0) return comp;
      }
      return 0;
    }
    function reverseComparator(comp, descending) {
      return toBoolean(descending)
          ? function(a,b){return comp(b,a);}
          : comp;
    }
    function compare(v1, v2){
      var t1 = typeof v1;
      var t2 = typeof v2;
      if (t1 == t2) {
        if (t1 == "string") {
           v1 = v1.toLowerCase();
           v2 = v2.toLowerCase();
        }
        if (v1 === v2) return 0;
        return v1 < v2 ? -1 : 1;
      } else {
        return t1 < t2 ? -1 : 1;
      }
    }
  };
}
<commit_msg>docs(orderBy): update examples to use modules<commit_after>'use strict';

/**
 * @ngdoc filter
 * @name orderBy
 * @kind function
 *
 * @description
 * Orders a specified `array` by the `expression` predicate. It is ordered alphabetically
 * for strings and numerically for numbers. Note: if you notice numbers are not being sorted
 * correctly, make sure they are actually being saved as numbers and not strings.
 *
 * @param {Array} array The array to sort.
 * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be
 *    used by the comparator to determine the order of elements.
 *
 *    Can be one of:
 *
 *    - `function`: Getter function. The result of this function will be sorted using the
 *      `<`, `=`, `>` operator.
 *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'
 *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control
 *      ascending or descending sort order (for example, +name or -name).
 *    - `Array`: An array of function or string predicates. The first predicate in the array
 *      is used for sorting, but when two items are equivalent, the next predicate is used.
 *
 * @param {boolean=} reverse Reverse the order of the array.
 * @returns {Array} Sorted copy of the source array.
 *
 * @example
   <example module="orderByExample">
     <file name="index.html">

Sorting predicate = {{predicate}}; reverse = {{reverse}}

         [ unsorted ]

             Name
                 (^)
             Phone Number
             Age

             {{friend.name}}
             {{friend.phone}}
             {{friend.age}}

     </file>
   </example>
 *
 * It's also possible to call the orderBy filter manually, by injecting `$filter`, retrieving the
 * filter routine with `$filter('orderBy')`, and calling the returned filter routine with the
 * desired parameters.
 *
 * Example:
 *
 * @example
  <example module="orderByExample">
    <file name="index.html">

            Name
              (^)
            Phone Number
            Age

            {{friend.name}}
            {{friend.phone}}
            {{friend.age}}

    </file>

    <file name="script.js">
      angular.module('orderByExample', [])
        .controller('ExampleController', ['$scope', '$filter', function($scope, $filter) {
          var orderBy = $filter('orderBy');
          $scope.friends = [
            { name: 'John',    phone: '555-1212',    age: 10 },
            { name: 'Mary',    phone: '555-9876',    age: 19 },
            { name: 'Mike',    phone: '555-4321',    age: 21 },
            { name: 'Adam',    phone: '555-5678',    age: 35 },
            { name: 'Julie',   phone: '555-8765',    age: 29 }
          ];
          $scope.order = function(predicate, reverse) {
            $scope.friends = orderBy($scope.friends, predicate, reverse);
          };
          $scope.order('-age',false);
        }]);
    </file>
</example>
 */
orderByFilter.$inject = ['$parse'];
function orderByFilter($parse){
  return function(array, sortPredicate, reverseOrder) {
    if (!isArray(array)) return array;
    if (!sortPredicate) return array;
    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];
    sortPredicate = map(sortPredicate, function(predicate){
      var descending = false, get = predicate || identity;
      if (isString(predicate)) {
        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {
          descending = predicate.charAt(0) == '-';
          predicate = predicate.substring(1);
        }
        get = $parse(predicate);
        if (get.constant) {
          var key = get();
          return reverseComparator(function(a,b) {
            return compare(a[key], b[key]);
          }, descending);
        }
      }
      return reverseComparator(function(a,b){
        return compare(get(a),get(b));
      }, descending);
    });
    var arrayCopy = [];
    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }
    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));

    function comparator(o1, o2){
      for ( var i = 0; i < sortPredicate.length; i++) {
        var comp = sortPredicate[i](o1, o2);
        if (comp !== 0) return comp;
      }
      return 0;
    }
    function reverseComparator(comp, descending) {
      return toBoolean(descending)
          ? function(a,b){return comp(b,a);}
          : comp;
    }
    function compare(v1, v2){
      var t1 = typeof v1;
      var t2 = typeof v2;
      if (t1 == t2) {
        if (t1 == "string") {
           v1 = v1.toLowerCase();
           v2 = v2.toLowerCase();
        }
        if (v1 === v2) return 0;
        return v1 < v2 ? -1 : 1;
      } else {
        return t1 < t2 ? -1 : 1;
      }
    }
  };
}
<|endoftext|>