@workiom/frappe-gantt 1.0.25 → 1.0.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -72,7 +72,7 @@ gantt.tasks.append(...)
72
72
  gantt.tasks.refresh()
73
73
  ```
74
74
 
75
- Each task object accepts an optional `bar_label` string. When set to a truthy value and the global `show_bar_label` option is `true`, the bar renders `bar_label` instead of `name`. An empty string falls back to `name`. To hide bar labels entirely, set the `show_bar_label` option to `false`.
75
+ Each task object accepts an optional `bar_label` string. When defined (including an empty string) and the global `show_bar_label` option is `true`, the bar renders `bar_label` instead of `name`. Only `null` or `undefined` falls back to `name`. To hide bar labels entirely, set the `show_bar_label` option to `false`.
76
76
 
77
77
  ### Configuration
78
78
 
@@ -108,7 +108,7 @@ Frappe Gantt offers a wide range of options to customize your chart.
108
108
  | `readonly_dates` | Disables editing task dates. | `true`, `false` | `false` |
109
109
  | `readonly` | Disables all editing features. | `true`, `false` | `false` |
110
110
  | `scroll_to` | Determines the starting point when chart is rendered. | `today`, `start`, `end`, or a date string. | `today` |
111
- | `show_bar_label` | Whether to render the text label inside each task bar. When `true`, label text comes from `task.bar_label` if truthy, otherwise from `task.name`. | `true`, `false` | `true` |
111
+ | `show_bar_label` | Whether to render the text label inside each task bar. When `true`, label text comes from `task.bar_label` when defined (including empty string), otherwise from `task.name`. | `true`, `false` | `true` |
112
112
  | `show_expected_progress` | Shows expected progress for tasks. | `true`, `false` | `false` |
113
113
  | `task_add_icon_position` | Position of the add task icon relative to task bar. | `null` (hidden), `'before'`, `'after'` | `null` |
114
114
  | `today_button` | Adds a button to navigate to today's date. | `true`, `false` | `true` |
@@ -772,7 +772,7 @@ class B {
772
772
  draw_label() {
773
773
  let t = this.x + this.$bar.getWidth() / 2;
774
774
  this.task.thumbnail && (t = this.x + this.image_size + 5);
775
- const e = this.gantt.options.show_bar_label ? this.task.bar_label || this.task.name : "";
775
+ const e = this.gantt.options.show_bar_label ? this.task.bar_label ?? this.task.name : "";
776
776
  this.$bar_label = w("text", {
777
777
  x: t,
778
778
  y: this.y + this.height / 2,
@@ -98,7 +98,7 @@
98
98
  V ${s-o}
99
99
  a ${o} ${o} 0 0 1 ${-o} ${o}
100
100
  H ${e}
101
- m 5 -5 l -5 5 l 5 5`}_get_connected_bars(){const t=this.from_task.task.id,e=this.to_task.task.id;return Array.from(this.gantt.$svg.querySelectorAll(`[data-id="${CSS.escape(t)}"], [data-id="${CSS.escape(e)}"]`))}draw(){let t="";this.is_invalid?t="arrow-invalid":this.is_critical&&(t="arrow-critical"),this.element=w("path",{d:this.path,"data-from":this.from_task.task.id,"data-to":this.to_task.task.id,class:t}),this.hit_element=w("path",{d:this.path,stroke:"transparent","stroke-width":15,fill:"none",style:"pointer-events: stroke; cursor: pointer;"}),this.hit_element.addEventListener("mouseenter",()=>{this.is_hovered=!0,this.element.classList.add("arrow-hover");const e=this.is_invalid?"bar-arrow-invalid":this.is_critical?"bar-arrow-critical":"bar-arrow-hover";this._get_connected_bars().forEach(i=>{const s=i.querySelector(".bar");s&&s.classList.add(e)}),this._show_label()}),this.hit_element.addEventListener("mouseleave",()=>{this.is_hovered=!1,this.element.classList.remove("arrow-hover"),this._get_connected_bars().forEach(e=>{const i=e.querySelector(".bar");i&&(i.classList.remove("bar-arrow-hover"),this.is_active||i.classList.remove("bar-arrow-critical","bar-arrow-invalid"))}),!this.is_active&&!this.is_hovered&&this._hide_label()}),this.hit_element.addEventListener("click",e=>{e.stopPropagation(),this.is_active?this.gantt.set_active_arrow(null):this.gantt.set_active_arrow(this)})}_get_type_abbr(){return{"finish-to-start":"FS","start-to-start":"SS","finish-to-finish":"FF","start-to-finish":"SF"}[this.dependency_type]||"FS"}_show_label(){if(this.label_element)return;const t=this._get_type_abbr(),e=21,i=20,{x:s,y:n,side:a}=this.label_pos,o=a==="left"?s-10-e/2:s+10+e/2,d=n;this.label_element=w("g",{class:"arrow-type-label"});const h=w("rect",{x:o-e/2,y:d-i/2,width:e,height:i,rx:3}),_=w("text",{x:o,y:d,"dominant-baseline":"middle","text-anchor":"middle"});_.textContent=t,this.label_element.appendChild(h),this.label_element.appendChild(_),this.label_element.addEventListener("mouseenter",()=>{this.hit_element.dispatchEvent(new MouseEvent("mouseenter",{bubbles:!1}))}),this.label_element.addEventListener("mouseleave",()=>{this.hit_element.dispatchEvent(new MouseEvent("mouseleave",{bubbles:!1}))}),this.label_element.addEventListener("click",l=>{l.stopPropagation(),this._toggle_type_dropdown()}),this.gantt.layers.arrow.appendChild(this.label_element)}_hide_label(){this.label_element&&(this.label_element.remove(),this.label_element=null)}_show_type_dropdown(){if(this.gantt.options.readonly||this.type_dropdown||(this.is_active||this.gantt.set_active_arrow(this),!this.label_element))return;const t=[{abbr:"FS",label:"Finish to Start",value:"finish-to-start"},{abbr:"SS",label:"Start to Start",value:"start-to-start"},{abbr:"FF",label:"Finish to Finish",value:"finish-to-finish"},{abbr:"SF",label:"Start to Finish",value:"start-to-finish"}];this.type_dropdown=document.createElement("div"),this.type_dropdown.className="arrow-type-dropdown",this.type_dropdown.addEventListener("click",a=>a.stopPropagation()),t.forEach(({abbr:a,label:o,value:d})=>{const h=document.createElement("div");h.className="arrow-type-option"+(d===this.dependency_type?" active":"");const _=document.createElement("strong");_.textContent=a;const l=document.createElement("span");l.textContent=o,h.appendChild(_),h.appendChild(l),h.addEventListener("click",p=>{p.stopPropagation(),this.gantt.change_dependency_type(this,d)}),this.type_dropdown.appendChild(h)}),this.gantt.$container.appendChild(this.type_dropdown);const e=this.label_element.getBoundingClientRect(),i=this.gantt.$container.getBoundingClientRect();this.type_dropdown.style.top=e.bottom-i.top+this.gantt.$container.scrollTop+"px",this.type_dropdown.style.left=e.left-i.left+this.gantt.$container.scrollLeft+"px";const s=this.label_element.querySelector("text"),n=this.label_element.querySelector("rect");if(s&&(s.textContent=this._get_type_abbr()+" ▾"),n){const o=parseFloat(n.getAttribute("width")),d=parseFloat(n.getAttribute("x"))+o/2;n.setAttribute("x",String(d-34/2)),n.setAttribute("width",String(34))}}_hide_type_dropdown(){var i,s;this.type_dropdown&&(this.type_dropdown.remove(),this.type_dropdown=null);const t=(i=this.label_element)==null?void 0:i.querySelector("text"),e=(s=this.label_element)==null?void 0:s.querySelector("rect");if(t&&(t.textContent=this._get_type_abbr()),e){const a=parseFloat(e.getAttribute("x"))+parseFloat(e.getAttribute("width"))/2;e.setAttribute("x",String(a-21/2)),e.setAttribute("width",String(21))}}_toggle_type_dropdown(){this.type_dropdown?this._hide_type_dropdown():this._show_type_dropdown()}activate(){this.is_active=!0,this.element.classList.add("arrow-active"),this._show_label();const t=this.is_invalid?"bar-arrow-invalid":this.is_critical?"bar-arrow-critical":"bar-arrow-active";this._get_connected_bars().forEach(e=>{const i=e.querySelector(".bar");i&&i.classList.add(t)})}deactivate(){this._hide_type_dropdown(),this.is_active=!1,this.element.classList.remove("arrow-active"),this._hide_label(),this._get_connected_bars().forEach(t=>{const e=t.querySelector(".bar");e&&e.classList.remove("bar-arrow-active","bar-arrow-critical","bar-arrow-invalid")})}update(){this.calculate_path(),this.element.setAttribute("d",this.path),this.hit_element.setAttribute("d",this.path),this.is_invalid=this.check_invalid_dependency();let t="";this.is_invalid?t="arrow-invalid":this.is_critical&&(t="arrow-critical"),this.is_hovered&&(t+=" arrow-hover"),this.is_active&&(t+=" arrow-active"),this.element.setAttribute("class",t.trim())}}class G{constructor(t,e){this.set_defaults(t,e),this.prepare_wrappers(),this.prepare_helpers(),this.refresh()}refresh(){this.bar_group.innerHTML="",this.handle_group.innerHTML="",this.task.custom_class?this.group.classList.add(this.task.custom_class):this.group.classList=["bar-wrapper"],this.unbind(),this.prepare_values(),this.draw(),this.bind()}set_defaults(t,e){this.action_completed=!1,this.gantt=t,this.task=e,this.name=this.name||"",this.is_dragging=!1,this.is_hovering_bar=!1,this.is_hovering_icon=!1,this.add_icon_hide_timeout=null}prepare_wrappers(){this.group=w("g",{class:"bar-wrapper"+(this.task.custom_class?" "+this.task.custom_class:""),"data-id":this.task.id}),this.bar_group=w("g",{class:"bar-group",append_to:this.group}),this.handle_group=w("g",{class:"handle-group",append_to:this.group})}prepare_values(){this.invalid=this.task.invalid,this.height=this.gantt.options.bar_height,this.image_size=this.height-5,(!this.task._start||!(this.task._start instanceof Date))&&(this.task._start=new Date(this.task.start)),(!this.task._end||!(this.task._end instanceof Date))&&(this.task._end=new Date(this.task.end)),this.compute_x(),this.compute_y(),this.compute_duration(),this.corner_radius=this.gantt.options.bar_corner_radius,this.width=this.gantt.config.column_width*this.duration,(!this.task.progress||this.task.progress<0)&&(this.task.progress=0),this.task.progress>100&&(this.task.progress=100)}prepare_helpers(){SVGElement.prototype.getX=function(){return+this.getAttribute("x")},SVGElement.prototype.getY=function(){return+this.getAttribute("y")},SVGElement.prototype.getWidth=function(){return+this.getAttribute("width")},SVGElement.prototype.getHeight=function(){return+this.getAttribute("height")},SVGElement.prototype.getEndX=function(){return this.getX()+this.getWidth()}}prepare_expected_progress_values(){this.compute_expected_progress(),this.expected_progress_width=this.gantt.options.column_width*this.duration*(this.expected_progress/100)||0}draw(){this.draw_bar(),this.draw_progress_bar(),this.gantt.options.show_expected_progress&&(this.prepare_expected_progress_values(),this.draw_expected_progress_bar()),this.draw_label(),this.draw_resize_handles(),this.task.thumbnail&&this.draw_thumbnail(),this.gantt.options.task_add_icon_position&&this.draw_add_task_icon(),this.draw_connector_circles()}draw_bar(){this.$bar=w("rect",{x:this.x,y:this.y,width:this.width,height:this.height,rx:this.corner_radius,ry:this.corner_radius,class:"bar",append_to:this.bar_group}),this.task.color&&(this.$bar.style.fill=this.task.color),X(this.$bar,"width",0,this.width),this.invalid&&this.$bar.classList.add("bar-invalid")}draw_expected_progress_bar(){this.invalid||(this.$expected_bar_progress=w("rect",{x:this.x,y:this.y,width:this.expected_progress_width,height:this.height,rx:this.corner_radius,ry:this.corner_radius,class:"bar-expected-progress",append_to:this.bar_group}),X(this.$expected_bar_progress,"width",0,this.expected_progress_width))}draw_progress_bar(){if(this.invalid)return;this.progress_width=this.calculate_progress_width();let t=this.corner_radius;/^((?!chrome|android).)*safari/i.test(navigator.userAgent)||(t=this.corner_radius+2),this.$bar_progress=w("rect",{x:this.x,y:this.y,width:this.progress_width,height:this.height,rx:t,ry:t,class:"bar-progress",append_to:this.bar_group}),this.task.color_progress&&(this.$bar_progress.style.fill=this.task.color_progress);const e=g.diff(this.task._start,this.gantt.gantt_start,this.gantt.config.unit)/this.gantt.config.step*this.gantt.config.column_width;this.$date_highlight&&this.$date_highlight.parentNode&&this.$date_highlight.parentNode.removeChild(this.$date_highlight);let i=this.gantt.create_el({classes:`date-range-highlight hide highlight-${CSS.escape(this.task.id)}`,width:this.width,left:e});this.$date_highlight=i,this.gantt.$lower_header.prepend(this.$date_highlight),X(this.$bar_progress,"width",0,this.progress_width)}calculate_progress_width(){const t=this.$bar.getWidth(),e=this.x+t,i=this.gantt.config.ignored_positions.reduce((d,h)=>d+(h>=this.x&&h<e),0)*this.gantt.config.column_width;let s=(t-i)*this.task.progress/100;const n=this.x+s,a=this.gantt.config.ignored_positions.reduce((d,h)=>d+(h>=this.x&&h<n),0)*this.gantt.config.column_width;s+=a;let o=this.gantt.get_ignored_region(this.x+s);for(;o.length;)s+=this.gantt.config.column_width,o=this.gantt.get_ignored_region(this.x+s);return this.progress_width=s,s}draw_label(){let t=this.x+this.$bar.getWidth()/2;this.task.thumbnail&&(t=this.x+this.image_size+5);const e=this.gantt.options.show_bar_label?this.task.bar_label||this.task.name:"";this.$bar_label=w("text",{x:t,y:this.y+this.height/2,innerHTML:e,class:"bar-label",append_to:this.bar_group}),this.task.color_text&&(this.$bar_label.style.fill=this.task.color_text),requestAnimationFrame(()=>this.update_label_position())}draw_thumbnail(){let t=10,e=2,i,s;i=w("defs",{append_to:this.bar_group}),w("rect",{id:"rect_"+this.task.id,x:this.x+t,y:this.y+e,width:this.image_size,height:this.image_size,rx:"15",class:"img_mask",append_to:i}),s=w("clipPath",{id:"clip_"+this.task.id,append_to:i}),w("use",{href:"#rect_"+this.task.id,append_to:s}),w("image",{x:this.x+t,y:this.y+e,width:this.image_size,height:this.image_size,class:"bar-img",href:this.task.thumbnail,clipPath:"clip_"+this.task.id,append_to:this.bar_group})}draw_add_task_icon(){this.icon_size=20,this.icon_padding=5;let i;if(this.gantt.options.task_add_icon_position==="before")i=this.x-20-5;else if(this.gantt.options.task_add_icon_position==="after")i=this.x+this.$bar.getWidth()+5;else return;const s=this.y+(this.height-20)/2;this.$add_icon_group=w("g",{class:"add-task-icon hide",append_to:this.handle_group}),this.$add_icon_circle=w("circle",{cx:i+20/2,cy:s+20/2,r:20/2,class:"add-task-icon-bg",append_to:this.$add_icon_group}),this.$add_icon_vertical=w("line",{x1:i+20/2,y1:s+5,x2:i+20/2,y2:s+20-5,class:"add-task-icon-plus",append_to:this.$add_icon_group}),this.$add_icon_horizontal=w("line",{x1:i+5,y1:s+20/2,x2:i+20-5,y2:s+20/2,class:"add-task-icon-plus",append_to:this.$add_icon_group}),u.on(this.$add_icon_group,"mousedown",n=>{n.stopPropagation()}),u.on(this.$add_icon_group,"mouseup",n=>{n.stopPropagation()}),u.on(this.$add_icon_group,"click",n=>{n.stopPropagation(),this.gantt.trigger_event("task_add",[this.task])}),u.on(this.$add_icon_group,"mouseenter",n=>{this.is_hovering_icon=!0,this.add_icon_hide_timeout&&(clearTimeout(this.add_icon_hide_timeout),this.add_icon_hide_timeout=null),this.$add_icon_group.classList.add("active"),this.$add_icon_group.classList.remove("hide"),n.stopPropagation()}),u.on(this.$add_icon_group,"mouseleave",()=>{this.is_hovering_icon=!1,this.$add_icon_group.classList.remove("active"),this.is_hovering_bar||this.$add_icon_group.classList.add("hide")})}draw_resize_handles(){if(this.invalid||this.gantt.options.readonly)return;const t=this.$bar,e=8;if(this.handles=[],this.gantt.options.readonly_dates||(this.handles.push(w("rect",{x:t.getEndX()-e,y:t.getY()+(this.height-this.height*.8)/2,width:e,height:this.height*.8,rx:2,ry:2,class:"handle right",append_to:this.handle_group})),this.handles.push(w("rect",{x:t.getX()-e,y:t.getY()+(this.height-this.height*.8)/2,width:e,height:this.height*.8,rx:2,ry:2,class:"handle left",append_to:this.handle_group}))),!this.gantt.options.readonly_progress){const i=this.$bar_progress;this.$handle_progress=w("circle",{cx:i.getEndX(),cy:i.getY()+i.getHeight()/2,r:4.5,class:"handle progress",append_to:this.handle_group}),this.handles.push(this.$handle_progress)}for(let i of this.handles)u.on(i,"mouseenter",()=>i.classList.add("active")),u.on(i,"mouseleave",()=>i.classList.remove("active"))}draw_connector_circles(){if(this.$connector_start=null,this.$connector_end=null,!this.gantt.options.allow_dependency_creation||this.gantt.options.readonly)return;const t=this.gantt.options.isRTL,e=this.y+this.height/2,i=t?this.x+this.width:this.x,s=t?this.x:this.x+this.width;this.$connector_start=w("circle",{class:"connector-circle connector-start","data-endpoint":"start",cx:i,cy:e,r:4,append_to:this.handle_group}),this.$connector_end=w("circle",{class:"connector-circle connector-end","data-endpoint":"end",cx:s,cy:e,r:4,append_to:this.handle_group})}update_connector_circles(){if(!this.$connector_start)return;const t=this.gantt.options.isRTL,e=this.$bar.getX(),i=this.$bar.getWidth(),s=this.y+this.height/2,n=t?e+i:e,a=t?e:e+i;this.$connector_start.setAttribute("cx",n),this.$connector_start.setAttribute("cy",s),this.$connector_end.setAttribute("cx",a),this.$connector_end.setAttribute("cy",s)}bind(){this.invalid||this.setup_click_event()}unbind(){this.invalid||this.group&&this.event_listeners&&(this.event_listeners.forEach(({event:t,handler:e})=>{u.off(this.group,t,e)}),this.event_listeners=[])}setup_click_event(){this.event_listeners=[];let t=this.task.id;const e=p=>{this.gantt.trigger_event("hover",[this.task,p.screenX,p.screenY,p])};if(u.on(this.group,"mouseover",e),this.event_listeners.push({event:"mouseover",handler:e}),this.gantt.options.popup_on==="click"){const p=c=>{const m=c.offsetX||c.layerX;if(this.$handle_progress){const f=+this.$handle_progress.getAttribute("cx");if(f>m-1&&f<m+1||this.gantt.bar_being_dragged)return}this.gantt.show_popup({x:c.offsetX||c.layerX,y:c.offsetY||c.layerY,task:this.task,target:this.$bar})};u.on(this.group,"click",p),this.event_listeners.push({event:"click",handler:p})}let i;const s=p=>{i=setTimeout(()=>{this.gantt.options.popup_on==="hover"&&this.gantt.show_popup({x:p.offsetX||p.layerX,y:p.offsetY||p.layerY,task:this.task,target:this.$bar});const c=this.gantt.$container.querySelector(`.highlight-${CSS.escape(t)}`);c&&c.classList.remove("hide")},200),this.$add_icon_group&&(this.is_hovering_bar=!0,this.add_icon_hide_timeout&&(clearTimeout(this.add_icon_hide_timeout),this.add_icon_hide_timeout=null),this.is_dragging||this.$add_icon_group.classList.remove("hide"))};u.on(this.group,"mouseenter",s),this.event_listeners.push({event:"mouseenter",handler:s});const n=()=>{var c,m;clearTimeout(i),this.gantt.options.popup_on==="hover"&&((m=(c=this.gantt.popup)==null?void 0:c.hide)==null||m.call(c));const p=this.gantt.$container.querySelector(`.highlight-${CSS.escape(t)}`);p&&p.classList.add("hide"),this.$add_icon_group&&(this.is_hovering_bar=!1,this.add_icon_hide_timeout&&clearTimeout(this.add_icon_hide_timeout),this.add_icon_hide_timeout=setTimeout(()=>{this.is_hovering_icon||this.$add_icon_group.classList.add("hide")},200))};u.on(this.group,"mouseleave",n),this.event_listeners.push({event:"mouseleave",handler:n});const a=()=>{this.is_dragging=!0,this.hide_add_icon()};u.on(this.group,"mousedown",a),this.event_listeners.push({event:"mousedown",handler:a});const o=()=>{setTimeout(()=>{this.gantt.bar_being_dragged!==!0&&(this.is_dragging=!1,this.$add_icon_group&&this.is_hovering_bar&&this.$add_icon_group.classList.remove("hide"))},0)};u.on(this.group,"mouseup",o),this.event_listeners.push({event:"mouseup",handler:o});const d=()=>{this.action_completed||this.gantt.bar_being_dragged||this.gantt.trigger_event("click",[this.task])};u.on(this.group,"click",d),this.event_listeners.push({event:"click",handler:d});const h=()=>{this.action_completed||(this.group.classList.remove("active"),this.gantt.popup&&this.gantt.popup.parent.classList.remove("hide"),this.gantt.trigger_event("double_click",[this.task]))};u.on(this.group,"dblclick",h),this.event_listeners.push({event:"dblclick",handler:h});let _=!1;const l=p=>{if(!_)return _=!0,setTimeout(function(){_=!1},300),!1;p.preventDefault(),!this.action_completed&&(this.group.classList.remove("active"),this.gantt.popup&&this.gantt.popup.parent.classList.remove("hide"),this.gantt.trigger_event("double_click",[this.task]))};u.on(this.group,"touchstart",l),this.event_listeners.push({event:"touchstart",handler:l})}update_bar_position({x:t=null,width:e=null}){const i=this.$bar;t&&(this.update_attr(i,"x",t),this.x=t,this.$date_highlight.style.left=t+"px"),e>0&&(this.update_attr(i,"width",e),this.$date_highlight.style.width=e+"px"),this.update_label_position(),this.update_handle_position(),this.update_add_icon_position(),this.date_changed(),this.compute_duration(),this.gantt.options.show_expected_progress&&this.update_expected_progressbar_position(),this.update_progressbar_position(),this.update_arrow_position(),this.update_connector_circles()}update_label_position_on_horizontal_scroll({x:t,sx:e}){const i=this.gantt.$container,s=this.group.querySelector(".bar-label"),n=this.group.querySelector(".bar-img")||"",a=this.bar_group.querySelector(".img_mask")||"";let o=this.$bar.getX()+this.$bar.getWidth(),d=s.getX()+t,h=n&&n.getX()+t||0,_=n&&n.getBBox().width+7||7,l=d+s.getBBox().width+7,p=e+i.clientWidth/2;s.classList.contains("big")||(l<o&&t>0&&l<p||d-_>this.$bar.getX()&&t<0&&l>p)&&(s.setAttribute("x",d),n&&(n.setAttribute("x",h),a.setAttribute("x",h)))}date_changed(){let t=!1;const{new_start_date:e,new_end_date:i}=this.compute_start_end_date();Number(this.task._start)!==Number(e)&&(t=!0,this.task._start=e),Number(this.task._end)!==Number(i)&&(t=!0,this.task._end=i),t&&this.gantt.trigger_event("date_change",[this.task,e,g.add(i,-1,"second")])}progress_changed(){this.task.progress=this.compute_progress(),this.gantt.trigger_event("progress_change",[this.task,this.task.progress])}set_action_completed(){this.action_completed=!0,setTimeout(()=>this.action_completed=!1,10),this.is_dragging=!1,this.$add_icon_group&&this.is_hovering_bar&&this.$add_icon_group.classList.remove("hide")}compute_start_end_date(){const t=this.$bar,e=t.getX()/this.gantt.config.column_width;let i=g.add(this.gantt.gantt_start,e*this.gantt.config.step,this.gantt.config.unit);const s=t.getWidth()/this.gantt.config.column_width,n=g.add(i,s*this.gantt.config.step,this.gantt.config.unit);return{new_start_date:i,new_end_date:n}}compute_progress(){this.progress_width=this.$bar_progress.getWidth(),this.x=this.$bar_progress.getBBox().x;const t=this.x+this.progress_width,e=this.progress_width-this.gantt.config.ignored_positions.reduce((s,n)=>s+(n>=this.x&&n<=t),0)*this.gantt.config.column_width;if(e<0)return 0;const i=this.$bar.getWidth()-this.ignored_duration_raw*this.gantt.config.column_width;return parseInt(e/i*100,10)}compute_expected_progress(){this.expected_progress=g.diff(g.today(),this.task._start,"hour")/this.gantt.config.step,this.expected_progress=(this.expected_progress<this.duration?this.expected_progress:this.duration)*100/this.duration}compute_x(){const{column_width:t}=this.gantt.config,e=this.task._start,i=this.gantt.gantt_start;let n=g.diff(e,i,this.gantt.config.unit)/this.gantt.config.step*t;this.x=n}compute_y(){this.y=this.gantt.config.header_height+this.gantt.options.padding/2+this.task._index*(this.height+this.gantt.options.padding)}compute_duration(){let t=0,e=0;for(let i=new Date(this.task._start);i<this.task._end;i.setDate(i.getDate()+1))e++,!this.gantt.config.ignored_dates.find(s=>s.getTime()===i.getTime())&&(!this.gantt.config.ignored_function||!this.gantt.config.ignored_function(i))&&t++;this.task.actual_duration=t,this.task.ignored_duration=e-t,this.duration=g.convert_scales(e+"d",this.gantt.config.unit)/this.gantt.config.step,this.actual_duration_raw=g.convert_scales(t+"d",this.gantt.config.unit)/this.gantt.config.step,this.ignored_duration_raw=this.duration-this.actual_duration_raw}update_attr(t,e,i){return i=+i,isNaN(i)||t.setAttribute(e,i),t}update_expected_progressbar_position(){this.invalid||(this.$expected_bar_progress.setAttribute("x",this.$bar.getX()),this.compute_expected_progress(),this.$expected_bar_progress.setAttribute("width",this.gantt.config.column_width*this.actual_duration_raw*(this.expected_progress/100)||0))}update_progressbar_position(){this.invalid||this.gantt.options.readonly||(this.$bar_progress.setAttribute("x",this.$bar.getX()),this.$bar_progress.setAttribute("width",this.calculate_progress_width()))}update_label_position(){const t=this.bar_group.querySelector(".img_mask")||"",e=this.$bar,i=this.group.querySelector(".bar-label"),s=this.group.querySelector(".bar-img");let n=5,a=this.image_size+10;const o=i.getBBox().width,d=e.getWidth();o>d?(i.classList.add("big"),s?(s.setAttribute("x",e.getEndX()+n),t.setAttribute("x",e.getEndX()+n),i.setAttribute("x",e.getEndX()+a)):i.setAttribute("x",e.getEndX()+n)):(i.classList.remove("big"),s?(s.setAttribute("x",e.getX()+n),t.setAttribute("x",e.getX()+n),i.setAttribute("x",e.getX()+d/2+a)):i.setAttribute("x",e.getX()+d/2-o/2))}update_handle_position(){if(this.invalid||this.gantt.options.readonly)return;const t=this.$bar;this.handle_group.querySelector(".handle.left").setAttribute("x",t.getX()),this.handle_group.querySelector(".handle.right").setAttribute("x",t.getEndX());const e=this.group.querySelector(".handle.progress");e&&e.setAttribute("cx",this.$bar_progress.getEndX())}update_add_icon_position(){if(!this.$add_icon_group)return;const t=this.icon_size,e=this.icon_padding;let i;if(this.gantt.options.task_add_icon_position==="before")i=this.x-t-e;else if(this.gantt.options.task_add_icon_position==="after")i=this.x+this.$bar.getWidth()+e;else return;const s=this.y+(this.height-t)/2;this.$add_icon_circle.setAttribute("cx",i+t/2),this.$add_icon_circle.setAttribute("cy",s+t/2),this.$add_icon_vertical.setAttribute("x1",i+t/2),this.$add_icon_vertical.setAttribute("y1",s+5),this.$add_icon_vertical.setAttribute("x2",i+t/2),this.$add_icon_vertical.setAttribute("y2",s+t-5),this.$add_icon_horizontal.setAttribute("x1",i+5),this.$add_icon_horizontal.setAttribute("y1",s+t/2),this.$add_icon_horizontal.setAttribute("x2",i+t-5),this.$add_icon_horizontal.setAttribute("y2",s+t/2)}hide_add_icon(){this.$add_icon_group&&this.$add_icon_group.classList.add("hide")}update_arrow_position(){this.arrows=this.arrows||[];for(let t of this.arrows)t.update()}}class I{constructor(t,e,i){this.parent=t,this.popup_func=e,this.gantt=i,this.make()}make(){this.parent.innerHTML=`
101
+ m 5 -5 l -5 5 l 5 5`}_get_connected_bars(){const t=this.from_task.task.id,e=this.to_task.task.id;return Array.from(this.gantt.$svg.querySelectorAll(`[data-id="${CSS.escape(t)}"], [data-id="${CSS.escape(e)}"]`))}draw(){let t="";this.is_invalid?t="arrow-invalid":this.is_critical&&(t="arrow-critical"),this.element=w("path",{d:this.path,"data-from":this.from_task.task.id,"data-to":this.to_task.task.id,class:t}),this.hit_element=w("path",{d:this.path,stroke:"transparent","stroke-width":15,fill:"none",style:"pointer-events: stroke; cursor: pointer;"}),this.hit_element.addEventListener("mouseenter",()=>{this.is_hovered=!0,this.element.classList.add("arrow-hover");const e=this.is_invalid?"bar-arrow-invalid":this.is_critical?"bar-arrow-critical":"bar-arrow-hover";this._get_connected_bars().forEach(i=>{const s=i.querySelector(".bar");s&&s.classList.add(e)}),this._show_label()}),this.hit_element.addEventListener("mouseleave",()=>{this.is_hovered=!1,this.element.classList.remove("arrow-hover"),this._get_connected_bars().forEach(e=>{const i=e.querySelector(".bar");i&&(i.classList.remove("bar-arrow-hover"),this.is_active||i.classList.remove("bar-arrow-critical","bar-arrow-invalid"))}),!this.is_active&&!this.is_hovered&&this._hide_label()}),this.hit_element.addEventListener("click",e=>{e.stopPropagation(),this.is_active?this.gantt.set_active_arrow(null):this.gantt.set_active_arrow(this)})}_get_type_abbr(){return{"finish-to-start":"FS","start-to-start":"SS","finish-to-finish":"FF","start-to-finish":"SF"}[this.dependency_type]||"FS"}_show_label(){if(this.label_element)return;const t=this._get_type_abbr(),e=21,i=20,{x:s,y:n,side:a}=this.label_pos,o=a==="left"?s-10-e/2:s+10+e/2,d=n;this.label_element=w("g",{class:"arrow-type-label"});const h=w("rect",{x:o-e/2,y:d-i/2,width:e,height:i,rx:3}),_=w("text",{x:o,y:d,"dominant-baseline":"middle","text-anchor":"middle"});_.textContent=t,this.label_element.appendChild(h),this.label_element.appendChild(_),this.label_element.addEventListener("mouseenter",()=>{this.hit_element.dispatchEvent(new MouseEvent("mouseenter",{bubbles:!1}))}),this.label_element.addEventListener("mouseleave",()=>{this.hit_element.dispatchEvent(new MouseEvent("mouseleave",{bubbles:!1}))}),this.label_element.addEventListener("click",l=>{l.stopPropagation(),this._toggle_type_dropdown()}),this.gantt.layers.arrow.appendChild(this.label_element)}_hide_label(){this.label_element&&(this.label_element.remove(),this.label_element=null)}_show_type_dropdown(){if(this.gantt.options.readonly||this.type_dropdown||(this.is_active||this.gantt.set_active_arrow(this),!this.label_element))return;const t=[{abbr:"FS",label:"Finish to Start",value:"finish-to-start"},{abbr:"SS",label:"Start to Start",value:"start-to-start"},{abbr:"FF",label:"Finish to Finish",value:"finish-to-finish"},{abbr:"SF",label:"Start to Finish",value:"start-to-finish"}];this.type_dropdown=document.createElement("div"),this.type_dropdown.className="arrow-type-dropdown",this.type_dropdown.addEventListener("click",a=>a.stopPropagation()),t.forEach(({abbr:a,label:o,value:d})=>{const h=document.createElement("div");h.className="arrow-type-option"+(d===this.dependency_type?" active":"");const _=document.createElement("strong");_.textContent=a;const l=document.createElement("span");l.textContent=o,h.appendChild(_),h.appendChild(l),h.addEventListener("click",p=>{p.stopPropagation(),this.gantt.change_dependency_type(this,d)}),this.type_dropdown.appendChild(h)}),this.gantt.$container.appendChild(this.type_dropdown);const e=this.label_element.getBoundingClientRect(),i=this.gantt.$container.getBoundingClientRect();this.type_dropdown.style.top=e.bottom-i.top+this.gantt.$container.scrollTop+"px",this.type_dropdown.style.left=e.left-i.left+this.gantt.$container.scrollLeft+"px";const s=this.label_element.querySelector("text"),n=this.label_element.querySelector("rect");if(s&&(s.textContent=this._get_type_abbr()+" ▾"),n){const o=parseFloat(n.getAttribute("width")),d=parseFloat(n.getAttribute("x"))+o/2;n.setAttribute("x",String(d-34/2)),n.setAttribute("width",String(34))}}_hide_type_dropdown(){var i,s;this.type_dropdown&&(this.type_dropdown.remove(),this.type_dropdown=null);const t=(i=this.label_element)==null?void 0:i.querySelector("text"),e=(s=this.label_element)==null?void 0:s.querySelector("rect");if(t&&(t.textContent=this._get_type_abbr()),e){const a=parseFloat(e.getAttribute("x"))+parseFloat(e.getAttribute("width"))/2;e.setAttribute("x",String(a-21/2)),e.setAttribute("width",String(21))}}_toggle_type_dropdown(){this.type_dropdown?this._hide_type_dropdown():this._show_type_dropdown()}activate(){this.is_active=!0,this.element.classList.add("arrow-active"),this._show_label();const t=this.is_invalid?"bar-arrow-invalid":this.is_critical?"bar-arrow-critical":"bar-arrow-active";this._get_connected_bars().forEach(e=>{const i=e.querySelector(".bar");i&&i.classList.add(t)})}deactivate(){this._hide_type_dropdown(),this.is_active=!1,this.element.classList.remove("arrow-active"),this._hide_label(),this._get_connected_bars().forEach(t=>{const e=t.querySelector(".bar");e&&e.classList.remove("bar-arrow-active","bar-arrow-critical","bar-arrow-invalid")})}update(){this.calculate_path(),this.element.setAttribute("d",this.path),this.hit_element.setAttribute("d",this.path),this.is_invalid=this.check_invalid_dependency();let t="";this.is_invalid?t="arrow-invalid":this.is_critical&&(t="arrow-critical"),this.is_hovered&&(t+=" arrow-hover"),this.is_active&&(t+=" arrow-active"),this.element.setAttribute("class",t.trim())}}class G{constructor(t,e){this.set_defaults(t,e),this.prepare_wrappers(),this.prepare_helpers(),this.refresh()}refresh(){this.bar_group.innerHTML="",this.handle_group.innerHTML="",this.task.custom_class?this.group.classList.add(this.task.custom_class):this.group.classList=["bar-wrapper"],this.unbind(),this.prepare_values(),this.draw(),this.bind()}set_defaults(t,e){this.action_completed=!1,this.gantt=t,this.task=e,this.name=this.name||"",this.is_dragging=!1,this.is_hovering_bar=!1,this.is_hovering_icon=!1,this.add_icon_hide_timeout=null}prepare_wrappers(){this.group=w("g",{class:"bar-wrapper"+(this.task.custom_class?" "+this.task.custom_class:""),"data-id":this.task.id}),this.bar_group=w("g",{class:"bar-group",append_to:this.group}),this.handle_group=w("g",{class:"handle-group",append_to:this.group})}prepare_values(){this.invalid=this.task.invalid,this.height=this.gantt.options.bar_height,this.image_size=this.height-5,(!this.task._start||!(this.task._start instanceof Date))&&(this.task._start=new Date(this.task.start)),(!this.task._end||!(this.task._end instanceof Date))&&(this.task._end=new Date(this.task.end)),this.compute_x(),this.compute_y(),this.compute_duration(),this.corner_radius=this.gantt.options.bar_corner_radius,this.width=this.gantt.config.column_width*this.duration,(!this.task.progress||this.task.progress<0)&&(this.task.progress=0),this.task.progress>100&&(this.task.progress=100)}prepare_helpers(){SVGElement.prototype.getX=function(){return+this.getAttribute("x")},SVGElement.prototype.getY=function(){return+this.getAttribute("y")},SVGElement.prototype.getWidth=function(){return+this.getAttribute("width")},SVGElement.prototype.getHeight=function(){return+this.getAttribute("height")},SVGElement.prototype.getEndX=function(){return this.getX()+this.getWidth()}}prepare_expected_progress_values(){this.compute_expected_progress(),this.expected_progress_width=this.gantt.options.column_width*this.duration*(this.expected_progress/100)||0}draw(){this.draw_bar(),this.draw_progress_bar(),this.gantt.options.show_expected_progress&&(this.prepare_expected_progress_values(),this.draw_expected_progress_bar()),this.draw_label(),this.draw_resize_handles(),this.task.thumbnail&&this.draw_thumbnail(),this.gantt.options.task_add_icon_position&&this.draw_add_task_icon(),this.draw_connector_circles()}draw_bar(){this.$bar=w("rect",{x:this.x,y:this.y,width:this.width,height:this.height,rx:this.corner_radius,ry:this.corner_radius,class:"bar",append_to:this.bar_group}),this.task.color&&(this.$bar.style.fill=this.task.color),X(this.$bar,"width",0,this.width),this.invalid&&this.$bar.classList.add("bar-invalid")}draw_expected_progress_bar(){this.invalid||(this.$expected_bar_progress=w("rect",{x:this.x,y:this.y,width:this.expected_progress_width,height:this.height,rx:this.corner_radius,ry:this.corner_radius,class:"bar-expected-progress",append_to:this.bar_group}),X(this.$expected_bar_progress,"width",0,this.expected_progress_width))}draw_progress_bar(){if(this.invalid)return;this.progress_width=this.calculate_progress_width();let t=this.corner_radius;/^((?!chrome|android).)*safari/i.test(navigator.userAgent)||(t=this.corner_radius+2),this.$bar_progress=w("rect",{x:this.x,y:this.y,width:this.progress_width,height:this.height,rx:t,ry:t,class:"bar-progress",append_to:this.bar_group}),this.task.color_progress&&(this.$bar_progress.style.fill=this.task.color_progress);const e=g.diff(this.task._start,this.gantt.gantt_start,this.gantt.config.unit)/this.gantt.config.step*this.gantt.config.column_width;this.$date_highlight&&this.$date_highlight.parentNode&&this.$date_highlight.parentNode.removeChild(this.$date_highlight);let i=this.gantt.create_el({classes:`date-range-highlight hide highlight-${CSS.escape(this.task.id)}`,width:this.width,left:e});this.$date_highlight=i,this.gantt.$lower_header.prepend(this.$date_highlight),X(this.$bar_progress,"width",0,this.progress_width)}calculate_progress_width(){const t=this.$bar.getWidth(),e=this.x+t,i=this.gantt.config.ignored_positions.reduce((d,h)=>d+(h>=this.x&&h<e),0)*this.gantt.config.column_width;let s=(t-i)*this.task.progress/100;const n=this.x+s,a=this.gantt.config.ignored_positions.reduce((d,h)=>d+(h>=this.x&&h<n),0)*this.gantt.config.column_width;s+=a;let o=this.gantt.get_ignored_region(this.x+s);for(;o.length;)s+=this.gantt.config.column_width,o=this.gantt.get_ignored_region(this.x+s);return this.progress_width=s,s}draw_label(){let t=this.x+this.$bar.getWidth()/2;this.task.thumbnail&&(t=this.x+this.image_size+5);const e=this.gantt.options.show_bar_label?this.task.bar_label??this.task.name:"";this.$bar_label=w("text",{x:t,y:this.y+this.height/2,innerHTML:e,class:"bar-label",append_to:this.bar_group}),this.task.color_text&&(this.$bar_label.style.fill=this.task.color_text),requestAnimationFrame(()=>this.update_label_position())}draw_thumbnail(){let t=10,e=2,i,s;i=w("defs",{append_to:this.bar_group}),w("rect",{id:"rect_"+this.task.id,x:this.x+t,y:this.y+e,width:this.image_size,height:this.image_size,rx:"15",class:"img_mask",append_to:i}),s=w("clipPath",{id:"clip_"+this.task.id,append_to:i}),w("use",{href:"#rect_"+this.task.id,append_to:s}),w("image",{x:this.x+t,y:this.y+e,width:this.image_size,height:this.image_size,class:"bar-img",href:this.task.thumbnail,clipPath:"clip_"+this.task.id,append_to:this.bar_group})}draw_add_task_icon(){this.icon_size=20,this.icon_padding=5;let i;if(this.gantt.options.task_add_icon_position==="before")i=this.x-20-5;else if(this.gantt.options.task_add_icon_position==="after")i=this.x+this.$bar.getWidth()+5;else return;const s=this.y+(this.height-20)/2;this.$add_icon_group=w("g",{class:"add-task-icon hide",append_to:this.handle_group}),this.$add_icon_circle=w("circle",{cx:i+20/2,cy:s+20/2,r:20/2,class:"add-task-icon-bg",append_to:this.$add_icon_group}),this.$add_icon_vertical=w("line",{x1:i+20/2,y1:s+5,x2:i+20/2,y2:s+20-5,class:"add-task-icon-plus",append_to:this.$add_icon_group}),this.$add_icon_horizontal=w("line",{x1:i+5,y1:s+20/2,x2:i+20-5,y2:s+20/2,class:"add-task-icon-plus",append_to:this.$add_icon_group}),u.on(this.$add_icon_group,"mousedown",n=>{n.stopPropagation()}),u.on(this.$add_icon_group,"mouseup",n=>{n.stopPropagation()}),u.on(this.$add_icon_group,"click",n=>{n.stopPropagation(),this.gantt.trigger_event("task_add",[this.task])}),u.on(this.$add_icon_group,"mouseenter",n=>{this.is_hovering_icon=!0,this.add_icon_hide_timeout&&(clearTimeout(this.add_icon_hide_timeout),this.add_icon_hide_timeout=null),this.$add_icon_group.classList.add("active"),this.$add_icon_group.classList.remove("hide"),n.stopPropagation()}),u.on(this.$add_icon_group,"mouseleave",()=>{this.is_hovering_icon=!1,this.$add_icon_group.classList.remove("active"),this.is_hovering_bar||this.$add_icon_group.classList.add("hide")})}draw_resize_handles(){if(this.invalid||this.gantt.options.readonly)return;const t=this.$bar,e=8;if(this.handles=[],this.gantt.options.readonly_dates||(this.handles.push(w("rect",{x:t.getEndX()-e,y:t.getY()+(this.height-this.height*.8)/2,width:e,height:this.height*.8,rx:2,ry:2,class:"handle right",append_to:this.handle_group})),this.handles.push(w("rect",{x:t.getX()-e,y:t.getY()+(this.height-this.height*.8)/2,width:e,height:this.height*.8,rx:2,ry:2,class:"handle left",append_to:this.handle_group}))),!this.gantt.options.readonly_progress){const i=this.$bar_progress;this.$handle_progress=w("circle",{cx:i.getEndX(),cy:i.getY()+i.getHeight()/2,r:4.5,class:"handle progress",append_to:this.handle_group}),this.handles.push(this.$handle_progress)}for(let i of this.handles)u.on(i,"mouseenter",()=>i.classList.add("active")),u.on(i,"mouseleave",()=>i.classList.remove("active"))}draw_connector_circles(){if(this.$connector_start=null,this.$connector_end=null,!this.gantt.options.allow_dependency_creation||this.gantt.options.readonly)return;const t=this.gantt.options.isRTL,e=this.y+this.height/2,i=t?this.x+this.width:this.x,s=t?this.x:this.x+this.width;this.$connector_start=w("circle",{class:"connector-circle connector-start","data-endpoint":"start",cx:i,cy:e,r:4,append_to:this.handle_group}),this.$connector_end=w("circle",{class:"connector-circle connector-end","data-endpoint":"end",cx:s,cy:e,r:4,append_to:this.handle_group})}update_connector_circles(){if(!this.$connector_start)return;const t=this.gantt.options.isRTL,e=this.$bar.getX(),i=this.$bar.getWidth(),s=this.y+this.height/2,n=t?e+i:e,a=t?e:e+i;this.$connector_start.setAttribute("cx",n),this.$connector_start.setAttribute("cy",s),this.$connector_end.setAttribute("cx",a),this.$connector_end.setAttribute("cy",s)}bind(){this.invalid||this.setup_click_event()}unbind(){this.invalid||this.group&&this.event_listeners&&(this.event_listeners.forEach(({event:t,handler:e})=>{u.off(this.group,t,e)}),this.event_listeners=[])}setup_click_event(){this.event_listeners=[];let t=this.task.id;const e=p=>{this.gantt.trigger_event("hover",[this.task,p.screenX,p.screenY,p])};if(u.on(this.group,"mouseover",e),this.event_listeners.push({event:"mouseover",handler:e}),this.gantt.options.popup_on==="click"){const p=c=>{const m=c.offsetX||c.layerX;if(this.$handle_progress){const f=+this.$handle_progress.getAttribute("cx");if(f>m-1&&f<m+1||this.gantt.bar_being_dragged)return}this.gantt.show_popup({x:c.offsetX||c.layerX,y:c.offsetY||c.layerY,task:this.task,target:this.$bar})};u.on(this.group,"click",p),this.event_listeners.push({event:"click",handler:p})}let i;const s=p=>{i=setTimeout(()=>{this.gantt.options.popup_on==="hover"&&this.gantt.show_popup({x:p.offsetX||p.layerX,y:p.offsetY||p.layerY,task:this.task,target:this.$bar});const c=this.gantt.$container.querySelector(`.highlight-${CSS.escape(t)}`);c&&c.classList.remove("hide")},200),this.$add_icon_group&&(this.is_hovering_bar=!0,this.add_icon_hide_timeout&&(clearTimeout(this.add_icon_hide_timeout),this.add_icon_hide_timeout=null),this.is_dragging||this.$add_icon_group.classList.remove("hide"))};u.on(this.group,"mouseenter",s),this.event_listeners.push({event:"mouseenter",handler:s});const n=()=>{var c,m;clearTimeout(i),this.gantt.options.popup_on==="hover"&&((m=(c=this.gantt.popup)==null?void 0:c.hide)==null||m.call(c));const p=this.gantt.$container.querySelector(`.highlight-${CSS.escape(t)}`);p&&p.classList.add("hide"),this.$add_icon_group&&(this.is_hovering_bar=!1,this.add_icon_hide_timeout&&clearTimeout(this.add_icon_hide_timeout),this.add_icon_hide_timeout=setTimeout(()=>{this.is_hovering_icon||this.$add_icon_group.classList.add("hide")},200))};u.on(this.group,"mouseleave",n),this.event_listeners.push({event:"mouseleave",handler:n});const a=()=>{this.is_dragging=!0,this.hide_add_icon()};u.on(this.group,"mousedown",a),this.event_listeners.push({event:"mousedown",handler:a});const o=()=>{setTimeout(()=>{this.gantt.bar_being_dragged!==!0&&(this.is_dragging=!1,this.$add_icon_group&&this.is_hovering_bar&&this.$add_icon_group.classList.remove("hide"))},0)};u.on(this.group,"mouseup",o),this.event_listeners.push({event:"mouseup",handler:o});const d=()=>{this.action_completed||this.gantt.bar_being_dragged||this.gantt.trigger_event("click",[this.task])};u.on(this.group,"click",d),this.event_listeners.push({event:"click",handler:d});const h=()=>{this.action_completed||(this.group.classList.remove("active"),this.gantt.popup&&this.gantt.popup.parent.classList.remove("hide"),this.gantt.trigger_event("double_click",[this.task]))};u.on(this.group,"dblclick",h),this.event_listeners.push({event:"dblclick",handler:h});let _=!1;const l=p=>{if(!_)return _=!0,setTimeout(function(){_=!1},300),!1;p.preventDefault(),!this.action_completed&&(this.group.classList.remove("active"),this.gantt.popup&&this.gantt.popup.parent.classList.remove("hide"),this.gantt.trigger_event("double_click",[this.task]))};u.on(this.group,"touchstart",l),this.event_listeners.push({event:"touchstart",handler:l})}update_bar_position({x:t=null,width:e=null}){const i=this.$bar;t&&(this.update_attr(i,"x",t),this.x=t,this.$date_highlight.style.left=t+"px"),e>0&&(this.update_attr(i,"width",e),this.$date_highlight.style.width=e+"px"),this.update_label_position(),this.update_handle_position(),this.update_add_icon_position(),this.date_changed(),this.compute_duration(),this.gantt.options.show_expected_progress&&this.update_expected_progressbar_position(),this.update_progressbar_position(),this.update_arrow_position(),this.update_connector_circles()}update_label_position_on_horizontal_scroll({x:t,sx:e}){const i=this.gantt.$container,s=this.group.querySelector(".bar-label"),n=this.group.querySelector(".bar-img")||"",a=this.bar_group.querySelector(".img_mask")||"";let o=this.$bar.getX()+this.$bar.getWidth(),d=s.getX()+t,h=n&&n.getX()+t||0,_=n&&n.getBBox().width+7||7,l=d+s.getBBox().width+7,p=e+i.clientWidth/2;s.classList.contains("big")||(l<o&&t>0&&l<p||d-_>this.$bar.getX()&&t<0&&l>p)&&(s.setAttribute("x",d),n&&(n.setAttribute("x",h),a.setAttribute("x",h)))}date_changed(){let t=!1;const{new_start_date:e,new_end_date:i}=this.compute_start_end_date();Number(this.task._start)!==Number(e)&&(t=!0,this.task._start=e),Number(this.task._end)!==Number(i)&&(t=!0,this.task._end=i),t&&this.gantt.trigger_event("date_change",[this.task,e,g.add(i,-1,"second")])}progress_changed(){this.task.progress=this.compute_progress(),this.gantt.trigger_event("progress_change",[this.task,this.task.progress])}set_action_completed(){this.action_completed=!0,setTimeout(()=>this.action_completed=!1,10),this.is_dragging=!1,this.$add_icon_group&&this.is_hovering_bar&&this.$add_icon_group.classList.remove("hide")}compute_start_end_date(){const t=this.$bar,e=t.getX()/this.gantt.config.column_width;let i=g.add(this.gantt.gantt_start,e*this.gantt.config.step,this.gantt.config.unit);const s=t.getWidth()/this.gantt.config.column_width,n=g.add(i,s*this.gantt.config.step,this.gantt.config.unit);return{new_start_date:i,new_end_date:n}}compute_progress(){this.progress_width=this.$bar_progress.getWidth(),this.x=this.$bar_progress.getBBox().x;const t=this.x+this.progress_width,e=this.progress_width-this.gantt.config.ignored_positions.reduce((s,n)=>s+(n>=this.x&&n<=t),0)*this.gantt.config.column_width;if(e<0)return 0;const i=this.$bar.getWidth()-this.ignored_duration_raw*this.gantt.config.column_width;return parseInt(e/i*100,10)}compute_expected_progress(){this.expected_progress=g.diff(g.today(),this.task._start,"hour")/this.gantt.config.step,this.expected_progress=(this.expected_progress<this.duration?this.expected_progress:this.duration)*100/this.duration}compute_x(){const{column_width:t}=this.gantt.config,e=this.task._start,i=this.gantt.gantt_start;let n=g.diff(e,i,this.gantt.config.unit)/this.gantt.config.step*t;this.x=n}compute_y(){this.y=this.gantt.config.header_height+this.gantt.options.padding/2+this.task._index*(this.height+this.gantt.options.padding)}compute_duration(){let t=0,e=0;for(let i=new Date(this.task._start);i<this.task._end;i.setDate(i.getDate()+1))e++,!this.gantt.config.ignored_dates.find(s=>s.getTime()===i.getTime())&&(!this.gantt.config.ignored_function||!this.gantt.config.ignored_function(i))&&t++;this.task.actual_duration=t,this.task.ignored_duration=e-t,this.duration=g.convert_scales(e+"d",this.gantt.config.unit)/this.gantt.config.step,this.actual_duration_raw=g.convert_scales(t+"d",this.gantt.config.unit)/this.gantt.config.step,this.ignored_duration_raw=this.duration-this.actual_duration_raw}update_attr(t,e,i){return i=+i,isNaN(i)||t.setAttribute(e,i),t}update_expected_progressbar_position(){this.invalid||(this.$expected_bar_progress.setAttribute("x",this.$bar.getX()),this.compute_expected_progress(),this.$expected_bar_progress.setAttribute("width",this.gantt.config.column_width*this.actual_duration_raw*(this.expected_progress/100)||0))}update_progressbar_position(){this.invalid||this.gantt.options.readonly||(this.$bar_progress.setAttribute("x",this.$bar.getX()),this.$bar_progress.setAttribute("width",this.calculate_progress_width()))}update_label_position(){const t=this.bar_group.querySelector(".img_mask")||"",e=this.$bar,i=this.group.querySelector(".bar-label"),s=this.group.querySelector(".bar-img");let n=5,a=this.image_size+10;const o=i.getBBox().width,d=e.getWidth();o>d?(i.classList.add("big"),s?(s.setAttribute("x",e.getEndX()+n),t.setAttribute("x",e.getEndX()+n),i.setAttribute("x",e.getEndX()+a)):i.setAttribute("x",e.getEndX()+n)):(i.classList.remove("big"),s?(s.setAttribute("x",e.getX()+n),t.setAttribute("x",e.getX()+n),i.setAttribute("x",e.getX()+d/2+a)):i.setAttribute("x",e.getX()+d/2-o/2))}update_handle_position(){if(this.invalid||this.gantt.options.readonly)return;const t=this.$bar;this.handle_group.querySelector(".handle.left").setAttribute("x",t.getX()),this.handle_group.querySelector(".handle.right").setAttribute("x",t.getEndX());const e=this.group.querySelector(".handle.progress");e&&e.setAttribute("cx",this.$bar_progress.getEndX())}update_add_icon_position(){if(!this.$add_icon_group)return;const t=this.icon_size,e=this.icon_padding;let i;if(this.gantt.options.task_add_icon_position==="before")i=this.x-t-e;else if(this.gantt.options.task_add_icon_position==="after")i=this.x+this.$bar.getWidth()+e;else return;const s=this.y+(this.height-t)/2;this.$add_icon_circle.setAttribute("cx",i+t/2),this.$add_icon_circle.setAttribute("cy",s+t/2),this.$add_icon_vertical.setAttribute("x1",i+t/2),this.$add_icon_vertical.setAttribute("y1",s+5),this.$add_icon_vertical.setAttribute("x2",i+t/2),this.$add_icon_vertical.setAttribute("y2",s+t-5),this.$add_icon_horizontal.setAttribute("x1",i+5),this.$add_icon_horizontal.setAttribute("y1",s+t/2),this.$add_icon_horizontal.setAttribute("x2",i+t-5),this.$add_icon_horizontal.setAttribute("y2",s+t/2)}hide_add_icon(){this.$add_icon_group&&this.$add_icon_group.classList.add("hide")}update_arrow_position(){this.arrows=this.arrows||[];for(let t of this.arrows)t.update()}}class I{constructor(t,e,i){this.parent=t,this.popup_func=e,this.gantt=i,this.make()}make(){this.parent.innerHTML=`
102
102
  <div class="title"></div>
103
103
  <div class="subtitle"></div>
104
104
  <div class="details"></div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@workiom/frappe-gantt",
3
- "version": "1.0.25",
3
+ "version": "1.0.26",
4
4
  "description": "A simple, modern, interactive gantt library for the web",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
package/src/bar.js CHANGED
@@ -240,7 +240,7 @@ export default class Bar {
240
240
  }
241
241
 
242
242
  const labelText = this.gantt.options.show_bar_label
243
- ? (this.task.bar_label || this.task.name)
243
+ ? (this.task.bar_label ?? this.task.name)
244
244
  : '';
245
245
 
246
246
  this.$bar_label = createSVG('text', {