<commit_before>var MapMoveEvents = function(leafletMap) {

    var _eventType = [
        "move",
        "movestart",
        "moveend",
        "drag",
        "dragstart",
        "dragend",
        "pan",
        "panstart",
        "panend",
        "rotate",
        "rotatestart",
        "rotateend",
        "tilt",
        "tiltstart",
        "tiltend",
        "zoomstart",
        "zoomend"
    ];

    var _onEvent = function(eventKey) {
        leafletMap.fire(_eventType[eventKey]);
    };

    this.setEventCallbacks = function(cameraApi) {
        cameraApi.setEventCallback(_onEvent);
    };
};
module.exports = MapMoveEvents;<commit_msg>Checking the Camera event type has been defined before firing the event.<commit_after>var MapMoveEvents = function(leafletMap) {

    var _eventType = [
        "move",
        "movestart",
        "moveend",
        "drag",
        "dragstart",
        "dragend",
        "pan",
        "panstart",
        "panend",
        "rotate",
        "rotatestart",
        "rotateend",
        "tilt",
        "tiltstart",
        "tiltend",
        "zoomstart",
        "zoomend"
    ];

    var _onEvent = function(eventKey) {
        if (typeof _eventType[eventKey] === undefined) {
            return;
        }
        leafletMap.fire(_eventType[eventKey]);
    };

    this.setEventCallbacks = function(cameraApi) {
        cameraApi.setEventCallback(_onEvent);
    };
};
module.exports = MapMoveEvents;<|endoftext|>


<commit_before>
export default class GA {

    constructor(trackingCode){
        window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date
        ga('create', trackingCode, 'auto')
    }

    send(location){
        ga('send', {
            hitType: 'pageview',
            page: location.pathname+location.search,
            location: window.location.origin + location.pathname,
            title: document.title
        })
    }
}

<commit_msg>edit ga pageview data<commit_after>
export default class GA {

    constructor(trackingCode){
        window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date
        ga('create', trackingCode, 'auto')
    }

    send(location){
        ga('send', {
            hitType: 'pageview'
        })
    }
}

<|endoftext|>


<commit_before>(function() {

var $ = jQuery; // Handle namespaced jQuery

// DocumentCloud workspace hotkeys. To tell if a key is currently being pressed,
// just ask `VS.app.hotkeys.[key]` on `keypress`, or ask `VS.app.hotkeys.key(e)`
// on `keydown`.
//
// For the most headache-free way to use this utility, check modifier keys,
// like shift and command, with `VS.app.hotkeys.shift`, and check every other
// key with `VS.app.hotkeys.key(e) == 'key_name'`.
VS.app.hotkeys = {

  // Keys that will be mapped to the `hotkeys` namespace.
  KEYS: {
    '16':  'shift',
    '17':  'command',
    '91':  'command',
    '93':  'command',
    '224': 'command',
    '13':  'enter',
    '37':  'left',
    '38':  'upArrow',
    '39':  'right',
    '40':  'downArrow',
    '46':  'delete',
    '8':   'backspace',
    '9':   'tab',
    '188': 'comma'
  },

  // Binds global keydown and keyup events to listen for keys that match `this.KEYS`.
  initialize : function() {
    _.bindAll(this, 'down', 'up', 'blur');
    $(document).bind('keydown', this.down);
    $(document).bind('keyup', this.up);
    // $(window).bind('blur', this.blur);
  },

  // On `keydown`, turn on all keys that match.
  down : function(e) {
    var key = this.KEYS[e.which];
    if (key) this[key] = true;
  },

  // On `keyup`, turn off all keys that match.
  up : function(e) {
    var key = this.KEYS[e.which];
    if (key) this[key] = false;
  },

  // If an input is blurred, all keys need to be turned off, since they are no longer
  // able to modify the document.
  blur : function(e) {
    for (var key in this.KEYS) this[this.KEYS[key]] = false;
  },

  // Check a key from an event and return the common english name.
  key : function(e) {
    return this.KEYS[e.which];
  },

  // Colon is special, since the value is different between browsers.
  colon : function(e) {
    var charCode = e.which;
    return charCode && String.fromCharCode(charCode) == ":";
  },

  // Check a key from an event and match it against any known characters.
  // The `keyCode` is different depending on the event type: `keydown` vs. `keypress`.
  //
  // These were determined by looping through every `keyCode` and `charCode` that
  // resulted from `keydown` and `keypress` events and counting what was printable.
  printable : function(e) {
    var code = e.which;
    if (e.type == 'keydown') {
      if (code == 32 ||                      // space
          (code >= 48 && code <= 90) ||      // 0-1a-z
          (code >= 96 && code <= 111) ||     // 0-9+-/*.
          (code >= 186 && code <= 192) ||    // ;=,-./^
          (code >= 219 && code <= 222)) {    // (\)'
        return true;
      }
    } else {
      // [space]!"#$%&'()*+,-.0-9:;<=>?@A-Z[\]^_`a-z{|} and unicode characters
      if ((code >= 32 && code <= 126)  ||
          (code >= 160 && code <= 500) ||
          (String.fromCharCode(code) == ":")) {
        return true;
      }
    }
    return false;
  }

};

})();<commit_msg>uncommenting important hotkeys.js blur function.<commit_after>(function() {

var $ = jQuery; // Handle namespaced jQuery

// DocumentCloud workspace hotkeys. To tell if a key is currently being pressed,
// just ask `VS.app.hotkeys.[key]` on `keypress`, or ask `VS.app.hotkeys.key(e)`
// on `keydown`.
//
// For the most headache-free way to use this utility, check modifier keys,
// like shift and command, with `VS.app.hotkeys.shift`, and check every other
// key with `VS.app.hotkeys.key(e) == 'key_name'`.
VS.app.hotkeys = {

  // Keys that will be mapped to the `hotkeys` namespace.
  KEYS: {
    '16':  'shift',
    '17':  'command',
    '91':  'command',
    '93':  'command',
    '224': 'command',
    '13':  'enter',
    '37':  'left',
    '38':  'upArrow',
    '39':  'right',
    '40':  'downArrow',
    '46':  'delete',
    '8':   'backspace',
    '9':   'tab',
    '188': 'comma'
  },

  // Binds global keydown and keyup events to listen for keys that match `this.KEYS`.
  initialize : function() {
    _.bindAll(this, 'down', 'up', 'blur');
    $(document).bind('keydown', this.down);
    $(document).bind('keyup', this.up);
    $(window).bind('blur', this.blur);
  },

  // On `keydown`, turn on all keys that match.
  down : function(e) {
    var key = this.KEYS[e.which];
    if (key) this[key] = true;
  },

  // On `keyup`, turn off all keys that match.
  up : function(e) {
    var key = this.KEYS[e.which];
    if (key) this[key] = false;
  },

  // If an input is blurred, all keys need to be turned off, since they are no longer
  // able to modify the document.
  blur : function(e) {
    for (var key in this.KEYS) this[this.KEYS[key]] = false;
  },

  // Check a key from an event and return the common english name.
  key : function(e) {
    return this.KEYS[e.which];
  },

  // Colon is special, since the value is different between browsers.
  colon : function(e) {
    var charCode = e.which;
    return charCode && String.fromCharCode(charCode) == ":";
  },

  // Check a key from an event and match it against any known characters.
  // The `keyCode` is different depending on the event type: `keydown` vs. `keypress`.
  //
  // These were determined by looping through every `keyCode` and `charCode` that
  // resulted from `keydown` and `keypress` events and counting what was printable.
  printable : function(e) {
    var code = e.which;
    if (e.type == 'keydown') {
      if (code == 32 ||                      // space
          (code >= 48 && code <= 90) ||      // 0-1a-z
          (code >= 96 && code <= 111) ||     // 0-9+-/*.
          (code >= 186 && code <= 192) ||    // ;=,-./^
          (code >= 219 && code <= 222)) {    // (\)'
        return true;
      }
    } else {
      // [space]!"#$%&'()*+,-.0-9:;<=>?@A-Z[\]^_`a-z{|} and unicode characters
      if ((code >= 32 && code <= 126)  ||
          (code >= 160 && code <= 500) ||
          (String.fromCharCode(code) == ":")) {
        return true;
      }
    }
    return false;
  }

};

})();<|endoftext|>


<commit_before>/**
Definition of the HandlebarsGenerator class.
@license MIT. See LICENSE.md for details.
@module handlebars-generator.js
*/

(function() {

  var _ = require('underscore')
    , HANDLEBARS = require('handlebars')
    , FS = require('fs')
    , registerHelpers = require('../helpers/handlebars-helpers')
    , PATH = require('path')
    , parsePath = require('parse-filepath')
    , READFILES = require('recursive-readdir-sync')
    , SLASH = require('slash');

  /**
  Perform template-based resume generation using Handlebars.js.
  @class HandlebarsGenerator
  */
  var HandlebarsGenerator = module.exports = {

    generate: function( json, jst, format, cssInfo, opts, theme ) {

      registerPartials( format, theme );
      registerHelpers( theme );

      // Preprocess text
      var encData = json;
      ( format === 'html' || format === 'pdf' ) && (encData = json.markdownify());
      ( format === 'doc' ) && (encData = json.xmlify());

      // Compile and run the Handlebars template.
      var template = HANDLEBARS.compile(jst, { strict: false, assumeObjects: false });
      return template({
        r: encData,
        RAW: json,
        filt: opts.filters,
        cssInfo: cssInfo,
        format: format,
        opts: opts,
        headFragment: opts.headFragment || ''
      });

    }

  };

  function registerPartials(format, theme) {
    if( format === 'html' || format === 'doc' || format == 'md' ) {

      // Locate the global partials folder
      var partialsFolder = PATH.join(
        parsePath( require.resolve('fresh-themes') ).dirname,
        '/partials/',
        format
      );

      // Register global partials in the /partials/[format] folder
      // TODO: Only do this once per HMR invocation.
      _.each( READFILES( partialsFolder, function(error){ }), function( el ) {
        var pathInfo = parsePath( el );
        var name = SLASH( PATH.relative( partialsFolder, el )
          .replace(/\.(?:html|xml|hbs|md|txt)$/i, '') );
        var tplData = FS.readFileSync( el, 'utf8' );
        var compiledTemplate = HANDLEBARS.compile( tplData );
        HANDLEBARS.registerPartial( name, compiledTemplate );
        theme.partialsInitialized = true;
      });

    }

    // Register theme-specific partials
    _.each( theme.partials, function( el ) {
      var tplData = FS.readFileSync( el.path, 'utf8' );
      var compiledTemplate = HANDLEBARS.compile( tplData );
      HANDLEBARS.registerPartial( el.name, compiledTemplate );
    });
  }

}());
<commit_msg>Process TXT global partials.<commit_after>/**
Definition of the HandlebarsGenerator class.
@license MIT. See LICENSE.md for details.
@module handlebars-generator.js
*/

(function() {

  var _ = require('underscore')
    , HANDLEBARS = require('handlebars')
    , FS = require('fs')
    , registerHelpers = require('../helpers/handlebars-helpers')
    , PATH = require('path')
    , parsePath = require('parse-filepath')
    , READFILES = require('recursive-readdir-sync')
    , SLASH = require('slash');

  /**
  Perform template-based resume generation using Handlebars.js.
  @class HandlebarsGenerator
  */
  var HandlebarsGenerator = module.exports = {

    generate: function( json, jst, format, cssInfo, opts, theme ) {

      registerPartials( format, theme );
      registerHelpers( theme );

      // Preprocess text
      var encData = json;
      ( format === 'html' || format === 'pdf' ) && (encData = json.markdownify());
      ( format === 'doc' ) && (encData = json.xmlify());

      // Compile and run the Handlebars template.
      var template = HANDLEBARS.compile(jst, { strict: false, assumeObjects: false });
      return template({
        r: encData,
        RAW: json,
        filt: opts.filters,
        cssInfo: cssInfo,
        format: format,
        opts: opts,
        headFragment: opts.headFragment || ''
      });

    }

  };

  function registerPartials(format, theme) {
    if( _.contains( ['html','doc','md','txt'], format )) {

      // Locate the global partials folder
      var partialsFolder = PATH.join(
        parsePath( require.resolve('fresh-themes') ).dirname,
        '/partials/',
        format
      );

      // Register global partials in the /partials/[format] folder
      // TODO: Only do this once per HMR invocation.
      _.each( READFILES( partialsFolder, function(error){ }), function( el ) {
        var pathInfo = parsePath( el );
        var name = SLASH( PATH.relative( partialsFolder, el )
          .replace(/\.(?:html|xml|hbs|md|txt)$/i, '') );
        var tplData = FS.readFileSync( el, 'utf8' );
        var compiledTemplate = HANDLEBARS.compile( tplData );
        HANDLEBARS.registerPartial( name, compiledTemplate );
        theme.partialsInitialized = true;
      });

    }

    // Register theme-specific partials
    _.each( theme.partials, function( el ) {
      var tplData = FS.readFileSync( el.path, 'utf8' );
      var compiledTemplate = HANDLEBARS.compile( tplData );
      HANDLEBARS.registerPartial( el.name, compiledTemplate );
    });
  }

}());
<|endoftext|>


<commit_before>'use babel'

import * as _ from 'lodash'
import * as path from 'path'
import * as helper from 'atom-linter'
import * as likelySubtags from './likely-subtags'
var tags = require('language-tags')
import { Disposable, Emitter, CompositeDisposable } from 'atom'
import Spell from './spell'

export default class LanguageManager extends Disposable {

  constructor () {
    super(() => {
      this.disposables.dispose()
      this.checkers = new Map()
    })
    this.disposables = new CompositeDisposable()
    this.checkers = new Map()
    this.systemLanguages = ['en-US']
    require('os-locale')((err, locale) => {
      if (!err) {
        this.systemLanguages = [tags(locale.replace(/_/g, '-')).format()]
      }
    })
    this.emitter = new Emitter()
    this.disposables.add(this.emitter)
    this.dictionaries = new Map()
    this.languages = new Map()
    atom.config.onDidChange('linter-spell.spellPath', () => {
      this.checkers = new Map()
      this.updateDictionaries()
    })
    atom.config.onDidChange('linter-spell.defaultLanguages', () => {
      this.updateConfigLanguages()
    })
    this.updateDictionaries()
    this.updateConfigLanguages()
  }

  getAvailableLanguages () {
    let l = []
    for (const lang of this.dictionaries.keys()) {
      l.push(lang.replace(/-\*/g, ''))
    }
    l.sort()
    return l
  }

  getChecker (languages) {
    let id = languages.join()
    if (this.checkers.has(id)) return this.checkers.get(id)

    let checker = new Spell(languages)
    this.disposables.add(checker)
    this.checkers.set(id, checker)
    checker.onError(err => {
      console.error(err)
      if (this.checkers.has(id)) {
        this.checkers.delete(id)
        atom.notifications.addError(
          'Spell Checker Communication Error',
          { detail: `Unable to communicate with spell checker. Please verify your settings of linter-spell.\n${err}` })
      }
    })
    return checker
  }

  updateConfigLanguages () {
    this.configLanguages = atom.config.get('linter-spell.defaultLanguages')
    if (this.configLanguages.length === 0) {
      this.configLanguages = null
    }
  }

  parse (name) {
    let parts = name.split(/[-_]/)
    let i = 0
    let lang = []
    for (const type of ['language', 'extlang', 'script', 'region', 'variant']) {
      if (i < parts.length) {
        lang.push((tags.type(parts[i], type) && (type !== 'region' || parts[i].match(/^[A-Z]+$/))) ? parts[i++] : '*')
      }
    }
    return _.dropRightWhile(lang, p => p === '*').join('-') || '*'
  }

  maximizeRank (tag) {
    let rank = 0
    let value
    for (const entry of this.dictionaries.entries()) {
      const newRank = this.rank(entry[0], tag)
      if (newRank > rank) {
        rank = newRank
        value = entry
      }
    }
    return value
  }

  onDidChangeLanguages (callback) {
    return this.emitter.on('change-languages', callback)
  }

  getLanguages (textEditor, type) {
    let l = this.languages.get(textEditor)
    if (!l) {
      global.grammarManager.updateLanguage(textEditor)
      l = this.languages.get(textEditor)
      if (!l) {
        if (global.grammarManager.getGrammar(textEditor)) {
          this.languages.set(textEditor, l = {})
        } else {
          return
        }
      }
    }
    return type ? l[type] : (l.manual || l.auto || this.configLanguages || this.systemLanguages)
  }

  setLanguages (textEditor, languages, type) {
    let l = this.languages.get(textEditor) || {}
    l[type] = languages
    this.languages.set(textEditor, l)
    this.emitter.emit('change-languages', null)
  }

  resolve (languages, notify) {
    let d = []
    for (const language of languages) {
      const fallback = likelySubtags[language]
      let dict = this.maximizeRank(language)
      if (fallback) dict = dict || this.maximizeRank(fallback)
      if (dict) {
        d.push(dict)
      } else if (notify) {
        atom.notifications.addWarning(
          'Missing Dictionary', {
            detail: `Unable to find a dictionary for language ${language}${fallback ? ' with fallback ' + fallback : ''}.`
          })
      }
    }
    return d
  }

  resolveDictionaries (languages) {
    return _.map(this.resolve(languages, true), entry => entry[1])
  }

  resolveLanguages (languages) {
    return _.map(this.resolve(languages, false), entry => entry[0].replace(/-\*/g, ''))
  }

  addDictionary (name) {
    const lang = this.parse(name)
    if (lang !== '*' && (!this.dictionaries.has(lang) || name < this.dictionaries.get(lang))) {
      this.dictionaries.set(lang, name)
    }
  }

  async updateDictionaries () {
    const spellPath = atom.config.get('linter-spell.spellPath')
    const ispell = path.parse(spellPath).name.toLowerCase()
    let output = ''
    this.dictionaries.clear()
    switch (ispell) {
      case 'aspell':
        output = await helper.exec(spellPath, ['dicts'], { stream: 'stdout' })
        for (const line of output.split(/[\r\n]+/g)) {
          this.addDictionary(line)
        }
        break
      case 'hunspell':
        output = await helper.exec(spellPath, ['-D'], { stream: 'stderr', stdin: '', throwOnStdErr: false })
        let save = false
        for (const line of output.split(/[\r\n]+/g)) {
          if (line.match(/AVAILABLE DICTIONARIES/)) {
            save = true
          } else if (line.match(/:$/)) {
            save = false
          } else if (save) {
            this.addDictionary(path.basename(line))
          }
        }
        break
    }
    this.emitter.emit('change-languages', null)
  }

  rank (range, tag) {
    // From https://tools.ietf.org/html/rfc4647
    range = range.toLowerCase().split(/[-_]/)
    tag = tag.toLowerCase().split(/[-_]/)
    let rank = 1
    // Split both the extended language range and the language tag being
    // compared into a list of subtags by dividing on the hyphen (%x2D)
    // character.  Two subtags match if either they are the same when
    // compared case-insensitively or the language range's subtag is the
    // wildcard '*'.

    // Begin with the first subtag in each list.  If the first subtag in
    // the range does not match the first subtag in the tag, the overall
    // match fails.  Otherwise, move to the next subtag in both the
    // range and the tag.
    if (range[0] !== '*' && range[0] !== tag[0]) {
      return 0
    }

    // While there are more subtags left in the language range's list:
    for (let i = 1, j = 1; i < range.length;) {
      if (range[i] === '*') {
        // If the subtag currently being examined in the range is the
        // wildcard ('*'), move to the next subtag in the range and
        // continue with the loop.
        i++
      } else if (j >= tag.length) {
        // Else, if there are no more subtags in the language tag's
        // list, the match fails.
        return 0
      } else if (range[i] === '*' || range[i] === tag[j]) {
        // Else, if the current subtag in the range's list matches the
        // current subtag in the language tag's list, move to the next
        // subtag in both lists and continue with the loop.
        if (range[i] !== '*') rank += Math.pow(2, i)
        i++
        j++
      } else if (tag[j].length === 1) {
        // Else, if the language tag's subtag is a "singleton" (a single
        // letter or digit, which includes the private-use subtag 'x')
        // the match fails.
        return 0
      } else {
        // Else, move to the next subtag in the language tag's list and
        // continue with the loop.
        j++
      }
    }

    return rank
  }

}
<commit_msg>Fix dictionary scan in translated hunspell<commit_after>'use babel'

import * as _ from 'lodash'
import * as path from 'path'
import * as helper from 'atom-linter'
import * as likelySubtags from './likely-subtags'
var tags = require('language-tags')
import { Disposable, Emitter, CompositeDisposable } from 'atom'
import Spell from './spell'

export default class LanguageManager extends Disposable {

  constructor () {
    super(() => {
      this.disposables.dispose()
      this.checkers = new Map()
    })
    this.disposables = new CompositeDisposable()
    this.checkers = new Map()
    this.systemLanguages = ['en-US']
    require('os-locale')((err, locale) => {
      if (!err) {
        this.systemLanguages = [tags(locale.replace(/_/g, '-')).format()]
      }
    })
    this.emitter = new Emitter()
    this.disposables.add(this.emitter)
    this.dictionaries = new Map()
    this.languages = new Map()
    atom.config.onDidChange('linter-spell.spellPath', () => {
      this.checkers = new Map()
      this.updateDictionaries()
    })
    atom.config.onDidChange('linter-spell.defaultLanguages', () => {
      this.updateConfigLanguages()
    })
    this.updateDictionaries()
    this.updateConfigLanguages()
  }

  getAvailableLanguages () {
    let l = []
    for (const lang of this.dictionaries.keys()) {
      l.push(lang.replace(/-\*/g, ''))
    }
    l.sort()
    return l
  }

  getChecker (languages) {
    let id = languages.join()
    if (this.checkers.has(id)) return this.checkers.get(id)

    let checker = new Spell(languages)
    this.disposables.add(checker)
    this.checkers.set(id, checker)
    checker.onError(err => {
      console.error(err)
      if (this.checkers.has(id)) {
        this.checkers.delete(id)
        atom.notifications.addError(
          'Spell Checker Communication Error',
          { detail: `Unable to communicate with spell checker. Please verify your settings of linter-spell.\n${err}` })
      }
    })
    return checker
  }

  updateConfigLanguages () {
    this.configLanguages = atom.config.get('linter-spell.defaultLanguages')
    if (this.configLanguages.length === 0) {
      this.configLanguages = null
    }
  }

  parse (name) {
    let parts = name.split(/[-_]/)
    let i = 0
    let lang = []
    for (const type of ['language', 'extlang', 'script', 'region', 'variant']) {
      if (i < parts.length) {
        lang.push((tags.type(parts[i], type) && (type !== 'region' || parts[i].match(/^[A-Z]+$/))) ? parts[i++] : '*')
      }
    }
    return _.dropRightWhile(lang, p => p === '*').join('-') || '*'
  }

  maximizeRank (tag) {
    let rank = 0
    let value
    for (const entry of this.dictionaries.entries()) {
      const newRank = this.rank(entry[0], tag)
      if (newRank > rank) {
        rank = newRank
        value = entry
      }
    }
    return value
  }

  onDidChangeLanguages (callback) {
    return this.emitter.on('change-languages', callback)
  }

  getLanguages (textEditor, type) {
    let l = this.languages.get(textEditor)
    if (!l) {
      global.grammarManager.updateLanguage(textEditor)
      l = this.languages.get(textEditor)
      if (!l) {
        if (global.grammarManager.getGrammar(textEditor)) {
          this.languages.set(textEditor, l = {})
        } else {
          return
        }
      }
    }
    return type ? l[type] : (l.manual || l.auto || this.configLanguages || this.systemLanguages)
  }

  setLanguages (textEditor, languages, type) {
    let l = this.languages.get(textEditor) || {}
    l[type] = languages
    this.languages.set(textEditor, l)
    this.emitter.emit('change-languages', null)
  }

  resolve (languages, notify) {
    let d = []
    for (const language of languages) {
      const fallback = likelySubtags[language]
      let dict = this.maximizeRank(language)
      if (fallback) dict = dict || this.maximizeRank(fallback)
      if (dict) {
        d.push(dict)
      } else if (notify) {
        atom.notifications.addWarning(
          'Missing Dictionary', {
            detail: `Unable to find a dictionary for language ${language}${fallback ? ' with fallback ' + fallback : ''}.`
          })
      }
    }
    return d
  }

  resolveDictionaries (languages) {
    return _.map(this.resolve(languages, true), entry => entry[1])
  }

  resolveLanguages (languages) {
    return _.map(this.resolve(languages, false), entry => entry[0].replace(/-\*/g, ''))
  }

  addDictionary (name) {
    const lang = this.parse(name)
    if (lang !== '*' && (!this.dictionaries.has(lang) || name < this.dictionaries.get(lang))) {
      this.dictionaries.set(lang, name)
    }
  }

  async updateDictionaries () {
    const spellPath = atom.config.get('linter-spell.spellPath')
    const ispell = path.parse(spellPath).name.toLowerCase()
    let output = ''
    this.dictionaries.clear()
    switch (ispell) {
      case 'aspell':
        output = await helper.exec(spellPath, ['dicts'], { stream: 'stdout' })
        for (const line of output.split(/[\r\n]+/g)) {
          this.addDictionary(line)
        }
        break
      case 'hunspell':
        output = await helper.exec(spellPath, ['-D'], { stream: 'stderr', stdin: '', throwOnStdErr: false })
        let save = false
        for (const line of output.split(/[\r\n]+/g)) {
          if (line.match(/-d.*:$/)) {
            save = true
          } else if (line.match(/:$/)) {
            save = false
          } else if (save) {
            this.addDictionary(path.basename(line))
          }
        }
        break
    }
    this.emitter.emit('change-languages', null)
  }

  rank (range, tag) {
    // From https://tools.ietf.org/html/rfc4647
    range = range.toLowerCase().split(/[-_]/)
    tag = tag.toLowerCase().split(/[-_]/)
    let rank = 1
    // Split both the extended language range and the language tag being
    // compared into a list of subtags by dividing on the hyphen (%x2D)
    // character.  Two subtags match if either they are the same when
    // compared case-insensitively or the language range's subtag is the
    // wildcard '*'.

    // Begin with the first subtag in each list.  If the first subtag in
    // the range does not match the first subtag in the tag, the overall
    // match fails.  Otherwise, move to the next subtag in both the
    // range and the tag.
    if (range[0] !== '*' && range[0] !== tag[0]) {
      return 0
    }

    // While there are more subtags left in the language range's list:
    for (let i = 1, j = 1; i < range.length;) {
      if (range[i] === '*') {
        // If the subtag currently being examined in the range is the
        // wildcard ('*'), move to the next subtag in the range and
        // continue with the loop.
        i++
      } else if (j >= tag.length) {
        // Else, if there are no more subtags in the language tag's
        // list, the match fails.
        return 0
      } else if (range[i] === '*' || range[i] === tag[j]) {
        // Else, if the current subtag in the range's list matches the
        // current subtag in the language tag's list, move to the next
        // subtag in both lists and continue with the loop.
        if (range[i] !== '*') rank += Math.pow(2, i)
        i++
        j++
      } else if (tag[j].length === 1) {
        // Else, if the language tag's subtag is a "singleton" (a single
        // letter or digit, which includes the private-use subtag 'x')
        // the match fails.
        return 0
      } else {
        // Else, move to the next subtag in the language tag's list and
        // continue with the loop.
        j++
      }
    }

    return rank
  }

}
<|endoftext|>


<commit_before>import Scanner from "./scanner";
import Token from "./token";

const punctuators = [
	".", "#", "^", "/", "@", ">", "<", "+",
	"?", ":", "=", "|", "~", "%", "[", "]"
];

export default function scanPunctuator (scanner: Scanner): ?Token {
	if (punctuators.indexOf(scanner.char) === -1) {
		return;
	}

	const token = new Token(Token.Punctuator, scanner.char);
	token.configure(scanner);

	return token;
}
<commit_msg>Add missing @flow<commit_after>// @flow

import Scanner from "./scanner";
import Token from "./token";

const punctuators = [
	".", "#", "^", "/", "@", ">", "<", "+",
	"?", ":", "=", "|", "~", "%", "[", "]"
];

export default function scanPunctuator (scanner: Scanner): ?Token {
	if (punctuators.indexOf(scanner.char) === -1) {
		return;
	}

	const token = new Token(Token.Punctuator, scanner.char);
	token.configure(scanner);

	return token;
}
<|endoftext|>


<commit_before>'use babel'

import {Emitter, CompositeDisposable} from 'atom'

const Validate = require('./validate')
const Helpers = require('./helpers')

export default class MessageRegistry {
  constructor() {
    this.active = true
    this.subscriptions = new CompositeDisposable()
    this.emitter = new Emitter()

    // Map<EditorLinter | null, Map<Linter, array<Message>>>
    this.messages = new Map()
    this.queue = []

    this.subscriptions.add(this.emitter)
    this.subscriptions.add(atom.config.observe('linter.ignoredMessageTypes', ignoredMessageTypes => {
      this.ignoredMessageTypes = new Set(ignoredMessageTypes)
    }))

    const UpdateMessages = () => {
      if (this.active) {
        if (this.queue.length) {
          this.processQueue()
        }
        Helpers.requestUpdateFrame(UpdateMessages)
      }
    }
    UpdateMessages()
  }
  set({linter, messages, editor = null}) {
    // Do not set messages if the linter is deactivated
    if (linter.deactivated) {
      return
    }

    // Validate messages
    try {
      Validate.messages(messages, linter)
    } catch (e) {
      return Helpers.error(e)
    }

    // Filter ignored ones
    if (this.ignoredMessageTypes.size) {
      messages = messages.filter(i => !this.ignoredMessageTypes.has(i.type))
    }

    this.queue.push({messages, linter, editor})
  }
  processQueue() {
    let added = []
    let removed = []

    this.queue.forEach(({messages, linter, editor}) => {
      let foundChange = false

      const lastMessages = this.getMessages(linter, editor)
      const currentMessages = new Map()

      if (lastMessages.size === 0) {
        added = messages
      } else {
        messages.forEach(function(message) {
          if (!lastMessages.has(message.key)) {
            foundChange = true
            added.push(message)
          }
          currentMessages.set(message.key, message)
        })

        if (!foundChange && messages.length === lastMessages.size) {
          // Nothing has changed here, no need to look for removed message
        } else {
          lastMessages.forEach(function(_, key) {
            if (!currentMessages.has(key)) {
              foundChange = true
              removed.push(lastMessages.get(key))
            }
          })
        }
      }

      if (foundChange) {
        this.setMessages(linter, editor, messages)
      }
    })

    if (added.length || removed.length) {
      const getAllMessages = () => this.getAllMessages()
      this.emitter.emit('did-update-messages', {added, removed, get messages() {
        return getAllMessages()
      }})
    }
  }
  getAllMessages() {
    let messages = []
    this.messages.forEach(function(bufferMessages) {
      bufferMessages.forEach(function(linterMessages) {
        messages = messages.concat(linterMessages)
      })
    })
    return messages
  }
  getMessages(linter, editor) {
    const bufferMessages = this.messages.get(editor)
    return (bufferMessages ? bufferMessages.get(linter) : undefined) || new Map()
  }
  setMessages(linter, editor, messages) {
    let bufferMessages = this.messages.get(editor)

    if (!bufferMessages) {
      this.messages.set(editor, bufferMessages = new Map())
    }
    bufferMessages.set(linter, messages)
  }
  onDidUpdateMessages(callback) {
    return this.emitter.on('did-update-messages', callback)
  }
  deleteMessages(linter) {
    // TODO
  }
  deleteEditorMessages(editorLinter) {
    // TODO
  }
  dispose() {
    this.active = false
    this.subscriptions.dispose()
    this.messages.clear()
    this.queue = []
  }
}
<commit_msg>:new: Make new queue implementation more stable<commit_after>'use babel'

import {Emitter, CompositeDisposable} from 'atom'

const Validate = require('./validate')
const Helpers = require('./helpers')

export default class MessageRegistry {
  constructor() {
    this.active = true
    this.subscriptions = new CompositeDisposable()
    this.emitter = new Emitter()

    // Map<EditorLinter | null, Map<Linter, array<Message>>>
    this.messages = new Map()
    this.queue = []

    this.subscriptions.add(this.emitter)
    this.subscriptions.add(atom.config.observe('linter.ignoredMessageTypes', ignoredMessageTypes => {
      this.ignoredMessageTypes = new Set(ignoredMessageTypes)
    }))

    const UpdateMessages = () => {
      if (this.active) {
        if (this.queue.length) {
          this.processQueue()
        }
        Helpers.requestUpdateFrame(UpdateMessages)
      }
    }
    UpdateMessages()
  }
  set({linter, messages, editor = null}) {
    // Do not set messages if the linter is deactivated
    if (linter.deactivated) {
      return
    }

    // Validate messages
    try {
      Validate.messages(messages, linter)
    } catch (e) {
      return Helpers.error(e)
    }

    // Filter ignored ones
    if (this.ignoredMessageTypes.size) {
      messages = messages.filter(i => !this.ignoredMessageTypes.has(i.type))
    }

    this.queue.push({messages, linter, editor})
  }
  processQueue() {
    let added = []
    let removed = []

    this.queue.forEach(({messages, linter, editor}) => {
      let foundNew = false
      let foundChange = false

      const lastMessages = this.getMessages(linter, editor)
      const currentMessages = new Map()

      if (lastMessages.size === 0) {
        added = messages
        messages.forEach(function(message) {
          currentMessages.set(message.key, message)
        })
        foundNew = true
      } else {
        messages.forEach(function(message) {
          if (!lastMessages.has(message.key)) {
            foundChange = true
            added.push(message)
          }
          currentMessages.set(message.key, message)
        })

        if (!foundChange && messages.length === lastMessages.size) {
          // Nothing has changed here, no need to look for removed message
        } else {
          lastMessages.forEach(function(_, key) {
            if (!currentMessages.has(key)) {
              foundChange = true
              removed.push(lastMessages.get(key))
            }
          })
        }
      }

      if (foundChange || foundNew) {
        this.setMessages(linter, editor, currentMessages)
      }
    })

    if (added.length || removed.length) {
      const getAllMessages = () => this.getAllMessages()
      this.emitter.emit('did-update-messages', {added, removed, get messages() {
        return getAllMessages()
      }})
    }
  }
  getAllMessages() {
    let messages = []
    this.messages.forEach(function(bufferMessages) {
      bufferMessages.forEach(function(linterMessages) {
        linterMessages.forEach(function(message) {
          messages.push(message)
        })
      })
    })
    return messages
  }
  getMessages(linter, editor) {
    const bufferMessages = this.messages.get(editor)
    return (bufferMessages ? bufferMessages.get(linter) : undefined) || new Map()
  }
  setMessages(linter, editor, messages) {
    let bufferMessages = this.messages.get(editor)

    if (!bufferMessages) {
      this.messages.set(editor, bufferMessages = new Map())
    }
    bufferMessages.set(linter, messages)
  }
  onDidUpdateMessages(callback) {
    return this.emitter.on('did-update-messages', callback)
  }
  deleteMessages(linter) {
    // TODO
  }
  deleteEditorMessages(editorLinter) {
    // TODO
  }
  dispose() {
    this.active = false
    this.subscriptions.dispose()
    this.messages.clear()
    this.queue = []
  }
}
<|endoftext|>


<commit_before>var uri = require('url')
  , State = require('../state')
  , dispatch = require('../utils').dispatch
  , swizzleRedirect = require('../utils/swizzle-redirect')
  , swizzleRender = require('../utils/swizzle-render')
  , swizzleEnd = require('../utils/swizzle-end')
  , flatten = require('utils-flatten')
  , merge = require('utils-merge')
  , utils = require('../utils')
  , debug = require('debug')('flowstate')
  , SessionStore = require('../stores/session');

  // TIPS: Generally, push a state before redirecting (unless wizard style
  //  alternatively, handler can lazily push, for its own state, to preserve storage
  //  which could be done based on the presence of a returnTo (which is not the handlers URL)

/**
 * Load state.
 *
 * This middleware is used to load state associated with a request.  The state
 * will be made available at `req.state`.
 *
 * HTTP is a stateless protocol.  In order to support stateful interactions, the
 * client and server need to operate in coordination.  The server is responsible
 * for persisting state associated with a request.  The client is responsible for
 * indicating that state in subsequent requests to the server (via a `state`
 * parameter in the query or body, by default).  The server then loads the
 * previously persisted state in order to continue processing the transaction.
 *
 * Options:
 *
 *     name   set req.state only if the state name is equal to the option value
 *     required   require state, failing otherwise (default: false)
 *
 * Examples:
 *
 *     app.get('/login',
 *       flowstate.loadState(),
 *       function(req, res, next) {
 *         res.locals.failureCount = req.state.failureCount;
 *         res.render('login');
 *       });
 *
 *     app.get('/login/callback',
 *       flowstate.loadState({ name: 'oauth2-redirect', required: true }),
 *       function(req, res, next) {
 *         // ...
 *       });
 *
 * @return {Function}
 * @api public
 */
module.exports = function(options) {
  options = options || {}

  var store = options.store || new SessionStore(options);
  var getHandle = options.getHandle || function(req) {
    return (req.query && req.query.state) || (req.body && req.body.state);
  }

  var mutationMethods = options.mutationMethods === undefined
    ? ['POST', 'PUT', 'PATCH', 'DELETE']
    : options.mutationMethods

  // WIP: On state init, set `resume` if the state is not intended for this lcoation

  // TODO: add a "locations" option, with relative paths that will be added to location

  return function state(req, res, next) {
    // self-awareness
    if (req.state) { return next(); }

    // expose store
    req.stateStore = store;

    res.pushState = function(state, url, end) {
      end = end !== undefined ? end : true;

      // WIP: Test case where this is a relative URL
      state.location = uri.resolve(utils.originalURL(req), url);
      req.state.push(state);
      end && this.redirect(url);
    }

    res.resumeState = function(yields, cb) {
      if (typeof yields == 'function') {
        cb = yields;
        yields = undefined;
      }

      req.state.complete();

      if (req.state.returnTo) {
        // TODO: underscore the parameters, adn redirect with query
        this.redirect(req.state.returnTo);
      } else if (req.state.resumeState) {
        var self = this;

        req.state.destroy(function(err) {
          if (err) { return cb(err); } // FIXME: this should be next?

          store.load(req, req.state.resumeState, function(err, data) {
            if (err) { return cb(err); }  // FIXME: this should be next?

            // WIP: Need a state stack to traverse to do destroy on res.render/res.redirect

            var state = new State(req, data, req.state.resumeState);
            merge(state, yields);

            // TODO: This can be short-circuited to alway save, and optimize in there
            if (!state.isModified()) {
              self.redirect(data.location + '?state=' + state.handle);
            } else {
              state.save(function(err) {
                if (err) { return cb(err); }
                self.redirect(state.location + '?state=' + state.handle);
              });
            }
          });
        });
      } else {
        cb();
      }
    }

    // swizzle redirect to commit the state
    swizzleRedirect(res, function commitState(url, cb) {
      debug('redirect %s, %O (handle: %s, modified: %o, saved: %o, complete: %o, new: %o)', url, req.state,
        req.state.handle, req.state.isModified(), req.state.isSaved(), req.state.isComplete(), req.state.isNew());

      function proceed(v) {
        if (!v) { return cb(); }

        // Add `state` as a query parameter to the URL that the user agent is
        // being redirected to.
        var l = uri.parse(url, true);
        delete l.search;
        l.query.state = v;
        return cb(null, uri.format(l));
      }

      if (req.state.isComplete()) {
        proceed();
      } else if (req.state.isModified()) {
        // NOTE: can be modified and new
        req.state.save(function(err) {
          if (err) { return next(err); } // FIXME: This should call cb? No
          debug('set `state` query parameter to saved state (%s)', req.state.handle);
          proceed(req.state.handle);
        });
      } else if (req.state.isNew()) {
        // newly initialized state, without any state to actually track.  Just pass on
        // the parent state.
        // TODO: Also pass on returnTo url?
        proceed(req.state.resumeState);
      } else { // current state
        debug('set `state` query parameter to current state (%s)', req.state.handle);
        proceed(req.state.handle);
      }
    });

    // swizzle render to commit the state
    swizzleRender(res, function commitState(cb) {
      debug('render %O (handle: %s, modified: %o, saved: %o, complete: %o)', req.state,
        req.state.handle, req.state.isModified(), req.state.isSaved(), req.state.isComplete());

      // TODO: generalize this and make it an option, like csurf
      // TODO: dont' complete the state if it is flagged to continue

      // TODO: Shouldn't do this if done after resumeState.
      //.      swizzle it back to orig
      if (mutationMethods.indexOf(req.method) != -1) {
        if (Math.floor(res.statusCode / 100) == 2) {
          req.state.complete();
        }
      }

      if (req.state.isComplete()) {
        cb();
      } else if (req.state.isModified()) {
        req.state.save(function(err) {
          if (err) { return next(err); } // FIXME: This should call cb?
          debug('set `res.locals.state` to saved state (%s)', req.state.handle);
          res.locals.state = req.state.handle;
          cb();
        });
      } else if (req.state.isNew()) {
        if (req.state.resumeState) {
          debug('set `res.locals.state` to parent state (%s)', req.state.resumeState);
          res.locals.state = req.state.resumeState;
        }
        if (req.state.returnTo) { res.locals.returnTo = req.state.returnTo; }
        cb();
      } else { // current state
        debug('set `res.locals.state` to current state (%s)', req.state.handle);
        res.locals.state = req.state.handle;
        cb();
      }
    });

    swizzleEnd(res, function autoDestroy(cb) {
      debug('end %O (handle: %s, complete: %o)', req.state,
        req.state.handle, req.state.isComplete());

      // WIP: figure out how to maintain incomplete states
      // probably best to mandate external states be  flagged complete ??

      // TODO: also check fo unchanged?
      //if (!req.state.isNew()) {
      if (req.state.isComplete()) {
        debug('destroying complete state (%s)', req.state.handle);
        req.state.destroy(function(err) {
          //if (err) { return next(err); }
          //return proceed(state.state, state);
          cb();
        });
      } else {
        cb();
      }
    });

    function generate() {
      var data = {
        returnTo: (req.query && req.query.return_to) || (req.body && req.body.return_to) || (req.header ? req.header('referer') : undefined)
      }
      if (options.continue) {
        data.location = uri.resolve(utils.originalURL(req), options.continue);
      }
      // TODO: Test case for initialized state without a location that is then saved.  is location added?

      // TODO: Should returnTo be defaulted to current URL over referrer?
      //if (!req.state.returnTo && !req.state.state && !req.yieldState)  { req.state.returnTo = req.originalUrl || req.url; }

      // TODO: Might want to use a default URL passed as option in this case?
      //if (data.returnTo == utils.originalURL(req)) {
        // TODO: Maybe we do want to return to same resource?  POST to create, and then view?
        // Don't return to same resource
        //delete data.returnTo;
      //}

      // TODO: test case for originalUrl
      req.state = new State(req, data, undefined);
      // TODO: Delete this line once tests are fixed
      if (req.state.returnTo === undefined) { delete req.state.returnTo; }
    }

    function inflate(state, h) {
      req.state = new State(req, state, h);
    }

    // Initialize a state if the browser didn't send a state handle, or the
    // endpoint indicated that state, if any, is external to this app.
    //
    // The latter case is common with federated protocols, such as OpenID
    // Connect and OAuth 2.0, in which clients make requests that initiate
    // stateful transactions within the app making use of this middleware.
    // These requests may have a `state` parameter, but its value is meant to be
    // included when the browser is redirected back to the client so the client
    // can maintain its state.
    var h = getHandle(req);
    if (!h || options.external) {
      generate();
      next();
      return;
    }

    store.load(req, h, function(err, state) {
      if (err) { return next(err); }

      if (!state) {
        generate();
        next();
        return;
      }

      var url = utils.originalURLWithoutQuery(req);
      if (state.location !== url) {
        // The referened state is not intended for the endpoint that was
        // requested.
        //
        // A new state will be initialized which, when complete, will trigger
        // the referenced state to resume.  This process is managed by building
        // a logical stack of states as the browser is redirected or navigated
        // to a series of pages, where a reference to the current state is
        // relayed with each request.  Once a request is processed which does
        // not result in a further redirect, the stack unwinds by popping the
        // state to be resumed.
        inflate({ location: url, resumeState: h });
      } else {
        inflate(state, h);
      }

      next();
    });
  };
};
<commit_msg>Remove todo item.<commit_after>var uri = require('url')
  , State = require('../state')
  , dispatch = require('../utils').dispatch
  , swizzleRedirect = require('../utils/swizzle-redirect')
  , swizzleRender = require('../utils/swizzle-render')
  , swizzleEnd = require('../utils/swizzle-end')
  , flatten = require('utils-flatten')
  , merge = require('utils-merge')
  , utils = require('../utils')
  , debug = require('debug')('flowstate')
  , SessionStore = require('../stores/session');

  // TIPS: Generally, push a state before redirecting (unless wizard style
  //  alternatively, handler can lazily push, for its own state, to preserve storage
  //  which could be done based on the presence of a returnTo (which is not the handlers URL)

/**
 * Load state.
 *
 * This middleware is used to load state associated with a request.  The state
 * will be made available at `req.state`.
 *
 * HTTP is a stateless protocol.  In order to support stateful interactions, the
 * client and server need to operate in coordination.  The server is responsible
 * for persisting state associated with a request.  The client is responsible for
 * indicating that state in subsequent requests to the server (via a `state`
 * parameter in the query or body, by default).  The server then loads the
 * previously persisted state in order to continue processing the transaction.
 *
 * Options:
 *
 *     name   set req.state only if the state name is equal to the option value
 *     required   require state, failing otherwise (default: false)
 *
 * Examples:
 *
 *     app.get('/login',
 *       flowstate.loadState(),
 *       function(req, res, next) {
 *         res.locals.failureCount = req.state.failureCount;
 *         res.render('login');
 *       });
 *
 *     app.get('/login/callback',
 *       flowstate.loadState({ name: 'oauth2-redirect', required: true }),
 *       function(req, res, next) {
 *         // ...
 *       });
 *
 * @return {Function}
 * @api public
 */
module.exports = function(options) {
  options = options || {}

  var store = options.store || new SessionStore(options);
  var getHandle = options.getHandle || function(req) {
    return (req.query && req.query.state) || (req.body && req.body.state);
  }

  var mutationMethods = options.mutationMethods === undefined
    ? ['POST', 'PUT', 'PATCH', 'DELETE']
    : options.mutationMethods

  // WIP: On state init, set `resume` if the state is not intended for this lcoation

  // TODO: add a "locations" option, with relative paths that will be added to location

  return function state(req, res, next) {
    // self-awareness
    if (req.state) { return next(); }

    // expose store
    req.stateStore = store;

    res.pushState = function(state, url, end) {
      end = end !== undefined ? end : true;

      // WIP: Test case where this is a relative URL
      state.location = uri.resolve(utils.originalURL(req), url);
      req.state.push(state);
      end && this.redirect(url);
    }

    res.resumeState = function(yields, cb) {
      if (typeof yields == 'function') {
        cb = yields;
        yields = undefined;
      }

      req.state.complete();

      if (req.state.returnTo) {
        // TODO: underscore the parameters, adn redirect with query
        this.redirect(req.state.returnTo);
      } else if (req.state.resumeState) {
        var self = this;

        req.state.destroy(function(err) {
          if (err) { return cb(err); } // FIXME: this should be next?

          store.load(req, req.state.resumeState, function(err, data) {
            if (err) { return cb(err); }  // FIXME: this should be next?

            // WIP: Need a state stack to traverse to do destroy on res.render/res.redirect

            var state = new State(req, data, req.state.resumeState);
            merge(state, yields);

            // TODO: This can be short-circuited to alway save, and optimize in there
            if (!state.isModified()) {
              self.redirect(data.location + '?state=' + state.handle);
            } else {
              state.save(function(err) {
                if (err) { return cb(err); }
                self.redirect(state.location + '?state=' + state.handle);
              });
            }
          });
        });
      } else {
        cb();
      }
    }

    // swizzle redirect to commit the state
    swizzleRedirect(res, function commitState(url, cb) {
      debug('redirect %s, %O (handle: %s, modified: %o, saved: %o, complete: %o, new: %o)', url, req.state,
        req.state.handle, req.state.isModified(), req.state.isSaved(), req.state.isComplete(), req.state.isNew());

      function proceed(v) {
        if (!v) { return cb(); }

        // Add `state` as a query parameter to the URL that the user agent is
        // being redirected to.
        var l = uri.parse(url, true);
        delete l.search;
        l.query.state = v;
        return cb(null, uri.format(l));
      }

      if (req.state.isComplete()) {
        proceed();
      } else if (req.state.isModified()) {
        // NOTE: can be modified and new
        req.state.save(function(err) {
          if (err) { return next(err); } // FIXME: This should call cb? No
          debug('set `state` query parameter to saved state (%s)', req.state.handle);
          proceed(req.state.handle);
        });
      } else if (req.state.isNew()) {
        // newly initialized state, without any state to actually track.  Just pass on
        // the parent state.
        // TODO: Also pass on returnTo url?
        proceed(req.state.resumeState);
      } else { // current state
        debug('set `state` query parameter to current state (%s)', req.state.handle);
        proceed(req.state.handle);
      }
    });

    // swizzle render to commit the state
    swizzleRender(res, function commitState(cb) {
      debug('render %O (handle: %s, modified: %o, saved: %o, complete: %o)', req.state,
        req.state.handle, req.state.isModified(), req.state.isSaved(), req.state.isComplete());

      // TODO: generalize this and make it an option, like csurf
      // TODO: dont' complete the state if it is flagged to continue

      // TODO: Shouldn't do this if done after resumeState.
      //.      swizzle it back to orig
      if (mutationMethods.indexOf(req.method) != -1) {
        if (Math.floor(res.statusCode / 100) == 2) {
          req.state.complete();
        }
      }

      if (req.state.isComplete()) {
        cb();
      } else if (req.state.isModified()) {
        req.state.save(function(err) {
          if (err) { return next(err); } // FIXME: This should call cb?
          debug('set `res.locals.state` to saved state (%s)', req.state.handle);
          res.locals.state = req.state.handle;
          cb();
        });
      } else if (req.state.isNew()) {
        if (req.state.resumeState) {
          debug('set `res.locals.state` to parent state (%s)', req.state.resumeState);
          res.locals.state = req.state.resumeState;
        }
        if (req.state.returnTo) { res.locals.returnTo = req.state.returnTo; }
        cb();
      } else { // current state
        debug('set `res.locals.state` to current state (%s)', req.state.handle);
        res.locals.state = req.state.handle;
        cb();
      }
    });

    swizzleEnd(res, function autoDestroy(cb) {
      debug('end %O (handle: %s, complete: %o)', req.state,
        req.state.handle, req.state.isComplete());

      // WIP: figure out how to maintain incomplete states
      // probably best to mandate external states be  flagged complete ??

      // TODO: also check fo unchanged?
      //if (!req.state.isNew()) {
      if (req.state.isComplete()) {
        debug('destroying complete state (%s)', req.state.handle);
        req.state.destroy(function(err) {
          //if (err) { return next(err); }
          //return proceed(state.state, state);
          cb();
        });
      } else {
        cb();
      }
    });

    function generate() {
      var data = {
        returnTo: (req.query && req.query.return_to) || (req.body && req.body.return_to) || (req.header ? req.header('referer') : undefined)
      }
      if (options.continue) {
        data.location = uri.resolve(utils.originalURL(req), options.continue);
      }

      // TODO: Should returnTo be defaulted to current URL over referrer?
      //if (!req.state.returnTo && !req.state.state && !req.yieldState)  { req.state.returnTo = req.originalUrl || req.url; }

      // TODO: Might want to use a default URL passed as option in this case?
      //if (data.returnTo == utils.originalURL(req)) {
        // TODO: Maybe we do want to return to same resource?  POST to create, and then view?
        // Don't return to same resource
        //delete data.returnTo;
      //}

      // TODO: test case for originalUrl
      req.state = new State(req, data, undefined);
      // TODO: Delete this line once tests are fixed
      if (req.state.returnTo === undefined) { delete req.state.returnTo; }
    }

    function inflate(state, h) {
      req.state = new State(req, state, h);
    }

    // Initialize a state if the browser didn't send a state handle, or the
    // endpoint indicated that state, if any, is external to this app.
    //
    // The latter case is common with federated protocols, such as OpenID
    // Connect and OAuth 2.0, in which clients make requests that initiate
    // stateful transactions within the app making use of this middleware.
    // These requests may have a `state` parameter, but its value is meant to be
    // included when the browser is redirected back to the client so the client
    // can maintain its state.
    var h = getHandle(req);
    if (!h || options.external) {
      generate();
      next();
      return;
    }

    store.load(req, h, function(err, state) {
      if (err) { return next(err); }

      if (!state) {
        generate();
        next();
        return;
      }

      var url = utils.originalURLWithoutQuery(req);
      if (state.location !== url) {
        // The referened state is not intended for the endpoint that was
        // requested.
        //
        // A new state will be initialized which, when complete, will trigger
        // the referenced state to resume.  This process is managed by building
        // a logical stack of states as the browser is redirected or navigated
        // to a series of pages, where a reference to the current state is
        // relayed with each request.  Once a request is processed which does
        // not result in a further redirect, the stack unwinds by popping the
        // state to be resumed.
        inflate({ location: url, resumeState: h });
      } else {
        inflate(state, h);
      }

      next();
    });
  };
};
<|endoftext|>


<commit_before>// collection.js
//
// data object representing an collection
//
// Copyright 2011-2012, StatusNet Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

var _ = require("underscore"),
    Step = require("step"),
    DatabankObject = require("databank").DatabankObject,
    ActivityObject = require("./activityobject").ActivityObject,
    Stream = require("./stream").Stream;

var Collection = DatabankObject.subClass("collection", ActivityObject);

Collection.schema = {
    pkey: "id",
    fields: ["author",
             "displayName",
             "image",
             "objectTypes",
             "published",
             "summary",
             "updated",
             "url"]
};

Collection.isList = function(props, callback) {
    var User = require("./user").User;

    if (_(props).has('author') &&
        _(props.author).has('id') &&
        _(props).has('objectTypes') &&
        _(props).has('displayName') &&
        _(props.objectTypes).isArray() &&
        props.objectTypes.length === 1) {
        User.fromPerson(props.author.id, function(err, user) {
            if (err) {
                callback(err, null);
            } else if (!user) {
                callback(null, false);
            } else {
                callback(null, true);
            }
        });
    } else {
        callback(null, false);
    }
};

Collection.checkList = function(props, callback) {
    Collection.isList(props, function(err, isList) {
        if (err) {
            callback(err, null);
        } else if (!isList) {
            callback(null, props);
        } else {
            Collection.search({"author.id": props.author.id, "displayName": props.displayName}, function(err, results) {
                var i, hit = false;
                if (err) {
                    callback(err, null);
                } else if (results.length === 0) {
                    callback(null, props);
                } else {
                    for (i = 0; i < results.length; i++) {
                        if (JSON.stringify(results[i].objectTypes) === JSON.stringify(props.objectTypes)) {
                            hit = true;
                            break;
                        }
                    }
                    if (hit) {
                        callback(new Error("A folder for '" + props.objectTypes.join(",") + "' named '" + props.displayName + "'already exists."), null);
                    } else {
                        callback(null, props);
                    }
                }
            });
        }
    });
};

Collection.beforeCreate = function(props, callback) {

    Step(
        function() {
            Collection.checkList(props, this);
        },
        function(err, props) {
            if (err) {
                callback(err, null);
            } else {
                Collection.parent.beforeCreate(props, callback);
            }
        }
    );
};

Collection.prototype.afterCreate = function(callback) {
    var coll = this,
        User = require("./user").User;

    Step(
        function() {
            Collection.isList(coll, this);
        },
        function(err, isList) {
            if (err) throw err;
            if (!isList) {
                callback(null);
            } else {
                Stream.create({name: "collection:"+coll.id}, this);
            }
        },
        function(err, stream) {
            if (err) throw err;
            User.fromPerson(coll.author.id, this);
        },
        function(err, user) {
            if (err) throw err;
            user.addList(coll, this);
        },
        function(err) {
            if (err) {
                callback(err);
            } else {
                callback(null);
            }
        }
    );
};

Collection.prototype.afterDel = function(callback) {
    var coll = this,
        User = require("./user").User;

    Step(
        function() {
            Collection.isList(coll, this);
        },
        function(err, isList) {
            if (err) throw err;
            if (!isList) {
                callback(null);
            } else {
                Stream.get("collection:"+coll.id, this);
            }
        },
        function(err, stream) {
            if (err) throw err;
            stream.del(this);
        },
        function(err) {
            if (err) throw err;
            User.fromPerson(coll.author.id, this);
        },
        function(err, user) {
            if (err) throw err;
            user.removeList(coll, this);
        },
        function(err) {
            if (err) {
                callback(err);
            } else {
                callback(null);
            }
        }
    );
};

exports.Collection = Collection;
<commit_msg>Revert "Collections that can store things"<commit_after>// collection.js
//
// data object representing an collection
//
// Copyright 2011-2012, StatusNet Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

var _ = require("underscore"),
    DatabankObject = require("databank").DatabankObject,
    ActivityObject = require("./activityobject").ActivityObject;

var Collection = DatabankObject.subClass("collection", ActivityObject);

Collection.schema = {
    pkey: "id",
    fields: ["author",
             "displayName",
             "image",
             "objectTypes",
             "published",
             "summary",
             "updated",
             "url"]
};

Collection.isFolder = function(props, callback) {
    var User = require("./user").User;

    if (_(props).has('author') &&
        _(props.author).has('id') &&
        _(props).has('objectTypes') &&
        _(props).has('displayName') &&
        _(props.objectTypes).isArray() &&
        props.objectTypes.length === 1) {
        User.fromPerson(props.author.id, function(err, user) {
            if (err) {
                callback(err, null);
            } else if (!user) {
                callback(null, false);
            } else {
                callback(null, true);
            }
        });
    } else {
        callback(null, false);
    }
};

Collection.checkFolder = function(props, callback) {
};

Collection.beforeCreate = function(props, callback) {
    Collection.checkFolder(props, function(err, props) {
        if (err) {
            callback(err, null);
        } else {
            Collection.parent.beforeCreate(props, callback);
        }
    });
};

Collection.prototype.afterCreate = function(callback) {
    Collection.checkFolder(props, function(err, props) {
        if (err) {
            callback(err, null);
        } else {
            Collection.parent.beforeCreate(props, callback);
        }
    });
};

Collection.prototype.afterDel = function(callback) {
};

exports.Collection = Collection;
<|endoftext|>


<commit_before>/*!
 * ${copyright}
 */

// Provides control sap.m.TabStripSelect.
sap.ui.define(['jquery.sap.global', './Popover', './TabStripSelectList', './library', 'sap/ui/core/Control', 'sap/ui/core/EnabledPropagator', 'sap/ui/core/IconPool', 'sap/m/Select'],
	function(jQuery, Popover, TabStripSelectList, library, Control, EnabledPropagator, IconPool, Select) {
		"use strict";

		/**
		 * Constructor for a new TabStripSelect.
		 *
		 * @param {string} [sId] ID for the new control, generated automatically if no ID is given.
		 * @param {object} [mSettings] Initial settings for the new control.
		 *
		 * @class
		 * The sap.m.TabStripSelect control provides a list of items that allows users to interact with an item.
		 * @extends sap.m.Select
		 *
		 * @author SAP SE
		 * @version ${version}
		 * @since 1.34
		 *
		 * @constructor
		 * @private
		 * @alias sap.m.TabStripSelect
		 * @ui5-metamodel This control will also be described in the UI5 (legacy) design time meta model.
		 */
		var TabStripSelect = Select.extend("sap.m.TabStripSelect", /** @lends sap.m.TabStripSelect.prototype */ {
			metadata: {
				library: "sap.m"

			},
			aggregations: {
				/**
				 * Holds the items contained within this control.
				 */
				items: { type: "sap.m.TabStripItem", multiple: true, singularName: "item", bindable: "bindable" },
				list: { type: "sap.m.TabStripSelectList", multiple: false, bindable: "bindable" }
			},
			properties: {
				/*
				 * Altering this property hides/shows the control in the DOM
				 * // ToDo: remove this todo comment when it is confirmed this property will be used
				 */
				visible: { type: "boolean", group : "Misc", defaultValue : true }
			}
		});

		TabStripSelect.CSS_CLASS_INVISIBLE = 'sapMSltInvisible';
		TabStripSelect.SPACE_BETWEEN_SELECT_BUTTON_AND_POPOVER = 5;

		/**
		 * Initialization hook.
		 * @override
		 * @private
		 */
		TabStripSelect.prototype.init = function() {
			// set the picker type
			this.setPickerType("Popover");

			// initialize composites
			this.createPicker(this.getPickerType());

			// selected item on focus
			this._oSelectionOnFocus = null;

			// to detect when the control is in the rendering phase
			this._bRenderingPhase = false;

			// to detect if the focusout event is triggered due a rendering
			this._bFocusoutDueRendering = false;
			// used to prevent the change event from firing when the user scrolls
			// the picker popup (dropdown) list using the mouse
			this._bProcessChange = false;
		};

		/**
		 * Create the select list instance
		 *
		 * @override
		 * @private
		 * @returns {*}
		 */
		TabStripSelect.prototype.createList = function() {
			// list to use inside the picker
			this._oList = new TabStripSelectList({
				width: "100%"
			}).attachSelectionChange(this.onSelectionChange, this)
			.addEventDelegate({
				ontap: function(oEvent) {
					this.close();
				}
			}, this);

			return this._oList;
		};

		/**
		 * Method for proxying calls of the select methods to the inner select list methods.
		 * @override
		 * @param {string} sFunctionName The name of the called method
		 * @param {array} aArgs The supplied arguments
		 * @returns {mixed} The result of the called method
		 * @private
		 */
		TabStripSelect.prototype._callMethodInControl = function(sFunctionName, aArgs) {
			var vRes,
			    oList;
			if (aArgs[0] === "items") {
				oList = this.getList();
				if (oList) {
					vRes = TabStripSelectList.prototype[sFunctionName].apply(oList, aArgs);
				}

				// Force the picker control (holding the select list) to re-render as well, in order to have the
				// right position in case the longest item was removed (and picker width is changed)
				if (sFunctionName === 'removeAggregation' && this.isOpen()) {
					this.getPicker().rerender();
				}

			} else {
				vRes = Control.prototype[sFunctionName].apply(this, aArgs);
			}

			return vRes;
		};

		/**
		 * Creates an instance of sap.m.Popover.
		 *
		 * @override
		 * @private
		 * @returns {sap.m.Popover}
		 */
		TabStripSelect.prototype._createPopover = function() {
			var that = this,
			    oPicker = new Popover({
				    showArrow: false,
				    showHeader: false,
				    placement: sap.m.PlacementType.Vertical,
				    offsetX: 0,
				    offsetY: sap.ui.Device.system.phone ? 0 : TabStripSelect.SPACE_BETWEEN_SELECT_BUTTON_AND_POPOVER,
				    initialFocus: this,
				    bounce: false
			    });

			// detect when the scrollbar is pressed
			oPicker.addEventDelegate({
				ontouchstart: function(oEvent) {
					var oPickerDomRef = this.getDomRef("cont");

					if (oEvent.target === oPickerDomRef) {
						that._bProcessChange = false;
					}
				}
			}, oPicker);

			this._decoratePopover(oPicker);
			return oPicker;
		};

		/**
		 * This event handler is called after the picker popup is rendered.
		 * @override
		 * @private
		 */
		TabStripSelect.prototype.onAfterRenderingPicker = function() {
			Select.prototype.onAfterRenderingPicker.call(this);
			var iPickerOffsetX = this.getPicker().$().width() - this.$().width();
			this.getPicker().setOffsetX(-iPickerOffsetX);
			this.getPicker()._calcPlacement(); // needed to apply the new offset after the popup is open
		};

		/**
		 * Cleans up before destruction.
		 * @override
		 * @private
		 */
		TabStripSelect.prototype.exit = function() {
			Select.prototype.exit.call(this);
			this._oList.destroy();
			this._oList = null;
		};

		/**
		 * Handle the touch start event on the TabStripSelect.
		 *
		 * @param {jQuery.Event} oEvent The event object.
		 * @private
		 */
		TabStripSelect.prototype.ontouchstart = function(oEvent) {

			// mark the event for components that needs to know if the event was handled
			oEvent.setMarked();

			if (this.getEnabled() && this.isOpenArea(oEvent.target)) {

				// add the active state to the TabStripSelect's field
				this.addStyleClass(this.getRenderer().CSS_CLASS + "Pressed");
			}
		};

		/**
		 * Handle the touch end event on the TabStripSelect.
		 *
		 * @param {jQuery.Event} oEvent The event object.
		 * @private
		 */
		TabStripSelect.prototype.ontouchend = function(oEvent) {

			// mark the event for components that needs to know if the event was handled
			oEvent.setMarked();

			if (this.getEnabled() && (!this.isOpen() || !this.hasContent()) && this.isOpenArea(oEvent.target)) {

				// remove the active state of the Select HTMLDIVElement container
				this.removeStyleClass(this.getRenderer().CSS_CLASS + "Pressed");
			}
		};

		/**
		 * This event handler is called before the picker popup is closed.
		 *
		 * @private
		 */
		TabStripSelect.prototype.onBeforeClose = function() {
			var oDomRef = this.getFocusDomRef();

			if (oDomRef) {

				// note: the "aria-owns" attribute is removed when the list is not visible and in view
				oDomRef.removeAttribute("aria-owns");

				// the "aria-activedescendant" attribute is removed when the currently active descendant is not visible
				oDomRef.removeAttribute("aria-activedescendant");
			}

			// remove the active state of the Select's field
			this.removeStyleClass(this.getRenderer().CSS_CLASS + "Pressed");
		};

		/**
		 * This event handler is called after the picker popup is closed.
		 *
		 * @private
		 */
		TabStripSelect.prototype.onAfterClose = function() {
			var oDomRef = this.getFocusDomRef();

			if (oDomRef) {
				oDomRef.setAttribute("aria-expanded", "false");

				// note: the "aria-owns" attribute is removed when the list is not visible and in view
				oDomRef.removeAttribute("aria-owns");
			}
		};

		return TabStripSelect;

}, /* bExport= */ false);

<commit_msg>[INTERNAL][FIX] sap.m.TabStrip: Popup position fixed in RTL<commit_after>/*!
 * ${copyright}
 */

// Provides control sap.m.TabStripSelect.
sap.ui.define(['jquery.sap.global', './Popover', './TabStripSelectList', './library', 'sap/ui/core/Control', 'sap/ui/core/EnabledPropagator', 'sap/ui/core/IconPool', 'sap/m/Select'],
	function(jQuery, Popover, TabStripSelectList, library, Control, EnabledPropagator, IconPool, Select) {
		"use strict";

		/**
		 * Constructor for a new TabStripSelect.
		 *
		 * @param {string} [sId] ID for the new control, generated automatically if no ID is given.
		 * @param {object} [mSettings] Initial settings for the new control.
		 *
		 * @class
		 * The sap.m.TabStripSelect control provides a list of items that allows users to interact with an item.
		 * @extends sap.m.Select
		 *
		 * @author SAP SE
		 * @version ${version}
		 * @since 1.34
		 *
		 * @constructor
		 * @private
		 * @alias sap.m.TabStripSelect
		 * @ui5-metamodel This control will also be described in the UI5 (legacy) design time meta model.
		 */
		var TabStripSelect = Select.extend("sap.m.TabStripSelect", /** @lends sap.m.TabStripSelect.prototype */ {
			metadata: {
				library: "sap.m"

			},
			aggregations: {
				/**
				 * Holds the items contained within this control.
				 */
				items: { type: "sap.m.TabStripItem", multiple: true, singularName: "item", bindable: "bindable" },
				list: { type: "sap.m.TabStripSelectList", multiple: false, bindable: "bindable" }
			},
			properties: {
				/*
				 * Altering this property hides/shows the control in the DOM
				 * // ToDo: remove this todo comment when it is confirmed this property will be used
				 */
				visible: { type: "boolean", group : "Misc", defaultValue : true }
			}
		});

		TabStripSelect.CSS_CLASS_INVISIBLE = 'sapMSltInvisible';
		TabStripSelect.SPACE_BETWEEN_SELECT_BUTTON_AND_POPOVER = 5;

		/**
		 * Initialization hook.
		 * @override
		 * @private
		 */
		TabStripSelect.prototype.init = function() {
			// set the picker type
			this.setPickerType("Popover");

			// initialize composites
			this.createPicker(this.getPickerType());

			// selected item on focus
			this._oSelectionOnFocus = null;

			// to detect when the control is in the rendering phase
			this._bRenderingPhase = false;

			// to detect if the focusout event is triggered due a rendering
			this._bFocusoutDueRendering = false;
			// used to prevent the change event from firing when the user scrolls
			// the picker popup (dropdown) list using the mouse
			this._bProcessChange = false;
		};

		/**
		 * Create the select list instance
		 *
		 * @override
		 * @private
		 * @returns {*}
		 */
		TabStripSelect.prototype.createList = function() {
			// list to use inside the picker
			this._oList = new TabStripSelectList({
				width: "100%"
			}).attachSelectionChange(this.onSelectionChange, this)
			.addEventDelegate({
				ontap: function(oEvent) {
					this.close();
				}
			}, this);

			return this._oList;
		};

		/**
		 * Method for proxying calls of the select methods to the inner select list methods.
		 * @override
		 * @param {string} sFunctionName The name of the called method
		 * @param {array} aArgs The supplied arguments
		 * @returns {mixed} The result of the called method
		 * @private
		 */
		TabStripSelect.prototype._callMethodInControl = function(sFunctionName, aArgs) {
			var vRes,
			    oList;
			if (aArgs[0] === "items") {
				oList = this.getList();
				if (oList) {
					vRes = TabStripSelectList.prototype[sFunctionName].apply(oList, aArgs);
				}

				// Force the picker control (holding the select list) to re-render as well, in order to have the
				// right position in case the longest item was removed (and picker width is changed)
				if (sFunctionName === 'removeAggregation' && this.isOpen()) {
					this.getPicker().rerender();
				}

			} else {
				vRes = Control.prototype[sFunctionName].apply(this, aArgs);
			}

			return vRes;
		};

		/**
		 * Creates an instance of sap.m.Popover.
		 *
		 * @override
		 * @private
		 * @returns {sap.m.Popover}
		 */
		TabStripSelect.prototype._createPopover = function() {
			var that = this,
			    oPicker = new Popover({
				    showArrow: false,
				    showHeader: false,
				    placement: sap.m.PlacementType.Vertical,
				    offsetX: 0,
				    offsetY: sap.ui.Device.system.phone ? 0 : TabStripSelect.SPACE_BETWEEN_SELECT_BUTTON_AND_POPOVER,
				    initialFocus: this,
				    bounce: false
			    });

			// detect when the scrollbar is pressed
			oPicker.addEventDelegate({
				ontouchstart: function(oEvent) {
					var oPickerDomRef = this.getDomRef("cont");

					if (oEvent.target === oPickerDomRef) {
						that._bProcessChange = false;
					}
				}
			}, oPicker);

			this._decoratePopover(oPicker);
			return oPicker;
		};

		/**
		 * This event handler is called after the picker popup is rendered.
		 * @override
		 * @private
		 */
		TabStripSelect.prototype.onAfterRenderingPicker = function() {
			var iPickerOffsetX,
				bPageRTL = sap.ui.getCore().getConfiguration().getRTL();

			Select.prototype.onAfterRenderingPicker.call(this);
			if (bPageRTL) {
				iPickerOffsetX = this.$().width() - this.getPicker().$().width();
			} else {
				iPickerOffsetX = this.getPicker().$().width() - this.$().width();
			}

			this.getPicker().setOffsetX(-iPickerOffsetX);
			this.getPicker()._calcPlacement(); // needed to apply the new offset after the popup is open
		};

		/**
		 * Cleans up before destruction.
		 * @override
		 * @private
		 */
		TabStripSelect.prototype.exit = function() {
			Select.prototype.exit.call(this);
			this._oList.destroy();
			this._oList = null;
		};

		/**
		 * Handle the touch start event on the TabStripSelect.
		 *
		 * @param {jQuery.Event} oEvent The event object.
		 * @private
		 */
		TabStripSelect.prototype.ontouchstart = function(oEvent) {

			// mark the event for components that needs to know if the event was handled
			oEvent.setMarked();

			if (this.getEnabled() && this.isOpenArea(oEvent.target)) {

				// add the active state to the TabStripSelect's field
				this.addStyleClass(this.getRenderer().CSS_CLASS + "Pressed");
			}
		};

		/**
		 * Handle the touch end event on the TabStripSelect.
		 *
		 * @param {jQuery.Event} oEvent The event object.
		 * @private
		 */
		TabStripSelect.prototype.ontouchend = function(oEvent) {

			// mark the event for components that needs to know if the event was handled
			oEvent.setMarked();

			if (this.getEnabled() && (!this.isOpen() || !this.hasContent()) && this.isOpenArea(oEvent.target)) {

				// remove the active state of the Select HTMLDIVElement container
				this.removeStyleClass(this.getRenderer().CSS_CLASS + "Pressed");
			}
		};

		/**
		 * This event handler is called before the picker popup is closed.
		 *
		 * @private
		 */
		TabStripSelect.prototype.onBeforeClose = function() {
			var oDomRef = this.getFocusDomRef();

			if (oDomRef) {

				// note: the "aria-owns" attribute is removed when the list is not visible and in view
				oDomRef.removeAttribute("aria-owns");

				// the "aria-activedescendant" attribute is removed when the currently active descendant is not visible
				oDomRef.removeAttribute("aria-activedescendant");
			}

			// remove the active state of the Select's field
			this.removeStyleClass(this.getRenderer().CSS_CLASS + "Pressed");
		};

		/**
		 * This event handler is called after the picker popup is closed.
		 *
		 * @private
		 */
		TabStripSelect.prototype.onAfterClose = function() {
			var oDomRef = this.getFocusDomRef();

			if (oDomRef) {
				oDomRef.setAttribute("aria-expanded", "false");

				// note: the "aria-owns" attribute is removed when the list is not visible and in view
				oDomRef.removeAttribute("aria-owns");
			}
		};

		return TabStripSelect;

}, /* bExport= */ false);

<|endoftext|>


<commit_before>'use strict';

function DatasetSearchController($scope, $controller, $filter, $location,
    DatasetFactoryService, DatasetModel, NpdcCitationModel, NpdcAPA, npdcAppConfig, NpdcAutocompleteConfigFactory,
    NpdcSearchService, NpolarTranslate) {
  'ngInject';

  function query() {
    let param = $location.search();

    let sort = param.sort || null;

    let query =  {
      limit: param.limit||20,
      fields: 'title,id,collection,updated,released,links,people,organisations',
      facets: "sets,topics,links.rel,people.email,created_by,updated_by",
      sort,
      score: true
    };
    return query;
  }

  function init() {
    $controller('NpolarBaseController', {
      $scope: $scope
    });

    $scope.resource = DatasetFactoryService.resourceFactory();
    $scope.model = DatasetModel;

    npdcAppConfig.search.local.results.title = (d) => d.title;
    npdcAppConfig.search.local.results.detail = function(entry) {
      return NpdcAPA.reference(NpdcCitationModel.authors(entry), NpdcCitationModel.year(entry));
    };

    // Show datasets with data link (only on first load)
    if (!$location.search().q  || $location.search().q === "") {
      $location.search(Object.assign({}, $location.search(), { 'filter-links.rel': 'data' }));
    }

    $scope.$on('$locationChangeSuccess', (event, data) => {
      $scope.search(query());
    });
  }

  init();

  $scope.search(query()).$promise.then(r => {
    NpolarTranslate.dictionary['npdc.app.Title'] = DatasetModel.getAppTitle();
  });

}
module.exports = DatasetSearchController;
<commit_msg>Authenticated users: no default has data filter<commit_after>'use strict';

function DatasetSearchController($scope, $controller, $filter, $location,
    NpolarApiSecurity,
    DatasetFactoryService, DatasetModel, NpdcCitationModel, NpdcAPA, npdcAppConfig, NpdcAutocompleteConfigFactory,
    NpdcSearchService, NpolarTranslate) {
  'ngInject';

  function query() {
    let param = $location.search();

    let sort = param.sort || null;

    let query =  {
      limit: param.limit||20,
      fields: 'title,id,collection,updated,released,links,people,organisations',
      facets: "sets,topics,links.rel,people.email,created_by,updated_by",
      sort,
      score: true
    };
    return query;
  }

  function init() {
    $controller('NpolarBaseController', {
      $scope: $scope
    });

    $scope.resource = DatasetFactoryService.resourceFactory();
    $scope.model = DatasetModel;

    npdcAppConfig.search.local.results.title = (d) => d.title;
    npdcAppConfig.search.local.results.detail = function(entry) {
      return NpdcAPA.reference(NpdcCitationModel.authors(entry), NpdcCitationModel.year(entry));
    };

    // Show datasets with data link (only on first load, and only if not authenticated)
    if (!NpolarApiSecurity.isAuthenticated() && !$location.search().q  || $location.search().q === "") {
      $location.search(Object.assign({}, $location.search(), { 'filter-links.rel': 'data' }));
    }

    $scope.$on('$locationChangeSuccess', (event, data) => {
      $scope.search(query());
    });
  }

  init();

  $scope.search(query()).$promise.then(r => {
    NpolarTranslate.dictionary['npdc.app.Title'] = DatasetModel.getAppTitle();
  });

}
module.exports = DatasetSearchController;
<|endoftext|>