3 var instance = openerp;
5 instance.web.Tip = instance.web.Class.extend({
9 self.tip_mutex = new $.Mutex();
13 var Tips = new instance.web.Model('web.tip');
14 Tips.query(['title', 'description', 'action_id', 'model', 'type', 'mode', 'trigger_selector',
15 'highlight_selector', 'end_selector', 'end_event', 'placement', 'is_consumed'])
16 .all().then(function(tips) {
21 instance.web.bus.on('action', this, function(action) {
22 self.on_action(action);
25 instance.web.bus.on('view_shown', this, function(view) {
26 if (_.keys(view.fields_view).length === 0) {
27 view.on('view_loaded', this, function(fields_view) {
34 view.on('switch_mode', this, function() {
38 instance.web.bus.on('view_switch_mode', this, function(viewManager, mode) {
39 self.on_switch(viewManager, mode);
42 instance.web.bus.on('form_view_shown', this, function(formView) {
43 self.on_form_view(formView);
46 instance.web.bus.on('form_view_saved', this, function(formView) {
47 self.on_form_view(formView);
52 on_action: function(action) {
54 var action_id = action.id;
55 var model = action.res_model;
58 on_view: function(view) {
60 var fields_view = view.fields_view;
61 var action_id = view.ViewManager.action ? view.ViewManager.action.id : null;
62 var model = fields_view.model;
65 if(fields_view.type === 'kanban') {
66 var dataset_def = $.Deferred();
67 var groups_def = $.Deferred();
68 view.on("kanban_dataset_processed", self, function() {
69 var length = view.dataset.ids.length;
70 dataset_def.resolve(length);
72 view.on('kanban_groups_processed', self, function() {
75 dataset_def.done(function(length) {
76 self.eval_tip(action_id, model, fields_view.type);
78 groups_def.done(function() {
79 self.eval_tip(action_id, model, fields_view.type);
84 on_form_view: function(formView) {
86 var model = formView.model;
87 var type = formView.datarecord.type ? formView.datarecord.type : null;
89 self.eval_tip(null, model, mode, type);
93 on_switch: function (viewManager, mode) {
95 var action = viewManager.action;
96 var action_id = action.id;
97 var model = action.res_model;
100 eval_tip: function(action_id, model, mode, type) {
106 valid_tips = _.filter(self.tips, function (tip) {
107 return tip.action_id[0] === action_id;
111 filter.model = model;
113 tips = _.where(self.tips, filter);
115 tips = _.filter(tips, function(tip) {
119 return tip.type === type;
123 valid_tips = _.uniq(valid_tips.concat(tips));
124 _.each(valid_tips, function(tip) {
125 if (!tip.is_consumed) {
132 add_tip: function(tip) {
134 self.tip_mutex.exec(function() {
135 return $.when(self.do_tip(tip));
139 do_tip: function (tip) {
141 var def = $.Deferred();
142 var Tips = new instance.web.Model('web.tip');
143 var highlight_selector = tip.highlight_selector;
144 var triggers = tip.trigger_selector ? tip.trigger_selector.split(',') : [];
145 var trigger_tip = true;
147 if(!$(highlight_selector).length > 0) {
150 for (var i = 0; i < triggers.length; i++) {
151 if(!$(triggers[i]).length > 0) {
157 self.$element = $(highlight_selector).first();
158 var _top = self.$element.offset().top -5;
159 var _left = self.$element.offset().left -5;
160 var _width = self.$element.outerWidth() + 10;
161 var _height = self.$element.outerHeight() + 10;
163 self.$helper = $("<div>", { class: 'oe_tip_helper' });
164 self.$element.after(self.$helper);
165 self.$helper.offset({top: _top , left: _left});
166 self.$helper.width(_width);
167 self.$helper.height(_height);
169 self.$overlay = $("<div>", { class: 'oe_tip_overlay' });
170 $('body').append(self.$overlay);
171 self.$element.addClass('oe_tip_show_element');
173 // fix the stacking context problem
174 _.each(self.$element.parentsUntil('body'), function(el) {
175 var zIndex = $(el).css('z-index');
176 var opacity = parseFloat($(el).css('opacity'));
178 if (/[0-9]+/.test(zIndex) || opacity < 1) {
179 $(el).addClass('oe_tip_fix_parent');
183 self.$element.popover({
184 placement: tip.placement,
186 content: tip.description,
191 var $cross = $('<button type="button" class="close">×</button>');
192 $cross.addClass('oe_tip_close');
195 $('.popover-title').prepend($cross);
197 $('.popover-content').prepend($cross);
201 tip.end_selector = tip.end_selector ? tip.end_selector : tip.highlight_selector;
202 $(tip.end_selector).one(tip.end_event, function($ev) {
208 $cross.on('click', function($ev) {
212 self.$overlay.on('click', function($ev) {
216 $(document).on('keyup.web_tip', function($ev) {
217 if ($ev.which === 27) { // esc
228 end_tip: function(tip) {
230 var Tips = new instance.web.Model('web.tip');
231 self.$element.popover('destroy');
232 self.$overlay.remove();
233 self.$helper.remove();
234 self.$element.removeClass('oe_tip_show_element');
235 _.each($('.oe_tip_fix_parent'), function(el) {
236 $(el).removeClass('oe_tip_fix_parent');
238 $(document).off('keyup.web_tip');
239 Tips.call('consume', [tip.id], {});
240 tip.is_consumed = true;
244 instance.web.WebClient = instance.web.WebClient.extend({
245 show_application: function() {
247 this.tip_handler = new instance.web.Tip();