<commit_before>// For getting a new Morphic world setup in old Lively
import { num, arr } from "lively.lang";
import { pt, Color, Point } from "lively.graphics";
import { morph, MorphicEnv } from "lively.morphic";
import { ObjectDrawer, Window } from "lively.morphic/widgets.js";

export function setupMorphicWorldOn(htmlMorph) {
  var rootNode = htmlMorph.renderContext().shapeNode,
      env = MorphicEnv.default(),
      world = morph({
        env, type: "world", extent: Point.ensure(htmlMorph.getExtent()),
        submorphs: [
          new ObjectDrawer({env, position: pt(20,10)}),
          new Window({env, extent: pt(200, 300), position: pt(200,200)}),
          new Window({env, extent: pt(200, 300), position: pt(400,200)})
        ]});
  env.setWorldRenderedOn(world, rootNode)

  // FIXME currently used for show()
  window.$$world = world;
  return env;
}

function addMorphicSetupMethods(htmlMorph) {
  htmlMorph.doNotSerialize = ["env"];
  htmlMorph.addScript(function cleanupNewMorphicWorld() {
    if (this.env) {
      this.env && this.env.uninstall();
    }
    this.setHTML('');
    this.env = null;
    window.lively.modules.importPackage("node_modules/lively.morphic")
      .then(() => window.System.import("lively.morphic/env.js"))
      .then(env => env.MorphicEnv.reset());
  });

  htmlMorph.addScript(function setupNewMorphicWorld() {
    this.cleanupNewMorphicWorld();
    return window.lively.next.bootstrapped
      .then(() => window.lively.modules.importPackage("node_modules/lively.morphic"))
      .then(() => window.System.import("lively.morphic/old-lively-helpers.js"))
      .then(helpers => this.env = helpers.setupMorphicWorldOn(this))
      .catch(err => window.$world.logError(err));
  });

  htmlMorph.addScript(function onShutdown() { this.cleanupNewMorphicWorld(); });
  htmlMorph.addScript(function onLoad() { this.setupNewMorphicWorld(); });
}

function createHtmlMorph() {
  var htmlMorph = new lively.morphic.HtmlWrapperMorph(pt(666,600));
  htmlMorph.removeStyleClassName("selectable");
  htmlMorph.addScript(function onMouseDown() {});
  htmlMorph.addScript(function onContextMenu() {});
  htmlMorph.addScript(function onKeyDown() {});
  htmlMorph.name = "lively.morphic world"
  htmlMorph.setHTML("");
  htmlMorph.setFill(window.Color.white);
  addMorphicSetupMethods(htmlMorph);

  var win = htmlMorph.openInWindow();
  win.name = "window for lively.morphic world";

  var titleBar = htmlMorph.getWindow().titleBar;
  var resetButton = new lively.morphic.Button(window.rect(0,0,60,18), "reset");
  titleBar.addMorph(resetButton);
  var left = Math.min.apply(null, titleBar.buttons.invoke("getPosition").pluck("x"));
  resetButton.align(resetButton.bounds().topRight(), window.pt(left-10, 2))
  titleBar.buttons.push(resetButton);
  window.lively.bindings.connect(resetButton, 'fire', htmlMorph, 'setupNewMorphicWorld');
  window.lively.bindings.connect(htmlMorph.getWindow().closeButton, 'fire', htmlMorph, 'cleanupNewMorphicWorld');

  return htmlMorph;
}

export function createWorld(world) {
  var htmlMorph = createHtmlMorph();
  htmlMorph.getWindow().openInWorldCenter()
  htmlMorph.onLoad()
  return htmlMorph;
}
<commit_msg>env reset on cleanupNewMorphicWorld in old ively helpers<commit_after>// For getting a new Morphic world setup in old Lively
import { num, arr } from "lively.lang";
import { pt, Color, Point } from "lively.graphics";
import { morph, MorphicEnv } from "lively.morphic";
import { ObjectDrawer, Window } from "lively.morphic/widgets.js";

export function setupMorphicWorldOn(htmlMorph) {
  var rootNode = htmlMorph.renderContext().shapeNode,
      env = MorphicEnv.default(),
      world = morph({
        env, type: "world", extent: Point.ensure(htmlMorph.getExtent()),
        submorphs: [
          new ObjectDrawer({env, position: pt(20,10)}),
          new Window({env, extent: pt(200, 300), position: pt(200,200)}),
          new Window({env, extent: pt(200, 300), position: pt(400,200)})
        ]});
  env.setWorldRenderedOn(world, rootNode)

  // FIXME currently used for show()
  window.$$world = world;
  return env;
}

function addMorphicSetupMethods(htmlMorph) {
  htmlMorph.doNotSerialize = ["env"];
  htmlMorph.addScript(function cleanupNewMorphicWorld() {
    if (this.env) {
      this.env.uninstall();
      this.env.constructor.reset();
    }
    this.setHTML('');
    this.env = null;
    window.lively.modules.importPackage("node_modules/lively.morphic")
      .then(() => window.System.import("lively.morphic/env.js"))
      .then(env => env.MorphicEnv.reset());
  });

  htmlMorph.addScript(function setupNewMorphicWorld() {
    this.cleanupNewMorphicWorld();
    return window.lively.next.bootstrapped
      .then(() => window.lively.modules.importPackage("node_modules/lively.morphic"))
      .then(() => window.System.import("lively.morphic/old-lively-helpers.js"))
      .then(helpers => this.env = helpers.setupMorphicWorldOn(this))
      .catch(err => window.$world.logError(err));
  });

  htmlMorph.addScript(function onShutdown() { this.cleanupNewMorphicWorld(); });
  htmlMorph.addScript(function onLoad() { this.setupNewMorphicWorld(); });
}

function createHtmlMorph() {
  var htmlMorph = new lively.morphic.HtmlWrapperMorph(pt(666,600));
  htmlMorph.removeStyleClassName("selectable");
  htmlMorph.addScript(function onMouseDown() {});
  htmlMorph.addScript(function onContextMenu() {});
  htmlMorph.addScript(function onKeyDown() {});
  htmlMorph.name = "lively.morphic world"
  htmlMorph.setHTML("");
  htmlMorph.setFill(window.Color.white);
  addMorphicSetupMethods(htmlMorph);

  var win = htmlMorph.openInWindow();
  win.name = "window for lively.morphic world";

  var titleBar = htmlMorph.getWindow().titleBar;
  var resetButton = new lively.morphic.Button(window.rect(0,0,60,18), "reset");
  titleBar.addMorph(resetButton);
  var left = Math.min.apply(null, titleBar.buttons.invoke("getPosition").pluck("x"));
  resetButton.align(resetButton.bounds().topRight(), window.pt(left-10, 2))
  titleBar.buttons.push(resetButton);
  window.lively.bindings.connect(resetButton, 'fire', htmlMorph, 'setupNewMorphicWorld');
  window.lively.bindings.connect(htmlMorph.getWindow().closeButton, 'fire', htmlMorph, 'cleanupNewMorphicWorld');

  return htmlMorph;
}

export function createWorld(world) {
  var htmlMorph = createHtmlMorph();
  htmlMorph.getWindow().openInWorldCenter()
  htmlMorph.onLoad()
  return htmlMorph;
}
<|endoftext|>


<commit_before>exports.definition = {
	config: {
		// No need to define columns object, loading the db_file
		// below will do that for us.

		"adapter": {
			"type": "sql",

			// The table name inside the sqlite database to use for
			// models and collections based on this definition.
			"collection_name": "fighters",

			// db_file tells model to use myapp.sqlite file to install
			// database and to use "myapp" as the database name for
			// all further operations
			"db_file": "/myapp.sqlite",

			// idAttribute tells Alloy/Backbone to use this column in
			// my table as its unique identifier field. Without
			// specifying this, Alloy's default behavior is to create
			// and "alloy_id" field which will uniquely identify your
			// rows in the table.
			"idAttribute": "id"
		}
	}
}<commit_msg>addition of attribute remoteBackup to model adapter to provide ability to set Ti.Filesystem.File.remoteBackup.<commit_after>exports.definition = {
	config: {
		// No need to define columns object, loading the db_file
		// below will do that for us.

		"adapter": {
			"type": "sql",

			// The table name inside the sqlite database to use for
			// models and collections based on this definition.
			"collection_name": "fighters",

			// db_file tells model to use myapp.sqlite file to install
			// database and to use "myapp" as the database name for
			// all further operations
			"db_file": "/myapp.sqlite",

			// idAttribute tells Alloy/Backbone to use this column in
			// my table as its unique identifier field. Without
			// specifying this, Alloy's default behavior is to create
			// and "alloy_id" field which will uniquely identify your
			// rows in the table.
			"idAttribute": "id",

			// remoteBackup tells Alloy to set the value of the property
			// Ti.Filesystem.File.remoteBackup. This setting tells iOS
			// whether or not to allow your database to be backed up to
			// iCloud or in iTunes backups. This setting is optional and has
			// one value "off" otherwise it defaults to "on".
			"remoteBackup": "off"
		}
	}
}<|endoftext|>


<commit_before>(function() {
  'use strict';
  Polymer({
    is: 'paper-typeahead',
    behaviors: [
      Polymer.IronA11yKeysBehavior,
      Polymer.IronSelectableBehavior,
      Polymer.PaperInputBehavior,
      Polymer.IronControlState,
      Polymer.IronFormElementBehavior
    ],
    properties: {
      arrowsUpdateInput: {
        type: Boolean,
        value: false
      },
      showEmptyResults: {
        type: Boolean,
        value: false
      },
      typedValue: {
        type: String,
        observer: '_typedValueChanged',
        value: '',
        notify: true
      },
      elevation: {
        type: Number,
        value: 1
      },
      keyEventTarget: {
        type: Object,
        value: function() {
          return this;
        }
      },
      typeaheadDisabled: {
        type: Boolean,
        value: false
      },
      data: {
        type: Array,
        value: function() { return []; }
      },
      maxResults: {
        type: Number,
        value: 10
      },
      filteredItems: {
        type: Array,
        computed: '_getFiltered(data.*, typedValue, filterFn, maxResults,' +
        'typeaheadDisabled)',
        notify: true
      },
      filterFn: {
        type: Function,
        value: function() {
          return function(data, value) {
            var r = RegExp(value, 'i');

            if (value === '') {
              return this.showEmptyResults ? data : [];
            }

            return data.filter(function(v) {
              return (r.test(v) ? v : null);
            });
          };
        }
      },
      // private because we don't want the user to set it true if there is no results
      _hideResults: {
        type: Boolean,
        value: true
      },
    },
    keyBindings: {
      'up': '_upPressed',
      'down': '_downPressed',
      'esc': '_escPressed',
      'enter': '_enterPressed'
    },
    listeners: {
      'iron-activate': '_itemPressed',
      'focus': '_onFocus',
      'blur': '_onBlur',
    },
    _itemPressed: function(e) {
      // if pressed item is not paper-input-container
      if (e.detail.selected) {
        this.selectResult(e.detail.selected - 1);
      }
    },
    _upPressed: function() {
      if (!this._hideResults) {
        this.selectPrevious();
        this.value = this.selected && this.arrowsUpdateInput ?
          this.filteredItems[this.selected - 1] : this.typedValue;
      }
    },
    _downPressed: function() {
      if (!this._hideResults) {
        this.selectNext();
        this.value = this.selected && this.arrowsUpdateInput ?
          this.filteredItems[this.selected - 1] : this.typedValue;
      // if there are results and they are hide
      } else if (this.filteredItems.length) {
        // just show them
        this._hideResults = false;
      }
    },
    _escPressed: function() {
      this.selected = 0;
      this._hideResults = true;
    },
    _enterPressed: function() {
      // -1 since paper-input-container is part of selectable array, index is shifted
      this.selectResult(this.selected - 1);
    },
    _typedValueChanged: function() {
      this.selected = 0;
      this._hideResults = this.filteredItems.length ? false : true;
    },
    _mouseenterItem: function(e) {
      this.select(this.indexOf(e.target));
    },
    _mouseleaveItems: function() {
      this.selected = 0;
    },
    _getFiltered: function(
      data, typedValue, filterFn, maxResults, typeaheadDisabled) {
      if (typeaheadDisabled) { return []; }
      return filterFn.call(this, data.base, typedValue)
        .slice(0, maxResults);
    },
    get items() {
      return Array.from(Polymer.dom(this.root).querySelectorAll('.selectable'));
    },
    /**
     * Select a Result in the filteredItems array by index then close the results.
     *
     * @param {Number} itemIndex The index of the item to select
     */
    selectResult: function(itemIndex) {
      this.typedValue = this.value = this.filteredItems[itemIndex];

      this.fire('selected', {target: this.value});
      this.closeResults();
    },
    /**
     * Manually display the results if the filteredItems array is not empty.
     *
     * @return {Boolean} True if the results are displayed.
     */
    tryDisplayResults: function() {
      var items = this.filteredItems;

      if (this._hideResults && items && items.length) {
        this.set('_hideResults', false);
      }

      return !this._hideResults;
    },
    /**
     * Manually hide the results.
     */
    hideResults: function() {
      this._hideResults = true;
    },
    /**
     * Manually hide the results and reset selected item.
     */
    closeResults: function() {
      this._hideResults = true;
      this.selected = 0;
    },
    /**
     * Stop the _onBlur event from firing when scrollbar is clicked.
     */
    _mouseDownItems: function(event) {
      event.preventDefault();
    },
    _onFocus: function() {
      this.tryDisplayResults();
    },
    _onBlur: function() {
      this.closeResults();
    },
  });
})();
<commit_msg>Select first result when a user types<commit_after>(function() {
  'use strict';
  Polymer({
    is: 'paper-typeahead',
    behaviors: [
      Polymer.IronA11yKeysBehavior,
      Polymer.IronSelectableBehavior,
      Polymer.PaperInputBehavior,
      Polymer.IronControlState,
      Polymer.IronFormElementBehavior
    ],
    properties: {
      arrowsUpdateInput: {
        type: Boolean,
        value: false
      },
      showEmptyResults: {
        type: Boolean,
        value: false
      },
      typedValue: {
        type: String,
        observer: '_typedValueChanged',
        value: '',
        notify: true
      },
      elevation: {
        type: Number,
        value: 1
      },
      keyEventTarget: {
        type: Object,
        value: function() {
          return this;
        }
      },
      typeaheadDisabled: {
        type: Boolean,
        value: false
      },
      data: {
        type: Array,
        value: function() { return []; }
      },
      maxResults: {
        type: Number,
        value: 10
      },
      filteredItems: {
        type: Array,
        computed: '_getFiltered(data.*, typedValue, filterFn, maxResults,' +
        'typeaheadDisabled)',
        notify: true
      },
      filterFn: {
        type: Function,
        value: function() {
          return function(data, value) {
            var r = RegExp(value, 'i');

            if (value === '') {
              return this.showEmptyResults ? data : [];
            }

            return data.filter(function(v) {
              return (r.test(v) ? v : null);
            });
          };
        }
      },
      // private because we don't want the user to set it true if there is no results
      _hideResults: {
        type: Boolean,
        value: true
      },
    },
    keyBindings: {
      'up': '_upPressed',
      'down': '_downPressed',
      'esc': '_escPressed',
      'enter': '_enterPressed'
    },
    listeners: {
      'iron-activate': '_itemPressed',
      'focus': '_onFocus',
      'blur': '_onBlur',
    },
    _itemPressed: function(e) {
      // if pressed item is not paper-input-container
      if (e.detail.selected) {
        this.selectResult(e.detail.selected - 1);
      }
    },
    _upPressed: function() {
      if (!this._hideResults) {
        this.selectPrevious();
        this.value = this.selected && this.arrowsUpdateInput ?
          this.filteredItems[this.selected - 1] : this.typedValue;
      }
    },
    _downPressed: function() {
      if (!this._hideResults) {
        this.selectNext();
        this.value = this.selected && this.arrowsUpdateInput ?
          this.filteredItems[this.selected - 1] : this.typedValue;
      // if there are results and they are hide
      } else if (this.filteredItems.length) {
        // just show them
        this._hideResults = false;
      }
    },
    _escPressed: function() {
      this.selected = 0;
      this._hideResults = true;
    },
    _enterPressed: function() {
      // -1 since paper-input-container is part of selectable array, index is shifted
      this.selectResult(this.selected - 1);
    },
    _typedValueChanged: function() {
      var hasItems = this.filteredItems && this.filteredItems.length;
      if (hasItems) {
        this.selected = 1;
      }

      this._hideResults = !hasItems;
    },
    _mouseenterItem: function(e) {
      this.select(this.indexOf(e.target));
    },
    _mouseleaveItems: function() {
      this.selected = 0;
    },
    _getFiltered: function(
      data, typedValue, filterFn, maxResults, typeaheadDisabled) {
      if (typeaheadDisabled) { return []; }
      return filterFn.call(this, data.base, typedValue)
        .slice(0, maxResults);
    },
    get items() {
      return Array.from(Polymer.dom(this.root).querySelectorAll('.selectable'));
    },
    /**
     * Select a Result in the filteredItems array by index then close the results.
     *
     * @param {Number} itemIndex The index of the item to select
     */
    selectResult: function(itemIndex) {
      this.typedValue = this.value = this.filteredItems[itemIndex];

      this.fire('selected', {target: this.value});
      this.closeResults();
    },
    /**
     * Manually display the results if the filteredItems array is not empty.
     *
     * @return {Boolean} True if the results are displayed.
     */
    tryDisplayResults: function() {
      var items = this.filteredItems;

      if (this._hideResults && items && items.length) {
        this.set('_hideResults', false);
      }

      return !this._hideResults;
    },
    /**
     * Manually hide the results.
     */
    hideResults: function() {
      this._hideResults = true;
    },
    /**
     * Manually hide the results and reset selected item.
     */
    closeResults: function() {
      this._hideResults = true;
      this.selected = 0;
    },
    /**
     * Stop the _onBlur event from firing when scrollbar is clicked.
     */
    _mouseDownItems: function(event) {
      event.preventDefault();
    },
    _onFocus: function() {
      this.tryDisplayResults();
    },
    _onBlur: function() {
      this.closeResults();
    },
  });
})();
<|endoftext|>


<commit_before>/**
 * Babel JavaScript Support
 *
 * Copyright (C) 2008 Edgewall Software
 * All rights reserved.
 *
 * This software is licensed as described in the file COPYING, which
 * you should have received as part of this distribution. The terms
 * are also available at http://babel.edgewall.org/wiki/License.
 *
 * This software consists of voluntary contributions made by many
 * individuals. For the exact contribution history, see the revision
 * history and logs, available at http://babel.edgewall.org/log/.
 */

/**
 * A simple module that provides a gettext like translation interface.
 * The catalog passed to load() must be a object conforming to this
 * interface::
 *
 *    {
 *      messages:     an object of {msgid: translations} items where
 *                    translations is an array of messages or a single
 *                    string if the message is not pluralizable.
 *      plural_expr:  the plural expression for the language.
 *      locale:       the identifier for this locale.
 *      domain:       the name of the domain.
 *    }
 *
 * Missing elements in the object are ignored.
 *
 * Typical usage::
 *
 *    var translations = babel.Translations.load(...).install();
 */
var babel = new function() {

  var defaultPluralExpr = function(n) { return n == 1 ? 0 : 1; };
  var formatRegex = /%(?:(?:\(([^\)]+)\))?([disr])|%)/g;

  /**
   * A translations object implementing the gettext interface
   */
  var Translations = this.Translations = function(locale, domain) {
    this.messages = {};
    this.locale = locale || 'unknown';
    this.domain = domain || 'messages';
    this.pluralexpr = defaultPluralExpr;
  };

  /**
   * Create a new translations object from the catalog and return it.
   * See the babel-module comment for more details.
   */
  Translations.load = function(catalog) {
    var rv = new Translations();
    rv.load(catalog);
    return rv;
  };

  Translations.prototype = {
    /**
     * translate a single string
     *
     * If extra parameters are given, use them to fill the format
     * specified by the string.
     */
    gettext: function(string) {
      var translated = this.messages[string];
      if (typeof translated == 'undefined')
        translated = string;
      else if (typeof translated != 'string')
        translated = translated[0];
      if (arguments.length > 1) {
        arguments[0] = translated;
        return babel.format.apply(this, arguments);
      }
      return translated;
    },

    /**
     * translate a pluralizable string
     *
     * If extra parameters are given, use them to fill the format
     * specified by the string.
     */
    ngettext: function(singular, plural, n) {
      var translated = this.messages[singular];
      if (typeof translated == 'undefined')
        translated = (n == 1) ? singular : plural;
      else
        translated = translated[this.pluralexpr(n)];
      if (arguments.length > 3) {
        var format_args = Array.prototype.slice.call(arguments, 3);
        format_args.unshift(translated);
        return babel.format.apply(this, format_args)
      }
      return translated;
    },

    /**
     * Install this translation document wide.  After this call, there are
     * three new methods on the window object: _, gettext and ngettext
     */
    install: function() {
      var self = this;
      window._ = window.gettext = function() {
        return self.gettext.apply(self, arguments);
      };
      window.ngettext = function(singular, plural, n) {
        return self.ngettext.apply(self, arguments);
      };
      return this;
    },

    /**
     * Works like Translations.load but updates the instance rather
     * then creating a new one.
     */
    load: function(catalog) {
      if (catalog.messages)
        this.update(catalog.messages)
      if (catalog.plural_expr)
        this.setPluralExpr(catalog.plural_expr);
      if (catalog.locale)
        this.locale = catalog.locale;
      if (catalog.domain)
        this.domain = catalog.domain;
      return this;
    },

    /**
     * Updates the translations with the object of messages.
     */
    update: function(mapping) {
      for (var key in mapping)
        if (mapping.hasOwnProperty(key))
          this.messages[key] = mapping[key];
      return this;
    },

    /**
     * Sets the plural expression
     */
    setPluralExpr: function(expr) {
      this.pluralexpr = new Function('n', 'return +(' + expr + ')');
      return this;
    }
  };

  /**
   * A python inspired string formatting function.  Supports named and
   * positional placeholders and "s", "d" and "i" as type characters
   * without any formatting specifications.
   *
   * Examples::
   *
   *    babel.format(_('Hello %s'), name)
   *    babel.format(_('Progress: %(percent)s%%'), {percent: 100})
   */
  this.format = function() {
    var arg, string = arguments[0], idx = 0;
    if (arguments.length == 1)
      return string;
    else if (arguments.length == 2 && typeof arguments[1] == 'object')
      arg = arguments[1];
    else {
      arg = [];
      for (var i = 1, n = arguments.length; i != n; ++i)
        arg[i - 1] = arguments[i];
    }
    return string.replace(formatRegex, function(all, name, type) {
      if (all == '%%') return '%';
      var value = arg[name || idx++];
      return (type == 'i' || type == 'd') ? +value : value;
    });
  }

};
<commit_msg>1.0dev: Added `dgettext` and `dngettext` in babel.js and fixed `gettext` cannot transrate messages for Trac.<commit_after>/**
 * Babel JavaScript Support
 *
 * Copyright (C) 2008 Edgewall Software
 * All rights reserved.
 *
 * This software is licensed as described in the file COPYING, which
 * you should have received as part of this distribution. The terms
 * are also available at http://babel.edgewall.org/wiki/License.
 *
 * This software consists of voluntary contributions made by many
 * individuals. For the exact contribution history, see the revision
 * history and logs, available at http://babel.edgewall.org/log/.
 */

/**
 * A simple module that provides a gettext like translation interface.
 * The catalog passed to load() must be a object conforming to this
 * interface::
 *
 *    {
 *      messages:     an object of {msgid: translations} items where
 *                    translations is an array of messages or a single
 *                    string if the message is not pluralizable.
 *      plural_expr:  the plural expression for the language.
 *      locale:       the identifier for this locale.
 *      domain:       the name of the domain.
 *    }
 *
 * Missing elements in the object are ignored.
 *
 * Typical usage::
 *
 *    var translations = babel.Translations.load(...).install();
 */
var babel = new function() {

  var defaultPluralExpr = function(n) { return n == 1 ? 0 : 1; };
  var formatRegex = /%(?:(?:\(([^\)]+)\))?([disr])|%)/g;
  var translations = {};
  var merged;

  /**
   * A translations object implementing the gettext interface
   */
  var Translations = this.Translations = function(locale, domain) {
    this.messages = {};
    this.locale = locale || 'unknown';
    this.domain = domain || 'messages';
    this.pluralexpr = defaultPluralExpr;
  };

  /**
   * Create a new translations object from the catalog and return it.
   * See the babel-module comment for more details.
   */
  Translations.load = function(catalog) {
    var rv = new Translations();
    rv.load(catalog);
    translations[rv.domain] = rv;
    merged.load(catalog);
    return rv;
  };

  /**
   * Get a Translations instance from the loaded translations. If the
   * specified domain doesn't exist, returns a dummy Translations
   * instance.
   */
  Translations.get = function(domain) {
    return translations[domain] || (new Translations({domain: domain}));
  };

  Translations.prototype = {
    /**
     * translate a single string
     *
     * If extra parameters are given, use them to fill the format
     * specified by the string.
     */
    gettext: function(string) {
      var translated = this.messages[string];
      if (typeof translated == 'undefined')
        translated = string;
      else if (typeof translated != 'string')
        translated = translated[0];
      if (arguments.length > 1) {
        arguments[0] = translated;
        return babel.format.apply(this, arguments);
      }
      return translated;
    },

    /**
     * translate a pluralizable string
     *
     * If extra parameters are given, use them to fill the format
     * specified by the string.
     */
    ngettext: function(singular, plural, n) {
      var translated = this.messages[singular];
      if (typeof translated == 'undefined')
        translated = (n == 1) ? singular : plural;
      else
        translated = translated[this.pluralexpr(n)];
      if (arguments.length > 3) {
        var format_args = Array.prototype.slice.call(arguments, 3);
        format_args.unshift(translated);
        return babel.format.apply(this, format_args)
      }
      return translated;
    },

    /**
     * Install this translation document wide.  After this call, there are
     * three new methods on the window object: _, gettext and ngettext
     */
    install: function() {
      window._ = window.gettext = function() {
        return merged.gettext.apply(merged, arguments);
      };
      window.ngettext = function(singular, plural, n) {
        return merged.ngettext.apply(merged, arguments);
      };
      return this;
    },

    /**
     * Works like Translations.load but updates the instance rather
     * then creating a new one.
     */
    load: function(catalog) {
      if (catalog.messages)
        this.update(catalog.messages)
      if (catalog.plural_expr)
        this.setPluralExpr(catalog.plural_expr);
      if (catalog.locale)
        this.locale = catalog.locale;
      if (catalog.domain)
        this.domain = catalog.domain;
      return this;
    },

    /**
     * Updates the translations with the object of messages.
     */
    update: function(mapping) {
      for (var key in mapping)
        if (mapping.hasOwnProperty(key))
          this.messages[key] = mapping[key];
      return this;
    },

    /**
     * Sets the plural expression
     */
    setPluralExpr: function(expr) {
      this.pluralexpr = new Function('n', 'return +(' + expr + ')');
      return this;
    }
  };

  merged = new Translations({});

  /**
   * Translate a single string in the specified domain.
   *
   * If extra parameters are given, use them to fill the format
   * specified by the string.
   */
  window.dgettext = this.dgettext = function(domain, string) {
    var rv = translations[domain];
    var args = Array.prototype.slice.call(arguments, 1);
    if (typeof rv != 'undefined')
      return rv.gettext.apply(rv, args);
    if (arguments.length > 1)
      return babel.format.apply(this, args);
    return string;
  };

  /**
   * Translate a pluralizable string in the specified domain.
   *
   * If extra parameters are given, use them to fill the format
   * specified by the string.
   */
  window.dngettext = this.dngettext = function(domain, singular, plural, n) {
    var rv = translations[domain];
    if (typeof rv != 'undefined') {
      var args = Array.prototype.slice.call(arguments, 1);
      return rv.ngettext.apply(rv, args);
    }
    if (arguments.length > 4) {
      var args = Array.prototype.slice.call(arguments, 4);
      args.unshift(singular);
      return babel.format.apply(this, format_args)
    }
    return (n == 1) ? singular : plural;
  };

  /**
   * A python inspired string formatting function.  Supports named and
   * positional placeholders and "s", "d" and "i" as type characters
   * without any formatting specifications.
   *
   * Examples::
   *
   *    babel.format(_('Hello %s'), name)
   *    babel.format(_('Progress: %(percent)s%%'), {percent: 100})
   */
  this.format = function() {
    var arg, string = arguments[0], idx = 0;
    if (arguments.length == 1)
      return string;
    else if (arguments.length == 2 && typeof arguments[1] == 'object')
      arg = arguments[1];
    else {
      arg = [];
      for (var i = 1, n = arguments.length; i != n; ++i)
        arg[i - 1] = arguments[i];
    }
    return string.replace(formatRegex, function(all, name, type) {
      if (all == '%%') return '%';
      var value = arg[name || idx++];
      return (type == 'i' || type == 'd') ? +value : value;
    });
  }

};
<|endoftext|>


<commit_before>//返回上一页   2016/12/25 deng
function backBtn(){
/*	if(_topicPageSign == 'yes'){
		execRoot("setCurrentPageId('main_page')");*/
	//退出聊天列表时首页的未读消息数去除
	exec('main_page',"removeUnreadNum()");

	//聊天列表未读数去除
	exec('dialoglist_page',"changeUnreadColor()");

	//openWin('main_page', 'main_page/main_page.html', '');
	closeWin('dialoglist_page');
}

//关闭当前页，返回主界面   2016/12/25 deng
function closeBtn(){
	execRoot("setCurrentPageId('main_page')");
	openWin('main_page', 'main_page/main_page.html', '');
	closeWin('dialoglist_page');
}

function showDialogList(data){
	//将聊天列表的数据放入之前先将存在的数据删除
	var allDialog=$(".dialog");
	for(var i=0;i<allDialog.length;i++){
		allDialog.eq(i).remove();
	}

	for(var d in data){
		var createTime=data[d].create_time;//最新回复时间
		var ifread=data[d].ifread;//是否有未读
		var msg=data[d].msg;//消息内容
		var toUserId=data[d].to_user_id;
		var toUserImgUrl=data[d].to_user_imgUrl;
		var toUserName=data[d].to_user_name;

		appendDialogElement(createTime,ifread,msg,toUserId,toUserImgUrl,toUserName);
	}
	//从首页传过来的聊天列表的未读信息
	if(unreadObjList.length>0){
		for(var i in unreadObjList){
			unreadMsg(unreadObjList[i].user,unreadObjList[i].data,unreadObjList[i].postTimeStr,unreadObjList[i].touserId,unreadObjList[i].unreadNum);
		}
	}

	//将聊天列表的外框的height设置
	var dialogListOut=$("#dialog_list");
	var dialogListOutHeight=$("body").height()-64;
	dialogListOut.css("height",dialogListOutHeight+"px");
}

function appendDialogElement(createTime,ifread,msg,toUserId,toUserImgUrl,toUserName){
	var dialog=$("

").attr("class", "dialog cursor").attr("id", toUserId);
	//onerror是实现获得图片失败的时候放的默认图片,只要有一个图片路径就行
	var toUserImg="";
	var dialogContent=$("

").attr("class", "dialog_content");

	var dialogContentTop=$("

").attr("class", "dialog_content_top");
	msg=cutStringIfTooLong(msg,17);
	var dialogContentMsg=$("

").attr("class", "dialog_content_msg").text(msg);

	var dialogContentName=$("

").attr("class", "dialog_content_name").text(toUserName);
	var dialogContentTime=$("

").attr("class", "dialog_content_time").text(showDialogListTime(createTime));

	dialogContentTop.append(dialogContentName).append(dialogContentTime);
	dialogContent.append(dialogContentTop).append(dialogContentMsg);
	dialog.append(toUserImg).append(dialogContent);

  	var dialogList=$("#dialog_list");
	dialogList.append(dialog);

	//设置聊天列表的各个大小
	var heightForWindow=$("body").height();
	var dialogHeight=(heightForWindow-63)*0.1;
	dialog.css("height",dialogHeight);

	//聊天列表动态布局
	setDialogListNode(dialog,dialogContent);

	dialog.click(function() {//绑定点击事件.
		enterDialogPage(toUserId,toUserName);
	});
}

//聊天列表动态布局
function setDialogListNode(dialog,dialogContent){
	var dialogHeight=parseInt(dialog.css("height"));//获得聊天列表单个的高度
	var dialogWidth=parseInt(dialog.css("width"));//获得聊天列表单个的高度

	//头像css设置
	var toUserImgHeight=dialogWidth*0.1026;//图片的高度是聊天列表宽度的0.1026
	var toUserImgMargin=(dialogHeight-toUserImgHeight)/2;
	var toUserImg=dialog.find("img");
	toUserImg.css("height",toUserImgHeight);
	toUserImg.css("width",toUserImgHeight);
	toUserImg.css("margin-left",toUserImgMargin*2);
	toUserImg.css("margin-top",toUserImgMargin);

	//文字css设置
	var dialogContentWidth=dialogWidth-toUserImgHeight-(toUserImgMargin*5);
	dialogContent.css("height",toUserImgHeight);
	dialogContent.css("width",dialogContentWidth);
	dialogContent.css("margin-top",toUserImgMargin);
	dialogContent.css("margin-left",toUserImgMargin);

	//dialogContent.css("margin-left",toUserImgMargin/2);

	//设置文字内容的line-height
	var dialogContentNameHeight=dialogContent.find(".dialog_content_name").css("height");
	$(".dialog_content_name").css("line-height",(parseInt(dialogContentNameHeight))+"px");
	$(".dialog_content_name").css("font-size",parseInt(dialogContentNameHeight)*0.7+"px");

	var dialogContentTimeHeight=dialogContent.find(".dialog_content_time").css("height");
	$(".dialog_content_time").css("line-height",dialogContentTimeHeight);
	$(".dialog_content_time").css("font-size",parseInt(dialogContentTimeHeight)*0.5+"px");
	$(".dialog_content_time").css("margin-right",toUserImgMargin+"px");

	var dialogContentMsgHeight=dialogContent.find(".dialog_content_msg").css("height");
	$(".dialog_content_msg").css("line-height",dialogContentMsgHeight);
	$(".dialog_content_msg").css("font-size",parseInt(dialogContentMsgHeight)*0.65+"px");
}

//2017.08.25  叶夷   通过传入的时间判断之后显示(传入的时间格式为 2017-08-25 16:35:00 转换的效果如  下午4:30)
function showDialogListTime(time){
	var dialogTime;//最后返回的时间

	//这是传入的时间
	var splitTime=time.split(" ");//将时间字符串分成年月日和时分秒两部分
	var onePartTime=splitTime[0];//年月日部分
	var twoPartTime=splitTime[1];//时分秒部分
	var hourTime=twoPartTime.split(":")[0];//这是小时
	var minuteTime=twoPartTime.split(":")[1];//这是分钟

	//这是今天的时间
	var todayTime = new Date();
	var nowYearTime=todayTime.getFullYear();//这是年份
	var nowMonthTime=todayTime.getMonth()+1;//这是月份，月份是从0开始的
	var nowDayTime=todayTime.getDate();

	var betweenDayNumber=daysBetween(onePartTime,nowYearTime+"-"+nowMonthTime+"-"+nowDayTime);//天数差

	//进行对比
	//1.先对比是否是今天
	if(betweenDayNumber==0){//是今天
		//2.是上午还是下午
		if(hourTime<12){//上午
			dialogTime="上午 "+hourTime+":"+minuteTime;
		}else{//下午
			dialogTime="下午 "+(hourTime-12)+":"+minuteTime;
		}
	}else if(betweenDayNumber<=7){//一个星期内
		dialogTime=getWeek(new Date(onePartTime));
	}else{//超过一个星期
		dialogTime=onePartTime;
	}
	return dialogTime;
}

//2017.08.25  叶夷    求两个时间的天数差 日期格式为 YYYY-MM-dd
function daysBetween(DateOne,DateTwo)
{
	var OneMonth = DateOne.substring(5,DateOne.lastIndexOf ('-'));
	var OneDay = DateOne.substring(DateOne.length,DateOne.lastIndexOf ('-')+1);
	var OneYear = DateOne.substring(0,DateOne.indexOf ('-'));

	var TwoMonth = DateTwo.substring(5,DateTwo.lastIndexOf ('-'));
	var TwoDay = DateTwo.substring(DateTwo.length,DateTwo.lastIndexOf ('-')+1);
	var TwoYear = DateTwo.substring(0,DateTwo.indexOf ('-'));

	var cha=((Date.parse(OneMonth+'/'+OneDay+'/'+OneYear)- Date.parse(TwoMonth+'/'+TwoDay+'/'+TwoYear))/86400000);
	return Math.abs(cha);
}

//2017.08.25  叶夷 获得星期  传入的data为:  new Date("2017-8-25")
function getWeek(date){
	var week;
	if(date.getDay()==0) week="星期日"
	if(date.getDay()==1) week="星期一"
	if(date.getDay()==2) week="星期二"
	if(date.getDay()==3) week="星期三"
	if(date.getDay()==4) week="星期四"
	if(date.getDay()==5) week="星期五"
	if(date.getDay()==6) week="星期六"
	return week;
}

//未读消息数提示，最新消息内容和最新时间更新
function unreadMsg(user,data,postTimeStr,respondeUserId,unreadNum){
	var unreadParent=$("#"+respondeUserId);
	if (unreadParent.find('.unread').length==0) {//如果没有未读消息,则加上一个1;
		var unreadNumNode = $("

").attr("class", "unread").text(unreadNum);
		unreadParent.append(unreadNumNode);
		//未读消息的位置
		//头像的位置
		var dialogImg=$(".dialog").find("img");
		var dialogImgWidth=parseInt(dialogImg.css("width"));
		var dialogImgMargin=parseInt(dialogImg.css("margin"));

		var unreadLeft=dialogImgWidth+dialogImgMargin;
		unreadNumNode.css("margin-left",unreadLeft+"px");
		//unreadNumNode.css("top",dialogImgMargin/2+"px");

	} else {//如果已有未读消息,则加上1:
		unreadNum  = unreadParent.find('.unread').text();
		unreadNum++;
		unreadParent.find('.unread').text(unreadNum);
	}

	updateDialogContentAndTime(user,data,postTimeStr,respondeUserId);
}

//把聊天列表的内容和时间更新
function updateDialogContentAndTime(user,data,postTimeStr,respondeUserId){
	var unreadParent=$("#"+respondeUserId);
	//内容
	var dialog_content_msg=unreadParent.find(".dialog_content_msg");
	if(user==""){
		dialog_content_msg.text(data);
	}else{
		dialog_content_msg.text(user+"："+data);
	}

	//把时间更新
	var dialog_content_time=unreadParent.find(".dialog_content_time");
	dialog_content_time.text(showDialogListTime(postTimeStr));
}

//2017.08.15 叶夷目前首页未读消息提示的显示方案是这样的：
//如果A给我发了3条未读消息，B给我发了2条未读消息，首页显示的是5条未读消息，我打开和A的聊天页面，聊天列表里B的未读提示还存在，不过颜色变暗，首页的未读提示消失
//这里是使聊天列表没打开过有未读提示的聊天页未读提示颜色变暗
function changeUnreadColor(){
	$(".unread").css("opacity","0.7");
}

/**2017.10.16 叶夷  聊天列表消息置顶*/
function makeDialogListTop(respondeUserId){
	var oneDialogDiv=$("#"+respondeUserId);
	var copyOneDialogDiv=oneDialogDiv.clone();

	//先将节点从dialog_list删除再放入第一位中
	oneDialogDiv.remove();
	$("#dialog_list").prepend(copyOneDialogDiv);

	var toUserName=copyOneDialogDiv.find(".dialog_content_name").text();
	copyOneDialogDiv.click(function() {//绑定点击事件.
		enterDialogPage(respondeUserId,toUserName);
	});
}<commit_msg>聊天列表头像稍微小一点，上对齐<commit_after>//返回上一页   2016/12/25 deng
function backBtn(){
/*	if(_topicPageSign == 'yes'){
		execRoot("setCurrentPageId('main_page')");*/
	//退出聊天列表时首页的未读消息数去除
	exec('main_page',"removeUnreadNum()");

	//聊天列表未读数去除
	exec('dialoglist_page',"changeUnreadColor()");

	//openWin('main_page', 'main_page/main_page.html', '');
	closeWin('dialoglist_page');
}

//关闭当前页，返回主界面   2016/12/25 deng
function closeBtn(){
	execRoot("setCurrentPageId('main_page')");
	openWin('main_page', 'main_page/main_page.html', '');
	closeWin('dialoglist_page');
}

function showDialogList(data){
	//将聊天列表的数据放入之前先将存在的数据删除
	var allDialog=$(".dialog");
	for(var i=0;i<allDialog.length;i++){
		allDialog.eq(i).remove();
	}

	for(var d in data){
		var createTime=data[d].create_time;//最新回复时间
		var ifread=data[d].ifread;//是否有未读
		var msg=data[d].msg;//消息内容
		var toUserId=data[d].to_user_id;
		var toUserImgUrl=data[d].to_user_imgUrl;
		var toUserName=data[d].to_user_name;

		appendDialogElement(createTime,ifread,msg,toUserId,toUserImgUrl,toUserName);
	}
	//从首页传过来的聊天列表的未读信息
	if(unreadObjList.length>0){
		for(var i in unreadObjList){
			unreadMsg(unreadObjList[i].user,unreadObjList[i].data,unreadObjList[i].postTimeStr,unreadObjList[i].touserId,unreadObjList[i].unreadNum);
		}
	}

	//将聊天列表的外框的height设置
	var dialogListOut=$("#dialog_list");
	var dialogListOutHeight=$("body").height()-64;
	dialogListOut.css("height",dialogListOutHeight+"px");
}

function appendDialogElement(createTime,ifread,msg,toUserId,toUserImgUrl,toUserName){
	var dialog=$("

").attr("class", "dialog cursor").attr("id", toUserId);
	//onerror是实现获得图片失败的时候放的默认图片,只要有一个图片路径就行
	var toUserImg="";
	var dialogContent=$("

").attr("class", "dialog_content");

	var dialogContentTop=$("

").attr("class", "dialog_content_top");
	msg=cutStringIfTooLong(msg,17);
	var dialogContentMsg=$("

").attr("class", "dialog_content_msg").text(msg);

	var dialogContentName=$("

").attr("class", "dialog_content_name").text(toUserName);
	var dialogContentTime=$("

").attr("class", "dialog_content_time").text(showDialogListTime(createTime));

	dialogContentTop.append(dialogContentName).append(dialogContentTime);
	dialogContent.append(dialogContentTop).append(dialogContentMsg);
	dialog.append(toUserImg).append(dialogContent);

  	var dialogList=$("#dialog_list");
	dialogList.append(dialog);

	//设置聊天列表的各个大小
	var heightForWindow=$("body").height();
	var dialogHeight=(heightForWindow-63)*0.1;
	dialog.css("height",dialogHeight);

	//聊天列表动态布局
	setDialogListNode(dialog,dialogContent);

	dialog.click(function() {//绑定点击事件.
		enterDialogPage(toUserId,toUserName);
	});
}

//聊天列表动态布局
function setDialogListNode(dialog,dialogContent){
	var dialogHeight=parseInt(dialog.css("height"));//获得聊天列表单个的高度
	var dialogWidth=parseInt(dialog.css("width"));//获得聊天列表单个的高度

	//头像css设置
	var toUserImgHeight=dialogWidth*0.0943;//图片的高度是聊天列表宽度的0.1026
	var toUserImgMargin=(dialogHeight-toUserImgHeight)/2;
	var toUserImg=dialog.find("img");
	toUserImg.css("height",toUserImgHeight);
	toUserImg.css("width",toUserImgHeight);
	toUserImg.css("margin-left",toUserImgMargin*2);
	toUserImg.css("margin-top",toUserImgMargin);

	//文字css设置
	var dialogContentWidth=dialogWidth-toUserImgHeight-(toUserImgMargin*5);
	dialogContent.css("height",dialogWidth*0.1026);
	dialogContent.css("width",dialogContentWidth);
	dialogContent.css("margin-top",toUserImgMargin);
	dialogContent.css("margin-left",toUserImgMargin);

	//dialogContent.css("margin-left",toUserImgMargin/2);

	//设置文字内容的line-height
	var dialogContentNameHeight=dialogContent.find(".dialog_content_name").css("height");
	$(".dialog_content_name").css("line-height",(parseInt(dialogContentNameHeight))+"px");
	$(".dialog_content_name").css("font-size",parseInt(dialogContentNameHeight)*0.7+"px");

	var dialogContentTimeHeight=dialogContent.find(".dialog_content_time").css("height");
	$(".dialog_content_time").css("line-height",dialogContentTimeHeight);
	$(".dialog_content_time").css("font-size",parseInt(dialogContentTimeHeight)*0.5+"px");
	$(".dialog_content_time").css("margin-right",toUserImgMargin+"px");

	var dialogContentMsgHeight=dialogContent.find(".dialog_content_msg").css("height");
	$(".dialog_content_msg").css("line-height",dialogContentMsgHeight);
	$(".dialog_content_msg").css("font-size",parseInt(dialogContentMsgHeight)*0.65+"px");
}

//2017.08.25  叶夷   通过传入的时间判断之后显示(传入的时间格式为 2017-08-25 16:35:00 转换的效果如  下午4:30)
function showDialogListTime(time){
	var dialogTime;//最后返回的时间

	//这是传入的时间
	var splitTime=time.split(" ");//将时间字符串分成年月日和时分秒两部分
	var onePartTime=splitTime[0];//年月日部分
	var twoPartTime=splitTime[1];//时分秒部分
	var hourTime=twoPartTime.split(":")[0];//这是小时
	var minuteTime=twoPartTime.split(":")[1];//这是分钟

	//这是今天的时间
	var todayTime = new Date();
	var nowYearTime=todayTime.getFullYear();//这是年份
	var nowMonthTime=todayTime.getMonth()+1;//这是月份，月份是从0开始的
	var nowDayTime=todayTime.getDate();

	var betweenDayNumber=daysBetween(onePartTime,nowYearTime+"-"+nowMonthTime+"-"+nowDayTime);//天数差

	//进行对比
	//1.先对比是否是今天
	if(betweenDayNumber==0){//是今天
		//2.是上午还是下午
		if(hourTime<12){//上午
			dialogTime="上午 "+hourTime+":"+minuteTime;
		}else{//下午
			dialogTime="下午 "+(hourTime-12)+":"+minuteTime;
		}
	}else if(betweenDayNumber<=7){//一个星期内
		dialogTime=getWeek(new Date(onePartTime));
	}else{//超过一个星期
		dialogTime=onePartTime;
	}
	return dialogTime;
}

//2017.08.25  叶夷    求两个时间的天数差 日期格式为 YYYY-MM-dd
function daysBetween(DateOne,DateTwo)
{
	var OneMonth = DateOne.substring(5,DateOne.lastIndexOf ('-'));
	var OneDay = DateOne.substring(DateOne.length,DateOne.lastIndexOf ('-')+1);
	var OneYear = DateOne.substring(0,DateOne.indexOf ('-'));

	var TwoMonth = DateTwo.substring(5,DateTwo.lastIndexOf ('-'));
	var TwoDay = DateTwo.substring(DateTwo.length,DateTwo.lastIndexOf ('-')+1);
	var TwoYear = DateTwo.substring(0,DateTwo.indexOf ('-'));

	var cha=((Date.parse(OneMonth+'/'+OneDay+'/'+OneYear)- Date.parse(TwoMonth+'/'+TwoDay+'/'+TwoYear))/86400000);
	return Math.abs(cha);
}

//2017.08.25  叶夷 获得星期  传入的data为:  new Date("2017-8-25")
function getWeek(date){
	var week;
	if(date.getDay()==0) week="星期日"
	if(date.getDay()==1) week="星期一"
	if(date.getDay()==2) week="星期二"
	if(date.getDay()==3) week="星期三"
	if(date.getDay()==4) week="星期四"
	if(date.getDay()==5) week="星期五"
	if(date.getDay()==6) week="星期六"
	return week;
}

//未读消息数提示，最新消息内容和最新时间更新
function unreadMsg(user,data,postTimeStr,respondeUserId,unreadNum){
	var unreadParent=$("#"+respondeUserId);
	if (unreadParent.find('.unread').length==0) {//如果没有未读消息,则加上一个1;
		var unreadNumNode = $("

").attr("class", "unread").text(unreadNum);
		unreadParent.append(unreadNumNode);
		//未读消息的位置
		//头像的位置
		var dialogImg=$(".dialog").find("img");
		var dialogImgWidth=parseInt(dialogImg.css("width"));
		var dialogImgMargin=parseInt(dialogImg.css("margin"));

		var unreadLeft=dialogImgWidth+dialogImgMargin;
		unreadNumNode.css("margin-left",unreadLeft+"px");
		//unreadNumNode.css("top",dialogImgMargin/2+"px");

	} else {//如果已有未读消息,则加上1:
		unreadNum  = unreadParent.find('.unread').text();
		unreadNum++;
		unreadParent.find('.unread').text(unreadNum);
	}

	updateDialogContentAndTime(user,data,postTimeStr,respondeUserId);
}

//把聊天列表的内容和时间更新
function updateDialogContentAndTime(user,data,postTimeStr,respondeUserId){
	var unreadParent=$("#"+respondeUserId);
	//内容
	var dialog_content_msg=unreadParent.find(".dialog_content_msg");
	if(user==""){
		dialog_content_msg.text(data);
	}else{
		dialog_content_msg.text(user+"："+data);
	}

	//把时间更新
	var dialog_content_time=unreadParent.find(".dialog_content_time");
	dialog_content_time.text(showDialogListTime(postTimeStr));
}

//2017.08.15 叶夷目前首页未读消息提示的显示方案是这样的：
//如果A给我发了3条未读消息，B给我发了2条未读消息，首页显示的是5条未读消息，我打开和A的聊天页面，聊天列表里B的未读提示还存在，不过颜色变暗，首页的未读提示消失
//这里是使聊天列表没打开过有未读提示的聊天页未读提示颜色变暗
function changeUnreadColor(){
	$(".unread").css("opacity","0.7");
}

/**2017.10.16 叶夷  聊天列表消息置顶*/
function makeDialogListTop(respondeUserId){
	var oneDialogDiv=$("#"+respondeUserId);
	var copyOneDialogDiv=oneDialogDiv.clone();

	//先将节点从dialog_list删除再放入第一位中
	oneDialogDiv.remove();
	$("#dialog_list").prepend(copyOneDialogDiv);

	var toUserName=copyOneDialogDiv.find(".dialog_content_name").text();
	copyOneDialogDiv.click(function() {//绑定点击事件.
		enterDialogPage(respondeUserId,toUserName);
	});
}<|endoftext|>


<commit_before>var muni = ''; // contains muni code to name conversion
var features = '';

$(document).ready(function() {
    // load muni json into variable
    var jqxhrMuni = $.getJSON("./muni.json", function( data ) {
        muni = data;
    });
    // load features json into variable
    var jqxhrFeat = $.getJSON("./AllFeatures.geo.json", function( data ) {
        features = data;
            console.log("popup-features.head.hits: " + features.head.hits);
    });

    // set up map
    //load basic Leaflet map
    var bounds = [[55.2, 10.8], [69.1, 24.4]];
    var map = L.map('map', {'zoomControl':false}).fitBounds(bounds);
    map.addControl(
        L.control.zoom({
            'zoomInTitle':'Zooma in',
            'zoomOutTitle':'Zooma ut'
        })
    );

    var attribution = 'Ett projekt från Wikimedia Sverige med stöd av Vinnova. | ';
    //settings for MapQuest
    var mapQuest = L.tileLayer("http://{s}.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.png", {
        attribution: attribution + 'Kartdata © OpenStreetMap-bidragsgivare. kartrendering av MapQuest',
        maxZoom: 19,
        subdomains: ['otile1','otile2','otile3','otile4']
    });

    //settings for OSM Sweden
    var osmSE = L.tileLayer('http://{s}.tile.openstreetmap.se/hydda/full/{z}/{x}/{y}.png', {
        maxZoom: 18,
        subdomains: 'abc',
        attribution: attribution + 'Kartdata © OpenStreetMap-bidragsgivare, kartrendering av OpenStreetMap Sweden'
    }).addTo(map);
    map.addLayer(osmSE);

    //settings for OSM
    var osm = L.tileLayer("//{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
        attribution: attribution + 'Kartdata © OpenStreetMap-bidragsgivare',
        maxZoom: 19,
    });

    //set-up markers
    var noPicIcon = L.icon({
        iconUrl: 'images/withoutimageicon.png',
        iconSize: [32, 32],
        iconAnchor: [16, 31],
        popupAnchor: [0, -16]
    });
    var picIcon = L.icon({
        iconUrl: 'images/withimageicon.png',
        iconSize: [32, 32],
        iconAnchor: [16, 31],
        popupAnchor: [0, -16]
    });

    //geoJson, once it is loaded
    jqxhrFeat.complete( function() {
        var odokLayer = L.geoJson(features, {
            onEachFeature: function (feature, layer) {
                layer.bindPopup(makePopup(feature));
            },
            pointToLayer: function (feature, latlng) {
                if (feature.properties.image){
                    return L.marker(latlng, {icon: picIcon, title:feature.properties.title });
                }else{
                    return L.marker(latlng, {icon: noPicIcon, title:feature.properties.title });
                }
            }
        });

        //Clustering
        var markers = new L.MarkerClusterGroup({showCoverageOnHover: false});
        markers.addLayer(odokLayer);        // add it to the cluster group
        map.addLayer(markers);		        // add it to the map
        // commented out since it overrides the hash
        //map.fitBounds(markers.getBounds()); //set view on the cluster extent

        //for layers control
        var baseMaps = {
            "MapQuest": mapQuest,
            "OSM": osm,
            "OSM Sweden": osmSE
        };
        var overlayMaps = {
            "kluster": markers,
            "individuella": odokLayer
        };
        L.control.layers(baseMaps, overlayMaps).addTo(map);
    });

    // search
    var osmOptions = {text: 'Sök plats'};
    var osmGeocoder = new L.Control.OSMGeocoder(osmOptions);
    map.addControl(osmGeocoder);

    // locate
    L.control.locate({
        position: 'topleft',  // set the location of the control
        drawCircle: true,  // controls whether a circle is drawn that shows the uncertainty about the location
        icon: 'fa fa-crosshairs',  // class for icon, fa-location-arrow or fa-map-marker
        metric: true,  // use metric or imperial units
        showPopup: true, // display a popup when the user click on the inner marker
        strings: {
            title: "Visa var jag är",  // title of the locate control
            popup: "Du är inom {distance} meter från denna punkt",  // text to appear if user clicks on circle
            outsideMapBoundsMsg: "Du verkar befinna dig utanför kartans gränser" // default message for onLocationOutsideMapBounds
        },
        locateOptions :{
            maxZoom: 16
        }
    }).addTo(map);

    // Hash
    var hash = new L.Hash(map);

    //Rightclick gives coords (for improving data)
    var popup = L.popup();
    function onMapClick(e) {
        popup
            .setLatLng(e.latlng)
            .setContent("Du klickade på koordinaten:
" + e.latlng.lat + ", " + e.latlng.lng)
            .openOn(map);
    }
    map.on('contextmenu', onMapClick);
});

// create the popupcontents
function makePopup(feature) {
    // Based on https://stackoverflow.com/questions/10889954
    var properties = feature.properties;
    var desc = "";

    // code originally from updateFeatures.py
    // image
    if (properties.image) {
        var showImage = '';
        if (properties.spatial.inside == 1 && properties.free == 'unfree') {
            showImage = 'Commons-icon.svg';
        }
        else {
            showImage = properties.image.replace(/\s/g, '_');
        }
        desc += '';
        desc += '';
        desc += '';

        // info
    }
    desc += '
';
    if (properties.title) {
        desc += '
 '; //title
        desc += '' + properties.title + '';
        desc += '
';
    }

    // artist - year
    desc += '
 ';
    if (properties.artist) {
        $.each(properties.artist, function(index, ai) {
            if (ai.wikidata) {
                desc += '';
                desc += ai.name;
                desc += '';
            }
            else {
                desc += ai.name;
            }
            desc += ', ';
        });
        desc = desc.slice(0,-2); // remove trailing ", "
    }
    else {
        desc += 'Okänd konstnär';
    }
    if (properties.year) {
        desc += ' - ' + properties.year;
    }

    // Muni - address
    desc += '

 ';
    if (muni[properties.spatial.muni]) {
        desc += muni[properties.spatial.muni].full;
    }
    else {
        console.log("Object has weird muni. Id: " + properties.id + " muni: " + properties.spatial.muni);
    }
    if (properties.spatial.district) {
        desc += ' (' + properties.spatial.district + ')';
    }
    if (properties.spatial.address) {
        desc += ' - ' + properties.spatial.address;
    }
    desc += '

';
    if (properties.image || properties.descriptions.wiki || properties.descriptions.descr) {
        desc += '
';
    }
    // description
    var jqxhr;
    if (properties.descriptions.wikidata) {
        desc += properties.descriptions.ingress;
        desc += '  ';
        desc += 'Läs mer om konstverket på Wikipedia';
        desc += '.';
    }
    else if (properties.descriptions.descr) {
        desc += properties.descriptions.descr;
    }

    return desc;

}
<commit_msg>Limit sig.fig<commit_after>var muni = ''; // contains muni code to name conversion
var features = '';

$(document).ready(function() {
    // load muni json into variable
    var jqxhrMuni = $.getJSON("./muni.json", function( data ) {
        muni = data;
    });
    // load features json into variable
    var jqxhrFeat = $.getJSON("./AllFeatures.geo.json", function( data ) {
        features = data;
            console.log("popup-features.head.hits: " + features.head.hits);
    });

    // set up map
    //load basic Leaflet map
    var bounds = [[55.2, 10.8], [69.1, 24.4]];
    var map = L.map('map', {'zoomControl':false}).fitBounds(bounds);
    map.addControl(
        L.control.zoom({
            'zoomInTitle':'Zooma in',
            'zoomOutTitle':'Zooma ut'
        })
    );

    var attribution = 'Ett projekt från Wikimedia Sverige med stöd av Vinnova. | ';
    //settings for MapQuest
    var mapQuest = L.tileLayer("http://{s}.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.png", {
        attribution: attribution + 'Kartdata © OpenStreetMap-bidragsgivare. kartrendering av MapQuest',
        maxZoom: 19,
        subdomains: ['otile1','otile2','otile3','otile4']
    });

    //settings for OSM Sweden
    var osmSE = L.tileLayer('http://{s}.tile.openstreetmap.se/hydda/full/{z}/{x}/{y}.png', {
        maxZoom: 18,
        subdomains: 'abc',
        attribution: attribution + 'Kartdata © OpenStreetMap-bidragsgivare, kartrendering av OpenStreetMap Sweden'
    }).addTo(map);
    map.addLayer(osmSE);

    //settings for OSM
    var osm = L.tileLayer("//{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
        attribution: attribution + 'Kartdata © OpenStreetMap-bidragsgivare',
        maxZoom: 19,
    });

    //set-up markers
    var noPicIcon = L.icon({
        iconUrl: 'images/withoutimageicon.png',
        iconSize: [32, 32],
        iconAnchor: [16, 31],
        popupAnchor: [0, -16]
    });
    var picIcon = L.icon({
        iconUrl: 'images/withimageicon.png',
        iconSize: [32, 32],
        iconAnchor: [16, 31],
        popupAnchor: [0, -16]
    });

    //geoJson, once it is loaded
    jqxhrFeat.complete( function() {
        var odokLayer = L.geoJson(features, {
            onEachFeature: function (feature, layer) {
                layer.bindPopup(makePopup(feature));
            },
            pointToLayer: function (feature, latlng) {
                if (feature.properties.image){
                    return L.marker(latlng, {icon: picIcon, title:feature.properties.title });
                }else{
                    return L.marker(latlng, {icon: noPicIcon, title:feature.properties.title });
                }
            }
        });

        //Clustering
        var markers = new L.MarkerClusterGroup({showCoverageOnHover: false});
        markers.addLayer(odokLayer);        // add it to the cluster group
        map.addLayer(markers);		        // add it to the map
        // commented out since it overrides the hash
        //map.fitBounds(markers.getBounds()); //set view on the cluster extent

        //for layers control
        var baseMaps = {
            "MapQuest": mapQuest,
            "OSM": osm,
            "OSM Sweden": osmSE
        };
        var overlayMaps = {
            "kluster": markers,
            "individuella": odokLayer
        };
        L.control.layers(baseMaps, overlayMaps).addTo(map);
    });

    // search
    var osmOptions = {text: 'Sök plats'};
    var osmGeocoder = new L.Control.OSMGeocoder(osmOptions);
    map.addControl(osmGeocoder);

    // locate
    L.control.locate({
        position: 'topleft',  // set the location of the control
        drawCircle: true,  // controls whether a circle is drawn that shows the uncertainty about the location
        icon: 'fa fa-crosshairs',  // class for icon, fa-location-arrow or fa-map-marker
        metric: true,  // use metric or imperial units
        showPopup: true, // display a popup when the user click on the inner marker
        strings: {
            title: "Visa var jag är",  // title of the locate control
            popup: "Du är inom {distance} meter från denna punkt",  // text to appear if user clicks on circle
            outsideMapBoundsMsg: "Du verkar befinna dig utanför kartans gränser" // default message for onLocationOutsideMapBounds
        },
        locateOptions :{
            maxZoom: 16
        }
    }).addTo(map);

    // Hash
    var hash = new L.Hash(map);

    //Right-click gives coords (for improving data)
    var popup = L.popup();
    function onMapClick(e) {
        popup
            .setLatLng(e.latlng)
            .setContent("Du klickade på koordinaten:
" + e.latlng.lat.toFixed(6) + ", " + e.latlng.lng.toFixed(6))
            .openOn(map);
    }
    map.on('contextmenu', onMapClick);
});

// create the popupcontents
function makePopup(feature) {
    // Based on https://stackoverflow.com/questions/10889954
    var properties = feature.properties;
    var desc = "";

    // code originally from updateFeatures.py
    // image
    if (properties.image) {
        var showImage = '';
        if (properties.spatial.inside == 1 && properties.free == 'unfree') {
            showImage = 'Commons-icon.svg';
        }
        else {
            showImage = properties.image.replace(/\s/g, '_');
        }
        desc += '';
        desc += '';
        desc += '';

        // info
    }
    desc += '
';
    if (properties.title) {
        desc += '
 '; //title
        desc += '' + properties.title + '';
        desc += '
';
    }

    // artist - year
    desc += '
 ';
    if (properties.artist) {
        $.each(properties.artist, function(index, ai) {
            if (ai.wikidata) {
                desc += '';
                desc += ai.name;
                desc += '';
            }
            else {
                desc += ai.name;
            }
            desc += ', ';
        });
        desc = desc.slice(0,-2); // remove trailing ", "
    }
    else {
        desc += 'Okänd konstnär';
    }
    if (properties.year) {
        desc += ' - ' + properties.year;
    }

    // Muni - address
    desc += '

 ';
    if (muni[properties.spatial.muni]) {
        desc += muni[properties.spatial.muni].full;
    }
    else {
        console.log("Object has weird muni. Id: " + properties.id + " muni: " + properties.spatial.muni);
    }
    if (properties.spatial.district) {
        desc += ' (' + properties.spatial.district + ')';
    }
    if (properties.spatial.address) {
        desc += ' - ' + properties.spatial.address;
    }
    desc += '

';
    if (properties.image || properties.descriptions.wiki || properties.descriptions.descr) {
        desc += '
';
    }
    // description
    var jqxhr;
    if (properties.descriptions.wikidata) {
        desc += properties.descriptions.ingress;
        desc += '  ';
        desc += 'Läs mer om konstverket på Wikipedia';
        desc += '.';
    }
    else if (properties.descriptions.descr) {
        desc += properties.descriptions.descr;
    }

    return desc;

}
<|endoftext|>


<commit_before>#!/usr/bin/env node

/**
 * Original Code
 * https://raw.githubusercontent.com/angular/angular.js/master/validate-commit-msg.js
 * Git COMMIT-MSG hook for validating commit message
 * See https://github.com/naver/egjs/wiki/Commit-Guidelines
 * modified by egjs
 */

'use strict';

var fs = require('fs');
var util = require('util');

var MAX_LENGTH = 100;
var PATTERN = /^(?:fixup!\s*)?(\w*)(\(([\w\$\,\.\*/-]*)\))?\: (.*)$/;
var IGNORED = /^WIP\:/;
var TYPES = {
  feat: true,
  fix: true,
  docs: true,
  style: true,
  refactor: true,
  test: true,
  chore: true
};

var error = function() {
  // gitx does not display it
  // http://gitx.lighthouseapp.com/projects/17830/tickets/294-feature-display-hook-error-message-when-hook-fails
  // https://groups.google.com/group/gitx/browse_thread/thread/a03bcab60844b812
  console.error('INVALID COMMIT MSG: ' + util.format.apply(null, arguments));
};

var validateMessage = function(message, fullMessage) {
  var isValid = true;

  if (IGNORED.test(message)) {
    console.log('Commit message validation ignored.');
    return true;
  }

  if (message.length > MAX_LENGTH) {
    error('is longer than %d characters !', MAX_LENGTH);
    isValid = false;
  }

  var match = PATTERN.exec(message);

  if (!match) {
    var data = fs.readFileSync(__dirname+'/../../config/commit.template', 'utf8');
    error('\n\r======= Your commit message =======\n\r' + fullMessage + '\n\r' + data);
    return false;
  }

  var type = match[1];
  var module = match[3];
  var subject = match[4];

  if (!TYPES.hasOwnProperty(type)) {
    error('"%s" is not allowed type !', type);
    return false;
  }

  // Some more ideas, do want anything like this ?
  // - allow only specific scopes (eg. fix(docs) should not be allowed ?
  // - auto correct the type to lower case ?
  // - auto correct first letter of the subject to lower case ?
  // - auto add empty line after subject ?
  // - auto remove empty () ?
  // - auto correct typos in type ?
  // - store incorrect messages, so that we can learn

  return isValid;
};

var firstLineFromBuffer = function(buffer) {
  return buffer.toString().split('\n').shift();
};

var removeInfo = function(buffer) {
  return buffer.toString().replace(/\n(#\s(?:.*?)$)/gm,"");
};

// publish for testing
exports.validateMessage = validateMessage;

// hacky start if not run by jasmine :-D
if (process.argv.join('').indexOf('jasmine-node') === -1) {
  var commitMsgFile = process.argv[2];
  var incorrectLogFile = commitMsgFile.replace('COMMIT_EDITMSG', 'logs/incorrect-commit-msgs');

  fs.readFile(commitMsgFile, function(err, buffer) {
    var msg = firstLineFromBuffer(buffer);

    if (!validateMessage(msg, removeInfo(buffer))) {
      fs.appendFile(incorrectLogFile, msg + '\n', function() {
        process.exit(1);
      });
    } else {
      process.exit(0);
    }
  });
}<commit_msg>style(commit-messge): Limit PR title<commit_after>#!/usr/bin/env node

/**
 * Original Code
 * https://raw.githubusercontent.com/angular/angular.js/master/validate-commit-msg.js
 * Git COMMIT-MSG hook for validating commit message
 * See https://github.com/naver/egjs/wiki/Commit-Guidelines
 * modified by egjs
 */

'use strict';

var fs = require('fs');
var util = require('util');

var MAX_TITLE_LENGTH = 50;
var MAX_LENGTH = 100;
var PATTERN = /^(?:fixup!\s*)?(\w*)(\(([\w\$\,\.\*/-]*)\))?\: (.*)$/;
var IGNORED = /^WIP\:/;
var TYPES = {
  feat: true,
  fix: true,
  docs: true,
  style: true,
  refactor: true,
  test: true,
  chore: true
};

var error = function() {
  // gitx does not display it
  // http://gitx.lighthouseapp.com/projects/17830/tickets/294-feature-display-hook-error-message-when-hook-fails
  // https://groups.google.com/group/gitx/browse_thread/thread/a03bcab60844b812
  console.error('INVALID COMMIT MSG: ' + util.format.apply(null, arguments));
};

var validateMessage = function(message, fullMessage) {
  var isValid = true;

  if (IGNORED.test(message)) {
    console.log('Commit message validation ignored.');
    return true;
  }

  if (message.length > MAX_LENGTH) {
    error('is longer than %d characters !', MAX_LENGTH);
    isValid = false;
  }

  var match = PATTERN.exec(message);

  if (!match) {
    var data = fs.readFileSync(__dirname+'/../../config/commit.template', 'utf8');
    error('\n\r======= Your commit message =======\n\r' + fullMessage + '\n\r' + data);
    return false;
  }

  var type = match[1];
  var module = match[3];
  var subject = match[4];

  if (subject.length > MAX_TITLE_LENGTH) {

    error('The maximum length for PR subject is %d characters !', MAX_TITLE_LENGTH);
    isValid = false;
  }

  if (!TYPES.hasOwnProperty(type)) {
    error('"%s" is not allowed type !', type);
    return false;
  }

  // Some more ideas, do want anything like this ?
  // - allow only specific scopes (eg. fix(docs) should not be allowed ?
  // - auto correct the type to lower case ?
  // - auto correct first letter of the subject to lower case ?
  // - auto add empty line after subject ?
  // - auto remove empty () ?
  // - auto correct typos in type ?
  // - store incorrect messages, so that we can learn

  return isValid;
};

var firstLineFromBuffer = function(buffer) {
  return buffer.toString().split('\n').shift();
};

var removeInfo = function(buffer) {
  return buffer.toString().replace(/\n(#\s(?:.*?)$)/gm,"");
};

// publish for testing
exports.validateMessage = validateMessage;

// hacky start if not run by jasmine :-D
if (process.argv.join('').indexOf('jasmine-node') === -1) {
  var commitMsgFile = process.argv[2];
  var incorrectLogFile = commitMsgFile.replace('COMMIT_EDITMSG', 'logs/incorrect-commit-msgs');

  fs.readFile(commitMsgFile, function(err, buffer) {
    var msg = firstLineFromBuffer(buffer);

    if (!validateMessage(msg, removeInfo(buffer))) {
      fs.appendFile(incorrectLogFile, msg + '\n', function() {
        process.exit(1);
      });
    } else {
      process.exit(0);
    }
  });
}<|endoftext|>


<commit_before>var buyPaymentButton = $('#buy-ticket-btn');
var addTicketBtn = $('#add-user-form');
var userBonusInput = $('#user-bonus-input');
var applyBonusBtn = $('#btn-apply-bonus');
var paymentList = $('#payment-list');

function editTicketRow(index, ticketBlock, ticket) {
    if (index) {
        ticketBlock.find('.payer__number').html(index);
    }
    ticketBlock.find('.user-payment__name').html(ticket.user.name+' '+ticket.user.surname);
    ticketBlock.find('.label-hidden-user-name').html(ticket.user.name);
    ticketBlock.find('.label-hidden-user-surname').html(ticket.user.surname);
    ticketBlock.find('.user-payment__email').html(ticket.user.email);
    if (ticket.has_discount) {
        ticketBlock.find('.user-payment__price').html(''+ticket.amount_without_discount+''+ticket.amount);
        ticketBlock.find('.user-payment__price-strike').show();
        ticketBlock.find('.user-payment__discount').html(ticket.discount_description).show();
        if (ticket.promo_code) {
            ticketBlock.find('.label-hidden-user-promocode').html(ticket.promo_code.code);
        } else {
            ticketBlock.find('.label-hidden-user-promocode').html('');
        }
    } else {
        ticketBlock.find('.user-payment__price').html(ticket.amount);
        ticketBlock.find('.user-payment__discount').hide();
        ticketBlock.find('.label-hidden-user-promocode').html('');
    }
    ticketBlock.attr('id', ticket.id);
}

function addTicketRowBlock(index, ticket, replaceId) {
    var newTicketRow = $('#payer-block').clone();
    editTicketRow(index, newTicketRow, ticket);
    newTicketRow.show();
    if (replaceId) {
        $('#'+replaceId).replaceWith(newTicketRow[0].outerHTML);
    } else {
        newTicketRow.appendTo('#payment-list');
    }
}

function editPaymentBlock(paymentData) {
    var elem = $('#payment-total-data');

    if (paymentData.fwdays_amount > 0) {
        elem.find('.payment-cart__text--strike').html(paymentData.base_amount).show();
        elem.find('.payment-cart__hint').html(paymentData.fwdays_amount_formatted+'').show();
    } else {
        elem.find('.payment-cart__hint').hide();
        elem.find('.payment-cart__text--strike').hide();
    }

    if (paymentData.fwdays_amount === 0 && paymentData.user.balance > 0) {
        userBonusInput.val(paymentData.user.balance).attr('max', paymentData.user.balance);
        elem.find('.payment-use-fwdays-bonus').show();
        elem.find('.payment-user-bonus-label').show();
        elem.find('.payment-user-bonus-tooltip').show();
    } else {
        elem.find('.payment-use-fwdays-bonus').hide();
        elem.find('.payment-user-bonus-label').hide();
        elem.find('.payment-user-bonus-tooltip').hide();
    }

    elem.find('.payment-cart__amount').html(paymentData.amount_formatted);

    if (!elem.is(":visible")) {
        elem.show();
        addTicketBtn.show();
    }

    if (paymentData.ticket_count === 0) {
        elem.hide();
        addTicketBtn.hide();
    }
}

function reloadingPage($this) {
    if ($this.hasClass('reload_page')) {
        window.location.reload();
        return true;
    }
    return false;
}

function applyFwdaysBonus(amount) {
    $.post(Routing.generate('payment_apply_fwdays_bonus',
        {
            'amount': amount
        }),
        function (data) {
            if (data.result) {
                saved_payment_amount = data.payment_data.amount;
                editPaymentBlock(data.payment_data);
            } else {
                console.log('Error:'+data.error);
            }
        }).always(function() {
            applyBonusBtn.removeClass('disabled');
        });
}

applyBonusBtn.click(function () {
    var amount = userBonusInput.val();
    applyBonusBtn.addClass('disabled');
    applyFwdaysBonus(amount);
});

userBonusInput.change(function (event) {
    var max = $(this).attr('max');
    if ($(this).val() > max) {
        $(this).val(max);
    }
    if ($(this).val() < 0) {
        $(this).val(0);
    }
});

$(document).on('click', '.delete-fwdays-bonus', function () {
    applyFwdaysBonus(0);
});

$(document).on('click', '.ticket-delete-btn', function () {
    var elem = $(this).closest('.payer');
    var e_slug = paymentList.data('event');
    $.post(Routing.generate('remove_ticket_from_payment',
        {
            eventSlug: e_slug,
            id: elem.attr('id')
        }),
        function (data) {
            if (data.result) {
                saved_payment_amount = data.payment_data.amount;
                elem.remove();
                editPaymentBlock(data.payment_data);
                refreshDeleteButtons();
                recalculateTicketsCount();
            } else {
                console.log('Error:'+data.error);
            }
        });
});

$(document).on('click', '.ticket-edit-btn', function () {
    var ticketRow = $(this).closest( ".payer" );
    var editTicketBlock = $('#payer-block-edit').clone();
    var number = ticketRow.find('.payer__number').html();
    editTicketBlock.attr('id', 'payer-block-edit-'+number);
    editTicketBlock.show();
    editTicketBlock.insertAfter(ticketRow);
    ticketRow.hide();
    editTicketBlock = $('#'+editTicketBlock.attr('id'));
    copyDataFromRowToBlock(ticketRow, editTicketBlock);
    addValidator(editTicketBlock);
});

function copyDataFromRowToBlock(ticketRow, editTicketBlock) {
    var user_name = ticketRow.find('.label-hidden-user-name').html();
    var user_sur_name = ticketRow.find('.label-hidden-user-surname').html();
    var user_email = ticketRow.find('.user-payment__email').html();
    var promo_code = ticketRow.find('.label-hidden-user-promocode').html();

    editTicketBlock.attr('data-ticket-id', ticketRow.attr('id'));
    editTicketBlock.find('.payer__number').html(ticketRow.find('.payer__number').html());
    editTicketBlock.find('.payment_user_name').val(user_name).attr('data-old-value', user_name);
    editTicketBlock.find('.payment_user_surname').val(user_sur_name).attr('data-old-value', user_sur_name);
    editTicketBlock.find('.payment_user_email').val(user_email).attr('data-old-value', user_email);
    editTicketBlock.find('.user_promo_code').val(promo_code).attr('data-old-value', promo_code);
    editTicketBlock.find('.add-user-btn').removeClass('add-user-btn').addClass('edit-user-btn');
}

addTicketBtn.on('click', function () {
    var newTicketBlock = $('#payer-block-edit').clone();
    ++ticket_count;
    newTicketBlock.attr('id', 'payer-block-edit-'+ticket_count);
    newTicketBlock.find('.payer__number').html(ticket_count);
    newTicketBlock.appendTo('#payment-list').show();
    addValidator(newTicketBlock);
});

function recalculateTicketsCount() {
    var numbers = $('.payer__number');
    $.each(numbers, function( index, value ) {
        $(value).html(index-1);
    });
    ticket_count = numbers.length-2;
}

function refreshDeleteButtons() {
    var buttons = $('.ticket-delete-btn');
    if (buttons.length > 2) {
        $.each(buttons, function (index, value) {
            $(value).show();
        });
    } else {
        $.each(buttons, function (index, value) {
            $(value).hide();
        });
    }
}

$(document).ready(function () {
   var $firstEditForm = $('#payer-block-edit-1');
   if ($firstEditForm.length) {
       addValidator($firstEditForm);
   }
});

$(document).on('click', '.add-user-btn', function () {
    var $this = $(this);
    var ticketBlock = $this.closest('.payer-form');
    var input_name = ticketBlock.find('.payment_user_name');
    var input_surname = ticketBlock.find('.payment_user_surname');
    var input_email = ticketBlock.find('.payment_user_email');
    var input_promocode = ticketBlock.find('.user_promo_code');

    if (input_name.valid() &&
        input_surname.valid() &&
        input_email.valid() &&
        input_promocode.valid()) {

        var e_slug = paymentList.data('event');
        $.ajax({
            url: Routing.generate('add_ticket_participant', {eventSlug: e_slug}),
            method: 'POST',
            data: {name: input_name.val(), surname: input_surname.val(), email: input_email.val(), promocode: input_promocode.val()},
            success: function (data) {
                if (data.result && !reloadingPage($this)) {
                    saved_payment_amount = data.payment_data.amount;
                    addTicketRowBlock(
                        data.payment_data.ticket_count,
                        data.ticket_data,
                        ticketBlock.attr('id')
                    );
                    editPaymentBlock(data.payment_data);
                    refreshDeleteButtons();
                    recalculateTicketsCount();
                } else {
                    var validator = ticketBlock.validate();
                    validator.showErrors(data.error );
                }
            }
        })
    }
});

$(document).on('click', '.edit-user-btn', function () {
    var $this = $(this);
    var ticketBlock = $this.closest('.payer-form');
    var input_name = ticketBlock.find('.payment_user_name');
    var input_surname = ticketBlock.find('.payment_user_surname');
    var input_email = ticketBlock.find('.payment_user_email');
    var input_promocode = ticketBlock.find('.user_promo_code');
    var ticket_id = ticketBlock.data('ticket-id');
    var parent_row = $('#'+ticket_id);

    if (input_name.val() === input_name.data('old-value') &&
        input_surname.val() === input_surname.data('old-value') &&
        input_email.val() === input_email.data('old-value') &&
        input_promocode.val() === input_promocode.data('old-value')
    ) {
        parent_row.show();
        ticketBlock.remove();
        return;
    }

    if (input_name.valid() &&
        input_surname.valid() &&
        input_email.valid() &&
        input_promocode.valid()) {

        var e_slug = paymentList.data('event');
        $.ajax({
            url: Routing.generate('edit_ticket_participant', {eventSlug: e_slug, id: ticket_id}),
            method: 'POST',
            data: {name: input_name.val(), surname: input_surname.val(), email: input_email.val(), promocode: input_promocode.val()},
            success: function (data) {
                if (data.result && !reloadingPage($this)) {
                    saved_payment_amount = data.payment_data.amount;
                    editTicketRow(null, parent_row, data.ticket_data);
                    editPaymentBlock(data.payment_data);
                    parent_row.show();
                    ticketBlock.remove();
                    refreshDeleteButtons();
                    recalculateTicketsCount();
                } else {
                    var validator = ticketBlock.validate();
                    validator.showErrors(data.error);
                }
            }
        })
    }
});

buyPaymentButton.on('click', function (e) {
    e.preventDefault();
    var submit_btn = $(this);
    submit_btn.prop("disabled", true);
    var user_phone_elem = $('#user_phone');
    var use_phone = user_phone_elem.val();

    if (!$('#payment-form').valid()) {
        submit_btn.prop("disabled", false);
        return;
    }

    if (user_phone_elem.data('old-phone') !== use_phone) {
        $.post(Routing.generate('update_user_phone', {phoneNumber: use_phone}), function (data) {});
    }

    var e_slug = paymentList.data('event');

    $.ajax({
        url: Routing.generate('event_paying', {slug: e_slug}),
        method: 'POST',
        data: {'saved_data': saved_payment_amount},
        success: function (data) {
            submit_btn.prop("disabled", false);
            if (data.result) {
                if (data.amount_changed) {
                    saved_payment_amount = data.payment_data.amount;
                    paymentList.empty();
                    $.each(data.payment_data.tickets, function( index, value ) {
                        addTicketRowBlock(index+1, value, null);
                    });
                    editPaymentBlock(data.payment_data);

                    if (data.payment_data.ticket_count === 0) {
                        ticket_count = 0;
                        addTicketBtn.click();
                    }

                    alert(data.payment_data.amount_changed_text);
                } else {
                    var $form = $(data.form);
                    paymentList.after($form);
                    $form.submit();
                }
            } else {
                alert(data.error);
                console.log(data.error);
            }
        },
        error: function () {
            submit_btn.prop("disabled", false);
            console.log('error');
        },
        always: function () {
            submit_btn.prop("disabled", false);
        }
    })
});<commit_msg>Fix js.<commit_after>var buyPaymentButton = $('#buy-ticket-btn');
var addTicketBtn = $('#add-user-form');
var userBonusInput = $('#user-bonus-input');
var applyBonusBtn = $('#btn-apply-bonus');
var paymentList = $('#payment-list');

function editTicketRow(index, ticketBlock, ticket) {
    if (index) {
        ticketBlock.find('.payer__number').html(index);
    }
    ticketBlock.find('.user-payment__name').html(ticket.user.name+' '+ticket.user.surname);
    ticketBlock.find('.label-hidden-user-name').html(ticket.user.name);
    ticketBlock.find('.label-hidden-user-surname').html(ticket.user.surname);
    ticketBlock.find('.user-payment__email').html(ticket.user.email);
    if (ticket.has_discount) {
        ticketBlock.find('.user-payment__price').html(''+ticket.amount_without_discount+''+ticket.amount);
        ticketBlock.find('.user-payment__price-strike').show();
        ticketBlock.find('.user-payment__discount').html(ticket.discount_description).show();
        if (ticket.promo_code) {
            ticketBlock.find('.label-hidden-user-promocode').html(ticket.promo_code.code);
        } else {
            ticketBlock.find('.label-hidden-user-promocode').html('');
        }
    } else {
        ticketBlock.find('.user-payment__price').html(ticket.amount);
        ticketBlock.find('.user-payment__discount').hide();
        ticketBlock.find('.label-hidden-user-promocode').html('');
    }
    ticketBlock.attr('id', ticket.id);
}

function addTicketRowBlock(index, ticket, replaceId) {
    var newTicketRow = $('#payer-block').clone();
    editTicketRow(index, newTicketRow, ticket);
    newTicketRow.show();
    if (replaceId) {
        $('#'+replaceId).replaceWith(newTicketRow[0].outerHTML);
    } else {
        newTicketRow.appendTo('#payment-list');
    }
}

function editPaymentBlock(paymentData) {
    var elem = $('#payment-total-data');

    if (paymentData.fwdays_amount > 0) {
        elem.find('.payment-cart__text--strike').html(paymentData.base_amount).show();
        elem.find('.payment-cart__hint').html(paymentData.fwdays_amount_formatted+'').show();
    } else {
        elem.find('.payment-cart__hint').hide();
        elem.find('.payment-cart__text--strike').hide();
    }

    if (paymentData.fwdays_amount === 0 && paymentData.user.balance > 0) {
        userBonusInput.val(paymentData.user.balance).attr('max', paymentData.user.balance);
        elem.find('.payment-use-fwdays-bonus').show();
        elem.find('.payment-user-bonus-label').show();
        elem.find('.payment-user-bonus-tooltip').show();
    } else {
        elem.find('.payment-use-fwdays-bonus').hide();
        elem.find('.payment-user-bonus-label').hide();
        elem.find('.payment-user-bonus-tooltip').hide();
    }

    elem.find('.payment-cart__amount').html(paymentData.amount_formatted);

    if (!elem.is(":visible")) {
        elem.show();
        addTicketBtn.show();
    }

    if (paymentData.ticket_count === 0) {
        elem.hide();
        addTicketBtn.hide();
    }
}

function reloadingPage($this) {
    if ($this.hasClass('reload_page')) {
        window.location.reload();
        return true;
    }
    return false;
}

function applyFwdaysBonus(amount) {
    $.post(Routing.generate('payment_apply_fwdays_bonus',
        {
            'amount': amount
        }),
        function (data) {
            if (data.result) {
                saved_payment_amount = data.payment_data.amount;
                editPaymentBlock(data.payment_data);
            } else {
                console.log('Error:'+data.error);
            }
        }).always(function() {
            applyBonusBtn.removeClass('disabled');
        });
}

applyBonusBtn.click(function () {
    var amount = userBonusInput.val();
    applyBonusBtn.addClass('disabled');
    applyFwdaysBonus(amount);
});

userBonusInput.change(function (event) {
    var max = $(this).attr('max');
    if ($(this).val() > max) {
        $(this).val(max);
    }
    if ($(this).val() < 0) {
        $(this).val(0);
    }
});

$(document).on('click', '.delete-fwdays-bonus', function () {
    applyFwdaysBonus(0);
});

$(document).on('click', '.ticket-delete-btn', function () {
    var elem = $(this).closest('.payer');
    var e_slug = paymentList.data('event');
    $.post(Routing.generate('remove_ticket_from_payment',
        {
            eventSlug: e_slug,
            id: elem.attr('id')
        }),
        function (data) {
            if (data.result) {
                saved_payment_amount = data.payment_data.amount;
                elem.remove();
                editPaymentBlock(data.payment_data);
                refreshDeleteButtons();
                recalculateTicketsCount();
            } else {
                console.log('Error:'+data.error);
            }
        });
});

$(document).on('click', '.ticket-edit-btn', function () {
    var ticketRow = $(this).closest( ".payer" );
    var editTicketBlock = $('#payer-block-edit').clone();
    var number = ticketRow.find('.payer__number').html();
    editTicketBlock.attr('id', 'payer-block-edit-'+number);
    editTicketBlock.show();
    editTicketBlock.insertAfter(ticketRow);
    ticketRow.hide();
    editTicketBlock = $('#'+editTicketBlock.attr('id'));
    copyDataFromRowToBlock(ticketRow, editTicketBlock);
    addValidator(editTicketBlock);
});

function copyDataFromRowToBlock(ticketRow, editTicketBlock) {
    var user_name = ticketRow.find('.label-hidden-user-name').html();
    var user_sur_name = ticketRow.find('.label-hidden-user-surname').html();
    var user_email = ticketRow.find('.user-payment__email').html();
    var promo_code = ticketRow.find('.label-hidden-user-promocode').html();

    editTicketBlock.attr('data-ticket-id', ticketRow.attr('id'));
    editTicketBlock.find('.payer__number').html(ticketRow.find('.payer__number').html());
    editTicketBlock.find('.payment_user_name').val(user_name).attr('data-old-value', user_name);
    editTicketBlock.find('.payment_user_surname').val(user_sur_name).attr('data-old-value', user_sur_name);
    editTicketBlock.find('.payment_user_email').val(user_email).attr('data-old-value', user_email);
    editTicketBlock.find('.user_promo_code').val(promo_code).attr('data-old-value', promo_code);
    editTicketBlock.find('.add-user-btn').removeClass('add-user-btn').addClass('edit-user-btn');
}

addTicketBtn.on('click', function () {
    var newTicketBlock = $('#payer-block-edit').clone();
    ++ticket_count;
    newTicketBlock.attr('id', 'payer-block-edit-'+ticket_count);
    newTicketBlock.find('.payer__number').html(ticket_count);
    newTicketBlock.appendTo('#payment-list').show();
    addValidator(newTicketBlock);
});

function recalculateTicketsCount() {
    var numbers = $('.payer__number');
    $.each(numbers, function( index, value ) {
        $(value).html(index-1);
    });
    ticket_count = numbers.length-2;
}

function refreshDeleteButtons() {
    var buttons = $('.ticket-delete-btn');
    if (buttons.length > 2) {
        $.each(buttons, function (index, value) {
            $(value).show();
        });
    } else {
        $.each(buttons, function (index, value) {
            $(value).hide();
        });
    }
}

$(document).ready(function () {
   var $firstEditForm = $('#payer-block-edit-1');
   if ($firstEditForm.length) {
       addValidator($firstEditForm);
   }
});

$(document).on('click', '.add-user-btn', function () {
    var $this = $(this);
    var ticketBlock = $this.closest('.payer-form');
    var input_name = ticketBlock.find('.payment_user_name');
    var input_surname = ticketBlock.find('.payment_user_surname');
    var input_email = ticketBlock.find('.payment_user_email');
    var input_promocode = ticketBlock.find('.user_promo_code');

    if (input_name.valid() &&
        input_surname.valid() &&
        input_email.valid() &&
        input_promocode.valid()) {

        var e_slug = paymentList.data('event');
        $.ajax({
            url: Routing.generate('add_ticket_participant', {eventSlug: e_slug}),
            method: 'POST',
            data: {name: input_name.val(), surname: input_surname.val(), email: input_email.val(), promocode: input_promocode.val()},
            success: function (data) {
                if (data.result && !reloadingPage($this)) {
                    saved_payment_amount = data.payment_data.amount;
                    addTicketRowBlock(
                        data.payment_data.ticket_count,
                        data.ticket_data,
                        ticketBlock.attr('id')
                    );
                    editPaymentBlock(data.payment_data);
                    refreshDeleteButtons();
                    recalculateTicketsCount();
                } else {
                    var validator = ticketBlock.validate();
                    validator.showErrors(data.error );
                }
            }
        })
    }
});

$(document).on('click', '.edit-user-btn', function () {
    var $this = $(this);
    var ticketBlock = $this.closest('.payer-form');
    var input_name = ticketBlock.find('.payment_user_name');
    var input_surname = ticketBlock.find('.payment_user_surname');
    var input_email = ticketBlock.find('.payment_user_email');
    var input_promocode = ticketBlock.find('.user_promo_code');
    var ticket_id = ticketBlock.data('ticket-id');
    var parent_row = $('#'+ticket_id);

    if (input_name.val() === input_name.data('old-value') &&
        input_surname.val() === input_surname.data('old-value') &&
        input_email.val() === input_email.data('old-value') &&
        input_promocode.val() === input_promocode.data('old-value')
    ) {
        parent_row.show();
        ticketBlock.remove();
        return;
    }

    if (input_name.valid() &&
        input_surname.valid() &&
        input_email.valid() &&
        input_promocode.valid()) {

        var e_slug = paymentList.data('event');
        $.ajax({
            url: Routing.generate('edit_ticket_participant', {eventSlug: e_slug, id: ticket_id}),
            method: 'POST',
            data: {name: input_name.val(), surname: input_surname.val(), email: input_email.val(), promocode: input_promocode.val()},
            success: function (data) {
                if (data.result && !reloadingPage($this)) {
                    saved_payment_amount = data.payment_data.amount;
                    editTicketRow(null, parent_row, data.ticket_data);
                    editPaymentBlock(data.payment_data);
                    parent_row.show();
                    ticketBlock.remove();
                    refreshDeleteButtons();
                    recalculateTicketsCount();
                } else {
                    var validator = ticketBlock.validate();
                    validator.showErrors(data.error);
                }
            }
        })
    }
});

buyPaymentButton.on('click', function (e) {
    e.preventDefault();
    var submit_btn = $(this);
    submit_btn.prop("disabled", true);
    var user_phone_elem = $('#user_phone');
    var use_phone = user_phone_elem.val();

    if (!$('#payment-form').valid()) {
        submit_btn.prop("disabled", false);
        return;
    }

    if (user_phone_elem.data('old-phone') !== use_phone) {
        $.post(Routing.generate('update_user_phone', {phoneNumber: use_phone}), function (data) {});
    }

    var e_slug = paymentList.data('event');

    $.ajax({
        url: Routing.generate('event_paying', {slug: e_slug}),
        method: 'POST',
        data: {'saved_data': saved_payment_amount},
        success: function (data) {
            submit_btn.prop("disabled", false);
            if (data.result) {
                if (data.amount_changed) {
                    saved_payment_amount = data.payment_data.amount;
                    paymentList.empty();
                    $.each(data.payment_data.tickets, function( index, value ) {
                        addTicketRowBlock(index+1, value);
                    });
                    editPaymentBlock(data.payment_data);

                    if (data.payment_data.ticket_count === 0) {
                        ticket_count = 0;
                        addTicketBtn.click();
                    }

                    alert(data.payment_data.amount_changed_text);
                } else {
                    var $form = $(data.form);
                    paymentList.after($form);
                    $form.submit();
                }
            } else {
                alert(data.error);
                console.log(data.error);
            }
        },
        error: function () {
            submit_btn.prop("disabled", false);
            console.log('error');
        },
        always: function () {
            submit_btn.prop("disabled", false);
        }
    })
});<|endoftext|>