- Jump To … +
  ./source/core/animation-loop.js ./source/core/display-cycle.js ./source/core/document-root-elements.js ./source/core/document.js ./source/core/events.js ./source/core/init.js ./source/core/library.js ./source/core/random-seed.js ./source/core/shared-vars.js ./source/core/snippets.js ./source/core/system-flags.js ./source/core/user-interaction.js ./source/core/utilities.js ./source/factory/action.js ./source/factory/anchor.js ./source/factory/animation.js ./source/factory/array-pool.js ./source/factory/bezier.js ./source/factory/block.js ./source/factory/canvas.js ./source/factory/cell-fragment.js ./source/factory/cell.js ./source/factory/cog.js ./source/factory/color.js ./source/factory/conic-gradient.js ./source/factory/coordinate.js ./source/factory/crescent.js ./source/factory/drag-zone.js ./source/factory/element.js ./source/factory/emitter.js ./source/factory/filter-engine-bluenoise-data.js ./source/factory/filter-engine.js ./source/factory/filter.js ./source/factory/font-attributes.js ./source/factory/gradient.js ./source/factory/grid.js ./source/factory/group.js ./source/factory/image-asset.js ./source/factory/keyboard-zone.js ./source/factory/line-spiral.js ./source/factory/line.js ./source/factory/loom.js ./source/factory/mesh.js ./source/factory/net.js ./source/factory/noise-asset.js ./source/factory/observe-update.js ./source/factory/oval.js ./source/factory/palette.js ./source/factory/particle-force.js ./source/factory/particle-history.js ./source/factory/particle-spring.js ./source/factory/particle-world.js ./source/factory/particle.js ./source/factory/pattern.js ./source/factory/phrase.js ./source/factory/picture.js ./source/factory/polygon.js ./source/factory/polyline.js ./source/factory/quadratic.js ./source/factory/quaternion.js ./source/factory/radial-gradient.js ./source/factory/raw-asset.js ./source/factory/reaction-diffusion-asset.js ./source/factory/rectangle.js ./source/factory/render-animation.js ./source/factory/shape.js ./source/factory/spiral.js ./source/factory/sprite-asset.js ./source/factory/stack.js ./source/factory/star.js ./source/factory/state.js ./source/factory/tetragon.js ./source/factory/ticker.js ./source/factory/tracer.js ./source/factory/tween.js ./source/factory/unstacked-element.js ./source/factory/vector.js ./source/factory/video-asset.js ./source/factory/wheel.js ./source/mixin/anchor.js ./source/mixin/asset-advanced-functionality.js ./source/mixin/asset-consumer.js ./source/mixin/asset.js ./source/mixin/base.js ./source/mixin/cascade.js ./source/mixin/cell-key-functions.js ./source/mixin/delta.js ./source/mixin/display-shape.js ./source/mixin/dom.js ./source/mixin/entity.js ./source/mixin/filter.js ./source/mixin/mimic.js ./source/mixin/path.js ./source/mixin/pattern.js ./source/mixin/pivot.js ./source/mixin/position.js ./source/mixin/shape-basic.js ./source/mixin/shape-curve.js ./source/mixin/shape-path-calculation.js ./source/mixin/styles.js ./source/mixin/tween.js

- §

  # Element factory

  The Scrawl-canvas Stack/Element system is an attempt to supplement DOM elements with Scrawl-canvas entity positioning and dimensioning functionality.

  - Entitys exist in a Cell environment
  - They can position themselves within that Cell either absolutely (px coordinates), or relatively (% coordinates, with values relative to the Cell’s dimensions), or by reference (using other entity’s coordinates to calculate their own coordinates - `pivot`, `mimic`, `path`)
  - They can also base their dimensions on absolute (px) or relative (%) values
  - They can be animated directly (`set`, `deltaSet`), or through automation (`delta` object), or through the Scrawl-canvas `tween` functionality
  - They can be stored and retrieved (‘packet’ functionality), cloned (‘clone’, based on packets) and killed (‘kill’ functions)

  A Stack is a wrapper object around a DOM element, whose direct children are given Scrawl-canvas Element wrappers:

      Stack    ~~> Canvas/Cell
      Element  ~~> Entity (eg Block)

  During initialization Scrawl-canvas will search the DOM tree and automatically create Stack wrappers for any element which has been given a `data-scrawl-stack` attribute which resolves to true. Every direct (first level) child inside the stack element will have Element wrappers created for them (except for <canvas> elements). As part of this work, Scrawl-canvas will modify the affected elements’ `position` CSS style:

  - Stack elements have `relative` positioning within the DOM
  - Element elements have `absolute` positioning within the Stack

  The `makeElement` function is not exported by the scrawl object. To create a new Element within a Stack, use `mystack.addNewElement({})`.

  Element wrapper objects use the base, position, anchor and dom mixins. Thus Element wrappers are also artefact objects. As such, Elements can be used (almost) like any other artefact; in particular, other artefacts - including any canvas-based entity - can use Elements as their pivot or mimic targets.

  Element wrappers are included in the Scrawl-canvas packet system; they can be saved and cloned. Killing an Element wrapper will remove its DOM element from the document.

- §

  #### Demos:

  - All stack demos include examples of using Elements. In particular:
  - DOM-002 - Element mouse, pivot and mimic functionality
  - DOM-003 - Dynamically create and clone Element artefacts; drag and drop elements (including SVG elements) around a Stack
  - DOM-004 - Limitless rockets (clone and destroy elements, tweens, tickers)
  - DOM-006 - Tween actions on a DOM element; tracking tween and ticker activity (analytics)
  - DOM-015 - Use stacked DOM artefact corners as pivot points
  - Snippets-002 - Scrawl-canvas stack element snippets
- §

  #### Imports

      import { constructors } from '../core/library.js';

      import { doCreate, isa_dom, removeItem, Ωempty } from '../core/utilities.js';

      import { uiSubscribedElements } from '../core/user-interaction.js';

      import { makeCanvas } from './canvas.js';

      import baseMix from '../mixin/base.js';
      import domMix from '../mixin/dom.js';

      import { ABSOLUTE, CANVAS, CORNER_SELECTOR, ELEMENT, MIMIC, T_ELEMENT } from '../core/shared-vars.js';

- §

  #### Element constructor

      const Element = function (items = Ωempty) {

          const el = items.domElement;

          this.makeName(items.name);
          this.register();

          if (el) {

- §

  Scrawl-canvas does not retain an Element’s textContent or innerHTML values internally. However these can be set on initialization, and subsequently, by using the attributes `text` (for textContent, which automatically escapes all HTML-related tags and entities) and `content` (which should respect HTML tags and entities)

              if (items.text) el.textContent = items.text;
              else if (items.content) el.innerHTML = items.content;
          }

          this.initializePositions();
          this.dimensions[0] = this.dimensions[1] = 100;

          this.pathCorners = [];
          this.css = {};
          this.here = {};

          this.initializeDomLayout(items);

          this.set(this.defs);

          this.initializeAccessibility();

          this.set(items);

          const myEl = this.domElement;

          if (myEl) myEl.id = this.name;

          this.apply();

          return this;
      };

- §

  #### Element prototype

      const P = Element.prototype = doCreate();
      P.type = T_ELEMENT;
      P.lib = ELEMENT;
      P.isArtefact = true;
      P.isAsset = false;

- §

  #### Mixins

  - base
  - dom

      baseMix(P);
      domMix(P);

- §

  #### Element attributes

  - Attributes defined in the base mixin: name.
  - Attributes defined in the position mixin: group, visibility, order, calculateOrder, stampOrder, start, startX, startY, handle, handleX, handleY, offset, offsetX, offsetY, dimensions, width, height, pivoted, mimicked, lockTo, lockXTo, lockYTo, scale, roll, noUserInteraction, noPositionDependencies, noCanvasEngineUpdates, noFilters, noPathUpdates, purge, bringToFrontOnDrag.
  - Attributes defined in the delta mixin: delta, noDeltaUpdates.
  - Attributes defined in the pivot mixin: pivot, pivotCorner, addPivotHandle, addPivotOffset, addPivotRotation.
  - Attributes defined in the mimic mixin: mimic, useMimicDimensions, useMimicScale, useMimicStart, useMimicHandle, useMimicOffset, useMimicRotation, useMimicFlip, addOwnDimensionsToMimic, addOwnScaleToMimic, addOwnStartToMimic, addOwnHandleToMimic, addOwnOffsetToMimic, addOwnRotationToMimic.
  - Attributes defined in the path mixin: path, pathPosition, addPathHandle, addPathOffset, addPathRotation, constantPathSpeed.
  - Attributes defined in the anchor mixin: anchor.
  - Attributes defined in the dom mixin: domElement, pitch, yaw, offsetZ, css, classes, position, actionResize, trackHere, domAttributes.

  No additional attributes required beyond those supplied by the mixins

- §

  #### Packet management

  No additional packet functionality required

- §

  #### Clone management

  No additional clone functionality required

- §

  #### Kill management

      P.factoryKill = function () {

          removeItem(uiSubscribedElements, this.name);

          this.domElement.remove();
      };

- §

  #### Get, Set, deltaSet

      const S = P.setters;

- §

  `text` - this is the preferred way to update an element’s text content because the text supplied in the argument is not treated as HTML by the browser.

  When we update the DOM attribute `element.textContent`, it deletes any position-reporting corner divs we may have added to the element. Thus we need to repopulate the element with its ‘kids’ after updating the text

      S.text = function (item) {

          const el = this.domElement;

          if (isa_dom(el)) {

              const corners = el.querySelectorAll(CORNER_SELECTOR);

              el.textContent = item;

              corners.forEach(c => el.appendChild(c));

              this.dirtyContent = true;
          }
      };

- §

  `content` - WARNING - this is a dangerous function! It does not perform any character escaping before inserting the supplied argument into the element. Raw HTML (including, for instance, <script> tags) will be added to the DOM. It’s up to the developer to make sure this content is safe!

  When we update the DOM attribute `element.innerHTML`, it deletes any position-reporting corner divs we may have added to the element. Thus we need to repopulate the element with its ‘kids’ after updating the text

      S.content = function (item) {

          const el = this.domElement;

          if (isa_dom(el)) {

              const corners = el.querySelectorAll(CORNER_SELECTOR);

              el.innerHTML = item;

              corners.forEach(c => el.appendChild(c));

              this.dirtyContent = true;
          }
      };

- §

  #### Prototype functions

- §

  `cleanDimensionsAdditionalActions` - overwrites mixin/position function.

      P.cleanDimensionsAdditionalActions = function () {

          this.dirtyDomDimensions = true;
      };

- §

  #### Snippet-related functions

- §

  `addCanvas` - adds a new <canvas> element to Scrawl-canvas stack immediately before this element, and sets up the canvas to mimic the element (meaning it will mimic changes to the element’s dimensions, positioning, scale and 3D rotational values)

  - The function can accept a Javascript object argument containing key:value pairs which will be used to set up the new canvas’s attributes after it has been created.
  - To make the canvas look as if it is in front of the element, set the element’s opacity CSS attribute to 0
  - This function is used when adding a Scrawl-canvas snippet to a stacked element.

      P.addCanvas = function (items = Ωempty) {

          if (!this.canvas) {

              const canvas = document.createElement(CANVAS),
                  el = this.domElement;

              canvas.id = `${this.name}-canvas`;

              const rect = el.getBoundingClientRect();

              el.parentNode.insertBefore(canvas, this.domElement);

              const art = makeCanvas({
                  name: `${this.name}-canvas`,
                  domElement: canvas,

                  position: ABSOLUTE,

                  width: rect.width,
                  height: rect.height,

                  mimic: this.name,
                  lockTo: MIMIC,

                  useMimicDimensions: true,
                  useMimicScale: true,
                  useMimicStart: true,
                  useMimicHandle: true,
                  useMimicOffset: true,
                  useMimicRotation: true,

                  addOwnDimensionsToMimic: false,
                  addOwnScaleToMimic: false,
                  addOwnStartToMimic: false,
                  addOwnHandleToMimic: false,
                  addOwnOffsetToMimic: false,
                  addOwnRotationToMimic: false,
              });

              art.set(items);

              this.canvas = art;

              return art;
          }
          else return this.canvas;
      };

- §

  #### Factory

      Get a handle to a Stack wrapper
      let stack = scrawl.library.stack.mystack;

      stack.addNewElement({

          name: 'list',
          tag: 'ul',

          width: '25%',
          height: 80,

          startX: 400,
          startY: 120,
          handleX: 'center',
          handleY: 'center',

          roll: 30,

          classes: 'red-text',

          content: `<li>unordered list</li>
      <li>with several</li>
      <li>bullet points</li>`,

          css: {
              font: '12px fantasy',
              paddingInlineStart: '20px',
              paddingTop: '0.5em',
              margin: '0',
              border: '1px solid red',
              cursor: 'grab',
          },

      }).clone({

          name: 'list-no-border',

          startY: 250,
          scale: 1.25,
          pitch: 60,
          yaw: 80,

          css: {
              border: 0,
          },
      });

      export const makeElement = function (items) {

          if (!items) return false;
          return new Element(items);
      };

      constructors.Element = Element;