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