<commit_before>
const Player = require('../core/Player');
const CardArea = require('../core/CardArea');
const cmd = require('../core/protocol');

class ServerPlayer extends Player {

	constructor(user) {
		super();
		this.user = user;

		this.handArea = new CardArea(CardArea.Type.Hand, this);
		this.equipArea = new CardArea(CardArea.Type.Equip, this);
		this.delayedTrickArea = new CardArea(CardArea.Type.DelayedTrick, this);
		this.judgeArea = new CardArea(CardArea.Type.Judge, this);
	}

	async askForGeneral(generals, options = {}) {
		options = Object.assign({
			timeout: 40,
			num: 1,
			sameKingdom: false,
			forced: true,
		}, options);

		let reply = [];
		try {
			reply = await this.user.request(cmd.ChooseGeneral, {
				sameKingdom: !!options.sameKingdom,
				num: options.num || 1,
				generals: generals.map((general, i) => ({
					id: i,
					kingdom: general.kingdom(),
					name: general.name(),
				}))
			}, options.timeout * 1000);
		} catch (error) {
		}

		let chosen_generals = [];
		if (reply && reply instanceof Array) {
			for (let id of reply) {
				if (id >= 0 && id < generals.length) {
					chosen_generals.push(generals[i]);
				}
			}
		}

		if (options.forced && chosen_generals.length < options.num && generals.length >= options.num) {
			let available_generals = generals;
			if (options.sameKingdom && options.num > 1) {
				let kingdoms = new Map;
				for (let general of generals) {
					let alliances = kingdoms.get(general.kingdom());
					if (!alliances) {
						kingdoms.set(general.kingdom(), [general]);
					} else {
						alliances.push(general);
					}
				}

				let available_kingdoms = [];
				for (let [_, alliances] of kingdoms) {
					if (alliances.length >= options.num) {
						available_kingdoms.push(alliances);
					}
				}

				let index = Math.floor(Math.random() * available_kingdoms.length);
				available_generals = available_kingdoms[index];
			}

			do {
				let index = Math.floor(Math.random() * available_generals.length);
				let chosen = available_generals[index];
				if (chosen_generals.indexOf(chosen) < 0
					&& chosen_generals.every) {
					chosen_generals.push(chosen);
				}
			} while (chosen_generals.length < options.num);
		}

		return chosen_generals;
	}

	updateProperty(prop, value) {
		this.user.send(cmd.UpdatePlayer, {
			uid: this.user.id,
			prop,
			value
		});
	}

	broadcastProperty(prop, value) {
		const room = this.user && this.user.room;
		if (!room) {
			return;
		}
		room.broadcast(cmd.UpdatePlayer, {
			uid: this.user.id,
			prop,
			value
		});
	}

}

module.exports = ServerPlayer;
<commit_msg>Fix typos<commit_after>
const Player = require('../core/Player');
const CardArea = require('../core/CardArea');
const cmd = require('../core/protocol');

class ServerPlayer extends Player {

	constructor(user) {
		super();
		this.user = user;

		this.handArea = new CardArea(CardArea.Type.Hand, this);
		this.equipArea = new CardArea(CardArea.Type.Equip, this);
		this.delayedTrickArea = new CardArea(CardArea.Type.DelayedTrick, this);
		this.judgeArea = new CardArea(CardArea.Type.Judge, this);
	}

	async askForGeneral(generals, options = {}) {
		options = Object.assign({
			timeout: 40,
			num: 1,
			sameKingdom: false,
			forced: true,
		}, options);

		let reply = [];
		try {
			reply = await this.user.request(cmd.ChooseGeneral, {
				sameKingdom: !!options.sameKingdom,
				num: options.num || 1,
				generals: generals.map((general, i) => ({
					id: i,
					kingdom: general.kingdom(),
					name: general.name(),
				}))
			}, options.timeout * 1000);
		} catch (error) {
			console.error(error);
		}

		let chosen_generals = [];
		if (reply && reply instanceof Array) {
			for (let id of reply) {
				if (id >= 0 && id < generals.length) {
					chosen_generals.push(generals[id]);
				}
			}
		}

		if (options.forced && chosen_generals.length < options.num && generals.length >= options.num) {
			let available_generals = generals;
			if (options.sameKingdom && options.num > 1) {
				let kingdoms = new Map;
				for (let general of generals) {
					let alliances = kingdoms.get(general.kingdom());
					if (!alliances) {
						kingdoms.set(general.kingdom(), [general]);
					} else {
						alliances.push(general);
					}
				}

				let available_kingdoms = [];
				for (let [_, alliances] of kingdoms) {
					if (alliances.length >= options.num) {
						available_kingdoms.push(alliances);
					}
				}

				let index = Math.floor(Math.random() * available_kingdoms.length);
				available_generals = available_kingdoms[index];
			}

			do {
				let index = Math.floor(Math.random() * available_generals.length);
				let chosen = available_generals[index];
				if (chosen_generals.indexOf(chosen) < 0
					&& chosen_generals.every) {
					chosen_generals.push(chosen);
				}
			} while (chosen_generals.length < options.num);
		}

		return chosen_generals;
	}

	updateProperty(prop, value) {
		this.user.send(cmd.UpdatePlayer, {
			uid: this.user.id,
			prop,
			value
		});
	}

	broadcastProperty(prop, value) {
		const room = this.user && this.user.room;
		if (!room) {
			return;
		}
		room.broadcast(cmd.UpdatePlayer, {
			uid: this.user.id,
			prop,
			value
		});
	}

}

module.exports = ServerPlayer;
<|endoftext|>


<commit_before>import Immutable from "immutable";
import won from "../../won-es6.js";

import { isUriRead } from "../../won-localstorage.js";

export function parseConnection(jsonldConnection) {
  const jsonldConnectionImm = Immutable.fromJS(jsonldConnection);

  let parsedConnection = {
    belongsToUri: undefined,
    socketUri: jsonldConnectionImm.get("socket"),
    targetSocketUri: jsonldConnectionImm.get("targetSocket"),
    data: {
      uri: undefined,
      state: undefined,
      messages: Immutable.Map(),
      socket: undefined, //will be determined by the reduce-connections
      agreementData: {
        agreementUris: Immutable.Set(),
        pendingProposalUris: Immutable.Set(),
        pendingCancellationProposalUris: Immutable.Set(),
        cancellationPendingAgreementUris: Immutable.Set(),
        acceptedCancellationProposalUris: Immutable.Set(),
        cancelledAgreementUris: Immutable.Set(),
        rejectedMessageUris: Immutable.Set(),
        retractedMessageUris: Immutable.Set(),
        proposedMessageUris: Immutable.Set(),
        claimedMessageUris: Immutable.Set(),
      },
      petriNetData: Immutable.Map(),
      targetAtomUri: undefined,
      targetConnectionUri: undefined,
      targetSocket: undefined, //will be determined by the reduce-connections
      creationDate: undefined,
      lastUpdateDate: undefined,
      unread: undefined,
      isRated: false,
      showAgreementData: false,
      showPetriNetData: false,
      multiSelectType: undefined,
    },
  };

  const belongsToUri = jsonldConnectionImm.get("sourceAtom");
  const targetAtomUri = jsonldConnectionImm.get("targetAtom");
  const targetConnectionUri = jsonldConnectionImm.get("targetConnection");
  const uri = jsonldConnectionImm.get("uri");

  if (!!uri && !!belongsToUri && !!targetAtomUri) {
    parsedConnection.belongsToUri = belongsToUri;
    parsedConnection.data.uri = uri;
    parsedConnection.data.unread = !isUriRead(uri);
    parsedConnection.data.targetAtomUri = targetAtomUri;
    parsedConnection.data.targetConnectionUri = targetConnectionUri;

    const creationDate = jsonldConnectionImm.get("modified");
    if (creationDate) {
      parsedConnection.data.creationDate = new Date(creationDate);
      parsedConnection.data.lastUpdateDate = parsedConnection.data.creationDate;
    }

    const state = jsonldConnectionImm.get("connectionState");
    if (
      state === won.WON.RequestReceived ||
      state === won.WON.RequestSent ||
      state === won.WON.Suggested ||
      state === won.WON.Connected ||
      state === won.WON.Closed
    ) {
      parsedConnection.data.state = state;
    } else {
      console.error(
        "Cant parse connection, data is an invalid connection-object (faulty state): ",
        jsonldConnectionImm.toJS()
      );
      return undefined; // FOR UNKNOWN STATES
    }

    return Immutable.fromJS(parsedConnection);
  } else {
    console.error(
      "Cant parse connection, data is an invalid connection-object (mandatory uris could not be retrieved): ",
      jsonldConnectionImm.toJS()
    );
    return undefined;
  }
}
<commit_msg>Refactor parseConnection function: - adds socketUri and targetSocketUri to data - adds FIXME's to the parseConnections - refactors error handling (errors are handled in the if's and the correct case is handled in the else, removed cascaded if statements) - pull jsonLdData fetches directly in the jsonConnection initialization<commit_after>import Immutable from "immutable";
import won from "../../won-es6.js";

import { isUriRead } from "../../won-localstorage.js";

export function parseConnection(jsonldConnection) {
  const jsonldConnectionImm = Immutable.fromJS(jsonldConnection);

  let parsedConnection = {
    belongsToUri: jsonldConnectionImm.get("sourceAtom"),
    socketUri: jsonldConnectionImm.get("socket"), //TODO: REMOVE THIS AFTER REFACTORING
    targetSocketUri: jsonldConnectionImm.get("targetSocket"), //TODO: REMOVE THIS AFTER REFACTORING
    data: {
      uri: jsonldConnectionImm.get("uri"),
      state: jsonldConnectionImm.get("connectionState"),
      messages: Immutable.Map(),
      socketUri: jsonldConnectionImm.get("socket"),
      targetSocketUri: jsonldConnectionImm.get("targetSocket"),
      socket: undefined, //will be determined by the reduce-connections //TODO: REMOVE THIS AFTER REFACTORING
      targetSocket: undefined, //will be determined by the reduce-connections
      agreementData: {
        agreementUris: Immutable.Set(),
        pendingProposalUris: Immutable.Set(),
        pendingCancellationProposalUris: Immutable.Set(),
        cancellationPendingAgreementUris: Immutable.Set(),
        acceptedCancellationProposalUris: Immutable.Set(),
        cancelledAgreementUris: Immutable.Set(),
        rejectedMessageUris: Immutable.Set(),
        retractedMessageUris: Immutable.Set(),
        proposedMessageUris: Immutable.Set(),
        claimedMessageUris: Immutable.Set(),
      },
      petriNetData: Immutable.Map(),
      targetAtomUri: jsonldConnectionImm.get("targetAtom"),
      targetConnectionUri: jsonldConnectionImm.get("targetConnection"),
      creationDate: undefined,
      lastUpdateDate: undefined,
      unread: undefined,
      isRated: false,
      showAgreementData: false,
      showPetriNetData: false,
      multiSelectType: undefined,
    },
  };

  if (
    !parsedConnection.data.socketUri ||
    !parsedConnection.data.targetSocketUri
  ) {
    console.error(
      "Cant parse connection, at least one of the mandatory socketUris is empty: ",
      jsonldConnectionImm.toJS()
    );
  } else if (
    !parsedConnection.data.uri ||
    !parsedConnection.belongsToUri ||
    !parsedConnection.data.targetAtomUri
  ) {
    console.error(
      "Cant parse connection, data is an invalid connection-object (mandatory uris could not be retrieved): ",
      jsonldConnectionImm.toJS()
    );
  } else if (
    !(
      parsedConnection.data.state === won.WON.RequestReceived ||
      parsedConnection.data.state === won.WON.RequestSent ||
      parsedConnection.data.state === won.WON.Suggested ||
      parsedConnection.data.state === won.WON.Connected ||
      parsedConnection.data.state === won.WON.Closed
    )
  ) {
    console.error(
      "Cant parse connection, data is an invalid connection-object (faulty state): ",
      jsonldConnectionImm.toJS()
    );
  } else {
    parsedConnection.data.unread = !isUriRead(parsedConnection.data.uri);

    const creationDate = jsonldConnectionImm.get("modified");
    if (creationDate) {
      parsedConnection.data.creationDate = new Date(creationDate);
      parsedConnection.data.lastUpdateDate = parsedConnection.data.creationDate;
    }

    return Immutable.fromJS(parsedConnection);
  }
  return undefined;
}
<|endoftext|>


<commit_before>/** @lends TagsEditorView */
define(function(require) {
    'use strict';

    /**
     * Tags-select content editor. Please note that it requires column data format
     * corresponding to multi-select-cell.
     *
     * ### Column configuration samples:
     * ``` yml
     * datagrid:
     *   {grid-uid}:
     *     inline_editing:
     *       enable: true
     *     # <grid configuration> goes here
     *     columns:
     *       # Sample 1. Full configuration
     *       {column-name-1}:
     *         inline_editing:
     *           editor:
     *             view: orodatagrid/js/app/views/editor/multi-relation-editor-view
     *             view_options:
     *               placeholder: '<placeholder>'
     *               css_class_name: '<class-name>'
     *               maximumSelectionLength: 3
     *           validation_rules:
     *             NotBlank: true
     * ```
     *
     * ### Options in yml:
     *
     * Column option name                                  | Description
     * :---------------------------------------------------|:-----------
     * inline_editing.editor.view_options.placeholder      | Optional. Placeholder translation key for an empty element
     * inline_editing.editor.view_options.placeholder_raw  | Optional. Raw placeholder value
     * inline_editing.editor.view_options.css_class_name   | Optional. Additional css class name for editor view DOM el
     * inline_editing.editor.view_options.maximumSelectionLength | Optional. Maximum selection length
     * inline_editing.editor.validation_rules | Optional. Validation rules. See [documentation](https://goo.gl/j9dj4Y)
     *
     * ### Constructor parameters
     *
     * @class
     * @param {Object} options - Options container
     * @param {Object} options.model - Current row model
     * @param {Backgrid.Cell} options.cell - Current datagrid cell
     * @param {Backgrid.Column} options.column - Current datagrid column
     * @param {string} options.placeholder - Placeholder translation key for an empty element
     * @param {string} options.placeholder_raw - Raw placeholder value. It overrides placeholder translation key
     * @param {string} options.maximumSelectionLength - Maximum selection length
     * @param {Object} options.validationRules - Validation rules. See [documentation here](https://goo.gl/j9dj4Y)
     *
     * @augments [SelectEditorView](./select-editor-view.md)
     * @exports TagsEditorView
     */
    var TagsEditorView;
    var SelectEditorView = require('./select-editor-view');
    var _ = require('underscore');

    TagsEditorView = SelectEditorView.extend(/** @exports TagsEditorView.prototype */{
        className: 'tags-select-editor',
        initialize: function (options) {
            this.options = options;
            TagsEditorView.__super__.initialize.apply(this, arguments);
        },
        getAvailableOptions: function () {
            var value = this.model.get(this.options.column.get('name'));
            if (!_.isArray(value))
                return [];
            return value;
        },

        getSelect2Options: function() {
            var options = {
                tags: true,
                allowClear: false,
                tokenSeparators:  [',', ' '],
                data: {results: this.availableChoices},
                createSearchChoice: function (term) {
                    return { id: term, text: term, isNew: true };
                }
            }
            return options;
        },

        getModelValue: function() {
            var value = this.model.get(this.options.column.get('name'));

            if (!_.isArray(value))
                return [];

            return value.map(function (v, i, a) {
                return v.id;
            });
        },

        getValue: function() {
            var selections = this.$('input[name=value]').select2('data');
            return selections;
        }
    });

    return TagsEditorView;
});
<commit_msg>CRM-4657 CRM-4551 Chaged data format cell.<commit_after>/** @lends TagsEditorView */
define(function(require) {
    'use strict';

    /**
     * Tags-select content editor. Please note that it requires column data format
     * corresponding to tags-cell.
     *
     * ### Column configuration samples:
     * ``` yml
     * datagrid:
     *   {grid-uid}:
     *     inline_editing:
     *       enable: true
     *     # <grid configuration> goes here
     *     columns:
     *       # Sample 1. Full configuration
     *       {column-name-1}:
     *         inline_editing:
     *           editor:
     *             view: orodatagrid/js/app/views/editor/tags-editor-view
     *             view_options:
     *               placeholder: '<placeholder>'
     *               css_class_name: '<class-name>'
     *               maximumSelectionLength: 3
     *           validation_rules:
     *             NotBlank: true
     * ```
     *
     * ### Options in yml:
     *
     * Column option name                                  | Description
     * :---------------------------------------------------|:-----------
     * inline_editing.editor.view_options.placeholder      | Optional. Placeholder translation key for an empty element
     * inline_editing.editor.view_options.placeholder_raw  | Optional. Raw placeholder value
     * inline_editing.editor.view_options.css_class_name   | Optional. Additional css class name for editor view DOM el
     * inline_editing.editor.view_options.maximumSelectionLength | Optional. Maximum selection length
     * inline_editing.editor.validation_rules | Optional. Validation rules. See [documentation](https://goo.gl/j9dj4Y)
     *
     * ### Constructor parameters
     *
     * @class
     * @param {Object} options - Options container
     * @param {Object} options.model - Current row model
     * @param {Backgrid.Cell} options.cell - Current datagrid cell
     * @param {Backgrid.Column} options.column - Current datagrid column
     * @param {string} options.placeholder - Placeholder translation key for an empty element
     * @param {string} options.placeholder_raw - Raw placeholder value. It overrides placeholder translation key
     * @param {string} options.maximumSelectionLength - Maximum selection length
     * @param {Object} options.validationRules - Validation rules. See [documentation here](https://goo.gl/j9dj4Y)
     *
     * @augments [SelectEditorView](./select-editor-view.md)
     * @exports TagsEditorView
     */
    var TagsEditorView;
    var RelatedIdRelationEditorView = require('./related-id-relation-editor-view');
    var SelectEditorView = require('./select-editor-view');
    var tools = require('oroui/js/tools');
    var _ = require('underscore');

    TagsEditorView = SelectEditorView.extend(/** @exports TagsEditorView.prototype */{
        className: 'tags-select-editor',
        initialize: function (options) {
            this.options = options;
            TagsEditorView.__super__.initialize.apply(this, arguments);
        },
        getAvailableOptions: function () {
            var value = this.model.get(this.options.column.get('name'));
            if (!_.isArray(value))
                return [];
            return value;
        },

        getSelect2Options: function() {
            var options = {
                tags: true,
                allowClear: false,
                tokenSeparators:  [',', ' '],
                data: {results: this.availableChoices},
                createSearchChoice: function (term) {
                    return { id: term, text: term, isNew: true };
                }
            }
            return options;
        },

        getModelValue: function() {
            var value = this.model.get(this.options.column.get('name'));

            if (!_.isArray(value))
                return {data: []};

            return {
                data: value.map(function (v, i, a) {
                    return {id: v.id};
                })
            }
        },

        getValue: function() {
            var selections = this.$('input[name=value]').select2('data');
            return {
                data: selections.map(function(v) {
                    return {id: v.id, text: v.text, locked: v.locked};
                }),
                count: selections.length
            };
        },
        getInitialResultItem: function() {
            var modelValue = this.getModelValue();
            if (modelValue !== null && modelValue && modelValue.data) {
                return modelValue.data;
            } else {
                return [];
            }
        },

        getFormattedValue: function() {
            return this.getInitialResultItem()
                .map(function(item) {return item.id;})
                .join(',');
        },

        filterInitialResultItem: function(choices) {
            choices = _.clone(choices);
            return choices;
        },
        getServerUpdateData: function() {
            var data = {};
            data[this.options.column.get('name')] = this.getValue();
            return data;
        },

        getModelUpdateData: function() {
            return this.getServerUpdateData();
        }
    }, {
        DEFAULT_ACCESSOR_CLASS: 'oroentity/js/tools/entity-select-search-api-accessor',
        processColumnMetadata: function(columnMetadata) {
            var apiSpec = columnMetadata.inline_editing.autocomplete_api_accessor;
            if (!_.isObject(apiSpec)) {
                throw new Error('`autocomplete_api_accessor` is required option');
            }
            if (!apiSpec.class) {
                apiSpec.class = RelatedIdRelationEditorView.DEFAULT_ACCESSOR_CLASS;
            }
            return tools.loadModuleAndReplace(apiSpec, 'class');
        }
    });

    return TagsEditorView;
});
<|endoftext|>


<commit_before>import Ember from 'ember';

export default Ember.Component.extend({
  tagName: 'md-backdrop',
  classNames: ['paper-backdrop', 'md-opaque', 'md-default-theme'],

  subscribeToTouchEvents: function() {
    var hammer = new Hammer(this.get('element'));
    hammer.on('tap', Ember.run.bind(this, this._collapseSidenav));
  }.on('didInsertElement'),

  _collapseSidenav: function(event) {
    Ember.$(event.target).trigger('collapseSidenav');
    return false;
  }

});
<commit_msg>Add destroy logic<commit_after>import Ember from 'ember';

export default Ember.Component.extend({
  tagName: 'md-backdrop',
  classNames: ['paper-backdrop', 'md-opaque', 'md-default-theme'],

  // Hammer event handler for tapping backdrop
  tapHammer: null,

  subscribeToTouchEvents: function() {
    var hammer = new Hammer(this.get('element'));
    hammer.on('tap', Ember.run.bind(this, this._collapseSidenav));
    this.set('tapHammer', hammer);
  }.on('didInsertElement'),

  _collapseSidenav: function(event) {
    Ember.$(event.target).trigger('collapseSidenav');
    return false;
  },

  onWillDestroyElement: function() {
    if (Ember.isPresent(this.get('tapHammer'))) {
      this.get('tapHammer').destroy();
    }
  }.on('willDestroyElement')

});
<|endoftext|>


<commit_before>// Wraps Tizen interface "NFCAdapter" that resides in Tizen module "NFC".

define(['Ti/_/declare', 'Ti/_/Evented', 'Tizen/_/NFC/NFCTag', 'Tizen/_/NFC/NFCPeer'], function(declare, Evented, NFCTag, NFCPeer) {

	var listening,
		adapter = declare(Evented, {

			constructor: function(args) {
				if (args.toString() === '[object NFCAdapter]') {
					// args is a native Tizen object; simply wrap it (take ownership of it)
					this._obj = args;
				}
			},

			setPowered: function(state, callback) {
				return this._obj.setPowered(state, callback && function() {
					callback({
						success: true,
						code: 0
					});
				}, callback && function(e) {
					callback({
						success: false,
						error: e.type + ': ' + e.message,
						code: e.code
					});
				});
			},

			addEventListener: function () {
				var self = this;

				Evented.addEventListener.apply(this, arguments);

				if (! listening) {
					listening = true;

					// Add Tag event listeners.
					this._obj.setTagListener({
						onattach: function (nfcTag) {
							self.fireEvent('tagattached', {
								nfcTag: new NFCTag(nfcTag)
							});
						},
						ondetach: function () {
							self.fireEvent('tagdetached');
						}
					});

					// Add Peer event listeners.
					this._obj.setPeerListener({
						onattach: function (nfcPeer) {
							self.fireEvent('peerattached', {
								nfcPeer: new NFCPeer(nfcPeer)
							});
						},
						ondetach: function () {
							self.FireEvent('peerdetached');
						}
					});
				}
			},

			getCachedMessage: function() {
				return this._obj.getCachedMessage();
			},

			constants: {
				powered: {
					get: function() {
						return this._obj.powered;
					}
				}
			}

		});

	// Initialize declaredClass, so that toString() works properly on such objects.
	// Correct operation of toString() is required for proper wrapping and automated testing.
	adapter.prototype.declaredClass = 'Tizen.NFC.NFCAdapter';
	return adapter;
});
<commit_msg>Fixed events in NFC.NFCASdapter<commit_after>// Wraps Tizen interface "NFCAdapter" that resides in Tizen module "NFC".

define(['Ti/_/declare', 'Ti/_/Evented', 'Tizen/_/NFC/NFCTag', 'Tizen/_/NFC/NFCPeer'], function(declare, Evented, NFCTag, NFCPeer) {

	var listening,
		adapter = declare(Evented, {

			constructor: function(args) {
				if (args.toString() === '[object NFCAdapter]') {
					// args is a native Tizen object; simply wrap it (take ownership of it)
					this._obj = args;
				}
			},

			setPowered: function(state, callback) {
				this._obj.setPowered(state, callback && function() {
					callback({
						success: true,
						code: 0
					});
				}, callback && function(e) {
					callback({
						success: false,
						error: e.type + ': ' + e.message,
						code: e.code
					});
				});
			},

			setTagListener: function(detectCallback, tagFilter) {
				this._obj.setTagListener({
					onattach: function(nfcTag) {
						detectCallback.onattach(new NFCTag(nfcTag));
					},
					ondetach: function() {
						detectCallback.ondetach();
					}
				}, tagFilter);
			},

			unsetTagListener: function() {
				this._obj.unsetTagListener();
			},

			addEventListener: function () {
				var self = this;

				Evented.addEventListener.apply(this, arguments);

				if (! listening) {
					listening = true;

					// Add Tag event listeners.
					this._obj.setTagListener({
						onattach: function (nfcTag) {
							self.fireEvent('tagattached', {
								nfcTag: new NFCTag(nfcTag)
							});
						},
						ondetach: function () {
							self.fireEvent('tagdetached');
						}
					});

					// Add Peer event listeners.
					this._obj.setPeerListener({
						onattach: function (nfcPeer) {
							self.fireEvent('peerattached', {
								nfcPeer: new NFCPeer(nfcPeer)
							});
						},
						ondetach: function () {
							self.FireEvent('peerdetached');
						}
					});
				}
			},

			getCachedMessage: function() {
				return this._obj.getCachedMessage();
			},

			constants: {
				powered: {
					get: function() {
						return this._obj.powered;
					}
				}
			}

		});

	// Initialize declaredClass, so that toString() works properly on such objects.
	// Correct operation of toString() is required for proper wrapping and automated testing.
	adapter.prototype.declaredClass = 'Tizen.NFC.NFCAdapter';
	return adapter;
});
<|endoftext|>


<commit_before>(function () {
    'use strict';

    angular
        .module('dpMap')
        .component('dpToggleLayerSelection', {
            bindings: {
                overlays: '=',
                showLayerSelection: '='
            },
            templateUrl: 'modules/map/components/toggle-layer-selection/toggle-layer-selection.html',
            controller: DpToggleLayerSelectionController,
            controllerAs: 'vm'
        });

    DpToggleLayerSelectionController.$inject = ['$scope', 'store', 'ACTIONS'];

    function DpToggleLayerSelectionController ($scope, store, ACTIONS) {
        var vm = this;

        $scope.$watch('showLayerSelection', function () {
            if (!vm.showLayerSelection) {
                vm.buttonTitle = 'Kaartlagen selecteren';
            } else {
                vm.buttonTitle = 'Sluit paneel voor selecteren kaartlagen';
            }
        });

        vm.toggle = function () {
            store.dispatch({
                type: ACTIONS[vm.showLayerSelection ? 'HIDE_LAYER_SELECTION' : 'SHOW_LAYER_SELECTION']
            });
        };
    }
})();<commit_msg>vm. vergeten<commit_after>(function () {
    'use strict';

    angular
        .module('dpMap')
        .component('dpToggleLayerSelection', {
            bindings: {
                overlays: '=',
                showLayerSelection: '='
            },
            templateUrl: 'modules/map/components/toggle-layer-selection/toggle-layer-selection.html',
            controller: DpToggleLayerSelectionController,
            controllerAs: 'vm'
        });

    DpToggleLayerSelectionController.$inject = ['$scope', 'store', 'ACTIONS'];

    function DpToggleLayerSelectionController ($scope, store, ACTIONS) {
        var vm = this;

        $scope.$watch('vm.showLayerSelection', function () {
            if (!vm.showLayerSelection) {
                vm.buttonTitle = 'Kaartlagen selecteren';
            } else {
                vm.buttonTitle = 'Sluit paneel voor selecteren kaartlagen';
            }
        });

        vm.toggle = function () {
            store.dispatch({
                type: ACTIONS[vm.showLayerSelection ? 'HIDE_LAYER_SELECTION' : 'SHOW_LAYER_SELECTION']
            });
        };
    }
})();<|endoftext|>


<commit_before>import Ember from 'ember';
const {observer, on, run} = Ember;

export default Ember.Component.extend({
  editor: undefined,
  tagName: 'textarea',
  _contentChangedListner: null,

  // Change the editor content if value changes
  valueChanged: observer('value', function() {
    let editor = this.get('editor');
    if (editor && editor.getContent() !== this.get('value')) {
      editor.setContent(this.get('value') || '');
    }
  }),

  // Change de value if editor content changes
  contentChanged(editor) {
    this.set('value', editor.getContent());
  },

  //Bind events to function
  setEvents: observer('editor', function() {
    let editor = this.get('editor');

    this._contentChangedListner = run.bind(this, ()=> {
      run.debounce(this, this.contentChanged, editor, 1);
    });

    editor.on('change keyup keydown keypress mousedown', this._contentChangedListner);
  }),

  // Initialize tinymce
  initTiny: on('didInsertElement', observer('options', function() {
    let {options, editor} = this.getProperties('options', 'editor');

    let customOptions = {
      selector: `#${this.get('elementId')}`,
      init_instance_callback : (editor) => {
        this.set('editor', editor);
        this.get('editor').setContent(this.get('value') || ''); //Set content with default text
      },
    };

    if (editor){
      editor.destroy();
    }

    tinymce.init(Ember.$.extend( customOptions, options ));
  })),

  // Destroy tinymce editor instance when editor is removed from the page.  Otherwise, it won't be
  // created again when added back to the page (i.e. navigating away from and back to the route).
  cleanUp: on('willDestroyElement', function() {
    let editor = this.get('editor');
    if (editor) {
      editor.off('change keyup keydown keypress mousedown', this._contentChangedListner);
      editor.destroy();
    }
  })
});
<commit_msg>fix typo<commit_after>import Ember from 'ember';
const {observer, on, run} = Ember;

export default Ember.Component.extend({
  editor: undefined,
  tagName: 'textarea',
  _contentChangedListener: null,

  // Change the editor content if value changes
  valueChanged: observer('value', function() {
    let editor = this.get('editor');
    if (editor && editor.getContent() !== this.get('value')) {
      editor.setContent(this.get('value') || '');
    }
  }),

  // Change de value if editor content changes
  contentChanged(editor) {
    this.set('value', editor.getContent());
  },

  //Bind events to function
  setEvents: observer('editor', function() {
    let editor = this.get('editor');

    this._contentChangedListener = run.bind(this, ()=> {
      run.debounce(this, this.contentChanged, editor, 1);
    });

    editor.on('change keyup keydown keypress mousedown', this._contentChangedListener);
  }),

  // Initialize tinymce
  initTiny: on('didInsertElement', observer('options', function() {
    let {options, editor} = this.getProperties('options', 'editor');

    let customOptions = {
      selector: `#${this.get('elementId')}`,
      init_instance_callback : (editor) => {
        this.set('editor', editor);
        this.get('editor').setContent(this.get('value') || ''); //Set content with default text
      },
    };

    if (editor){
      editor.destroy();
    }

    tinymce.init(Ember.$.extend( customOptions, options ));
  })),

  // Destroy tinymce editor instance when editor is removed from the page.  Otherwise, it won't be
  // created again when added back to the page (i.e. navigating away from and back to the route).
  cleanUp: on('willDestroyElement', function() {
    let editor = this.get('editor');
    if (editor) {
      editor.off('change keyup keydown keypress mousedown', this._contentChangedListener);
      editor.destroy();
    }
  })
});
<|endoftext|>


<commit_before>'use strict';

// Create Download Packages controller
angular.module('packages').controller('CreateDownloadPackagesController', ['$scope', '$stateParams', '$location', 'Authentication', '$state', 'Download', '$http', '$window', 'Packages',
  function ($scope, $stateParams, $location, Authentication, $state, Download, $http, $window, Packages) {
    $scope.authentication = Authentication;

    // Merge all the feature
    var mergePackages = function(pages) {
      var page, zipFile, zip;
      var zipFileName, zipFileZip, zipFileTemplate, zipFileContent;
      var i, j, k;
1
      // 1. Get all version in each package & each feature
      var inputmethodVersions = [];
      for (i=0;i<pages.length;i++) {
        page = pages[i];

        for (j=0;j<page.zipFiles.length;j++) {
          zipFile = page.zipFiles[j];

          inputmethodVersions.push(zipFile.template.start);
          inputmethodVersions.push(zipFile.template.end);
        }
      }
      // 2. Unique
      var uniqueInputmethodVersions = [];
      window.$.each(inputmethodVersions, function(i, el){
        if(window.$.inArray(el, uniqueInputmethodVersions) === -1) uniqueInputmethodVersions.push(el);
      });
      // 3. Sort
      uniqueInputmethodVersions.sort();
      var emptyVersions = uniqueInputmethodVersions.splice(0,1);
      var emptyVersion = emptyVersions[0];
      uniqueInputmethodVersions.push(emptyVersion);

      // 4. Create version duration
      var inputmethodVersionDurations = [];
      for (i=0+1;i<uniqueInputmethodVersions.length;i++) {
        var version = uniqueInputmethodVersions[i];

        inputmethodVersionDurations.push({ start:uniqueInputmethodVersions[i-1], end:uniqueInputmethodVersions[i] });
      }
      // 5. For each duration, merge each feature zip
      var allzips = [];
      for (i=0;i<inputmethodVersionDurations.length;i++) {
        var versionDuration = inputmethodVersionDurations[i];

        var allZipFileZip = new $window.JSZip();
        var allZipFileName = versionDuration.start + "~" + versionDuration.end + "." + "zip";
        var allZipFileTemplate = versionDuration;

        for (j=0;j<pages.length;j++) {
          page = pages[j];

          for (k=0;k<page.zipFiles.length;k++) {
            zipFile = page.zipFiles[k];

            zipFileZip = zipFile.file;
            zipFileTemplate = zipFile.template;

            // Add the feature zip
            if (Packages.versionContain(zipFileTemplate,versionDuration)==Packages.VersionContainResult.Contain) {
              zipFileContent = zipFileZip.generate({type: "base64"});
              allZipFileZip.load(zipFileContent, {base64: true});
            }
          }
        }

        allzips.push({name: allZipFileName, file: allZipFileZip, template: allZipFileTemplate});
      }

      return allzips;
    };

    // Merge all the feature
    $scope.packages.zipFiles = mergePackages($scope.packages.feature.selectPages);

    // Create config.plist
    var plistTemplateFilePath = "modules/packages/client/template/com.baidu.inputmethod.resource.config.plist";
    var plistFileName = "com.baidu.inputmethod.resource.config.plist";
    // 1. get plist template
    $http.get(plistTemplateFilePath)
        .success(function(response) {
          var page, zipFile, zip;
          var zipFileName, zipFileZip, zipFileTemplate, zipFileContent;
          var i, j;
          var plistTemplate = response;

          // template -> plist
          var data = $scope.packages.info;
          var plist = $window.microtemplate(plistTemplate,data);

          // Feature
          for (i=0;i<$scope.packages.feature.selectPages.length;i++) {
            page = $scope.packages.feature.selectPages[i];

            // Feature:1. put plist into zips
            for (j=0;j<page.zipFiles.length;j++) {
              zipFile = page.zipFiles[j];

              zipFile.file.file(plistFileName, plist);
            }

            // Feature:2. Create all.zip
            zip = new $window.JSZip();
            for(j=0;j<page.zipFiles.length;j++) {
              zipFile = page.zipFiles[j];

              zipFileName = zipFile.name;
              zipFileZip = zipFile.file;

              zipFileContent = zipFileZip.generate({type: "base64"});
              zip.file(zipFileName, zipFileContent, {base64: true});
            }
            page.zipFiles.push({name: 'all.zip', file: zip, template: null});
          }

          // All:1. put plist into zips
          for (i=0;i<$scope.packages.zipFiles.length;i++) {
            zipFile = $scope.packages.zipFiles[i];

            zipFile.file.file(plistFileName, plist);
          }

          // All:2. Create all.zip
          zip = new $window.JSZip();
          for(i=0;i<$scope.packages.zipFiles.length;i++) {
            zipFile = $scope.packages.zipFiles[i];

            zipFileName = zipFile.name;
            zipFileZip = zipFile.file;

            zipFileContent = zipFileZip.generate({type: "base64"});
            zip.file(zipFileName, zipFileContent, {base64: true});
          }
          $scope.packages.zipFiles.push({name: 'all.zip', file: zip, template: null});
        })
        .error(function(error) {
          alert(error);
        });

    // Download zip file
    $scope.download = function(zipFile) {
      var zipFileName = zipFile.name;
      var zipFileZip = zipFile.file;

      var content = zipFileZip.generate({type: "blob"});
      Download.downloadFile(zipFileName, content);
    };
  }
]);

<commit_msg>Fix Bug<commit_after>'use strict';

// Create Download Packages controller
angular.module('packages').controller('CreateDownloadPackagesController', ['$scope', '$stateParams', '$location', 'Authentication', '$state', 'Download', '$http', '$window', 'Packages',
  function ($scope, $stateParams, $location, Authentication, $state, Download, $http, $window, Packages) {
    $scope.authentication = Authentication;

    // Merge all the feature
    var mergePackages = function(pages) {
      var page, zipFile, zip;
      var zipFileName, zipFileZip, zipFileTemplate, zipFileContent;
      var i, j, k;

      // 1. Get all version in each package & each feature
      var inputmethodVersions = [];
      for (i=0;i<pages.length;i++) {
        page = pages[i];

        for (j=0;j<page.zipFiles.length;j++) {
          zipFile = page.zipFiles[j];

          inputmethodVersions.push(zipFile.template.start);
          inputmethodVersions.push(zipFile.template.end);
        }
      }

      // 2. Unique
      var uniqueInputmethodVersions = [];
      window.$.each(inputmethodVersions, function(i, el){
        if(window.$.inArray(el, uniqueInputmethodVersions) === -1) uniqueInputmethodVersions.push(el);
      });

      // 3. Sort
      uniqueInputmethodVersions.sort();
      var emptyVersions = uniqueInputmethodVersions.splice(0,1);
      var emptyVersion = emptyVersions[0];
      uniqueInputmethodVersions.push(emptyVersion);

      // 4. Create version duration
      var inputmethodVersionDurations = [];
      for (i=0+1;i<uniqueInputmethodVersions.length;i++) {
        var version = uniqueInputmethodVersions[i];

        inputmethodVersionDurations.push({ start:uniqueInputmethodVersions[i-1], end:uniqueInputmethodVersions[i] });
      }
      // 5. For each duration, merge each feature zip
      var allzips = [];
      for (i=0;i<inputmethodVersionDurations.length;i++) {
        var versionDuration = inputmethodVersionDurations[i];

        var allZipFileZip = new $window.JSZip();
        var allZipFileName = versionDuration.start + "~" + versionDuration.end + "." + "zip";
        var allZipFileTemplate = versionDuration;

        for (j=0;j<pages.length;j++) {
          page = pages[j];

          for (k=0;k<page.zipFiles.length;k++) {
            zipFile = page.zipFiles[k];

            zipFileZip = zipFile.file;
            zipFileTemplate = zipFile.template;

            // Add the feature zip
            if (Packages.versionContain(zipFileTemplate,versionDuration)==Packages.VersionContainResult.Contain) {
              zipFileContent = zipFileZip.generate({type: "base64"});
              allZipFileZip.load(zipFileContent, {base64: true});
            }
          }
        }

        allzips.push({name: allZipFileName, file: allZipFileZip, template: allZipFileTemplate});
      }

      return allzips;
    };

    // Merge all the feature
    $scope.packages.zipFiles = mergePackages($scope.packages.feature.selectPages);

    // Create config.plist
    var plistTemplateFilePath = "modules/packages/client/template/com.baidu.inputmethod.resource.config.plist";
    var plistFileName = "com.baidu.inputmethod.resource.config.plist";
    // 1. get plist template
    $http.get(plistTemplateFilePath)
        .success(function(response) {
          var page, zipFile, zip;
          var zipFileName, zipFileZip, zipFileTemplate, zipFileContent;
          var i, j;
          var plistTemplate = response;

          // template -> plist
          var data = $scope.packages.info;
          var plist = $window.microtemplate(plistTemplate,data);

          // Feature
          for (i=0;i<$scope.packages.feature.selectPages.length;i++) {
            page = $scope.packages.feature.selectPages[i];

            // Feature:1. put plist into zips
            for (j=0;j<page.zipFiles.length;j++) {
              zipFile = page.zipFiles[j];

              zipFile.file.file(plistFileName, plist);
            }

            // Feature:2. Create all.zip
            zip = new $window.JSZip();
            for(j=0;j<page.zipFiles.length;j++) {
              zipFile = page.zipFiles[j];

              zipFileName = zipFile.name;
              zipFileZip = zipFile.file;

              zipFileContent = zipFileZip.generate({type: "base64"});
              zip.file(zipFileName, zipFileContent, {base64: true});
            }
            page.zipFiles.push({name: 'all.zip', file: zip, template: null});
          }

          // All:1. put plist into zips
          for (i=0;i<$scope.packages.zipFiles.length;i++) {
            zipFile = $scope.packages.zipFiles[i];

            zipFile.file.file(plistFileName, plist);
          }

          // All:2. Create all.zip
          zip = new $window.JSZip();
          for(i=0;i<$scope.packages.zipFiles.length;i++) {
            zipFile = $scope.packages.zipFiles[i];

            zipFileName = zipFile.name;
            zipFileZip = zipFile.file;

            zipFileContent = zipFileZip.generate({type: "base64"});
            zip.file(zipFileName, zipFileContent, {base64: true});
          }
          $scope.packages.zipFiles.push({name: 'all.zip', file: zip, template: null});
        })
        .error(function(error) {
          alert(error);
        });

    // Download zip file
    $scope.download = function(zipFile) {
      var zipFileName = zipFile.name;
      var zipFileZip = zipFile.file;

      var content = zipFileZip.generate({type: "blob"});
      Download.downloadFile(zipFileName, content);
    };
  }
]);

<|endoftext|>


<commit_before>import Ember from 'ember'
import asserts from 'ember-frost-navigation/utils/asserts'

export default Ember.Service.extend({
  routing: Ember.inject.service('-routing'),
  _modalBound: false,
  _registerMap: {
    category (config) {
      return this._registerCategory(config)
    },
    app (config) {
      return this._registerApp(config)
    }
  },
  register (config) {
    return new Ember.RSVP.Promise((resolve, reject) => {
      this._registerMap[config.navType].call(this, config)
        .then(resolve)
        .catch(reject)
    })
  },
  _registerCategory (config = {}) {
    return new Ember.RSVP.Promise((resolve, reject) => {
      try {
        Ember.assert(asserts.categoryName, config.name)
      } catch (e) {
        reject(e)
      }
      this.categories.push({
        name: config.name,
        columns: config.columns || []
      })
      if (config.as) {
        this._registerApp({
          categoryName: config.name,
          columnTitle: config.columnTitle,
          name: config.as,
          icon: config.icon,
          color: config.color,
          description: config.description,
          route: config.as
        }).then(resolve).catch(reject)
      } else {
        resolve(this)
      }
    })
  },
  _registerApp (config = {}) {
    return new Ember.RSVP.Promise((resolve, reject) => {
      try {
        let _category = this.categories.find(e => e.name === config.categoryName)
        Ember.assert(asserts.categoryNotFound, _category)
        let section = null;
        _category.columns.forEach(function (row) {
          section = row.find(e => e.title === config.columnTitle)
        })
        if (!section) {
          _category.columns.push([section = {
            title: config.columnTitle,
            color: config.color,
            routes: []
          }])
        }
        section.routes.push({
          icon: config.icon,
          name: config.name,
          description: config.description,
          route: config.route
        })
      } catch (e) {
        reject(e)
      }
      resolve(this)
    })
  },
  transitionTo (route) {
    this.get('routing').transitionTo(route)
  },
  _activeCategory: null,
  categories: Ember.A()
})
<commit_msg>activeCategory null on transitionTo<commit_after>import Ember from 'ember'
import asserts from 'ember-frost-navigation/utils/asserts'

export default Ember.Service.extend({
  routing: Ember.inject.service('-routing'),
  _modalBound: false,
  _registerMap: {
    category (config) {
      return this._registerCategory(config)
    },
    app (config) {
      return this._registerApp(config)
    }
  },
  register (config) {
    return new Ember.RSVP.Promise((resolve, reject) => {
      this._registerMap[config.navType].call(this, config)
        .then(resolve)
        .catch(reject)
    })
  },
  _registerCategory (config = {}) {
    return new Ember.RSVP.Promise((resolve, reject) => {
      try {
        Ember.assert(asserts.categoryName, config.name)
      } catch (e) {
        reject(e)
      }
      this.categories.push({
        name: config.name,
        columns: config.columns || []
      })
      if (config.as) {
        this._registerApp({
          categoryName: config.name,
          columnTitle: config.columnTitle,
          name: config.as,
          icon: config.icon,
          color: config.color,
          description: config.description,
          route: config.as
        }).then(resolve).catch(reject)
      } else {
        resolve(this)
      }
    })
  },
  _registerApp (config = {}) {
    return new Ember.RSVP.Promise((resolve, reject) => {
      try {
        let _category = this.categories.find(e => e.name === config.categoryName)
        Ember.assert(asserts.categoryNotFound, _category)
        let section = null;
        _category.columns.forEach(function (row) {
          section = row.find(e => e.title === config.columnTitle)
        })
        if (!section) {
          _category.columns.push([section = {
            title: config.columnTitle,
            color: config.color,
            routes: []
          }])
        }
        section.routes.push({
          icon: config.icon,
          name: config.name,
          description: config.description,
          route: config.route
        })
      } catch (e) {
        reject(e)
      }
      resolve(this)
    })
  },
  transitionTo (route) {
    this.get('routing').transitionTo(route)
    this.set('_activeCategory', null)
  },
  _activeCategory: null,
  categories: Ember.A()
})
<|endoftext|>


<commit_before>(function (Backbone, _, $, undefined) {
"use strict";

Backbone.$ = $;

window.Daybed = window.Daybed || {};

//
// SETTINGS : global config.
//
Daybed.SETTINGS = {
    SERVER: "http://localhost:8000"
};

//
//  Item : a record
//
Daybed.Item = Backbone.Model.extend({
    urlRoot: function () {
        return Daybed.SETTINGS.SERVER +
               '/data/' + this.definition.id;
    },

    /**
     * Fields values
     */
    fieldsValues: function () {
        var columns = this.definition.fieldsNames(),
            fields = _.pick.apply(_, ([this.attributes]).concat(columns));
        return _.values(fields);
    }
});

//
// ItemList : Collection of Item
//
Daybed.ItemList = Backbone.Collection.extend({
    model: Daybed.Item,

    initialize: function (definition) {
        this.definition = definition;
    },

    url: function () {
        return Daybed.SETTINGS.SERVER +
               '/data/' + this.definition.id;
    },

    parse: function (response) {
        return response.data;
    },

    /**
     * Fetch only once Definition is ready.
     */
    fetch: function () {
        var args = Array.prototype.slice.call(arguments);
        this.definition.whenReady((function () {
            Backbone.Collection.prototype.fetch.apply(this, args);
        }).bind(this));
    },

    /**
     * Override instanciation to link with Definition instance.
     */
    _prepareModel: function () {
        var m = Backbone.Collection.prototype._prepareModel.apply(this, arguments);
        m.definition = this.definition;
        return m;
    }
});

//
//  Definition : a model
//
Daybed.Definition = Backbone.Model.extend({
    /**
     * Backbone.forms schema for Definition forms
     */
    schema: {
        id:  { type: 'Hidden', title: '' },
        title: 'Text',
        description: 'Text',
        fields: { type: 'List', itemType: 'Object', subSchema: {
            name: { validators: ['required'] },
            description: 'Text',
            required: { type: 'Checkbox', editorAttrs: { 'checked' : 'checked' } },
            type: { type: 'Select', options: ['int', 'string', 'decimal', 'boolean',
                                              'email', 'url', 'point', 'line', 'polygon'] }
        }}
    },

    /**
     * Meta-types are fake types. Daybed does not know them.
     */
    metaTypes: {
        'text': 'string'
    },

    initialize: function () {
        // Add meta types to schema choice list
        var choices = this.schema.fields.subSchema.type.options;
        for (var metatype in this.metaTypes) {
            if (!_.contains(choices, metatype))
                choices.push(metatype);
        }
    },

    save: function () {
        // Substitute meta types by daybed types
        $(this.attributes.fields).each((function (i, field) {
            var meta = this.metaTypes[field.type];
            if (meta) {
                field.meta = field.type;
                field.type = meta;
            }
        }).bind(this));
        Backbone.Model.prototype.save.apply(this, arguments);
    },

    url: function () {
        return Daybed.SETTINGS.SERVER +
               '/definitions/' + this.id;
    },

    /**
     * @returns {boolean} True if *Definition* is initialized (fetched from server)
     */
    isReady: function () {
        return this.attributes.fields && this.attributes.fields.length > 0;
    },

    /**
     * Calls ``cb`` when *Definition* was fetched from server.
     * @param {function} cb
     */
    whenReady: function (cb) {
        if (this.isReady())
            cb();
        else {
            this.once('change', function () {
                this.whenReady(cb);
            }, this);
        }
    },

    /**
     * Fields names
     */
    fieldsNames: function () {
        return _.pluck(this.attributes.fields, 'name');
    },

    /**
     * Builds a Backbone.forms schema from the *Definition* record,
     * for {Item} forms.
     * For each model field, add a Backbone.forms declaration.
     * @returns {Object}
     */
    itemSchema: function () {
        if (!this.isReady())
            throw "Definition is not ready. Fetch it first.";
        var typeMapping = {
            'int': 'Number',
            'string': 'Text',
            'boolean': 'Checkbox'
        };
        var fieldMapping = {
            'default': function (f) {
                var d = {help: f.description},
                    t = typeMapping[f.type];
                if (t) d.type = t;
                return d;
            },
            'text': function () {
                return { type: 'TextArea' };
            },
            'decimal': function (f) {
                var d = fieldMapping['default'](f);
                d.editorAttrs = {pattern: '[-+]?[0-9]*\\.?[0-9]+'};
                return d;
            },
            'email': function (f) {
                var d = fieldMapping['default'](f);
                d.validators = ['required', 'email'];
                return d;
            },
            'url': function (f) {
                var d = fieldMapping['default'](f);
                d.validators = ['required', 'url'];
                return d;
            }
        };
        var schema = {};
        // Backbone.Forms fields from this Daybed definition
        $(this.attributes.fields).each(function (i, field) {
            var build = fieldMapping[field.meta || field.type];
            schema[field.name] = (build ?
                                  build(field) : fieldMapping['default'](field));
        });
        return schema;
    }
});

//
// FormView : Generic Backbone form
//
Daybed.FormView = Backbone.View.extend({
    model: Daybed.Item,
    tagName: "div",
    className: "well",

    template: Mustache.compile('
{{ l.title }}
' +
                               '

' +
                               '{{#l.cancel}}{{ l.cancel }} {{/l.cancel}}' +
                               '{{ l.save }}'),
    templateError: Mustache.compile('{{ msg }}'),

    events: {
        "click .submit": "submit",
        "click .cancel": "cancel"
    },

    initialize: function () {
        this.definition = this.options.definition || this.options.instance.definition;
        this.definition.whenReady(this.setup.bind(this));
    },

    setup: function (instance) {
        // Stop watching previous bound instance if any.
        if (this.instance) {
            this.instance.off('change', this.success);
            this.instance.off('sync', this.success);
            this.instance.off('error', this.error);
        }

        // Bind new instance to this form
        this.instance = instance || this.options.instance || new this.model({});
        this.instance.definition = this.instance.definition || this.definition;
        this.instance.schema = this.instance.schema || this.definition.itemSchema();

        this.instance.on('change', this.refresh, this);
        this.instance.on('sync', this.success, this);
        this.instance.on('error', this.error, this);

        this.creation = this.instance.attributes.id === undefined;
        this.validateOnly = !!this.options.validateOnly;

        // Underlying backbone-forms object
        this.form = new Backbone.Form({
            model: this.instance
        });

        this.refresh();

        // UI Labels...
        this.l = {};
        this.l.title = this.options.title ||
                       (this.creation ? "Create " : "Edit ") + this.definition.attributes.title.toLowerCase();
        this.l.cancel = 'cancel' in this.options ? this.options.cancel : "Cancel";
        this.l.save = this.options.save || (this.creation ? "Create" : "Save");
    },

    render: function () {
        this.$el.html(this.template(this));
        this.$('.form').html(this.form.render().el);
        this.delegateEvents();
        return this;
    },

    cancel: function (e) {
        if (e) e.preventDefault();
        this.trigger('cancel');
        this.reset();
        return false;
    },

    reset: function () {
        this.$('form')[0].reset();
    },

    submit: function(e) {
        if (e) e.preventDefault();
        // Serialize form fields
        var data = this.form.getValue();
        this.trigger('submit', data);
        this.save();
        return false;
    },

    save: function () {
        // Hide previous validation errors (if any)
        this.$('.field-error').remove();
        // Store form data into instance, and save it
        this.form.commit();
        // Submit form (POST/PUT)
        var headers = {};
        // Header validate only tells Daybed not to store
        if (this.validateOnly)
            headers['X-Daybed-Validate-Only'] = 'true';
        this.instance.save({}, {headers: headers});
    },

    success: function (model, response, options) {
        this.trigger((this.creation ? 'created' :
                      this.validateOnly ? 'validated' :
                      'saved'), arguments);
        return false;
    },

    error: function (model, response, options) {
        var descriptions = [];
        try {
            descriptions = JSON.parse(response.responseText);
            this.showErrors(descriptions);
        }
        catch (e) {
            this.$el.html(this.templateError({msg: response.responseText}));
        }
        this.trigger('error', {model: model,
                               errors: descriptions});
        return false;
    },

    /**
     * Show each error along its field
     */
    showErrors: function (descriptions) {
        $(descriptions.errors).each((function (i, e) {
            var name = e.name.split('.')[0];
            this.$("[name='" + name + "']")
                .after(this.templateError({msg: e.description}));
        }).bind(this));
    },

    /**
     * Refresh field values from instance attributes.
     */
    refresh: function () {
        for (var f in this.instance.changed) {
            if (f == 'id') continue;
            var formfield = this.$("[name='"+ f + "']");
            if (formfield.length === 0)
                console.warn("Could not find form field '" + f + "'");
            formfield.val(this.instance.get(f));
        }
    }
});

/**
 * Form rendering helper
 */
Daybed.renderForm = function (selector, options) {
    var definition = new Daybed.Definition(options),
        formView = new Daybed.FormView({definition: definition});

    definition.whenReady(function () {
        $(selector).html(formView.render().el);
    });

    definition.fetch();
    return formView;
};

//
// TableRowView : a single row for TableView
//
Daybed.TableRowView = Backbone.View.extend({
    tagName: 'tr',

    template: Mustache.compile('{{#fieldsValues}}{{.}}	{{/fieldsValues}}' +
                               'Edit ' +
                               '    x	'),

    events: {
        'click .edit': 'edit',
        'click .close': 'destroy'
    },

    initialize: function () {
        this.model.on('change', this.render, this);
        this.model.on('destroy', this.remove, this);
    },

    render: function (){
        this.$el.html(this.template(this.model));
        return this;
    },

    destroy: function (){
        this.model.destroy();
    },

    edit: function () {
        this.trigger('edit', this.model, this);
    }
});

//
// TableView : a generic list view for ItemList collections.
//
Daybed.TableView = Backbone.View.extend({
    tagName: 'table',
    className: 'table',
    rowView: Daybed.TableRowView,

    template: Mustache.compile('
' +
                               '{{#fields}}' +
                               '  {{name}}	' +
                               '{{/fields}}Actions	' +
                               '

'),

    initialize: function () {
        this.collection.on('add', this.addOne, this);
        this.collection.on('reset', this.addAll, this);
    },

    render: function () {
        this.$el.html(this.template(this.collection.definition.attributes));
        return this;
    },

    addOne: function (record) {
        var view = new this.rowView({model: record});
        view.on('edit', this.edit, this);
        this.$('tbody').prepend(view.render().el);
    },

    addAll: function () {
        this.collection.each(this.addOne, this);
    },

    edit: function (record, row) {
        this.trigger('edit', record, row);
    }
});

})(Backbone,  _, jQuery);
<commit_msg>Prevent default on edit/destroy and add confirmation dialog<commit_after>(function (Backbone, _, $, undefined) {
"use strict";

Backbone.$ = $;

window.Daybed = window.Daybed || {};

//
// SETTINGS : global config.
//
Daybed.SETTINGS = {
    SERVER: "http://localhost:8000"
};

//
//  Item : a record
//
Daybed.Item = Backbone.Model.extend({
    urlRoot: function () {
        return Daybed.SETTINGS.SERVER +
               '/data/' + this.definition.id;
    },

    /**
     * Fields values
     */
    fieldsValues: function () {
        var columns = this.definition.fieldsNames(),
            fields = _.pick.apply(_, ([this.attributes]).concat(columns));
        return _.values(fields);
    }
});

//
// ItemList : Collection of Item
//
Daybed.ItemList = Backbone.Collection.extend({
    model: Daybed.Item,

    initialize: function (definition) {
        this.definition = definition;
    },

    url: function () {
        return Daybed.SETTINGS.SERVER +
               '/data/' + this.definition.id;
    },

    parse: function (response) {
        return response.data;
    },

    /**
     * Fetch only once Definition is ready.
     */
    fetch: function () {
        var args = Array.prototype.slice.call(arguments);
        this.definition.whenReady((function () {
            Backbone.Collection.prototype.fetch.apply(this, args);
        }).bind(this));
    },

    /**
     * Override instanciation to link with Definition instance.
     */
    _prepareModel: function () {
        var m = Backbone.Collection.prototype._prepareModel.apply(this, arguments);
        m.definition = this.definition;
        return m;
    }
});

//
//  Definition : a model
//
Daybed.Definition = Backbone.Model.extend({
    /**
     * Backbone.forms schema for Definition forms
     */
    schema: {
        id:  { type: 'Hidden', title: '' },
        title: 'Text',
        description: 'Text',
        fields: { type: 'List', itemType: 'Object', subSchema: {
            name: { validators: ['required'] },
            description: 'Text',
            required: { type: 'Checkbox', editorAttrs: { 'checked' : 'checked' } },
            type: { type: 'Select', options: ['int', 'string', 'decimal', 'boolean',
                                              'email', 'url', 'point', 'line', 'polygon'] }
        }}
    },

    /**
     * Meta-types are fake types. Daybed does not know them.
     */
    metaTypes: {
        'text': 'string'
    },

    initialize: function () {
        // Add meta types to schema choice list
        var choices = this.schema.fields.subSchema.type.options;
        for (var metatype in this.metaTypes) {
            if (!_.contains(choices, metatype))
                choices.push(metatype);
        }
    },

    save: function () {
        // Substitute meta types by daybed types
        $(this.attributes.fields).each((function (i, field) {
            var meta = this.metaTypes[field.type];
            if (meta) {
                field.meta = field.type;
                field.type = meta;
            }
        }).bind(this));
        Backbone.Model.prototype.save.apply(this, arguments);
    },

    url: function () {
        return Daybed.SETTINGS.SERVER +
               '/definitions/' + this.id;
    },

    /**
     * @returns {boolean} True if *Definition* is initialized (fetched from server)
     */
    isReady: function () {
        return this.attributes.fields && this.attributes.fields.length > 0;
    },

    /**
     * Calls ``cb`` when *Definition* was fetched from server.
     * @param {function} cb
     */
    whenReady: function (cb) {
        if (this.isReady())
            cb();
        else {
            this.once('change', function () {
                this.whenReady(cb);
            }, this);
        }
    },

    /**
     * Fields names
     */
    fieldsNames: function () {
        return _.pluck(this.attributes.fields, 'name');
    },

    /**
     * Builds a Backbone.forms schema from the *Definition* record,
     * for {Item} forms.
     * For each model field, add a Backbone.forms declaration.
     * @returns {Object}
     */
    itemSchema: function () {
        if (!this.isReady())
            throw "Definition is not ready. Fetch it first.";
        var typeMapping = {
            'int': 'Number',
            'string': 'Text',
            'boolean': 'Checkbox'
        };
        var fieldMapping = {
            'default': function (f) {
                var d = {help: f.description},
                    t = typeMapping[f.type];
                if (t) d.type = t;
                return d;
            },
            'text': function () {
                return { type: 'TextArea' };
            },
            'decimal': function (f) {
                var d = fieldMapping['default'](f);
                d.editorAttrs = {pattern: '[-+]?[0-9]*\\.?[0-9]+'};
                return d;
            },
            'email': function (f) {
                var d = fieldMapping['default'](f);
                d.validators = ['required', 'email'];
                return d;
            },
            'url': function (f) {
                var d = fieldMapping['default'](f);
                d.validators = ['required', 'url'];
                return d;
            }
        };
        var schema = {};
        // Backbone.Forms fields from this Daybed definition
        $(this.attributes.fields).each(function (i, field) {
            var build = fieldMapping[field.meta || field.type];
            schema[field.name] = (build ?
                                  build(field) : fieldMapping['default'](field));
        });
        return schema;
    }
});

//
// FormView : Generic Backbone form
//
Daybed.FormView = Backbone.View.extend({
    model: Daybed.Item,
    tagName: "div",
    className: "well",

    template: Mustache.compile('
{{ l.title }}
' +
                               '

' +
                               '{{#l.cancel}}{{ l.cancel }} {{/l.cancel}}' +
                               '{{ l.save }}'),
    templateError: Mustache.compile('{{ msg }}'),

    events: {
        "click .submit": "submit",
        "click .cancel": "cancel"
    },

    initialize: function () {
        this.definition = this.options.definition || this.options.instance.definition;
        this.definition.whenReady(this.setup.bind(this));
    },

    setup: function (instance) {
        // Stop watching previous bound instance if any.
        if (this.instance) {
            this.instance.off('change', this.success);
            this.instance.off('sync', this.success);
            this.instance.off('error', this.error);
        }

        // Bind new instance to this form
        this.instance = instance || this.options.instance || new this.model({});
        this.instance.definition = this.instance.definition || this.definition;
        this.instance.schema = this.instance.schema || this.definition.itemSchema();

        this.instance.on('change', this.refresh, this);
        this.instance.on('sync', this.success, this);
        this.instance.on('error', this.error, this);

        this.creation = this.instance.attributes.id === undefined;
        this.validateOnly = !!this.options.validateOnly;

        // Underlying backbone-forms object
        this.form = new Backbone.Form({
            model: this.instance
        });

        this.refresh();

        // UI Labels...
        this.l = {};
        this.l.title = this.options.title ||
                       (this.creation ? "Create " : "Edit ") + this.definition.attributes.title.toLowerCase();
        this.l.cancel = 'cancel' in this.options ? this.options.cancel : "Cancel";
        this.l.save = this.options.save || (this.creation ? "Create" : "Save");
    },

    render: function () {
        this.$el.html(this.template(this));
        this.$('.form').html(this.form.render().el);
        this.delegateEvents();
        return this;
    },

    cancel: function (e) {
        if (e) e.preventDefault();
        this.trigger('cancel');
        this.reset();
        return false;
    },

    reset: function () {
        this.$('form')[0].reset();
    },

    submit: function(e) {
        if (e) e.preventDefault();
        // Serialize form fields
        var data = this.form.getValue();
        this.trigger('submit', data);
        this.save();
        return false;
    },

    save: function () {
        // Hide previous validation errors (if any)
        this.$('.field-error').remove();
        // Store form data into instance, and save it
        this.form.commit();
        // Submit form (POST/PUT)
        var headers = {};
        // Header validate only tells Daybed not to store
        if (this.validateOnly)
            headers['X-Daybed-Validate-Only'] = 'true';
        this.instance.save({}, {headers: headers});
    },

    success: function (model, response, options) {
        this.trigger((this.creation ? 'created' :
                      this.validateOnly ? 'validated' :
                      'saved'), arguments);
        return false;
    },

    error: function (model, response, options) {
        var descriptions = [];
        try {
            descriptions = JSON.parse(response.responseText);
            this.showErrors(descriptions);
        }
        catch (e) {
            this.$el.html(this.templateError({msg: response.responseText}));
        }
        this.trigger('error', {model: model,
                               errors: descriptions});
        return false;
    },

    /**
     * Show each error along its field
     */
    showErrors: function (descriptions) {
        $(descriptions.errors).each((function (i, e) {
            var name = e.name.split('.')[0];
            this.$("[name='" + name + "']")
                .after(this.templateError({msg: e.description}));
        }).bind(this));
    },

    /**
     * Refresh field values from instance attributes.
     */
    refresh: function () {
        for (var f in this.instance.changed) {
            if (f == 'id') continue;
            var formfield = this.$("[name='"+ f + "']");
            if (formfield.length === 0)
                console.warn("Could not find form field '" + f + "'");
            formfield.val(this.instance.get(f));
        }
    }
});

/**
 * Form rendering helper
 */
Daybed.renderForm = function (selector, options) {
    var definition = new Daybed.Definition(options),
        formView = new Daybed.FormView({definition: definition});

    definition.whenReady(function () {
        $(selector).html(formView.render().el);
    });

    definition.fetch();
    return formView;
};

//
// TableRowView : a single row for TableView
//
Daybed.TableRowView = Backbone.View.extend({
    tagName: 'tr',

    template: Mustache.compile('{{#fieldsValues}}{{.}}	{{/fieldsValues}}' +
                               'Edit ' +
                               '    x	'),

    events: {
        'click .edit': 'edit',
        'click .close': 'destroy'
    },

    initialize: function () {
        this.model.on('change', this.render, this);
        this.model.on('destroy', this.remove, this);
    },

    render: function (){
        this.$el.html(this.template(this.model));
        return this;
    },

    destroy: function (e) {
        e.preventDefault();
        if (confirm("Are you sure ?") === true) {
            this.model.destroy();
        }
    },

    edit: function (e) {
        e.preventDefault();
        this.trigger('edit', this.model, this);
    }
});

//
// TableView : a generic list view for ItemList collections.
//
Daybed.TableView = Backbone.View.extend({
    tagName: 'table',
    className: 'table',
    rowView: Daybed.TableRowView,

    template: Mustache.compile('
' +
                               '{{#fields}}' +
                               '  {{name}}	' +
                               '{{/fields}}Actions	' +
                               '

'),

    initialize: function () {
        this.collection.on('add', this.addOne, this);
        this.collection.on('reset', this.addAll, this);
    },

    render: function () {
        this.$el.html(this.template(this.collection.definition.attributes));
        return this;
    },

    addOne: function (record) {
        var view = new this.rowView({model: record});
        view.on('edit', this.edit, this);
        this.$('tbody').prepend(view.render().el);
    },

    addAll: function () {
        this.collection.each(this.addOne, this);
    },

    edit: function (record, row) {
        this.trigger('edit', record, row);
    }
});

})(Backbone,  _, jQuery);
<|endoftext|>


<commit_before>/*---------------------------------------------------------
 * OpenERP base library
 *---------------------------------------------------------*/

openerp.base.views = function(openerp) {

openerp.base.ActionManager = openerp.base.Controller.extend({
// process all kind of actions
    init: function(session, element_id) {
        this._super(session, element_id);
        this.viewmanager = null;
    },
    /**
     * Process an action
     * Supported actions: act_window
     */
    do_action: function(action) {
        // instantiate the right controllers by understanding the action
        if(action.type == "ir.actions.act_window") {
            if (this.viewmanager) {
                this.viewmanager.stop();
            }
            this.viewmanager = new openerp.base.ViewManager(this.session,this.element_id, false);
            this.viewmanager.do_action_window(action);
            this.viewmanager.start();
        }
    }
});

/**
 * Registry for all the main views
 */
openerp.base.views = new openerp.base.Registry();

openerp.base.ViewManager =  openerp.base.Controller.extend({
    init: function(session, element_id, desactivate_sidebar) {
        this._super(session, element_id);
        this.action = null;
        this.dataset = null;
        this.searchview = null;
        this.active_view = null;
        this.views = {};
        if (desactivate_sidebar)
            this.sidebar = null;
        else
            this.sidebar = new openerp.base.Sidebar(null, this);
    },
    start: function() {
        if (this.sidebar) {
            this.$element.find('.view-manager-main-sidebar').html(this.sidebar.render());
            this.sidebar.start();
        }
    },
    stop: function() {
        // should be replaced by automatic destruction implemented in BaseWidget
        if (this.sidebar) {
            this.sidebar.stop();
        }
        this._super();
    },
    /**
     * Asks the view manager to switch visualization mode.
     *
     * @param {String} view_type type of view to display
     * @returns {jQuery.Deferred} new view loading promise
     */
    on_mode_switch: function(view_type) {
        var view_promise;
        this.active_view = view_type;
        var view = this.views[view_type];
        if (!view.controller) {
            // Lazy loading of views
            var controller = new (openerp.base.views.get_object(view_type))(
                this, this.session, this.element_id + "_view_" + view_type, this.dataset, view.view_id);
            view_promise = controller.start();
            this.views[view_type].controller = controller;
        }

        if (view.controller.searchable === false) {
            this.searchview.hide();
        } else {
            this.searchview.show();
        }

        this.$element
            .find('.views-switchers button').removeAttr('disabled')
            .filter('[data-view-type="' + view_type + '"]')
            .attr('disabled', true);

        for (var i in this.views) {
            if (this.views[i].controller) {
                if (i === view_type) {
                    this.views[i].controller.do_show();
                } else {
                    this.views[i].controller.do_hide();
                }
            }
        }
        return view_promise;
    },
    /**
     * Extract search view defaults from the current action's context.
     *
     * These defaults are of the form {search_default_*: value}
     *
     * @returns {Object} a clean defaults mapping of {field_name: value}
     */
    search_defaults: function () {
        var defaults = {};
        _.each(this.action.context, function (value, key) {
            var match = /^search_default_(.*)$/.exec(key);
            if (match) {
                defaults[match[1]] = value;
            }
        });
        return defaults;
    },
    /**
     * Sets up the current viewmanager's search view.
     *
     * @param action the action being executed
     * @returns {jQuery.Deferred} search view startup deferred
     */
    setup_search_view:function (action) {
        var self = this;
        if (this.searchview) {
            this.searchview.stop();
        }
        var view_id = action.search_view_id ? action.search_view_id[0] || false : false;

        this.searchview = new openerp.base.SearchView(this, this.session, this.element_id + "_search", this.dataset, view_id, this.search_defaults());
        this.searchview.on_search.add(function() {
            self.views[self.active_view].controller.do_search.apply(self, arguments);
        });
        return this.searchview.start();
    },
    do_action_window: function(action) {
        var self = this;
        this.action = action;
        this.dataset = new openerp.base.DataSet(this.session, action.res_model);
        this.dataset.start();

        this.$element.html(QWeb.render("ViewManager", {"prefix": this.element_id, views: action.views}));

        var searchview_loaded = this.setup_search_view(action);

        this.$element.find('.oe_vm_switch button').click(function() {
            self.on_mode_switch($(this).data('view-type'));
        });
        _.each(action.views, function(view) {
            self.views[view[1]] = { view_id: view[0], controller: null };
        });

        // switch to the first one in sequence
        var inital_view_loaded = this.on_mode_switch(action.views[0][1]);

        if (action['auto_search']) {
            $.when(searchview_loaded, inital_view_loaded)
                .then(this.searchview.do_search);
        }
    },
    // create when root, also add to parent when o2m
    on_create: function() {
    },
    on_remove: function() {
    },
    on_edit: function() {
    },
    /**
     * Called when one of the view want to execute an action
     */
    on_action: function(action) {
    }
});

openerp.base.ViewManagerRoot = openerp.base.ViewManager.extend({
// Extends view manager
});

openerp.base.ViewManagerUsedAsAMany2One = openerp.base.ViewManager.extend({
// Extends view manager
});

openerp.base.BaseWidget = openerp.base.Controller.extend({
    /**
     * The name of the QWeb template that will be used for rendering. Must be redifined
     * in subclasses or the render() method can not be used.
     *
     * @type string
     */
    template: null,
    /**
     * The prefix used to generate an id automatically. Should be redifined in subclasses.
     * If it is not defined, a default identifier will be used.
     *
     * @type string
     */
    identifier_prefix: 'generic-identifier',
    /**
     * Base class for widgets. Handle rendering (based on a QWeb template), identifier
     * generation, parenting and destruction of the widget.
     * Contructor. Also initialize the identifier.
     *
     * @params {openerp.base.search.BaseWidget} parent The parent widget.
     */
    init: function (parent, session) {
        this._super(session);
        this.children = [];
        this.parent = null;
        this.set_parent(parent);
        this.make_id(this.identifier_prefix);
    },
    /**
     * Sets and returns a globally unique identifier for the widget.
     *
     * If a prefix is appended, the identifier will be appended to it.
     *
     * @params sections prefix sections, empty/falsy sections will be removed
     */
    make_id: function () {
        this.element_id = _.uniqueId(_.toArray(arguments).join('_'));
        return this.element_id;
    },
    /**
     * "Starts" the widgets. Called at the end of the rendering, this allows
     * to get a jQuery object referring to the DOM ($element attribute).
     */
    start: function () {
        this._super();
        var tmp = document.getElementById(this.element_id);
        this.$element = tmp ? $(tmp) : null;
    },
    /**
     * "Stops" the widgets. Called when the view destroys itself, this
     * lets the widgets clean up after themselves.
     */
    stop: function () {
        var tmp_children = this.children;
        this.children = [];
        _.each(tmp_children, function(x) {
            x.stop();
        });
        if(this.$element != null) {
            this.$element.remove();
        }
        this.set_parent(null);
        this._super();
    },
    /**
     * Set the parent of this component, also unregister the previous parent if there
     * was one.
     *
     * @param {openerp.base.BaseWidget} parent The new parent.
     */
    set_parent: function(parent) {
        if(this.parent) {
            this.parent.children = _.without(this.parent.children, this);
        }
        this.parent = parent;
        if(this.parent) {
            parent.children.push(this);
        }
    },
    /**
     * Render the widget. This.template must be defined.
     * The content of the current object is passed as context to the template.
     *
     * @param {object} additional Additional context arguments to pass to the template.
     */
    render: function (additional) {
        return QWeb.render(this.template, _.extend({}, this, additional != null ? additional : {}));
    }
});

openerp.base.Sidebar = openerp.base.BaseWidget.extend({
    template: "ViewManager.sidebar",
    init: function(parent, view_manager) {
        this._super(parent, view_manager.session);
        this.view_manager = view_manager;
        this.sections = [];
    },
    load_multi_actions: function() {
        if (_.detect(this.sections, function(x) {return x.type=="multi_actions";}) != undefined)
            return;
        var self = this;
        this.rpc("/base/sidebar/get_actions",
                {"model": this.view_manager.dataset.model}, function(result) {
            self.sections.push({type: "multi_actions", elements:
            _.map(result, function(x) {return {text:x[2].name, action:x}; })});
            self.refresh();
        });
    },
    refresh: function() {
        this.$element.html(QWeb.render("ViewManager.sidebar.internal", this));
        var self = this;
        this.$element.find("a").click(function(e) {
            $this = jQuery(this);
            var i = $this.attr("data-i");
            var j = $this.attr("data-i");
            var action = self.sections[i].elements[j];
            // TODO: do something with the action
            e.stopPropagation();
            e.preventDefault();
        });
    },
    start: function() {
        this._super();
        this.refresh();
    }
});

openerp.base.views.add('calendar', 'openerp.base.CalendarView');

openerp.base.CalendarView = openerp.base.Controller.extend({
    start: function () {
        this._super();
        this.$element.append('Calendar view');
    },
    do_show: function () {
        this.$element.show();
    },
    do_hide: function () {
        this.$element.hide();
    }
});

openerp.base.views.add('gantt', 'openerp.base.GanttView');
openerp.base.GanttView = openerp.base.Controller.extend({
    start: function () {
        this._super();
        this.$element.append('Gantt view');
    },
    do_show: function () {
        this.$element.show();
    },
    do_hide: function () {
        this.$element.hide();
    }
});

openerp.base.views.add('tree', 'openerp.base.TreeView');
openerp.base.TreeView = openerp.base.Controller.extend({
/**
 * Genuine tree view (the one displayed as a tree, not the list)
 */
    start: function () {
        this._super();
        this.$element.append('Tree view');
    },
    do_show: function () {
        this.$element.show();
    },
    do_hide: function () {
        this.$element.hide();
    }
});

openerp.base.views.add('graph', 'openerp.base.GraphView');
openerp.base.GraphView = openerp.base.Controller.extend({
    start: function () {
        this._super();
        this.$element.append('Graph view');
    },
    do_show: function () {
        this.$element.show();
    },
    do_hide: function () {
        this.$element.hide();
    }
});

openerp.base.ProcessView = openerp.base.Controller.extend({
});

openerp.base.HelpView = openerp.base.Controller.extend({
});

};

// vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax:
<commit_msg>[IMP] Implemented theorical handling of sidebar actions.<commit_after>/*---------------------------------------------------------
 * OpenERP base library
 *---------------------------------------------------------*/

openerp.base.views = function(openerp) {

openerp.base.ActionManager = openerp.base.Controller.extend({
// process all kind of actions
    init: function(session, element_id) {
        this._super(session, element_id);
        this.viewmanager = null;
    },
    /**
     * Process an action
     * Supported actions: act_window
     */
    do_action: function(action) {
        // instantiate the right controllers by understanding the action
        if(action.type == "ir.actions.act_window") {
            if (this.viewmanager) {
                this.viewmanager.stop();
            }
            this.viewmanager = new openerp.base.ViewManager(this.session,this.element_id, false);
            this.viewmanager.do_action_window(action);
            this.viewmanager.start();
        }
    }
});

/**
 * Registry for all the main views
 */
openerp.base.views = new openerp.base.Registry();

openerp.base.ViewManager =  openerp.base.Controller.extend({
    init: function(session, element_id, desactivate_sidebar) {
        this._super(session, element_id);
        this.action = null;
        this.dataset = null;
        this.searchview = null;
        this.active_view = null;
        this.views = {};
        if (desactivate_sidebar)
            this.sidebar = null;
        else
            this.sidebar = new openerp.base.Sidebar(null, this);
    },
    start: function() {
        if (this.sidebar) {
            this.$element.find('.view-manager-main-sidebar').html(this.sidebar.render());
            this.sidebar.start();
        }
    },
    stop: function() {
        // should be replaced by automatic destruction implemented in BaseWidget
        if (this.sidebar) {
            this.sidebar.stop();
        }
        this._super();
    },
    /**
     * Asks the view manager to switch visualization mode.
     *
     * @param {String} view_type type of view to display
     * @returns {jQuery.Deferred} new view loading promise
     */
    on_mode_switch: function(view_type) {
        var view_promise;
        this.active_view = view_type;
        var view = this.views[view_type];
        if (!view.controller) {
            // Lazy loading of views
            var controller = new (openerp.base.views.get_object(view_type))(
                this, this.session, this.element_id + "_view_" + view_type, this.dataset, view.view_id);
            view_promise = controller.start();
            this.views[view_type].controller = controller;
        }

        if (view.controller.searchable === false) {
            this.searchview.hide();
        } else {
            this.searchview.show();
        }

        this.$element
            .find('.views-switchers button').removeAttr('disabled')
            .filter('[data-view-type="' + view_type + '"]')
            .attr('disabled', true);

        for (var i in this.views) {
            if (this.views[i].controller) {
                if (i === view_type) {
                    this.views[i].controller.do_show();
                } else {
                    this.views[i].controller.do_hide();
                }
            }
        }
        return view_promise;
    },
    /**
     * Extract search view defaults from the current action's context.
     *
     * These defaults are of the form {search_default_*: value}
     *
     * @returns {Object} a clean defaults mapping of {field_name: value}
     */
    search_defaults: function () {
        var defaults = {};
        _.each(this.action.context, function (value, key) {
            var match = /^search_default_(.*)$/.exec(key);
            if (match) {
                defaults[match[1]] = value;
            }
        });
        return defaults;
    },
    /**
     * Sets up the current viewmanager's search view.
     *
     * @param action the action being executed
     * @returns {jQuery.Deferred} search view startup deferred
     */
    setup_search_view:function (action) {
        var self = this;
        if (this.searchview) {
            this.searchview.stop();
        }
        var view_id = action.search_view_id ? action.search_view_id[0] || false : false;

        this.searchview = new openerp.base.SearchView(this, this.session, this.element_id + "_search", this.dataset, view_id, this.search_defaults());
        this.searchview.on_search.add(function() {
            self.views[self.active_view].controller.do_search.apply(self, arguments);
        });
        return this.searchview.start();
    },
    do_action_window: function(action) {
        var self = this;
        this.action = action;
        this.dataset = new openerp.base.DataSet(this.session, action.res_model);
        this.dataset.start();

        this.$element.html(QWeb.render("ViewManager", {"prefix": this.element_id, views: action.views}));

        var searchview_loaded = this.setup_search_view(action);

        this.$element.find('.oe_vm_switch button').click(function() {
            self.on_mode_switch($(this).data('view-type'));
        });
        _.each(action.views, function(view) {
            self.views[view[1]] = { view_id: view[0], controller: null };
        });

        // switch to the first one in sequence
        var inital_view_loaded = this.on_mode_switch(action.views[0][1]);

        if (action['auto_search']) {
            $.when(searchview_loaded, inital_view_loaded)
                .then(this.searchview.do_search);
        }
    },
    // create when root, also add to parent when o2m
    on_create: function() {
    },
    on_remove: function() {
    },
    on_edit: function() {
    },
    /**
     * Called when one of the view want to execute an action
     */
    on_action: function(action) {
    }
});

openerp.base.ViewManagerRoot = openerp.base.ViewManager.extend({
// Extends view manager
});

openerp.base.ViewManagerUsedAsAMany2One = openerp.base.ViewManager.extend({
// Extends view manager
});

openerp.base.BaseWidget = openerp.base.Controller.extend({
    /**
     * The name of the QWeb template that will be used for rendering. Must be redifined
     * in subclasses or the render() method can not be used.
     *
     * @type string
     */
    template: null,
    /**
     * The prefix used to generate an id automatically. Should be redifined in subclasses.
     * If it is not defined, a default identifier will be used.
     *
     * @type string
     */
    identifier_prefix: 'generic-identifier',
    /**
     * Base class for widgets. Handle rendering (based on a QWeb template), identifier
     * generation, parenting and destruction of the widget.
     * Contructor. Also initialize the identifier.
     *
     * @params {openerp.base.search.BaseWidget} parent The parent widget.
     */
    init: function (parent, session) {
        this._super(session);
        this.children = [];
        this.parent = null;
        this.set_parent(parent);
        this.make_id(this.identifier_prefix);
    },
    /**
     * Sets and returns a globally unique identifier for the widget.
     *
     * If a prefix is appended, the identifier will be appended to it.
     *
     * @params sections prefix sections, empty/falsy sections will be removed
     */
    make_id: function () {
        this.element_id = _.uniqueId(_.toArray(arguments).join('_'));
        return this.element_id;
    },
    /**
     * "Starts" the widgets. Called at the end of the rendering, this allows
     * to get a jQuery object referring to the DOM ($element attribute).
     */
    start: function () {
        this._super();
        var tmp = document.getElementById(this.element_id);
        this.$element = tmp ? $(tmp) : null;
    },
    /**
     * "Stops" the widgets. Called when the view destroys itself, this
     * lets the widgets clean up after themselves.
     */
    stop: function () {
        var tmp_children = this.children;
        this.children = [];
        _.each(tmp_children, function(x) {
            x.stop();
        });
        if(this.$element != null) {
            this.$element.remove();
        }
        this.set_parent(null);
        this._super();
    },
    /**
     * Set the parent of this component, also unregister the previous parent if there
     * was one.
     *
     * @param {openerp.base.BaseWidget} parent The new parent.
     */
    set_parent: function(parent) {
        if(this.parent) {
            this.parent.children = _.without(this.parent.children, this);
        }
        this.parent = parent;
        if(this.parent) {
            parent.children.push(this);
        }
    },
    /**
     * Render the widget. This.template must be defined.
     * The content of the current object is passed as context to the template.
     *
     * @param {object} additional Additional context arguments to pass to the template.
     */
    render: function (additional) {
        return QWeb.render(this.template, _.extend({}, this, additional != null ? additional : {}));
    }
});

openerp.base.Sidebar = openerp.base.BaseWidget.extend({
    template: "ViewManager.sidebar",
    init: function(parent, view_manager) {
        this._super(parent, view_manager.session);
        this.view_manager = view_manager;
        this.sections = [];
    },
    load_multi_actions: function() {
        if (_.detect(this.sections, function(x) {return x.type=="multi_actions";}) != undefined)
            return;
        var self = this;
        this.rpc("/base/sidebar/get_actions",
                {"model": this.view_manager.dataset.model}, function(result) {
            self.sections.push({type: "multi_actions", elements:
            _.map(result, function(x) {return {text:x[2].name, action:x}; })});
            self.refresh();
        });
    },
    refresh: function() {
        this.$element.html(QWeb.render("ViewManager.sidebar.internal", this));
        var self = this;
        this.$element.find("a").click(function(e) {
            $this = jQuery(this);
            var i = $this.attr("data-i");
            var j = $this.attr("data-i");
            var action = self.sections[i].elements[j];
            // I know this doesn't work, one day it will
            new openerp.base.ActionManager(this.view_manager, null).do_action(action);
            e.stopPropagation();
            e.preventDefault();
        });
    },
    start: function() {
        this._super();
        this.refresh();
    }
});

openerp.base.views.add('calendar', 'openerp.base.CalendarView');

openerp.base.CalendarView = openerp.base.Controller.extend({
    start: function () {
        this._super();
        this.$element.append('Calendar view');
    },
    do_show: function () {
        this.$element.show();
    },
    do_hide: function () {
        this.$element.hide();
    }
});

openerp.base.views.add('gantt', 'openerp.base.GanttView');
openerp.base.GanttView = openerp.base.Controller.extend({
    start: function () {
        this._super();
        this.$element.append('Gantt view');
    },
    do_show: function () {
        this.$element.show();
    },
    do_hide: function () {
        this.$element.hide();
    }
});

openerp.base.views.add('tree', 'openerp.base.TreeView');
openerp.base.TreeView = openerp.base.Controller.extend({
/**
 * Genuine tree view (the one displayed as a tree, not the list)
 */
    start: function () {
        this._super();
        this.$element.append('Tree view');
    },
    do_show: function () {
        this.$element.show();
    },
    do_hide: function () {
        this.$element.hide();
    }
});

openerp.base.views.add('graph', 'openerp.base.GraphView');
openerp.base.GraphView = openerp.base.Controller.extend({
    start: function () {
        this._super();
        this.$element.append('Graph view');
    },
    do_show: function () {
        this.$element.show();
    },
    do_hide: function () {
        this.$element.hide();
    }
});

openerp.base.ProcessView = openerp.base.Controller.extend({
});

openerp.base.HelpView = openerp.base.Controller.extend({
});

};

// vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax:
<|endoftext|>