<commit_before>import _ from 'lodash'
import Promise from 'bluebird'
import util from 'util'

export const ID_SEPARATOR = '--'
export const PATH_SEPARATOR = '.'
export const VALUE_SEPARATOR = ','

export function idQuery(model, id) {
  const fields = primaryKeys(model)
  const values = id.split(ID_SEPARATOR)

  if (fields.length !== values.length) {
    throw new Error('The number of ID parameter values does not match the number of ID fields')
  }

  return _.zipObject(fields, values)
}

function primaryKeys(model) {
  return _.keys(model.primaryKeys)
}

export function id(model, document) {
  const fields = primaryKeys(model)
  const values = _.map(fields, field => document[field])
  return values.join(ID_SEPARATOR)
}

export function type(model) {
  return _.kebabCase(model.name)
}

function foreignKeys(model) {
  return _.reject(
    _.map(model.attributes, (attribute, key) => {
      return _.has(attribute, 'references') ? key : undefined
    }),
    _.isEmpty
  )
}

function attributeKeys(model) {
  const foreign = foreignKeys(model)
  const primary = primaryKeys(model)
  const excludeKeys = primary.concat(foreign)
  return _.without(_.keys(model.attributes), ...excludeKeys)
}

export function attributes(model, document) {
  const keys = attributeKeys(model)
  return _.pick(document, keys)
}

function relationshipKeys(model) {
  return _.keys(model.associations)
}

export function relationships(model, document) {
  const relationships = {}
  const keys = relationshipKeys(model)
  _.forEach(keys, key => {
    if (!document[key]) {
      return
    }

    relationships[key] = document[key]
  })
  return relationships
}

export function hasAssociation(model, path) {
  const parts = path.split(PATH_SEPARATOR)
  let result = true
  let part
  while (part = parts.shift()) {
    const target = `associations.${part}.target`
    if (!_.has(model, target)) {
      result = false
      break;
    }
    model = _.get(model, target)
  }

  return result
}

export function getAssociationModel(model, path) {
  const parts = path.split(PATH_SEPARATOR)
  let part
  while (part = parts.shift()) {
    const target = `associations.${part}.target`
    if (!_.has(model, target)) {
      throw new Error('Association does not exist')
    }
    model = _.get(model, target)
  }

  return model
}

export function isIncluded(model, path, include) {
  const params = _.filter(include.split(VALUE_SEPARATOR), value => {
    return hasAssociation(model, value)
  })

  let result = false

  _.forEach(params, value => {
    const includeParts = value.split(PATH_SEPARATOR)
    const pathParts = path.split(PATH_SEPARATOR)
    let match = true
    for (let i = 0; i < pathParts.length; i += 1) {
      if (includeParts[i] !== pathParts[i]) {
        match = false
        break
      }
    }
    if (match) {
      result = match
      return false
    }
  })

  return result
}

export function includePath(model, path) {
  const parts = path.split(PATH_SEPARATOR)
  const part = parts.shift()

  const associationModel = getAssociationModel(model, part)

  if (parts.length === 0) {
    return {
      model: associationModel,
      as: part
    }
  }

  return {
    model: associationModel,
    as: part,
    include: [includePath(associationModel, parts.join(PATH_SEPARATOR))]
  }
}

function merge(paths, include) {
  return paths.reduce((include, path) => {
    const exists = include.find(element => element.model === path.model && element.as === path.as)
    if (!exists) {
      include.push(path)
      return include
    }

    if (!_.isArray(exists.include)) {
      exists.include = []
    }
    if (_.isArray(path.include)) {
      exists.include.push(...path.include)
    }

    exists.include = merge(exists.include, [])

    return include
  }, include)
}

export function include(model, include) {
  if (!_.isString(include)) {
    throw new Error('"include" must be string')
  }
  include = include.split(VALUE_SEPARATOR)
  const paths = include.map(path => includePath(model, path))
  return merge(paths, [])
}

export function setRelationship({model, document, path, resourceIdentifiers, transaction}) {
  if (!_.isArray(resourceIdentifiers)) {
    resourceIdentifiers = [resourceIdentifiers]
  }

  const associationModel = getAssociationModel(model, path)

  // TODO support composite primary keys
  const ids = _.map(resourceIdentifiers, resourceIdentifier => resourceIdentifier.id)
  const associationType = model.associations[path].associationType
  return associationModel
    .findAll({
      where: {id: {$in: ids}},
      transaction
    })
    .then(relatedDocuments => {
      // TODO sequelize docs say we should be able todo sth like this document.set('projects', documents)
      switch (associationType) {
        case 'HasOne':
          return document[`set${_.capitalize(path)}`](relatedDocuments.shift(), {transaction})
        case 'HasMany':
          return document[`set${_.capitalize(path)}`](relatedDocuments, {transaction})
        default:
          console.warn('Associations different than "HasOne" and "HasMany" are not supported')
      }
    })
}
<commit_msg>chore: fix lint error<commit_after>import _ from 'lodash'
import Promise from 'bluebird'
import util from 'util'

export const ID_SEPARATOR = '--'
export const PATH_SEPARATOR = '.'
export const VALUE_SEPARATOR = ','

export function idQuery(model, id) {
  const fields = primaryKeys(model)
  const values = id.split(ID_SEPARATOR)

  if (fields.length !== values.length) {
    throw new Error('The number of ID parameter values does not match the number of ID fields')
  }

  return _.zipObject(fields, values)
}

function primaryKeys(model) {
  return _.keys(model.primaryKeys)
}

export function id(model, document) {
  const fields = primaryKeys(model)
  const values = _.map(fields, field => document[field])
  return values.join(ID_SEPARATOR)
}

export function type(model) {
  return _.kebabCase(model.name)
}

function foreignKeys(model) {
  return _.reject(
    _.map(model.attributes, (attribute, key) => {
      return _.has(attribute, 'references') ? key : undefined
    }),
    _.isEmpty
  )
}

function attributeKeys(model) {
  const foreign = foreignKeys(model)
  const primary = primaryKeys(model)
  const excludeKeys = primary.concat(foreign)
  return _.without(_.keys(model.attributes), ...excludeKeys)
}

export function attributes(model, document) {
  const keys = attributeKeys(model)
  return _.pick(document, keys)
}

function relationshipKeys(model) {
  return _.keys(model.associations)
}

export function relationships(model, document) {
  const relationships = {}
  const keys = relationshipKeys(model)
  _.forEach(keys, key => {
    if (!document[key]) {
      return
    }

    relationships[key] = document[key]
  })
  return relationships
}

export function hasAssociation(model, path) {
  const parts = path.split(PATH_SEPARATOR)
  let result = true
  let part
  while (part = parts.shift()) {
    const target = `associations.${part}.target`
    if (!_.has(model, target)) {
      result = false
      break
    }
    model = _.get(model, target)
  }

  return result
}

export function getAssociationModel(model, path) {
  const parts = path.split(PATH_SEPARATOR)
  let part
  while (part = parts.shift()) {
    const target = `associations.${part}.target`
    if (!_.has(model, target)) {
      throw new Error('Association does not exist')
    }
    model = _.get(model, target)
  }

  return model
}

export function isIncluded(model, path, include) {
  const params = _.filter(include.split(VALUE_SEPARATOR), value => {
    return hasAssociation(model, value)
  })

  let result = false

  _.forEach(params, value => {
    const includeParts = value.split(PATH_SEPARATOR)
    const pathParts = path.split(PATH_SEPARATOR)
    let match = true
    for (let i = 0; i < pathParts.length; i += 1) {
      if (includeParts[i] !== pathParts[i]) {
        match = false
        break
      }
    }
    if (match) {
      result = match
      return false
    }
  })

  return result
}

export function includePath(model, path) {
  const parts = path.split(PATH_SEPARATOR)
  const part = parts.shift()

  const associationModel = getAssociationModel(model, part)

  if (parts.length === 0) {
    return {
      model: associationModel,
      as: part
    }
  }

  return {
    model: associationModel,
    as: part,
    include: [includePath(associationModel, parts.join(PATH_SEPARATOR))]
  }
}

function merge(paths, include) {
  return paths.reduce((include, path) => {
    const exists = include.find(element => element.model === path.model && element.as === path.as)
    if (!exists) {
      include.push(path)
      return include
    }

    if (!_.isArray(exists.include)) {
      exists.include = []
    }
    if (_.isArray(path.include)) {
      exists.include.push(...path.include)
    }

    exists.include = merge(exists.include, [])

    return include
  }, include)
}

export function include(model, include) {
  if (!_.isString(include)) {
    throw new Error('"include" must be string')
  }
  include = include.split(VALUE_SEPARATOR)
  const paths = include.map(path => includePath(model, path))
  return merge(paths, [])
}

export function setRelationship({model, document, path, resourceIdentifiers, transaction}) {
  if (!_.isArray(resourceIdentifiers)) {
    resourceIdentifiers = [resourceIdentifiers]
  }

  const associationModel = getAssociationModel(model, path)

  // TODO support composite primary keys
  const ids = _.map(resourceIdentifiers, resourceIdentifier => resourceIdentifier.id)
  const associationType = model.associations[path].associationType
  return associationModel
    .findAll({
      where: {id: {$in: ids}},
      transaction
    })
    .then(relatedDocuments => {
      // TODO sequelize docs say we should be able todo sth like this document.set('projects', documents)
      switch (associationType) {
        case 'HasOne':
          return document[`set${_.capitalize(path)}`](relatedDocuments.shift(), {transaction})
        case 'HasMany':
          return document[`set${_.capitalize(path)}`](relatedDocuments, {transaction})
        default:
          console.warn('Associations different than "HasOne" and "HasMany" are not supported')
      }
    })
}
<|endoftext|>


<commit_before>import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import NotiFeeds from './NotiFeeds'
import ChatFeeds from './ChatFeeds'
import { defaultChatSubject } from 'constants/defaultValues'
import { fetchNotifications } from 'redux/actions/NotiActions'

class Notification extends Component {
  static propTypes = {
    chatMode: PropTypes.bool.isRequired,
    children: PropTypes.node,
    className: PropTypes.string,
    currentChatSubject: PropTypes.object,
    fetchNotifications: PropTypes.func.isRequired,
    myId: PropTypes.number,
    notifications: PropTypes.array.isRequired,
    position: PropTypes.string
  }

  componentDidMount() {
    const { fetchNotifications } = this.props
    fetchNotifications()
  }

  render() {
    const {
      notifications,
      myId,
      className,
      currentChatSubject: { content = defaultChatSubject, loaded, ...subject },
      children
    } = this.props
    return (

            {children && (

                {children}

            )}
            {loaded && <ChatFeeds content={content} {...subject} />}
            {notifications.length > 0 && (
              <NotiFeeds
                notifications={notifications}
                myId={myId}
                style={{ marginTop: loaded && '1em' }}
              />
            )}

    )
  }

  handleScroll = () => {
    const { scrollHeight, clientHeight, scrollTop } = this.NotificationBox
    if (scrollTop === 0 || scrollHeight - clientHeight === scrollTop) {
      this.setState({ scrollLocked: true })
    } else {
      this.setState({ scrollLocked: false })
    }
  }

  onMouseMove = () => {
    const { scrollLocked } = this.state
    if (scrollLocked) this.setState({ scrollLocked: false })
  }

  onPageScroll = () => {
    const { chatMode } = this.props
    const { scrollLocked } = this.state
    if (scrollLocked) {
      window.scrollTo(0, this.state.scrollPosition)
    }
    if (!chatMode) {
      this.setState({ scrollPosition: window.scrollY })
    }
  }
}

export default connect(
  state => ({
    chatMode: state.ChatReducer.chatMode,
    myId: state.UserReducer.userId,
    notifications: state.NotiReducer.notifications,
    currentChatSubject: state.NotiReducer.currentChatSubject
  }),
  { fetchNotifications }
)(Notification)
<commit_msg>notification css change<commit_after>import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import NotiFeeds from './NotiFeeds'
import ChatFeeds from './ChatFeeds'
import { defaultChatSubject } from 'constants/defaultValues'
import { fetchNotifications } from 'redux/actions/NotiActions'

class Notification extends Component {
  static propTypes = {
    chatMode: PropTypes.bool.isRequired,
    children: PropTypes.node,
    className: PropTypes.string,
    currentChatSubject: PropTypes.object,
    fetchNotifications: PropTypes.func.isRequired,
    myId: PropTypes.number,
    notifications: PropTypes.array.isRequired,
    position: PropTypes.string
  }

  state = {
    scrollPosition: ExecutionEnvironment.canUseDOM ? window.scrollY : 0,
    scrollLocked: false
  }

  componentDidMount() {
    const { fetchNotifications } = this.props
    addEvent(window, 'mousemove', this.onMouseMove)
    addEvent(window, 'scroll', this.onPageScroll)
    fetchNotifications()
  }

  componentWillUnmount() {
    if (ExecutionEnvironment.canUseDOM) {
      removeEvent(window, 'mousemove', this.onMouseMove)
      removeEvent(window, 'scroll', this.onPageScroll)
    }
  }

  render() {
    const {
      notifications,
      myId,
      className,
      currentChatSubject: { content = defaultChatSubject, loaded, ...subject },
      children
    } = this.props
    return (

            {children && (

                {children}

            )}
            {loaded && <ChatFeeds content={content} {...subject} />}
            {notifications.length > 0 && (
              <NotiFeeds
                notifications={notifications}
                myId={myId}
                style={{ marginTop: loaded && '1em' }}
              />
            )}

    )
  }

  handleScroll = () => {
    const { scrollHeight, clientHeight, scrollTop } = this.NotificationBox
    if (scrollTop === 0 || scrollHeight - clientHeight === scrollTop) {
      this.setState({ scrollLocked: true })
    } else {
      this.setState({ scrollLocked: false })
    }
  }

  onMouseMove = () => {
    const { scrollLocked } = this.state
    if (scrollLocked) this.setState({ scrollLocked: false })
  }

  onPageScroll = () => {
    const { chatMode } = this.props
    const { scrollLocked } = this.state
    if (scrollLocked) {
      window.scrollTo(0, this.state.scrollPosition)
    }
    if (!chatMode) {
      this.setState({ scrollPosition: window.scrollY })
    }
  }
}

export default connect(
  state => ({
    chatMode: state.ChatReducer.chatMode,
    myId: state.UserReducer.userId,
    notifications: state.NotiReducer.notifications,
    currentChatSubject: state.NotiReducer.currentChatSubject
  }),
  { fetchNotifications }
)(Notification)
<|endoftext|>


<commit_before>/*
Copyright (c) 2003-2012, CKSource - Frederico Knabben. All rights reserved.
For licensing, see LICENSE.html or http://ckeditor.com/license
*/

CKEDITOR.editorConfig = function( config )
{
	// Define changes to default configuration here. For example:
	// config.language = 'fr';
	// config.uiColor = '#AADC6E';
};
<commit_msg>forcePasteAsPlainText for ckeditor, useful when pasting from word<commit_after>/*
Copyright (c) 2003-2012, CKSource - Frederico Knabben. All rights reserved.
For licensing, see LICENSE.html or http://ckeditor.com/license
*/

CKEDITOR.editorConfig = function( config )
{
	// Define changes to default configuration here. For example:
	// config.language = 'fr';
	// config.uiColor = '#AADC6E';
	config.forcePasteAsPlainText = true;
};
<|endoftext|>


<commit_before>var util = require('../util');
var stats = require('../stats');
var countmap = require('./countmap');

var types = {
  "count": measure({
    name: "count",
    set:  "this.cell.num"
  }),
  "nulls": measure({
    name: "nulls",
    set:  "this.cell.num - this.cell.valid"
  }),
  "valid": measure({
    name: "valid",
    set:  "this.cell.valid"
  }),
  "data": measure({
    name: "data",
    init: "this.data = [];",
    add:  "this.data.push(t);",
    rem:  "this.data.splice(this.data.indexOf(t), 1);",
    set:  "this.data", idx: -1
  }),
  "distinct": measure({
    name: "distinct",
    init: "this.distinct = new this.map();",
    add:  "this.distinct.add(v);",
    rem:  "this.distinct.rem(v);",
    set:  "this.distinct.size()", idx: -1
  }),
  "sum": measure({
    name: "sum",
    init: "this.sum = 0;",
    add:  "this.sum += v;",
    rem:  "this.sum -= v;",
    set:  "this.sum"
  }),
  "mean": measure({
    name: "mean",
    init: "this.mean = 0;",
    add:  "var d = v - this.mean; this.mean += d / this.cell.num;",
    rem:  "var d = v - this.mean; this.mean -= d / this.cell.num;",
    set:  "this.mean"
  }),
  "var": measure({
    name: "var",
    init: "this.dev = 0;",
    add:  "this.dev += d * (v - this.mean);",
    rem:  "this.dev -= d * (v - this.mean);",
    set:  "this.dev / (this.cell.num-1)",
    req:  ["mean"], idx: 1
  }),
  "varp": measure({
    name: "varp",
    set:  "this.dev / this.cell.num",
    req:  ["var"], idx: 2
  }),
  "stdev": measure({
    name: "stdev",
    set:  "Math.sqrt(this.dev / (this.cell.num-1))",
    req:  ["var"], idx: 2
  }),
  "stdevp": measure({
    name: "stdevp",
    set:  "Math.sqrt(this.dev / this.cell.num)",
    req:  ["var"], idx: 2
  }),
  "median": measure({
    name: "median",
    set:  "this.stats.median(this.data, this.get)",
    req:  ["data"], idx: 3
  }),
  "argmin": measure({
    name: "argmin",
    add:  "if (v < this.min) this.argmin = t;",
    rem:  "this.argmin = null;",
    set:  "this.argmin || this.data[this.stats.extent.index(this.data, this.get)[0]]",
    req:  ["min", "data"], idx: 3
  }),
  "argmax": measure({
    name: "argmax",
    add:  "if (v > this.max) this.argmax = t;",
    rem:  "this.argmax = null;",
    set:  "this.argmax || this.data[this.stats.extent.index(this.data, this.get)[1]]",
    req:  ["max", "data"], idx: 3
  }),
  "min": measure({
    name: "min",
    init: "this.min = +Infinity;",
    add:  "if (v < this.min) this.min = v;",
    rem:  "this.min = null;",
    set:  "this.min != null ? this.min : this.stats.extent(this.data, this.get)[0]",
    req:  ["data"], idx: 4
  }),
  "max": measure({
    name: "max",
    init: "this.max = -Infinity;",
    add:  "if (v > this.max) this.max = v;",
    rem:  "this.max = null;",
    set:  "this.max != null ? this.max : this.stats.extent(this.data, this.get)[1]",
    req:  ["data"], idx: 4
  })
};

function measure(base) {
  return function(out) {
    var m = util.extend({init:"", add:"", rem:"", idx:0}, base);
    m.out = out || base.name;
    return m;
  };
}

function resolve(agg) {
  function collect(m, a) {
    (a.req || []).forEach(function(r) {
      if (!m[r]) collect(m, m[r] = types[r]());
    });
    return m;
  }
  var map = agg.reduce(
    collect,
    agg.reduce(function(m, a) { return (m[a.name] = a, m); }, {})
  );
  var all = [];
  for (var k in map) all.push(map[k]);
  all.sort(function(a,b) { return a.idx - b.idx; });
  return all;
}

function compile(agg, accessor) {
  var all = resolve(agg),
      ctr = "this.tuple = t; this.cell = c; c.valid = 0;",
      add = "if (!this.valid(v)) return; this.cell.valid++;",
      rem = "if (!this.valid(v)) return; this.cell.valid--;",
      set = "var t = this.tuple;";

  all.forEach(function(a) {
    if (a.idx < 0) {
      ctr = a.init + ctr;
      add = a.add + add;
      rem = a.rem + rem;
    } else {
      ctr += a.init;
      add += a.add;
      rem += a.rem;
    }
  });
  agg.forEach(function(a) {
    set += "this.assign(t,'"+a.out+"',"+a.set+");";
  });
  set += "return t;";

  ctr = Function("c", "t", ctr);
  ctr.prototype.assign = assign;
  ctr.prototype.add = Function("t", "var v = this.get(t);" + add);
  ctr.prototype.rem = Function("t", "var v = this.get(t);" + rem);
  ctr.prototype.set = Function(set);
  ctr.prototype.get = accessor;
  ctr.prototype.mod = mod;
  ctr.prototype.map = countmap;
  ctr.prototype.stats = stats;
  ctr.prototype.valid = util.isNotNull;
  return ctr;
}

function assign(x, name, val) {
  x[name] = val;
}

function mod(v_new, v_old) {
  if (v_old === undefined || v_old === v_new) return;
  this.rem(v_old);
  this.add(v_new);
};

types.create = compile;
module.exports = types;<commit_msg>Allow custom measure assignment function.<commit_after>var util = require('../util');
var stats = require('../stats');
var countmap = require('./countmap');

var types = {
  "count": measure({
    name: "count",
    set:  "this.cell.num"
  }),
  "nulls": measure({
    name: "nulls",
    set:  "this.cell.num - this.cell.valid"
  }),
  "valid": measure({
    name: "valid",
    set:  "this.cell.valid"
  }),
  "data": measure({
    name: "data",
    init: "this.data = [];",
    add:  "this.data.push(t);",
    rem:  "this.data.splice(this.data.indexOf(t), 1);",
    set:  "this.data", idx: -1
  }),
  "distinct": measure({
    name: "distinct",
    init: "this.distinct = new this.map();",
    add:  "this.distinct.add(v);",
    rem:  "this.distinct.rem(v);",
    set:  "this.distinct.size()", idx: -1
  }),
  "sum": measure({
    name: "sum",
    init: "this.sum = 0;",
    add:  "this.sum += v;",
    rem:  "this.sum -= v;",
    set:  "this.sum"
  }),
  "mean": measure({
    name: "mean",
    init: "this.mean = 0;",
    add:  "var d = v - this.mean; this.mean += d / this.cell.num;",
    rem:  "var d = v - this.mean; this.mean -= d / this.cell.num;",
    set:  "this.mean"
  }),
  "var": measure({
    name: "var",
    init: "this.dev = 0;",
    add:  "this.dev += d * (v - this.mean);",
    rem:  "this.dev -= d * (v - this.mean);",
    set:  "this.dev / (this.cell.num-1)",
    req:  ["mean"], idx: 1
  }),
  "varp": measure({
    name: "varp",
    set:  "this.dev / this.cell.num",
    req:  ["var"], idx: 2
  }),
  "stdev": measure({
    name: "stdev",
    set:  "Math.sqrt(this.dev / (this.cell.num-1))",
    req:  ["var"], idx: 2
  }),
  "stdevp": measure({
    name: "stdevp",
    set:  "Math.sqrt(this.dev / this.cell.num)",
    req:  ["var"], idx: 2
  }),
  "median": measure({
    name: "median",
    set:  "this.stats.median(this.data, this.get)",
    req:  ["data"], idx: 3
  }),
  "argmin": measure({
    name: "argmin",
    add:  "if (v < this.min) this.argmin = t;",
    rem:  "this.argmin = null;",
    set:  "this.argmin || this.data[this.stats.extent.index(this.data, this.get)[0]]",
    req:  ["min", "data"], idx: 3
  }),
  "argmax": measure({
    name: "argmax",
    add:  "if (v > this.max) this.argmax = t;",
    rem:  "this.argmax = null;",
    set:  "this.argmax || this.data[this.stats.extent.index(this.data, this.get)[1]]",
    req:  ["max", "data"], idx: 3
  }),
  "min": measure({
    name: "min",
    init: "this.min = +Infinity;",
    add:  "if (v < this.min) this.min = v;",
    rem:  "this.min = null;",
    set:  "this.min != null ? this.min : this.stats.extent(this.data, this.get)[0]",
    req:  ["data"], idx: 4
  }),
  "max": measure({
    name: "max",
    init: "this.max = -Infinity;",
    add:  "if (v > this.max) this.max = v;",
    rem:  "this.max = null;",
    set:  "this.max != null ? this.max : this.stats.extent(this.data, this.get)[1]",
    req:  ["data"], idx: 4
  })
};

function measure(base) {
  return function(out) {
    var m = util.extend({init:"", add:"", rem:"", idx:0}, base);
    m.out = out || base.name;
    return m;
  };
}

function resolve(agg) {
  function collect(m, a) {
    (a.req || []).forEach(function(r) {
      if (!m[r]) collect(m, m[r] = types[r]());
    });
    return m;
  }
  var map = agg.reduce(
    collect,
    agg.reduce(function(m, a) { return (m[a.name] = a, m); }, {})
  );
  var all = [];
  for (var k in map) all.push(map[k]);
  all.sort(function(a,b) { return a.idx - b.idx; });
  return all;
}

function create(agg, accessor, mutator) {
  var all = resolve(agg),
      ctr = "this.tuple = t; this.cell = c; c.valid = 0;",
      add = "if (!this.valid(v)) return; this.cell.valid++;",
      rem = "if (!this.valid(v)) return; this.cell.valid--;",
      set = "var t = this.tuple;";

  all.forEach(function(a) {
    if (a.idx < 0) {
      ctr = a.init + ctr;
      add = a.add + add;
      rem = a.rem + rem;
    } else {
      ctr += a.init;
      add += a.add;
      rem += a.rem;
    }
  });
  agg.forEach(function(a) {
    set += "this.assign(t,'"+a.out+"',"+a.set+");";
  });
  set += "return t;";

  ctr = Function("c", "t", ctr);
  ctr.prototype.assign = mutator || assign;
  ctr.prototype.add = Function("t", "var v = this.get(t);" + add);
  ctr.prototype.rem = Function("t", "var v = this.get(t);" + rem);
  ctr.prototype.set = Function(set);
  ctr.prototype.get = accessor;
  ctr.prototype.mod = mod;
  ctr.prototype.map = countmap;
  ctr.prototype.stats = stats;
  ctr.prototype.valid = util.isNotNull;
  return ctr;
}

function assign(x, name, val) {
  x[name] = val;
}

function mod(v_new, v_old) {
  if (v_old === undefined || v_old === v_new) return;
  this.rem(v_old);
  this.add(v_new);
};

types.create = create;
module.exports = types;<|endoftext|>


<commit_before>import select from 'select-dom';
import linkifyUrls from 'linkify-urls';
import linkifyIssues from 'linkify-issues';
import {getOwnerAndRepo} from '../libs/page-detect';
import getTextNodes from '../libs/get-text-nodes';

// Shared class necessary to avoid also shortening the links
export const linkifiedURLClass = 'rgh-linkified-code';

const {
	ownerName,
	repoName
} = getOwnerAndRepo();

const options = {
	user: ownerName,
	repo: repoName,
	type: 'dom',
	baseUrl: ''
};

export const editTextNodes = (fn, el) => {
	// Spread required because the elements will change and the TreeWalker will break
	for (const textNode of [...getTextNodes(el)]) {
		if (fn === linkifyUrls && textNode.textContent.length < 11) { // Shortest url: http://j.mp
			continue;
		}
		const linkified = fn(textNode.textContent, options);
		if (linkified.children.length > 0) { // Children are
			if (fn === linkifyIssues) {
				// Enable native issue title fetch
				for (const link of linkified.children) {
					const issue = link.href.split('/').pop();
					link.setAttribute('class', `issue-link js-issue-link tooltipped tooltipped-ne ${linkifiedURLClass}`);
					link.setAttribute('data-error-text', 'Failed to load issue title');
					link.setAttribute('data-permission-text', 'Issue title is private');
					link.setAttribute('data-url', link.href);
					link.setAttribute('data-id', `rgh-issue-${issue}`);
				}
			}
			textNode.replaceWith(linkified);
		}
	}
};

export default () => {
	const wrappers = select.all(`.blob-wrapper:not(.${linkifiedURLClass})`);

	// Don't linkify any already linkified code
	if (wrappers.length === 0) {
		return;
	}

	// Linkify full URLs
	// `.blob-code-inner` in diffs
	// `pre` in GitHub comments
	for (const el of select.all('.blob-code-inner, pre', wrappers)) {
		editTextNodes(linkifyUrls, el);
	}

	// Linkify issue refs in comments
	for (const el of select.all('span.pl-c', wrappers)) {
		editTextNodes(linkifyIssues, el);
	}

	// Mark code block as touched
	for (const el of wrappers) {
		el.classList.add(linkifiedURLClass);
	}
};
<commit_msg>Don't shorten links in code (#1145)<commit_after>import select from 'select-dom';
import linkifyUrls from 'linkify-urls';
import linkifyIssues from 'linkify-issues';
import {getOwnerAndRepo} from '../libs/page-detect';
import getTextNodes from '../libs/get-text-nodes';

// Shared class necessary to avoid also shortening the links
export const linkifiedURLClass = 'rgh-linkified-code';

const {
	ownerName,
	repoName
} = getOwnerAndRepo();

const options = {
	user: ownerName,
	repo: repoName,
	type: 'dom',
	baseUrl: '',
	attributes: {
		class: linkifiedURLClass // Necessary to avoid also shortening the links
	}
};

export const editTextNodes = (fn, el) => {
	// Spread required because the elements will change and the TreeWalker will break
	for (const textNode of [...getTextNodes(el)]) {
		if (fn === linkifyUrls && textNode.textContent.length < 11) { // Shortest url: http://j.mp
			continue;
		}
		const linkified = fn(textNode.textContent, options);
		if (linkified.children.length > 0) { // Children are
			if (fn === linkifyIssues) {
				// Enable native issue title fetch
				for (const link of linkified.children) {
					const issue = link.href.split('/').pop();
					link.setAttribute('class', 'issue-link js-issue-link tooltipped tooltipped-ne');
					link.setAttribute('data-error-text', 'Failed to load issue title');
					link.setAttribute('data-permission-text', 'Issue title is private');
					link.setAttribute('data-url', link.href);
					link.setAttribute('data-id', `rgh-issue-${issue}`);
				}
			}
			textNode.replaceWith(linkified);
		}
	}
};

export default () => {
	const wrappers = select.all(`.blob-wrapper:not(.${linkifiedURLClass})`);

	// Don't linkify any already linkified code
	if (wrappers.length === 0) {
		return;
	}

	// Linkify full URLs
	// `.blob-code-inner` in diffs
	// `pre` in GitHub comments
	for (const el of select.all('.blob-code-inner, pre', wrappers)) {
		editTextNodes(linkifyUrls, el);
	}

	// Linkify issue refs in comments
	for (const el of select.all('span.pl-c', wrappers)) {
		editTextNodes(linkifyIssues, el);
	}

	// Mark code block as touched
	for (const el of wrappers) {
		el.classList.add(linkifiedURLClass);
	}
};
<|endoftext|>


<commit_before>/**
 * Angular Reftracker
 *
 * Copyright (c) 2014 l0co
 *
 * The MIT License (MIT)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 * @author l0co@wp.pl
 * @license MIT
 */

'use strict';

var refTracker = angular.module('refTracker', []);

/**
 * References cache
 */
refTracker.provider('refCache', function() {

    // default id resolver working with UUID id-s in "id" object field
    var idResolver = function(object) {
        if (object.id)
            return object.id;
        return null;
    };

    /**
     * Update id resolver
     * @param {function} func function(object) returning unique string id of the object, or null if the object
     *                        has no id (so it won't be considered for reference management).
     */
    this.setIDResolver = function(func) {
        idResolver = func;
    };

    this.$get = ['$log',
        function($log) {
            return new function RefCache() {
                var cache = {};

                function CacheEntry(id) {
                    this.id = id;
                    this.refCount = 0;
                    this.reference = null;
                }

                function isObjectOrArray(object) {
                    return object && typeof object === "object";
                }

                function isArray(object) {
                    return Array.isArray(object);
                }

                function isObject(object) {
                    return isObjectOrArray(object) && !isArray(object);
                }

                function isString(object) {
                    return typeof object == "string";
                }

                /**
                 * Scans object/array recursively to look for references
                 * @param object Base object
                 * @param operation 'add' or 'remove'
                 * @param visited Visited elements
                 * @return {*}
                 */
                function scanR(object, operation, visited) {
                    visited = visited || {};

                    // array part
                    if (isArray(object)) {
                        var array = [];
                        angular.forEach(object, function(o) {
                            array.push(scanR(o, operation, visited));
                        });
                        return array;
                    }

                    // unknown part
                    if (!isObject(object))
                        return object;

                    // object part
                    var id = idResolver(object);
                    if (!id)
                        return object;

                    if (!visited[id]) {
                        visited[id] = true;
                        var cacheEntry = cache[id];

                        if (operation == 'add') {

                            // add new reference

                            if (!cacheEntry) {
                                // object not in cache
                                cacheEntry = new CacheEntry(id);
                                cacheEntry.reference = object;
                                cache[id] = cacheEntry;
                            }

                            cacheEntry.refCount++;

                            var ref = cacheEntry.reference;
                            angular.extend(ref, object);
                            for (var prop in ref)
                                ref[prop] = scanR(ref[prop], operation, visited);

                            $log.debug('new object', id, ref, 'with refcount', cacheEntry.refCount);

                            return ref;

                        } else {

                            // remove reference

                            if (cacheEntry) {
                                cacheEntry.refCount--;

                                $log.debug('remove object', id, cacheEntry.reference, 'with refcount',
                                    cacheEntry.refCount);

                                if (cacheEntry.refCount<=0) {
                                    delete cache[id];
                                }

                                for (var prop in cacheEntry.reference)
                                    scanR(cacheEntry.reference[prop], operation, visited);
                            }

                        }
                    }

                    return object;
                }

                /**
                 * Adds new object reference to cache
                 * @param {object} object Object to add (will be added recursively)
                 * @returns {object} referenced object
                 */
                this.addReference = function(object) {
                    if (!isObjectOrArray(object))
                        return object;
                    return scanR(object, 'add');
                };

                /**
                 * Removes the object reference from cache
                 * @param {object} object Object to remove (will be removed recursively)
                 */
                this.removeReference = function(object) {
                    if (!isObjectOrArray(object))
                        return;
                    scanR(object, 'remove');
                };

                /**
                 * Returns the managed object reference
                 * @param identity {object|string} Object reference or its id.
                 * @return {object} Managed object reference or null if such reference is not found.
                 */
                this.findReference = function(identity) {
                    var id = null;
                    if (isString(identity))
                        id = identity;

                    if (!id) {
                        if (!isObject(identity))
                            return null;

                        id = idResolver(identity);
                        if (!id)
                            return null;
                    }

                    var cacheEntry = cache[id];
                    if (cacheEntry)
                        return cacheEntry.reference;

                    return null;
                };

                /**
                 * Executed on asynchronous object event
                 * @param identity {object|string} Object changed asynchronously or its id
                 * @param event {object} The event object
                 * @param callback {function} function(object, event) triggered on manages reference of object. Null
                 *                            assumes default behavior which is copy the event properties to the managed
                 *                            object reference.
                 */
                this.async = function(identity, event, callback) {
                    callback = callback || function(object, event) {
                        angular.extend(object, event);
                    };

                    var ref = this.findReference(identity);
                    if (ref)
                        callback(ref, event);
                };

            };
        }
    ];

});

/**
 * Managed references scope
 */
refTracker.factory('ManagedScope', ['refCache',
    function(refCache) {

        /**
         * Managed references scope constructor
         * @param {object} $scope scope to join
         */
        return function ManagedScope($scope) {
            var referenced = [];

            function removeFromReferenced(object) {
                // find out if the object is already referenced
                var idx = referenced.indexOf(object);
                if (idx>-1) {
                    refCache.removeReference(object); // remove from referenced objects
                    referenced.splice(idx, 1);
                }
            }

            /**
             * Creates new object reference and adds it to the $scope as $scope.propName
             * @param propName {string} Scope property name
             * @param object {object|object[]} Object to add
             */
            this.set = function(propName, object) {
                // remove already existing references of previous value
                if ($scope[propName])
                    removeFromReferenced($scope[propName]);

                object = refCache.addReference(object);
                referenced.push(object); // add to referenced objects

                $scope[propName] = object;
            };

            /**
             * This function needs to be called if you join new object not to the scope directly (for that is set()),
             * but to the object already set in managed scope and tracked by reftracker. If such new reference
             * is created in existing object, this function adds new reference to the object withing the scope.
             * @param object {object|object[]} Newly created object joined to already managed reference
             */
            this.add = function(object) {
                return refCache.addReference(object);
            };

            /**
             * This function needs to be called if you remove new object from the managed scope either it's
             * direct scope object, or is removed from already managed object structure.
             * @param object {object|object[]} Object removed from scope or already managed reference
             */
            this.remove = function(object) {
                removeFromReferenced(object);
                return refCache.removeReference(object);
            };

            /**
             * refCache cleanup function on scope destroy
             */
            $scope.$on('$destroy', function() {
                angular.forEach(referenced, function(object) {
                    refCache.removeReference(object);
                });
                referenced = [];
            });
        }

    }
]);
<commit_msg>add update object reference method<commit_after>/**
 * Angular Reftracker
 *
 * Copyright (c) 2014 l0co
 *
 * The MIT License (MIT)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 * @author l0co@wp.pl
 * @license MIT
 */

'use strict';

var refTracker = angular.module('refTracker', []);

/**
 * References cache
 */
refTracker.provider('refCache', function() {

    // default id resolver working with UUID id-s in "id" object field
    var idResolver = function(object) {
        if (object.id)
            return object.id;
        return null;
    };

    /**
     * Update id resolver
     * @param {function} func function(object) returning unique string id of the object, or null if the object
     *                        has no id (so it won't be considered for reference management).
     */
    this.setIDResolver = function(func) {
        idResolver = func;
    };

    this.$get = ['$log',
        function($log) {
            return new function RefCache() {
                var cache = {};

                function CacheEntry(id) {
                    this.id = id;
                    this.refCount = 0;
                    this.reference = null;
                }

                function isObjectOrArray(object) {
                    return object && typeof object === "object";
                }

                function isArray(object) {
                    return Array.isArray(object);
                }

                function isObject(object) {
                    return isObjectOrArray(object) && !isArray(object);
                }

                function isString(object) {
                    return typeof object == "string";
                }

                /**
                 * Scans object/array recursively to look for references
                 * @param object Base object
                 * @param operation 'add' or 'remove'
                 * @param visited Visited elements
                 * @return {*}
                 */
                function scanR(object, operation, visited) {
                    visited = visited || {};

                    // array part
                    if (isArray(object)) {
                        var array = [];
                        angular.forEach(object, function(o) {
                            array.push(scanR(o, operation, visited));
                        });
                        return array;
                    }

                    // unknown part
                    if (!isObject(object))
                        return object;

                    // object part
                    var id = idResolver(object);
                    if (!id)
                        return object;

                    if (!visited[id]) {
                        visited[id] = true;
                        var cacheEntry = cache[id];

                        if (operation == 'add') {

                            // add new reference

                            if (!cacheEntry) {
                                // object not in cache
                                cacheEntry = new CacheEntry(id);
                                cacheEntry.reference = object;
                                cache[id] = cacheEntry;
                            }

                            cacheEntry.refCount++;

                            var ref = cacheEntry.reference;
                            angular.extend(ref, object);
                            for (var prop in ref)
                                ref[prop] = scanR(ref[prop], operation, visited);

                            $log.debug('new object', id, ref, 'with refcount', cacheEntry.refCount);

                            return ref;

                        } else {

                            // remove reference

                            if (cacheEntry) {
                                cacheEntry.refCount--;

                                $log.debug('remove object', id, cacheEntry.reference, 'with refcount',
                                    cacheEntry.refCount);

                                if (cacheEntry.refCount<=0) {
                                    delete cache[id];
                                }

                                for (var prop in cacheEntry.reference)
                                    scanR(cacheEntry.reference[prop], operation, visited);
                            }

                        }
                    }

                    return object;
                }

                /**
                 * Adds new object reference to cache
                 * @param {object} object Object to add (will be added recursively)
                 * @returns {object} referenced object
                 */
                this.addReference = function(object) {
                    if (!isObjectOrArray(object))
                        return object;
                    return scanR(object, 'add');
                };

                /**
                 * Removes the object reference from cache
                 * @param {object} object Object to remove (will be removed recursively)
                 */
                this.removeReference = function(object) {
                    if (!isObjectOrArray(object))
                        return;
                    scanR(object, 'remove');
                };

                /**
                 * Returns the managed object reference
                 * @param identity {object|string} Object reference or its id.
                 * @return {object} Managed object reference or null if such reference is not found.
                 */
                this.findReference = function(identity) {
                    var id = null;
                    if (isString(identity))
                        id = identity;

                    if (!id) {
                        if (!isObject(identity))
                            return null;

                        id = idResolver(identity);
                        if (!id)
                            return null;
                    }

                    var cacheEntry = cache[id];
                    if (cacheEntry)
                        return cacheEntry.reference;

                    return null;
                };

                /**
                 * Executed on asynchronous object event
                 * @param identity {object|string} Object changed asynchronously or its id
                 * @param event {object} The event object (if null, identity will be used as the event object)
                 * @param callback {function} function(object, event) triggered on manages reference of object. Null
                 *                            assumes default behavior which is copy the event properties to the managed
                 *                            object reference.
                 */
                this.async = function(identity, event, callback) {
                    callback = callback || function(object, event) {
                        angular.extend(object, event);
                    };

                    event = event || identity;

                    var ref = this.findReference(identity);
                    if (ref)
                        callback(ref, event);
                };

                /**
                 * Updates the object reference with new instance
                 * @param object {object} Object to update
                 */
                this.update = function(object) {
                    this.async(object);
                }

            };
        }
    ];

});

/**
 * Managed references scope
 */
refTracker.factory('ManagedScope', ['refCache',
    function(refCache) {

        /**
         * Managed references scope constructor
         * @param {object} $scope scope to join
         */
        return function ManagedScope($scope) {
            var referenced = [];

            function removeFromReferenced(object) {
                // find out if the object is already referenced
                var idx = referenced.indexOf(object);
                if (idx>-1) {
                    refCache.removeReference(object); // remove from referenced objects
                    referenced.splice(idx, 1);
                }
            }

            /**
             * Creates new object reference and adds it to the $scope as $scope.propName
             * @param propName {string} Scope property name
             * @param object {object|object[]} Object to add
             */
            this.set = function(propName, object) {
                // remove already existing references of previous value
                if ($scope[propName])
                    removeFromReferenced($scope[propName]);

                object = refCache.addReference(object);
                referenced.push(object); // add to referenced objects

                $scope[propName] = object;
            };

            /**
             * This function needs to be called if you join new object not to the scope directly (for that is set()),
             * but to the object already set in managed scope and tracked by reftracker. If such new reference
             * is created in existing object, this function adds new reference to the object withing the scope.
             * @param object {object|object[]} Newly created object joined to already managed reference
             */
            this.add = function(object) {
                return refCache.addReference(object);
            };

            /**
             * This function needs to be called if you remove new object from the managed scope either it's
             * direct scope object, or is removed from already managed object structure.
             * @param object {object|object[]} Object removed from scope or already managed reference
             */
            this.remove = function(object) {
                removeFromReferenced(object);
                return refCache.removeReference(object);
            };

            /**
             * refCache cleanup function on scope destroy
             */
            $scope.$on('$destroy', function() {
                angular.forEach(referenced, function(object) {
                    refCache.removeReference(object);
                });
                referenced = [];
            });
        }

    }
]);
<|endoftext|>


<commit_before>var utils = require('../utils.js'),
    is = utils.is;
//a set of functions for parsing, converting and intepolating color values
var Color = {};
Color.TRANSPARENT  = 'transparent';
// TODO: Color.RED, Color.BLUE, ....
Color.HEX_RE       = /^#?([a-fA-F\d]{2})([a-fA-F\d]{2})([a-fA-F\d]{2})$/i;
Color.HEX_SHORT_RE = /^#?([a-fA-F\d])([a-fA-F\d])([a-fA-F\d])$/i;
Color.RGB_RE       = /^rgb\s*\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)$/i;
Color.RGBA_RE      = /^rgba\s*\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*(\d*[.]?\d+)\s*\)$/i;
Color.HSL_RE       = /^hsl\s*\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*%\s*,\s*([0-9]{1,3})\s*%\s*\)$/i;
Color.HSLA_RE      = /^hsla\s*\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*%\s*,\s*([0-9]{1,3})\s*%\s*,\s*(\d*[.]?\d+)\s*\)$/i;
Color.from = function(test) {
    return is.str(test) ? Color.fromStr(test) : (test.r && test);
};
Color.fromStr = function(str) {
    return Color.fromHex(str)
        || Color.fromRgb(str)
        || Color.fromRgba(str)
        || Color.fromHsl(str)
        || { r: 0, g: 0, b: 0, a: 0};
};
Color.fromHex = function(hex) {
    if (hex[0] !== '#') return null;
    var result = Color.HEX_RE.exec(hex);
    if (result) {
        return {
            r: parseInt(result[1], 16),
            g: parseInt(result[2], 16),
            b: parseInt(result[3], 16),
            a: 1
        };
    }
    result = Color.HEX_SHORT_RE.exec(hex);
    return result ? {
        r: parseInt(result[1] + result[1], 16),
        g: parseInt(result[2] + result[2], 16),
        b: parseInt(result[3] + result[3], 16),
        a: 1
    } : null;
};
Color.fromRgb = function(rgb) {
    if (rgb.indexOf('rgb(') !== 0) return null;
    var result = Color.RGB_RE.exec(rgb);
    return result ? {
        r: parseInt(result[1]),
        g: parseInt(result[2]),
        b: parseInt(result[3]),
        a: 1
    } : null;
};
Color.fromRgba = function(rgba) {
    if (rgba.indexOf('rgba(') !== 0) return null;
    var result = Color.RGBA_RE.exec(rgba);
    return result ? {
        r: parseInt(result[1]),
        g: parseInt(result[2]),
        b: parseInt(result[3]),
        a: parseFloat(result[4])
    } : null;
};
Color.fromHslVal = function(hue, sat, light) {
    var hueToRgb = Color.hueToRgb;
    var t2;
    if (light <= 0.5) {
        t2 = light * (sat + 1);
    } else {
        t2 = light + sat - (light * sat);
    }
    var t1 = light * 2 - t2;
    return { r: hueToRgb(t1, t2, hue + 2),
             g: hueToRgb(t1, t2, hue),
             b: hueToRgb(t1, t2, hue - 2),
             a: 1 };

};
Color.fromHsl = function(hsl) {
    return null;
    if (hsl.indexOf('hsl(') !== 0) return null;
    var result = Color.HSL_RE.exec(hsl);
    return result ? Color.fromHslVal(
        parseInt(result[1]) / 180 * Math.PI,
        parseInt(result[2]) / 100,
        parseInt(result[3]) / 100
    ) : null;
};
Color.fromHsla = function(hsla) {
    if (hsla.indexOf('hsla(') !== 0) return null;
    var result = Color.HSLA_RE.exec(hsl);
    if (!result) return null;
    result = Color.fromHslVal(
        parseInt(result[1]) / 180 * Math.PI,
        parseInt(result[2]) / 100,
        parseInt(result[3]) / 100
    );
    result.a = parseFloat(result[4]);
    return result;
};
Color.hueToRgb = function(t1, t2, hue) {
    if (hue < 0) hue += 6;
    if (hue >= 6) hue -= 6;
    if (hue < 1) return (t2 - t1) * hue + t1;
    else if (hue < 3) return t2;
    else if (hue < 4) return (t2 - t1) * (4 - hue) + t1;
    else return t1;
};
Color.rgb = function(r, g, b) {
    return 'rgb(' + (r * 255) + ',' + (g * 255) + ',' + (b * 255) + ')';
};
Color.rgba = function(r, g, b, a) {
    return 'rgba(' + (r * 255) + ',' + (g * 255) + ',' + (b * 255) + ','
                               + (is.defined(a) ? a.toFixed(2) : 1.0) + ')';
};
Color.hsl = function(h, s, l) {
    return Color.dhsl(h / Math.PI * 180, s, l);
};
Color.dhsl = function(dh, s, l) {
    return 'hsl(' + Math.floor(dh) + ',' +
                    Math.floor(s * 100) + '%,' +
                    Math.floor(l * 100) + '%)';
};
Color.hsla = function(h, s, l, a) {
    return Color.dhsla(h / Math.PI * 180, s, l, a);
};
Color.dhsla = function(dh, s, l, a) {
    return 'hsla('+ Math.floor(dh) + ',' +
                    Math.floor(s * 100) + '%,' +
                    Math.floor(l * 100) + '%,' +
                    (is.defined(a) ? a.toFixed(2) : 1.0) + ')';
};
Color.adapt = function(color) {
    if (!color) return null;
    if (is.str(color)) return color;
    // "r" is reserved for gradients, so we test for "g" to be sure
    if (is.defined(color.g)) return Color.toRgbaStr(color);
    if (is.defined(color.h)) return Color.toHslaStr(color);
}
Color.toRgbaStr = function(color) {
    return Color.rgba(color.r,
                      color.g,
                      color.b,
                      color.a);
};
Color.toHslaStr = function(color) {
    return Color.hsla(color.h,
                      color.s,
                      color.l,
                      color.a);
};
Color.interpolate = function(c1, c2, t) {
    return {
        r: Math.round(utils.interpolateFloat(c1.r, c2.r, t)),
        g: Math.round(utils.interpolateFloat(c1.g, c2.g, t)),
        b: Math.round(utils.interpolateFloat(c1.b, c2.b, t)),
        a: utils.interpolateFloat(c1.a, c2.a, t)
    };
};

module.exports = Color;
<commit_msg>less math in converting colors to string<commit_after>var utils = require('../utils.js'),
    is = utils.is;
//a set of functions for parsing, converting and intepolating color values
var Color = {};
Color.TRANSPARENT  = 'transparent';
// TODO: Color.RED, Color.BLUE, ....
Color.HEX_RE       = /^#?([a-fA-F\d]{2})([a-fA-F\d]{2})([a-fA-F\d]{2})$/i;
Color.HEX_SHORT_RE = /^#?([a-fA-F\d])([a-fA-F\d])([a-fA-F\d])$/i;
Color.RGB_RE       = /^rgb\s*\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)$/i;
Color.RGBA_RE      = /^rgba\s*\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*(\d*[.]?\d+)\s*\)$/i;
Color.HSL_RE       = /^hsl\s*\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*%\s*,\s*([0-9]{1,3})\s*%\s*\)$/i;
Color.HSLA_RE      = /^hsla\s*\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*%\s*,\s*([0-9]{1,3})\s*%\s*,\s*(\d*[.]?\d+)\s*\)$/i;
Color.from = function(test) {
    return is.str(test) ? Color.fromStr(test) : (test.r && test);
};
Color.fromStr = function(str) {
    return Color.fromHex(str)
        || Color.fromRgb(str)
        || Color.fromRgba(str)
        || Color.fromHsl(str)
        || { r: 0, g: 0, b: 0, a: 0};
};
Color.fromHex = function(hex) {
    if (hex[0] !== '#') return null;
    var result = Color.HEX_RE.exec(hex);
    if (result) {
        return {
            r: parseInt(result[1], 16),
            g: parseInt(result[2], 16),
            b: parseInt(result[3], 16),
            a: 1
        };
    }
    result = Color.HEX_SHORT_RE.exec(hex);
    return result ? {
        r: parseInt(result[1] + result[1], 16),
        g: parseInt(result[2] + result[2], 16),
        b: parseInt(result[3] + result[3], 16),
        a: 1
    } : null;
};
Color.fromRgb = function(rgb) {
    if (rgb.indexOf('rgb(') !== 0) return null;
    var result = Color.RGB_RE.exec(rgb);
    return result ? {
        r: parseInt(result[1]),
        g: parseInt(result[2]),
        b: parseInt(result[3]),
        a: 1
    } : null;
};
Color.fromRgba = function(rgba) {
    if (rgba.indexOf('rgba(') !== 0) return null;
    var result = Color.RGBA_RE.exec(rgba);
    return result ? {
        r: parseInt(result[1]),
        g: parseInt(result[2]),
        b: parseInt(result[3]),
        a: parseFloat(result[4])
    } : null;
};
Color.fromHslVal = function(hue, sat, light) {
    var hueToRgb = Color.hueToRgb;
    var t2;
    if (light <= 0.5) {
        t2 = light * (sat + 1);
    } else {
        t2 = light + sat - (light * sat);
    }
    var t1 = light * 2 - t2;
    return { r: hueToRgb(t1, t2, hue + 2),
             g: hueToRgb(t1, t2, hue),
             b: hueToRgb(t1, t2, hue - 2),
             a: 1 };

};
Color.fromHsl = function(hsl) {
    return null;
    if (hsl.indexOf('hsl(') !== 0) return null;
    var result = Color.HSL_RE.exec(hsl);
    return result ? Color.fromHslVal(
        parseInt(result[1]) / 180 * Math.PI,
        parseInt(result[2]) / 100,
        parseInt(result[3]) / 100
    ) : null;
};
Color.fromHsla = function(hsla) {
    if (hsla.indexOf('hsla(') !== 0) return null;
    var result = Color.HSLA_RE.exec(hsl);
    if (!result) return null;
    result = Color.fromHslVal(
        parseInt(result[1]) / 180 * Math.PI,
        parseInt(result[2]) / 100,
        parseInt(result[3]) / 100
    );
    result.a = parseFloat(result[4]);
    return result;
};
Color.hueToRgb = function(t1, t2, hue) {
    if (hue < 0) hue += 6;
    if (hue >= 6) hue -= 6;
    if (hue < 1) return (t2 - t1) * hue + t1;
    else if (hue < 3) return t2;
    else if (hue < 4) return (t2 - t1) * (4 - hue) + t1;
    else return t1;
};
Color.rgb = function(r, g, b) {
    return 'rgb(' + r + ',' + g + ',' + b + ')';
};
Color.rgba = function(r, g, b, a) {
    return 'rgba(' + r + ',' + g + ',' + b + ','
                               + (is.defined(a) ? a.toFixed(2) : 1.0) + ')';
};
Color.hsl = function(h, s, l) {
    return Color.dhsl(h / Math.PI * 180, s, l);
};
Color.dhsl = function(dh, s, l) {
    return 'hsl(' + Math.floor(dh) + ',' +
                    Math.floor(s * 100) + '%,' +
                    Math.floor(l * 100) + '%)';
};
Color.hsla = function(h, s, l, a) {
    return Color.dhsla(h / Math.PI * 180, s, l, a);
};
Color.dhsla = function(dh, s, l, a) {
    return 'hsla('+ Math.floor(dh) + ',' +
                    Math.floor(s * 100) + '%,' +
                    Math.floor(l * 100) + '%,' +
                    (is.defined(a) ? a.toFixed(2) : 1.0) + ')';
};
Color.adapt = function(color) {
    if (!color) return null;
    if (is.str(color)) return color;
    // "r" is reserved for gradients, so we test for "g" to be sure
    if (is.defined(color.g)) return Color.toRgbaStr(color);
    if (is.defined(color.h)) return Color.toHslaStr(color);
}
Color.toRgbaStr = function(color) {
    return Color.rgba(color.r,
                      color.g,
                      color.b,
                      color.a);
};
Color.toHslaStr = function(color) {
    return Color.hsla(color.h,
                      color.s,
                      color.l,
                      color.a);
};
Color.interpolate = function(c1, c2, t) {
    return {
        r: Math.round(utils.interpolateFloat(c1.r, c2.r, t)),
        g: Math.round(utils.interpolateFloat(c1.g, c2.g, t)),
        b: Math.round(utils.interpolateFloat(c1.b, c2.b, t)),
        a: utils.interpolateFloat(c1.a, c2.a, t)
    };
};

module.exports = Color;
<|endoftext|>


<commit_before>/* eslint vars-on-top: 0 */
/* globals $ */
var popoverLocalInit = function() {
  var options = {
    html: true,
    placement: function(context, source) {
      var position = $(source).offset();
      $(context).addClass($(source).attr('data-popover-class'));
      if ($(source).hasClass('a-js-popoverBig')) {
        return 'bottom';
      }
      if (position.left < 125) {
        return 'right';
      }
      if (position.left > ($(document).width() - $(source).width() - 125)) {
        return 'left';
      }
      return 'bottom';
    },
    content: function() {
      if ($(this).attr('data-popover-content')) {
        return $('#' + $(this).data('popover-content')).html();
      }
      return false;
    },
    template: '

'
  };

  $('[data-toggle="popover"]').popover(options);

  $('.a-js-togglePopoverIcons').each(function() {
    // $(this).find('i').eq(1).hide();
    $(this).find('.a-js-popoverIconExpanded').hide();
  });

  $('.a-js-popoverIconExpanded').on('click', function() {
    $('.a-js-popoverIconExpanded').hide();
    $('.a-js-popoverIconInitial').show();
    // $(this).hide();
    // $('.a-js-popoverIconInitial').show();
  });
  $('.a-js-popoverIconInitial').on('click', function() {
    $(this).hide();
    $(this).parent().find('.a-js-popoverIconExpanded').show();
  });
};

var forceFocusTriggerElement;
var popoverGlobalInit = function() {
  $('[data-toggle="dropdown"]').on('click', function(e) {
    if (window.innerWidth < 992) {
      $('.a-dropdown-overflow-menu-right').removeClass('dropdown-menu-right');
    } else {
      $('.a-dropdown-overflow-menu-right').addClass('dropdown-menu-right');
    }
  });

  $('body').on('show.bs.popover', '[data-toggle="popover"].a-js-tabable-popover', function(e) {
    var triggerElement = this;
    $(triggerElement).closest('.a-modal').scrollTop(0);
  });

  $('body').on('shown.bs.popover', '[data-toggle="popover"].a-js-tabable-popover', function(e) {
    var triggerElement = this;
    setTimeout(function() {
      $(triggerElement).after($($(triggerElement).data('bs.popover').tip));
      $(triggerElement).closest('.a-modal').one('scroll', function() {
        $('[data-toggle="popover"]').popover('hide');
      });
    }, 0);
  });

  $('body').on('shown.bs.popover', '[data-toggle="popover"].a-js-popover-forceFocus', function(e) {
    $('body').append($('<button class="sr-only a-js-popoverTrick">ignoreme</button>'));
    forceFocusTriggerElement = this;
    $(forceFocusTriggerElement).one('blur', function() {
      var that = this;
      if (forceFocusTriggerElement) {
        $($(this).data('bs.popover').tip).find('button,input,a,textarea').filter(':visible:first').focus();
      }
    });
  });

  $('body').on('hidden.bs.popover', '[data-toggle="popover"].a-js-popover-forceFocus', function(e) {
    $('body').find('.a-js-popoverTrick').remove();
  });

  // hides popover when the checkbutton is checked
  $('body').on('focus', '[data-toggle="popover"].sr-only', function(e) {
    if ($(this).is(':checked')) {
      $(this).popover('hide');
    } else {
      $(this).popover('show');
    }
  });

  // show/hide popover on checkbutton change
  $('body').on('change', 'a-switch[data-toggle=popover]', function() {
    if ($(this).is(':checked')) {
      $(this).popover('hide');
    } else {
      $(this).popover('show');
    }
  });

  // Hide all existing popovers when opening a new popover
  $('body').on('click', '[data-toggle="popover"]', function(e) {
    $('[data-toggle="popover"]').not(this).popover('hide');
  });

  // Hide all existing popovers when focusing a new element
  // which is not the open popover or any of its content
  $('body').on('blur', '[data-toggle="popover"], .popover *', function(e) {
    setTimeout(function() {
      var $focused = $(':focus');
      if ((($focused.length !== 0 || forceFocusTriggerElement) && !$focused.hasClass('popover') && $focused.parents('.popover').length === 0) || $focused.hasClass('a-js-popoverTrick')) {
        // disable blur when in modal to allow use of non-original scrollbar
        if ($('.modal.show').length > 0) {
          $('.popover-big[data-toggle="popover"]').popover('hide');
        }
      }
    }, 0);
  });

  // Hide popovers when clicking on something else than the trigger element
  // and the popover itself
  $('body').on('click', function(e) {
    if ($(e.target).data('toggle') !== 'popover'
      && $(e.target).parents('[data-toggle="popover"]').length === 0
      && $(e.target).parents('.popover.show').length === 0) {
      $('[data-toggle="popover"]').popover('hide');
      forceFocusTriggerElement = false;
      $(this).parent().find('.a-js-popoverIconInitial').show();
      $(this).parent().find('.a-js-popoverIconExpanded').hide();
    }
  });

  function resetTranslate() {
    $('.popover-big').attr('style', $('.popover-big').attr('style').replace(/translateX\(.*?\)/, 'translateX(0px)'));
  }

  function adjustBig() {
    var modalHeight;
    var padding;
    if ($('.popover-big').length > 0) {
      if ($('.modal.show').length > 0) {
        // Add padding to make sure modal is big enough to contain popover
        modalHeight = $('.modal-dialog').height() + $('.modalPage').height();
        padding = ($('.popover').offset().top + $('.modal').scrollTop() + $('.popover').height() + 5) - modalHeight;
        $('.modalPage').css('padding-bottom', padding + 'px');
        // tranlate is somehow added by Bootstrap later when in modal??
        setTimeout(resetTranslate, 0);
      } else {
        resetTranslate();
      }
    }
  }

  $('body').on('shown.bs.popover', '.a-js-persistPopover', function() {
    $('.arrow').html('');
    $('html, body').animate({
      scrollTop: $('.a-js-persistPopover').offset().top - 50
    }, 250);

    adjustBig();
  });

  // clean up modal page fix
  $('body').on('hidden.bs.popover', 'a-js-persistPopover', function(e) {
    $('.modalPage').css('padding-bottom', '0px');
  });

  $(window).scroll(adjustBig);
  $('.modal').scroll(adjustBig);
  $(window).resize(adjustBig);
};
<commit_msg>Removed commit f7ce4e6.<commit_after>/* globals $ */
var popoverLocalInit = function() {
  var options = {
    html: true,
    placement: function(context, source) {
      var position = $(source).offset();
      $(context).addClass($(source).attr('data-popover-class'));
      if ($(source).hasClass('a-js-popoverBig')) {
        return 'bottom';
      }
      if (position.left < 125) {
        return 'right';
      }
      if (position.left > ($(document).width() - $(source).width() - 125)) {
        return 'left';
      }
      return 'bottom';
    },
    content: function() {
      if ($(this).attr('data-popover-content')) {
        return $('#' + $(this).data('popover-content')).html();
      }
      return false;
    },
    template: '

'
  };

  $('[data-toggle="popover"]').popover(options);

  $('.a-js-togglePopoverIcons').each(function() {
    // $(this).find('i').eq(1).hide();
    $(this).find('.a-js-popoverIconExpanded').hide();
  });

  $('.a-js-popoverIconExpanded').on('click', function() {
    $('.a-js-popoverIconExpanded').hide();
    $('.a-js-popoverIconInitial').show();
    // $(this).hide();
    // $('.a-js-popoverIconInitial').show();
  });
  $('.a-js-popoverIconInitial').on('click', function() {
    $(this).hide();
    $(this).parent().find('.a-js-popoverIconExpanded').show();
  });
};

var forceFocusTriggerElement;
var popoverGlobalInit = function() {
  $('[data-toggle="dropdown"]').on('click', function(e) {
    if (window.innerWidth < 992) {
      $('.a-dropdown-overflow-menu-right').removeClass('dropdown-menu-right');
    } else {
      $('.a-dropdown-overflow-menu-right').addClass('dropdown-menu-right');
    }
  });

  $('body').on('show.bs.popover', '[data-toggle="popover"].a-js-tabable-popover', function(e) {
    var triggerElement = this;
    $(triggerElement).closest('.a-modal').scrollTop(0);
  });

  $('body').on('shown.bs.popover', '[data-toggle="popover"].a-js-tabable-popover', function(e) {
    var triggerElement = this;
    setTimeout(function() {
      $(triggerElement).after($($(triggerElement).data('bs.popover').tip));
      $(triggerElement).closest('.a-modal').one('scroll', function() {
        $('[data-toggle="popover"]').popover('hide');
      });
    }, 0);
  });

  $('body').on('shown.bs.popover', '[data-toggle="popover"].a-js-popover-forceFocus', function(e) {
    $('body').append($('<button class="sr-only a-js-popoverTrick">ignoreme</button>'));
    forceFocusTriggerElement = this;
    $(forceFocusTriggerElement).one('blur', function() {
      var that = this;
      if (forceFocusTriggerElement) {
        $($(this).data('bs.popover').tip).find('button,input,a,textarea').filter(':visible:first').focus();
      }
    });
  });

  $('body').on('hidden.bs.popover', '[data-toggle="popover"].a-js-popover-forceFocus', function(e) {
    $('body').find('.a-js-popoverTrick').remove();
  });

  // hides popover when the checkbutton is checked
  $('body').on('focus', '[data-toggle="popover"].sr-only', function(e) {
    if ($(this).is(':checked')) {
      $(this).popover('hide');
    } else {
      $(this).popover('show');
    }
  });

  // show/hide popover on checkbutton change
  $('body').on('change', 'a-switch[data-toggle=popover]', function() {
    if ($(this).is(':checked')) {
      $(this).popover('hide');
    } else {
      $(this).popover('show');
    }
  });

  // Hide all existing popovers when opening a new popover
  $('body').on('click', '[data-toggle="popover"]', function(e) {
    $('[data-toggle="popover"]').not(this).popover('hide');
  });

  // Hide all existing popovers when focusing a new element
  // which is not the open popover or any of its content
  $('body').on('blur', '[data-toggle="popover"], .popover *', function(e) {
    setTimeout(function() {
      var $focused = $(':focus');
      if ((($focused.length !== 0 || forceFocusTriggerElement) && !$focused.hasClass('popover') && $focused.parents('.popover').length === 0) || $focused.hasClass('a-js-popoverTrick')) {
        // disable blur when in modal to allow use of non-original scrollbar
        if ($('.modal.show').length > 0) {
          $('.popover-big[data-toggle="popover"]').popover('hide');
        }
      }
    }, 0);
  });

  // Hide popovers when clicking on something else than the trigger element
  // and the popover itself
  $('body').on('click', function(e) {
    if ($(e.target).data('toggle') !== 'popover'
      && $(e.target).parents('[data-toggle="popover"]').length === 0
      && $(e.target).parents('.popover.show').length === 0) {
      $('[data-toggle="popover"]').popover('hide');
      forceFocusTriggerElement = false;
      $(this).parent().find('.a-js-popoverIconInitial').show();
      $(this).parent().find('.a-js-popoverIconExpanded').hide();
    }
  });

  function resetTranslate() {
    $('.popover-big').attr('style', $('.popover-big').attr('style').replace(/translateX\(.*?\)/, 'translateX(0px)'));
  }

  function adjustBig() {
    var modalHeight;
    var padding;
    if ($('.popover-big').length > 0) {
      if ($('.modal.show').length > 0) {
        // Add padding to make sure modal is big enough to contain popover
        modalHeight = $('.modal-dialog').height() + $('.modalPage').height();
        padding = ($('.popover').offset().top + $('.modal').scrollTop() + $('.popover').height() + 5) - modalHeight;
        $('.modalPage').css('padding-bottom', padding + 'px');
        // tranlate is somehow added by Bootstrap later when in modal??
        setTimeout(resetTranslate, 0);
      } else {
        resetTranslate();
      }
    }
  }

  $('body').on('shown.bs.popover', '.a-js-persistPopover', function() {
    $('.arrow').html('');
    $('html, body').animate({
      scrollTop: $('.a-js-persistPopover').offset().top - 50
    }, 250);

    adjustBig();
  });

  // clean up modal page fix
  $('body').on('hidden.bs.popover', 'a-js-persistPopover', function(e) {
    $('.modalPage').css('padding-bottom', '0px');
  });

  $(window).scroll(adjustBig);
  $('.modal').scroll(adjustBig);
  $(window).resize(adjustBig);
};
<|endoftext|>


<commit_before>import {inject, bindable, bindingMode, DOM} from 'aurelia-framework';
import $ from 'jquery';
import 'bootstrap-tagsinput/dist/bootstrap-tagsinput';
import {globalExtraOptions, globalPickerOptions} from './picker-global-options';

@inject(Element)
export class AbpTagsInputCustomElement {
  @bindable({defaultBindingMode: bindingMode.twoWay}) element;
  @bindable({defaultBindingMode: bindingMode.twoWay}) value;

  // plugin own variables
  @bindable bootstrapVersion = globalExtraOptions.bootstrapVersion;
  @bindable placeholder = '';

  // picker options
  @bindable options;

  // events (from the View)
  @bindable onBeforeItemAdd;
  @bindable onBeforeItemRemove;
  @bindable onItemAdded;
  @bindable onItemAddedOnInit;
  @bindable onItemRemoved;

  // variables
  events = {};
  methods = {};
  options = {};
  suppressValueChanged;

  constructor(elm) {
    this.elm = elm;

    // ensure the element exposes a "focus" method for Aurelia-Validation
    elm.focus = () => this.input.focus();
  }

  attached() {
    // reference to the DOM element
    this.domElm = $(this.elm).find('input');

    // Bootstrap 3 & 4 have different class names
    //if tagClass isn't yet configured we will define the tagClass depending on the version
    let pickerOptions = this.options || {};
    if (!this.options.tagClass) {
      pickerOptions.tagClass = this.bootstrapVersion === 3 ? 'label label-info' : 'badge badge-info';
    }

    // create TagsInput
    this.applyExposeEvents();
    this.exposeMethods();

    // finally create the tagsinput with all options
    pickerOptions = Object.assign({}, globalPickerOptions, pickerOptions);
    this.domElm.tagsinput(pickerOptions);

    // expose the element object to the outside
    // this will be useful for calling events/methods/options from the outside
    this.element = {
      events: this.events,
      options: this.options,
      methods: this.methods
    };
  }

  /**
   * Apply/expose tagsinput events
   * Each event has 2 ways of triggering an event (from the View as an attribute or from the ViewModel has a function call)
   */
  applyExposeEvents() {
    this.domElm.on('beforeItemAdd', (e) => {
      if (typeof this.onBeforeItemAdd === 'function') {
        this.onBeforeItemAdd(e);
      }
      if (typeof this.events.onBeforeItemAdd === 'function') {
        this.events.onBeforeItemAdd(e);
      }
    });

    this.domElm.on('beforeItemRemove', (e) => {
      if (typeof this.onBeforeItemRemove === 'function') {
        this.onBeforeItemRemove(e);
      }
      if (typeof this.events.onBeforeItemRemove === 'function') {
        this.events.onBeforeItemRemove(e);
      }
    });

    this.domElm.on('itemAdded', (e) => {
      // refresh the value attribute (except when we explicitly don't want it)
      if (!e.options || !e.options.preventRefresh) {
        this.suppressValueChanged = true;
        this.value = this.domElm.tagsinput('items');
      }
      if (typeof this.onItemAdded === 'function') {
        this.onItemAdded(e);
      }
      if (typeof this.events.onItemAdded === 'function') {
        this.events.onItemAdded(e);
      }
    });

    this.domElm.on('itemAddedOnInit', (e) => {
      if (typeof this.onItemAddedOnInit === 'function') {
        this.onItemAddedOnInit(e);
      }
      if (typeof this.events.onItemAddedOnInit === 'function') {
        this.events.onItemAddedOnInit(e);
      }
    });

    this.domElm.on('itemRemoved', (e) => {
      // refresh the value attribute (except when we explicitly don't want it)
      if (!e.options || !e.options.preventRefresh) {
        this.suppressValueChanged = true;
        this.value = this.domElm.tagsinput('items');
      }
      if (typeof this.onItemRemoved === 'function') {
        this.onItemRemoved(e);
      }
      if (typeof this.events.onItemRemoved === 'function') {
        this.events.onItemRemoved(e);
      }
    });
  }

  /**
   * forward "blur" events to the custom element
   * As described in Aurelia-Validation
   * https://www.danyow.net/aurelia-validation-alpha/
   */
  blur() {
    const event = DOM.createCustomEvent('blur');
    this.elm.dispatchEvent(event);
  }

  /**
   * Expose tagsinput methods
   */
  exposeMethods() {
    let methods = {
      add: (value) => this.domElm.tagsinput('add', value),
      destroy: () => this.domElm.tagsinput('destroy'),
      focus: () => this.domElm.tagsinput('focus'),
      input: () => { return this.domElm.tagsinput('input'); },
      refresh: () => this.domElm.tagsinput('refresh'),
      remove: (value) => this.domElm.tagsinput('remove', value),
      removeAll: () => {
        this.suppressValueChanged = true;
        this.domElm.tagsinput('removeAll');
        this.value = this.domElm.tagsinput('items');
      }
    };

    this.methods = methods;
  }

  detached() {
    this.domElm.tagsinput('destroy');
  }

  /** A simple array compare */
  areEqualArray(arr1, arr2) {
    if (arr1 === null && arr2 === null) {
      return true;
    }
    if (!Array.isArray(arr1) || !Array.isArray(arr2) || (arr1.length !== arr2.length)) {
      return false;
    }
    for (let i = 0; i < arr1.length; i++) {
      if (arr1[i] !== arr2[i]) {
        return false;
      }
    }
    return true;
  }

  /**
   * because of a bug which still has an open issue on Github for the `refresh` not working correctly
   * https://github.com/bootstrap-tagsinput/bootstrap-tagsinput/issues/98
   * we need to `removeAll` and then loop on each new item to add them back as new tag
   * however we want to avoid recursive call on valueChanged by using preventRefresh flag & comparing split values
   * @param newValue
   * @param oldValue
   */
  valueChanged(newValue, oldValue) {
    // tagsinput deals with the values as csv, while the value could also be an array of values
    // let's make them all on the same type as array of string which will be easier to deal with
    let newValueSplit = (typeof newValue === 'string') ? newValue.split(',') : newValue;
    let oldValueSplit = (typeof oldValue === 'string') ? oldValue.split(',') : oldValue;

    // check the newValue vs oldValue but also the split result
    // because in some cases we might have tagsinput saying the value is "tag1, tag2" while the newValue is ["tag1", "tag2"]
    // which are equivalent and so we check that too
    if (newValue && this.domElm && (newValue !== oldValue) && !this.areEqualArray(newValueSplit, oldValueSplit)) {
      if (this.suppressValueChanged) {
        this.suppressValueChanged = false;
        return;
      }
      if (!this.suppressValueChanged) {
        this.domElm.tagsinput('removeAll');
        if (Array.isArray(newValue)) {
          newValue.forEach(value => this.domElm.tagsinput('add', value, {preventRefresh: true}));
        } else {
          this.domElm.tagsinput('add', newValue, {preventRefresh: true});
        }
      }
    }
  }
}
<commit_msg>fix exception if this.options is null<commit_after>import {inject, bindable, bindingMode, DOM} from 'aurelia-framework';
import $ from 'jquery';
import 'bootstrap-tagsinput/dist/bootstrap-tagsinput';
import {globalExtraOptions, globalPickerOptions} from './picker-global-options';

@inject(Element)
export class AbpTagsInputCustomElement {
  @bindable({defaultBindingMode: bindingMode.twoWay}) element;
  @bindable({defaultBindingMode: bindingMode.twoWay}) value;

  // plugin own variables
  @bindable bootstrapVersion = globalExtraOptions.bootstrapVersion;
  @bindable placeholder = '';

  // picker options
  @bindable options;

  // events (from the View)
  @bindable onBeforeItemAdd;
  @bindable onBeforeItemRemove;
  @bindable onItemAdded;
  @bindable onItemAddedOnInit;
  @bindable onItemRemoved;

  // variables
  events = {};
  methods = {};
  options = {};
  suppressValueChanged;

  constructor(elm) {
    this.elm = elm;

    // ensure the element exposes a "focus" method for Aurelia-Validation
    elm.focus = () => this.input.focus();
  }

  attached() {
    // reference to the DOM element
    this.domElm = $(this.elm).find('input');

    // Bootstrap 3 & 4 have different class names
    //if tagClass isn't yet configured we will define the tagClass depending on the version
    let pickerOptions = this.options || {};
    if (!pickerOptions.tagClass) {
      pickerOptions.tagClass = this.bootstrapVersion === 3 ? 'label label-info' : 'badge badge-info';
    }

    // create TagsInput
    this.applyExposeEvents();
    this.exposeMethods();

    // finally create the tagsinput with all options
    pickerOptions = Object.assign({}, globalPickerOptions, pickerOptions);
    this.domElm.tagsinput(pickerOptions);

    // expose the element object to the outside
    // this will be useful for calling events/methods/options from the outside
    this.element = {
      events: this.events,
      options: pickerOptions,
      methods: this.methods
    };
  }

  /**
   * Apply/expose tagsinput events
   * Each event has 2 ways of triggering an event (from the View as an attribute or from the ViewModel has a function call)
   */
  applyExposeEvents() {
    this.domElm.on('beforeItemAdd', (e) => {
      if (typeof this.onBeforeItemAdd === 'function') {
        this.onBeforeItemAdd(e);
      }
      if (typeof this.events.onBeforeItemAdd === 'function') {
        this.events.onBeforeItemAdd(e);
      }
    });

    this.domElm.on('beforeItemRemove', (e) => {
      if (typeof this.onBeforeItemRemove === 'function') {
        this.onBeforeItemRemove(e);
      }
      if (typeof this.events.onBeforeItemRemove === 'function') {
        this.events.onBeforeItemRemove(e);
      }
    });

    this.domElm.on('itemAdded', (e) => {
      // refresh the value attribute (except when we explicitly don't want it)
      if (!e.options || !e.options.preventRefresh) {
        this.suppressValueChanged = true;
        this.value = this.domElm.tagsinput('items');
      }
      if (typeof this.onItemAdded === 'function') {
        this.onItemAdded(e);
      }
      if (typeof this.events.onItemAdded === 'function') {
        this.events.onItemAdded(e);
      }
    });

    this.domElm.on('itemAddedOnInit', (e) => {
      if (typeof this.onItemAddedOnInit === 'function') {
        this.onItemAddedOnInit(e);
      }
      if (typeof this.events.onItemAddedOnInit === 'function') {
        this.events.onItemAddedOnInit(e);
      }
    });

    this.domElm.on('itemRemoved', (e) => {
      // refresh the value attribute (except when we explicitly don't want it)
      if (!e.options || !e.options.preventRefresh) {
        this.suppressValueChanged = true;
        this.value = this.domElm.tagsinput('items');
      }
      if (typeof this.onItemRemoved === 'function') {
        this.onItemRemoved(e);
      }
      if (typeof this.events.onItemRemoved === 'function') {
        this.events.onItemRemoved(e);
      }
    });
  }

  /**
   * forward "blur" events to the custom element
   * As described in Aurelia-Validation
   * https://www.danyow.net/aurelia-validation-alpha/
   */
  blur() {
    const event = DOM.createCustomEvent('blur');
    this.elm.dispatchEvent(event);
  }

  /**
   * Expose tagsinput methods
   */
  exposeMethods() {
    let methods = {
      add: (value) => this.domElm.tagsinput('add', value),
      destroy: () => this.domElm.tagsinput('destroy'),
      focus: () => this.domElm.tagsinput('focus'),
      input: () => { return this.domElm.tagsinput('input'); },
      refresh: () => this.domElm.tagsinput('refresh'),
      remove: (value) => this.domElm.tagsinput('remove', value),
      removeAll: () => {
        this.suppressValueChanged = true;
        this.domElm.tagsinput('removeAll');
        this.value = this.domElm.tagsinput('items');
      }
    };

    this.methods = methods;
  }

  detached() {
    this.domElm.tagsinput('destroy');
  }

  /** A simple array compare */
  areEqualArray(arr1, arr2) {
    if (arr1 === null && arr2 === null) {
      return true;
    }
    if (!Array.isArray(arr1) || !Array.isArray(arr2) || (arr1.length !== arr2.length)) {
      return false;
    }
    for (let i = 0; i < arr1.length; i++) {
      if (arr1[i] !== arr2[i]) {
        return false;
      }
    }
    return true;
  }

  /**
   * because of a bug which still has an open issue on Github for the `refresh` not working correctly
   * https://github.com/bootstrap-tagsinput/bootstrap-tagsinput/issues/98
   * we need to `removeAll` and then loop on each new item to add them back as new tag
   * however we want to avoid recursive call on valueChanged by using preventRefresh flag & comparing split values
   * @param newValue
   * @param oldValue
   */
  valueChanged(newValue, oldValue) {
    // tagsinput deals with the values as csv, while the value could also be an array of values
    // let's make them all on the same type as array of string which will be easier to deal with
    let newValueSplit = (typeof newValue === 'string') ? newValue.split(',') : newValue;
    let oldValueSplit = (typeof oldValue === 'string') ? oldValue.split(',') : oldValue;

    // check the newValue vs oldValue but also the split result
    // because in some cases we might have tagsinput saying the value is "tag1, tag2" while the newValue is ["tag1", "tag2"]
    // which are equivalent and so we check that too
    if (newValue && this.domElm && (newValue !== oldValue) && !this.areEqualArray(newValueSplit, oldValueSplit)) {
      if (this.suppressValueChanged) {
        this.suppressValueChanged = false;
        return;
      }
      if (!this.suppressValueChanged) {
        this.domElm.tagsinput('removeAll');
        if (Array.isArray(newValue)) {
          newValue.forEach(value => this.domElm.tagsinput('add', value, {preventRefresh: true}));
        } else {
          this.domElm.tagsinput('add', newValue, {preventRefresh: true});
        }
      }
    }
  }
}
<|endoftext|>


<commit_before>import { remote } from 'electron'

export const twitterCredential = remote.getGlobal('twitterCredential');remote.getGlobal('twitterCredential');
export const credential = remote.getGlobal('credential');
<commit_msg>Remove unneeded code<commit_after>import { remote } from 'electron'

export const twitterCredential = remote.getGlobal('twitterCredential');
export const credential = remote.getGlobal('credential');
<|endoftext|>


<commit_before>const config = require('../../config');
const https = require('https');
const url = require('url');
const request = require('request');

const GITHUB_API_ROOT = 'https://api.github.com';

// const getlocalAppRootUrl = request => {
//   return process.env.NODE_ENV == 'production'
//     ? url.format({
//         protocol: 'https', // request.protocol returns http for now since the node server itself is only using http. However the api is used over https thanks to azure / IIS
//         host: request.hostname,
//         // port: request.port,
//         pathname: ''
//       })
//     : 'https://localhost:3000'; // hard coded value in development because the request came through the webpack dev server on a different port and via https.
// };

const getProxyRequestOptions = url => ({
  url: GITHUB_API_ROOT + url.replace('/api', ''),
  headers: {
    Authorization: `token ${config.github.botToken}`
    //,"user-agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36"
    ,"accept-encoding": "identity",
  }
});

// const rewriteResponseHeaders = (request, response) => {
//   if (response.headers.link) {
//     response.headers.link = response.headers.link.replace(GITHUB_API_ROOT, getlocalAppRootUrl(request) + '/api');
//     console.log(`Request App: Rewritten response.headers.link: ${JSON.stringify(response.headers.link)}`);
//   } else {
//     console.log(`Request App: response.headers.link falsy, nothing to rewrite`);
//   }
// };

const genericErrorHandler = (error, response, body) => {
  if (error) {
    if (error.code === 'ECONNREFUSED') {
      console.error('Refused connection');
    } else if (error.code === 'ETIMEDOUT') {
      console.error('Connection timed out');
    } else {
      throw error;
    }
  }
};

// const validateRepository = (organisation, repo, projects) => {
//   if (projects.filter(p => p.organisation == organisation && p.repository == repo).length == 0) {
//     console.error(`Request App: Repository not found : ${organisation}/${repo}`);
//     return false;
//   } else {
//     console.log(`Request App: Valid repository: ${organisation}/${repo}`);
//     return true;
//   }
// };

module.exports = {
  getProxyRequestOptions,
  //rewriteResponseHeaders,
  genericErrorHandler//,
  //validateRepository
};<commit_msg>Remove unused dependencies<commit_after>const config = require('../../config');
const url = require('url');

const GITHUB_API_ROOT = 'https://api.github.com';

const getProxyRequestOptions = url => ({
  url: GITHUB_API_ROOT + url.replace('/api', ''),
  headers: {
    Authorization: `token ${config.github.botToken}`
    //,"user-agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36"
    ,"accept-encoding": "identity",
  }
});

const genericErrorHandler = (error, response, body) => {
  if (error) {
    if (error.code === 'ECONNREFUSED') {
      console.error('Refused connection');
    } else if (error.code === 'ETIMEDOUT') {
      console.error('Connection timed out');
    } else {
      throw error;
    }
  }
};

module.exports = {
  getProxyRequestOptions,
  genericErrorHandler
};<|endoftext|>