Version 3.18.1
Show:

File: graphics/js/VMLGraphic.js

  1. /**
  2. * <a href="http://www.w3.org/TR/NOTE-VML">VML</a> implementation of the <a href="Graphic.html">`Graphic`</a> class.
  3. * `VMLGraphic` is not intended to be used directly. Instead, use the <a href="Graphic.html">`Graphic`</a> class.
  4. * If the browser lacks <a href="http://www.w3.org/TR/SVG/">SVG</a> and <a href="http://www.w3.org/TR/html5/the-canvas-element.html">Canvas</a>
  5. * capabilities, the <a href="Graphic.html">`Graphic`</a> class will point to the `VMLGraphic` class.
  6. *
  7. * @module graphics
  8. * @class VMLGraphic
  9. * @constructor
  10. */
  11. VMLGraphic = function() {
  12. VMLGraphic.superclass.constructor.apply(this, arguments);
  13. };
  14. VMLGraphic.NAME = "vmlGraphic";
  15. VMLGraphic.ATTRS = {
  16. /**
  17. * Whether or not to render the `Graphic` automatically after to a specified parent node after init. This can be a Node
  18. * instance or a CSS selector string.
  19. *
  20. * @config render
  21. * @type Node | String
  22. */
  23. render: {},
  24. /**
  25. * Unique id for class instance.
  26. *
  27. * @config id
  28. * @type String
  29. */
  30. id: {
  31. valueFn: function()
  32. {
  33. return Y.guid();
  34. },
  35. setter: function(val)
  36. {
  37. var node = this._node;
  38. if(node)
  39. {
  40. node.setAttribute("id", val);
  41. }
  42. return val;
  43. }
  44. },
  45. /**
  46. * Key value pairs in which a shape instance is associated with its id.
  47. *
  48. * @config shapes
  49. * @type Object
  50. * @readOnly
  51. */
  52. shapes: {
  53. readOnly: true,
  54. getter: function()
  55. {
  56. return this._shapes;
  57. }
  58. },
  59. /**
  60. * Object containing size and coordinate data for the content of a Graphic in relation to the coordSpace node.
  61. *
  62. * @config contentBounds
  63. * @type Object
  64. */
  65. contentBounds: {
  66. readOnly: true,
  67. getter: function()
  68. {
  69. return this._contentBounds;
  70. }
  71. },
  72. /**
  73. * The html element that represents to coordinate system of the Graphic instance.
  74. *
  75. * @config node
  76. * @type HTMLElement
  77. */
  78. node: {
  79. readOnly: true,
  80. getter: function()
  81. {
  82. return this._node;
  83. }
  84. },
  85. /**
  86. * Indicates the width of the `Graphic`.
  87. *
  88. * @config width
  89. * @type Number
  90. */
  91. width: {
  92. setter: function(val)
  93. {
  94. if(this._node)
  95. {
  96. this._node.style.width = val + "px";
  97. }
  98. return val;
  99. }
  100. },
  101. /**
  102. * Indicates the height of the `Graphic`.
  103. *
  104. * @config height
  105. * @type Number
  106. */
  107. height: {
  108. setter: function(val)
  109. {
  110. if(this._node)
  111. {
  112. this._node.style.height = val + "px";
  113. }
  114. return val;
  115. }
  116. },
  117. /**
  118. * Determines the sizing of the Graphic.
  119. *
  120. * <dl>
  121. * <dt>sizeContentToGraphic</dt><dd>The Graphic's width and height attributes are, either explicitly set through the
  122. * <code>width</code> and <code>height</code> attributes or are determined by the dimensions of the parent element. The
  123. * content contained in the Graphic will be sized to fit with in the Graphic instance's dimensions. When using this
  124. * setting, the <code>preserveAspectRatio</code> attribute will determine how the contents are sized.</dd>
  125. * <dt>sizeGraphicToContent</dt><dd>(Also accepts a value of true) The Graphic's width and height are determined by the
  126. * size and positioning of the content.</dd>
  127. * <dt>false</dt><dd>The Graphic's width and height attributes are, either explicitly set through the <code>width</code>
  128. * and <code>height</code> attributes or are determined by the dimensions of the parent element. The contents of the
  129. * Graphic instance are not affected by this setting.</dd>
  130. * </dl>
  131. *
  132. *
  133. * @config autoSize
  134. * @type Boolean | String
  135. * @default false
  136. */
  137. autoSize: {
  138. value: false
  139. },
  140. /**
  141. * Determines how content is sized when <code>autoSize</code> is set to <code>sizeContentToGraphic</code>.
  142. *
  143. * <dl>
  144. * <dt>none<dt><dd>Do not force uniform scaling. Scale the graphic content of the given element non-uniformly if necessary
  145. * such that the element's bounding box exactly matches the viewport rectangle.</dd>
  146. * <dt>xMinYMin</dt><dd>Force uniform scaling position along the top left of the Graphic's node.</dd>
  147. * <dt>xMidYMin</dt><dd>Force uniform scaling horizontally centered and positioned at the top of the Graphic's node.<dd>
  148. * <dt>xMaxYMin</dt><dd>Force uniform scaling positioned horizontally from the right and vertically from the top.</dd>
  149. * <dt>xMinYMid</dt>Force uniform scaling positioned horizontally from the left and vertically centered.</dd>
  150. * <dt>xMidYMid (the default)</dt><dd>Force uniform scaling with the content centered.</dd>
  151. * <dt>xMaxYMid</dt><dd>Force uniform scaling positioned horizontally from the right and vertically centered.</dd>
  152. * <dt>xMinYMax</dt><dd>Force uniform scaling positioned horizontally from the left and vertically from the bottom.</dd>
  153. * <dt>xMidYMax</dt><dd>Force uniform scaling horizontally centered and position vertically from the bottom.</dd>
  154. * <dt>xMaxYMax</dt><dd>Force uniform scaling positioned horizontally from the right and vertically from the bottom.</dd>
  155. * </dl>
  156. *
  157. * @config preserveAspectRatio
  158. * @type String
  159. * @default xMidYMid
  160. */
  161. preserveAspectRatio: {
  162. value: "xMidYMid"
  163. },
  164. /**
  165. * The contentBounds will resize to greater values but not values. (for performance)
  166. * When resizing the contentBounds down is desirable, set the resizeDown value to true.
  167. *
  168. * @config resizeDown
  169. * @type Boolean
  170. */
  171. resizeDown: {
  172. resizeDown: false
  173. },
  174. /**
  175. * Indicates the x-coordinate for the instance.
  176. *
  177. * @config x
  178. * @type Number
  179. */
  180. x: {
  181. getter: function()
  182. {
  183. return this._x;
  184. },
  185. setter: function(val)
  186. {
  187. this._x = val;
  188. if(this._node)
  189. {
  190. this._node.style.left = val + "px";
  191. }
  192. return val;
  193. }
  194. },
  195. /**
  196. * Indicates the y-coordinate for the instance.
  197. *
  198. * @config y
  199. * @type Number
  200. */
  201. y: {
  202. getter: function()
  203. {
  204. return this._y;
  205. },
  206. setter: function(val)
  207. {
  208. this._y = val;
  209. if(this._node)
  210. {
  211. this._node.style.top = val + "px";
  212. }
  213. return val;
  214. }
  215. },
  216. /**
  217. * Indicates whether or not the instance will automatically redraw after a change is made to a shape.
  218. * This property will get set to false when batching operations.
  219. *
  220. * @config autoDraw
  221. * @type Boolean
  222. * @default true
  223. * @private
  224. */
  225. autoDraw: {
  226. value: true
  227. },
  228. visible: {
  229. value: true,
  230. setter: function(val)
  231. {
  232. this._toggleVisible(val);
  233. return val;
  234. }
  235. }
  236. };
  237. Y.extend(VMLGraphic, Y.GraphicBase, {
  238. /**
  239. * Sets the value of an attribute.
  240. *
  241. * @method set
  242. * @param {String|Object} name The name of the attribute. Alternatively, an object of key value pairs can
  243. * be passed in to set multiple attributes at once.
  244. * @param {Any} value The value to set the attribute to. This value is ignored if an object is received as
  245. * the name param.
  246. */
  247. set: function()
  248. {
  249. var host = this,
  250. attr = arguments[0],
  251. redrawAttrs = {
  252. autoDraw: true,
  253. autoSize: true,
  254. preserveAspectRatio: true,
  255. resizeDown: true
  256. },
  257. key,
  258. forceRedraw = false;
  259. AttributeLite.prototype.set.apply(host, arguments);
  260. if(host._state.autoDraw === true && Y.Object.size(this._shapes) > 0)
  261. {
  262. if(Y_LANG.isString && redrawAttrs[attr])
  263. {
  264. forceRedraw = true;
  265. }
  266. else if(Y_LANG.isObject(attr))
  267. {
  268. for(key in redrawAttrs)
  269. {
  270. if(redrawAttrs.hasOwnProperty(key) && attr[key])
  271. {
  272. forceRedraw = true;
  273. break;
  274. }
  275. }
  276. }
  277. }
  278. if(forceRedraw)
  279. {
  280. host._redraw();
  281. }
  282. },
  283. /**
  284. * Storage for `x` attribute.
  285. *
  286. * @property _x
  287. * @type Number
  288. * @private
  289. */
  290. _x: 0,
  291. /**
  292. * Storage for `y` attribute.
  293. *
  294. * @property _y
  295. * @type Number
  296. * @private
  297. */
  298. _y: 0,
  299. /**
  300. * Gets the current position of the graphic instance in page coordinates.
  301. *
  302. * @method getXY
  303. * @return Array The XY position of the shape.
  304. */
  305. getXY: function()
  306. {
  307. var node = this.parentNode,
  308. x = this.get("x"),
  309. y = this.get("y"),
  310. xy;
  311. if(node)
  312. {
  313. xy = Y.DOM.getXY(node);
  314. xy[0] += x;
  315. xy[1] += y;
  316. }
  317. else
  318. {
  319. xy = Y.DOM._getOffset(this._node);
  320. }
  321. return xy;
  322. },
  323. /**
  324. * Initializes the class.
  325. *
  326. * @method initializer
  327. * @private
  328. */
  329. initializer: function() {
  330. var render = this.get("render"),
  331. visibility = this.get("visible") ? "visible" : "hidden";
  332. this._shapes = {};
  333. this._contentBounds = {
  334. left: 0,
  335. top: 0,
  336. right: 0,
  337. bottom: 0
  338. };
  339. this._node = this._createGraphic();
  340. this._node.style.left = this.get("x") + "px";
  341. this._node.style.top = this.get("y") + "px";
  342. this._node.style.visibility = visibility;
  343. this._node.setAttribute("id", this.get("id"));
  344. if(render)
  345. {
  346. this.render(render);
  347. }
  348. },
  349. /**
  350. * Adds the graphics node to the dom.
  351. *
  352. * @method render
  353. * @param {HTMLElement} parentNode node in which to render the graphics node into.
  354. */
  355. render: function(render) {
  356. var parentNode = render || DOCUMENT.body,
  357. node = this._node,
  358. w,
  359. h;
  360. if(render instanceof Y.Node)
  361. {
  362. parentNode = render._node;
  363. }
  364. else if(Y.Lang.isString(render))
  365. {
  366. parentNode = Y.Selector.query(render, DOCUMENT.body, true);
  367. }
  368. w = this.get("width") || parseInt(Y.DOM.getComputedStyle(parentNode, "width"), 10);
  369. h = this.get("height") || parseInt(Y.DOM.getComputedStyle(parentNode, "height"), 10);
  370. parentNode.appendChild(node);
  371. this.parentNode = parentNode;
  372. this.set("width", w);
  373. this.set("height", h);
  374. return this;
  375. },
  376. /**
  377. * Removes all nodes.
  378. *
  379. * @method destroy
  380. */
  381. destroy: function()
  382. {
  383. this.removeAllShapes();
  384. if(this._node)
  385. {
  386. this._removeChildren(this._node);
  387. if(this._node.parentNode)
  388. {
  389. this._node.parentNode.removeChild(this._node);
  390. }
  391. this._node = null;
  392. }
  393. },
  394. /**
  395. * Generates a shape instance by type.
  396. *
  397. * @method addShape
  398. * @param {Object} cfg attributes for the shape
  399. * @return Shape
  400. */
  401. addShape: function(cfg)
  402. {
  403. cfg.graphic = this;
  404. if(!this.get("visible"))
  405. {
  406. cfg.visible = false;
  407. }
  408. var ShapeClass = this._getShapeClass(cfg.type),
  409. shape = new ShapeClass(cfg);
  410. this._appendShape(shape);
  411. shape._appendStrokeAndFill();
  412. return shape;
  413. },
  414. /**
  415. * Adds a shape instance to the graphic instance.
  416. *
  417. * @method _appendShape
  418. * @param {Shape} shape The shape instance to be added to the graphic.
  419. * @private
  420. */
  421. _appendShape: function(shape)
  422. {
  423. var node = shape.node,
  424. parentNode = this._frag || this._node;
  425. if(this.get("autoDraw") || this.get("autoSize") === "sizeContentToGraphic")
  426. {
  427. parentNode.appendChild(node);
  428. }
  429. else
  430. {
  431. this._getDocFrag().appendChild(node);
  432. }
  433. },
  434. /**
  435. * Removes a shape instance from from the graphic instance.
  436. *
  437. * @method removeShape
  438. * @param {Shape|String} shape The instance or id of the shape to be removed.
  439. */
  440. removeShape: function(shape)
  441. {
  442. if(!(shape instanceof VMLShape))
  443. {
  444. if(Y_LANG.isString(shape))
  445. {
  446. shape = this._shapes[shape];
  447. }
  448. }
  449. if(shape && (shape instanceof VMLShape))
  450. {
  451. shape._destroy();
  452. this._shapes[shape.get("id")] = null;
  453. delete this._shapes[shape.get("id")];
  454. }
  455. if(this.get("autoDraw"))
  456. {
  457. this._redraw();
  458. }
  459. },
  460. /**
  461. * Removes all shape instances from the dom.
  462. *
  463. * @method removeAllShapes
  464. */
  465. removeAllShapes: function()
  466. {
  467. var shapes = this._shapes,
  468. i;
  469. for(i in shapes)
  470. {
  471. if(shapes.hasOwnProperty(i))
  472. {
  473. shapes[i].destroy();
  474. }
  475. }
  476. this._shapes = {};
  477. },
  478. /**
  479. * Removes all child nodes.
  480. *
  481. * @method _removeChildren
  482. * @param node
  483. * @private
  484. */
  485. _removeChildren: function(node)
  486. {
  487. if(node.hasChildNodes())
  488. {
  489. var child;
  490. while(node.firstChild)
  491. {
  492. child = node.firstChild;
  493. this._removeChildren(child);
  494. node.removeChild(child);
  495. }
  496. }
  497. },
  498. /**
  499. * Clears the graphics object.
  500. *
  501. * @method clear
  502. */
  503. clear: function() {
  504. this.removeAllShapes();
  505. this._removeChildren(this._node);
  506. },
  507. /**
  508. * Toggles visibility
  509. *
  510. * @method _toggleVisible
  511. * @param {Boolean} val indicates visibilitye
  512. * @private
  513. */
  514. _toggleVisible: function(val)
  515. {
  516. var i,
  517. shapes = this._shapes,
  518. visibility = val ? "visible" : "hidden";
  519. if(shapes)
  520. {
  521. for(i in shapes)
  522. {
  523. if(shapes.hasOwnProperty(i))
  524. {
  525. shapes[i].set("visible", val);
  526. }
  527. }
  528. }
  529. if(this._node)
  530. {
  531. this._node.style.visibility = visibility;
  532. }
  533. if(this._node)
  534. {
  535. this._node.style.visibility = visibility;
  536. }
  537. },
  538. /**
  539. * Sets the size of the graphics object.
  540. *
  541. * @method setSize
  542. * @param w {Number} width to set for the instance.
  543. * @param h {Number} height to set for the instance.
  544. */
  545. setSize: function(w, h) {
  546. w = Math.round(w);
  547. h = Math.round(h);
  548. this._node.style.width = w + 'px';
  549. this._node.style.height = h + 'px';
  550. },
  551. /**
  552. * Sets the positon of the graphics object.
  553. *
  554. * @method setPosition
  555. * @param {Number} x x-coordinate for the object.
  556. * @param {Number} y y-coordinate for the object.
  557. */
  558. setPosition: function(x, y)
  559. {
  560. x = Math.round(x);
  561. y = Math.round(y);
  562. this._node.style.left = x + "px";
  563. this._node.style.top = y + "px";
  564. },
  565. /**
  566. * Creates a group element
  567. *
  568. * @method _createGraphic
  569. * @private
  570. */
  571. _createGraphic: function() {
  572. var group = DOCUMENT.createElement(
  573. '<group xmlns="urn:schemas-microsft.com:vml"' +
  574. ' style="behavior:url(#default#VML);padding:0px 0px 0px 0px;display:block;position:absolute;top:0px;left:0px;zoom:1;"' +
  575. '/>'
  576. );
  577. return group;
  578. },
  579. /**
  580. * Creates a graphic node
  581. *
  582. * @method _createGraphicNode
  583. * @param {String} type node type to create
  584. * @param {String} pe specified pointer-events value
  585. * @return HTMLElement
  586. * @private
  587. */
  588. _createGraphicNode: function(type)
  589. {
  590. return DOCUMENT.createElement(
  591. '<' +
  592. type +
  593. ' xmlns="urn:schemas-microsft.com:vml"' +
  594. ' style="behavior:url(#default#VML);display:inline-block;zoom:1;"' +
  595. '/>'
  596. );
  597. },
  598. /**
  599. * Returns a shape based on the id of its dom node.
  600. *
  601. * @method getShapeById
  602. * @param {String} id Dom id of the shape's node attribute.
  603. * @return Shape
  604. */
  605. getShapeById: function(id)
  606. {
  607. return this._shapes[id];
  608. },
  609. /**
  610. * Returns a shape class. Used by `addShape`.
  611. *
  612. * @method _getShapeClass
  613. * @param {Shape | String} val Indicates which shape class.
  614. * @return Function
  615. * @private
  616. */
  617. _getShapeClass: function(val)
  618. {
  619. var shape = this._shapeClass[val];
  620. if(shape)
  621. {
  622. return shape;
  623. }
  624. return val;
  625. },
  626. /**
  627. * Look up for shape classes. Used by `addShape` to retrieve a class for instantiation.
  628. *
  629. * @property _shapeClass
  630. * @type Object
  631. * @private
  632. */
  633. _shapeClass: {
  634. circle: Y.VMLCircle,
  635. rect: Y.VMLRect,
  636. path: Y.VMLPath,
  637. ellipse: Y.VMLEllipse,
  638. pieslice: Y.VMLPieSlice
  639. },
  640. /**
  641. * Allows for creating multiple shapes in order to batch appending and redraw operations.
  642. *
  643. * @method batch
  644. * @param {Function} method Method to execute.
  645. */
  646. batch: function(method)
  647. {
  648. var autoDraw = this.get("autoDraw");
  649. this.set("autoDraw", false);
  650. method.apply();
  651. this.set("autoDraw", autoDraw);
  652. },
  653. /**
  654. * Returns a document fragment to for attaching shapes.
  655. *
  656. * @method _getDocFrag
  657. * @return DocumentFragment
  658. * @private
  659. */
  660. _getDocFrag: function()
  661. {
  662. if(!this._frag)
  663. {
  664. this._frag = DOCUMENT.createDocumentFragment();
  665. }
  666. return this._frag;
  667. },
  668. /**
  669. * Adds a shape to the redraw queue and calculates the contentBounds.
  670. *
  671. * @method addToRedrawQueue
  672. * @param shape {VMLShape}
  673. * @protected
  674. */
  675. addToRedrawQueue: function(shape)
  676. {
  677. var shapeBox,
  678. box;
  679. this._shapes[shape.get("id")] = shape;
  680. if(!this.get("resizeDown"))
  681. {
  682. shapeBox = shape.getBounds();
  683. box = this._contentBounds;
  684. box.left = box.left < shapeBox.left ? box.left : shapeBox.left;
  685. box.top = box.top < shapeBox.top ? box.top : shapeBox.top;
  686. box.right = box.right > shapeBox.right ? box.right : shapeBox.right;
  687. box.bottom = box.bottom > shapeBox.bottom ? box.bottom : shapeBox.bottom;
  688. box.width = box.right - box.left;
  689. box.height = box.bottom - box.top;
  690. this._contentBounds = box;
  691. }
  692. if(this.get("autoDraw"))
  693. {
  694. this._redraw();
  695. }
  696. },
  697. /**
  698. * Redraws all shapes.
  699. *
  700. * @method _redraw
  701. * @private
  702. */
  703. _redraw: function()
  704. {
  705. var autoSize = this.get("autoSize"),
  706. preserveAspectRatio,
  707. node = this.parentNode,
  708. nodeWidth = parseFloat(Y.DOM.getComputedStyle(node, "width")),
  709. nodeHeight = parseFloat(Y.DOM.getComputedStyle(node, "height")),
  710. xCoordOrigin = 0,
  711. yCoordOrigin = 0,
  712. box = this.get("resizeDown") ? this._getUpdatedContentBounds() : this._contentBounds,
  713. left = box.left,
  714. right = box.right,
  715. top = box.top,
  716. bottom = box.bottom,
  717. contentWidth = right - left,
  718. contentHeight = bottom - top,
  719. aspectRatio,
  720. xCoordSize,
  721. yCoordSize,
  722. scaledWidth,
  723. scaledHeight,
  724. visible = this.get("visible");
  725. this._node.style.visibility = "hidden";
  726. if(autoSize)
  727. {
  728. if(autoSize === "sizeContentToGraphic")
  729. {
  730. preserveAspectRatio = this.get("preserveAspectRatio");
  731. if(preserveAspectRatio === "none" || contentWidth/contentHeight === nodeWidth/nodeHeight)
  732. {
  733. xCoordOrigin = left;
  734. yCoordOrigin = top;
  735. xCoordSize = contentWidth;
  736. yCoordSize = contentHeight;
  737. }
  738. else
  739. {
  740. if(contentWidth * nodeHeight/contentHeight > nodeWidth)
  741. {
  742. aspectRatio = nodeHeight/nodeWidth;
  743. xCoordSize = contentWidth;
  744. yCoordSize = contentWidth * aspectRatio;
  745. scaledHeight = (nodeWidth * (contentHeight/contentWidth)) * (yCoordSize/nodeHeight);
  746. yCoordOrigin = this._calculateCoordOrigin(preserveAspectRatio.slice(5).toLowerCase(), scaledHeight, yCoordSize);
  747. yCoordOrigin = top + yCoordOrigin;
  748. xCoordOrigin = left;
  749. }
  750. else
  751. {
  752. aspectRatio = nodeWidth/nodeHeight;
  753. xCoordSize = contentHeight * aspectRatio;
  754. yCoordSize = contentHeight;
  755. scaledWidth = (nodeHeight * (contentWidth/contentHeight)) * (xCoordSize/nodeWidth);
  756. xCoordOrigin = this._calculateCoordOrigin(preserveAspectRatio.slice(1, 4).toLowerCase(), scaledWidth, xCoordSize);
  757. xCoordOrigin = xCoordOrigin + left;
  758. yCoordOrigin = top;
  759. }
  760. }
  761. this._node.style.width = nodeWidth + "px";
  762. this._node.style.height = nodeHeight + "px";
  763. this._node.coordOrigin = xCoordOrigin + ", " + yCoordOrigin;
  764. }
  765. else
  766. {
  767. xCoordSize = contentWidth;
  768. yCoordSize = contentHeight;
  769. this._node.style.width = contentWidth + "px";
  770. this._node.style.height = contentHeight + "px";
  771. this._state.width = contentWidth;
  772. this._state.height = contentHeight;
  773. }
  774. this._node.coordSize = xCoordSize + ", " + yCoordSize;
  775. }
  776. else
  777. {
  778. this._node.style.width = nodeWidth + "px";
  779. this._node.style.height = nodeHeight + "px";
  780. this._node.coordSize = nodeWidth + ", " + nodeHeight;
  781. }
  782. if(this._frag)
  783. {
  784. this._node.appendChild(this._frag);
  785. this._frag = null;
  786. }
  787. if(visible)
  788. {
  789. this._node.style.visibility = "visible";
  790. }
  791. },
  792. /**
  793. * Determines the value for either an x or y coordinate to be used for the <code>coordOrigin</code> of the Graphic.
  794. *
  795. * @method _calculateCoordOrigin
  796. * @param {String} position The position for placement. Possible values are min, mid and max.
  797. * @param {Number} size The total scaled size of the content.
  798. * @param {Number} coordsSize The coordsSize for the Graphic.
  799. * @return Number
  800. * @private
  801. */
  802. _calculateCoordOrigin: function(position, size, coordsSize)
  803. {
  804. var coord;
  805. switch(position)
  806. {
  807. case "min" :
  808. coord = 0;
  809. break;
  810. case "mid" :
  811. coord = (size - coordsSize)/2;
  812. break;
  813. case "max" :
  814. coord = (size - coordsSize);
  815. break;
  816. }
  817. return coord;
  818. },
  819. /**
  820. * Recalculates and returns the `contentBounds` for the `Graphic` instance.
  821. *
  822. * @method _getUpdatedContentBounds
  823. * @return {Object}
  824. * @private
  825. */
  826. _getUpdatedContentBounds: function()
  827. {
  828. var bounds,
  829. i,
  830. shape,
  831. queue = this._shapes,
  832. box = {};
  833. for(i in queue)
  834. {
  835. if(queue.hasOwnProperty(i))
  836. {
  837. shape = queue[i];
  838. bounds = shape.getBounds();
  839. box.left = Y_LANG.isNumber(box.left) ? Math.min(box.left, bounds.left) : bounds.left;
  840. box.top = Y_LANG.isNumber(box.top) ? Math.min(box.top, bounds.top) : bounds.top;
  841. box.right = Y_LANG.isNumber(box.right) ? Math.max(box.right, bounds.right) : bounds.right;
  842. box.bottom = Y_LANG.isNumber(box.bottom) ? Math.max(box.bottom, bounds.bottom) : bounds.bottom;
  843. }
  844. }
  845. box.left = Y_LANG.isNumber(box.left) ? box.left : 0;
  846. box.top = Y_LANG.isNumber(box.top) ? box.top : 0;
  847. box.right = Y_LANG.isNumber(box.right) ? box.right : 0;
  848. box.bottom = Y_LANG.isNumber(box.bottom) ? box.bottom : 0;
  849. this._contentBounds = box;
  850. return box;
  851. },
  852. /**
  853. * Inserts shape on the top of the tree.
  854. *
  855. * @method _toFront
  856. * @param {VMLShape} Shape to add.
  857. * @private
  858. */
  859. _toFront: function(shape)
  860. {
  861. var contentNode = this._node;
  862. if(shape instanceof Y.VMLShape)
  863. {
  864. shape = shape.get("node");
  865. }
  866. if(contentNode && shape)
  867. {
  868. contentNode.appendChild(shape);
  869. }
  870. },
  871. /**
  872. * Inserts shape as the first child of the content node.
  873. *
  874. * @method _toBack
  875. * @param {VMLShape} Shape to add.
  876. * @private
  877. */
  878. _toBack: function(shape)
  879. {
  880. var contentNode = this._node,
  881. targetNode;
  882. if(shape instanceof Y.VMLShape)
  883. {
  884. shape = shape.get("node");
  885. }
  886. if(contentNode && shape)
  887. {
  888. targetNode = contentNode.firstChild;
  889. if(targetNode)
  890. {
  891. contentNode.insertBefore(shape, targetNode);
  892. }
  893. else
  894. {
  895. contentNode.appendChild(shape);
  896. }
  897. }
  898. }
  899. });
  900. Y.VMLGraphic = VMLGraphic;