- 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

- §

  # Cascade mixin

  This mixin sets up the Scrawl-canvas functionality required to perform its Display cycle.

  - The Display cycle is initiated by Stack and DOM-related Cell wrappers (generally Canvas wrappers) - controller objects
  - The cycle cascades from the wrappers to all artefact objects associated with them, as mediated by Group objects.

  The mixin also includes code to assist drag-and-drop functionality.

- §

  #### Imports

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

      import { mergeOver, pushUnique, removeItem, xtGet, Ωempty } from '../core/utilities.js';

      import { releaseArray, requestArray } from '../factory/array-pool.js';

      import { _floor, ADD_ARTEFACT_CLASSES, REMOVE_ARTEFACT_CLASSES, REVERSE_BY_DELTA, SET_ARTEFACTS, UPDATE_ARTEFACTS, UPDATE_BY_DELTA } from '../core/shared-vars.js';

- §

  #### Export function

      export default function (P = Ωempty) {

- §

  #### Shared attributes

          const defaultAttributes = {

- §

  The groups attribute holds the String names of all the Group objects associated with the controller object.

              groups: null,

- §

  The groupBuckets attribute holds a reference to each Group object, in a set of arrays grouping Groups according to their order values.

              groupBuckets: null,

- §

  The batchResort Boolean flag determines whether the Groups will be sorted by their order value before instructions get passed to each in sequence. Best to leave this flag alone to do its job.

              batchResort: true,
          };
          P.defs = mergeOver(P.defs, defaultAttributes);

- §

  #### Packet management

  No additional packet functionality required

- §

  #### Clone management

  No additional clone functionality required

- §

  #### Kill management

  No additional kill functionality required

- §

  #### Get, Set, deltaSet

          const G = P.getters,
              S = P.setters;

- §

  groups

          G.groups = function () {

              return [].concat(this.groups);
          };

          S.groups = function (item) {

              this.groups.length = 0;
              this.addGroups(item);
          };

- §

  #### Prototype functions

- §

  `sortGroups` - internal function - Groups are sorted from the groups Array into the groupBuckets array using a bespoke bucket sort algorithm, based on each Group object’s order attribute

          P.sortGroups = function () {

              if (this.batchResort) {

                  this.batchResort = false;

                  const {groups, groupBuckets} = this;
                  const buckets = requestArray();

                  let i, iz, obj, name, order, arr;

                  for (i = 0, iz = groups.length; i < iz; i++) {

                      name = groups[i];
                      obj = group[name];

                      if (obj) {

                          order = _floor(obj.order) || 0;

                          if (!buckets[order]) buckets[order] = requestArray();

                          buckets[order].push(obj);
                      }
                  }
                  groupBuckets.length = 0;

                  for (i = 0, iz = buckets.length; i < iz; i++) {

                      arr = buckets[i];

                      if (arr) {

                          groupBuckets.push(...arr);
                          releaseArray(arr);
                      }
                  }
                  releaseArray(buckets);
              }
          };

- §

  `initializeCascade` - internal function used by factory constructors

          P.initializeCascade = function () {

              this.groups = [];
              this.groupBuckets = [];
          };

- §

  ##### Group management

  Groups should be added to, and removed from, the controller object using the addGroups and removeGroups functions. The argument can be one or more Group object’s name attribute, or the Group object(s) itself.

- §

  `addGroups`

          P.addGroups = function (...args) {

              const groups = this.groups;

              args.forEach(item => {

                  if (item.substring) pushUnique(groups, item);
                  else if (group[item]) pushUnique(groups, item.name);

              }, this);

              this.batchResort = true;
              return this;
          };

- §

  `removeGroups`

          P.removeGroups = function (...args) {

              const groups = this.groups;

              args.forEach( item => {

                  if (item.substring) removeItem(groups, item);
                  else if (group[item]) removeItem(groups, item.name);

              }, this);

              this.batchResort = true;
              return this;
          };

- §

  `cascadeAction` - internal helper function used by the functions below

          P.cascadeAction = function (items, action) {

              let g;

              this.groups.forEach(name => {

                  g = group[name];

                  if (g) g[action](items);

              }, this);

              return this;
          };

- §

  `updateArtefacts` - Update all artefact objects in all the controller object’s Groups. The supplied argument will be passed on to each artefact’s `setDelta` function.

          P.updateArtefacts = function (items) {

              this.cascadeAction(items, UPDATE_ARTEFACTS);
              return this;
          };

- §

  `updateArtefacts` - Set all artefact objects in all the controller object’s Groups. The supplied argument will be passed on to each artefact’s `set` functions

          P.setArtefacts = function (items) {

              this.cascadeAction(items, SET_ARTEFACTS);
              return this;
          };

- §

  `addArtefactClasses` - specific to DOM-related artefacts (Stack, Canvas, Element)

          P.addArtefactClasses = function (items) {

              this.cascadeAction(items, ADD_ARTEFACT_CLASSES);
              return this;
          };

- §

  `removeArtefactClasses` - specific to DOM-related artefacts (Stack, Canvas, Element)

          P.removeArtefactClasses = function (items) {

              this.cascadeAction(items, REMOVE_ARTEFACT_CLASSES);
              return this;
          };

- §

  `updateByDelta` - triggers the related artefact function, to update (add) its attributes by values held in its `delta` object attribute

          P.updateByDelta = function () {

              this.cascadeAction(false, UPDATE_BY_DELTA);
              return this;
          };

- §

  `reverseByDelta` - triggers the related artefact function, to reverse (subtract) its attributes by values held in its `delta` object attribute

          P.reverseByDelta = function () {

              this.cascadeAction(false, REVERSE_BY_DELTA);
              return this;
          };

- §

  ##### Collision detection

  The `getArtefactAt` function checks to see if any of the controller object’s Groups’ artefacts are located at the supplied coordinates in the argument object.

  - The first artefact to report back as being at that coordinate will be returned by the function
  - Where no artefacts are present at that coordinate the function returns false.
  - The artefact with the highest order attribute value will be returned first.
  - This function forms part of the Scrawl-canvas drag-and-drop functionality.

          P.getArtefactAt = function (items) {

              items = xtGet(items, this.here, false);

              if (items) {

                  let g, res;

                  for (let i = this.groups.length - 1; i >= 0; i--) {

                      g = group[this.groups[i]];

                      if (g) {

                          res = g.getArtefactAt(items);

                          if (res) return res;
                      }
                  }
              }
              return false;
          };

- §

  The `getAllArtefactsAt` function returns all of the controller object’s Groups’ artefacts located at the supplied coordinates in the argument object.

  - The artefact with the highest order attribute value will be returned first.
  - The function will always return an array of artefact objects, or an empty Array

          P.getAllArtefactsAt = function (items) {

              items = xtGet(items, this.here, false);

              const results = [];

              if (items) {

                  let g, res;

                  for (let i = this.groups.length - 1; i >= 0; i--) {

                      g = group[this.groups[i]];

                      if (g) {

                          res = g.getAllArtefactsAt(items);

                          if (res) results.push(...res);
                      }
                  }
              }
              return results;
          };
      }