reservation plugin - unbound request (unclean
[unfold.git] / portal / static / unbound_reservation_static / src / renderers-vml.js
1 /*
2  * jsPlumb
3  * 
4  * Title:jsPlumb 1.5.5
5  * 
6  * Provides a way to visually connect elements on an HTML page, using either SVG, Canvas
7  * elements, or VML.  
8  * 
9  * This file contains the VML renderers.
10  *
11  * Copyright (c) 2010 - 2013 Simon Porritt (http://jsplumb.org)
12  * 
13  * http://jsplumb.org
14  * http://github.com/sporritt/jsplumb
15  * http://code.google.com/p/jsplumb
16  * 
17  * Dual licensed under the MIT and GPL2 licenses.
18  */
19
20 ;(function() {
21         
22         // http://ajaxian.com/archives/the-vml-changes-in-ie-8
23         // http://www.nczonline.net/blog/2010/01/19/internet-explorer-8-document-and-browser-modes/
24         // http://www.louisremi.com/2009/03/30/changes-in-vml-for-ie8-or-what-feature-can-the-ie-dev-team-break-for-you-today/
25         
26         var vmlAttributeMap = {
27                 "stroke-linejoin":"joinstyle",
28                 "joinstyle":"joinstyle",                
29                 "endcap":"endcap",
30                 "miterlimit":"miterlimit"
31         },
32         jsPlumbStylesheet = null;
33         
34         if (document.createStyleSheet && document.namespaces) {                 
35                 
36                 var ruleClasses = [
37                                 ".jsplumb_vml", "jsplumb\\:textbox", "jsplumb\\:oval", "jsplumb\\:rect", 
38                                 "jsplumb\\:stroke", "jsplumb\\:shape", "jsplumb\\:group"
39                         ],
40                         rule = "behavior:url(#default#VML);position:absolute;";
41
42                 jsPlumbStylesheet = document.createStyleSheet();
43
44                 for (var i = 0; i < ruleClasses.length; i++)
45                         jsPlumbStylesheet.addRule(ruleClasses[i], rule);
46
47                 // in this page it is also mentioned that IE requires the extra arg to the namespace
48                 // http://www.louisremi.com/2009/03/30/changes-in-vml-for-ie8-or-what-feature-can-the-ie-dev-team-break-for-you-today/
49                 // but someone commented saying they didn't need it, and it seems jsPlumb doesnt need it either.
50                 // var iev = document.documentMode;
51                 //if (!iev || iev < 8)
52                         document.namespaces.add("jsplumb", "urn:schemas-microsoft-com:vml");
53                 //else
54                 //      document.namespaces.add("jsplumb", "urn:schemas-microsoft-com:vml", "#default#VML");
55         }
56         
57         jsPlumb.vml = {};
58         
59         var scale = 1000,
60
61     _groupMap = {},
62     _getGroup = function(container, connectorClass) {
63         var id = jsPlumb.getId(container),
64             g = _groupMap[id];
65         if(!g) {
66             g = _node("group", [0,0,scale, scale], {"class":connectorClass});
67             //g.style.position=absolute;
68             //g["coordsize"] = "1000,1000";
69             g.style.backgroundColor="red";
70             _groupMap[id] = g;
71             //jsPlumb.appendElement(g, container);  // todo if this gets reinstated, remember to use the current jsplumb instance.
72             //jsPlumb.CurrentLibrary.getDOMElement(container).appendChild(g);
73             //document.body.appendChild(g);
74         }
75         return g;
76     },
77         _atts = function(o, atts) {
78                 for (var i in atts) { 
79                         // IE8 fix: setattribute does not work after an element has been added to the dom!
80                         // http://www.louisremi.com/2009/03/30/changes-in-vml-for-ie8-or-what-feature-can-the-ie-dev-team-break-for-you-today/
81                         //o.setAttribute(i, atts[i]);
82
83                         /*There is an additional problem when accessing VML elements by using get/setAttribute. The simple solution is following:
84
85                         if (document.documentMode==8) {
86                         ele.opacity=1;
87                         } else {
88                         ele.setAttribute(‘opacity’,1);
89                         }
90                         */
91
92                         o[i] = atts[i];
93                 }
94         },
95         _node = function(name, d, atts, parent, _jsPlumb, deferToJsPlumbContainer) {
96                 atts = atts || {};
97                 var o = document.createElement("jsplumb:" + name);
98                 if (deferToJsPlumbContainer)
99                         _jsPlumb.appendElement(o, parent);
100                 else
101                         jsPlumb.CurrentLibrary.appendElement(o, parent);
102                 o.className = (atts["class"] ? atts["class"] + " " : "") + "jsplumb_vml";
103                 _pos(o, d);
104                 _atts(o, atts);
105                 return o;
106         },
107         _pos = function(o,d, zIndex) {
108                 o.style.left = d[0] + "px";             
109                 o.style.top =  d[1] + "px";
110                 o.style.width= d[2] + "px";
111                 o.style.height= d[3] + "px";
112                 o.style.position = "absolute";
113                 if (zIndex)
114                         o.style.zIndex = zIndex;
115         },
116         _conv = jsPlumb.vml.convertValue = function(v) {
117                 return Math.floor(v * scale);
118         },      
119         // tests if the given style is "transparent" and then sets the appropriate opacity node to 0 if so,
120         // or 1 if not.  TODO in the future, support variable opacity.
121         _maybeSetOpacity = function(styleToWrite, styleToCheck, type, component) {
122                 if ("transparent" === styleToCheck)
123                         component.setOpacity(type, "0.0");
124                 else
125                         component.setOpacity(type, "1.0");
126         },
127         _applyStyles = function(node, style, component, _jsPlumb) {
128                 var styleToWrite = {};
129                 if (style.strokeStyle) {
130                         styleToWrite.stroked = "true";
131                         var strokeColor = jsPlumbUtil.convertStyle(style.strokeStyle, true);
132                         styleToWrite.strokecolor = strokeColor;
133                         _maybeSetOpacity(styleToWrite, strokeColor, "stroke", component);
134                         styleToWrite.strokeweight = style.lineWidth + "px";
135                 }
136                 else styleToWrite.stroked = "false";
137                 
138                 if (style.fillStyle) {
139                         styleToWrite.filled = "true";
140                         var fillColor = jsPlumbUtil.convertStyle(style.fillStyle, true);
141                         styleToWrite.fillcolor = fillColor;
142                         _maybeSetOpacity(styleToWrite, fillColor, "fill", component);
143                 }
144                 else styleToWrite.filled = "false";
145                 
146                 if(style.dashstyle) {
147                         if (component.strokeNode == null) {
148                                 component.strokeNode = _node("stroke", [0,0,0,0], { dashstyle:style.dashstyle }, node, _jsPlumb);                               
149                         }
150                         else
151                                 component.strokeNode.dashstyle = style.dashstyle;
152                 }                                       
153                 else if (style["stroke-dasharray"] && style.lineWidth) {
154                         var sep = style["stroke-dasharray"].indexOf(",") == -1 ? " " : ",",
155                         parts = style["stroke-dasharray"].split(sep),
156                         styleToUse = "";
157                         for(var i = 0; i < parts.length; i++) {
158                                 styleToUse += (Math.floor(parts[i] / style.lineWidth) + sep);
159                         }
160                         if (component.strokeNode == null) {
161                                 component.strokeNode = _node("stroke", [0,0,0,0], { dashstyle:styleToUse }, node, _jsPlumb);                            
162                         }
163                         else
164                                 component.strokeNode.dashstyle = styleToUse;
165                 }
166                 
167                 _atts(node, styleToWrite);
168         },
169         /*
170          * Base class for Vml endpoints and connectors. Extends jsPlumbUIComponent. 
171          */
172         VmlComponent = function() {                             
173                 var self = this, renderer = {};
174                 jsPlumb.jsPlumbUIComponent.apply(this, arguments);      
175
176                 this.opacityNodes = {
177                         "stroke":null,
178                         "fill":null
179                 };
180                 this.initOpacityNodes = function(vml) {
181                         self.opacityNodes.stroke = _node("stroke", [0,0,1,1], {opacity:"0.0"}, vml, self._jsPlumb.instance);
182                         self.opacityNodes.fill = _node("fill", [0,0,1,1], {opacity:"0.0"}, vml, self._jsPlumb.instance);                                                        
183                 };
184                 this.setOpacity = function(type, value) {
185                         var node = self.opacityNodes[type];
186                         if (node) node.opacity = "" + value;
187                 };
188                 var displayElements = [ ];
189                 this.getDisplayElements = function() { 
190                         return displayElements; 
191                 };
192                 
193                 this.appendDisplayElement = function(el, doNotAppendToCanvas) {
194                         if (!doNotAppendToCanvas) self.canvas.parentNode.appendChild(el);
195                         displayElements.push(el);
196                 };
197         };
198         jsPlumbUtil.extend(VmlComponent, jsPlumb.jsPlumbUIComponent, {
199                 cleanup:function() {                    
200                         if (this.bgCanvas) jsPlumbUtil.removeElement(this.bgCanvas);
201                         jsPlumbUtil.removeElement(this.canvas);                                         
202                 }
203         });
204
205         /*
206          * Base class for Vml connectors. extends VmlComponent.
207          */
208         var VmlConnector = jsPlumb.ConnectorRenderers.vml = function(params) {          
209                 this.strokeNode = null;
210                 this.canvas = null;
211                 VmlComponent.apply(this, arguments);
212                 var clazz = this._jsPlumb.instance.connectorClass + (params.cssClass ? (" " + params.cssClass) : "");
213                 this.paint = function(style) {          
214                         if (style !== null) {                   
215
216                                 // we need to be at least 1 pixel in each direction, because otherwise coordsize gets set to
217                                 // 0 and overlays cannot paint.
218                                 this.w = Math.max(this.w, 1);
219                                 this.h = Math.max(this.h, 1);
220
221                                 var segments = this.getSegments(), p = { "path":"" },
222                     d = [this.x, this.y, this.w, this.h];
223                                 
224                                 // create path from segments.   
225                                 for (var i = 0; i < segments.length; i++) {
226                                         p.path += jsPlumb.Segments.vml.SegmentRenderer.getPath(segments[i]);
227                                         p.path += " ";
228                                 }
229
230                 //*
231                                 if (style.outlineColor) {
232                                         var outlineWidth = style.outlineWidth || 1,
233                                         outlineStrokeWidth = style.lineWidth + (2 * outlineWidth),
234                                         outlineStyle = {
235                                                 strokeStyle : jsPlumbUtil.convertStyle(style.outlineColor),
236                                                 lineWidth : outlineStrokeWidth
237                                         };
238                                         for (var aa in vmlAttributeMap) outlineStyle[aa] = style[aa];
239                                         
240                                         if (this.bgCanvas == null) {                                            
241                                                 p["class"] = clazz;
242                                                 p.coordsize = (d[2] * scale) + "," + (d[3] * scale);
243                                                 this.bgCanvas = _node("shape", d, p, params.parent, this._jsPlumb.instance, true);                                              
244                                                 _pos(this.bgCanvas, d);
245                                                 this.appendDisplayElement(this.bgCanvas, true); 
246                                                 this.attachListeners(this.bgCanvas, this);                                      
247                                                 this.initOpacityNodes(this.bgCanvas, ["stroke"]);               
248                                         }
249                                         else {
250                                                 p.coordsize = (d[2] * scale) + "," + (d[3] * scale);
251                                                 _pos(this.bgCanvas, d);
252                                                 _atts(this.bgCanvas, p);
253                                         }
254                                         
255                                         _applyStyles(this.bgCanvas, outlineStyle, this);
256                                 }
257                                 //*/
258                                 
259                                 if (this.canvas == null) {                                                                              
260                                         p["class"] = clazz;
261                                         p.coordsize = (d[2] * scale) + "," + (d[3] * scale);                                    
262                                         this.canvas = _node("shape", d, p, params.parent, this._jsPlumb.instance, true);                                                        
263                     //var group = _getGroup(params.parent);                   // test of append everything to a group
264                     //group.appendChild(self.canvas);                           // sort of works but not exactly;
265                                         //params["_jsPlumb"].appendElement(self.canvas, params.parent);    //before introduction of groups
266
267                                         this.appendDisplayElement(this.canvas, true);                                                                           
268                                         this.attachListeners(this.canvas, this);                                        
269                                         this.initOpacityNodes(this.canvas, ["stroke"]);         
270                                 }
271                                 else {
272                                         p.coordsize = (d[2] * scale) + "," + (d[3] * scale);
273                                         _pos(this.canvas, d);
274                                         _atts(this.canvas, p);
275                                 }
276                                 
277                                 _applyStyles(this.canvas, style, this, this._jsPlumb.instance);
278                         }
279                 };      
280                                 
281         };
282         jsPlumbUtil.extend(VmlConnector, VmlComponent, {
283                 reattachListeners : function() {
284                         if (this.canvas) this.reattachListenersForElement(this.canvas, this);
285                 },
286                 setVisible:function(v) {
287                         if (this.canvas) {
288                                 this.canvas.style.display = v ? "block" : "none";
289                         }
290                         if (this.bgCanvas) {
291                                 this.bgCanvas.style.display = v ? "block" : "none";
292                         }
293                 }
294         });     
295         
296         /*
297          * 
298          * Base class for Vml Endpoints. extends VmlComponent.
299          * 
300          */
301         var VmlEndpoint = window.VmlEndpoint = function(params) {
302                 VmlComponent.apply(this, arguments);
303                 this._jsPlumb.vml = null;//, opacityStrokeNode = null, opacityFillNode = null;
304                 this.canvas = document.createElement("div");
305                 this.canvas.style.position = "absolute";
306                 this._jsPlumb.clazz = this._jsPlumb.instance.endpointClass + (params.cssClass ? (" " + params.cssClass) : "");
307
308                 // TODO vml endpoint adds class to VML at constructor time.  but the addClass method adds VML
309                 // to the enclosing DIV. what to do?  seems like it would be better to just target the div.
310                 // HOWEVER...vml connection has no containing div.  why not? it feels like it should.
311
312                 //var group = _getGroup(params.parent);
313         //group.appendChild(self.canvas);
314                 params._jsPlumb.appendElement(this.canvas, params.parent);
315
316                 this.paint = function(style, anchor) {
317                         var p = { }, vml = this._jsPlumb.vml;                           
318                         
319                         jsPlumbUtil.sizeElement(this.canvas, this.x, this.y, this.w, this.h);
320                         if (this._jsPlumb.vml == null) {
321                                 p["class"] = this._jsPlumb.clazz;
322                                 vml = this._jsPlumb.vml = this.getVml([0,0, this.w, this.h], p, anchor, this.canvas, this._jsPlumb.instance);                           
323                                 this.attachListeners(vml, this);
324
325                                 this.appendDisplayElement(vml, true);
326                                 this.appendDisplayElement(this.canvas, true);
327                                 
328                                 this.initOpacityNodes(vml, ["fill"]);                   
329                         }
330                         else {                          
331                                 _pos(vml, [0,0, this.w, this.h]);
332                                 _atts(vml, p);
333                         }
334                         
335                         _applyStyles(vml, style, this);
336                 };              
337         };
338         jsPlumbUtil.extend(VmlEndpoint, VmlComponent, {
339                 reattachListeners : function() {
340                         if (this._jsPlumb.vml) this.reattachListenersForElement(this._jsPlumb.vml, this);
341                 }
342         });
343         
344 // ******************************* vml segments *****************************************************   
345                 
346         jsPlumb.Segments.vml = {
347                 SegmentRenderer : {             
348                         getPath : function(segment) {
349                                 return ({
350                                         "Straight":function(segment) {
351                                                 var d = segment.params;
352                                                 return "m" + _conv(d.x1) + "," + _conv(d.y1) + " l" + _conv(d.x2) + "," + _conv(d.y2) + " e";
353                                         },
354                                         "Bezier":function(segment) {
355                                                 var d = segment.params;
356                                                 return "m" + _conv(d.x1) + "," + _conv(d.y1) + 
357                                                         " c" + _conv(d.cp1x) + "," + _conv(d.cp1y) + "," + _conv(d.cp2x) + "," + _conv(d.cp2y) + "," + _conv(d.x2) + "," + _conv(d.y2) + " e";
358                                         },
359                                         "Arc":function(segment) {                                       
360                                                 var d = segment.params,
361                                                         xmin = Math.min(d.x1, d.x2),
362                                                         xmax = Math.max(d.x1, d.x2),
363                                                         ymin = Math.min(d.y1, d.y2),
364                                                         ymax = Math.max(d.y1, d.y2),                                                                                                            
365                                                         sf = segment.anticlockwise ? 1 : 0,
366                                                         pathType = (segment.anticlockwise ? "at " : "wa "),
367                                                         makePosString = function() {
368                                                                 if (d.loopback)
369                                                                         return "0,0," + _conv(2*d.r) + "," + _conv(2 * d.r);
370
371                                                                 var xy = [
372                                                                                 null,
373                                                                                 [ function() { return [xmin, ymin ];}, function() { return [xmin - d.r, ymin - d.r ];}],
374                                                                                 [ function() { return [xmin - d.r, ymin ];}, function() { return [xmin, ymin - d.r ];}],
375                                                                                 [ function() { return [xmin - d.r, ymin - d.r ];}, function() { return [xmin, ymin ];}],
376                                                                                 [ function() { return [xmin, ymin - d.r ];}, function() { return [xmin - d.r, ymin ];}]
377                                                                         ][segment.segment][sf]();
378
379                                                                 return _conv(xy[0]) + "," + _conv(xy[1]) + "," + _conv(xy[0] + (2*d.r)) + "," + _conv(xy[1] + (2*d.r));
380                                                         };
381
382                                                 return pathType + " " + makePosString() + "," + _conv(d.x1) + "," + _conv(d.y1) + "," + _conv(d.x2) + "," + _conv(d.y2) + " e";                                                                                         
383                                         }
384                                                 
385                                 })[segment.type](segment);      
386                         }
387                 }
388         };
389         
390 // ******************************* /vml segments *****************************************************  
391
392 // ******************************* vml endpoints *****************************************************
393         
394         jsPlumb.Endpoints.vml.Dot = function() {
395                 jsPlumb.Endpoints.Dot.apply(this, arguments);
396                 VmlEndpoint.apply(this, arguments);
397                 this.getVml = function(d, atts, anchor, parent, _jsPlumb) { return _node("oval", d, atts, parent, _jsPlumb); };
398         };
399         jsPlumbUtil.extend(jsPlumb.Endpoints.vml.Dot, VmlEndpoint);
400         
401         jsPlumb.Endpoints.vml.Rectangle = function() {
402                 jsPlumb.Endpoints.Rectangle.apply(this, arguments);
403                 VmlEndpoint.apply(this, arguments);
404                 this.getVml = function(d, atts, anchor, parent, _jsPlumb) { return _node("rect", d, atts, parent, _jsPlumb); };
405         };
406         jsPlumbUtil.extend(jsPlumb.Endpoints.vml.Rectangle, VmlEndpoint);
407         
408         /*
409          * VML Image Endpoint is the same as the default image endpoint.
410          */
411         jsPlumb.Endpoints.vml.Image = jsPlumb.Endpoints.Image;
412         
413         /**
414          * placeholder for Blank endpoint in vml renderer.
415          */
416         jsPlumb.Endpoints.vml.Blank = jsPlumb.Endpoints.Blank;
417         
418 // ******************************* /vml endpoints ***************************************************** 
419
420 // ******************************* vml overlays *****************************************************
421         
422         /**
423          * VML Label renderer. uses the default label renderer (which adds an element to the DOM)
424          */
425         jsPlumb.Overlays.vml.Label  = jsPlumb.Overlays.Label;
426         
427         /**
428          * VML Custom renderer. uses the default Custom renderer (which adds an element to the DOM)
429          */
430         jsPlumb.Overlays.vml.Custom = jsPlumb.Overlays.Custom;
431         
432         /**
433          * Abstract VML arrow superclass
434          */
435         var AbstractVmlArrowOverlay = function(superclass, originalArgs) {
436         superclass.apply(this, originalArgs);
437         VmlComponent.apply(this, originalArgs);
438         var self = this, path = null;
439         self.canvas = null; 
440         self.isAppendedAtTopLevel = true;
441         var getPath = function(d) {             
442                 return "m " + _conv(d.hxy.x) + "," + _conv(d.hxy.y) +
443                        " l " + _conv(d.tail[0].x) + "," + _conv(d.tail[0].y) + 
444                        " " + _conv(d.cxy.x) + "," + _conv(d.cxy.y) + 
445                        " " + _conv(d.tail[1].x) + "," + _conv(d.tail[1].y) + 
446                        " x e";
447         };
448         this.paint = function(params, containerExtents) {
449                 // only draws for connectors, not endpoints.
450                 if (params.component.canvas && containerExtents) {
451                         var p = {}, d = params.d, connector = params.component;
452                                 if (params.strokeStyle) {
453                                         p.stroked = "true";
454                                         p.strokecolor = jsPlumbUtil.convertStyle(params.strokeStyle, true);                             
455                                 }
456                                 if (params.lineWidth) p.strokeweight = params.lineWidth + "px";
457                                 if (params.fillStyle) {
458                                         p.filled = "true";
459                                         p.fillcolor = params.fillStyle;
460                                 }                       
461
462                                 var xmin = Math.min(d.hxy.x, d.tail[0].x, d.tail[1].x, d.cxy.x),
463                                         ymin = Math.min(d.hxy.y, d.tail[0].y, d.tail[1].y, d.cxy.y),
464                                         xmax = Math.max(d.hxy.x, d.tail[0].x, d.tail[1].x, d.cxy.x),
465                                         ymax = Math.max(d.hxy.y, d.tail[0].y, d.tail[1].y, d.cxy.y),
466                                         w = Math.abs(xmax - xmin),
467                                         h = Math.abs(ymax - ymin),
468                                         dim = [xmin, ymin, w, h];
469
470                                 // for VML, we create overlays using shapes that have the same dimensions and
471                                 // coordsize as their connector - overlays calculate themselves relative to the
472                                 // connector (it's how it's been done since the original canvas implementation, because
473                                 // for canvas that makes sense).
474                                 p.path = getPath(d);
475                                 p.coordsize = (connector.w * scale) + "," + (connector.h * scale);                      
476                                 
477                                 dim[0] = connector.x;
478                                 dim[1] = connector.y;
479                                 dim[2] = connector.w;
480                                 dim[3] = connector.h;
481                                 
482                         if (self.canvas == null) {
483                                 var overlayClass = connector._jsPlumb.overlayClass || "";
484                                 var clazz = originalArgs && (originalArgs.length == 1) ? (originalArgs[0].cssClass || "") : "";
485                                 p["class"] = clazz + " " + overlayClass;
486                                         self.canvas = _node("shape", dim, p, connector.canvas.parentNode, connector._jsPlumb.instance, true);                                                           
487                                         connector.appendDisplayElement(self.canvas, true);
488                                         self.attachListeners(self.canvas, connector);
489                                         self.attachListeners(self.canvas, self);
490                                 }
491                                 else {                          
492                                         _pos(self.canvas, dim);
493                                         _atts(self.canvas, p);
494                                 }               
495                         }
496         };
497         
498         this.reattachListeners = function() {
499                         if (self.canvas) self.reattachListenersForElement(self.canvas, self);
500                 };
501
502                 this.cleanup = function() {
503                 if (self.canvas != null) jsPlumb.CurrentLibrary.removeElement(self.canvas);
504         };
505     };
506     jsPlumbUtil.extend(AbstractVmlArrowOverlay, [VmlComponent, jsPlumb.Overlays.AbstractOverlay], {
507         setVisible : function(state) {
508             this.canvas.style.display = state ? "block" : "none";
509         }
510     });
511         
512         jsPlumb.Overlays.vml.Arrow = function() {
513         AbstractVmlArrowOverlay.apply(this, [jsPlumb.Overlays.Arrow, arguments]);       
514     };
515     jsPlumbUtil.extend(jsPlumb.Overlays.vml.Arrow, [ jsPlumb.Overlays.Arrow, AbstractVmlArrowOverlay ]);
516     
517     jsPlumb.Overlays.vml.PlainArrow = function() {
518         AbstractVmlArrowOverlay.apply(this, [jsPlumb.Overlays.PlainArrow, arguments]);          
519     };
520     jsPlumbUtil.extend(jsPlumb.Overlays.vml.PlainArrow, [ jsPlumb.Overlays.PlainArrow, AbstractVmlArrowOverlay ]);
521     
522     jsPlumb.Overlays.vml.Diamond = function() {
523         AbstractVmlArrowOverlay.apply(this, [jsPlumb.Overlays.Diamond, arguments]);     
524     };
525     jsPlumbUtil.extend(jsPlumb.Overlays.vml.Diamond, [ jsPlumb.Overlays.Diamond, AbstractVmlArrowOverlay ]);
526     
527 // ******************************* /vml overlays *****************************************************    
528     
529 })();