merged with trunk
bzr revid: dhr@tinyerp.com-20120725045258-xp2ujf7b4dn8v2ms
This commit is contained in:
@@ -20,6 +20,7 @@
|
||||
"static/lib/jquery.form/jquery.form.js",
|
||||
"static/lib/jquery.validate/jquery.validate.js",
|
||||
"static/lib/jquery.ba-bbq/jquery.ba-bbq.js",
|
||||
"static/lib/spinjs/spin.js",
|
||||
"static/lib/jquery.blockUI/jquery.blockUI.js",
|
||||
"static/lib/jquery.ui/js/jquery-ui-1.8.17.custom.min.js",
|
||||
"static/lib/jquery.ui.timepicker/js/jquery-ui-timepicker-addon.js",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@charset "UTF-8";
|
||||
@charset "utf-8";
|
||||
@font-face {
|
||||
font-family: "mnmliconsRegular";
|
||||
src: url("/web/static/src/font/mnmliconsv21-webfont.eot") format("eot");
|
||||
@@ -1408,20 +1408,31 @@
|
||||
filter: alpha(opacity=50);
|
||||
opacity: 0.5;
|
||||
}
|
||||
.openerp .oe_searchview .oe_searchview_search {
|
||||
font-size: 1px;
|
||||
letter-spacing: -1px;
|
||||
color: transparent;
|
||||
-moz-box-shadow: none;
|
||||
-webkit-box-shadow: none;
|
||||
box-shadow: none;
|
||||
-moz-border-radius: 0;
|
||||
-webkit-border-radius: 0;
|
||||
border-radius: 0;
|
||||
position: absolute;
|
||||
left: 3px;
|
||||
top: 1px;
|
||||
padding: 0;
|
||||
border: none;
|
||||
background: transparent;
|
||||
}
|
||||
.openerp .oe_searchview .oe_searchview_search:before {
|
||||
font: 21px "mnmliconsRegular";
|
||||
content: "r";
|
||||
color: #a3a3a3;
|
||||
}
|
||||
.openerp .oe_searchview .oe_searchview_facets {
|
||||
min-height: 22px;
|
||||
}
|
||||
.openerp .oe_searchview .oe_searchview_facets:before {
|
||||
color: #cccccc;
|
||||
font-family: "mnmliconsRegular";
|
||||
content: "r";
|
||||
font-size: 130%;
|
||||
display: inline;
|
||||
position: relative;
|
||||
left: 6px;
|
||||
top: 2px;
|
||||
color: #a3a3a3;
|
||||
padding-right: 4px;
|
||||
margin-left: 15px;
|
||||
}
|
||||
.openerp .oe_searchview .oe_searchview_facets * {
|
||||
vertical-align: top;
|
||||
@@ -2180,7 +2191,7 @@
|
||||
height: auto;
|
||||
line-height: 16px;
|
||||
}
|
||||
.openerp .oe_form_field_one2many .oe_list_buttons.oe_editing .oe_list_save {
|
||||
.openerp .oe_form_field_one2many .oe_list_buttons.oe_editing .oe_list_save, .openerp .oe_form_field_many2many .oe_list_buttons.oe_editing .oe_list_save {
|
||||
visibility: hidden;
|
||||
}
|
||||
.openerp .oe_form .oe_form_field_many2many > .oe_list .oe_list_pager_single_page {
|
||||
@@ -2266,9 +2277,6 @@
|
||||
padding: 3px 6px;
|
||||
white-space: pre-line;
|
||||
}
|
||||
.openerp .oe_list_content > tbody > tr > td.oe_list_field_cell progress {
|
||||
width: 100%;
|
||||
}
|
||||
.openerp .oe_list_content > tbody > tr > td > button, .openerp .oe_list_content > tbody > tr > th > button {
|
||||
border: none;
|
||||
background: transparent;
|
||||
@@ -2441,19 +2449,6 @@
|
||||
.kitten-mode-activated > * {
|
||||
opacity: 0.7;
|
||||
}
|
||||
.kitten-mode-activated .oe_footer a {
|
||||
background-image: url(http://www.risacher.com/la-rache/zfiles/la-rache.png);
|
||||
font-size: 1px;
|
||||
letter-spacing: -1px;
|
||||
color: transparent;
|
||||
display: inline-block;
|
||||
height: 15px;
|
||||
width: 80px;
|
||||
vertical-align: top;
|
||||
}
|
||||
.kitten-mode-activated .oe_footer a span {
|
||||
display: none;
|
||||
}
|
||||
|
||||
div.ui-widget-overlay {
|
||||
background: black;
|
||||
|
||||
@@ -1101,19 +1101,20 @@ $sheet-max-width: 860px
|
||||
border-right: 5px solid transparent
|
||||
@include opacity()
|
||||
|
||||
.oe_searchview_search
|
||||
@include text-to-icon("r", #a3a3a3)
|
||||
@include box-shadow(none)
|
||||
@include radius(0)
|
||||
position: absolute
|
||||
left: 3px
|
||||
top: 1px
|
||||
padding: 0
|
||||
border: none
|
||||
background: transparent
|
||||
|
||||
.oe_searchview_facets
|
||||
min-height: 22px
|
||||
&:before
|
||||
color: #ccc
|
||||
font-family: "mnmliconsRegular"
|
||||
content: "r"
|
||||
font-size: 130%
|
||||
display: inline
|
||||
position: relative
|
||||
left: 6px
|
||||
top: 2px
|
||||
color: #a3a3a3
|
||||
padding-right: 4px
|
||||
margin-left: 15px
|
||||
*
|
||||
vertical-align: top
|
||||
display: inline-block
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 7.0 KiB |
@@ -257,7 +257,7 @@ instance.web.Loading = instance.web.Widget.extend({
|
||||
// Block UI after 3s
|
||||
this.long_running_timer = setTimeout(function () {
|
||||
self.blocked_ui = true;
|
||||
$.blockUI();
|
||||
instance.web.blockUI();
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
@@ -276,7 +276,7 @@ instance.web.Loading = instance.web.Widget.extend({
|
||||
// Don't unblock if blocked by somebody else
|
||||
if (self.blocked_ui) {
|
||||
this.blocked_ui = false;
|
||||
$.unblockUI();
|
||||
instance.web.unblockUI();
|
||||
}
|
||||
this.$element.fadeOut();
|
||||
this.getParent().$element.removeClass('oe_wait');
|
||||
@@ -287,7 +287,7 @@ instance.web.Loading = instance.web.Widget.extend({
|
||||
instance.web.DatabaseManager = instance.web.Widget.extend({
|
||||
init: function(parent) {
|
||||
this._super(parent);
|
||||
this.unblockUIFunction = $.unblockUI;
|
||||
this.unblockUIFunction = instance.web.unblockUI;
|
||||
$.validator.addMethod('matches', function (s, _, re) {
|
||||
return new RegExp(re).test(s);
|
||||
}, _t("Invalid database name"));
|
||||
@@ -354,16 +354,16 @@ instance.web.DatabaseManager = instance.web.Widget.extend({
|
||||
* from unblocking the UI
|
||||
*/
|
||||
blockUI: function () {
|
||||
$.blockUI();
|
||||
$.unblockUI = function () {};
|
||||
instance.web.blockUI();
|
||||
instance.web.unblockUI = function () {};
|
||||
},
|
||||
/**
|
||||
* Reinstates $.unblockUI so third parties can play with blockUI, and
|
||||
* unblocks the UI
|
||||
*/
|
||||
unblockUI: function () {
|
||||
$.unblockUI = this.unblockUIFunction;
|
||||
$.unblockUI();
|
||||
instance.web.unblockUI = this.unblockUIFunction;
|
||||
instance.web.unblockUI();
|
||||
},
|
||||
/**
|
||||
* Displays an error dialog resulting from the various RPC communications
|
||||
|
||||
@@ -550,7 +550,39 @@ $.async_when = function() {
|
||||
/** Setup blockui */
|
||||
if ($.blockUI) {
|
||||
$.blockUI.defaults.baseZ = 1100;
|
||||
$.blockUI.defaults.message = '<img src="/web/static/src/img/throbber2.gif">';
|
||||
$.blockUI.defaults.message = '<div class="oe_blockui_spin" style="height: 50px">';
|
||||
$.blockUI.defaults.css.border = '0';
|
||||
$.blockUI.defaults.css["background-color"] = '';
|
||||
$.blockUI.spinners = [];
|
||||
}
|
||||
instance.web.blockUI = function() {
|
||||
var tmp = $.blockUI.apply($, arguments);
|
||||
var target = $(".oe_blockui_spin")[0];
|
||||
var opts = {
|
||||
lines: 13, // The number of lines to draw
|
||||
length: 7, // The length of each line
|
||||
width: 4, // The line thickness
|
||||
radius: 10, // The radius of the inner circle
|
||||
rotate: 0, // The rotation offset
|
||||
color: '#FFF', // #rgb or #rrggbb
|
||||
speed: 1, // Rounds per second
|
||||
trail: 60, // Afterglow percentage
|
||||
shadow: false, // Whether to render a shadow
|
||||
hwaccel: false, // Whether to use hardware acceleration
|
||||
className: 'spinner', // The CSS class to assign to the spinner
|
||||
zIndex: 2e9, // The z-index (defaults to 2000000000)
|
||||
top: 'auto', // Top position relative to parent in px
|
||||
left: 'auto' // Left position relative to parent in px
|
||||
};
|
||||
var spinner = new Spinner(opts).spin(target);
|
||||
$.blockUI.spinners.push(spinner);
|
||||
return tmp;
|
||||
}
|
||||
instance.web.unblockUI = function() {
|
||||
_.each($.blockUI.spinners, function(el) {
|
||||
el.stop();
|
||||
});
|
||||
return $.unblockUI.apply($, arguments);
|
||||
}
|
||||
|
||||
/** Setup default session */
|
||||
|
||||
@@ -376,7 +376,7 @@ instance.web.DataExport = instance.web.Dialog.extend({
|
||||
|
||||
exported_fields.unshift({name: 'id', label: 'External ID'});
|
||||
var export_format = this.$element.find("#export_format").val();
|
||||
$.blockUI();
|
||||
instance.web.blockUI();
|
||||
this.session.get_file({
|
||||
url: '/web/export/' + export_format,
|
||||
data: {data: JSON.stringify({
|
||||
@@ -387,7 +387,7 @@ instance.web.DataExport = instance.web.Dialog.extend({
|
||||
import_compat: Boolean(
|
||||
this.$element.find("#import_compat").val())
|
||||
})},
|
||||
complete: $.unblockUI
|
||||
complete: instance.web.unblockUI
|
||||
});
|
||||
},
|
||||
close: function() {
|
||||
|
||||
@@ -330,6 +330,12 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea
|
||||
});
|
||||
}
|
||||
|
||||
// Launch a search on clicking the oe_searchview_search button
|
||||
this.$element.on('click', 'button.oe_searchview_search', function (e) {
|
||||
e.stopImmediatePropagation();
|
||||
self.do_search();
|
||||
});
|
||||
|
||||
this.$element.on('keydown',
|
||||
'.oe_searchview_input, .oe_searchview_facet', function (e) {
|
||||
switch(e.which) {
|
||||
@@ -1475,7 +1481,17 @@ instance.web.search.ManyToOneField = instance.web.search.CharField.extend({
|
||||
facet_for: function (value) {
|
||||
var self = this;
|
||||
if (value instanceof Array) {
|
||||
return $.when(facet_from(this, value));
|
||||
if (value.length === 2 && _.isString(value[1])) {
|
||||
return $.when(facet_from(this, value));
|
||||
}
|
||||
if (value.length > 1) {
|
||||
// more than one search_default m2o id? Should we OR them?
|
||||
throw new Error(
|
||||
_("M2O search fields do not currently handle multiple default values"));
|
||||
}
|
||||
// there are many cases of {search_default_$m2ofield: [id]}, need
|
||||
// to handle this as if it were a single value.
|
||||
value = value[0];
|
||||
}
|
||||
return this.model.call('name_get', [value], {}).pipe(function (names) {
|
||||
if (_(names).isEmpty()) { return null; }
|
||||
|
||||
@@ -3027,8 +3027,11 @@ instance.web.form.FieldOne2Many = instance.web.form.AbstractField.extend({
|
||||
this.viewmanager.on_controller_inited.add_last(function(view_type, controller) {
|
||||
controller.o2m = self;
|
||||
if (view_type == "list") {
|
||||
if (self.get("effective_readonly"))
|
||||
controller.set_editable(false);
|
||||
if (self.get("effective_readonly")) {
|
||||
controller.on('edit:before', self, function (e) {
|
||||
e.cancel = true;
|
||||
});
|
||||
}
|
||||
} else if (view_type === "form") {
|
||||
if (self.get("effective_readonly")) {
|
||||
$(".oe_form_buttons", controller.$element).children().remove();
|
||||
@@ -3301,7 +3304,7 @@ instance.web.form.One2ManyListView = instance.web.ListView.extend({
|
||||
.value();
|
||||
},
|
||||
do_add_record: function () {
|
||||
if (this.options.editable) {
|
||||
if (this.editable()) {
|
||||
this._super.apply(this, arguments);
|
||||
} else {
|
||||
var self = this;
|
||||
@@ -4108,10 +4111,12 @@ instance.web.form.SelectCreatePopup = instance.web.form.AbstractFormPopup.extend
|
||||
self.dataset, false,
|
||||
_.extend({'deletable': false,
|
||||
'selectable': !self.options.disable_multiple_selection,
|
||||
'read_only': true,
|
||||
'import_enabled': false,
|
||||
'$buttons': self.$buttonpane,
|
||||
}, self.options.list_view_options || {}));
|
||||
self.view_list.on('edit:before', self, function (e) {
|
||||
e.cancel = true;
|
||||
});
|
||||
self.view_list.popup = self;
|
||||
self.view_list.appendTo($(".oe_popup_list", self.$element)).pipe(function() {
|
||||
self.view_list.do_show();
|
||||
@@ -4343,7 +4348,7 @@ instance.web.form.FieldBinary = instance.web.form.AbstractField.extend(instance.
|
||||
//link.target = '_blank';
|
||||
link.href = "data:application/octet-stream;base64," + value;
|
||||
} else {
|
||||
$.blockUI();
|
||||
instance.web.blockUI();
|
||||
this.session.get_file({
|
||||
url: '/web/binary/saveas_ajax',
|
||||
data: {data: JSON.stringify({
|
||||
@@ -4353,7 +4358,7 @@ instance.web.form.FieldBinary = instance.web.form.AbstractField.extend(instance.
|
||||
filename_field: (this.node.attrs.filename || ''),
|
||||
context: this.view.dataset.get_context()
|
||||
})},
|
||||
complete: $.unblockUI,
|
||||
complete: instance.web.unblockUI,
|
||||
error: instance.webclient.crashmanager.on_rpc_error
|
||||
});
|
||||
ev.stopPropagation();
|
||||
|
||||
@@ -21,9 +21,6 @@ instance.web.ListView = instance.web.View.extend( /** @lends instance.web.ListVi
|
||||
// whether the view rows can be reordered (via vertical drag & drop)
|
||||
'reorderable': true,
|
||||
'action_buttons': true,
|
||||
// if true, the view can't be editable, ignoring the view's and the context's
|
||||
// instructions
|
||||
'read_only': false,
|
||||
// if true, the 'Import', 'Export', etc... buttons will be shown
|
||||
'import_enabled': true,
|
||||
},
|
||||
|
||||
@@ -12,6 +12,8 @@ openerp.web.list_editable = function (instance) {
|
||||
var self = this;
|
||||
this._super.apply(this, arguments);
|
||||
|
||||
this._force_editability = null;
|
||||
this._context_editable = false;
|
||||
this.editor = this.make_editor();
|
||||
// Stores records of {field, cell}, allows for re-rendering fields
|
||||
// depending on cell state during and after resize events
|
||||
@@ -37,6 +39,11 @@ openerp.web.list_editable = function (instance) {
|
||||
}
|
||||
});
|
||||
|
||||
this.on('edit:before', this, function (event) {
|
||||
if (!self.editable() || self.editor.is_editing()) {
|
||||
event.cancel = true;
|
||||
}
|
||||
});
|
||||
this.on('edit:after', this, function () {
|
||||
self.$element.add(self.$buttons).addClass('oe_editing');
|
||||
});
|
||||
@@ -62,26 +69,16 @@ openerp.web.list_editable = function (instance) {
|
||||
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) {
|
||||
// TODO: fix handling of editability status to be simpler & clearer & more coherent
|
||||
// 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 = (
|
||||
! this.options.read_only && ((force && "bottom") || this.defaults.editable));
|
||||
editable: function () {
|
||||
return this.fields_view.arch.attrs.editable
|
||||
|| this._context_editable
|
||||
|| this.options.editable;
|
||||
},
|
||||
/**
|
||||
* Replace do_search to handle editability process
|
||||
*/
|
||||
do_search: function(domain, context, group_by) {
|
||||
this.set_editable(context['set_editable']);
|
||||
this._context_editable = !!context.set_editable;
|
||||
this._super.apply(this, arguments);
|
||||
},
|
||||
/**
|
||||
@@ -89,7 +86,7 @@ openerp.web.list_editable = function (instance) {
|
||||
* as an editable row at the top or bottom of the list)
|
||||
*/
|
||||
do_add_record: function () {
|
||||
if (this.options.editable) {
|
||||
if (this.editable()) {
|
||||
this.$element.find('table:first').show();
|
||||
this.$element.find('.oe_view_nocontent').remove();
|
||||
this.start_edition();
|
||||
@@ -103,9 +100,8 @@ openerp.web.list_editable = function (instance) {
|
||||
this.editor.destroy();
|
||||
}
|
||||
// tree/@editable takes priority on everything else if present.
|
||||
this.options.editable = ! this.options.read_only && (data.arch.attrs.editable || this.options.editable);
|
||||
var result = this._super(data, grouped);
|
||||
if (this.options.editable) {
|
||||
if (this.editable()) {
|
||||
// FIXME: any hook available to ensure this is only done once?
|
||||
this.$buttons
|
||||
.off('click', '.oe_list_save')
|
||||
@@ -202,12 +198,20 @@ openerp.web.list_editable = function (instance) {
|
||||
return;
|
||||
}
|
||||
|
||||
// FIXME: need better way to get the field back from bubbling (delegated) DOM events somehow
|
||||
field.$element.attr('data-fieldname', field_name);
|
||||
self.fields_for_resize.push({field: field, cell: cell});
|
||||
}, options).pipe(function () {
|
||||
$recordRow.addClass('oe_edition');
|
||||
self.resize_fields();
|
||||
return record.attributes;
|
||||
});
|
||||
}).fail(function () {
|
||||
// if the start_edition event is cancelled and it was a
|
||||
// creation, remove the newly-created empty record
|
||||
if (!record.get('id')) {
|
||||
self.records.remove(record);
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
@@ -377,7 +381,7 @@ openerp.web.list_editable = function (instance) {
|
||||
return this.reload_record(record);
|
||||
},
|
||||
prepends_on_create: function () {
|
||||
return this.options.editable === 'top';
|
||||
return this.editable() === 'top';
|
||||
},
|
||||
setup_events: function () {
|
||||
var self = this;
|
||||
@@ -399,18 +403,20 @@ openerp.web.list_editable = function (instance) {
|
||||
*
|
||||
* @private
|
||||
* @param {String} [next_record='succ'] method to call on the records collection to get the next record to edit
|
||||
* @param {Object} [options]
|
||||
* @param {String} [options.focus_field]
|
||||
* @return {*}
|
||||
*/
|
||||
_next: function (next_record) {
|
||||
_next: function (next_record, options) {
|
||||
next_record = next_record || 'succ';
|
||||
var self = this;
|
||||
return this.save_edition().pipe(function (saveInfo) {
|
||||
if (saveInfo.created) {
|
||||
return self.start_edition();
|
||||
}
|
||||
return self.start_edition(
|
||||
self.records[next_record](
|
||||
saveInfo.record, {wraparound: true}));
|
||||
var record = self.records[next_record](
|
||||
saveInfo.record, {wraparound: true});
|
||||
return self.start_edition(record, options);
|
||||
});
|
||||
},
|
||||
keyup_ENTER: function () {
|
||||
@@ -440,25 +446,80 @@ openerp.web.list_editable = function (instance) {
|
||||
}
|
||||
return selection.start;
|
||||
},
|
||||
keydown_UP: function (e) {
|
||||
/**
|
||||
* @param DOMEvent event
|
||||
* @param {String} record_direction direction to move into to get the next record (pred | succ)
|
||||
* @param {Function} is_valid_move whether the edition should be moved to the next record
|
||||
* @private
|
||||
*/
|
||||
_key_move_record: function (event, record_direction, is_valid_move) {
|
||||
if (!this.editor.is_editing('edit')) { return $.when(); }
|
||||
// FIXME: assumes editable widgets are input-type elements
|
||||
var index = this._text_cursor(e.target);
|
||||
var index = this._text_cursor(event.target);
|
||||
// If selecting or not at the start of the input
|
||||
if (index === null || index !== 0) { return $.when(); }
|
||||
if (!is_valid_move(event.target, index)) { return $.when(); }
|
||||
|
||||
e.preventDefault();
|
||||
return this._next('pred');
|
||||
event.preventDefault();
|
||||
var source_field = $(event.target).closest('[data-fieldname]')
|
||||
.attr('data-fieldname');
|
||||
return this._next(record_direction, {focus_field: source_field});
|
||||
|
||||
},
|
||||
keydown_UP: function (e) {
|
||||
return this._key_move_record(e, 'pred', function (el, index) {
|
||||
return index === 0;
|
||||
});
|
||||
},
|
||||
keydown_DOWN: function (e) {
|
||||
if (!this.editor.is_editing('edit')) { return $.when(); }
|
||||
// FIXME: assumes editable widgets are input-type elements
|
||||
var index = this._text_cursor(e.target);
|
||||
// If selecting or not at the end of the input
|
||||
if (index === null || index !== e.target.value.length) { return $.when(); }
|
||||
return this._key_move_record(e, 'succ', function (el, index) {
|
||||
return index === el.value.length;
|
||||
});
|
||||
},
|
||||
|
||||
e.preventDefault();
|
||||
return this._next();
|
||||
keydown_LEFT: function (e) {
|
||||
// If the cursor is at the beginning of the field
|
||||
var source_field = $(e.target).closest('[data-fieldname]')
|
||||
.attr('data-fieldname');
|
||||
var index = this._text_cursor(e.target);
|
||||
if (index !== 0) { return $.when(); }
|
||||
|
||||
var fields_order = this.editor.form.fields_order;
|
||||
var field_index = _(fields_order).indexOf(source_field);
|
||||
|
||||
// Look for the closest visible form field to the left
|
||||
var fields = this.editor.form.fields;
|
||||
var field;
|
||||
do {
|
||||
if (--field_index < 0) { return $.when(); }
|
||||
|
||||
field = fields[fields_order[field_index]];
|
||||
} while (!field.$element.is(':visible'));
|
||||
|
||||
// and focus it
|
||||
field.focus();
|
||||
return $.when();
|
||||
},
|
||||
keydown_RIGHT: function (e) {
|
||||
// same as above, but with cursor at the end of the field and
|
||||
// looking for new fields at the right
|
||||
var source_field = $(e.target).closest('[data-fieldname]')
|
||||
.attr('data-fieldname');
|
||||
var index = this._text_cursor(e.target);
|
||||
if (index !== e.target.value.length) { return $.when(); }
|
||||
|
||||
var fields_order = this.editor.form.fields_order;
|
||||
var field_index = _(fields_order).indexOf(source_field);
|
||||
|
||||
var fields = this.editor.form.fields;
|
||||
var field;
|
||||
do {
|
||||
if (++field_index >= fields_order.length) { return $.when(); }
|
||||
|
||||
field = fields[fields_order[field_index]];
|
||||
} while (!field.$element.is(':visible'));
|
||||
|
||||
field.focus();
|
||||
return $.when();
|
||||
},
|
||||
keydown_TAB: function (e) {
|
||||
var form = this.editor.form;
|
||||
@@ -642,7 +703,7 @@ openerp.web.list_editable = function (instance) {
|
||||
|
||||
instance.web.ListView.List.include(/** @lends instance.web.ListView.List# */{
|
||||
row_clicked: function (event) {
|
||||
if (!this.options.editable) {
|
||||
if (!this.view.editable()) {
|
||||
return this._super.apply(this, arguments);
|
||||
}
|
||||
var record_id = $(event.currentTarget).data('id');
|
||||
|
||||
@@ -274,7 +274,7 @@ instance.web.ActionManager = instance.web.Widget.extend({
|
||||
},
|
||||
ir_actions_report_xml: function(action, on_closed) {
|
||||
var self = this;
|
||||
$.blockUI();
|
||||
instance.web.blockUI();
|
||||
self.rpc("/web/session/eval_domain_and_context", {
|
||||
contexts: [action.context],
|
||||
domains: []
|
||||
@@ -284,7 +284,7 @@ instance.web.ActionManager = instance.web.Widget.extend({
|
||||
self.session.get_file({
|
||||
url: '/web/report',
|
||||
data: {action: JSON.stringify(action)},
|
||||
complete: $.unblockUI,
|
||||
complete: instance.web.unblockUI,
|
||||
success: function(){
|
||||
if (!self.dialog && on_closed) {
|
||||
on_closed();
|
||||
@@ -841,7 +841,7 @@ instance.web.Sidebar = instance.web.Widget.extend({
|
||||
} else {
|
||||
self.do_attachement_update(self.dataset, self.model_id);
|
||||
}
|
||||
$.unblockUI();
|
||||
instance.web.unblockUI();
|
||||
});
|
||||
},
|
||||
start: function() {
|
||||
@@ -980,7 +980,7 @@ instance.web.Sidebar = instance.web.Widget.extend({
|
||||
$e.parent().find('input[type=file]').prop('disabled', true);
|
||||
$e.parent().find('button').prop('disabled', true).find('img, span').toggle();
|
||||
this.$('.oe_sidebar_add_attachment span').text(_t('Uploading...'));
|
||||
$.blockUI();
|
||||
instance.web.blockUI();
|
||||
}
|
||||
},
|
||||
on_attachment_delete: function(e) {
|
||||
|
||||
@@ -1220,6 +1220,8 @@
|
||||
<div class="oe_searchview_clear"/>
|
||||
<div class="oe_searchview_unfold_drawer" title="Advanced Search..."/>
|
||||
<div class="oe_searchview_drawer"/>
|
||||
<button type="button" class="oe_searchview_search"
|
||||
title="Search Again">Search</button>
|
||||
</div>
|
||||
|
||||
<div t-name="SearchView.InputView"
|
||||
|
||||
@@ -47,3 +47,9 @@ Undocumented stuff
|
||||
|
||||
* What is the difference between ``readonly`` and
|
||||
``effective_readonly``?
|
||||
|
||||
* No facilities for DOM events handling/delegations e.g. handling
|
||||
keyup/keydown/keypress from a form fields into the form's user.
|
||||
|
||||
* Also no way to reverse from a DOM node (e.g. DOMEvent#target) back to a
|
||||
form view field easily
|
||||
|
||||
+30
-19
@@ -87,34 +87,37 @@ List view edition is an extension to the base listview providing the
|
||||
capability of inline record edition by delegating to an embedded form
|
||||
view.
|
||||
|
||||
.. todo::
|
||||
Editability status
|
||||
++++++++++++++++++
|
||||
|
||||
cleanup options and settings for editability configuration. Right
|
||||
now there are:
|
||||
The editability status of a list view can be queried through the
|
||||
:js:func:`~openerp.web.ListView.editable` method, will return a falsy
|
||||
value if the listview is not currently editable.
|
||||
|
||||
``defaults.editable``
|
||||
The editability status is based on three flags:
|
||||
|
||||
``null``, ``"top"`` or ``"bottom"``, generally broken and
|
||||
useless
|
||||
``tree/@editable``
|
||||
|
||||
``context.set_editable``
|
||||
If present, can be either ``"top"`` or ``"bottom"``. Either will
|
||||
make the list view editable, with new records being respectively
|
||||
created at the top or at the bottom of the view.
|
||||
|
||||
forces ``options.editable`` to ``"bottom"``
|
||||
``context.set_editable``
|
||||
|
||||
``view.arch.attrs.editable``
|
||||
Boolean flag extracted from a search context (during the
|
||||
:js:func:`~openerp.web.ListView.do_search`` handler), ``true``
|
||||
will make the view editable (from the top), ``false`` or the
|
||||
absence of the flag is a noop.
|
||||
|
||||
same as ``defaults.editable``, but applied separately (after
|
||||
reloading the view), if absent delegates to
|
||||
``options.editable`` which may have been set previously.
|
||||
``defaults.editable``
|
||||
|
||||
``options.read_only``
|
||||
Like ``tree/@editable``, one of absent (``null``)), ``"top"`` or
|
||||
``"bottom"``, fallback for the list view if none of the previous
|
||||
two flags are set.
|
||||
|
||||
force options.editable to false, or something?
|
||||
|
||||
.. note:: can probably be replaced by cancelling ``edit:before``
|
||||
|
||||
and :js:func:`~openerp.web.ListView.set_editable` which
|
||||
ultimately behaves weird-as-fuck-ly.
|
||||
These three flags can only *make* a listview editable, they can *not*
|
||||
override a previously set flag. To do that, a listview user should
|
||||
instead cancel :ref:`the edit:before event <listview-edit-before>`.
|
||||
|
||||
The editable list view module adds a number of methods to the list
|
||||
view, on top of implementing the :js:class:`EditorDelegate` protocol:
|
||||
@@ -219,6 +222,14 @@ view provides a number of dedicated events to its lifecycle.
|
||||
abort its current behavior as soon as possible, and rollback
|
||||
any state modification.
|
||||
|
||||
Generally speaking, an event should only be cancelled (by
|
||||
setting the ``cancel`` flag to ``true``), uncancelling an
|
||||
event is undefined as event handlers are executed on a
|
||||
first-come-first-serve basis and later handlers may
|
||||
re-cancel an uncancelled event.
|
||||
|
||||
.. _listview-edit-before:
|
||||
|
||||
``edit:before`` *cancellable*
|
||||
|
||||
Invoked before the list view starts editing a record.
|
||||
|
||||
Reference in New Issue
Block a user