1/* 2@license 3 4dhtmlxGantt v.6.3.5 Standard 5 6This version of dhtmlxGantt is distributed under GPL 2.0 license and can be legally used in GPL projects. 7 8To use dhtmlxGantt in non-GPL projects (and get Pro version of the product), please obtain Commercial/Enterprise or Ultimate license on our site https://dhtmlx.com/docs/products/dhtmlxGantt/#licensing or contact us at sales@dhtmlx.com 9 10(c) XB Software Ltd. 11 12*/ 13(function webpackUniversalModuleDefinition(root, factory) { 14 if(typeof exports === 'object' && typeof module === 'object') 15 module.exports = factory(); 16 else if(typeof define === 'function' && define.amd) 17 define("ext/dhtmlxgantt_smart_rendering", [], factory); 18 else if(typeof exports === 'object') 19 exports["ext/dhtmlxgantt_smart_rendering"] = factory(); 20 else 21 root["ext/dhtmlxgantt_smart_rendering"] = factory(); 22})(window, function() { 23return /******/ (function(modules) { // webpackBootstrap 24/******/ // The module cache 25/******/ var installedModules = {}; 26/******/ 27/******/ // The require function 28/******/ function __webpack_require__(moduleId) { 29/******/ 30/******/ // Check if module is in cache 31/******/ if(installedModules[moduleId]) { 32/******/ return installedModules[moduleId].exports; 33/******/ } 34/******/ // Create a new module (and put it into the cache) 35/******/ var module = installedModules[moduleId] = { 36/******/ i: moduleId, 37/******/ l: false, 38/******/ exports: {} 39/******/ }; 40/******/ 41/******/ // Execute the module function 42/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 43/******/ 44/******/ // Flag the module as loaded 45/******/ module.l = true; 46/******/ 47/******/ // Return the exports of the module 48/******/ return module.exports; 49/******/ } 50/******/ 51/******/ 52/******/ // expose the modules object (__webpack_modules__) 53/******/ __webpack_require__.m = modules; 54/******/ 55/******/ // expose the module cache 56/******/ __webpack_require__.c = installedModules; 57/******/ 58/******/ // define getter function for harmony exports 59/******/ __webpack_require__.d = function(exports, name, getter) { 60/******/ if(!__webpack_require__.o(exports, name)) { 61/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); 62/******/ } 63/******/ }; 64/******/ 65/******/ // define __esModule on exports 66/******/ __webpack_require__.r = function(exports) { 67/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { 68/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); 69/******/ } 70/******/ Object.defineProperty(exports, '__esModule', { value: true }); 71/******/ }; 72/******/ 73/******/ // create a fake namespace object 74/******/ // mode & 1: value is a module id, require it 75/******/ // mode & 2: merge all properties of value into the ns 76/******/ // mode & 4: return value when already ns object 77/******/ // mode & 8|1: behave like require 78/******/ __webpack_require__.t = function(value, mode) { 79/******/ if(mode & 1) value = __webpack_require__(value); 80/******/ if(mode & 8) return value; 81/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; 82/******/ var ns = Object.create(null); 83/******/ __webpack_require__.r(ns); 84/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); 85/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); 86/******/ return ns; 87/******/ }; 88/******/ 89/******/ // getDefaultExport function for compatibility with non-harmony modules 90/******/ __webpack_require__.n = function(module) { 91/******/ var getter = module && module.__esModule ? 92/******/ function getDefault() { return module['default']; } : 93/******/ function getModuleExports() { return module; }; 94/******/ __webpack_require__.d(getter, 'a', getter); 95/******/ return getter; 96/******/ }; 97/******/ 98/******/ // Object.prototype.hasOwnProperty.call 99/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; 100/******/ 101/******/ // __webpack_public_path__ 102/******/ __webpack_require__.p = "/codebase/sources/"; 103/******/ 104/******/ 105/******/ // Load entry module and return exports 106/******/ return __webpack_require__(__webpack_require__.s = "./sources/ext/smart_rendering.js"); 107/******/ }) 108/************************************************************************/ 109/******/ ({ 110 111/***/ "./sources/ext/smart_rendering.js": 112/*!****************************************!*\ 113 !*** ./sources/ext/smart_rendering.js ***! 114 \****************************************/ 115/*! no static exports found */ 116/***/ (function(module, exports) { 117 118gantt.config.smart_rendering = true; 119 120gantt._smart_render = { 121 getViewPort: function(){ 122 123 var timeline = gantt.$ui.getView("timeline"); 124 var grid = gantt.$ui.getView("grid"); 125 var view = gantt.$layout; 126 if (timeline && timeline.isVisible()) { 127 view = timeline; 128 } else if (grid && grid.isVisible()) { 129 view = grid; 130 } 131 132 var viewSize = view.getSize(); 133 var scrollPos = gantt.getScrollState(); 134 135 return { 136 y: scrollPos.y, 137 y_end: scrollPos.y + viewSize.y, 138 x: scrollPos.x, 139 x_end: scrollPos.x + viewSize.x 140 }; 141 }, 142 getScrollSizes: function(){ 143 var scroll = gantt.getScrollState(); 144 scroll.x = scroll.x || 0; 145 scroll.y = scroll.y || gantt.getVisibleTaskCount()*gantt.config.row_height; 146 return scroll; 147 }, 148 isInViewPort: function(item, viewPort){ 149 return !!(item.y < viewPort.y_end && item.y_end > viewPort.y); 150 }, 151 152 isTaskDisplayed: function(id, task){ 153 if(gantt.$keyboardNavigation && gantt.$keyboardNavigation.dispatcher.isTaskFocused(id)){ 154 return true; 155 } 156 157 return this.isInViewPort(this.getTaskPosition(id), this.getViewPort()); 158 }, 159 isLinkDisplayed: function(id, link){ 160 return this.isInViewPort(this.getLinkPosition(id, link), this.getViewPort()); 161 }, 162 getTaskPosition: function(id){ 163 var y = gantt.getTaskTop(id); 164 return { 165 y: y, 166 y_end: y + gantt.config.row_height 167 }; 168 }, 169 getLinkPosition: function(id, link){ 170 var from_pos = gantt.getTaskTop(link.source), 171 to_pos = gantt.getTaskTop(link.target); 172 173 return { 174 y: Math.min(from_pos, to_pos), 175 y_end: Math.max(from_pos, to_pos) + gantt.config.row_height 176 }; 177 }, 178 getRange: function(buffer){ 179 buffer = buffer || 0; 180 181 var port = this.getViewPort(); 182 183 var firstTask = Math.floor(Math.max(0, port.y) / gantt.config.row_height) - buffer; 184 var lastTask = Math.ceil(Math.max(0, port.y_end) / gantt.config.row_height) + buffer; 185 186 var visibleTasks = gantt.$data.tasksStore.getIndexRange(firstTask, lastTask); 187 var visibleIds = []; 188 for(var i = 0; i < visibleTasks.length; i++){ 189 visibleIds.push(visibleTasks[i].id); 190 } 191 192 return visibleIds; 193 }, 194 _redrawItems: function(renderers, visibleItems){ 195 var shouldBeVisible = {}; 196 for(var t = 0; t < visibleItems.length; t++){ 197 shouldBeVisible[visibleItems[t].id] = true; 198 } 199 var alreadyVisible = {}; 200 201 for(var r = 0; r < renderers.length; r++){ 202 var render = renderers[r]; 203 204 for(var i in render.rendered){ 205 if(!shouldBeVisible[i]){ 206 render.hide(i); 207 }else{ 208 var node = render.rendered[i]; 209 if(node && node.parentNode) { 210 alreadyVisible[i] = true; 211 } 212 } 213 } 214 215 for(var t = 0; t < visibleItems.length; t++){ 216 if(!alreadyVisible[visibleItems[t].id]) 217 render.restore(visibleItems[t]); 218 } 219 } 220 }, 221 222 _getVisibleTasks: function(){ 223 var ids = this.getRange(); 224 var rows = []; 225 for(var i=0; i < ids.length; i++){ 226 var item = gantt.getTask(ids[i]); 227 item.$index = i; 228 //this._update_parents(item.id, true); 229 gantt.resetProjectDates(item); 230 rows.push(item); 231 } 232 return rows; 233 }, 234 _getVisibleLinks: function(){ 235 var visible_links = []; 236 var links = gantt.$data.linksStore.getIndexRange(); 237 238 for(var i = 0; i < links.length; i++){ 239 if(this.isLinkDisplayed(links[i].id, links[i])){ 240 visible_links.push(links[i]); 241 } 242 } 243 return visible_links; 244 }, 245 246 _recalculateLinkedProjects: function(visibleLinks){ 247 // projects have dynamic duration, make sure that durations are recalculated before links display, 248 // so links are shown on correct dates 249 var recalculateTasks = {}; 250 for(var i = 0; i < visibleLinks.length; i++){ 251 recalculateTasks[visibleLinks[i].source] = true; 252 recalculateTasks[visibleLinks[i].target] = true; 253 } 254 255 for(var i in recalculateTasks){ 256 if(gantt.isTaskExists(i)) 257 gantt.resetProjectDates(gantt.getTask(i)); 258 } 259 }, 260 updateRender: function(){ 261 gantt.callEvent("onBeforeSmartRender", []); 262 var visibleTasks = this._getVisibleTasks(); 263 var visibleLinks = this._getVisibleLinks(); 264 265 // TODO: performance test 266 this._recalculateLinkedProjects(visibleLinks); 267 268 var layers = gantt.$services.getService("layers"); 269 270 var taskRenderer = layers.getDataRender("task"); 271 var linkRenderer = layers.getDataRender("link"); 272 273 this._redrawTasks(taskRenderer.getLayers(), visibleTasks); 274 this._redrawItems(linkRenderer.getLayers(), visibleLinks); 275 gantt.callEvent("onSmartRender", []); 276 }, 277 278 // hook to override from key nav 279 _redrawTasks: function(layers, visibleTasks){ 280 this._redrawItems(layers, visibleTasks); 281 }, 282 283 cached:{}, 284 285 _takeFromCache: function(id, payload, cacheName){ 286 if(!this.cached[cacheName]) 287 this.cached[cacheName] = null; 288 var cached = this.cached[cacheName]; 289 290 if(id !== undefined){ 291 if(!cached){ 292 cached = this.cached[cacheName] = {}; 293 } 294 295 if(cached[id] === undefined){ 296 cached[id] = payload(id); 297 } 298 299 return cached[id]; 300 }else{ 301 if(!cached){ 302 cached = payload(); 303 } 304 return cached; 305 } 306 307 }, 308 initCache:function(){ 309 var caches = [ 310 "getLinkPosition", 311 "getTaskPosition", 312 "isTaskDisplayed", 313 "isLinkDisplayed", 314 "getViewPort", 315 "getScrollSizes" 316 ]; 317 318 for(var i = 0; i < caches.length; i++){ 319 var method = caches[i]; 320 var payload = gantt.bind(this[method], this); 321 322 this[method] = (function(calculate, cache){ 323 return function(id){ 324 return this._takeFromCache(id, calculate, cache); 325 }; 326 })(payload, method); 327 } 328 329 this.invalidateCache(); 330 this.initCache = function(){}; 331 }, 332 invalidateCache: function(){ 333 var smartRender = this; 334 335 336 function clearViewPortCache(){ 337 smartRender.cached.getViewPort = null; 338 smartRender.cached.getScrollSizes = null; 339 smartRender.cached.isTaskDisplayed = null; 340 smartRender.cached.isLinkDisplayed = null; 341 } 342 function clearDataCache(){ 343 smartRender.cached.isTaskDisplayed = null; 344 smartRender.cached.isLinkDisplayed = null; 345 smartRender.cached.getLinkPosition = null; 346 smartRender.cached.getTaskPosition = null; 347 } 348 349 function clearAllCache(){ 350 clearViewPortCache(); 351 clearDataCache(); 352 } 353 354 function clearTaskCache(id){ 355 if(smartRender.cached.isTaskDisplayed){ 356 smartRender.cached.isTaskDisplayed[id] = undefined; 357 } 358 if(smartRender.cached.getTaskPosition){ 359 smartRender.cached.getTaskPosition[id] = undefined; 360 } 361 } 362 363 364 function clearLinkCache(id){ 365 if(smartRender.cached.isLinkDisplayed){ 366 smartRender.cached.isLinkDisplayed[id] = undefined; 367 } 368 if(smartRender.cached.getLinkPosition){ 369 smartRender.cached.getLinkPosition[id] = undefined; 370 } 371 } 372 gantt.attachEvent("onClear", function(){ 373 clearAllCache(); 374 }); 375 gantt.attachEvent("onParse", function(){ 376 clearAllCache(); 377 }); 378 379 gantt.attachEvent("onAfterLinkUpdate", clearLinkCache); 380 gantt.attachEvent("onAfterTaskAdd", clearAllCache); 381 gantt.attachEvent("onAfterTaskDelete", clearAllCache); 382 gantt.attachEvent("onAfterTaskUpdate", clearTaskCache); 383 gantt.attachEvent("onGanttScroll", clearViewPortCache); 384 gantt.attachEvent("onDataRender", clearAllCache); 385 386 this.invalidateCache = function(){}; 387 } 388 389}; 390 391gantt.attachEvent("onGanttScroll", function(oldLeft, oldTop, left, top){ 392 if(gantt.config.smart_rendering){ 393 394 if((oldTop != top) || (oldLeft == left)){ 395 396 //var visibleTasks = gantt._smart_render.getRange(); 397 gantt._smart_render.updateRender(); 398 399 } 400 401 } 402}); 403 404gantt.attachEvent("onDataRender", function() { 405 if(gantt.config.smart_rendering){ 406 gantt._smart_render.updateRender(); 407 } 408}); 409 410(function(){ 411 var attachOnce = gantt.attachEvent("onGanttReady", function(){ 412 var layers = gantt.$services.getService("layers"); 413 var taskRenderer = layers.getDataRender("task"); 414 taskRenderer.filters.push(function(id, task){ 415 if(!gantt.config.smart_rendering) 416 return true; 417 else 418 return !!gantt._smart_render.isTaskDisplayed(id, task); 419 }); 420 421 var linkRenderer = layers.getDataRender("link"); 422 linkRenderer.filters.push(function(id, link){ 423 if(!gantt.config.smart_rendering) 424 return true; 425 else 426 return !!gantt._smart_render.isLinkDisplayed(id, link); 427 }); 428 429 gantt.detachEvent(attachOnce); 430 }); 431})(); 432 433 434 435/***/ }) 436 437/******/ }); 438});