<commit_before>/**
 * handles editability case for lists, because it depends on form and forms already depends on lists it had to be split out
 * @namespace
 */
openerp.web.list_editable = function (openerp) {
    var KEY_RETURN = 13,
        KEY_ESCAPE = 27;
    var QWeb = openerp.web.qweb;

    // editability status of list rows
    openerp.web.ListView.prototype.defaults.editable = null;

    // TODO: not sure second @lends on existing item is correct, to check
    openerp.web.ListView.include(/** @lends openerp.web.ListView# */{
        init: function () {
            var self = this;
            this._super.apply(this, arguments);
            $(this.groups).bind({
                'edit': function (e, id, dataset) {
                    self.do_edit(dataset.index, id, dataset);
                },
                'saved': function () {
                    if (self.groups.get_selection().length) {
                        return;
                    }
                    self.configure_pager(self.dataset);
                    self.compute_aggregates();
                }
            })
        },
        /**
         * Handles the activation of a record in editable mode (making a record
         * editable), called *after* the record has become editable.
         *
         * The default behavior is to setup the listview's dataset to match
         * whatever dataset was provided by the editing List
         *
         * @param {Number} index index of the record in the dataset
         * @param {Object} id identifier of the record being edited
         * @param {openerp.web.DataSet} dataset dataset in which the record is available
         */
        do_edit: function (index, id, dataset) {
            _.extend(this.dataset, dataset);
        },
        /**
         * Sets editability status for the list, based on defaults, view
         * architecture and the provided flag, if any.
         *
         * @param {Boolean} [force] forces the list to editability. Sets new row edition status to "bottom".
         */
        set_editable: function (force) {
            // If ``force``, set editability to bottom
            // otherwise rely on view default
            // view' @editable is handled separately as we have not yet
            // fetched and processed the view at this point.
            this.options.editable = (
                    (force && "bottom")
                    || this.defaults.editable);
        },
        /**
         * Replace do_search to handle editability process
         */
        do_search: function(domain, context, group_by) {
            this.set_editable(context['set_editable']);
            this._super.apply(this, arguments);
        },
        /**
         * Replace do_add_record to handle editability (and adding new record
         * as an editable row at the top or bottom of the list)
         */
        do_add_record: function () {
            if (this.options.editable) {
                this.groups.new_record();
            } else {
                this._super();
            }
        },
        on_loaded: function (data, grouped) {
            // tree/@editable takes priority on everything else if present.
            this.options.editable = data.arch.attrs.editable || this.options.editable;
            return this._super(data, grouped);
        },
        /**
         * Ensures the editable list is saved (saves any pending edition if
         * needed, or tries to)
         *
         * Returns a deferred to the end of the saving.
         *
         * @returns {$.Deferred}
         */
        ensure_saved: function () {
            return this.groups.ensure_saved();
        }
    });

    openerp.web.ListView.Groups.include(/** @lends openerp.web.ListView.Groups# */{
        passtrough_events: openerp.web.ListView.Groups.prototype.passtrough_events + " edit saved",
        new_record: function () {
            // TODO: handle multiple children
            this.children[null].new_record();
        },
        /**
         * Ensures descendant editable List instances are all saved if they have
         * pending editions.
         *
         * @returns {$.Deferred}
         */
        ensure_saved: function () {
            return $.when.apply(null,
                _.invoke(
                    _.values(this.children),
                    'ensure_saved'));
        }
    });

    openerp.web.ListView.List.include(/** @lends openerp.web.ListView.List# */{
        row_clicked: function (event) {
            if (!this.options.editable) {
                return this._super.apply(this, arguments);
            }
            this.edit_record($(event.currentTarget).data('id'));
        },
        /**
         * Checks if a record is being edited, and if so cancels it
         */
        cancel_pending_edition: function () {
            var self = this, cancelled;
            if (!this.edition) {
                return $.when();
            }

            if (this.edition_id) {
                cancelled = this.reload_record(this.records.get(this.edition_id));
            } else {
                cancelled = $.when();
            }
            cancelled.then(function () {
                self.view.unpad_columns();
                self.edition_form.stop();
                self.edition_form.$element.remove();
                delete self.edition_form;
                self.dataset.index = null;
                delete self.edition_id;
                delete self.edition;
            });
            this.pad_table_to(5);
            return cancelled;
        },
        /**
         * Adapts this list's view description to be suitable to the inner form
         * view of a row being edited.
         *
         * @returns {Object} fields_view_get's view section suitable for putting into form view of editable rows.
         */
        get_form_fields_view: function () {
            // deep copy of view
            var view = $.extend(true, {}, this.group.view.fields_view);
            _(view.arch.children).each(function (widget) {
                widget.attrs.nolabel = true;
                if (widget.tag === 'button') {
                    delete widget.attrs.string;
                }
            });
            view.arch.attrs.col = 2 * view.arch.children.length;
            return view;
        },
        on_row_keyup: function (e) {
            var self = this;
            switch (e.which) {
            case KEY_RETURN:
                this.save_row().then(function (result) {
                    if (result.created) {
                        self.new_record();
                        return;
                    }

                    var next_record_id,
                        next_record = self.records.at(
                                self.records.indexOf(result.edited_record) + 1);
                    if (next_record) {
                        next_record_id = next_record.get('id');
                        self.dataset.index = _(self.dataset.ids)
                                .indexOf(next_record_id);
                    } else {
                        self.dataset.index = 0;
                        next_record_id = self.records.at(0).get('id');
                    }
                    self.edit_record(next_record_id);
                });
                break;
            case KEY_ESCAPE:
                this.cancel_edition();
                break;
            }
        },
        render_row_as_form: function (row) {
            var self = this;
            this.ensure_saved().then(function () {
                var record_id = $(row).data('id');
                var $new_row = $('<tr>', {
                        id: _.uniqueId('oe-editable-row-'),
                        'data-id': record_id,
                        'class': (row ? $(row).attr('class') : '') + ' oe_forms',
                        click: function (e) {e.stopPropagation();}
                    })
                    .delegate('button.oe-edit-row-save', 'click', function () {
                        self.save_row();
                    })
                    .delegate('button', 'keyup', function (e) {
                        e.stopImmediatePropagation();
                    })
                    .keyup(function () {
                        return self.on_row_keyup.apply(self, arguments); })
                    .keydown(function (e) { e.stopPropagation(); });
                if (row) {
                    $new_row.replaceAll(row);
                } else if (self.options.editable) {
                    var $last_child = self.$current.children('tr:last');
                    if (self.records.length) {
                        if (self.options.editable === 'top') {
                            $new_row.insertBefore(
                                self.$current.children('[data-id]:first'));
                        } else {
                            $new_row.insertAfter(
                                self.$current.children('[data-id]:last'));
                        }
                    } else {
                        $new_row.prependTo(self.$current);
                    }
                    if ($last_child.is(':not([data-id])')) {
                        $last_child.remove();
                    }
                }
                self.edition = true;
                self.edition_id = record_id;
                self.dataset.index = _(self.dataset.ids).indexOf(record_id) || null;
                if (self.dataset.index === -1) {
                    self.dataset.index = null;
                }
                self.edition_form = _.extend(new openerp.web.ListEditableFormView(self.view, self.dataset, false), {
                    form_template: 'ListView.row.form',
                    registry: openerp.web.list.form.widgets,
                    $element: $new_row
                });
                // HA HA
                self.edition_form.appendTo();
                // put in $.when just in case  FormView.on_loaded becomes asynchronous
                $.when(self.edition_form.on_loaded(self.get_form_fields_view())).then(function () {
                    $new_row.find('> td')
                          .addClass('oe-field-cell')
                          .removeAttr('width')
                      .end()
                      .find('td:last').removeClass('oe-field-cell').end();
                    if (self.options.selectable) {
                        $new_row.prepend('<th>');
                    }
                    if (self.options.isClarkGable) {
                        $new_row.prepend('<th>');
                    }
                    // pad in case of groupby
                    _(self.columns).each(function (column) {
                        if (column.meta) {
                            $new_row.prepend('<td>');
                        }
                    });
                    // Add column for the save, if
                    // there is none in the list
                    if (!self.options.deletable) {
                        self.view.pad_columns(
                            1, {except: $new_row});
                    }

                    self.edition_form.do_show();
                });
            });
        },
        handle_onwrite: function (source_record_id) {
            var self = this;
            var on_write_callback = self.view.fields_view.arch.attrs.on_write;
            if (!on_write_callback) { return; }
            this.dataset.call(on_write_callback, [source_record_id], function (ids) {
                _(ids).each(function (id) {
                    var record = self.records.get(id);
                    if (!record) {
                        // insert after the source record
                        var index = self.records.indexOf(
                            self.records.get(source_record_id)) + 1;
                        record = new openerp.web.list.Record({id: id});
                        self.records.add(record, {at: index});
                        self.dataset.ids.splice(index, 0, id);
                    }
                    self.reload_record(record);
                });
            });
        },
        /**
         * Saves the current row, and returns a Deferred resolving to an object
         * with the following properties:
         *
         * ``created``
         *   Boolean flag indicating whether the record saved was being created
         *   (``true`` or edited (``false``)
         * ``edited_record``
         *   The result of saving the record (either the newly created record,
         *   or the post-edition record), after insertion in the Collection if
         *   needs be.
         *
         * @returns {$.Deferred<{created: Boolean, edited_record: Record}>}
         */
        save_row: function () {
            //noinspection JSPotentiallyInvalidConstructorUsage
            var self = this;
            return this.edition_form
                .do_save(null, this.options.editable === 'top')
                .pipe(function (result) {
                    if (result.created && !self.edition_id) {
                        self.records.add({id: result.result},
                            {at: self.options.editable === 'top' ? 0 : null});
                        self.edition_id = result.result;
                    }
                    var edited_record = self.records.get(self.edition_id);

                    return $.when(
                        self.handle_onwrite(self.edition_id),
                        self.cancel_pending_edition().then(function () {
                            $(self).trigger('saved', [self.dataset]);
                        })).pipe(function () {
                            return {
                                created: result.created || false,
                                edited_record: edited_record
                            };
                        });
                });
        },
        /**
         * If the current list is being edited, ensures it's saved
         */
        ensure_saved: function () {
            if (this.edition) {
                // kinda-hack-ish: if the user has entered data in a field,
                // oe_form_dirty will be set on the form so save, otherwise
                // discard the current (entirely empty) line
                if (this.edition_form.$element.is('.oe_form_dirty')) {
                    return this.save_row();
                }
                return this.cancel_pending_edition();
            }
            //noinspection JSPotentiallyInvalidConstructorUsage
            return $.when();
        },
        /**
         * Cancels the edition of the row for the current dataset index
         */
        cancel_edition: function () {
            this.cancel_pending_edition();
        },
        /**
         * Edits record currently selected via dataset
         */
        edit_record: function (record_id) {
            this.render_row_as_form(
                this.$current.find('[data-id=' + record_id + ']'));
            $(this).trigger(
                'edit',
                [record_id, this.dataset]);
        },
        new_record: function () {
            this.render_row_as_form();
        },
        render_record: function (record) {
            var index = this.records.indexOf(record),
                 self = this;
            // FIXME: context dict should probably be extracted cleanly
            return QWeb.render('ListView.row', {
                columns: this.columns,
                options: this.options,
                record: record,
                row_parity: (index % 2 === 0) ? 'even' : 'odd',
                view: this.view,
                render_cell: function () {
                    return self.render_cell.apply(self, arguments); },
                edited: !!this.edition_form
            });
        }
    });
    if (!openerp.web.list) {
        openerp.web.list = {};
    }
    if (!openerp.web.list.form) {
        openerp.web.list.form = {};
    }
    openerp.web.list.form.WidgetFrame = openerp.web.form.WidgetFrame.extend({
        template: 'ListView.row.frame'
    });
    var form_widgets = openerp.web.form.widgets;
    openerp.web.list.form.widgets = form_widgets.extend({
        'frame': 'openerp.web.list.form.WidgetFrame'
    });
    // All form widgets inherit a problematic behavior from
    // openerp.web.form.WidgetFrame: the cell itself is removed when invisible
    // whether it's @invisible or @attrs[invisible]. In list view, only the
    // former should completely remove the cell. We need to override update_dom
    // on all widgets since we can't just hit on widget itself (I think)
    var list_form_widgets = openerp.web.list.form.widgets;
    _(form_widgets.map).each(function (widget_path, key) {
        if (key === 'frame') { return; }
        var new_path = 'openerp.web.list.form.' + key;

        openerp.web.list.form[key] = (form_widgets.get_object(key)).extend({
            update_dom: function () {
                this.$element.children().css('visibility', '');
                if (this.modifiers.tree_invisible) {
                    var old_invisible = this.invisible;
                    this.invisible = true;
                    this._super.apply(this, arguments);
                    this.invisible = old_invisible;
                } else if (this.invisible) {
                    this.$element.children().css('visibility', 'hidden');
                } else {
                    this._super.apply(this, arguments);
                }
            }
        });
        list_form_widgets.add(key, new_path);
    });

    openerp.web.ListEditableFormView = openerp.web.FormView.extend({
        init_view: function() {},
        _render_and_insert: function () {
            return this.start();
        }
    });
};
<commit_msg>[FIX] don't break the handling of record index 0 in editable list views: index 0 means something different than index = null<commit_after>/**
 * handles editability case for lists, because it depends on form and forms already depends on lists it had to be split out
 * @namespace
 */
openerp.web.list_editable = function (openerp) {
    var KEY_RETURN = 13,
        KEY_ESCAPE = 27;
    var QWeb = openerp.web.qweb;

    // editability status of list rows
    openerp.web.ListView.prototype.defaults.editable = null;

    // TODO: not sure second @lends on existing item is correct, to check
    openerp.web.ListView.include(/** @lends openerp.web.ListView# */{
        init: function () {
            var self = this;
            this._super.apply(this, arguments);
            $(this.groups).bind({
                'edit': function (e, id, dataset) {
                    self.do_edit(dataset.index, id, dataset);
                },
                'saved': function () {
                    if (self.groups.get_selection().length) {
                        return;
                    }
                    self.configure_pager(self.dataset);
                    self.compute_aggregates();
                }
            })
        },
        /**
         * Handles the activation of a record in editable mode (making a record
         * editable), called *after* the record has become editable.
         *
         * The default behavior is to setup the listview's dataset to match
         * whatever dataset was provided by the editing List
         *
         * @param {Number} index index of the record in the dataset
         * @param {Object} id identifier of the record being edited
         * @param {openerp.web.DataSet} dataset dataset in which the record is available
         */
        do_edit: function (index, id, dataset) {
            _.extend(this.dataset, dataset);
        },
        /**
         * Sets editability status for the list, based on defaults, view
         * architecture and the provided flag, if any.
         *
         * @param {Boolean} [force] forces the list to editability. Sets new row edition status to "bottom".
         */
        set_editable: function (force) {
            // If ``force``, set editability to bottom
            // otherwise rely on view default
            // view' @editable is handled separately as we have not yet
            // fetched and processed the view at this point.
            this.options.editable = (
                    (force && "bottom")
                    || this.defaults.editable);
        },
        /**
         * Replace do_search to handle editability process
         */
        do_search: function(domain, context, group_by) {
            this.set_editable(context['set_editable']);
            this._super.apply(this, arguments);
        },
        /**
         * Replace do_add_record to handle editability (and adding new record
         * as an editable row at the top or bottom of the list)
         */
        do_add_record: function () {
            if (this.options.editable) {
                this.groups.new_record();
            } else {
                this._super();
            }
        },
        on_loaded: function (data, grouped) {
            // tree/@editable takes priority on everything else if present.
            this.options.editable = data.arch.attrs.editable || this.options.editable;
            return this._super(data, grouped);
        },
        /**
         * Ensures the editable list is saved (saves any pending edition if
         * needed, or tries to)
         *
         * Returns a deferred to the end of the saving.
         *
         * @returns {$.Deferred}
         */
        ensure_saved: function () {
            return this.groups.ensure_saved();
        }
    });

    openerp.web.ListView.Groups.include(/** @lends openerp.web.ListView.Groups# */{
        passtrough_events: openerp.web.ListView.Groups.prototype.passtrough_events + " edit saved",
        new_record: function () {
            // TODO: handle multiple children
            this.children[null].new_record();
        },
        /**
         * Ensures descendant editable List instances are all saved if they have
         * pending editions.
         *
         * @returns {$.Deferred}
         */
        ensure_saved: function () {
            return $.when.apply(null,
                _.invoke(
                    _.values(this.children),
                    'ensure_saved'));
        }
    });

    openerp.web.ListView.List.include(/** @lends openerp.web.ListView.List# */{
        row_clicked: function (event) {
            if (!this.options.editable) {
                return this._super.apply(this, arguments);
            }
            this.edit_record($(event.currentTarget).data('id'));
        },
        /**
         * Checks if a record is being edited, and if so cancels it
         */
        cancel_pending_edition: function () {
            var self = this, cancelled;
            if (!this.edition) {
                return $.when();
            }

            if (this.edition_id) {
                cancelled = this.reload_record(this.records.get(this.edition_id));
            } else {
                cancelled = $.when();
            }
            cancelled.then(function () {
                self.view.unpad_columns();
                self.edition_form.stop();
                self.edition_form.$element.remove();
                delete self.edition_form;
                self.dataset.index = null;
                delete self.edition_id;
                delete self.edition;
            });
            this.pad_table_to(5);
            return cancelled;
        },
        /**
         * Adapts this list's view description to be suitable to the inner form
         * view of a row being edited.
         *
         * @returns {Object} fields_view_get's view section suitable for putting into form view of editable rows.
         */
        get_form_fields_view: function () {
            // deep copy of view
            var view = $.extend(true, {}, this.group.view.fields_view);
            _(view.arch.children).each(function (widget) {
                widget.attrs.nolabel = true;
                if (widget.tag === 'button') {
                    delete widget.attrs.string;
                }
            });
            view.arch.attrs.col = 2 * view.arch.children.length;
            return view;
        },
        on_row_keyup: function (e) {
            var self = this;
            switch (e.which) {
            case KEY_RETURN:
                this.save_row().then(function (result) {
                    if (result.created) {
                        self.new_record();
                        return;
                    }

                    var next_record_id,
                        next_record = self.records.at(
                                self.records.indexOf(result.edited_record) + 1);
                    if (next_record) {
                        next_record_id = next_record.get('id');
                        self.dataset.index = _(self.dataset.ids)
                                .indexOf(next_record_id);
                    } else {
                        self.dataset.index = 0;
                        next_record_id = self.records.at(0).get('id');
                    }
                    self.edit_record(next_record_id);
                });
                break;
            case KEY_ESCAPE:
                this.cancel_edition();
                break;
            }
        },
        render_row_as_form: function (row) {
            var self = this;
            this.ensure_saved().then(function () {
                var record_id = $(row).data('id');
                var $new_row = $('<tr>', {
                        id: _.uniqueId('oe-editable-row-'),
                        'data-id': record_id,
                        'class': (row ? $(row).attr('class') : '') + ' oe_forms',
                        click: function (e) {e.stopPropagation();}
                    })
                    .delegate('button.oe-edit-row-save', 'click', function () {
                        self.save_row();
                    })
                    .delegate('button', 'keyup', function (e) {
                        e.stopImmediatePropagation();
                    })
                    .keyup(function () {
                        return self.on_row_keyup.apply(self, arguments); })
                    .keydown(function (e) { e.stopPropagation(); });
                if (row) {
                    $new_row.replaceAll(row);
                } else if (self.options.editable) {
                    var $last_child = self.$current.children('tr:last');
                    if (self.records.length) {
                        if (self.options.editable === 'top') {
                            $new_row.insertBefore(
                                self.$current.children('[data-id]:first'));
                        } else {
                            $new_row.insertAfter(
                                self.$current.children('[data-id]:last'));
                        }
                    } else {
                        $new_row.prependTo(self.$current);
                    }
                    if ($last_child.is(':not([data-id])')) {
                        $last_child.remove();
                    }
                }
                self.edition = true;
                self.edition_id = record_id;
                self.dataset.index = _(self.dataset.ids).indexOf(record_id);
                if (self.dataset.index === -1) {
                    self.dataset.index = null;
                }
                self.edition_form = _.extend(new openerp.web.ListEditableFormView(self.view, self.dataset, false), {
                    form_template: 'ListView.row.form',
                    registry: openerp.web.list.form.widgets,
                    $element: $new_row
                });
                // HA HA
                self.edition_form.appendTo();
                // put in $.when just in case  FormView.on_loaded becomes asynchronous
                $.when(self.edition_form.on_loaded(self.get_form_fields_view())).then(function () {
                    $new_row.find('> td')
                          .addClass('oe-field-cell')
                          .removeAttr('width')
                      .end()
                      .find('td:last').removeClass('oe-field-cell').end();
                    if (self.options.selectable) {
                        $new_row.prepend('<th>');
                    }
                    if (self.options.isClarkGable) {
                        $new_row.prepend('<th>');
                    }
                    // pad in case of groupby
                    _(self.columns).each(function (column) {
                        if (column.meta) {
                            $new_row.prepend('<td>');
                        }
                    });
                    // Add column for the save, if
                    // there is none in the list
                    if (!self.options.deletable) {
                        self.view.pad_columns(
                            1, {except: $new_row});
                    }

                    self.edition_form.do_show();
                });
            });
        },
        handle_onwrite: function (source_record_id) {
            var self = this;
            var on_write_callback = self.view.fields_view.arch.attrs.on_write;
            if (!on_write_callback) { return; }
            this.dataset.call(on_write_callback, [source_record_id], function (ids) {
                _(ids).each(function (id) {
                    var record = self.records.get(id);
                    if (!record) {
                        // insert after the source record
                        var index = self.records.indexOf(
                            self.records.get(source_record_id)) + 1;
                        record = new openerp.web.list.Record({id: id});
                        self.records.add(record, {at: index});
                        self.dataset.ids.splice(index, 0, id);
                    }
                    self.reload_record(record);
                });
            });
        },
        /**
         * Saves the current row, and returns a Deferred resolving to an object
         * with the following properties:
         *
         * ``created``
         *   Boolean flag indicating whether the record saved was being created
         *   (``true`` or edited (``false``)
         * ``edited_record``
         *   The result of saving the record (either the newly created record,
         *   or the post-edition record), after insertion in the Collection if
         *   needs be.
         *
         * @returns {$.Deferred<{created: Boolean, edited_record: Record}>}
         */
        save_row: function () {
            //noinspection JSPotentiallyInvalidConstructorUsage
            var self = this;
            return this.edition_form
                .do_save(null, this.options.editable === 'top')
                .pipe(function (result) {
                    if (result.created && !self.edition_id) {
                        self.records.add({id: result.result},
                            {at: self.options.editable === 'top' ? 0 : null});
                        self.edition_id = result.result;
                    }
                    var edited_record = self.records.get(self.edition_id);

                    return $.when(
                        self.handle_onwrite(self.edition_id),
                        self.cancel_pending_edition().then(function () {
                            $(self).trigger('saved', [self.dataset]);
                        })).pipe(function () {
                            return {
                                created: result.created || false,
                                edited_record: edited_record
                            };
                        });
                });
        },
        /**
         * If the current list is being edited, ensures it's saved
         */
        ensure_saved: function () {
            if (this.edition) {
                // kinda-hack-ish: if the user has entered data in a field,
                // oe_form_dirty will be set on the form so save, otherwise
                // discard the current (entirely empty) line
                if (this.edition_form.$element.is('.oe_form_dirty')) {
                    return this.save_row();
                }
                return this.cancel_pending_edition();
            }
            //noinspection JSPotentiallyInvalidConstructorUsage
            return $.when();
        },
        /**
         * Cancels the edition of the row for the current dataset index
         */
        cancel_edition: function () {
            this.cancel_pending_edition();
        },
        /**
         * Edits record currently selected via dataset
         */
        edit_record: function (record_id) {
            this.render_row_as_form(
                this.$current.find('[data-id=' + record_id + ']'));
            $(this).trigger(
                'edit',
                [record_id, this.dataset]);
        },
        new_record: function () {
            this.render_row_as_form();
        },
        render_record: function (record) {
            var index = this.records.indexOf(record),
                 self = this;
            // FIXME: context dict should probably be extracted cleanly
            return QWeb.render('ListView.row', {
                columns: this.columns,
                options: this.options,
                record: record,
                row_parity: (index % 2 === 0) ? 'even' : 'odd',
                view: this.view,
                render_cell: function () {
                    return self.render_cell.apply(self, arguments); },
                edited: !!this.edition_form
            });
        }
    });
    if (!openerp.web.list) {
        openerp.web.list = {};
    }
    if (!openerp.web.list.form) {
        openerp.web.list.form = {};
    }
    openerp.web.list.form.WidgetFrame = openerp.web.form.WidgetFrame.extend({
        template: 'ListView.row.frame'
    });
    var form_widgets = openerp.web.form.widgets;
    openerp.web.list.form.widgets = form_widgets.extend({
        'frame': 'openerp.web.list.form.WidgetFrame'
    });
    // All form widgets inherit a problematic behavior from
    // openerp.web.form.WidgetFrame: the cell itself is removed when invisible
    // whether it's @invisible or @attrs[invisible]. In list view, only the
    // former should completely remove the cell. We need to override update_dom
    // on all widgets since we can't just hit on widget itself (I think)
    var list_form_widgets = openerp.web.list.form.widgets;
    _(form_widgets.map).each(function (widget_path, key) {
        if (key === 'frame') { return; }
        var new_path = 'openerp.web.list.form.' + key;

        openerp.web.list.form[key] = (form_widgets.get_object(key)).extend({
            update_dom: function () {
                this.$element.children().css('visibility', '');
                if (this.modifiers.tree_invisible) {
                    var old_invisible = this.invisible;
                    this.invisible = true;
                    this._super.apply(this, arguments);
                    this.invisible = old_invisible;
                } else if (this.invisible) {
                    this.$element.children().css('visibility', 'hidden');
                } else {
                    this._super.apply(this, arguments);
                }
            }
        });
        list_form_widgets.add(key, new_path);
    });

    openerp.web.ListEditableFormView = openerp.web.FormView.extend({
        init_view: function() {},
        _render_and_insert: function () {
            return this.start();
        }
    });
};
<|endoftext|>


<commit_before>/** @babel */

import FileList from '../lib/file-list'
import FileDiff from '../lib/file-diff'
import {createFileDiffsFromPath} from './helpers'
import {it, beforeEach} from './async-spec-helpers'

function createFileList (filePath) {
  let fileDiffs = createFileDiffsFromPath(filePath)
  return new FileList(fileDiffs)
}

describe('FileList', function () {
  let fileList

  it('emits a change event when a file is staged', function () {
    fileList = createFileList('fixtures/two-file-diff.txt')
    let changeHandler = jasmine.createSpy()
    fileList.onDidChange(changeHandler)

    let fileDiff = fileList.getFiles()[0]
    fileDiff.stage()
    expect(changeHandler.callCount).toBe(1)
    let args = changeHandler.mostRecentCall.args
    expect(args[0].fileList).toBe(fileList)
    expect(args[0].events).toHaveLength(1)
    expect(args[0].events[0].file).toBe(fileDiff)
  })

  it('emits a change event when a file is staged', function () {
    fileList = createFileList('fixtures/two-file-diff.txt')
    let changeHandler = jasmine.createSpy()
    fileList.onDidChange(changeHandler)

    fileList.getFiles()[0].getHunks()[0].stage()
    let args = changeHandler.mostRecentCall.args
    expect(args[0].fileList).toBe(fileList)
    expect(args[0].events).toHaveLength(1)
    expect(args[0].events[0].file).toBe(fileList.getFiles()[0])
  })

  it('opens a new diff item as pending when openFileDiffAtIndex is called', function () {
    spyOn(atom.workspace, 'open')
    fileList.openFileDiffAtIndex(0)

    let args = atom.workspace.open.mostRecentCall.args
    console.log(args)
    expect(args[0]).toContain('config.coffee')
    expect(args[1].pending).toBe(true)
  })

  describe('the file cache', function () {
    let fileDiffA, fileDiffB
    beforeEach(function () {
      fileDiffA = new FileDiff({
        oldPathName: 'src/a.js',
        newPathName: 'src/a.js'
      })
      fileDiffB = new FileDiff({
        oldPathName: 'src/b.js',
        newPathName: 'src/b.js'
      })
      fileList = new FileList([fileDiffA, fileDiffB])
    })

    it('creates and retreives fileDiffs', function () {
      expect(fileList.getFileFromPathName(fileDiffA.getNewPathName())).toBe(fileDiffA)
      expect(fileList.getFileFromPathName(fileDiffB.getNewPathName())).toBe(fileDiffB)

      let fileDiffC = fileList.getOrCreateFileFromPathName('src/c.js')
      expect(fileList.getFileFromPathName(fileDiffC.getNewPathName())).toBe(fileDiffC)
    })

    it('moves model to the new file key when a file is renamed', function () {
      fileDiffA.setNewPathName('src/a-new.js')
      fileList.setFiles([fileDiffA, fileDiffB])
      expect(fileList.getFileFromPathName('src/a-new.js')).toBe(fileDiffA)
      expect(fileList.getFileFromPathName('src/a.js')).toBeUndefined()
      expect(fileList.getFileFromPathName(fileDiffB.getNewPathName())).toBe(fileDiffB)
    })
  })
})
<commit_msg>Nope, not this log line<commit_after>/** @babel */

import FileList from '../lib/file-list'
import FileDiff from '../lib/file-diff'
import {createFileDiffsFromPath} from './helpers'
import {it, beforeEach} from './async-spec-helpers'

function createFileList (filePath) {
  let fileDiffs = createFileDiffsFromPath(filePath)
  return new FileList(fileDiffs)
}

describe('FileList', function () {
  let fileList

  it('emits a change event when a file is staged', function () {
    fileList = createFileList('fixtures/two-file-diff.txt')
    let changeHandler = jasmine.createSpy()
    fileList.onDidChange(changeHandler)

    let fileDiff = fileList.getFiles()[0]
    fileDiff.stage()
    expect(changeHandler.callCount).toBe(1)
    let args = changeHandler.mostRecentCall.args
    expect(args[0].fileList).toBe(fileList)
    expect(args[0].events).toHaveLength(1)
    expect(args[0].events[0].file).toBe(fileDiff)
  })

  it('emits a change event when a file is staged', function () {
    fileList = createFileList('fixtures/two-file-diff.txt')
    let changeHandler = jasmine.createSpy()
    fileList.onDidChange(changeHandler)

    fileList.getFiles()[0].getHunks()[0].stage()
    let args = changeHandler.mostRecentCall.args
    expect(args[0].fileList).toBe(fileList)
    expect(args[0].events).toHaveLength(1)
    expect(args[0].events[0].file).toBe(fileList.getFiles()[0])
  })

  it('opens a new diff item as pending when openFileDiffAtIndex is called', function () {
    spyOn(atom.workspace, 'open')
    fileList.openFileDiffAtIndex(0)

    let args = atom.workspace.open.mostRecentCall.args
    expect(args[0]).toContain('config.coffee')
    expect(args[1].pending).toBe(true)
  })

  describe('the file cache', function () {
    let fileDiffA, fileDiffB
    beforeEach(function () {
      fileDiffA = new FileDiff({
        oldPathName: 'src/a.js',
        newPathName: 'src/a.js'
      })
      fileDiffB = new FileDiff({
        oldPathName: 'src/b.js',
        newPathName: 'src/b.js'
      })
      fileList = new FileList([fileDiffA, fileDiffB])
    })

    it('creates and retreives fileDiffs', function () {
      expect(fileList.getFileFromPathName(fileDiffA.getNewPathName())).toBe(fileDiffA)
      expect(fileList.getFileFromPathName(fileDiffB.getNewPathName())).toBe(fileDiffB)

      let fileDiffC = fileList.getOrCreateFileFromPathName('src/c.js')
      expect(fileList.getFileFromPathName(fileDiffC.getNewPathName())).toBe(fileDiffC)
    })

    it('moves model to the new file key when a file is renamed', function () {
      fileDiffA.setNewPathName('src/a-new.js')
      fileList.setFiles([fileDiffA, fileDiffB])
      expect(fileList.getFileFromPathName('src/a-new.js')).toBe(fileDiffA)
      expect(fileList.getFileFromPathName('src/a.js')).toBeUndefined()
      expect(fileList.getFileFromPathName(fileDiffB.getNewPathName())).toBe(fileDiffB)
    })
  })
})
<|endoftext|>


<commit_before>/*---------------------------------------------------------
 * OpenERP Web Mobile Form View
 *---------------------------------------------------------*/

openerp.web_mobile.form_mobile = function (openerp) {

openerp.web_mobile.FormView = openerp.web.Widget.extend({
    init: function(session, element_id, list_id, action, head_title, resmodel, viewid) {
        this._super(session, element_id);
        this.list_id = list_id;
        this.action = action;
        this.head_title = head_title;
        this.resmodel = resmodel;
        this.viewid = viewid;

    },
    start: function() {
        var self = this;
        var id = this.list_id;

        var model = this.action.res_model || this.resmodel;
        if(this.action){
            var view_id = this.action.views[1][0];
        }else{
            var view_id = this.viewid;
        }

        this.dataset = new openerp.web.DataSetSearch(this, model, null, null);
        var context = new openerp.web.CompoundContext(this.dataset.get_context());
        this.dataset.read_slice([],{}, function (result) {

            for (var i = 0; i < result.length; i++) {
                if (result[i].id == id) {
                    var data = result[i];
                }
            }
            self.rpc("/web/view/load", {"model": model, "view_id": view_id, "view_type": "form", context: context}, function (result) {
                var fields = result.fields;
                var view_fields = result.arch.children;
                var get_fields = self.get_fields(view_fields);
                var selection = new openerp.web_mobile.Selection();

                for (var j = 0; j < view_fields.length; j++) {
                    if (view_fields[j].tag == 'notebook') {
                        var notebooks = view_fields[j];
                    }
                }
                self.$element.html(QWeb.render("FormView", {'get_fields': get_fields, 'notebooks': notebooks || false, 'fields' : fields, 'values' : data ,'temp_flag':'1'}));

                    self.$element.find("[data-role=header]").find('h1').html(self.head_title);
                    self.$element.find("[data-role=header]").find('#home').click(function(){
                        $.mobile.changePage("#oe_menu", "slide", true, true);
                    });
                    self.$element.find("[data-role=footer]").find('#shrotcuts').click(function(){
                        if(!$('#oe_shortcuts').html().length){
                            this.shortcuts = new openerp.web_mobile.Shortcuts(self, "oe_shortcuts");
                            this.shortcuts.start();
                        }
                        else{
                            $.mobile.changePage("#oe_shortcuts", "slide", true, true);
                        }
                    });
                    self.$element.find("[data-role=footer]").find('#preference').click(function(){
                        if(!$('#oe_options').html().length){
                            this.options = new openerp.web_mobile.Options(self, "oe_options");
                            this.options.start();
                        }
                        else{
                            $.mobile.changePage("#oe_options", "slide", true, true);
                        }
                    });
                    self.$element.find('#formbutton').click(function(){
                        var selected_id = $(this).prev().find('select').val();
                        var select_model = $(this).prev().find('select').attr('for');
                        if(selected_id!="false"){
                            if(!$('[id^="oe_form_'+selected_id+select_model+'"]').html()){
                                $('

').appendTo('#moe');
                                    this.formview = new openerp.web_mobile.FormView(self, "oe_form_"+selected_id+select_model, selected_id, '', 'head',select_model,false);
                                    this.formview.start();
                            }else{
                                $.mobile.changePage('#oe_form_'+selected_id+select_model, "slide", true, true);
                            }
                        }
                    });
                    self.$element.find('[data-role=collapsible-set]').find('[data-role=collapsible]').each(function(i){

                        for (var k = 0; k < notebooks.children.length; k++) {
                            if (notebooks.children[k].attrs.string == $(this).attr('id')) {
                                get_fields = self.get_fields(notebooks.children[k].children);
                                for (var i = 0; i < get_fields.length; i++) {
                                    if (fields[get_fields[i].attrs.name].type == 'one2many'){
                                        self.relational_fields = get_fields[i].attrs.name;
                                        if(fields[get_fields[i].attrs.name].views.form){
                                            var get_fields_test = self.get_fields(fields[get_fields[i].attrs.name].views.form.arch.children);
                                            var fields_test = fields[get_fields[i].attrs.name]['views'].form.fields;
                                            var notebook=fields[get_fields[i].attrs.name].views.form.arch;
                                        }
                                    }
                                }
                            }

                            if(notebook){
                                $(this).find('p').html(QWeb.render("FormView", {'get_fields': get_fields,'fields' : result.fields, 'values' : data,'til': notebook.attrs.string }));
                            }else{
                                $(this).find('p').html(QWeb.render("FormView", {'get_fields': get_fields,'fields' : result.fields, 'values' : data }));
                            }
                            $(this).find('p').find('#formbutton').click(function(){
                                var selected_id = $(this).prev().find('select').val();
                                var select_model = $(this).prev().find('select').attr('for');
                                if(selected_id!="false"){
                                    if(!$('[id^="oe_form_'+selected_id+select_model+'"]').html()){
                                        $('

').appendTo('#moe');
                                        this.formview = new openerp.web_mobile.FormView(self, "oe_form_"+selected_id+select_model, selected_id, '', 'head',select_model,false);
                                        this.formview.start();
                                    }else{
                                        $.mobile.changePage('#oe_form_'+selected_id+select_model, "slide", true, true);
                                    }
                                }
                            });

                        }
                    });
                    self.$element.find('[data-role=collapsible-set]').find('[data-role=collapsible]').find('p').find('[data-role=content]').find('ul').find('li').click(function(ev){
                        ev.preventDefault();
                        ev.stopPropagation();
                        var latid,lastid;
                        $(this).parents().each(function(){
                            latid = $(this).attr('id');
                            self.$element.find('[data-role=collapsible-set]').find('[data-role=collapsible]').each(function(){
                                if(latid==$(this).attr('id')){
                                    lastid = $(this).attr('id');
                                }
                            });
                        });
                        var relational = $(this).attr('for');
                        if(result.fields[relational]){

                            var head = $.trim($(this).text());
                            var dataset = new openerp.web.DataSetStatic(self, result.fields[relational].relation, result.fields[relational].context);
                            dataset.domain=[['id', 'in', data[relational]]];
                            dataset.name_search('', dataset.domain, 'in',false ,function(res){
                                for(var i=0;i<res.length;i++){
                                    var splited_data = res[i][1].split(',');
                                    res[i][1] = splited_data[0];
                                }
                                if(!$('[id^="oe_list_'+relational+'_'+self.element_id+'"]').html()){
                                    $('

').appendTo('#moe');
                                    $('[id^="oe_list_'+relational+'_'+self.element_id+'"]').html(QWeb.render("ListView", {'records' : res}));
                                    $('[id^="oe_list_'+relational+'_'+self.element_id+'"]').find("[data-role=header]").find('h1').html(head);
                                    $('[id^="oe_list_'+relational+'_'+self.element_id+'"]').find("[data-role=header]").find('#home').click(function(){
                                        $.mobile.changePage("#oe_menu", "slide", true, true);
                                    });
                                    $('[id^="oe_list_'+relational+'_'+self.element_id+'"]').find("[data-role=footer]").find('#shrotcuts').click(function(){
                                        if(!$('#oe_shortcuts').html().length){
                                            this.shortcuts = new openerp.web_mobile.Shortcuts(self, "oe_shortcuts");
                                            this.shortcuts.start();
                                        }
                                        else{
                                            $.mobile.changePage("#oe_shortcuts", "slide", true, true);
                                        }
                                    });
                                    $('[id^="oe_list_'+relational+'_'+self.element_id+'"]').find("[data-role=footer]").find('#preference').click(function(){
                                        if(!$('#oe_options').html().length){
                                            this.options = new openerp.web_mobile.Options(self, "oe_options");
                                            this.options.start();
                                        }
                                        else{
                                            $.mobile.changePage("#oe_options", "slide", true, true);
                                        }
                                    });
                                    $('[id^="oe_list_'+relational+'_'+self.element_id+'"]').find("a#list-id").click(function(ev){
                                        ev.preventDefault();
                                        ev.stopPropagation();
                                        var head_title = $(this).text();
                                        var listid = $(ev.currentTarget).data('id');
                                        dataset = new openerp.web.DataSetSearch(self, dataset.model, null, null);
                                        dataset.read_slice([],{}, function (result_relational) {
                                            for (var i = 0; i < result_relational.length; i++) {
                                                if (result_relational[i].id == listid) {
                                                    var data_relational = result_relational[i];
                                                }
                                            }
                                            if(!$('[id^="oe_form_'+listid+result.fields[relational].relation+'"]').html()){
                                                $('

').appendTo('#moe');
                                                for (var k = 0; k < notebooks.children.length; k++) {
                                                    if (notebooks.children[k].attrs.string == lastid) {
                                                        get_fields = self.get_fields(notebooks.children[k].children);
                                                        for (var i = 0; i < get_fields.length; i++) {
                                                            if (fields[get_fields[i].attrs.name].type == 'one2many'){
                                                                self.relational_fields = get_fields[i].attrs.name;
                                                                if(fields[get_fields[i].attrs.name].views.form){
                                                                    var get_fields_test = self.get_fields(fields[get_fields[i].attrs.name].views.form.arch.children);
                                                                    var fields_test = fields[get_fields[i].attrs.name]['views'].form.fields;
                                                                    var notebook=fields[get_fields[i].attrs.name].views.form.arch;
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                                $('[id^="oe_form_'+listid+result.fields[relational].relation+'"]').html(QWeb.render("FormView", {'get_fields': get_fields_test, 'notebooks': false, 'fields' : fields_test, 'values' : data_relational, 'temp_flag':'1' }));

                                                $('[id^="oe_form_'+listid+result.fields[relational].relation+'"]').find("[data-role=header]").find('h1').html(head_title);
                                                $('[id^="oe_form_'+listid+result.fields[relational].relation+'"]').find("[data-role=header]").find('#home').click(function(){
                                                    $.mobile.changePage("#oe_menu", "slide", true, true);
                                                });
                                                $('[id^="oe_form_'+listid+result.fields[relational].relation+'"]').find("[data-role=footer]").find('#shrotcuts').click(function(){
                                                    if(!$('#oe_shortcuts').html().length){
                                                        this.shortcuts = new openerp.web_mobile.Shortcuts(self, "oe_shortcuts");
                                                        this.shortcuts.start();
                                                    }
                                                    else{
                                                        $.mobile.changePage("#oe_shortcuts", "slide", true, true);
                                                    }
                                                });
                                                $('[id^="oe_form_'+listid+result.fields[relational].relation+'"]').find("[data-role=footer]").find('#preference').click(function(){
                                                    if(!$('#oe_options').html().length){
                                                        this.options = new openerp.web_mobile.Options(self, "oe_options");
                                                        this.options.start();
                                                    }
                                                    else{
                                                        $.mobile.changePage("#oe_options", "slide", true, true);
                                                    }
                                                });
                                                $('[id^="oe_form_'+listid+result.fields[relational].relation+'"]').find('#formbutton').click(function(){
                                                    var selected_id = $(this).prev().find('select').val();
                                                    var select_model = $(this).prev().find('select').attr('for');
                                                    if(selected_id!="false"){
                                                        if(!$('[id^="oe_form_'+selected_id+select_model+'"]').html()){
                                                            $('

').appendTo('#moe');
                                                            this.formview = new openerp.web_mobile.FormView(self, "oe_form_"+selected_id+select_model, selected_id, '', 'head',select_model,false);
                                                            this.formview.start();
                                                        }else{
                                                            $.mobile.changePage('#oe_form_'+selected_id+select_model, "slide", true, true);
                                                        }
                                                    }
                                                });
                                                $.mobile.changePage('#oe_form_'+listid+result.fields[relational].relation, "slide", true, true);
                                            }else{
                                                $.mobile.changePage('#oe_form_'+listid+result.fields[relational].relation, "slide", true, true);
                                            }
                                        });
                                    });
                                    $.mobile.changePage("#oe_list_"+relational+"_"+self.element_id, "slide", true, true);
                                }else{
                                    $.mobile.changePage("#oe_list_"+relational+"_"+self.element_id, "slide", true, true);
                                }
                            });
                        }
                    });
                    $.mobile.changePage("#"+self.element_id, "slide", true, true);
                });
        });
    },
    get_fields: function(view_fields, fields) {
        this.fields = fields || [];
        for (var i=0; i < view_fields.length; i++){
            if (view_fields[i].tag == 'field') {
                this.fields.push(view_fields[i]);
            }
            if (view_fields[i].tag == 'group') {
                this.get_fields(view_fields[i].children, this.fields);
            }
        }
        return this.fields;
    }
});
};
<commit_msg>[IMP] Set header for many2one formview.<commit_after>/*---------------------------------------------------------
 * OpenERP Web Mobile Form View
 *---------------------------------------------------------*/

openerp.web_mobile.form_mobile = function (openerp) {

openerp.web_mobile.FormView = openerp.web.Widget.extend({
    init: function(session, element_id, list_id, action, head_title, resmodel, viewid) {
        this._super(session, element_id);
        this.list_id = list_id;
        this.action = action;
        this.head_title = head_title;
        this.resmodel = resmodel;
        this.viewid = viewid;

    },
    start: function() {
        var self = this;
        var id = this.list_id;

        var model = this.action.res_model || this.resmodel;
        if(this.action){
            var view_id = this.action.views[1][0];
        }else{
            var view_id = this.viewid;
        }

        this.dataset = new openerp.web.DataSetSearch(this, model, null, null);
        var context = new openerp.web.CompoundContext(this.dataset.get_context());
        this.dataset.read_slice([],{}, function (result) {

            for (var i = 0; i < result.length; i++) {
                if (result[i].id == id) {
                    var data = result[i];
                }
            }
            self.rpc("/web/view/load", {"model": model, "view_id": view_id, "view_type": "form", context: context}, function (result) {
                var fields = result.fields;
                var view_fields = result.arch.children;
                var get_fields = self.get_fields(view_fields);
                var selection = new openerp.web_mobile.Selection();

                for (var j = 0; j < view_fields.length; j++) {
                    if (view_fields[j].tag == 'notebook') {
                        var notebooks = view_fields[j];
                    }
                }
                self.$element.html(QWeb.render("FormView", {'get_fields': get_fields, 'notebooks': notebooks || false, 'fields' : fields, 'values' : data ,'temp_flag':'1'}));

                    self.$element.find("[data-role=header]").find('h1').html(self.head_title);
                    self.$element.find("[data-role=header]").find('#home').click(function(){
                        $.mobile.changePage("#oe_menu", "slide", true, true);
                    });
                    self.$element.find("[data-role=footer]").find('#shrotcuts').click(function(){
                        if(!$('#oe_shortcuts').html().length){
                            this.shortcuts = new openerp.web_mobile.Shortcuts(self, "oe_shortcuts");
                            this.shortcuts.start();
                        }
                        else{
                            $.mobile.changePage("#oe_shortcuts", "slide", true, true);
                        }
                    });
                    self.$element.find("[data-role=footer]").find('#preference').click(function(){
                        if(!$('#oe_options').html().length){
                            this.options = new openerp.web_mobile.Options(self, "oe_options");
                            this.options.start();
                        }
                        else{
                            $.mobile.changePage("#oe_options", "slide", true, true);
                        }
                    });
                    self.$element.find('#formbutton').click(function(){
                        var head = $(this).prev().find('select').find("option:selected").text();
                        var selected_id = $(this).prev().find('select').val();
                        var select_model = $(this).prev().find('select').attr('for');
                        if(selected_id!="false"){
                            if(!$('[id^="oe_form_'+selected_id+select_model+'"]').html()){
                                $('

').appendTo('#moe');
                                    this.formview = new openerp.web_mobile.FormView(self, "oe_form_"+selected_id+select_model, selected_id, '', head, select_model, false);
                                    this.formview.start();
                            }else{
                                $.mobile.changePage('#oe_form_'+selected_id+select_model, "slide", true, true);
                            }
                        }
                    });
                    self.$element.find('[data-role=collapsible-set]').find('[data-role=collapsible]').each(function(i){

                        for (var k = 0; k < notebooks.children.length; k++) {
                            if (notebooks.children[k].attrs.string == $(this).attr('id')) {
                                get_fields = self.get_fields(notebooks.children[k].children);
                                for (var i = 0; i < get_fields.length; i++) {
                                    if (fields[get_fields[i].attrs.name].type == 'one2many'){
                                        self.relational_fields = get_fields[i].attrs.name;
                                        if(fields[get_fields[i].attrs.name].views.form){
                                            var get_fields_test = self.get_fields(fields[get_fields[i].attrs.name].views.form.arch.children);
                                            var fields_test = fields[get_fields[i].attrs.name]['views'].form.fields;
                                            var notebook=fields[get_fields[i].attrs.name].views.form.arch;
                                        }
                                    }
                                }
                            }

                            if(notebook){
                                $(this).find('p').html(QWeb.render("FormView", {'get_fields': get_fields,'fields' : result.fields, 'values' : data,'til': notebook.attrs.string }));
                            }else{
                                $(this).find('p').html(QWeb.render("FormView", {'get_fields': get_fields,'fields' : result.fields, 'values' : data }));
                            }
                            $(this).find('p').find('#formbutton').click(function(){
                                var head = $(this).prev().find('select').find("option:selected").text();
                                var selected_id = $(this).prev().find('select').val();
                                var select_model = $(this).prev().find('select').attr('for');
                                if(selected_id!="false"){
                                    if(!$('[id^="oe_form_'+selected_id+select_model+'"]').html()){
                                        $('

').appendTo('#moe');
                                        this.formview = new openerp.web_mobile.FormView(self, "oe_form_"+selected_id+select_model, selected_id, '', head, select_model, false);
                                        this.formview.start();
                                    }else{
                                        $.mobile.changePage('#oe_form_'+selected_id+select_model, "slide", true, true);
                                    }
                                }
                            });

                        }
                    });
                    self.$element.find('[data-role=collapsible-set]').find('[data-role=collapsible]').find('p').find('[data-role=content]').find('ul').find('li').click(function(ev){
                        ev.preventDefault();
                        ev.stopPropagation();
                        var latid,lastid;
                        $(this).parents().each(function(){
                            latid = $(this).attr('id');
                            self.$element.find('[data-role=collapsible-set]').find('[data-role=collapsible]').each(function(){
                                if(latid==$(this).attr('id')){
                                    lastid = $(this).attr('id');
                                }
                            });
                        });
                        var relational = $(this).attr('for');
                        if(result.fields[relational]){

                            var head = $.trim($(this).text());
                            var dataset = new openerp.web.DataSetStatic(self, result.fields[relational].relation, result.fields[relational].context);
                            dataset.domain=[['id', 'in', data[relational]]];
                            dataset.name_search('', dataset.domain, 'in',false ,function(res){
                                for(var i=0;i<res.length;i++){
                                    var splited_data = res[i][1].split(',');
                                    res[i][1] = splited_data[0];
                                }
                                if(!$('[id^="oe_list_'+relational+'_'+self.element_id+'"]').html()){
                                    $('

').appendTo('#moe');
                                    $('[id^="oe_list_'+relational+'_'+self.element_id+'"]').html(QWeb.render("ListView", {'records' : res}));
                                    $('[id^="oe_list_'+relational+'_'+self.element_id+'"]').find("[data-role=header]").find('h1').html(head);
                                    $('[id^="oe_list_'+relational+'_'+self.element_id+'"]').find("[data-role=header]").find('#home').click(function(){
                                        $.mobile.changePage("#oe_menu", "slide", true, true);
                                    });
                                    $('[id^="oe_list_'+relational+'_'+self.element_id+'"]').find("[data-role=footer]").find('#shrotcuts').click(function(){
                                        if(!$('#oe_shortcuts').html().length){
                                            this.shortcuts = new openerp.web_mobile.Shortcuts(self, "oe_shortcuts");
                                            this.shortcuts.start();
                                        }
                                        else{
                                            $.mobile.changePage("#oe_shortcuts", "slide", true, true);
                                        }
                                    });
                                    $('[id^="oe_list_'+relational+'_'+self.element_id+'"]').find("[data-role=footer]").find('#preference').click(function(){
                                        if(!$('#oe_options').html().length){
                                            this.options = new openerp.web_mobile.Options(self, "oe_options");
                                            this.options.start();
                                        }
                                        else{
                                            $.mobile.changePage("#oe_options", "slide", true, true);
                                        }
                                    });
                                    $('[id^="oe_list_'+relational+'_'+self.element_id+'"]').find("a#list-id").click(function(ev){
                                        ev.preventDefault();
                                        ev.stopPropagation();
                                        var head_title = $(this).text();
                                        var listid = $(ev.currentTarget).data('id');
                                        dataset = new openerp.web.DataSetSearch(self, dataset.model, null, null);
                                        dataset.read_slice([],{}, function (result_relational) {
                                            for (var i = 0; i < result_relational.length; i++) {
                                                if (result_relational[i].id == listid) {
                                                    var data_relational = result_relational[i];
                                                }
                                            }
                                            if(!$('[id^="oe_form_'+listid+result.fields[relational].relation+'"]').html()){
                                                $('

').appendTo('#moe');
                                                for (var k = 0; k < notebooks.children.length; k++) {
                                                    if (notebooks.children[k].attrs.string == lastid) {
                                                        get_fields = self.get_fields(notebooks.children[k].children);
                                                        for (var i = 0; i < get_fields.length; i++) {
                                                            if (fields[get_fields[i].attrs.name].type == 'one2many'){
                                                                self.relational_fields = get_fields[i].attrs.name;
                                                                if(fields[get_fields[i].attrs.name].views.form){
                                                                    var get_fields_test = self.get_fields(fields[get_fields[i].attrs.name].views.form.arch.children);
                                                                    var fields_test = fields[get_fields[i].attrs.name]['views'].form.fields;
                                                                    var notebook=fields[get_fields[i].attrs.name].views.form.arch;
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                                $('[id^="oe_form_'+listid+result.fields[relational].relation+'"]').html(QWeb.render("FormView", {'get_fields': get_fields_test, 'notebooks': false, 'fields' : fields_test, 'values' : data_relational, 'temp_flag':'1' }));

                                                $('[id^="oe_form_'+listid+result.fields[relational].relation+'"]').find("[data-role=header]").find('h1').html(head_title);
                                                $('[id^="oe_form_'+listid+result.fields[relational].relation+'"]').find("[data-role=header]").find('#home').click(function(){
                                                    $.mobile.changePage("#oe_menu", "slide", true, true);
                                                });
                                                $('[id^="oe_form_'+listid+result.fields[relational].relation+'"]').find("[data-role=footer]").find('#shrotcuts').click(function(){
                                                    if(!$('#oe_shortcuts').html().length){
                                                        this.shortcuts = new openerp.web_mobile.Shortcuts(self, "oe_shortcuts");
                                                        this.shortcuts.start();
                                                    }
                                                    else{
                                                        $.mobile.changePage("#oe_shortcuts", "slide", true, true);
                                                    }
                                                });
                                                $('[id^="oe_form_'+listid+result.fields[relational].relation+'"]').find("[data-role=footer]").find('#preference').click(function(){
                                                    if(!$('#oe_options').html().length){
                                                        this.options = new openerp.web_mobile.Options(self, "oe_options");
                                                        this.options.start();
                                                    }
                                                    else{
                                                        $.mobile.changePage("#oe_options", "slide", true, true);
                                                    }
                                                });
                                                $('[id^="oe_form_'+listid+result.fields[relational].relation+'"]').find('#formbutton').click(function(){
                                                    var head = $(this).prev().find('select').find("option:selected").text();
                                                    var selected_id = $(this).prev().find('select').val();
                                                    var select_model = $(this).prev().find('select').attr('for');
                                                    if(selected_id!="false"){
                                                        if(!$('[id^="oe_form_'+selected_id+select_model+'"]').html()){
                                                            $('

').appendTo('#moe');
                                                            this.formview = new openerp.web_mobile.FormView(self, "oe_form_"+selected_id+select_model, selected_id, '', head, select_model, false);
                                                            this.formview.start();
                                                        }else{
                                                            $.mobile.changePage('#oe_form_'+selected_id+select_model, "slide", true, true);
                                                        }
                                                    }
                                                });
                                                $.mobile.changePage('#oe_form_'+listid+result.fields[relational].relation, "slide", true, true);
                                            }else{
                                                $.mobile.changePage('#oe_form_'+listid+result.fields[relational].relation, "slide", true, true);
                                            }
                                        });
                                    });
                                    $.mobile.changePage("#oe_list_"+relational+"_"+self.element_id, "slide", true, true);
                                }else{
                                    $.mobile.changePage("#oe_list_"+relational+"_"+self.element_id, "slide", true, true);
                                }
                            });
                        }
                    });
                    $.mobile.changePage("#"+self.element_id, "slide", true, true);
                });
        });
    },
    get_fields: function(view_fields, fields) {
        this.fields = fields || [];
        for (var i=0; i < view_fields.length; i++){
            if (view_fields[i].tag == 'field') {
                this.fields.push(view_fields[i]);
            }
            if (view_fields[i].tag == 'group') {
                this.get_fields(view_fields[i].children, this.fields);
            }
        }
        return this.fields;
    }
});
};
<|endoftext|>


<commit_before>/*
Copyright (c) 2011, Chris Umbel

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

var metaphone = require('lib/natural/metaphone');

describe('metaphone', function() {
    metaphone.attach();

    it('should drop duplicate adjacent letters, except C', function() {
        expect(metaphone.dedup('dropping')).toBe('droping');
    });

    it('should not drop duplicat C', function() {
        expect(metaphone.dedup('accelerate')).toBe('accelerate');
    });

    it('should drop some initial letters', function() {
        expect(metaphone.dropInitialLetters('knuth')).toBe('nuth');
        expect(metaphone.dropInitialLetters('gnat')).toBe('nat');
        expect(metaphone.dropInitialLetters('aegis')).toBe('egis');
        expect(metaphone.dropInitialLetters('pneumatic')).toBe('neumatic');
        expect(metaphone.dropInitialLetters('wrack')).toBe('rack');
    });

    it('should not drop other initial letters', function() {
        expect(metaphone.dropInitialLetters('garbage')).toBe('garbage');
    });

    it('should b if if words end with mb', function() {
        expect(metaphone.dropBafterMAtEnd('dumb')).toBe('dum');
    });

    it('should not drop b after m if not at end of word', function() {
        expect(metaphone.dropBafterMAtEnd('dumbo')).toBe('dumbo');
    });

    it('should replace CH to X', function() {
        expect(metaphone.cTransform('change')).toBe('xhange');
    });

    it('should not replace CH to X if part of SCH', function() {
        expect(metaphone.cTransform('discharger')).toBe('diskharger');
    });

    it('should replace CIA to X', function() {
        expect(metaphone.cTransform('aesthetician')).toBe('aesthetixian');
    });

    it('C should become S if followed by I, E, or Y', function() {
        expect(metaphone.cTransform('cieling')).toBe('sieling');
    });

    it('should transform other C\'s to K', function() {
        expect(metaphone.cTransform('cuss')).toBe('kuss');
    });

    it('should transform D to J if followed by GE, GY, GI', function() {
        expect(metaphone.dTransform('abridge')).toBe('abrijge');
    });

    it('should transform D to T if not followed by GE, GY, GI', function() {
        expect(metaphone.dTransform('bid')).toBe('bit');
    });

    it('should drop G before H if not at the end or before vowell', function() {
        expect(metaphone.dropG('alight')).toBe('aliht');
    });

    it('should drop G if followed by N or NED at the end', function() {
        expect(metaphone.dropG('aligned')).toBe('alined');
        expect(metaphone.dropG('align')).toBe('alin');
    });

    it('should transform G to J if followed by I, E or Y and not preceeded by G', function() {
        expect(metaphone.transformG('age')).toBe('aje');
        expect(metaphone.transformG('gin')).toBe('jin');
    });

    it('should transform G to K', function() {
        expect(metaphone.transformG('august')).toBe('aukust');
    });

    it('should reduce GG to G before turning to K', function() {
        expect(metaphone.transformG('aggrade')).toBe('akrade');
    });

    it('should drop H if after vowell and not before vowell', function() {
        expect(metaphone.dropH('alriht')).toBe('alrit');
    });

    it('should not drop H if after vowell', function() {
        expect(metaphone.dropH('that')).toBe('that');
    });

    it('should not drop H if not before vowell', function() {
        expect(metaphone.dropH('chump')).toBe('chump');
    });

    it('should transform CK to K', function() {
        expect(metaphone.transformCK('check')).toBe('chek');
    });

    it('should transform PH to F', function() {
        expect(metaphone.transformPH('phone')).toBe('fone');
    });

    it('should transform Q to K', function() {
        expect(metaphone.transformQ('quack')).toBe('kuack');
    });

    it('should transform S to X if followed by H, IO, or IA', function() {
        expect(metaphone.transformS('shack')).toBe('xhack');
        expect(metaphone.transformS('sialagogues')).toBe('xialagogues');
        expect(metaphone.transformS('asia')).toBe('axia');
    });

    it('should not transform S to X if not followed by H, IO, or IA', function() {
        expect(metaphone.transformS('substance')).toBe('substance');
    });

    it('should transform T to X if followed by IA or IO', function() {
        expect(metaphone.transformT('dementia')).toBe('demenxia');
        expect(metaphone.transformT('abbreviation')).toBe('abbreviaxion');
    });

    it('should transform TH to 0', function() {
        expect(metaphone.transformT('that')).toBe('0at');
    });

    it('should drop T if followed by CH', function() {
        expect(metaphone.dropT('backstitch')).toBe('backstich');
    });

    it('should transform V to F', function() {
        expect(metaphone.transformV('vestige')).toBe('festige');
    });

    it('should transform WH to W if at beginning', function() {
        expect(metaphone.transformWH('whisper')).toBe('wisper');
    });

    it('should drop W if not followed by vowell', function() {
        expect(metaphone.dropW('bowl')).toBe('bol');
        expect(metaphone.dropW('warsaw')).toBe('warsa');
    });

    it('should transform X to S if at beginning', function() {
        expect(metaphone.transformX('xenophile')).toBe('senophile');
    });

    it('should transform X to KS if not at beginning', function() {
        expect(metaphone.transformX('admixed')).toBe('admiksed');
    });

    it('should drop Y of not followed by a vowell', function() {
        expect(metaphone.dropY('analyzer')).toBe('analzer');
        expect(metaphone.dropY('specify')).toBe('specif');
    });

    it('should not drop Y of followed by a vowell', function() {
        expect(metaphone.dropY('allying')).toBe('allying');
    });

    it('should transform Z to S', function() {
        expect(metaphone.transformZ('blaze')).toBe('blase');
    });

    it('should drop all vowels except initial', function() {
        expect(metaphone.dropVowels('ablaze')).toBe('ablz');
        expect(metaphone.dropVowels('adamantium')).toBe('admntm');
    });

    it('should do all', function() {
        expect(metaphone.process('ablaze')).toBe('abls');
        expect(metaphone.process('transition')).toBe('trnsxn');
        expect(metaphone.process('astronomical')).toBe('astrnmkl');
        expect(metaphone.process('buzzard')).toBe('bsrt');
        expect(metaphone.process('wonderer')).toBe('wntrr');
        expect(metaphone.process('district')).toBe('tstrkt');
        expect(metaphone.process('hockey')).toBe('hk');
    });

    it('should compare strings', function() {
        expect(metaphone.compare('phonetics', 'fonetix')).toBeTruthy();
        expect(metaphone.compare('phonetics', 'garbonzo')).toBeFalsy();
    });

    it('should compare strings with string patch', function() {
        expect('phonetics'.soundsLike('fonetix')).toBeTruthy();
        expect('phonetics'.soundsLike('garbonzo')).toBeFalsy();
    });
});
<commit_msg>beffed up tests/docs<commit_after>/*
Copyright (c) 2011, Chris Umbel

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

var metaphone = require('lib/natural/metaphone');

describe('metaphone', function() {
    metaphone.attach();

    it('should drop duplicate adjacent letters, except C', function() {
        expect(metaphone.dedup('dropping')).toBe('droping');
    });

    it('should not drop duplicat C', function() {
        expect(metaphone.dedup('accelerate')).toBe('accelerate');
    });

    it('should drop some initial letters', function() {
        expect(metaphone.dropInitialLetters('knuth')).toBe('nuth');
        expect(metaphone.dropInitialLetters('gnat')).toBe('nat');
        expect(metaphone.dropInitialLetters('aegis')).toBe('egis');
        expect(metaphone.dropInitialLetters('pneumatic')).toBe('neumatic');
        expect(metaphone.dropInitialLetters('wrack')).toBe('rack');
    });

    it('should not drop other initial letters', function() {
        expect(metaphone.dropInitialLetters('garbage')).toBe('garbage');
    });

    it('should b if if words end with mb', function() {
        expect(metaphone.dropBafterMAtEnd('dumb')).toBe('dum');
    });

    it('should not drop b after m if not at end of word', function() {
        expect(metaphone.dropBafterMAtEnd('dumbo')).toBe('dumbo');
    });

    it('should replace CH to X', function() {
        expect(metaphone.cTransform('change')).toBe('xhange');
    });

    it('should not replace CH to X if part of SCH', function() {
        expect(metaphone.cTransform('discharger')).toBe('diskharger');
    });

    it('should replace CIA to X', function() {
        expect(metaphone.cTransform('aesthetician')).toBe('aesthetixian');
    });

    it('C should become S if followed by I, E, or Y', function() {
        expect(metaphone.cTransform('cieling')).toBe('sieling');
    });

    it('should transform other C\'s to K', function() {
        expect(metaphone.cTransform('cuss')).toBe('kuss');
    });

    it('should transform D to J if followed by GE, GY, GI', function() {
        expect(metaphone.dTransform('abridge')).toBe('abrijge');
    });

    it('should transform D to T if not followed by GE, GY, GI', function() {
        expect(metaphone.dTransform('bid')).toBe('bit');
    });

    it('should drop G before H if not at the end or before vowell', function() {
        expect(metaphone.dropG('alight')).toBe('aliht');
    });

    it('should drop G if followed by N or NED at the end', function() {
        expect(metaphone.dropG('aligned')).toBe('alined');
        expect(metaphone.dropG('align')).toBe('alin');
    });

    it('should transform G to J if followed by I, E or Y and not preceeded by G', function() {
        expect(metaphone.transformG('age')).toBe('aje');
        expect(metaphone.transformG('gin')).toBe('jin');
    });

    it('should transform G to K', function() {
        expect(metaphone.transformG('august')).toBe('aukust');
    });

    it('should reduce GG to G before turning to K', function() {
        expect(metaphone.transformG('aggrade')).toBe('akrade');
    });

    it('should drop H if after vowell and not before vowell', function() {
        expect(metaphone.dropH('alriht')).toBe('alrit');
    });

    it('should not drop H if after vowell', function() {
        expect(metaphone.dropH('that')).toBe('that');
    });

    it('should not drop H if not before vowell', function() {
        expect(metaphone.dropH('chump')).toBe('chump');
    });

    it('should transform CK to K', function() {
        expect(metaphone.transformCK('check')).toBe('chek');
    });

    it('should transform PH to F', function() {
        expect(metaphone.transformPH('phone')).toBe('fone');
    });

    it('should transform Q to K', function() {
        expect(metaphone.transformQ('quack')).toBe('kuack');
    });

    it('should transform S to X if followed by H, IO, or IA', function() {
        expect(metaphone.transformS('shack')).toBe('xhack');
        expect(metaphone.transformS('sialagogues')).toBe('xialagogues');
        expect(metaphone.transformS('asia')).toBe('axia');
    });

    it('should not transform S to X if not followed by H, IO, or IA', function() {
        expect(metaphone.transformS('substance')).toBe('substance');
    });

    it('should transform T to X if followed by IA or IO', function() {
        expect(metaphone.transformT('dementia')).toBe('demenxia');
        expect(metaphone.transformT('abbreviation')).toBe('abbreviaxion');
    });

    it('should transform TH to 0', function() {
        expect(metaphone.transformT('that')).toBe('0at');
    });

    it('should drop T if followed by CH', function() {
        expect(metaphone.dropT('backstitch')).toBe('backstich');
    });

    it('should transform V to F', function() {
        expect(metaphone.transformV('vestige')).toBe('festige');
    });

    it('should transform WH to W if at beginning', function() {
        expect(metaphone.transformWH('whisper')).toBe('wisper');
    });

    it('should drop W if not followed by vowell', function() {
        expect(metaphone.dropW('bowl')).toBe('bol');
        expect(metaphone.dropW('warsaw')).toBe('warsa');
    });

    it('should transform X to S if at beginning', function() {
        expect(metaphone.transformX('xenophile')).toBe('senophile');
    });

    it('should transform X to KS if not at beginning', function() {
        expect(metaphone.transformX('admixed')).toBe('admiksed');
    });

    it('should drop Y of not followed by a vowell', function() {
        expect(metaphone.dropY('analyzer')).toBe('analzer');
        expect(metaphone.dropY('specify')).toBe('specif');
    });

    it('should not drop Y of followed by a vowell', function() {
        expect(metaphone.dropY('allying')).toBe('allying');
    });

    it('should transform Z to S', function() {
        expect(metaphone.transformZ('blaze')).toBe('blase');
    });

    it('should drop all vowels except initial', function() {
        expect(metaphone.dropVowels('ablaze')).toBe('ablz');
        expect(metaphone.dropVowels('adamantium')).toBe('admntm');
    });

    it('should do all', function() {
        expect(metaphone.process('ablaze')).toBe('abls');
        expect(metaphone.process('transition')).toBe('trnsxn');
        expect(metaphone.process('astronomical')).toBe('astrnmkl');
        expect(metaphone.process('buzzard')).toBe('bsrt');
        expect(metaphone.process('wonderer')).toBe('wntrr');
        expect(metaphone.process('district')).toBe('tstrkt');
        expect(metaphone.process('hockey')).toBe('hk');
        expect(metaphone.process('capital')).toBe('kptl');
        expect(metaphone.process('penguin')).toBe('pnkn');
        expect(metaphone.process('garbonzo')).toBe('krbns');
    });

    it('should compare strings', function() {
        expect(metaphone.compare('phonetics', 'fonetix')).toBeTruthy();
        expect(metaphone.compare('phonetics', 'garbonzo')).toBeFalsy();
    });

    it('should compare strings with string patch', function() {
        expect('phonetics'.soundsLike('fonetix')).toBeTruthy();
        expect('phonetics'.soundsLike('garbonzo')).toBeFalsy();
    });
});
<|endoftext|>