<commit_before>/*
 * Namespace: lb.base.i18n
 * Base Internationalization (i18n) Module
 *
 * This module provides the basis for the adaptation of a web application to
 * different languages in an international context.
 *
 * The issue is addressed in a generic way in this module, which relies on
 * language codes associated with a set of language properties defined by the
 * application:
 * - string properties,
 * - functions for localized behavior, formatting and sorting,
 * - object properties, to group properties within. The groups may be nested.
 *
 * A language code is a string which identifies the language, region and other
 * variations of the language as defined in RFC5646 "Tags for Identifying
 * Languages", for example:
 * - 'en' for English,
 * - 'fr' for French,
 * - 'en-GB' for English/Great Britain,
 * - 'en-US' for English/USA,
 * - 'fr-FR' for French/France,
 * - 'fr-CA' for French/Canada.
 *
 * The lookup of language properties is done from the most specific language
 * to the less specific language, with longer language codes considered more
 * specific than shorter language codes. Only language codes which are
 * substrings of the language selected for the lookup are considered.
 * For example, if the selected language is 'en-GB', 'en-GB' and 'en' are
 * considered in this order, while 'en-US', 'fr-FR', 'fr-CA' and 'fr' are left
 * out.
 *
 * The empty string '' is the least specific language code possible, which will
 * always be considered last in the lookup process. Common default properties
 * can be associated with the empty language code '', they will be shared by
 * all languages.
 *
 * Any custom property may be defined in language properties for the needs of
 * your application, and associated with a language code by calling
 * addLanguageProperties(). Calling reset() removes all language properties.
 *
 * The list of language codes associated with language properties is returned
 * by getLanguageCodes(). It is initially empty.
 * [Note: changes pending - add getLanguageCodes]
 *
 * Author:
 * Eric Bréchemier <legalbox@eric.brechemier.name>
 *
 * Copyright:
 * Legal Box SAS (c) 2010, All Rights Reserved
 *
 * License:
 * BSD License
 * http://creativecommons.org/licenses/BSD/
 *
 * Version:
 * 2010-12-17
 */
/*requires lb.base.js */
/*jslint white:false, plusplus:false */
/*global lb, goog, navigator */
// preserve the module, if already loaded
lb.base.i18n = lb.base.i18n || (function() {
  // Builder of
  // Closure for lb.base.i18n module

  // Declare aliases
  var getOption = lb.base.config.getOption,

  // private fields

      // languages - array, the list of language objects, sorted by language
      //             code, from less specific to most specific.
      //             Each language object is in the format:
      //             | {
      //             |    language: 'en-US', // string, language code
      //             |    properties: {...}  // object, properties given
      //             |                       // in addLanguageProperties
      //             | }
      // Note:
      // In current implementation, the same language code may be repeated in
      // several language objects. These duplicates may be merged into a single
      // language object in a future implementation (trading less memory for
      // more computations due to added merging step).
      languages = [];

  function getLanguage(){
    // For internal use - refactoring in progress
    // Return the default language configured with 'lbLanguage' property

    var defaultLanguage = navigator.language ||
                          navigator.browserLanguage ||
                          '';
    return getOption('lbLanguage',defaultLanguage).toLowerCase();
  }

  function getLanguageVariants(language){
    // Function: getLanguageVariants(language): array
    // Get the language variants for given language, sorted by language tag
    // from less specific to most specific.
    //
    // Parameter:
    //   language - string, an optional language tag, as defined in RFC5646
    //              "Tags for Identifying Languages".
    //              Omitting the language and null or undefined values
    //              (or any value without the toLowerCase() property) act as a
    //              wildcard to return all language variants.
    //
    // Returns:
    //   * array, the list of properties objects for all language variants
    //     whose tag is a subset of given language, ordered by language tag,
    //   * or if the optional language argument is omitted,
    //     array, the list of properties objects for all language variants,
    //     sorted by language tag.
    //
    // Note:
    //   In case several language variants were added for the same tag, the
    //   language variant added last is considered more specific and comes
    //   last in this list.

    var isWildcard = language===undefined ||
                     language===null ||
                     !language.toLowerCase,
        languageProperties = [],
        i,
        languageVariant;
    if (!isWildcard){
      language = language.toLowerCase();
    }
    for(i=0; i<languages.length; i++){
      languageVariant = languages[i];
      if ( isWildcard ||
        // selected language starts with the tag of this language variant
        language.indexOf(languageVariant.language)===0 ){
        languageProperties.push(languageVariant.properties);
      }
    }
    return languageProperties;
  }

  function addLanguageProperties(languageCode,languageProperties){
    // Function: addLanguageProperties(languageCode,languageProperties)
    // Add or replace language properties associated with given language code.
    //
    // Language properties may be specified in multiple calls with the same
    // language code. In case of duplicate properties, the ones last are
    // considered more specific and take precedence over properties defined
    // previously.
    //
    // Parameters:
    //   languageCode - string, the language code identifying the language,
    //                  as defined in RFC5646 "Tags for Identifying Languages"
    //   languageProperties - object, a set of language properties
    //
    // Note:
    //   Nothing happens in case the given language code is null, undefined,
    //   or misses the toLowerCase method.
    if ( languageCode===undefined ||
         languageCode===null ||
         !languageCode.toLowerCase ){
      return;
    }

    // Note: array.sort does not guarantee that the order of items with the
    // same value is preserved. This is the case in recent versions of Firefox,
    // Opera and Chrome, but not in IE and Safari.
    //
    // Thus I chose to insert the new item at the highest position where
    // the lexical order of previous language is lesser or equal, instead of
    // adding the item to the array and calling sort().

    var lowerCaseLanguage = languageCode.toLowerCase(),
        newLanguageVariant = {
          language: lowerCaseLanguage,
          properties: languageProperties
        },
        length = languages.length,
        i = 0,
        j;

    // find the first suitable position for insertion
    for (j=length-1; j>=0; j--){
      if (lowerCaseLanguage >= languages[j].language){
        i = j+1; // insert just after
        break;
      }
    }

    // insert at found location (possibly 0)
    languages.splice(i,0,newLanguageVariant);
  }

  function getProperty(){
    // Function: getProperty(...,name): any
    // Lookup the property with given name, optionally nested within
    // other properties, based on language configured in 'lbLanguage' property.
    //
    // The last argument is the name of the property. Preceding arguments
    // are the names of parent properties, allowing to nest a property
    // within sections and subsections. In any case, the first property is
    // always looked for at the top of language variants.
    //
    // Parameters:
    //   ... - string, the name of parent properties, starting at the top level
    //   name - string, the name of the looked up property
    //
    // Returns:
    //   * any, the value of the property found in the most specific language
    //     variant according to the language currently selected,
    //   * or null if the property is not found in suitable languages.

    var name,
        properties = getLanguageVariants( getLanguage() ),
        property,
        i,
        j;
    // for each language variant, from most specific to less specific
    for (i=properties.length-1; i>=0; i--){
      property = properties[i]; // start at top
      for (j=0; j<arguments.length && property; j++){
        name = arguments[j];
        if (name in property && j===arguments.length-1){
          return property[name];
        }
        property = property[name];
      }
    }
    return null;
  }

  function getValueOf(){
    // Function: getValueOf(...,name,args): any
    //
    // Lookup the function with given name, optionally nested within
    // other properties, based on selected language, and return the first
    // defined result value of such a function.
    //
    // The last two arguments are the name of the function and arguments to be
    // provided in calls to the function. Preceding arguments, if any, are the
    // names of parent properties, allowing to nest the function within
    // sections and subsections. The first property, or the function name in
    // case no parent property is provided, is looked for at the top of
    // language variants for the current language.
    //
    // Parameters:
    //   ... - string, the name of parent properties, starting at the top level
    //   name - string, the name of the looked up function
    //   args - array, the list of arguments for the function
    //
    // Returns:
    //   * any, the value of the most specific function found in given position
    //     which returns a value different from null,
    //   * or null if there is no such function found in suitable languages.

    var namePosition = arguments.length-2,
        name,
        argsPosition = namePosition+1,
        args = arguments[argsPosition],
        properties = getLanguageVariants( getLanguage() ),
        property,
        i,
        j,
        func,
        value;

    // for each language variant, from most specific to less specific
    for (i=properties.length-1; i>=0; i--){
      property = properties[i]; // start at top
      for (j=0; j<=namePosition && property; j++){
        name = arguments[j];
        if (name in property && j===namePosition){
          func = property[name];
          if (typeof func === 'function'){
            value = func.apply(null,args);
            if (value!==undefined && value!==null){
              return value;
            }
          }
        }
        property = property[name];
      }
    }
    return null;
  }

  function reset(){
    // Function: reset()
    // Remove all language variants.

    languages.length = 0;
  }

  return { // public API
    getLanguageVariants: getLanguageVariants,
    addLanguageProperties: addLanguageProperties,
    getProperty: getProperty,
    getValueOf: getValueOf,
    reset: reset
  };
}());
<commit_msg>Refactoring: renamed 'language' field of language objects to 'code'<commit_after>/*
 * Namespace: lb.base.i18n
 * Base Internationalization (i18n) Module
 *
 * This module provides the basis for the adaptation of a web application to
 * different languages in an international context.
 *
 * The issue is addressed in a generic way in this module, which relies on
 * language codes associated with a set of language properties defined by the
 * application:
 * - string properties,
 * - functions for localized behavior, formatting and sorting,
 * - object properties, to group properties within. The groups may be nested.
 *
 * A language code is a string which identifies the language, region and other
 * variations of the language as defined in RFC5646 "Tags for Identifying
 * Languages", for example:
 * - 'en' for English,
 * - 'fr' for French,
 * - 'en-GB' for English/Great Britain,
 * - 'en-US' for English/USA,
 * - 'fr-FR' for French/France,
 * - 'fr-CA' for French/Canada.
 *
 * The lookup of language properties is done from the most specific language
 * to the less specific language, with longer language codes considered more
 * specific than shorter language codes. Only language codes which are
 * substrings of the language selected for the lookup are considered.
 * For example, if the selected language is 'en-GB', 'en-GB' and 'en' are
 * considered in this order, while 'en-US', 'fr-FR', 'fr-CA' and 'fr' are left
 * out.
 *
 * The empty string '' is the least specific language code possible, which will
 * always be considered last in the lookup process. Common default properties
 * can be associated with the empty language code '', they will be shared by
 * all languages.
 *
 * Any custom property may be defined in language properties for the needs of
 * your application, and associated with a language code by calling
 * addLanguageProperties(). Calling reset() removes all language properties.
 *
 * The list of language codes associated with language properties is returned
 * by getLanguageCodes(). It is initially empty.
 * [Note: changes pending - add getLanguageCodes]
 *
 * Author:
 * Eric Bréchemier <legalbox@eric.brechemier.name>
 *
 * Copyright:
 * Legal Box SAS (c) 2010, All Rights Reserved
 *
 * License:
 * BSD License
 * http://creativecommons.org/licenses/BSD/
 *
 * Version:
 * 2010-12-17
 */
/*requires lb.base.js */
/*jslint white:false, plusplus:false */
/*global lb, goog, navigator */
// preserve the module, if already loaded
lb.base.i18n = lb.base.i18n || (function() {
  // Builder of
  // Closure for lb.base.i18n module

  // Declare aliases
  var getOption = lb.base.config.getOption,

  // private fields

      // languages - array, the list of language objects, sorted by language
      //             code, from less specific to most specific.
      //             Each language object is in the format:
      //             | {
      //             |    code: 'en-US', // string, language code
      //             |    properties: {...}  // object, properties given
      //             |                       // in addLanguageProperties
      //             | }
      // Note:
      // In current implementation, the same language code may be repeated in
      // several language objects. These duplicates may be merged into a single
      // language object in a future implementation (trading less memory for
      // more computations due to added merging step).
      languages = [];

  function getLanguage(){
    // For internal use - refactoring in progress
    // Return the default language configured with 'lbLanguage' property

    var defaultLanguage = navigator.language ||
                          navigator.browserLanguage ||
                          '';
    return getOption('lbLanguage',defaultLanguage).toLowerCase();
  }

  function getLanguageVariants(language){
    // Function: getLanguageVariants(language): array
    // Get the language variants for given language, sorted by language tag
    // from less specific to most specific.
    //
    // Parameter:
    //   language - string, an optional language tag, as defined in RFC5646
    //              "Tags for Identifying Languages".
    //              Omitting the language and null or undefined values
    //              (or any value without the toLowerCase() property) act as a
    //              wildcard to return all language variants.
    //
    // Returns:
    //   * array, the list of properties objects for all language variants
    //     whose tag is a subset of given language, ordered by language tag,
    //   * or if the optional language argument is omitted,
    //     array, the list of properties objects for all language variants,
    //     sorted by language tag.
    //
    // Note:
    //   In case several language variants were added for the same tag, the
    //   language variant added last is considered more specific and comes
    //   last in this list.

    var isWildcard = language===undefined ||
                     language===null ||
                     !language.toLowerCase,
        languageProperties = [],
        i,
        languageVariant;
    if (!isWildcard){
      language = language.toLowerCase();
    }
    for(i=0; i<languages.length; i++){
      languageVariant = languages[i];
      if ( isWildcard ||
        // selected language starts with the tag of this language variant
        language.indexOf(languageVariant.code)===0 ){
        languageProperties.push(languageVariant.properties);
      }
    }
    return languageProperties;
  }

  function addLanguageProperties(languageCode,languageProperties){
    // Function: addLanguageProperties(languageCode,languageProperties)
    // Add or replace language properties associated with given language code.
    //
    // Language properties may be specified in multiple calls with the same
    // language code. In case of duplicate properties, the ones last are
    // considered more specific and take precedence over properties defined
    // previously.
    //
    // Parameters:
    //   languageCode - string, the language code identifying the language,
    //                  as defined in RFC5646 "Tags for Identifying Languages"
    //   languageProperties - object, a set of language properties
    //
    // Note:
    //   Nothing happens in case the given language code is null, undefined,
    //   or misses the toLowerCase method.
    if ( languageCode===undefined ||
         languageCode===null ||
         !languageCode.toLowerCase ){
      return;
    }

    // Note: array.sort does not guarantee that the order of items with the
    // same value is preserved. This is the case in recent versions of Firefox,
    // Opera and Chrome, but not in IE and Safari.
    //
    // Thus I chose to insert the new item at the highest position where
    // the lexical order of previous language is lesser or equal, instead of
    // adding the item to the array and calling sort().

    var lowerCaseLanguage = languageCode.toLowerCase(),
        newLanguageVariant = {
          code: lowerCaseLanguage,
          properties: languageProperties
        },
        length = languages.length,
        i = 0,
        j;

    // find the first suitable position for insertion
    for (j=length-1; j>=0; j--){
      if (lowerCaseLanguage >= languages[j].code){
        i = j+1; // insert just after
        break;
      }
    }

    // insert at found location (possibly 0)
    languages.splice(i,0,newLanguageVariant);
  }

  function getProperty(){
    // Function: getProperty(...,name): any
    // Lookup the property with given name, optionally nested within
    // other properties, based on language configured in 'lbLanguage' property.
    //
    // The last argument is the name of the property. Preceding arguments
    // are the names of parent properties, allowing to nest a property
    // within sections and subsections. In any case, the first property is
    // always looked for at the top of language variants.
    //
    // Parameters:
    //   ... - string, the name of parent properties, starting at the top level
    //   name - string, the name of the looked up property
    //
    // Returns:
    //   * any, the value of the property found in the most specific language
    //     variant according to the language currently selected,
    //   * or null if the property is not found in suitable languages.

    var name,
        properties = getLanguageVariants( getLanguage() ),
        property,
        i,
        j;
    // for each language variant, from most specific to less specific
    for (i=properties.length-1; i>=0; i--){
      property = properties[i]; // start at top
      for (j=0; j<arguments.length && property; j++){
        name = arguments[j];
        if (name in property && j===arguments.length-1){
          return property[name];
        }
        property = property[name];
      }
    }
    return null;
  }

  function getValueOf(){
    // Function: getValueOf(...,name,args): any
    //
    // Lookup the function with given name, optionally nested within
    // other properties, based on selected language, and return the first
    // defined result value of such a function.
    //
    // The last two arguments are the name of the function and arguments to be
    // provided in calls to the function. Preceding arguments, if any, are the
    // names of parent properties, allowing to nest the function within
    // sections and subsections. The first property, or the function name in
    // case no parent property is provided, is looked for at the top of
    // language variants for the current language.
    //
    // Parameters:
    //   ... - string, the name of parent properties, starting at the top level
    //   name - string, the name of the looked up function
    //   args - array, the list of arguments for the function
    //
    // Returns:
    //   * any, the value of the most specific function found in given position
    //     which returns a value different from null,
    //   * or null if there is no such function found in suitable languages.

    var namePosition = arguments.length-2,
        name,
        argsPosition = namePosition+1,
        args = arguments[argsPosition],
        properties = getLanguageVariants( getLanguage() ),
        property,
        i,
        j,
        func,
        value;

    // for each language variant, from most specific to less specific
    for (i=properties.length-1; i>=0; i--){
      property = properties[i]; // start at top
      for (j=0; j<=namePosition && property; j++){
        name = arguments[j];
        if (name in property && j===namePosition){
          func = property[name];
          if (typeof func === 'function'){
            value = func.apply(null,args);
            if (value!==undefined && value!==null){
              return value;
            }
          }
        }
        property = property[name];
      }
    }
    return null;
  }

  function reset(){
    // Function: reset()
    // Remove all language variants.

    languages.length = 0;
  }

  return { // public API
    getLanguageVariants: getLanguageVariants,
    addLanguageProperties: addLanguageProperties,
    getProperty: getProperty,
    getValueOf: getValueOf,
    reset: reset
  };
}());
<|endoftext|>


<commit_before>/*{
  "id":"data",
	"scope":["server"],
	"desc":"data(redis) api/interface"
}*/

var redis = require('redis')
, client = redis.createClient()
, telepath = require('tele')

module.exports = function () {
  var self = this
  telepath(this)

  this.recv = function (data) {
    for (key in data) {
      switch (key) {
        case 'set': self.set(data[key]);break
        case 'get': self.get(data[key]);break
        case 'hset': self.hset(data[key]);break
        case 'hget': self.hget(data[key]);break
      }
    }
  }

  this.set = function (params) {
    var key = params[0]
    , val = params[1]
    client.set(key, val)
  }

  this.get = function (key) {
    client.get(key, function (err, data) {
      if (err) throw err
      console.log('data got '+data)
      self.send(data)
    })
  }

  this.hset = function (params) {
    var hash = params[0]
    , key = params[1]
    , val = params[2]

    client.hset(hash, key, val)
  }

  this.hget = function (prams, cb) {
    var hash = params[0]
    , key = params[1]
    , val = params[2]

    client.hget(params, cb)
  }
}
<commit_msg>added JSON.parse to _wilds/data recv to fix errs in switch statement<commit_after>/*{
  "id":"data",
	"scope":["server"],
	"desc":"data(redis) api/interface"
}*/

var redis = require('redis')
, client = redis.createClient()
, telepath = require('tele')

module.exports = function () {
  var self = this
  telepath(this)

  this.recv = function (json) {
    var data = JSON.parse(json)
    for (key in data) {
      switch (key) {
        case 'set': self.set(data[key]);break;
        case 'get': self.get(data[key]);break;
        case 'hset': self.hset(data[key]);break;
        case 'hget': self.hget(data[key]);break;
      }
    }
  }

  this.set = function (params) {
    var key = params[0]
    , val = params[1]
    client.set(key, val)
  }

  this.get = function (key) {
    client.get(key, function (err, data) {
      if (err) throw err
      self.send(data)
    })
  }

  this.hset = function (params) {
    var hash = params[0]
    , key = params[1]
    , val = params[2]

    client.hset(hash, key, val)
  }

  this.hget = function (prams, cb) {
    var hash = params[0]
    , key = params[1]
    , val = params[2]

    client.hget(params, cb)
  }
}
<|endoftext|>


<commit_before><commit_msg>Added include descendants UI functionality<commit_after><|endoftext|>


<commit_before>import {
  attributeBindings,
  classNameBindings,
  classNames,
  layout as templateLayout,
  tagName,
} from '@ember-decorators/component';

import { observes } from '@ember-decorators/object';
import { computed } from '@ember/object';
import { deprecatingAlias, equal, or } from '@ember/object/computed';
import { scheduleOnce } from '@ember/runloop';
import Component from '@ember/component';
import layout from 'ember-bootstrap/templates/components/bs-button';
import sizeClass from 'ember-bootstrap/utils/cp/size-class';
import typeClass from 'ember-bootstrap/utils/cp/type-class';
import overrideableCP from 'ember-bootstrap/utils/cp/overrideable';
import defaultValue from 'ember-bootstrap/utils/default-decorator';

/**
  Implements a HTML button element, with support for all [Bootstrap button CSS styles](http://getbootstrap.com/css/#buttons)
  as well as advanced functionality such as button states.

  ### Basic Usage

  ```hbs
  <BsButton @type="primary" @icon="glyphicon glyphicon-download">
    Downloads
  </BsButton>
  ```

  ### Actions

  Use the `onClick` property of the component to send an action to your controller. It will receive the button's value
  (see the `value` property) as an argument.

  ```hbs
  <BsButton @type="primary" @icon="glyphicon glyphicon-download" @onClick=(action "download")>
    Downloads
  </BsButton>
  ```

  ### Promise support for automatic state change

  When returning a Promise for any asynchronous operation from the `onClick` closure action the button will
  manage an internal state ("default" > "pending" > "fulfilled"/"rejected") automatically, changing its label
  according to the state of the promise:

  ```hbs
  <BsButton
    (at)type="primary"
    (at)icon="glyphicon glyphicon-download"
    (at)defaultText="Download"
    (at)pendingText="Loading..."
    (at)fulfilledText="Completed!"
    (at)rejectedText="Oups!?"
    (at)onClick={{action "download"}}
  />
  ```

  ```js
  // controller.js
  export default Ember.Controller.extend({
    actions: {
      download(value) {
        return new Ember.RSVP.Promise(...);
      }
    }
  });
  ```

  For further customization `isPending`, `isFulfilled`, `isRejected` and `isSettled` properties are yielded:

  ```hbs
  <BsButton @onClick=(action "download") as |button|>
    Download
    {{#if button.isPending}}
      <span class="loading-spinner"></span>
    {{/if}}
  </BsButton>
  ```

  You can `reset` the state represented by these properties and used for button's text by setting `reset` property to
  `true`.

  @class Button
  @namespace Components
  @extends Ember.Component
  @public
*/
@templateLayout(layout)
@tagName('button')
@classNames('btn')
@classNameBindings('active', 'block:btn-block', 'sizeClass', 'typeClass')
@attributeBindings('_disabled:disabled', 'buttonType:type', 'title')
export default class Button extends Component {
  /**
   * Default label of the button. Not need if used as a block component
   *
   * @property defaultText
   * @type string
   * @public
   */
  @defaultValue
  defaultText = null;

  /**
   * Label of the button used if `onClick` event has returned a Promise which is pending.
   * Not considered if used as a block component.
   *
   * @property pendingText
   * @type string
   * @public
   */
  @defaultValue
  pendingText = undefined;

  /**
   * Label of the button used if `onClick` event has returned a Promise which succeeded.
   * Not considered if used as a block component.
   *
   * @property fulfilledText
   * @type string
   * @public
   */
  @defaultValue
  fulfilledText = undefined;

  /**
   * @property resolvedText
   * @type string
   * @deprecated
   * @public
   */
  @deprecatingAlias('fulfilledText', {
    id: 'ember-bootstrap.bs-button-resolved-text',
    until: '3.0.0'
  })
  resolvedText;

  /**
   * Label of the button used if `onClick` event has returned a Promise which failed.
   * Not considered if used as a block component.
   *
   * @property rejectedText
   * @type string
   * @public
   */
  @defaultValue
  rejectedText = undefined;

  /**
   * Property to disable the button
   *
   * The button is disabled by default if `preventConcurrency` is `true` and
   * a Promise returned by `onClick` action is pending. You may explicitly
   * enable / disable the button by setting `disabled` to `true` or `false`.
   * Setting it to `null` restores the default behavior.
   *
   * @property disabled
   * @type ?boolean
   * @default null
   * @public
   */
  @defaultValue
  disabled = null;

  @computed('disabled', 'isPending', 'preventConcurrency')
  get _disabled() {
    if (this.get('disabled') !== null) {
      return this.get('disabled');
    }

    return this.get('isPending') && this.get('preventConcurrency');
  }

  /**
   * Set the type of the button, either 'button' or 'submit'
   *
   * @property buttonType
   * @type String
   * @default 'button'
   * @public
   */
  @defaultValue
  buttonType = 'button';

  /**
   * Set the 'active' class to apply active/pressed CSS styling
   *
   * @property active
   * @type boolean
   * @default false
   * @public
   */
  @defaultValue
  active = false;

  /**
   * Property for block level buttons
   *
   * See the [Bootstrap docs](http://getbootstrap.com/css/#buttons-sizes)
   * @property block
   * @type boolean
   * @default false
   * @public
   */
  @defaultValue
  block = false;

  /**
   * A click event on a button will not bubble up the DOM tree if it has an `onClick` action handler. Set to true to
   * enable the event to bubble
   *
   * @property bubble
   * @type boolean
   * @default false
   * @public
   */
  @defaultValue
  bubble = false;

  /**
   * If button is active and this is set, the icon property will match this property
   *
   * @property iconActive
   * @type String
   * @public
   */
  @defaultValue
  iconActive = null;

  /**
   * If button is inactive and this is set, the icon property will match this property
   *
   * @property iconInactive
   * @type String
   * @public
   */
  @defaultValue
  iconInactive = null;

  /**
   * Class(es) (e.g. glyphicons or font awesome) to use as a button icon
   * This will render a  element in front of the button's label
   *
   * @property icon
   * @type String
   * @readonly
   * @public
   */
  @overrideableCP('active', function() {
    if (this.get('active')) {
      return this.get('iconActive');
    } else {
      return this.get('iconInactive');
    }
  })
  icon;

  /**
   * Supply a value that will be associated with this button. This will be send
   * as a parameter of the default action triggered when clicking the button
   *
   * @property value
   * @type any
   * @public
   */
  @defaultValue
  value = null;

  /**
   * Controls if `onClick` action is fired concurrently. If `true` clicking button multiple times will not trigger
   * `onClick` action if a Promise returned by previous click is not settled yet.
   *
   * This does not affect event bubbling.
   *
   * @property preventConcurrency
   * @type Boolean
   * @default true
   * @public
   */
  @defaultValue
  preventConcurrency = true;

  /**
   * State of the button. The button's label (if not used as a block component) will be set to the
   * `<state>Text` property.
   * This property will automatically be set when using a click action that supplies the callback with a promise.
   * Possible values are: "default" > "pending" > "fulfilled" / "rejected".
   * It could be reseted by `reset` property.
   *
   * @property state
   * @type String
   * @default 'default'
   * @private
   */
  @defaultValue
  state = 'default';

  /**
   * Promise returned by `onClick` event is pending.
   *
   * @property isPending
   * @type Boolean
   * @private
   */
  @equal('state', 'pending')
  isPending;

  /**
   * Promise returned by `onClick` event has been succeeded.
   *
   * @property isFulfilled
   * @type Boolean
   * @private
   */
  @equal('state', 'fulfilled')
  isFulfilled;

  /**
   * Promise returned by `onClick` event has been rejected.
   *
   * @property isRejected
   * @type Boolean
   * @private
   */
  @equal('state', 'rejected')
  isRejected;

  /**
   * Promise returned by `onClick` event has been succeeded or rejected.
   *
   * @property isFulfilled
   * @type Boolean
   * @private
   */
  @or('isFulfilled', 'isRejected')
  isSettled;

  /**
   * Set this to `true` to reset the `state`. A typical use case is to bind this attribute with ember-data isDirty flag.
   *
   * The old value is not taken into consideration. Setting a `true` value to `true` again will also reset `state`.
   * In that case it's even to notify the observer system that the property has changed by calling
   * [`notifyPropertyChange()`](https://www.emberjs.com/api/ember/3.2/classes/EmberObject/methods/notifyPropertyChange?anchor=notifyPropertyChange).
   *
   * @property reset
   * @type boolean
   * @public
   */
  @defaultValue
  reset = null;

  /**
   * Property for size styling, set to 'lg', 'sm' or 'xs'
   *
   * Also see the [Bootstrap docs](https://getbootstrap.com/docs/4.3/components/buttons/#sizes)
   *
   * @property size
   * @type String
   * @public
   */
  @defaultValue
  size = null;

  @sizeClass('btn', 'size')
  sizeClass;

  /**
   * Property for type styling
   *
   * For the available types see the [Bootstrap docs](https://getbootstrap.com/docs/4.3/components/buttons/)
   *
   * @property type
   * @type String
   * @default 'default'
   * @public
   */

  @typeClass('btn', 'type')
  typeClass;

  /**
   * The HTML title attribute
   *
   * @property title
   * @type string
   * @public
   */
  @defaultValue
  title = null;

  /**
   * When clicking the button this action is called with the value of the button (that is the value of the "value" property).
   *
   * Return a promise object, and the buttons state will automatically set to "pending", "resolved" and/or "rejected".
   * This could be used to automatically set the button's text depending on promise state (`defaultText`, `pendingText`,
   * `fulfilledText`, `rejectedText`) and for futher customization using the yielded `isPending`, `isFulfilled`,
   * `isRejected` properties.
   *
   * The click event will not bubble up, unless you set `bubble` to true.
   *
   * @event onClick
   * @param {*} value
   * @public
   */
  @defaultValue
  onClick = null;

  /**
   * This will reset the state property to 'default', and with that the button's label to defaultText
   *
   * @method resetState
   * @private
   */
  resetState() {
    this.set('state', 'default');
  }

  @observes('reset')
  resetObserver() {
    if (this.get('reset')) {
      scheduleOnce('actions', this, 'resetState');
    }
  }

  @computed('state', 'defaultText', 'pendingText', 'fulfilledText', 'rejectedText')
  get text() {
    return this.getWithDefault(`${this.get('state')}Text`, this.get('defaultText'));
  }

  /**
   * @method click
   * @private
   */
  click() {
    let action = this.get('onClick');
    let preventConcurrency = this.get('preventConcurrency');

    if (action === null || action === undefined) {
      return;
    }

    if (!preventConcurrency || !this.get('isPending')) {
      let promise = (action)(this.get('value'));
      if (promise && typeof promise.then === 'function' && !this.get('isDestroyed')) {
        this.set('state', 'pending');
        promise.then(() => {
          if (!this.get('isDestroyed')) {
            this.set('state', 'fulfilled');
          }
        }, () => {
          if (!this.get('isDestroyed')) {
            this.set('state', 'rejected');
          }
        }
        );
      }
    }

    return this.get('bubble');
  }
}
<commit_msg>Removed deprecated Button#resolvedText<commit_after>import {
  attributeBindings,
  classNameBindings,
  classNames,
  layout as templateLayout,
  tagName,
} from '@ember-decorators/component';

import { observes } from '@ember-decorators/object';
import { computed } from '@ember/object';
import { equal, or } from '@ember/object/computed';
import { scheduleOnce } from '@ember/runloop';
import Component from '@ember/component';
import layout from 'ember-bootstrap/templates/components/bs-button';
import sizeClass from 'ember-bootstrap/utils/cp/size-class';
import typeClass from 'ember-bootstrap/utils/cp/type-class';
import overrideableCP from 'ember-bootstrap/utils/cp/overrideable';
import defaultValue from 'ember-bootstrap/utils/default-decorator';

/**
  Implements a HTML button element, with support for all [Bootstrap button CSS styles](http://getbootstrap.com/css/#buttons)
  as well as advanced functionality such as button states.

  ### Basic Usage

  ```hbs
  <BsButton @type="primary" @icon="glyphicon glyphicon-download">
    Downloads
  </BsButton>
  ```

  ### Actions

  Use the `onClick` property of the component to send an action to your controller. It will receive the button's value
  (see the `value` property) as an argument.

  ```hbs
  <BsButton @type="primary" @icon="glyphicon glyphicon-download" @onClick=(action "download")>
    Downloads
  </BsButton>
  ```

  ### Promise support for automatic state change

  When returning a Promise for any asynchronous operation from the `onClick` closure action the button will
  manage an internal state ("default" > "pending" > "fulfilled"/"rejected") automatically, changing its label
  according to the state of the promise:

  ```hbs
  <BsButton
    (at)type="primary"
    (at)icon="glyphicon glyphicon-download"
    (at)defaultText="Download"
    (at)pendingText="Loading..."
    (at)fulfilledText="Completed!"
    (at)rejectedText="Oups!?"
    (at)onClick={{action "download"}}
  />
  ```

  ```js
  // controller.js
  export default Ember.Controller.extend({
    actions: {
      download(value) {
        return new Ember.RSVP.Promise(...);
      }
    }
  });
  ```

  For further customization `isPending`, `isFulfilled`, `isRejected` and `isSettled` properties are yielded:

  ```hbs
  <BsButton @onClick=(action "download") as |button|>
    Download
    {{#if button.isPending}}
      <span class="loading-spinner"></span>
    {{/if}}
  </BsButton>
  ```

  You can `reset` the state represented by these properties and used for button's text by setting `reset` property to
  `true`.

  @class Button
  @namespace Components
  @extends Ember.Component
  @public
*/
@templateLayout(layout)
@tagName('button')
@classNames('btn')
@classNameBindings('active', 'block:btn-block', 'sizeClass', 'typeClass')
@attributeBindings('_disabled:disabled', 'buttonType:type', 'title')
export default class Button extends Component {
  /**
   * Default label of the button. Not need if used as a block component
   *
   * @property defaultText
   * @type string
   * @public
   */
  @defaultValue
  defaultText = null;

  /**
   * Label of the button used if `onClick` event has returned a Promise which is pending.
   * Not considered if used as a block component.
   *
   * @property pendingText
   * @type string
   * @public
   */
  @defaultValue
  pendingText = undefined;

  /**
   * Label of the button used if `onClick` event has returned a Promise which succeeded.
   * Not considered if used as a block component.
   *
   * @property fulfilledText
   * @type string
   * @public
   */
  @defaultValue
  fulfilledText = undefined;

  /**
   * Label of the button used if `onClick` event has returned a Promise which failed.
   * Not considered if used as a block component.
   *
   * @property rejectedText
   * @type string
   * @public
   */
  @defaultValue
  rejectedText = undefined;

  /**
   * Property to disable the button
   *
   * The button is disabled by default if `preventConcurrency` is `true` and
   * a Promise returned by `onClick` action is pending. You may explicitly
   * enable / disable the button by setting `disabled` to `true` or `false`.
   * Setting it to `null` restores the default behavior.
   *
   * @property disabled
   * @type ?boolean
   * @default null
   * @public
   */
  @defaultValue
  disabled = null;

  @computed('disabled', 'isPending', 'preventConcurrency')
  get _disabled() {
    if (this.get('disabled') !== null) {
      return this.get('disabled');
    }

    return this.get('isPending') && this.get('preventConcurrency');
  }

  /**
   * Set the type of the button, either 'button' or 'submit'
   *
   * @property buttonType
   * @type String
   * @default 'button'
   * @public
   */
  @defaultValue
  buttonType = 'button';

  /**
   * Set the 'active' class to apply active/pressed CSS styling
   *
   * @property active
   * @type boolean
   * @default false
   * @public
   */
  @defaultValue
  active = false;

  /**
   * Property for block level buttons
   *
   * See the [Bootstrap docs](http://getbootstrap.com/css/#buttons-sizes)
   * @property block
   * @type boolean
   * @default false
   * @public
   */
  @defaultValue
  block = false;

  /**
   * A click event on a button will not bubble up the DOM tree if it has an `onClick` action handler. Set to true to
   * enable the event to bubble
   *
   * @property bubble
   * @type boolean
   * @default false
   * @public
   */
  @defaultValue
  bubble = false;

  /**
   * If button is active and this is set, the icon property will match this property
   *
   * @property iconActive
   * @type String
   * @public
   */
  @defaultValue
  iconActive = null;

  /**
   * If button is inactive and this is set, the icon property will match this property
   *
   * @property iconInactive
   * @type String
   * @public
   */
  @defaultValue
  iconInactive = null;

  /**
   * Class(es) (e.g. glyphicons or font awesome) to use as a button icon
   * This will render a  element in front of the button's label
   *
   * @property icon
   * @type String
   * @readonly
   * @public
   */
  @overrideableCP('active', function() {
    if (this.get('active')) {
      return this.get('iconActive');
    } else {
      return this.get('iconInactive');
    }
  })
  icon;

  /**
   * Supply a value that will be associated with this button. This will be send
   * as a parameter of the default action triggered when clicking the button
   *
   * @property value
   * @type any
   * @public
   */
  @defaultValue
  value = null;

  /**
   * Controls if `onClick` action is fired concurrently. If `true` clicking button multiple times will not trigger
   * `onClick` action if a Promise returned by previous click is not settled yet.
   *
   * This does not affect event bubbling.
   *
   * @property preventConcurrency
   * @type Boolean
   * @default true
   * @public
   */
  @defaultValue
  preventConcurrency = true;

  /**
   * State of the button. The button's label (if not used as a block component) will be set to the
   * `<state>Text` property.
   * This property will automatically be set when using a click action that supplies the callback with a promise.
   * Possible values are: "default" > "pending" > "fulfilled" / "rejected".
   * It could be reseted by `reset` property.
   *
   * @property state
   * @type String
   * @default 'default'
   * @private
   */
  @defaultValue
  state = 'default';

  /**
   * Promise returned by `onClick` event is pending.
   *
   * @property isPending
   * @type Boolean
   * @private
   */
  @equal('state', 'pending')
  isPending;

  /**
   * Promise returned by `onClick` event has been succeeded.
   *
   * @property isFulfilled
   * @type Boolean
   * @private
   */
  @equal('state', 'fulfilled')
  isFulfilled;

  /**
   * Promise returned by `onClick` event has been rejected.
   *
   * @property isRejected
   * @type Boolean
   * @private
   */
  @equal('state', 'rejected')
  isRejected;

  /**
   * Promise returned by `onClick` event has been succeeded or rejected.
   *
   * @property isFulfilled
   * @type Boolean
   * @private
   */
  @or('isFulfilled', 'isRejected')
  isSettled;

  /**
   * Set this to `true` to reset the `state`. A typical use case is to bind this attribute with ember-data isDirty flag.
   *
   * The old value is not taken into consideration. Setting a `true` value to `true` again will also reset `state`.
   * In that case it's even to notify the observer system that the property has changed by calling
   * [`notifyPropertyChange()`](https://www.emberjs.com/api/ember/3.2/classes/EmberObject/methods/notifyPropertyChange?anchor=notifyPropertyChange).
   *
   * @property reset
   * @type boolean
   * @public
   */
  @defaultValue
  reset = null;

  /**
   * Property for size styling, set to 'lg', 'sm' or 'xs'
   *
   * Also see the [Bootstrap docs](https://getbootstrap.com/docs/4.3/components/buttons/#sizes)
   *
   * @property size
   * @type String
   * @public
   */
  @defaultValue
  size = null;

  @sizeClass('btn', 'size')
  sizeClass;

  /**
   * Property for type styling
   *
   * For the available types see the [Bootstrap docs](https://getbootstrap.com/docs/4.3/components/buttons/)
   *
   * @property type
   * @type String
   * @default 'default'
   * @public
   */

  @typeClass('btn', 'type')
  typeClass;

  /**
   * The HTML title attribute
   *
   * @property title
   * @type string
   * @public
   */
  @defaultValue
  title = null;

  /**
   * When clicking the button this action is called with the value of the button (that is the value of the "value" property).
   *
   * Return a promise object, and the buttons state will automatically set to "pending", "resolved" and/or "rejected".
   * This could be used to automatically set the button's text depending on promise state (`defaultText`, `pendingText`,
   * `fulfilledText`, `rejectedText`) and for futher customization using the yielded `isPending`, `isFulfilled`,
   * `isRejected` properties.
   *
   * The click event will not bubble up, unless you set `bubble` to true.
   *
   * @event onClick
   * @param {*} value
   * @public
   */
  @defaultValue
  onClick = null;

  /**
   * This will reset the state property to 'default', and with that the button's label to defaultText
   *
   * @method resetState
   * @private
   */
  resetState() {
    this.set('state', 'default');
  }

  @observes('reset')
  resetObserver() {
    if (this.get('reset')) {
      scheduleOnce('actions', this, 'resetState');
    }
  }

  @computed('state', 'defaultText', 'pendingText', 'fulfilledText', 'rejectedText')
  get text() {
    return this.getWithDefault(`${this.get('state')}Text`, this.get('defaultText'));
  }

  /**
   * @method click
   * @private
   */
  click() {
    let action = this.get('onClick');
    let preventConcurrency = this.get('preventConcurrency');

    if (action === null || action === undefined) {
      return;
    }

    if (!preventConcurrency || !this.get('isPending')) {
      let promise = (action)(this.get('value'));
      if (promise && typeof promise.then === 'function' && !this.get('isDestroyed')) {
        this.set('state', 'pending');
        promise.then(() => {
          if (!this.get('isDestroyed')) {
            this.set('state', 'fulfilled');
          }
        }, () => {
          if (!this.get('isDestroyed')) {
            this.set('state', 'rejected');
          }
        }
        );
      }
    }

    return this.get('bubble');
  }
}
<|endoftext|>


<commit_before>var Vectors = require('./Vectors');
var StringUtils = require('./StringUtils');
var rgbToHex = require('./rgbToHex');
var Layer = require('./Layer');
var Tagger = require('./Tagger');

var LayerParser = (function (Vectors, StringUtils, rgbToHex, Layer, Tagger, Math) {
    "use strict";

    function LayerParser(psDocument, animations) {
        this.doc = psDocument;
        this.animations = animations;
    }

    function setOpacity(layer, drawable) {
        if (Layer.isOpacitySet(layer)) {
            drawable.alpha = Layer.getOpacity(layer);
        }
    }

    function setSmartObjectRotation(layer, drawable, topLeft_x, topLeft_y, topRight_x, topRight_y, optionalVector) {
        var isRotation = Layer.isRotated(layer, topLeft_x, topLeft_y);

        if (isRotation) {
            drawable.rotation = Layer.getRotation(optionalVector || topLeft_x, topLeft_y, topRight_x, topRight_y);
        } else {
            drawable.rotation = 0;
        }

        return isRotation;
    }

    function setMatrixRotation(drawable, transformMatrix) {
        if (Layer.isMatrixRotation(transformMatrix)) {
            drawable.rotation = Layer.getMatrixRotation(transformMatrix);
        } else {
            drawable.rotation = 0;
        }
    }

    function setMatrixScale(drawable, transformMatrix) {
        if (transformMatrix)
            drawable.scale = Layer.getMatrixScale(transformMatrix);
    }

    LayerParser.prototype.parseBasicImage = function (layer) {
        var width = layer.bounds.right - layer.bounds.left;
        var height = layer.bounds.bottom - layer.bounds.top;

        var nameParts = layer.name.split(' ');

        var tags = Tagger.parseTags(nameParts);

        var drawable = {
            type: 'image',
            x: Math.floor(layer.bounds.left + width / 2 - this.doc.getArtboard().left),
            y: Math.floor(layer.bounds.top + height / 2 - this.doc.getArtboard().top),
            width: width,
            height: height,
            referenceId: layer.id
        };

        if (StringUtils.includes(nameParts[0], '.png')) {
            drawable.filename = nameParts[0];
        }
        if (tags.length > 0) {
            drawable.tags = tags;
            Tagger.setTaggedId(layer, drawable);
            Tagger.setTaggedZIndex(layer, drawable);
            if (this.animations) {
                Tagger.referenceAnimationTagging(drawable, tags, this.animations, this.doc.getArtboard());
            }
        }

        if (layer.type != 'shapeLayer' && layer.path && layer.path.pathComponents[0].origin.type == 'rect') {
            var mask = {};

            var a = layer.path.pathComponents[0].subpathListKey[0].points[0].anchor;
            var b = layer.path.pathComponents[0].subpathListKey[0].points[1].anchor;
            var c = layer.path.pathComponents[0].subpathListKey[0].points[2].anchor;

            var a_b = Vectors.get(a.x, a.y, b.x, b.y);
            mask.width = Math.floor(Vectors.magnitude(a_b.x, a_b.y));

            var b_c = Vectors.get(b.x, b.y, c.x, c.y);
            mask.height = Math.floor(Vectors.magnitude(b_c.x, b_c.y));

            mask.rotation = Layer.getRotation(a_b);

            var bounds = layer.path.pathComponents[0].origin.bounds;
            var boundsWidth = bounds.right - bounds.left;
            var boundsHeight = bounds.bottom - bounds.top;

            mask.x = Math.floor(bounds.left + boundsWidth / 2 - this.doc.getArtboard().left);
            mask.y = Math.floor(bounds.top + boundsHeight / 2 - this.doc.getArtboard().top);

            drawable.mask = mask;
        }

        return drawable;
    };

    LayerParser.prototype.parseShape = function (layer) {
        var type;
        if (layer.path.pathComponents[0].origin.type == 'line') {
            type = 'line';

        } else if (layer.path.pathComponents[0].origin.type == 'rect') {
            type = 'rectangle';
        }

        var drawable = this.parseBasicImage(layer);
        drawable.type = type;

        if (type == 'line') {
            var a = layer.path.pathComponents[0].subpathListKey[0].points[1].anchor;
            var b = layer.path.pathComponents[0].subpathListKey[0].points[2].anchor;
            var v = Vectors.get(a.x, a.y, b.x, b.y);
            drawable.length = Math.floor(Vectors.magnitude(v.x, v.y));
            drawable.rotation = Layer.getRotation(v);
        }

        setOpacity(layer, drawable);
        drawable.filled = layer.fill !== undefined;
        if (layer.strokeStyle) {
            drawable.filled = layer.strokeStyle.fillEnabled;
            if (layer.strokeStyle.strokeEnabled)
                drawable.lineWidth = layer.strokeStyle.strokeStyleLineWidth.value;
        }
        var color = drawable.filled ? layer.fill.color : layer.strokeStyle.strokeStyleContent.color;
        drawable.color = rgbToHex(color.red, color.green, color.blue);

        return drawable;
    };

    LayerParser.prototype.parseText = function (layer) {
        var drawable = this.parseBasicImage(layer);
        drawable.type = 'text';
        drawable.msg = layer.text.textKey;

        setOpacity(layer, drawable);
        setMatrixRotation(drawable, layer.text.transform);
        setMatrixScale(drawable, layer.text.transform);

        var style = layer.text.textStyleRange[0].textStyle; // apply only style of 1st style range
        drawable.font = style.fontName;
        drawable.size = style.size.value; // maybe px vs pt issues
        drawable.color = style.color ? rgbToHex(style.color.red, style.color.green, style.color.blue) : '#000000';

        return drawable;
    };

    LayerParser.prototype.parseSmartObject = function (layer) {
        var drawable = this.parseBasicImage(layer);

        var topLeft_x = Math.floor(layer.smartObject.transform[0]);
        var topLeft_y = Math.floor(layer.smartObject.transform[1]);
        var topRight_x = Math.floor(layer.smartObject.transform[2]);
        var topRight_y = Math.floor(layer.smartObject.transform[3]);
        var vector = Vectors.get(topLeft_x, topLeft_y, topRight_x, topRight_y);

        var isRotation = setSmartObjectRotation(layer, drawable, topLeft_x, topLeft_y, topRight_x, topRight_y, vector);

        var original = this.doc.getPlaced(layer.smartObject);
        // var originalHeight = original.bounds.bottom - original.bounds.top; // not used, atm scale affects w&h equally
        var originalWidth = original.bounds.right - original.bounds.left;

        if (isRotation) {
            drawable.scale = Vectors.magnitude(vector.x, vector.y) / originalWidth;
        } else {
            drawable.scale = drawable.width / originalWidth;
        }
        drawable.scale = Math.round(drawable.scale * 100) / 100;

        setOpacity(layer, drawable);

        return drawable;
    };

    LayerParser.prototype.parseLayer = function (layer) {
        if (layer.smartObject) {
            return this.parseSmartObject(layer);

        } else if (StringUtils.includes(layer.name, '.png')) {
            return this.parseBasicImage(layer);

        } else if (layer.type == 'textLayer') {
            return this.parseText(layer);

        } else if (layer.type == 'shapeLayer') {
            return this.parseShape(layer);
        }
    };

    LayerParser.prototype.parseButton = function (layerGroup) {
        var button = {};
        button.type = 'button';
        Tagger.setTaggedId(layerGroup, button);
        Tagger.setTaggedZIndex(layerGroup, button);

        layerGroup.layers.forEach(function (layer) {
            if (layer.type == 'textLayer') {
                button.text = this.parseText(layer);
            } else if (StringUtils.includes(layer.name, '#input')) {
                button.input = this.parseShape(layer);
            } else if (StringUtils.includes(layer.name, '#background')) {
                button.background = this.parseLayer(layer);
            }
        }, this);

        return button;
    };

    LayerParser.prototype.parseTaggedLayerGroup = function (layerGroup) {
        var drawables = [];
        if (StringUtils.includes(layerGroup.name, '#ignore')) {
            return drawables;

        } else if (StringUtils.includes(layerGroup.name, '#button')) {
            drawables.push(this.parseButton(layerGroup));

        } else if (StringUtils.includes(layerGroup.name, '#')) {
            var tags = Tagger.parseTags(layerGroup.name.split(' '));
            this.parseLayerGroup(layerGroup).forEach(function (elem) {
                if (elem.tags) {
                    elem.tags.push.apply(elem.tags, tags);
                } else {
                    elem.tags = tags.slice();
                }
                if (this.animations) {
                    Tagger.referenceAnimationTagging(elem, tags, this.animations, this.doc.getArtboard());
                }
                Tagger.setGroupTaggedZIndex(elem, tags);

                drawables.push(elem);
            }, this);
        }

        return drawables;
    };

    LayerParser.prototype.parseLayerGroup = function (layerGroup) {
        var drawables = [];
        layerGroup.layers.forEach(function (layer) {
            if (layer.type == 'layer' || layer.type == 'textLayer' || layer.type == 'shapeLayer') {
                var drawable = this.parseLayer(layer);
                if (drawable)
                    drawables.push(drawable);

            } else if (layer.type == 'layerSection') {
                drawables.push.apply(drawables, this.parseGroup(layer));
            }
        }, this);

        return drawables;
    };

    LayerParser.prototype.parseGroup = function (layerGroup) {
        if (StringUtils.includes(layerGroup.name, '#')) {
            return this.parseTaggedLayerGroup(layerGroup);

        } else if (StringUtils.includes(layerGroup.name, '.png')) {
            return [this.parseBasicImage(layerGroup)];

        } else {
            return this.parseLayerGroup(layerGroup);
        }
    };

    return LayerParser;
})(Vectors, StringUtils, rgbToHex, Layer, Tagger, Math);

module.exports = LayerParser;<commit_msg>set opacity of basic images, parse basic images prior to tagged stuff if you have to choose<commit_after>var Vectors = require('./Vectors');
var StringUtils = require('./StringUtils');
var rgbToHex = require('./rgbToHex');
var Layer = require('./Layer');
var Tagger = require('./Tagger');

var LayerParser = (function (Vectors, StringUtils, rgbToHex, Layer, Tagger, Math) {
    "use strict";

    function LayerParser(psDocument, animations) {
        this.doc = psDocument;
        this.animations = animations;
    }

    function setOpacity(layer, drawable) {
        if (Layer.isOpacitySet(layer)) {
            drawable.alpha = Layer.getOpacity(layer);
        }
    }

    function setSmartObjectRotation(layer, drawable, topLeft_x, topLeft_y, topRight_x, topRight_y, optionalVector) {
        var isRotation = Layer.isRotated(layer, topLeft_x, topLeft_y);

        if (isRotation) {
            drawable.rotation = Layer.getRotation(optionalVector || topLeft_x, topLeft_y, topRight_x, topRight_y);
        } else {
            drawable.rotation = 0;
        }

        return isRotation;
    }

    function setMatrixRotation(drawable, transformMatrix) {
        if (Layer.isMatrixRotation(transformMatrix)) {
            drawable.rotation = Layer.getMatrixRotation(transformMatrix);
        } else {
            drawable.rotation = 0;
        }
    }

    function setMatrixScale(drawable, transformMatrix) {
        if (transformMatrix)
            drawable.scale = Layer.getMatrixScale(transformMatrix);
    }

    LayerParser.prototype.parseBasicImage = function (layer) {
        var width = layer.bounds.right - layer.bounds.left;
        var height = layer.bounds.bottom - layer.bounds.top;

        var nameParts = layer.name.split(' ');

        var tags = Tagger.parseTags(nameParts);

        var drawable = {
            type: 'image',
            x: Math.floor(layer.bounds.left + width / 2 - this.doc.getArtboard().left),
            y: Math.floor(layer.bounds.top + height / 2 - this.doc.getArtboard().top),
            width: width,
            height: height,
            referenceId: layer.id
        };

        setOpacity(layer, drawable);

        if (StringUtils.includes(nameParts[0], '.png')) {
            drawable.filename = nameParts[0];
        }
        if (tags.length > 0) {
            drawable.tags = tags;
            Tagger.setTaggedId(layer, drawable);
            Tagger.setTaggedZIndex(layer, drawable);
            if (this.animations) {
                Tagger.referenceAnimationTagging(drawable, tags, this.animations, this.doc.getArtboard());
            }
        }

        if (layer.type != 'shapeLayer' && layer.path && layer.path.pathComponents[0].origin.type == 'rect') {
            var mask = {};

            var a = layer.path.pathComponents[0].subpathListKey[0].points[0].anchor;
            var b = layer.path.pathComponents[0].subpathListKey[0].points[1].anchor;
            var c = layer.path.pathComponents[0].subpathListKey[0].points[2].anchor;

            var a_b = Vectors.get(a.x, a.y, b.x, b.y);
            mask.width = Math.floor(Vectors.magnitude(a_b.x, a_b.y));

            var b_c = Vectors.get(b.x, b.y, c.x, c.y);
            mask.height = Math.floor(Vectors.magnitude(b_c.x, b_c.y));

            mask.rotation = Layer.getRotation(a_b);

            var bounds = layer.path.pathComponents[0].origin.bounds;
            var boundsWidth = bounds.right - bounds.left;
            var boundsHeight = bounds.bottom - bounds.top;

            mask.x = Math.floor(bounds.left + boundsWidth / 2 - this.doc.getArtboard().left);
            mask.y = Math.floor(bounds.top + boundsHeight / 2 - this.doc.getArtboard().top);

            drawable.mask = mask;
        }

        return drawable;
    };

    LayerParser.prototype.parseShape = function (layer) {
        var type;
        if (layer.path.pathComponents[0].origin.type == 'line') {
            type = 'line';

        } else if (layer.path.pathComponents[0].origin.type == 'rect') {
            type = 'rectangle';
        }

        var drawable = this.parseBasicImage(layer);
        drawable.type = type;

        if (type == 'line') {
            var a = layer.path.pathComponents[0].subpathListKey[0].points[1].anchor;
            var b = layer.path.pathComponents[0].subpathListKey[0].points[2].anchor;
            var v = Vectors.get(a.x, a.y, b.x, b.y);
            drawable.length = Math.floor(Vectors.magnitude(v.x, v.y));
            drawable.rotation = Layer.getRotation(v);
        }

        drawable.filled = layer.fill !== undefined;
        if (layer.strokeStyle) {
            drawable.filled = layer.strokeStyle.fillEnabled;
            if (layer.strokeStyle.strokeEnabled)
                drawable.lineWidth = layer.strokeStyle.strokeStyleLineWidth.value;
        }
        var color = drawable.filled ? layer.fill.color : layer.strokeStyle.strokeStyleContent.color;
        drawable.color = rgbToHex(color.red, color.green, color.blue);

        return drawable;
    };

    LayerParser.prototype.parseText = function (layer) {
        var drawable = this.parseBasicImage(layer);
        drawable.type = 'text';
        drawable.msg = layer.text.textKey;

        setMatrixRotation(drawable, layer.text.transform);
        setMatrixScale(drawable, layer.text.transform);

        var style = layer.text.textStyleRange[0].textStyle; // apply only style of 1st style range
        drawable.font = style.fontName;
        drawable.size = style.size.value; // maybe px vs pt issues
        drawable.color = style.color ? rgbToHex(style.color.red, style.color.green, style.color.blue) : '#000000';

        return drawable;
    };

    LayerParser.prototype.parseSmartObject = function (layer) {
        var drawable = this.parseBasicImage(layer);

        var topLeft_x = Math.floor(layer.smartObject.transform[0]);
        var topLeft_y = Math.floor(layer.smartObject.transform[1]);
        var topRight_x = Math.floor(layer.smartObject.transform[2]);
        var topRight_y = Math.floor(layer.smartObject.transform[3]);
        var vector = Vectors.get(topLeft_x, topLeft_y, topRight_x, topRight_y);

        var isRotation = setSmartObjectRotation(layer, drawable, topLeft_x, topLeft_y, topRight_x, topRight_y, vector);

        var original = this.doc.getPlaced(layer.smartObject);
        // var originalHeight = original.bounds.bottom - original.bounds.top; // not used, atm scale affects w&h equally
        var originalWidth = original.bounds.right - original.bounds.left;

        if (isRotation) {
            drawable.scale = Vectors.magnitude(vector.x, vector.y) / originalWidth;
        } else {
            drawable.scale = drawable.width / originalWidth;
        }
        drawable.scale = Math.round(drawable.scale * 100) / 100;

        return drawable;
    };

    LayerParser.prototype.parseLayer = function (layer) {
        if (layer.smartObject) {
            return this.parseSmartObject(layer);

        } else if (StringUtils.includes(layer.name, '.png')) {
            return this.parseBasicImage(layer);

        } else if (layer.type == 'textLayer') {
            return this.parseText(layer);

        } else if (layer.type == 'shapeLayer') {
            return this.parseShape(layer);
        }
    };

    LayerParser.prototype.parseButton = function (layerGroup) {
        var button = {};
        button.type = 'button';
        Tagger.setTaggedId(layerGroup, button);
        Tagger.setTaggedZIndex(layerGroup, button);

        layerGroup.layers.forEach(function (layer) {
            if (layer.type == 'textLayer') {
                button.text = this.parseText(layer);
            } else if (StringUtils.includes(layer.name, '#input')) {
                button.input = this.parseShape(layer);
            } else if (StringUtils.includes(layer.name, '#background')) {
                button.background = this.parseLayer(layer);
            }
        }, this);

        return button;
    };

    LayerParser.prototype.parseTaggedLayerGroup = function (layerGroup) {
        var drawables = [];
        if (StringUtils.includes(layerGroup.name, '#ignore')) {
            return drawables;

        } else if (StringUtils.includes(layerGroup.name, '#button')) {
            drawables.push(this.parseButton(layerGroup));

        } else if (StringUtils.includes(layerGroup.name, '#')) {
            var tags = Tagger.parseTags(layerGroup.name.split(' '));
            this.parseLayerGroup(layerGroup).forEach(function (elem) {
                if (elem.tags) {
                    elem.tags.push.apply(elem.tags, tags);
                } else {
                    elem.tags = tags.slice();
                }
                if (this.animations) {
                    Tagger.referenceAnimationTagging(elem, tags, this.animations, this.doc.getArtboard());
                }
                Tagger.setGroupTaggedZIndex(elem, tags);

                drawables.push(elem);
            }, this);
        }

        return drawables;
    };

    LayerParser.prototype.parseLayerGroup = function (layerGroup) {
        var drawables = [];
        layerGroup.layers.forEach(function (layer) {
            if (layer.type == 'layer' || layer.type == 'textLayer' || layer.type == 'shapeLayer') {
                var drawable = this.parseLayer(layer);
                if (drawable)
                    drawables.push(drawable);

            } else if (layer.type == 'layerSection') {
                drawables.push.apply(drawables, this.parseGroup(layer));
            }
        }, this);

        return drawables;
    };

    LayerParser.prototype.parseGroup = function (layerGroup) {
        if (StringUtils.includes(layerGroup.name, '.png')) {
            return [this.parseBasicImage(layerGroup)];

        } else if (StringUtils.includes(layerGroup.name, '#')) {
            return this.parseTaggedLayerGroup(layerGroup);

        } else {
            return this.parseLayerGroup(layerGroup);
        }
    };

    return LayerParser;
})(Vectors, StringUtils, rgbToHex, Layer, Tagger, Math);

module.exports = LayerParser;<|endoftext|>


<commit_before>var Mapbender = Mapbender || {};
Mapbender.transCallBack = function(objToCallBack, termsToTranslate, saveAtAll) {
    if(typeof(saveAtAll) === 'undefined'){
        saveAtAll = false;
    }
    if(typeof(Mapbender.alltranslations) !== 'undefined'){
        try {
            var result = {};
            for(var key in termsToTranslate){
                result[key] = Mapbender.alltranslations[key];
            }
            objToCallBack.transCallBack(result);
            return;
        }catch(e){}
    }
    var mb = this;
    $.ajax({
        url: mb.configuration.transPath,
        type: "post",
        data: termsToTranslate,
        dataType: "json",
        complete: function(jqXHR, textStatus) {
            if(textStatus == "success") {
                termsToTranslate = $.parseJSON(jqXHR.responseText);
                if(saveAtAll) {
                    if(typeof(Mapbender.alltranslations) === 'undefined'){
                        Mapbender.alltranslations = {};
                    }
                    for(var key in termsToTranslate){
                        Mapbender.alltranslations[key] = termsToTranslate[key];
                    }
                }
            }
            objToCallBack.transCallBack(termsToTranslate);
        }
    });
};

Mapbender.strToHex = function(term) {
    var r="";
    var c=0;
    var h;
    while(c<term.length){
        h=term.charCodeAt(c++).toString(16);
        while(h.length<3) h="0"+h;
        r+=h;
    }
    return r;
//    return term.toLowerCase().replace(/[^a-z0-9]/g, "_");
};

Mapbender.termsToTranslate = function(terms) {
    var translatedterms = {};
    for(var i = 0; i < terms.length; i++) {
        translatedterms[this.strToHex(terms[i])] = terms[i];
    }
    return translatedterms;
};

Mapbender.getTrans = function(translatedterms, term) {
    var result = term;
    try {
        result = translatedterms[this.strToHex(term)];
    }catch(e){  }
    return result;
};

Mapbender.getTransFromAll = function(term) {
    var result = term;
    try {
        result = Mapbender.alltranslations[this.strToHex(term)];
    }catch(e){  }
    return result;
};
<commit_msg>translation geändert<commit_after>var Mapbender = Mapbender || {};
Mapbender.alltranslations = {};
Mapbender.transCallBack = function(objToCallBack, termsToTranslate, saveAtAll) {
    if(typeof(saveAtAll) === 'undefined'){
        saveAtAll = false;
    }
    if(typeof(Mapbender.alltranslations) !== 'undefined'){
        var result = {};
        var ok = true;
        for(var key in termsToTranslate){
            if(typeof(Mapbender.alltranslations[key]) === 'undefined') {
                ok = false;
                break;
            } else {
                result[key] = Mapbender.alltranslations[key];
            }
        }
        if(ok) {
            objToCallBack.transCallBack(result);
            return;
        }
    }
    var mb = this;
    $.ajax({
        url: mb.configuration.transPath,
        type: "post",
        data: termsToTranslate,
        dataType: "json",
        complete: function(jqXHR, textStatus) {
            if(textStatus == "success") {
                termsToTranslate = $.parseJSON(jqXHR.responseText);
                if(saveAtAll) {
                    for(var key in termsToTranslate){
                        Mapbender.alltranslations[key] = termsToTranslate[key];
                    }
                }
            }
            objToCallBack.transCallBack(termsToTranslate);
        }
    });
};

Mapbender.strToHex = function(term) {
    var r="";
    var c=0;
    var h;
    while(c<term.length){
        h=term.charCodeAt(c++).toString(16);
        while(h.length<3) h="0"+h;
        r+=h;
    }
    return r;
//    return term.toLowerCase().replace(/[^a-z0-9]/g, "_");
};

Mapbender.termsToTranslate = function(terms) {
    var translatedterms = {};
    for(var i = 0; i < terms.length; i++) {
        translatedterms[this.strToHex(terms[i])] = terms[i];
    }
    return translatedterms;
};

Mapbender.getTrans = function(translatedterms, term) {
    var result = term;
    try {
        result = translatedterms[this.strToHex(term)];
    }catch(e){  }
    return result;
};

Mapbender.getTransFromAll = function(term) {
    var result = term;
    try {
        result = Mapbender.alltranslations[this.strToHex(term)];
    }catch(e){
        var e = e;
    }
    return result;
};
<|endoftext|>


<commit_before>var _ = require('lodash');
module.exports = function(model) {
    'use strict';

    let propertyTypes = [
        'number',
        'string',
        'histogram',
        'composition'
    ];

    let propertyUnits = [
        'mm',
        'm',
        'c',
        'f'
    ];

    return {
        mustExist: mustExist,
        mustNotExist: mustNotExist,
        mustNotExistInProject: mustNotExistInProject,
        isValidPropertyType: isValidPropertyType,
        isValidUnit: isValidUnit
    };

    // mustExist looks up an entry in the named table by id. If
    // the entry doesn't exist it returns an error.
    function mustExist(what, modelName, done) {
        model[modelName].get(what).then(function(value) {
            let error = null;
            if (!value) {
                error = {
                    rule: 'mustExist',
                    actual: what,
                    expected: 'did not find ' + what + ' in model'
                };
            }
            done(error);
        });
    }

    // mustNotExist looks up an entry in the named table by the named
    // index. If the entry exists it returns an error.
    function mustNotExist(what, spec, done) {
        let pieces = spec.split(':'),
            modelName = pieces[0],
            modelIndex = pieces[1];
        model[modelName].get(what, modelIndex).then(function(value) {
            let error = null;
            if (value) {
                // found a match, when we shouldn't have
                error = {
                    rule: 'mustNotExist',
                    actual: what,
                    expected: `found ${what} in model`
                };
            }
            done(error);
        });
    }

    // mustNotExistInProject ensures that the item doesn't exist in
    // the project.
    function mustNotExistInProject(what, spec, done) {
        let pieces = spec.split(':'),
            modelName = pieces[0],
            index = pieces[1];
        let project_id = this.project_id;
        model[modelName].findInProject(this.project_id, index, what).then(function(matches) {
            let error = matches.length === 0 ? null : {
                rule: 'mustNotExistInProject',
                actual: 'what',
                expected: `${index}:${what} should not exist in project ${project_id}`
            };
            done(error);
        });
    }

    // isValidPropertyType checks the different known types for a property.
    function isValidPropertyType(what, _ignore) {
        let invalid = {
            rule: 'isValidPropertyType',
            actual: what,
            expected: `type to be one of ${propertyTypes}`
        };
        return _.indexOf(propertyTypes, what) === -1 ? invalid : null;
    }

    // isValidUnit checks the different known types for unit.
    function isValidUnit(what, _ignore) {
        let invalid = {
            rule: 'isValidUnit',
            actual: what,
            expected: `units to be one of ${propertyUnits}`
        };
        return _.indexOf(propertyUnits, what) === -1 ? invalid : null;
    }
};
<commit_msg>Add mustExistInProject.<commit_after>var _ = require('lodash');
module.exports = function(model) {
    'use strict';

    let propertyTypes = [
        'number',
        'string',
        'histogram',
        'composition'
    ];

    let propertyUnits = [
        'mm',
        'm',
        'c',
        'f'
    ];

    return {
        mustExist: mustExist,
        mustNotExist: mustNotExist,
        mustNotExistInProject: mustNotExistInProject,
        mustExistInProject: mustExistInProject,
        isValidPropertyType: isValidPropertyType,
        isValidUnit: isValidUnit
    };

    ////////////////////////////////////////

    // mustExist looks up an entry in the named table by id. If
    // the entry doesn't exist it returns an error.
    function mustExist(what, modelName, done) {
        model[modelName].get(what).then(function(value) {
            let error = null;
            if (!value) {
                error = {
                    rule: 'mustExist',
                    actual: what,
                    expected: 'did not find ' + what + ' in model'
                };
            }
            done(error);
        });
    }

    // mustNotExist looks up an entry in the named table by the named
    // index. If the entry exists it returns an error.
    function mustNotExist(what, spec, done) {
        let pieces = spec.split(':'),
            modelName = pieces[0],
            modelIndex = pieces[1];
        model[modelName].get(what, modelIndex).then(function(value) {
            let error = null;
            if (value) {
                // found a match, when we shouldn't have
                error = {
                    rule: 'mustNotExist',
                    actual: what,
                    expected: `found ${what} in model`
                };
            }
            done(error);
        });
    }

    // mustNotExistInProject ensures that the item doesn't exist in
    // the project.
    function mustNotExistInProject(what, spec, done) {
        let pieces = spec.split(':'),
            modelName = pieces[0],
            index = pieces[1];
        let project_id = this.project_id;
        model[modelName].findInProject(this.project_id, index, what).then(function(matches) {
            let error = matches.length === 0 ? null : {
                rule: 'mustNotExistInProject',
                actual: what,
                expected: `${index}:${what} should not exist in project ${project_id}`
            };
            done(error);
        });
    }

    // mustExistInProject ensures that the item exists in the project.
    function mustExistInProject(what, modelName, done) {
        let project_id = this.project_id;
        model[modelName].findInProject(this.project_id, 'id', what)
            .then(function(matches) {
                let error = matches.length !== 0 ? null : {
                    rules: 'mustExistInProject',
                    actual: what,
                    expected: `${what} should exist in project ${project_id}`
                };
                done(error);
            });
    }

    // isValidPropertyType checks the different known types for a property.
    function isValidPropertyType(what, _ignore) {
        let invalid = {
            rule: 'isValidPropertyType',
            actual: what,
            expected: `type to be one of ${propertyTypes}`
        };
        return _.indexOf(propertyTypes, what) === -1 ? invalid : null;
    }

    // isValidUnit checks the different known types for unit.
    function isValidUnit(what, _ignore) {
        let invalid = {
            rule: 'isValidUnit',
            actual: what,
            expected: `units to be one of ${propertyUnits}`
        };
        return _.indexOf(propertyUnits, what) === -1 ? invalid : null;
    }
};
<|endoftext|>