');
+ doc_bar.append(doc_el);
+
+ doc_bar.css({"left": width+10 + "px" });
+ doc_bar.css({"position": "absolute" });
+ $(el).append(doc_bar);
+
+ }
+ else {
+
+ doc_bar = $('
');
+ doc_bar.append(doc_el);
+
+ el = widget.$el;
+ find_el = $(el).find(".task-gantt-bar-plan-info-end");
+ $(find_el).before(doc_bar);
+ }
+
+ }
+
+ // var row_id = widget.record.id;
+ // var rowdata = widget.$el;
+ //
+ // //console.log(widget.$el)
+ //
+ // if (_.has(widget.bar_widget, "done_slider") && widget.bar_widget.done_slider) {
+ //
+ // var el = widget.bar_widget.done_slider[0];
+ //
+ //
+ // var fel = $(el).find(".task-gantt-done-info");
+ // var _bar = $('
');
+ // var doc_bar = $('
');
+ // _bar.append(doc_bar);
+ //
+ // if (fel.length){
+ // $(fel).append(_bar);
+ // }else{
+ // $(el).append(_bar);
+ //
+ // }
+ //
+ // } else if (_.has(widget.bar_widget, "deadline_bar") && widget.bar_widget.deadline_bar) {
+ //
+ // var d_el = widget.bar_widget.deadline_bar[0];
+ //
+ // var width = parseInt($(d_el).css('width'));
+ //
+ // var d_bar = $('
');
+ // //
+ // d_bar.css({"left": width+10 + "px" });
+ // d_bar.css({"position": "absolute" });
+ //
+ //
+ // var d_doc_bar = $('
');
+ // d_bar.append(d_doc_bar);
+ //
+ // $(d_el).append(d_bar);
+ //
+ //
+ //
+ // }
+ // else{
+ //
+ // var row_el = widget.$el;
+ //
+ // var p_el = $(row_el).find(".task-gantt-bar-plan-info-end"); //.task-gantt-bar-plan-info-end //task-gantt-bar-plan
+ //
+ // var p_bar = $('
');
+ //
+ // var p_doc_bar = $('
');
+ // p_bar.append(p_doc_bar);
+ //
+ // // p_el.before(p_bar);
+ //
+ //
+ //
+ // var domain = [
+ // ['res_model', '=', "project.task"],
+ // ['res_id', '=', widget.record_id],
+ // ['type', 'in', ['binary', 'url']]
+ // ];
+ // var fields = ['name', 'url', 'type',
+ // 'create_uid', 'create_date', 'write_uid', 'write_date'];
+ //
+ // parentg._rpc({
+ // model: 'ir.attachment',
+ // method: 'search_read',
+ // context: parentg.state.contexts,
+ // domain: domain,
+ // fields: fields,
+ // }).then(function (result) {
+ // if (result.length){
+ // p_el.before(p_bar);
+ // }
+ //
+ // });
+ //
+ //
+ // }
+
+
+
+ //
+
+ // if (widget.record.subtask_count > 0) {
+
+
+
+ // var start_time = false;
+ // if (widget.record.summary_date_start){
+ // start_time = widget.record.summary_date_start.getTime();
+ // }
+ //
+ // var stop_time = false;
+ // if (widget.record.summary_date_end){
+ // stop_time = widget.record.summary_date_end.getTime();
+ // }
+ //
+ // var start_pxscale = Math.round((start_time-parentg.firstDayScale) / parentg.pxScaleUTC);
+ // var stop_pxscale = Math.round((stop_time-parentg.firstDayScale) / parentg.pxScaleUTC);
+ //
+ // var bar_left = start_pxscale;
+ // var bar_width = stop_pxscale-start_pxscale;
+ //
+ // var summary_bar = $('
');
+ //
+ // summary_bar.addClass("task-gantt-bar-summary-"+row_id);
+ //
+ // summary_bar.css({"left": bar_left + "px"});
+ // summary_bar.css({"width": bar_width + "px"});
+ //
+ // var row_data = _.find(parentg.gantt_timeline_data_widget, function (o) { return o.record_id === row_id; })
+ // var rowdata = row_data.el;
+ //
+ // var bar_summary_start = $('
');
+ // var bar_summary_end = $('
');
+ //
+ // summary_bar.append(bar_summary_start);
+ // summary_bar.append(bar_summary_end);
+ //
+ // var bar_summary_width = $('
');
+ // bar_summary_width.css({"width": bar_width + "px"});
+ //
+ // summary_bar.append(bar_summary_width);
+ //
+ // $(rowdata).append(summary_bar);
+
+ // }
+
+
+ }
+
+ return true;
+ })
+
+
+ }
+
+
+});
+
+return {
+ DocsWidget: GanttTimeLineDocs
+}
+
+});
\ No newline at end of file
diff --git a/odex25_project/web_gantt_native/static/src/js/gantt_timeline_bar_first.js b/odex25_project/web_gantt_native/static/src/js/gantt_timeline_bar_first.js
new file mode 100644
index 000000000..98eec9bfb
--- /dev/null
+++ b/odex25_project/web_gantt_native/static/src/js/gantt_timeline_bar_first.js
@@ -0,0 +1,230 @@
+odoo.define('web_gantt_native.BarFirst', function (require) {
+"use strict";
+
+
+var Widget = require('web.Widget');
+var time = require('web.time');
+
+
+
+
+var GanttTimeLineFirst = Widget.extend({
+ template: "GanttTimeLine.first",
+
+ init: function(parent) {
+ this._super.apply(this, arguments);
+ },
+
+
+ start: function(){
+
+ var parentg = this.getParent();
+
+ var data_widgets = parentg.gantt_timeline_data_widget;
+
+
+
+
+ _.each(data_widgets, function(widget) {
+
+ if (parentg.ItemsSorted && widget.record.is_group) {
+
+ var row_id = widget.record.group_id[0];
+
+ // var barfirst_datas = parentg.BarFirst_Data;
+ var link_first_result = _.where(parentg.BarFirst_Data, {data_row_id: row_id});
+
+ if (link_first_result.length > 0){
+
+ var link_first_data = link_first_result[0];
+
+ var start_time = false;
+ if (link_first_data.date_start){
+ start_time = link_first_data.date_start.getTime();
+ }
+
+ var stop_time = false;
+ if (link_first_data.date_end){
+ stop_time = link_first_data.date_end.getTime();
+ }
+
+
+ if (start_time && stop_time){
+
+ var start_pxscale = Math.round((start_time-parentg.firstDayScale) / parentg.pxScaleUTC);
+ var stop_pxscale = Math.round((stop_time-parentg.firstDayScale) / parentg.pxScaleUTC);
+
+ var bar_left = start_pxscale;
+ var bar_width = stop_pxscale-start_pxscale;
+
+ var first_bar = $('
');
+ first_bar.addClass("task-gantt-bar-first-"+row_id);
+
+ first_bar.css({"left": bar_left + "px"});
+ first_bar.css({"width": bar_width + "px"});
+
+ // var rowdata = '#task-gantt-timeline-group-row-'+row_id;
+ var rowdata = widget.$el;
+
+ var first_bar_start = $('
');
+ var first_bar_end = $('
');
+
+ var height_m = parseInt(widget.record.task_count);
+
+ if (height_m){
+ first_bar_start.css({"height": (1+height_m)*30 + "px"});
+ first_bar_end.css({"height": (1+height_m)*30 + "px"});
+ }
+
+
+
+ first_bar.append(first_bar_start);
+ first_bar.append(first_bar_end);
+
+
+
+ $(rowdata).append(first_bar);
+
+ }
+
+
+ }
+
+
+
+ // if (widget.record.subtask_count > 0) {
+ //
+ // var start_time = false;
+ // if (widget.record.summary_date_start){
+ // start_time = widget.record.summary_date_start.getTime();
+ // }
+ //
+ // var stop_time = false;
+ // if (widget.record.summary_date_end){
+ // stop_time = widget.record.summary_date_end.getTime();
+ // }
+ //
+ // var start_pxscale = Math.round((start_time-parentg.firstDayScale) / parentg.pxScaleUTC);
+ // var stop_pxscale = Math.round((stop_time-parentg.firstDayScale) / parentg.pxScaleUTC);
+ //
+ // var bar_left = start_pxscale;
+ // var bar_width = stop_pxscale-start_pxscale;
+ //
+ // var summary_bar = $('
');
+ //
+ // summary_bar.addClass("task-gantt-bar-summary-"+row_id);
+ //
+ // summary_bar.css({"left": bar_left + "px"});
+ // summary_bar.css({"width": bar_width + "px"});
+ //
+ // var rowdata = '#task-gantt-timeline-row-'+row_id;
+ //
+ //
+ // var bar_summary_start = $('
');
+ // var bar_summary_end = $('
');
+ //
+ // summary_bar.append(bar_summary_start);
+ // summary_bar.append(bar_summary_end);
+ //
+ // var bar_summary_width = $('
');
+ // bar_summary_width.css({"width": bar_width + "px"});
+ //
+ // summary_bar.append(bar_summary_width);
+ //
+ // $(rowdata).append(summary_bar);
+ //
+ // }
+
+
+ }
+
+ return true;
+ })
+
+
+ }
+
+
+});
+
+function get_data_barfirst (parentg) {
+
+ // var ghosts = parentg.Ghost;
+ // var ghost_id = parentg.fields_view.arch.attrs.ghost_id;
+ // var ghost_ids_name = parentg.fields_view.arch.attrs.ghost_name;
+ // var ghost_ids_date_start = parentg.fields_view.arch.attrs.ghost_date_start;
+ // var ghost_ids_date_end = parentg.fields_view.arch.attrs.ghost_date_end;
+ // var ghost_ids_durations = parentg.fields_view.arch.attrs.ghost_durations;
+
+ // var barfirsts = parentg.BarFirst;
+ var barfirsts = parentg.gantt.data.BarFirst;
+
+ var barfirst_id = "id";
+ var barfirst_name = "name";
+ var barfirst_date_start = "date_start";
+ var barfirst_date_end = "date_end";
+
+ var data_barfirst = _.map(barfirsts, function(barfirst) {
+
+ var data_row_id = barfirst[barfirst_id];
+
+ var date_start = barfirst[barfirst_date_start];
+ if (date_start){
+ date_start = time.auto_str_to_date(date_start);
+ }
+
+ var date_end = barfirst[barfirst_date_end];
+ if (date_end){
+ date_end = time.auto_str_to_date(date_end);
+ }
+
+
+ return {
+ data_row_id: data_row_id,
+ name : barfirst[barfirst_name],
+ date_start : date_start,
+ date_end : date_end,
+
+ }
+ });
+
+ // try {
+ // var data_min = _.min(data_ghosts, function (ghost) {
+ // return ghost.date_start;
+ // });
+ // }
+ // catch (err) {}
+ //
+ //
+ // try {
+ // var data_max = _.max(data_ghosts, function (ghost) {
+ // return ghost.date_end;
+ // });
+ // }
+ // catch (err) {}
+ //
+ //
+ //
+ // try {
+ // var start_time = data_min["date_start"].getTime();
+ // parentg.GtimeStopA = parentg.GtimeStopA.concat(start_time);
+ // } catch (err) {}
+ //
+ // try {
+ // var stop_time = data_max["date_end"].getTime();
+ // parentg.GtimeStartA = parentg.GtimeStartA.concat(stop_time);
+ // } catch (err) {}
+
+
+ return data_barfirst;
+
+
+}
+
+
+return {
+ get_data_barfirst: get_data_barfirst,
+ BarFirstWidget: GanttTimeLineFirst
+}
+
+});
\ No newline at end of file
diff --git a/odex25_project/web_gantt_native/static/src/js/gantt_timeline_bar_summary.js b/odex25_project/web_gantt_native/static/src/js/gantt_timeline_bar_summary.js
new file mode 100644
index 000000000..29e357e7d
--- /dev/null
+++ b/odex25_project/web_gantt_native/static/src/js/gantt_timeline_bar_summary.js
@@ -0,0 +1,96 @@
+odoo.define('web_gantt_native.Summary', function (require) {
+"use strict";
+
+
+var Widget = require('web.Widget');
+
+
+
+var GanttTimeLineSummary = Widget.extend({
+ template: "GanttTimeLine.summary",
+
+ init: function(parent) {
+ this._super.apply(this, arguments);
+ },
+
+
+ start: function(){
+
+ var parentg = this.getParent();
+
+ var data_widgets = parentg.gantt_timeline_data_widget;
+
+ _.each(data_widgets, function(widget) {
+
+ if (!widget.record.is_group) {
+
+ var row_id = widget.record.id;
+
+ // if (widget.record.subtask_count > 0 || widget.record.isParent) {
+
+ if (widget.record.isParent) {
+
+ var start_time = false;
+ if (widget.record.summary_date_start){
+ start_time = widget.record.summary_date_start.getTime();
+ }
+
+ var stop_time = false;
+ if (widget.record.summary_date_end){
+ stop_time = widget.record.summary_date_end.getTime();
+ }
+
+ if (start_time && stop_time){
+
+ var start_pxscale = Math.round((start_time-parentg.firstDayScale) / parentg.pxScaleUTC);
+ var stop_pxscale = Math.round((stop_time-parentg.firstDayScale) / parentg.pxScaleUTC);
+
+ var bar_left = start_pxscale;
+ var bar_width = stop_pxscale-start_pxscale;
+
+ var summary_bar = $('
');
+
+ summary_bar.addClass("task-gantt-bar-summary-"+row_id);
+
+ summary_bar.css({"left": bar_left + "px"});
+ summary_bar.css({"width": bar_width + "px"});
+
+ var row_data = _.find(parentg.gantt_timeline_data_widget, function (o) { return o.record_id === row_id; })
+ var rowdata = row_data.el;
+
+ var bar_summary_start = $('
');
+ var bar_summary_end = $('
');
+
+ summary_bar.append(bar_summary_start);
+ summary_bar.append(bar_summary_end);
+
+ var bar_summary_width = $('
');
+ bar_summary_width.css({"width": bar_width + "px"});
+
+ summary_bar.append(bar_summary_width);
+
+ $(rowdata).append(summary_bar);
+
+ }
+
+
+
+ }
+
+
+ }
+
+ return true;
+ })
+
+
+ }
+
+
+});
+
+return {
+ SummaryWidget: GanttTimeLineSummary
+}
+
+});
\ No newline at end of file
diff --git a/odex25_project/web_gantt_native/static/src/js/gantt_timeline_data.js b/odex25_project/web_gantt_native/static/src/js/gantt_timeline_data.js
new file mode 100644
index 000000000..7279368f1
--- /dev/null
+++ b/odex25_project/web_gantt_native/static/src/js/gantt_timeline_data.js
@@ -0,0 +1,1207 @@
+odoo.define('web_gantt_native.TimeLineData', function (require) {
+"use strict";
+
+
+var core = require('web.core');
+var Dialog = require('web.Dialog');
+
+var Widget = require('web.Widget');
+
+var time = require('web.time');
+var _t = core._t;
+
+
+var GanttToolTip = require('web_gantt_native.ToolTip');
+var GanttToolHint = require('web_gantt_native.ToolHint');
+var GanttHeaderHint = require('web_gantt_native.HeaderHint');
+
+var NativeGanttData = require('web_gantt_native.NativeGanttData');
+
+
+var GanttTimeLineData = Widget.extend({
+ template: "GanttTimeLine.data",
+
+ events: {
+
+ 'mouseover .task-gantt-bar-plan' :'HandleTipOver',
+ 'mouseout .task-gantt-bar-plan' :'HandleTipOut',
+ },
+
+
+ init: function(parent, timeScale, timeType, record, options) {
+ this._super(parent);
+ this.parent = parent;
+ this.record = record;
+ this.record_id = this.record['id'];
+
+ this.BarRecord = undefined;
+ this.BarClickDiffX = undefined;
+ this.BarClickX = undefined;
+ this.BarClickDown = false;
+
+ this.items_sorted = options.items_sorted;
+ this.tree_view = options.tree_view;
+
+ },
+
+
+
+
+ get_position_x: function(gantt_date_start, gantt_date_stop, any_date){
+
+ var task_start_time = gantt_date_start.getTime();
+ var task_stop_time = gantt_date_stop.getTime();
+
+ var task_start_pxscale = Math.round((task_start_time-this.parent.firstDayScale) / this.parent.pxScaleUTC);
+ var task_stop_pxscale = Math.round((task_stop_time-this.parent.firstDayScale) / this.parent.pxScaleUTC);
+
+ var bar_left = task_start_pxscale;
+ var bar_width = task_stop_pxscale-task_start_pxscale;
+
+ var any_status = false;
+
+ if (any_date) {
+
+ var any_date_time = any_date.getTime();
+ var any_date_pxscale = Math.round((any_date_time-this.parent.firstDayScale) / this.parent.pxScaleUTC);
+
+ var bar_any_left = false;
+ var bar_any_width = false;
+
+
+ if (any_date_pxscale >= task_stop_pxscale){
+
+ bar_any_left = bar_width;
+ bar_any_width = any_date_pxscale-task_stop_pxscale;
+ any_status = 'after_stop';
+
+ }
+
+ if (any_date_pxscale < task_stop_pxscale){
+
+ bar_any_left = bar_width - (task_stop_pxscale - any_date_pxscale);
+ bar_any_width = task_stop_pxscale-any_date_pxscale;
+ any_status = 'before_stop'
+
+ }
+
+ if (any_date_pxscale <= task_start_pxscale){
+
+ bar_any_left = bar_width - (task_stop_pxscale - any_date_pxscale);
+ bar_any_width = task_start_pxscale-any_date_pxscale;
+ any_status = 'before_start'
+
+ }
+
+ }
+
+ return {
+ bar_left: bar_left,
+ bar_width: bar_width,
+ bar_any_left : bar_any_left,
+ bar_any_width : bar_any_width,
+ any_status: any_status
+ };
+
+ },
+
+ deadline_slider_gen: function (get_possition, not_render, id, gantt_bar) {
+
+ // bar_any_left : bar_any_left,
+ // bar_any_width : bar_any_width,
+ // any_status: any_status
+ bar_deadline_slider = false;
+
+ if (!not_render) {
+
+ var bar_deadline_left = get_possition.bar_any_left;
+ var bar_deadline_width = get_possition.bar_any_width;
+ var bar_deadline_status = get_possition.any_status;
+
+ //Can Render Deadline
+ if (bar_deadline_left && bar_deadline_width) {
+
+
+ //Deadline Ssider
+ var bar_deadline_slider = $('
');
+ var bar_deadline_slider_left = bar_deadline_left + bar_deadline_width;
+
+ if (bar_deadline_status === 'before_stop' || bar_deadline_status === 'before_start') {
+ bar_deadline_slider_left = bar_deadline_left
+ }
+
+ bar_deadline_slider.css({"left": bar_deadline_slider_left + "px"});
+
+ // var deadline_left = this.lag_any(moment(), this.record.date_deadline, " late", " left", false);
+ // if (deadline_left) {
+ //
+ // var bar_dl = $('
');
+ // var bar_dl_text = $('
');
+ // bar_dl_text.text(deadline_left);
+ // bar_dl.append(bar_dl_text);
+ // bar_deadline_slider.append(bar_dl);
+ // }
+ }
+ }
+
+ this.DragDeadLine(id, gantt_bar, bar_deadline_slider);
+
+ return bar_deadline_slider
+ },
+
+
+
+ deadline_bar_gen: function (get_possition, deadline_lag) {
+
+ var deadline_bar = false;
+
+ if (!deadline_lag && this.record.date_deadline) {
+
+ var bar_deadline_left = get_possition.bar_any_left;
+ var bar_deadline_width = get_possition.bar_any_width;
+ var bar_deadline_status = get_possition.any_status;
+
+ //Bar to Today
+
+ var deadline_today = get_possition;
+ var text_margin = 20;
+ if (this.parent.isTODAYline){
+ deadline_today = this.get_position_x(moment().toDate(), moment().toDate(), this.record.date_deadline);
+ text_margin = 5;
+ }
+
+
+ deadline_bar = $('
');
+
+ var bar_today_left = bar_deadline_left;
+ var bar_today_width = deadline_today.bar_any_width;
+ var bar_today_status = deadline_today.any_status;
+ var gantt_bar_size = get_possition.bar_left + get_possition.bar_width;
+ var lag_calc = 0;
+
+ //deadline color and align
+ deadline_bar.css({"background": "rgba(255, 190, 190, 0.33)"});
+ var text_align = "right";
+
+ if (bar_today_status === 'after_stop') {
+ deadline_bar.css({"background": "rgba(167, 239, 62, 0.33)"});
+ text_align = "left";
+ }
+
+
+
+ //deadline possition
+
+ if (bar_today_status === 'after_stop') {
+ bar_today_left = bar_deadline_left-bar_today_width;
+
+ }
+
+
+ if (bar_today_status === 'after_stop' && bar_deadline_status === "after_stop"){
+ bar_today_left = bar_deadline_left-(bar_today_width-bar_deadline_width);
+ }
+
+
+
+ if ((bar_today_status === "before_start" || bar_today_status === "before_stop") && bar_deadline_status === 'after_stop' ) {
+ bar_today_left = bar_deadline_left + bar_deadline_width;
+ }
+
+
+
+ deadline_bar.css({"left": bar_today_left + "px"});
+ deadline_bar.css({"width": bar_today_width + "px"});
+
+
+
+
+ // var deadline_left = this.lag_any(moment(), this.record.date_deadline, "late ", " left", false);
+ var deadline_left = this.lag_any(moment(), this.record.date_deadline, "- ", "+ ", true);
+ if (deadline_left) {
+
+ var bar_dl = $('
');
+
+ bar_dl.css({"text-align": text_align});
+ bar_dl.css("margin-"+text_align.toString(), lag_calc + text_margin + "px" );
+ bar_dl.text(deadline_left);
+ deadline_bar.append(bar_dl);
+
+
+
+ }
+
+ }
+
+ return deadline_bar
+
+ },
+
+ done_bar_gen: function (deadline_lag) {
+
+ var done_append = true;
+ var done_slider = false;
+
+ if (this.parent.fields_view.arch.attrs.state_status) {
+ done_append = false;
+
+ if(this.record.state === this.parent.fields_view.arch.attrs.state_status){
+ done_append = true;
+ }
+ }
+
+ if (done_append){
+
+ var get_upossition_done = this.get_position_x(this.record.task_start, this.record.task_stop, this.record.date_done);
+ var done_status = get_upossition_done.any_status;
+
+ if (done_status){
+
+ done_slider = $('
');
+
+ var done_left = get_upossition_done.bar_any_left;
+ var done_width = get_upossition_done.bar_any_width;
+ var done_slider_left = done_left+done_width;
+
+ if (done_status === 'before_stop' || done_status === 'before_start'){
+ done_slider_left = done_left;
+ }
+
+ done_slider.css({"left": done_slider_left + "px"});
+
+
+ var bar_d = $('
');
+ var bar_d_text = $('
');
+ if (deadline_lag){
+ bar_d_text.text(deadline_lag);
+ }
+ bar_d.append(bar_d_text);
+ done_slider.append(bar_d);
+
+
+ }
+ }
+
+ return done_slider
+
+
+ },
+
+ progress_bar_gen: function (get_possition) {
+
+ var bar_progress = false;
+
+ if (this.record.progress) {
+
+ var progress_value = (get_possition.bar_width / 100) * this.record.progress;
+
+ if (progress_value < 0) {
+
+ progress_value = -progress_value + get_possition.bar_width
+ }
+
+ bar_progress = $('
');
+ bar_progress.css({"width": progress_value + "px"});
+
+ }
+
+ return bar_progress
+
+
+ },
+
+ progress_bar_on_gantt_gen: function (get_possition, gantt_bar) {
+
+ var bar_progress = false;
+
+ if (this.record.progress && !this.record.on_gantt) {
+
+ bar_progress = $('
' + this.record.progress + '%
');
+ bar_progress.css({"left": get_possition.bar_width / 3 + "px"});
+
+ if (gantt_bar.width() > 40){
+ var d_k = 3;
+ if (gantt_bar.width() < 65){
+ d_k = 10;
+ }
+ bar_progress.css({"left": get_possition.bar_width / d_k + "px"});
+ }
+ }
+
+ return bar_progress
+
+ },
+
+ lag_any: function (first_date, second_date, lag_pos, lag_neg, left_position) {
+
+ var lag_result = false;
+
+ if (first_date && second_date){
+
+ var m_diff = moment(first_date).diff(moment(second_date));
+ var m_duration = moment.duration(m_diff);
+
+ var duration_seconds = parseInt(m_duration.asSeconds());
+
+ if (duration_seconds){
+
+ lag_result = humanizeDuration(duration_seconds*1000,{ units: "d", maxDecimalPoints: 2 });
+
+ var pos_neg = lag_pos;
+
+ if (duration_seconds < 0){
+ pos_neg = lag_neg
+ }
+
+ if (left_position){
+ lag_result = pos_neg+lag_result;
+ }
+ else{
+ lag_result = lag_result+pos_neg;
+ }
+
+ }
+ }
+
+ return lag_result
+
+ },
+
+
+ start: function(){
+
+ var self = this;
+ var id = this.record_id;
+
+
+ if (!this.record.is_group) {
+
+ //Color
+ var color_gantt = false;
+
+ if (this.record["color_gantt_set"]){
+ color_gantt = this.record["color_gantt"]
+ }
+
+ if (!color_gantt){
+ color_gantt = "rgba(242, 197, 116, 0.6)";
+
+ if (this.record.schedule_mode === "auto") {
+ color_gantt = "rgba(111, 197, 242, 0.6)";
+ }
+
+ if (this.record.constrain_type !== "asap" && this.record.constrain_type !== undefined && this.record.schedule_mode === "auto") {
+ color_gantt = "rgba(242, 133, 113, 0.6)";
+ }
+ }
+
+ // var color_gantt parse and replace;
+ var color_rgba = color_gantt.replace(/[^\d.,]/g, '').split(',');
+
+ if (self.tree_view) {
+
+ var isParent = this.record['isParent'];
+ if (isParent) {
+ color_rgba[3] = 0.2;
+ }
+
+ }else{
+ // Task have subtask
+ var subtask_count = this.record['subtask_count'];
+ if (subtask_count) {
+ color_rgba[3] = 0.2;
+ }
+
+ }
+
+ color_gantt = "rgba(" + color_rgba[0] + "," + color_rgba[1] + "," + color_rgba[2] + "," + color_rgba[3] + ")";
+
+ //Gantt Bar
+ var gantt_bar = $('
');
+
+
+
+ //Possition X
+ var get_possition = this.get_position_x(this.record.task_start, this.record.task_stop, this.record.date_deadline);
+
+ gantt_bar.css({"left": get_possition.bar_left + "px"});
+ gantt_bar.css({"width": get_possition.bar_width + "px"});
+
+ // this.bar_left = get_possition.bar_left;
+ // this.bar_width = get_possition.bar_width;
+
+
+ //Hiden Star End bar for change main bar
+ var bar_start = $('
');
+ var bar_end = $('
');
+
+
+
+ if (get_possition.bar_width === 0) {
+ bar_start.addClass("task-gantt-bar-plan-start-zero");
+ bar_end.addClass("task-gantt-bar-plan-end-zero");
+ }
+
+ gantt_bar.append(bar_start);
+ gantt_bar.append(bar_end);
+
+
+ // Get deadline_lag if exist
+ var deadline_lag = this.lag_any(this.record.date_deadline, this.record.date_done, "+ ", "- ", true);
+
+ var gantt_bar_widget = {};
+ //Done Bar
+ gantt_bar_widget["done_slider"] = this.done_bar_gen(deadline_lag);
+
+ //Deadline Slider
+ gantt_bar_widget["deadline_slider"] = this.deadline_slider_gen(get_possition, deadline_lag, id, gantt_bar);
+
+ //Deadline bar
+ gantt_bar_widget["deadline_bar"] = this.deadline_bar_gen(get_possition, deadline_lag);
+
+ //Progress bar
+ gantt_bar_widget["progress_bar"] = this.progress_bar_gen(get_possition);
+
+ //Progress bar on gantt
+ gantt_bar_widget["progress_bar_on_gantt"] = this.progress_bar_on_gantt_gen(get_possition, gantt_bar);
+
+
+ //Task Name on Gantt
+ if (this.record.on_gantt) {
+
+ var bar_name = $('
'+ this.record.value_name +'
');
+ bar_name.css({"width": get_possition.bar_width-5 + "px"});
+ gantt_bar.append(bar_name);
+ }
+
+
+ //Milestone
+ var color_gantt_milestone = false;
+ if (this.record.is_milestone) {
+
+ bar_end.addClass("fa fa-flag fa-1x");
+ color_gantt_milestone = "rgba(242, 197, 116, 0.1";
+
+ if (this.record.schedule_mode === "auto") {
+ color_gantt_milestone = "rgba(111, 197, 242, 0.1)"
+ }
+
+ if (this.record.constrain_type !== "asap" && this.record.schedule_mode === "auto") {
+ color_gantt_milestone = "rgba(242, 133, 113, 0.1)";
+ }
+ }
+
+
+ // if (self.tree_view) {
+ //
+ // var isParent = this.record['isParent'];
+ // if (isParent) {
+ // gantt_bar.css({"opacity": "0.85"});
+ // }
+ //
+ // }else{
+ // // Task have subtask
+ // var subtask_count = this.record['subtask_count'];
+ // if (subtask_count) {
+ // gantt_bar.css({"opacity": "0.85"});
+ // }
+ //
+ // }
+
+
+
+
+
+
+
+ //if exist id for data gantt
+ if (id !== undefined) {
+
+ this.$el.prop('id', "task-gantt-timeline-row-" + id + "");
+ this.$el.prop('data-id', id);
+ this.$el.prop('allowRowHover', true);
+ this.$el.prop('record', this.record);
+ this.$el.prop('record_id', id);
+ gantt_bar.prop('record_id', id);
+ gantt_bar.prop('record', this.record);
+
+ gantt_bar.addClass("task-gantt-bar-plan-" + id + "");
+
+ }
+
+ //Critical path
+ var critical_path = this.record['critical_path'];
+ var cp_shows = this.record['cp_shows'];
+ var p_loop = this.record['p_loop'];
+
+ if (p_loop){
+ gantt_bar.addClass("task-gantt-items-p-loop");
+ }
+ else if (critical_path && cp_shows){
+ gantt_bar.addClass("task-gantt-items-critical-path");
+ }
+
+
+ // Gantt Bar Color
+ if (color_gantt_milestone){
+ color_gantt = color_gantt_milestone
+ }
+
+ this.record.color_gantt = color_gantt;
+ gantt_bar.css({"background": color_gantt});
+
+
+
+ //Widget to gantt bar
+
+ this.bar_widget = gantt_bar_widget;
+ _.each(gantt_bar_widget, function (widget, key) {
+ gantt_bar.append(widget);
+ });
+
+
+ //Gantt Bar to EL
+ this.$el.append(gantt_bar);
+
+ }
+ else{
+ var group_id = this.record.group_id[0];
+
+ this.$el.prop('id', "task-gantt-timeline-group-row-" + group_id + "");
+ this.$el.prop('group-data-id', group_id);
+
+ }
+
+
+ //Drag Actions
+
+ //Drag Gantt Bar
+ this.DragGantt(self, id, gantt_bar, this.record);
+ // this.ChangeSizeEnd(self, id, bar_end, gantt_bar, this.record);
+ this.ChangeSizeStart(self, id, gantt_bar, this.record);
+
+
+ var fold = self.record['fold'];
+ // if (self.tree_view) {
+ if (fold) {
+ this.$el.css({'display': 'none'});
+ }
+ // }
+
+ },
+
+
+ DragDeadLine: function(id, gantt_el, element) {
+
+ if (element) {
+ var record = this.record;
+ var self = this;
+ var drag_el = element;
+ var containment_el = "task-gantt-timeline-row-" + id + "";
+
+ drag_el.draggable({
+
+ axis: "x",
+ containment: containment_el,
+ scroll: false,
+
+ start: async function (event, ui) {
+
+ self.BarRecord = record;
+ //
+ //Hint Widget Destroy
+ self.HintDestroy(self.parent);
+
+ //Tip Widget Destroy
+ self.TipDestroy(self.parent);
+
+ //Create Bar Hint
+ var gantt_line_hint = await new GanttToolHint(self.parent);
+ gantt_line_hint.appendTo(self.parent.$('.task-gantt-line-hints'));
+
+ self.parent.hint_move_widget = gantt_line_hint;
+
+ //Hide
+ self.HideDeadline("deadline");
+ self.$el.prop('allowRowHover', false);
+
+ },
+ drag: function (event, ui) {
+
+ //Hint
+ var bar_info = self.GetGanttBarPlanPxTime();
+ if (self.parent.hint_move_widget){
+ self.parent.hint_move_widget.show_hint(drag_el, bar_info, ui, "deadline");
+ }
+
+
+ },
+
+ stop: function (event, ui) {
+
+ //Bar Save
+ self.BarSave(self.BarRecord.id, "deadline");
+
+ //Hint Widget Destroy
+ self.HintDestroy(self.parent);
+
+ self.BarRecord = undefined;
+
+ // drag_el.draggable('disable');
+
+ }
+
+ }).css("position", "absolute");
+ }
+ },
+
+
+
+
+ ChangeSizeStart: function (self, id, gantt_bar, record) {
+
+ if (id !== undefined) {
+
+ if (record["schedule_mode"] === "manual" || record["schedule_mode"] === undefined) {
+
+
+ var containment_el = "task-gantt-timeline-row-" + id + "";
+
+ gantt_bar.resizable({
+
+
+ handles: {
+ 'e': '.task-gantt-bar-plan-end',
+ 'w': '.task-gantt-bar-plan-start'
+
+ },
+
+
+ // containment: containment_el,
+ start: async function (event, ui) {
+
+ self.BarRecord = event.currentTarget.record;
+ // self.BarClickDiffX = event.target.offsetLeft - event.clientX;
+ // self.BarClickX = event.clientX;
+ // self.BarClickDown = true;
+
+
+ //Hint Widget Destroy
+ self.HintDestroy(self.parent);
+
+ //Tip Widget Destroy
+ self.TipDestroy(self.parent);
+
+ //Create Bar Hint
+ var gantt_line_hint = await new GanttToolHint(self.parent);
+ gantt_line_hint.appendTo(self.parent.$('.task-gantt-line-hints'));
+
+ self.parent.hint_move_widget = gantt_line_hint;
+
+ //Hide
+ self.HideDeadline();
+
+ self.$el.prop('allowRowHover', false);
+ // drag_el.css({"position": "relative" });
+ // drag_el.css({"opacity": 0.8 });
+ // drag_el.css({"background": "rgb(76, 92, 246)" });
+ gantt_bar.css({"background": "rgba(98, 196, 51, 0.38)"});
+
+ },
+ resize: function (event, ui) {
+
+ //Hint
+ var bar_info = self.GetGanttBarPlanPxTime();
+ if (self.parent.hint_move_widget){
+ self.parent.hint_move_widget.show_hint(gantt_bar, bar_info);
+ }
+
+
+
+ },
+ stop: function (event, ui) {
+ //Bar Save
+ self.BarSave(self.BarRecord.id, "bar");
+
+ //Hint Widget Destroy
+ self.HintDestroy(self.parent);
+
+ self.BarRecord = undefined;
+ // gantt_bar.resizable('disable');
+ // gantt_bar.draggable('disable');
+
+ // self.$el.prop('allowRowHover', true);
+ self.ScrollToTop = $('.task-gantt').scrollTop();
+
+ }
+
+ });
+
+
+ }
+ }
+
+ },
+
+
+
+ ChangeSizeEnd: function (self, id, element, gantt_bar, record) {
+
+ if (id !== undefined) {
+
+ if (record["schedule_mode"] === "manual" || record["schedule_mode"] === undefined) {
+
+ var drag_el = element;
+ var containment_el = "task-gantt-timeline-row-" + id + "";
+
+ drag_el.draggable({
+
+ axis: "x",
+ containment: containment_el,
+ scroll: false,
+ zIndex: 1000,
+
+ start: async function (event, ui) {
+
+ self.BarRecord = event.currentTarget.parentElement.record;
+ self.BarClickDiffX = event.target.offsetLeft - event.clientX;
+ self.BarClickX = event.clientX;
+
+ //Hint Widget Destroy
+ self.HintDestroy(self.parent);
+
+ //Tip Widget Destroy
+ self.TipDestroy(self.parent);
+
+ //Create Bar Hint
+ var gantt_line_hint = await new GanttToolHint(self.parent);
+ gantt_line_hint.appendTo(self.parent.$('.task-gantt-line-hints'));
+
+ self.parent.hint_move_widget = gantt_line_hint;
+
+ //Hide
+ self.HideDeadline();
+
+ self.$el.prop('allowRowHover', false);
+ drag_el.css({"position": "relative"});
+ drag_el.css({"opacity": 0.8});
+ drag_el.css({"background": "rgb(76, 92, 246)"});
+ gantt_bar.css({"background": "rgba(98, 196, 51, 0.38)"});
+
+
+ },
+ drag: function (event, ui) {
+
+ //Hint
+ var bar_info = self.GetGanttBarPlanPxTime();
+
+ if (self.parent.hint_move_widget){
+ self.parent.hint_move_widget.show_hint(gantt_bar, bar_info, ui);
+
+ var offsetWidth = event.target.offsetParent.offsetWidth;
+ var DiffForMove = self.BarClickX - event.clientX; //raznica mez nazatijem i tekuchej poziciji mishi
+ var BarNewPos = offsetWidth - DiffForMove; //Velichina smechenija bloka.
+ var NewBarClickDiffX = offsetWidth - event.clientX; //tekucheje rastojanija mezdu nachalom blok i tekuchem pol mishki
+ var Kdiff = self.BarClickDiffX - NewBarClickDiffX + 5; //Koeficent corekciji dla poderzanija rastojanije meszu nachalom
+ //bloka i tekuchem polozenijem mishi. 5 shirina elemnta end (div dragabble)
+
+ var new_width = BarNewPos+Kdiff+DiffForMove;
+
+ if (new_width > 0){
+ gantt_bar.css({"width": (new_width) + "px"});
+ }
+
+ }
+
+
+ },
+
+
+ stop: function (event, ui) {
+
+
+ //Bar Save
+ self.BarSave(self.BarRecord.id, "bar");
+
+ //Hint Widget Destroy
+ self.HintDestroy(self.parent);
+
+ self.BarRecord = undefined;
+
+ self.$el.prop('allowRowHover', true);
+
+ drag_el.css({"position": "absolute" });
+
+ }
+
+ }).css("position", "absolute");
+ }
+ }
+ },
+
+
+
+ DragGantt: function(self, id, element, record) {
+
+ if (id !== undefined) {
+
+ if (record["schedule_mode"] === "manual" || record["schedule_mode"] === undefined) {
+
+ var drag_el = element;
+ var containment_el = "task-gantt-timeline-row-" + id + "";
+
+ drag_el.draggable({
+
+ axis: "x",
+ containment: containment_el,
+ scroll: false,
+
+ start: async function (event, ui) {
+
+ self.BarRecord = event.currentTarget.record;
+
+ //Hint Widget Destroy
+ self.HintDestroy(self.parent);
+
+ //Tip Widget Destroy
+ self.TipDestroy(self.parent);
+
+ //Create Bar Hint
+ var gantt_line_hint = await new GanttToolHint(self.parent);
+
+ gantt_line_hint.appendTo(self.parent.$('.task-gantt-line-hints'));
+
+ self.parent.hint_move_widget = gantt_line_hint;
+
+ //Hide
+ self.HideDeadline();
+
+ self.$el.prop('allowRowHover', false);
+ // drag_el.css({"position": "relative" });
+ // drag_el.css({"opacity": 0.8 });
+ // drag_el.css({"background": "rgb(76, 92, 246)" });
+ drag_el.css({"background": "rgba(98, 196, 51, 0.38)"});
+
+ },
+
+ drag: function (event, ui) {
+ //Hint
+ var bar_info = self.GetGanttBarPlanPxTime();
+
+ if (self.parent.hint_move_widget){
+ self.parent.hint_move_widget.show_hint(drag_el, bar_info);
+ }
+
+
+ },
+
+ stop: function (event, ui) {
+ //Bar Save
+ self.BarSave(self.BarRecord.id, "bar");
+
+ //Hint Widget Destroy
+ self.HintDestroy(self.parent);
+
+ self.BarRecord = undefined;
+
+ // drag_el.resizable('disable');
+ // drag_el.draggable('disable');
+
+ }
+
+ }).css("position", "absolute");
+ }
+ }
+ },
+
+
+ HintDestroy: function(parent) {
+
+ if (parent.hint_move_widget){
+
+ parent.hint_move_widget.destroy();
+ parent.hint_move_widget = undefined;
+ }
+ },
+
+ TipDestroy: function(parent) {
+
+ if (parent.tip_move_widget) {
+ parent.tip_move_widget.destroy();
+ parent.tip_move_widget = undefined;
+ }
+ },
+
+
+
+
+ HandleTipOver: function(event) {
+
+ var self = this;
+
+ // var bar_record_id = event.target.record_id ;
+ // var bar_record_id = this.record_id;
+ // var gantt_bar = $(".task-gantt-bar-plan-" + bar_record_id + "");
+
+ if (self.parent.tip_move_widget) {
+ self.parent.tip_move_widget.destroy();
+ self.parent.tip_move_widget = undefined;
+
+ }
+
+ if (!self.parent.hint_move_widget) {
+
+ var gantt_bar = this.$el.children('.task-gantt-bar-plan');
+ // //Create Bar Hint
+ var gantt_line_tip = new GanttToolTip(self.parent, gantt_bar, event);
+ gantt_line_tip.appendTo(self.parent.$('.task-gantt-line-tips'));
+ self.parent.tip_move_widget = gantt_line_tip;
+
+ var record_id = gantt_bar[0].record.id;
+ if (record_id){
+ var rowdata = $('#task-gantt-bar-intersection-'+record_id);
+ rowdata.addClass("task-gantt-bar-intersection-hover");
+ }
+
+
+
+
+ }
+ },
+
+
+ HandleTipOut: function() {
+
+ var self = this;
+
+ if (self.parent.tip_move_widget) {
+
+ var record_id = self.parent.tip_move_widget.record[0].record_id
+ if (record_id){
+ var rowdata = $('#task-gantt-bar-intersection-'+record_id);
+ rowdata.removeClass("task-gantt-bar-intersection-hover");
+ }
+ self.parent.tip_move_widget.destroy();
+ self.parent.tip_move_widget = undefined;
+
+
+ }
+ },
+
+
+
+ HideDeadline: function(type){
+
+ var gantt_bar = this.$el.children('.task-gantt-bar-plan');
+
+ //Deadline
+ var gantt_bardeadline = gantt_bar.children('.task-gantt-bar-deadline');
+ if (gantt_bardeadline) {
+ gantt_bardeadline.hide();
+ }
+
+
+ if (type !== "deadline"){
+
+ //Done Slider
+ var gantt_done_slider = gantt_bar.children('.task-gantt-done-slider');
+ if (gantt_done_slider) {
+ gantt_done_slider.hide();
+ }
+
+
+ //Deadline Slider
+ var bar_deadline_slider = gantt_bar.children('.task-gantt-deadline-slider');
+
+ if (bar_deadline_slider) {
+ bar_deadline_slider.hide();
+ }
+ }
+ },
+
+
+//Save BAR
+
+
+
+
+
+ BarSave: function(r_id, type){
+
+ var self = this ;
+ var data = {};
+
+ var bar_info = this.GetGanttBarPlanPxTime();
+
+ var model_fields_dict = this.parent.model_fields_dict;
+ var parent = this.parent;
+
+ // var match_task_id = _.find(parent.rows_to_gantt, function(item) { return item.id === r_id });
+
+ var $zTree = parent.widget_ztree.$zTree;
+
+ var match_task_id = $zTree.getNodeByParam('id', r_id);
+
+ if (type === "bar"){
+
+ var f_data_start = model_fields_dict["date_start"];
+ var f_date_stop = model_fields_dict["date_stop"];
+
+ data[f_data_start] = time.datetime_to_str(bar_info.task_start);
+ data[f_date_stop] = time.datetime_to_str(bar_info.task_end);
+
+ this.parent.TimeToLeft = $('.task-gantt-timeline').scrollLeft();
+ this.parent.ScrollToTop = $('.task-gantt').scrollTop();
+
+ // Redonly Check
+
+ var check_fieds = [f_data_start, f_date_stop];
+ // var readonly = this.CheckReadonly(check_filed);
+
+ var readonly = NativeGanttData.CheckReadOnly(check_fieds, self.parent.fields, self.BarRecord);
+
+
+ var check_readonly = _.findWhere(readonly,{readonly: true});
+
+ if (check_readonly){
+ Dialog.alert(this, _.str.sprintf(_t("You are trying to write on a read-only field! : '%s' "),check_readonly["field"]));
+
+ return self.trigger_up('gantt_refresh_after_change');
+ }
+
+ var l10n = _t.database.parameters;
+
+ var formatDate = time.strftime_to_moment_format( l10n.date_format + ' ' + l10n.time_format);
+
+ // var task_start = moment(bar_info.task_start).format(formatDate);
+ // var task_end = moment(bar_info.task_end).format(formatDate);
+
+ var duration = moment.duration(moment(bar_info.task_start).diff(moment(bar_info.task_end)));
+
+ var duration_seconds = duration.asSeconds();
+
+
+ if (match_task_id) {
+ match_task_id.task_start = bar_info.task_start;
+ match_task_id.task_stop = bar_info.task_end;
+ match_task_id.duration = duration_seconds;
+ }
+
+ $zTree.selectNode(match_task_id);
+
+ }
+
+
+ if (type === "deadline"){
+
+
+ var f_date_deadline = model_fields_dict["date_deadline"];
+
+
+ data[f_date_deadline] = time.datetime_to_str(bar_info.deadline_time);
+
+
+ this.parent.TimeToLeft = $('.task-gantt-timeline').scrollLeft();
+ this.parent.ScrollToTop = $('.task-gantt').scrollTop();
+
+ // Redonly Check
+
+ var check_field_deadline = [f_date_deadline];
+ // var readonly_deadline = this.CheckReadonly(check_filed_deadline);
+ var readonly_deadline = NativeGanttData.CheckReadOnly(check_field_deadline, self.parent.fields, self.BarRecord);
+
+ var check_readonly_deadline = _.findWhere(readonly_deadline,{readonly: true});
+
+
+ if (check_readonly_deadline){
+ Dialog.alert(this, _.str.sprintf(_t("You are trying to write on a read-only field! : '%s' "),check_readonly_deadline["field"]));
+
+ return self.trigger_up('gantt_refresh_after_change');
+ }
+
+
+ if (match_task_id) {
+ match_task_id.date_deadline = bar_info.deadline_time;
+ }
+ }
+
+
+ //Save and refresh after change
+ parent._rpc({
+ model: parent.state.modelName,
+ method: 'write',
+ args: [[r_id], data],
+ context: parent.state.contexts
+ })
+ .then(function(ev) {
+ // self.trigger_up('gantt_refresh_after_change',ev );
+
+ self.trigger_up('warning', {
+ title: _t('Bar Data Update'),
+ message: _t('Data updated : ') + ev
+ });
+
+ });
+
+ self.trigger_up('gantt_fast_refresh_after_change');
+
+
+ },
+
+
+
+ GetGanttBarPlanPxTime: function (){
+
+ var gantt_bar = this.$el.children('.task-gantt-bar-plan');
+
+ var tleft = parseInt(gantt_bar.css('left'), 10);
+ var twidth = parseInt(gantt_bar.css('width'), 10);
+
+ var tright = tleft + twidth;
+ var task_start = (tleft*this.parent.pxScaleUTC)+this.parent.firstDayScale;
+ var task_end = (tright*this.parent.pxScaleUTC)+this.parent.firstDayScale;
+
+
+ var new_task_start = new Date(0); // The 0 there is the key, which sets the date to the epoch setUTCSeconds(task_start);
+ new_task_start.setTime(task_start);
+
+ var new_task_end = new Date(0); // The 0 there is the key, which sets the date to the epoch setUTCSeconds(task_start);
+ new_task_end.setTime(task_end);
+
+
+
+ var gantt_bar_deadline = gantt_bar.children('.task-gantt-deadline-slider');
+
+ if (gantt_bar_deadline) {
+
+ var deadline_px1 = parseInt(gantt_bar_deadline.css('left'), 10);
+
+ var deadline_px = deadline_px1 + tleft;
+
+ if (deadline_px1 < 0) {
+
+ deadline_px = tleft + deadline_px1;
+ }
+
+ var deadline_time = (deadline_px*this.parent.pxScaleUTC)+this.parent.firstDayScale;
+
+ var new_deadline_time = new Date(0); // The 0 there is the key, which sets the date to the epoch setUTCSeconds(task_start);
+ new_deadline_time.setTime(deadline_time);
+ new_deadline_time.setUTCHours(0, 0, 0, 0)
+
+ }
+
+
+ return {
+ task_start: new_task_start,
+ task_end:new_task_end,
+ deadline_time : new_deadline_time
+ };
+ }
+
+
+});
+
+return GanttTimeLineData;
+
+});
diff --git a/odex25_project/web_gantt_native/static/src/js/gantt_timeline_ghost.js b/odex25_project/web_gantt_native/static/src/js/gantt_timeline_ghost.js
new file mode 100644
index 000000000..dab2bdad5
--- /dev/null
+++ b/odex25_project/web_gantt_native/static/src/js/gantt_timeline_ghost.js
@@ -0,0 +1,172 @@
+odoo.define('web_gantt_native.Ghost', function (require) {
+"use strict";
+
+var Widget = require('web.Widget');
+var time = require('web.time');
+
+
+
+function get_data_ghosts (parentg) {
+
+ var ghosts = parentg.gantt.data.Ghost;
+ var ghost_id = parentg.fields_view.arch.attrs.ghost_id;
+ var ghost_ids_name = parentg.fields_view.arch.attrs.ghost_name;
+ var ghost_ids_date_start = parentg.fields_view.arch.attrs.ghost_date_start;
+ var ghost_ids_date_end = parentg.fields_view.arch.attrs.ghost_date_end;
+ var ghost_ids_durations = parentg.fields_view.arch.attrs.ghost_durations;
+
+ var data_ghosts = _.map(ghosts, function(ghost) {
+
+ var data_row_id = ghost[ghost_id][0];
+
+ var durations = ghost[ghost_ids_durations];
+
+ var date_start = time.auto_str_to_date(ghost[ghost_ids_date_start]);
+ if (!date_start){
+ return
+ }
+ var date_end = time.auto_str_to_date(ghost[ghost_ids_date_end]);
+ if (!date_end){
+
+ if (durations){
+ date_end = moment(date_start).add(durations*60, 'minutes')._d;
+ }
+ else{
+ return
+ }
+ }
+
+ return {
+ data_row_id: data_row_id,
+ name : ghost[ghost_ids_name],
+ date_start : date_start,
+ date_end : date_end,
+ durations : ghost[ghost_ids_durations]
+ }
+ });
+
+ try {
+ var data_min = _.min(data_ghosts, function (ghost) {
+ return ghost.date_start;
+ });
+ }
+ catch (err) {}
+
+
+ try {
+ var data_max = _.max(data_ghosts, function (ghost) {
+ return ghost.date_end;
+ });
+ }
+ catch (err) {}
+
+
+
+ try {
+ var start_time = data_min["date_start"].getTime();
+ parentg.GtimeStopA = parentg.GtimeStopA.concat(start_time);
+ } catch (err) {}
+
+ try {
+ var stop_time = data_max["date_end"].getTime();
+ parentg.GtimeStartA = parentg.GtimeStartA.concat(stop_time);
+ } catch (err) {}
+
+
+ return data_ghosts;
+
+
+
+}
+
+
+var GanttTimeLineGhost = Widget.extend({
+ template: "GanttTimeLine.ghost",
+
+ init: function(parent) {
+ this._super.apply(this, arguments);
+ },
+
+
+ start: function(){
+
+ var parentg = this.getParent();
+
+
+ var data_widgets = parentg.gantt_timeline_data_widget;
+
+ var data_ghosts = parentg.Ghost_Data;
+
+ _.each(data_widgets, function(widget) {
+
+ if (!widget.record.is_group) {
+
+ var row_id = widget.record.id;
+
+ var link_ghosts = _.where(data_ghosts, {data_row_id: row_id});
+
+ if (link_ghosts.length > 0){
+
+ var data_min = _.min(link_ghosts, function(ghost){ return ghost.date_start; });
+ var data_max = _.max(link_ghosts, function(ghost){ return ghost.date_end; });
+
+ var start_time = data_min["date_start"].getTime();
+ var stop_time = data_max["date_end"].getTime();
+
+ var start_pxscale = Math.round((start_time-parentg.firstDayScale) / parentg.pxScaleUTC);
+ var stop_pxscale = Math.round((stop_time-parentg.firstDayScale) / parentg.pxScaleUTC);
+
+ var bar_left = start_pxscale;
+ var bar_width = stop_pxscale-start_pxscale;
+
+ var ghost_bar = $('
');
+
+ ghost_bar.addClass("task-gantt-bar-ghosts-"+row_id);
+
+ ghost_bar.css({"left": bar_left + "px"});
+ ghost_bar.css({"width": bar_width + "px"});
+
+ // var rowdata = '#task-gantt-timeline-row-'+row_id;
+ var rowdata = widget.$el;
+
+
+ _.each(link_ghosts, function(link_ghost){
+
+ var ghost_bar_x = $('
');
+ var ghost_start_time = link_ghost["date_start"].getTime();
+ var ghost_stop_time = link_ghost["date_end"].getTime();
+
+ var ghost_start_pxscale = Math.round((ghost_start_time-parentg.firstDayScale) / parentg.pxScaleUTC);
+ var ghost_stop_pxscale = Math.round((ghost_stop_time-parentg.firstDayScale) / parentg.pxScaleUTC);
+
+ var ghost_bar_left = ghost_start_pxscale;
+ var ghost_bar_width = ghost_stop_pxscale-ghost_start_pxscale;
+
+ ghost_bar_x.css({"left": ghost_bar_left + "px"});
+ ghost_bar_x.css({"width": ghost_bar_width + "px"});
+
+ $(rowdata).append(ghost_bar_x);
+ });
+
+ $(rowdata).append(ghost_bar);
+
+
+ }
+
+ }
+
+ return true;
+ })
+
+
+ }
+
+
+});
+
+return {
+ get_data_ghosts: get_data_ghosts,
+ GhostWidget: GanttTimeLineGhost
+}
+
+});
\ No newline at end of file
diff --git a/odex25_project/web_gantt_native/static/src/js/gantt_timeline_head.js b/odex25_project/web_gantt_native/static/src/js/gantt_timeline_head.js
new file mode 100644
index 000000000..70dba364e
--- /dev/null
+++ b/odex25_project/web_gantt_native/static/src/js/gantt_timeline_head.js
@@ -0,0 +1,175 @@
+odoo.define('web_gantt_native.TimeLineHead', function (require) {
+"use strict";
+
+
+var core = require('web.core');
+var Widget = require('web.Widget');
+
+
+
+
+var GanttTimeLineHead = Widget.extend({
+ template: "GanttTimeLine.head",
+
+ init: function(parent, timeScale, timeType, first_scale, second_scale) {
+ this._super(parent);
+
+ this.timeScale = timeScale;
+ this.timeType = timeType;
+
+ this.first_scale = first_scale;
+ this.second_scale = second_scale;
+ this.parent = parent;
+ this.TODAY = moment();
+
+
+ // this.record_id = this.record['id']
+
+ },
+
+
+
+ start: function(){
+
+
+
+
+
+ var self = this;
+ var el = self.$el;
+
+ var el_scale_secondary = el.find('.task-gantt-scale-secondary');
+
+
+ if (this.timeType === 'year_month') {
+
+ _.each(this.first_scale, function(range_date , rdate){
+
+ _.each(range_date, function(quarter){
+
+ var div_cell ='';
+
+ div_cell = $('
');
+ div_cell.css({ width: self.timeScale + "px" });
+ div_cell.css({ 'margin-top': -52 + "px" });
+ el_scale_secondary.append(div_cell);
+ });
+
+ });
+
+ }
+
+
+ if (this.timeType === 'quarter') {
+ _.each(this.first_scale, function(range_date , rdate){
+ _.each(range_date, function(quarter){
+ var div_cell ='';
+
+ div_cell = $('
');
+ div_cell.css({ width: self.timeScale + "px" });
+
+ div_cell.css({ 'margin-top': -52 + "px" });
+
+ el_scale_secondary.append(div_cell);
+ });
+ });
+ }
+
+
+ if (this.timeType === 'month_week') {
+ _.each(this.first_scale, function(range_date , rdate){
+ _.each(range_date, function(hour){
+ var div_cell ='';
+
+ div_cell = $('
');
+ div_cell.css({ width: self.timeScale + "px" });
+
+ div_cell.css({ 'margin-top': -52 + "px" });
+
+ if (moment(hour).isSame(self.TODAY, 'week')){
+ div_cell.addClass('task-gantt-today-column');
+ }
+
+ el_scale_secondary.append(div_cell);
+ });
+
+ });
+
+ }
+
+
+ if (this.timeType === 'month_day')
+ {
+ _.each(this.second_scale, function(day){
+
+ var div_cell ='';
+
+ div_cell = $('
');
+ div_cell.css({ width: self.timeScale + "px" });
+
+ if (moment(day).isoWeekday() === 6 || moment(day).isoWeekday() === 7){
+ div_cell.addClass('task-gantt-weekend-column');
+ }
+ self.parent.isTODAYline = false;
+ if (moment(day).isSame(self.TODAY, 'day')){
+ div_cell.addClass('task-gantt-today-column');
+ self.parent.isTODAYline = true;
+ }
+
+ div_cell.css({ 'margin-top': -52 + "px" });
+
+ return el_scale_secondary.append(div_cell);
+
+ });
+
+
+ }
+
+
+ if (this.timeType === 'day_1hour' ||
+ this.timeType === 'day_2hour' ||
+ this.timeType === 'day_4hour' ||
+ this.timeType === 'day_8hour' ) {
+
+
+
+ _.each(this.first_scale, function(range_date , rdate){
+
+ _.each(range_date, function(hour){
+
+ var div_cell ='';
+
+ // var hours_string = moment(hour).format("HH:mm");
+ div_cell = $('
');
+ // div_cell = $('
'+hours_string+' ');
+ div_cell.css({ width: self.timeScale + "px" });
+
+ if (moment(hour).isoWeekday() === 6 || moment(hour).isoWeekday() === 7){
+ div_cell.addClass('task-gantt-weekend-column');
+ }
+
+ if (moment(hour).isSame(self.TODAY, 'day')){
+ div_cell.addClass('task-gantt-today-column');
+ }
+
+ div_cell.css({ 'margin-top': -52 + "px" });
+ el_scale_secondary.append(div_cell);
+
+ });
+
+
+ }
+ );
+
+ }
+
+
+
+ },
+
+
+});
+
+return GanttTimeLineHead;
+
+});
\ No newline at end of file
diff --git a/odex25_project/web_gantt_native/static/src/js/gantt_timeline_header.js b/odex25_project/web_gantt_native/static/src/js/gantt_timeline_header.js
new file mode 100644
index 000000000..ebdde105d
--- /dev/null
+++ b/odex25_project/web_gantt_native/static/src/js/gantt_timeline_header.js
@@ -0,0 +1,295 @@
+odoo.define('web_gantt_native.TimeLineHeader', function (require) {
+"use strict";
+
+
+var core = require('web.core');
+var Widget = require('web.Widget');
+var GanttHeaderHint = require('web_gantt_native.HeaderHint');
+
+
+
+var GanttTimeLineHeader = Widget.extend({
+ // template: "TimelineGantt.header",
+
+ events: {
+ 'mouseover .task-gantt-bottom-column' :'HandleTipOver',
+ 'mouseout .task-gantt-bottom-column' :'HandleTipOut',
+ },
+
+ init: function(parent, timeScale, timeType, first_scale, second_scale, template, add_to) {
+ this._super(parent);
+
+ this.timeScale = timeScale;
+ this.timeType = timeType;
+
+ this.first_scale = first_scale;
+ this.second_scale = second_scale;
+
+ this.TODAY = moment();
+
+ this.template = template;
+ this.add_to = add_to;
+ },
+
+
+ HandleTipOver: function(ev) {
+ var self = this;
+ if (ev.target['data-id']){
+
+ if (self.__parentedParent.header_hint_widget) {
+ self.__parentedParent.header_hint_widget.do_show();
+ }
+ self.__parentedParent.header_hint_widget.show_hint(ev.target, ev.pageX, ev.pageY )
+ }
+ },
+
+
+ HandleTipOut: function(ev) {
+ var self = this;
+ if (self.__parentedParent.header_hint_widget) {
+ self.__parentedParent.header_hint_widget.do_hide();
+ }
+ },
+
+
+ start: function(){
+
+ var self = this;
+ var el = self.$el;
+ let renderer = self.__parentedParent
+
+ var gutterOffset = self.__parentedParent.local_storage.getItem("gantt_offset") || self.__parentedParent.gutterOffset;
+
+ var el_gantt_items = el.find('.timeline-gantt-items'+self.add_to);
+
+ el_gantt_items.css("width", gutterOffset);
+
+
+ var el_scale_primary = el.find('.timeline-gantt-scale-primary');
+ var el_scale_secondary = el.find('.timeline-gantt-scale-secondary');
+
+ var tip_el = self.__parentedParent.$('.task-gantt-line-tips')
+ var gantt_header_hint = new GanttHeaderHint(self.__parentedParent);
+ gantt_header_hint.appendTo(tip_el);
+ self.__parentedParent.header_hint_widget = gantt_header_hint;
+
+
+ if (this.timeType === 'day_1hour' ||
+ this.timeType === 'day_2hour' ||
+ this.timeType === 'day_4hour' ||
+ this.timeType === 'day_8hour' ) {
+
+ _.each(this.first_scale, function(range_date , rdate){
+
+ var dm = moment(rdate).format("Do MMM dd - YY");
+ var monthScale = self.timeScale*range_date.length;
+
+ var div_cell = $('
');
+ div_cell.css({ width: monthScale + "px" });
+ div_cell.append($('
'+dm+' '));
+
+ el_scale_primary.append(div_cell);
+
+
+ _.each(range_date, function(hour){
+
+ var div_cell ='';
+
+ var hours_string = moment(hour).format("HH:mm");
+
+ div_cell = $('
'+hours_string+' ');
+ div_cell.css({ width: self.timeScale + "px" });
+
+ if (moment(hour).isoWeekday() === 6 || moment(hour).isoWeekday() === 7){
+ div_cell.addClass('task-gantt-weekend-column');
+ }
+
+ if (moment(hour).isSame(self.TODAY, 'day')){
+ div_cell.addClass('task-gantt-today-column');
+ }
+
+ el_scale_secondary.append(div_cell);
+
+ });
+ });
+ }
+
+
+
+ if (this.timeType == 'month_day')
+ {
+ _.each(this.second_scale, function(day){
+
+ var div_cell ='';
+
+ div_cell = $('
'+moment(day).date()+' ');
+ div_cell.css({ width: self.timeScale + "px" });
+
+ if (moment(day).isoWeekday() === 6 || moment(day).isoWeekday() === 7){
+ div_cell.addClass('task-gantt-weekend-column');
+ }
+
+ if (moment(day).isSame(self.TODAY, 'day')){
+ div_cell.addClass('task-gantt-today-column');
+ }
+
+ var day_s = moment(day).format('Do MMM dd (YY)');
+ div_cell.prop('data-id',day_s);
+
+ return el_scale_secondary.append(div_cell);
+
+ });
+
+ _.each(this.first_scale, function(month){
+
+
+ var monthScale = self.timeScale*month.days;
+
+ var div_cell = $('
');
+ div_cell.css({ width: monthScale + "px" });
+ div_cell.append($('
' + month.year + ' - ' + month.month + ' '));
+
+
+ return el_scale_primary.append(div_cell);
+
+ });
+
+ }
+
+
+ if (this.timeType == 'month_week') {
+
+
+ _.each(this.first_scale, function(range_date , rdate){
+
+ var dm = moment(rdate,"YYYY").format("YYYY");
+
+ var monthScale = self.timeScale*range_date.length;
+
+ var div_cell = $('
');
+ div_cell.css({ width: monthScale + "px" });
+ div_cell.append($('
'+dm+' '));
+
+ el_scale_primary.append(div_cell);
+
+
+ _.each(range_date, function(week_num){
+
+ var div_cell ='';
+
+ var week_string = moment(week_num).format("W");
+
+ let marker = "iW"
+ if (renderer.week_type === "week"){
+ marker = "W"
+ }
+
+ div_cell = $('
'+week_string+' ');
+ div_cell.css({ width: self.timeScale + "px" });
+
+ var week_s = moment(week_num).startOf(renderer.week_type).format('Do MMM dd (YY)');
+ var week_e = moment(week_num).endOf(renderer.week_type).format('Do MMM dd (YY)');
+
+
+ div_cell.prop('data-id',marker+": "+week_string+": "+week_s+" - "+week_e);
+
+ if (moment(week_num).isSame(self.TODAY, 'week')){
+ div_cell.addClass('task-gantt-today-column');
+ }
+
+ el_scale_secondary.append(div_cell);
+
+
+ });
+
+ });
+
+ }
+
+
+ if (this.timeType == 'quarter') {
+
+
+ _.each(this.first_scale, function(range_date , rdate){
+
+
+ var dm = moment(rdate,"YYYY").format("YYYY");
+
+ var monthScale = self.timeScale*range_date.length;
+
+
+
+ var div_cell = $('
');
+ div_cell.css({ width: monthScale + "px" });
+ div_cell.append($('
'+dm+' '));
+
+ el_scale_primary.append(div_cell);
+
+
+ _.each(range_date, function(quarter){
+
+ var div_cell ='';
+
+ var week_string = moment(quarter).format("Q");
+
+ div_cell = $('
'+week_string+' ');
+ div_cell.css({ width: self.timeScale + "px" });
+
+ el_scale_secondary.append(div_cell);
+ });
+
+ });
+
+
+ }
+
+
+
+ if (this.timeType == 'year_month') {
+
+
+ _.each(this.first_scale, function(range_date , rdate){
+
+
+ var dm = moment(rdate,"YYYY").format("YYYY");
+
+ var monthScale = self.timeScale*range_date.length;
+
+
+
+ var div_cell = $('
');
+ div_cell.css({ width: monthScale + "px" });
+ div_cell.append($('
'+dm+' '));
+
+ el_scale_primary.append(div_cell);
+
+
+ _.each(range_date, function(quarter){
+
+ var div_cell ='';
+
+ var week_string = moment(quarter).format("MMM");
+
+ div_cell = $('
'+week_string+' ');
+ div_cell.css({ width: self.timeScale + "px" });
+
+ el_scale_secondary.append(div_cell);
+ });
+
+ });
+
+ }
+
+
+
+
+
+ }
+
+
+
+});
+
+return GanttTimeLineHeader;
+
+});
\ No newline at end of file
diff --git a/odex25_project/web_gantt_native/static/src/js/gantt_timeline_header_hint.js b/odex25_project/web_gantt_native/static/src/js/gantt_timeline_header_hint.js
new file mode 100644
index 000000000..c2ba986cd
--- /dev/null
+++ b/odex25_project/web_gantt_native/static/src/js/gantt_timeline_header_hint.js
@@ -0,0 +1,57 @@
+odoo.define('web_gantt_native.HeaderHint', function (require) {
+"use strict";
+
+
+var core = require('web.core');
+var Widget = require('web.Widget');
+var time = require('web.time');
+
+var _t = core._t;
+
+
+
+var GanttHeaderHint = Widget.extend({
+ template: "GanttHeaderHint",
+
+
+ init: function(parent) {
+
+ this._super(parent);
+
+ },
+
+ start: function() {
+
+ var self = this;
+
+ self.$el.append('
');
+ $('
').appendTo(self.$el.children(".task-gantt-line-hint-names"));
+
+ self.$el.append('
');
+ $('
').appendTo(self.$el.children(".task-gantt-line-hint-values"));
+
+ },
+
+
+ renderElement: function () {
+ this._super();
+
+ },
+
+ show_hint : function(target, ex, ey) {
+
+ var self = this;
+
+ var o_left = ex;
+ var o_top = ey;
+
+ this.$el.find('div.hint-start-value').text(target['data-id']);
+ this.$el.offset({ top: o_top+30, left: o_left});
+
+ }
+
+});
+
+return GanttHeaderHint;
+
+});
\ No newline at end of file
diff --git a/odex25_project/web_gantt_native/static/src/js/gantt_timeline_info.js b/odex25_project/web_gantt_native/static/src/js/gantt_timeline_info.js
new file mode 100644
index 000000000..ccd17d7f8
--- /dev/null
+++ b/odex25_project/web_gantt_native/static/src/js/gantt_timeline_info.js
@@ -0,0 +1,111 @@
+odoo.define('web_gantt_native.Info', function (require) {
+"use strict";
+
+var Widget = require('web.Widget');
+
+var GanttTimeLineInfo = Widget.extend({
+ // template: "GanttTimeLine.info",
+
+ init: function(parent) {
+ this._super.apply(this, arguments);
+ },
+
+ gen_element: function(e_text, e_pos){
+
+
+ var e_class = 'task-gantt-bar-plan-info-' + e_pos;
+ var bar_e = $('
');
+ var bar_e_text = $('
');
+ bar_e_text.text(e_text);
+ bar_e.append(bar_e_text);
+
+ return bar_e
+
+
+ },
+
+
+ start: function(){
+
+ var self = this;
+ var el = self.$el;
+
+ var parentg = this.getParent();
+
+ var data_widgets = parentg.gantt_timeline_data_widget;
+
+ var task_info = parentg.Task_Info;
+
+ _.each(data_widgets, function(widget) {
+
+ if (!widget.record.is_group) {
+
+
+ var el = widget.$el;
+
+ var row_id = widget.record.id;
+ var cp_detail = widget.record.cp_detail;
+ var rowdata = '.task-gantt-bar-plan-' + row_id;
+ var row_el = el.find(rowdata);
+
+
+ var info_data = {};
+
+ var task_info_to = _.where(task_info, {task_id: row_id});
+
+ _.each(task_info_to, function(info){
+
+ if (info["show"] || cp_detail) {
+
+ _.each(info, function (info, key) {
+
+ if (info_data[key]) {
+
+ if (info) {
+ info_data[key] = info_data[key] + ', ' + info
+ }
+ } else {
+ info_data[key] = info
+
+ }
+
+ });
+ }
+
+
+ });
+
+
+ //Record for text
+
+ var info_list = {};
+
+ info_list["start"] = info_data["start"] || '';
+ info_list["left-up"] = info_data["left_up"] || '';
+ info_list["left-down"] = info_data["left_down"] || '';
+ info_list["end"] = info_data["end"] || '';
+ info_list["right-up"] = info_data["right_up"] || '';
+ info_list["right-down"] = info_data["right_down"] || '';
+
+ _.each(info_list, function( val, key ) {
+
+ row_el.append(self.gen_element(val, key));
+
+ })
+
+ }
+
+ return true;
+ })
+
+
+ }
+
+
+});
+
+return {
+ InfoWidget: GanttTimeLineInfo
+}
+
+});
\ No newline at end of file
diff --git a/odex25_project/web_gantt_native/static/src/js/gantt_timeline_intersection.js b/odex25_project/web_gantt_native/static/src/js/gantt_timeline_intersection.js
new file mode 100644
index 000000000..bcbdcf74e
--- /dev/null
+++ b/odex25_project/web_gantt_native/static/src/js/gantt_timeline_intersection.js
@@ -0,0 +1,123 @@
+
+
+odoo.define('web_gantt_native.InterSection', function (require) {
+ "use strict";
+
+ var Widget = require('web.Widget');
+ var time = require('web.time');
+
+
+
+ var GanttTimeLineInterSection = Widget.extend({
+ template: "GanttTimeLine.intersection",
+
+ init: function(parent) {
+ this._super.apply(this, arguments);
+
+ },
+
+
+ get_position_x: function(gantt_date_start, gantt_date_stop, parent){
+
+ var task_start_time = gantt_date_start.getTime();
+ var task_stop_time = gantt_date_stop.getTime();
+
+ var task_start_pxscale = Math.round((task_start_time-parent.firstDayScale) / parent.pxScaleUTC);
+ var task_stop_pxscale = Math.round((task_stop_time-parent.firstDayScale) / parent.pxScaleUTC);
+
+ var bar_left = task_start_pxscale;
+ var bar_width = task_stop_pxscale-task_start_pxscale;
+
+ return {
+ bar_left: bar_left,
+ bar_width: bar_width,
+ };
+
+ },
+
+ start: function(){
+ // var self = this;
+
+ let parentg = this.getParent();
+
+ if (parentg.industry_show) {
+
+ let get_position_x= this.get_position_x
+
+ let $zTree = parentg.widget_ztree.$zTree;
+ // let nodes = $zTree.getNodes();
+
+ let data_widgets = parentg.gantt_timeline_data_widget;
+
+
+ _.each(data_widgets, function(widget) {
+ if (widget.record.is_group) {
+ let el = widget.$el
+ let node = $zTree.getNodeByParam("zt_id", widget.record.zt_id, null);
+
+ let before_left = false
+ let before_top = 0
+
+ let childNodes = $zTree.transformToArray(node);
+
+ let sorted_childNodes = _.sortBy(childNodes, 'task_start');
+
+ _.each(sorted_childNodes, function (child) {
+
+ if (child["id"] !== undefined) {
+
+ let id = child["id"]
+ //Gantt Bar
+ var gantt_bar = $('
');
+ gantt_bar.prop('id', "task-gantt-bar-intersection-" + id);
+
+ //Possition X
+ var get_possition = get_position_x(child.task_start, child.task_stop, parentg);
+
+ var bar_name = $('
'+ child.value_name +'
');
+ bar_name.css({"width": get_possition.bar_width-5 + "px"});
+ gantt_bar.append(bar_name);
+
+
+ if (before_left && before_left > get_possition.bar_left){
+
+ if (before_top === 0){
+ before_top = 16
+ }
+ else{
+ before_top = 0
+ }
+ }
+
+ before_left = get_possition.bar_left + get_possition.bar_width
+
+ gantt_bar.css({"top": before_top + "px"});
+ gantt_bar.css({"left": get_possition.bar_left + "px"});
+ gantt_bar.css({"width": get_possition.bar_width + "px"});
+
+ gantt_bar.css({"background": "rgba(242, 133, 113, 0.6)"});
+
+ el.append(gantt_bar);
+
+ }
+ })
+ }
+ })
+ }
+ }
+ });
+
+ return {
+ InterSectionWidget: GanttTimeLineInterSection
+ }
+
+});
+
+
+
+
+
+
+
+
+
diff --git a/odex25_project/web_gantt_native/static/src/js/gantt_timeline_res_bar.js b/odex25_project/web_gantt_native/static/src/js/gantt_timeline_res_bar.js
new file mode 100644
index 000000000..78b5cd94d
--- /dev/null
+++ b/odex25_project/web_gantt_native/static/src/js/gantt_timeline_res_bar.js
@@ -0,0 +1,272 @@
+
+
+odoo.define('web_gantt_native.ResBar', function (require) {
+"use strict";
+
+var Widget = require('web.Widget');
+var time = require('web.time');
+
+
+// function secondsToTime(secs)
+// {
+//
+//
+// var pad = function(num, size) { return ('000' + num).slice(size * -1); },
+// time = parseFloat(secs).toFixed(3),
+// hours = Math.floor(time / 60 / 60),
+// minutes = Math.floor(time / 60) % 60,
+// seconds = Math.floor(time - minutes * 60),
+// milliseconds = time.slice(-3);
+//
+// var obj = {
+// "h": pad(hours, 2),
+// "m": pad(minutes, 2),
+// "s": pad(seconds, 2)
+// };
+// return obj;
+//
+// }
+
+
+
+var GanttTimeLineResBar = Widget.extend({
+ template: "GanttTimeLine.resbar",
+
+ init: function(parent) {
+ this._super.apply(this, arguments);
+ },
+
+
+ start: function(){
+
+ var parentg = this.getParent();
+
+ var data_widgets = parentg.gantt_timeline_data_widget;
+ var task_load_data = parentg.Task_Load_Data;
+
+
+
+ if (task_load_data){
+
+ var gantt_attrs = parentg.arch.attrs;
+ var load_id = gantt_attrs["load_id"];
+ var load_id_from = gantt_attrs["load_id_from"];
+ var load_bar_record_row = gantt_attrs["load_bar_record_row"];
+ var load_data_id = gantt_attrs["load_data_id"];
+
+ // var subtask_project_id = gantt_attrs["subtask_project_id"];
+
+ // S1
+ var data_load_s1 = _.map(task_load_data, function (res_data) {
+
+ var active_id = res_data[load_id] ? res_data[load_id][0] : -1;
+ var active_id_from = res_data[load_id_from] ? res_data[load_id_from][0] : -1;
+
+ return {
+ data_from: res_data["data_from"],
+ data_to : res_data["data_to"],
+ active_id : active_id,
+ active_id_from: active_id_from
+ }
+ });
+
+ var data_load_s2 = _.groupBy(data_load_s1, 'active_id' );
+
+ _.each(data_widgets, function(widget) {
+
+ if (!widget.record.is_group) {
+
+ var row_id = widget.record["id"];
+ if (load_bar_record_row){
+ row_id = widget.record[load_bar_record_row];
+ }
+
+
+ var color_gantt = widget.record["color_gantt"];
+
+
+ var data_load = data_load_s2[row_id];
+
+
+ // if (data_load) {
+ // gantt_bar.css({"background": color_gantt.replace(/[^,]+(?=\))/, '0.2')});
+ // }
+ var rowdata = widget.$el;
+ var active_id_from_data = widget.record["load_data_id"] ? widget.record["load_data_id"][0] : -1;
+
+ if (load_data_id === "id") {
+ active_id_from_data = widget.record["id"];
+ }
+
+ _.each(data_load, function(link_load){
+
+ if (active_id_from_data === link_load.active_id_from){
+
+
+ var dt_start = time.auto_str_to_date(link_load.data_from);
+ var time_start = dt_start.getTime();
+
+ var dt_to = time.auto_str_to_date(link_load.data_to);
+ var time_to = dt_to.getTime();
+
+
+ var load_start_pxscale = Math.round((time_start-parentg.firstDayScale) / parentg.pxScaleUTC);
+ var load_stop_pxscale = Math.round((time_to-parentg.firstDayScale) / parentg.pxScaleUTC);
+
+ var load_bar_left = load_start_pxscale;
+ var load_bar_width = load_stop_pxscale-load_start_pxscale;
+
+ var load_bar_x = $('
');
+
+ load_bar_x.css({"left": load_bar_left + "px"});
+ load_bar_x.css({"width": load_bar_width + "px"});
+
+ var gantt_bar = $(rowdata).find(".task-gantt-bar-plan");
+
+ gantt_bar.css({"background": color_gantt.replace(/[^,]+(?=\))/, '0.4')});
+ load_bar_x.css({"background": color_gantt});
+
+ $(rowdata).append(load_bar_x);
+
+ }
+
+
+
+ });
+
+
+ }
+
+
+
+
+
+
+ });
+
+
+
+ // var data_load = self.task_load_data[id];
+ //
+ // if (data_load) {
+ // gantt_bar.css({"background": color_gantt.replace(/[^,]+(?=\))/, '0.2')});
+ // }
+ //
+ // _.each(data_load, function(link_load){
+ //
+ //
+ // var dt_start = time.auto_str_to_date(link_load.data_from);
+ // var time_start = dt_start.getTime();
+ //
+ // var dt_to = time.auto_str_to_date(link_load.data_to);
+ // var time_to = dt_to.getTime();
+ //
+ //
+ // var load_start_pxscale = Math.round((time_start-self.parent.firstDayScale) / self.parent.pxScaleUTC);
+ // var load_stop_pxscale = Math.round((time_to-self.parent.firstDayScale) / self.parent.pxScaleUTC);
+ //
+ // var load_bar_left = load_start_pxscale;
+ // var load_bar_width = load_stop_pxscale-load_start_pxscale;
+ //
+ // var load_bar_x = $('
');
+ //
+ // load_bar_x.css({"left": load_bar_left + "px"});
+ // load_bar_x.css({"width": load_bar_width + "px"});
+ //
+ // load_bar_x.css({"background": color_gantt});
+ //
+ // self.$el.append(load_bar_x);
+ //
+ //
+ // });
+
+
+ // _.each(data_widgets, function(widget) {
+ //
+ // if (widget.record.is_group) {
+ //
+ // var row_id = widget.record["group_id"] ? widget.record["group_id"][0] : -1;
+ // var data_load_w = _.where(data_load_s3, {user_id: row_id});
+ //
+ // // Get Load Data
+ // if (typeof data_load_w !== 'undefined' && data_load_w.length > 0 ){
+ //
+ // var data_group = data_load_w[0]["data_group"];
+ //
+ // var gp_load = _.map(data_group , function (data_load_value, key) {
+ //
+ //
+ // var duration = _.reduce(data_load_value,
+ // function (memoizer, value) {
+ // return memoizer + value.duration;
+ // }, 0);
+ //
+ // var r_obj = [];
+ // r_obj["date"] = key;
+ // r_obj["duration"] = duration;
+ //
+ // return r_obj
+ // });
+ // }
+ //
+ // var rowdata = widget.$el;
+ //
+ // // Render Load Data
+ // _.each(gp_load, function(link_load){
+ //
+ // var date_point = time.auto_str_to_date(link_load.date);
+ // var start_time = date_point.getTime();
+ //
+ // var left_point = Math.round((start_time-parentg.firstDayScale) / parentg.pxScaleUTC);
+ //
+ // var load_bar_x = $('
');
+ //
+ // // var duration_seconds = humanizeDuration(parseInt(link_load.duration, 10)*1000, {round: true });
+ //
+ // var duration_ = secondsToTime(link_load.duration);
+ //
+ // var load_duration = $('
'+duration_.h+'
');
+ // load_bar_x.append(load_duration);
+ //
+ //
+ // if (duration_.m !== "00") {
+ // var load_duration_m = $('
' + duration_.m + '
');
+ // load_bar_x.append(load_duration_m);
+ // }
+ //
+ //
+ // load_bar_x.css({"left": left_point + "px"});
+ // load_bar_x.css({"width": parentg.timeScale + "px"});
+ //
+ // $(rowdata).append(load_bar_x);
+ // });
+ //
+ //
+ // }
+ //
+ // });
+
+
+
+ }
+
+ }
+
+});
+
+return {
+ ResBarWidget: GanttTimeLineResBar
+
+
+}
+
+});
+
+
+
+
+
+
+
+
+
diff --git a/odex25_project/web_gantt_native/static/src/js/gantt_timeline_res_level.js b/odex25_project/web_gantt_native/static/src/js/gantt_timeline_res_level.js
new file mode 100644
index 000000000..8e372c574
--- /dev/null
+++ b/odex25_project/web_gantt_native/static/src/js/gantt_timeline_res_level.js
@@ -0,0 +1,186 @@
+odoo.define('web_gantt_native.ResLevel', function (require) {
+"use strict";
+
+var Widget = require('web.Widget');
+var time = require('web.time');
+
+
+function secondsToTime(secs)
+{
+
+ var pad = function(num, size) { return ('000' + num).slice(size * -1); },
+ time = parseFloat(secs).toFixed(3),
+ hours = Math.floor(time / 60 / 60),
+ minutes = Math.floor(time / 60) % 60,
+ seconds = Math.floor(time - minutes * 60),
+ milliseconds = time.slice(-3);
+
+ var obj = {
+ "h": pad(hours, 2),
+ "m": pad(minutes, 2),
+ "s": pad(seconds, 2)
+ };
+ return obj;
+
+}
+
+
+var GanttTimeLineResLevel = Widget.extend({
+ template: "GanttTimeLine.reslevel",
+
+ init: function(parent) {
+ this._super.apply(this, arguments);
+ },
+
+
+ start: function(){
+
+ var parentg = this.getParent();
+
+ var data_widgets = parentg.gantt_timeline_data_widget;
+ var data_load = parentg.Task_Load_Data;
+
+
+
+ if (data_load){
+
+ // S1
+ var data_load_s1 = _.map(data_load, function (res_data) {
+ return {
+ data_aggr: res_data["data_aggr"],
+ duration : res_data["duration"],
+ load_id : res_data["resource_id"] ? res_data["resource_id"][0] : -1
+ }
+ });
+
+ // S2
+ var data_load_s2 = _.groupBy(data_load_s1, 'load_id' );
+
+ // S3
+ var data_load_s3 = _.map(data_load_s2, function (value, key) {
+
+ var data_group = _.groupBy(value, 'data_aggr' );
+ return {
+ load_id : parseInt(key) || -1,
+ data_group: data_group
+ }
+ });
+
+
+ _.each(data_widgets, function(widget) {
+
+ if (widget.record.is_group) {
+
+ var row_id = widget.record["group_id"] ? widget.record["group_id"][0] : -1;
+ var data_load_w = _.where(data_load_s3, {load_id: row_id});
+
+ // Get Load Data
+ if (typeof data_load_w !== 'undefined' && data_load_w.length > 0 ){
+
+ var data_group = data_load_w[0]["data_group"];
+
+ var gp_load = _.map(data_group , function (data_load_value, key) {
+
+
+ var duration = _.reduce(data_load_value,
+ function (memoizer, value) {
+ return memoizer + value.duration;
+ }, 0);
+
+ var r_obj = [];
+ r_obj["date"] = key;
+ r_obj["duration"] = duration;
+
+ return r_obj
+ });
+ }
+
+ var rowdata = widget.$el;
+
+ // Render Load Data
+ _.each(gp_load, function(link_load){
+
+ var date_point = time.auto_str_to_date(link_load.date);
+ var start_time = date_point.getTime();
+
+ var left_point = Math.round((start_time-parentg.firstDayScale) / parentg.pxScaleUTC);
+
+ var load_bar_x = $('
');
+
+ // var duration_seconds = humanizeDuration(parseInt(link_load.duration, 10)*1000, {round: true });
+
+ var duration_ = secondsToTime(link_load.duration);
+
+
+
+ var bar_W = 20;
+ var one_line = false;
+ if (parentg.timeType === "day_1hour"){
+ bar_W = 2 * bar_W * 24;
+ one_line = true
+ }
+ else if (parentg.timeType === "day_2hour"){
+ bar_W = 2 * bar_W * 12;
+ one_line = true
+ }else if (parentg.timeType === "day_4hour"){
+ bar_W = 2 * bar_W * 6;
+ one_line = true
+ }else if (parentg.timeType === "day_8hour"){
+ bar_W = 2 * bar_W * 3;
+ one_line = true
+ }
+
+
+
+ if (one_line){
+
+ bar_W = bar_W - 10;
+ left_point = left_point + 5;
+
+ var _m = '';
+ if (duration_.m !== "00") {
+ _m = ' : '+duration_.m;
+
+ }
+ var bar_one_line = $('
'+duration_.h+''+_m+'
');
+
+ bar_one_line.css({"font-size": '1.0em'});
+ load_bar_x.css({"background": 'rgba(223, 224, 222, 0.3)'});
+
+
+ load_bar_x.append(bar_one_line)
+
+
+
+ }else{
+ load_bar_x.append($('
'+duration_.h+'
'));
+ if (duration_.m !== "00") {
+ load_bar_x.append($('
' + duration_.m + '
'));
+
+ }
+ }
+
+
+ load_bar_x.css({"left": left_point + "px"});
+ load_bar_x.css({"width": bar_W + "px"});
+
+ $(rowdata).append(load_bar_x);
+ });
+
+ }
+
+ });
+
+ }
+
+ }
+
+});
+
+return {
+ ResLevelWidget: GanttTimeLineResLevel
+
+
+}
+
+});
\ No newline at end of file
diff --git a/odex25_project/web_gantt_native/static/src/js/gantt_timeline_scroll.js b/odex25_project/web_gantt_native/static/src/js/gantt_timeline_scroll.js
new file mode 100644
index 000000000..ca01a13a7
--- /dev/null
+++ b/odex25_project/web_gantt_native/static/src/js/gantt_timeline_scroll.js
@@ -0,0 +1,177 @@
+odoo.define('web_gantt_native.TimeLineScroll', function (require) {
+"use strict";
+
+
+var core = require('web.core');
+var Widget = require('web.Widget');
+var time = require('web.time');
+
+
+var _t = core._t;
+
+
+
+var GanttTimeLineScroll = Widget.extend({
+ template: "TimelineGantt.scroll",
+
+ init: function(parent, timeScale, timeType, first_scale, second_scale) {
+ this._super(parent);
+
+ this.timeScale = timeScale;
+ this.timeType = timeType;
+
+ this.first_scale = first_scale;
+ this.second_scale = second_scale;
+
+ this.TODAY = moment();
+
+ // this.record_id = this.record['id']
+
+ },
+
+
+ scrollOffset: function (gantt_data_offset){
+
+
+ var scale_width = $('.timeline-gantt-scroll-scale').width()-50;
+
+ if (scale_width) {
+
+ var x1 = $('.task-gantt-timeline').width();
+ var x2 = $('.task-gantt-timeline-data').width();
+ var scroll_width = x2 - x1;
+
+ var scale = scroll_width/(scale_width);
+
+ var offset_left = (gantt_data_offset) / scale;
+
+ if (offset_left > scale_width){
+ offset_left = scale_width
+ }
+
+ if (offset_left <= 0){
+ offset_left = 0
+ }
+
+
+ // $(".timeline-gantt-scroll-slider").offset({ left: offset_left });
+
+ $(".timeline-gantt-scroll-slider").css({left:offset_left});
+ //$(".timeline-gantt-scroll-slider").position({ left: offset_left });
+
+ }
+
+
+
+
+ },
+
+
+ updateCounterStatus: function ($event_counter, scale_width ,scroll_width) {
+
+ var self = this.__parentedParent;
+
+ // var offset = $event_counter.offset();
+ // var offset_left = offset.left;
+
+ var offset_left = $event_counter[0].offsetLeft;
+
+ var scale = scroll_width/(scale_width-50);
+ var scale_x = offset_left * scale;
+
+
+ $('.timeline-gantt-head').animate( { scrollLeft: scale_x }, 0);
+ $('.task-gantt-timeline').animate( { scrollLeft: scale_x }, 0);
+
+
+ //Test
+ self.TimeToLeft = scale_x;
+
+
+ },
+
+
+
+ start: function(){
+
+ var self = this;
+ var el = self.$el;
+ //
+ // var gutterOffset = self.__parentedParent.gutterOffsetSession || self.__parentedParent.gutterOffset;
+ //
+ //
+ //
+ // var menu = $('.o_sub_menu_content');
+ //
+ // if (menu){
+ // gutterOffset = gutterOffset + menu[0].offsetWidth;
+ // }
+
+ // var div_cell = $('
');
+
+ var div_cell = $('
');
+
+ var scale_width = 0;
+ var scroll_width = 0;
+
+ div_cell.draggable({
+ axis: "x",
+ containment: ".timeline-gantt-scroll-scale",
+ scroll: false,
+
+ start: function () {
+
+ var timeline = $('.task-gantt-timeline');
+
+ scale_width = $('.timeline-gantt-scroll-scale').width();
+ var x1 = timeline.width();
+ var x2 = $('.task-gantt-timeline-data').width();
+ scroll_width = x2 - x1;
+
+ var x13 = timeline.scrollLeft();
+
+ },
+
+ drag: function() {
+
+ self.updateCounterStatus( div_cell, scale_width, scroll_width);
+ },
+
+ });
+
+ var parent = this.__parentedParent;
+
+
+ var scroll_start_dt = new Date(0);
+ scroll_start_dt.setTime(parent.firstDayDate);
+
+ var scroll_end_dt = new Date(0);
+ scroll_end_dt.setTime(parent.lastDayDate);
+
+ var l10n = _t.database.parameters;
+ var formatDate = time.strftime_to_moment_format( l10n.date_format + ' ' + l10n.time_format);
+
+ var scroll_start_str = moment(scroll_start_dt).format(formatDate);
+ var scroll_end_str = moment(scroll_end_dt).format(formatDate);
+
+ var bar_start = $('
');
+ var bar_end = $('
');
+
+ $('
'+scroll_start_str+'
').appendTo(bar_start);
+ $('
'+scroll_end_str+'
').appendTo(bar_end);
+
+ el.append(bar_start);
+ el.append(bar_end);
+
+ el.append(div_cell);
+
+ return this._super.apply(arguments);
+
+ }
+
+
+});
+
+return GanttTimeLineScroll;
+
+});
\ No newline at end of file
diff --git a/odex25_project/web_gantt_native/static/src/js/gantt_tool_field.js b/odex25_project/web_gantt_native/static/src/js/gantt_tool_field.js
new file mode 100644
index 000000000..774421208
--- /dev/null
+++ b/odex25_project/web_gantt_native/static/src/js/gantt_tool_field.js
@@ -0,0 +1,653 @@
+odoo.define('web_gantt_native.ToolField', function (require) {
+"use strict";
+
+
+ var time = require('web.time');
+ var field_utils = require('web.field_utils');
+
+ // var formats = require('web.formats');
+
+
+
+
+ function getFields(parent, group_bys) {
+
+ // this.fields_keys = _.keys(this.fields_view.fields);
+
+ var gantt_fields_0 = [
+ "id",
+ "display_name"
+ ];
+
+ var gantt_fields_1 = [
+
+ "name",
+ "date_start",
+ "date_stop",
+ "progress",
+ "user_id",
+
+ "task_time",
+
+ "project_id",
+ "date_deadline",
+ "progress",
+
+ "on_gantt",
+
+ "date_done",
+ "state",
+
+ "subtask_project_id",
+ "load_data_id",
+
+ "parent_id",
+
+ "default_seq",
+
+ "sorting_seq",
+ "sorting_level",
+ "subtask_count",
+
+ "is_milestone",
+ "schedule_mode",
+ "constrain_type",
+ "constrain_date",
+ "duration",
+ "plan_duration",
+
+ "summary_date_start",
+ "summary_date_end",
+
+ "plan_action",
+
+ "color_gantt_set",
+ "color_gantt",
+ "duration_scale",
+
+ "fold",
+
+ "critical_path",
+ "cp_shows",
+ "cp_detail",
+
+ "p_loop",
+
+ "doc_count"
+
+
+ ];
+
+ var model_fields_dict = [];
+ var model_fields = _.compact(_.map(gantt_fields_1, function(key) {
+
+ var key_field = parent.fields_view.arch.attrs[key] || '';
+ model_fields_dict[key] = key_field;
+ return key_field
+ }));
+
+
+ model_fields = _.uniq(model_fields.concat(group_bys, gantt_fields_0));
+
+
+ return {
+ model_fields : model_fields,
+ gantt_fields : gantt_fields_1,
+ model_fields_dict : model_fields_dict
+ }
+
+ }
+
+
+
+ function flatRows (row_datas, ItemsSorted) {
+
+ var rows_to_gantt = [];
+ var self = this;
+ //var sefl = undefined;
+ self.ItemsSorted = ItemsSorted;
+
+ //recursive tree to flat task.
+ var generate_flat_gantt = function(value, parent_value) {
+
+ var zt_id = false;
+ var zt_pId = "root_";
+
+
+ if (parent_value && !self.ItemsSorted){
+
+ zt_pId = parent_value.zt_id
+ }
+
+
+ if (value.is_group) {
+
+ value.zt_id =zt_pId+value.group_info[0]+"_"+value.group_info[1];
+
+ rows_to_gantt.push({
+
+ id: value.id,
+ is_group: value.is_group,
+ group_id: value.group_info,
+ // level: value.level,
+ value_name: value.task_name,
+ group_field: value.group_field,
+ task_count: value.task_count,
+ fold: value.fold,
+
+ zt_pId: zt_pId,
+ zt_id: value.zt_id,
+ });
+
+ }
+ else {
+
+ //Some browser crash
+ var assign_to = undefined;
+ try {
+ assign_to = value.assign_to[1];
+ } catch (err) {}
+
+
+ if (self.ItemsSorted){
+
+ zt_pId = parent_value.zt_id;
+
+ if ( value.parent_id ){
+
+ zt_pId = value.parent_id[0]
+
+ }
+
+ }
+
+
+ // zt_pId = 0;
+ // if ( value.parent_id ){
+ //
+ // zt_pId = value.parent_id[0]
+ // }
+
+
+ rows_to_gantt.push({
+
+ zt_id: value.id,
+ zt_pId : zt_pId,
+
+ is_group: value.is_group,
+ // group_field: value.group_field,
+
+ id: value.id,
+ group_id: value.group_info,
+ // level: value.level,
+ value_name: value.task_name,
+
+ assign_to: assign_to,
+
+ task_start: value.task_start,
+ task_stop: value.task_stop,tree_seq: value.tree_seq,
+
+ default_seq: value.default_seq,
+
+ sorting_level : value.sorting_level,
+ sorting_seq: value.sorting_seq,
+
+ project_id : value.project_id,
+
+ date_deadline: value.date_deadline,
+ progress: value.progress,
+
+ is_milestone: value.is_milestone,
+ on_gantt: value.on_gantt,
+
+ schedule_mode: value.schedule_mode,
+ constrain_type: value.constrain_type,
+ constrain_date: value.constrain_date,
+ duration: value.duration,
+ plan_duration: value.plan_duration,
+
+
+ plan_action: value.plan_action,
+
+ color_gantt: value.color_gantt,
+ color_gantt_set: value.color_gantt_set,
+
+ duration_scale: value.duration_scale,
+
+ summary_date_start: value.summary_date_start,
+ summary_date_end: value.summary_date_end,
+
+ subtask_project_id: value.subtask_project_id,
+ load_data_id: value.load_data_id,
+
+ parent_id: value.parent_id,
+ subtask_count: value.subtask_count,
+
+ date_done: value.date_done,
+ state: value.state,
+
+ fold: value.fold,
+
+ critical_path: value.critical_path,
+ cp_shows: value.cp_shows,
+ cp_detail: value.cp_detail,
+
+ p_loop: value.p_loop,
+ doc_count: value.doc_count,
+
+ });
+
+ }
+
+ _.map(value.child_task, function(sub_task) {
+ generate_flat_gantt(sub_task, value);
+ });
+ };
+
+
+ //Generate Flat Gant to rows_to_gantt
+ _.map(row_datas, function(result) {
+ return generate_flat_gantt(result);
+ });
+
+ return rows_to_gantt;
+
+
+ }
+
+
+ function groupRows (tasks, group_bys, self_parent, ItemsSorted) {
+
+ var parent = self_parent;
+ var GtimeStopA = [];
+ var GtimeStartA = [];
+
+ var model_fields_dict = parent.model_fields_dict;
+ var gantt_attrs = parent.gantt_attrs;
+ var second_sort = parent.second_sort;
+ var main_group = parent.main_group;
+
+ //prevent more that 1 group by
+ // if (group_bys.length > 0) {
+ // group_bys = [group_bys[0]];
+ // }
+
+
+ // if there is no group by, simulate it
+ if (group_bys.length === 0) {
+ group_bys = ["_pseudo_group_by"];
+ _.each(tasks, function(el) {
+ el._pseudo_group_by = "Plain Gantt View";
+ });
+ this.fields._pseudo_group_by = {type: "string"};
+ }
+
+
+ //Sort
+ var sort_fld = "sequence";
+
+
+ if (second_sort){
+
+ sort_fld = model_fields_dict["default_seq"];
+ if (sort_fld) {
+ tasks = _.sortBy(tasks, function (o) {
+ return o[sort_fld];
+ });
+ }
+ }
+
+
+ if (!second_sort){
+
+ if (ItemsSorted){
+
+ sort_fld = model_fields_dict["sorting_seq"];
+ if (sort_fld) {
+ tasks = _.sortBy(tasks, function (o) {
+ return o[sort_fld];
+ });
+ }
+
+ }
+
+ }
+
+
+ // get the groups
+ var split_groups = function(tasks, group_bys) {
+
+ if (group_bys.length === 0)
+ return tasks;
+ var sp_groups = [];
+ _.each(tasks, function(task) {
+ var group_name = task[_.first(group_bys)];
+ var group = _.find(sp_groups, function(group) { return _.isEqual(group.name, group_name); });
+ if (group === undefined) {
+ group = {name:group_name, tasks: [], __is_group: true};
+ sp_groups.push(group);
+ }
+ group.tasks.push(task);
+ });
+ _.each(sp_groups, function(group) {
+ group.tasks = split_groups(group.tasks, _.rest(group_bys));
+ });
+ return sp_groups;
+ };
+
+ var groups = split_groups(tasks, group_bys);
+
+
+ //Sort by sequenses group if detect.
+ if (second_sort) {
+
+ var s_field = gantt_attrs["second_seq_field"];
+ groups = _.map(groups, function(result) {
+
+ var s_id = result["name"][0];
+ var sort_element = _.findWhere(second_sort, {id: s_id});
+
+ if (sort_element) {
+ result["sort_seq"] = sort_element[s_field];
+ }else{
+ result["sort_seq"] = -1;
+ }
+
+ return result
+
+ });
+
+
+ groups = _.sortBy(groups, function (o) {
+ return o["sort_seq"];
+ });
+
+ }
+
+ if (main_group) {
+
+ groups = _.map(groups, function(result) {
+
+ var s_id = result["name"][0];
+ var main_element = _.findWhere(main_group, {id: s_id});
+
+ if (main_element) {
+ result["g_data"] = main_element;
+ }else{
+ result["g_data"] = false;
+ }
+
+ return result
+
+ });
+ }
+
+
+
+
+ var assign_to = [];
+ // genrate task
+ var generate_task_info = function(task, plevel) {
+
+ var level = plevel || 0;
+ if (task.__is_group) {
+ assign_to = task.user_id;
+ var task_infos = _.compact(_.map(task.tasks, function(sub_task) {
+ return generate_task_info(sub_task, level + 1);
+ }));
+ if (task_infos.length === 0)
+ return;
+
+ //before
+ // format_value (value, descriptor, value_if_empty)
+ // var group_name = formats.format_value(task.name, parent.fields[group_bys[level]]);
+
+
+ //last//
+ // var field = parent.fields[group_bys[level]];
+ // var group_name = field_utils.format[field.type](task.name, field);
+
+ var group_name = undefined;
+
+ var field = parent.fields[group_bys[level]];
+
+ if (field && field.type === "datetime"){
+ var value_format = time.auto_str_to_date(task.name);
+ value_format = moment(value_format);
+ group_name = field_utils.format[field.type](value_format, field, {timezone: false} );
+ }
+ else{
+ group_name = field_utils.format[field.type](task.name, field);
+ }
+
+ // Group by check is fold
+ var fold = false;
+ if (task.hasOwnProperty("g_data"))
+ {
+ fold = task.g_data["fold"]
+ }
+
+
+
+ var task_count = task_infos.length;
+ return {
+ is_group: task.__is_group,
+ group_info: task.name,
+ group_field: group_bys[level],
+ child_task:task_infos,
+ task_name:group_name,
+ level:level,
+ task_count: task_count,
+ fold: fold
+ };
+ } else {
+
+ var today = new Date();
+ var task_name = task.__name;
+
+
+ assign_to = task[model_fields_dict["user_id"]];
+
+ var mp_level = task[model_fields_dict["mp_level"]];
+
+ var default_seq = task[model_fields_dict["default_seq"]];
+
+ var sorting_level = task[model_fields_dict["sorting_level"]];
+ var sorting_seq = task[model_fields_dict["sorting_seq"]];
+
+ var subtask_project_id = task[model_fields_dict["subtask_project_id"]];
+ var load_data_id = task[model_fields_dict["load_data_id"]];
+
+ var parent_id = task[model_fields_dict["parent_id"]];
+ var subtask_count = task[model_fields_dict["subtask_count"]];
+
+
+ var task_start = time.auto_str_to_date(task[model_fields_dict["date_start"]]);
+ if (!task_start){
+ task_start = today
+ }
+
+ var task_stop = time.auto_str_to_date(task[model_fields_dict["date_stop"]]);
+ if (!task_stop) {
+ task_stop = task_start
+ }
+
+ var date_deadline = time.auto_str_to_date(task[model_fields_dict["date_deadline"]]);
+ if (!date_deadline){
+ date_deadline = false
+ }
+
+ var progress = task[model_fields_dict["progress"]];
+ var is_milestone = task[model_fields_dict["is_milestone"]];
+ var on_gantt = task[model_fields_dict["on_gantt"]];
+
+ var project_id = undefined;
+ try {
+ project_id = task[model_fields_dict["project_id"]][0];
+ } catch (err) {}
+
+
+ var date_done = time.auto_str_to_date(task[model_fields_dict["date_done"]]);
+ if (!date_done){
+ date_done = false
+ }
+
+
+ var constrain_date = time.auto_str_to_date(task[model_fields_dict["constrain_date"]]);
+ if (!constrain_date){
+ constrain_date = false
+ }
+
+ var duration = task[model_fields_dict["duration"]];
+ var plan_duration = task[model_fields_dict["plan_duration"]];
+
+
+ var plan_action = task[model_fields_dict["plan_action"]];
+
+ var color_gantt_set = task[model_fields_dict["color_gantt_set"]];
+ var color_gantt = task[model_fields_dict["color_gantt"]];
+
+ var duration_scale = task[model_fields_dict["duration_scale"]];
+
+
+ var summary_date_start = time.auto_str_to_date(task[model_fields_dict["summary_date_start"]]);
+ if (!summary_date_start){
+ summary_date_start = false
+ }
+
+ var summary_date_end = time.auto_str_to_date(task[model_fields_dict["summary_date_end"]]);
+ if (!summary_date_end){
+ summary_date_end = false
+ }
+
+
+ var schedule_mode = task[model_fields_dict["schedule_mode"]];
+ var constrain_type = task[model_fields_dict["constrain_type"]];
+
+ var state = task[model_fields_dict["state"]];
+
+ var fold = task[model_fields_dict["fold"]];
+
+ var critical_path = task[model_fields_dict["critical_path"]];
+ var cp_shows = task[model_fields_dict["cp_shows"]];
+ var cp_detail = task[model_fields_dict["cp_detail"]];
+
+ var p_loop = task[model_fields_dict["p_loop"]];
+ var doc_count = task[model_fields_dict["doc_count"]];
+
+
+
+
+ try {
+ GtimeStopA.push(task_stop.getTime());
+ } catch (err) {}
+
+ try {
+ GtimeStartA.push(task_start.getTime());
+ } catch (err) {}
+
+ try {
+ GtimeStopA.push(date_done.getTime());
+ GtimeStartA.push(date_done.getTime());
+ } catch (err) {}
+
+ try {
+ GtimeStopA.push(date_deadline.getTime());
+ GtimeStartA.push(date_deadline.getTime());
+ } catch (err) {}
+
+
+
+ return {
+ id:task.id,
+ task_name: task_name,
+ task_start: task_start,
+ task_stop: task_stop,
+ level:level,
+ assign_to:assign_to,
+
+ mp_level : mp_level,
+
+ default_seq : default_seq,
+
+ sorting_level : sorting_level,
+ sorting_seq : sorting_seq,
+
+ project_id: project_id,
+
+ date_deadline: date_deadline,
+
+ progress: progress,
+
+ is_milestone: is_milestone,
+
+ constrain_date: constrain_date,
+ schedule_mode: schedule_mode,
+ constrain_type: constrain_type,
+
+ duration: duration,
+ plan_duration: plan_duration,
+
+
+ plan_action: plan_action,
+
+ color_gantt_set: color_gantt_set,
+ color_gantt: color_gantt,
+
+ duration_scale: duration_scale,
+
+ summary_date_start: summary_date_start,
+ summary_date_end: summary_date_end,
+
+ on_gantt: on_gantt,
+
+ subtask_project_id: subtask_project_id,
+ load_data_id: load_data_id,
+
+ parent_id: parent_id,
+ subtask_count: subtask_count,
+
+ date_done: date_done,
+ state: state,
+
+ fold:fold,
+
+ critical_path:critical_path,
+ cp_shows: cp_shows,
+ cp_detail: cp_detail,
+
+ p_loop: p_loop,
+
+ doc_count: doc_count,
+
+ is_group: false,
+ // group_field: group_bys[level],
+
+
+ };
+ }
+ };
+
+ //generate projects info from groupby
+ var projects = _.map(groups, function(result) {
+ return generate_task_info(result, 0);
+ });
+
+
+ return {
+ projects : projects,
+ timestop : GtimeStopA,
+ timestart : GtimeStartA
+
+ }
+
+
+ }
+
+ return {
+ flatRows: flatRows,
+ groupRows: groupRows,
+ getFields : getFields
+ }
+
+});
\ No newline at end of file
diff --git a/odex25_project/web_gantt_native/static/src/js/gantt_tool_hint.js b/odex25_project/web_gantt_native/static/src/js/gantt_tool_hint.js
new file mode 100644
index 000000000..228cfcca2
--- /dev/null
+++ b/odex25_project/web_gantt_native/static/src/js/gantt_tool_hint.js
@@ -0,0 +1,105 @@
+odoo.define('web_gantt_native.ToolHint', function (require) {
+"use strict";
+
+
+var core = require('web.core');
+var Widget = require('web.Widget');
+var time = require('web.time');
+
+
+
+
+var _t = core._t;
+
+
+
+var GanttToolHint = Widget.extend({
+ template: "GanttToolHint",
+
+
+ init: function(parent) {
+
+ this._super(parent);
+
+ },
+
+ start: function() {
+
+ var self = this;
+
+ this.$el.append('
');
+
+ $('
Start date:
').appendTo(this.$el.children(".task-gantt-line-hint-names"));
+ $('
End date:
').appendTo(this.$el.children(".task-gantt-line-hint-names"));
+ $('
Duration:
').appendTo(this.$el.children(".task-gantt-line-hint-names"));
+ $('
Deadline:
').appendTo(this.$el.children(".task-gantt-line-hint-names"));
+
+ this.$el.append('
');
+
+ $('
').appendTo(this.$el.children(".task-gantt-line-hint-values"));
+ $('
').appendTo(this.$el.children(".task-gantt-line-hint-values"));
+ $('
').appendTo(this.$el.children(".task-gantt-line-hint-values"));
+ $('
').appendTo(this.$el.children(".task-gantt-line-hint-values"));
+
+
+ },
+
+
+ renderElement: function () {
+ this._super();
+
+ },
+
+ show_hint : function(gantt_bar, start_end, ui, type) {
+
+ // var task_start = start_end.task_start;
+ // task_start = time.auto_date_to_str(task_start, 'datetime');
+ // var task_end = start_end.task_end;
+ // task_end = time.auto_date_to_str(task_end, 'datetime');
+
+
+ var l10n = _t.database.parameters;
+
+ var formatDate = time.strftime_to_moment_format( l10n.date_format + ' ' + l10n.time_format);
+
+
+ var task_start = moment(start_end.task_start).format(formatDate);
+ var task_end = moment(start_end.task_end).format(formatDate);
+
+ var duration = moment.duration(moment(start_end.task_start).diff(moment(start_end.task_end)));
+
+ var duration_seconds = humanizeDuration(parseInt(duration.asSeconds(), 10)*1000, {round: true });
+
+
+
+ var o_left = gantt_bar.offset().left;
+ var o_top = gantt_bar.offset().top;
+
+ if (ui){
+ o_left = ui.offset.left;
+ o_top = ui.offset.top;
+
+ }
+
+ this.$el.find('div.hint-start-value').text(task_start);
+ this.$el.find('div.hint-end-value').text(task_end);
+ this.$el.find('div.hint-duration-value').text(duration_seconds);
+
+
+ if (type === "deadline"){
+
+
+ var formatDateOnly = time.strftime_to_moment_format( l10n.date_format);
+ var deadline_time = moment(start_end.deadline_time).format(formatDateOnly);
+ this.$el.find('div.hint-deadline-value').text(deadline_time);
+
+ }
+
+ this.$el.offset({ top: o_top-55, left: o_left});
+ }
+
+});
+
+return GanttToolHint;
+
+});
\ No newline at end of file
diff --git a/odex25_project/web_gantt_native/static/src/js/gantt_tool_tip.js b/odex25_project/web_gantt_native/static/src/js/gantt_tool_tip.js
new file mode 100644
index 000000000..24f9ec861
--- /dev/null
+++ b/odex25_project/web_gantt_native/static/src/js/gantt_tool_tip.js
@@ -0,0 +1,240 @@
+odoo.define('web_gantt_native.ToolTip', function (require) {
+"use strict";
+
+
+var core = require('web.core');
+var Widget = require('web.Widget');
+var time = require('web.time');
+var _t = core._t;
+
+
+
+var GanttToolTip = Widget.extend({
+ template: "GanttToolTip",
+
+ /// this.chart.tooltip.show(this.resizerOffsetX, this);
+
+ init: function(parent, ganttbar, event) {
+
+ this._super(parent);
+ this.record = ganttbar;
+ this.event = event;
+
+ },
+
+ start: function() {
+
+
+ var self = this;
+
+ this.$el.append('
');
+
+ var record = self.record[0];
+
+ if (record) {
+
+ var record_data = record.record;
+
+ var name = record_data['value_name'];
+
+ // var task_start = record_data['task_start'].toUTCString()
+ //
+ // var ttt = record_data.task_start;
+
+ // var formatDate = "DD.MM.YYYY HH:mm:ss"; // the string that represents desired format.
+ var l10n = _t.database.parameters;
+
+ var formatDate = time.strftime_to_moment_format( l10n.date_format + ' ' + l10n.time_format);
+
+
+ // var task_start = time.auto_date_to_str(record_data.task_start, 'datetime');
+
+
+ var task_start = moment(record_data["task_start"]).format(formatDate);
+ var task_stop = moment(record_data["task_stop"]).format(formatDate);
+
+ var date_deadline = false;
+ if (record_data["date_deadline"]) {
+
+ date_deadline = moment(record_data["date_deadline"]).format(formatDate);
+ }
+
+
+ // var task_stop = record_data['task_stop'];
+ // task_stop = time.auto_date_to_str(task_stop, 'datetime');
+
+ // var date_deadline = record_data['date_deadline'];
+ // date_deadline = time.auto_date_to_str(date_deadline, 'datetime');
+
+ var progress = '';
+ var progress_name = 'progress';
+ if (record_data['progress']){
+ progress = record_data['progress'];
+
+ var progress_field = self.__parentedParent.model_fields_dict['progress'];
+ if (progress_field){
+ progress_name = self.__parentedParent.fields[progress_field].string;
+
+ }
+ self.__parentedParent.fields[''];
+ // progress_name
+ //self.model_fields_dict = getFields["model_fields_dict"];
+
+ }
+
+ var date_done = false;
+ if (record_data["date_done"]) {
+
+ date_done = moment(record_data["date_done"]).format(formatDate);
+
+ }
+
+ var duration = false;
+ if (record_data["duration"]) {
+ var total = parseInt(record_data["duration"], 10);
+
+ if (record_data['duration_scale']) {
+ duration = humanizeDuration(total*1000,{ units: record_data['duration_scale'].split(","), round: true });
+ }
+ else{
+ duration = humanizeDuration(total*1000, {round: true });
+
+ }
+
+ }
+
+ var plan_duration = false;
+ if (record_data["plan_duration"]) {
+ var plan_total = parseInt(record_data["plan_duration"], 10);
+
+ if (record_data['duration_scale']) {
+ plan_duration = humanizeDuration(plan_total*1000,{ units: record_data['duration_scale'].split(","), round: true});
+ }
+ else{
+ plan_duration = humanizeDuration(plan_total*1000, {round: true });
+ }
+
+ }
+
+
+
+
+
+ var constrain_type = false;
+ if (record_data['constrain_type']){
+
+
+ var type = [];
+ type["asap"] = 'As Soon As Possible';
+ type["alap"] = 'As Late As Possible';
+ type["fnet"] = 'Finish No Earlier Than';
+ type["fnlt"] = 'Finish No Later Than';
+ type["mso"] = 'Must Start On';
+ type["mfo"] = 'Must Finish On';
+ type["snet"] = 'Start No Earlier Than';
+ type["snlt"] = 'Start No Later Than';
+
+ constrain_type = type[record_data['constrain_type']];
+
+
+ }
+
+ var constrain_date = "none";
+ if (record_data["constrain_date"]) {
+
+ constrain_date = moment(record_data["constrain_date"]).format(formatDate);
+
+ }
+
+
+
+
+
+ $('
Name:
').appendTo(this.$el.children(".task-gantt-line-tip-names"));
+ $('
Start date:
').appendTo(this.$el.children(".task-gantt-line-tip-names"));
+ $('
End date:
').appendTo(this.$el.children(".task-gantt-line-tip-names"));
+ $('
Deadline:
').appendTo(this.$el.children(".task-gantt-line-tip-names"));
+ $('
'+progress_name+'
').appendTo(this.$el.children(".task-gantt-line-tip-names"));
+
+ if (date_done) {
+ $('
Done date:
').appendTo(this.$el.children(".task-gantt-line-tip-names"));
+ }
+
+ if (plan_duration) {
+ $('
Plan Duration:
').appendTo(this.$el.children(".task-gantt-line-tip-names"));
+ }
+
+ if (duration) {
+ $('
Duration:
').appendTo(this.$el.children(".task-gantt-line-tip-names"));
+ }
+
+ if (constrain_type) {
+ $('
Constraint:
').appendTo(this.$el.children(".task-gantt-line-tip-names"));
+ }
+
+ this.$el.append('
');
+
+
+
+
+ $('
' + name + '
').appendTo(this.$el.children(".task-gantt-line-tip-values"));
+ $('
' + task_start + '
').appendTo(this.$el.children(".task-gantt-line-tip-values"));
+ $('
' + task_stop + '
').appendTo(this.$el.children(".task-gantt-line-tip-values"));
+ $('
' + date_deadline + '
').appendTo(this.$el.children(".task-gantt-line-tip-values"));
+ $('
' + progress + '%
').appendTo(this.$el.children(".task-gantt-line-tip-values"));
+
+ if (date_done) {
+ $('
' + date_done + '
').appendTo(this.$el.children(".task-gantt-line-tip-values"));
+ }
+ if (plan_duration) {
+ $('
' + plan_duration + '
').appendTo(this.$el.children(".task-gantt-line-tip-values"));
+ }
+
+ if (duration) {
+ $('
' + duration + '
').appendTo(this.$el.children(".task-gantt-line-tip-values"));
+ }
+
+ if (constrain_type) {
+ $('
' + constrain_type + ': ' + constrain_date + '
').appendTo(this.$el.children(".task-gantt-line-tip-values"));
+ }
+
+
+ }
+
+ if (self.record.offset()) {
+
+ var o_left = this.event.pageX;
+ var o_top = self.record.offset().top;
+
+ var o_right = $(window).width() - (self.record.offset().left + self.record.outerWidth());
+
+ var tip_lenght = this.$el.children(".task-gantt-line-tip-names").children().length;
+ var top_new = o_top - (15*tip_lenght); // if added tip plus 15 every tip
+
+ if (o_top < 325){
+ top_new = o_top + 20;
+ }
+
+ if (o_right < 200){
+ o_left = o_left - 200;
+ }
+
+ this.$el.offset({top: top_new , left: o_left});
+ }
+
+ },
+
+
+ renderElement: function () {
+ this._super();
+ this.$el.data('record', this);
+
+ },
+
+
+
+});
+
+return GanttToolTip;
+
+});
\ No newline at end of file
diff --git a/odex25_project/web_gantt_native/static/src/js/native_gantt_controller.js b/odex25_project/web_gantt_native/static/src/js/native_gantt_controller.js
new file mode 100644
index 000000000..68b239dc8
--- /dev/null
+++ b/odex25_project/web_gantt_native/static/src/js/native_gantt_controller.js
@@ -0,0 +1,650 @@
+odoo.define('web_gantt_native.NativeGanttController', function (require) {
+"use strict";
+
+var AbstractController = require('web.AbstractController');
+var core = require('web.core');
+var config = require('web.config');
+var Dialog = require('web.Dialog');
+var dialogs = require('web.view_dialogs');
+var time = require('web.time');
+
+var GanttPager = require('web_gantt_native.Pager');
+
+
+
+var _t = core._t;
+var QWeb = core.qweb;
+
+
+var NativeGanttController = AbstractController.extend({
+
+ custom_events: _.extend({}, AbstractController.prototype.custom_events, {
+ gantt_refresh_after_change: '_onGanttRefresh',
+ gantt_fast_refresh_after_change: '_refresh_after_change',
+ gantt_add_hover: '_add_hover',
+ gantt_remove_hover: '_remove_hover',
+
+ // gantt_drop_item: '_drop_item',
+
+ 'sort_item': function (event) {
+ this.sort_item(event.target);
+ },
+
+ }),
+ events: _.extend({}, AbstractController.prototype.events, {
+
+ 'mouseover .task-gantt-info, .task-gantt-timeline-row' :'HandleHoverOver',
+ 'mouseout .task-gantt-info, .task-gantt-timeline-row' :'HandleHoverOut',
+
+ }),
+
+
+
+ init: function (parent, model, renderer, params) {
+ this._super.apply(this, arguments);
+ this.set('title', params.title);
+ this.context = params.context;
+ this.initialState = params.initialState;
+
+ },
+
+
+ _onOpenRecord: function (event) {
+ event.stopPropagation();
+ // var record = this.model.get(event.data.id, {raw: true});
+ this.trigger_up('switch_view', {
+ view_type: 'form',
+ res_id: event.data.res_id,
+ mode: event.data.mode || 'readonly',
+ model: event.data.model
+ });
+ },
+
+
+ _onGanttRefresh: function (event) {
+ var self = this;
+ this.model._do_load().then(function (ev) {
+ self.reload();
+ });
+
+ },
+
+
+ _refresh_after_change: function () {
+ this.renderer.fast_update = true;
+ var def = this._update(this.initialState, { shouldUpdateSearchComponents: false });
+ return Promise.all([def]);
+
+ },
+
+ _update: async function (state, params) {
+ var self = this;
+ //Get Zoom Event from time scale type
+ var def = undefined;
+ if (this.renderer.timeType === 'month_day'){
+ await self.ZoomDaysClick();
+ }
+ if (this.renderer.timeType === 'day_1hour'){
+ await self.Zoom1hClick();
+ }
+ if (this.renderer.timeType === 'day_2hour'){
+ await self.Zoom2hClick();
+ }
+ if (this.renderer.timeType === 'day_4hour'){
+ await self.Zoom4hClick();
+ }
+ if (this.renderer.timeType === 'day_8hour'){
+ await self.Zoom8hClick();
+ }
+ if (this.renderer.timeType === 'year_month'){
+ await self.ZoomMonthClick();
+ }
+ if (this.renderer.timeType === 'month_week'){
+ await self.ZoomWeeksClick();
+ }
+ if (this.renderer.timeType === 'quarter'){
+ await self.ZoomQuarterClick();
+ }
+
+
+
+ //Update
+
+ //Get Getter offset from session
+
+ $('.task-gantt-list').width(this.renderer.local_storage.getItem("gantt_offset") || this.renderer.gutterOffset);
+ $('.timeline-gantt-items').width(this.renderer.local_storage.getItem("gantt_offset") || this.renderer.gutterOffset);
+
+ $('.task-gantt-items').width(this.renderer.local_storage.getItem("items_offset") || this.renderer.itemsOffset);
+ //Hover selected rows after refresh page
+ var rowdata = '#task-gantt-timeline-row-'+this.renderer.hover_id;
+ var rowitem = '#task-gantt-item-'+this.renderer.hover_id;
+
+ $(rowdata).addClass("task-gantt-timeline-row-hover");
+ $(rowitem).addClass("task-gantt-item-hover");
+
+
+ // Goto Vertial and Horizontal Scroll
+ if (this.renderer.TimeToLeft) {
+ var task_left = this.renderer.TimeToLeft;
+ $('.task-gantt-timeline').animate({
+ scrollLeft: task_left
+ }, 0, function() {
+ // Animation complete.
+ });
+ $('.timeline-gantt-head').animate({
+ scrollLeft: task_left
+ }, 0, function() {
+ // Animation complete.
+ });
+
+
+ this.renderer.gantt_timeline_scroll_widget.scrollOffset(task_left);
+
+ }
+
+
+ if (this.renderer.ScrollToTop) {
+ var panel_top = this.renderer.ScrollToTop;
+ $('.task-gantt').animate({
+ scrollTop: panel_top
+ }, 0, function() {
+ // Animation complete.
+ });
+ }
+
+ if (this.pager){
+ this.pager.refresh(this.renderer.state.pager.records, this.renderer.state.pager.limit);
+ }
+
+ // sync sync promise :
+ // await this._super(...arguments);
+ // await this.update({ shouldUpdateSearchComponents: false }, { reload: false });
+ // return Promise.all([def, this._super.apply(this, arguments)]);
+ // return this._super.apply(this, arguments);
+ },
+
+
+ renderPager: function ($node, options) {
+
+ var self = this;
+ var data = [];
+
+ data["size"] = this.renderer.state.pager.records;
+ data["limit"] = this.renderer.state.pager.limit;
+
+ this.pager = new GanttPager(this, data.size, data.limit, options);
+
+ this.pager.on('pager_changed', this, function (newState) {
+ self.pager.disable();
+ self.renderer.state.pager.limit = parseInt(newState.limit);
+ self.reload().then(self.pager.enable.bind(self.pager));
+ });
+
+ this.pager.appendTo($node);
+
+ },
+
+
+ renderButtons: function ($node) {
+
+ var context = {measures: _.pairs(_.omit(this.measures, '__count__'))};
+ this.$buttons = $(QWeb.render('APSGanttView.buttons', context));
+ this.$buttons.click(this.on_button_click.bind(this));
+
+ this.renderPager(this.$buttons)
+
+ },
+
+ on_button_click: function (event) {
+
+ this.renderer.fast_update = true;
+ let $target = $(event.target);
+
+ if ($target.hasClass('task-gantt-today')) { return this.ClickToday(); }
+ if ($target.hasClass('task-gantt-zoom-1h')) { this.renderer.timeType = 'day_1hour';}
+ if ($target.hasClass('task-gantt-zoom-2h')) { this.renderer.timeType = 'day_2hour'; }
+ if ($target.hasClass('task-gantt-zoom-4h')) { this.renderer.timeType = 'day_4hour'; }
+ if ($target.hasClass('task-gantt-zoom-8h')) { this.renderer.timeType = 'day_8hour'; }
+ if ($target.hasClass('task-gantt-zoom-days')) { this.renderer.timeType = 'month_day'; }
+ if ($target.hasClass('task-gantt-zoom-month')) { this.renderer.timeType = 'year_month'; }
+ if ($target.hasClass('task-gantt-zoom-weeks')) { this.renderer.timeType = 'month_week' }
+ if ($target.hasClass('task-gantt-zoom-quarter')) { this.renderer.timeType = 'quarter' }
+
+ return this._refresh_after_change();
+ },
+
+
+
+ ModificateAfterRender: function () {
+
+ // Goto Horizontal Scroll and slider possition
+ if (this.renderer.TimeToLeft) {
+ var task_left = this.renderer.TimeToLeft;
+ $('.task-gantt-timeline').animate({
+ scrollLeft: task_left
+ }, 0, function () {
+ // Animation complete.
+ });
+ $('.timeline-gantt-head').animate({
+ scrollLeft: task_left
+ }, 0, function () {
+ // Animation complete.
+ });
+
+ this.renderer.gantt_timeline_scroll_widget.scrollOffset(task_left);
+ }
+ },
+
+
+
+
+
+ //Zoom Out - Zoom In
+
+ Zoom1hClick: async function() {
+ await this.ZoomHoursClick(1, 'day_1hour' );
+ // this.timeType = 'day_1hour';
+ },
+ Zoom2hClick: async function() {
+ await this.ZoomHoursClick(2, 'day_2hour');
+ // this.timeType = 'day_2hour';
+ },
+ Zoom4hClick: async function() {
+ await this.ZoomHoursClick(4, 'day_4hour');
+ // this.timeType = 'day_4hour';
+ },
+ Zoom8hClick: async function() {
+ await this.ZoomHoursClick(8, 'day_8hour');
+ // this.timeType = 'day_8hour';
+ },
+
+
+
+ ZoomHoursClick: async function (div_hour, timeType) {
+
+ this.renderer.firstDayDate = moment(this.renderer.GtimeStart).clone().startOf('month'); //Start month
+ this.renderer.lastDayDate = moment(this.renderer.GtimeStop).clone().endOf('month'); //End
+
+ this.renderer.timeScaleUTC = this.renderer.lastDayDate.valueOf() - this.renderer.firstDayDate.valueOf(); // raznica vremeni
+ this.renderer.firstDayScale = this.renderer.firstDayDate.valueOf();
+
+ var iter = moment(this.renderer.firstDayDate).twix(this.renderer.lastDayDate).iterate(div_hour, 'hours');
+
+ var hour2Range = [];
+ while (iter.hasNext()) {
+
+ hour2Range.push(iter.next().toDate())
+
+ }
+
+
+ var daysGroup = _(hour2Range).groupBy(function (day) {
+ return moment(day).format("YYYY MM DD");
+
+ });
+
+ this.renderer.timeType = timeType;
+ this.renderer.timeScale = 40; //px
+
+ var iter_k = moment(this.renderer.firstDayDate).twix(this.renderer.lastDayDate).iterate(1, 'hours');
+
+ var K_scale = 0;
+ while (iter_k.hasNext()) {
+ iter_k.next();
+ K_scale = K_scale + 1;
+ }
+
+ K_scale = K_scale / div_hour;
+ // var K_scale = hour2Range.length;
+ //
+ // var first_tzm_m = this.renderer.firstDayDate.format("ZZ");
+ // var second_tzm_m = this.renderer.lastDayDate.format("ZZ");
+ // var diff_tzm_h = ( first_tzm_m - second_tzm_m)/100;
+ //
+ // K_scale = K_scale - (diff_tzm_h / div_hour);
+
+
+ this.renderer.timeline_width = this.renderer.timeScale * K_scale; // min otrzok 60 - eto 4 4asa. v sutkah 6 otrezkov
+ // this.renderer.timeline_width = this.renderer.timeScale*1092.5; // min otrzok 60 - eto 4 4asa. v sutkah 6 otrezkov
+
+ this.renderer.pxScaleUTC = Math.round(this.renderer.timeScaleUTC / this.renderer.timeline_width); // skolko vremeni v odnom px
+
+ await this.renderer.AddItemList();
+
+ await this.renderer.AddItemsData();
+
+ await this.renderer.AddTimeLineHead(this.renderer.timeScale, this.renderer.timeType, daysGroup, false);
+ await this.renderer.AddTimeLineData(this.renderer.timeScale, this.renderer.timeType, this.renderer.rows_to_gantt);
+
+ await this.renderer.AddTimeLineArrow(this.renderer.timeline_width);
+ await this.renderer.AddTimeLineGhost();
+
+ await this.renderer.AddTimeLineSummary();
+ await this.renderer.AddTimeLineFirst();
+
+ await this.renderer.DivResize();
+ await this.renderer.ModeActive();
+
+ this.ModificateAfterRender()
+
+ },
+
+
+ ZoomDaysClick: async function () {
+
+ this.renderer.firstDayDate = moment(this.renderer.GtimeStart).clone().startOf('month'); //Start month
+ this.renderer.lastDayDate = moment(this.renderer.GtimeStop).clone().endOf('month'); //End
+ this.renderer.timeScaleUTC = this.renderer.lastDayDate.valueOf() - this.renderer.firstDayDate.valueOf(); //raznica vremeni
+ this.renderer.firstDayScale = this.renderer.firstDayDate.valueOf();
+
+ var currentLocaleData = moment.localeData();
+
+ //Get Days Range
+ var iter = moment(this.renderer.firstDayDate).twix(this.renderer.lastDayDate).iterate("days");
+
+ var dayRange = [];
+ while (iter.hasNext()) {
+ dayRange.push(iter.next().toDate())
+ }
+
+ //Get Year - Month range
+ var iter_first = moment(this.renderer.firstDayDate).twix(this.renderer.lastDayDate).iterate("month");
+
+ var monthRange = [];
+ while (iter_first.hasNext()) {
+
+ var mt_month = iter_first.next();
+ var month = [];
+
+ month['year'] = mt_month.year();
+ month['month'] = currentLocaleData.months(mt_month);
+ month['days'] = mt_month.daysInMonth();
+
+ monthRange.push(month)
+ }
+
+ this.renderer.timeScale = 24; //px
+
+ this.renderer.timeType = 'month_day';
+ this.renderer.timeline_width = this.renderer.timeScale * dayRange.length;
+ this.renderer.pxScaleUTC = Math.round(this.renderer.timeScaleUTC / this.renderer.timeline_width); // skolko vremeni v odnom px
+
+ await this.renderer.AddItemList();
+
+
+ await this.renderer.AddItemsData();
+
+ await this.renderer.AddTimeLineHead(this.renderer.timeScale, this.renderer.timeType, monthRange, dayRange);
+ await this.renderer.AddTimeLineData(this.renderer.timeScale, this.renderer.timeType, this.renderer.rows_to_gantt);
+
+ await this.renderer.AddTimeLineArrow(this.renderer.timeline_width);
+ await this.renderer.AddTimeLineGhost();
+
+ await this.renderer.AddTimeLineSummary();
+ await this.renderer.AddTimeLineFirst();
+
+ await this.renderer.DivResize();
+ await this.renderer.ModeActive();
+
+
+ this.ModificateAfterRender()
+
+ },
+
+ ZoomMonthClick: async function () {
+
+ this.renderer.firstDayDate = moment(this.renderer.GtimeStart).clone().startOf('month'); //Start month
+ this.renderer.lastDayDate = moment(this.renderer.GtimeStop).clone().endOf('month'); //End
+ this.renderer.timeScaleUTC = this.renderer.lastDayDate.valueOf() - this.renderer.firstDayDate.valueOf(); // raznica vremeni
+ this.renderer.firstDayScale = this.renderer.firstDayDate.valueOf();
+
+ var iter = moment(this.renderer.firstDayDate).twix(this.renderer.lastDayDate).iterate('month');
+
+ var month2Range = [];
+ while (iter.hasNext()) {
+
+ month2Range.push(iter.next().toDate())
+
+ }
+
+ var monthGroup = _(month2Range).groupBy(function (month) {
+ return moment(month).format("YYYY");
+
+ });
+
+
+ this.renderer.timeScale = 30;//px
+ this.renderer.timeType = 'year_month';
+
+ this.renderer.timeline_width = this.renderer.timeScale * month2Range.length; // min otrzok 60 - eto 4 4asa. v sutkah 6 otrezkov
+ this.renderer.pxScaleUTC = Math.round(this.renderer.timeScaleUTC / this.renderer.timeline_width); // skolko vremeni v odnom px
+
+ await this.renderer.AddItemList();
+
+ await this.renderer.AddItemsData();
+
+ await this.renderer.AddTimeLineHead(this.renderer.timeScale, this.renderer.timeType, monthGroup, false);
+ await this.renderer.AddTimeLineData(this.renderer.timeScale, this.renderer.timeType, this.renderer.rows_to_gantt);
+
+ await this.renderer.AddTimeLineArrow(this.renderer.timeline_width);
+ await this.renderer.AddTimeLineGhost();
+
+ await this.renderer.AddTimeLineSummary();
+ await this.renderer.AddTimeLineFirst();
+
+ await this.renderer.DivResize();
+ await this.renderer.ModeActive();
+
+ this.ModificateAfterRender()
+
+ },
+
+
+ ZoomWeeksClick: async function () {
+ //
+ let firstDayDate = moment(this.renderer.GtimeStart).clone().startOf(this.renderer.week_type).add(-3, 'weeks'); //Start month
+ let lastDayDate = moment(this.renderer.GtimeStop).clone().endOf(this.renderer.week_type).add(3, 'weeks'); //End
+
+ var iter = moment(firstDayDate).twix(lastDayDate).iterate('Week');
+
+ var week2Range = [];
+ while (iter.hasNext()) {
+ week2Range.push(iter.next().toDate())
+ }
+
+ this.renderer.firstDayDate = moment(week2Range[0]).startOf(this.renderer.week_type)
+ this.renderer.lastDayDate = moment(week2Range[week2Range.length-1])
+
+ this.renderer.timeScaleUTC = this.renderer.lastDayDate.valueOf() - this.renderer.firstDayDate.valueOf(); // raznica vremeni
+ this.renderer.firstDayScale = this.renderer.firstDayDate.valueOf();
+
+
+ var weeksGroup = _(week2Range).groupBy(function (week) {
+ return moment(week).format("YYYY");
+ });
+
+
+ this.renderer.timeScale = 30;//px
+ this.renderer.timeType = 'month_week';
+
+ this.renderer.timeline_width = this.renderer.timeScale * week2Range.length; // min otrzok 60 - eto 4 4asa. v sutkah 6 otrezkov
+ this.renderer.pxScaleUTC = Math.round(this.renderer.timeScaleUTC / this.renderer.timeline_width); // skolko vremeni v odnom px
+
+ await this.renderer.AddItemList();
+
+ await this.renderer.AddItemsData();
+
+ await this.renderer.AddTimeLineHead(this.renderer.timeScale, this.renderer.timeType, weeksGroup, false);
+ await this.renderer.AddTimeLineData(this.renderer.timeScale, this.renderer.timeType, this.renderer.rows_to_gantt);
+
+ await this.renderer.AddTimeLineArrow(this.renderer.timeline_width);
+ await this.renderer.AddTimeLineGhost();
+
+ await this.renderer.AddTimeLineSummary();
+ await this.renderer.AddTimeLineFirst();
+
+ await this.renderer.DivResize();
+ await this.renderer.ModeActive();
+
+ this.ModificateAfterRender()
+
+ },
+
+
+ ZoomQuarterClick: async function () {
+
+
+ this.renderer.firstDayDate = moment(this.renderer.GtimeStart).clone().startOf('Quarter'); //Start month
+ this.renderer.lastDayDate = moment(this.renderer.GtimeStop).clone().endOf('Quarter'); //End
+ this.renderer.timeScaleUTC = this.renderer.lastDayDate.valueOf() - this.renderer.firstDayDate.valueOf(); // raznica vremeni
+ this.renderer.firstDayScale = this.renderer.firstDayDate.valueOf();
+
+
+ var iter = moment(this.renderer.firstDayDate).twix(this.renderer.lastDayDate).iterate('Quarter');
+
+ var quarter2Range = [];
+ while (iter.hasNext()) {
+ quarter2Range.push(iter.next().toDate())
+ }
+
+ var quarterGroup = _(quarter2Range).groupBy(function (quarter) {
+ return moment(quarter).format("YYYY");
+ });
+
+
+ this.renderer.timeScale = 80;//px
+ this.renderer.timeType = 'quarter';
+
+ this.renderer.timeline_width = this.renderer.timeScale * quarter2Range.length; // min otrzok 60 - eto 4 4asa. v sutkah 6 otrezkov
+ this.renderer.pxScaleUTC = Math.round(this.renderer.timeScaleUTC / this.renderer.timeline_width); // skolko vremeni v odnom px
+
+ await this.renderer.AddItemList();
+
+ await this.renderer.AddItemsData();
+
+ await this.renderer.AddTimeLineHead(this.renderer.timeScale, this.renderer.timeType, quarterGroup, false);
+ await this.renderer.AddTimeLineData(this.renderer.timeScale, this.renderer.timeType, this.renderer.rows_to_gantt);
+
+ await this.renderer.AddTimeLineArrow(this.renderer.timeline_width);
+ await this.renderer.AddTimeLineGhost();
+
+ await this.renderer.AddTimeLineSummary();
+ await this.renderer.AddTimeLineFirst();
+
+ await this.renderer.DivResize();
+ await this.renderer.ModeActive();
+
+ this.ModificateAfterRender()
+
+
+ },
+
+
+
+//Today Focus of Gantt Line Focus
+ ClickToday: function (event) {
+
+ var today = new Date();
+
+ var toscale = this.TimeToScale(today.getTime());
+
+ this.renderer.TimeToLeft = toscale;
+ this.Focus_Gantt(toscale);
+
+ },
+
+ // Any can focus on BAR
+ Focus_Gantt: function(task_start){
+
+ $('.timeline-gantt-head').animate( { scrollLeft: task_start-500 }, 1000);
+ $('.task-gantt-timeline').animate( { scrollLeft: task_start-500 }, 1000);
+
+ this.renderer.gantt_timeline_scroll_widget.scrollOffset(task_start-500);
+
+ },
+
+ TimeToScale: function(time){
+
+ if (time){
+
+ return Math.round((time-this.renderer.firstDayScale) / this.renderer.pxScaleUTC);
+ }
+
+ },
+
+
+// HandleHover
+ _add_hover: function(ev) {
+
+ var rowdata = '#task-gantt-timeline-row-'+ev.data['data_id'];
+ $(rowdata).addClass("task-gantt-timeline-row-hover");
+
+ var item_info = '#item-info-'+ev.data['data_id'];
+ $(item_info).addClass("item-info-hover");
+
+
+ },
+
+ _remove_hover: function(ev) {
+
+ var rowdata = '#task-gantt-timeline-row-'+ev.data['data_id'];
+ $(rowdata).removeClass("task-gantt-timeline-row-hover");
+
+ var item_info = '#item-info-'+ev.data['data_id'];
+ $(item_info).removeClass("item-info-hover");
+
+ },
+
+ HandleHoverOver: function(ev) {
+
+ if (ev.target.allowRowHover)
+ {
+
+ // var rowsort = '#task-gantt-item-sorting-'+ev.target['data-id'];
+ var rowdata = '#task-gantt-timeline-row-'+ev.target['data-id'];
+ // var rowitem = '#task-gantt-item-'+ev.target['data-id'];
+
+ var z_item = '.task-gantt-item-'+ev.target['data-id'];
+
+ // $(rowsort).addClass("task-gantt-sorting-item-hover");
+
+ $(rowdata).addClass("task-gantt-timeline-row-hover");
+ // $(rowitem).addClass("task-gantt-item-hover");
+
+ $(z_item).addClass("task-gantt-item-hover");
+
+ var item_info = '#item-info-'+ev.target['data-id'];
+ $(item_info).addClass("item-info-hover");
+
+
+ }
+
+ },
+
+
+ HandleHoverOut: function(ev) {
+
+
+ var item_info = '#item-info-'+ev.target['data-id'];
+ $(item_info).removeClass("item-info-hover");
+
+ // var rowsort = '#task-gantt-item-sorting-'+ev.target['data-id'];
+ var rowdata = '#task-gantt-timeline-row-'+ev.target['data-id'];
+ // var rowitem = '#task-gantt-item-'+ev.target['data-id'];
+
+ var z_item = '.task-gantt-item-'+ev.target['data-id'];
+
+ // $(rowsort).removeClass("task-gantt-sorting-item-hover");
+ $(rowdata).removeClass("task-gantt-timeline-row-hover");
+ // $(rowitem).removeClass("task-gantt-item-hover");
+
+ $(z_item).removeClass("task-gantt-item-hover");
+
+ }
+
+});
+
+return NativeGanttController;
+
+});
diff --git a/odex25_project/web_gantt_native/static/src/js/native_gantt_data.js b/odex25_project/web_gantt_native/static/src/js/native_gantt_data.js
new file mode 100644
index 000000000..3a21eac90
--- /dev/null
+++ b/odex25_project/web_gantt_native/static/src/js/native_gantt_data.js
@@ -0,0 +1,77 @@
+odoo.define('web_gantt_native.NativeGanttData', function (require) {
+ "use strict";
+
+
+
+ function CheckReadOnly(check_fieds, parent_fields, record){
+ // var self = this;
+
+ var readonly_fields = [];
+ _.each(check_fieds, function (field, field_key ) {
+
+ var readonly_status = false;
+ // var check_field = self.parent.fields[field];
+ // var check_state = self.BarRecord["state"];
+
+ var check_field = parent_fields[field];
+ var check_state = record["state"];
+
+ var states = check_field["states"];
+
+ if (check_state && states ){
+
+ var where_state = [];
+
+ _.each(states, function (state, key) {
+
+ var param1 = false;
+ var param2 = false;
+
+ if (state[0].length === 2){
+
+ param1 = state[0][0];
+ param2 = state[0][1];
+ }
+
+ if (param1 === 'readonly'){
+ where_state.push({state : key, param: param2 });
+ }
+
+ if (param2 === true){
+ readonly_status = true
+ }
+ });
+
+ var check_readonly = _.findWhere(where_state,{state: check_state});
+
+ if (readonly_status){
+ if (!check_readonly){
+ readonly_status = false
+ }
+ }
+ else{
+ if (!check_readonly){
+ readonly_status = true
+ }
+ }
+ }
+ else{
+ readonly_status = check_field.readonly
+ }
+
+ readonly_fields.push({field : field, readonly: readonly_status });
+
+ });
+ return readonly_fields;
+
+ }
+
+
+
+ return {
+ CheckReadOnly : CheckReadOnly,
+
+ }
+
+
+});
\ No newline at end of file
diff --git a/odex25_project/web_gantt_native/static/src/js/native_gantt_model.js b/odex25_project/web_gantt_native/static/src/js/native_gantt_model.js
new file mode 100644
index 000000000..ce6cb82c7
--- /dev/null
+++ b/odex25_project/web_gantt_native/static/src/js/native_gantt_model.js
@@ -0,0 +1,762 @@
+odoo.define('web_gantt_native.NativeGanttModel', function (require) {
+"use strict";
+
+var AbstractModel = require('web.AbstractModel');
+var GanttToolField = require('web_gantt_native.ToolField');
+var GanttTimeLineGhost = require('web_gantt_native.Ghost');
+var GanttTimeLineFirst = require('web_gantt_native.BarFirst');
+var framework = require('web.framework');
+var local_storage = require('web.local_storage');
+
+
+return AbstractModel.extend({
+
+ init: function () {
+ this._super.apply(this, arguments);
+ this.gantt = null;
+
+ },
+
+ get: function () {
+ return _.extend({}, this.gantt);
+ },
+
+ load: function (params) {
+ this.modelName = params.modelName;
+ this.fields_view = params.fieldsView;
+ //this.params = params;
+ // this.fieldNames = params.fieldNames;
+ // this.fieldsInfo = params.fieldsInfo;
+ this.gantt = {
+ modelName : params.modelName,
+ group_bys : params.groupedBy,
+ domains : params.domain || [],
+ contexts : params.context || {},
+ fields_view : params.fieldsView,
+ fields : params.fields,
+ pager : [],
+ orderedBy : params.orderedBy
+
+ }
+
+ return this._do_load();
+
+ },
+
+ //---1---//
+ _do_load: function () {
+
+ var domains = this.gantt.domains;
+ var contexts = this.gantt.contexts;
+ var group_bys = this.gantt.group_bys;
+ this.lock_view = local_storage.getItem("lock_view") || 400;
+
+ var self = this;
+
+ self.main_group_id_name = self.fields_view.arch.attrs.main_group_id_name;
+ self.action_menu = self.fields_view.arch.attrs.action_menu;
+
+
+ // self.last_domains = domains;
+ // self.last_contexts = contexts;
+ // self.last_group_bys = group_bys;
+ // self.date_start = null;
+ // self.date_stop = null;
+
+ var n_group_bys = [];
+
+ // select the group by - we can select group by from attribute where XML if not determinate dafault group
+ // for model
+
+ if (this.fields_view.arch.attrs.default_group_by) {
+ n_group_bys = this.fields_view.arch.attrs.default_group_by.split(',');
+ }
+
+ if (group_bys.length) {
+ n_group_bys = group_bys;
+ }
+
+
+
+ var getFields = GanttToolField.getFields(self, n_group_bys);
+ self.model_fields = getFields["model_fields"];
+ self.model_fields_dict = getFields["model_fields_dict"];
+
+ var fields = self.model_fields;
+ // fields.push('display_name');
+
+ // this.fields_view.arch.attrs.default_group_by
+ var export_wizard = false;
+
+ if (self.fields_view.arch.attrs.hasOwnProperty('export_wizard')){
+ export_wizard = self.fields_view.arch.attrs.export_wizard
+ }
+
+
+
+ //Pager
+ var limit_view = 0;
+ if (self.fields_view.arch.attrs.hasOwnProperty('limit_view')){
+ limit_view = parseInt(self.fields_view.arch.attrs.limit_view)
+ }
+
+ if(self.gantt.pager.limit){
+ limit_view = self.gantt.pager.limit
+ }
+
+
+ //Load Level
+ var load_group_id_name = self.fields_view.arch.attrs.load_group_id_name;
+ self.LoadMode = false;
+ if (n_group_bys.length === 1) {
+
+ if (n_group_bys[0] === load_group_id_name || n_group_bys[-1] === load_group_id_name) {
+ self.LoadMode = true;
+ }
+ }
+
+ if (n_group_bys.length > 1 ) {
+
+ if (n_group_bys[n_group_bys.length-1] === load_group_id_name) {
+ self.LoadMode = true;
+ }
+ }
+
+ // Sort allow only if Group by project and domain search by project.
+ // Project get from XML = main_group_id_name = "project_id"
+
+ self.ItemsSorted = false;
+ if (n_group_bys.length === 1){
+
+ if (n_group_bys[0] === self.main_group_id_name){
+ self.ItemsSorted = true;
+ }
+ if (domains.length > 0){
+ if (domains[0][0] !== self.main_group_id_name){
+ self.ItemsSorted = false;
+ }
+ }
+
+ if (domains.length > 1){
+ self.ItemsSorted = false;
+ }
+ }
+
+ if (self.fields_view.arch.attrs.no_group_sort_mode){
+ self.ItemsSorted = false;
+ }
+
+ // Tree View only if group by main_group_id_name
+ self.TreeView = false;
+
+ if (n_group_bys.length === 1) {
+
+ if (n_group_bys[0] === self.main_group_id_name || n_group_bys[-1] === self.main_group_id_name) {
+ self.TreeView = true;
+ }
+ }
+
+ if (n_group_bys.length > 1 ) {
+
+ if (n_group_bys[n_group_bys.length-1] === self.main_group_id_name) {
+ self.TreeView = true;
+ }
+ }
+
+
+
+ self.gantt.data = {
+ ItemsSorted : self.ItemsSorted,
+ ExportWizard : export_wizard,
+ TreeView : self.TreeView,
+ Main_Group_Id_Name : self.main_group_id_name,
+ Action_Menu : self.action_menu,
+ model_fields : fields,
+ model_fields_dict : self.model_fields_dict,
+ model_fields_view : self.fields_view,
+ LoadMode : self.LoadMode,
+
+ };
+
+ return this._rpc({
+ model: this.modelName,
+ method: 'search_read',
+ context: this.gantt.contexts,
+ domain: this.gantt.domains,
+ fields: _.uniq(fields),
+ limit: limit_view,
+ orderBy: this.gantt.orderedBy,
+ })
+ .then(function (data) {
+ self.gantt.pager.limit = limit_view;
+ return self.on_data_loaded_count(data, n_group_bys);
+ });
+
+ },
+
+
+
+
+
+
+
+
+ on_data_loaded_count: function(tasks, group_bys) {
+ var self = this;
+
+ return this._rpc({
+ model: this.modelName,
+ method: 'search_count',
+ args: [this.gantt.domains],
+ context: this.gantt.contexts,
+ })
+ .then(function (result) {
+ self.gantt.pager.records = result;
+
+ if (self.gantt.pager.records > self.gantt.pager.limit){
+ self.gantt.data.ItemsSorted = false
+ }
+
+ return self.on_data_loaded_dummy(tasks, group_bys);
+ });
+
+
+ },
+
+
+
+ on_data_loaded_dummy: function(tasks, group_bys) {
+ var self = this;
+ return self.on_data_loaded_info(tasks, group_bys);
+ },
+
+ //Fist Entry poin load predecessor after. get atributes from XML
+ on_data_loaded_info: function(tasks, group_bys) {
+ var self = this;
+ var ids = _.pluck(tasks, "id");
+
+ var info_model = self.fields_view.arch.attrs.info_model;
+ var info_task_id = "task_id";
+
+ if (info_model) {
+
+ return this._rpc({
+ model: info_model,
+ method: 'search_read',
+ context: this.gantt.contexts,
+ domain: [[info_task_id, 'in', _.uniq(ids)]],
+ fields: _.uniq([info_task_id,"start", "end", "left_up","left_down","right_up","right_down","show"])
+ })
+ .then(function (result) {
+
+ if (result){
+ result = _.map(result, function(info) {
+
+ if (info.task_id){
+ info.task_id = info.task_id[0];
+ return info;
+ }
+ });
+ }
+
+
+
+ self.gantt.data.task_info = result;
+ return self.on_data_loaded_predecessor(tasks, group_bys);
+ });
+ }
+ else{
+ return self.on_data_loaded_predecessor(tasks, group_bys);
+ }
+
+ },
+
+
+
+
+
+ //Fist Entry poin load predecessor after. get atributes from XML
+ on_data_loaded_predecessor: function(tasks, group_bys) {
+ var self = this;
+ var ids = _.pluck(tasks, "id");
+
+ var predecessor_model = self.fields_view.arch.attrs.predecessor_model;
+ var predecessor_task_id = self.fields_view.arch.attrs.predecessor_task_id;
+ var predecessor_parent_task_id = self.fields_view.arch.attrs.predecessor_parent_task_id;
+ var predecessor_type = self.fields_view.arch.attrs.predecessor_type;
+
+ if (predecessor_model) {
+
+ return this._rpc({
+ model: predecessor_model,
+ method: 'search_read',
+ context: this.gantt.contexts,
+ domain: [[predecessor_task_id, 'in', _.uniq(ids)]],
+ fields: _.uniq([predecessor_task_id, predecessor_parent_task_id, predecessor_type])
+ })
+ .then(function (result) {
+ self.gantt.data.predecessor = result;
+ return self.on_data_loaded_ghost(tasks, group_bys);
+ });
+ }
+ else{
+ return self.on_data_loaded_ghost(tasks, group_bys);
+ }
+
+ },
+
+
+ on_data_loaded_ghost: function(tasks, group_bys) {
+ var self = this;
+ var ids = _.pluck(tasks, "id");
+
+ var ghost_date_field = [];
+ var ghost_model = self.fields_view.arch.attrs.ghost_model;
+
+
+ var ghost_id = self.fields_view.arch.attrs.ghost_id;
+ ghost_date_field.push(ghost_id);
+
+ var ghost_name = self.fields_view.arch.attrs.ghost_name;
+ ghost_date_field.push(ghost_name);
+
+ var ghost_date_start = self.fields_view.arch.attrs.ghost_date_start;
+ if (ghost_date_start){
+ ghost_date_field.push(ghost_date_start) ;
+ }
+
+ var ghost_date_end = self.fields_view.arch.attrs.ghost_date_end;
+ if (ghost_date_end){
+ ghost_date_field.push(ghost_date_end) ;
+ }
+
+ var ghost_durations = self.fields_view.arch.attrs.ghost_durations;
+ ghost_date_field.push(ghost_durations);
+
+ if (ghost_model) {
+ return this._rpc({
+ model: ghost_model,
+ method: 'search_read',
+ context: this.gantt.contexts,
+ domain: [[ghost_id, 'in', _.uniq(ids)]],
+ fields: _.uniq(ghost_date_field)
+ })
+ .then(function (result) {
+ self.gantt.data.Ghost = result;
+ self.gantt.data.Ghost_Data = GanttTimeLineGhost.get_data_ghosts(self);
+
+ return self.on_data_loaded_barfirst(tasks, group_bys);
+ });
+
+ }
+ else{
+ return self.on_data_loaded_barfirst(tasks, group_bys);
+ }
+
+ },
+
+
+
+
+
+
+
+ on_data_loaded_barfirst: function(tasks, group_bys) {
+
+ var self = this;
+
+ if (self.ItemsSorted) {
+
+ var barfirst_field = "project_id";
+
+ var barfirst_field_ids = _.pluck(tasks, "project_id");
+
+ var ids = _.pluck(barfirst_field_ids, "0");
+
+ var barfirst_model = "project.project";
+ var barfirst_name = "name";
+ var barfirst_date_start = "date_start";
+ var barfirst_date_end = "date_end";
+
+
+ return this._rpc({
+ model: barfirst_model,
+ method: 'search_read',
+ context: this.gantt.contexts,
+ domain: [['id', 'in', _.uniq(ids)]],
+ fields: _.uniq(['id', barfirst_name, barfirst_date_start, barfirst_date_end])
+ })
+ .then(function (result) {
+ self.gantt.data.BarFirst = result;
+ self.gantt.data.BarFirst_Data = GanttTimeLineFirst.get_data_barfirst(self);
+
+ return self.on_data_loaded_name_get(tasks, group_bys);
+ });
+
+ }
+ else{
+ return self.on_data_loaded_name_get(tasks, group_bys);
+ }
+
+ },
+
+
+ //Get name get from model form name field
+ on_data_loaded_name_get: function(tasks, group_bys) {
+ var self = this;
+ var ids = _.pluck(tasks, "id");
+
+ return this._rpc({
+ model: this.modelName,
+ method: 'name_get',
+ args: [ids],
+ context: this.gantt.contexts,
+ })
+ .then(function (names) {
+ var ntasks = _.map(tasks, function(task) {
+ return _.extend({__name: _.detect(names, function(name) { return name[0] == task.id; })[1]}, task);
+ });
+
+ // return self.gantt_render(ntasks, group_bys);
+ self.gantt.data.ntasks = ntasks;
+ self.gantt.data.group_bys = group_bys;
+ return self.get_second_sort_data(ntasks, group_bys);
+
+ });
+
+
+ },
+
+
+ get_second_sort_data: function(tasks, group_bys) {
+
+ var self = this;
+ self.gantt.data["second_sort"] = undefined;
+ var gantt_attrs = self.fields_view.arch.attrs;
+
+ var link_field = gantt_attrs["second_seq_link_field"];
+
+ if (group_bys.length === 1 && group_bys[0] === link_field) {
+
+ var ids = [];
+ _.map(tasks, function (result) {
+
+ if (result[link_field]) {
+ ids.push(result[link_field][0]);
+ }
+ });
+
+ var s_model = gantt_attrs["second_seq_model"];
+ var s_field = gantt_attrs["second_seq_field"];
+
+ return this._rpc({
+ model: s_model,
+ method: 'search_read',
+ context: this.gantt.contexts,
+ domain: [['id', 'in', _.uniq(ids)]],
+ fields: _.uniq(['id',s_field])
+ })
+ .then(function (result) {
+ self.gantt.data["second_sort"] = result;
+ return self.get_minmax_step(tasks, group_bys);
+ });
+ }
+ else {
+ return self.get_main_group_data(tasks, group_bys);
+ }
+
+
+ },
+
+
+ get_main_group_data: function(tasks, group_bys) {
+
+ var self = this;
+ self.gantt.data["main_group"] = undefined;
+ var gantt_attrs = self.fields_view.arch.attrs;
+
+ var main_id = gantt_attrs["main_group_id_name"];
+ var s_model = gantt_attrs["main_group_model"];
+ var s_field = ["id", "name","fold"];
+
+ if (group_bys.length === 1 && group_bys[0] === main_id && s_model) {
+
+ var ids = [];
+ _.map(tasks, function (result) {
+
+ if (result[main_id]) {
+ ids.push(result[main_id][0]);
+ }
+ });
+
+ return this._rpc({
+ model: s_model,
+ method: 'search_read',
+ context: this.gantt.contexts,
+ domain: [['id', 'in', _.uniq(ids)]],
+ fields: _.uniq(s_field)
+ })
+ .then(function (result) {
+ self.gantt.data["main_group"] = result;
+ return self.get_minmax_step(tasks, group_bys);
+ });
+ }
+ else{
+ return self.get_minmax_step(tasks, group_bys);
+ }
+
+
+
+ },
+
+
+ get_minmax_step: function(tasks, group_bys) {
+ var self = this;
+
+ var parent = {};
+
+ parent.fields = self.gantt.fields;
+
+ parent.model_fields_dict = self.gantt.data.model_fields_dict;
+ parent.gantt_attrs = self.gantt.data.model_fields_view.arch.attrs;
+ parent.second_sort = self.gantt.data.second_sort;
+ parent.main_group = self.gantt.data.main_group;
+
+ var groupRows = GanttToolField.groupRows(tasks, group_bys, parent, self.ItemsSorted);
+
+ self.gantt.data["rows_to_gantt"] = GanttToolField.flatRows(groupRows["projects"], self.ItemsSorted);
+
+ // self.gantt.data["projects"] = groupRows["projects"];
+ //Get Max Min date for data
+ var GtimeStartA = groupRows["timestart"];
+ var GtimeStopA = groupRows["timestop"];
+
+
+ self.gantt.data["GtimeStart"] = Math.min.apply(null, GtimeStartA); // MAX date in date range
+ self.gantt.data["GtimeStop"] = Math.max.apply(null, GtimeStopA); // Min date in date range
+
+ GtimeStopA = [];
+ GtimeStartA = [];
+
+ return self.get_res_task_load(tasks, group_bys);
+
+
+ },
+
+ get_res_task_load: function(tasks, group_bys) {
+ var self = this;
+
+ var gantt_attrs = self.fields_view.arch.attrs;
+
+ var load_model = gantt_attrs["load_bar_model"];
+ var load_id = gantt_attrs["load_id"];
+ var load_id_from = gantt_attrs["load_id_from"];
+ var load_ids_from = gantt_attrs["load_ids_from"];
+
+ var ids = false;
+ if (load_ids_from === "id"){
+
+ ids = _.pluck(tasks, "id");
+
+ }
+ else if(load_ids_from !== "" && load_ids_from !== undefined){
+
+ var gp_load = _.map(tasks , function (group_value) {
+ if (group_value[load_ids_from] !== false && group_value[load_ids_from] !== undefined && group_value[load_ids_from].length > 0 ){
+ return group_value[load_ids_from][0]
+ }
+
+ // if (group_value[load_id] !== false && group_value[load_id].length == 1 ){
+ // return group_value[load_id]
+ // }
+
+ });
+
+ ids = _.compact(gp_load);
+
+ }
+
+
+ if (ids){
+ var _fields = [load_id, load_id_from, 'data_from', 'data_to', 'data_aggr', 'duration'];
+ var _domain = [[load_id_from, 'in', _.uniq(ids)]];
+
+ return this._rpc({
+ model: load_model,
+ method: 'search_read',
+ context: this.gantt.contexts,
+ domain: _domain,
+ fields: _fields
+ })
+ .then(function (result) {
+ self.gantt.data["Task_Load_Data"] = result;
+ return self.get_res_load(tasks, group_bys);
+ });
+
+ }
+ else{
+ return true
+ }
+
+
+ // var ghost_id = self.fields_view.arch.attrs.ghost_id;
+ // var ghost_model = self.fields_view.arch.attrs.ghost_model;
+ // var ghost_name = self.fields_view.arch.attrs.ghost_name;
+ // var ghost_date_start = self.fields_view.arch.attrs.ghost_date_start;
+ // var ghost_date_end = self.fields_view.arch.attrs.ghost_date_end;
+ // var ghost_durations = self.fields_view.arch.attrs.ghost_durations;
+ //
+ // if (ghost_model) {
+ // return this._rpc({
+ // model: ghost_model,
+ // method: 'search_read',
+ // context: this.gantt.contexts,
+ // domain: [[ghost_id, 'in', _.uniq(ids)]],
+ // fields: _.uniq([ghost_id ,ghost_name, ghost_date_start, ghost_date_end, ghost_durations])
+ // })
+ // .then(function (result) {
+ // self.gantt.data.Ghost = result;
+ // self.gantt.data.Ghost_Data = GanttTimeLineGhost.get_data_ghosts(self);
+ //
+ // return self.get_res_load(tasks, group_bys);
+ // });
+ //
+ // }
+ // else{
+ // return self.get_res_load(tasks, group_bys);
+ // }
+
+ },
+
+
+
+ get_res_load: function(tasks, group_bys) {
+
+ var self = this;
+
+
+ if (self.LoadMode) {
+
+ // var _contexts = self.gantt.contexts;
+
+ // var _ctx = {
+ // 'group_by': 'data_aggr',
+ // 'lang': _contexts.lang,
+ // 'tz': _contexts.tz,
+ // 'uid': _contexts.uid
+ // };
+ var gantt_attrs = self.fields_view.arch.attrs;
+ var load_model = gantt_attrs["load_bar_model"];
+ var _ctx = self.gantt.contexts;
+
+ var m_GtimeStart = moment(self.gantt.data["GtimeStart"]).format("YYYY-MM-DD");
+ var m_GtimeStop = moment(self.gantt.data["GtimeStop"]).format("YYYY-MM-DD");
+ // var _domain = [['data_aggr', '>=', m_GtimeStart], ['data_aggr', '<=', m_GtimeStop]];
+
+ var data_load_group = _.where(self.gantt.data["rows_to_gantt"], {is_group: true});
+
+ var gp_load = _.map(data_load_group , function (group_value) {
+ if (group_value.group_id !== false && group_value.group_id.length > 0 ){
+ return group_value.group_id[0]
+ }
+ });
+
+ var gp_domain_ids = _.compact(gp_load);
+ var _domain = [['resource_id', 'in', _.uniq(gp_domain_ids)],['data_aggr', '>=', m_GtimeStart], ['data_aggr', '<=', m_GtimeStop]];
+ // var _fields = ['task_id', 'data_from', 'data_to', 'user_id', 'data_aggr', 'duration', 'resource_id'];
+ var _fields = ['task_id', 'data_from', 'data_to', 'data_aggr', 'duration', 'resource_id'];
+
+ // project.task.detail.plan
+ // project.task.detail.plan.res.link
+ return this._rpc({
+ model: load_model,
+ method: 'search_read',
+ context: _ctx,
+ domain: _domain,
+ fields: _fields
+ })
+
+ .then(function (result) {
+ self.gantt.data["Load_Data"] = result;
+ return true
+ });
+
+ }
+ else{
+ return true
+ }
+
+
+ },
+
+ // var m_GtimeStart = moment(self.GtimeStart).format("YYYY-MM-DD");
+ // var m_GtimeStop = moment(self.GtimeStop).format("YYYY-MM-DD");
+ //
+ // var _contexts = self.state.contexts;
+ //
+ // // var _domain = [['data_aggr', '>=', m_GtimeStartA], ['data_aggr', '<=', m_GtimeStopA], ['iser_id', 'in', _.uniq(ids)]];
+ // // _.uniq([user_id ,ghost_name, ghost_date_start, ghost_date_end, ghost_durations])
+ //
+ // var _domain = [['data_aggr', '>=', m_GtimeStart], ['data_aggr', '<=', m_GtimeStop]];
+ // var _fields = ['task_id', 'data_from', 'data_to', 'durations', 'user_id', 'data_aggr'];
+ //
+ //
+ // if (self.LoadMode) {
+ // this._rpc({
+ //
+ // model: "project.task.detail.plan",
+ // method: 'search_read',
+ // context: _contexts,
+ // domain: _domain,
+ // fields: _fields
+ // })
+ //
+ // .then(function (result) {
+ // self.state.data.Dloads = result;
+ // });
+ //
+ // }
+
+ // var tasks = self.state.data.ntasks;
+ // var group_bys = self.state.data.group_bys;
+ //
+ //
+ // var groupRows = GanttToolField.groupRows(tasks, group_bys, parent);
+
+ // //Get all tasks with group
+ // self.projects = groupRows["projects"];
+ //
+ // //Get Max Min date for data
+ // self.GtimeStopA = self.GtimeStopA.concat(groupRows["timestop"]);
+ // self.GtimeStartA = self.GtimeStartA.concat(groupRows["timestart"]);
+ //
+ // //Calc Min - Max
+ // self.GtimeStart = Math.min.apply(null, self.GtimeStartA); // MAX date in date range
+ // self.GtimeStop = Math.max.apply(null, self.GtimeStopA); // Min date in date range
+ //
+ // //Clean
+ // self.GtimeStartA = [];
+ // self.GtimeStopA = [];
+
+
+
+
+
+
+
+ reload: function (handle, params) {
+ if (params.domain) {
+ this.gantt.domains = params.domain;
+ }
+ if (params.context) {
+ this.gantt.contexts = params.context;
+ }
+ if (params.groupBy) {
+ this.gantt.group_bys = params.groupBy;
+ }
+ return this._do_load();
+ },
+
+});
+
+});
diff --git a/odex25_project/web_gantt_native/static/src/js/native_gantt_renderer.js b/odex25_project/web_gantt_native/static/src/js/native_gantt_renderer.js
new file mode 100644
index 000000000..ee3b7d1a6
--- /dev/null
+++ b/odex25_project/web_gantt_native/static/src/js/native_gantt_renderer.js
@@ -0,0 +1,578 @@
+odoo.define('web_gantt_native.NativeGanttRenderer', function (require) {
+"use strict";
+
+var AbstractRenderer = require('web.AbstractRenderer');
+var core = require('web.core');
+var field_utils = require('web.field_utils');
+var time = require('web.time');
+
+var GanttToolField = require('web_gantt_native.ToolField');
+
+
+var GanttTimeLineHead = require('web_gantt_native.TimeLineHead');
+var GanttTimeLineHeader = require('web_gantt_native.TimeLineHeader');
+var GanttTimeLineScroll = require('web_gantt_native.TimeLineScroll');
+
+var GanttTimeLineData = require('web_gantt_native.TimeLineData');
+
+var GanttTimeLineArrow = require('web_gantt_native.TimeLineArrow');
+
+var GanttTimeLineGhost = require('web_gantt_native.Ghost');
+var GanttTimeLineSummary = require('web_gantt_native.Summary');
+var GanttTimeLineFirst = require('web_gantt_native.BarFirst');
+
+var GanttTimeLineInfo = require('web_gantt_native.Info');
+
+var GanttResourcesLevel = require('web_gantt_native.ResLevel');
+var GanttResourcesBar = require('web_gantt_native.ResBar');
+
+var GanttTimeLineInterSection = require('web_gantt_native.InterSection');
+
+var GanttListOptionsItem = require('web_gantt_native.ItemOptions');
+var GanttTimeLineDocs = require('web_gantt_native.Docs');
+
+
+
+var GanttListAction = require('web_gantt_native.ItemAction');
+var GanttItemzTree = require('web_gantt_native.ItemzTree');
+var GanttListInfo = require('web_gantt_native.ItemInfo');
+
+
+
+var session = require('web.session');
+var local_storage = require('web.local_storage');
+
+
+var _t = core._t;
+var _lt = core._lt;
+
+var QWeb = core.qweb;
+
+return AbstractRenderer.extend({
+ className: "o_native_gantt_view",
+ display_name: _lt('Gantt APS'),
+
+
+ /**
+ * @overrie
+ */
+
+ init: function () {
+ this._super.apply(this, arguments);
+
+ var self = this;
+
+ this.chart_id = _.uniqueId();
+ this.gantt_events = [];
+
+ this.type = this.arch.attrs.type || 'native_gantt';
+
+ this.firstDayDate = undefined;
+ this.lastDayDate = undefined;
+
+ this.GtimeStartA = [];
+ this.GtimeStopA = [];
+
+ this.GtimeStart = undefined;
+ this.GtimeStop = undefined;
+
+
+ this.widgets = [];
+
+ this.session = session;
+
+ this.counter = 0;
+ this.widgets = [];
+ this.options = "all";
+ this.fast_update = false;
+
+ this.local_storage = local_storage
+
+ this.gutterOffset = local_storage.getItem("gantt_offset") || 400;
+ this.itemsOffset = local_storage.getItem("items_offset") || 300;
+
+
+ this.gutterOffsetX = 2;
+ this.timeline_width = undefined;
+ this.timeScale = undefined;
+
+ this.timeTypeActive = undefined;
+
+ this.timeType = undefined;
+ this.gantt_timeline_head_widget = undefined;
+ this.gantt_timeline_data_widget = [];
+ this.pxScaleUTC = undefined;
+ this.firstDayScale = undefined;
+ this.rows_to_gantt = undefined;
+ this.timeScaleUTC = undefined;
+
+ this.firstDayDate = undefined;
+ this.lastDayDate = undefined;
+
+
+ this.GtimeStartA = [];
+ this.GtimeStopA = [];
+
+ this.GtimeStart = undefined;
+ this.GtimeStop = undefined;
+
+
+
+ this.BarMovieValue = undefined;
+ this.BarClickDiffX = undefined;
+ this.BarClickX = undefined;
+
+ this.BarRecord= undefined;
+
+ this.BarClickDown = false;
+
+ this.BarWidth = undefined;
+
+ this.TimeToLeft = false;
+
+ this.ItemsSorted = false;
+
+ this.hint_move_widget = undefined;
+ this.tip_move_widget = undefined;
+
+ //week
+ this.header_hint_widget = undefined;
+ this.week_type = local_storage.getItem("gantt_week_type") || "isoweek";
+
+ this.hover_id = undefined;
+
+ this.ScrollToTop = undefined;
+
+
+ this.Predecessor = undefined;
+
+ this.Ghost = undefined;
+ this.Ghost_Data = undefined;
+
+ this.BarFirst = undefined;
+ this.BarFirst_Data = undefined;
+
+
+ this.main_group_id_name = undefined;
+
+ //ui
+ this.list_show = parseInt(local_storage.getItem("gantt_list_show")) || 0;
+ this.industry_show = parseInt(local_storage.getItem("gantt_industry_show")) || 0;
+
+
+ //format date
+ let l10n = _t.database.parameters;
+ this.formatDateTime = time.strftime_to_moment_format( l10n.date_format + ' ' + l10n.time_format);
+ this.formatDate = time.strftime_to_moment_format( l10n.date_format);
+
+
+ },
+ /**
+ * @override
+ */
+ destroy: function () {
+ while (this.gantt_events.length) {
+ gantt.detachEvent(this.gantt_events.pop());
+ }
+ this._super();
+ },
+
+ //--------------------------------------------------------------------------
+ // Private
+ //--------------------------------------------------------------------------
+
+
+ _render: function () {
+
+ this._renderGantt();
+ return this._super.apply(this, arguments);
+ // return $.when();
+ },
+
+ _renderGantt: function () {
+ var self = this;
+
+ // var parent = {};
+
+ self.Predecessor = self.state.data.predecessor;
+ self.Task_Info = self.state.data.task_info;
+
+ self.Ghost = self.state.data.Ghost ;
+ self.Ghost_Data = self.state.data.Ghost_Data ;
+
+ self.BarFirst = self.state.data.BarFirst;
+ self.BarFirst_Data = self.state.data.BarFirst_Data;
+
+ self.ExportWizard = self.state.data.ExportWizard;
+ self.Main_Group_Id_Name = self.state.data.Main_Group_Id_Name;
+ self.Action_Menu = self.state.data.Action_Menu;
+
+ self.fields_view = self.state.fields_view;
+ self.ItemsSorted = self.state.data.ItemsSorted;
+ self.fields = self.state.fields;
+ self.model_fields_dict = self.state.data.model_fields_dict;
+ self.TreeView = self.state.data.TreeView;
+
+ self.LoadMode = self.state.data.LoadMode;
+ self.Load_Data = self.state.data.Load_Data;
+
+ self.Task_Load_Data = self.state.data.Task_Load_Data;
+
+ self.GtimeStart = self.state.data.GtimeStart;
+ self.GtimeStop = self.state.data.GtimeStop;
+
+
+ //set time scale type if is undefined
+ if ( self.timeType === undefined ) {
+ self.timeType = 'month_day';
+ }
+
+
+ //Gantt Conteriner Render.
+ self.$el.html(QWeb.render('GanttContainerView.main', {
+ 'title': "My Table",
+ 'widget': self,
+ 'display_name': self.display_name,
+ 'gutterOffset' : self.local_storage.getItem("gantt_offset") || self.gutterOffset
+
+ }));
+
+ //Sorted and grouped to flat list
+ self.rows_to_gantt = self.state.data.rows_to_gantt;
+
+
+ // Start - End month
+ self.firstDayDate = moment(self.GtimeStart).clone().startOf('month'); //Start month
+ self.lastDayDate = moment(self.GtimeStop).clone().endOf('month'); //End month
+ self.timeScaleUTC = self.lastDayDate.valueOf() - self.firstDayDate.valueOf(); // raznica vremeni
+ self.firstDayScale = self.firstDayDate.valueOf();
+
+
+ },
+
+ AddItemList: function (){
+ var self = this;
+
+ var options = { items_sorted: this.ItemsSorted,
+ export_wizard: this.ExportWizard,
+ main_group_id_name: this.Main_Group_Id_Name,
+ tree_view : this.TreeView,
+ action_menu: this.Action_Menu,
+
+ };
+
+ this.widget_ztree = new GanttItemzTree(this, this.rows_to_gantt, options);
+ this.widget_ztree.appendTo(this.$('.task-gantt-items'));
+ },
+
+
+ AddItemsData: function (){
+ var self = this;
+
+
+ //Item Action
+ if (self.widget_item_action){
+ this.widget_item_action.destroy();
+ self.widget_item_action = [];
+ }
+
+ var options = {
+ items_sorted: self.ItemsSorted,
+ export_wizard: self.ExportWizard,
+ main_group_id_name: self.Main_Group_Id_Name,
+ tree_view: self.TreeView,
+ action_menu: self.Action_Menu,
+ };
+
+ self.widget_item_action = new GanttListAction(self, options);
+ self.widget_item_action.appendTo(self.$('.task-gantt-action'));
+
+
+ //Item Info
+ if (self.widget_item_info){
+ this.widget_item_info.destroy();
+ self.widget_item_info = [];
+ }
+
+ self.widget_item_info = new GanttListInfo(self, options);
+ self.widget_item_info.appendTo(self.$('.task-gantt-info'));
+
+
+ },
+
+
+ AddTimeLineArrow: function( timeline_width ) {
+
+ var self = this;
+ if (self.gantt_timeline_arrow_widget){
+ this.gantt_timeline_arrow_widget.destroy();
+ self.gantt_timeline_arrow_widget = [];
+ }
+
+ this.gantt_timeline_arrow_widget = new GanttTimeLineArrow(self, timeline_width );
+ this.gantt_timeline_arrow_widget.appendTo(self.$('.task-gantt-timeline-inner'));
+
+ },
+
+
+ AddTimeLineHead: async function (timeScale, time_type, time_month, time_day) {
+
+ var self = this;
+
+ // GanttTimeLineHead
+ if (this.gantt_timeline_head_widget) {
+ this.gantt_timeline_head_widget.destroy();
+ this.gantt_timeline_head_widget = [];
+ }
+ this.gantt_timeline_head_widget = await new GanttTimeLineHead(self, timeScale, time_type, time_month, time_day);
+ this.gantt_timeline_head_widget.appendTo(self.$('.task-gantt-timeline-inner'));
+
+
+ // GanttTimeLineHeader
+ if (this.gantt_timeline_header_widget) {
+ this.gantt_timeline_header_widget.destroy();
+ this.gantt_timeline_header_widget = [];
+ }
+
+ this.gantt_timeline_header_widget = await new GanttTimeLineHeader(self, timeScale, time_type, time_month, time_day, "TimelineGantt.header", "");
+ this.gantt_timeline_header_widget.appendTo(self.$('.timeline-gantt'));
+
+
+ // // GanttTimeLineHeader layout
+ // if (this.gantt_timeline_header_layout_widget) {
+ // this.gantt_timeline_header_layout_widget.destroy();
+ // this.gantt_timeline_header_layout_widget = [];
+ // }
+ //
+ // this.gantt_timeline_header_layout_widget = await new GanttTimeLineHeader(self, timeScale, time_type, time_month, time_day, "TimelineGanttLayout.header", "-layout");
+ // this.gantt_timeline_header_layout_widget.appendTo(self.$('.timeline-gantt-layout'));
+
+
+ // GanttListOptionsItem
+ if (this.gantt_item_options_widget) {
+ this.gantt_item_options_widget.destroy();
+ this.gantt_item_options_widget = [];
+ }
+ this.gantt_item_options_widget = await new GanttListOptionsItem.OptionsItem(self);
+ this.gantt_item_options_widget.appendTo(self.$('.timeline-gantt-options'));
+
+
+ // GanttTimeLineScroll
+ if (this.gantt_timeline_scroll_widget) {
+ this.gantt_timeline_scroll_widget.destroy();
+ this.gantt_timeline_scroll_widget = [];
+ }
+ this.gantt_timeline_scroll_widget = new GanttTimeLineScroll(self, timeScale, time_type, time_month, time_day);
+ this.gantt_timeline_scroll_widget.appendTo(self.$('.timeline-gantt-scroll'));
+
+
+ },
+
+
+ AddTimeLineData: function(timeScale, time_type, rows_to_gantt ) {
+
+ var self = this;
+ if (this.gantt_timeline_data_widget.length > 0){
+ this.gantt_timeline_data_widget = [];
+ }
+
+ var $zTree = self.widget_ztree.$zTree;
+ var options = { items_sorted: self.ItemsSorted, tree_view : self.TreeView};
+ var nodes = $zTree.getNodes();
+
+ _.each(nodes, function (node) {
+ var childNodes = $zTree.transformToArray(node);
+
+ _.each(childNodes, function (child) {
+ var gantt_time_line_data = new GanttTimeLineData(self, timeScale, time_type, child, options);
+ gantt_time_line_data.appendTo(self.$('.task-gantt-timeline-data'));
+ self.gantt_timeline_data_widget.push(gantt_time_line_data);
+
+ })
+ });
+
+ },
+
+
+ AddTimeLineGhost: async function () {
+
+ //Ghost
+ var self = this;
+ if (self.gantt_timeline_ghost_widget) {
+ this.gantt_timeline_ghost_widget.destroy();
+ self.gantt_timeline_ghost_widget = [];
+ }
+
+ this.gantt_timeline_ghost_widget = await new GanttTimeLineGhost.GhostWidget(self);
+
+ this.gantt_timeline_ghost_widget.appendTo(self.$('.task-gantt-timeline-data'));
+
+
+ //Info
+ if (self.gantt_timeline_info_widget) {
+ this.gantt_timeline_info_widget.destroy();
+ self.gantt_timeline_info_widget = [];
+ }
+
+ this.gantt_timeline_info_widget = new GanttTimeLineInfo.InfoWidget(self);
+ this.gantt_timeline_info_widget.appendTo(self.$('.task-gantt-bar-plan'));
+
+ //Resources Level
+ if (self.gantt_timeline_res_level_widget) {
+ this.gantt_timeline_res_level_widget.destroy();
+ self.gantt_timeline_res_level_widget = [];
+ }
+ this.gantt_timeline_res_level_widget = new GanttResourcesLevel.ResLevelWidget(self);
+ this.gantt_timeline_res_level_widget.appendTo(self.$('.task-gantt-timeline-data'));
+
+
+ //Detail Task
+ if (self.gantt_timeline_res_bar_widget) {
+ this.gantt_timeline_res_bar_widget.destroy();
+ self.gantt_timeline_res_bar_widget = [];
+ }
+ this.gantt_timeline_res_bar_widget = new GanttResourcesBar.ResBarWidget(self);
+ this.gantt_timeline_res_bar_widget.appendTo(self.$('.task-gantt-timeline-data'));
+
+
+ //InterSection
+ if (self.gantt_timeline_inter_section_widget) {
+ this.gantt_timeline_inter_section_widget.destroy();
+ self.gantt_timeline_inter_section_widget = [];
+ }
+ this.gantt_timeline_inter_section_widget = new GanttTimeLineInterSection.InterSectionWidget(self);
+ this.gantt_timeline_inter_section_widget.appendTo(self.$('.task-gantt-timeline-data'));
+
+
+ //Docs
+ if (self.gantt_timeline_docs_widget) {
+ this.gantt_timeline_docs_widget.destroy();
+ self.gantt_timeline_docs_widget = [];
+ }
+ this.gantt_timeline_docs_widget = new GanttTimeLineDocs.DocsWidget(self);
+ this.gantt_timeline_docs_widget.appendTo(self.$('.task-gantt-timeline-data'));
+
+
+ },
+
+ AddTimeLineSummary: function() {
+
+ var self = this;
+ if (self.gantt_timeline_summary_widget){
+ self.gantt_timeline_summary_widget.destroy();
+ self.gantt_timeline_summary_widget = [];
+ }
+
+ self.gantt_timeline_summary_widget = new GanttTimeLineSummary.SummaryWidget(self);
+ self.gantt_timeline_summary_widget.appendTo(self.$('.task-gantt-timeline-data'));
+
+ },
+
+ AddTimeLineFirst: function() {
+
+ var self = this;
+ if (self.gantt_timeline_first_widget){
+ this.gantt_timeline_first_widget.destroy();
+ self.gantt_timeline_first_widget = [];
+ }
+
+ this.gantt_timeline_first_widget = new GanttTimeLineFirst.BarFirstWidget(self);
+ this.gantt_timeline_first_widget.appendTo(self.$('.task-gantt-timeline-data'));
+
+ },
+
+
+ DivResize: function () {
+ var self = this;
+
+ var items = self.$(".task-gantt-items")
+ items.width(self.local_storage.getItem("items_offset") || self.itemsOffset);
+ items.resizable({
+ handles: "e",
+ resize: function (event, ui) {
+ self.local_storage.setItem("items_offset", self.$(".task-gantt-items").width());
+ },
+ start: async function (event, ui) {
+ self.$('.task-gantt-items-gutter').addClass("task-gantt-items-gutter-hover")
+ },
+
+ stop: function (event, ui) {
+ self.$('.task-gantt-items-gutter').removeClass("task-gantt-items-gutter-hover")
+ }
+
+ });
+
+ self.$('.task-gantt-list').resizable({
+ handles: "e",
+ resize: function (event, ui) {
+ let pxc = self.$('.task-gantt-list').width();
+ self.$('.timeline-gantt-items').width(pxc);
+ self.local_storage.setItem("gantt_offset", pxc);
+ },
+
+ start: async function (event, ui) {
+
+ self.$('.timeline-gantt-gutter').addClass("task-gantt-gutter-hover")
+ self.$('.task-gantt-gutter').addClass("task-gantt-gutter-hover")
+ },
+
+ stop: function (event, ui) {
+ self.$('.timeline-gantt-gutter').removeClass("task-gantt-gutter-hover")
+ self.$('.task-gantt-gutter').removeClass("task-gantt-gutter-hover")
+
+ }
+
+
+ });
+
+ },
+
+ ModeSelect: function(mode){
+ let result = undefined
+ if (mode === "day_1hour"){
+ result = "1h"
+ } else if (mode === "day_2hour") {
+ result = "2h"
+ } else if (mode === "day_4hour") {
+ result = "4h"
+ } else if (mode === "day_8hour") {
+ result = "8h"
+ } else if (mode === "month_day") {
+ result = "days"
+ } else if (mode === "year_month") {
+ result = "month"
+ } else if (mode === "month_week") {
+ result = "weeks"
+ } else if (mode === "quarter") {
+ result = "quarter"
+ }
+ return result
+
+ },
+
+ ModeActive: function () {
+ let self = this;
+ let timeTypeActive = self.ModeSelect(self.timeTypeActive)
+ let mode = self.ModeSelect(self.timeType)
+
+ self.timeTypeActive = self.timeType
+
+ if (timeTypeActive !== mode && self.__parentedParent.hasOwnProperty('$buttons')){
+
+ let old_element = self.__parentedParent.$buttons.find(".task-gantt-zoom-"+timeTypeActive)
+
+ old_element.removeClass("btn-info");
+ old_element.addClass("btn-default");
+
+ let element = self.__parentedParent.$buttons.find(".task-gantt-zoom-"+mode)
+ element.removeClass("btn-default");
+ element.addClass("btn-info");
+
+ }
+
+ }
+
+
+});
+
+});
diff --git a/odex25_project/web_gantt_native/static/src/js/native_gantt_view.js b/odex25_project/web_gantt_native/static/src/js/native_gantt_view.js
new file mode 100644
index 000000000..761d6de6d
--- /dev/null
+++ b/odex25_project/web_gantt_native/static/src/js/native_gantt_view.js
@@ -0,0 +1,63 @@
+odoo.define('web_gantt_native.NativeGanttView', function (require) {
+"use strict";
+
+var AbstractView = require('web.AbstractView');
+var core = require('web.core');
+
+var NativeGanttModel = require('web_gantt_native.NativeGanttModel');
+var NativeGanttRenderer = require('web_gantt_native.NativeGanttRenderer');
+var NativeGanttController = require('web_gantt_native.NativeGanttController');
+
+var view_registry = require('web.view_registry');
+
+var _lt = core._lt;
+
+var GanttContainer = AbstractView.extend({
+
+ display_name: _lt('Native Gantt'),
+ icon: 'fa-tasks',
+ viewType: 'ganttaps',
+
+ config: _.extend({}, AbstractView.prototype.config, {
+ Model: NativeGanttModel,
+ Controller: NativeGanttController,
+ Renderer: NativeGanttRenderer,
+ }),
+ // searchMenuTypes: ['filter', 'groupBy', 'timeRange', 'favorite'],
+
+
+ init: function (viewInfo, params) {
+
+ this._super.apply(this, arguments);
+
+
+ this.rendererParams.viewType = this.viewType;
+
+ this.controllerParams.confirmOnDelete = true;
+ this.controllerParams.archiveEnabled = 'active' in this.fields;
+ this.controllerParams.hasButtons = 'action_buttons' in params ? params.action_buttons : true;
+
+ this.loadParams.fieldsInfo = this.fieldsInfo;
+ this.loadParams.fields = viewInfo.fields;
+ this.loadParams.context = params.context || {};
+ this.loadParams.limit = parseInt(this.arch.attrs.limit, 10) || params.limit;
+ this.loadParams.viewType = this.viewType;
+ this.loadParams.parentID = params.parentID;
+ this.recordID = params.recordID;
+
+ this.model = params.model;
+
+ this.loadParams.fieldsView = viewInfo;
+ this.loadParams.fieldsView.arch = this.arch;
+ this.loadParams.mapping = this.arch.attrs;
+
+
+
+ },
+});
+
+view_registry.add('ganttaps', GanttContainer);
+
+return GanttContainer;
+
+});
diff --git a/odex25_project/web_gantt_native/static/src/lib/jquery.ztree.core.js b/odex25_project/web_gantt_native/static/src/lib/jquery.ztree.core.js
new file mode 100644
index 000000000..d409f5e6a
--- /dev/null
+++ b/odex25_project/web_gantt_native/static/src/lib/jquery.ztree.core.js
@@ -0,0 +1,2006 @@
+/*
+ * JQuery zTree core
+ * v3.5.43
+ * http://treejs.cn/
+ *
+ * Copyright (c) 2010 Hunter.z
+ *
+ * Licensed same as jquery - MIT License
+ * http://www.opensource.org/licenses/mit-license.php
+ *
+ * Date: 2020-04-04
+ */
+
+(function ($) {
+ var settings = {}, roots = {}, caches = {},
+ //default consts of core
+ _consts = {
+ className: {
+ BUTTON: "button",
+ LEVEL: "level",
+ ICO_LOADING: "ico_loading",
+ SWITCH: "switch",
+ NAME: 'node_name'
+ },
+ event: {
+ NODECREATED: "ztree_nodeCreated",
+ CLICK: "ztree_click",
+ EXPAND: "ztree_expand",
+ COLLAPSE: "ztree_collapse",
+ ASYNC_SUCCESS: "ztree_async_success",
+ ASYNC_ERROR: "ztree_async_error",
+ REMOVE: "ztree_remove",
+ SELECTED: "ztree_selected",
+ UNSELECTED: "ztree_unselected"
+ },
+ id: {
+ A: "_a",
+ ICON: "_ico",
+ SPAN: "_span",
+ SWITCH: "_switch",
+ UL: "_ul"
+ },
+ line: {
+ ROOT: "root",
+ ROOTS: "roots",
+ CENTER: "center",
+ BOTTOM: "bottom",
+ NOLINE: "noline",
+ LINE: "line"
+ },
+ folder: {
+ OPEN: "open",
+ CLOSE: "close",
+ DOCU: "docu"
+ },
+ node: {
+ CURSELECTED: "curSelectedNode"
+ }
+ },
+ //default setting of core
+ _setting = {
+ treeId: "",
+ treeObj: null,
+ view: {
+ addDiyDom: null,
+ autoCancelSelected: true,
+ dblClickExpand: true,
+ expandSpeed: "fast",
+ fontCss: {},
+ nodeClasses: {},
+ nameIsHTML: false,
+ selectedMulti: true,
+ showIcon: true,
+ showLine: true,
+ showTitle: true,
+ txtSelectedEnable: false
+ },
+ data: {
+ key: {
+ isParent: "isParent",
+ children: "children",
+ name: "name",
+ title: "",
+ url: "url",
+ icon: "icon"
+ },
+ simpleData: {
+ enable: false,
+ idKey: "id",
+ pIdKey: "pId",
+ rootPId: null
+ },
+ keep: {
+ parent: false,
+ leaf: false
+ }
+ },
+ async: {
+ enable: false,
+ contentType: "application/x-www-form-urlencoded",
+ type: "post",
+ dataType: "text",
+ headers: {},
+ xhrFields: {},
+ url: "",
+ autoParam: [],
+ otherParam: [],
+ dataFilter: null
+ },
+ callback: {
+ beforeAsync: null,
+ beforeClick: null,
+ beforeDblClick: null,
+ beforeRightClick: null,
+ beforeMouseDown: null,
+ beforeMouseUp: null,
+ beforeExpand: null,
+ beforeCollapse: null,
+ beforeRemove: null,
+
+ onAsyncError: null,
+ onAsyncSuccess: null,
+ onNodeCreated: null,
+ onClick: null,
+ onDblClick: null,
+ onRightClick: null,
+ onMouseDown: null,
+ onMouseUp: null,
+ onExpand: null,
+ onCollapse: null,
+ onRemove: null
+ }
+ },
+ //default root of core
+ //zTree use root to save full data
+ _initRoot = function (setting) {
+ var r = data.getRoot(setting);
+ if (!r) {
+ r = {};
+ data.setRoot(setting, r);
+ }
+ data.nodeChildren(setting, r, []);
+ r.expandTriggerFlag = false;
+ r.curSelectedList = [];
+ r.noSelection = true;
+ r.createdNodes = [];
+ r.zId = 0;
+ r._ver = (new Date()).getTime();
+ },
+ //default cache of core
+ _initCache = function (setting) {
+ var c = data.getCache(setting);
+ if (!c) {
+ c = {};
+ data.setCache(setting, c);
+ }
+ c.nodes = [];
+ c.doms = [];
+ },
+ //default bindEvent of core
+ _bindEvent = function (setting) {
+ var o = setting.treeObj,
+ c = consts.event;
+ o.bind(c.NODECREATED, function (event, treeId, node) {
+ tools.apply(setting.callback.onNodeCreated, [event, treeId, node]);
+ });
+
+ o.bind(c.CLICK, function (event, srcEvent, treeId, node, clickFlag) {
+ tools.apply(setting.callback.onClick, [srcEvent, treeId, node, clickFlag]);
+ });
+
+ o.bind(c.EXPAND, function (event, treeId, node) {
+ tools.apply(setting.callback.onExpand, [event, treeId, node]);
+ });
+
+ o.bind(c.COLLAPSE, function (event, treeId, node) {
+ tools.apply(setting.callback.onCollapse, [event, treeId, node]);
+ });
+
+ o.bind(c.ASYNC_SUCCESS, function (event, treeId, node, msg) {
+ tools.apply(setting.callback.onAsyncSuccess, [event, treeId, node, msg]);
+ });
+
+ o.bind(c.ASYNC_ERROR, function (event, treeId, node, XMLHttpRequest, textStatus, errorThrown) {
+ tools.apply(setting.callback.onAsyncError, [event, treeId, node, XMLHttpRequest, textStatus, errorThrown]);
+ });
+
+ o.bind(c.REMOVE, function (event, treeId, treeNode) {
+ tools.apply(setting.callback.onRemove, [event, treeId, treeNode]);
+ });
+
+ o.bind(c.SELECTED, function (event, treeId, node) {
+ tools.apply(setting.callback.onSelected, [treeId, node]);
+ });
+ o.bind(c.UNSELECTED, function (event, treeId, node) {
+ tools.apply(setting.callback.onUnSelected, [treeId, node]);
+ });
+ },
+ _unbindEvent = function (setting) {
+ var o = setting.treeObj,
+ c = consts.event;
+ o.unbind(c.NODECREATED)
+ .unbind(c.CLICK)
+ .unbind(c.EXPAND)
+ .unbind(c.COLLAPSE)
+ .unbind(c.ASYNC_SUCCESS)
+ .unbind(c.ASYNC_ERROR)
+ .unbind(c.REMOVE)
+ .unbind(c.SELECTED)
+ .unbind(c.UNSELECTED);
+ },
+ //default event proxy of core
+ _eventProxy = function (event) {
+ var target = event.target,
+ setting = data.getSetting(event.data.treeId),
+ tId = "", node = null,
+ nodeEventType = "", treeEventType = "",
+ nodeEventCallback = null, treeEventCallback = null,
+ tmp = null;
+
+ if (tools.eqs(event.type, "mousedown")) {
+ treeEventType = "mousedown";
+ } else if (tools.eqs(event.type, "mouseup")) {
+ treeEventType = "mouseup";
+ } else if (tools.eqs(event.type, "contextmenu")) {
+ treeEventType = "contextmenu";
+ } else if (tools.eqs(event.type, "click")) {
+ if (tools.eqs(target.tagName, "span") && target.getAttribute("treeNode" + consts.id.SWITCH) !== null) {
+ tId = tools.getNodeMainDom(target).id;
+ nodeEventType = "switchNode";
+ } else {
+ tmp = tools.getMDom(setting, target, [{tagName: "a", attrName: "treeNode" + consts.id.A}]);
+ if (tmp) {
+ tId = tools.getNodeMainDom(tmp).id;
+ nodeEventType = "clickNode";
+ }
+ }
+ } else if (tools.eqs(event.type, "dblclick")) {
+ treeEventType = "dblclick";
+ tmp = tools.getMDom(setting, target, [{tagName: "a", attrName: "treeNode" + consts.id.A}]);
+ if (tmp) {
+ tId = tools.getNodeMainDom(tmp).id;
+ nodeEventType = "switchNode";
+ }
+ }
+ if (treeEventType.length > 0 && tId.length == 0) {
+ tmp = tools.getMDom(setting, target, [{tagName: "a", attrName: "treeNode" + consts.id.A}]);
+ if (tmp) {
+ tId = tools.getNodeMainDom(tmp).id;
+ }
+ }
+ // event to node
+ if (tId.length > 0) {
+ node = data.getNodeCache(setting, tId);
+ switch (nodeEventType) {
+ case "switchNode" :
+ var isParent = data.nodeIsParent(setting, node);
+ if (!isParent) {
+ nodeEventType = "";
+ } else if (tools.eqs(event.type, "click")
+ || (tools.eqs(event.type, "dblclick") && tools.apply(setting.view.dblClickExpand, [setting.treeId, node], setting.view.dblClickExpand))) {
+ nodeEventCallback = handler.onSwitchNode;
+ } else {
+ nodeEventType = "";
+ }
+ break;
+ case "clickNode" :
+ nodeEventCallback = handler.onClickNode;
+ break;
+ }
+ }
+ // event to zTree
+ switch (treeEventType) {
+ case "mousedown" :
+ treeEventCallback = handler.onZTreeMousedown;
+ break;
+ case "mouseup" :
+ treeEventCallback = handler.onZTreeMouseup;
+ break;
+ case "dblclick" :
+ treeEventCallback = handler.onZTreeDblclick;
+ break;
+ case "contextmenu" :
+ treeEventCallback = handler.onZTreeContextmenu;
+ break;
+ }
+ var proxyResult = {
+ stop: false,
+ node: node,
+ nodeEventType: nodeEventType,
+ nodeEventCallback: nodeEventCallback,
+ treeEventType: treeEventType,
+ treeEventCallback: treeEventCallback
+ };
+ return proxyResult
+ },
+ //default init node of core
+ _initNode = function (setting, level, n, parentNode, isFirstNode, isLastNode, openFlag) {
+ if (!n) return;
+ var r = data.getRoot(setting),
+ children = data.nodeChildren(setting, n);
+ n.level = level;
+ n.tId = setting.treeId + "_" + (++r.zId);
+ n.parentTId = parentNode ? parentNode.tId : null;
+ n.open = (typeof n.open == "string") ? tools.eqs(n.open, "true") : !!n.open;
+ var isParent = data.nodeIsParent(setting, n);
+ if (tools.isArray(children)) {
+ data.nodeIsParent(setting, n, true);
+ n.zAsync = true;
+ } else {
+ isParent = data.nodeIsParent(setting, n, isParent);
+ n.open = (isParent && !setting.async.enable) ? n.open : false;
+ n.zAsync = !isParent;
+ }
+ n.isFirstNode = isFirstNode;
+ n.isLastNode = isLastNode;
+ n.getParentNode = function () {
+ return data.getNodeCache(setting, n.parentTId);
+ };
+ n.getPreNode = function () {
+ return data.getPreNode(setting, n);
+ };
+ n.getNextNode = function () {
+ return data.getNextNode(setting, n);
+ };
+ n.getIndex = function () {
+ return data.getNodeIndex(setting, n);
+ };
+ n.getPath = function () {
+ return data.getNodePath(setting, n);
+ };
+ n.isAjaxing = false;
+ data.fixPIdKeyValue(setting, n);
+ },
+ _init = {
+ bind: [_bindEvent],
+ unbind: [_unbindEvent],
+ caches: [_initCache],
+ nodes: [_initNode],
+ proxys: [_eventProxy],
+ roots: [_initRoot],
+ beforeA: [],
+ afterA: [],
+ innerBeforeA: [],
+ innerAfterA: [],
+ zTreeTools: []
+ },
+ //method of operate data
+ data = {
+ addNodeCache: function (setting, node) {
+ data.getCache(setting).nodes[data.getNodeCacheId(node.tId)] = node;
+ },
+ getNodeCacheId: function (tId) {
+ return tId.substring(tId.lastIndexOf("_") + 1);
+ },
+ addAfterA: function (afterA) {
+ _init.afterA.push(afterA);
+ },
+ addBeforeA: function (beforeA) {
+ _init.beforeA.push(beforeA);
+ },
+ addInnerAfterA: function (innerAfterA) {
+ _init.innerAfterA.push(innerAfterA);
+ },
+ addInnerBeforeA: function (innerBeforeA) {
+ _init.innerBeforeA.push(innerBeforeA);
+ },
+ addInitBind: function (bindEvent) {
+ _init.bind.push(bindEvent);
+ },
+ addInitUnBind: function (unbindEvent) {
+ _init.unbind.push(unbindEvent);
+ },
+ addInitCache: function (initCache) {
+ _init.caches.push(initCache);
+ },
+ addInitNode: function (initNode) {
+ _init.nodes.push(initNode);
+ },
+ addInitProxy: function (initProxy, isFirst) {
+ if (!!isFirst) {
+ _init.proxys.splice(0, 0, initProxy);
+ } else {
+ _init.proxys.push(initProxy);
+ }
+ },
+ addInitRoot: function (initRoot) {
+ _init.roots.push(initRoot);
+ },
+ addNodesData: function (setting, parentNode, index, nodes) {
+ var children = data.nodeChildren(setting, parentNode), params;
+ if (!children) {
+ children = data.nodeChildren(setting, parentNode, []);
+ index = -1;
+ } else if (index >= children.length) {
+ index = -1;
+ }
+
+ if (children.length > 0 && index === 0) {
+ children[0].isFirstNode = false;
+ view.setNodeLineIcos(setting, children[0]);
+ } else if (children.length > 0 && index < 0) {
+ children[children.length - 1].isLastNode = false;
+ view.setNodeLineIcos(setting, children[children.length - 1]);
+ }
+ data.nodeIsParent(setting, parentNode, true);
+
+ if (index < 0) {
+ data.nodeChildren(setting, parentNode, children.concat(nodes));
+ } else {
+ params = [index, 0].concat(nodes);
+ children.splice.apply(children, params);
+ }
+ },
+ addSelectedNode: function (setting, node) {
+ var root = data.getRoot(setting);
+ if (!data.isSelectedNode(setting, node)) {
+ root.curSelectedList.push(node);
+ }
+ },
+ addCreatedNode: function (setting, node) {
+ if (!!setting.callback.onNodeCreated || !!setting.view.addDiyDom) {
+ var root = data.getRoot(setting);
+ root.createdNodes.push(node);
+ }
+ },
+ addZTreeTools: function (zTreeTools) {
+ _init.zTreeTools.push(zTreeTools);
+ },
+ exSetting: function (s) {
+ $.extend(true, _setting, s);
+ },
+ fixPIdKeyValue: function (setting, node) {
+ if (setting.data.simpleData.enable) {
+ node[setting.data.simpleData.pIdKey] = node.parentTId ? node.getParentNode()[setting.data.simpleData.idKey] : setting.data.simpleData.rootPId;
+ }
+ },
+ getAfterA: function (setting, node, array) {
+ for (var i = 0, j = _init.afterA.length; i < j; i++) {
+ _init.afterA[i].apply(this, arguments);
+ }
+ },
+ getBeforeA: function (setting, node, array) {
+ for (var i = 0, j = _init.beforeA.length; i < j; i++) {
+ _init.beforeA[i].apply(this, arguments);
+ }
+ },
+ getInnerAfterA: function (setting, node, array) {
+ for (var i = 0, j = _init.innerAfterA.length; i < j; i++) {
+ _init.innerAfterA[i].apply(this, arguments);
+ }
+ },
+ getInnerBeforeA: function (setting, node, array) {
+ for (var i = 0, j = _init.innerBeforeA.length; i < j; i++) {
+ _init.innerBeforeA[i].apply(this, arguments);
+ }
+ },
+ getCache: function (setting) {
+ return caches[setting.treeId];
+ },
+ getNodeIndex: function (setting, node) {
+ if (!node) return null;
+ var p = node.parentTId ? node.getParentNode() : data.getRoot(setting),
+ children = data.nodeChildren(setting, p);
+ for (var i = 0, l = children.length - 1; i <= l; i++) {
+ if (children[i] === node) {
+ return i;
+ }
+ }
+ return -1;
+ },
+ getNextNode: function (setting, node) {
+ if (!node) return null;
+ var p = node.parentTId ? node.getParentNode() : data.getRoot(setting),
+ children = data.nodeChildren(setting, p);
+ for (var i = 0, l = children.length - 1; i <= l; i++) {
+ if (children[i] === node) {
+ return (i == l ? null : children[i + 1]);
+ }
+ }
+ return null;
+ },
+ getNodeByParam: function (setting, nodes, key, value) {
+ if (!nodes || !key) return null;
+ for (var i = 0, l = nodes.length; i < l; i++) {
+ var node = nodes[i];
+ if (node[key] == value) {
+ return nodes[i];
+ }
+ var children = data.nodeChildren(setting, node);
+ var tmp = data.getNodeByParam(setting, children, key, value);
+ if (tmp) return tmp;
+ }
+ return null;
+ },
+ getNodeCache: function (setting, tId) {
+ if (!tId) return null;
+ var n = caches[setting.treeId].nodes[data.getNodeCacheId(tId)];
+ return n ? n : null;
+ },
+ getNodePath: function (setting, node) {
+ if (!node) return null;
+
+ var path;
+ if (node.parentTId) {
+ path = node.getParentNode().getPath();
+ } else {
+ path = [];
+ }
+
+ if (path) {
+ path.push(node);
+ }
+
+ return path;
+ },
+ getNodes: function (setting) {
+ return data.nodeChildren(setting, data.getRoot(setting));
+ },
+ getNodesByParam: function (setting, nodes, key, value) {
+ if (!nodes || !key) return [];
+ var result = [];
+ for (var i = 0, l = nodes.length; i < l; i++) {
+ var node = nodes[i];
+ if (node[key] == value) {
+ result.push(node);
+ }
+ var children = data.nodeChildren(setting, node);
+ result = result.concat(data.getNodesByParam(setting, children, key, value));
+ }
+ return result;
+ },
+ getNodesByParamFuzzy: function (setting, nodes, key, value) {
+ if (!nodes || !key) return [];
+ var result = [];
+ value = value.toLowerCase();
+ for (var i = 0, l = nodes.length; i < l; i++) {
+ var node = nodes[i];
+ if (typeof node[key] == "string" && nodes[i][key].toLowerCase().indexOf(value) > -1) {
+ result.push(node);
+ }
+ var children = data.nodeChildren(setting, node);
+ result = result.concat(data.getNodesByParamFuzzy(setting, children, key, value));
+ }
+ return result;
+ },
+ getNodesByFilter: function (setting, nodes, filter, isSingle, invokeParam) {
+ if (!nodes) return (isSingle ? null : []);
+ var result = isSingle ? null : [];
+ for (var i = 0, l = nodes.length; i < l; i++) {
+ var node = nodes[i];
+ if (tools.apply(filter, [node, invokeParam], false)) {
+ if (isSingle) {
+ return node;
+ }
+ result.push(node);
+ }
+ var children = data.nodeChildren(setting, node);
+ var tmpResult = data.getNodesByFilter(setting, children, filter, isSingle, invokeParam);
+ if (isSingle && !!tmpResult) {
+ return tmpResult;
+ }
+ result = isSingle ? tmpResult : result.concat(tmpResult);
+ }
+ return result;
+ },
+ getPreNode: function (setting, node) {
+ if (!node) return null;
+ var p = node.parentTId ? node.getParentNode() : data.getRoot(setting),
+ children = data.nodeChildren(setting, p);
+ for (var i = 0, l = children.length; i < l; i++) {
+ if (children[i] === node) {
+ return (i == 0 ? null : children[i - 1]);
+ }
+ }
+ return null;
+ },
+ getRoot: function (setting) {
+ return setting ? roots[setting.treeId] : null;
+ },
+ getRoots: function () {
+ return roots;
+ },
+ getSetting: function (treeId) {
+ return settings[treeId];
+ },
+ getSettings: function () {
+ return settings;
+ },
+ getZTreeTools: function (treeId) {
+ var r = this.getRoot(this.getSetting(treeId));
+ return r ? r.treeTools : null;
+ },
+ initCache: function (setting) {
+ for (var i = 0, j = _init.caches.length; i < j; i++) {
+ _init.caches[i].apply(this, arguments);
+ }
+ },
+ initNode: function (setting, level, node, parentNode, preNode, nextNode) {
+ for (var i = 0, j = _init.nodes.length; i < j; i++) {
+ _init.nodes[i].apply(this, arguments);
+ }
+ },
+ initRoot: function (setting) {
+ for (var i = 0, j = _init.roots.length; i < j; i++) {
+ _init.roots[i].apply(this, arguments);
+ }
+ },
+ isSelectedNode: function (setting, node) {
+ var root = data.getRoot(setting);
+ for (var i = 0, j = root.curSelectedList.length; i < j; i++) {
+ if (node === root.curSelectedList[i]) return true;
+ }
+ return false;
+ },
+ nodeChildren: function (setting, node, newChildren) {
+ if (!node) {
+ return null;
+ }
+ var key = setting.data.key.children;
+ if (typeof newChildren !== 'undefined') {
+ node[key] = newChildren;
+ }
+ return node[key];
+ },
+ nodeIsParent: function (setting, node, newIsParent) {
+ if (!node) {
+ return false;
+ }
+ var key = setting.data.key.isParent;
+ if (typeof newIsParent !== 'undefined') {
+ if (typeof newIsParent === "string") {
+ newIsParent = tools.eqs(newIsParent, "true");
+ }
+ newIsParent = !!newIsParent;
+ node[key] = newIsParent;
+ } else if (typeof node[key] == "string"){
+ node[key] = tools.eqs(node[key], "true");
+ } else {
+ node[key] = !!node[key];
+ }
+ return node[key];
+ },
+ nodeName: function (setting, node, newName) {
+ var key = setting.data.key.name;
+ if (typeof newName !== 'undefined') {
+ node[key] = newName;
+ }
+ return "" + node[key];
+ },
+ nodeTitle: function (setting, node) {
+ var t = setting.data.key.title === "" ? setting.data.key.name : setting.data.key.title;
+ return "" + node[t];
+ },
+ removeNodeCache: function (setting, node) {
+ var children = data.nodeChildren(setting, node);
+ if (children) {
+ for (var i = 0, l = children.length; i < l; i++) {
+ data.removeNodeCache(setting, children[i]);
+ }
+ }
+ data.getCache(setting).nodes[data.getNodeCacheId(node.tId)] = null;
+ },
+ removeSelectedNode: function (setting, node) {
+ var root = data.getRoot(setting);
+ for (var i = 0, j = root.curSelectedList.length; i < j; i++) {
+ if (node === root.curSelectedList[i] || !data.getNodeCache(setting, root.curSelectedList[i].tId)) {
+ root.curSelectedList.splice(i, 1);
+ setting.treeObj.trigger(consts.event.UNSELECTED, [setting.treeId, node]);
+ i--;
+ j--;
+ }
+ }
+ },
+ setCache: function (setting, cache) {
+ caches[setting.treeId] = cache;
+ },
+ setRoot: function (setting, root) {
+ roots[setting.treeId] = root;
+ },
+ setZTreeTools: function (setting, zTreeTools) {
+ for (var i = 0, j = _init.zTreeTools.length; i < j; i++) {
+ _init.zTreeTools[i].apply(this, arguments);
+ }
+ },
+ transformToArrayFormat: function (setting, nodes) {
+ if (!nodes) return [];
+ var r = [];
+ if (tools.isArray(nodes)) {
+ for (var i = 0, l = nodes.length; i < l; i++) {
+ var node = nodes[i];
+ _do(node);
+ }
+ } else {
+ _do(nodes);
+ }
+ return r;
+
+ function _do(_node) {
+ r.push(_node);
+ var children = data.nodeChildren(setting, _node);
+ if (children) {
+ r = r.concat(data.transformToArrayFormat(setting, children));
+ }
+ }
+ },
+ transformTozTreeFormat: function (setting, sNodes) {
+ var i, l,
+ key = setting.data.simpleData.idKey,
+ parentKey = setting.data.simpleData.pIdKey;
+ if (!key || key == "" || !sNodes) return [];
+
+ if (tools.isArray(sNodes)) {
+ var r = [];
+ var tmpMap = {};
+ for (i = 0, l = sNodes.length; i < l; i++) {
+ tmpMap[sNodes[i][key]] = sNodes[i];
+ }
+ for (i = 0, l = sNodes.length; i < l; i++) {
+ var p = tmpMap[sNodes[i][parentKey]];
+ if (p && sNodes[i][key] != sNodes[i][parentKey]) {
+ var children = data.nodeChildren(setting, p);
+ if (!children) {
+ children = data.nodeChildren(setting, p, []);
+ }
+ children.push(sNodes[i]);
+ } else {
+ r.push(sNodes[i]);
+ }
+ }
+ return r;
+ } else {
+ return [sNodes];
+ }
+ }
+ },
+ //method of event proxy
+ event = {
+ bindEvent: function (setting) {
+ for (var i = 0, j = _init.bind.length; i < j; i++) {
+ _init.bind[i].apply(this, arguments);
+ }
+ },
+ unbindEvent: function (setting) {
+ for (var i = 0, j = _init.unbind.length; i < j; i++) {
+ _init.unbind[i].apply(this, arguments);
+ }
+ },
+ bindTree: function (setting) {
+ var eventParam = {
+ treeId: setting.treeId
+ },
+ o = setting.treeObj;
+ if (!setting.view.txtSelectedEnable) {
+ // for can't select text
+ o.bind('selectstart', handler.onSelectStart).css({
+ "-moz-user-select": "-moz-none"
+ });
+ }
+ o.bind('click', eventParam, event.proxy);
+ o.bind('dblclick', eventParam, event.proxy);
+ o.bind('mouseover', eventParam, event.proxy);
+ o.bind('mouseout', eventParam, event.proxy);
+ o.bind('mousedown', eventParam, event.proxy);
+ o.bind('mouseup', eventParam, event.proxy);
+ o.bind('contextmenu', eventParam, event.proxy);
+ },
+ unbindTree: function (setting) {
+ var o = setting.treeObj;
+ o.unbind('selectstart', handler.onSelectStart)
+ .unbind('click', event.proxy)
+ .unbind('dblclick', event.proxy)
+ .unbind('mouseover', event.proxy)
+ .unbind('mouseout', event.proxy)
+ .unbind('mousedown', event.proxy)
+ .unbind('mouseup', event.proxy)
+ .unbind('contextmenu', event.proxy);
+ },
+ doProxy: function (e) {
+ var results = [];
+ for (var i = 0, j = _init.proxys.length; i < j; i++) {
+ var proxyResult = _init.proxys[i].apply(this, arguments);
+ results.push(proxyResult);
+ if (proxyResult.stop) {
+ break;
+ }
+ }
+ return results;
+ },
+ proxy: function (e) {
+ var setting = data.getSetting(e.data.treeId);
+ if (!tools.uCanDo(setting, e)) return true;
+ var results = event.doProxy(e),
+ r = true, x = false;
+ for (var i = 0, l = results.length; i < l; i++) {
+ var proxyResult = results[i];
+ if (proxyResult.nodeEventCallback) {
+ x = true;
+ r = proxyResult.nodeEventCallback.apply(proxyResult, [e, proxyResult.node]) && r;
+ }
+ if (proxyResult.treeEventCallback) {
+ x = true;
+ r = proxyResult.treeEventCallback.apply(proxyResult, [e, proxyResult.node]) && r;
+ }
+ }
+ return r;
+ }
+ },
+ //method of event handler
+ handler = {
+ onSwitchNode: function (event, node) {
+ var setting = data.getSetting(event.data.treeId);
+ if (node.open) {
+ if (tools.apply(setting.callback.beforeCollapse, [setting.treeId, node], true) == false) return true;
+ data.getRoot(setting).expandTriggerFlag = true;
+ view.switchNode(setting, node);
+ } else {
+ if (tools.apply(setting.callback.beforeExpand, [setting.treeId, node], true) == false) return true;
+ data.getRoot(setting).expandTriggerFlag = true;
+ view.switchNode(setting, node);
+ }
+ return true;
+ },
+ onClickNode: function (event, node) {
+ var setting = data.getSetting(event.data.treeId),
+ clickFlag = ((setting.view.autoCancelSelected && (event.ctrlKey || event.metaKey)) && data.isSelectedNode(setting, node)) ? 0 : (setting.view.autoCancelSelected && (event.ctrlKey || event.metaKey) && setting.view.selectedMulti) ? 2 : 1;
+ if (tools.apply(setting.callback.beforeClick, [setting.treeId, node, clickFlag], true) == false) return true;
+ if (clickFlag === 0) {
+ view.cancelPreSelectedNode(setting, node);
+ } else {
+ view.selectNode(setting, node, clickFlag === 2);
+ }
+ setting.treeObj.trigger(consts.event.CLICK, [event, setting.treeId, node, clickFlag]);
+ return true;
+ },
+ onZTreeMousedown: function (event, node) {
+ var setting = data.getSetting(event.data.treeId);
+ if (tools.apply(setting.callback.beforeMouseDown, [setting.treeId, node], true)) {
+ tools.apply(setting.callback.onMouseDown, [event, setting.treeId, node]);
+ }
+ return true;
+ },
+ onZTreeMouseup: function (event, node) {
+ var setting = data.getSetting(event.data.treeId);
+ if (tools.apply(setting.callback.beforeMouseUp, [setting.treeId, node], true)) {
+ tools.apply(setting.callback.onMouseUp, [event, setting.treeId, node]);
+ }
+ return true;
+ },
+ onZTreeDblclick: function (event, node) {
+ var setting = data.getSetting(event.data.treeId);
+ if (tools.apply(setting.callback.beforeDblClick, [setting.treeId, node], true)) {
+ tools.apply(setting.callback.onDblClick, [event, setting.treeId, node]);
+ }
+ return true;
+ },
+ onZTreeContextmenu: function (event, node) {
+ var setting = data.getSetting(event.data.treeId);
+ if (tools.apply(setting.callback.beforeRightClick, [setting.treeId, node], true)) {
+ tools.apply(setting.callback.onRightClick, [event, setting.treeId, node]);
+ }
+ return (typeof setting.callback.onRightClick) != "function";
+ },
+ onSelectStart: function (e) {
+ var n = e.originalEvent.srcElement.nodeName.toLowerCase();
+ return (n === "input" || n === "textarea");
+ }
+ },
+ //method of tools for zTree
+ tools = {
+ apply: function (fun, param, defaultValue) {
+ if ((typeof fun) == "function") {
+ return fun.apply(zt, param ? param : []);
+ }
+ return defaultValue;
+ },
+ canAsync: function (setting, node) {
+ var children = data.nodeChildren(setting, node);
+ var isParent = data.nodeIsParent(setting, node);
+ return (setting.async.enable && node && isParent && !(node.zAsync || (children && children.length > 0)));
+ },
+ clone: function (obj) {
+ if (obj === null) return null;
+ var o = tools.isArray(obj) ? [] : {};
+ for (var i in obj) {
+ o[i] = (obj[i] instanceof Date) ? new Date(obj[i].getTime()) : (typeof obj[i] === "object" ? tools.clone(obj[i]) : obj[i]);
+ }
+ return o;
+ },
+ eqs: function (str1, str2) {
+ return str1.toLowerCase() === str2.toLowerCase();
+ },
+ isArray: function (arr) {
+ return Object.prototype.toString.apply(arr) === "[object Array]";
+ },
+ isElement: function (o) {
+ return (
+ typeof HTMLElement === "object" ? o instanceof HTMLElement : //DOM2
+ o && typeof o === "object" && o !== null && o.nodeType === 1 && typeof o.nodeName === "string"
+ );
+ },
+ $: function (node, exp, setting) {
+ if (!!exp && typeof exp != "string") {
+ setting = exp;
+ exp = "";
+ }
+ if (typeof node == "string") {
+ return $(node, setting ? setting.treeObj.get(0).ownerDocument : null);
+ } else {
+ return $("#" + node.tId + exp, setting ? setting.treeObj : null);
+ }
+ },
+ getMDom: function (setting, curDom, targetExpr) {
+ if (!curDom) return null;
+ while (curDom && curDom.id !== setting.treeId) {
+ for (var i = 0, l = targetExpr.length; curDom.tagName && i < l; i++) {
+ if (tools.eqs(curDom.tagName, targetExpr[i].tagName) && curDom.getAttribute(targetExpr[i].attrName) !== null) {
+ return curDom;
+ }
+ }
+ curDom = curDom.parentNode;
+ }
+ return null;
+ },
+ getNodeMainDom: function (target) {
+ return ($(target).parent("li").get(0) || $(target).parentsUntil("li").parent().get(0));
+ },
+ isChildOrSelf: function (dom, parentId) {
+ return ($(dom).closest("#" + parentId).length > 0);
+ },
+ uCanDo: function (setting, e) {
+ return true;
+ }
+ },
+ //method of operate ztree dom
+ view = {
+ addNodes: function (setting, parentNode, index, newNodes, isSilent) {
+ var isParent = data.nodeIsParent(setting, parentNode);
+ if (setting.data.keep.leaf && parentNode && !isParent) {
+ return;
+ }
+ if (!tools.isArray(newNodes)) {
+ newNodes = [newNodes];
+ }
+ if (setting.data.simpleData.enable) {
+ newNodes = data.transformTozTreeFormat(setting, newNodes);
+ }
+ if (parentNode) {
+ var target_switchObj = $$(parentNode, consts.id.SWITCH, setting),
+ target_icoObj = $$(parentNode, consts.id.ICON, setting),
+ target_ulObj = $$(parentNode, consts.id.UL, setting);
+
+ if (!parentNode.open) {
+ view.replaceSwitchClass(parentNode, target_switchObj, consts.folder.CLOSE);
+ view.replaceIcoClass(parentNode, target_icoObj, consts.folder.CLOSE);
+ parentNode.open = false;
+ target_ulObj.css({
+ "display": "none"
+ });
+ }
+
+ data.addNodesData(setting, parentNode, index, newNodes);
+ view.createNodes(setting, parentNode.level + 1, newNodes, parentNode, index);
+ if (!isSilent) {
+ view.expandCollapseParentNode(setting, parentNode, true);
+ }
+ } else {
+ data.addNodesData(setting, data.getRoot(setting), index, newNodes);
+ view.createNodes(setting, 0, newNodes, null, index);
+ }
+ },
+ appendNodes: function (setting, level, nodes, parentNode, index, initFlag, openFlag) {
+ if (!nodes) return [];
+ var html = [];
+
+ var tmpPNode = (parentNode) ? parentNode : data.getRoot(setting),
+ tmpPChild = data.nodeChildren(setting, tmpPNode),
+ isFirstNode, isLastNode;
+
+ if (!tmpPChild || index >= tmpPChild.length - nodes.length) {
+ index = -1;
+ }
+
+ for (var i = 0, l = nodes.length; i < l; i++) {
+ var node = nodes[i];
+ if (initFlag) {
+ isFirstNode = ((index === 0 || tmpPChild.length == nodes.length) && (i == 0));
+ isLastNode = (index < 0 && i == (nodes.length - 1));
+ data.initNode(setting, level, node, parentNode, isFirstNode, isLastNode, openFlag);
+ data.addNodeCache(setting, node);
+ }
+ var isParent = data.nodeIsParent(setting, node);
+
+ var childHtml = [];
+ var children = data.nodeChildren(setting, node);
+ if (children && children.length > 0) {
+ //make child html first, because checkType
+ childHtml = view.appendNodes(setting, level + 1, children, node, -1, initFlag, openFlag && node.open);
+ }
+ if (openFlag) {
+ view.makeDOMNodeMainBefore(html, setting, node);
+ view.makeDOMNodeLine(html, setting, node);
+ data.getBeforeA(setting, node, html);
+ view.makeDOMNodeNameBefore(html, setting, node);
+ data.getInnerBeforeA(setting, node, html);
+ view.makeDOMNodeIcon(html, setting, node);
+ data.getInnerAfterA(setting, node, html);
+ view.makeDOMNodeNameAfter(html, setting, node);
+ data.getAfterA(setting, node, html);
+ if (isParent && node.open) {
+ view.makeUlHtml(setting, node, html, childHtml.join(''));
+ }
+ view.makeDOMNodeMainAfter(html, setting, node);
+ data.addCreatedNode(setting, node);
+ }
+ }
+ return html;
+ },
+ appendParentULDom: function (setting, node) {
+ var html = [],
+ nObj = $$(node, setting);
+ if (!nObj.get(0) && !!node.parentTId) {
+ view.appendParentULDom(setting, node.getParentNode());
+ nObj = $$(node, setting);
+ }
+ var ulObj = $$(node, consts.id.UL, setting);
+ if (ulObj.get(0)) {
+ ulObj.remove();
+ }
+ var children = data.nodeChildren(setting, node),
+ childHtml = view.appendNodes(setting, node.level + 1, children, node, -1, false, true);
+ view.makeUlHtml(setting, node, html, childHtml.join(''));
+ nObj.append(html.join(''));
+ },
+ asyncNode: function (setting, node, isSilent, callback) {
+ var i, l;
+ var isParent = data.nodeIsParent(setting, node);
+ if (node && !isParent) {
+ tools.apply(callback);
+ return false;
+ } else if (node && node.isAjaxing) {
+ return false;
+ } else if (tools.apply(setting.callback.beforeAsync, [setting.treeId, node], true) == false) {
+ tools.apply(callback);
+ return false;
+ }
+ if (node) {
+ node.isAjaxing = true;
+ var icoObj = $$(node, consts.id.ICON, setting);
+ icoObj.attr({"style": "", "class": consts.className.BUTTON + " " + consts.className.ICO_LOADING});
+ }
+
+ var tmpParam = {};
+ var autoParam = tools.apply(setting.async.autoParam, [setting.treeId, node], setting.async.autoParam);
+ for (i = 0, l = autoParam.length; node && i < l; i++) {
+ var pKey = autoParam[i].split("="), spKey = pKey;
+ if (pKey.length > 1) {
+ spKey = pKey[1];
+ pKey = pKey[0];
+ }
+ tmpParam[spKey] = node[pKey];
+ }
+ var otherParam = tools.apply(setting.async.otherParam, [setting.treeId, node], setting.async.otherParam);
+ if (tools.isArray(otherParam)) {
+ for (i = 0, l = otherParam.length; i < l; i += 2) {
+ tmpParam[otherParam[i]] = otherParam[i + 1];
+ }
+ } else {
+ for (var p in otherParam) {
+ tmpParam[p] = otherParam[p];
+ }
+ }
+
+ var _tmpV = data.getRoot(setting)._ver;
+ $.ajax({
+ contentType: setting.async.contentType,
+ cache: false,
+ type: setting.async.type,
+ url: tools.apply(setting.async.url, [setting.treeId, node], setting.async.url),
+ data: setting.async.contentType.indexOf('application/json') > -1 ? JSON.stringify(tmpParam) : tmpParam,
+ dataType: setting.async.dataType,
+ headers: setting.async.headers,
+ xhrFields: setting.async.xhrFields,
+ success: function (msg) {
+ if (_tmpV != data.getRoot(setting)._ver) {
+ return;
+ }
+ var newNodes = [];
+ try {
+ if (!msg || msg.length == 0) {
+ newNodes = [];
+ } else if (typeof msg == "string") {
+ newNodes = eval("(" + msg + ")");
+ } else {
+ newNodes = msg;
+ }
+ } catch (err) {
+ newNodes = msg;
+ }
+
+ if (node) {
+ node.isAjaxing = null;
+ node.zAsync = true;
+ }
+ view.setNodeLineIcos(setting, node);
+ if (newNodes && newNodes !== "") {
+ newNodes = tools.apply(setting.async.dataFilter, [setting.treeId, node, newNodes], newNodes);
+ view.addNodes(setting, node, -1, !!newNodes ? tools.clone(newNodes) : [], !!isSilent);
+ } else {
+ view.addNodes(setting, node, -1, [], !!isSilent);
+ }
+ setting.treeObj.trigger(consts.event.ASYNC_SUCCESS, [setting.treeId, node, msg]);
+ tools.apply(callback);
+ },
+ error: function (XMLHttpRequest, textStatus, errorThrown) {
+ if (_tmpV != data.getRoot(setting)._ver) {
+ return;
+ }
+ if (node) node.isAjaxing = null;
+ view.setNodeLineIcos(setting, node);
+ setting.treeObj.trigger(consts.event.ASYNC_ERROR, [setting.treeId, node, XMLHttpRequest, textStatus, errorThrown]);
+ }
+ });
+ return true;
+ },
+ cancelPreSelectedNode: function (setting, node, excludeNode) {
+ var list = data.getRoot(setting).curSelectedList,
+ i, n;
+ for (i = list.length - 1; i >= 0; i--) {
+ n = list[i];
+ if (node === n || (!node && (!excludeNode || excludeNode !== n))) {
+ $$(n, consts.id.A, setting).removeClass(consts.node.CURSELECTED);
+ if (node) {
+ data.removeSelectedNode(setting, node);
+ break;
+ } else {
+ list.splice(i, 1);
+ setting.treeObj.trigger(consts.event.UNSELECTED, [setting.treeId, n]);
+ }
+ }
+ }
+ },
+ createNodeCallback: function (setting) {
+ if (!!setting.callback.onNodeCreated || !!setting.view.addDiyDom) {
+ var root = data.getRoot(setting);
+ while (root.createdNodes.length > 0) {
+ var node = root.createdNodes.shift();
+ tools.apply(setting.view.addDiyDom, [setting.treeId, node]);
+ if (!!setting.callback.onNodeCreated) {
+ setting.treeObj.trigger(consts.event.NODECREATED, [setting.treeId, node]);
+ }
+ }
+ }
+ },
+ createNodes: function (setting, level, nodes, parentNode, index) {
+ if (!nodes || nodes.length == 0) return;
+ var root = data.getRoot(setting),
+ openFlag = !parentNode || parentNode.open || !!$$(data.nodeChildren(setting, parentNode)[0], setting).get(0);
+ root.createdNodes = [];
+ var zTreeHtml = view.appendNodes(setting, level, nodes, parentNode, index, true, openFlag),
+ parentObj, nextObj;
+
+ if (!parentNode) {
+ parentObj = setting.treeObj;
+ //setting.treeObj.append(zTreeHtml.join(''));
+ } else {
+ var ulObj = $$(parentNode, consts.id.UL, setting);
+ if (ulObj.get(0)) {
+ parentObj = ulObj;
+ //ulObj.append(zTreeHtml.join(''));
+ }
+ }
+ if (parentObj) {
+ if (index >= 0) {
+ nextObj = parentObj.children()[index];
+ }
+ if (index >= 0 && nextObj) {
+ $(nextObj).before(zTreeHtml.join(''));
+ } else {
+ parentObj.append(zTreeHtml.join(''));
+ }
+ }
+
+ view.createNodeCallback(setting);
+ },
+ destroy: function (setting) {
+ if (!setting) return;
+ data.initCache(setting);
+ data.initRoot(setting);
+ event.unbindTree(setting);
+ event.unbindEvent(setting);
+ setting.treeObj.empty();
+ delete settings[setting.treeId];
+ },
+ expandCollapseNode: function (setting, node, expandFlag, animateFlag, callback) {
+ var root = data.getRoot(setting);
+ var tmpCb, _callback;
+ if (!node) {
+ tools.apply(callback, []);
+ return;
+ }
+ var children = data.nodeChildren(setting, node);
+ var isParent = data.nodeIsParent(setting, node);
+ if (root.expandTriggerFlag) {
+ _callback = callback;
+ tmpCb = function () {
+ if (_callback) _callback();
+ if (node.open) {
+ setting.treeObj.trigger(consts.event.EXPAND, [setting.treeId, node]);
+ } else {
+ setting.treeObj.trigger(consts.event.COLLAPSE, [setting.treeId, node]);
+ }
+ };
+ callback = tmpCb;
+ root.expandTriggerFlag = false;
+ }
+ if (!node.open && isParent && ((!$$(node, consts.id.UL, setting).get(0)) || (children && children.length > 0 && !$$(children[0], setting).get(0)))) {
+ view.appendParentULDom(setting, node);
+ view.createNodeCallback(setting);
+ }
+ if (node.open == expandFlag) {
+ tools.apply(callback, []);
+ return;
+ }
+ var ulObj = $$(node, consts.id.UL, setting),
+ switchObj = $$(node, consts.id.SWITCH, setting),
+ icoObj = $$(node, consts.id.ICON, setting);
+
+ if (isParent) {
+ node.open = !node.open;
+ if (node.iconOpen && node.iconClose) {
+ icoObj.attr("style", view.makeNodeIcoStyle(setting, node));
+ }
+
+ if (node.open) {
+ view.replaceSwitchClass(node, switchObj, consts.folder.OPEN);
+ view.replaceIcoClass(node, icoObj, consts.folder.OPEN);
+ if (animateFlag == false || setting.view.expandSpeed == "") {
+ ulObj.show();
+ tools.apply(callback, []);
+ } else {
+ if (children && children.length > 0) {
+ ulObj.slideDown(setting.view.expandSpeed, callback);
+ } else {
+ ulObj.show();
+ tools.apply(callback, []);
+ }
+ }
+ } else {
+ view.replaceSwitchClass(node, switchObj, consts.folder.CLOSE);
+ view.replaceIcoClass(node, icoObj, consts.folder.CLOSE);
+ if (animateFlag == false || setting.view.expandSpeed == "" || !(children && children.length > 0)) {
+ ulObj.hide();
+ tools.apply(callback, []);
+ } else {
+ ulObj.slideUp(setting.view.expandSpeed, callback);
+ }
+ }
+ } else {
+ tools.apply(callback, []);
+ }
+ },
+ expandCollapseParentNode: function (setting, node, expandFlag, animateFlag, callback) {
+ if (!node) return;
+ if (!node.parentTId) {
+ view.expandCollapseNode(setting, node, expandFlag, animateFlag, callback);
+ return;
+ } else {
+ view.expandCollapseNode(setting, node, expandFlag, animateFlag);
+ }
+ if (node.parentTId) {
+ view.expandCollapseParentNode(setting, node.getParentNode(), expandFlag, animateFlag, callback);
+ }
+ },
+ expandCollapseSonNode: function (setting, node, expandFlag, animateFlag, callback) {
+ var root = data.getRoot(setting),
+ treeNodes = (node) ? data.nodeChildren(setting, node) : data.nodeChildren(setting, root),
+ selfAnimateSign = (node) ? false : animateFlag,
+ expandTriggerFlag = data.getRoot(setting).expandTriggerFlag;
+ data.getRoot(setting).expandTriggerFlag = false;
+ if (treeNodes) {
+ for (var i = 0, l = treeNodes.length; i < l; i++) {
+ if (treeNodes[i]) view.expandCollapseSonNode(setting, treeNodes[i], expandFlag, selfAnimateSign);
+ }
+ }
+ data.getRoot(setting).expandTriggerFlag = expandTriggerFlag;
+ view.expandCollapseNode(setting, node, expandFlag, animateFlag, callback);
+ },
+ isSelectedNode: function (setting, node) {
+ if (!node) {
+ return false;
+ }
+ var list = data.getRoot(setting).curSelectedList,
+ i;
+ for (i = list.length - 1; i >= 0; i--) {
+ if (node === list[i]) {
+ return true;
+ }
+ }
+ return false;
+ },
+ makeDOMNodeIcon: function (html, setting, node) {
+ var nameStr = data.nodeName(setting, node),
+ name = setting.view.nameIsHTML ? nameStr : nameStr.replace(/&/g, '&').replace(//g, '>');
+ html.push("
", name, " ");
+ },
+ makeDOMNodeLine: function (html, setting, node) {
+ html.push("
");
+ },
+ makeDOMNodeMainAfter: function (html, setting, node) {
+ html.push("");
+ },
+ makeDOMNodeMainBefore: function (html, setting, node) {
+ html.push("
");
+ },
+ makeDOMNodeNameAfter: function (html, setting, node) {
+ html.push("");
+ },
+ makeDOMNodeNameBefore: function (html, setting, node) {
+ var title = data.nodeTitle(setting, node),
+ url = view.makeNodeUrl(setting, node),
+ fontcss = view.makeNodeFontCss(setting, node),
+ nodeClasses = view.makeNodeClasses(setting, node),
+ fontStyle = [];
+ for (var f in fontcss) {
+ fontStyle.push(f, ":", fontcss[f], ";");
+ }
+ html.push(" 0) ? "href='" + url + "'" : ""), " target='", view.makeNodeTarget(node), "' style='", fontStyle.join(''),
+ "'");
+ if (tools.apply(setting.view.showTitle, [setting.treeId, node], setting.view.showTitle) && title) {
+ html.push("title='", title.replace(/'/g, "'").replace(//g, '>'), "'");
+ }
+ html.push(">");
+ },
+ makeNodeFontCss: function (setting, node) {
+ var fontCss = tools.apply(setting.view.fontCss, [setting.treeId, node], setting.view.fontCss);
+ return (fontCss && ((typeof fontCss) != "function")) ? fontCss : {};
+ },
+ makeNodeClasses: function (setting, node) {
+ var classes = tools.apply(setting.view.nodeClasses, [setting.treeId, node], setting.view.nodeClasses);
+ return (classes && (typeof classes !== "function")) ? classes : {add:[], remove:[]};
+ },
+ makeNodeIcoClass: function (setting, node) {
+ var icoCss = ["ico"];
+ if (!node.isAjaxing) {
+ var isParent = data.nodeIsParent(setting, node);
+ icoCss[0] = (node.iconSkin ? node.iconSkin + "_" : "") + icoCss[0];
+ if (isParent) {
+ icoCss.push(node.open ? consts.folder.OPEN : consts.folder.CLOSE);
+ } else {
+ icoCss.push(consts.folder.DOCU);
+ }
+ }
+ return consts.className.BUTTON + " " + icoCss.join('_');
+ },
+ makeNodeIcoStyle: function (setting, node) {
+ var icoStyle = [];
+ if (!node.isAjaxing) {
+ var isParent = data.nodeIsParent(setting, node);
+ var icon = (isParent && node.iconOpen && node.iconClose) ? (node.open ? node.iconOpen : node.iconClose) : node[setting.data.key.icon];
+ if (icon) icoStyle.push("background:url(", icon, ") 0 0 no-repeat;");
+ if (setting.view.showIcon == false || !tools.apply(setting.view.showIcon, [setting.treeId, node], true)) {
+ icoStyle.push("display:none;");
+ }
+ }
+ return icoStyle.join('');
+ },
+ makeNodeLineClass: function (setting, node) {
+ var lineClass = [];
+ if (setting.view.showLine) {
+ if (node.level == 0 && node.isFirstNode && node.isLastNode) {
+ lineClass.push(consts.line.ROOT);
+ } else if (node.level == 0 && node.isFirstNode) {
+ lineClass.push(consts.line.ROOTS);
+ } else if (node.isLastNode) {
+ lineClass.push(consts.line.BOTTOM);
+ } else {
+ lineClass.push(consts.line.CENTER);
+ }
+ } else {
+ lineClass.push(consts.line.NOLINE);
+ }
+ if (data.nodeIsParent(setting, node)) {
+ lineClass.push(node.open ? consts.folder.OPEN : consts.folder.CLOSE);
+ } else {
+ lineClass.push(consts.folder.DOCU);
+ }
+ return view.makeNodeLineClassEx(node) + lineClass.join('_');
+ },
+ makeNodeLineClassEx: function (node) {
+ return consts.className.BUTTON + " " + consts.className.LEVEL + node.level + " " + consts.className.SWITCH + " ";
+ },
+ makeNodeTarget: function (node) {
+ return (node.target || "_blank");
+ },
+ makeNodeUrl: function (setting, node) {
+ var urlKey = setting.data.key.url;
+ return node[urlKey] ? node[urlKey] : null;
+ },
+ makeUlHtml: function (setting, node, html, content) {
+ html.push("");
+ html.push(content);
+ html.push(" ");
+ },
+ makeUlLineClass: function (setting, node) {
+ return ((setting.view.showLine && !node.isLastNode) ? consts.line.LINE : "");
+ },
+ removeChildNodes: function (setting, node) {
+ if (!node) return;
+ var nodes = data.nodeChildren(setting, node);
+ if (!nodes) return;
+
+ for (var i = 0, l = nodes.length; i < l; i++) {
+ data.removeNodeCache(setting, nodes[i]);
+ }
+ data.removeSelectedNode(setting);
+ delete node[setting.data.key.children];
+
+ if (!setting.data.keep.parent) {
+ data.nodeIsParent(setting, node, false);
+ node.open = false;
+ var tmp_switchObj = $$(node, consts.id.SWITCH, setting),
+ tmp_icoObj = $$(node, consts.id.ICON, setting);
+ view.replaceSwitchClass(node, tmp_switchObj, consts.folder.DOCU);
+ view.replaceIcoClass(node, tmp_icoObj, consts.folder.DOCU);
+ $$(node, consts.id.UL, setting).remove();
+ } else {
+ $$(node, consts.id.UL, setting).empty();
+ }
+ },
+ scrollIntoView: function (setting, dom) {
+ if (!dom) {
+ return;
+ }
+ // support IE 7 / 8
+ if (typeof Element === 'undefined' || typeof HTMLElement === 'undefined') {
+ var contRect = setting.treeObj.get(0).getBoundingClientRect(),
+ findMeRect = dom.getBoundingClientRect();
+ if (findMeRect.top < contRect.top || findMeRect.bottom > contRect.bottom
+ || findMeRect.right > contRect.right || findMeRect.left < contRect.left) {
+ dom.scrollIntoView();
+ }
+ return;
+ }
+ // CC-BY jocki84@googlemail.com, https://gist.github.com/jocki84/6ffafd003387179a988e
+ if (!Element.prototype.scrollIntoViewIfNeeded) {
+ Element.prototype.scrollIntoViewIfNeeded = function (centerIfNeeded) {
+ "use strict";
+
+ function makeRange(start, length) {
+ return {"start": start, "length": length, "end": start + length};
+ }
+
+ function coverRange(inner, outer) {
+ if (
+ false === centerIfNeeded ||
+ (outer.start < inner.end && inner.start < outer.end)
+ ) {
+ return Math.max(
+ inner.end - outer.length,
+ Math.min(outer.start, inner.start)
+ );
+ }
+ return (inner.start + inner.end - outer.length) / 2;
+ }
+
+ function makePoint(x, y) {
+ return {
+ "x": x,
+ "y": y,
+ "translate": function translate(dX, dY) {
+ return makePoint(x + dX, y + dY);
+ }
+ };
+ }
+
+ function absolute(elem, pt) {
+ while (elem) {
+ pt = pt.translate(elem.offsetLeft, elem.offsetTop);
+ elem = elem.offsetParent;
+ }
+ return pt;
+ }
+
+ var target = absolute(this, makePoint(0, 0)),
+ extent = makePoint(this.offsetWidth, this.offsetHeight),
+ elem = this.parentNode,
+ origin;
+
+ while (elem instanceof HTMLElement) {
+ // Apply desired scroll amount.
+ origin = absolute(elem, makePoint(elem.clientLeft, elem.clientTop));
+ elem.scrollLeft = coverRange(
+ makeRange(target.x - origin.x, extent.x),
+ makeRange(elem.scrollLeft, elem.clientWidth)
+ );
+ elem.scrollTop = coverRange(
+ makeRange(target.y - origin.y, extent.y),
+ makeRange(elem.scrollTop, elem.clientHeight)
+ );
+
+ // Determine actual scroll amount by reading back scroll properties.
+ target = target.translate(-elem.scrollLeft, -elem.scrollTop);
+ elem = elem.parentNode;
+ }
+ };
+ }
+ dom.scrollIntoViewIfNeeded();
+ },
+ setFirstNode: function (setting, parentNode) {
+ var children = data.nodeChildren(setting, parentNode);
+ if (children.length > 0) {
+ children[0].isFirstNode = true;
+ }
+ },
+ setLastNode: function (setting, parentNode) {
+ var children = data.nodeChildren(setting, parentNode);
+ if (children.length > 0) {
+ children[children.length - 1].isLastNode = true;
+ }
+ },
+ removeNode: function (setting, node) {
+ var root = data.getRoot(setting),
+ parentNode = (node.parentTId) ? node.getParentNode() : root;
+
+ node.isFirstNode = false;
+ node.isLastNode = false;
+ node.getPreNode = function () {
+ return null;
+ };
+ node.getNextNode = function () {
+ return null;
+ };
+
+ if (!data.getNodeCache(setting, node.tId)) {
+ return;
+ }
+
+ $$(node, setting).remove();
+ data.removeNodeCache(setting, node);
+ data.removeSelectedNode(setting, node);
+
+ var children = data.nodeChildren(setting, parentNode);
+ for (var i = 0, l = children.length; i < l; i++) {
+ if (children[i].tId == node.tId) {
+ children.splice(i, 1);
+ break;
+ }
+ }
+ view.setFirstNode(setting, parentNode);
+ view.setLastNode(setting, parentNode);
+
+ var tmp_ulObj, tmp_switchObj, tmp_icoObj,
+ childLength = children.length;
+
+ //repair nodes old parent
+ if (!setting.data.keep.parent && childLength == 0) {
+ //old parentNode has no child nodes
+ data.nodeIsParent(setting, parentNode, false);
+ parentNode.open = false;
+ delete parentNode[setting.data.key.children];
+ tmp_ulObj = $$(parentNode, consts.id.UL, setting);
+ tmp_switchObj = $$(parentNode, consts.id.SWITCH, setting);
+ tmp_icoObj = $$(parentNode, consts.id.ICON, setting);
+ view.replaceSwitchClass(parentNode, tmp_switchObj, consts.folder.DOCU);
+ view.replaceIcoClass(parentNode, tmp_icoObj, consts.folder.DOCU);
+ tmp_ulObj.css("display", "none");
+
+ } else if (setting.view.showLine && childLength > 0) {
+ //old parentNode has child nodes
+ var newLast = children[childLength - 1];
+ tmp_ulObj = $$(newLast, consts.id.UL, setting);
+ tmp_switchObj = $$(newLast, consts.id.SWITCH, setting);
+ tmp_icoObj = $$(newLast, consts.id.ICON, setting);
+ if (parentNode == root) {
+ if (children.length == 1) {
+ //node was root, and ztree has only one root after move node
+ view.replaceSwitchClass(newLast, tmp_switchObj, consts.line.ROOT);
+ } else {
+ var tmp_first_switchObj = $$(children[0], consts.id.SWITCH, setting);
+ view.replaceSwitchClass(children[0], tmp_first_switchObj, consts.line.ROOTS);
+ view.replaceSwitchClass(newLast, tmp_switchObj, consts.line.BOTTOM);
+ }
+ } else {
+ view.replaceSwitchClass(newLast, tmp_switchObj, consts.line.BOTTOM);
+ }
+ tmp_ulObj.removeClass(consts.line.LINE);
+ }
+ },
+ replaceIcoClass: function (node, obj, newName) {
+ if (!obj || node.isAjaxing) return;
+ var tmpName = obj.attr("class");
+ if (tmpName == undefined) return;
+ var tmpList = tmpName.split("_");
+ switch (newName) {
+ case consts.folder.OPEN:
+ case consts.folder.CLOSE:
+ case consts.folder.DOCU:
+ tmpList[tmpList.length - 1] = newName;
+ break;
+ }
+ obj.attr("class", tmpList.join("_"));
+ },
+ replaceSwitchClass: function (node, obj, newName) {
+ if (!obj) return;
+ var tmpName = obj.attr("class");
+ if (tmpName == undefined) return;
+ var tmpList = tmpName.split("_");
+ switch (newName) {
+ case consts.line.ROOT:
+ case consts.line.ROOTS:
+ case consts.line.CENTER:
+ case consts.line.BOTTOM:
+ case consts.line.NOLINE:
+ tmpList[0] = view.makeNodeLineClassEx(node) + newName;
+ break;
+ case consts.folder.OPEN:
+ case consts.folder.CLOSE:
+ case consts.folder.DOCU:
+ tmpList[1] = newName;
+ break;
+ }
+ obj.attr("class", tmpList.join("_"));
+ if (newName !== consts.folder.DOCU) {
+ obj.removeAttr("disabled");
+ } else {
+ obj.attr("disabled", "disabled");
+ }
+ },
+ selectNode: function (setting, node, addFlag) {
+ if (!addFlag) {
+ view.cancelPreSelectedNode(setting, null, node);
+ }
+ $$(node, consts.id.A, setting).addClass(consts.node.CURSELECTED);
+ data.addSelectedNode(setting, node);
+ setting.treeObj.trigger(consts.event.SELECTED, [setting.treeId, node]);
+ },
+ setNodeFontCss: function (setting, treeNode) {
+ var aObj = $$(treeNode, consts.id.A, setting),
+ fontCss = view.makeNodeFontCss(setting, treeNode);
+ if (fontCss) {
+ aObj.css(fontCss);
+ }
+ },
+ setNodeClasses: function (setting, treeNode) {
+ var aObj = $$(treeNode, consts.id.A, setting),
+ classes = view.makeNodeClasses(setting, treeNode);
+ if ('add' in classes && classes.add.length) {
+ aObj.addClass(classes.add.join(' '));
+ }
+ if ('remove' in classes && classes.remove.length) {
+ aObj.removeClass(classes.remove.join(' '));
+ }
+ },
+ setNodeLineIcos: function (setting, node) {
+ if (!node) return;
+ var switchObj = $$(node, consts.id.SWITCH, setting),
+ ulObj = $$(node, consts.id.UL, setting),
+ icoObj = $$(node, consts.id.ICON, setting),
+ ulLine = view.makeUlLineClass(setting, node);
+ if (ulLine.length == 0) {
+ ulObj.removeClass(consts.line.LINE);
+ } else {
+ ulObj.addClass(ulLine);
+ }
+ switchObj.attr("class", view.makeNodeLineClass(setting, node));
+ if (data.nodeIsParent(setting, node)) {
+ switchObj.removeAttr("disabled");
+ } else {
+ switchObj.attr("disabled", "disabled");
+ }
+ icoObj.removeAttr("style");
+ icoObj.attr("style", view.makeNodeIcoStyle(setting, node));
+ icoObj.attr("class", view.makeNodeIcoClass(setting, node));
+ },
+ setNodeName: function (setting, node) {
+ var title = data.nodeTitle(setting, node),
+ nObj = $$(node, consts.id.SPAN, setting);
+ nObj.empty();
+ if (setting.view.nameIsHTML) {
+ nObj.html(data.nodeName(setting, node));
+ } else {
+ nObj.text(data.nodeName(setting, node));
+ }
+ if (tools.apply(setting.view.showTitle, [setting.treeId, node], setting.view.showTitle)) {
+ var aObj = $$(node, consts.id.A, setting);
+ aObj.attr("title", !title ? "" : title);
+ }
+ },
+ setNodeTarget: function (setting, node) {
+ var aObj = $$(node, consts.id.A, setting);
+ aObj.attr("target", view.makeNodeTarget(node));
+ },
+ setNodeUrl: function (setting, node) {
+ var aObj = $$(node, consts.id.A, setting),
+ url = view.makeNodeUrl(setting, node);
+ if (url == null || url.length == 0) {
+ aObj.removeAttr("href");
+ } else {
+ aObj.attr("href", url);
+ }
+ },
+ switchNode: function (setting, node) {
+ if (node.open || !tools.canAsync(setting, node)) {
+ view.expandCollapseNode(setting, node, !node.open);
+ } else if (setting.async.enable) {
+ if (!view.asyncNode(setting, node)) {
+ view.expandCollapseNode(setting, node, !node.open);
+ return;
+ }
+ } else if (node) {
+ view.expandCollapseNode(setting, node, !node.open);
+ }
+ }
+ };
+ // zTree defind
+ $.fn.zTree = {
+ consts: _consts,
+ _z: {
+ tools: tools,
+ view: view,
+ event: event,
+ data: data
+ },
+ getZTreeObj: function (treeId) {
+ var o = data.getZTreeTools(treeId);
+ return o ? o : null;
+ },
+ destroy: function (treeId) {
+ if (!!treeId && treeId.length > 0) {
+ view.destroy(data.getSetting(treeId));
+ } else {
+ for (var s in settings) {
+ view.destroy(settings[s]);
+ }
+ }
+ },
+ init: function (obj, zSetting, zNodes) {
+ var setting = tools.clone(_setting);
+ $.extend(true, setting, zSetting);
+ setting.treeId = obj.attr("id");
+ setting.treeObj = obj;
+ setting.treeObj.empty();
+ settings[setting.treeId] = setting;
+ //For some older browser,(e.g., ie6)
+ if (typeof document.body.style.maxHeight === "undefined") {
+ setting.view.expandSpeed = "";
+ }
+ data.initRoot(setting);
+ var root = data.getRoot(setting);
+ zNodes = zNodes ? tools.clone(tools.isArray(zNodes) ? zNodes : [zNodes]) : [];
+ if (setting.data.simpleData.enable) {
+ data.nodeChildren(setting, root, data.transformTozTreeFormat(setting, zNodes));
+ } else {
+ data.nodeChildren(setting, root, zNodes);
+ }
+
+ data.initCache(setting);
+ event.unbindTree(setting);
+ event.bindTree(setting);
+ event.unbindEvent(setting);
+ event.bindEvent(setting);
+
+ var zTreeTools = {
+ setting: setting,
+ addNodes: function (parentNode, index, newNodes, isSilent) {
+ if (!parentNode) parentNode = null;
+ var isParent = data.nodeIsParent(setting, parentNode);
+ if (parentNode && !isParent && setting.data.keep.leaf) return null;
+
+ var i = parseInt(index, 10);
+ if (isNaN(i)) {
+ isSilent = !!newNodes;
+ newNodes = index;
+ index = -1;
+ } else {
+ index = i;
+ }
+ if (!newNodes) return null;
+
+
+ var xNewNodes = tools.clone(tools.isArray(newNodes) ? newNodes : [newNodes]);
+
+ function addCallback() {
+ view.addNodes(setting, parentNode, index, xNewNodes, (isSilent == true));
+ }
+
+ if (tools.canAsync(setting, parentNode)) {
+ view.asyncNode(setting, parentNode, isSilent, addCallback);
+ } else {
+ addCallback();
+ }
+ return xNewNodes;
+ },
+ cancelSelectedNode: function (node) {
+ view.cancelPreSelectedNode(setting, node);
+ },
+ destroy: function () {
+ view.destroy(setting);
+ },
+ expandAll: function (expandFlag) {
+ expandFlag = !!expandFlag;
+ view.expandCollapseSonNode(setting, null, expandFlag, true);
+ return expandFlag;
+ },
+ expandNode: function (node, expandFlag, sonSign, focus, callbackFlag) {
+ if (!node || !data.nodeIsParent(setting, node)) return null;
+ if (expandFlag !== true && expandFlag !== false) {
+ expandFlag = !node.open;
+ }
+ callbackFlag = !!callbackFlag;
+
+ if (callbackFlag && expandFlag && (tools.apply(setting.callback.beforeExpand, [setting.treeId, node], true) == false)) {
+ return null;
+ } else if (callbackFlag && !expandFlag && (tools.apply(setting.callback.beforeCollapse, [setting.treeId, node], true) == false)) {
+ return null;
+ }
+ if (expandFlag && node.parentTId) {
+ view.expandCollapseParentNode(setting, node.getParentNode(), expandFlag, false);
+ }
+ if (expandFlag === node.open && !sonSign) {
+ return null;
+ }
+
+ data.getRoot(setting).expandTriggerFlag = callbackFlag;
+ if (!tools.canAsync(setting, node) && sonSign) {
+ view.expandCollapseSonNode(setting, node, expandFlag, true, showNodeFocus);
+ } else {
+ node.open = !expandFlag;
+ view.switchNode(this.setting, node);
+ showNodeFocus();
+ }
+ return expandFlag;
+
+ function showNodeFocus() {
+ var a = $$(node, setting).get(0);
+ if (a && focus !== false) {
+ view.scrollIntoView(setting, a);
+ }
+ }
+ },
+ getNodes: function () {
+ return data.getNodes(setting);
+ },
+ getNodeByParam: function (key, value, parentNode) {
+ if (!key) return null;
+ return data.getNodeByParam(setting, parentNode ? data.nodeChildren(setting, parentNode) : data.getNodes(setting), key, value);
+ },
+ getNodeByTId: function (tId) {
+ return data.getNodeCache(setting, tId);
+ },
+ getNodesByParam: function (key, value, parentNode) {
+ if (!key) return null;
+ return data.getNodesByParam(setting, parentNode ? data.nodeChildren(setting, parentNode) : data.getNodes(setting), key, value);
+ },
+ getNodesByParamFuzzy: function (key, value, parentNode) {
+ if (!key) return null;
+ return data.getNodesByParamFuzzy(setting, parentNode ? data.nodeChildren(setting, parentNode) : data.getNodes(setting), key, value);
+ },
+ getNodesByFilter: function (filter, isSingle, parentNode, invokeParam) {
+ isSingle = !!isSingle;
+ if (!filter || (typeof filter != "function")) return (isSingle ? null : []);
+ return data.getNodesByFilter(setting, parentNode ? data.nodeChildren(setting, parentNode) : data.getNodes(setting), filter, isSingle, invokeParam);
+ },
+ getNodeIndex: function (node) {
+ if (!node) return null;
+ var parentNode = (node.parentTId) ? node.getParentNode() : data.getRoot(setting);
+ var children = data.nodeChildren(setting, parentNode);
+ for (var i = 0, l = children.length; i < l; i++) {
+ if (children[i] == node) return i;
+ }
+ return -1;
+ },
+ getSelectedNodes: function () {
+ var r = [], list = data.getRoot(setting).curSelectedList;
+ for (var i = 0, l = list.length; i < l; i++) {
+ r.push(list[i]);
+ }
+ return r;
+ },
+ isSelectedNode: function (node) {
+ return data.isSelectedNode(setting, node);
+ },
+ reAsyncChildNodesPromise: function (parentNode, reloadType, isSilent) {
+ var promise = new Promise(function (resolve, reject) {
+ try {
+ zTreeTools.reAsyncChildNodes(parentNode, reloadType, isSilent, function () {
+ resolve(parentNode);
+ });
+ } catch (e) {
+ reject(e);
+ }
+ });
+ return promise;
+ },
+ reAsyncChildNodes: function (parentNode, reloadType, isSilent, callback) {
+ if (!this.setting.async.enable) return;
+ var isRoot = !parentNode;
+ if (isRoot) {
+ parentNode = data.getRoot(setting);
+ }
+ if (reloadType == "refresh") {
+ var children = data.nodeChildren(setting, parentNode);
+ for (var i = 0, l = children ? children.length : 0; i < l; i++) {
+ data.removeNodeCache(setting, children[i]);
+ }
+ data.removeSelectedNode(setting);
+ data.nodeChildren(setting, parentNode, []);
+ if (isRoot) {
+ this.setting.treeObj.empty();
+ } else {
+ var ulObj = $$(parentNode, consts.id.UL, setting);
+ ulObj.empty();
+ }
+ }
+ view.asyncNode(this.setting, isRoot ? null : parentNode, !!isSilent, callback);
+ },
+ refresh: function () {
+ this.setting.treeObj.empty();
+ var root = data.getRoot(setting),
+ nodes = data.nodeChildren(setting, root);
+ data.initRoot(setting);
+ data.nodeChildren(setting, root, nodes);
+ data.initCache(setting);
+ view.createNodes(setting, 0, data.nodeChildren(setting, root), null, -1);
+ },
+ removeChildNodes: function (node) {
+ if (!node) return null;
+ var nodes = data.nodeChildren(setting, node);
+ view.removeChildNodes(setting, node);
+ return nodes ? nodes : null;
+ },
+ removeNode: function (node, callbackFlag) {
+ if (!node) return;
+ callbackFlag = !!callbackFlag;
+ if (callbackFlag && tools.apply(setting.callback.beforeRemove, [setting.treeId, node], true) == false) return;
+ view.removeNode(setting, node);
+ if (callbackFlag) {
+ this.setting.treeObj.trigger(consts.event.REMOVE, [setting.treeId, node]);
+ }
+ },
+ selectNode: function (node, addFlag, isSilent) {
+ if (!node) return;
+ if (tools.uCanDo(setting)) {
+ addFlag = setting.view.selectedMulti && addFlag;
+ if (node.parentTId) {
+ view.expandCollapseParentNode(setting, node.getParentNode(), true, false, showNodeFocus);
+ } else if (!isSilent) {
+ try {
+ $$(node, setting).focus().blur();
+ } catch (e) {
+ }
+ }
+ view.selectNode(setting, node, addFlag);
+ }
+
+ function showNodeFocus() {
+ if (isSilent) {
+ return;
+ }
+ var a = $$(node, setting).get(0);
+ view.scrollIntoView(setting, a);
+ }
+ },
+ transformTozTreeNodes: function (simpleNodes) {
+ return data.transformTozTreeFormat(setting, simpleNodes);
+ },
+ transformToArray: function (nodes) {
+ return data.transformToArrayFormat(setting, nodes);
+ },
+ updateNode: function (node, checkTypeFlag) {
+ if (!node) return;
+ var nObj = $$(node, setting);
+ if (nObj.get(0) && tools.uCanDo(setting)) {
+ view.setNodeName(setting, node);
+ view.setNodeTarget(setting, node);
+ view.setNodeUrl(setting, node);
+ view.setNodeLineIcos(setting, node);
+ view.setNodeFontCss(setting, node);
+ view.setNodeClasses(setting, node);
+ }
+ }
+ };
+ root.treeTools = zTreeTools;
+ data.setZTreeTools(setting, zTreeTools);
+ var children = data.nodeChildren(setting, root);
+ if (children && children.length > 0) {
+ view.createNodes(setting, 0, children, null, -1);
+ } else if (setting.async.enable && setting.async.url && setting.async.url !== '') {
+ view.asyncNode(setting);
+ }
+ return zTreeTools;
+ }
+ };
+
+ var zt = $.fn.zTree,
+ $$ = tools.$,
+ consts = zt.consts;
+})(jQuery);
\ No newline at end of file
diff --git a/odex25_project/web_gantt_native/static/src/lib/jquery.ztree.exedit.js b/odex25_project/web_gantt_native/static/src/lib/jquery.ztree.exedit.js
new file mode 100644
index 000000000..4dcc2ad71
--- /dev/null
+++ b/odex25_project/web_gantt_native/static/src/lib/jquery.ztree.exedit.js
@@ -0,0 +1,1204 @@
+/*
+ * JQuery zTree exedit
+ * v3.5.43
+ * http://treejs.cn/
+ *
+ * Copyright (c) 2010 Hunter.z
+ *
+ * Licensed same as jquery - MIT License
+ * http://www.opensource.org/licenses/mit-license.php
+ *
+ * Date: 2020-04-04
+ */
+
+(function ($) {
+ //default consts of exedit
+ var _consts = {
+ event: {
+ DRAG: "ztree_drag",
+ DROP: "ztree_drop",
+ RENAME: "ztree_rename",
+ DRAGMOVE: "ztree_dragmove"
+ },
+ id: {
+ EDIT: "_edit",
+ INPUT: "_input",
+ REMOVE: "_remove"
+ },
+ move: {
+ TYPE_INNER: "inner",
+ TYPE_PREV: "prev",
+ TYPE_NEXT: "next"
+ },
+ node: {
+ CURSELECTED_EDIT: "curSelectedNode_Edit",
+ TMPTARGET_TREE: "tmpTargetzTree",
+ TMPTARGET_NODE: "tmpTargetNode"
+ }
+ },
+ //default setting of exedit
+ _setting = {
+ edit: {
+ enable: false,
+ editNameSelectAll: false,
+ showRemoveBtn: true,
+ showRenameBtn: true,
+ removeTitle: "remove",
+ renameTitle: "rename",
+ drag: {
+ autoExpandTrigger: false,
+ isCopy: true,
+ isMove: true,
+ prev: true,
+ next: true,
+ inner: true,
+ minMoveSize: 5,
+ borderMax: 10,
+ borderMin: -5,
+ maxShowNodeNum: 5,
+ autoOpenTime: 500
+ }
+ },
+ view: {
+ addHoverDom: null,
+ removeHoverDom: null
+ },
+ callback: {
+ beforeDrag: null,
+ beforeDragOpen: null,
+ beforeDrop: null,
+ beforeEditName: null,
+ beforeRename: null,
+ onDrag: null,
+ onDragMove: null,
+ onDrop: null,
+ onRename: null
+ }
+ },
+ //default root of exedit
+ _initRoot = function (setting) {
+ var r = data.getRoot(setting), rs = data.getRoots();
+ r.curEditNode = null;
+ r.curEditInput = null;
+ r.curHoverNode = null;
+ r.dragFlag = 0;
+ r.dragNodeShowBefore = [];
+ r.dragMaskList = new Array();
+ rs.showHoverDom = true;
+ },
+ //default cache of exedit
+ _initCache = function (treeId) {
+ },
+ //default bind event of exedit
+ _bindEvent = function (setting) {
+ var o = setting.treeObj;
+ var c = consts.event;
+ o.bind(c.RENAME, function (event, treeId, treeNode, isCancel) {
+ tools.apply(setting.callback.onRename, [event, treeId, treeNode, isCancel]);
+ });
+
+ o.bind(c.DRAG, function (event, srcEvent, treeId, treeNodes) {
+ tools.apply(setting.callback.onDrag, [srcEvent, treeId, treeNodes]);
+ });
+
+ o.bind(c.DRAGMOVE, function (event, srcEvent, treeId, treeNodes) {
+ tools.apply(setting.callback.onDragMove, [srcEvent, treeId, treeNodes]);
+ });
+
+ o.bind(c.DROP, function (event, srcEvent, treeId, treeNodes, targetNode, moveType, isCopy) {
+ tools.apply(setting.callback.onDrop, [srcEvent, treeId, treeNodes, targetNode, moveType, isCopy]);
+ });
+ },
+ _unbindEvent = function (setting) {
+ var o = setting.treeObj;
+ var c = consts.event;
+ o.unbind(c.RENAME);
+ o.unbind(c.DRAG);
+ o.unbind(c.DRAGMOVE);
+ o.unbind(c.DROP);
+ },
+ //default event proxy of exedit
+ _eventProxy = function (e) {
+ var target = e.target,
+ setting = data.getSetting(e.data.treeId),
+ relatedTarget = e.relatedTarget,
+ tId = "", node = null,
+ nodeEventType = "", treeEventType = "",
+ nodeEventCallback = null, treeEventCallback = null,
+ tmp = null;
+
+ if (tools.eqs(e.type, "mouseover")) {
+ tmp = tools.getMDom(setting, target, [{tagName: "a", attrName: "treeNode" + consts.id.A}]);
+ if (tmp) {
+ tId = tools.getNodeMainDom(tmp).id;
+ nodeEventType = "hoverOverNode";
+ }
+ } else if (tools.eqs(e.type, "mouseout")) {
+ tmp = tools.getMDom(setting, relatedTarget, [{tagName: "a", attrName: "treeNode" + consts.id.A}]);
+ if (!tmp) {
+ tId = "remove";
+ nodeEventType = "hoverOutNode";
+ }
+ } else if (tools.eqs(e.type, "mousedown")) {
+ tmp = tools.getMDom(setting, target, [{tagName: "a", attrName: "treeNode" + consts.id.A}]);
+ if (tmp) {
+ tId = tools.getNodeMainDom(tmp).id;
+ nodeEventType = "mousedownNode";
+ }
+ }
+ if (tId.length > 0) {
+ node = data.getNodeCache(setting, tId);
+ switch (nodeEventType) {
+ case "mousedownNode" :
+ nodeEventCallback = _handler.onMousedownNode;
+ break;
+ case "hoverOverNode" :
+ nodeEventCallback = _handler.onHoverOverNode;
+ break;
+ case "hoverOutNode" :
+ nodeEventCallback = _handler.onHoverOutNode;
+ break;
+ }
+ }
+ var proxyResult = {
+ stop: false,
+ node: node,
+ nodeEventType: nodeEventType,
+ nodeEventCallback: nodeEventCallback,
+ treeEventType: treeEventType,
+ treeEventCallback: treeEventCallback
+ };
+ return proxyResult
+ },
+ //default init node of exedit
+ _initNode = function (setting, level, n, parentNode, isFirstNode, isLastNode, openFlag) {
+ if (!n) return;
+ n.isHover = false;
+ n.editNameFlag = false;
+ },
+ //update zTreeObj, add method of edit
+ _zTreeTools = function (setting, zTreeTools) {
+ zTreeTools.cancelEditName = function (newName) {
+ var root = data.getRoot(this.setting);
+ if (!root.curEditNode) return;
+ view.cancelCurEditNode(this.setting, newName ? newName : null, true);
+ }
+ zTreeTools.copyNode = function (targetNode, node, moveType, isSilent) {
+ if (!node) return null;
+ var isParent = data.nodeIsParent(setting, targetNode);
+ if (targetNode && !isParent && this.setting.data.keep.leaf && moveType === consts.move.TYPE_INNER) return null;
+ var _this = this,
+ newNode = tools.clone(node);
+ if (!targetNode) {
+ targetNode = null;
+ moveType = consts.move.TYPE_INNER;
+ }
+ if (moveType == consts.move.TYPE_INNER) {
+ function copyCallback() {
+ view.addNodes(_this.setting, targetNode, -1, [newNode], isSilent);
+ }
+
+ if (tools.canAsync(this.setting, targetNode)) {
+ view.asyncNode(this.setting, targetNode, isSilent, copyCallback);
+ } else {
+ copyCallback();
+ }
+ } else {
+ view.addNodes(this.setting, targetNode.parentNode, -1, [newNode], isSilent);
+ view.moveNode(this.setting, targetNode, newNode, moveType, false, isSilent);
+ }
+ return newNode;
+ }
+ zTreeTools.editName = function (node) {
+ if (!node || !node.tId || node !== data.getNodeCache(this.setting, node.tId)) return;
+ if (node.parentTId) view.expandCollapseParentNode(this.setting, node.getParentNode(), true);
+ view.editNode(this.setting, node)
+ }
+ zTreeTools.moveNode = function (targetNode, node, moveType, isSilent) {
+ if (!node) return node;
+ var isParent = data.nodeIsParent(setting, targetNode);
+ if (targetNode && !isParent && this.setting.data.keep.leaf && moveType === consts.move.TYPE_INNER) {
+ return null;
+ } else if (targetNode && ((node.parentTId == targetNode.tId && moveType == consts.move.TYPE_INNER) || $$(node, this.setting).find("#" + targetNode.tId).length > 0)) {
+ return null;
+ } else if (!targetNode) {
+ targetNode = null;
+ }
+ var _this = this;
+
+ function moveCallback() {
+ view.moveNode(_this.setting, targetNode, node, moveType, false, isSilent);
+ }
+
+ if (tools.canAsync(this.setting, targetNode) && moveType === consts.move.TYPE_INNER) {
+ view.asyncNode(this.setting, targetNode, isSilent, moveCallback);
+ } else {
+ moveCallback();
+ }
+ return node;
+ }
+ zTreeTools.setEditable = function (editable) {
+ this.setting.edit.enable = editable;
+ return this.refresh();
+ }
+ },
+ //method of operate data
+ _data = {
+ setSonNodeLevel: function (setting, parentNode, node) {
+ if (!node) return;
+ var children = data.nodeChildren(setting, node);
+ node.level = (parentNode) ? parentNode.level + 1 : 0;
+ if (!children) return;
+ for (var i = 0, l = children.length; i < l; i++) {
+ if (children[i]) data.setSonNodeLevel(setting, node, children[i]);
+ }
+ }
+ },
+ //method of event proxy
+ _event = {},
+ //method of event handler
+ _handler = {
+ onHoverOverNode: function (event, node) {
+ var setting = data.getSetting(event.data.treeId),
+ root = data.getRoot(setting);
+ if (root.curHoverNode != node) {
+ _handler.onHoverOutNode(event);
+ }
+ root.curHoverNode = node;
+ view.addHoverDom(setting, node);
+ },
+ onHoverOutNode: function (event, node) {
+ var setting = data.getSetting(event.data.treeId),
+ root = data.getRoot(setting);
+ if (root.curHoverNode && !data.isSelectedNode(setting, root.curHoverNode)) {
+ view.removeTreeDom(setting, root.curHoverNode);
+ root.curHoverNode = null;
+ }
+ },
+ onMousedownNode: function (eventMouseDown, _node) {
+ var i, l,
+ setting = data.getSetting(eventMouseDown.data.treeId),
+ root = data.getRoot(setting), roots = data.getRoots();
+ //right click can't drag & drop
+ if (eventMouseDown.button == 2 || !setting.edit.enable || (!setting.edit.drag.isCopy && !setting.edit.drag.isMove)) return true;
+
+ //input of edit node name can't drag & drop
+ var target = eventMouseDown.target,
+ _nodes = data.getRoot(setting).curSelectedList,
+ nodes = [];
+ if (!data.isSelectedNode(setting, _node)) {
+ nodes = [_node];
+ } else {
+ for (i = 0, l = _nodes.length; i < l; i++) {
+ if (_nodes[i].editNameFlag && tools.eqs(target.tagName, "input") && target.getAttribute("treeNode" + consts.id.INPUT) !== null) {
+ return true;
+ }
+ nodes.push(_nodes[i]);
+ if (nodes[0].parentTId !== _nodes[i].parentTId) {
+ nodes = [_node];
+ break;
+ }
+ }
+ }
+
+ view.editNodeBlur = true;
+ view.cancelCurEditNode(setting);
+
+ var doc = $(setting.treeObj.get(0).ownerDocument),
+ body = $(setting.treeObj.get(0).ownerDocument.body), curNode, tmpArrow, tmpTarget,
+ isOtherTree = false,
+ targetSetting = setting,
+ sourceSetting = setting,
+ preNode, nextNode,
+ preTmpTargetNodeId = null,
+ preTmpMoveType = null,
+ tmpTargetNodeId = null,
+ moveType = consts.move.TYPE_INNER,
+ mouseDownX = eventMouseDown.clientX,
+ mouseDownY = eventMouseDown.clientY,
+ startTime = (new Date()).getTime();
+
+ if (tools.uCanDo(setting)) {
+ doc.bind("mousemove", _docMouseMove);
+ }
+
+ function _docMouseMove(event) {
+ //avoid start drag after click node
+ if (root.dragFlag == 0 && Math.abs(mouseDownX - event.clientX) < setting.edit.drag.minMoveSize
+ && Math.abs(mouseDownY - event.clientY) < setting.edit.drag.minMoveSize) {
+ return true;
+ }
+ var i, l, tmpNode, tmpDom, tmpNodes;
+ body.css("cursor", "pointer");
+
+ if (root.dragFlag == 0) {
+ if (tools.apply(setting.callback.beforeDrag, [setting.treeId, nodes], true) == false) {
+ _docMouseUp(event);
+ return true;
+ }
+
+ for (i = 0, l = nodes.length; i < l; i++) {
+ if (i == 0) {
+ root.dragNodeShowBefore = [];
+ }
+ tmpNode = nodes[i];
+ if (data.nodeIsParent(setting, tmpNode) && tmpNode.open) {
+ view.expandCollapseNode(setting, tmpNode, !tmpNode.open);
+ root.dragNodeShowBefore[tmpNode.tId] = true;
+ } else {
+ root.dragNodeShowBefore[tmpNode.tId] = false;
+ }
+ }
+
+ root.dragFlag = 1;
+ roots.showHoverDom = false;
+ tools.showIfameMask(setting, true);
+
+ //sort
+ var isOrder = true, lastIndex = -1;
+ if (nodes.length > 1) {
+ var pNodes = nodes[0].parentTId ? data.nodeChildren(setting, nodes[0].getParentNode()) : data.getNodes(setting);
+ tmpNodes = [];
+ for (i = 0, l = pNodes.length; i < l; i++) {
+ if (root.dragNodeShowBefore[pNodes[i].tId] !== undefined) {
+ if (isOrder && lastIndex > -1 && (lastIndex + 1) !== i) {
+ isOrder = false;
+ }
+ tmpNodes.push(pNodes[i]);
+ lastIndex = i;
+ }
+ if (nodes.length === tmpNodes.length) {
+ nodes = tmpNodes;
+ break;
+ }
+ }
+ }
+ if (isOrder) {
+ preNode = nodes[0].getPreNode();
+ nextNode = nodes[nodes.length - 1].getNextNode();
+ }
+
+ //set node in selected
+ curNode = $$("", setting);
+ for (i = 0, l = nodes.length; i < l; i++) {
+ tmpNode = nodes[i];
+ tmpNode.editNameFlag = false;
+ view.selectNode(setting, tmpNode, i > 0);
+ view.removeTreeDom(setting, tmpNode);
+
+ if (i > setting.edit.drag.maxShowNodeNum - 1) {
+ continue;
+ }
+
+ tmpDom = $$(" ", setting);
+ tmpDom.append($$(tmpNode, consts.id.A, setting).clone());
+ tmpDom.css("padding", "0");
+ tmpDom.children("#" + tmpNode.tId + consts.id.A).removeClass(consts.node.CURSELECTED);
+ curNode.append(tmpDom);
+ if (i == setting.edit.drag.maxShowNodeNum - 1) {
+ tmpDom = $$(" ... ", setting);
+ curNode.append(tmpDom);
+ }
+ }
+ curNode.attr("id", nodes[0].tId + consts.id.UL + "_tmp");
+ curNode.addClass(setting.treeObj.attr("class"));
+ curNode.appendTo(body);
+
+ tmpArrow = $$(" ", setting);
+ tmpArrow.attr("id", "zTreeMove_arrow_tmp");
+ tmpArrow.appendTo(body);
+
+ setting.treeObj.trigger(consts.event.DRAG, [event, setting.treeId, nodes]);
+ }
+
+ if (root.dragFlag == 1) {
+ if (tmpTarget && tmpArrow.attr("id") == event.target.id && tmpTargetNodeId && (event.clientX + doc.scrollLeft() + 2) > ($("#" + tmpTargetNodeId + consts.id.A, tmpTarget).offset().left)) {
+ var xT = $("#" + tmpTargetNodeId + consts.id.A, tmpTarget);
+ event.target = (xT.length > 0) ? xT.get(0) : event.target;
+ } else if (tmpTarget) {
+ tmpTarget.removeClass(consts.node.TMPTARGET_TREE);
+ if (tmpTargetNodeId) $("#" + tmpTargetNodeId + consts.id.A, tmpTarget).removeClass(consts.node.TMPTARGET_NODE + "_" + consts.move.TYPE_PREV)
+ .removeClass(consts.node.TMPTARGET_NODE + "_" + _consts.move.TYPE_NEXT).removeClass(consts.node.TMPTARGET_NODE + "_" + _consts.move.TYPE_INNER);
+ }
+ tmpTarget = null;
+ tmpTargetNodeId = null;
+
+ //judge drag & drop in multi ztree
+ isOtherTree = false;
+ targetSetting = setting;
+ var settings = data.getSettings();
+ for (var s in settings) {
+ if (settings[s].treeId && settings[s].edit.enable && settings[s].treeId != setting.treeId
+ && (event.target.id == settings[s].treeId || $(event.target).parents("#" + settings[s].treeId).length > 0)) {
+ isOtherTree = true;
+ targetSetting = settings[s];
+ }
+ }
+
+ var docScrollTop = doc.scrollTop(),
+ docScrollLeft = doc.scrollLeft(),
+ treeOffset = targetSetting.treeObj.offset(),
+ scrollHeight = targetSetting.treeObj.get(0).scrollHeight,
+ scrollWidth = targetSetting.treeObj.get(0).scrollWidth,
+ dTop = (event.clientY + docScrollTop - treeOffset.top),
+ dBottom = (targetSetting.treeObj.height() + treeOffset.top - event.clientY - docScrollTop),
+ dLeft = (event.clientX + docScrollLeft - treeOffset.left),
+ dRight = (targetSetting.treeObj.width() + treeOffset.left - event.clientX - docScrollLeft),
+ isTop = (dTop < setting.edit.drag.borderMax && dTop > setting.edit.drag.borderMin),
+ isBottom = (dBottom < setting.edit.drag.borderMax && dBottom > setting.edit.drag.borderMin),
+ isLeft = (dLeft < setting.edit.drag.borderMax && dLeft > setting.edit.drag.borderMin),
+ isRight = (dRight < setting.edit.drag.borderMax && dRight > setting.edit.drag.borderMin),
+ isTreeInner = dTop > setting.edit.drag.borderMin && dBottom > setting.edit.drag.borderMin && dLeft > setting.edit.drag.borderMin && dRight > setting.edit.drag.borderMin,
+ isTreeTop = (isTop && targetSetting.treeObj.scrollTop() <= 0),
+ isTreeBottom = (isBottom && (targetSetting.treeObj.scrollTop() + targetSetting.treeObj.height() + 10) >= scrollHeight),
+ isTreeLeft = (isLeft && targetSetting.treeObj.scrollLeft() <= 0),
+ isTreeRight = (isRight && (targetSetting.treeObj.scrollLeft() + targetSetting.treeObj.width() + 10) >= scrollWidth);
+
+ if (event.target && tools.isChildOrSelf(event.target, targetSetting.treeId)) {
+ //get node dom
+ var targetObj = event.target;
+ while (targetObj && targetObj.tagName && !tools.eqs(targetObj.tagName, "li") && targetObj.id != targetSetting.treeId) {
+ targetObj = targetObj.parentNode;
+ }
+
+ var canMove = true;
+ //don't move to self or children of self
+ for (i = 0, l = nodes.length; i < l; i++) {
+ tmpNode = nodes[i];
+ if (targetObj.id === tmpNode.tId) {
+ canMove = false;
+ break;
+ } else if ($$(tmpNode, setting).find("#" + targetObj.id).length > 0) {
+ canMove = false;
+ break;
+ }
+ }
+ if (canMove && event.target && tools.isChildOrSelf(event.target, targetObj.id + consts.id.A)) {
+ tmpTarget = $(targetObj);
+ tmpTargetNodeId = targetObj.id;
+ }
+ }
+
+ //the mouse must be in zTree
+ tmpNode = nodes[0];
+ if (isTreeInner && tools.isChildOrSelf(event.target, targetSetting.treeId)) {
+ //judge mouse move in root of ztree
+ if (!tmpTarget && (event.target.id == targetSetting.treeId || isTreeTop || isTreeBottom || isTreeLeft || isTreeRight) && (isOtherTree || (!isOtherTree && tmpNode.parentTId))) {
+ tmpTarget = targetSetting.treeObj;
+ }
+ //auto scroll top
+ if (isTop) {
+ targetSetting.treeObj.scrollTop(targetSetting.treeObj.scrollTop() - 10);
+ } else if (isBottom) {
+ targetSetting.treeObj.scrollTop(targetSetting.treeObj.scrollTop() + 10);
+ }
+ if (isLeft) {
+ targetSetting.treeObj.scrollLeft(targetSetting.treeObj.scrollLeft() - 10);
+ } else if (isRight) {
+ targetSetting.treeObj.scrollLeft(targetSetting.treeObj.scrollLeft() + 10);
+ }
+ //auto scroll left
+ if (tmpTarget && tmpTarget != targetSetting.treeObj && tmpTarget.offset().left < targetSetting.treeObj.offset().left) {
+ targetSetting.treeObj.scrollLeft(targetSetting.treeObj.scrollLeft() + tmpTarget.offset().left - targetSetting.treeObj.offset().left);
+ }
+ }
+
+ curNode.css({
+ "top": (event.clientY + docScrollTop + 3) + "px",
+ "left": (event.clientX + docScrollLeft + 3) + "px"
+ });
+
+ var dX = 0;
+ var dY = 0;
+ if (tmpTarget && tmpTarget.attr("id") != targetSetting.treeId) {
+ var tmpTargetNode = tmpTargetNodeId == null ? null : data.getNodeCache(targetSetting, tmpTargetNodeId),
+ isCopy = ((event.ctrlKey || event.metaKey) && setting.edit.drag.isMove && setting.edit.drag.isCopy) || (!setting.edit.drag.isMove && setting.edit.drag.isCopy),
+ isPrev = !!(preNode && tmpTargetNodeId === preNode.tId),
+ isNext = !!(nextNode && tmpTargetNodeId === nextNode.tId),
+ isInner = (tmpNode.parentTId && tmpNode.parentTId == tmpTargetNodeId),
+ canPrev = (isCopy || !isNext) && tools.apply(targetSetting.edit.drag.prev, [targetSetting.treeId, nodes, tmpTargetNode], !!targetSetting.edit.drag.prev),
+ canNext = (isCopy || !isPrev) && tools.apply(targetSetting.edit.drag.next, [targetSetting.treeId, nodes, tmpTargetNode], !!targetSetting.edit.drag.next),
+ canInner = (isCopy || !isInner) && !(targetSetting.data.keep.leaf && !data.nodeIsParent(setting, tmpTargetNode)) && tools.apply(targetSetting.edit.drag.inner, [targetSetting.treeId, nodes, tmpTargetNode], !!targetSetting.edit.drag.inner);
+
+ function clearMove() {
+ tmpTarget = null;
+ tmpTargetNodeId = "";
+ moveType = consts.move.TYPE_INNER;
+ tmpArrow.css({
+ "display": "none"
+ });
+ if (window.zTreeMoveTimer) {
+ clearTimeout(window.zTreeMoveTimer);
+ window.zTreeMoveTargetNodeTId = null
+ }
+ }
+
+ if (!canPrev && !canNext && !canInner) {
+ clearMove();
+ } else {
+ var tmpTargetA = $("#" + tmpTargetNodeId + consts.id.A, tmpTarget),
+ tmpNextA = tmpTargetNode.isLastNode ? null : $("#" + tmpTargetNode.getNextNode().tId + consts.id.A, tmpTarget.next()),
+ tmpTop = tmpTargetA.offset().top,
+ tmpLeft = tmpTargetA.offset().left,
+ prevPercent = canPrev ? (canInner ? 0.25 : (canNext ? 0.5 : 1)) : -1,
+ nextPercent = canNext ? (canInner ? 0.75 : (canPrev ? 0.5 : 0)) : -1,
+ dY_percent = (event.clientY + docScrollTop - tmpTop) / tmpTargetA.height();
+
+ if ((prevPercent == 1 || dY_percent <= prevPercent && dY_percent >= -.2) && canPrev) {
+ dX = 1 - tmpArrow.width();
+ dY = tmpTop - tmpArrow.height() / 2;
+ moveType = consts.move.TYPE_PREV;
+ } else if ((nextPercent == 0 || dY_percent >= nextPercent && dY_percent <= 1.2) && canNext) {
+ dX = 1 - tmpArrow.width();
+ dY = (tmpNextA == null || (data.nodeIsParent(setting, tmpTargetNode) && tmpTargetNode.open)) ? (tmpTop + tmpTargetA.height() - tmpArrow.height() / 2) : (tmpNextA.offset().top - tmpArrow.height() / 2);
+ moveType = consts.move.TYPE_NEXT;
+ } else if (canInner) {
+ dX = 5 - tmpArrow.width();
+ dY = tmpTop;
+ moveType = consts.move.TYPE_INNER;
+ } else {
+ clearMove();
+ }
+
+ if (tmpTarget) {
+ tmpArrow.css({
+ "display": "block",
+ "top": dY + "px",
+ "left": (tmpLeft + dX) + "px"
+ });
+ tmpTargetA.addClass(consts.node.TMPTARGET_NODE + "_" + moveType);
+
+ if (preTmpTargetNodeId != tmpTargetNodeId || preTmpMoveType != moveType) {
+ startTime = (new Date()).getTime();
+ }
+ if (tmpTargetNode && data.nodeIsParent(setting, tmpTargetNode) && moveType == consts.move.TYPE_INNER) {
+ var startTimer = true;
+ if (window.zTreeMoveTimer && window.zTreeMoveTargetNodeTId !== tmpTargetNode.tId) {
+ clearTimeout(window.zTreeMoveTimer);
+ window.zTreeMoveTargetNodeTId = null;
+ } else if (window.zTreeMoveTimer && window.zTreeMoveTargetNodeTId === tmpTargetNode.tId) {
+ startTimer = false;
+ }
+ if (startTimer) {
+ window.zTreeMoveTimer = setTimeout(function () {
+ if (moveType != consts.move.TYPE_INNER) return;
+ if (tmpTargetNode && data.nodeIsParent(setting, tmpTargetNode) && !tmpTargetNode.open && (new Date()).getTime() - startTime > targetSetting.edit.drag.autoOpenTime
+ && tools.apply(targetSetting.callback.beforeDragOpen, [targetSetting.treeId, tmpTargetNode], true)) {
+ view.switchNode(targetSetting, tmpTargetNode);
+ if (targetSetting.edit.drag.autoExpandTrigger) {
+ targetSetting.treeObj.trigger(consts.event.EXPAND, [targetSetting.treeId, tmpTargetNode]);
+ }
+ }
+ }, targetSetting.edit.drag.autoOpenTime + 50);
+ window.zTreeMoveTargetNodeTId = tmpTargetNode.tId;
+ }
+ }
+ }
+ }
+ } else {
+ moveType = consts.move.TYPE_INNER;
+ if (tmpTarget && tools.apply(targetSetting.edit.drag.inner, [targetSetting.treeId, nodes, null], !!targetSetting.edit.drag.inner)) {
+ tmpTarget.addClass(consts.node.TMPTARGET_TREE);
+ } else {
+ tmpTarget = null;
+ }
+ tmpArrow.css({
+ "display": "none"
+ });
+ if (window.zTreeMoveTimer) {
+ clearTimeout(window.zTreeMoveTimer);
+ window.zTreeMoveTargetNodeTId = null;
+ }
+ }
+ preTmpTargetNodeId = tmpTargetNodeId;
+ preTmpMoveType = moveType;
+
+ setting.treeObj.trigger(consts.event.DRAGMOVE, [event, setting.treeId, nodes]);
+ }
+ return false;
+ }
+
+ doc.bind("mouseup", _docMouseUp);
+
+ function _docMouseUp(event) {
+ if (window.zTreeMoveTimer) {
+ clearTimeout(window.zTreeMoveTimer);
+ window.zTreeMoveTargetNodeTId = null;
+ }
+ preTmpTargetNodeId = null;
+ preTmpMoveType = null;
+ doc.unbind("mousemove", _docMouseMove);
+ doc.unbind("mouseup", _docMouseUp);
+ doc.unbind("selectstart", _docSelect);
+ body.css("cursor", "");
+ if (tmpTarget) {
+ tmpTarget.removeClass(consts.node.TMPTARGET_TREE);
+ if (tmpTargetNodeId) $("#" + tmpTargetNodeId + consts.id.A, tmpTarget).removeClass(consts.node.TMPTARGET_NODE + "_" + consts.move.TYPE_PREV)
+ .removeClass(consts.node.TMPTARGET_NODE + "_" + _consts.move.TYPE_NEXT).removeClass(consts.node.TMPTARGET_NODE + "_" + _consts.move.TYPE_INNER);
+ }
+ tools.showIfameMask(setting, false);
+
+ roots.showHoverDom = true;
+ if (root.dragFlag == 0) return;
+ root.dragFlag = 0;
+
+ var i, l, tmpNode;
+ for (i = 0, l = nodes.length; i < l; i++) {
+ tmpNode = nodes[i];
+ if (data.nodeIsParent(setting, tmpNode) && root.dragNodeShowBefore[tmpNode.tId] && !tmpNode.open) {
+ view.expandCollapseNode(setting, tmpNode, !tmpNode.open);
+ delete root.dragNodeShowBefore[tmpNode.tId];
+ }
+ }
+
+ if (curNode) curNode.remove();
+ if (tmpArrow) tmpArrow.remove();
+
+ var isCopy = ((event.ctrlKey || event.metaKey) && setting.edit.drag.isMove && setting.edit.drag.isCopy) || (!setting.edit.drag.isMove && setting.edit.drag.isCopy);
+ if (!isCopy && tmpTarget && tmpTargetNodeId && nodes[0].parentTId && tmpTargetNodeId == nodes[0].parentTId && moveType == consts.move.TYPE_INNER) {
+ tmpTarget = null;
+ }
+ if (tmpTarget) {
+ var dragTargetNode = tmpTargetNodeId == null ? null : data.getNodeCache(targetSetting, tmpTargetNodeId);
+ if (tools.apply(setting.callback.beforeDrop, [targetSetting.treeId, nodes, dragTargetNode, moveType, isCopy], true) == false) {
+ view.selectNodes(sourceSetting, nodes);
+ return;
+ }
+ var newNodes = isCopy ? tools.clone(nodes) : nodes;
+
+ function dropCallback() {
+ if (isOtherTree) {
+ if (!isCopy) {
+ for (var i = 0, l = nodes.length; i < l; i++) {
+ view.removeNode(setting, nodes[i]);
+ }
+ }
+ if (moveType == consts.move.TYPE_INNER) {
+ view.addNodes(targetSetting, dragTargetNode, -1, newNodes);
+ } else {
+ view.addNodes(targetSetting, dragTargetNode.getParentNode(), moveType == consts.move.TYPE_PREV ? dragTargetNode.getIndex() : dragTargetNode.getIndex() + 1, newNodes);
+ }
+ } else {
+ if (isCopy && moveType == consts.move.TYPE_INNER) {
+ view.addNodes(targetSetting, dragTargetNode, -1, newNodes);
+ } else if (isCopy) {
+ view.addNodes(targetSetting, dragTargetNode.getParentNode(), moveType == consts.move.TYPE_PREV ? dragTargetNode.getIndex() : dragTargetNode.getIndex() + 1, newNodes);
+ } else {
+ if (moveType != consts.move.TYPE_NEXT) {
+ for (i = 0, l = newNodes.length; i < l; i++) {
+ view.moveNode(targetSetting, dragTargetNode, newNodes[i], moveType, false);
+ }
+ } else {
+ for (i = -1, l = newNodes.length - 1; i < l; l--) {
+ view.moveNode(targetSetting, dragTargetNode, newNodes[l], moveType, false);
+ }
+ }
+ }
+ }
+ view.selectNodes(targetSetting, newNodes);
+
+ var a = $$(newNodes[0], setting).get(0);
+ view.scrollIntoView(setting, a);
+
+ setting.treeObj.trigger(consts.event.DROP, [event, targetSetting.treeId, newNodes, dragTargetNode, moveType, isCopy]);
+ }
+
+ if (moveType == consts.move.TYPE_INNER && tools.canAsync(targetSetting, dragTargetNode)) {
+ view.asyncNode(targetSetting, dragTargetNode, false, dropCallback);
+ } else {
+ dropCallback();
+ }
+
+ } else {
+ view.selectNodes(sourceSetting, nodes);
+ setting.treeObj.trigger(consts.event.DROP, [event, setting.treeId, nodes, null, null, null]);
+ }
+ }
+
+ doc.bind("selectstart", _docSelect);
+
+ function _docSelect() {
+ return false;
+ }
+
+ // 2018-03-30 FireFox has fixed this issue.
+ //Avoid FireFox's Bug
+ //If zTree Div CSS set 'overflow', so drag node outside of zTree, and event.target is error.
+ // if(eventMouseDown.preventDefault) {
+ // eventMouseDown.preventDefault();
+ // }
+ return true;
+ }
+ },
+ //method of tools for zTree
+ _tools = {
+ getAbs: function (obj) {
+ var oRect = obj.getBoundingClientRect(),
+ scrollTop = document.body.scrollTop + document.documentElement.scrollTop,
+ scrollLeft = document.body.scrollLeft + document.documentElement.scrollLeft;
+ return [oRect.left + scrollLeft, oRect.top + scrollTop];
+ },
+ inputFocus: function (inputObj) {
+ if (inputObj.get(0)) {
+ inputObj.focus();
+ tools.setCursorPosition(inputObj.get(0), inputObj.val().length);
+ }
+ },
+ inputSelect: function (inputObj) {
+ if (inputObj.get(0)) {
+ inputObj.focus();
+ inputObj.select();
+ }
+ },
+ setCursorPosition: function (obj, pos) {
+ if (obj.setSelectionRange) {
+ obj.focus();
+ obj.setSelectionRange(pos, pos);
+ } else if (obj.createTextRange) {
+ var range = obj.createTextRange();
+ range.collapse(true);
+ range.moveEnd('character', pos);
+ range.moveStart('character', pos);
+ range.select();
+ }
+ },
+ showIfameMask: function (setting, showSign) {
+ var root = data.getRoot(setting);
+ //clear full mask
+ while (root.dragMaskList.length > 0) {
+ root.dragMaskList[0].remove();
+ root.dragMaskList.shift();
+ }
+ if (showSign) {
+ //show mask
+ var iframeList = $$("iframe", setting);
+ for (var i = 0, l = iframeList.length; i < l; i++) {
+ var obj = iframeList.get(i),
+ r = tools.getAbs(obj),
+ dragMask = $$("
", setting);
+ dragMask.appendTo($$("body", setting));
+ root.dragMaskList.push(dragMask);
+ }
+ }
+ }
+ },
+ //method of operate ztree dom
+ _view = {
+ addEditBtn: function (setting, node) {
+ if (node.editNameFlag || $$(node, consts.id.EDIT, setting).length > 0) {
+ return;
+ }
+ if (!tools.apply(setting.edit.showRenameBtn, [setting.treeId, node], setting.edit.showRenameBtn)) {
+ return;
+ }
+ var aObj = $$(node, consts.id.A, setting),
+ editStr = " ";
+ aObj.append(editStr);
+
+ $$(node, consts.id.EDIT, setting).bind('click',
+ function () {
+ if (!tools.uCanDo(setting) || tools.apply(setting.callback.beforeEditName, [setting.treeId, node], true) == false) return false;
+ view.editNode(setting, node);
+ return false;
+ }
+ ).show();
+ },
+ addRemoveBtn: function (setting, node) {
+ if (node.editNameFlag || $$(node, consts.id.REMOVE, setting).length > 0) {
+ return;
+ }
+ if (!tools.apply(setting.edit.showRemoveBtn, [setting.treeId, node], setting.edit.showRemoveBtn)) {
+ return;
+ }
+ var aObj = $$(node, consts.id.A, setting),
+ removeStr = " ";
+ aObj.append(removeStr);
+
+ $$(node, consts.id.REMOVE, setting).bind('click',
+ function () {
+ if (!tools.uCanDo(setting) || tools.apply(setting.callback.beforeRemove, [setting.treeId, node], true) == false) return false;
+ view.removeNode(setting, node);
+ setting.treeObj.trigger(consts.event.REMOVE, [setting.treeId, node]);
+ return false;
+ }
+ ).bind('mousedown',
+ function (eventMouseDown) {
+ return true;
+ }
+ ).show();
+ },
+ addHoverDom: function (setting, node) {
+ if (data.getRoots().showHoverDom) {
+ node.isHover = true;
+ if (setting.edit.enable) {
+ view.addEditBtn(setting, node);
+ view.addRemoveBtn(setting, node);
+ }
+ tools.apply(setting.view.addHoverDom, [setting.treeId, node]);
+ }
+ },
+ cancelCurEditNode: function (setting, forceName, isCancel) {
+ var root = data.getRoot(setting),
+ node = root.curEditNode;
+
+ if (node) {
+ var inputObj = root.curEditInput,
+ newName = forceName ? forceName : (isCancel ? data.nodeName(setting, node) : inputObj.val());
+ if (tools.apply(setting.callback.beforeRename, [setting.treeId, node, newName, isCancel], true) === false) {
+ return false;
+ }
+ data.nodeName(setting, node, newName);
+ var aObj = $$(node, consts.id.A, setting);
+ aObj.removeClass(consts.node.CURSELECTED_EDIT);
+ inputObj.unbind();
+ view.setNodeName(setting, node);
+ node.editNameFlag = false;
+ root.curEditNode = null;
+ root.curEditInput = null;
+ view.selectNode(setting, node, false);
+ setting.treeObj.trigger(consts.event.RENAME, [setting.treeId, node, isCancel]);
+ }
+ root.noSelection = true;
+ return true;
+ },
+ editNode: function (setting, node) {
+ var root = data.getRoot(setting);
+ view.editNodeBlur = false;
+ if (data.isSelectedNode(setting, node) && root.curEditNode == node && node.editNameFlag) {
+ setTimeout(function () {
+ tools.inputFocus(root.curEditInput);
+ }, 0);
+ return;
+ }
+ node.editNameFlag = true;
+ view.removeTreeDom(setting, node);
+ view.cancelCurEditNode(setting);
+ view.selectNode(setting, node, false);
+ $$(node, consts.id.SPAN, setting).html(" ");
+ var inputObj = $$(node, consts.id.INPUT, setting);
+ inputObj.attr("value", data.nodeName(setting, node));
+ if (setting.edit.editNameSelectAll) {
+ tools.inputSelect(inputObj);
+ } else {
+ tools.inputFocus(inputObj);
+ }
+
+ inputObj.bind('blur', function (event) {
+ if (!view.editNodeBlur) {
+ view.cancelCurEditNode(setting);
+ }
+ }).bind('keydown', function (event) {
+ if (event.keyCode == "13") {
+ view.editNodeBlur = true;
+ view.cancelCurEditNode(setting);
+ } else if (event.keyCode == "27") {
+ view.cancelCurEditNode(setting, null, true);
+ }
+ }).bind('click', function (event) {
+ return false;
+ }).bind('dblclick', function (event) {
+ return false;
+ });
+
+ $$(node, consts.id.A, setting).addClass(consts.node.CURSELECTED_EDIT);
+ root.curEditInput = inputObj;
+ root.noSelection = false;
+ root.curEditNode = node;
+ },
+ moveNode: function (setting, targetNode, node, moveType, animateFlag, isSilent) {
+ var root = data.getRoot(setting);
+ if (targetNode == node) return;
+ if (setting.data.keep.leaf && targetNode && !data.nodeIsParent(setting, targetNode) && moveType == consts.move.TYPE_INNER) return;
+ var oldParentNode = (node.parentTId ? node.getParentNode() : root),
+ targetNodeIsRoot = (targetNode === null || targetNode == root);
+ if (targetNodeIsRoot && targetNode === null) targetNode = root;
+ if (targetNodeIsRoot) moveType = consts.move.TYPE_INNER;
+ var targetParentNode = (targetNode.parentTId ? targetNode.getParentNode() : root);
+
+ if (moveType != consts.move.TYPE_PREV && moveType != consts.move.TYPE_NEXT) {
+ moveType = consts.move.TYPE_INNER;
+ }
+
+ if (moveType == consts.move.TYPE_INNER) {
+ if (targetNodeIsRoot) {
+ //parentTId of root node is null
+ node.parentTId = null;
+ } else {
+ if (!data.nodeIsParent(setting, targetNode)) {
+ data.nodeIsParent(setting, targetNode, true);
+ targetNode.open = !!targetNode.open;
+ view.setNodeLineIcos(setting, targetNode);
+ }
+ node.parentTId = targetNode.tId;
+ }
+ }
+
+ //move node Dom
+ var targetObj, target_ulObj;
+ if (targetNodeIsRoot) {
+ targetObj = setting.treeObj;
+ target_ulObj = targetObj;
+ } else {
+ if (!isSilent && moveType == consts.move.TYPE_INNER) {
+ view.expandCollapseNode(setting, targetNode, true, false);
+ } else if (!isSilent) {
+ view.expandCollapseNode(setting, targetNode.getParentNode(), true, false);
+ }
+ targetObj = $$(targetNode, setting);
+ target_ulObj = $$(targetNode, consts.id.UL, setting);
+ if (!!targetObj.get(0) && !target_ulObj.get(0)) {
+ var ulstr = [];
+ view.makeUlHtml(setting, targetNode, ulstr, '');
+ targetObj.append(ulstr.join(''));
+ }
+ target_ulObj = $$(targetNode, consts.id.UL, setting);
+ }
+ var nodeDom = $$(node, setting);
+ if (!nodeDom.get(0)) {
+ nodeDom = view.appendNodes(setting, node.level, [node], null, -1, false, true).join('');
+ } else if (!targetObj.get(0)) {
+ nodeDom.remove();
+ }
+ if (target_ulObj.get(0) && moveType == consts.move.TYPE_INNER) {
+ target_ulObj.append(nodeDom);
+ } else if (targetObj.get(0) && moveType == consts.move.TYPE_PREV) {
+ targetObj.before(nodeDom);
+ } else if (targetObj.get(0) && moveType == consts.move.TYPE_NEXT) {
+ targetObj.after(nodeDom);
+ }
+
+ //repair the data after move
+ var i, l,
+ tmpSrcIndex = -1,
+ tmpTargetIndex = 0,
+ oldNeighbor = null,
+ newNeighbor = null,
+ oldLevel = node.level;
+ var oldChildren = data.nodeChildren(setting, oldParentNode);
+ var targetParentChildren = data.nodeChildren(setting, targetParentNode);
+ var targetChildren = data.nodeChildren(setting, targetNode);
+ if (node.isFirstNode) {
+ tmpSrcIndex = 0;
+ if (oldChildren.length > 1) {
+ oldNeighbor = oldChildren[1];
+ oldNeighbor.isFirstNode = true;
+ }
+ } else if (node.isLastNode) {
+ tmpSrcIndex = oldChildren.length - 1;
+ oldNeighbor = oldChildren[tmpSrcIndex - 1];
+ oldNeighbor.isLastNode = true;
+ } else {
+ for (i = 0, l = oldChildren.length; i < l; i++) {
+ if (oldChildren[i].tId == node.tId) {
+ tmpSrcIndex = i;
+ break;
+ }
+ }
+ }
+ if (tmpSrcIndex >= 0) {
+ oldChildren.splice(tmpSrcIndex, 1);
+ }
+ if (moveType != consts.move.TYPE_INNER) {
+ for (i = 0, l = targetParentChildren.length; i < l; i++) {
+ if (targetParentChildren[i].tId == targetNode.tId) tmpTargetIndex = i;
+ }
+ }
+ if (moveType == consts.move.TYPE_INNER) {
+ if (!targetChildren) {
+ targetChildren = data.nodeChildren(setting, targetNode, []);
+ }
+ if (targetChildren.length > 0) {
+ newNeighbor = targetChildren[targetChildren.length - 1];
+ newNeighbor.isLastNode = false;
+ }
+ targetChildren.splice(targetChildren.length, 0, node);
+ node.isLastNode = true;
+ node.isFirstNode = (targetChildren.length == 1);
+ } else if (targetNode.isFirstNode && moveType == consts.move.TYPE_PREV) {
+ targetParentChildren.splice(tmpTargetIndex, 0, node);
+ newNeighbor = targetNode;
+ newNeighbor.isFirstNode = false;
+ node.parentTId = targetNode.parentTId;
+ node.isFirstNode = true;
+ node.isLastNode = false;
+
+ } else if (targetNode.isLastNode && moveType == consts.move.TYPE_NEXT) {
+ targetParentChildren.splice(tmpTargetIndex + 1, 0, node);
+ newNeighbor = targetNode;
+ newNeighbor.isLastNode = false;
+ node.parentTId = targetNode.parentTId;
+ node.isFirstNode = false;
+ node.isLastNode = true;
+
+ } else {
+ if (moveType == consts.move.TYPE_PREV) {
+ targetParentChildren.splice(tmpTargetIndex, 0, node);
+ } else {
+ targetParentChildren.splice(tmpTargetIndex + 1, 0, node);
+ }
+ node.parentTId = targetNode.parentTId;
+ node.isFirstNode = false;
+ node.isLastNode = false;
+ }
+ data.fixPIdKeyValue(setting, node);
+ data.setSonNodeLevel(setting, node.getParentNode(), node);
+
+ //repair node what been moved
+ view.setNodeLineIcos(setting, node);
+ view.repairNodeLevelClass(setting, node, oldLevel);
+
+ //repair node's old parentNode dom
+ if (!setting.data.keep.parent && oldChildren.length < 1) {
+ //old parentNode has no child nodes
+ data.nodeIsParent(setting, oldParentNode, false);
+ oldParentNode.open = false;
+ var tmp_ulObj = $$(oldParentNode, consts.id.UL, setting),
+ tmp_switchObj = $$(oldParentNode, consts.id.SWITCH, setting),
+ tmp_icoObj = $$(oldParentNode, consts.id.ICON, setting);
+ view.replaceSwitchClass(oldParentNode, tmp_switchObj, consts.folder.DOCU);
+ view.replaceIcoClass(oldParentNode, tmp_icoObj, consts.folder.DOCU);
+ tmp_ulObj.css("display", "none");
+
+ } else if (oldNeighbor) {
+ //old neigbor node
+ view.setNodeLineIcos(setting, oldNeighbor);
+ }
+
+ //new neigbor node
+ if (newNeighbor) {
+ view.setNodeLineIcos(setting, newNeighbor);
+ }
+
+ //repair checkbox / radio
+ if (!!setting.check && setting.check.enable && view.repairChkClass) {
+ view.repairChkClass(setting, oldParentNode);
+ view.repairParentChkClassWithSelf(setting, oldParentNode);
+ if (oldParentNode != node.parent)
+ view.repairParentChkClassWithSelf(setting, node);
+ }
+
+ //expand parents after move
+ if (!isSilent) {
+ view.expandCollapseParentNode(setting, node.getParentNode(), true, animateFlag);
+ }
+ },
+ removeEditBtn: function (setting, node) {
+ $$(node, consts.id.EDIT, setting).unbind().remove();
+ },
+ removeRemoveBtn: function (setting, node) {
+ $$(node, consts.id.REMOVE, setting).unbind().remove();
+ },
+ removeTreeDom: function (setting, node) {
+ node.isHover = false;
+ view.removeEditBtn(setting, node);
+ view.removeRemoveBtn(setting, node);
+ tools.apply(setting.view.removeHoverDom, [setting.treeId, node]);
+ },
+ repairNodeLevelClass: function (setting, node, oldLevel) {
+ if (oldLevel === node.level) return;
+ var liObj = $$(node, setting),
+ aObj = $$(node, consts.id.A, setting),
+ ulObj = $$(node, consts.id.UL, setting),
+ oldClass = consts.className.LEVEL + oldLevel,
+ newClass = consts.className.LEVEL + node.level;
+ liObj.removeClass(oldClass);
+ liObj.addClass(newClass);
+ aObj.removeClass(oldClass);
+ aObj.addClass(newClass);
+ ulObj.removeClass(oldClass);
+ ulObj.addClass(newClass);
+ },
+ selectNodes: function (setting, nodes) {
+ for (var i = 0, l = nodes.length; i < l; i++) {
+ view.selectNode(setting, nodes[i], i > 0);
+ }
+ }
+ },
+
+ _z = {
+ tools: _tools,
+ view: _view,
+ event: _event,
+ data: _data
+ };
+ $.extend(true, $.fn.zTree.consts, _consts);
+ $.extend(true, $.fn.zTree._z, _z);
+
+ var zt = $.fn.zTree,
+ tools = zt._z.tools,
+ consts = zt.consts,
+ view = zt._z.view,
+ data = zt._z.data,
+ event = zt._z.event,
+ $$ = tools.$;
+
+ data.exSetting(_setting);
+ data.addInitBind(_bindEvent);
+ data.addInitUnBind(_unbindEvent);
+ data.addInitCache(_initCache);
+ data.addInitNode(_initNode);
+ data.addInitProxy(_eventProxy);
+ data.addInitRoot(_initRoot);
+ data.addZTreeTools(_zTreeTools);
+
+ var _cancelPreSelectedNode = view.cancelPreSelectedNode;
+ view.cancelPreSelectedNode = function (setting, node) {
+ var list = data.getRoot(setting).curSelectedList;
+ for (var i = 0, j = list.length; i < j; i++) {
+ if (!node || node === list[i]) {
+ view.removeTreeDom(setting, list[i]);
+ if (node) break;
+ }
+ }
+ if (_cancelPreSelectedNode) _cancelPreSelectedNode.apply(view, arguments);
+ }
+
+ var _createNodes = view.createNodes;
+ view.createNodes = function (setting, level, nodes, parentNode, index) {
+ if (_createNodes) {
+ _createNodes.apply(view, arguments);
+ }
+ if (!nodes) return;
+ if (view.repairParentChkClassWithSelf) {
+ view.repairParentChkClassWithSelf(setting, parentNode);
+ }
+ }
+
+ var _makeNodeUrl = view.makeNodeUrl;
+ view.makeNodeUrl = function (setting, node) {
+ return setting.edit.enable ? null : (_makeNodeUrl.apply(view, arguments));
+ }
+
+ var _removeNode = view.removeNode;
+ view.removeNode = function (setting, node) {
+ var root = data.getRoot(setting);
+ if (root.curEditNode === node) root.curEditNode = null;
+ if (_removeNode) {
+ _removeNode.apply(view, arguments);
+ }
+ }
+
+ var _selectNode = view.selectNode;
+ view.selectNode = function (setting, node, addFlag) {
+ var root = data.getRoot(setting);
+ if (data.isSelectedNode(setting, node) && root.curEditNode == node && node.editNameFlag) {
+ return false;
+ }
+ if (_selectNode) _selectNode.apply(view, arguments);
+ view.addHoverDom(setting, node);
+ return true;
+ }
+
+ var _uCanDo = tools.uCanDo;
+ tools.uCanDo = function (setting, e) {
+ var root = data.getRoot(setting);
+ if (e && (tools.eqs(e.type, "mouseover") || tools.eqs(e.type, "mouseout") || tools.eqs(e.type, "mousedown") || tools.eqs(e.type, "mouseup"))) {
+ return true;
+ }
+ if (root.curEditNode) {
+ view.editNodeBlur = false;
+ root.curEditInput.focus();
+ }
+ return (!root.curEditNode) && (_uCanDo ? _uCanDo.apply(view, arguments) : true);
+ }
+})(jQuery);
\ No newline at end of file
diff --git a/odex25_project/web_gantt_native/static/src/lib/twix.js b/odex25_project/web_gantt_native/static/src/lib/twix.js
new file mode 100644
index 000000000..27235c8f5
--- /dev/null
+++ b/odex25_project/web_gantt_native/static/src/lib/twix.js
@@ -0,0 +1,669 @@
+// Generated by CoffeeScript 1.10.0
+(function() {
+ var hasModule, isArray, makeTwix,
+ slice = [].slice;
+
+ hasModule = (typeof module !== "undefined" && module !== null) && (module.exports != null);
+
+ isArray = function(input) {
+ return Object.prototype.toString.call(input) === '[object Array]';
+ };
+
+ makeTwix = function(moment) {
+ var Twix;
+ if (moment == null) {
+ throw new Error("Can't find moment");
+ }
+ Twix = (function() {
+ function Twix(start, end, parseFormat, options) {
+ var ref;
+ if (options == null) {
+ options = {};
+ }
+ if (typeof parseFormat !== 'string') {
+ options = parseFormat != null ? parseFormat : {};
+ parseFormat = null;
+ }
+ if (typeof options === 'boolean') {
+ options = {
+ allDay: options
+ };
+ }
+ this._oStart = moment(start, parseFormat, options.parseStrict);
+ this._oEnd = moment(end, parseFormat, options.parseStrict);
+ this.allDay = (ref = options.allDay) != null ? ref : false;
+ this._mutated();
+ }
+
+ Twix._extend = function() {
+ var attr, first, j, len, other, others;
+ first = arguments[0], others = 2 <= arguments.length ? slice.call(arguments, 1) : [];
+ for (j = 0, len = others.length; j < len; j++) {
+ other = others[j];
+ for (attr in other) {
+ if (typeof other[attr] !== 'undefined') {
+ first[attr] = other[attr];
+ }
+ }
+ }
+ return first;
+ };
+
+ Twix.prototype.start = function() {
+ return this._start.clone();
+ };
+
+ Twix.prototype.end = function() {
+ return this._end.clone();
+ };
+
+ Twix.prototype.isSame = function(period) {
+ return this._start.isSame(this._end, period);
+ };
+
+ Twix.prototype.length = function(period) {
+ return this._displayEnd.diff(this._start, period);
+ };
+
+ Twix.prototype.count = function(period) {
+ var end, start;
+ start = this.start().startOf(period);
+ end = this.end().startOf(period);
+ return end.diff(start, period) + 1;
+ };
+
+ Twix.prototype.countInner = function(period) {
+ var end, ref, start;
+ ref = this._inner(period), start = ref[0], end = ref[1];
+ if (start >= end) {
+ return 0;
+ }
+ return end.diff(start, period);
+ };
+
+ Twix.prototype.iterate = function(intervalAmount, period, minHours) {
+ var end, hasNext, ref, start;
+ ref = this._prepIterateInputs(intervalAmount, period, minHours), intervalAmount = ref[0], period = ref[1], minHours = ref[2];
+ start = this.start().startOf(period);
+ end = this.end().startOf(period);
+ if (this.allDay) {
+ end = end.add(1, 'd');
+ }
+ hasNext = (function(_this) {
+ return function() {
+ return (!_this.allDay && start <= end && (!minHours || !start.isSame(end) || _this._end.hours() > minHours)) || (_this.allDay && start < end);
+ };
+ })(this);
+ return this._iterateHelper(period, start, hasNext, intervalAmount);
+ };
+
+ Twix.prototype.iterateInner = function(intervalAmount, period) {
+ var end, hasNext, ref, ref1, start;
+ ref = this._prepIterateInputs(intervalAmount, period), intervalAmount = ref[0], period = ref[1];
+ ref1 = this._inner(period, intervalAmount), start = ref1[0], end = ref1[1];
+ hasNext = function() {
+ return start < end;
+ };
+ return this._iterateHelper(period, start, hasNext, intervalAmount);
+ };
+
+ Twix.prototype.humanizeLength = function() {
+ if (this.allDay) {
+ if (this.isSame('d')) {
+ return 'all day';
+ } else {
+ return this._start.from(this.end().add(1, 'd'), true);
+ }
+ } else {
+ return this._start.from(this._end, true);
+ }
+ };
+
+ Twix.prototype.asDuration = function(units) {
+ var diff;
+ diff = this._end.diff(this._start);
+ return moment.duration(diff);
+ };
+
+ Twix.prototype.isPast = function() {
+ return this._lastMilli < moment();
+ };
+
+ Twix.prototype.isFuture = function() {
+ return this._start > moment();
+ };
+
+ Twix.prototype.isCurrent = function() {
+ return !this.isPast() && !this.isFuture();
+ };
+
+ Twix.prototype.contains = function(mom) {
+ if (!moment.isMoment(mom)) {
+ mom = moment(mom);
+ }
+ return this._start <= mom && this._lastMilli >= mom;
+ };
+
+ Twix.prototype.isEmpty = function() {
+ return this._start.isSame(this._displayEnd);
+ };
+
+ Twix.prototype.overlaps = function(other) {
+ return this._displayEnd.isAfter(other._start) && this._start.isBefore(other._displayEnd);
+ };
+
+ Twix.prototype.engulfs = function(other) {
+ return this._start <= other._start && this._displayEnd >= other._displayEnd;
+ };
+
+ Twix.prototype.union = function(other) {
+ var allDay, newEnd, newStart;
+ allDay = this.allDay && other.allDay;
+ newStart = this._start < other._start ? this._start : other._start;
+ newEnd = this._lastMilli > other._lastMilli ? (allDay ? this._end : this._displayEnd) : (allDay ? other._end : other._displayEnd);
+ return new Twix(newStart, newEnd, allDay);
+ };
+
+ Twix.prototype.intersection = function(other) {
+ var allDay, newEnd, newStart;
+ allDay = this.allDay && other.allDay;
+ newStart = this._start > other._start ? this._start : other._start;
+ newEnd = this._lastMilli < other._lastMilli ? (allDay ? this._end : this._displayEnd) : (allDay ? other._end : other._displayEnd);
+ return new Twix(newStart, newEnd, allDay);
+ };
+
+ Twix.prototype.xor = function() {
+ var allDay, arr, endTime, i, item, j, k, last, len, len1, o, open, other, others, ref, results, start, t;
+ others = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ open = 0;
+ start = null;
+ results = [];
+ allDay = ((function() {
+ var j, len, results1;
+ results1 = [];
+ for (j = 0, len = others.length; j < len; j++) {
+ o = others[j];
+ if (o.allDay) {
+ results1.push(o);
+ }
+ }
+ return results1;
+ })()).length === others.length;
+ arr = [];
+ ref = [this].concat(others);
+ for (i = j = 0, len = ref.length; j < len; i = ++j) {
+ item = ref[i];
+ arr.push({
+ time: item._start,
+ i: i,
+ type: 0
+ });
+ arr.push({
+ time: item._displayEnd,
+ i: i,
+ type: 1
+ });
+ }
+ arr = arr.sort(function(a, b) {
+ return a.time - b.time;
+ });
+ for (k = 0, len1 = arr.length; k < len1; k++) {
+ other = arr[k];
+ if (other.type === 1) {
+ open -= 1;
+ }
+ if (open === other.type) {
+ start = other.time;
+ }
+ if (open === (other.type + 1) % 2) {
+ if (start) {
+ last = results[results.length - 1];
+ if (last && last._end.isSame(start)) {
+ last._oEnd = other.time;
+ last._mutated();
+ } else {
+ endTime = allDay ? other.time.clone().subtract(1, 'd') : other.time;
+ t = new Twix(start, endTime, allDay);
+ if (!t.isEmpty()) {
+ results.push(t);
+ }
+ }
+ }
+ start = null;
+ }
+ if (other.type === 0) {
+ open += 1;
+ }
+ }
+ return results;
+ };
+
+ Twix.prototype.difference = function() {
+ var j, len, others, ref, results1, t;
+ others = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ ref = this.xor.apply(this, others).map((function(_this) {
+ return function(i) {
+ return _this.intersection(i);
+ };
+ })(this));
+ results1 = [];
+ for (j = 0, len = ref.length; j < len; j++) {
+ t = ref[j];
+ if (!t.isEmpty() && t.isValid()) {
+ results1.push(t);
+ }
+ }
+ return results1;
+ };
+
+ Twix.prototype.split = function() {
+ var args, dur, end, final, i, mom, start, time, times, vals;
+ args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ end = start = this.start();
+ if (moment.isDuration(args[0])) {
+ dur = args[0];
+ } else if ((!moment.isMoment(args[0]) && !isArray(args[0]) && typeof args[0] === 'object') || (typeof args[0] === 'number' && typeof args[1] === 'string')) {
+ dur = moment.duration(args[0], args[1]);
+ } else if (isArray(args[0])) {
+ times = args[0];
+ } else {
+ times = args;
+ }
+ if (times) {
+ times = (function() {
+ var j, len, results1;
+ results1 = [];
+ for (j = 0, len = times.length; j < len; j++) {
+ time = times[j];
+ results1.push(moment(time));
+ }
+ return results1;
+ })();
+ times = ((function() {
+ var j, len, results1;
+ results1 = [];
+ for (j = 0, len = times.length; j < len; j++) {
+ mom = times[j];
+ if (mom.isValid() && mom >= start) {
+ results1.push(mom);
+ }
+ }
+ return results1;
+ })()).sort();
+ }
+ if ((dur && dur.asMilliseconds() === 0) || (times && times.length === 0)) {
+ return [this];
+ }
+ vals = [];
+ i = 0;
+ final = this._displayEnd;
+ while (start < final && ((times == null) || times[i])) {
+ end = dur ? start.clone().add(dur) : times[i].clone();
+ end = moment.min(final, end);
+ if (!start.isSame(end)) {
+ vals.push(moment.twix(start, end));
+ }
+ start = end;
+ i += 1;
+ }
+ if (!end.isSame(this._displayEnd) && times) {
+ vals.push(moment.twix(end, this._displayEnd));
+ }
+ return vals;
+ };
+
+ Twix.prototype.divide = function(parts) {
+ return this.split(this.length() / parts, 'ms').slice(0, +(parts - 1) + 1 || 9e9);
+ };
+
+ Twix.prototype.isValid = function() {
+ return this._start.isValid() && this._end.isValid() && this._start <= this._displayEnd;
+ };
+
+ Twix.prototype.equals = function(other) {
+ return (other instanceof Twix) && this.allDay === other.allDay && this._start.valueOf() === other._start.valueOf() && this._end.valueOf() === other._end.valueOf();
+ };
+
+ Twix.prototype.toString = function() {
+ return "{start: " + (this._start.format()) + ", end: " + (this._end.format()) + ", allDay: " + (this.allDay ? 'true' : 'false') + "}";
+ };
+
+ Twix.prototype.toArray = function(intervalAmount, period, minHours) {
+ var itr, range;
+ itr = this.iterate(intervalAmount, period, minHours);
+ range = [];
+ while (itr.hasNext()) {
+ range.push(itr.next());
+ }
+ return range;
+ };
+
+ Twix.prototype.simpleFormat = function(momentOpts, inopts) {
+ var options, s;
+ options = {
+ allDay: '(all day)',
+ template: Twix.formatTemplate
+ };
+ Twix._extend(options, inopts || {});
+ s = options.template(this._start.format(momentOpts), this._end.format(momentOpts));
+ if (this.allDay && options.allDay) {
+ s += " " + options.allDay;
+ }
+ return s;
+ };
+
+ Twix.prototype.format = function(inopts) {
+ var atomicMonthDate, common_bucket, end_bucket, fold, format, fs, global_first, goesIntoTheMorning, j, len, momentHourFormat, needDate, needsMeridiem, options, process, start_bucket, together;
+ if (this.isEmpty()) {
+ return '';
+ }
+ momentHourFormat = this._start.localeData()._longDateFormat['LT'][0];
+ options = {
+ groupMeridiems: true,
+ spaceBeforeMeridiem: true,
+ showDayOfWeek: false,
+ hideTime: false,
+ hideYear: false,
+ implicitMinutes: true,
+ implicitDate: false,
+ implicitYear: true,
+ yearFormat: 'YYYY',
+ monthFormat: 'MMM',
+ weekdayFormat: 'ddd',
+ dayFormat: 'D',
+ meridiemFormat: 'A',
+ hourFormat: momentHourFormat,
+ minuteFormat: 'mm',
+ allDay: 'all day',
+ explicitAllDay: false,
+ lastNightEndsAt: 0,
+ template: Twix.formatTemplate
+ };
+ Twix._extend(options, inopts || {});
+ fs = [];
+ needsMeridiem = options.hourFormat && options.hourFormat[0] === 'h';
+ goesIntoTheMorning = options.lastNightEndsAt > 0 && !this.allDay && this.end().startOf('d').valueOf() === this.start().add(1, 'd').startOf('d').valueOf() && this._start.hours() > 12 && this._end.hours() < options.lastNightEndsAt;
+ needDate = !options.hideDate && (!options.implicitDate || this.start().startOf('d').valueOf() !== moment().startOf('d').valueOf() || !(this.isSame('d') || goesIntoTheMorning));
+ atomicMonthDate = !(this.allDay || options.hideTime);
+ if (this.allDay && this.isSame('d') && (options.implicitDate || options.explicitAllDay)) {
+ fs.push({
+ name: 'all day simple',
+ fn: function() {
+ return options.allDay;
+ },
+ pre: ' ',
+ slot: 0
+ });
+ }
+ if (needDate && !options.hideYear && (!options.implicitYear || this._start.year() !== moment().year() || !this.isSame('y'))) {
+ fs.push({
+ name: 'year',
+ fn: function(date) {
+ return date.format(options.yearFormat);
+ },
+ pre: ', ',
+ slot: 4
+ });
+ }
+ if (atomicMonthDate && needDate) {
+ fs.push({
+ name: 'month-date',
+ fn: function(date) {
+ return date.format(options.monthFormat + " " + options.dayFormat);
+ },
+ ignoreEnd: function() {
+ return goesIntoTheMorning;
+ },
+ pre: ' ',
+ slot: 2
+ });
+ }
+ if (!atomicMonthDate && needDate) {
+ fs.push({
+ name: 'month',
+ fn: function(date) {
+ return date.format(options.monthFormat);
+ },
+ pre: ' ',
+ slot: 2
+ });
+ }
+ if (!atomicMonthDate && needDate) {
+ fs.push({
+ name: 'date',
+ fn: function(date) {
+ return date.format(options.dayFormat);
+ },
+ pre: ' ',
+ slot: 3
+ });
+ }
+ if (needDate && options.showDayOfWeek) {
+ fs.push({
+ name: 'day of week',
+ fn: function(date) {
+ return date.format(options.weekdayFormat);
+ },
+ pre: ' ',
+ slot: 1
+ });
+ }
+ if (options.groupMeridiems && needsMeridiem && !this.allDay && !options.hideTime) {
+ fs.push({
+ name: 'meridiem',
+ fn: function(t) {
+ return t.format(options.meridiemFormat);
+ },
+ slot: 6,
+ pre: options.spaceBeforeMeridiem ? ' ' : ''
+ });
+ }
+ if (!this.allDay && !options.hideTime) {
+ fs.push({
+ name: 'time',
+ fn: function(date) {
+ var str;
+ str = date.minutes() === 0 && options.implicitMinutes && needsMeridiem ? date.format(options.hourFormat) : date.format(options.hourFormat + ":" + options.minuteFormat);
+ if (!options.groupMeridiems && needsMeridiem) {
+ if (options.spaceBeforeMeridiem) {
+ str += ' ';
+ }
+ str += date.format(options.meridiemFormat);
+ }
+ return str;
+ },
+ slot: 5,
+ pre: ', '
+ });
+ }
+ start_bucket = [];
+ end_bucket = [];
+ common_bucket = [];
+ together = true;
+ process = (function(_this) {
+ return function(format) {
+ var end_str, start_group, start_str;
+ start_str = format.fn(_this._start);
+ end_str = format.ignoreEnd && format.ignoreEnd() ? start_str : format.fn(_this._end);
+ start_group = {
+ format: format,
+ value: function() {
+ return start_str;
+ }
+ };
+ if (end_str === start_str && together) {
+ return common_bucket.push(start_group);
+ } else {
+ if (together) {
+ together = false;
+ common_bucket.push({
+ format: {
+ slot: format.slot,
+ pre: ''
+ },
+ value: function() {
+ return options.template(fold(start_bucket), fold(end_bucket, true).trim());
+ }
+ });
+ }
+ start_bucket.push(start_group);
+ return end_bucket.push({
+ format: format,
+ value: function() {
+ return end_str;
+ }
+ });
+ }
+ };
+ })(this);
+ for (j = 0, len = fs.length; j < len; j++) {
+ format = fs[j];
+ process(format);
+ }
+ global_first = true;
+ fold = function(array, skip_pre) {
+ var k, len1, local_first, ref, section, str;
+ local_first = true;
+ str = '';
+ ref = array.sort(function(a, b) {
+ return a.format.slot - b.format.slot;
+ });
+ for (k = 0, len1 = ref.length; k < len1; k++) {
+ section = ref[k];
+ if (!global_first) {
+ if (local_first && skip_pre) {
+ str += ' ';
+ } else {
+ str += section.format.pre;
+ }
+ }
+ str += section.value();
+ global_first = false;
+ local_first = false;
+ }
+ return str;
+ };
+ return fold(common_bucket);
+ };
+
+ Twix.prototype._iterateHelper = function(period, iter, hasNext, intervalAmount) {
+ return {
+ next: function() {
+ var val;
+ if (!hasNext()) {
+ return null;
+ } else {
+ val = iter.clone();
+ iter.add(intervalAmount, period);
+ return val;
+ }
+ },
+ hasNext: hasNext
+ };
+ };
+
+ Twix.prototype._prepIterateInputs = function() {
+ var inputs, intervalAmount, minHours, period, ref, ref1;
+ inputs = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+ if (typeof inputs[0] === 'number') {
+ return inputs;
+ }
+ if (typeof inputs[0] === 'string') {
+ period = inputs.shift();
+ intervalAmount = (ref = inputs.pop()) != null ? ref : 1;
+ if (inputs.length) {
+ minHours = (ref1 = inputs[0]) != null ? ref1 : false;
+ }
+ }
+ if (moment.isDuration(inputs[0])) {
+ period = 'ms';
+ intervalAmount = inputs[0].as(period);
+ }
+ return [intervalAmount, period, minHours];
+ };
+
+ Twix.prototype._inner = function(period, intervalAmount) {
+ var durationCount, durationPeriod, end, modulus, start;
+ if (period == null) {
+ period = 'ms';
+ }
+ if (intervalAmount == null) {
+ intervalAmount = 1;
+ }
+ start = this.start();
+ end = this._displayEnd.clone();
+ if (start > start.clone().startOf(period)) {
+ start.startOf(period).add(intervalAmount, period);
+ }
+ if (end < end.clone().endOf(period)) {
+ end.startOf(period);
+ }
+ durationPeriod = start.twix(end).asDuration(period);
+ durationCount = durationPeriod.get(period);
+ modulus = durationCount % intervalAmount;
+ end.subtract(modulus, period);
+ return [start, end];
+ };
+
+ Twix.prototype._mutated = function() {
+ this._start = this.allDay ? this._oStart.clone().startOf('d') : this._oStart;
+ this._lastMilli = this.allDay ? this._oEnd.clone().endOf('d') : this._oEnd;
+ this._end = this.allDay ? this._oEnd.clone().startOf('d') : this._oEnd;
+ return this._displayEnd = this.allDay ? this._end.clone().add(1, 'd') : this._end;
+ };
+
+ return Twix;
+
+ })();
+ Twix._extend(moment.locale(), {
+ _twix: Twix.defaults
+ });
+ Twix.formatTemplate = function(leftSide, rightSide) {
+ return leftSide + " - " + rightSide;
+ };
+ moment.twix = function() {
+ return (function(func, args, ctor) {
+ ctor.prototype = func.prototype;
+ var child = new ctor, result = func.apply(child, args);
+ return Object(result) === result ? result : child;
+ })(Twix, arguments, function(){});
+ };
+ moment.fn.twix = function() {
+ return (function(func, args, ctor) {
+ ctor.prototype = func.prototype;
+ var child = new ctor, result = func.apply(child, args);
+ return Object(result) === result ? result : child;
+ })(Twix, [this].concat(slice.call(arguments)), function(){});
+ };
+ moment.fn.forDuration = function(duration, allDay) {
+ return new Twix(this, this.clone().add(duration), allDay);
+ };
+ if (moment.duration.fn) {
+ moment.duration.fn.afterMoment = function(startingTime, allDay) {
+ return new Twix(startingTime, moment(startingTime).clone().add(this), allDay);
+ };
+ moment.duration.fn.beforeMoment = function(startingTime, allDay) {
+ return new Twix(moment(startingTime).clone().subtract(this), startingTime, allDay);
+ };
+ }
+ moment.twixClass = Twix;
+ return Twix;
+ };
+
+ if (hasModule) {
+ return module.exports = makeTwix(require('moment'));
+ }
+
+ if (typeof define === 'function') {
+ define('twix', ['moment'], function(moment) {
+ return makeTwix(moment);
+ });
+ }
+
+ if (this.moment) {
+ this.Twix = makeTwix(this.moment);
+ } else if (typeof moment !== "undefined" && moment !== null) {
+ this.Twix = makeTwix(moment);
+ }
+
+}).call(this);
\ No newline at end of file
diff --git a/odex25_project/web_gantt_native/static/src/xml/web_gantt_template.xml b/odex25_project/web_gantt_native/static/src/xml/web_gantt_template.xml
new file mode 100644
index 000000000..0f07eda3d
--- /dev/null
+++ b/odex25_project/web_gantt_native/static/src/xml/web_gantt_template.xml
@@ -0,0 +1,239 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/odex25_project/web_gantt_native/views/web_gantt_src.xml b/odex25_project/web_gantt_native/views/web_gantt_src.xml
new file mode 100644
index 000000000..5f76ed432
--- /dev/null
+++ b/odex25_project/web_gantt_native/views/web_gantt_src.xml
@@ -0,0 +1,74 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/odex25_project/web_widget_colorpicker/README.rst b/odex25_project/web_widget_colorpicker/README.rst
new file mode 100644
index 000000000..779d7e8e8
--- /dev/null
+++ b/odex25_project/web_widget_colorpicker/README.rst
@@ -0,0 +1,41 @@
+Color Picker widget for Odoo web client
+================================
+
+
+Features
+========
+
+Now only in RGBA code.
+
+
+* Display the color on form view when you are not editing it
+
+ |form_view_no_edit|
+
+* Display the color on form view when you editing it
+
+ |form_view_edit|
+
+Usage
+=====
+
+You need to declare a char.
+
+ colorpicker = fields.Char(
+ string="Color Picker",
+ )
+
+
+In the view declaration,
+
+ ...
+
+
+
+ ...
+
+
diff --git a/odex25_project/web_widget_colorpicker/__init__.py b/odex25_project/web_widget_colorpicker/__init__.py
new file mode 100644
index 000000000..ec51c5a2b
--- /dev/null
+++ b/odex25_project/web_widget_colorpicker/__init__.py
@@ -0,0 +1,2 @@
+# -*- coding: utf-8 -*-
+#
diff --git a/odex25_project/web_widget_colorpicker/__manifest__.py b/odex25_project/web_widget_colorpicker/__manifest__.py
new file mode 100644
index 000000000..0345bdb55
--- /dev/null
+++ b/odex25_project/web_widget_colorpicker/__manifest__.py
@@ -0,0 +1,50 @@
+# -*- coding: utf-8 -*-
+{
+ "name": """Web Widget Colorpicker""",
+ "summary": """Added Color Picker for From""",
+ "category": "Odex25-Project/Odex25-Project",
+ "images": ['static/description/icon.png'],
+ "version": "14.21.04.21",
+ "description": """
+
+ For Form View - added = widget="colorpicker"
+
+ ...
+
+
+
+ ...
+
+ """,
+
+ "author": "Viktor Vorobjov",
+ "license": "LGPL-3",
+ "website": "https://straga.github.io",
+ "support": "vostraga@gmail.com",
+ "price": 0.00,
+ "currency": "EUR",
+
+ "depends": [
+ "web"
+ ],
+ "external_dependencies": {"python": [], "bin": []},
+ "data": [
+ 'view/web_widget_colorpicker_view.xml'
+ ],
+ "qweb": [
+ 'static/src/xml/widget.xml',
+
+ ],
+ "demo": [],
+
+ "post_load": None,
+ "pre_init_hook": None,
+ "post_init_hook": None,
+ "installable": True,
+ "auto_install": False,
+ "application": False,
+}
diff --git a/odex25_project/web_widget_colorpicker/images/form_view_edit.png b/odex25_project/web_widget_colorpicker/images/form_view_edit.png
new file mode 100644
index 000000000..716e936ee
Binary files /dev/null and b/odex25_project/web_widget_colorpicker/images/form_view_edit.png differ
diff --git a/odex25_project/web_widget_colorpicker/images/form_view_no_edit.png b/odex25_project/web_widget_colorpicker/images/form_view_no_edit.png
new file mode 100644
index 000000000..cb097a6cb
Binary files /dev/null and b/odex25_project/web_widget_colorpicker/images/form_view_no_edit.png differ
diff --git a/odex25_project/web_widget_colorpicker/static/description/form_view_edit.png b/odex25_project/web_widget_colorpicker/static/description/form_view_edit.png
new file mode 100644
index 000000000..716e936ee
Binary files /dev/null and b/odex25_project/web_widget_colorpicker/static/description/form_view_edit.png differ
diff --git a/odex25_project/web_widget_colorpicker/static/description/form_view_no_edit.png b/odex25_project/web_widget_colorpicker/static/description/form_view_no_edit.png
new file mode 100644
index 000000000..cb097a6cb
Binary files /dev/null and b/odex25_project/web_widget_colorpicker/static/description/form_view_no_edit.png differ
diff --git a/odex25_project/web_widget_colorpicker/static/description/icon.png b/odex25_project/web_widget_colorpicker/static/description/icon.png
new file mode 100644
index 000000000..ab43cbc9f
Binary files /dev/null and b/odex25_project/web_widget_colorpicker/static/description/icon.png differ
diff --git a/odex25_project/web_widget_colorpicker/static/description/index.html b/odex25_project/web_widget_colorpicker/static/description/index.html
new file mode 100644
index 000000000..1ad296b60
--- /dev/null
+++ b/odex25_project/web_widget_colorpicker/static/description/index.html
@@ -0,0 +1,80 @@
+
+
+
Web Widget field
+
Bootstrap Color Picker
+
+
+
+
+
+
+
+
+
+
+
+
+
Demo
+
Live:https://demo14.garage12.eu/
+
user: demo Password:demog
+
+
+
+
+
+
+
+
+
in Action
+
+
+
+ Form View
+
+
+
+
+
+
+ Edit Form View
+
+
+
+
+
+
+
+
+
+
+
+
+
Need our service?
+
Contact us by email
+
+
+
+
+
+
+
diff --git a/odex25_project/web_widget_colorpicker/static/src/css/widget.css b/odex25_project/web_widget_colorpicker/static/src/css/widget.css
new file mode 100644
index 000000000..651b7d263
--- /dev/null
+++ b/odex25_project/web_widget_colorpicker/static/src/css/widget.css
@@ -0,0 +1,30 @@
+.openerp .oe_form .oe_form_field_time_delta input {
+ width: 100%;
+}
+
+.openerp .oe_form .oe_form_field_delta div {
+ border: 1px solid;
+ display: inline-block;
+ height: 14px;
+ margin-right: 10px;
+ position: relative;
+ top: 3px;
+ width: 40px;
+}
+
+.oe_list_field_time_delta div {
+ border: 1px solid;
+ display: inline-block;
+ height: 14px;
+ margin-right: 10px;
+ position: relative;
+ top: 3px;
+ width: 40px;
+}
+
+.time_delta_box {
+ width: 10px;
+ height: 10px;
+ display: inline-block;
+ margin-right: 5px;
+}
diff --git a/odex25_project/web_widget_colorpicker/static/src/js/widget.js b/odex25_project/web_widget_colorpicker/static/src/js/widget.js
new file mode 100644
index 000000000..1ff50069f
--- /dev/null
+++ b/odex25_project/web_widget_colorpicker/static/src/js/widget.js
@@ -0,0 +1,58 @@
+odoo.define('web.web_widget_colorpicker', function(require) {
+ "use strict";
+
+ var field_registry = require('web.field_registry');
+ var fields = require('web.basic_fields');
+
+ var FieldColorPicker = fields.FieldChar.extend({
+
+ template: 'FieldColorPicker',
+ widget_class: 'oe_form_field_color',
+
+ _renderReadonly: function () {
+ var show_value = this._formatValue(this.value);
+ this.$el.text(show_value);
+ this.$el.css("background-color", show_value);
+
+ },
+
+ _getValue: function () {
+ var $input = this.$el.find('input');
+
+ var val = $input.val();
+ var isOk = /^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+(?:\.\d+)?))?\)$/i.test(val);
+
+ if (!isOk) {
+ return '';
+ }
+
+ return $input.val();
+
+
+ },
+
+ _renderEdit: function () {
+
+ var show_value = this.value ;
+ var $input = this.$el.find('input');
+ $input.val(show_value);
+
+ this.$el.colorpicker({format: 'rgba'});
+ this.$input = $input;
+
+ },
+
+
+ });
+
+ field_registry
+ .add('colorpicker', FieldColorPicker);
+
+
+
+return {
+ FieldColorPicker: FieldColorPicker
+};
+
+
+});
diff --git a/odex25_project/web_widget_colorpicker/static/src/lib/bootstrap-colorpicker/css/bootstrap-colorpicker.css b/odex25_project/web_widget_colorpicker/static/src/lib/bootstrap-colorpicker/css/bootstrap-colorpicker.css
new file mode 100644
index 000000000..2abaeb1b3
--- /dev/null
+++ b/odex25_project/web_widget_colorpicker/static/src/lib/bootstrap-colorpicker/css/bootstrap-colorpicker.css
@@ -0,0 +1,230 @@
+/*!
+ * Bootstrap Colorpicker v2.5.1
+ * https://itsjavi.com/bootstrap-colorpicker/
+ *
+ * Originally written by (c) 2012 Stefan Petre
+ * Licensed under the Apache License v2.0
+ * http://www.apache.org/licenses/LICENSE-2.0.txt
+ *
+ */
+.colorpicker-saturation {
+ width: 100px;
+ height: 100px;
+ background-image: url("data:image/png;base64,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");
+ cursor: crosshair;
+ float: left;
+}
+.colorpicker-saturation i {
+ display: block;
+ height: 5px;
+ width: 5px;
+ border: 1px solid #000;
+ -webkit-border-radius: 5px;
+ -moz-border-radius: 5px;
+ border-radius: 5px;
+ position: absolute;
+ top: 0;
+ left: 0;
+ margin: -4px 0 0 -4px;
+}
+.colorpicker-saturation i b {
+ display: block;
+ height: 5px;
+ width: 5px;
+ border: 1px solid #fff;
+ -webkit-border-radius: 5px;
+ -moz-border-radius: 5px;
+ border-radius: 5px;
+}
+.colorpicker-hue,
+.colorpicker-alpha {
+ width: 15px;
+ height: 100px;
+ float: left;
+ cursor: row-resize;
+ margin-left: 4px;
+ margin-bottom: 4px;
+}
+.colorpicker-hue i,
+.colorpicker-alpha i {
+ display: block;
+ height: 1px;
+ background: #000;
+ border-top: 1px solid #fff;
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ margin-top: -1px;
+}
+.colorpicker-hue {
+ background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAABkCAMAAABw8qpSAAABLFBMVEXqFBb/ABH/ACL/ADH/AEH/AFD/AGD/AG7/AH7/AI3/AJ3/AKz/ALz/AMr/ANv/AOr/APr2AP/mAP/XAP/HAP+4AP+oAP+aAP+JAP97AP9rAP9cAP9MAP8+AP8tAP8fAP8PAP8BAv8AEP8AH/8AL/8APv8ATv8AXP8Abf8Ae/8Ai/8Amv8Aqv8AuP8Ayf8A1/8A5/8A9/8A//gA/+kA/9kA/8oA/7oA/6wA/5sA/40A/30A/24A/14A/1AA/z8A/zEA/yEA/xEB/wMN/wAd/wAs/wA8/wBK/wBb/wBp/wB5/wCI/wCY/wCm/wC3/wDF/wDV/wDk/wD1/wD/+gD/7AD/3AD/zAD/vgD/rQD/nwD/jgD/gAD/cAD/YgD/UQD/QwD/MgD/JAD/FAD4Eg42qAedAAAAh0lEQVR4XgXAg3EDAAAAwI9to7Zt27a1/w49BASFhEVExcQlJKWkZWTl5BUUlZRVVNXUNTS1tHXo1KVbj159+g0YNGTYiFFjxk2YNGXajFlz5i1YtGTZilVr1m3YtGXbjl179h04dOTYiVNnzl24dOXajVt37j149OTZi1dv3n349OXbj19//wOxE1dQ8reGAAAAAElFTkSuQmCC");
+}
+.colorpicker-alpha {
+ background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAABkCAQAAAAVxWkcAAABr0lEQVR4Xo2VwU0DQQxF7dmRuNIFlzlSAR3QAaXQQdIBJVABFXDcOVAAd67cjJLR07dkhcSrkZKfb/t7bG88rFo3B5gZPMNycItu2xloGV7MWHzM9zuzFWCkmA0nK6AszCUJDW6+mG6R03ncw5v8EMTEvZ2O3AliYjpslblc0RF9LmZYWxURU6aKytWZYsoWCAe+xwOZp1GsEukGiIkYxcQCHck99+gRgB7JncyIB5SGEhP3Yh5P6JwX+u6AnYot104d8DJT7uH7M9JH6OZbimj0vfMVaYnJIZFJDBW9kHlerL2C6JV4mSt7uuo2N57RxnZ+usQjn0R1jwBJBrNO3evJpVYUWsJ/E3UiXRlv24/7YZ04xmEdWlzcKS+B/eapeyMvFd2k0+hRk/T0AmTW8h69s2sjYMsdPntECiILhAeIMZAeH4QvUwfn6ijC0tTV+fT9ky8jM9nK2g7Ly1VjSpKYq6IvsAm7MtNu1orEqa/K3KNvgMFdhfquPfJmp2dbh0/8Gzb6Y22ViaNr6n5410zXdngVhbu6XqdOtWOuin5hjABGp4a2uotZ71MVCfwDBt2/v37yo6AAAAAASUVORK5CYII=");
+ display: none;
+}
+.colorpicker-saturation,
+.colorpicker-hue,
+.colorpicker-alpha {
+ background-size: contain;
+}
+.colorpicker {
+ padding: 4px;
+ min-width: 130px;
+ margin-top: 1px;
+ -webkit-border-radius: 4px;
+ -moz-border-radius: 4px;
+ border-radius: 4px;
+ z-index: 2500;
+}
+.colorpicker:before,
+.colorpicker:after {
+ display: table;
+ content: "";
+ line-height: 0;
+}
+.colorpicker:after {
+ clear: both;
+}
+.colorpicker:before {
+ content: '';
+ display: inline-block;
+ border-left: 7px solid transparent;
+ border-right: 7px solid transparent;
+ border-bottom: 7px solid #ccc;
+ border-bottom-color: rgba(0, 0, 0, 0.2);
+ position: absolute;
+ top: -7px;
+ left: 6px;
+}
+.colorpicker:after {
+ content: '';
+ display: inline-block;
+ border-left: 6px solid transparent;
+ border-right: 6px solid transparent;
+ border-bottom: 6px solid #ffffff;
+ position: absolute;
+ top: -6px;
+ left: 7px;
+}
+.colorpicker div {
+ position: relative;
+}
+.colorpicker.colorpicker-with-alpha {
+ min-width: 140px;
+}
+.colorpicker.colorpicker-with-alpha .colorpicker-alpha {
+ display: block;
+}
+.colorpicker-color {
+ height: 10px;
+ margin-top: 5px;
+ clear: both;
+ background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAABkCAQAAAAVxWkcAAABr0lEQVR4Xo2VwU0DQQxF7dmRuNIFlzlSAR3QAaXQQdIBJVABFXDcOVAAd67cjJLR07dkhcSrkZKfb/t7bG88rFo3B5gZPMNycItu2xloGV7MWHzM9zuzFWCkmA0nK6AszCUJDW6+mG6R03ncw5v8EMTEvZ2O3AliYjpslblc0RF9LmZYWxURU6aKytWZYsoWCAe+xwOZp1GsEukGiIkYxcQCHck99+gRgB7JncyIB5SGEhP3Yh5P6JwX+u6AnYot104d8DJT7uH7M9JH6OZbimj0vfMVaYnJIZFJDBW9kHlerL2C6JV4mSt7uuo2N57RxnZ+usQjn0R1jwBJBrNO3evJpVYUWsJ/E3UiXRlv24/7YZ04xmEdWlzcKS+B/eapeyMvFd2k0+hRk/T0AmTW8h69s2sjYMsdPntECiILhAeIMZAeH4QvUwfn6ijC0tTV+fT9ky8jM9nK2g7Ly1VjSpKYq6IvsAm7MtNu1orEqa/K3KNvgMFdhfquPfJmp2dbh0/8Gzb6Y22ViaNr6n5410zXdngVhbu6XqdOtWOuin5hjABGp4a2uotZ71MVCfwDBt2/v37yo6AAAAAASUVORK5CYII=");
+ background-position: 0 100%;
+}
+.colorpicker-color div {
+ height: 10px;
+}
+.colorpicker-selectors {
+ display: none;
+ height: 10px;
+ margin-top: 5px;
+ clear: both;
+}
+.colorpicker-selectors i {
+ cursor: pointer;
+ float: left;
+ height: 10px;
+ width: 10px;
+}
+.colorpicker-selectors i + i {
+ margin-left: 3px;
+}
+.colorpicker-element .input-group-addon i,
+.colorpicker-element .add-on i {
+ display: inline-block;
+ cursor: pointer;
+ height: 16px;
+ vertical-align: text-top;
+ width: 16px;
+}
+.colorpicker.colorpicker-inline {
+ position: relative;
+ display: inline-block;
+ float: none;
+ z-index: auto;
+}
+.colorpicker.colorpicker-horizontal {
+ width: 110px;
+ min-width: 110px;
+ height: auto;
+}
+.colorpicker.colorpicker-horizontal .colorpicker-saturation {
+ margin-bottom: 4px;
+}
+.colorpicker.colorpicker-horizontal .colorpicker-color {
+ width: 100px;
+}
+.colorpicker.colorpicker-horizontal .colorpicker-hue,
+.colorpicker.colorpicker-horizontal .colorpicker-alpha {
+ width: 100px;
+ height: 15px;
+ float: left;
+ cursor: col-resize;
+ margin-left: 0px;
+ margin-bottom: 4px;
+}
+.colorpicker.colorpicker-horizontal .colorpicker-hue i,
+.colorpicker.colorpicker-horizontal .colorpicker-alpha i {
+ display: block;
+ height: 15px;
+ background: #ffffff;
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 1px;
+ border: none;
+ margin-top: 0px;
+}
+.colorpicker.colorpicker-horizontal .colorpicker-hue {
+ background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAAABCAMAAAAfBfuPAAABLFBMVEXqFBb/ABH/ACL/ADH/AEH/AFD/AGD/AG7/AH7/AI3/AJ3/AKz/ALz/AMr/ANv/AOr/APr2AP/mAP/XAP/HAP+4AP+oAP+aAP+JAP97AP9rAP9cAP9MAP8+AP8tAP8fAP8PAP8BAv8AEP8AH/8AL/8APv8ATv8AXP8Abf8Ae/8Ai/8Amv8Aqv8AuP8Ayf8A1/8A5/8A9/8A//gA/+kA/9kA/8oA/7oA/6wA/5sA/40A/30A/24A/14A/1AA/z8A/zEA/yEA/xEB/wMN/wAd/wAs/wA8/wBK/wBb/wBp/wB5/wCI/wCY/wCm/wC3/wDF/wDV/wDk/wD1/wD/+gD/7AD/3AD/zAD/vgD/rQD/nwD/jgD/gAD/cAD/YgD/UQD/QwD/MgD/JAD/FAD4Eg42qAedAAAAbUlEQVR4XgXAghEDsbxtlrZt27ax/w49ACAYQTGcICmaYTleECVZUTXdMC1Wm93hdLk9Xp8/EAyFI9FYPJFMpTPZXL5QLJUr1Vq90Wy1O91efzAcjSfT2XyxXK03293+cDydL9fb/fF8vT/f3x+LfRNXARMbCAAAAABJRU5ErkJggg==");
+}
+.colorpicker.colorpicker-horizontal .colorpicker-alpha {
+ background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAAAKCAQAAADoFTP1AAAB9ElEQVR4XoWTQW4VMRBEu9qWEimL7DhEMp8NF+ASnJJLcAQgE1bcgBUSkYKUuHCrZ9pjeqSU5Yn9LPu7umJQBIIv+k7vIOrtK66L4lmr3pVOrOv3otp619KZ0/KjdNI79L52Uo09FBQWrU0vfe5trezU+hLsoUKd3Repovte+0vbq/7Lj5XbaHECKasR9G4MPlbp+gzZxd6koPEJCkAYC5SjcOTAIIOK90Dja1IfIZ8Z+zAY9jm3b5Ia+MT5sFcqRJrR2AYYA8Kua5BzYRrFPNmD4PQMegGJMOffJJUsWiI3nCHZZjInNdffLWOufzbc3JaboCAVxwmnRHbhLSPwRJ4wU0BRSc6HkECYYVw95nMKgJOcylxrJttE5Ibzf9Xq9GPvP+WX3MiV/MGHfRu/SentRQrfG1GzsIrytdNXucSRKxQNIGHM9YhGFQJcdjNcBZvfJayuYe4Sia1CzwW+19mWOhe37HsxJWKwbu/jluEU15QzAQjAqCEbhMJc78GYV2E0kooHDubUImWkTOhGpgv8PoT8DJG/bzxna4BZ0eOFSOaLADGeSpFsg5AzeaDZIDQQXjZ4y/8ryfzUXBwdELRjTjCNvOeT0rNlrJz90vwy6N9pXXQEluX0inElpPWokSdiLCfiNJJjMKQ8Qsh8GEKQKMo/eiHrNbI9UksAAAAASUVORK5CYII=");
+}
+.colorpicker-right:before {
+ left: auto;
+ right: 6px;
+}
+.colorpicker-right:after {
+ left: auto;
+ right: 7px;
+}
+.colorpicker-no-arrow:before {
+ border-right: 0;
+ border-left: 0;
+}
+.colorpicker-no-arrow:after {
+ border-right: 0;
+ border-left: 0;
+}
+.colorpicker.colorpicker-visible,
+.colorpicker-alpha.colorpicker-visible,
+.colorpicker-saturation.colorpicker-visible,
+.colorpicker-hue.colorpicker-visible,
+.colorpicker-selectors.colorpicker-visible {
+ display: block;
+}
+.colorpicker.colorpicker-hidden,
+.colorpicker-alpha.colorpicker-hidden,
+.colorpicker-saturation.colorpicker-hidden,
+.colorpicker-hue.colorpicker-hidden,
+.colorpicker-selectors.colorpicker-hidden {
+ display: none;
+}
+.colorpicker-inline.colorpicker-visible {
+ display: inline-block;
+}
+/*# sourceMappingURL=bootstrap-colorpicker.css.map */
\ No newline at end of file
diff --git a/odex25_project/web_widget_colorpicker/static/src/lib/bootstrap-colorpicker/css/bootstrap-colorpicker.css.map b/odex25_project/web_widget_colorpicker/static/src/lib/bootstrap-colorpicker/css/bootstrap-colorpicker.css.map
new file mode 100644
index 000000000..3c46f50b5
--- /dev/null
+++ b/odex25_project/web_widget_colorpicker/static/src/lib/bootstrap-colorpicker/css/bootstrap-colorpicker.css.map
@@ -0,0 +1 @@
+{"version":3,"sources":["src/less/colorpicker.less"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Bootstrap Colorpicker v2.5.1\n * https://itsjavi.com/bootstrap-colorpicker/\n *\n * Originally written by (c) 2012 Stefan Petre\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0.txt\n *\n */\n\n.bgImg(@imgBase64) {\n background-image: url(\"@{imgBase64}\");\n}\n\n.borderRadius(@size) {\n -webkit-border-radius: @size;\n -moz-border-radius: @size;\n border-radius: @size;\n}\n\n.colorpicker-saturation {\n width: 100px;\n height: 100px;\n .bgImg('data:image/png;base64,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');\n cursor: crosshair;\n float: left;\n i {\n display: block;\n height: 5px;\n width: 5px;\n border: 1px solid #000;\n .borderRadius(5px);\n position: absolute;\n top: 0;\n left: 0;\n margin: -4px 0 0 -4px;\n b {\n display: block;\n height: 5px;\n width: 5px;\n border: 1px solid #fff;\n .borderRadius(5px);\n }\n }\n}\n\n.colorpicker-hue,\n.colorpicker-alpha {\n width: 15px;\n height: 100px;\n float: left;\n cursor: row-resize;\n margin-left: 4px;\n margin-bottom: 4px;\n}\n\n.colorpicker-hue i,\n.colorpicker-alpha i {\n display: block;\n height: 1px;\n background: #000;\n border-top: 1px solid #fff;\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n margin-top: -1px;\n}\n\n.colorpicker-hue {\n .bgImg('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAABkCAMAAABw8qpSAAABLFBMVEXqFBb/ABH/ACL/ADH/AEH/AFD/AGD/AG7/AH7/AI3/AJ3/AKz/ALz/AMr/ANv/AOr/APr2AP/mAP/XAP/HAP+4AP+oAP+aAP+JAP97AP9rAP9cAP9MAP8+AP8tAP8fAP8PAP8BAv8AEP8AH/8AL/8APv8ATv8AXP8Abf8Ae/8Ai/8Amv8Aqv8AuP8Ayf8A1/8A5/8A9/8A//gA/+kA/9kA/8oA/7oA/6wA/5sA/40A/30A/24A/14A/1AA/z8A/zEA/yEA/xEB/wMN/wAd/wAs/wA8/wBK/wBb/wBp/wB5/wCI/wCY/wCm/wC3/wDF/wDV/wDk/wD1/wD/+gD/7AD/3AD/zAD/vgD/rQD/nwD/jgD/gAD/cAD/YgD/UQD/QwD/MgD/JAD/FAD4Eg42qAedAAAAh0lEQVR4XgXAg3EDAAAAwI9to7Zt27a1/w49BASFhEVExcQlJKWkZWTl5BUUlZRVVNXUNTS1tHXo1KVbj159+g0YNGTYiFFjxk2YNGXajFlz5i1YtGTZilVr1m3YtGXbjl179h04dOTYiVNnzl24dOXajVt37j149OTZi1dv3n349OXbj19//wOxE1dQ8reGAAAAAElFTkSuQmCC');\n}\n\n.colorpicker-alpha {\n .bgImg('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAABkCAQAAAAVxWkcAAABr0lEQVR4Xo2VwU0DQQxF7dmRuNIFlzlSAR3QAaXQQdIBJVABFXDcOVAAd67cjJLR07dkhcSrkZKfb/t7bG88rFo3B5gZPMNycItu2xloGV7MWHzM9zuzFWCkmA0nK6AszCUJDW6+mG6R03ncw5v8EMTEvZ2O3AliYjpslblc0RF9LmZYWxURU6aKytWZYsoWCAe+xwOZp1GsEukGiIkYxcQCHck99+gRgB7JncyIB5SGEhP3Yh5P6JwX+u6AnYot104d8DJT7uH7M9JH6OZbimj0vfMVaYnJIZFJDBW9kHlerL2C6JV4mSt7uuo2N57RxnZ+usQjn0R1jwBJBrNO3evJpVYUWsJ/E3UiXRlv24/7YZ04xmEdWlzcKS+B/eapeyMvFd2k0+hRk/T0AmTW8h69s2sjYMsdPntECiILhAeIMZAeH4QvUwfn6ijC0tTV+fT9ky8jM9nK2g7Ly1VjSpKYq6IvsAm7MtNu1orEqa/K3KNvgMFdhfquPfJmp2dbh0/8Gzb6Y22ViaNr6n5410zXdngVhbu6XqdOtWOuin5hjABGp4a2uotZ71MVCfwDBt2/v37yo6AAAAAASUVORK5CYII=');\n display: none;\n}\n\n.colorpicker-saturation,\n.colorpicker-hue,\n.colorpicker-alpha {\n background-size: contain;\n}\n\n.colorpicker {\n padding: 4px;\n min-width: 130px;\n margin-top: 1px;\n .borderRadius(4px);\n z-index: 2500;\n}\n\n.colorpicker:before,\n.colorpicker:after {\n display: table;\n content: \"\";\n line-height: 0;\n}\n\n.colorpicker:after {\n clear: both;\n}\n\n.colorpicker:before {\n content: '';\n display: inline-block;\n border-left: 7px solid transparent;\n border-right: 7px solid transparent;\n border-bottom: 7px solid #ccc;\n border-bottom-color: rgba(0, 0, 0, 0.2);\n position: absolute;\n top: -7px;\n left: 6px;\n}\n\n.colorpicker:after {\n content: '';\n display: inline-block;\n border-left: 6px solid transparent;\n border-right: 6px solid transparent;\n border-bottom: 6px solid #ffffff;\n position: absolute;\n top: -6px;\n left: 7px;\n}\n\n.colorpicker div {\n position: relative;\n}\n\n.colorpicker.colorpicker-with-alpha {\n min-width: 140px;\n}\n\n.colorpicker.colorpicker-with-alpha .colorpicker-alpha {\n display: block;\n}\n\n.colorpicker-color {\n height: 10px;\n margin-top: 5px;\n clear: both;\n .bgImg('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAABkCAQAAAAVxWkcAAABr0lEQVR4Xo2VwU0DQQxF7dmRuNIFlzlSAR3QAaXQQdIBJVABFXDcOVAAd67cjJLR07dkhcSrkZKfb/t7bG88rFo3B5gZPMNycItu2xloGV7MWHzM9zuzFWCkmA0nK6AszCUJDW6+mG6R03ncw5v8EMTEvZ2O3AliYjpslblc0RF9LmZYWxURU6aKytWZYsoWCAe+xwOZp1GsEukGiIkYxcQCHck99+gRgB7JncyIB5SGEhP3Yh5P6JwX+u6AnYot104d8DJT7uH7M9JH6OZbimj0vfMVaYnJIZFJDBW9kHlerL2C6JV4mSt7uuo2N57RxnZ+usQjn0R1jwBJBrNO3evJpVYUWsJ/E3UiXRlv24/7YZ04xmEdWlzcKS+B/eapeyMvFd2k0+hRk/T0AmTW8h69s2sjYMsdPntECiILhAeIMZAeH4QvUwfn6ijC0tTV+fT9ky8jM9nK2g7Ly1VjSpKYq6IvsAm7MtNu1orEqa/K3KNvgMFdhfquPfJmp2dbh0/8Gzb6Y22ViaNr6n5410zXdngVhbu6XqdOtWOuin5hjABGp4a2uotZ71MVCfwDBt2/v37yo6AAAAAASUVORK5CYII=');\n background-position: 0 100%;\n}\n\n.colorpicker-color div {\n height: 10px;\n}\n\n.colorpicker-selectors {\n display: none;\n height: 10px;\n margin-top: 5px;\n clear: both;\n}\n\n.colorpicker-selectors i {\n cursor: pointer;\n float: left;\n height: 10px;\n width: 10px;\n}\n\n.colorpicker-selectors i + i {\n margin-left: 3px;\n}\n\n.colorpicker-element .input-group-addon i,\n.colorpicker-element .add-on i {\n display: inline-block;\n cursor: pointer;\n height: 16px;\n vertical-align: text-top;\n width: 16px;\n}\n\n.colorpicker.colorpicker-inline {\n position: relative;\n display: inline-block;\n float: none;\n z-index: auto;\n}\n\n.colorpicker.colorpicker-horizontal {\n width: 110px;\n min-width: 110px;\n height: auto;\n}\n\n.colorpicker.colorpicker-horizontal .colorpicker-saturation {\n margin-bottom: 4px;\n}\n\n.colorpicker.colorpicker-horizontal .colorpicker-color {\n width: 100px;\n}\n\n.colorpicker.colorpicker-horizontal .colorpicker-hue,\n.colorpicker.colorpicker-horizontal .colorpicker-alpha {\n width: 100px;\n height: 15px;\n float: left;\n cursor: col-resize;\n margin-left: 0px;\n margin-bottom: 4px;\n}\n\n.colorpicker.colorpicker-horizontal .colorpicker-hue i,\n.colorpicker.colorpicker-horizontal .colorpicker-alpha i {\n display: block;\n height: 15px;\n background: #ffffff;\n position: absolute;\n top: 0;\n left: 0;\n width: 1px;\n border: none;\n margin-top: 0px;\n}\n\n.colorpicker.colorpicker-horizontal .colorpicker-hue {\n .bgImg('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAAABCAMAAAAfBfuPAAABLFBMVEXqFBb/ABH/ACL/ADH/AEH/AFD/AGD/AG7/AH7/AI3/AJ3/AKz/ALz/AMr/ANv/AOr/APr2AP/mAP/XAP/HAP+4AP+oAP+aAP+JAP97AP9rAP9cAP9MAP8+AP8tAP8fAP8PAP8BAv8AEP8AH/8AL/8APv8ATv8AXP8Abf8Ae/8Ai/8Amv8Aqv8AuP8Ayf8A1/8A5/8A9/8A//gA/+kA/9kA/8oA/7oA/6wA/5sA/40A/30A/24A/14A/1AA/z8A/zEA/yEA/xEB/wMN/wAd/wAs/wA8/wBK/wBb/wBp/wB5/wCI/wCY/wCm/wC3/wDF/wDV/wDk/wD1/wD/+gD/7AD/3AD/zAD/vgD/rQD/nwD/jgD/gAD/cAD/YgD/UQD/QwD/MgD/JAD/FAD4Eg42qAedAAAAbUlEQVR4XgXAghEDsbxtlrZt27ax/w49ACAYQTGcICmaYTleECVZUTXdMC1Wm93hdLk9Xp8/EAyFI9FYPJFMpTPZXL5QLJUr1Vq90Wy1O91efzAcjSfT2XyxXK03293+cDydL9fb/fF8vT/f3x+LfRNXARMbCAAAAABJRU5ErkJggg==');\n}\n\n.colorpicker.colorpicker-horizontal .colorpicker-alpha {\n .bgImg('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAAAKCAQAAADoFTP1AAAB9ElEQVR4XoWTQW4VMRBEu9qWEimL7DhEMp8NF+ASnJJLcAQgE1bcgBUSkYKUuHCrZ9pjeqSU5Yn9LPu7umJQBIIv+k7vIOrtK66L4lmr3pVOrOv3otp619KZ0/KjdNI79L52Uo09FBQWrU0vfe5trezU+hLsoUKd3Repovte+0vbq/7Lj5XbaHECKasR9G4MPlbp+gzZxd6koPEJCkAYC5SjcOTAIIOK90Dja1IfIZ8Z+zAY9jm3b5Ia+MT5sFcqRJrR2AYYA8Kua5BzYRrFPNmD4PQMegGJMOffJJUsWiI3nCHZZjInNdffLWOufzbc3JaboCAVxwmnRHbhLSPwRJ4wU0BRSc6HkECYYVw95nMKgJOcylxrJttE5Ibzf9Xq9GPvP+WX3MiV/MGHfRu/SentRQrfG1GzsIrytdNXucSRKxQNIGHM9YhGFQJcdjNcBZvfJayuYe4Sia1CzwW+19mWOhe37HsxJWKwbu/jluEU15QzAQjAqCEbhMJc78GYV2E0kooHDubUImWkTOhGpgv8PoT8DJG/bzxna4BZ0eOFSOaLADGeSpFsg5AzeaDZIDQQXjZ4y/8ryfzUXBwdELRjTjCNvOeT0rNlrJz90vwy6N9pXXQEluX0inElpPWokSdiLCfiNJJjMKQ8Qsh8GEKQKMo/eiHrNbI9UksAAAAASUVORK5CYII=');\n}\n\n.colorpicker-right:before {\n left: auto;\n right: 6px;\n}\n\n.colorpicker-right:after {\n left: auto;\n right: 7px;\n}\n\n.colorpicker-no-arrow:before {\n border-right: 0;\n border-left: 0;\n}\n\n.colorpicker-no-arrow:after {\n border-right: 0;\n border-left: 0;\n}\n\n.colorpicker,\n.colorpicker-alpha,\n.colorpicker-saturation,\n.colorpicker-hue,\n.colorpicker-selectors {\n &.colorpicker-visible {\n display: block;\n }\n}\n\n.colorpicker,\n.colorpicker-alpha,\n.colorpicker-saturation,\n.colorpicker-hue,\n.colorpicker-selectors {\n &.colorpicker-hidden {\n display: none;\n }\n}\n\n.colorpicker-inline.colorpicker-visible {\n display: inline-block;\n}\n"]}
\ No newline at end of file
diff --git a/odex25_project/web_widget_colorpicker/static/src/lib/bootstrap-colorpicker/css/bootstrap-colorpicker.min.css b/odex25_project/web_widget_colorpicker/static/src/lib/bootstrap-colorpicker/css/bootstrap-colorpicker.min.css
new file mode 100644
index 000000000..43494ca46
--- /dev/null
+++ b/odex25_project/web_widget_colorpicker/static/src/lib/bootstrap-colorpicker/css/bootstrap-colorpicker.min.css
@@ -0,0 +1,10 @@
+/*!
+ * Bootstrap Colorpicker v2.5.1
+ * https://itsjavi.com/bootstrap-colorpicker/
+ *
+ * Originally written by (c) 2012 Stefan Petre
+ * Licensed under the Apache License v2.0
+ * http://www.apache.org/licenses/LICENSE-2.0.txt
+ *
+ */.colorpicker-saturation{width:100px;height:100px;background-image:url(data:image/png;base64,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);cursor:crosshair;float:left}.colorpicker-saturation i{display:block;height:5px;width:5px;border:1px solid #000;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;position:absolute;top:0;left:0;margin:-4px 0 0 -4px}.colorpicker-saturation i b{display:block;height:5px;width:5px;border:1px solid #fff;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.colorpicker-alpha,.colorpicker-hue{width:15px;height:100px;float:left;cursor:row-resize;margin-left:4px;margin-bottom:4px}.colorpicker-alpha i,.colorpicker-hue i{display:block;height:1px;background:#000;border-top:1px solid #fff;position:absolute;top:0;left:0;width:100%;margin-top:-1px}.colorpicker-hue{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAABkCAMAAABw8qpSAAABLFBMVEXqFBb/ABH/ACL/ADH/AEH/AFD/AGD/AG7/AH7/AI3/AJ3/AKz/ALz/AMr/ANv/AOr/APr2AP/mAP/XAP/HAP+4AP+oAP+aAP+JAP97AP9rAP9cAP9MAP8+AP8tAP8fAP8PAP8BAv8AEP8AH/8AL/8APv8ATv8AXP8Abf8Ae/8Ai/8Amv8Aqv8AuP8Ayf8A1/8A5/8A9/8A//gA/+kA/9kA/8oA/7oA/6wA/5sA/40A/30A/24A/14A/1AA/z8A/zEA/yEA/xEB/wMN/wAd/wAs/wA8/wBK/wBb/wBp/wB5/wCI/wCY/wCm/wC3/wDF/wDV/wDk/wD1/wD/+gD/7AD/3AD/zAD/vgD/rQD/nwD/jgD/gAD/cAD/YgD/UQD/QwD/MgD/JAD/FAD4Eg42qAedAAAAh0lEQVR4XgXAg3EDAAAAwI9to7Zt27a1/w49BASFhEVExcQlJKWkZWTl5BUUlZRVVNXUNTS1tHXo1KVbj159+g0YNGTYiFFjxk2YNGXajFlz5i1YtGTZilVr1m3YtGXbjl179h04dOTYiVNnzl24dOXajVt37j149OTZi1dv3n349OXbj19//wOxE1dQ8reGAAAAAElFTkSuQmCC)}.colorpicker-alpha{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAABkCAQAAAAVxWkcAAABr0lEQVR4Xo2VwU0DQQxF7dmRuNIFlzlSAR3QAaXQQdIBJVABFXDcOVAAd67cjJLR07dkhcSrkZKfb/t7bG88rFo3B5gZPMNycItu2xloGV7MWHzM9zuzFWCkmA0nK6AszCUJDW6+mG6R03ncw5v8EMTEvZ2O3AliYjpslblc0RF9LmZYWxURU6aKytWZYsoWCAe+xwOZp1GsEukGiIkYxcQCHck99+gRgB7JncyIB5SGEhP3Yh5P6JwX+u6AnYot104d8DJT7uH7M9JH6OZbimj0vfMVaYnJIZFJDBW9kHlerL2C6JV4mSt7uuo2N57RxnZ+usQjn0R1jwBJBrNO3evJpVYUWsJ/E3UiXRlv24/7YZ04xmEdWlzcKS+B/eapeyMvFd2k0+hRk/T0AmTW8h69s2sjYMsdPntECiILhAeIMZAeH4QvUwfn6ijC0tTV+fT9ky8jM9nK2g7Ly1VjSpKYq6IvsAm7MtNu1orEqa/K3KNvgMFdhfquPfJmp2dbh0/8Gzb6Y22ViaNr6n5410zXdngVhbu6XqdOtWOuin5hjABGp4a2uotZ71MVCfwDBt2/v37yo6AAAAAASUVORK5CYII=);display:none}.colorpicker-alpha,.colorpicker-hue,.colorpicker-saturation{background-size:contain}.colorpicker{padding:4px;min-width:130px;margin-top:1px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;z-index:2500}.colorpicker:after,.colorpicker:before{display:table;content:"";line-height:0}.colorpicker:after{clear:both}.colorpicker:before{content:'';display:inline-block;border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-bottom-color:rgba(0,0,0,.2);position:absolute;top:-7px;left:6px}.colorpicker:after{content:'';display:inline-block;border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #fff;position:absolute;top:-6px;left:7px}.colorpicker div{position:relative}.colorpicker.colorpicker-with-alpha{min-width:140px}.colorpicker.colorpicker-with-alpha .colorpicker-alpha{display:block}.colorpicker-color{height:10px;margin-top:5px;clear:both;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAABkCAQAAAAVxWkcAAABr0lEQVR4Xo2VwU0DQQxF7dmRuNIFlzlSAR3QAaXQQdIBJVABFXDcOVAAd67cjJLR07dkhcSrkZKfb/t7bG88rFo3B5gZPMNycItu2xloGV7MWHzM9zuzFWCkmA0nK6AszCUJDW6+mG6R03ncw5v8EMTEvZ2O3AliYjpslblc0RF9LmZYWxURU6aKytWZYsoWCAe+xwOZp1GsEukGiIkYxcQCHck99+gRgB7JncyIB5SGEhP3Yh5P6JwX+u6AnYot104d8DJT7uH7M9JH6OZbimj0vfMVaYnJIZFJDBW9kHlerL2C6JV4mSt7uuo2N57RxnZ+usQjn0R1jwBJBrNO3evJpVYUWsJ/E3UiXRlv24/7YZ04xmEdWlzcKS+B/eapeyMvFd2k0+hRk/T0AmTW8h69s2sjYMsdPntECiILhAeIMZAeH4QvUwfn6ijC0tTV+fT9ky8jM9nK2g7Ly1VjSpKYq6IvsAm7MtNu1orEqa/K3KNvgMFdhfquPfJmp2dbh0/8Gzb6Y22ViaNr6n5410zXdngVhbu6XqdOtWOuin5hjABGp4a2uotZ71MVCfwDBt2/v37yo6AAAAAASUVORK5CYII=);background-position:0 100%}.colorpicker-color div{height:10px}.colorpicker-selectors{display:none;height:10px;margin-top:5px;clear:both}.colorpicker-selectors i{cursor:pointer;float:left;height:10px;width:10px}.colorpicker-selectors i+i{margin-left:3px}.colorpicker-element .add-on i,.colorpicker-element .input-group-addon i{display:inline-block;cursor:pointer;height:16px;vertical-align:text-top;width:16px}.colorpicker.colorpicker-inline{position:relative;display:inline-block;float:none;z-index:auto}.colorpicker.colorpicker-horizontal{width:110px;min-width:110px;height:auto}.colorpicker.colorpicker-horizontal .colorpicker-saturation{margin-bottom:4px}.colorpicker.colorpicker-horizontal .colorpicker-color{width:100px}.colorpicker.colorpicker-horizontal .colorpicker-alpha,.colorpicker.colorpicker-horizontal .colorpicker-hue{width:100px;height:15px;float:left;cursor:col-resize;margin-left:0;margin-bottom:4px}.colorpicker.colorpicker-horizontal .colorpicker-alpha i,.colorpicker.colorpicker-horizontal .colorpicker-hue i{display:block;height:15px;background:#fff;position:absolute;top:0;left:0;width:1px;border:none;margin-top:0}.colorpicker.colorpicker-horizontal .colorpicker-hue{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAAABCAMAAAAfBfuPAAABLFBMVEXqFBb/ABH/ACL/ADH/AEH/AFD/AGD/AG7/AH7/AI3/AJ3/AKz/ALz/AMr/ANv/AOr/APr2AP/mAP/XAP/HAP+4AP+oAP+aAP+JAP97AP9rAP9cAP9MAP8+AP8tAP8fAP8PAP8BAv8AEP8AH/8AL/8APv8ATv8AXP8Abf8Ae/8Ai/8Amv8Aqv8AuP8Ayf8A1/8A5/8A9/8A//gA/+kA/9kA/8oA/7oA/6wA/5sA/40A/30A/24A/14A/1AA/z8A/zEA/yEA/xEB/wMN/wAd/wAs/wA8/wBK/wBb/wBp/wB5/wCI/wCY/wCm/wC3/wDF/wDV/wDk/wD1/wD/+gD/7AD/3AD/zAD/vgD/rQD/nwD/jgD/gAD/cAD/YgD/UQD/QwD/MgD/JAD/FAD4Eg42qAedAAAAbUlEQVR4XgXAghEDsbxtlrZt27ax/w49ACAYQTGcICmaYTleECVZUTXdMC1Wm93hdLk9Xp8/EAyFI9FYPJFMpTPZXL5QLJUr1Vq90Wy1O91efzAcjSfT2XyxXK03293+cDydL9fb/fF8vT/f3x+LfRNXARMbCAAAAABJRU5ErkJggg==)}.colorpicker.colorpicker-horizontal .colorpicker-alpha{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAAAKCAQAAADoFTP1AAAB9ElEQVR4XoWTQW4VMRBEu9qWEimL7DhEMp8NF+ASnJJLcAQgE1bcgBUSkYKUuHCrZ9pjeqSU5Yn9LPu7umJQBIIv+k7vIOrtK66L4lmr3pVOrOv3otp619KZ0/KjdNI79L52Uo09FBQWrU0vfe5trezU+hLsoUKd3Repovte+0vbq/7Lj5XbaHECKasR9G4MPlbp+gzZxd6koPEJCkAYC5SjcOTAIIOK90Dja1IfIZ8Z+zAY9jm3b5Ia+MT5sFcqRJrR2AYYA8Kua5BzYRrFPNmD4PQMegGJMOffJJUsWiI3nCHZZjInNdffLWOufzbc3JaboCAVxwmnRHbhLSPwRJ4wU0BRSc6HkECYYVw95nMKgJOcylxrJttE5Ibzf9Xq9GPvP+WX3MiV/MGHfRu/SentRQrfG1GzsIrytdNXucSRKxQNIGHM9YhGFQJcdjNcBZvfJayuYe4Sia1CzwW+19mWOhe37HsxJWKwbu/jluEU15QzAQjAqCEbhMJc78GYV2E0kooHDubUImWkTOhGpgv8PoT8DJG/bzxna4BZ0eOFSOaLADGeSpFsg5AzeaDZIDQQXjZ4y/8ryfzUXBwdELRjTjCNvOeT0rNlrJz90vwy6N9pXXQEluX0inElpPWokSdiLCfiNJJjMKQ8Qsh8GEKQKMo/eiHrNbI9UksAAAAASUVORK5CYII=)}.colorpicker-right:before{left:auto;right:6px}.colorpicker-right:after{left:auto;right:7px}.colorpicker-no-arrow:before{border-right:0;border-left:0}.colorpicker-no-arrow:after{border-right:0;border-left:0}.colorpicker-alpha.colorpicker-visible,.colorpicker-hue.colorpicker-visible,.colorpicker-saturation.colorpicker-visible,.colorpicker-selectors.colorpicker-visible,.colorpicker.colorpicker-visible{display:block}.colorpicker-alpha.colorpicker-hidden,.colorpicker-hue.colorpicker-hidden,.colorpicker-saturation.colorpicker-hidden,.colorpicker-selectors.colorpicker-hidden,.colorpicker.colorpicker-hidden{display:none}.colorpicker-inline.colorpicker-visible{display:inline-block}
+/*# sourceMappingURL=bootstrap-colorpicker.min.css.map */
\ No newline at end of file
diff --git a/odex25_project/web_widget_colorpicker/static/src/lib/bootstrap-colorpicker/css/bootstrap-colorpicker.min.css.map b/odex25_project/web_widget_colorpicker/static/src/lib/bootstrap-colorpicker/css/bootstrap-colorpicker.min.css.map
new file mode 100644
index 000000000..82c3ed06a
--- /dev/null
+++ b/odex25_project/web_widget_colorpicker/static/src/lib/bootstrap-colorpicker/css/bootstrap-colorpicker.min.css.map
@@ -0,0 +1 @@
+{"version":3,"sources":["src/less/colorpicker.less"],"names":[],"mappings":";;;;;;;;AAoBA,wBACE,MAAA,MACA,OAAA,MAXA,iBAAsB,g7KAatB,OAAA,UACA,MAAA,KACA,0BACE,QAAA,MACA,OAAA,IACA,MAAA,IACA,OAAA,IAAA,MAAA,KAfF,sBAAA,IACA,mBAAA,IACA,cAAA,IAeE,SAAA,SACA,IAAA,EACA,KAAA,EACA,OAAA,KAAA,EAAA,EAAA,KACA,4BACE,QAAA,MACA,OAAA,IACA,MAAA,IACA,OAAA,IAAA,MAAA,KAzBJ,sBAAA,IACA,mBAAA,IACA,cAAA,IA8BF,mBADA,iBAEE,MAAA,KACA,OAAA,MACA,MAAA,KACA,OAAA,WACA,YAAA,IACA,cAAA,IAIiB,qBADF,mBAEf,QAAA,MACA,OAAA,IACA,WAAA,KACA,WAAA,IAAA,MAAA,KACA,SAAA,SACA,IAAA,EACA,KAAA,EACA,MAAA,KACA,WAAA,KAGF,iBA1DE,iBAAsB,4rBA8DxB,mBA9DE,iBAAsB,wqBAgEtB,QAAA,KAKF,mBADA,iBADA,wBAGE,gBAAA,QAGF,aACE,QAAA,IACA,UAAA,MACA,WAAA,IAxEA,sBAAA,IACA,mBAAA,IACA,cAAA,IAwEA,QAAA,KAIU,mBADA,oBAEV,QAAA,MACA,QAAA,GACA,YAAA,EAGU,mBACV,MAAA,KAGU,oBACV,QAAA,GACA,QAAA,aACA,YAAA,IAAA,MAAA,YACA,aAAA,IAAA,MAAA,YACA,cAAA,IAAA,MAAA,KACA,oBAAA,eACA,SAAA,SACA,IAAA,KACA,KAAA,IAGU,mBACV,QAAA,GACA,QAAA,aACA,YAAA,IAAA,MAAA,YACA,aAAA,IAAA,MAAA,YACA,cAAA,IAAA,MAAA,KACA,SAAA,SACA,IAAA,KACA,KAAA,IAGW,iBACX,SAAA,SAGU,oCACV,UAAA,MAGkC,uDAClC,QAAA,MAGF,mBACE,OAAA,KACA,WAAA,IACA,MAAA,KAlIA,iBAAsB,wqBAoItB,oBAAA,EAAA,KAGiB,uBACjB,OAAA,KAGF,uBACE,QAAA,KACA,OAAA,KACA,WAAA,IACA,MAAA,KAGqB,yBACrB,OAAA,QACA,MAAA,KACA,OAAA,KACA,MAAA,KAGuB,2BACvB,YAAA,IAI2B,+BADW,0CAEtC,QAAA,aACA,OAAA,QACA,OAAA,KACA,eAAA,SACA,MAAA,KAGU,gCACV,SAAA,SACA,QAAA,aACA,MAAA,KACA,QAAA,KAGU,oCACV,MAAA,MACA,UAAA,MACA,OAAA,KAGkC,4DAClC,cAAA,IAGkC,uDAClC,MAAA,MAIkC,uDADA,qDAElC,MAAA,MACA,OAAA,KACA,MAAA,KACA,OAAA,WACA,YAAA,EACA,cAAA,IAIqD,yDADF,uDAEnD,QAAA,MACA,OAAA,KACA,WAAA,KACA,SAAA,SACA,IAAA,EACA,KAAA,EACA,MAAA,IACA,OAAA,KACA,WAAA,EAGkC,qDAlNlC,iBAAsB,4pBAsNY,uDAtNlC,iBAAsB,owBA0NN,0BAChB,KAAA,KACA,MAAA,IAGgB,yBAChB,KAAA,KACA,MAAA,IAGmB,6BACnB,aAAA,EACA,YAAA,EAGmB,4BACnB,aAAA,EACA,YAAA,EAQC,uCAAA,qCAAA,4CAAA,2CAAA,iCACC,QAAA,MASD,sCAAA,oCAAA,2CAAA,0CAAA,gCACC,QAAA,KAIe,wCACjB,QAAA"}
\ No newline at end of file
diff --git a/odex25_project/web_widget_colorpicker/static/src/lib/bootstrap-colorpicker/img/bootstrap-colorpicker/alpha-horizontal.png b/odex25_project/web_widget_colorpicker/static/src/lib/bootstrap-colorpicker/img/bootstrap-colorpicker/alpha-horizontal.png
new file mode 100644
index 000000000..f83188951
Binary files /dev/null and b/odex25_project/web_widget_colorpicker/static/src/lib/bootstrap-colorpicker/img/bootstrap-colorpicker/alpha-horizontal.png differ
diff --git a/odex25_project/web_widget_colorpicker/static/src/lib/bootstrap-colorpicker/img/bootstrap-colorpicker/alpha.png b/odex25_project/web_widget_colorpicker/static/src/lib/bootstrap-colorpicker/img/bootstrap-colorpicker/alpha.png
new file mode 100644
index 000000000..2e53a30e7
Binary files /dev/null and b/odex25_project/web_widget_colorpicker/static/src/lib/bootstrap-colorpicker/img/bootstrap-colorpicker/alpha.png differ
diff --git a/odex25_project/web_widget_colorpicker/static/src/lib/bootstrap-colorpicker/img/bootstrap-colorpicker/hue-horizontal.png b/odex25_project/web_widget_colorpicker/static/src/lib/bootstrap-colorpicker/img/bootstrap-colorpicker/hue-horizontal.png
new file mode 100644
index 000000000..3dcd5946a
Binary files /dev/null and b/odex25_project/web_widget_colorpicker/static/src/lib/bootstrap-colorpicker/img/bootstrap-colorpicker/hue-horizontal.png differ
diff --git a/odex25_project/web_widget_colorpicker/static/src/lib/bootstrap-colorpicker/img/bootstrap-colorpicker/hue.png b/odex25_project/web_widget_colorpicker/static/src/lib/bootstrap-colorpicker/img/bootstrap-colorpicker/hue.png
new file mode 100644
index 000000000..6f5ec2e50
Binary files /dev/null and b/odex25_project/web_widget_colorpicker/static/src/lib/bootstrap-colorpicker/img/bootstrap-colorpicker/hue.png differ
diff --git a/odex25_project/web_widget_colorpicker/static/src/lib/bootstrap-colorpicker/img/bootstrap-colorpicker/saturation.png b/odex25_project/web_widget_colorpicker/static/src/lib/bootstrap-colorpicker/img/bootstrap-colorpicker/saturation.png
new file mode 100644
index 000000000..170841cba
Binary files /dev/null and b/odex25_project/web_widget_colorpicker/static/src/lib/bootstrap-colorpicker/img/bootstrap-colorpicker/saturation.png differ
diff --git a/odex25_project/web_widget_colorpicker/static/src/lib/bootstrap-colorpicker/js/bootstrap-colorpicker.js b/odex25_project/web_widget_colorpicker/static/src/lib/bootstrap-colorpicker/js/bootstrap-colorpicker.js
new file mode 100644
index 000000000..b2cdf560c
--- /dev/null
+++ b/odex25_project/web_widget_colorpicker/static/src/lib/bootstrap-colorpicker/js/bootstrap-colorpicker.js
@@ -0,0 +1,1325 @@
+/*!
+ * Bootstrap Colorpicker v2.5.1
+ * https://itsjavi.com/bootstrap-colorpicker/
+ *
+ * Originally written by (c) 2012 Stefan Petre
+ * Licensed under the Apache License v2.0
+ * http://www.apache.org/licenses/LICENSE-2.0.txt
+ *
+ */
+
+(function(root, factory) {
+ if (typeof define === 'function' && define.amd) {
+ // AMD. Register as an anonymous module unless amdModuleId is set
+ define(["jquery"], function(jq) {
+ return (factory(jq));
+ });
+ } else if (typeof exports === 'object') {
+ // Node. Does not work with strict CommonJS, but
+ // only CommonJS-like environments that support module.exports,
+ // like Node.
+ module.exports = factory(require("jquery"));
+ } else if (jQuery && !jQuery.fn.colorpicker) {
+ factory(jQuery);
+ }
+}(this, function($) {
+ 'use strict';
+ /**
+ * Color manipulation helper class
+ *
+ * @param {Object|String} [val]
+ * @param {Object} [predefinedColors]
+ * @param {String|null} [fallbackColor]
+ * @param {String|null} [fallbackFormat]
+ * @param {Boolean} [hexNumberSignPrefix]
+ * @constructor
+ */
+ var Color = function(
+ val, predefinedColors, fallbackColor, fallbackFormat, hexNumberSignPrefix) {
+ this.fallbackValue = fallbackColor ?
+ (
+ fallbackColor && (typeof fallbackColor.h !== 'undefined') ?
+ fallbackColor :
+ this.value = {
+ h: 0,
+ s: 0,
+ b: 0,
+ a: 1
+ }
+ ) :
+ null;
+
+ this.fallbackFormat = fallbackFormat ? fallbackFormat : 'rgba';
+
+ this.hexNumberSignPrefix = hexNumberSignPrefix === true;
+
+ this.value = this.fallbackValue;
+
+ this.origFormat = null; // original string format
+
+ this.predefinedColors = predefinedColors ? predefinedColors : {};
+
+ // We don't want to share aliases across instances so we extend new object
+ this.colors = $.extend({}, Color.webColors, this.predefinedColors);
+
+ if (val) {
+ if (typeof val.h !== 'undefined') {
+ this.value = val;
+ } else {
+ this.setColor(String(val));
+ }
+ }
+
+ if (!this.value) {
+ // Initial value is always black if no arguments are passed or val is empty
+ this.value = {
+ h: 0,
+ s: 0,
+ b: 0,
+ a: 1
+ };
+ }
+ };
+
+ Color.webColors = { // 140 predefined colors from the HTML Colors spec
+ "aliceblue": "f0f8ff",
+ "antiquewhite": "faebd7",
+ "aqua": "00ffff",
+ "aquamarine": "7fffd4",
+ "azure": "f0ffff",
+ "beige": "f5f5dc",
+ "bisque": "ffe4c4",
+ "black": "000000",
+ "blanchedalmond": "ffebcd",
+ "blue": "0000ff",
+ "blueviolet": "8a2be2",
+ "brown": "a52a2a",
+ "burlywood": "deb887",
+ "cadetblue": "5f9ea0",
+ "chartreuse": "7fff00",
+ "chocolate": "d2691e",
+ "coral": "ff7f50",
+ "cornflowerblue": "6495ed",
+ "cornsilk": "fff8dc",
+ "crimson": "dc143c",
+ "cyan": "00ffff",
+ "darkblue": "00008b",
+ "darkcyan": "008b8b",
+ "darkgoldenrod": "b8860b",
+ "darkgray": "a9a9a9",
+ "darkgreen": "006400",
+ "darkkhaki": "bdb76b",
+ "darkmagenta": "8b008b",
+ "darkolivegreen": "556b2f",
+ "darkorange": "ff8c00",
+ "darkorchid": "9932cc",
+ "darkred": "8b0000",
+ "darksalmon": "e9967a",
+ "darkseagreen": "8fbc8f",
+ "darkslateblue": "483d8b",
+ "darkslategray": "2f4f4f",
+ "darkturquoise": "00ced1",
+ "darkviolet": "9400d3",
+ "deeppink": "ff1493",
+ "deepskyblue": "00bfff",
+ "dimgray": "696969",
+ "dodgerblue": "1e90ff",
+ "firebrick": "b22222",
+ "floralwhite": "fffaf0",
+ "forestgreen": "228b22",
+ "fuchsia": "ff00ff",
+ "gainsboro": "dcdcdc",
+ "ghostwhite": "f8f8ff",
+ "gold": "ffd700",
+ "goldenrod": "daa520",
+ "gray": "808080",
+ "green": "008000",
+ "greenyellow": "adff2f",
+ "honeydew": "f0fff0",
+ "hotpink": "ff69b4",
+ "indianred": "cd5c5c",
+ "indigo": "4b0082",
+ "ivory": "fffff0",
+ "khaki": "f0e68c",
+ "lavender": "e6e6fa",
+ "lavenderblush": "fff0f5",
+ "lawngreen": "7cfc00",
+ "lemonchiffon": "fffacd",
+ "lightblue": "add8e6",
+ "lightcoral": "f08080",
+ "lightcyan": "e0ffff",
+ "lightgoldenrodyellow": "fafad2",
+ "lightgrey": "d3d3d3",
+ "lightgreen": "90ee90",
+ "lightpink": "ffb6c1",
+ "lightsalmon": "ffa07a",
+ "lightseagreen": "20b2aa",
+ "lightskyblue": "87cefa",
+ "lightslategray": "778899",
+ "lightsteelblue": "b0c4de",
+ "lightyellow": "ffffe0",
+ "lime": "00ff00",
+ "limegreen": "32cd32",
+ "linen": "faf0e6",
+ "magenta": "ff00ff",
+ "maroon": "800000",
+ "mediumaquamarine": "66cdaa",
+ "mediumblue": "0000cd",
+ "mediumorchid": "ba55d3",
+ "mediumpurple": "9370d8",
+ "mediumseagreen": "3cb371",
+ "mediumslateblue": "7b68ee",
+ "mediumspringgreen": "00fa9a",
+ "mediumturquoise": "48d1cc",
+ "mediumvioletred": "c71585",
+ "midnightblue": "191970",
+ "mintcream": "f5fffa",
+ "mistyrose": "ffe4e1",
+ "moccasin": "ffe4b5",
+ "navajowhite": "ffdead",
+ "navy": "000080",
+ "oldlace": "fdf5e6",
+ "olive": "808000",
+ "olivedrab": "6b8e23",
+ "orange": "ffa500",
+ "orangered": "ff4500",
+ "orchid": "da70d6",
+ "palegoldenrod": "eee8aa",
+ "palegreen": "98fb98",
+ "paleturquoise": "afeeee",
+ "palevioletred": "d87093",
+ "papayawhip": "ffefd5",
+ "peachpuff": "ffdab9",
+ "peru": "cd853f",
+ "pink": "ffc0cb",
+ "plum": "dda0dd",
+ "powderblue": "b0e0e6",
+ "purple": "800080",
+ "red": "ff0000",
+ "rosybrown": "bc8f8f",
+ "royalblue": "4169e1",
+ "saddlebrown": "8b4513",
+ "salmon": "fa8072",
+ "sandybrown": "f4a460",
+ "seagreen": "2e8b57",
+ "seashell": "fff5ee",
+ "sienna": "a0522d",
+ "silver": "c0c0c0",
+ "skyblue": "87ceeb",
+ "slateblue": "6a5acd",
+ "slategray": "708090",
+ "snow": "fffafa",
+ "springgreen": "00ff7f",
+ "steelblue": "4682b4",
+ "tan": "d2b48c",
+ "teal": "008080",
+ "thistle": "d8bfd8",
+ "tomato": "ff6347",
+ "turquoise": "40e0d0",
+ "violet": "ee82ee",
+ "wheat": "f5deb3",
+ "white": "ffffff",
+ "whitesmoke": "f5f5f5",
+ "yellow": "ffff00",
+ "yellowgreen": "9acd32",
+ "transparent": "transparent"
+ };
+
+ Color.prototype = {
+ constructor: Color,
+ colors: {}, // merged web and predefined colors
+ predefinedColors: {},
+ /**
+ * @return {Object}
+ */
+ getValue: function() {
+ return this.value;
+ },
+ /**
+ * @param {Object} val
+ */
+ setValue: function(val) {
+ this.value = val;
+ },
+ _sanitizeNumber: function(val) {
+ if (typeof val === 'number') {
+ return val;
+ }
+ if (isNaN(val) || (val === null) || (val === '') || (val === undefined)) {
+ return 1;
+ }
+ if (val === '') {
+ return 0;
+ }
+ if (typeof val.toLowerCase !== 'undefined') {
+ if (val.match(/^\./)) {
+ val = "0" + val;
+ }
+ return Math.ceil(parseFloat(val) * 100) / 100;
+ }
+ return 1;
+ },
+ isTransparent: function(strVal) {
+ if (!strVal || !(typeof strVal === 'string' || strVal instanceof String)) {
+ return false;
+ }
+ strVal = strVal.toLowerCase().trim();
+ return (strVal === 'transparent') || (strVal.match(/#?00000000/)) || (strVal.match(/(rgba|hsla)\(0,0,0,0?\.?0\)/));
+ },
+ rgbaIsTransparent: function(rgba) {
+ return ((rgba.r === 0) && (rgba.g === 0) && (rgba.b === 0) && (rgba.a === 0));
+ },
+ // parse a string to HSB
+ /**
+ * @protected
+ * @param {String} strVal
+ * @returns {boolean} Returns true if it could be parsed, false otherwise
+ */
+ setColor: function(strVal) {
+ strVal = strVal.toLowerCase().trim();
+ if (strVal) {
+ if (this.isTransparent(strVal)) {
+ this.value = {
+ h: 0,
+ s: 0,
+ b: 0,
+ a: 0
+ };
+ return true;
+ } else {
+ var parsedColor = this.parse(strVal);
+ if (parsedColor) {
+ this.value = this.value = {
+ h: parsedColor.h,
+ s: parsedColor.s,
+ b: parsedColor.b,
+ a: parsedColor.a
+ };
+ if (!this.origFormat) {
+ this.origFormat = parsedColor.format;
+ }
+ } else if (this.fallbackValue) {
+ // if parser fails, defaults to fallbackValue if defined, otherwise the value won't be changed
+ this.value = this.fallbackValue;
+ }
+ }
+ }
+ return false;
+ },
+ setHue: function(h) {
+ this.value.h = 1 - h;
+ },
+ setSaturation: function(s) {
+ this.value.s = s;
+ },
+ setBrightness: function(b) {
+ this.value.b = 1 - b;
+ },
+ setAlpha: function(a) {
+ this.value.a = Math.round((parseInt((1 - a) * 100, 10) / 100) * 100) / 100;
+ },
+ toRGB: function(h, s, b, a) {
+ if (arguments.length === 0) {
+ h = this.value.h;
+ s = this.value.s;
+ b = this.value.b;
+ a = this.value.a;
+ }
+
+ h *= 360;
+ var R, G, B, X, C;
+ h = (h % 360) / 60;
+ C = b * s;
+ X = C * (1 - Math.abs(h % 2 - 1));
+ R = G = B = b - C;
+
+ h = ~~h;
+ R += [C, X, 0, 0, X, C][h];
+ G += [X, C, C, X, 0, 0][h];
+ B += [0, 0, X, C, C, X][h];
+
+ return {
+ r: Math.round(R * 255),
+ g: Math.round(G * 255),
+ b: Math.round(B * 255),
+ a: a
+ };
+ },
+ toHex: function(ignoreFormat, h, s, b, a) {
+ if (arguments.length <= 1) {
+ h = this.value.h;
+ s = this.value.s;
+ b = this.value.b;
+ a = this.value.a;
+ }
+
+ var prefix = '#';
+ var rgb = this.toRGB(h, s, b, a);
+
+ if (this.rgbaIsTransparent(rgb)) {
+ return 'transparent';
+ }
+
+ if (!ignoreFormat) {
+ prefix = (this.hexNumberSignPrefix ? '#' : '');
+ }
+
+ var hexStr = prefix + (
+ (1 << 24) +
+ (parseInt(rgb.r) << 16) +
+ (parseInt(rgb.g) << 8) +
+ parseInt(rgb.b))
+ .toString(16)
+ .slice(1);
+
+ return hexStr;
+ },
+ toHSL: function(h, s, b, a) {
+ if (arguments.length === 0) {
+ h = this.value.h;
+ s = this.value.s;
+ b = this.value.b;
+ a = this.value.a;
+ }
+
+ var H = h,
+ L = (2 - s) * b,
+ S = s * b;
+ if (L > 0 && L <= 1) {
+ S /= L;
+ } else {
+ S /= 2 - L;
+ }
+ L /= 2;
+ if (S > 1) {
+ S = 1;
+ }
+ return {
+ h: isNaN(H) ? 0 : H,
+ s: isNaN(S) ? 0 : S,
+ l: isNaN(L) ? 0 : L,
+ a: isNaN(a) ? 0 : a
+ };
+ },
+ toAlias: function(r, g, b, a) {
+ var c, rgb = (arguments.length === 0) ? this.toHex(true) : this.toHex(true, r, g, b, a);
+
+ // support predef. colors in non-hex format too, as defined in the alias itself
+ var original = this.origFormat === 'alias' ? rgb : this.toString(false, this.origFormat);
+
+ for (var alias in this.colors) {
+ c = this.colors[alias].toLowerCase().trim();
+ if ((c === rgb) || (c === original)) {
+ return alias;
+ }
+ }
+ return false;
+ },
+ RGBtoHSB: function(r, g, b, a) {
+ r /= 255;
+ g /= 255;
+ b /= 255;
+
+ var H, S, V, C;
+ V = Math.max(r, g, b);
+ C = V - Math.min(r, g, b);
+ H = (C === 0 ? null :
+ V === r ? (g - b) / C :
+ V === g ? (b - r) / C + 2 :
+ (r - g) / C + 4
+ );
+ H = ((H + 360) % 6) * 60 / 360;
+ S = C === 0 ? 0 : C / V;
+ return {
+ h: this._sanitizeNumber(H),
+ s: S,
+ b: V,
+ a: this._sanitizeNumber(a)
+ };
+ },
+ HueToRGB: function(p, q, h) {
+ if (h < 0) {
+ h += 1;
+ } else if (h > 1) {
+ h -= 1;
+ }
+ if ((h * 6) < 1) {
+ return p + (q - p) * h * 6;
+ } else if ((h * 2) < 1) {
+ return q;
+ } else if ((h * 3) < 2) {
+ return p + (q - p) * ((2 / 3) - h) * 6;
+ } else {
+ return p;
+ }
+ },
+ HSLtoRGB: function(h, s, l, a) {
+ if (s < 0) {
+ s = 0;
+ }
+ var q;
+ if (l <= 0.5) {
+ q = l * (1 + s);
+ } else {
+ q = l + s - (l * s);
+ }
+
+ var p = 2 * l - q;
+
+ var tr = h + (1 / 3);
+ var tg = h;
+ var tb = h - (1 / 3);
+
+ var r = Math.round(this.HueToRGB(p, q, tr) * 255);
+ var g = Math.round(this.HueToRGB(p, q, tg) * 255);
+ var b = Math.round(this.HueToRGB(p, q, tb) * 255);
+ return [r, g, b, this._sanitizeNumber(a)];
+ },
+ /**
+ * @param {String} strVal
+ * @returns {Object} Object containing h,s,b,a,format properties or FALSE if failed to parse
+ */
+ parse: function(strVal) {
+ if (arguments.length === 0) {
+ return false;
+ }
+
+ var that = this,
+ result = false,
+ isAlias = (typeof this.colors[strVal] !== 'undefined'),
+ values, format;
+
+ if (isAlias) {
+ strVal = this.colors[strVal].toLowerCase().trim();
+ }
+
+ $.each(this.stringParsers, function(i, parser) {
+ var match = parser.re.exec(strVal);
+ values = match && parser.parse.apply(that, [match]);
+ if (values) {
+ result = {};
+ format = (isAlias ? 'alias' : (parser.format ? parser.format : that.getValidFallbackFormat()));
+ if (format.match(/hsla?/)) {
+ result = that.RGBtoHSB.apply(that, that.HSLtoRGB.apply(that, values));
+ } else {
+ result = that.RGBtoHSB.apply(that, values);
+ }
+ if (result instanceof Object) {
+ result.format = format;
+ }
+ return false; // stop iterating
+ }
+ return true;
+ });
+ return result;
+ },
+ getValidFallbackFormat: function() {
+ var formats = [
+ 'rgba', 'rgb', 'hex', 'hsla', 'hsl'
+ ];
+ if (this.origFormat && (formats.indexOf(this.origFormat) !== -1)) {
+ return this.origFormat;
+ }
+ if (this.fallbackFormat && (formats.indexOf(this.fallbackFormat) !== -1)) {
+ return this.fallbackFormat;
+ }
+
+ return 'rgba'; // By default, return a format that will not lose the alpha info
+ },
+ /**
+ *
+ * @param {string} [format] (default: rgba)
+ * @param {boolean} [translateAlias] Return real color for pre-defined (non-standard) aliases (default: false)
+ * @param {boolean} [forceRawValue] Forces hashtag prefix when getting hex color (default: false)
+ * @returns {String}
+ */
+ toString: function(forceRawValue, format, translateAlias) {
+ format = format || this.origFormat || this.fallbackFormat;
+ translateAlias = translateAlias || false;
+
+ var c = false;
+
+ switch (format) {
+ case 'rgb':
+ {
+ c = this.toRGB();
+ if (this.rgbaIsTransparent(c)) {
+ return 'transparent';
+ }
+ return 'rgb(' + c.r + ',' + c.g + ',' + c.b + ')';
+ }
+ break;
+ case 'rgba':
+ {
+ c = this.toRGB();
+ return 'rgba(' + c.r + ',' + c.g + ',' + c.b + ',' + c.a + ')';
+ }
+ break;
+ case 'hsl':
+ {
+ c = this.toHSL();
+ return 'hsl(' + Math.round(c.h * 360) + ',' + Math.round(c.s * 100) + '%,' + Math.round(c.l * 100) + '%)';
+ }
+ break;
+ case 'hsla':
+ {
+ c = this.toHSL();
+ return 'hsla(' + Math.round(c.h * 360) + ',' + Math.round(c.s * 100) + '%,' + Math.round(c.l * 100) + '%,' + c.a + ')';
+ }
+ break;
+ case 'hex':
+ {
+ return this.toHex(forceRawValue);
+ }
+ break;
+ case 'alias':
+ {
+ c = this.toAlias();
+
+ if (c === false) {
+ return this.toString(forceRawValue, this.getValidFallbackFormat());
+ }
+
+ if (translateAlias && !(c in Color.webColors) && (c in this.predefinedColors)) {
+ return this.predefinedColors[c];
+ }
+
+ return c;
+ }
+ default:
+ {
+ return c;
+ }
+ break;
+ }
+ },
+ // a set of RE's that can match strings and generate color tuples.
+ // from John Resig color plugin
+ // https://github.com/jquery/jquery-color/
+ stringParsers: [{
+ re: /rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*?\)/,
+ format: 'rgb',
+ parse: function(execResult) {
+ return [
+ execResult[1],
+ execResult[2],
+ execResult[3],
+ 1
+ ];
+ }
+ }, {
+ re: /rgb\(\s*(\d*(?:\.\d+)?)\%\s*,\s*(\d*(?:\.\d+)?)\%\s*,\s*(\d*(?:\.\d+)?)\%\s*?\)/,
+ format: 'rgb',
+ parse: function(execResult) {
+ return [
+ 2.55 * execResult[1],
+ 2.55 * execResult[2],
+ 2.55 * execResult[3],
+ 1
+ ];
+ }
+ }, {
+ re: /rgba\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d*(?:\.\d+)?)\s*)?\)/,
+ format: 'rgba',
+ parse: function(execResult) {
+ return [
+ execResult[1],
+ execResult[2],
+ execResult[3],
+ execResult[4]
+ ];
+ }
+ }, {
+ re: /rgba\(\s*(\d*(?:\.\d+)?)\%\s*,\s*(\d*(?:\.\d+)?)\%\s*,\s*(\d*(?:\.\d+)?)\%\s*(?:,\s*(\d*(?:\.\d+)?)\s*)?\)/,
+ format: 'rgba',
+ parse: function(execResult) {
+ return [
+ 2.55 * execResult[1],
+ 2.55 * execResult[2],
+ 2.55 * execResult[3],
+ execResult[4]
+ ];
+ }
+ }, {
+ re: /hsl\(\s*(\d*(?:\.\d+)?)\s*,\s*(\d*(?:\.\d+)?)\%\s*,\s*(\d*(?:\.\d+)?)\%\s*?\)/,
+ format: 'hsl',
+ parse: function(execResult) {
+ return [
+ execResult[1] / 360,
+ execResult[2] / 100,
+ execResult[3] / 100,
+ execResult[4]
+ ];
+ }
+ }, {
+ re: /hsla\(\s*(\d*(?:\.\d+)?)\s*,\s*(\d*(?:\.\d+)?)\%\s*,\s*(\d*(?:\.\d+)?)\%\s*(?:,\s*(\d*(?:\.\d+)?)\s*)?\)/,
+ format: 'hsla',
+ parse: function(execResult) {
+ return [
+ execResult[1] / 360,
+ execResult[2] / 100,
+ execResult[3] / 100,
+ execResult[4]
+ ];
+ }
+ }, {
+ re: /#?([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/,
+ format: 'hex',
+ parse: function(execResult) {
+ return [
+ parseInt(execResult[1], 16),
+ parseInt(execResult[2], 16),
+ parseInt(execResult[3], 16),
+ 1
+ ];
+ }
+ }, {
+ re: /#?([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/,
+ format: 'hex',
+ parse: function(execResult) {
+ return [
+ parseInt(execResult[1] + execResult[1], 16),
+ parseInt(execResult[2] + execResult[2], 16),
+ parseInt(execResult[3] + execResult[3], 16),
+ 1
+ ];
+ }
+ }],
+ colorNameToHex: function(name) {
+ if (typeof this.colors[name.toLowerCase()] !== 'undefined') {
+ return this.colors[name.toLowerCase()];
+ }
+ return false;
+ }
+ };
+
+ /*
+ * Default plugin options
+ */
+ var defaults = {
+ horizontal: false, // horizontal mode layout ?
+ inline: false, //forces to show the colorpicker as an inline element
+ color: false, //forces a color
+ format: false, //forces a format
+ input: 'input', // children input selector
+ container: false, // container selector
+ component: '.add-on, .input-group-addon', // children component selector
+ fallbackColor: false, // fallback color value. null = keeps current color.
+ fallbackFormat: 'hex', // fallback color format
+ hexNumberSignPrefix: true, // put a '#' (number sign) before hex strings
+ sliders: {
+ saturation: {
+ maxLeft: 100,
+ maxTop: 100,
+ callLeft: 'setSaturation',
+ callTop: 'setBrightness'
+ },
+ hue: {
+ maxLeft: 0,
+ maxTop: 100,
+ callLeft: false,
+ callTop: 'setHue'
+ },
+ alpha: {
+ maxLeft: 0,
+ maxTop: 100,
+ callLeft: false,
+ callTop: 'setAlpha'
+ }
+ },
+ slidersHorz: {
+ saturation: {
+ maxLeft: 100,
+ maxTop: 100,
+ callLeft: 'setSaturation',
+ callTop: 'setBrightness'
+ },
+ hue: {
+ maxLeft: 100,
+ maxTop: 0,
+ callLeft: 'setHue',
+ callTop: false
+ },
+ alpha: {
+ maxLeft: 100,
+ maxTop: 0,
+ callLeft: 'setAlpha',
+ callTop: false
+ }
+ },
+ template: '',
+ align: 'right',
+ customClass: null, // custom class added to the colorpicker element
+ colorSelectors: null // custom color aliases
+ };
+
+ /**
+ * Colorpicker component class
+ *
+ * @param {Object|String} element
+ * @param {Object} options
+ * @constructor
+ */
+ var Colorpicker = function(element, options) {
+ this.element = $(element).addClass('colorpicker-element');
+ this.options = $.extend(true, {}, defaults, this.element.data(), options);
+ this.component = this.options.component;
+ this.component = (this.component !== false) ? this.element.find(this.component) : false;
+ if (this.component && (this.component.length === 0)) {
+ this.component = false;
+ }
+ this.container = (this.options.container === true) ? this.element : this.options.container;
+ this.container = (this.container !== false) ? $(this.container) : false;
+
+ // Is the element an input? Should we search inside for any input?
+ this.input = this.element.is('input') ? this.element : (this.options.input ?
+ this.element.find(this.options.input) : false);
+ if (this.input && (this.input.length === 0)) {
+ this.input = false;
+ }
+ // Set HSB color
+ this.color = this.createColor(this.options.color !== false ? this.options.color : this.getValue());
+
+ this.format = this.options.format !== false ? this.options.format : this.color.origFormat;
+
+ if (this.options.color !== false) {
+ this.updateInput(this.color);
+ this.updateData(this.color);
+ }
+
+ // Setup picker
+ var $picker = this.picker = $(this.options.template);
+ if (this.options.customClass) {
+ $picker.addClass(this.options.customClass);
+ }
+ if (this.options.inline) {
+ $picker.addClass('colorpicker-inline colorpicker-visible');
+ } else {
+ $picker.addClass('colorpicker-hidden');
+ }
+ if (this.options.horizontal) {
+ $picker.addClass('colorpicker-horizontal');
+ }
+ if (
+ (['rgba', 'hsla', 'alias'].indexOf(this.format) !== -1) ||
+ this.options.format === false ||
+ this.getValue() === 'transparent'
+ ) {
+ $picker.addClass('colorpicker-with-alpha');
+ }
+ if (this.options.align === 'right') {
+ $picker.addClass('colorpicker-right');
+ }
+ if (this.options.inline === true) {
+ $picker.addClass('colorpicker-no-arrow');
+ }
+ if (this.options.colorSelectors) {
+ var colorpicker = this,
+ selectorsContainer = colorpicker.picker.find('.colorpicker-selectors');
+
+ if (selectorsContainer.length > 0) {
+ $.each(this.options.colorSelectors, function(name, color) {
+ var $btn = $(' ')
+ .addClass('colorpicker-selectors-color')
+ .css('background-color', color)
+ .data('class', name).data('alias', name);
+
+ $btn.on('mousedown.colorpicker touchstart.colorpicker', function(event) {
+ event.preventDefault();
+ colorpicker.setValue(
+ colorpicker.format === 'alias' ? $(this).data('alias') : $(this).css('background-color')
+ );
+ });
+ selectorsContainer.append($btn);
+ });
+ selectorsContainer.show().addClass('colorpicker-visible');
+ }
+ }
+
+ // Prevent closing the colorpicker when clicking on itself
+ $picker.on('mousedown.colorpicker touchstart.colorpicker', $.proxy(function(e) {
+ if (e.target === e.currentTarget) {
+ e.preventDefault();
+ }
+ }, this));
+
+ // Bind click/tap events on the sliders
+ $picker.find('.colorpicker-saturation, .colorpicker-hue, .colorpicker-alpha')
+ .on('mousedown.colorpicker touchstart.colorpicker', $.proxy(this.mousedown, this));
+
+ $picker.appendTo(this.container ? this.container : $('body'));
+
+ // Bind other events
+ if (this.input !== false) {
+ this.input.on({
+ 'keyup.colorpicker': $.proxy(this.keyup, this)
+ });
+ this.input.on({
+ 'change.colorpicker': $.proxy(this.change, this)
+ });
+ if (this.component === false) {
+ this.element.on({
+ 'focus.colorpicker': $.proxy(this.show, this)
+ });
+ }
+ if (this.options.inline === false) {
+ this.element.on({
+ 'focusout.colorpicker': $.proxy(this.hide, this)
+ });
+ }
+ }
+
+ if (this.component !== false) {
+ this.component.on({
+ 'click.colorpicker': $.proxy(this.show, this)
+ });
+ }
+
+ if ((this.input === false) && (this.component === false)) {
+ this.element.on({
+ 'click.colorpicker': $.proxy(this.show, this)
+ });
+ }
+
+ // for HTML5 input[type='color']
+ if ((this.input !== false) && (this.component !== false) && (this.input.attr('type') === 'color')) {
+
+ this.input.on({
+ 'click.colorpicker': $.proxy(this.show, this),
+ 'focus.colorpicker': $.proxy(this.show, this)
+ });
+ }
+ this.update();
+
+ $($.proxy(function() {
+ this.element.trigger('create');
+ }, this));
+ };
+
+ Colorpicker.Color = Color;
+
+ Colorpicker.prototype = {
+ constructor: Colorpicker,
+ destroy: function() {
+ this.picker.remove();
+ this.element.removeData('colorpicker', 'color').off('.colorpicker');
+ if (this.input !== false) {
+ this.input.off('.colorpicker');
+ }
+ if (this.component !== false) {
+ this.component.off('.colorpicker');
+ }
+ this.element.removeClass('colorpicker-element');
+ this.element.trigger({
+ type: 'destroy'
+ });
+ },
+ reposition: function() {
+ if (this.options.inline !== false || this.options.container) {
+ return false;
+ }
+ var type = this.container && this.container[0] !== window.document.body ? 'position' : 'offset';
+ var element = this.component || this.element;
+ var offset = element[type]();
+ if (this.options.align === 'right') {
+ offset.left -= this.picker.outerWidth() - element.outerWidth();
+ }
+ this.picker.css({
+ top: offset.top + element.outerHeight(),
+ left: offset.left
+ });
+ },
+ show: function(e) {
+ if (this.isDisabled()) {
+ // Don't show the widget if it's disabled (the input)
+ return;
+ }
+ this.picker.addClass('colorpicker-visible').removeClass('colorpicker-hidden');
+ this.reposition();
+ $(window).on('resize.colorpicker', $.proxy(this.reposition, this));
+ if (e && (!this.hasInput() || this.input.attr('type') === 'color')) {
+ if (e.stopPropagation && e.preventDefault) {
+ e.stopPropagation();
+ e.preventDefault();
+ }
+ }
+ if ((this.component || !this.input) && (this.options.inline === false)) {
+ $(window.document).on({
+ 'mousedown.colorpicker': $.proxy(this.hide, this)
+ });
+ }
+ this.element.trigger({
+ type: 'showPicker',
+ color: this.color
+ });
+ },
+ hide: function(e) {
+ if ((typeof e !== 'undefined') && e.target) {
+ // Prevent hide if triggered by an event and an element inside the colorpicker has been clicked/touched
+ if (
+ $(e.currentTarget).parents('.colorpicker').length > 0 ||
+ $(e.target).parents('.colorpicker').length > 0
+ ) {
+ return false;
+ }
+ }
+ this.picker.addClass('colorpicker-hidden').removeClass('colorpicker-visible');
+ $(window).off('resize.colorpicker', this.reposition);
+ $(window.document).off({
+ 'mousedown.colorpicker': this.hide
+ });
+ this.update();
+ this.element.trigger({
+ type: 'hidePicker',
+ color: this.color
+ });
+ },
+ updateData: function(val) {
+ val = val || this.color.toString(false, this.format);
+ this.element.data('color', val);
+ return val;
+ },
+ updateInput: function(val) {
+ val = val || this.color.toString(false, this.format);
+ if (this.input !== false) {
+ this.input.prop('value', val);
+ this.input.trigger('change');
+ }
+ return val;
+ },
+ updatePicker: function(val) {
+ if (typeof val !== 'undefined') {
+ this.color = this.createColor(val);
+ }
+ var sl = (this.options.horizontal === false) ? this.options.sliders : this.options.slidersHorz;
+ var icns = this.picker.find('i');
+ if (icns.length === 0) {
+ return;
+ }
+ if (this.options.horizontal === false) {
+ sl = this.options.sliders;
+ icns.eq(1).css('top', sl.hue.maxTop * (1 - this.color.value.h)).end()
+ .eq(2).css('top', sl.alpha.maxTop * (1 - this.color.value.a));
+ } else {
+ sl = this.options.slidersHorz;
+ icns.eq(1).css('left', sl.hue.maxLeft * (1 - this.color.value.h)).end()
+ .eq(2).css('left', sl.alpha.maxLeft * (1 - this.color.value.a));
+ }
+ icns.eq(0).css({
+ 'top': sl.saturation.maxTop - this.color.value.b * sl.saturation.maxTop,
+ 'left': this.color.value.s * sl.saturation.maxLeft
+ });
+
+ this.picker.find('.colorpicker-saturation')
+ .css('backgroundColor', this.color.toHex(true, this.color.value.h, 1, 1, 1));
+
+ this.picker.find('.colorpicker-alpha')
+ .css('backgroundColor', this.color.toHex(true));
+
+ this.picker.find('.colorpicker-color, .colorpicker-color div')
+ .css('backgroundColor', this.color.toString(true, this.format));
+
+ return val;
+ },
+ updateComponent: function(val) {
+ var color;
+
+ if (typeof val !== 'undefined') {
+ color = this.createColor(val);
+ } else {
+ color = this.color;
+ }
+
+ if (this.component !== false) {
+ var icn = this.component.find('i').eq(0);
+ if (icn.length > 0) {
+ icn.css({
+ 'backgroundColor': color.toString(true, this.format)
+ });
+ } else {
+ this.component.css({
+ 'backgroundColor': color.toString(true, this.format)
+ });
+ }
+ }
+
+ return color.toString(false, this.format);
+ },
+ update: function(force) {
+ var val;
+ if ((this.getValue(false) !== false) || (force === true)) {
+ // Update input/data only if the current value is not empty
+ val = this.updateComponent();
+ this.updateInput(val);
+ this.updateData(val);
+ this.updatePicker(); // only update picker if value is not empty
+ }
+ return val;
+
+ },
+ setValue: function(val) { // set color manually
+ this.color = this.createColor(val);
+ this.update(true);
+ this.element.trigger({
+ type: 'changeColor',
+ color: this.color,
+ value: val
+ });
+ },
+ /**
+ * Creates a new color using the instance options
+ * @protected
+ * @param {String} val
+ * @returns {Color}
+ */
+ createColor: function(val) {
+ return new Color(
+ val ? val : null,
+ this.options.colorSelectors,
+ this.options.fallbackColor ? this.options.fallbackColor : this.color,
+ this.options.fallbackFormat,
+ this.options.hexNumberSignPrefix
+ );
+ },
+ getValue: function(defaultValue) {
+ defaultValue = (typeof defaultValue === 'undefined') ? this.options.fallbackColor : defaultValue;
+ var val;
+ if (this.hasInput()) {
+ val = this.input.val();
+ } else {
+ val = this.element.data('color');
+ }
+ if ((val === undefined) || (val === '') || (val === null)) {
+ // if not defined or empty, return default
+ val = defaultValue;
+ }
+ return val;
+ },
+ hasInput: function() {
+ return (this.input !== false);
+ },
+ isDisabled: function() {
+ if (this.hasInput()) {
+ return (this.input.prop('disabled') === true);
+ }
+ return false;
+ },
+ disable: function() {
+ if (this.hasInput()) {
+ this.input.prop('disabled', true);
+ this.element.trigger({
+ type: 'disable',
+ color: this.color,
+ value: this.getValue()
+ });
+ return true;
+ }
+ return false;
+ },
+ enable: function() {
+ if (this.hasInput()) {
+ this.input.prop('disabled', false);
+ this.element.trigger({
+ type: 'enable',
+ color: this.color,
+ value: this.getValue()
+ });
+ return true;
+ }
+ return false;
+ },
+ currentSlider: null,
+ mousePointer: {
+ left: 0,
+ top: 0
+ },
+ mousedown: function(e) {
+ if (!e.pageX && !e.pageY && e.originalEvent && e.originalEvent.touches) {
+ e.pageX = e.originalEvent.touches[0].pageX;
+ e.pageY = e.originalEvent.touches[0].pageY;
+ }
+ e.stopPropagation();
+ e.preventDefault();
+
+ var target = $(e.target);
+
+ //detect the slider and set the limits and callbacks
+ var zone = target.closest('div');
+ var sl = this.options.horizontal ? this.options.slidersHorz : this.options.sliders;
+ if (!zone.is('.colorpicker')) {
+ if (zone.is('.colorpicker-saturation')) {
+ this.currentSlider = $.extend({}, sl.saturation);
+ } else if (zone.is('.colorpicker-hue')) {
+ this.currentSlider = $.extend({}, sl.hue);
+ } else if (zone.is('.colorpicker-alpha')) {
+ this.currentSlider = $.extend({}, sl.alpha);
+ } else {
+ return false;
+ }
+ var offset = zone.offset();
+ //reference to guide's style
+ this.currentSlider.guide = zone.find('i')[0].style;
+ this.currentSlider.left = e.pageX - offset.left;
+ this.currentSlider.top = e.pageY - offset.top;
+ this.mousePointer = {
+ left: e.pageX,
+ top: e.pageY
+ };
+ //trigger mousemove to move the guide to the current position
+ $(window.document).on({
+ 'mousemove.colorpicker': $.proxy(this.mousemove, this),
+ 'touchmove.colorpicker': $.proxy(this.mousemove, this),
+ 'mouseup.colorpicker': $.proxy(this.mouseup, this),
+ 'touchend.colorpicker': $.proxy(this.mouseup, this)
+ }).trigger('mousemove');
+ }
+ return false;
+ },
+ mousemove: function(e) {
+ if (!e.pageX && !e.pageY && e.originalEvent && e.originalEvent.touches) {
+ e.pageX = e.originalEvent.touches[0].pageX;
+ e.pageY = e.originalEvent.touches[0].pageY;
+ }
+ e.stopPropagation();
+ e.preventDefault();
+ var left = Math.max(
+ 0,
+ Math.min(
+ this.currentSlider.maxLeft,
+ this.currentSlider.left + ((e.pageX || this.mousePointer.left) - this.mousePointer.left)
+ )
+ );
+ var top = Math.max(
+ 0,
+ Math.min(
+ this.currentSlider.maxTop,
+ this.currentSlider.top + ((e.pageY || this.mousePointer.top) - this.mousePointer.top)
+ )
+ );
+ this.currentSlider.guide.left = left + 'px';
+ this.currentSlider.guide.top = top + 'px';
+ if (this.currentSlider.callLeft) {
+ this.color[this.currentSlider.callLeft].call(this.color, left / this.currentSlider.maxLeft);
+ }
+ if (this.currentSlider.callTop) {
+ this.color[this.currentSlider.callTop].call(this.color, top / this.currentSlider.maxTop);
+ }
+ // Change format dynamically
+ // Only occurs if user choose the dynamic format by
+ // setting option format to false
+ if (
+ this.options.format === false &&
+ (this.currentSlider.callTop === 'setAlpha' ||
+ this.currentSlider.callLeft === 'setAlpha')
+ ) {
+
+ // Converting from hex / rgb to rgba
+ if (this.color.value.a !== 1) {
+ this.format = 'rgba';
+ this.color.origFormat = 'rgba';
+ }
+
+ // Converting from rgba to hex
+ else {
+ this.format = 'hex';
+ this.color.origFormat = 'hex';
+ }
+ }
+ this.update(true);
+
+ this.element.trigger({
+ type: 'changeColor',
+ color: this.color
+ });
+ return false;
+ },
+ mouseup: function(e) {
+ e.stopPropagation();
+ e.preventDefault();
+ $(window.document).off({
+ 'mousemove.colorpicker': this.mousemove,
+ 'touchmove.colorpicker': this.mousemove,
+ 'mouseup.colorpicker': this.mouseup,
+ 'touchend.colorpicker': this.mouseup
+ });
+ return false;
+ },
+ change: function(e) {
+ this.keyup(e);
+ },
+ keyup: function(e) {
+ if ((e.keyCode === 38)) {
+ if (this.color.value.a < 1) {
+ this.color.value.a = Math.round((this.color.value.a + 0.01) * 100) / 100;
+ }
+ this.update(true);
+ } else if ((e.keyCode === 40)) {
+ if (this.color.value.a > 0) {
+ this.color.value.a = Math.round((this.color.value.a - 0.01) * 100) / 100;
+ }
+ this.update(true);
+ } else {
+ this.color = this.createColor(this.input.val());
+ // Change format dynamically
+ // Only occurs if user choose the dynamic format by
+ // setting option format to false
+ if (this.color.origFormat && this.options.format === false) {
+ this.format = this.color.origFormat;
+ }
+ if (this.getValue(false) !== false) {
+ this.updateData();
+ this.updateComponent();
+ this.updatePicker();
+ }
+ }
+ this.element.trigger({
+ type: 'changeColor',
+ color: this.color,
+ value: this.input.val()
+ });
+ }
+ };
+
+ $.colorpicker = Colorpicker;
+
+ $.fn.colorpicker = function(option) {
+ var apiArgs = Array.prototype.slice.call(arguments, 1),
+ isSingleElement = (this.length === 1),
+ returnValue = null;
+
+ var $jq = this.each(function() {
+ var $this = $(this),
+ inst = $this.data('colorpicker'),
+ options = ((typeof option === 'object') ? option : {});
+
+ if (!inst) {
+ inst = new Colorpicker(this, options);
+ $this.data('colorpicker', inst);
+ }
+
+ if (typeof option === 'string') {
+ if ($.isFunction(inst[option])) {
+ returnValue = inst[option].apply(inst, apiArgs);
+ } else { // its a property ?
+ if (apiArgs.length) {
+ // set property
+ inst[option] = apiArgs[0];
+ }
+ returnValue = inst[option];
+ }
+ } else {
+ returnValue = $this;
+ }
+ });
+ return isSingleElement ? returnValue : $jq;
+ };
+
+ $.fn.colorpicker.constructor = Colorpicker;
+
+}));
diff --git a/odex25_project/web_widget_colorpicker/static/src/lib/bootstrap-colorpicker/js/bootstrap-colorpicker.min.js b/odex25_project/web_widget_colorpicker/static/src/lib/bootstrap-colorpicker/js/bootstrap-colorpicker.min.js
new file mode 100644
index 000000000..0271a46f1
--- /dev/null
+++ b/odex25_project/web_widget_colorpicker/static/src/lib/bootstrap-colorpicker/js/bootstrap-colorpicker.min.js
@@ -0,0 +1,5 @@
+/*!
+ * Bootstrap Colorpicker v2.5.1
+ * https://itsjavi.com/bootstrap-colorpicker/
+ */
+!function(a,b){"function"==typeof define&&define.amd?define(["jquery"],function(a){return b(a)}):"object"==typeof exports?module.exports=b(require("jquery")):jQuery&&!jQuery.fn.colorpicker&&b(jQuery)}(this,function(a){"use strict";var b=function(c,d,e,f,g){this.fallbackValue=e?e&&"undefined"!=typeof e.h?e:this.value={h:0,s:0,b:0,a:1}:null,this.fallbackFormat=f?f:"rgba",this.hexNumberSignPrefix=g===!0,this.value=this.fallbackValue,this.origFormat=null,this.predefinedColors=d?d:{},this.colors=a.extend({},b.webColors,this.predefinedColors),c&&("undefined"!=typeof c.h?this.value=c:this.setColor(String(c))),this.value||(this.value={h:0,s:0,b:0,a:1})};b.webColors={aliceblue:"f0f8ff",antiquewhite:"faebd7",aqua:"00ffff",aquamarine:"7fffd4",azure:"f0ffff",beige:"f5f5dc",bisque:"ffe4c4",black:"000000",blanchedalmond:"ffebcd",blue:"0000ff",blueviolet:"8a2be2",brown:"a52a2a",burlywood:"deb887",cadetblue:"5f9ea0",chartreuse:"7fff00",chocolate:"d2691e",coral:"ff7f50",cornflowerblue:"6495ed",cornsilk:"fff8dc",crimson:"dc143c",cyan:"00ffff",darkblue:"00008b",darkcyan:"008b8b",darkgoldenrod:"b8860b",darkgray:"a9a9a9",darkgreen:"006400",darkkhaki:"bdb76b",darkmagenta:"8b008b",darkolivegreen:"556b2f",darkorange:"ff8c00",darkorchid:"9932cc",darkred:"8b0000",darksalmon:"e9967a",darkseagreen:"8fbc8f",darkslateblue:"483d8b",darkslategray:"2f4f4f",darkturquoise:"00ced1",darkviolet:"9400d3",deeppink:"ff1493",deepskyblue:"00bfff",dimgray:"696969",dodgerblue:"1e90ff",firebrick:"b22222",floralwhite:"fffaf0",forestgreen:"228b22",fuchsia:"ff00ff",gainsboro:"dcdcdc",ghostwhite:"f8f8ff",gold:"ffd700",goldenrod:"daa520",gray:"808080",green:"008000",greenyellow:"adff2f",honeydew:"f0fff0",hotpink:"ff69b4",indianred:"cd5c5c",indigo:"4b0082",ivory:"fffff0",khaki:"f0e68c",lavender:"e6e6fa",lavenderblush:"fff0f5",lawngreen:"7cfc00",lemonchiffon:"fffacd",lightblue:"add8e6",lightcoral:"f08080",lightcyan:"e0ffff",lightgoldenrodyellow:"fafad2",lightgrey:"d3d3d3",lightgreen:"90ee90",lightpink:"ffb6c1",lightsalmon:"ffa07a",lightseagreen:"20b2aa",lightskyblue:"87cefa",lightslategray:"778899",lightsteelblue:"b0c4de",lightyellow:"ffffe0",lime:"00ff00",limegreen:"32cd32",linen:"faf0e6",magenta:"ff00ff",maroon:"800000",mediumaquamarine:"66cdaa",mediumblue:"0000cd",mediumorchid:"ba55d3",mediumpurple:"9370d8",mediumseagreen:"3cb371",mediumslateblue:"7b68ee",mediumspringgreen:"00fa9a",mediumturquoise:"48d1cc",mediumvioletred:"c71585",midnightblue:"191970",mintcream:"f5fffa",mistyrose:"ffe4e1",moccasin:"ffe4b5",navajowhite:"ffdead",navy:"000080",oldlace:"fdf5e6",olive:"808000",olivedrab:"6b8e23",orange:"ffa500",orangered:"ff4500",orchid:"da70d6",palegoldenrod:"eee8aa",palegreen:"98fb98",paleturquoise:"afeeee",palevioletred:"d87093",papayawhip:"ffefd5",peachpuff:"ffdab9",peru:"cd853f",pink:"ffc0cb",plum:"dda0dd",powderblue:"b0e0e6",purple:"800080",red:"ff0000",rosybrown:"bc8f8f",royalblue:"4169e1",saddlebrown:"8b4513",salmon:"fa8072",sandybrown:"f4a460",seagreen:"2e8b57",seashell:"fff5ee",sienna:"a0522d",silver:"c0c0c0",skyblue:"87ceeb",slateblue:"6a5acd",slategray:"708090",snow:"fffafa",springgreen:"00ff7f",steelblue:"4682b4",tan:"d2b48c",teal:"008080",thistle:"d8bfd8",tomato:"ff6347",turquoise:"40e0d0",violet:"ee82ee",wheat:"f5deb3",white:"ffffff",whitesmoke:"f5f5f5",yellow:"ffff00",yellowgreen:"9acd32",transparent:"transparent"},b.prototype={constructor:b,colors:{},predefinedColors:{},getValue:function(){return this.value},setValue:function(a){this.value=a},_sanitizeNumber:function(a){return"number"==typeof a?a:isNaN(a)||null===a||""===a||void 0===a?1:""===a?0:"undefined"!=typeof a.toLowerCase?(a.match(/^\./)&&(a="0"+a),Math.ceil(100*parseFloat(a))/100):1},isTransparent:function(a){return!(!a||!("string"==typeof a||a instanceof String))&&(a=a.toLowerCase().trim(),"transparent"===a||a.match(/#?00000000/)||a.match(/(rgba|hsla)\(0,0,0,0?\.?0\)/))},rgbaIsTransparent:function(a){return 0===a.r&&0===a.g&&0===a.b&&0===a.a},setColor:function(a){if(a=a.toLowerCase().trim()){if(this.isTransparent(a))return this.value={h:0,s:0,b:0,a:0},!0;var b=this.parse(a);b?(this.value=this.value={h:b.h,s:b.s,b:b.b,a:b.a},this.origFormat||(this.origFormat=b.format)):this.fallbackValue&&(this.value=this.fallbackValue)}return!1},setHue:function(a){this.value.h=1-a},setSaturation:function(a){this.value.s=a},setBrightness:function(a){this.value.b=1-a},setAlpha:function(a){this.value.a=Math.round(parseInt(100*(1-a),10)/100*100)/100},toRGB:function(a,b,c,d){0===arguments.length&&(a=this.value.h,b=this.value.s,c=this.value.b,d=this.value.a),a*=360;var e,f,g,h,i;return a=a%360/60,i=c*b,h=i*(1-Math.abs(a%2-1)),e=f=g=c-i,a=~~a,e+=[i,h,0,0,h,i][a],f+=[h,i,i,h,0,0][a],g+=[0,0,h,i,i,h][a],{r:Math.round(255*e),g:Math.round(255*f),b:Math.round(255*g),a:d}},toHex:function(a,b,c,d,e){arguments.length<=1&&(b=this.value.h,c=this.value.s,d=this.value.b,e=this.value.a);var f="#",g=this.toRGB(b,c,d,e);if(this.rgbaIsTransparent(g))return"transparent";a||(f=this.hexNumberSignPrefix?"#":"");var h=f+((1<<24)+(parseInt(g.r)<<16)+(parseInt(g.g)<<8)+parseInt(g.b)).toString(16).slice(1);return h},toHSL:function(a,b,c,d){0===arguments.length&&(a=this.value.h,b=this.value.s,c=this.value.b,d=this.value.a);var e=a,f=(2-b)*c,g=b*c;return g/=f>0&&f<=1?f:2-f,f/=2,g>1&&(g=1),{h:isNaN(e)?0:e,s:isNaN(g)?0:g,l:isNaN(f)?0:f,a:isNaN(d)?0:d}},toAlias:function(a,b,c,d){var e,f=0===arguments.length?this.toHex(!0):this.toHex(!0,a,b,c,d),g="alias"===this.origFormat?f:this.toString(!1,this.origFormat);for(var h in this.colors)if(e=this.colors[h].toLowerCase().trim(),e===f||e===g)return h;return!1},RGBtoHSB:function(a,b,c,d){a/=255,b/=255,c/=255;var e,f,g,h;return g=Math.max(a,b,c),h=g-Math.min(a,b,c),e=0===h?null:g===a?(b-c)/h:g===b?(c-a)/h+2:(a-b)/h+4,e=(e+360)%6*60/360,f=0===h?0:h/g,{h:this._sanitizeNumber(e),s:f,b:g,a:this._sanitizeNumber(d)}},HueToRGB:function(a,b,c){return c<0?c+=1:c>1&&(c-=1),6*c<1?a+(b-a)*c*6:2*c<1?b:3*c<2?a+(b-a)*(2/3-c)*6:a},HSLtoRGB:function(a,b,c,d){b<0&&(b=0);var e;e=c<=.5?c*(1+b):c+b-c*b;var f=2*c-e,g=a+1/3,h=a,i=a-1/3,j=Math.round(255*this.HueToRGB(f,e,g)),k=Math.round(255*this.HueToRGB(f,e,h)),l=Math.round(255*this.HueToRGB(f,e,i));return[j,k,l,this._sanitizeNumber(d)]},parse:function(b){if(0===arguments.length)return!1;var c,d,e=this,f=!1,g="undefined"!=typeof this.colors[b];return g&&(b=this.colors[b].toLowerCase().trim()),a.each(this.stringParsers,function(a,h){var i=h.re.exec(b);return c=i&&h.parse.apply(e,[i]),!c||(f={},d=g?"alias":h.format?h.format:e.getValidFallbackFormat(),f=d.match(/hsla?/)?e.RGBtoHSB.apply(e,e.HSLtoRGB.apply(e,c)):e.RGBtoHSB.apply(e,c),f instanceof Object&&(f.format=d),!1)}),f},getValidFallbackFormat:function(){var a=["rgba","rgb","hex","hsla","hsl"];return this.origFormat&&a.indexOf(this.origFormat)!==-1?this.origFormat:this.fallbackFormat&&a.indexOf(this.fallbackFormat)!==-1?this.fallbackFormat:"rgba"},toString:function(a,c,d){c=c||this.origFormat||this.fallbackFormat,d=d||!1;var e=!1;switch(c){case"rgb":return e=this.toRGB(),this.rgbaIsTransparent(e)?"transparent":"rgb("+e.r+","+e.g+","+e.b+")";case"rgba":return e=this.toRGB(),"rgba("+e.r+","+e.g+","+e.b+","+e.a+")";case"hsl":return e=this.toHSL(),"hsl("+Math.round(360*e.h)+","+Math.round(100*e.s)+"%,"+Math.round(100*e.l)+"%)";case"hsla":return e=this.toHSL(),"hsla("+Math.round(360*e.h)+","+Math.round(100*e.s)+"%,"+Math.round(100*e.l)+"%,"+e.a+")";case"hex":return this.toHex(a);case"alias":return e=this.toAlias(),e===!1?this.toString(a,this.getValidFallbackFormat()):d&&!(e in b.webColors)&&e in this.predefinedColors?this.predefinedColors[e]:e;default:return e}},stringParsers:[{re:/rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*?\)/,format:"rgb",parse:function(a){return[a[1],a[2],a[3],1]}},{re:/rgb\(\s*(\d*(?:\.\d+)?)\%\s*,\s*(\d*(?:\.\d+)?)\%\s*,\s*(\d*(?:\.\d+)?)\%\s*?\)/,format:"rgb",parse:function(a){return[2.55*a[1],2.55*a[2],2.55*a[3],1]}},{re:/rgba\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d*(?:\.\d+)?)\s*)?\)/,format:"rgba",parse:function(a){return[a[1],a[2],a[3],a[4]]}},{re:/rgba\(\s*(\d*(?:\.\d+)?)\%\s*,\s*(\d*(?:\.\d+)?)\%\s*,\s*(\d*(?:\.\d+)?)\%\s*(?:,\s*(\d*(?:\.\d+)?)\s*)?\)/,format:"rgba",parse:function(a){return[2.55*a[1],2.55*a[2],2.55*a[3],a[4]]}},{re:/hsl\(\s*(\d*(?:\.\d+)?)\s*,\s*(\d*(?:\.\d+)?)\%\s*,\s*(\d*(?:\.\d+)?)\%\s*?\)/,format:"hsl",parse:function(a){return[a[1]/360,a[2]/100,a[3]/100,a[4]]}},{re:/hsla\(\s*(\d*(?:\.\d+)?)\s*,\s*(\d*(?:\.\d+)?)\%\s*,\s*(\d*(?:\.\d+)?)\%\s*(?:,\s*(\d*(?:\.\d+)?)\s*)?\)/,format:"hsla",parse:function(a){return[a[1]/360,a[2]/100,a[3]/100,a[4]]}},{re:/#?([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/,format:"hex",parse:function(a){return[parseInt(a[1],16),parseInt(a[2],16),parseInt(a[3],16),1]}},{re:/#?([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/,format:"hex",parse:function(a){return[parseInt(a[1]+a[1],16),parseInt(a[2]+a[2],16),parseInt(a[3]+a[3],16),1]}}],colorNameToHex:function(a){return"undefined"!=typeof this.colors[a.toLowerCase()]&&this.colors[a.toLowerCase()]}};var c={horizontal:!1,inline:!1,color:!1,format:!1,input:"input",container:!1,component:".add-on, .input-group-addon",fallbackColor:!1,fallbackFormat:"hex",hexNumberSignPrefix:!0,sliders:{saturation:{maxLeft:100,maxTop:100,callLeft:"setSaturation",callTop:"setBrightness"},hue:{maxLeft:0,maxTop:100,callLeft:!1,callTop:"setHue"},alpha:{maxLeft:0,maxTop:100,callLeft:!1,callTop:"setAlpha"}},slidersHorz:{saturation:{maxLeft:100,maxTop:100,callLeft:"setSaturation",callTop:"setBrightness"},hue:{maxLeft:100,maxTop:0,callLeft:"setHue",callTop:!1},alpha:{maxLeft:100,maxTop:0,callLeft:"setAlpha",callTop:!1}},template:'',align:"right",customClass:null,colorSelectors:null},d=function(b,d){this.element=a(b).addClass("colorpicker-element"),this.options=a.extend(!0,{},c,this.element.data(),d),this.component=this.options.component,this.component=this.component!==!1&&this.element.find(this.component),this.component&&0===this.component.length&&(this.component=!1),this.container=this.options.container===!0?this.element:this.options.container,this.container=this.container!==!1&&a(this.container),this.input=this.element.is("input")?this.element:!!this.options.input&&this.element.find(this.options.input),this.input&&0===this.input.length&&(this.input=!1),this.color=this.createColor(this.options.color!==!1?this.options.color:this.getValue()),this.format=this.options.format!==!1?this.options.format:this.color.origFormat,this.options.color!==!1&&(this.updateInput(this.color),this.updateData(this.color));var e=this.picker=a(this.options.template);if(this.options.customClass&&e.addClass(this.options.customClass),this.options.inline?e.addClass("colorpicker-inline colorpicker-visible"):e.addClass("colorpicker-hidden"),this.options.horizontal&&e.addClass("colorpicker-horizontal"),["rgba","hsla","alias"].indexOf(this.format)===-1&&this.options.format!==!1&&"transparent"!==this.getValue()||e.addClass("colorpicker-with-alpha"),"right"===this.options.align&&e.addClass("colorpicker-right"),this.options.inline===!0&&e.addClass("colorpicker-no-arrow"),this.options.colorSelectors){var f=this,g=f.picker.find(".colorpicker-selectors");g.length>0&&(a.each(this.options.colorSelectors,function(b,c){var d=a(" ").addClass("colorpicker-selectors-color").css("background-color",c).data("class",b).data("alias",b);d.on("mousedown.colorpicker touchstart.colorpicker",function(b){b.preventDefault(),f.setValue("alias"===f.format?a(this).data("alias"):a(this).css("background-color"))}),g.append(d)}),g.show().addClass("colorpicker-visible"))}e.on("mousedown.colorpicker touchstart.colorpicker",a.proxy(function(a){a.target===a.currentTarget&&a.preventDefault()},this)),e.find(".colorpicker-saturation, .colorpicker-hue, .colorpicker-alpha").on("mousedown.colorpicker touchstart.colorpicker",a.proxy(this.mousedown,this)),e.appendTo(this.container?this.container:a("body")),this.input!==!1&&(this.input.on({"keyup.colorpicker":a.proxy(this.keyup,this)}),this.input.on({"change.colorpicker":a.proxy(this.change,this)}),this.component===!1&&this.element.on({"focus.colorpicker":a.proxy(this.show,this)}),this.options.inline===!1&&this.element.on({"focusout.colorpicker":a.proxy(this.hide,this)})),this.component!==!1&&this.component.on({"click.colorpicker":a.proxy(this.show,this)}),this.input===!1&&this.component===!1&&this.element.on({"click.colorpicker":a.proxy(this.show,this)}),this.input!==!1&&this.component!==!1&&"color"===this.input.attr("type")&&this.input.on({"click.colorpicker":a.proxy(this.show,this),"focus.colorpicker":a.proxy(this.show,this)}),this.update(),a(a.proxy(function(){this.element.trigger("create")},this))};d.Color=b,d.prototype={constructor:d,destroy:function(){this.picker.remove(),this.element.removeData("colorpicker","color").off(".colorpicker"),this.input!==!1&&this.input.off(".colorpicker"),this.component!==!1&&this.component.off(".colorpicker"),this.element.removeClass("colorpicker-element"),this.element.trigger({type:"destroy"})},reposition:function(){if(this.options.inline!==!1||this.options.container)return!1;var a=this.container&&this.container[0]!==window.document.body?"position":"offset",b=this.component||this.element,c=b[a]();"right"===this.options.align&&(c.left-=this.picker.outerWidth()-b.outerWidth()),this.picker.css({top:c.top+b.outerHeight(),left:c.left})},show:function(b){this.isDisabled()||(this.picker.addClass("colorpicker-visible").removeClass("colorpicker-hidden"),this.reposition(),a(window).on("resize.colorpicker",a.proxy(this.reposition,this)),!b||this.hasInput()&&"color"!==this.input.attr("type")||b.stopPropagation&&b.preventDefault&&(b.stopPropagation(),b.preventDefault()),!this.component&&this.input||this.options.inline!==!1||a(window.document).on({"mousedown.colorpicker":a.proxy(this.hide,this)}),this.element.trigger({type:"showPicker",color:this.color}))},hide:function(b){return("undefined"==typeof b||!b.target||!(a(b.currentTarget).parents(".colorpicker").length>0||a(b.target).parents(".colorpicker").length>0))&&(this.picker.addClass("colorpicker-hidden").removeClass("colorpicker-visible"),a(window).off("resize.colorpicker",this.reposition),a(window.document).off({"mousedown.colorpicker":this.hide}),this.update(),void this.element.trigger({type:"hidePicker",color:this.color}))},updateData:function(a){return a=a||this.color.toString(!1,this.format),this.element.data("color",a),a},updateInput:function(a){return a=a||this.color.toString(!1,this.format),this.input!==!1&&(this.input.prop("value",a),this.input.trigger("change")),a},updatePicker:function(a){"undefined"!=typeof a&&(this.color=this.createColor(a));var b=this.options.horizontal===!1?this.options.sliders:this.options.slidersHorz,c=this.picker.find("i");if(0!==c.length)return this.options.horizontal===!1?(b=this.options.sliders,c.eq(1).css("top",b.hue.maxTop*(1-this.color.value.h)).end().eq(2).css("top",b.alpha.maxTop*(1-this.color.value.a))):(b=this.options.slidersHorz,c.eq(1).css("left",b.hue.maxLeft*(1-this.color.value.h)).end().eq(2).css("left",b.alpha.maxLeft*(1-this.color.value.a))),c.eq(0).css({top:b.saturation.maxTop-this.color.value.b*b.saturation.maxTop,left:this.color.value.s*b.saturation.maxLeft}),this.picker.find(".colorpicker-saturation").css("backgroundColor",this.color.toHex(!0,this.color.value.h,1,1,1)),this.picker.find(".colorpicker-alpha").css("backgroundColor",this.color.toHex(!0)),this.picker.find(".colorpicker-color, .colorpicker-color div").css("backgroundColor",this.color.toString(!0,this.format)),a},updateComponent:function(a){var b;if(b="undefined"!=typeof a?this.createColor(a):this.color,this.component!==!1){var c=this.component.find("i").eq(0);c.length>0?c.css({backgroundColor:b.toString(!0,this.format)}):this.component.css({backgroundColor:b.toString(!0,this.format)})}return b.toString(!1,this.format)},update:function(a){var b;return this.getValue(!1)===!1&&a!==!0||(b=this.updateComponent(),this.updateInput(b),this.updateData(b),this.updatePicker()),b},setValue:function(a){this.color=this.createColor(a),this.update(!0),this.element.trigger({type:"changeColor",color:this.color,value:a})},createColor:function(a){return new b(a?a:null,this.options.colorSelectors,this.options.fallbackColor?this.options.fallbackColor:this.color,this.options.fallbackFormat,this.options.hexNumberSignPrefix)},getValue:function(a){a="undefined"==typeof a?this.options.fallbackColor:a;var b;return b=this.hasInput()?this.input.val():this.element.data("color"),void 0!==b&&""!==b&&null!==b||(b=a),b},hasInput:function(){return this.input!==!1},isDisabled:function(){return!!this.hasInput()&&this.input.prop("disabled")===!0},disable:function(){return!!this.hasInput()&&(this.input.prop("disabled",!0),this.element.trigger({type:"disable",color:this.color,value:this.getValue()}),!0)},enable:function(){return!!this.hasInput()&&(this.input.prop("disabled",!1),this.element.trigger({type:"enable",color:this.color,value:this.getValue()}),!0)},currentSlider:null,mousePointer:{left:0,top:0},mousedown:function(b){!b.pageX&&!b.pageY&&b.originalEvent&&b.originalEvent.touches&&(b.pageX=b.originalEvent.touches[0].pageX,b.pageY=b.originalEvent.touches[0].pageY),b.stopPropagation(),b.preventDefault();var c=a(b.target),d=c.closest("div"),e=this.options.horizontal?this.options.slidersHorz:this.options.sliders;if(!d.is(".colorpicker")){if(d.is(".colorpicker-saturation"))this.currentSlider=a.extend({},e.saturation);else if(d.is(".colorpicker-hue"))this.currentSlider=a.extend({},e.hue);else{if(!d.is(".colorpicker-alpha"))return!1;this.currentSlider=a.extend({},e.alpha)}var f=d.offset();this.currentSlider.guide=d.find("i")[0].style,this.currentSlider.left=b.pageX-f.left,this.currentSlider.top=b.pageY-f.top,this.mousePointer={left:b.pageX,top:b.pageY},a(window.document).on({"mousemove.colorpicker":a.proxy(this.mousemove,this),"touchmove.colorpicker":a.proxy(this.mousemove,this),"mouseup.colorpicker":a.proxy(this.mouseup,this),"touchend.colorpicker":a.proxy(this.mouseup,this)}).trigger("mousemove")}return!1},mousemove:function(a){!a.pageX&&!a.pageY&&a.originalEvent&&a.originalEvent.touches&&(a.pageX=a.originalEvent.touches[0].pageX,a.pageY=a.originalEvent.touches[0].pageY),a.stopPropagation(),a.preventDefault();var b=Math.max(0,Math.min(this.currentSlider.maxLeft,this.currentSlider.left+((a.pageX||this.mousePointer.left)-this.mousePointer.left))),c=Math.max(0,Math.min(this.currentSlider.maxTop,this.currentSlider.top+((a.pageY||this.mousePointer.top)-this.mousePointer.top)));return this.currentSlider.guide.left=b+"px",this.currentSlider.guide.top=c+"px",this.currentSlider.callLeft&&this.color[this.currentSlider.callLeft].call(this.color,b/this.currentSlider.maxLeft),this.currentSlider.callTop&&this.color[this.currentSlider.callTop].call(this.color,c/this.currentSlider.maxTop),this.options.format!==!1||"setAlpha"!==this.currentSlider.callTop&&"setAlpha"!==this.currentSlider.callLeft||(1!==this.color.value.a?(this.format="rgba",this.color.origFormat="rgba"):(this.format="hex",this.color.origFormat="hex")),this.update(!0),this.element.trigger({type:"changeColor",color:this.color}),!1},mouseup:function(b){return b.stopPropagation(),b.preventDefault(),a(window.document).off({"mousemove.colorpicker":this.mousemove,"touchmove.colorpicker":this.mousemove,"mouseup.colorpicker":this.mouseup,"touchend.colorpicker":this.mouseup}),!1},change:function(a){this.keyup(a)},keyup:function(a){38===a.keyCode?(this.color.value.a<1&&(this.color.value.a=Math.round(100*(this.color.value.a+.01))/100),this.update(!0)):40===a.keyCode?(this.color.value.a>0&&(this.color.value.a=Math.round(100*(this.color.value.a-.01))/100),this.update(!0)):(this.color=this.createColor(this.input.val()),this.color.origFormat&&this.options.format===!1&&(this.format=this.color.origFormat),this.getValue(!1)!==!1&&(this.updateData(),this.updateComponent(),this.updatePicker())),this.element.trigger({type:"changeColor",color:this.color,value:this.input.val()})}},a.colorpicker=d,a.fn.colorpicker=function(b){var c=Array.prototype.slice.call(arguments,1),e=1===this.length,f=null,g=this.each(function(){var e=a(this),g=e.data("colorpicker"),h="object"==typeof b?b:{};g||(g=new d(this,h),e.data("colorpicker",g)),"string"==typeof b?a.isFunction(g[b])?f=g[b].apply(g,c):(c.length&&(g[b]=c[0]),f=g[b]):f=e});return e?f:g},a.fn.colorpicker.constructor=d});
\ No newline at end of file
diff --git a/odex25_project/web_widget_colorpicker/static/src/xml/widget.xml b/odex25_project/web_widget_colorpicker/static/src/xml/widget.xml
new file mode 100644
index 000000000..14f1a8003
--- /dev/null
+++ b/odex25_project/web_widget_colorpicker/static/src/xml/widget.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/odex25_project/web_widget_colorpicker/view/web_widget_colorpicker_view.xml b/odex25_project/web_widget_colorpicker/view/web_widget_colorpicker_view.xml
new file mode 100644
index 000000000..b9169e773
--- /dev/null
+++ b/odex25_project/web_widget_colorpicker/view/web_widget_colorpicker_view.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/odex25_project/web_widget_time_delta/README.rst b/odex25_project/web_widget_time_delta/README.rst
new file mode 100644
index 000000000..c015fd14c
--- /dev/null
+++ b/odex25_project/web_widget_time_delta/README.rst
@@ -0,0 +1,51 @@
+Timedelta widget for Odoo web client
+================================
+
+
+Features
+========
+
+
+* Display the time on form view
+
+ |formview|
+
+* Display the time on list view
+
+ |listview|
+
+
+Usage
+=====
+
+You need to declare a integer field Default set second.
+
+ duration = fields.integer(
+ string="Duration",
+ help="Set Duration",
+ default="60"
+ )
+
+
+In the view declaration, put widget='time_delta' for Form and widget='time_delta_list' for List
+
+ ...
+
+
+ ...
+
+ ...
+
+
+ ...
+
+ ...
+
+
+ ...
+
diff --git a/odex25_project/web_widget_time_delta/__init__.py b/odex25_project/web_widget_time_delta/__init__.py
new file mode 100644
index 000000000..ec51c5a2b
--- /dev/null
+++ b/odex25_project/web_widget_time_delta/__init__.py
@@ -0,0 +1,2 @@
+# -*- coding: utf-8 -*-
+#
diff --git a/odex25_project/web_widget_time_delta/__manifest__.py b/odex25_project/web_widget_time_delta/__manifest__.py
new file mode 100644
index 000000000..b395c2036
--- /dev/null
+++ b/odex25_project/web_widget_time_delta/__manifest__.py
@@ -0,0 +1,72 @@
+# -*- coding: utf-8 -*-
+{
+ "name": """Web Widget Time Delta""",
+ "summary": """Added Time Delta Human friedly for From and List""",
+ "category": "Odex25-Project/Odex25-Project",
+ "images": ['static/description/icon.png'],
+ "version": "14.21.05.28.0",
+ "description": """
+
+ update: round True
+ update: fix for bootstrap hide
+
+ XML string:
+ For Form View - added = widget="time_delta"
+ For List View - added = widget="time_delta"
+
+
+
+ XML field:
+
+
+ PYTHON
+ duration = fields.Integer(string='Plan Duration') store in seconds.
+
+ duration_scale = fields.Char(string='Duration Scale', related="project_id.duration_scale", readonly=True, )
+ duration_picker = fields.Selection(string='Duration Picker', related="project_id.duration_picker", readonly=True, )
+
+
+ Selection
+ @api.model
+ def _get_duration_picker(self):
+ value = [
+ ('day', _('Day')),
+ ('second', _('Second')),
+ ('day_second', _('Day Second'))
+ ]
+ return value
+
+
+ """,
+
+ "author": "Viktor Vorobjov",
+ "license": "LGPL-3",
+ "website": "https://straga.github.io",
+ "support": "vostraga@gmail.com",
+ "price": 0.00,
+ "currency": "EUR",
+
+ "depends": [
+ "web"
+ ],
+ "external_dependencies": {"python": [], "bin": []},
+ "data": [
+ 'view/web_widget_time_delta_view.xml'
+ ],
+ "qweb": [
+ 'static/src/xml/widget.xml',
+
+ ],
+ "demo": [],
+
+ "post_load": None,
+ "pre_init_hook": None,
+ "post_init_hook": None,
+ "installable": True,
+ "auto_install": False,
+ "application": False,
+}
diff --git a/odex25_project/web_widget_time_delta/i18n/ar_001.po b/odex25_project/web_widget_time_delta/i18n/ar_001.po
new file mode 100644
index 000000000..c12f60ba7
--- /dev/null
+++ b/odex25_project/web_widget_time_delta/i18n/ar_001.po
@@ -0,0 +1,71 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * web_widget_time_delta
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 14.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2024-06-12 10:23+0000\n"
+"PO-Revision-Date: 2024-06-12 10:23+0000\n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: \n"
+
+#. module: web_widget_time_delta
+#: code:addons/web_widget_time_delta/static/src/js/widget.js:0
+#, python-format
+msgid "day"
+msgstr "يوم"
+
+#. module: web_widget_time_delta
+#. openerp-web
+#: code:addons/web_widget_time_delta/static/src/js/widget.js:0
+#, python-format
+msgid "days"
+msgstr "ايام"
+
+#. module: web_widget_time_delta
+#. openerp-web
+#: code:addons/web_widget_time_delta/static/src/js/widget.js:0
+#, python-format
+msgid "hour"
+msgstr "ساعة"
+
+#. module: web_widget_time_delta
+#. openerp-web
+#: code:addons/web_widget_time_delta/static/src/js/widget.js:0
+#, python-format
+msgid "hours"
+msgstr "ساعات"
+
+#. module: web_widget_time_delta
+#. openerp-web
+#: code:addons/web_widget_time_delta/static/src/js/widget.js:0
+#, python-format
+msgid "minute"
+msgstr "دقيقة"
+
+#. module: web_widget_time_delta
+#. openerp-web
+#: code:addons/web_widget_time_delta/static/src/js/widget.js:0
+#, python-format
+msgid "minutes"
+msgstr "دقائق"
+
+#. module: web_widget_time_delta
+#. openerp-web
+#: code:addons/web_widget_time_delta/static/src/js/widget.js:0
+#, python-format
+msgid "second"
+msgstr "ثانية"
+
+#. module: web_widget_time_delta
+#. openerp-web
+#: code:addons/web_widget_time_delta/static/src/js/widget.js:0
+#, python-format
+msgid "seconds"
+msgstr "ثواني"
diff --git a/odex25_project/web_widget_time_delta/images/form_view.png b/odex25_project/web_widget_time_delta/images/form_view.png
new file mode 100644
index 000000000..9f063c6f7
Binary files /dev/null and b/odex25_project/web_widget_time_delta/images/form_view.png differ
diff --git a/odex25_project/web_widget_time_delta/images/list_view.png b/odex25_project/web_widget_time_delta/images/list_view.png
new file mode 100644
index 000000000..3b36268cf
Binary files /dev/null and b/odex25_project/web_widget_time_delta/images/list_view.png differ
diff --git a/odex25_project/web_widget_time_delta/static/description/form_view.png b/odex25_project/web_widget_time_delta/static/description/form_view.png
new file mode 100644
index 000000000..9f063c6f7
Binary files /dev/null and b/odex25_project/web_widget_time_delta/static/description/form_view.png differ
diff --git a/odex25_project/web_widget_time_delta/static/description/icon.png b/odex25_project/web_widget_time_delta/static/description/icon.png
new file mode 100644
index 000000000..9f063c6f7
Binary files /dev/null and b/odex25_project/web_widget_time_delta/static/description/icon.png differ
diff --git a/odex25_project/web_widget_time_delta/static/description/index.html b/odex25_project/web_widget_time_delta/static/description/index.html
new file mode 100644
index 000000000..1491e6c72
--- /dev/null
+++ b/odex25_project/web_widget_time_delta/static/description/index.html
@@ -0,0 +1,80 @@
+
+
+
Web Widget field for Form and List
+
Humanize duration
+
+
+
+
+
+
+
+
+
+
+
+
+
Demo
+
Live:https://demo14.garage12.eu/
+
user: demo Password:demog
+
+
+
+
+
+
+
+
+
in Action
+
+
+
+ Form View
+
+
+
+
+
+
+ List View
+
+
+
+
+
+
+
+
+
+
+
+
+
Need our service?
+
Contact us by email
+
+
+
+
+
+
+
diff --git a/odex25_project/web_widget_time_delta/static/description/list_view.png b/odex25_project/web_widget_time_delta/static/description/list_view.png
new file mode 100644
index 000000000..3b36268cf
Binary files /dev/null and b/odex25_project/web_widget_time_delta/static/description/list_view.png differ
diff --git a/odex25_project/web_widget_time_delta/static/src/css/widget.css b/odex25_project/web_widget_time_delta/static/src/css/widget.css
new file mode 100644
index 000000000..0d6de10ab
--- /dev/null
+++ b/odex25_project/web_widget_time_delta/static/src/css/widget.css
@@ -0,0 +1,48 @@
+.openerp .oe_form .oe_form_field_time_delta input {
+ width: 100%;
+}
+
+.openerp .oe_form .oe_form_field_delta div {
+ border: 1px solid;
+ display: inline-block;
+ height: 14px;
+ margin-right: 10px;
+ position: relative;
+ top: 3px;
+ width: 40px;
+}
+
+.oe_list_field_time_delta div {
+ border: 1px solid;
+ display: inline-block;
+ height: 14px;
+ margin-right: 10px;
+ position: relative;
+ top: 3px;
+ width: 40px;
+}
+
+.time_delta_box {
+ width: 10px;
+ height: 10px;
+ display: inline-block;
+ margin-right: 5px;
+}
+
+/*.oe_form_field_time_delta .bdp-input input {*/
+ /*display: inline-block;*/
+ /*margin-bottom: 3px;*/
+ /*width: 45px;*/
+/*}*/
+
+.oe_form_field_time_delta .bdp-input .input-sm {
+ height: 30px;
+ padding: 3px 3px;
+ font-size: 12px;
+ line-height: 1.5;
+ border-radius: 3px;
+ display: inline-block;
+ margin-bottom: 3px;
+ width: 50px;
+}
+
diff --git a/odex25_project/web_widget_time_delta/static/src/js/widget.js b/odex25_project/web_widget_time_delta/static/src/js/widget.js
new file mode 100644
index 000000000..2db2bcdef
--- /dev/null
+++ b/odex25_project/web_widget_time_delta/static/src/js/widget.js
@@ -0,0 +1,171 @@
+odoo.define('web_widget_time_delta.TimeDelta', function (require) {
+ "use strict";
+ var field_registry = require('web.field_registry');
+ var fields = require('web.basic_fields');
+ var FieldProgressBar = fields.FieldProgressBar
+ var utils = require('web.utils');
+
+ var core = require('web.core');
+ var _t = core._t;
+
+ var FieldTimeDelta = fields.FieldChar.extend({
+
+ template: 'FieldTimeDelta',
+ widget_class: 'oe_form_field_time_delta',
+
+ init: function () {
+
+ this._super.apply(this, arguments);
+ this.mask_humanize = undefined;
+ this.showDays = false;
+ this.showSeconds = false;
+
+ if ("mask_humanize_string" in this.nodeOptions) {
+ this.mask_humanize = this.nodeOptions["mask_humanize_string"];
+ }
+
+ if ("mask_humanize_field" in this.nodeOptions) {
+ this.mask_humanize = this.recordData[this.nodeOptions["mask_humanize_field"]];
+ }
+
+ var mask_picker = "";
+ if ("mask_picker_string" in this.nodeOptions) {
+ mask_picker = this.nodeOptions["mask_picker_string"];
+
+ if (mask_picker === "day_second") {
+ this.showDays = true;
+ this.showSeconds = true;
+ }
+ if (mask_picker === "day") {
+ this.showDays = true;
+ }
+ if (mask_picker === "second") {
+ this.showSeconds = true;
+ }
+ }
+
+ if ("mask_picker_field" in this.nodeOptions) {
+ mask_picker = this.recordData[this.nodeOptions["mask_picker_field"]];
+
+ if (mask_picker === "day_second") {
+ this.showDays = true;
+ this.showSeconds = true;
+ }
+ if (mask_picker === "day") {
+ this.showDays = true;
+ }
+ if (mask_picker === "second") {
+ this.showSeconds = true;
+ }
+ }
+
+ },
+
+ _renderReadonlyValue: function (value) {
+
+ if (this.mask_humanize) {
+ return humanizeDuration(value * 1000, { units: this.mask_humanize.split(","), round: true });
+ }
+ else {
+ return humanizeDuration(value * 1000);
+ }
+ },
+
+ _renderReadonly: function () {
+ var total = parseInt(this.value, 10);
+ this.$el.text(this._renderReadonlyValue(total));
+ },
+
+ _getValue: function () {
+ var $input = this.$el.find('input');
+ return $input.val();
+ },
+
+ _renderEdit: function () {
+
+ var show_value = parseInt(this.value, 10);
+
+ if (this.hasOwnProperty('$input') && this.$input.data('durationPicker')) {
+ var is_duration = this.$input.data('durationPicker')
+ is_duration.setValue(show_value)
+ }
+ else {
+
+ var $input = this.$el.find('input');
+ $input.val(show_value);
+ var self = this;
+ $input.durationPicker({
+ translations: {
+ day: _t('day'),
+ hour: _t('hour'),
+ minute: _t('minute'),
+ second: _t('second'),
+ days: _t('days'),
+ hours: _t('hours'),
+ minutes: _t('minutes'),
+ seconds: _t('seconds')
+ },
+
+ showSeconds: self.showSeconds,
+ showDays: self.showDays,
+ onChanged: function (newVal) {
+ $input.val(newVal);
+ }
+ });
+ this.$input = $input;
+
+ }
+ },
+
+ });
+
+ field_registry
+ .add('time_delta_list', FieldTimeDelta)
+ .add('time_delta', FieldTimeDelta);
+
+ FieldProgressBar.include({
+ _render_value: function (v) {
+ var value = this.value;
+ var max_value = this.max_value;
+ if (!isNaN(v)) {
+ if (this.edit_max_value) {
+ max_value = v;
+ } else {
+ value = v;
+ }
+ }
+ value = value || 0;
+ max_value = max_value || 0;
+
+ var widthComplete;
+ if (value <= max_value) {
+ widthComplete = value / max_value * 100;
+ } else {
+ widthComplete = 100;
+ }
+
+ this.$('.o_progress').toggleClass('o_progress_overflow', value > max_value)
+ .attr('aria-valuemin', '0')
+ .attr('aria-valuemax', max_value)
+ .attr('aria-valuenow', value);
+ this.$('.o_progressbar_complete').css('width', widthComplete + '%');
+
+ if (!this.write_mode) {
+ if (max_value !== 100) {
+ this.$('.o_progressbar_value').text((value) + " / " + (max_value));
+ } else {
+ this.$('.o_progressbar_value').text((value) + "%");
+ }
+ } else if (isNaN(v)) {
+ this.$('.o_progressbar_value').val(this.edit_max_value ? max_value : value);
+ this.$('.o_progressbar_value').focus().select();
+ }
+ },
+ });
+ return {
+ FieldTimeDelta: FieldTimeDelta,
+ FieldProgressBar: FieldProgressBar
+ };
+
+
+});
diff --git a/odex25_project/web_widget_time_delta/static/src/lib/duration-humanize/README.md b/odex25_project/web_widget_time_delta/static/src/lib/duration-humanize/README.md
new file mode 100644
index 000000000..c98573ad8
--- /dev/null
+++ b/odex25_project/web_widget_time_delta/static/src/lib/duration-humanize/README.md
@@ -0,0 +1,280 @@
+Humanize Duration
+=================
+[](https://npmjs.org/package/humanize-duration)
+[](https://travis-ci.org/EvanHahn/HumanizeDuration.js)
+[](http://standardjs.com/)
+
+I have the time in milliseconds and I want it to become "30 minutes" or "3 days, 1 hour". Enter Humanize Duration!
+
+**This library is in maintenance mode. New languages and bug fixes will be added but no new features will be. If you're interested in helping out by taking over the project, please see [this GitHub issue](https://github.com/EvanHahn/HumanizeDuration.js/issues/120).**
+
+Basic usage
+-----------
+
+This package is available as *humanize-duration* on [npm](https://www.npmjs.com/package/humanize-duration) and Bower. You can also include the JavaScript file in the browser.
+
+In the browser:
+
+```html
+
+
+```
+
+In Node (or Browserify or Webpack or anywhere with CommonJS):
+
+```js
+var humanizeDuration = require('humanize-duration')
+humanizeDuration(12000) // '12 seconds'
+```
+
+Usage
+-----
+
+By default, Humanize Duration will humanize down to the second, and will return a decimal for the smallest unit. It will humanize in English by default.
+
+```js
+humanizeDuration(3000) // '3 seconds'
+humanizeDuration(2250) // '2.25 seconds'
+humanizeDuration(97320000) // '1 day, 3 hours, 2 minutes'
+```
+
+### Options
+
+You can change the settings by passing options as the second argument:
+
+**language**
+
+Language for unit display (accepts an [ISO 639-1 code](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) from one of the [supported languages](#supported-languages)).
+
+```js
+humanizeDuration(3000, { language: 'es' }) // '3 segundos'
+humanizeDuration(5000, { language: 'ko' }) // '5 초'
+```
+
+**delimiter**
+
+String to display between the previous unit and the next value.
+
+```js
+humanizeDuration(22140000, { delimiter: ' and ' }) // '6 hours and 9 minutes'
+humanizeDuration(22140000, { delimiter: '--' }) // '6 hours--9 minutes'
+```
+
+**spacer**
+
+String to display between each value and unit.
+
+```js
+humanizeDuration(260040000, { spacer: ' whole ' }) // '3 whole days, 14 whole minutes'
+humanizeDuration(260040000, { spacer: '' }) // '3days, 14minutes'
+```
+
+**largest**
+
+Number representing the maximum number of units to display for the duration.
+
+```js
+humanizeDuration(1000000000000) // '31 years, 8 months, 1 week, 19 hours, 46 minutes, 40 seconds'
+humanizeDuration(1000000000000, { largest: 2 }) // '31 years, 8 month'
+```
+
+**units**
+
+Array of strings to define which units are used to display the duration (if needed). Can be one, or a combination of any, of the following: `['y', 'mo', 'w', 'd', 'h', 'm', 's', 'ms']`
+
+```js
+humanizeDuration(3600000, { units: ['h'] }) // '1 hour'
+humanizeDuration(3600000, { units: ['m'] }) // '60 minutes'
+humanizeDuration(3600000, { units: ['d', 'h'] }) // '1 hour'
+```
+
+**round**
+
+Boolean value. Use `true` to [round](https://en.wikipedia.org/wiki/Rounding#Round_half_up) the smallest unit displayed (can be combined with `largest` and `units`).
+
+```js
+humanizeDuration(1200) // '1.2 seconds'
+humanizeDuration(1200, { round: true }) // '1 second'
+humanizeDuration(1600, { round: true }) // '2 seconds'
+```
+
+**decimal**
+
+String to substitute for the decimal point in a decimal fraction.
+
+```js
+humanizeDuration(1200) // '1.2 seconds'
+humanizeDuration(1200, { decimal: ' point ' }) // '1 point 2 seconds'
+```
+
+**conjunction**
+
+String to include before the final unit. You can also set `serialComma` to `false` to eliminate the final comma.
+
+```js
+humanizeDuration(22140000, { conjunction: ' and ' }) // '6 hours and 9 minutes'
+humanizeDuration(22141000, { conjunction: ' and ' }) // '6 hours, 9 minutes, and 1 second'
+humanizeDuration(22140000, { conjunction: ' and ', serialComma: false }) // '6 hours and 9 minutes'
+humanizeDuration(22141000, { conjunction: ' and ', serialComma: false }) // '6 hours, 9 minutes and 1 second'
+```
+
+**unitMeasures**
+
+Customize the value used to calculate each unit of time.
+
+```js
+humanizeDuration(400) // '0.4 seconds'
+humanizeDuration(400, { // '1 year, 1 month, 5 days'
+ unitMeasures: {
+ y: 365,
+ mo: 30,
+ w: 7,
+ d: 1
+ }
+})
+```
+
+**Combined example**
+
+```js
+humanizeDuration(3602000, {
+ language: 'es',
+ round: true,
+ spacer: ' glorioso ',
+ units: ['m']
+}) // '60 glorioso minutos'
+```
+
+### Humanizers
+
+If you find yourself setting same options over and over again, you can create a *humanizer* that changes the defaults, which you can still override later.
+
+```js
+var spanishHumanizer = humanizeDuration.humanizer({
+ language: 'es',
+ units: ['y', 'mo', 'd']
+})
+
+spanishHumanizer(71177400000) // '2 años, 3 meses, 2 días'
+spanishHumanizer(71177400000, { units: ['d', 'h'] }) // '823 días, 19.5 horas'
+```
+
+You can also add new languages to humanizers. For example:
+
+```js
+var shortEnglishHumanizer = humanizeDuration.humanizer({
+ language: 'shortEn',
+ languages: {
+ shortEn: {
+ y: function() { return 'y' },
+ mo: function() { return 'mo' },
+ w: function() { return 'w' },
+ d: function() { return 'd' },
+ h: function() { return 'h' },
+ m: function() { return 'm' },
+ s: function() { return 's' },
+ ms: function() { return 'ms' },
+ }
+ }
+})
+
+shortEnglishHumanizer(15600000) // '4 h, 20 m'
+```
+
+You can also add languages after initializing:
+
+```js
+var humanizer = humanizeDuration.humanizer()
+
+humanizer.languages.shortEn = {
+ y: function(c) { return c + 'y' },
+ // ...
+```
+
+Internally, the main `humanizeDuration` function is just a wrapper around a humanizer.
+
+Supported languages
+-------------------
+
+Humanize Duration supports the following languages:
+
+| Language | Code |
+|----------------------|---------|
+| Arabic | `ar` |
+| Bulgarian | `bg` |
+| Catalan | `ca` |
+| Chinese, simplified | `zh_CN` |
+| Chinese, traditional | `zh_TW` |
+| Czech | `cs` |
+| Danish | `da` |
+| Dutch | `nl` |
+| English | `en` |
+| Farsi/Persian | `fa` |
+| Finnish | `fi` |
+| French | `fr` |
+| German | `de` |
+| Greek | `gr` |
+| Hungarian | `hu` |
+| Icelandic | `is` |
+| Indonesian | `id` |
+| Italian | `it` |
+| Japanese | `ja` |
+| Korean | `ko` |
+| Lithuanian | `lt` |
+| Malay | `ms` |
+| Norwegian | `no` |
+| Polish | `pl` |
+| Portuguese | `pt` |
+| Russian | `ru` |
+| Spanish | `es` |
+| Swedish | `sv` |
+| Turkish | `tr` |
+| Ukrainian | `uk` |
+| Vietnamese | `vi` |
+
+For a list of supported languages, you can use the `getSupportedLanguages` function.
+
+```js
+humanizeDuration.getSupportedLanguages()
+// ['ar', 'bg', 'ca', 'cs', da', 'de', ...]
+```
+
+This function won't return any new languages you define; it will only return the defaults supported by the library.
+
+Credits
+-------
+
+Lovingly made by [Evan Hahn](http://evanhahn.com/) with help from:
+
+* [Martin Prins](https://github.com/magarcia) for language support
+* [Filipi Siqueira](https://github.com/filipi777) for Portuguese support
+* [Peter Rekdal Sunde](https://github.com/peters) for Norwegian support
+* [Michał Janiec](https://github.com/mjjaniec) for Polish support
+* [Eileen Li](https://github.com/eileen3) for Chinese support
+* [Tommy Brunn](https://github.com/Nevon) for Swedish support
+* [Giovanni Pellerano](https://github.com/evilaliv3) for Italian support
+* [Rahma Sghaier](https://twitter.com/sghaierrahma) for Arabic support
+* [Evgenios Kastanias](https://github.com/evgenios) for Greek support
+* [Oleksii Mylotskyi](https://github.com/spalax) for Ukrainian support
+* [Patrik Simek](https://github.com/patriksimek) for Czech support
+* [Toni Helminen](https://github.com/tonihelminen) for Finnish support
+* [Vidmantas Drasutis](https://github.com/Drasius2) for Lithuanian support
+* [Manh Tuan](https://github.com/J2TeaM) for Vietnamese support
+* [Leonard Lee](https://github.com/sheeeng) for Indonesian & Malay support
+* [Jesse Jackson](https://github.com/jsejcksn) for documentation help
+* [Óli Tómas Freysson](https://github.com/olitomas) for Icelandic support
+* [Saeed Ganji](https://github.com/shahabganji) for Farsi/Persian support
+* [Caner Elci](https://github.com/canerelci) for Bulgarian support
+
+Licensed under the permissive [Unlicense](https://unlicense.org/). Enjoy!
+
+Related modules
+---------------
+
+* [pretty-ms](https://github.com/sindresorhus/pretty-ms)
+* [angularjs-humanize-duration](https://github.com/sebastianhaas/angularjs-humanize-duration)
+* [millisec](https://github.com/sungwoncho/millisec)
+* [HumanizeDuration.ts](https://github.com/Nightapes/HumanizeDuration.ts), a TypeScript version of this module
+* [aurelia-time](https://github.com/shahabganji/aurelia-time)
diff --git a/odex25_project/web_widget_time_delta/static/src/lib/duration-humanize/humanize-duration.js b/odex25_project/web_widget_time_delta/static/src/lib/duration-humanize/humanize-duration.js
new file mode 100644
index 000000000..8c7d2bbd1
--- /dev/null
+++ b/odex25_project/web_widget_time_delta/static/src/lib/duration-humanize/humanize-duration.js
@@ -0,0 +1,736 @@
+// HumanizeDuration.js - https://git.io/j0HgmQ
+
+;(function () {
+ // This has to be defined separately because of a bug: we want to alias
+ // `gr` and `el` for backwards-compatiblity. In a breaking change, we can
+ // remove `gr` entirely.
+ // See https://github.com/EvanHahn/HumanizeDuration.js/issues/143 for more.
+ var greek = {
+ y: function (c) { return c === 1 ? 'χρόνος' : 'χρόνια' },
+ mo: function (c) { return c === 1 ? 'μήνας' : 'μήνες' },
+ w: function (c) { return c === 1 ? 'εβδομάδα' : 'εβδομάδες' },
+ d: function (c) { return c === 1 ? 'μέρα' : 'μέρες' },
+ h: function (c) { return c === 1 ? 'ώρα' : 'ώρες' },
+ m: function (c) { return c === 1 ? 'λεπτό' : 'λεπτά' },
+ s: function (c) { return c === 1 ? 'δευτερόλεπτο' : 'δευτερόλεπτα' },
+ ms: function (c) { return c === 1 ? 'χιλιοστό του δευτερολέπτου' : 'χιλιοστά του δευτερολέπτου' },
+ decimal: ','
+ }
+
+ var languages = {
+ ar: {
+ y: function (c) { return c === 1 ? 'سنة' : 'سنوات' },
+ mo: function (c) { return c === 1 ? 'شهر' : 'أشهر' },
+ w: function (c) { return c === 1 ? 'أسبوع' : 'أسابيع' },
+ d: function (c) { return c === 1 ? 'يوم' : 'أيام' },
+ h: function (c) { return c === 1 ? 'ساعة' : 'ساعات' },
+ m: function (c) {
+ return ['دقيقة', 'دقائق'][getArabicForm(c)]
+ },
+ s: function (c) { return c === 1 ? 'ثانية' : 'ثواني' },
+ ms: function (c) { return c === 1 ? 'جزء من الثانية' : 'أجزاء من الثانية' },
+ decimal: ','
+ },
+ bg: {
+ y: function (c) { return ['години', 'година', 'години'][getSlavicForm(c)] },
+ mo: function (c) { return ['месеца', 'месец', 'месеца'][getSlavicForm(c)] },
+ w: function (c) { return ['седмици', 'седмица', 'седмици'][getSlavicForm(c)] },
+ d: function (c) { return ['дни', 'ден', 'дни'][getSlavicForm(c)] },
+ h: function (c) { return ['часа', 'час', 'часа'][getSlavicForm(c)] },
+ m: function (c) { return ['минути', 'минута', 'минути'][getSlavicForm(c)] },
+ s: function (c) { return ['секунди', 'секунда', 'секунди'][getSlavicForm(c)] },
+ ms: function (c) { return ['милисекунди', 'милисекунда', 'милисекунди'][getSlavicForm(c)] },
+ decimal: ','
+ },
+ ca: {
+ y: function (c) { return 'any' + (c === 1 ? '' : 's') },
+ mo: function (c) { return 'mes' + (c === 1 ? '' : 'os') },
+ w: function (c) { return 'setman' + (c === 1 ? 'a' : 'es') },
+ d: function (c) { return 'di' + (c === 1 ? 'a' : 'es') },
+ h: function (c) { return 'hor' + (c === 1 ? 'a' : 'es') },
+ m: function (c) { return 'minut' + (c === 1 ? '' : 's') },
+ s: function (c) { return 'segon' + (c === 1 ? '' : 's') },
+ ms: function (c) { return 'milisegon' + (c === 1 ? '' : 's') },
+ decimal: ','
+ },
+ cs: {
+ y: function (c) { return ['rok', 'roku', 'roky', 'let'][getCzechOrSlovakForm(c)] },
+ mo: function (c) { return ['měsíc', 'měsíce', 'měsíce', 'měsíců'][getCzechOrSlovakForm(c)] },
+ w: function (c) { return ['týden', 'týdne', 'týdny', 'týdnů'][getCzechOrSlovakForm(c)] },
+ d: function (c) { return ['den', 'dne', 'dny', 'dní'][getCzechOrSlovakForm(c)] },
+ h: function (c) { return ['hodina', 'hodiny', 'hodiny', 'hodin'][getCzechOrSlovakForm(c)] },
+ m: function (c) { return ['minuta', 'minuty', 'minuty', 'minut'][getCzechOrSlovakForm(c)] },
+ s: function (c) { return ['sekunda', 'sekundy', 'sekundy', 'sekund'][getCzechOrSlovakForm(c)] },
+ ms: function (c) { return ['milisekunda', 'milisekundy', 'milisekundy', 'milisekund'][getCzechOrSlovakForm(c)] },
+ decimal: ','
+ },
+ da: {
+ y: 'år',
+ mo: function (c) { return 'måned' + (c === 1 ? '' : 'er') },
+ w: function (c) { return 'uge' + (c === 1 ? '' : 'r') },
+ d: function (c) { return 'dag' + (c === 1 ? '' : 'e') },
+ h: function (c) { return 'time' + (c === 1 ? '' : 'r') },
+ m: function (c) { return 'minut' + (c === 1 ? '' : 'ter') },
+ s: function (c) { return 'sekund' + (c === 1 ? '' : 'er') },
+ ms: function (c) { return 'millisekund' + (c === 1 ? '' : 'er') },
+ decimal: ','
+ },
+ de: {
+ y: function (c) { return 'Jahr' + (c === 1 ? '' : 'e') },
+ mo: function (c) { return 'Monat' + (c === 1 ? '' : 'e') },
+ w: function (c) { return 'Woche' + (c === 1 ? '' : 'n') },
+ d: function (c) { return 'Tag' + (c === 1 ? '' : 'e') },
+ h: function (c) { return 'Stunde' + (c === 1 ? '' : 'n') },
+ m: function (c) { return 'Minute' + (c === 1 ? '' : 'n') },
+ s: function (c) { return 'Sekunde' + (c === 1 ? '' : 'n') },
+ ms: function (c) { return 'Millisekunde' + (c === 1 ? '' : 'n') },
+ decimal: ','
+ },
+ el: greek,
+ en: {
+ y: function (c) { return 'year' + (c === 1 ? '' : 's') },
+ mo: function (c) { return 'month' + (c === 1 ? '' : 's') },
+ w: function (c) { return 'week' + (c === 1 ? '' : 's') },
+ d: function (c) { return 'day' + (c === 1 ? '' : 's') },
+ h: function (c) { return 'hour' + (c === 1 ? '' : 's') },
+ m: function (c) { return 'minute' + (c === 1 ? '' : 's') },
+ s: function (c) { return 'second' + (c === 1 ? '' : 's') },
+ ms: function (c) { return 'millisecond' + (c === 1 ? '' : 's') },
+ decimal: '.'
+ },
+ es: {
+ y: function (c) { return 'año' + (c === 1 ? '' : 's') },
+ mo: function (c) { return 'mes' + (c === 1 ? '' : 'es') },
+ w: function (c) { return 'semana' + (c === 1 ? '' : 's') },
+ d: function (c) { return 'día' + (c === 1 ? '' : 's') },
+ h: function (c) { return 'hora' + (c === 1 ? '' : 's') },
+ m: function (c) { return 'minuto' + (c === 1 ? '' : 's') },
+ s: function (c) { return 'segundo' + (c === 1 ? '' : 's') },
+ ms: function (c) { return 'milisegundo' + (c === 1 ? '' : 's') },
+ decimal: ','
+ },
+ fa: {
+ y: 'سال',
+ mo: 'ماه',
+ w: 'هفته',
+ d: 'روز',
+ h: 'ساعت',
+ m: 'دقیقه',
+ s: 'ثانیه',
+ ms: 'میلی ثانیه',
+ decimal: '.'
+ },
+ fi: {
+ y: function (c) { return c === 1 ? 'vuosi' : 'vuotta' },
+ mo: function (c) { return c === 1 ? 'kuukausi' : 'kuukautta' },
+ w: function (c) { return 'viikko' + (c === 1 ? '' : 'a') },
+ d: function (c) { return 'päivä' + (c === 1 ? '' : 'ä') },
+ h: function (c) { return 'tunti' + (c === 1 ? '' : 'a') },
+ m: function (c) { return 'minuutti' + (c === 1 ? '' : 'a') },
+ s: function (c) { return 'sekunti' + (c === 1 ? '' : 'a') },
+ ms: function (c) { return 'millisekunti' + (c === 1 ? '' : 'a') },
+ decimal: ','
+ },
+ fr: {
+ y: function (c) { return 'an' + (c >= 2 ? 's' : '') },
+ mo: 'mois',
+ w: function (c) { return 'semaine' + (c >= 2 ? 's' : '') },
+ d: function (c) { return 'jour' + (c >= 2 ? 's' : '') },
+ h: function (c) { return 'heure' + (c >= 2 ? 's' : '') },
+ m: function (c) { return 'minute' + (c >= 2 ? 's' : '') },
+ s: function (c) { return 'seconde' + (c >= 2 ? 's' : '') },
+ ms: function (c) { return 'milliseconde' + (c >= 2 ? 's' : '') },
+ decimal: ','
+ },
+ gr: greek,
+ hr: {
+ y: function (c) {
+ if (c % 10 === 2 || c % 10 === 3 || c % 10 === 4) {
+ return 'godine'
+ }
+ return 'godina'
+ },
+ mo: function (c) {
+ if (c === 1) {
+ return 'mjesec'
+ } else if (c === 2 || c === 3 || c === 4) {
+ return 'mjeseca'
+ }
+ return 'mjeseci'
+ },
+ w: function (c) {
+ if (c % 10 === 1 && c !== 11) {
+ return 'tjedan'
+ }
+ return 'tjedna'
+ },
+ d: function (c) { return c === 1 ? 'dan' : 'dana' },
+ h: function (c) {
+ if (c === 1) {
+ return 'sat'
+ } else if (c === 2 || c === 3 || c === 4) {
+ return 'sata'
+ }
+ return 'sati'
+ },
+ m: function (c) {
+ var mod10 = c % 10
+ if ((mod10 === 2 || mod10 === 3 || mod10 === 4) && (c < 10 || c > 14)) {
+ return 'minute'
+ }
+ return 'minuta'
+ },
+ s: function (c) {
+ if ((c === 10 || c === 11 || c === 12 || c === 13 || c === 14 || c === 16 || c === 17 || c === 18 || c === 19) || (c % 10 === 5)) {
+ return 'sekundi'
+ } else if (c % 10 === 1) {
+ return 'sekunda'
+ } else if (c % 10 === 2 || c % 10 === 3 || c % 10 === 4) {
+ return 'sekunde'
+ }
+ return 'sekundi'
+ },
+ ms: function (c) {
+ if (c === 1) {
+ return 'milisekunda'
+ } else if (c % 10 === 2 || c % 10 === 3 || c % 10 === 4) {
+ return 'milisekunde'
+ }
+ return 'milisekundi'
+ },
+ decimal: ','
+ },
+ hu: {
+ y: 'év',
+ mo: 'hónap',
+ w: 'hét',
+ d: 'nap',
+ h: 'óra',
+ m: 'perc',
+ s: 'másodperc',
+ ms: 'ezredmásodperc',
+ decimal: ','
+ },
+ id: {
+ y: 'tahun',
+ mo: 'bulan',
+ w: 'minggu',
+ d: 'hari',
+ h: 'jam',
+ m: 'menit',
+ s: 'detik',
+ ms: 'milidetik',
+ decimal: '.'
+ },
+ is: {
+ y: 'ár',
+ mo: function (c) { return 'mánuð' + (c === 1 ? 'ur' : 'ir') },
+ w: function (c) { return 'vik' + (c === 1 ? 'a' : 'ur') },
+ d: function (c) { return 'dag' + (c === 1 ? 'ur' : 'ar') },
+ h: function (c) { return 'klukkutím' + (c === 1 ? 'i' : 'ar') },
+ m: function (c) { return 'mínút' + (c === 1 ? 'a' : 'ur') },
+ s: function (c) { return 'sekúnd' + (c === 1 ? 'a' : 'ur') },
+ ms: function (c) { return 'millisekúnd' + (c === 1 ? 'a' : 'ur') },
+ decimal: '.'
+ },
+ it: {
+ y: function (c) { return 'ann' + (c === 1 ? 'o' : 'i') },
+ mo: function (c) { return 'mes' + (c === 1 ? 'e' : 'i') },
+ w: function (c) { return 'settiman' + (c === 1 ? 'a' : 'e') },
+ d: function (c) { return 'giorn' + (c === 1 ? 'o' : 'i') },
+ h: function (c) { return 'or' + (c === 1 ? 'a' : 'e') },
+ m: function (c) { return 'minut' + (c === 1 ? 'o' : 'i') },
+ s: function (c) { return 'second' + (c === 1 ? 'o' : 'i') },
+ ms: function (c) { return 'millisecond' + (c === 1 ? 'o' : 'i') },
+ decimal: ','
+ },
+ ja: {
+ y: '年',
+ mo: '月',
+ w: '週',
+ d: '日',
+ h: '時間',
+ m: '分',
+ s: '秒',
+ ms: 'ミリ秒',
+ decimal: '.'
+ },
+ ko: {
+ y: '년',
+ mo: '개월',
+ w: '주일',
+ d: '일',
+ h: '시간',
+ m: '분',
+ s: '초',
+ ms: '밀리 초',
+ decimal: '.'
+ },
+ lo: {
+ y: 'ປີ',
+ mo: 'ເດືອນ',
+ w: 'ອາທິດ',
+ d: 'ມື້',
+ h: 'ຊົ່ວໂມງ',
+ m: 'ນາທີ',
+ s: 'ວິນາທີ',
+ ms: 'ມິນລິວິນາທີ',
+ decimal: ','
+ },
+ lt: {
+ y: function (c) { return ((c % 10 === 0) || (c % 100 >= 10 && c % 100 <= 20)) ? 'metų' : 'metai' },
+ mo: function (c) { return ['mėnuo', 'mėnesiai', 'mėnesių'][getLithuanianForm(c)] },
+ w: function (c) { return ['savaitė', 'savaitės', 'savaičių'][getLithuanianForm(c)] },
+ d: function (c) { return ['diena', 'dienos', 'dienų'][getLithuanianForm(c)] },
+ h: function (c) { return ['valanda', 'valandos', 'valandų'][getLithuanianForm(c)] },
+ m: function (c) { return ['minutė', 'minutės', 'minučių'][getLithuanianForm(c)] },
+ s: function (c) { return ['sekundė', 'sekundės', 'sekundžių'][getLithuanianForm(c)] },
+ ms: function (c) { return ['milisekundė', 'milisekundės', 'milisekundžių'][getLithuanianForm(c)] },
+ decimal: ','
+ },
+ ms: {
+ y: 'tahun',
+ mo: 'bulan',
+ w: 'minggu',
+ d: 'hari',
+ h: 'jam',
+ m: 'minit',
+ s: 'saat',
+ ms: 'milisaat',
+ decimal: '.'
+ },
+ nl: {
+ y: 'jaar',
+ mo: function (c) { return c === 1 ? 'maand' : 'maanden' },
+ w: function (c) { return c === 1 ? 'week' : 'weken' },
+ d: function (c) { return c === 1 ? 'dag' : 'dagen' },
+ h: 'uur',
+ m: function (c) { return c === 1 ? 'minuut' : 'minuten' },
+ s: function (c) { return c === 1 ? 'seconde' : 'seconden' },
+ ms: function (c) { return c === 1 ? 'milliseconde' : 'milliseconden' },
+ decimal: ','
+ },
+ no: {
+ y: 'år',
+ mo: function (c) { return 'måned' + (c === 1 ? '' : 'er') },
+ w: function (c) { return 'uke' + (c === 1 ? '' : 'r') },
+ d: function (c) { return 'dag' + (c === 1 ? '' : 'er') },
+ h: function (c) { return 'time' + (c === 1 ? '' : 'r') },
+ m: function (c) { return 'minutt' + (c === 1 ? '' : 'er') },
+ s: function (c) { return 'sekund' + (c === 1 ? '' : 'er') },
+ ms: function (c) { return 'millisekund' + (c === 1 ? '' : 'er') },
+ decimal: ','
+ },
+ pl: {
+ y: function (c) { return ['rok', 'roku', 'lata', 'lat'][getPolishForm(c)] },
+ mo: function (c) { return ['miesiąc', 'miesiąca', 'miesiące', 'miesięcy'][getPolishForm(c)] },
+ w: function (c) { return ['tydzień', 'tygodnia', 'tygodnie', 'tygodni'][getPolishForm(c)] },
+ d: function (c) { return ['dzień', 'dnia', 'dni', 'dni'][getPolishForm(c)] },
+ h: function (c) { return ['godzina', 'godziny', 'godziny', 'godzin'][getPolishForm(c)] },
+ m: function (c) { return ['minuta', 'minuty', 'minuty', 'minut'][getPolishForm(c)] },
+ s: function (c) { return ['sekunda', 'sekundy', 'sekundy', 'sekund'][getPolishForm(c)] },
+ ms: function (c) { return ['milisekunda', 'milisekundy', 'milisekundy', 'milisekund'][getPolishForm(c)] },
+ decimal: ','
+ },
+ pt: {
+ y: function (c) { return 'ano' + (c === 1 ? '' : 's') },
+ mo: function (c) { return c === 1 ? 'mês' : 'meses' },
+ w: function (c) { return 'semana' + (c === 1 ? '' : 's') },
+ d: function (c) { return 'dia' + (c === 1 ? '' : 's') },
+ h: function (c) { return 'hora' + (c === 1 ? '' : 's') },
+ m: function (c) { return 'minuto' + (c === 1 ? '' : 's') },
+ s: function (c) { return 'segundo' + (c === 1 ? '' : 's') },
+ ms: function (c) { return 'milissegundo' + (c === 1 ? '' : 's') },
+ decimal: ','
+ },
+ ro: {
+ y: function (c) { return c === 1 ? 'an' : 'ani' },
+ mo: function (c) { return c === 1 ? 'lună' : 'luni' },
+ w: function (c) { return c === 1 ? 'săptămână' : 'săptămâni' },
+ d: function (c) { return c === 1 ? 'zi' : 'zile' },
+ h: function (c) { return c === 1 ? 'oră' : 'ore' },
+ m: function (c) { return c === 1 ? 'minut' : 'minute' },
+ s: function (c) { return c === 1 ? 'secundă' : 'secunde' },
+ ms: function (c) { return c === 1 ? 'milisecundă' : 'milisecunde' },
+ decimal: ','
+ },
+ ru: {
+ y: function (c) { return ['лет', 'год', 'года'][getSlavicForm(c)] },
+ mo: function (c) { return ['месяцев', 'месяц', 'месяца'][getSlavicForm(c)] },
+ w: function (c) { return ['недель', 'неделя', 'недели'][getSlavicForm(c)] },
+ d: function (c) { return ['дней', 'день', 'дня'][getSlavicForm(c)] },
+ h: function (c) { return ['часов', 'час', 'часа'][getSlavicForm(c)] },
+ m: function (c) { return ['минут', 'минута', 'минуты'][getSlavicForm(c)] },
+ s: function (c) { return ['секунд', 'секунда', 'секунды'][getSlavicForm(c)] },
+ ms: function (c) { return ['миллисекунд', 'миллисекунда', 'миллисекунды'][getSlavicForm(c)] },
+ decimal: ','
+ },
+ uk: {
+ y: function (c) { return ['років', 'рік', 'роки'][getSlavicForm(c)] },
+ mo: function (c) { return ['місяців', 'місяць', 'місяці'][getSlavicForm(c)] },
+ w: function (c) { return ['тижнів', 'тиждень', 'тижні'][getSlavicForm(c)] },
+ d: function (c) { return ['днів', 'день', 'дні'][getSlavicForm(c)] },
+ h: function (c) { return ['годин', 'година', 'години'][getSlavicForm(c)] },
+ m: function (c) { return ['хвилин', 'хвилина', 'хвилини'][getSlavicForm(c)] },
+ s: function (c) { return ['секунд', 'секунда', 'секунди'][getSlavicForm(c)] },
+ ms: function (c) { return ['мілісекунд', 'мілісекунда', 'мілісекунди'][getSlavicForm(c)] },
+ decimal: ','
+ },
+ ur: {
+ y: 'سال',
+ mo: function (c) { return c === 1 ? 'مہینہ' : 'مہینے' },
+ w: function (c) { return c === 1 ? 'ہفتہ' : 'ہفتے' },
+ d: 'دن',
+ h: function (c) { return c === 1 ? 'گھنٹہ' : 'گھنٹے' },
+ m: 'منٹ',
+ s: 'سیکنڈ',
+ ms: 'ملی سیکنڈ',
+ decimal: '.'
+ },
+ sk: {
+ y: function (c) { return ['rok', 'roky', 'roky', 'rokov'][getCzechOrSlovakForm(c)] },
+ mo: function (c) { return ['mesiac', 'mesiace', 'mesiace', 'mesiacov'][getCzechOrSlovakForm(c)] },
+ w: function (c) { return ['týždeň', 'týždne', 'týždne', 'týždňov'][getCzechOrSlovakForm(c)] },
+ d: function (c) { return ['deň', 'dni', 'dni', 'dní'][getCzechOrSlovakForm(c)] },
+ h: function (c) { return ['hodina', 'hodiny', 'hodiny', 'hodín'][getCzechOrSlovakForm(c)] },
+ m: function (c) { return ['minúta', 'minúty', 'minúty', 'minút'][getCzechOrSlovakForm(c)] },
+ s: function (c) { return ['sekunda', 'sekundy', 'sekundy', 'sekúnd'][getCzechOrSlovakForm(c)] },
+ ms: function (c) { return ['milisekunda', 'milisekundy', 'milisekundy', 'milisekúnd'][getCzechOrSlovakForm(c)] },
+ decimal: ','
+ },
+ sv: {
+ y: 'år',
+ mo: function (c) { return 'månad' + (c === 1 ? '' : 'er') },
+ w: function (c) { return 'veck' + (c === 1 ? 'a' : 'or') },
+ d: function (c) { return 'dag' + (c === 1 ? '' : 'ar') },
+ h: function (c) { return 'timm' + (c === 1 ? 'e' : 'ar') },
+ m: function (c) { return 'minut' + (c === 1 ? '' : 'er') },
+ s: function (c) { return 'sekund' + (c === 1 ? '' : 'er') },
+ ms: function (c) { return 'millisekund' + (c === 1 ? '' : 'er') },
+ decimal: ','
+ },
+ tr: {
+ y: 'yıl',
+ mo: 'ay',
+ w: 'hafta',
+ d: 'gün',
+ h: 'saat',
+ m: 'dakika',
+ s: 'saniye',
+ ms: 'milisaniye',
+ decimal: ','
+ },
+ th: {
+ y: 'ปี',
+ mo: 'เดือน',
+ w: 'อาทิตย์',
+ d: 'วัน',
+ h: 'ชั่วโมง',
+ m: 'นาที',
+ s: 'วินาที',
+ ms: 'มิลลิวินาที',
+ decimal: '.'
+ },
+ vi: {
+ y: 'năm',
+ mo: 'tháng',
+ w: 'tuần',
+ d: 'ngày',
+ h: 'giờ',
+ m: 'phút',
+ s: 'giây',
+ ms: 'mili giây',
+ decimal: ','
+ },
+ zh_CN: {
+ y: '年',
+ mo: '个月',
+ w: '周',
+ d: '天',
+ h: '小时',
+ m: '分钟',
+ s: '秒',
+ ms: '毫秒',
+ decimal: '.'
+ },
+ zh_TW: {
+ y: '年',
+ mo: '個月',
+ w: '周',
+ d: '天',
+ h: '小時',
+ m: '分鐘',
+ s: '秒',
+ ms: '毫秒',
+ decimal: '.'
+ }
+ }
+
+ // You can create a humanizer, which returns a function with default
+ // parameters.
+ function humanizer (passedOptions) {
+ var result = function humanizer (ms, humanizerOptions) {
+ var options = extend({}, result, humanizerOptions || {})
+ return doHumanization(ms, options)
+ }
+
+ return extend(result, {
+ language: 'en',
+ delimiter: ', ',
+ spacer: ' ',
+ conjunction: '',
+ serialComma: true,
+ units: ['y', 'mo', 'w', 'd', 'h', 'm', 's'],
+ languages: {},
+ round: false,
+ unitMeasures: {
+ y: 31557600000,
+ mo: 2629800000,
+ w: 604800000,
+ d: 86400000,
+ h: 3600000,
+ m: 60000,
+ s: 1000,
+ ms: 1
+ }
+ }, passedOptions)
+ }
+
+ // The main function is just a wrapper around a default humanizer.
+ var humanizeDuration = humanizer({})
+
+ // Build dictionary from options
+ function getDictionary (options) {
+ var languagesFromOptions = [options.language]
+
+ if (options.hasOwnProperty('fallbacks')) {
+ if (isArray(options.fallbacks) && options.fallbacks.length) {
+ languagesFromOptions = languagesFromOptions.concat(options.fallbacks)
+ } else {
+ throw new Error('fallbacks must be an array with at least one element')
+ }
+ }
+
+ for (var i = 0; i < languagesFromOptions.length; i++) {
+ var languageToTry = languagesFromOptions[i]
+ if (options.languages.hasOwnProperty(languageToTry)) {
+ return options.languages[languageToTry]
+ } else if (languages.hasOwnProperty(languageToTry)) {
+ return languages[languageToTry]
+ }
+ }
+
+ throw new Error('No language found.')
+ }
+
+ // doHumanization does the bulk of the work.
+ function doHumanization (ms, options) {
+ var i, len, piece
+
+ // Make sure we have a positive number.
+ // Has the nice sideffect of turning Number objects into primitives.
+ ms = Math.abs(ms)
+
+ var dictionary = getDictionary(options)
+ var pieces = []
+
+ // Start at the top and keep removing units, bit by bit.
+ var unitName, unitMS, unitCount
+ for (i = 0, len = options.units.length; i < len; i++) {
+ unitName = options.units[i]
+ unitMS = options.unitMeasures[unitName]
+
+ // What's the number of full units we can fit?
+ if (i + 1 === len) {
+ if (options.hasOwnProperty('maxDecimalPoints')) {
+ // We need to use this expValue to avoid rounding functionality of toFixed call
+ var expValue = Math.pow(10, options.maxDecimalPoints)
+ var unitCountFloat = (ms / unitMS)
+ unitCount = parseFloat((Math.floor(expValue * unitCountFloat) / expValue).toFixed(options.maxDecimalPoints))
+ } else {
+ unitCount = ms / unitMS
+ }
+ } else {
+ unitCount = Math.floor(ms / unitMS)
+ }
+
+ // Add the string.
+ pieces.push({
+ unitCount: unitCount,
+ unitName: unitName
+ })
+
+ // Remove what we just figured out.
+ ms -= unitCount * unitMS
+ }
+
+ var firstOccupiedUnitIndex = 0
+ for (i = 0; i < pieces.length; i++) {
+ if (pieces[i].unitCount) {
+ firstOccupiedUnitIndex = i
+ break
+ }
+ }
+
+ if (options.round) {
+ var ratioToLargerUnit, previousPiece
+ for (i = pieces.length - 1; i >= 0; i--) {
+ piece = pieces[i]
+ piece.unitCount = Math.round(piece.unitCount)
+
+ if (i === 0) { break }
+
+ previousPiece = pieces[i - 1]
+
+ ratioToLargerUnit = options.unitMeasures[previousPiece.unitName] / options.unitMeasures[piece.unitName]
+ if ((piece.unitCount % ratioToLargerUnit) === 0 || (options.largest && ((options.largest - 1) < (i - firstOccupiedUnitIndex)))) {
+ previousPiece.unitCount += piece.unitCount / ratioToLargerUnit
+ piece.unitCount = 0
+ }
+ }
+ }
+
+ var result = []
+ for (i = 0, pieces.length; i < len; i++) {
+ piece = pieces[i]
+ if (piece.unitCount) {
+ result.push(render(piece.unitCount, piece.unitName, dictionary, options))
+ }
+
+ if (result.length === options.largest) { break }
+ }
+
+ if (result.length) {
+ if (!options.conjunction || result.length === 1) {
+ return result.join(options.delimiter)
+ } else if (result.length === 2) {
+ return result.join(options.conjunction)
+ } else if (result.length > 2) {
+ return result.slice(0, -1).join(options.delimiter) + (options.serialComma ? ',' : '') + options.conjunction + result.slice(-1)
+ }
+ } else {
+ return render(0, options.units[options.units.length - 1], dictionary, options)
+ }
+ }
+
+ function render (count, type, dictionary, options) {
+ var decimal
+ if (options.decimal === void 0) {
+ decimal = dictionary.decimal
+ } else {
+ decimal = options.decimal
+ }
+
+ var countStr = count.toString().replace('.', decimal)
+
+ var dictionaryValue = dictionary[type]
+ var word
+ if (typeof dictionaryValue === 'function') {
+ word = dictionaryValue(count)
+ } else {
+ word = dictionaryValue
+ }
+
+ return countStr + options.spacer + word
+ }
+
+ function extend (destination) {
+ var source
+ for (var i = 1; i < arguments.length; i++) {
+ source = arguments[i]
+ for (var prop in source) {
+ if (source.hasOwnProperty(prop)) {
+ destination[prop] = source[prop]
+ }
+ }
+ }
+ return destination
+ }
+
+ // Internal helper function for Polish language.
+ function getPolishForm (c) {
+ if (c === 1) {
+ return 0
+ } else if (Math.floor(c) !== c) {
+ return 1
+ } else if (c % 10 >= 2 && c % 10 <= 4 && !(c % 100 > 10 && c % 100 < 20)) {
+ return 2
+ } else {
+ return 3
+ }
+ }
+
+ // Internal helper function for Russian and Ukranian languages.
+ function getSlavicForm (c) {
+ if (Math.floor(c) !== c) {
+ return 2
+ } else if ((c % 100 >= 5 && c % 100 <= 20) || (c % 10 >= 5 && c % 10 <= 9) || c % 10 === 0) {
+ return 0
+ } else if (c % 10 === 1) {
+ return 1
+ } else if (c > 1) {
+ return 2
+ } else {
+ return 0
+ }
+ }
+
+ // Internal helper function for Slovak language.
+ function getCzechOrSlovakForm (c) {
+ if (c === 1) {
+ return 0
+ } else if (Math.floor(c) !== c) {
+ return 1
+ } else if (c % 10 >= 2 && c % 10 <= 4 && c % 100 < 10) {
+ return 2
+ } else {
+ return 3
+ }
+ }
+
+ // Internal helper function for Lithuanian language.
+ function getLithuanianForm (c) {
+ if (c === 1 || (c % 10 === 1 && c % 100 > 20)) {
+ return 0
+ } else if (Math.floor(c) !== c || (c % 10 >= 2 && c % 100 > 20) || (c % 10 >= 2 && c % 100 < 10)) {
+ return 1
+ } else {
+ return 2
+ }
+ }
+
+ // Internal helper function for Arabic language.
+ function getArabicForm (c) {
+ if (c <= 2) { return 0 }
+ if (c > 2 && c < 11) { return 1 }
+ return 0
+ }
+
+ // We need to make sure we support browsers that don't have
+ // `Array.isArray`, so we define a fallback here.
+ var isArray = Array.isArray || function (arg) {
+ return Object.prototype.toString.call(arg) === '[object Array]'
+ }
+
+ humanizeDuration.getSupportedLanguages = function getSupportedLanguages () {
+ var result = []
+ for (var language in languages) {
+ if (languages.hasOwnProperty(language) && language !== 'gr') {
+ result.push(language)
+ }
+ }
+ return result
+ }
+
+ humanizeDuration.humanizer = humanizer
+
+ if (typeof define === 'function' && define.amd) {
+ define(function () {
+ return humanizeDuration
+ })
+ } else if (typeof module !== 'undefined' && module.exports) {
+ module.exports = humanizeDuration
+ } else {
+ this.humanizeDuration = humanizeDuration
+ }
+})(); // eslint-disable-line semi
\ No newline at end of file
diff --git a/odex25_project/web_widget_time_delta/static/src/lib/duration-picker/README.md b/odex25_project/web_widget_time_delta/static/src/lib/duration-picker/README.md
new file mode 100644
index 000000000..ce90303df
--- /dev/null
+++ b/odex25_project/web_widget_time_delta/static/src/lib/duration-picker/README.md
@@ -0,0 +1,56 @@
+# duration-picker
+copy `bootstrap-duration-picker.css` and `bootstrap-duration-picker.js` files to your project.
+## Dependencies
+
+- jQuery 1.*
+- Bootstrap 3.* (for styling only)
+
+## Usage
+
+```js
+$('.duration-picker').durationPicker();
+
+// or
+
+$('.duration-picker').durationPicker({
+
+ // optional object with translations (English is used by default)
+ translations: {
+ day: 'dia',
+ hour: 'hora',
+ minute: 'minuto',
+ second: 'segundo',
+ days: 'dias',
+ hours: 'horas',
+ minutes: 'minutos',
+ seconds: 'segundos',
+ },
+
+ // defines whether to show seconds or not
+ showSeconds: false,
+
+ // defines whether to show days or not
+ showDays: true,
+
+ // callback function that is passed value in seconds every time duration is changed
+ onChanged: function (value) {
+ console.log(value);
+ }
+});
+```
+
+## Public methods
+
+
+
+ Method
+ Example
+ Description
+
+
+ setValue
+ $('#selector').data('durationPicker').setValue(0);
+ Allows to reinitialize duration picker value after it's been created. Accepts new number of seconds
+
+
+
diff --git a/odex25_project/web_widget_time_delta/static/src/lib/duration-picker/jquery-duration-picker.css b/odex25_project/web_widget_time_delta/static/src/lib/duration-picker/jquery-duration-picker.css
new file mode 100644
index 000000000..ec782cccd
--- /dev/null
+++ b/odex25_project/web_widget_time_delta/static/src/lib/duration-picker/jquery-duration-picker.css
@@ -0,0 +1,19 @@
+
+.bdp-input input[disabled]{
+
+ background-color: #fff;
+}
+
+.bdp-input input {
+ display: inline-block;
+ margin-bottom: 3px;
+ width: 40px;
+}
+
+
+.bdp-block {
+ display: inline-block;
+ line-height: 1;
+ text-align: center;
+ padding: 5px 3px;
+}
\ No newline at end of file
diff --git a/odex25_project/web_widget_time_delta/static/src/lib/duration-picker/jquery-duration-picker.js b/odex25_project/web_widget_time_delta/static/src/lib/duration-picker/jquery-duration-picker.js
new file mode 100644
index 000000000..4f0577030
--- /dev/null
+++ b/odex25_project/web_widget_time_delta/static/src/lib/duration-picker/jquery-duration-picker.js
@@ -0,0 +1,164 @@
+'use strict';
+
+(function iife($) {
+
+ $.DurationPicker = function DurationPicker(mainElement, options) {
+
+ var defaults = {
+ translations: {
+ day: 'day',
+ hour: 'hour',
+ minute: 'minute',
+ second: 'second',
+ days: 'days',
+ hours: 'hours',
+ minutes: 'minutes',
+ seconds: 'seconds'
+ },
+ showSeconds: false,
+ showDays: true
+ };
+
+ var plugin = this;
+
+ plugin.settings = {};
+
+ var mainInput = $(mainElement);
+
+ plugin.init = function init() {
+ plugin.settings = $.extend({}, defaults, options);
+
+ var mainInputReplacer = $('', {
+ class: 'bdp-input',
+ html: [buildDisplayBlock('days', !plugin.settings.showDays), buildDisplayBlock('hours', false, plugin.settings.showDays ? 23 : 99999), buildDisplayBlock('minutes', false, 59), buildDisplayBlock('seconds', !plugin.settings.showSeconds, 59)]
+ });
+
+ mainInput.after(mainInputReplacer).hide();
+
+ if (mainInput.val() === '') mainInput.val(0);
+ plugin.setValue(mainInput.val());
+ };
+
+ var inputs = [];
+ var labels = [];
+ var disabled = mainInput.hasClass('readonly') || mainInput.attr('readonly') === 'readonly';
+
+ var days = 0;
+ var hours = 0;
+ var minutes = 0;
+ var seconds = 0;
+
+ //
+ // private methods
+ //
+ function translate(key) {
+ return plugin.settings.translations[key];
+ }
+
+ function updateWordLabel(value, label) {
+ var text = value === 1 ? label.substring(0, label.length - 1) : label;
+ labels[label].text(translate(text));
+ }
+
+ function updateUI() {
+ var total = seconds + minutes * 60 + hours * 60 * 60 + days * 24 * 60 * 60;
+ mainInput.val(total);
+ mainInput.change();
+
+ updateWordLabel(days, 'days');
+ updateWordLabel(hours, 'hours');
+ updateWordLabel(minutes, 'minutes');
+ updateWordLabel(seconds, 'seconds');
+
+ inputs.days.val(days);
+ inputs.hours.val(hours);
+ inputs.minutes.val(minutes);
+ inputs.seconds.val(seconds);
+
+ if (typeof plugin.settings.onChanged === 'function') {
+ plugin.settings.onChanged(mainInput.val());
+ }
+ }
+
+ function durationPickerChanged() {
+ days = parseInt(inputs.days.val(), 10) || 0;
+ hours = parseInt(inputs.hours.val(), 10) || 0;
+ minutes = parseInt(inputs.minutes.val(), 10) || 0;
+ seconds = parseInt(inputs.seconds.val(), 10) || 0;
+ updateUI();
+ }
+
+ function buildDisplayBlock(id, hidden, max) {
+ var input = $('
', {
+ class: 'form-control input-sm',
+ type: 'number',
+ min: 0,
+ value: 0,
+ disabled: disabled
+ }).change(durationPickerChanged);
+
+ if (max) {
+ input.attr('max', max);
+ }
+ inputs[id] = input;
+
+ var label = $('
', {
+ id: 'bdp-' + id + '-label',
+ text: translate(id)
+ });
+ labels[id] = label;
+
+ return $('
', {
+ class: 'bdp-block ' + (hidden ? 'd-none' : ''),
+ html: [input, label]
+ });
+ }
+
+ //
+ // public methods
+ //
+
+ function getValue() { return mainInput.val(); }
+
+ plugin.getValue = function() {
+ return getValue();
+ };
+
+ plugin.setValue = function setValue(value) {
+ mainInput.val(value);
+
+ var total = parseInt(value, 10);
+ seconds = total % 60;
+ total = Math.floor(total / 60);
+ minutes = total % 60;
+ total = Math.floor(total / 60);
+
+ if (plugin.settings.showDays) {
+ hours = total % 24;
+ days = Math.floor(total / 24);
+ } else {
+ hours = total;
+ days = 0;
+ }
+
+ updateUI();
+ };
+
+ plugin.destroy = function () {
+ mainInput.next('.bdp-input').remove();
+ mainInput.data('durationPicker', null).show();
+ };
+
+ plugin.init();
+ };
+
+ // eslint-disable-next-line no-param-reassign
+ $.fn.durationPicker = function durationPicker(options) {
+ return this.each(function () {
+ if (undefined === $(this).data('durationPicker')) {
+ var plugin = new $.DurationPicker(this, options);
+ $(this).data('durationPicker', plugin);
+ }
+ });
+ };
+})(jQuery); // eslint-disable-line no-undef
\ No newline at end of file
diff --git a/odex25_project/web_widget_time_delta/static/src/xml/widget.xml b/odex25_project/web_widget_time_delta/static/src/xml/widget.xml
new file mode 100644
index 000000000..99280279b
--- /dev/null
+++ b/odex25_project/web_widget_time_delta/static/src/xml/widget.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/odex25_project/web_widget_time_delta/view/web_widget_time_delta_view.xml b/odex25_project/web_widget_time_delta/view/web_widget_time_delta_view.xml
new file mode 100644
index 000000000..98e91611d
--- /dev/null
+++ b/odex25_project/web_widget_time_delta/view/web_widget_time_delta_view.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+