1/* 2Copyright DHTMLX LTD. http://www.dhtmlx.com 3To use this component please contact [email protected] to obtain license 4*/ 5 6if (!window.dhtmlx) { 7 dhtmlx = function(obj){ 8 for (var a in obj) dhtmlx[a]=obj[a]; 9 return dhtmlx; //simple singleton 10 }; 11} 12dhtmlx.extend_api=function(name,map,ext){ 13 var t = window[name]; 14 if (!t) return; //component not defined 15 window[name]=function(obj){ 16 if (obj && typeof obj == "object" && !obj.tagName){ 17 var that = t.apply(this,(map._init?map._init(obj):arguments)); 18 //global settings 19 for (var a in dhtmlx) 20 if (map[a]) this[map[a]](dhtmlx[a]); 21 //local settings 22 for (var a in obj){ 23 if (map[a]) this[map[a]](obj[a]); 24 else if (a.indexOf("on")==0){ 25 this.attachEvent(a,obj[a]); 26 } 27 } 28 } else 29 var that = t.apply(this,arguments); 30 if (map._patch) map._patch(this); 31 return that||this; 32 }; 33 window[name].prototype=t.prototype; 34 if (ext) 35 dhtmlXHeir(window[name].prototype,ext); 36}; 37 38dhtmlxAjax={ 39 get:function(url,callback){ 40 var t=new dtmlXMLLoaderObject(true); 41 t.async=(arguments.length<3); 42 t.waitCall=callback; 43 t.loadXML(url) 44 return t; 45 }, 46 post:function(url,post,callback){ 47 var t=new dtmlXMLLoaderObject(true); 48 t.async=(arguments.length<4); 49 t.waitCall=callback; 50 t.loadXML(url,true,post) 51 return t; 52 }, 53 getSync:function(url){ 54 return this.get(url,null,true) 55 }, 56 postSync:function(url,post){ 57 return this.post(url,post,null,true); 58 } 59} 60 61/** 62 * @desc: xmlLoader object 63 * @type: private 64 * @param: funcObject - xml parser function 65 * @param: object - jsControl object 66 * @param: async - sync/async mode (async by default) 67 * @param: rSeed - enable/disable random seed ( prevent IE caching) 68 * @topic: 0 69 */ 70function dtmlXMLLoaderObject(funcObject, dhtmlObject, async, rSeed){ 71 this.xmlDoc=""; 72 73 if (typeof (async) != "undefined") 74 this.async=async; 75 else 76 this.async=true; 77 78 this.onloadAction=funcObject||null; 79 this.mainObject=dhtmlObject||null; 80 this.waitCall=null; 81 this.rSeed=rSeed||false; 82 return this; 83}; 84 85dtmlXMLLoaderObject.count = 0; 86 87/** 88 * @desc: xml loading handler 89 * @type: private 90 * @param: dtmlObject - xmlLoader object 91 * @topic: 0 92 */ 93dtmlXMLLoaderObject.prototype.waitLoadFunction=function(dhtmlObject){ 94 var once = true; 95 this.check=function (){ 96 if ((dhtmlObject)&&(dhtmlObject.onloadAction != null)){ 97 if ((!dhtmlObject.xmlDoc.readyState)||(dhtmlObject.xmlDoc.readyState == 4)){ 98 if (!once) 99 return; 100 101 once=false; //IE 5 fix 102 dtmlXMLLoaderObject.count++; 103 if (typeof dhtmlObject.onloadAction == "function") 104 dhtmlObject.onloadAction(dhtmlObject.mainObject, null, null, null, dhtmlObject); 105 106 if (dhtmlObject.waitCall){ 107 dhtmlObject.waitCall.call(this,dhtmlObject); 108 dhtmlObject.waitCall=null; 109 } 110 } 111 } 112 }; 113 return this.check; 114}; 115 116/** 117 * @desc: return XML top node 118 * @param: tagName - top XML node tag name (not used in IE, required for Safari and Mozilla) 119 * @type: private 120 * @returns: top XML node 121 * @topic: 0 122 */ 123dtmlXMLLoaderObject.prototype.getXMLTopNode=function(tagName, oldObj){ 124 if (this.xmlDoc.responseXML){ 125 var temp = this.xmlDoc.responseXML.getElementsByTagName(tagName); 126 if(temp.length==0 && tagName.indexOf(":")!=-1) 127 var temp = this.xmlDoc.responseXML.getElementsByTagName((tagName.split(":"))[1]); 128 var z = temp[0]; 129 } else 130 var z = this.xmlDoc.documentElement; 131 132 if (z){ 133 this._retry=false; 134 return z; 135 } 136 137 if (!this._retry){ 138 this._retry=true; 139 var oldObj = this.xmlDoc; 140 this.loadXMLString(this.xmlDoc.responseText.replace(/^[\s]+/,""), true); 141 return this.getXMLTopNode(tagName, oldObj); 142 } 143 144 dhtmlxError.throwError("LoadXML", "Incorrect XML", [ 145 (oldObj||this.xmlDoc), 146 this.mainObject 147 ]); 148 149 return document.createElement("DIV"); 150}; 151 152/** 153 * @desc: load XML from string 154 * @type: private 155 * @param: xmlString - xml string 156 * @topic: 0 157 */ 158dtmlXMLLoaderObject.prototype.loadXMLString=function(xmlString, silent){ 159 160 if (!_isIE){ 161 var parser = new DOMParser();
162 this.xmlDoc=parser.parseFromString(xmlString, "text/xml"); 163 } else { 164 this.xmlDoc=new ActiveXObject("Microsoft.XMLDOM"); 165 this.xmlDoc.async=this.async; 166 this.xmlDoc.onreadystatechange = function(){}; 167 this.xmlDoc["loadXM"+"L"](xmlString); 168 } 169 170 if (silent) 171 return; 172 173 if (this.onloadAction) 174 this.onloadAction(this.mainObject, null, null, null, this); 175 176 if (this.waitCall){ 177 this.waitCall(); 178 this.waitCall=null; 179 } 180} 181/** 182 * @desc: load XML 183 * @type: private 184 * @param: filePath - xml file path 185 * @param: postMode - send POST request 186 * @param: postVars - list of vars for post request 187 * @topic: 0 188 */ 189dtmlXMLLoaderObject.prototype.loadXML=function(filePath, postMode, postVars, rpc){ 190 if (this.rSeed) 191 filePath+=((filePath.indexOf("?") != -1) ? "&" : "?")+"a_dhx_rSeed="+(new Date()).valueOf(); 192 this.filePath=filePath; 193 194 if ((!_isIE)&&(window.XMLHttpRequest)) 195 this.xmlDoc=new XMLHttpRequest(); 196 else { 197 this.xmlDoc=new ActiveXObject("Microsoft.XMLHTTP"); 198 } 199 200 if (this.async) 201 this.xmlDoc.onreadystatechange=new this.waitLoadFunction(this); 202 this.xmlDoc.open(postMode ? "POST" : "GET", filePath, this.async); 203 204 if (rpc){ 205 this.xmlDoc.setRequestHeader("User-Agent", "dhtmlxRPC v0.1 ("+navigator.userAgent+")"); 206 this.xmlDoc.setRequestHeader("Content-type", "text/xml"); 207 } 208 209 else if (postMode) 210 this.xmlDoc.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); 211 212 this.xmlDoc.setRequestHeader("X-Requested-With","XMLHttpRequest"); 213 this.xmlDoc.send(null||postVars); 214 215 if (!this.async) 216 (new this.waitLoadFunction(this))(); 217}; 218/** 219 * @desc: destructor, cleans used memory 220 * @type: private 221 * @topic: 0 222 */ 223dtmlXMLLoaderObject.prototype.destructor=function(){ 224 this._filterXPath = null; 225 this._getAllNamedChilds = null; 226 this._retry = null; 227 this.async = null; 228 this.rSeed = null; 229 this.filePath = null; 230 this.onloadAction = null; 231 this.mainObject = null; 232 this.xmlDoc = null; 233 this.doXPath = null; 234 this.doXPathOpera = null; 235 this.doXSLTransToObject = null; 236 this.doXSLTransToString = null; 237 this.loadXML = null; 238 this.loadXMLString = null; 239 // this.waitLoadFunction = null; 240 this.doSerialization = null; 241 this.xmlNodeToJSON = null; 242 this.getXMLTopNode = null; 243 this.setXSLParamValue = null; 244 return null; 245} 246 247dtmlXMLLoaderObject.prototype.xmlNodeToJSON = function(node){ 248 var t={}; 249 for (var i=0; i<node.attributes.length; i++) 250 t[node.attributes[i].name]=node.attributes[i].value; 251 t["_tagvalue"]=node.firstChild?node.firstChild.nodeValue:""; 252 for (var i=0; i<node.childNodes.length; i++){ 253 var name=node.childNodes[i].tagName; 254 if (name){ 255 if (!t[name]) t[name]=[]; 256 t[name].push(this.xmlNodeToJSON(node.childNodes[i])); 257 } 258 } 259 return t; 260} 261 262/** 263 * @desc: Call wrapper 264 * @type: private 265 * @param: funcObject - action handler 266 * @param: dhtmlObject - user data 267 * @returns: function handler 268 * @topic: 0 269 */ 270function callerFunction(funcObject, dhtmlObject){ 271 this.handler=function(e){ 272 if (!e) 273 e=window.event; 274 funcObject(e, dhtmlObject); 275 return true; 276 }; 277 return this.handler; 278}; 279 280/** 281 * @desc: Calculate absolute position of html object 282 * @type: private 283 * @param: htmlObject - html object 284 * @topic: 0 285 */ 286function getAbsoluteLeft(htmlObject){ 287 return getOffset(htmlObject).left; 288} 289/** 290 * @desc: Calculate absolute position of html object 291 * @type: private 292 * @param: htmlObject - html object 293 * @topic: 0 294 */ 295function getAbsoluteTop(htmlObject){ 296 return getOffset(htmlObject).top; 297} 298 299function getOffsetSum(elem) { 300 var top=0, left=0; 301 while(elem) { 302 top = top + parseInt(elem.offsetTop); 303 left = left + parseInt(elem.offsetLeft); 304 elem = elem.offsetParent; 305 } 306 return {top: top, left: left}; 307} 308function getOffsetRect(elem) { 309 var box = elem.getBoundingClientRect(); 310 var body = document.body; 311 var docElem = document.documentElement; 312 var scrollTop = window.pageYOffset || docElem.scrollTop || body.scrollTop; 313 var scrollLeft = window.pageXOffset || docElem.scrollLeft || body.scrollLeft; 314 var clientTop = docElem.clientTop || body.clientTop || 0; 315 var clientLeft = docElem.clientLeft || body.clientLeft || 0; 316 var top = box.top + scrollTop - clientTop; 317 var left = box.left + scrollLeft - clientLeft; 318 return { top: Math.round(top), left: Math.round(left) }; 319} 320function getOffset(elem) { 321 if (elem.getBoundingClientRect) { 322 return getOffsetRect(elem); 323 } else { 324 return getOffsetSum(elem); 325 } 326} 327 328/** 329 * @desc: Convert string to it boolean representation 330 * @type: private 331 * @param: inputString - string for covertion 332 * @topic: 0 333 */ 334function convertStringToBoolean(inputString){ 335 if (typeof (inputString) == "string") 336 inputString=inputString.toLowerCase(); 337 338 switch (inputString){ 339 case "1": 340 case "true": 341 case "yes": 342 case "y": 343 case 1: 344 case true: 345 return true; 346 break; 347 348 default: return false; 349 } 350} 351 352/** 353 * @desc: find out what symbol to use as url param delimiters in further params 354 * @type: private 355 * @param: str - current url string 356 * @topic: 0 357 */ 358function getUrlSymbol(str){ 359 if (str.indexOf("?") != -1) 360 return "&" 361 else
362 return "?" 363} 364 365function dhtmlDragAndDropObject(){ 366 if (window.dhtmlDragAndDrop) 367 return window.dhtmlDragAndDrop; 368 369 this.lastLanding=0; 370 this.dragNode=0; 371 this.dragStartNode=0; 372 this.dragStartObject=0; 373 this.tempDOMU=null; 374 this.tempDOMM=null; 375 this.waitDrag=0; 376 window.dhtmlDragAndDrop=this; 377 378 return this; 379}; 380 381dhtmlDragAndDropObject.prototype.removeDraggableItem=function(htmlNode){ 382 htmlNode.onmousedown=null; 383 htmlNode.dragStarter=null; 384 htmlNode.dragLanding=null; 385} 386dhtmlDragAndDropObject.prototype.addDraggableItem=function(htmlNode, dhtmlObject){ 387 htmlNode.onmousedown=this.preCreateDragCopy; 388 htmlNode.dragStarter=dhtmlObject; 389 this.addDragLanding(htmlNode, dhtmlObject); 390} 391dhtmlDragAndDropObject.prototype.addDragLanding=function(htmlNode, dhtmlObject){ 392 htmlNode.dragLanding=dhtmlObject; 393} 394dhtmlDragAndDropObject.prototype.preCreateDragCopy=function(e){ 395 if ((e||window.event) && (e||event).button == 2) 396 return; 397 398 if (window.dhtmlDragAndDrop.waitDrag){ 399 window.dhtmlDragAndDrop.waitDrag=0; 400 document.body.onmouseup=window.dhtmlDragAndDrop.tempDOMU; 401 document.body.onmousemove=window.dhtmlDragAndDrop.tempDOMM; 402 return false; 403 } 404 405 if (window.dhtmlDragAndDrop.dragNode) 406 window.dhtmlDragAndDrop.stopDrag(e); 407 408 window.dhtmlDragAndDrop.waitDrag=1; 409 window.dhtmlDragAndDrop.tempDOMU=document.body.onmouseup; 410 window.dhtmlDragAndDrop.tempDOMM=document.body.onmousemove; 411 window.dhtmlDragAndDrop.dragStartNode=this; 412 window.dhtmlDragAndDrop.dragStartObject=this.dragStarter; 413 document.body.onmouseup=window.dhtmlDragAndDrop.preCreateDragCopy; 414 document.body.onmousemove=window.dhtmlDragAndDrop.callDrag; 415 window.dhtmlDragAndDrop.downtime = new Date().valueOf(); 416 417 418 if ((e)&&(e.preventDefault)){ 419 e.preventDefault(); 420 return false; 421 } 422 return false; 423}; 424dhtmlDragAndDropObject.prototype.callDrag=function(e){ 425 if (!e) 426 e=window.event; 427 dragger=window.dhtmlDragAndDrop; 428 if ((new Date()).valueOf()-dragger.downtime<100) return; 429 430 //if ((e.button == 0)&&(_isIE)) 431 // return dragger.stopDrag(); 432 433 if (!dragger.dragNode){ 434 if (dragger.waitDrag){ 435 dragger.dragNode=dragger.dragStartObject._createDragNode(dragger.dragStartNode, e); 436 437 if (!dragger.dragNode) 438 return dragger.stopDrag(); 439 440 dragger.dragNode.onselectstart=function(){return false;} 441 dragger.gldragNode=dragger.dragNode; 442 document.body.appendChild(dragger.dragNode); 443 document.body.onmouseup=dragger.stopDrag; 444 dragger.waitDrag=0; 445 dragger.dragNode.pWindow=window; 446 dragger.initFrameRoute(); 447 } 448 else return dragger.stopDrag(e, true); 449 } 450 451 if (dragger.dragNode.parentNode != window.document.body && dragger.gldragNode){ 452 var grd = dragger.gldragNode; 453 454 if (dragger.gldragNode.old) 455 grd=dragger.gldragNode.old; 456 457 //if (!document.all) dragger.calculateFramePosition(); 458 grd.parentNode.removeChild(grd); 459 var oldBody = dragger.dragNode.pWindow; 460 461 if (grd.pWindow && grd.pWindow.dhtmlDragAndDrop.lastLanding) 462 grd.pWindow.dhtmlDragAndDrop.lastLanding.dragLanding._dragOut(grd.pWindow.dhtmlDragAndDrop.lastLanding); 463 464 // var oldp=dragger.dragNode.parentObject; 465 if (_isIE){ 466 var div = document.createElement("Div"); 467 div.innerHTML=dragger.dragNode.outerHTML; 468 dragger.dragNode=div.childNodes[0]; 469 } else 470 dragger.dragNode=dragger.dragNode.cloneNode(true); 471 472 dragger.dragNode.pWindow=window; 473 // dragger.dragNode.parentObject=oldp; 474 475 dragger.gldragNode.old=dragger.dragNode; 476 document.body.appendChild(dragger.dragNode); 477 oldBody.dhtmlDragAndDrop.dragNode=dragger.dragNode; 478 } 479 480 dragger.dragNode.style.left=e.clientX+15+(dragger.fx 481 ? dragger.fx*(-1) 482 : 0) 483 +(document.body.scrollLeft||document.documentElement.scrollLeft)+"px"; 484 dragger.dragNode.style.top=e.clientY+3+(dragger.fy 485 ? dragger.fy*(-1) 486 : 0) 487 +(document.body.scrollTop||document.documentElement.scrollTop)+"px"; 488 489 if (!e.srcElement) 490 var z = e.target; 491 else 492 z=e.srcElement; 493 dragger.checkLanding(z, e); 494} 495 496dhtmlDragAndDropObject.prototype.calculateFramePosition=function(n){
497 //this.fx = 0, this.fy = 0; 498 if (window.name){ 499 var el = parent.frames[window.name].frameElement.offsetParent; 500 var fx = 0; 501 var fy = 0; 502 503 while (el){ 504 fx+=el.offsetLeft; 505 fy+=el.offsetTop; 506 el=el.offsetParent; 507 } 508 509 if ((parent.dhtmlDragAndDrop)){ 510 var ls = parent.dhtmlDragAndDrop.calculateFramePosition(1); 511 fx+=ls.split('_')[0]*1; 512 fy+=ls.split('_')[1]*1; 513 } 514 515 if (n) 516 return fx+"_"+fy; 517 else 518 this.fx=fx; 519 this.fy=fy; 520 } 521 return "0_0"; 522} 523dhtmlDragAndDropObject.prototype.checkLanding=function(htmlObject, e){ 524 if ((htmlObject)&&(htmlObject.dragLanding)){ 525 if (this.lastLanding) 526 this.lastLanding.dragLanding._dragOut(this.lastLanding); 527 this.lastLanding=htmlObject; 528 this.lastLanding=this.lastLanding.dragLanding._dragIn(this.lastLanding, this.dragStartNode, e.clientX, 529 e.clientY, e); 530 this.lastLanding_scr=(_isIE ? e.srcElement : e.target); 531 } else { 532 if ((htmlObject)&&(htmlObject.tagName != "BODY")) 533 this.checkLanding(htmlObject.parentNode, e); 534 else { 535 if (this.lastLanding) 536 this.lastLanding.dragLanding._dragOut(this.lastLanding, e.clientX, e.clientY, e); 537 this.lastLanding=0; 538 539 if (this._onNotFound) 540 this._onNotFound(); 541 } 542 } 543} 544dhtmlDragAndDropObject.prototype.stopDrag=function(e, mode){ 545 dragger=window.dhtmlDragAndDrop; 546 547 if (!mode){ 548 dragger.stopFrameRoute(); 549 var temp = dragger.lastLanding; 550 dragger.lastLanding=null; 551 552 if (temp) 553 temp.dragLanding._drag(dragger.dragStartNode, dragger.dragStartObject, temp, (_isIE 554 ? event.srcElement 555 : e.target)); 556 } 557 dragger.lastLanding=null; 558 559 if ((dragger.dragNode)&&(dragger.dragNode.parentNode == document.body)) 560 dragger.dragNode.parentNode.removeChild(dragger.dragNode); 561 dragger.dragNode=0; 562 dragger.gldragNode=0; 563 dragger.fx=0; 564 dragger.fy=0; 565 dragger.dragStartNode=0; 566 dragger.dragStartObject=0; 567 document.body.onmouseup=dragger.tempDOMU; 568 document.body.onmousemove=dragger.tempDOMM; 569 dragger.tempDOMU=null; 570 dragger.tempDOMM=null; 571 dragger.waitDrag=0; 572} 573 574dhtmlDragAndDropObject.prototype.stopFrameRoute=function(win){ 575 if (win) 576 window.dhtmlDragAndDrop.stopDrag(1, 1); 577 578 for (var i = 0; i < window.frames.length; i++){ 579 try{ 580 if ((window.frames[i] != win)&&(window.frames[i].dhtmlDragAndDrop)) 581 window.frames[i].dhtmlDragAndDrop.stopFrameRoute(window); 582 } catch(e){} 583 } 584 585 try{ 586 if ((parent.dhtmlDragAndDrop)&&(parent != window)&&(parent != win)) 587 parent.dhtmlDragAndDrop.stopFrameRoute(window); 588 } catch(e){} 589} 590dhtmlDragAndDropObject.prototype.initFrameRoute=function(win, mode){ 591 if (win){ 592 window.dhtmlDragAndDrop.preCreateDragCopy(); 593 window.dhtmlDragAndDrop.dragStartNode=win.dhtmlDragAndDrop.dragStartNode; 594 window.dhtmlDragAndDrop.dragStartObject=win.dhtmlDragAndDrop.dragStartObject; 595 window.dhtmlDragAndDrop.dragNode=win.dhtmlDragAndDrop.dragNode; 596 window.dhtmlDragAndDrop.gldragNode=win.dhtmlDragAndDrop.dragNode; 597 window.document.body.onmouseup=window.dhtmlDragAndDrop.stopDrag; 598 window.waitDrag=0; 599 600 if (((!_isIE)&&(mode))&&((!_isFF)||(_FFrv < 1.8))) 601 window.dhtmlDragAndDrop.calculateFramePosition(); 602 } 603 try{ 604 if ((parent.dhtmlDragAndDrop)&&(parent != window)&&(parent != win)) 605 parent.dhtmlDragAndDrop.initFrameRoute(window); 606 }catch(e){} 607 608 for (var i = 0; i < window.frames.length; i++){ 609 try{ 610 if ((window.frames[i] != win)&&(window.frames[i].dhtmlDragAndDrop)) 611 window.frames[i].dhtmlDragAndDrop.initFrameRoute(window, ((!win||mode) ? 1 : 0)); 612 } catch(e){} 613 } 614} 615 616_isFF = false; 617_isIE = false; 618_isOpera = false; 619_isKHTML = false; 620_isMacOS = false; 621_isChrome = false; 622_FFrv = false; 623_KHTMLrv = false; 624_OperaRv = false; 625 626if (navigator.userAgent.indexOf('Macintosh') != -1) 627 _isMacOS=true; 628 629 630if (navigator.userAgent.toLowerCase().indexOf('chrome')>-1) 631 _isChrome=true; 632 633if ((navigator.userAgent.indexOf('Safari') != -1)||(navigator.userAgent.indexOf('Konqueror') != -1)){
634 _KHTMLrv = parseFloat(navigator.userAgent.substr(navigator.userAgent.indexOf('Safari')+7, 5)); 635 636 if (_KHTMLrv > 525){ //mimic FF behavior for Safari 3.1+ 637 _isFF=true; 638 _FFrv = 1.9; 639 } else 640 _isKHTML=true; 641} else if (navigator.userAgent.indexOf('Opera') != -1){ 642 _isOpera=true; 643 _OperaRv=parseFloat(navigator.userAgent.substr(navigator.userAgent.indexOf('Opera')+6, 3)); 644} 645 646 647else if (navigator.appName.indexOf("Microsoft") != -1){ 648 _isIE=true; 649 if ((navigator.appVersion.indexOf("MSIE 8.0")!= -1 || navigator.appVersion.indexOf("MSIE 9.0")!= -1 || navigator.appVersion.indexOf("MSIE 10.0")!= -1 ) && document.compatMode != "BackCompat"){ 650 _isIE=8; 651 } 652} else { 653 _isFF=true; 654 _FFrv = parseFloat(navigator.userAgent.split("rv:")[1]) 655} 656 657 658//multibrowser Xpath processor 659dtmlXMLLoaderObject.prototype.doXPath=function(xpathExp, docObj, namespace, result_type){ 660 if (_isKHTML || (!_isIE && !window.XPathResult)) 661 return this.doXPathOpera(xpathExp, docObj); 662 663 if (_isIE){ //IE 664 if (!docObj) 665 if (!this.xmlDoc.nodeName) 666 docObj=this.xmlDoc.responseXML 667 else 668 docObj=this.xmlDoc; 669 670 if (!docObj) 671 dhtmlxError.throwError("LoadXML", "Incorrect XML", [ 672 (docObj||this.xmlDoc), 673 this.mainObject 674 ]); 675 676 if (namespace != null) 677 docObj.setProperty("SelectionNamespaces", "xmlns:xsl='"+namespace+"'"); // 678 679 if (result_type == 'single'){ 680 return docObj.selectSingleNode(xpathExp); 681 } 682 else { 683 return docObj.selectNodes(xpathExp)||new Array(0); 684 } 685 } else { //Mozilla 686 var nodeObj = docObj; 687 688 if (!docObj){ 689 if (!this.xmlDoc.nodeName){ 690 docObj=this.xmlDoc.responseXML 691 } 692 else { 693 docObj=this.xmlDoc; 694 } 695 } 696 697 if (!docObj) 698 dhtmlxError.throwError("LoadXML", "Incorrect XML", [ 699 (docObj||this.xmlDoc), 700 this.mainObject 701 ]); 702 703 if (docObj.nodeName.indexOf("document") != -1){ 704 nodeObj=docObj; 705 } 706 else { 707 nodeObj=docObj; 708 docObj=docObj.ownerDocument; 709 } 710 var retType = XPathResult.ANY_TYPE; 711 712 if (result_type == 'single') 713 retType=XPathResult.FIRST_ORDERED_NODE_TYPE 714 var rowsCol = new Array(); 715 var col = docObj.evaluate(xpathExp, nodeObj, function(pref){ 716 return namespace 717 }, retType, null); 718 719 if (retType == XPathResult.FIRST_ORDERED_NODE_TYPE){ 720 return col.singleNodeValue; 721 } 722 var thisColMemb = col.iterateNext(); 723 724 while (thisColMemb){ 725 rowsCol[rowsCol.length]=thisColMemb; 726 thisColMemb=col.iterateNext(); 727 } 728 return rowsCol; 729 } 730} 731 732function _dhtmlxError(type, name, params){ 733 if (!this.catches) 734 this.catches=new Array(); 735 736 return this; 737} 738 739_dhtmlxError.prototype.catchError=function(type, func_name){ 740 this.catches[type]=func_name; 741} 742_dhtmlxError.prototype.throwError=function(type, name, params){ 743 if (this.catches[type]) 744 return this.catches[type](type, name, params); 745 746 if (this.catches["ALL"]) 747 return this.catches["ALL"](type, name, params); 748 749 alert("Error type: "+arguments[0]+"\nDescription: "+arguments[1]); 750 return null; 751} 752 753window.dhtmlxError=new _dhtmlxError(); 754 755 756//opera fake, while 9.0 not released 757//multibrowser Xpath processor 758dtmlXMLLoaderObject.prototype.doXPathOpera=function(xpathExp, docObj){ 759 //this is fake for Opera 760 var z = xpathExp.replace(/[\/]+/gi, "/").split('/'); 761 var obj = null; 762 var i = 1; 763 764 if (!z.length) 765 return []; 766 767 if (z[0] == ".") 768 obj=[docObj]; else if (z[0] == ""){ 769 obj=(this.xmlDoc.responseXML||this.xmlDoc).getElementsByTagName(z[i].replace(/\[[^\]]*\]/g, "")); 770 i++; 771 } else 772 return []; 773 774 for (i; i < z.length; i++)obj=this._getAllNamedChilds(obj, z[i]); 775 776 if (z[i-1].indexOf("[") != -1) 777 obj=this._filterXPath(obj, z[i-1]); 778 return obj; 779} 780 781dtmlXMLLoaderObject.prototype._filterXPath=function(a, b){ 782 var c = new Array(); 783 var b = b.replace(/[^\[]*\[\@/g, "").replace(/[\[\]\@]*/g, ""); 784 785 for (var i = 0; i < a.length; i++) 786 if (a[i].getAttribute(b)) 787 c[c.length]=a[i]; 788 789 return c; 790} 791dtmlXMLLoaderObject.prototype._getAllNamedChilds=function(a, b){ 792 var c = new Array(); 793 794 if (_isKHTML) 795 b=b.toUpperCase(); 796 797 for (var i = 0; i < a.length; i++)for (var j = 0; j < a[i].childNodes.length; j++){ 798 if (_isKHTML){ 799 if (a[i].childNodes[j].tagName&&a[i].childNodes[j].tagName.toUpperCase() == b) 800 c[c.length]=a[i].childNodes[j]; 801 } 802 803 else if (a[i].childNodes[j].tagName == b) 804 c[c.length]=a[i].childNodes[j]; 805 } 806 807 return c; 808} 809 810function dhtmlXHeir(a, b){ 811 for (var c in b) 812 if (typeof (b[c]) == "function") 813 a[c]=b[c]; 814 return a; 815} 816 817function dhtmlxEvent(el, event, handler){ 818 if (el.addEventListener) 819 el.addEventListener(event, handler, false); 820 821 else if (el.attachEvent) 822 el.attachEvent("on"+event, handler); 823} 824 825//============= XSL Extension =================================== 826 827dtmlXMLLoaderObject.prototype.xslDoc=null; 828dtmlXMLLoaderObject.prototype.setXSLParamValue=function(paramName, paramValue, xslDoc){ 829 if (!xslDoc) 830 xslDoc=this.xslDoc 831 832 if (xslDoc.responseXML) 833 xslDoc=xslDoc.responseXML; 834 var item = 835 this.doXPath("/xsl:stylesheet/xsl:variable[@name='"+paramName+"']", xslDoc, 836 "http:/\/www.w3.org/1999/XSL/Transform", "single"); 837 838 if (item != null) 839 item.firstChild.nodeValue=paramValue 840} 841dtmlXMLLoaderObject.prototype.doXSLTransToObject=function(xslDoc, xmlDoc){ 842 if (!xslDoc) 843 xslDoc=this.xslDoc; 844 845 if (xslDoc.responseXML) 846 xslDoc=xslDoc.responseXML 847 848 if (!xmlDoc) 849 xmlDoc=this.xmlDoc; 850 851 if (xmlDoc.responseXML) 852 xmlDoc=xmlDoc.responseXML 853 854 //MOzilla 855 if (!_isIE){ 856 if (!this.XSLProcessor){ 857 this.XSLProcessor=new XSLTProcessor(); 858 this.XSLProcessor.importStylesheet(xslDoc); 859 } 860 var result = this.XSLProcessor.transformToDocument(xmlDoc); 861 } else { 862 var result = new ActiveXObject("Msxml2.DOMDocument.3.0"); 863 try{ 864 xmlDoc.transformNodeToObject(xslDoc, result); 865 }catch(e){ 866 result = xmlDoc.transformNode(xslDoc); 867 } 868 } 869 return result; 870} 871 872dtmlXMLLoaderObject.prototype.doXSLTransToString=function(xslDoc, xmlDoc){ 873 var res = this.doXSLTransToObject(xslDoc, xmlDoc); 874 if(typeof(res)=="string") 875 return res; 876 return this.doSerialization(res); 877} 878 879dtmlXMLLoaderObject.prototype.doSerialization=function(xmlDoc){ 880 if (!xmlDoc) 881 xmlDoc=this.xmlDoc; 882 if (xmlDoc.responseXML) 883 xmlDoc=xmlDoc.responseXML 884 if (!_isIE){ 885 var xmlSerializer = new XMLSerializer(); 886 return xmlSerializer.serializeToString(xmlDoc); 887 } else 888 return xmlDoc.xml; 889} 890 891/** 892 * @desc: 893 * @type: private 894 */ 895dhtmlxEventable=function(obj){ 896 obj.attachEvent=function(name, catcher, callObj){ 897 name='ev_'+name.toLowerCase(); 898 if (!this[name]) 899 this[name]=new this.eventCatcher(callObj||this); 900 901 return(name+':'+this[name].addEvent(catcher)); //return ID (event name & event ID) 902 } 903 obj.callEvent=function(name, arg0){ 904 name='ev_'+name.toLowerCase(); 905 if (this[name]) 906 return this[name].apply(this, arg0); 907 return true; 908 } 909 obj.checkEvent=function(name){ 910 return (!!this['ev_'+name.toLowerCase()]) 911 } 912 obj.eventCatcher=function(obj){ 913 var dhx_catch = []; 914 var z = function(){ 915 var res = true; 916 for (var i = 0; i < dhx_catch.length; i++){ 917 if (dhx_catch[i] != null){ 918 var zr = dhx_catch[i].apply(obj, arguments); 919 res=res&&zr; 920 } 921 } 922 return res; 923 } 924 z.addEvent=function(ev){ 925 if (typeof (ev) != "function") 926 ev=eval(ev); 927 if (ev) 928 return dhx_catch.push(ev)-1; 929 return false; 930 } 931 z.removeEvent=function(id){ 932 dhx_catch[id]=null; 933 } 934 return z; 935 } 936 obj.detachEvent=function(id){ 937 if (id != false){ 938 var list = id.split(':'); //get EventName and ID 939 this[list[0]].removeEvent(list[1]); //remove event 940 } 941 } 942 obj.detachAllEvents = function(){ 943 for (var name in this){ 944 if (name.indexOf("ev_")==0) 945 delete this[name]; 946 } 947 } 948 obj = null; 949}; 950 951if(!window.dhtmlx) 952 window.dhtmlx = {}; 953 954(function(){ 955 var _dhx_msg_cfg = null; 956 function callback(config, result){ 957 var usercall = config.callback; 958 modality(false);
959 config.box.parentNode.removeChild(config.box); 960 _dhx_msg_cfg = config.box = null; 961 if (usercall) 962 usercall(result); 963 } 964 function modal_key(e){ 965 if (_dhx_msg_cfg){ 966 e = e||event; 967 var code = e.which||event.keyCode; 968 if (dhtmlx.message.keyboard){ 969 if (code == 13 || code == 32) 970 callback(_dhx_msg_cfg, true); 971 if (code == 27) 972 callback(_dhx_msg_cfg, false); 973 } 974 if (e.preventDefault) 975 e.preventDefault(); 976 return !(e.cancelBubble = true); 977 } 978 } 979 if (document.attachEvent) 980 document.attachEvent("onkeydown", modal_key); 981 else 982 document.addEventListener("keydown", modal_key, true); 983 984 function modality(mode){ 985 if(!modality.cover){ 986 modality.cover = document.createElement("DIV"); 987 //necessary for IE only 988 modality.cover.onkeydown = modal_key; 989 modality.cover.className = "dhx_modal_cover"; 990 document.body.appendChild(modality.cover); 991 } 992 var height = document.body.scrollHeight; 993 modality.cover.style.display = mode?"inline-block":"none"; 994 } 995 996 function button(text, result){ 997 var button_css = "dhtmlx_"+text.toLowerCase().replace(/ /g, "_")+"_button"; // dhtmlx_ok_button, dhtmlx_click_me_button 998 return "<div class='dhtmlx_popup_button "+button_css+"' result='"+result+"' ><div>"+text+"</div></div>"; 999 } 1000 1001 function info(text){ 1002 if (!t.area){ 1003 t.area = document.createElement("DIV"); 1004 t.area.className = "dhtmlx_message_area"; 1005 t.area.style[t.position]="5px"; 1006 document.body.appendChild(t.area); 1007 } 1008 1009 t.hide(text.id); 1010 var message = document.createElement("DIV"); 1011 message.innerHTML = "<div>"+text.text+"</div>"; 1012 message.className = "dhtmlx-info dhtmlx-" + text.type; 1013 message.onclick = function(){ 1014 t.hide(text.id); 1015 text = null; 1016 }; 1017 1018 if (t.position == "bottom" && t.area.firstChild) 1019 t.area.insertBefore(message,t.area.firstChild); 1020 else 1021 t.area.appendChild(message); 1022 1023 if (text.expire > 0) 1024 t.timers[text.id]=window.setTimeout(function(){ 1025 t.hide(text.id); 1026 }, text.expire); 1027 1028 t.pull[text.id] = message; 1029 message = null; 1030 1031 return text.id; 1032 } 1033 function _boxStructure(config, ok, cancel){ 1034 var box = document.createElement("DIV"); 1035 box.className = " dhtmlx_modal_box dhtmlx-"+config.type; 1036 box.setAttribute("dhxbox", 1); 1037 1038 var inner = ''; 1039 1040 if (config.width) 1041 box.style.width = config.width; 1042 if (config.height) 1043 box.style.height = config.height; 1044 if (config.title) 1045 inner+='<div class="dhtmlx_popup_title">'+config.title+'</div>'; 1046 inner+='<div class="dhtmlx_popup_text"><span>'+(config.content?'':config.text)+'</span></div><div class="dhtmlx_popup_controls">'; 1047 if (ok) 1048 inner += button(config.ok || "OK", true); 1049 if (cancel) 1050 inner += button(config.cancel || "Cancel", false); 1051 if (config.buttons){ 1052 for (var i=0; i<config.buttons.length; i++) 1053 inner += button(config.buttons[i],i); 1054 } 1055 inner += '</div>'; 1056 box.innerHTML = inner; 1057 1058 if (config.content){ 1059 var node = config.content; 1060 if (typeof node == "string") 1061 node = document.getElementById(node); 1062 if (node.style.display == 'none') 1063 node.style.display = ""; 1064 box.childNodes[config.title?1:0].appendChild(node); 1065 } 1066 1067 box.onclick = function(e){ 1068 e = e ||event; 1069 var source = e.target || e.srcElement; 1070 if (!source.className) source = source.parentNode; 1071 if (source.className.split(" ")[0] == "dhtmlx_popup_button"){ 1072 result = source.getAttribute("result"); 1073 result = (result == "true")||(result == "false"?false:result); 1074 callback(config, result); 1075 } 1076 }; 1077 config.box = box; 1078 if (ok||cancel) 1079 _dhx_msg_cfg = config; 1080 1081 return box; 1082 } 1083 function _createBox(config, ok, cancel){ 1084 var box = config.tagName ? config : _boxStructure(config, ok, cancel); 1085 1086 if (!config.hidden) 1087 modality(true); 1088 document.body.appendChild(box); 1089 var x = Math.abs(Math.floor(((window.innerWidth||document.documentElement.offsetWidth) - box.offsetWidth)/2)); 1090 var y = Math.abs(Math.floor(((window.innerHeight||document.documentElement.offsetHeight) - box.offsetHeight)/2)); 1091 if (config.position == "top") 1092 box.style.top = "-3px"; 1093 else 1094 box.style.top = y+'px'; 1095 box.style.left = x+'px'; 1096 //necessary for IE only 1097 box.onkeydown = modal_key; 1098 1099 box.focus(); 1100 if (config.hidden) 1101 dhtmlx.modalbox.hide(box); 1102 1103 return box; 1104 } 1105 1106 function alertPopup(config){ 1107 return _createBox(config, true, false); 1108 } 1109 function confirmPopup(config){ 1110 return _createBox(config, true, true); 1111 } 1112 function boxPopup(config){ 1113 return _createBox(config); 1114 } 1115 function box_params(text, type, callback){ 1116 if (typeof text != "object"){ 1117 if (typeof type == "function"){ 1118 callback = type; 1119 type = ""; 1120 } 1121 text = {text:text, type:type, callback:callback }; 1122 } 1123 return text; 1124 } 1125 function params(text, type, expire, id){ 1126 if (typeof text != "object")
1127 text = {text:text, type:type, expire:expire, id:id}; 1128 text.id = text.id||t.uid(); 1129 text.expire = text.expire||t.expire; 1130 return text; 1131 } 1132 dhtmlx.alert = function(){ 1133 text = box_params.apply(this, arguments); 1134 text.type = text.type || "confirm"; 1135 return alertPopup(text); 1136 }; 1137 dhtmlx.confirm = function(){ 1138 text = box_params.apply(this, arguments); 1139 text.type = text.type || "alert"; 1140 return confirmPopup(text); 1141 }; 1142 dhtmlx.modalbox = function(){ 1143 text = box_params.apply(this, arguments); 1144 text.type = text.type || "alert"; 1145 return boxPopup(text); 1146 }; 1147 dhtmlx.modalbox.hide = function(node){ 1148 while (node && node.getAttribute && !node.getAttribute("dhxbox")) 1149 node = node.parentNode; 1150 if (node){ 1151 node.parentNode.removeChild(node); 1152 modality(false); 1153 } 1154 }; 1155 var t = dhtmlx.message = function(text, type, expire, id){ 1156 text = params.apply(this, arguments); 1157 text.type = text.type||"info"; 1158 1159 var subtype = text.type.split("-")[0]; 1160 switch (subtype){ 1161 case "alert": 1162 return alertPopup(text); 1163 case "confirm": 1164 return confirmPopup(text); 1165 case "modalbox": 1166 return boxPopup(text); 1167 default: 1168 return info(text); 1169 break; 1170 } 1171 }; 1172 1173 t.seed = (new Date()).valueOf(); 1174 t.uid = function(){return t.seed++;}; 1175 t.expire = 4000; 1176 t.keyboard = true; 1177 t.position = "top"; 1178 t.pull = {}; 1179 t.timers = {}; 1180 1181 t.hideAll = function(){ 1182 for (var key in t.pull) 1183 t.hide(key); 1184 }; 1185 t.hide = function(id){ 1186 var obj = t.pull[id]; 1187 if (obj && obj.parentNode){ 1188 window.setTimeout(function(){ 1189 obj.parentNode.removeChild(obj); 1190 obj = null; 1191 },2000); 1192 obj.className+=" hidden"; 1193 1194 if(t.timers[id]) 1195 window.clearTimeout(t.timers[id]); 1196 delete t.pull[id]; 1197 } 1198 }; 1199})(); 1200/** 1201 * @desc: constructor, data processor object 1202 * @param: serverProcessorURL - url used for update 1203 * @type: public 1204 */ 1205function dataProcessor(serverProcessorURL){ 1206 this.serverProcessor = serverProcessorURL; 1207 this.action_param="!nativeeditor_status"; 1208 1209 this.object = null; 1210 this.updatedRows = []; //ids of updated rows 1211 1212 this.autoUpdate = true; 1213 this.updateMode = "cell"; 1214 this._tMode="GET"; 1215 this.post_delim = "_"; 1216 1217 this._waitMode=0; 1218 this._in_progress={};//? 1219 this._invalid={}; 1220 this.mandatoryFields=[]; 1221 this.messages=[]; 1222 1223 this.styles={ 1224 updated:"font-weight:bold;", 1225 inserted:"font-weight:bold;", 1226 deleted:"text-decoration : line-through;", 1227 invalid:"background-color:FFE0E0;", 1228 invalid_cell:"border-bottom:2px solid red;", 1229 error:"color:red;", 1230 clear:"font-weight:normal;text-decoration:none;" 1231 }; 1232 1233 this.enableUTFencoding(true); 1234 dhtmlxEventable(this); 1235 1236 return this; 1237 } 1238 1239dataProcessor.prototype={ 1240 /** 1241 * @desc: select GET or POST transaction model 1242 * @param: mode - GET/POST 1243 * @param: total - true/false - send records row by row or all at once (for grid only) 1244 * @type: public 1245 */ 1246 setTransactionMode:function(mode,total){ 1247 this._tMode=mode; 1248 this._tSend=total; 1249 }, 1250 escape:function(data){ 1251 if (this._utf) 1252 return encodeURIComponent(data); 1253 else 1254 return escape(data); 1255 }, 1256 /** 1257 * @desc: allows to set escaping mode 1258 * @param: true - utf based escaping, simple - use current page encoding 1259 * @type: public 1260 */ 1261 enableUTFencoding:function(mode){ 1262 this._utf=convertStringToBoolean(mode); 1263 }, 1264 /** 1265 * @desc: allows to define, which column may trigger update 1266 * @param: val - array or list of true/false values 1267 * @type: public 1268 */ 1269 setDataColumns:function(val){ 1270 this._columns=(typeof val == "string")?val.split(","):val; 1271 }, 1272 /** 1273 * @desc: get state of updating 1274 * @returns: true - all in sync with server, false - some items not updated yet. 1275 * @type: public 1276 */ 1277 getSyncState:function(){ 1278 return !this.updatedRows.length; 1279 }, 1280 /** 1281 * @desc: enable/disable named field for data syncing, will use column ids for grid 1282 * @param: mode - true/false 1283 * @type: public 1284 */ 1285 enableDataNames:function(mode){ 1286 this._endnm=convertStringToBoolean(mode); 1287 }, 1288 /** 1289 * @desc: enable/disable mode , when only changed fields and row id send to the server side, instead of all fields in default mode 1290 * @param: mode - true/false 1291 * @type: public 1292 */
1293 enablePartialDataSend:function(mode){ 1294 this._changed=convertStringToBoolean(mode); 1295 }, 1296 /** 1297 * @desc: set if rows should be send to server automaticaly 1298 * @param: mode - "row" - based on row selection changed, "cell" - based on cell editing finished, "off" - manual data sending 1299 * @type: public 1300 */ 1301 setUpdateMode:function(mode,dnd){ 1302 this.autoUpdate = (mode=="cell"); 1303 this.updateMode = mode; 1304 this.dnd=dnd; 1305 }, 1306 ignore:function(code,master){ 1307 this._silent_mode=true; 1308 code.call(master||window); 1309 this._silent_mode=false; 1310 }, 1311 /** 1312 * @desc: mark row as updated/normal. check mandatory fields,initiate autoupdate (if turned on) 1313 * @param: rowId - id of row to set update-status for 1314 * @param: state - true for "updated", false for "not updated" 1315 * @param: mode - update mode name 1316 * @type: public 1317 */ 1318 setUpdated:function(rowId,state,mode){ 1319 if (this._silent_mode) return; 1320 var ind=this.findRow(rowId); 1321 1322 mode=mode||"updated"; 1323 var existing = this.obj.getUserData(rowId,this.action_param); 1324 if (existing && mode == "updated") mode=existing; 1325 if (state){ 1326 this.set_invalid(rowId,false); //clear previous error flag 1327 this.updatedRows[ind]=rowId; 1328 this.obj.setUserData(rowId,this.action_param,mode); 1329 if (this._in_progress[rowId]) 1330 this._in_progress[rowId]="wait"; 1331 } else{ 1332 if (!this.is_invalid(rowId)){ 1333 this.updatedRows.splice(ind,1); 1334 this.obj.setUserData(rowId,this.action_param,""); 1335 } 1336 } 1337 1338 //clear changed flag 1339 if (!state) 1340 this._clearUpdateFlag(rowId); 1341 1342 this.markRow(rowId,state,mode); 1343 if (state && this.autoUpdate) this.sendData(rowId); 1344 }, 1345 _clearUpdateFlag:function(id){}, 1346 markRow:function(id,state,mode){ 1347 var str=""; 1348 var invalid=this.is_invalid(id); 1349 if (invalid){ 1350 str=this.styles[invalid]; 1351 state=true; 1352 } 1353 if (this.callEvent("onRowMark",[id,state,mode,invalid])){ 1354 //default logic 1355 str=this.styles[state?mode:"clear"]+str; 1356 1357 this.obj[this._methods[0]](id,str); 1358 1359 if (invalid && invalid.details){ 1360 str+=this.styles[invalid+"_cell"]; 1361 for (var i=0; i < invalid.details.length; i++) 1362 if (invalid.details[i]) 1363 this.obj[this._methods[1]](id,i,str); 1364 } 1365 } 1366 }, 1367 getState:function(id){ 1368 return this.obj.getUserData(id,this.action_param); 1369 }, 1370 is_invalid:function(id){ 1371 return this._invalid[id]; 1372 }, 1373 set_invalid:function(id,mode,details){ 1374 if (details) mode={value:mode, details:details, toString:function(){ return this.value.toString(); }}; 1375 this._invalid[id]=mode; 1376 }, 1377 /** 1378 * @desc: check mandatory fields and varify values of cells, initiate update (if specified) 1379 * @param: rowId - id of row to set update-status for 1380 * @type: public 1381 */ 1382 checkBeforeUpdate:function(rowId){ 1383 return true; 1384 }, 1385 /** 1386 * @desc: send row(s) values to server 1387 * @param: rowId - id of row which data to send. If not specified, then all "updated" rows will be send 1388 * @type: public 1389 */ 1390 sendData:function(rowId){ 1391 if (this._waitMode && (this.obj.mytype=="tree" || this.obj._h2)) return; 1392 if (this.obj.editStop) this.obj.editStop(); 1393 1394 1395 if(typeof rowId == "undefined" || this._tSend) return this.sendAllData(); 1396 if (this._in_progress[rowId]) return false; 1397 1398 this.messages=[]; 1399 if (!this.checkBeforeUpdate(rowId) && this.callEvent("onValidatationError",[rowId,this.messages])) return false; 1400 this._beforeSendData(this._getRowData(rowId),rowId); 1401 }, 1402 _beforeSendData:function(data,rowId){ 1403 if (!this.callEvent("onBeforeUpdate",[rowId,this.getState(rowId),data])) return false; 1404 this._sendData(data,rowId); 1405 }, 1406 serialize:function(data, id){ 1407 if (typeof data == "string") 1408 return data; 1409 if (typeof id != "undefined") 1410 return this.serialize_one(data,""); 1411 else{ 1412 var stack = []; 1413 var keys = []; 1414 for (var key in data) 1415 if (data.hasOwnProperty(key)){ 1416 stack.push(this.serialize_one(data[key],key+this.post_delim)); 1417 keys.push(key); 1418 } 1419 stack.push("ids="+this.escape(keys.join(","))); 1420 if (dhtmlx.security_key) 1421 stack.push("dhx_security="+dhtmlx.security_key); 1422 return stack.join("&"); 1423 } 1424 }, 1425 serialize_one:function(data, pref){ 1426 if (typeof data == "string") 1427 return data; 1428 var stack = []; 1429 for (var key in data) 1430 if (data.hasOwnProperty(key)) 1431 stack.push(this.escape((pref||"")+key)+"="+this.escape(data[key])); 1432 return stack.join("&"); 1433 },
1434 _sendData:function(a1,rowId){ 1435 if (!a1) return; //nothing to send 1436 if (!this.callEvent("onBeforeDataSending",rowId?[rowId,this.getState(rowId),a1]:[null, null, a1])) return false; 1437 1438 if (rowId) 1439 this._in_progress[rowId]=(new Date()).valueOf(); 1440 var a2=new dtmlXMLLoaderObject(this.afterUpdate,this,true); 1441 1442 var a3 = this.serverProcessor+(this._user?(getUrlSymbol(this.serverProcessor)+["dhx_user="+this._user,"dhx_version="+this.obj.getUserData(0,"version")].join("&")):""); 1443 1444 if (this._tMode!="POST") 1445 a2.loadXML(a3+((a3.indexOf("?")!=-1)?"&":"?")+this.serialize(a1,rowId)); 1446 else 1447 a2.loadXML(a3,true,this.serialize(a1,rowId)); 1448 1449 this._waitMode++; 1450 }, 1451 sendAllData:function(){ 1452 if (!this.updatedRows.length) return; 1453 1454 this.messages=[]; var valid=true; 1455 for (var i=0; i<this.updatedRows.length; i++) 1456 valid&=this.checkBeforeUpdate(this.updatedRows[i]); 1457 if (!valid && !this.callEvent("onValidatationError",["",this.messages])) return false; 1458 1459 if (this._tSend) 1460 this._sendData(this._getAllData()); 1461 else 1462 for (var i=0; i<this.updatedRows.length; i++) 1463 if (!this._in_progress[this.updatedRows[i]]){ 1464 if (this.is_invalid(this.updatedRows[i])) continue; 1465 this._beforeSendData(this._getRowData(this.updatedRows[i]),this.updatedRows[i]); 1466 if (this._waitMode && (this.obj.mytype=="tree" || this.obj._h2)) return; //block send all for tree 1467 } 1468 }, 1469 1470 1471 1472 1473 1474 1475 1476 1477 _getAllData:function(rowId){ 1478 var out={}; 1479 var has_one = false; 1480 for(var i=0;i<this.updatedRows.length;i++){ 1481 var id=this.updatedRows[i]; 1482 if (this._in_progress[id] || this.is_invalid(id)) continue; 1483 if (!this.callEvent("onBeforeUpdate",[id,this.getState(id)])) continue; 1484 out[id]=this._getRowData(id,id+this.post_delim); 1485 has_one = true; 1486 this._in_progress[id]=(new Date()).valueOf(); 1487 } 1488 return has_one?out:null; 1489 }, 1490 1491 1492 /** 1493 * @desc: specify column which value should be varified before sending to server 1494 * @param: ind - column index (0 based) 1495 * @param: verifFunction - function (object) which should verify cell value (if not specified, then value will be compared to empty string). Two arguments will be passed into it: value and column name 1496 * @type: public 1497 */ 1498 setVerificator:function(ind,verifFunction){ 1499 this.mandatoryFields[ind] = verifFunction||(function(value){return (value!="");}); 1500 }, 1501 /** 1502 * @desc: remove column from list of those which should be verified 1503 * @param: ind - column Index (0 based) 1504 * @type: public 1505 */ 1506 clearVerificator:function(ind){ 1507 this.mandatoryFields[ind] = false; 1508 }, 1509 1510 1511 1512 1513 1514 findRow:function(pattern){ 1515 var i=0; 1516 for(i=0;i<this.updatedRows.length;i++) 1517 if(pattern==this.updatedRows[i]) break; 1518 return i; 1519 }, 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 /** 1532 * @desc: define custom actions 1533 * @param: name - name of action, same as value of action attribute 1534 * @param: handler - custom function, which receives a XMl response content for action 1535 * @type: private 1536 */ 1537 defineAction:function(name,handler){ 1538 if (!this._uActions) this._uActions=[]; 1539 this._uActions[name]=handler; 1540 }, 1541 1542 1543 1544 1545 /** 1546* @desc: used in combination with setOnBeforeUpdateHandler to create custom client-server transport system 1547* @param: sid - id of item before update 1548* @param: tid - id of item after up0ate 1549* @param: action - action name 1550* @type: public 1551* @topic: 0 1552*/ 1553 afterUpdateCallback:function(sid, tid, action, btag) { 1554 var marker = sid; 1555 var correct=(action!="error" && action!="invalid"); 1556 if (!correct) this.set_invalid(sid,action); 1557 if ((this._uActions)&&(this._uActions[action])&&(!this._uActions[action](btag))) 1558 return (delete this._in_progress[marker]); 1559 1560 if (this._in_progress[marker]!="wait") 1561 this.setUpdated(sid, false); 1562 1563 var soid = sid; 1564 1565 switch (action) { 1566 case "update": 1567 case "updated": 1568 case "inserted": 1569 case "insert": 1570 if (tid != sid) { 1571 this.obj[this._methods[2]](sid, tid); 1572 sid = tid; 1573 } 1574 break;
1575 case "delete": 1576 case "deleted": 1577 this.obj.setUserData(sid, this.action_param, "true_deleted"); 1578 this.obj[this._methods[3]](sid); 1579 delete this._in_progress[marker]; 1580 return this.callEvent("onAfterUpdate", [sid, action, tid, btag]); 1581 break; 1582 } 1583 1584 if (this._in_progress[marker]!="wait"){ 1585 if (correct) this.obj.setUserData(sid, this.action_param,''); 1586 delete this._in_progress[marker]; 1587 } else { 1588 delete this._in_progress[marker]; 1589 this.setUpdated(tid,true,this.obj.getUserData(sid,this.action_param)); 1590 } 1591 1592 this.callEvent("onAfterUpdate", [sid, action, tid, btag]); 1593 }, 1594 1595 /** 1596 * @desc: response from server 1597 * @param: xml - XMLLoader object with response XML 1598 * @type: private 1599 */ 1600 afterUpdate:function(that,b,c,d,xml){ 1601 xml.getXMLTopNode("data"); //fix incorrect content type in IE 1602 if (!xml.xmlDoc.responseXML) return; 1603 var atag=xml.doXPath("//data/action"); 1604 for (var i=0; i<atag.length; i++){ 1605 var btag=atag[i]; 1606 var action = btag.getAttribute("type"); 1607 var sid = btag.getAttribute("sid"); 1608 var tid = btag.getAttribute("tid"); 1609 1610 that.afterUpdateCallback(sid,tid,action,btag); 1611 } 1612 that.finalizeUpdate(); 1613 }, 1614 finalizeUpdate:function(){ 1615 if (this._waitMode) this._waitMode--; 1616 1617 if ((this.obj.mytype=="tree" || this.obj._h2) && this.updatedRows.length) 1618 this.sendData(); 1619 this.callEvent("onAfterUpdateFinish",[]); 1620 if (!this.updatedRows.length) 1621 this.callEvent("onFullSync",[]); 1622 }, 1623 1624 1625 1626 1627 1628 /** 1629 * @desc: initializes data-processor 1630 * @param: anObj - dhtmlxGrid object to attach this data-processor to 1631 * @type: public 1632 */ 1633 init:function(anObj){ 1634 this.obj = anObj; 1635 if (this.obj._dp_init) 1636 this.obj._dp_init(this); 1637 }, 1638 1639 1640 setOnAfterUpdate:function(ev){ 1641 this.attachEvent("onAfterUpdate",ev); 1642 }, 1643 enableDebug:function(mode){ 1644 }, 1645 setOnBeforeUpdateHandler:function(func){ 1646 this.attachEvent("onBeforeDataSending",func); 1647 }, 1648 1649 1650 1651 /*! starts autoupdate mode 1652 @param interval 1653 time interval for sending update requests 1654 */ 1655 setAutoUpdate: function(interval, user) { 1656 interval = interval || 2000; 1657 1658 this._user = user || (new Date()).valueOf(); 1659 this._need_update = false; 1660 this._loader = null; 1661 this._update_busy = false; 1662 1663 this.attachEvent("onAfterUpdate",function(sid,action,tid,xml_node){ 1664 this.afterAutoUpdate(sid, action, tid, xml_node); 1665 }); 1666 this.attachEvent("onFullSync",function(){ 1667 this.fullSync(); 1668 }); 1669 1670 var self = this; 1671 window.setInterval(function(){ 1672 self.loadUpdate(); 1673 }, interval); 1674 }, 1675 1676 1677 /*! process updating request answer 1678 if status == collision version is depricated 1679 set flag for autoupdating immidiatly 1680 */ 1681 afterAutoUpdate: function(sid, action, tid, xml_node) { 1682 if (action == 'collision') { 1683 this._need_update = true; 1684 return false; 1685 } else { 1686 return true; 1687 } 1688 }, 1689 1690 1691 /*! callback function for onFillSync event 1692 call update function if it's need 1693 */ 1694 fullSync: function() { 1695 if (this._need_update == true) { 1696 this._need_update = false; 1697 this.loadUpdate(); 1698 } 1699 return true; 1700 }, 1701 1702 1703 /*! sends query to the server and call callback function 1704 */ 1705 getUpdates: function(url,callback){ 1706 if (this._update_busy) 1707 return false; 1708 else 1709 this._update_busy = true; 1710 1711 this._loader = this._loader || new dtmlXMLLoaderObject(true); 1712 1713 this._loader.async=true; 1714 this._loader.waitCall=callback; 1715 this._loader.loadXML(url); 1716 }, 1717 1718 1719 /*! returns xml node value 1720 @param node 1721 xml node 1722 */ 1723 _v: function(node) { 1724 if (node.firstChild) return node.firstChild.nodeValue; 1725 return ""; 1726 }, 1727 1728 1729 /*! returns values array of xml nodes array 1730 @param arr 1731 array of xml nodes 1732 */ 1733 _a: function(arr) { 1734 var res = []; 1735 for (var i=0; i < arr.length; i++) { 1736 res[i]=this._v(arr[i]); 1737 }; 1738 return res; 1739 }, 1740 1741 1742 /*! loads updates and processes them 1743 */ 1744 loadUpdate: function(){ 1745 var self = this; 1746 var version = this.obj.getUserData(0,"version"); 1747 var url = this.serverProcessor+getUrlSymbol(this.serverProcessor)+["dhx_user="+this._user,"dhx_version="+version].join("&"); 1748 url = url.replace("editing=true&",""); 1749 this.getUpdates(url, function(){ 1750 var vers = self._loader.doXPath("//userdata"); 1751 self.obj.setUserData(0,"version",self._v(vers[0])); 1752 1753 var upds = self._loader.doXPath("//update"); 1754 if (upds.length){ 1755 self._silent_mode = true; 1756 1757 for (var i=0; i<upds.length; i++) { 1758 var status = upds[i].getAttribute('status'); 1759 var id = upds[i].getAttribute('id'); 1760 var parent = upds[i].getAttribute('parent'); 1761 switch (status) { 1762 case 'inserted': 1763 self.callEvent("insertCallback",[upds[i], id, parent]);
1764 break; 1765 case 'updated': 1766 self.callEvent("updateCallback",[upds[i], id, parent]); 1767 break; 1768 case 'deleted': 1769 self.callEvent("deleteCallback",[upds[i], id, parent]); 1770 break; 1771 } 1772 } 1773 1774 self._silent_mode = false; 1775 } 1776 1777 self._update_busy = false; 1778 self = null; 1779 }); 1780 } 1781 1782}; 1783 1784//(c)dhtmlx ltd. www.dhtmlx.com 1785/* 1786 dhx_sort[index]=direction 1787 dhx_filter[index]=mask 1788*/ 1789if (window.dhtmlXGridObject){ 1790 dhtmlXGridObject.prototype._init_point_connector=dhtmlXGridObject.prototype._init_point; 1791 dhtmlXGridObject.prototype._init_point=function(){ 1792 var clear_url=function(url){ 1793 url=url.replace(/(\?|\&)connector[^\f]*/g,""); 1794 return url+(url.indexOf("?")!=-1?"&":"?")+"connector=true"+(this.hdr.rows.length > 0 ? "&dhx_no_header=1":""); 1795 }; 1796 var combine_urls=function(url){ 1797 return clear_url.call(this,url)+(this._connector_sorting||"")+(this._connector_filter||""); 1798 }; 1799 var sorting_url=function(url,ind,dir){ 1800 this._connector_sorting="&dhx_sort["+ind+"]="+dir; 1801 return combine_urls.call(this,url); 1802 }; 1803 var filtering_url=function(url,inds,vals){ 1804 for (var i=0; i<inds.length; i++) 1805 inds[i]="dhx_filter["+inds[i]+"]="+encodeURIComponent(vals[i]); 1806 this._connector_filter="&"+inds.join("&"); 1807 return combine_urls.call(this,url); 1808 }; 1809 this.attachEvent("onCollectValues",function(ind){ 1810 if (this._con_f_used[ind]){ 1811 if (typeof(this._con_f_used[ind]) == "object") 1812 return this._con_f_used[ind]; 1813 else 1814 return false; 1815 } 1816 return true; 1817 }); 1818 this.attachEvent("onDynXLS",function(){ 1819 this.xmlFileUrl=combine_urls.call(this,this.xmlFileUrl); 1820 return true; 1821 }); 1822 this.attachEvent("onBeforeSorting",function(ind,type,dir){ 1823 if (type=="connector"){ 1824 var self=this; 1825 this.clearAndLoad(sorting_url.call(this,this.xmlFileUrl,ind,dir),function(){ 1826 self.setSortImgState(true,ind,dir); 1827 }); 1828 return false; 1829 } 1830 return true; 1831 }); 1832 this.attachEvent("onFilterStart",function(a,b){ 1833 if (this._con_f_used.length){ 1834 this.clearAndLoad(filtering_url.call(this,this.xmlFileUrl,a,b)); 1835 return false; 1836 } 1837 return true; 1838 }); 1839 this.attachEvent("onXLE",function(a,b,c,xml){ 1840 if (!xml) return; 1841 }); 1842 1843 if (this._init_point_connector) this._init_point_connector(); 1844 }; 1845 dhtmlXGridObject.prototype._con_f_used=[]; 1846 dhtmlXGridObject.prototype._in_header_connector_text_filter=function(t,i){ 1847 if (!this._con_f_used[i]) 1848 this._con_f_used[i]=1; 1849 return this._in_header_text_filter(t,i); 1850 }; 1851 dhtmlXGridObject.prototype._in_header_connector_select_filter=function(t,i){ 1852 if (!this._con_f_used[i]) 1853 this._con_f_used[i]=2; 1854 return this._in_header_select_filter(t,i); 1855 }; 1856 dhtmlXGridObject.prototype.load_connector=dhtmlXGridObject.prototype.load; 1857 dhtmlXGridObject.prototype.load=function(url, call, type){ 1858 if (!this._colls_loaded && this.cellType){ 1859 var ar=[]; 1860 for (var i=0; i < this.cellType.length; i++) 1861 if (this.cellType[i].indexOf("co")==0 || this._con_f_used[i]==2) ar.push(i); 1862 if (ar.length) 1863 arguments[0]+=(arguments[0].indexOf("?")!=-1?"&":"?")+"connector=true&dhx_colls="+ar.join(","); 1864 } 1865 return this.load_connector.apply(this,arguments); 1866 }; 1867 dhtmlXGridObject.prototype._parseHead_connector=dhtmlXGridObject.prototype._parseHead; 1868 dhtmlXGridObject.prototype._parseHead=function(url, call, type){ 1869 this._parseHead_connector.apply(this,arguments); 1870 if (!this._colls_loaded){ 1871 var cols = this.xmlLoader.doXPath("./coll_options", arguments[0]); 1872 for (var i=0; i < cols.length; i++){ 1873 var f = cols[i].getAttribute("for"); 1874 var v = []; 1875 var combo=null; 1876 if (this.cellType[f] == "combo") 1877 combo = this.getColumnCombo(f); 1878 if (this.cellType[f].indexOf("co")==0) 1879 combo=this.getCombo(f); 1880 1881 var os = this.xmlLoader.doXPath("./item",cols[i]); 1882 for (var j=0; j<os.length; j++){ 1883 var val=os[j].getAttribute("value"); 1884 1885 if (combo){ 1886 var lab=os[j].getAttribute("label")||val; 1887 1888 if (combo.addOption) 1889 combo.addOption([[val, lab]]); 1890 else 1891 combo.put(val,lab); 1892 1893 v[v.length]=lab; 1894 } else 1895 v[v.length]=val; 1896 } 1897 if (this._con_f_used[f*1]) 1898 this._con_f_used[f*1]=v; 1899 } 1900 this._colls_loaded=true; 1901 } 1902 }; 1903} 1904 1905if (window.dataProcessor){ 1906 dataProcessor.prototype.init_original=dataProcessor.prototype.init; 1907 dataProcessor.prototype.init=function(obj){ 1908 this.init_original(obj); 1909 obj._dataprocessor=this; 1910 1911 this.setTransactionMode("POST",true); 1912 this.serverProcessor+=(this.serverProcessor.indexOf("?")!=-1?"&":"?")+"editing=true"; 1913 }; 1914} 1915dhtmlxError.catchError("LoadXML",function(a,b,c){ 1916 if (c[0].status != 0) { 1917 alert(c[0].responseText); 1918 } 1919}); 1920 1921window.dhtmlXScheduler = window.scheduler = { version: "3.7.0" }; 1922dhtmlxEventable(scheduler); 1923 1924scheduler.init=function(id,date,mode){ 1925 date=date||(scheduler._currentDate()); 1926 mode=mode||"week"; 1927
1928 scheduler.date.init(); 1929 1930 this._obj=(typeof id == "string")?document.getElementById(id):id; 1931 this._els=[]; 1932 this._scroll=true; 1933 this._quirks=(_isIE && document.compatMode == "BackCompat"); 1934 this._quirks7=(_isIE && navigator.appVersion.indexOf("MSIE 8")==-1); 1935 1936 this.get_elements(); 1937 this.init_templates(); 1938 this.set_actions(); 1939 dhtmlxEvent(window,"resize",function(){ 1940 window.clearTimeout(scheduler._resize_timer); 1941 scheduler._resize_timer=window.setTimeout(function(){ 1942 if (scheduler.callEvent("onSchedulerResize",[])) { 1943 scheduler.update_view(); 1944 scheduler.callEvent("onAfterSchedulerResize", []); 1945 } 1946 }, 100); 1947 }); 1948 1949 this._init_touch_events(); 1950 this.set_sizes(); 1951 scheduler.callEvent('onSchedulerReady', []); 1952 this.setCurrentView(date,mode); 1953}; 1954 1955scheduler.xy={ 1956 nav_height:22, 1957 min_event_height:40, 1958 scale_width:50, 1959 bar_height:20, 1960 scroll_width:18, 1961 scale_height:20, 1962 month_scale_height:20, 1963 menu_width:25, 1964 margin_top:0, 1965 margin_left:0, 1966 editor_width:140, 1967 lightbox_additional_height:50 1968}; 1969scheduler.keys={ 1970 edit_save:13, 1971 edit_cancel:27 1972}; 1973scheduler.set_sizes=function(){ 1974 var w = this._x = this._obj.clientWidth-this.xy.margin_left; 1975 var h = this._y = this._obj.clientHeight-this.xy.margin_top; 1976 1977 //not-table mode always has scroll - need to be fixed in future 1978 var scale_x=this._table_view?0:(this.xy.scale_width+this.xy.scroll_width); 1979 var scale_s=this._table_view?-1:this.xy.scale_width; 1980 1981 this.set_xy(this._els["dhx_cal_navline"][0],w,this.xy.nav_height,0,0); 1982 this.set_xy(this._els["dhx_cal_header"][0],w-scale_x,this.xy.scale_height,scale_s,this.xy.nav_height+(this._quirks?-1:1)); 1983 //to support alter-skin, we need a way to alter height directly from css 1984 var actual_height = this._els["dhx_cal_navline"][0].offsetHeight; 1985 if (actual_height > 0) this.xy.nav_height = actual_height; 1986 1987 var data_y=this.xy.scale_height+this.xy.nav_height+(this._quirks?-2:0); 1988 this.set_xy(this._els["dhx_cal_data"][0],w,h-(data_y+2),0,data_y+2); 1989}; 1990scheduler.set_xy=function(node,w,h,x,y){ 1991 node.style.width=Math.max(0,w)+"px"; 1992 node.style.height=Math.max(0,h)+"px"; 1993 if (arguments.length>3){ 1994 node.style.left=x+"px"; 1995 node.style.top=y+"px"; 1996 } 1997}; 1998scheduler.get_elements=function(){ 1999 //get all child elements as named hash 2000 var els=this._obj.getElementsByTagName("DIV"); 2001 for (var i=0; i < els.length; i++){ 2002 var name=els[i].className; 2003 if (name) name = name.split(" ")[0]; 2004 if (!this._els[name]) this._els[name]=[]; 2005 this._els[name].push(els[i]); 2006 2007 //check if name need to be changed 2008 var t=scheduler.locale.labels[els[i].getAttribute("name")||name]; 2009 if (t) els[i].innerHTML=t; 2010 } 2011}; 2012scheduler.set_actions=function(){ 2013 for (var a in this._els) 2014 if (this._click[a]) 2015 for (var i=0; i < this._els[a].length; i++) 2016 this._els[a][i].onclick=scheduler._click[a]; 2017 this._obj.onselectstart=function(e){ return false; }; 2018 this._obj.onmousemove=function(e){ 2019 if (!scheduler._temp_touch_block) 2020 scheduler._on_mouse_move(e||event); 2021 }; 2022 this._obj.onmousedown=function(e){ 2023 if (!scheduler._ignore_next_click) 2024 scheduler._on_mouse_down(e||event); 2025 }; 2026 this._obj.onmouseup=function(e){ 2027 if (!scheduler._ignore_next_click) 2028 scheduler._on_mouse_up(e||event); 2029 }; 2030 this._obj.ondblclick=function(e){ 2031 scheduler._on_dbl_click(e||event); 2032 }; 2033 this._obj.oncontextmenu = function(e) { 2034 var ev = e||event; 2035 var src = ev.target||ev.srcElement; 2036 var returnValue = scheduler.callEvent("onContextMenu", [scheduler._locate_event(src), ev]); 2037 return returnValue; 2038 }; 2039}; 2040scheduler.select=function(id){ 2041 if (this._select_id==id) return; 2042 this.editStop(false); 2043 this.unselect(); 2044 this._select_id = id; 2045 this.updateEvent(id); 2046}; 2047scheduler.unselect=function(id){ 2048 if (id && id!=this._select_id) return; 2049 var t=this._select_id; 2050 this._select_id = null; 2051 if (t) this.updateEvent(t); 2052}; 2053scheduler.getState=function(){ 2054 return { 2055 mode: this._mode, 2056 date: this._date, 2057 min_date: this._min_date, 2058 max_date: this._max_date, 2059 editor_id: this._edit_id, 2060 lightbox_id: this._lightbox_id, 2061 new_event: this._new_event, 2062 select_id: this._select_id, 2063 expanded: this.expanded, 2064 drag_id: this._drag_id, 2065 drag_mode: this._drag_mode 2066 }; 2067}; 2068scheduler._click={ 2069 dhx_cal_data:function(e){
2070 //in case of touch disable click processing 2071 if (scheduler._ignore_next_click){ 2072 if (e.preventDefault) 2073 e.preventDefault(); 2074 e.cancelBubble = true; 2075 return scheduler._ignore_next_click = false; 2076 } 2077 2078 var trg = e?e.target:event.srcElement; 2079 var id = scheduler._locate_event(trg); 2080 2081 e = e || event; 2082 2083 if (!id) { 2084 scheduler.callEvent("onEmptyClick",[scheduler.getActionData(e).date, e]); 2085 } else { 2086 if ( !scheduler.callEvent("onClick",[id,e]) || scheduler.config.readonly ) return; 2087 } 2088 2089 if (id && scheduler.config.select) { 2090 2091 scheduler.select(id); 2092 var mask = trg.className; 2093 if (mask.indexOf("_icon")!=-1) 2094 scheduler._click.buttons[mask.split(" ")[1].replace("icon_","")](id); 2095 } else 2096 scheduler._close_not_saved(); 2097 }, 2098 dhx_cal_prev_button:function(){ 2099 scheduler._click.dhx_cal_next_button(0,-1); 2100 }, 2101 dhx_cal_next_button:function(dummy,step){ 2102 scheduler.setCurrentView(scheduler.date.add( //next line changes scheduler._date , but seems it has not side-effects 2103 scheduler.date[scheduler._mode+"_start"](scheduler._date),(step||1),scheduler._mode)); 2104 }, 2105 dhx_cal_today_button:function(){ 2106 if (scheduler.callEvent("onBeforeTodayDisplayed", [])) { 2107 scheduler.setCurrentView(scheduler._currentDate()); 2108 } 2109 }, 2110 dhx_cal_tab:function(){ 2111 var name = this.getAttribute("name"); 2112 var mode = name.substring(0, name.search("_tab")); 2113 scheduler.setCurrentView(scheduler._date,mode); 2114 }, 2115 buttons:{ 2116 "delete":function(id){ 2117 var c = scheduler.locale.labels.confirm_deleting; 2118 scheduler._dhtmlx_confirm(c, scheduler.locale.labels.title_confirm_deleting, function(){ scheduler.deleteEvent(id) }); 2119 }, 2120 edit:function(id){ scheduler.edit(id); }, 2121 save:function(id){ scheduler.editStop(true); }, 2122 details:function(id){ scheduler.showLightbox(id); }, 2123 cancel:function(id){ scheduler.editStop(false); } 2124 } 2125}; 2126scheduler._dhtmlx_confirm = function(message, title, callback) { 2127 if (!message) 2128 return callback(); 2129 var opts = { text: message }; 2130 if (title) 2131 opts.title = title; 2132 if (callback) { 2133 opts.callback = function(result) { 2134 if (result) 2135 callback(); 2136 }; 2137 } 2138 dhtmlx.confirm(opts); 2139}; 2140scheduler.addEventNow=function(start,end,e){ 2141 var base = {}; 2142 if (start && start.constructor.toString().match(/object/i) !== null){ 2143 base = start; 2144 start = null; 2145 } 2146 2147 var d = (this.config.event_duration||this.config.time_step)*60000; 2148 if (!start) start = base.start_date||Math.round((scheduler._currentDate()).valueOf()/d)*d; 2149 var start_date = new Date(start); 2150 if (!end){ 2151 var start_hour = this.config.first_hour; 2152 if (start_hour > start_date.getHours()){ 2153 start_date.setHours(start_hour); 2154 start = start_date.valueOf(); 2155 } 2156 end = start.valueOf()+d; 2157 } 2158 var end_date = new Date(end); 2159 2160 // scheduler.addEventNow(new Date(), new Date()) + collision though get_visible events defect (such event was not retrieved) 2161 if(start_date.valueOf() == end_date.valueOf()) 2162 end_date.setTime(end_date.valueOf()+d); 2163 2164 base.start_date = base.start_date||start_date; 2165 base.end_date = base.end_date||end_date; 2166 base.text = base.text||this.locale.labels.new_event; 2167 base.id = this._drag_id = this.uid(); 2168 this._drag_mode="new-size"; 2169 2170 this._loading=true; 2171 this.addEvent(base); 2172 this.callEvent("onEventCreated",[this._drag_id,e]); 2173 this._loading=false; 2174 2175 this._drag_event={}; //dummy , to trigger correct event updating logic 2176 this._on_mouse_up(e); 2177}; 2178scheduler._on_dbl_click=function(e,src){ 2179 src = src||(e.target||e.srcElement); 2180 if (this.config.readonly) return; 2181 var name = src.className.split(" ")[0]; 2182 switch(name){ 2183 case "dhx_scale_holder": 2184 case "dhx_scale_holder_now": 2185 case "dhx_month_body": 2186 case "dhx_wa_day_data": 2187 case "dhx_marked_timespan": 2188 if (!scheduler.config.dblclick_create) break; 2189 this.addEventNow(this.getActionData(e).date,null,e); 2190 break; 2191 case "dhx_cal_event": 2192 case "dhx_wa_ev_body": 2193 case "dhx_agenda_line": 2194 case "dhx_grid_event": 2195 case "dhx_cal_event_line": 2196 case "dhx_cal_event_clear": 2197 var id = this._locate_event(src);
2198 if (!this.callEvent("onDblClick",[id,e])) return; 2199 if (this.config.details_on_dblclick || this._table_view || !this.getEvent(id)._timed || !this.config.select) 2200 this.showLightbox(id); 2201 else 2202 this.edit(id); 2203 break; 2204 case "dhx_time_block": 2205 case "dhx_cal_container": 2206 return; 2207 break; 2208 default: 2209 var t = this["dblclick_"+name]; 2210 if (t) { 2211 t.call(this,e); 2212 } 2213 else { 2214 if (src.parentNode && src != this) 2215 return scheduler._on_dbl_click(e,src.parentNode); 2216 } 2217 break; 2218 } 2219}; 2220 2221scheduler._mouse_coords=function(ev){ 2222 var pos; 2223 var b=document.body; 2224 var d = document.documentElement; 2225 if(ev.pageX || ev.pageY) 2226 pos={x:ev.pageX, y:ev.pageY}; 2227 else pos={ 2228 x:ev.clientX + (b.scrollLeft||d.scrollLeft||0) - b.clientLeft, 2229 y:ev.clientY + (b.scrollTop||d.scrollTop||0) - b.clientTop 2230 }; 2231 2232 //apply layout 2233 pos.x-=getAbsoluteLeft(this._obj)+(this._table_view?0:this.xy.scale_width); 2234 pos.y-=getAbsoluteTop(this._obj)+this.xy.nav_height+(this._dy_shift||0)+this.xy.scale_height-this._els["dhx_cal_data"][0].scrollTop; 2235 pos.ev = ev; 2236 2237 var handler = this["mouse_"+this._mode]; 2238 if (handler) 2239 return handler.call(this,pos); 2240 2241 //transform to date 2242 if (!this._table_view) { 2243 pos.x=Math.min(this._cols.length-1, Math.max(0,Math.ceil(pos.x/this._cols[0])-1)); 2244 pos.y=Math.max(0,Math.ceil(pos.y*60/(this.config.time_step*this.config.hour_size_px))-1)+this.config.first_hour*(60/this.config.time_step); 2245 } else { 2246 if (!this._cols || !this._colsS) // agenda/map views 2247 return pos; 2248 var dy=0; 2249 for (dy=1; dy < this._colsS.heights.length; dy++) 2250 if (this._colsS.heights[dy]>pos.y) break; 2251 2252 pos.y=Math.ceil( (Math.max(0, pos.x/this._cols[0])+Math.max(0,dy-1)*7)*24*60/this.config.time_step ); 2253 2254 if (scheduler._drag_mode || this._mode == "month") 2255 pos.y=(Math.max(0,Math.ceil(pos.x/this._cols[0])-1)+Math.max(0,dy-1)*7)*24*60/this.config.time_step; 2256 2257 pos.x=0; 2258 } 2259 2260 return pos; 2261}; 2262scheduler._close_not_saved=function(){ 2263 if (new Date().valueOf()-(scheduler._new_event||0) > 500 && scheduler._edit_id){ 2264 var c=scheduler.locale.labels.confirm_closing; 2265 2266 scheduler._dhtmlx_confirm(c, scheduler.locale.labels.title_confirm_closing, function() { scheduler.editStop(scheduler.config.positive_closing); }); 2267 } 2268}; 2269scheduler._correct_shift=function(start, back){ 2270 return start-=((new Date(scheduler._min_date)).getTimezoneOffset()-(new Date(start)).getTimezoneOffset())*60000*(back?-1:1); 2271}; 2272scheduler._on_mouse_move=function(e){ 2273 if (this._drag_mode){ 2274 var pos=this._mouse_coords(e); 2275 if (!this._drag_pos || pos.force_redraw || this._drag_pos.x!=pos.x || this._drag_pos.y!=pos.y ){ 2276 var start, end; 2277 if (this._edit_id!=this._drag_id) 2278 this._close_not_saved(); 2279 2280 this._drag_pos=pos; 2281 2282 if (this._drag_mode=="create"){ 2283 this._close_not_saved(); 2284 this._loading=true; //will be ignored by dataprocessor 2285 2286 start = this._get_date_from_pos(pos).valueOf(); 2287 2288 var res = this.callEvent("onBeforeEventCreated", [e]); 2289 if (!res) 2290 return; 2291 2292 if (!this._drag_start) { 2293 this._drag_start=start; 2294 return; 2295 } 2296 2297 end = start; 2298 if (end == this._drag_start) { 2299 } 2300 2301 var start_date = new Date(this._drag_start); 2302 var end_date = new Date(end); 2303 if ( (this._mode == "day" || this._mode == "week") 2304 && (start_date.getHours() == end_date.getHours() && start_date.getMinutes() == end_date.getMinutes()) ) { 2305 end_date = new Date(this._drag_start+1000); 2306 } 2307 2308 2309 this._drag_id=this.uid(); 2310 this.addEvent(start_date, end_date, this.locale.labels.new_event, this._drag_id, pos.fields); 2311 2312 this.callEvent("onEventCreated",[this._drag_id,e]); 2313 this._loading=false; 2314 this._drag_mode="new-size"; 2315 2316 } 2317 2318 var ev=this.getEvent(this._drag_id); 2319 2320 if (this._drag_mode=="move"){ 2321 start = this._min_date.valueOf()+(pos.y*this.config.time_step+pos.x*24*60 -(scheduler._move_pos_shift||0) )*60000; 2322 if (!pos.custom && this._table_view) start+=this.date.time_part(ev.start_date)*1000; 2323 start = this._correct_shift(start); 2324 end = ev.end_date.valueOf()-(ev.start_date.valueOf()-start); 2325 } else { // resize 2326 start = ev.start_date.valueOf(); 2327 end = ev.end_date.valueOf(); 2328 if (this._table_view) { 2329 var resize_date = this._min_date.valueOf()+pos.y*this.config.time_step*60000 + (pos.custom?0:24*60*60000); 2330 if (this._mode == "month") 2331 resize_date = this._correct_shift(resize_date, false); 2332 2333 if (pos.resize_from_start) 2334 start = resize_date; 2335 else 2336 end = resize_date; 2337 } else { 2338 end = this.date.date_part(new Date(ev.end_date)).valueOf()+pos.y*this.config.time_step*60000; 2339 this._els["dhx_cal_data"][0].style.cursor="s-resize"; 2340 if (this._mode == "week" || this._mode == "day") 2341 end = this._correct_shift(end); 2342 } 2343 if (this._drag_mode == "new-size") { 2344 if (end <= this._drag_start){ 2345 var shift = pos.shift||((this._table_view && !pos.custom)?24*60*60000:0); 2346 start = end-(pos.shift?0:shift); 2347 end = this._drag_start+(shift||(this.config.time_step*60000)); 2348 } else { 2349 start = this._drag_start; 2350 } 2351 } else { 2352 if (end<=start) 2353 end=start+this.config.time_step*60000; 2354 } 2355 } 2356 var new_end = new Date(end-1); 2357 var new_start = new Date(start); 2358 //prevent out-of-borders situation for day|week view 2359 if ( this._table_view || (new_end.getDate()==new_start.getDate() && new_end.getHours()<this.config.last_hour) || scheduler._allow_dnd ){ 2360 ev.start_date=new_start; 2361 ev.end_date=new Date(end); 2362 if (this.config.update_render){ 2363 //fix for repaint after dnd and scroll issue, #231 2364 var sx = scheduler._els["dhx_cal_data"][0].scrollTop; 2365 this.update_view(); 2366 scheduler._els["dhx_cal_data"][0].scrollTop = sx; 2367 } else 2368 this.updateEvent(this._drag_id); 2369 } 2370 if (this._table_view) { 2371 this.for_rendered(this._drag_id,function(r){ 2372 r.className+=" dhx_in_move"; 2373 }); 2374 } 2375 } 2376 } else { 2377 if (scheduler.checkEvent("onMouseMove")){ 2378 var id = this._locate_event(e.target||e.srcElement); 2379 this.callEvent("onMouseMove",[id,e]); 2380 } 2381 } 2382}; 2383scheduler._on_mouse_down=function(e,src) { 2384 // on Mac we do not get onmouseup event when clicking right mouse button leaving us in dnd state 2385 // let's ignore right mouse button then 2386 if (e.button == 2) 2387 return; 2388 2389 if (this.config.readonly || this._drag_mode) return; 2390 src = src||(e.target||e.srcElement); 2391 var classname = src.className && src.className.split(" ")[0]; 2392 2393 switch (classname) { 2394 case "dhx_cal_event_line": 2395 case "dhx_cal_event_clear": 2396 if (this._table_view) 2397 this._drag_mode="move"; //item in table mode 2398 break; 2399 case "dhx_event_move": 2400 case "dhx_wa_ev_body": 2401 this._drag_mode="move"; 2402 break; 2403 case "dhx_event_resize": 2404 this._drag_mode="resize"; 2405 break; 2406 case "dhx_scale_holder": 2407 case "dhx_scale_holder_now": 2408 case "dhx_month_body": 2409 case "dhx_matrix_cell": 2410 case "dhx_marked_timespan": 2411 this._drag_mode="create"; 2412 this.unselect(this._select_id); 2413 break; 2414 case "": 2415 if (src.parentNode) 2416 return scheduler._on_mouse_down(e,src.parentNode); 2417 default: 2418 if (scheduler.checkEvent("onMouseDown") && scheduler.callEvent("onMouseDown", [classname])) { 2419 if (src.parentNode && src != this) { 2420 return scheduler._on_mouse_down(e,src.parentNode); 2421 } 2422 } 2423 this._drag_mode=null; 2424 this._drag_id=null; 2425 break; 2426 } 2427 if (this._drag_mode){ 2428 var id = this._locate_event(src); 2429 if (!this.config["drag_"+this._drag_mode] || !this.callEvent("onBeforeDrag",[id, this._drag_mode, e])) 2430 this._drag_mode=this._drag_id=0; 2431 else { 2432 this._drag_id= id; 2433 this._drag_event = scheduler._lame_clone(this.getEvent(this._drag_id) || {}); 2434 } 2435 } 2436 this._drag_start=null; 2437}; 2438scheduler._on_mouse_up=function(e){
2439 if (this._drag_mode && this._drag_id){ 2440 this._els["dhx_cal_data"][0].style.cursor="default"; 2441 //drop 2442 var ev=this.getEvent(this._drag_id); 2443 if (this._drag_event._dhx_changed || !this._drag_event.start_date || ev.start_date.valueOf()!=this._drag_event.start_date.valueOf() || ev.end_date.valueOf()!=this._drag_event.end_date.valueOf()){ 2444 var is_new=(this._drag_mode=="new-size"); 2445 if (!this.callEvent("onBeforeEventChanged",[ev,e,is_new,this._drag_event])){ 2446 if (is_new) 2447 this.deleteEvent(ev.id, true); 2448 else { 2449 this._drag_event._dhx_changed = false; 2450 scheduler._lame_copy(ev, this._drag_event); 2451 this.updateEvent(ev.id); 2452 } 2453 } else { 2454 var drag_id = this._drag_id; 2455 this._drag_id = this._drag_mode = null; 2456 if (is_new && this.config.edit_on_create){ 2457 this.unselect(); 2458 this._new_event=new Date();//timestamp of creation 2459 //if selection disabled - force lightbox usage 2460 if (this._table_view || this.config.details_on_create || !this.config.select) { 2461 return this.showLightbox(drag_id); 2462 } 2463 this._drag_pos = true; //set flag to trigger full redraw 2464 this._select_id = this._edit_id = drag_id; 2465 } else { 2466 if (!this._new_event) 2467 this.callEvent(is_new?"onEventAdded":"onEventChanged",[drag_id,this.getEvent(drag_id)]); 2468 } 2469 } 2470 } 2471 if (this._drag_pos) this.render_view_data(); //redraw even if there is no real changes - necessary for correct positioning item after drag 2472 } 2473 this._drag_id = null; 2474 this._drag_mode=null; 2475 this._drag_pos=null; 2476}; 2477scheduler.update_view=function(){ 2478 this._reset_scale(); 2479 if (this._load_mode && this._load()) return this._render_wait = true; 2480 this.render_view_data(); 2481}; 2482scheduler.updateView = function(date, mode) { 2483 date = date || this._date; 2484 mode = mode || this._mode; 2485 var dhx_cal_data = 'dhx_cal_data'; 2486 2487 if (!this._mode) 2488 this._obj.className += " dhx_scheduler_" + mode; else { 2489 this._obj.className = this._obj.className.replace("dhx_scheduler_" + this._mode, "dhx_scheduler_" + mode); 2490 } 2491 2492 var prev_scroll = (this._mode == mode && this.config.preserve_scroll) ? this._els[dhx_cal_data][0].scrollTop : false; // saving current scroll 2493 2494 //hide old custom view 2495 if (this[this._mode + "_view"] && mode && this._mode != mode) 2496 this[this._mode + "_view"](false); 2497 2498 this._close_not_saved(); 2499 2500 var dhx_multi_day = 'dhx_multi_day'; 2501 if (this._els[dhx_multi_day]) { 2502 this._els[dhx_multi_day][0].parentNode.removeChild(this._els[dhx_multi_day][0]); 2503 this._els[dhx_multi_day] = null; 2504 } 2505 2506 this._mode = mode; 2507 this._date = date; 2508 this._table_view = (this._mode == "month"); 2509 2510 var tabs = this._els["dhx_cal_tab"]; 2511 if(tabs){//calendar can work without view tabs 2512 for (var i = 0; i < tabs.length; i++) { 2513 var name = tabs[i].className; 2514 name = name.replace(/ active/g, ""); 2515 if (tabs[i].getAttribute("name") == this._mode + "_tab") 2516 name = name + " active"; 2517 tabs[i].className = name; 2518 } 2519 } 2520 //show new view 2521 var view = this[this._mode + "_view"]; 2522 view ? view(true) : this.update_view(); 2523 2524 if (typeof prev_scroll == "number") // if we are updating or working with the same view scrollTop should be saved 2525 this._els[dhx_cal_data][0].scrollTop = prev_scroll; // restoring original scroll 2526}; 2527scheduler.setCurrentView = function(date, mode) { 2528 if (!this.callEvent("onBeforeViewChange", [this._mode, this._date, mode, date])) return; 2529 this.updateView(date, mode); 2530 this.callEvent("onViewChange", [this._mode, this._date]); 2531}; 2532scheduler._render_x_header = function(i,left,d,h){ 2533 //header scale 2534 var head=document.createElement("DIV"); 2535 head.className = "dhx_scale_bar"; 2536 var width = this._cols[i]-1; 2537 2538 if (this._mode == "month" && i === 0 && this.config.left_border) { 2539 head.className += " dhx_scale_bar_border"; 2540 left = left+1; 2541 } 2542 this.set_xy(head, width, this.xy.scale_height-2, left, 0);//-1 for border 2543 head.innerHTML=this.templates[this._mode+"_scale_date"](d,this._mode); //TODO - move in separate method 2544 h.appendChild(head); 2545}; 2546scheduler._reset_scale=function(){ 2547 //current mode doesn't support scales 2548 //we mustn't call reset_scale for such modes, so it just to be sure 2549 if (!this.templates[this._mode + "_date"]) return; 2550 2551 var h = this._els["dhx_cal_header"][0]; 2552 var b = this._els["dhx_cal_data"][0]; 2553 var c = this.config; 2554 2555 h.innerHTML = ""; 2556 b.scrollTop = 0; //fix flickering in FF 2557 b.innerHTML = ""; 2558 2559 var str = ((c.readonly || (!c.drag_resize)) ? " dhx_resize_denied" : "") + ((c.readonly || (!c.drag_move)) ? " dhx_move_denied" : ""); 2560 if (str) b.className = "dhx_cal_data" + str; 2561 2562 this._scales = {}; 2563 this._cols = []; //store for data section 2564 this._colsS = {height: 0}; 2565 this._dy_shift = 0; 2566 2567 this.set_sizes(); 2568 var summ=parseInt(h.style.width,10); //border delta 2569 var left=0; 2570 2571 var d,dd,sd,today; 2572 dd=this.date[this._mode+"_start"](new Date(this._date.valueOf())); 2573 d=sd=this._table_view?scheduler.date.week_start(dd):dd; 2574 today=this.date.date_part( scheduler._currentDate()); 2575 2576 //reset date in header 2577 var ed=scheduler.date.add(dd,1,this._mode); 2578 var count = 7; 2579 2580 if (!this._table_view){ 2581 var count_n = this.date["get_"+this._mode+"_end"]; 2582 if (count_n) ed = count_n(dd); 2583 count = Math.round((ed.valueOf()-dd.valueOf())/(1000*60*60*24)); 2584 } 2585 2586 this._min_date=d; 2587 this._els["dhx_cal_date"][0].innerHTML=this.templates[this._mode+"_date"](dd,ed,this._mode); 2588 2589 for (var i=0; i<count; i++){ 2590 this._cols[i]=Math.floor(summ/(count-i)); 2591 2592 this._render_x_header(i,left,d,h); 2593 if (!this._table_view){ 2594 var scales=document.createElement("DIV"); 2595 var cls = "dhx_scale_holder"; 2596 if (d.valueOf()==today.valueOf()) cls = "dhx_scale_holder_now"; 2597 scales.className=cls+" "+this.templates.week_date_class(d,today); 2598 this.set_xy(scales,this._cols[i]-1,c.hour_size_px*(c.last_hour-c.first_hour),left+this.xy.scale_width+1,0);//-1 for border 2599 b.appendChild(scales); 2600 this.callEvent("onScaleAdd",[scales, d]); 2601 } 2602 2603 d=this.date.add(d,1,"day"); 2604 summ-=this._cols[i];
2605 left+=this._cols[i]; 2606 this._colsS[i]=(this._cols[i-1]||0)+(this._colsS[i-1]||(this._table_view?0:this.xy.scale_width+2)); 2607 this._colsS['col_length'] = count+1; 2608 } 2609 this._max_date=d; 2610 this._colsS[count]=this._cols[count-1]+this._colsS[count-1]; 2611 2612 if (this._table_view) // month view 2613 this._reset_month_scale(b,dd,sd); 2614 else{ 2615 this._reset_hours_scale(b,dd,sd); 2616 if (c.multi_day) { 2617 var dhx_multi_day = 'dhx_multi_day'; 2618 2619 if(this._els[dhx_multi_day]) { 2620 this._els[dhx_multi_day][0].parentNode.removeChild(this._els[dhx_multi_day][0]); 2621 this._els[dhx_multi_day] = null; 2622 } 2623 2624 var navline = this._els["dhx_cal_navline"][0]; 2625 var top = navline.offsetHeight + this._els["dhx_cal_header"][0].offsetHeight+1; 2626 2627 var c1 = document.createElement("DIV"); 2628 c1.className = dhx_multi_day; 2629 c1.style.visibility="hidden"; 2630 this.set_xy(c1, this._colsS[this._colsS.col_length-1]+this.xy.scroll_width, 0, 0, top); // 2 extra borders, dhx_header has -1 bottom margin 2631 b.parentNode.insertBefore(c1,b); 2632 2633 var c2 = c1.cloneNode(true); 2634 c2.className = dhx_multi_day+"_icon"; 2635 c2.style.visibility="hidden"; 2636 this.set_xy(c2, this.xy.scale_width, 0, 0, top); // dhx_header has -1 bottom margin 2637 2638 c1.appendChild(c2); 2639 this._els[dhx_multi_day]=[c1,c2]; 2640 this._els[dhx_multi_day][0].onclick = this._click.dhx_cal_data; 2641 } 2642 } 2643}; 2644scheduler._reset_hours_scale=function(b,dd,sd){ 2645 var c=document.createElement("DIV"); 2646 c.className="dhx_scale_holder"; 2647 2648 var date = new Date(1980,1,1,this.config.first_hour,0,0); 2649 for (var i=this.config.first_hour*1; i < this.config.last_hour; i++) { 2650 var cc=document.createElement("DIV"); 2651 cc.className="dhx_scale_hour"; 2652 cc.style.height=this.config.hour_size_px-(this._quirks?0:1)+"px"; 2653 var width = this.xy.scale_width; 2654 if (this.config.left_border) { 2655 width = width - 1; 2656 cc.className += " dhx_scale_hour_border"; 2657 } 2658 cc.style.width = width + "px"; 2659 cc.innerHTML=scheduler.templates.hour_scale(date); 2660 2661 c.appendChild(cc); 2662 date=this.date.add(date,1,"hour"); 2663 } 2664 b.appendChild(c); 2665 if (this.config.scroll_hour) 2666 b.scrollTop = this.config.hour_size_px*(this.config.scroll_hour-this.config.first_hour); 2667}; 2668 2669scheduler._currentDate = function(){ 2670 if(scheduler.config.now_date){ 2671 return new Date(scheduler.config.now_date); 2672 } 2673 return new Date(); 2674}; 2675 2676scheduler._reset_month_scale=function(b,dd,sd){ 2677 var ed=scheduler.date.add(dd,1,"month"); 2678 2679 //trim time part for comparation reasons 2680 var cd = scheduler._currentDate(); 2681 this.date.date_part(cd); 2682 this.date.date_part(sd); 2683 2684 var rows=Math.ceil(Math.round((ed.valueOf()-sd.valueOf()) / (60*60*24*1000) ) / 7); 2685 var tdcss=[]; 2686 var height=(Math.floor(b.clientHeight/rows)-22); 2687 2688 this._colsS.height=height+22; 2689 var h = this._colsS.heights = []; 2690 for (var i=0; i<=7; i++) { 2691 var cell_width = ((this._cols[i]||0)-1); 2692 if (i === 0 && this.config.left_border) { 2693 cell_width = cell_width - 1; 2694 } 2695 tdcss[i]=" style='height:"+height+"px; width:"+cell_width+"px;' "; 2696 } 2697 2698 2699 2700 var cellheight = 0; 2701 this._min_date=sd; 2702 var html="<table cellpadding='0' cellspacing='0'>"; 2703 var rendered_dates = []; 2704 for (var i=0; i<rows; i++){ 2705 html+="<tr>"; 2706 2707 for (var j=0; j<7; j++) { 2708 html+="<td"; 2709 var cls = ""; 2710 if (sd<dd) 2711 cls='dhx_before'; 2712 else if (sd>=ed) 2713 cls='dhx_after'; 2714 else if (sd.valueOf()==cd.valueOf()) 2715 cls='dhx_now'; 2716 html+=" class='"+cls+" "+this.templates.month_date_class(sd,cd)+"' >"; 2717 var body_class = "dhx_month_body"; 2718 var head_class = "dhx_month_head"; 2719 if (j === 0 && this.config.left_border) { 2720 body_class += " dhx_month_body_border"; 2721 head_class += " dhx_month_head_border"; 2722 } 2723 html+="<div class='"+head_class+"'>"+this.templates.month_day(sd)+"</div>"; 2724 html+="<div class='"+body_class+"' "+tdcss[j]+"></div></td>"; 2725 rendered_dates.push(sd); 2726 sd=this.date.add(sd,1,"day"); 2727 } 2728 html+="</tr>"; 2729 h[i] = cellheight; 2730 cellheight+=this._colsS.height; 2731 } 2732 html+="</table>"; 2733 this._max_date=sd; 2734 2735 b.innerHTML=html; 2736 2737 this._scales = {}; 2738 var divs = b.getElementsByTagName('div'); 2739 for (var i=0; i<rendered_dates.length; i++) { // [header, body, header, body, ...] 2740 var div = divs[(i*2)+1]; 2741 var date = rendered_dates[i]; 2742 this._scales[+date] = div; 2743 } 2744 for (var i=0; i<rendered_dates.length; i++) { 2745 var date = rendered_dates[i]; 2746 this.callEvent("onScaleAdd", [this._scales[+date], date]); 2747 } 2748 2749 return sd; 2750}; 2751scheduler.getLabel = function(property, key) { 2752 var sections = this.config.lightbox.sections; 2753 for (var i=0; i<sections.length; i++) { 2754 if(sections[i].map_to == property) { 2755 var options = sections[i].options; 2756 for (var j=0; j<options.length; j++) { 2757 if(options[j].key == key) { 2758 return options[j].label; 2759 } 2760 } 2761 } 2762 } 2763 return ""; 2764}; 2765scheduler.updateCollection = function(list_name, collection) { 2766 var list = scheduler.serverList(list_name); 2767 if (!list) return false; 2768 list.splice(0, list.length); 2769 list.push.apply(list, collection || []); 2770 scheduler.callEvent("onOptionsLoad", []); 2771 scheduler.resetLightbox(); 2772 return true; 2773}; 2774scheduler._lame_clone = function(object, cache) { 2775 var i, t, result; // iterator, types array, result 2776 2777 cache = cache || []; 2778 2779 for (i=0; i<cache.length; i+=2) 2780 if(object === cache[i]) 2781 return cache[i+1]; 2782 2783 if (object && typeof object == "object") { 2784 result = {}; 2785 t = [Array,Date,Number,String,Boolean]; 2786 for (i=0; i<t.length; i++) { 2787 if (object instanceof t[i]) 2788 result = i ? new t[i](object) : new t[i](); // first one is array 2789 } 2790 cache.push(object, result); 2791 for (i in object) { 2792 if (Object.prototype.hasOwnProperty.apply(object, [i])) 2793 result[i] = scheduler._lame_clone(object[i], cache) 2794 } 2795 } 2796 return result || object; 2797}; 2798scheduler._lame_copy = function(target, source) { 2799 for (var key in source) { 2800 if (source.hasOwnProperty(key)) { 2801 target[key] = source[key]; 2802 } 2803 } 2804 return target; 2805}; 2806scheduler._get_date_from_pos = function(pos) { 2807 var start=this._min_date.valueOf()+(pos.y*this.config.time_step+(this._table_view?0:pos.x)*24*60)*60000; 2808 return new Date(this._correct_shift(start)); 2809}; 2810// n_ev - native event 2811scheduler.getActionData = function(n_ev) { 2812 var pos = this._mouse_coords(n_ev); 2813 return { 2814 date:this._get_date_from_pos(pos), 2815 section:pos.section 2816 }; 2817}; 2818scheduler._focus = function(node, select){ 2819 if (node && node.focus){ 2820 if (this.config.touch){ 2821 window.setTimeout(function(){ 2822 node.focus(); 2823 },100); 2824 } else { 2825 if (select && node.select) node.select(); 2826 node.focus(); 2827 } 2828 } 2829} 2830scheduler.date={ 2831 init:function(){ 2832 var s = scheduler.locale.date.month_short;
2833 var t = scheduler.locale.date.month_short_hash = {}; 2834 for (var i = 0; i < s.length; i++) 2835 t[s[i]]=i; 2836 2837 var s = scheduler.locale.date.month_full; 2838 var t = scheduler.locale.date.month_full_hash = {}; 2839 for (var i = 0; i < s.length; i++) 2840 t[s[i]]=i; 2841 }, 2842 date_part:function(date){ 2843 date.setHours(0); 2844 date.setMinutes(0); 2845 date.setSeconds(0); 2846 date.setMilliseconds(0); 2847 if (date.getHours() != 0) 2848 date.setTime(date.getTime() + 60 * 60 * 1000 * (24 - date.getHours())); 2849 return date; 2850 }, 2851 time_part:function(date){ 2852 return (date.valueOf()/1000 - date.getTimezoneOffset()*60)%86400; 2853 }, 2854 week_start:function(date){ 2855 var shift=date.getDay(); 2856 if (scheduler.config.start_on_monday){ 2857 if (shift===0) shift=6; 2858 else shift--; 2859 } 2860 return this.date_part(this.add(date,-1*shift,"day")); 2861 }, 2862 month_start:function(date){ 2863 date.setDate(1); 2864 return this.date_part(date); 2865 }, 2866 year_start:function(date){ 2867 date.setMonth(0); 2868 return this.month_start(date); 2869 }, 2870 day_start:function(date){ 2871 return this.date_part(date); 2872 }, 2873 add:function(date,inc,mode){ 2874 var ndate=new Date(date.valueOf()); 2875 switch(mode){ 2876 case "week": 2877 inc *= 7; 2878 case "day": 2879 ndate.setDate(ndate.getDate() + inc); 2880 if (!date.getHours() && ndate.getHours()) //shift to yesterday 2881 ndate.setTime(ndate.getTime() + 60 * 60 * 1000 * (24 - ndate.getHours())); 2882 break; 2883 case "month": ndate.setMonth(ndate.getMonth()+inc); break; 2884 case "year": ndate.setYear(ndate.getFullYear()+inc); break; 2885 case "hour": ndate.setHours(ndate.getHours()+inc); break; 2886 case "minute": ndate.setMinutes(ndate.getMinutes()+inc); break; 2887 default: 2888 return scheduler.date["add_"+mode](date,inc,mode); 2889 } 2890 return ndate; 2891 }, 2892 to_fixed:function(num){ 2893 if (num<10) return "0"+num; 2894 return num; 2895 }, 2896 copy:function(date){ 2897 return new Date(date.valueOf()); 2898 }, 2899 date_to_str:function(format,utc){ 2900 format=format.replace(/%[a-zA-Z]/g,function(a){ 2901 switch(a){ 2902 case "%d": return "\"+scheduler.date.to_fixed(date.getDate())+\""; 2903 case "%m": return "\"+scheduler.date.to_fixed((date.getMonth()+1))+\""; 2904 case "%j": return "\"+date.getDate()+\""; 2905 case "%n": return "\"+(date.getMonth()+1)+\""; 2906 case "%y": return "\"+scheduler.date.to_fixed(date.getFullYear()%100)+\""; 2907 case "%Y": return "\"+date.getFullYear()+\""; 2908 case "%D": return "\"+scheduler.locale.date.day_short[date.getDay()]+\""; 2909 case "%l": return "\"+scheduler.locale.date.day_full[date.getDay()]+\""; 2910 case "%M": return "\"+scheduler.locale.date.month_short[date.getMonth()]+\""; 2911 case "%F": return "\"+scheduler.locale.date.month_full[date.getMonth()]+\""; 2912 case "%h": return "\"+scheduler.date.to_fixed((date.getHours()+11)%12+1)+\""; 2913 case "%g": return "\"+((date.getHours()+11)%12+1)+\""; 2914 case "%G": return "\"+date.getHours()+\""; 2915 case "%H": return "\"+scheduler.date.to_fixed(date.getHours())+\""; 2916 case "%i": return "\"+scheduler.date.to_fixed(date.getMinutes())+\""; 2917 case "%a": return "\"+(date.getHours()>11?\"pm\":\"am\")+\""; 2918 case "%A": return "\"+(date.getHours()>11?\"PM\":\"AM\")+\""; 2919 case "%s": return "\"+scheduler.date.to_fixed(date.getSeconds())+\""; 2920 case "%W": return "\"+scheduler.date.to_fixed(scheduler.date.getISOWeek(date))+\""; 2921 default: return a; 2922 } 2923 }); 2924 if (utc) format=format.replace(/date\.get/g,"date.getUTC"); 2925 return new Function("date","return \""+format+"\";"); 2926 }, 2927 str_to_date:function(format,utc){ 2928 var splt="var temp=date.match(/[a-zA-Z]+|[0-9]+/g);"; 2929 var mask=format.match(/%[a-zA-Z]/g); 2930 for (var i=0; i<mask.length; i++){ 2931 switch(mask[i]){ 2932 case "%j": 2933 case "%d": splt+="set[2]=temp["+i+"]||1;"; 2934 break; 2935 case "%n": 2936 case "%m": splt+="set[1]=(temp["+i+"]||1)-1;"; 2937 break; 2938 case "%y": splt+="set[0]=temp["+i+"]*1+(temp["+i+"]>50?1900:2000);"; 2939 break; 2940 case "%g": 2941 case "%G": 2942 case "%h": 2943 case "%H": 2944 splt+="set[3]=temp["+i+"]||0;"; 2945 break; 2946 case "%i":
2947 splt+="set[4]=temp["+i+"]||0;"; 2948 break; 2949 case "%Y": splt+="set[0]=temp["+i+"]||0;"; 2950 break; 2951 case "%a": 2952 case "%A": splt+="set[3]=set[3]%12+((temp["+i+"]||'').toLowerCase()=='am'?0:12);"; 2953 break; 2954 case "%s": splt+="set[5]=temp["+i+"]||0;"; 2955 break; 2956 case "%M": splt+="set[1]=scheduler.locale.date.month_short_hash[temp["+i+"]]||0;"; 2957 break; 2958 case "%F": splt+="set[1]=scheduler.locale.date.month_full_hash[temp["+i+"]]||0;"; 2959 break; 2960 default: 2961 break; 2962 } 2963 } 2964 var code ="set[0],set[1],set[2],set[3],set[4],set[5]"; 2965 if (utc) code =" Date.UTC("+code+")"; 2966 return new Function("date","var set=[0,0,1,0,0,0]; "+splt+" return new Date("+code+");"); 2967 }, 2968 getISOWeek: function(ndate) { 2969 if(!ndate) return false; 2970 var nday = ndate.getDay(); 2971 if (nday === 0) { 2972 nday = 7; 2973 } 2974 var first_thursday = new Date(ndate.valueOf()); 2975 first_thursday.setDate(ndate.getDate() + (4 - nday)); 2976 var year_number = first_thursday.getFullYear(); // year of the first Thursday 2977 var ordinal_date = Math.round( (first_thursday.getTime() - new Date(year_number, 0, 1).getTime()) / 86400000); //ordinal date of the first Thursday - 1 (so not really ordinal date) 2978 var week_number = 1 + Math.floor( ordinal_date / 7); 2979 return week_number; 2980 }, 2981 getUTCISOWeek: function(ndate){ 2982 return this.getISOWeek(ndate); 2983 }, 2984 convert_to_utc: function(date) { 2985 return new Date(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds()); 2986 } 2987}; 2988scheduler.locale = { 2989 date:{ 2990 month_full:["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "
2990November", "December"], 2991 month_short:["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], 2992 day_full:["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], 2993 day_short:["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"] 2994 }, 2995 labels:{ 2996 dhx_cal_today_button:"Today", 2997 day_tab:"Day", 2998 week_tab:"Week", 2999 month_tab:"Month", 3000 new_event:"New event", 3001 icon_save:"Save", 3002 icon_cancel:"Cancel", 3003 icon_details:"Details", 3004 icon_edit:"Edit", 3005 icon_delete:"Delete", 3006 confirm_closing:"",//Your changes will be lost, are your sure ? 3007 confirm_deleting:"Event will be deleted permanently, are you sure?", 3008 section_description:"Description", 3009 section_time:"Time period", 3010 full_day:"Full day", 3011 3012 /*recurring events*/ 3013 confirm_recurring:"Do you want to edit the whole set of repeated events?", 3014 section_recurring:"Repeat event", 3015 button_recurring:"Disabled", 3016 button_recurring_open:"Enabled", 3017 button_edit_series: "Edit series", 3018 button_edit_occurrence: "Edit occurrence", 3019 3020 /*agenda view extension*/ 3021 agenda_tab:"Agenda", 3022 date:"Date", 3023 description:"Description", 3024 3025 /*year view extension*/ 3026 year_tab:"Year", 3027 3028 /* week agenda extension */ 3029 week_agenda_tab: "Agenda", 3030 3031 /*grid view extension*/ 3032 grid_tab: "Grid", 3033 drag_to_create:"Drag to create", 3034 drag_to_move:"Drag to move" 3035 } 3036}; 3037 3038 3039/* 3040%e Day of the month without leading zeros (01..31) 3041%d Day of the month, 2 digits with leading zeros (01..31) 3042%j Day of the year, 3 digits with leading zeros (001..366) 3043%a A textual representation of a day, two letters 3044%W A full textual representation of the day of the week 3045 3046%c Numeric representation of a month, without leading zeros (0..12) 3047%m Numeric representation of a month, with leading zeros (00..12) 3048%b A short textual representation of a month, three letters (Jan..Dec) 3049%M A full textual representation of a month, such as January or March (January..December) 3050 3051%y A two digit representation of a year (93..03) 3052%Y A full numeric representation of a year, 4 digits (1993..03) 3053*/ 3054 3055scheduler.config={ 3056 default_date: "%j %M %Y", 3057 month_date: "%F %Y", 3058 load_date: "%Y-%m-%d", 3059 week_date: "%l", 3060 day_date: "%D, %F %j", 3061 hour_date: "%H:%i", 3062 month_day: "%d", 3063 xml_date: "%m/%d/%Y %H:%i", 3064 api_date: "%d-%m-%Y %H:%i", 3065 3066 hour_size_px: 42, 3067 time_step: 5, 3068 3069 start_on_monday: 1, 3070 first_hour: 0, 3071 last_hour: 24, 3072 readonly: false, 3073 drag_resize: 1, 3074 drag_move: 1, 3075 drag_create: 1, 3076 dblclick_create: 1, 3077 edit_on_create: 1, 3078 details_on_create: 0, 3079 click_form_details: 0, 3080 3081 cascade_event_display: false, 3082 cascade_event_count: 4, 3083 cascade_event_margin: 30, 3084 3085 multi_day_height_limit: 0, 3086 3087 drag_lightbox: true, 3088 preserve_scroll: true, 3089 select: true, 3090 3091 server_utc: false, 3092 touch:true, 3093 touch_tip:true, 3094 touch_drag:500, 3095 quick_info_detached:true, 3096 3097 positive_closing: false, 3098 3099 icons_edit: ["icon_save", "icon_cancel"], 3100 icons_select: ["icon_details", "icon_edit", "icon_delete"], 3101 buttons_left: ["dhx_save_btn", "dhx_cancel_btn"], 3102 buttons_right: ["dhx_delete_btn"], 3103 lightbox: { 3104 sections: [ 3105 {name: "description", height: 200, map_to: "text", type: "textarea", focus: true}, 3106 {name: "time", height: 72, type: "time", map_to: "auto"} 3107 ] 3108 }, 3109 highlight_displayed_event: true, 3110 displayed_event_color: "#ffc5ab", 3111 displayed_event_text_color: "#7e2727", 3112 3113 left_border: false 3114}; 3115scheduler.templates={}; 3116scheduler.init_templates=function(){ 3117 var labels = scheduler.locale.labels; 3118 labels.dhx_save_btn = labels.icon_save; 3119 labels.dhx_cancel_btn = labels.icon_cancel; 3120 labels.dhx_delete_btn = labels.icon_delete; 3121 3122 3123 var d=scheduler.date.date_to_str; 3124 var c=scheduler.config; 3125 var f = function(a,b){ 3126 for (var c in b) 3127 if (!a[c]) a[c]=b[c]; 3128 }; 3129 f(scheduler.templates,{ 3130 day_date:d(c.default_date), 3131 month_date:d(c.month_date), 3132 week_date:function(d1,d2){ 3133 return scheduler.templates.day_date(d1)+" – "+scheduler.templates.day_date(scheduler.date.add(d2,-1,"day")); 3134 }, 3135 day_scale_date:d(c.default_date), 3136 month_scale_date:d(c.week_date), 3137 week_scale_date:d(c.day_date), 3138 hour_scale:d(c.hour_date), 3139 time_picker:d(c.hour_date), 3140 event_date:d(c.hour_date), 3141 month_day:d(c.month_day), 3142 xml_date:scheduler.date.str_to_date(c.xml_date,c.server_utc), 3143 load_format:d(c.load_date,c.server_utc), 3144 xml_format:d(c.xml_date,c.server_utc), 3145 api_date:scheduler.date.str_to_date(c.api_date), 3146 event_header:function(start,end,ev){ 3147 return scheduler.templates.event_date(start)+" - "+scheduler.templates.event_date(end); 3148 }, 3149 event_text:function(start,end,ev){ 3150 return ev.text; 3151 }, 3152 event_class:function(start,end,ev){ 3153 return ""; 3154 }, 3155 month_date_class:function(d){ 3156 return ""; 3157 }, 3158 week_date_class:function(d){ 3159 return ""; 3160 }, 3161 event_bar_date:function(start,end,ev){ 3162 return scheduler.templates.event_date(start)+" "; 3163 }, 3164 event_bar_text:function(start,end,ev){ 3165 return ev.text; 3166 } 3167 }); 3168 this.callEvent("onTemplatesReady",[]); 3169}; 3170 3171 3172 3173scheduler.uid = function() { 3174 if (!this._seed) this._seed = (new Date).valueOf(); 3175 return this._seed++; 3176}; 3177scheduler._events = {}; 3178scheduler.clearAll = function() { 3179 this._events = {}; 3180 this._loaded = {}; 3181 this.clear_view(); 3182 this.callEvent("onClearAll", []); 3183}; 3184scheduler.addEvent = function(start_date, end_date, text, id, extra_data) { 3185 if (!arguments.length) 3186 return this.addEventNow(); 3187 var ev = start_date; 3188 if (arguments.length != 1) { 3189 ev = extra_data || {}; 3190 ev.start_date = start_date; 3191 ev.end_date = end_date; 3192 ev.text = text; 3193 ev.id = id; 3194 } 3195 ev.id = ev.id || scheduler.uid(); 3196 ev.text = ev.text || ""; 3197 3198 if (typeof ev.start_date == "string") ev.start_date = this.templates.api_date(ev.start_date); 3199 if (typeof ev.end_date == "string") ev.end_date = this.templates.api_date(ev.end_date); 3200 3201 var d = (this.config.event_duration || this.config.time_step) * 60000; 3202 if (ev.start_date.valueOf() == ev.end_date.valueOf()) 3203 ev.end_date.setTime(ev.end_date.valueOf() + d);
3204 3205 ev._timed = this.is_one_day_event(ev); 3206 3207 var is_new = !this._events[ev.id]; 3208 this._events[ev.id] = ev; 3209 this.event_updated(ev); 3210 if (!this._loading) 3211 this.callEvent(is_new ? "onEventAdded" : "onEventChanged", [ev.id, ev]); 3212 return ev.id; 3213}; 3214scheduler.deleteEvent = function(id, silent) { 3215 var ev = this._events[id]; 3216 if (!silent && (!this.callEvent("onBeforeEventDelete", [id, ev]) || !this.callEvent("onConfirmedBeforeEventDelete", [id, ev]))) 3217 return; 3218 if (ev) { 3219 delete this._events[id]; 3220 this.unselect(id); 3221 this.event_updated(ev); 3222 } 3223 3224 this.callEvent("onEventDeleted", [id, ev]); 3225}; 3226scheduler.getEvent = function(id) { 3227 return this._events[id]; 3228}; 3229scheduler.setEvent = function(id, hash) { 3230 this._events[id] = hash; 3231}; 3232scheduler.for_rendered = function(id, method) { 3233 for (var i = this._rendered.length - 1; i >= 0; i--) 3234 if (this._rendered[i].getAttribute("event_id") == id) 3235 method(this._rendered[i], i); 3236}; 3237scheduler.changeEventId = function(id, new_id) { 3238 if (id == new_id) return; 3239 var ev = this._events[id]; 3240 if (ev) { 3241 ev.id = new_id; 3242 this._events[new_id] = ev; 3243 delete this._events[id]; 3244 } 3245 this.for_rendered(id, function(r) { 3246 r.setAttribute("event_id", new_id); 3247 }); 3248 if (this._select_id == id) this._select_id = new_id; 3249 if (this._edit_id == id) this._edit_id = new_id; 3250 //if (this._drag_id==id) this._drag_id=new_id; 3251 this.callEvent("onEventIdChange", [id, new_id]); 3252}; 3253 3254(function() { 3255 var attrs = ["text", "Text", "start_date", "StartDate", "end_date", "EndDate"]; 3256 var create_getter = function(name) { 3257 return function(id) { return (scheduler.getEvent(id))[name]; }; 3258 }; 3259 var create_setter = function(name) { 3260 return function(id, value) { 3261 var ev = scheduler.getEvent(id); 3262 ev[name] = value; 3263 ev._changed = true; 3264 ev._timed = this.is_one_day_event(ev); 3265 scheduler.event_updated(ev, true); 3266 }; 3267 }; 3268 for (var i = 0; i < attrs.length; i += 2) { 3269 scheduler["getEvent" + attrs[i + 1]] = create_getter(attrs[i]); 3270 scheduler["setEvent" + attrs[i + 1]] = create_setter(attrs[i]); 3271 } 3272})(); 3273 3274scheduler.event_updated = function(ev, force) { 3275 if (this.is_visible_events(ev)) 3276 this.render_view_data(); 3277 else 3278 this.clear_event(ev.id); 3279}; 3280scheduler.is_visible_events = function(ev) { 3281 return (ev.start_date < this._max_date && this._min_date < ev.end_date); 3282}; 3283scheduler.is_one_day_event = function(ev) { 3284 var delta = ev.end_date.getDate() - ev.start_date.getDate(); 3285 3286 if (!delta) 3287 return ev.start_date.getMonth() == ev.end_date.getMonth() && ev.start_date.getFullYear() == ev.end_date.getFullYear(); 3288 else { 3289 if (delta < 0) delta = Math.ceil((ev.end_date.valueOf() - ev.start_date.valueOf()) / (24 * 60 * 60 * 1000)); 3290 return (delta == 1 && !ev.end_date.getHours() && !ev.end_date.getMinutes() && (ev.start_date.getHours() || ev.start_date.getMinutes() )); 3291 } 3292 3293}; 3294scheduler.get_visible_events = function(only_timed) { 3295 //not the best strategy for sure 3296 var stack = []; 3297 3298 for (var id in this._events) 3299 if (this.is_visible_events(this._events[id])) 3300 if (!only_timed || this._events[id]._timed) 3301 if (this.filter_event(id, this._events[id])) 3302 stack.push(this._events[id]); 3303 3304 return stack; 3305}; 3306scheduler.filter_event = function(id, ev) { 3307 var filter = this["filter_" + this._mode]; 3308 return (filter) ? filter(id, ev) : true; 3309}; 3310scheduler.render_view_data = function(evs, hold) { 3311 if (!evs) { 3312 if (this._not_render) { 3313 this._render_wait = true; 3314 return; 3315 } 3316 this._render_wait = false; 3317 3318 this.clear_view(); 3319 evs = this.get_visible_events(!(this._table_view || this.config.multi_day)); 3320 } 3321 3322 if (this.config.multi_day && !this._table_view) { 3323 3324 var tvs = []; 3325 var tvd = []; 3326 for (var i = 0; i < evs.length; i++) { 3327 if (evs[i]._timed) 3328 tvs.push(evs[i]); 3329 else 3330 tvd.push(evs[i]); 3331 } 3332 3333 // multiday events 3334 this._rendered_location = this._els['dhx_multi_day'][0]; 3335 this._table_view = true; 3336 this.render_data(tvd, hold); 3337 this._table_view = false; 3338 3339 // normal events 3340 this._rendered_location = this._els['dhx_cal_data'][0]; 3341 this._table_view = false; 3342 this.render_data(tvs, hold);
3343 3344 } else { 3345 this._rendered_location = this._els['dhx_cal_data'][0]; 3346 this.render_data(evs, hold); 3347 } 3348}; 3349scheduler.render_data = function(evs, hold) { 3350 evs = this._pre_render_events(evs, hold); 3351 for (var i = 0; i < evs.length; i++) 3352 if (this._table_view) 3353 this.render_event_bar(evs[i]); 3354 else 3355 this.render_event(evs[i]); 3356}; 3357scheduler._pre_render_events = function(evs, hold) { 3358 var hb = this.xy.bar_height; 3359 var h_old = this._colsS.heights; 3360 var h = this._colsS.heights = [0, 0, 0, 0, 0, 0, 0]; 3361 var data = this._els["dhx_cal_data"][0]; 3362 3363 if (!this._table_view) 3364 evs = this._pre_render_events_line(evs, hold); //ignore long events for now 3365 else 3366 evs = this._pre_render_events_table(evs, hold); 3367 3368 if (this._table_view) { 3369 if (hold) 3370 this._colsS.heights = h_old; 3371 else { 3372 var evl = data.firstChild; 3373 if (evl.rows) { 3374 for (var i = 0; i < evl.rows.length; i++) { 3375 h[i]++; 3376 if ((h[i]) * hb > this._colsS.height - 22) { // 22 - height of cell's header 3377 //we have overflow, update heights 3378 var cells = evl.rows[i].cells; 3379 for (var j = 0; j < cells.length; j++) { 3380 cells[j].childNodes[1].style.height = h[i] * hb + "px"; 3381 } 3382 h[i] = (h[i - 1] || 0) + cells[0].offsetHeight; 3383 } 3384 h[i] = (h[i - 1] || 0) + evl.rows[i].cells[0].offsetHeight; 3385 } 3386 h.unshift(0); 3387 if (evl.parentNode.offsetHeight < evl.parentNode.scrollHeight && !evl._h_fix && scheduler.xy.scroll_width) { 3388 //we have v-scroll, decrease last day cell 3389 for (var i = 0; i < evl.rows.length; i++) { 3390 var cell = evl.rows[i].cells[6].childNodes[0]; 3391 var w = cell.offsetWidth - scheduler.xy.scroll_width + "px"; 3392 cell.style.width = w; 3393 cell.nextSibling.style.width = w; 3394 } 3395 evl._h_fix = true; 3396 } 3397 } else { 3398 if (!evs.length && this._els["dhx_multi_day"][0].style.visibility == "visible") 3399 h[0] = -1; 3400 if (evs.length || h[0] == -1) { 3401 //shift days to have space for multiday events 3402 var childs = evl.parentNode.childNodes; 3403 3404 // +1 so multiday events would have 2px from top and 2px from bottom by default 3405 var full_multi_day_height = (h[0] + 1) * hb + 1; 3406 3407 var used_multi_day_height = full_multi_day_height; 3408 var used_multi_day_height_css = full_multi_day_height + "px"; 3409 if (this.config.multi_day_height_limit) { 3410 used_multi_day_height = Math.min(full_multi_day_height, this.config.multi_day_height_limit) ; 3411 used_multi_day_height_css = used_multi_day_height + "px"; 3412 } 3413 3414 data.style.top = (this._els["dhx_cal_navline"][0].offsetHeight + this._els["dhx_cal_header"][0].offsetHeight + used_multi_day_height ) + 'px'; 3415 data.style.height = (this._obj.offsetHeight - parseInt(data.style.top, 10) - (this.xy.margin_top || 0)) + 'px'; 3416 3417 var multi_day_section = this._els["dhx_multi_day"][0]; 3418 multi_day_section.style.height = used_multi_day_height_css; 3419 multi_day_section.style.visibility = (h[0] == -1 ? "hidden" : "visible"); 3420 3421 // icon 3422 var multi_day_icon = this._els["dhx_multi_day"][1]; 3423 multi_day_icon.style.height = used_multi_day_height_css; 3424 multi_day_icon.style.visibility = (h[0] == -1 ? "hidden" : "visible"); 3425 multi_day_icon.className = h[0] ? "dhx_multi_day_icon" : "dhx_multi_day_icon_small"; 3426 this._dy_shift = (h[0] + 1) * hb; 3427 h[0] = 0; 3428 3429 if (used_multi_day_height != full_multi_day_height) { 3430 data.style.top = (parseInt(data.style.top) + 2) + "px"; 3431 3432 multi_day_section.style.overflowY = "auto"; 3433 multi_day_section.style.width = (parseInt(multi_day_section.style.width) - 2) + "px"; 3434 3435 multi_day_icon.style.position = "fixed"; 3436 multi_day_icon.style.top = ""; 3437 multi_day_icon.style.left = ""; 3438 } 3439 } 3440 } 3441 } 3442 } 3443 3444 return evs; 3445}; 3446scheduler._get_event_sday = function(ev) { 3447 return Math.floor((ev.start_date.valueOf() - this._min_date.valueOf()) / (24 * 60 * 60 * 1000)); 3448}; 3449scheduler._get_event_mapped_end_date = function(ev) { 3450 var end_date = ev.end_date; 3451 if (this.config.separate_short_events) { 3452 var ev_duration = (ev.end_date - ev.start_date) / 60000; // minutes 3453 if (ev_duration < this._min_mapped_duration) { 3454 end_date = this.date.add(end_date, this._min_mapped_duration - ev_duration, "minute"); 3455 } 3456 } 3457 return end_date; 3458}; 3459scheduler._pre_render_events_line = function(evs, hold) { 3460 evs.sort(function(a, b) { 3461 if (a.start_date.valueOf() == b.start_date.valueOf()) 3462 return a.id > b.id ? 1 : -1; 3463 return a.start_date > b.start_date ? 1 : -1; 3464 }); 3465 var days = []; //events by weeks 3466 var evs_originals = []; 3467 3468 this._min_mapped_duration = Math.ceil(this.xy.min_event_height * 60 / this.config.hour_size_px); // values could change along the way 3469 3470 for (var i = 0; i < evs.length; i++) { 3471 var ev = evs[i]; 3472 3473 //check date overflow 3474 var sd = ev.start_date; 3475 var ed = ev.end_date; 3476 //check scale overflow 3477 var sh = sd.getHours(); 3478 var eh = ed.getHours(); 3479 3480 ev._sday = this._get_event_sday(ev); // sday based on event start_date
3481 if (!days[ev._sday]) days[ev._sday] = []; 3482 3483 if (!hold) { 3484 ev._inner = false; 3485 3486 var stack = days[ev._sday]; 3487 3488 while (stack.length) { 3489 var t_ev = stack[stack.length - 1]; 3490 var t_end_date = this._get_event_mapped_end_date(t_ev); 3491 if (t_end_date.valueOf() <= ev.start_date.valueOf()) { 3492 stack.splice(stack.length - 1, 1); 3493 } else { 3494 break; 3495 } 3496 } 3497 3498 var sorderSet = false; 3499 for (var j = 0; j < stack.length; j++) { 3500 var t_ev = stack[j]; 3501 var t_end_date = this._get_event_mapped_end_date(t_ev); 3502 if (t_end_date.valueOf() <= ev.start_date.valueOf()) { 3503 sorderSet = true; 3504 ev._sorder = t_ev._sorder; 3505 stack.splice(j, 1); 3506 ev._inner = true; 3507 break; 3508 } 3509 } 3510 3511 if (stack.length) 3512 stack[stack.length - 1]._inner = true; 3513 3514 if (!sorderSet) { 3515 if (stack.length) { 3516 if (stack.length <= stack[stack.length - 1]._sorder) { 3517 if (!stack[stack.length - 1]._sorder) 3518 ev._sorder = 0; 3519 else 3520 for (j = 0; j < stack.length; j++) { 3521 var _is_sorder = false; 3522 for (var k = 0; k < stack.length; k++) { 3523 if (stack[k]._sorder == j) { 3524 _is_sorder = true; 3525 break; 3526 } 3527 } 3528 if (!_is_sorder) { 3529 ev._sorder = j; 3530 break; 3531 } 3532 } 3533 ev._inner = true; 3534 } else { 3535 var _max_sorder = stack[0]._sorder; 3536 for (j = 1; j < stack.length; j++) { 3537 if (stack[j]._sorder > _max_sorder) 3538 _max_sorder = stack[j]._sorder; 3539 } 3540 ev._sorder = _max_sorder + 1; 3541 ev._inner = false; 3542 } 3543 3544 } else 3545 ev._sorder = 0; 3546 } 3547 3548 stack.push(ev); 3549 3550 if (stack.length > (stack.max_count || 0)) { 3551 stack.max_count = stack.length; 3552 ev._count = stack.length; 3553 } else { 3554 ev._count = (ev._count) ? ev._count : 1; 3555 } 3556 } 3557 3558 if (sh < this.config.first_hour || eh >= this.config.last_hour) { 3559 // Need to create copy of event as we will be changing it's start/end date 3560 // e.g. first_hour = 11 and event.start_date hours = 9. Need to preserve that info 3561 evs_originals.push(ev); 3562 evs[i] = ev = this._copy_event(ev); 3563 3564 if (sh < this.config.first_hour) { 3565 ev.start_date.setHours(this.config.first_hour); 3566 ev.start_date.setMinutes(0); 3567 } 3568 if (eh >= this.config.last_hour) { 3569 ev.end_date.setMinutes(0); 3570 ev.end_date.setHours(this.config.last_hour); 3571 } 3572 3573 if (ev.start_date > ev.end_date || sh == this.config.last_hour) { 3574 evs.splice(i, 1); 3575 i--; 3576 continue; 3577 } 3578 } 3579 } 3580 if (!hold) { 3581 for (var i = 0; i < evs.length; i++) { 3582 evs[i]._count = days[evs[i]._sday].max_count; 3583 } 3584 for (var i = 0; i < evs_originals.length; i++) 3585 evs_originals[i]._count = days[evs_originals[i]._sday].max_count; 3586 } 3587 3588 return evs; 3589}; 3590scheduler._time_order = function(evs) { 3591 evs.sort(function(a, b) { 3592 if (a.start_date.valueOf() == b.start_date.valueOf()) { 3593 if (a._timed && !b._timed) return 1; 3594 if (!a._timed && b._timed) return -1; 3595 return a.id > b.id ? 1 : -1; 3596 } 3597 return a.start_date > b.start_date ? 1 : -1; 3598 }); 3599}; 3600scheduler._pre_render_events_table = function(evs, hold) { // max - max height of week slot 3601 this._time_order(evs); 3602 var out = []; 3603 var weeks = [ 3604 [], 3605 [], 3606 [], 3607 [], 3608 [], 3609 [], 3610 [] 3611 ]; //events by weeks 3612 var max = this._colsS.heights; 3613 var start_date; 3614 var cols = this._cols.length; 3615 var chunks_info = {}; 3616 3617 for (var i = 0; i < evs.length; i++) { 3618 var ev = evs[i]; 3619 var id = ev.id; 3620 if (!chunks_info[id]) { 3621 chunks_info[id] = { 3622 first_chunk: true, 3623 last_chunk: true 3624 }; 3625 } 3626 var chunk_info = chunks_info[id]; 3627 var sd = (start_date || ev.start_date); 3628 var ed = ev.end_date; 3629 //trim events which are crossing through current view 3630 if (sd < this._min_date) { 3631 chunk_info.first_chunk = false; 3632 sd = this._min_date; 3633 } 3634 if (ed > this._max_date) { 3635 chunk_info.last_chunk = false; 3636 ed = this._max_date; 3637 } 3638 3639 var locate_s = this.locate_holder_day(sd, false, ev); 3640 ev._sday = locate_s % cols; 3641 var locate_e = this.locate_holder_day(ed, true, ev) || cols; 3642 ev._eday = (locate_e % cols) || cols; //cols used to fill full week, when event end on monday 3643 ev._length = locate_e - locate_s; 3644 3645 //3600000 - compensate 1 hour during winter|summer time shift 3646 ev._sweek = Math.floor((this._correct_shift(sd.valueOf(), 1) - this._min_date.valueOf()) / (60 * 60 * 1000 * 24 * cols)); 3647 3648 //current slot 3649 var stack = weeks[ev._sweek]; 3650 //check order position 3651 var stack_line; 3652 3653 for (stack_line = 0; stack_line < stack.length; stack_line++) 3654 if (stack[stack_line]._eday <= ev._sday) 3655 break; 3656 3657 if (!ev._sorder || !hold) { 3658 ev._sorder = stack_line; 3659 } 3660 3661 if (ev._sday + ev._length <= cols) { 3662 start_date = null; 3663 out.push(ev); 3664 stack[stack_line] = ev; 3665 //get max height of slot 3666 max[ev._sweek] = stack.length - 1; 3667 ev._first_chunk = chunk_info.first_chunk; 3668 ev._last_chunk = chunk_info.last_chunk; 3669 } else { // split long event in chunks 3670 var copy = this._copy_event(ev);
3671 copy.id = ev.id; 3672 copy._length = cols - ev._sday; 3673 copy._eday = cols; 3674 copy._sday = ev._sday; 3675 copy._sweek = ev._sweek; 3676 copy._sorder = ev._sorder; 3677 copy.end_date = this.date.add(sd, copy._length, "day"); 3678 copy._first_chunk = chunk_info.first_chunk; 3679 if (chunk_info.first_chunk) { 3680 chunk_info.first_chunk = false; 3681 } 3682 3683 out.push(copy); 3684 stack[stack_line] = copy; 3685 start_date = copy.end_date; 3686 //get max height of slot 3687 max[ev._sweek] = stack.length - 1; 3688 i--; 3689 continue; //repeat same step 3690 } 3691 } 3692 return out; 3693}; 3694scheduler._copy_dummy = function() { 3695 var a = new Date(this.start_date); 3696 var b = new Date(this.end_date); 3697 this.start_date = a; 3698 this.end_date = b; 3699}; 3700scheduler._copy_event = function(ev) { 3701 this._copy_dummy.prototype = ev; 3702 return new this._copy_dummy(); 3703 //return {start_date:ev.start_date, end_date:ev.end_date, text:ev.text, id:ev.id} 3704}; 3705scheduler._rendered = []; 3706scheduler.clear_view = function() { 3707 for (var i = 0; i < this._rendered.length; i++) { 3708 var obj = this._rendered[i]; 3709 if (obj.parentNode) obj.parentNode.removeChild(obj); 3710 } 3711 this._rendered = []; 3712}; 3713scheduler.updateEvent = function(id) { 3714 var ev = this.getEvent(id); 3715 this.clear_event(id); 3716 3717 if (ev && this.is_visible_events(ev) && this.filter_event(id, ev) && (this._table_view || this.config.multi_day || ev._timed)) { 3718 if (this.config.update_render) 3719 this.render_view_data(); 3720 else 3721 this.render_view_data([ev], true); 3722 } 3723}; 3724scheduler.clear_event = function(id) { 3725 this.for_rendered(id, function(node, i) { 3726 if (node.parentNode) 3727 node.parentNode.removeChild(node); 3728 scheduler._rendered.splice(i, 1); 3729 }); 3730}; 3731scheduler.render_event = function(ev) { 3732 var menu = scheduler.xy.menu_width; 3733 var menu_offset = (this.config.use_select_menu_space) ? 0 : menu; 3734 if (ev._sday < 0) return; //can occur in case of recurring event during time shift 3735 var parent = scheduler.locate_holder(ev._sday); 3736 if (!parent) return; //attempt to render non-visible event 3737 var sm = ev.start_date.getHours() * 60 + ev.start_date.getMinutes(); 3738 var em = (ev.end_date.getHours() * 60 + ev.end_date.getMinutes()) || (scheduler.config.last_hour * 60); 3739 var ev_count = ev._count || 1; 3740 var ev_sorder = ev._sorder || 0; 3741 var top = (Math.round((sm * 60 * 1000 - this.config.first_hour * 60 * 60 * 1000) * this.config.hour_size_px / (60 * 60 * 1000))) % (this.config.hour_size_px * 24); //42px/hour 3742 var height = Math.max(scheduler.xy.min_event_height, (em - sm) * this.config.hour_size_px / 60); //42px/hour 3743 var width = Math.floor((parent.clientWidth - menu_offset) / ev_count); 3744 var left = ev_sorder * width + 1; 3745 if (!ev._inner) width = width * (ev_count - ev_sorder); 3746 if (this.config.cascade_event_display) { 3747 var limit = this.config.cascade_event_count; 3748 var margin = this.config.cascade_event_margin; 3749 left = ev_sorder % limit * margin; 3750 var right = (ev._inner) ? (ev_count - ev_sorder - 1) % limit * margin / 2 : 0; 3751 width = Math.floor(parent.clientWidth - menu_offset - left - right); 3752 } 3753 3754 var d = this._render_v_bar(ev.id, menu_offset + left, top, width, height, ev._text_style, scheduler.templates.event_header(ev.start_date, ev.end_date, ev), scheduler.templates.event_text(ev.start_date, ev.end_date, ev)); 3755 3756 this._rendered.push(d); 3757 parent.appendChild(d); 3758 3759 left = left + parseInt(parent.style.left, 10) + menu_offset; 3760 3761 if (this._edit_id == ev.id) { 3762 3763 d.style.zIndex = 1; //fix overlapping issue 3764 width = Math.max(width - 4, scheduler.xy.editor_width); 3765 d = document.createElement("DIV"); 3766 d.setAttribute("event_id", ev.id); 3767 this.set_xy(d, width, height - 20, left, top + 14); 3768 d.className = "dhx_cal_editor"; 3769 3770 var d2 = document.createElement("DIV"); 3771 this.set_xy(d2, width - 6, height - 26); 3772 d2.style.cssText += ";margin:2px 2px 2px 2px;overflow:hidden;"; 3773 3774 d.appendChild(d2); 3775 this._els["dhx_cal_data"][0].appendChild(d); 3776 this._rendered.push(d); 3777 3778 d2.innerHTML = "<textarea class='dhx_cal_editor'>" + ev.text + "</textarea>"; 3779 if (this._quirks7) d2.firstChild.style.height = height - 12 + "px"; //IEFIX 3780 this._editor = d2.firstChild; 3781 this._editor.onkeydown = function(e) { 3782 if ((e || event).shiftKey) return true; 3783 var code = (e || event).keyCode;
3784 if (code == scheduler.keys.edit_save) scheduler.editStop(true); 3785 if (code == scheduler.keys.edit_cancel) scheduler.editStop(false); 3786 }; 3787 this._editor.onselectstart = function (e) { 3788 return (e || event).cancelBubble = true; 3789 }; 3790 scheduler._focus(d2.firstChild, true); 3791 //IE and opera can add x-scroll during focusing 3792 this._els["dhx_cal_data"][0].scrollLeft = 0; 3793 } 3794 if (this.xy.menu_width !== 0 && this._select_id == ev.id) { 3795 if (this.config.cascade_event_display && this._drag_mode) 3796 d.style.zIndex = 1; //fix overlapping issue for cascade view in case of dnd of selected event 3797 var icons = this.config["icons_" + ((this._edit_id == ev.id) ? "edit" : "select")]; 3798 var icons_str = ""; 3799 var bg_color = (ev.color ? ("background-color: " + ev.color + ";") : ""); 3800 var color = (ev.textColor ? ("color: " + ev.textColor + ";") : ""); 3801 for (var i = 0; i < icons.length; i++) 3802 icons_str += "<div class='dhx_menu_icon " + icons[i] + "' style='" + bg_color + "" + color + "' title='" + this.locale.labels[icons[i]] + "'></div>"; 3803 var obj = this._render_v_bar(ev.id, left - menu + 1, top, menu, icons.length * 20 + 26 - 2, "", "<div style='" + bg_color + "" + color + "' class='dhx_menu_head'></div>", icons_str, true); 3804 obj.style.left = left - menu + 1; 3805 this._els["dhx_cal_data"][0].appendChild(obj); 3806 this._rendered.push(obj); 3807 } 3808}; 3809scheduler._render_v_bar = function (id, x, y, w, h, style, contentA, contentB, bottom) { 3810 var d = document.createElement("DIV"); 3811 var ev = this.getEvent(id); 3812 3813 var cs = (bottom) ? "dhx_cal_event dhx_cal_select_menu" : "dhx_cal_event"; 3814 3815 var cse = scheduler.templates.event_class(ev.start_date, ev.end_date, ev); 3816 if (cse) cs = cs + " " + cse; 3817 3818 var bg_color = (ev.color ? ("background:" + ev.color + ";") : ""); 3819 var color = (ev.textColor ? ("color:" + ev.textColor + ";") : ""); 3820 3821 var html = '<div event_id="' + id + '" class="' + cs + '" style="position:absolute; top:' + y + 'px; left:' + x + 'px; width:' + (w - 4) + 'px; height:' + h + 'px;' + (style || "") + '"></div>'; 3822 d.innerHTML = html; 3823 3824 var container = d.cloneNode(true).firstChild; 3825 3826 if (scheduler.renderEvent && !bottom && scheduler.renderEvent(container, ev)) { 3827 return container; 3828 } else { 3829 container = d.firstChild; 3830 3831 var inner_html = '<div class="dhx_event_move dhx_header" style=" width:' + (w - 6) + 'px;' + bg_color + '" > </div>'; 3832 inner_html += '<div class="dhx_event_move dhx_title" style="' + bg_color + '' + color + '">' + contentA + '</div>'; 3833 inner_html += '<div class="dhx_body" style=" width:' + (w - (this._quirks ? 4 : 14)) + 'px; height:' + (h - (this._quirks ? 20 : 30) + 1) + 'px;' + bg_color + '' + color + '">' + contentB + '</div>'; // +2 css specific, moved from render_event 3834 3835 var footer_class = "dhx_event_resize dhx_footer"; 3836 if (bottom) 3837 footer_class = "dhx_resize_denied " + footer_class; 3838 3839 inner_html += '<div class="' + footer_class + '" style=" width:' + (w - 8) + 'px;' + (bottom ? ' margin-top:-1px;' : '') + '' + bg_color + '' + color + '" ></div>'; 3840 3841 container.innerHTML = inner_html; 3842 } 3843 3844 return container; 3845}; 3846scheduler.locate_holder = function(day) { 3847 if (this._mode == "day") return this._els["dhx_cal_data"][0].firstChild; //dirty 3848 return this._els["dhx_cal_data"][0].childNodes[day]; 3849}; 3850scheduler.locate_holder_day = function(date, past) { 3851 var day = Math.floor((this._correct_shift(date, 1) - this._min_date) / (60 * 60 * 24 * 1000)); 3852 //when locating end data of event , we need to use next day if time part was defined 3853 if (past && this.date.time_part(date)) day++; 3854 return day; 3855}; 3856scheduler.render_event_bar = function (ev) { 3857 var parent = this._rendered_location; 3858 3859 var x = this._colsS[ev._sday]; 3860 var x2 = this._colsS[ev._eday]; 3861 if (x2 == x) x2 = this._colsS[ev._eday + 1]; 3862 var hb = this.xy.bar_height; 3863 3864 var y_event_offset = (ev.id == this._drag_id) ? 0 : ev._sorder * hb; 3865 var y = this._colsS.heights[ev._sweek] + (this._colsS.height ? (this.xy.month_scale_height + 2) : 2 ) + y_event_offset; 3866 3867 var d = document.createElement("DIV"); 3868 var cs = "dhx_cal_event_clear"; 3869 if (!ev._timed) { 3870 cs = "dhx_cal_event_line"; 3871 if (ev.hasOwnProperty("_first_chunk") && ev._first_chunk) 3872 cs += " dhx_cal_event_line_start"; 3873 if (ev.hasOwnProperty("_last_chunk") && ev._last_chunk) 3874 cs += " dhx_cal_event_line_end"; 3875 } 3876 3877 var cse = scheduler.templates.event_class(ev.start_date, ev.end_date, ev); 3878 if (cse) cs = cs + " " + cse; 3879 3880 var bg_color = (ev.color ? ("background:" + ev.color + ";") : ""); 3881 var color = (ev.textColor ? ("color:" + ev.textColor + ";") : ""); 3882 3883 var html = '<div event_id="' + ev.id + '" class="' + cs + '" style="position:absolute; top:' + y + 'px; left:' + x + 'px; width:' + (x2 - x - 15) + 'px;' + color + '' + bg_color + '' + (ev._text_style || "") + '">'; 3884 3885 ev = scheduler.getEvent(ev.id); // ev at this point could be a part of a larged event 3886 if (ev._timed) 3887 html += scheduler.templates.event_bar_date(ev.start_date, ev.end_date, ev); 3888 html += scheduler.templates.event_bar_text(ev.start_date, ev.end_date, ev) + '</div>'; 3889 html += '</div>'; 3890 3891 d.innerHTML = html; 3892 3893 this._rendered.push(d.firstChild); 3894 parent.appendChild(d.firstChild); 3895}; 3896 3897scheduler._locate_event = function(node) { 3898 var id = null; 3899 while (node && !id && node.getAttribute) { 3900 id = node.getAttribute("event_id"); 3901 node = node.parentNode; 3902 } 3903 return id; 3904}; 3905 3906scheduler.edit = function(id) { 3907 if (this._edit_id == id) return;
3908 this.editStop(false, id); 3909 this._edit_id = id; 3910 this.updateEvent(id); 3911}; 3912scheduler.editStop = function(mode, id) { 3913 if (id && this._edit_id == id) return; 3914 var ev = this.getEvent(this._edit_id); 3915 if (ev) { 3916 if (mode) ev.text = this._editor.value; 3917 this._edit_id = null; 3918 this._editor = null; 3919 this.updateEvent(ev.id); 3920 this._edit_stop_event(ev, mode); 3921 } 3922}; 3923scheduler._edit_stop_event = function(ev, mode) { 3924 if (this._new_event) { 3925 if (!mode) { 3926 if (ev) // in case of custom lightbox user can already delete event 3927 this.deleteEvent(ev.id, true); 3928 } else { 3929 this.callEvent("onEventAdded", [ev.id, ev]); 3930 } 3931 this._new_event = null; 3932 } else { 3933 if (mode) 3934 this.callEvent("onEventChanged", [ev.id, ev]); 3935 } 3936}; 3937 3938scheduler.getEvents = function(from, to) { 3939 var result = []; 3940 for (var a in this._events) { 3941 var ev = this._events[a]; 3942 if (ev && ( (!from && !to) || (ev.start_date < to && ev.end_date > from) )) 3943 result.push(ev); 3944 } 3945 return result; 3946}; 3947scheduler.getRenderedEvent = function(id) { 3948 if (!id) 3949 return; 3950 var rendered_events = scheduler._rendered; 3951 for (var i=0; i<rendered_events.length; i++) { 3952 var rendered_event = rendered_events[i]; 3953 if (rendered_event.getAttribute("event_id") == id) { 3954 return rendered_event; 3955 } 3956 } 3957 return null; 3958}; 3959scheduler.showEvent = function(id, mode) { 3960 var ev = (typeof id == "number" || typeof id == "string") ? scheduler.getEvent(id) : id; 3961 mode = mode||scheduler._mode; 3962 3963 if (!ev || (this.checkEvent("onBeforeEventDisplay") && !this.callEvent("onBeforeEventDisplay", [ev, mode]))) 3964 return; 3965 3966 var scroll_hour = scheduler.config.scroll_hour; 3967 scheduler.config.scroll_hour = ev.start_date.getHours(); 3968 var preserve_scroll = scheduler.config.preserve_scroll; 3969 scheduler.config.preserve_scroll = false; 3970 3971 var original_color = ev.color; 3972 var original_text_color = ev.textColor; 3973 if (scheduler.config.highlight_displayed_event) { 3974 ev.color = scheduler.config.displayed_event_color; 3975 ev.textColor = scheduler.config.displayed_event_text_color; 3976 } 3977 3978 scheduler.setCurrentView(new Date(ev.start_date), mode); 3979 3980 ev.color = original_color; 3981 ev.textColor = original_text_color; 3982 scheduler.config.scroll_hour = scroll_hour; 3983 scheduler.config.preserve_scroll = preserve_scroll; 3984 3985 if (scheduler.matrix && scheduler.matrix[mode]) { 3986 scheduler._els.dhx_cal_data[0].scrollTop = getAbsoluteTop(scheduler.getRenderedEvent(ev.id)) - getAbsoluteTop(scheduler._els.dhx_cal_data[0]) - 20; 3987 } 3988 3989 scheduler.callEvent("onAfterEventDisplay", [ev, mode]); 3990}; 3991 3992scheduler._loaded = {}; 3993scheduler._load = function(url, from) { 3994 url = url || this._load_url; 3995 url += (url.indexOf("?") == -1 ? "?" : "&") + "timeshift=" + (new Date()).getTimezoneOffset(); 3996 if (this.config.prevent_cache) url += "&uid=" + this.uid(); 3997 var to; 3998 from = from || this._date; 3999 4000 if (this._load_mode) { 4001 var lf = this.templates.load_format; 4002 4003 from = this.date[this._load_mode + "_start"](new Date(from.valueOf())); 4004 while (from > this._min_date) from = this.date.add(from, -1, this._load_mode); 4005 to = from; 4006 4007 var cache_line = true; 4008 while (to < this._max_date) { 4009 to = this.date.add(to, 1, this._load_mode); 4010 if (this._loaded[lf(from)] && cache_line) 4011 from = this.date.add(from, 1, this._load_mode); else cache_line = false; 4012 } 4013 4014 var temp_to = to; 4015 do { 4016 to = temp_to; 4017 temp_to = this.date.add(to, -1, this._load_mode); 4018 } while (temp_to > from && this._loaded[lf(temp_to)]); 4019 4020 if (to <= from) 4021 return false; //already loaded 4022 dhtmlxAjax.get(url + "&from=" + lf(from) + "&to=" + lf(to), function(l) {scheduler.on_load(l);}); 4023 while (from < to) { 4024 this._loaded[lf(from)] = true; 4025 from = this.date.add(from, 1, this._load_mode); 4026 } 4027 } else 4028 dhtmlxAjax.get(url, function(l) {scheduler.on_load(l);}); 4029 this.callEvent("onXLS", []); 4030 return true; 4031}; 4032scheduler.on_load = function(loader) { 4033 var evs; 4034 if (this._process) { 4035 evs = this[this._process].parse(loader.xmlDoc.responseText); 4036 } else { 4037 evs = this._magic_parser(loader); 4038 } 4039 4040 scheduler._process_loading(evs); 4041 4042 this.callEvent("onXLE", []); 4043}; 4044scheduler._process_loading = function(evs) { 4045 this._loading = true; 4046 this._not_render = true; 4047 for (var i = 0; i < evs.length; i++) { 4048 if (!this.callEvent("onEventLoading", [evs[i]])) continue; 4049 this.addEvent(evs[i]); 4050 } 4051 this._not_render = false; 4052 if (this._render_wait) this.render_view_data(); 4053 4054 this._loading = false; 4055 if (this._after_call) this._after_call(); 4056 this._after_call = null; 4057}; 4058scheduler._init_event = function(event) { 4059 event.text = (event.text || event._tagvalue) || ""; 4060 event.start_date = (event.start_date) ? scheduler.templates.xml_date(event.start_date) : null; 4061 event.end_date = (event.end_date) ? scheduler.templates.xml_date(event.end_date) : null; 4062}; 4063scheduler.json = {}; 4064scheduler.json.parse = function(data) { 4065 if (typeof data == "string") { 4066 scheduler._temp = eval("(" + data + ")"); 4067 data = (scheduler._temp) ? scheduler._temp.data || scheduler._temp : []; 4068 } 4069 4070 if (data.dhx_security) 4071 dhtmlx.security_key = data.dhx_security; 4072 4073 var collections = (scheduler._temp && scheduler._temp.collections) ? scheduler._temp.collections : {}; 4074 var collections_loaded = false; 4075 for (var key in collections) { 4076 if (collections.hasOwnProperty(key)) { 4077 collections_loaded = true; 4078 var collection = collections[key]; 4079 var arr = scheduler.serverList[key]; 4080 if (!arr) continue; 4081 arr.splice(0, arr.length); //clear old options 4082 for (var j = 0; j < collection.length; j++) { 4083 var option = collection[j]; 4084 var obj = { key: option.value, label: option.label }; // resulting option object 4085 for (var option_key in option) { 4086 if (option.hasOwnProperty(option_key)) { 4087 if (option_key == "value" || option_key == "label") 4088 continue; 4089 obj[option_key] = option[option_key]; // obj['value'] = option['value'] 4090 } 4091 } 4092 arr.push(obj); 4093 } 4094 } 4095 } 4096 if (collections_loaded) 4097 scheduler.callEvent("onOptionsLoad", []); 4098 4099 var evs = []; 4100 for (var i = 0; i < data.length; i++) { 4101 var event = data[i]; 4102 scheduler._init_event(event); 4103 evs.push(event); 4104 } 4105 return evs; 4106}; 4107scheduler.parse = function(data, type) { 4108 this._process = type; 4109 this.on_load({xmlDoc: {responseText: data}}); 4110}; 4111scheduler.load = function(url, call) { 4112 if (typeof call == "string") { 4113 this._process = call; 4114 call = arguments[2]; 4115 } 4116 4117 this._load_url = url; 4118 this._after_call = call; 4119 this._load(url, this._date); 4120}; 4121//possible values - day,week,month,year,all 4122scheduler.setLoadMode = function(mode) { 4123 if (mode == "all") mode = ""; 4124 this._load_mode = mode; 4125}; 4126 4127//current view by default, or all data if "true" as parameter provided 4128scheduler.refresh = function(refresh_all) { 4129 alert("not implemented"); 4130 /* 4131 this._loaded={}; 4132 this._load(); 4133 */ 4134}; 4135scheduler.serverList = function(name, array) { 4136 if (array) { 4137 return this.serverList[name] = array.slice(0); 4138 } 4139 return this.serverList[name] = (this.serverList[name] || []); 4140}; 4141scheduler._userdata = {}; 4142scheduler._magic_parser = function(loader) { 4143 var xml; 4144 if (!loader.getXMLTopNode) { //from a string 4145 var xml_string = loader.xmlDoc.responseText; 4146 loader = new dtmlXMLLoaderObject(function() {}); 4147 loader.loadXMLString(xml_string); 4148 } 4149 4150 xml = loader.getXMLTopNode("data"); 4151 if (xml.tagName != "data") return [];//not an xml 4152 var skey = xml.getAttribute("dhx_security"); 4153 if (skey) 4154 dhtmlx.security_key = skey; 4155 4156 var opts = loader.doXPath("//coll_options"); 4157 for (var i = 0; i < opts.length; i++) { 4158 var bind = opts[i].getAttribute("for"); 4159 var arr = this.serverList[bind];
4160 if (!arr) continue; 4161 arr.splice(0, arr.length); //clear old options 4162 var itms = loader.doXPath(".//item", opts[i]); 4163 for (var j = 0; j < itms.length; j++) { 4164 var itm = itms[j]; 4165 var attrs = itm.attributes; 4166 var obj = { key: itms[j].getAttribute("value"), label: itms[j].getAttribute("label")}; 4167 for (var k = 0; k < attrs.length; k++) { 4168 var attr = attrs[k]; 4169 if (attr.nodeName == "value" || attr.nodeName == "label") 4170 continue; 4171 obj[attr.nodeName] = attr.nodeValue; 4172 } 4173 arr.push(obj); 4174 } 4175 } 4176 if (opts.length) 4177 scheduler.callEvent("onOptionsLoad", []); 4178 4179 var ud = loader.doXPath("//userdata"); 4180 for (var i = 0; i < ud.length; i++) { 4181 var udx = this.xmlNodeToJSON(ud[i]); 4182 this._userdata[udx.name] = udx.text; 4183 } 4184 4185 var evs = []; 4186 xml = loader.doXPath("//event"); 4187 4188 for (var i = 0; i < xml.length; i++) { 4189 var ev = evs[i] = this.xmlNodeToJSON(xml[i]); 4190 scheduler._init_event(ev); 4191 } 4192 return evs; 4193}; 4194scheduler.xmlNodeToJSON = function(node) { 4195 var t = {}; 4196 for (var i = 0; i < node.attributes.length; i++) 4197 t[node.attributes[i].name] = node.attributes[i].value; 4198 4199 for (var i = 0; i < node.childNodes.length; i++) { 4200 var child = node.childNodes[i]; 4201 if (child.nodeType == 1) 4202 t[child.tagName] = child.firstChild ? child.firstChild.nodeValue : ""; 4203 } 4204 4205 if (!t.text) t.text = node.firstChild ? node.firstChild.nodeValue : ""; 4206 4207 return t; 4208}; 4209scheduler.attachEvent("onXLS", function() { 4210 if (this.config.show_loading === true) { 4211 var t; 4212 t = this.config.show_loading = document.createElement("DIV"); 4213 t.className = 'dhx_loading'; 4214 t.style.left = Math.round((this._x - 128) / 2) + "px"; 4215 t.style.top = Math.round((this._y - 15) / 2) + "px"; 4216 this._obj.appendChild(t); 4217 } 4218}); 4219scheduler.attachEvent("onXLE", function() { 4220 var t; 4221 if (t = this.config.show_loading) 4222 if (typeof t == "object") { 4223 this._obj.removeChild(t); 4224 this.config.show_loading = true; 4225 } 4226}); 4227 4228/* 4229This software is allowed to use under GPL or you need to obtain Commercial or Enterise License 4230to use it in not GPL project. Please contact [email protected] for details 4231*/ 4232scheduler.ical={ 4233 parse:function(str){ 4234 var data = str.match(RegExp(this.c_start+"[^\f]*"+this.c_end,"")); 4235 if (!data.length) return; 4236 4237 //unfolding 4238 data[0]=data[0].replace(/[\r\n]+(?=[a-z \t])/g," "); 4239 //drop property 4240 data[0]=data[0].replace(/\;[^:\r\n]*/g,""); 4241 4242 4243 var incoming=[]; 4244 var match; 4245 var event_r = RegExp("(?:"+this.e_start+")([^\f]*?)(?:"+this.e_end+")","g"); 4246 while (match=event_r.exec(data)){ 4247 var e={}; 4248 var param; 4249 var param_r = /[^\r\n]+[\r\n]+/g; 4250 while (param=param_r.exec(match[1])) 4251 this.parse_param(param.toString(),e); 4252 if (e.uid && !e.id) e.id = e.uid; //fallback to UID, when ID is not defined 4253 incoming.push(e); 4254 } 4255 return incoming; 4256 }, 4257 parse_param:function(str,obj){ 4258 var d = str.indexOf(":"); 4259 if (d==-1) return; 4260 4261 var name = str.substr(0,d).toLowerCase(); 4262 var value = str.substr(d+1).replace(/\\\,/g,",").replace(/[\r\n]+$/,""); 4263 if (name=="summary") 4264 name="text"; 4265 else if (name=="dtstart"){ 4266 name = "start_date"; 4267 value = this.parse_date(value,0,0); 4268 } 4269 else if (name=="dtend"){ 4270 name = "end_date"; 4271 value = this.parse_date(value,0,0); 4272 } 4273 obj[name]=value; 4274 }, 4275 parse_date:function(value,dh,dm){ 4276 var t = value.split("T"); 4277 if (t[1]){ 4278 dh=t[1].substr(0,2); 4279 dm=t[1].substr(2,2); 4280 } 4281 var dy = t[0].substr(0,4); 4282 var dn = parseInt(t[0].substr(4,2),10)-1; 4283 var dd = t[0].substr(6,2); 4284 if (scheduler.config.server_utc && !t[1]) { // if no hours/minutes were specified == full day event 4285 return new Date(Date.UTC(dy,dn,dd,dh,dm)) ; 4286 } 4287 return new Date(dy,dn,dd,dh,dm); 4288 }, 4289 c_start:"BEGIN:VCALENDAR", 4290 e_start:"BEGIN:VEVENT", 4291 e_end:"END:VEVENT", 4292 c_end:"END:VCALENDAR" 4293}; 4294scheduler.lightbox = {}; 4295scheduler.formSection = function(name){ 4296 var config = this.config.lightbox.sections; 4297 var i =0; 4298 for (i; i < config.length; i++) 4299 if (config[i].name == name) 4300 break; 4301 var section = config[i]; 4302 if (!scheduler._lightbox) 4303 scheduler.getLightbox(); 4304 var header = document.getElementById(section.id); 4305 var node = header.nextSibling; 4306 4307 var result = { 4308 section: section, 4309 header: header, 4310 node: node, 4311 getValue:function(ev){ 4312 return scheduler.form_blocks[section.type].get_value(node, (ev||{}), section); 4313 }, 4314 setValue:function(value, ev){ 4315 return scheduler.form_blocks[section.type].set_value(node, value, (ev||{}), section); 4316 } 4317 }; 4318 4319 var handler = scheduler.lightbox["get_"+section.type+"_control"]; 4320 return handler?handler(result):result; 4321}; 4322scheduler.lightbox.get_template_control = function(result) { 4323 result.control = result.node; 4324 return result; 4325}; 4326scheduler.lightbox.get_select_control = function(result) { 4327 result.control = result.node.getElementsByTagName('select')[0]; 4328 return result; 4329}; 4330scheduler.lightbox.get_textarea_control = function(result) { 4331 result.control = result.node.getElementsByTagName('textarea')[0]; 4332 return result; 4333}; 4334scheduler.lightbox.get_time_control = function(result) { 4335 result.control = result.node.getElementsByTagName('select'); // array 4336 return result; 4337}; 4338scheduler.form_blocks={ 4339 template:{ 4340 render: function(sns){ 4341 var height=(sns.height||"30")+"px"; 4342 return "<div class='dhx_cal_ltext dhx_cal_template' style='height:"+height+";'></div>"; 4343 }, 4344 set_value:function(node,value,ev,config){ 4345 node.innerHTML = value||""; 4346 }, 4347 get_value:function(node,ev,config){ 4348 return node.innerHTML||""; 4349 }, 4350 focus: function(node){ 4351 } 4352 }, 4353 textarea:{ 4354 render:function(sns){ 4355 var height=(sns.height||"130")+"px"; 4356 return "<div class='dhx_cal_ltext' style='height:"+height+";'><textarea></textarea></div>"; 4357 }, 4358 set_value:function(node,value,ev){ 4359 node.firstChild.value=value||""; 4360 }, 4361 get_value:function(node,ev){ 4362 return node.firstChild.value; 4363 }, 4364 focus:function(node){ 4365 var a=node.firstChild; scheduler._focus(a, true) 4366 } 4367 }, 4368 select:{ 4369 render:function(sns){ 4370 var height=(sns.height||"23")+"px"; 4371 var html="<div class='dhx_cal_ltext' style='height:"+height+";'><select style='width:100%;'>"; 4372 for (var i=0; i < sns.options.length; i++) 4373 html+="<option value='"+sns.options[i].key+"'>"+sns.options[i].label+"</option>"; 4374 html+="</select></div>"; 4375 return html; 4376 }, 4377 set_value:function(node,value,ev,sns){ 4378 var select = node.firstChild; 4379 if (!select._dhx_onchange && sns.onchange) { 4380 select.onchange = sns.onchange; 4381 select._dhx_onchange = true; 4382 } 4383 if (typeof value == "undefined") 4384 value = (select.options[0]||{}).value; 4385 select.value=value||""; 4386 }, 4387 get_value:function(node,ev){ 4388 return node.firstChild.value; 4389 }, 4390 focus:function(node){ 4391 var a=node.firstChild; scheduler._focus(a, true); 4392 } 4393 }, 4394 time:{ 4395 render:function(sns) { 4396 if (!sns.time_format) { 4397 // default order 4398 sns.time_format = ["%H:%i", "%d", "%m", "%Y"]; 4399 } 4400 // map: default order => real one 4401 sns._time_format_order = {}; 4402 var time_format = sns.time_format; 4403
4404 var cfg = scheduler.config; 4405 var dt = this.date.date_part(scheduler._currentDate()); 4406 var last = 24*60, first = 0; 4407 if(scheduler.config.limit_time_select){ 4408 last = 60*cfg.last_hour+1; 4409 first = 60*cfg.first_hour; 4410 dt.setHours(cfg.first_hour); 4411 } 4412 var html = ""; 4413 4414 for (var p = 0; p < time_format.length; p++) { 4415 var time_option = time_format[p]; 4416 4417 // adding spaces between selects 4418 if (p > 0) { 4419 html += " "; 4420 } 4421 4422 switch (time_option) { 4423 case "%Y": 4424 sns._time_format_order[3] = p; 4425 //year 4426 html+="<select>"; 4427 var year = dt.getFullYear()-5; //maybe take from config? 4428 for (var i=0; i < 10; i++) 4429 html+="<option value='"+(year+i)+"'>"+(year+i)+"</option>"; 4430 html+="</select> "; 4431 break; 4432 case "%m": 4433 sns._time_format_order[2] = p; 4434 //month 4435 html+="<select>"; 4436 for (var i=0; i < 12; i++) 4437 html+="<option value='"+i+"'>"+this.locale.date.month_full[i]+"</option>"; 4438 html += "</select>"; 4439 break; 4440 case "%d": 4441 sns._time_format_order[1] = p; 4442 //days 4443 html+="<select>"; 4444 for (var i=1; i < 32; i++) 4445 html+="<option value='"+i+"'>"+i+"</option>"; 4446 html += "</select>"; 4447 break; 4448 case "%H:%i": 4449 sns._time_format_order[0] = p; 4450 //hours 4451 html += "<select>"; 4452 var i = first; 4453 var tdate = dt.getDate(); 4454 sns._time_values = []; 4455 4456 while(i<last){ 4457 var time=this.templates.time_picker(dt); 4458 html+="<option value='"+i+"'>"+time+"</option>"; 4459 sns._time_values.push(i); 4460 dt.setTime(dt.valueOf()+this.config.time_step*60*1000); 4461 var diff = (dt.getDate()!=tdate)?1:0; // moved or not to the next day 4462 i=diff*24*60+dt.getHours()*60+dt.getMinutes(); 4463 } 4464 html += "</select>"; 4465 break; 4466 } 4467 } 4468 4469 return "<div style='height:30px;padding-top:0px;font-size:inherit;' class='dhx_section_time'>"+html+"<span style='font-weight:normal; font-size:10pt;'> – </span>"+html+"</div>"; 4470 }, 4471 set_value:function(node,value,ev,config){ 4472 var cfg = scheduler.config; 4473 var s=node.getElementsByTagName("select"); 4474 var map = config._time_format_order; 4475 4476 if(cfg.full_day) { 4477 if (!node._full_day){ 4478 var html = "<label class='dhx_fullday'><input type='checkbox' name='full_day' value='true'> "+scheduler.locale.labels.full_day+" </label></input>"; 4479 if (!scheduler.config.wide_form) 4480 html = node.previousSibling.innerHTML+html; 4481 node.previousSibling.innerHTML=html; 4482 node._full_day=true; 4483 } 4484 var input=node.previousSibling.getElementsByTagName("input")[0]; 4485 input.checked = (scheduler.date.time_part(ev.start_date)===0 && scheduler.date.time_part(ev.end_date)===0); 4486 4487 s[map[0]].disabled=input.checked; 4488 s[ map[0] + s.length/2 ].disabled=input.checked; 4489 4490 input.onclick = function(){ 4491 if(input.checked) { 4492 var obj = {}; 4493 scheduler.form_blocks.time.get_value(node,obj,config); 4494 4495 var start_date = scheduler.date.date_part(obj.start_date); 4496 var end_date = scheduler.date.date_part(obj.end_date); 4497 4498 if (+end_date == +start_date || (+end_date >= +start_date && (ev.end_date.getHours() != 0 || ev.end_date.getMinutes() != 0))) 4499 end_date = scheduler.date.add(end_date, 1, "day"); 4500 } 4501 4502 s[map[0]].disabled=input.checked; 4503 s[ map[0] + s.length/2 ].disabled=input.checked; 4504 4505 _fill_lightbox_select(s,0,start_date||ev.start_date); 4506 _fill_lightbox_select(s,4,end_date||ev.end_date); 4507 }; 4508 } 4509 4510 if(cfg.auto_end_date && cfg.event_duration) { 4511 function _update_lightbox_select() { 4512 var start_date = new Date(s[map[3]].value,s[map[2]].value,s[map[1]].value,0,s[map[0]].value); 4513 var end_date = new Date(start_date.getTime() + (scheduler.config.event_duration * 60 * 1000)); 4514 _fill_lightbox_select(s, 4, end_date); 4515 } 4516 for(var i=0; i<4; i++) { 4517 s[i].onchange = _update_lightbox_select; 4518 } 4519 } 4520 4521 function _fill_lightbox_select(s,i,d) { 4522 var time_values = config._time_values; 4523 var direct_value = d.getHours()*60+d.getMinutes(); 4524 var fixed_value = direct_value; 4525 var value_found = false; 4526 for (var k=0; k<time_values.length; k++) { 4527 var t_v = time_values[k]; 4528 if (t_v === direct_value) { 4529 value_found = true; 4530 break; 4531 } 4532 if (t_v < direct_value) 4533 fixed_value = t_v; 4534 } 4535 4536 s[i+map[0]].value=(value_found)?direct_value:fixed_value; 4537 if(!(value_found || fixed_value)){ 4538 s[i+map[0]].selectedIndex = -1;//show empty select in FF 4539 } 4540 s[i+map[1]].value=d.getDate(); 4541 s[i+map[2]].value=d.getMonth(); 4542 s[i+map[3]].value=d.getFullYear(); 4543 } 4544 4545 _fill_lightbox_select(s,0,ev.start_date); 4546 _fill_lightbox_select(s,4,ev.end_date); 4547 }, 4548 get_value:function(node, ev, config) { 4549 s=node.getElementsByTagName("select"); 4550 var map = config._time_format_order; 4551 4552 ev.start_date=new Date(s[map[3]].value,s[map[2]].value,s[map[1]].value,0,s[map[0]].value); 4553 ev.end_date=new Date(s[map[3]+4].value,s[map[2]+4].value,s[map[1]+4].value,0,s[map[0]+4].value); 4554 4555 if (ev.end_date<=ev.start_date) 4556 ev.end_date=scheduler.date.add(ev.start_date,scheduler.config.time_step,"minute"); 4557 return { 4558 start_date: new Date(ev.start_date), 4559 end_date: new Date(ev.end_date) 4560 }; 4561 }, 4562 focus:function(node){ 4563 scheduler._focus(node.getElementsByTagName("select")[0]); 4564 } 4565 } 4566}; 4567scheduler.showCover=function(box){ 4568 if (box){ 4569 box.style.display="block"; 4570 4571 var scroll_top = window.pageYOffset||document.body.scrollTop||document.documentElement.scrollTop; 4572 var scroll_left = window.pageXOffset||document.body.scrollLeft||document.documentElement.scrollLeft; 4573 4574 var view_height = window.innerHeight||document.documentElement.clientHeight; 4575 4576 if(scroll_top) // if vertical scroll on window 4577 box.style.top=Math.round(scroll_top+Math.max((view_height-box.offsetHeight)/2, 0))+"px"; 4578 else // vertical scroll on body 4579 box.style.top=Math.round(Math.max(((view_height-box.offsetHeight)/2), 0) + 9)+"px"; // +9 for compatibility with auto tests 4580
4581 // not quite accurate but used for compatibility reasons 4582 if(document.documentElement.scrollWidth > document.body.offsetWidth) // if horizontal scroll on the window 4583 box.style.left=Math.round(scroll_left+(document.body.offsetWidth-box.offsetWidth)/2)+"px"; 4584 else // horizontal scroll on the body 4585 box.style.left=Math.round((document.body.offsetWidth-box.offsetWidth)/2)+"px"; 4586 } 4587 this.show_cover(); 4588}; 4589scheduler.showLightbox=function(id){ 4590 if (!id) return; 4591 if (!this.callEvent("onBeforeLightbox",[id])) { 4592 if (this._new_event) 4593 this._new_event = null; 4594 return; 4595 } 4596 var box = this.getLightbox(); 4597 this.showCover(box); 4598 this._fill_lightbox(id,box); 4599 this.callEvent("onLightbox",[id]); 4600}; 4601scheduler._fill_lightbox = function(id, box) { 4602 var ev = this.getEvent(id); 4603 var s = box.getElementsByTagName("span"); 4604 if (scheduler.templates.lightbox_header) { 4605 s[1].innerHTML = ""; 4606 s[2].innerHTML = scheduler.templates.lightbox_header(ev.start_date, ev.end_date, ev); 4607 } else { 4608 s[1].innerHTML = this.templates.event_header(ev.start_date, ev.end_date, ev); 4609 s[2].innerHTML = (this.templates.event_bar_text(ev.start_date, ev.end_date, ev) || "").substr(0, 70); //IE6 fix 4610 } 4611 4612 var sns = this.config.lightbox.sections; 4613 for (var i = 0; i < sns.length; i++) { 4614 var current_sns = sns[i]; 4615 var node = document.getElementById(current_sns.id).nextSibling; 4616 var block = this.form_blocks[current_sns.type]; 4617 var value = (ev[current_sns.map_to] !== undefined) ? ev[current_sns.map_to] : current_sns.default_value; 4618 block.set_value.call(this, node, value, ev, current_sns); 4619 if (sns[i].focus) 4620 block.focus.call(this, node); 4621 } 4622 4623 scheduler._lightbox_id = id; 4624}; 4625scheduler._lightbox_out=function(ev){ 4626 var sns = this.config.lightbox.sections; 4627 for (var i=0; i < sns.length; i++) { 4628 var node = document.getElementById(sns[i].id); 4629 node=(node?node.nextSibling:node); 4630 var block=this.form_blocks[sns[i].type]; 4631 var res=block.get_value.call(this,node,ev, sns[i]); 4632 if (sns[i].map_to!="auto") 4633 ev[sns[i].map_to]=res; 4634 } 4635 return ev; 4636}; 4637scheduler._empty_lightbox=function(data){ 4638 var id=scheduler._lightbox_id; 4639 var ev=this.getEvent(id); 4640 var box=this.getLightbox(); 4641 4642 this._lame_copy(ev, data); 4643 4644 ev._timed=this.is_one_day_event(ev); 4645 this.setEvent(ev.id,ev); 4646 this._edit_stop_event(ev,true); 4647 this.render_view_data(); 4648}; 4649scheduler.hide_lightbox=function(id){ 4650 this.hideCover(this.getLightbox()); 4651 this._lightbox_id=null; 4652 this.callEvent("onAfterLightbox",[]); 4653}; 4654scheduler.hideCover=function(box){ 4655 if (box) box.style.display="none"; 4656 this.hide_cover(); 4657}; 4658scheduler.hide_cover=function(){ 4659 if (this._cover) 4660 this._cover.parentNode.removeChild(this._cover); 4661 this._cover=null; 4662}; 4663scheduler.show_cover=function(){ 4664 this._cover=document.createElement("DIV"); 4665 this._cover.className="dhx_cal_cover"; 4666 var _document_height = ((document.height !== undefined) ? document.height : document.body.offsetHeight); 4667 var _scroll_height = ((document.documentElement) ? document.documentElement.scrollHeight : 0); 4668 this._cover.style.height = Math.max(_document_height, _scroll_height) + 'px'; 4669 document.body.appendChild(this._cover); 4670}; 4671scheduler.save_lightbox=function(){ 4672 var data = this._lightbox_out({}, this._lame_copy(this.getEvent(this._lightbox_id))); 4673 if (this.checkEvent("onEventSave") && !this.callEvent("onEventSave",[this._lightbox_id, data, this._new_event])) 4674 return; 4675 this._empty_lightbox(data); 4676 this.hide_lightbox(); 4677}; 4678scheduler.startLightbox = function(id, box){ 4679 this._lightbox_id = id; 4680 this._custom_lightbox = true; 4681 this._lightbox = box; 4682 this.showCover(box); 4683}; 4684scheduler.endLightbox = function(mode, box){ 4685 this._edit_stop_event(scheduler.getEvent(this._lightbox_id),mode); 4686 if (mode) 4687 scheduler.render_view_data(); 4688 this.hideCover(box); 4689 this._lightbox_id = null; // in case of custom lightbox user only calls endLightbox so we need to reset _lightbox_id 4690}; 4691scheduler.resetLightbox = function(){ 4692 if (scheduler._lightbox && !scheduler._custom_lightbox) 4693 scheduler._lightbox.parentNode.removeChild(scheduler._lightbox); 4694 scheduler._lightbox = null; 4695}; 4696scheduler.cancel_lightbox=function(){ 4697 this.callEvent("onEventCancel",[this._lightbox_id, this._new_event]);
4698 this.endLightbox(false); 4699 this.hide_lightbox(); 4700}; 4701scheduler._init_lightbox_events=function(){ 4702 this.getLightbox().onclick=function(e){ 4703 var src=e?e.target:event.srcElement; 4704 if (!src.className) src=src.previousSibling; 4705 if (src && src.className) 4706 switch(src.className){ 4707 case "dhx_save_btn": 4708 scheduler.save_lightbox(); 4709 break; 4710 case "dhx_delete_btn": 4711 var c=scheduler.locale.labels.confirm_deleting; 4712 4713 scheduler._dhtmlx_confirm(c, scheduler.locale.labels.title_confirm_deleting, function(){ 4714 scheduler.deleteEvent(scheduler._lightbox_id); 4715 scheduler._new_event = null; //clear flag, if it was unsaved event 4716 scheduler.hide_lightbox(); 4717 }); 4718 4719 break; 4720 case "dhx_cancel_btn": 4721 scheduler.cancel_lightbox(); 4722 break; 4723 4724 default: 4725 if (src.getAttribute("dhx_button")) { 4726 scheduler.callEvent("onLightboxButton", [src.className, src, e]); 4727 } else { 4728 var index, block, sec; 4729 if (src.className.indexOf("dhx_custom_button") != -1) { 4730 if (src.className.indexOf("dhx_custom_button_") != -1) { 4731 index = src.parentNode.getAttribute("index"); 4732 sec = src.parentNode.parentNode; 4733 } else { 4734 index = src.getAttribute("index"); 4735 sec = src.parentNode; 4736 src = src.firstChild; 4737 } 4738 } 4739 if (index) { 4740 block = scheduler.form_blocks[scheduler.config.lightbox.sections[index].type]; 4741 block.button_click(index, src, sec, sec.nextSibling); 4742 } 4743 } 4744 break; 4745 } 4746 }; 4747 this.getLightbox().onkeydown=function(e){ 4748 switch((e||event).keyCode){ 4749 case scheduler.keys.edit_save: 4750 if ((e||event).shiftKey) return; 4751 scheduler.save_lightbox(); 4752 break; 4753 case scheduler.keys.edit_cancel: 4754 scheduler.cancel_lightbox(); 4755 break; 4756 default: 4757 break; 4758 } 4759 }; 4760}; 4761scheduler.setLightboxSize=function(){ 4762 var d = this._lightbox; 4763 if (!d) return; 4764 4765 var con = d.childNodes[1]; 4766 con.style.height="0px"; 4767 con.style.height=con.scrollHeight+"px"; 4768 d.style.height=con.scrollHeight+scheduler.xy.lightbox_additional_height+"px"; 4769 con.style.height=con.scrollHeight+"px"; //it is incredible , how ugly IE can be 4770}; 4771 4772scheduler._init_dnd_events = function(){ 4773 dhtmlxEvent(document.body, "mousemove", scheduler._move_while_dnd); 4774 dhtmlxEvent(document.body, "mouseup", scheduler._finish_dnd); 4775 scheduler._init_dnd_events = function(){}; 4776}; 4777scheduler._move_while_dnd = function(e){ 4778 if (scheduler._dnd_start_lb){ 4779 if (!document.dhx_unselectable){ 4780 document.body.className += " dhx_unselectable"; 4781 document.dhx_unselectable = true; 4782 } 4783 var lb = scheduler.getLightbox(); 4784 var now = (e&&e.target)?[e.pageX, e.pageY]:[event.clientX, event.clientY]; 4785 lb.style.top = scheduler._lb_start[1]+now[1]-scheduler._dnd_start_lb[1]+"px"; 4786 lb.style.left = scheduler._lb_start[0]+now[0]-scheduler._dnd_start_lb[0]+"px"; 4787 } 4788}; 4789scheduler._ready_to_dnd = function(e){ 4790 var lb = scheduler.getLightbox(); 4791 scheduler._lb_start = [parseInt(lb.style.left,10), parseInt(lb.style.top,10)]; 4792 scheduler._dnd_start_lb = (e&&e.target)?[e.pageX, e.pageY]:[event.clientX, event.clientY]; 4793}; 4794scheduler._finish_dnd = function(){ 4795 if (scheduler._lb_start){ 4796 scheduler._lb_start = scheduler._dnd_start_lb = false; 4797 document.body.className = document.body.className.replace(" dhx_unselectable",""); 4798 document.dhx_unselectable = false; 4799 } 4800}; 4801scheduler.getLightbox=function(){ //scheduler.config.wide_form=true; 4802 if (!this._lightbox){ 4803 var d=document.createElement("DIV"); 4804 d.className="dhx_cal_light"; 4805 if (scheduler.config.wide_form) 4806 d.className+=" dhx_cal_light_wide"; 4807 if (scheduler.form_blocks.recurring) 4808 d.className+=" dhx_cal_light_rec"; 4809 4810 if (/msie|MSIE 6/.test(navigator.userAgent)) 4811 d.className+=" dhx_ie6"; 4812 d.style.visibility="hidden"; 4813 var html = this._lightbox_template; 4814 4815 var buttons = this.config.buttons_left; 4816 for (var i = 0; i < buttons.length; i++) 4817 html+="<div class='dhx_btn_set dhx_left_btn_set "+buttons[i]+"_set'><div dhx_button='1' class='"+buttons[i]+"'></div><div>"+scheduler.locale.labels[buttons[i]]+"</div></div>"; 4818 4819 buttons = this.config.buttons_right; 4820 for (var i = 0; i < buttons.length; i++) 4821 html+="<div class='dhx_btn_set dhx_right_btn_set "+buttons[i]+"_set' style='float:right;'><div dhx_button='1' class='"+buttons[i]+"'></div><div>"+scheduler.locale.labels[buttons[i]]+"</div></div>"; 4822 4823 html+="</div>"; 4824 d.innerHTML=html; 4825 if (scheduler.config.drag_lightbox){ 4826 d.firstChild.onmousedown = scheduler._ready_to_dnd;
4827 d.firstChild.onselectstart = function(){ return false; }; 4828 d.firstChild.style.cursor = "pointer"; 4829 scheduler._init_dnd_events(); 4830 4831 } 4832 document.body.insertBefore(d,document.body.firstChild); 4833 this._lightbox=d; 4834 4835 var sns=this.config.lightbox.sections; 4836 html=""; 4837 for (var i=0; i < sns.length; i++) { 4838 var block=this.form_blocks[sns[i].type]; 4839 if (!block) continue; //ignore incorrect blocks 4840 sns[i].id="area_"+this.uid(); 4841 var button = ""; 4842 if (sns[i].button){ 4843 button = "<div class='dhx_custom_button' index='"+i+"'><div class='dhx_custom_button_"+sns[i].button+"'></div><div>"+this.locale.labels["button_"+sns[i].button]+"</div></div>"; 4844 } 4845 4846 if (this.config.wide_form){ 4847 html+="<div class='dhx_wrap_section'>"; 4848 } 4849 html+="<div id='"+sns[i].id+"' class='dhx_cal_lsection'>"+button+this.locale.labels["section_"+sns[i].name]+"</div>"+block.render.call(this,sns[i]); 4850 html+="</div>" 4851 } 4852 4853 var ds=d.getElementsByTagName("div"); 4854 for (var i=0; i<ds.length; i++) { 4855 var t_ds = ds[i]; 4856 if (t_ds.className == "dhx_cal_larea") { 4857 t_ds.innerHTML = html; 4858 break; 4859 } 4860 } 4861 4862 //sizes 4863 this.setLightboxSize(); 4864 4865 this._init_lightbox_events(this); 4866 d.style.display="none"; 4867 d.style.visibility="visible"; 4868 } 4869 return this._lightbox; 4870}; 4871scheduler._lightbox_template="<div class='dhx_cal_ltitle'><span class='dhx_mark'> </span><span class='dhx_time'></span><span class='dhx_title'></span></div><div class='dhx_cal_larea'></div>"; 4872 4873scheduler._init_touch_events = function(){ 4874 if (this.config.touch != "force") 4875 this.config.touch = this.config.touch 4876 && ( (navigator.userAgent.indexOf("Mobile")!=-1) 4877 || (navigator.userAgent.indexOf("iPad")!=-1) 4878 || (navigator.userAgent.indexOf("Android")!=-1) 4879 || (navigator.userAgent.indexOf("Touch")!=-1)); 4880 4881 if (this.config.touch){ 4882 this.xy.scroll_width = 0; 4883 if (window.navigator.msPointerEnabled){ 4884 this._touch_events(["MSPointerMove", "MSPointerDown", "MSPointerUp"], function(ev){ 4885 if (ev.pointerType == ev.MSPOINTER_TYPE_MOUSE ) return null; 4886 return ev; 4887 }, function(ev){ 4888 return (!ev || ev.pointerType == ev.MSPOINTER_TYPE_MOUSE); 4889 }); 4890 } else 4891 this._touch_events(["touchmove", "touchstart", "touchend"], function(ev){ 4892 if (ev.touches && ev.touches.length > 1) return null; 4893 if (ev.touches[0]) 4894 return { target:ev.target, pageX:ev.touches[0].pageX, pageY:ev.touches[0].pageY }; 4895 else 4896 return ev; 4897 }, function(){ return false; }); 4898 } 4899}; 4900 4901scheduler._touch_events = function(names, accessor, ignore){ 4902 //webkit on android need to be handled separately 4903 var a_webkit = (navigator.userAgent.indexOf("Android")!=-1) && (navigator.userAgent.indexOf("WebKit")!=-1); 4904 var source, tracker, timer, drag_mode, scroll_mode, action_mode; 4905 var dblclicktime = 0; 4906 4907 function check_direction_swipe(s_ev, e_ev, step){ 4908 if (!s_ev || !e_ev) return; 4909 4910 var dy = Math.abs(s_ev.pageY - e_ev.pageY); 4911 var dx = Math.abs(s_ev.pageX - e_ev.pageX); 4912 if (dx>step && (!dy || (dx/dy > 3))){ 4913 if (s_ev.pageX > e_ev.pageX) 4914 scheduler._click.dhx_cal_next_button(); 4915 else 4916 scheduler._click.dhx_cal_prev_button(); 4917 } 4918 }; 4919 dhtmlxEvent(document.body, names[0], function(e){ 4920 if (ignore(e)) return; 4921 4922 if (drag_mode){ 4923 scheduler._on_mouse_move(accessor(e)); 4924 scheduler._update_global_tip(); 4925 if (e.preventDefault) 4926 e.preventDefault(); 4927 e.cancelBubble = true; 4928 return false; 4929 } 4930 4931 if (tracker && a_webkit){ 4932 check_direction_swipe(tracker, accessor(e), 0); 4933 } 4934 4935 tracker = accessor(e); 4936 //ignore common and scrolling moves 4937 if (!action_mode) return; 4938 4939 //multitouch 4940 if (!tracker){ 4941 scroll_mode = true; 4942 return; 4943 } 4944 4945 //target changed - probably in scroll mode 4946 4947 if (source.target != tracker.target || (Math.abs(source.pageX - tracker.pageX) > 5) || (Math.abs(source.pageY - tracker.pageY) > 5)){ 4948 scroll_mode = true; 4949 clearTimeout(timer); 4950 } 4951 4952 }); 4953 4954 dhtmlxEvent(this._els["dhx_cal_data"][0], "scroll", drag_cancel); 4955 dhtmlxEvent(this._els["dhx_cal_data"][0], "touchcancel", drag_cancel); 4956 dhtmlxEvent(this._els["dhx_cal_data"][0], "contextmenu", function(e){
4957 if (action_mode){ 4958 if (e && e.preventDefault) 4959 e.preventDefault(); 4960 (e||event).cancelBubble = true; 4961 return false; 4962 } 4963 }); 4964 dhtmlxEvent(this._els["dhx_cal_data"][0], names[1], function(e){ 4965 if (ignore(e)) return; 4966 4967 drag_mode = scroll_mode = tracker = false; 4968 action_mode = true; 4969 scheduler._temp_touch_block = true; 4970 4971 var fake_event = tracker = accessor(e); 4972 if (!fake_event){ 4973 scroll_mode = true; 4974 return; 4975 } 4976 4977 //dbl click 4978 var now = new Date(); 4979 4980 if (!scroll_mode && !drag_mode && now - dblclicktime < 250){ 4981 scheduler._click.dhx_cal_data(fake_event); 4982 window.setTimeout(function(){ 4983 scheduler._on_dbl_click(fake_event); 4984 }, 50); 4985 4986 if (e.preventDefault) 4987 e.preventDefault(); 4988 e.cancelBubble = true; 4989 scheduler._block_next_stop = true; 4990 return false; 4991 } 4992 dblclicktime = now; 4993 4994 //drag 4995 4996 if (scroll_mode || drag_mode || !scheduler.config.touch_drag) 4997 return; 4998 4999 //there is no target 5000 timer = setTimeout(function(){ 5001 drag_mode = true; 5002 var target = source.target; 5003 if (target && target.className && target.className.indexOf("dhx_body") != -1) 5004 target = target.previousSibling; 5005 5006 scheduler._on_mouse_down(source, target); 5007 if (scheduler._drag_mode && scheduler._drag_mode != "create"){ 5008 var pos = -1; 5009 scheduler.for_rendered(scheduler._drag_id, function(node, i) { 5010 pos = node.getBoundingClientRect().top; 5011 node.style.display='none'; 5012 scheduler._rendered.splice(i, 1); 5013 }); 5014 if (pos>=0){ 5015 var step = scheduler.config.time_step; 5016 scheduler._move_pos_shift = step* Math.round((fake_event.pageY - pos)*60/(scheduler.config.hour_size_px*step)); 5017 } 5018 } 5019 5020 if (scheduler.config.touch_tip) 5021 scheduler._show_global_tip(); 5022 scheduler._on_mouse_move(source); 5023 },scheduler.config.touch_drag); 5024 5025 source = fake_event; 5026 }); 5027 function drag_cancel(e){ 5028 if (ignore(e)) return; 5029 scheduler._hide_global_tip(); 5030 if (drag_mode){ 5031 scheduler._on_mouse_up( accessor(e||event) ); 5032 scheduler._temp_touch_block = false; 5033 } 5034 scheduler._drag_id = null; 5035 scheduler._drag_mode=null; 5036 scheduler._drag_pos=null; 5037 5038 clearTimeout(timer); 5039 drag_mode = scroll_mode = action_mode = false; 5040 } 5041 dhtmlxEvent(this._els["dhx_cal_data"][0], names[2], function(e){ 5042 if (ignore(e)) return; 5043 5044 if (!drag_mode) 5045 check_direction_swipe(source, tracker, 200);
5046 5047 if (drag_mode) 5048 scheduler._ignore_next_click = true; 5049 5050 drag_cancel(e); 5051 if (scheduler._block_next_stop){ 5052 scheduler._block_next_stop = false; 5053 if (e.preventDefault) 5054 e.preventDefault(); 5055 e.cancelBubble = true; 5056 return false; 5057 } 5058 }); 5059 5060 dhtmlxEvent(document.body, names[2], drag_cancel); 5061}; 5062 5063scheduler._show_global_tip = function(){ 5064 scheduler._hide_global_tip(); 5065 5066 var toptip = scheduler._global_tip = document.createElement("DIV"); 5067 toptip.className='dhx_global_tip'; 5068 5069 scheduler._update_global_tip(1); 5070 5071 document.body.appendChild(toptip); 5072}; 5073scheduler._update_global_tip = function(init){ 5074 var toptip = scheduler._global_tip; 5075 if (toptip){ 5076 var time = ""; 5077 if (scheduler._drag_id && !init){ 5078 var ev = scheduler.getEvent(scheduler._drag_id); 5079 if (ev) 5080 time = "<div>" + (ev._timed ? scheduler.templates.event_header(ev.start_date, ev.end_date, ev):scheduler.templates.day_date(ev.start_date, ev.end_date, ev)) + "</div>"; 5081 } 5082 5083 if (scheduler._drag_mode == "create" || scheduler._drag_mode == "new-size") 5084 toptip.innerHTML = (scheduler.locale.drag_to_create || "Drag to create")+time; 5085 else 5086 toptip.innerHTML = (scheduler.locale.drag_to_move || "Drag to move")+time; 5087 } 5088}; 5089scheduler._hide_global_tip = function(){ 5090 var toptip = scheduler._global_tip; 5091 if (toptip && toptip.parentNode){ 5092 toptip.parentNode.removeChild(toptip); 5093 scheduler._global_tip = 0; 5094 } 5095}; 5096 5097scheduler._dp_init=function(dp){ 5098 dp._methods=["setEventTextStyle","","changeEventId","deleteEvent"]; 5099 5100 this.attachEvent("onEventAdded",function(id){ 5101 if (!this._loading && this.validId(id)) 5102 dp.setUpdated(id,true,"inserted"); 5103 }); 5104 this.attachEvent("onConfirmedBeforeEventDelete", function(id){ 5105 if (!this.validId(id)) return; 5106 var z=dp.getState(id); 5107 5108 if (z=="inserted" || this._new_event) { dp.setUpdated(id,false); return true; } 5109 if (z=="deleted") return false; 5110 if (z=="true_deleted") return true; 5111 5112 dp.setUpdated(id,true,"deleted"); 5113 return false; 5114 }); 5115 this.attachEvent("onEventChanged",function(id){ 5116 if (!this._loading && this.validId(id)) 5117 dp.setUpdated(id,true,"updated"); 5118 }); 5119 5120 dp._getRowData=function(id,pref){ 5121 var ev=this.obj.getEvent(id); 5122 var data = {}; 5123 5124 for (var a in ev){ 5125 if (a.indexOf("_")==0) continue; 5126 if (ev[a] && ev[a].getUTCFullYear) //not very good, but will work 5127 data[a] = this.obj.templates.xml_format(ev[a]); 5128 else 5129 data[a] = ev[a]; 5130 } 5131 5132 return data; 5133 }; 5134 dp._clearUpdateFlag=function(){}; 5135 5136 dp.attachEvent("insertCallback", scheduler._update_callback); 5137 dp.attachEvent("updateCallback", scheduler._update_callback); 5138 dp.attachEvent("deleteCallback", function(upd, id) { 5139 this.obj.setUserData(id, this.action_param, "true_deleted"); 5140 this.obj.deleteEvent(id); 5141 }); 5142 5143}; 5144 5145 5146scheduler.setUserData=function(id,name,value){ 5147 if (id) 5148 this.getEvent(id)[name]=value; 5149 else 5150 this._userdata[name]=value; 5151}; 5152scheduler.getUserData=function(id,name){ 5153 return id?this.getEvent(id)[name]:this._userdata[name]; 5154}; 5155scheduler.setEventTextStyle=function(id,style){ 5156 this.for_rendered(id,function(r){ 5157 r.style.cssText+=";"+style; 5158 }); 5159 var ev = this.getEvent(id); 5160 ev["_text_style"]=style; 5161 this.event_updated(ev); 5162}; 5163scheduler.validId=function(id){ 5164 return true; 5165}; 5166 5167scheduler._update_callback = function(upd,id){ 5168 var data = scheduler.xmlNodeToJSON(upd.firstChild); 5169 data.text = data.text||data._tagvalue; 5170 data.start_date = scheduler.templates.xml_date(data.start_date); 5171 data.end_date = scheduler.templates.xml_date(data.end_date); 5172 5173 scheduler.addEvent(data); 5174};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.