StackGenVis: Alignment of Data, Algorithms, and Models for Stacking Ensemble Learning Using Performance Metrics
				https://doi.org/10.1109/TVCG.2020.3030352
			
			
		
			You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							447 lines
						
					
					
						
							12 KiB
						
					
					
				
			
		
		
	
	
							447 lines
						
					
					
						
							12 KiB
						
					
					
				import { Interaction } from "../core/Interaction.js";
 | 
						|
import { ActionName } from "../core/scope.js";
 | 
						|
import * as arr from "../utils/arr.js";
 | 
						|
import * as dom from "../utils/domUtils.js";
 | 
						|
import extend from "../utils/extend.js";
 | 
						|
import * as is from "../utils/is.js";
 | 
						|
ActionName.Resize = 'resize';
 | 
						|
 | 
						|
function install(scope) {
 | 
						|
  const {
 | 
						|
    actions,
 | 
						|
    browser,
 | 
						|
 | 
						|
    /** @lends Interactable */
 | 
						|
    Interactable,
 | 
						|
    // tslint:disable-line no-shadowed-variable
 | 
						|
    defaults
 | 
						|
  } = scope; // Less Precision with touch input
 | 
						|
 | 
						|
  resize.cursors = initCursors(browser);
 | 
						|
  resize.defaultMargin = browser.supportsTouch || browser.supportsPointerEvent ? 20 : 10;
 | 
						|
  /**
 | 
						|
   * ```js
 | 
						|
   * interact(element).resizable({
 | 
						|
   *   onstart: function (event) {},
 | 
						|
   *   onmove : function (event) {},
 | 
						|
   *   onend  : function (event) {},
 | 
						|
   *
 | 
						|
   *   edges: {
 | 
						|
   *     top   : true,       // Use pointer coords to check for resize.
 | 
						|
   *     left  : false,      // Disable resizing from left edge.
 | 
						|
   *     bottom: '.resize-s',// Resize if pointer target matches selector
 | 
						|
   *     right : handleEl    // Resize if pointer target is the given Element
 | 
						|
   *   },
 | 
						|
   *
 | 
						|
   *     // Width and height can be adjusted independently. When `true`, width and
 | 
						|
   *     // height are adjusted at a 1:1 ratio.
 | 
						|
   *     square: false,
 | 
						|
   *
 | 
						|
   *     // Width and height can be adjusted independently. When `true`, width and
 | 
						|
   *     // height maintain the aspect ratio they had when resizing started.
 | 
						|
   *     preserveAspectRatio: false,
 | 
						|
   *
 | 
						|
   *   // a value of 'none' will limit the resize rect to a minimum of 0x0
 | 
						|
   *   // 'negate' will allow the rect to have negative width/height
 | 
						|
   *   // 'reposition' will keep the width/height positive by swapping
 | 
						|
   *   // the top and bottom edges and/or swapping the left and right edges
 | 
						|
   *   invert: 'none' || 'negate' || 'reposition'
 | 
						|
   *
 | 
						|
   *   // limit multiple resizes.
 | 
						|
   *   // See the explanation in the {@link Interactable.draggable} example
 | 
						|
   *   max: Infinity,
 | 
						|
   *   maxPerElement: 1,
 | 
						|
   * })
 | 
						|
   *
 | 
						|
   * var isResizeable = interact(element).resizable()
 | 
						|
   * ```
 | 
						|
   *
 | 
						|
   * Gets or sets whether resize actions can be performed on the target
 | 
						|
   *
 | 
						|
   * @param {boolean | object} [options] true/false or An object with event
 | 
						|
   * listeners to be fired on resize events (object makes the Interactable
 | 
						|
   * resizable)
 | 
						|
   * @return {boolean | Interactable} A boolean indicating if this can be the
 | 
						|
   * target of resize elements, or this Interactable
 | 
						|
   */
 | 
						|
 | 
						|
  Interactable.prototype.resizable = function (options) {
 | 
						|
    return resizable(this, options, scope);
 | 
						|
  };
 | 
						|
 | 
						|
  actions[ActionName.Resize] = resize;
 | 
						|
  actions.names.push(ActionName.Resize);
 | 
						|
  arr.merge(actions.eventTypes, ['resizestart', 'resizemove', 'resizeinertiastart', 'resizeresume', 'resizeend']);
 | 
						|
  actions.methodDict.resize = 'resizable';
 | 
						|
  defaults.actions.resize = resize.defaults;
 | 
						|
}
 | 
						|
 | 
						|
function resizeChecker(arg) {
 | 
						|
  const {
 | 
						|
    interaction,
 | 
						|
    interactable,
 | 
						|
    element,
 | 
						|
    rect,
 | 
						|
    buttons
 | 
						|
  } = arg;
 | 
						|
 | 
						|
  if (!rect) {
 | 
						|
    return undefined;
 | 
						|
  }
 | 
						|
 | 
						|
  const page = extend({}, interaction.coords.cur.page);
 | 
						|
  const resizeOptions = interactable.options.resize;
 | 
						|
 | 
						|
  if (!(resizeOptions && resizeOptions.enabled) || // check mouseButton setting if the pointer is down
 | 
						|
  interaction.pointerIsDown && /mouse|pointer/.test(interaction.pointerType) && (buttons & resizeOptions.mouseButtons) === 0) {
 | 
						|
    return undefined;
 | 
						|
  } // if using resize.edges
 | 
						|
 | 
						|
 | 
						|
  if (is.object(resizeOptions.edges)) {
 | 
						|
    const resizeEdges = {
 | 
						|
      left: false,
 | 
						|
      right: false,
 | 
						|
      top: false,
 | 
						|
      bottom: false
 | 
						|
    };
 | 
						|
 | 
						|
    for (const edge in resizeEdges) {
 | 
						|
      resizeEdges[edge] = checkResizeEdge(edge, resizeOptions.edges[edge], page, interaction._latestPointer.eventTarget, element, rect, resizeOptions.margin || resize.defaultMargin);
 | 
						|
    }
 | 
						|
 | 
						|
    resizeEdges.left = resizeEdges.left && !resizeEdges.right;
 | 
						|
    resizeEdges.top = resizeEdges.top && !resizeEdges.bottom;
 | 
						|
 | 
						|
    if (resizeEdges.left || resizeEdges.right || resizeEdges.top || resizeEdges.bottom) {
 | 
						|
      arg.action = {
 | 
						|
        name: ActionName.Resize,
 | 
						|
        edges: resizeEdges
 | 
						|
      };
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    const right = resizeOptions.axis !== 'y' && page.x > rect.right - resize.defaultMargin;
 | 
						|
    const bottom = resizeOptions.axis !== 'x' && page.y > rect.bottom - resize.defaultMargin;
 | 
						|
 | 
						|
    if (right || bottom) {
 | 
						|
      arg.action = {
 | 
						|
        name: 'resize',
 | 
						|
        axes: (right ? 'x' : '') + (bottom ? 'y' : '')
 | 
						|
      };
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return arg.action ? false : undefined;
 | 
						|
}
 | 
						|
 | 
						|
function resizable(interactable, options, scope) {
 | 
						|
  if (is.object(options)) {
 | 
						|
    interactable.options.resize.enabled = options.enabled !== false;
 | 
						|
    interactable.setPerAction(ActionName.Resize, options);
 | 
						|
    interactable.setOnEvents(ActionName.Resize, options);
 | 
						|
 | 
						|
    if (is.string(options.axis) && /^x$|^y$|^xy$/.test(options.axis)) {
 | 
						|
      interactable.options.resize.axis = options.axis;
 | 
						|
    } else if (options.axis === null) {
 | 
						|
      interactable.options.resize.axis = scope.defaults.actions.resize.axis;
 | 
						|
    }
 | 
						|
 | 
						|
    if (is.bool(options.preserveAspectRatio)) {
 | 
						|
      interactable.options.resize.preserveAspectRatio = options.preserveAspectRatio;
 | 
						|
    } else if (is.bool(options.square)) {
 | 
						|
      interactable.options.resize.square = options.square;
 | 
						|
    }
 | 
						|
 | 
						|
    return interactable;
 | 
						|
  }
 | 
						|
 | 
						|
  if (is.bool(options)) {
 | 
						|
    interactable.options.resize.enabled = options;
 | 
						|
    return interactable;
 | 
						|
  }
 | 
						|
 | 
						|
  return interactable.options.resize;
 | 
						|
}
 | 
						|
 | 
						|
function checkResizeEdge(name, value, page, element, interactableElement, rect, margin) {
 | 
						|
  // false, '', undefined, null
 | 
						|
  if (!value) {
 | 
						|
    return false;
 | 
						|
  } // true value, use pointer coords and element rect
 | 
						|
 | 
						|
 | 
						|
  if (value === true) {
 | 
						|
    // if dimensions are negative, "switch" edges
 | 
						|
    const width = is.number(rect.width) ? rect.width : rect.right - rect.left;
 | 
						|
    const height = is.number(rect.height) ? rect.height : rect.bottom - rect.top; // don't use margin greater than half the relevent dimension
 | 
						|
 | 
						|
    margin = Math.min(margin, (name === 'left' || name === 'right' ? width : height) / 2);
 | 
						|
 | 
						|
    if (width < 0) {
 | 
						|
      if (name === 'left') {
 | 
						|
        name = 'right';
 | 
						|
      } else if (name === 'right') {
 | 
						|
        name = 'left';
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    if (height < 0) {
 | 
						|
      if (name === 'top') {
 | 
						|
        name = 'bottom';
 | 
						|
      } else if (name === 'bottom') {
 | 
						|
        name = 'top';
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    if (name === 'left') {
 | 
						|
      return page.x < (width >= 0 ? rect.left : rect.right) + margin;
 | 
						|
    }
 | 
						|
 | 
						|
    if (name === 'top') {
 | 
						|
      return page.y < (height >= 0 ? rect.top : rect.bottom) + margin;
 | 
						|
    }
 | 
						|
 | 
						|
    if (name === 'right') {
 | 
						|
      return page.x > (width >= 0 ? rect.right : rect.left) - margin;
 | 
						|
    }
 | 
						|
 | 
						|
    if (name === 'bottom') {
 | 
						|
      return page.y > (height >= 0 ? rect.bottom : rect.top) - margin;
 | 
						|
    }
 | 
						|
  } // the remaining checks require an element
 | 
						|
 | 
						|
 | 
						|
  if (!is.element(element)) {
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  return is.element(value) // the value is an element to use as a resize handle
 | 
						|
  ? value === element // otherwise check if element matches value as selector
 | 
						|
  : dom.matchesUpTo(element, value, interactableElement);
 | 
						|
}
 | 
						|
 | 
						|
function initCursors(browser) {
 | 
						|
  return browser.isIe9 ? {
 | 
						|
    x: 'e-resize',
 | 
						|
    y: 's-resize',
 | 
						|
    xy: 'se-resize',
 | 
						|
    top: 'n-resize',
 | 
						|
    left: 'w-resize',
 | 
						|
    bottom: 's-resize',
 | 
						|
    right: 'e-resize',
 | 
						|
    topleft: 'se-resize',
 | 
						|
    bottomright: 'se-resize',
 | 
						|
    topright: 'ne-resize',
 | 
						|
    bottomleft: 'ne-resize'
 | 
						|
  } : {
 | 
						|
    x: 'ew-resize',
 | 
						|
    y: 'ns-resize',
 | 
						|
    xy: 'nwse-resize',
 | 
						|
    top: 'ns-resize',
 | 
						|
    left: 'ew-resize',
 | 
						|
    bottom: 'ns-resize',
 | 
						|
    right: 'ew-resize',
 | 
						|
    topleft: 'nwse-resize',
 | 
						|
    bottomright: 'nwse-resize',
 | 
						|
    topright: 'nesw-resize',
 | 
						|
    bottomleft: 'nesw-resize'
 | 
						|
  };
 | 
						|
}
 | 
						|
 | 
						|
function start({
 | 
						|
  iEvent,
 | 
						|
  interaction
 | 
						|
}) {
 | 
						|
  if (interaction.prepared.name !== 'resize' || !interaction.prepared.edges) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  const rect = interaction.rect;
 | 
						|
  interaction._rects = {
 | 
						|
    start: extend({}, rect),
 | 
						|
    corrected: extend({}, rect),
 | 
						|
    previous: extend({}, rect),
 | 
						|
    delta: {
 | 
						|
      left: 0,
 | 
						|
      right: 0,
 | 
						|
      width: 0,
 | 
						|
      top: 0,
 | 
						|
      bottom: 0,
 | 
						|
      height: 0
 | 
						|
    }
 | 
						|
  };
 | 
						|
  iEvent.edges = interaction.prepared.edges;
 | 
						|
  iEvent.rect = interaction._rects.corrected;
 | 
						|
  iEvent.deltaRect = interaction._rects.delta;
 | 
						|
}
 | 
						|
 | 
						|
function move({
 | 
						|
  iEvent,
 | 
						|
  interaction
 | 
						|
}) {
 | 
						|
  if (interaction.prepared.name !== 'resize' || !interaction.prepared.edges) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  const resizeOptions = interaction.interactable.options.resize;
 | 
						|
  const invert = resizeOptions.invert;
 | 
						|
  const invertible = invert === 'reposition' || invert === 'negate'; // eslint-disable-next-line no-shadow
 | 
						|
 | 
						|
  const current = interaction.rect;
 | 
						|
  const {
 | 
						|
    start: startRect,
 | 
						|
    corrected,
 | 
						|
    delta: deltaRect,
 | 
						|
    previous
 | 
						|
  } = interaction._rects;
 | 
						|
  extend(previous, corrected);
 | 
						|
 | 
						|
  if (invertible) {
 | 
						|
    // if invertible, copy the current rect
 | 
						|
    extend(corrected, current);
 | 
						|
 | 
						|
    if (invert === 'reposition') {
 | 
						|
      // swap edge values if necessary to keep width/height positive
 | 
						|
      if (corrected.top > corrected.bottom) {
 | 
						|
        const swap = corrected.top;
 | 
						|
        corrected.top = corrected.bottom;
 | 
						|
        corrected.bottom = swap;
 | 
						|
      }
 | 
						|
 | 
						|
      if (corrected.left > corrected.right) {
 | 
						|
        const swap = corrected.left;
 | 
						|
        corrected.left = corrected.right;
 | 
						|
        corrected.right = swap;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    // if not invertible, restrict to minimum of 0x0 rect
 | 
						|
    corrected.top = Math.min(current.top, startRect.bottom);
 | 
						|
    corrected.bottom = Math.max(current.bottom, startRect.top);
 | 
						|
    corrected.left = Math.min(current.left, startRect.right);
 | 
						|
    corrected.right = Math.max(current.right, startRect.left);
 | 
						|
  }
 | 
						|
 | 
						|
  corrected.width = corrected.right - corrected.left;
 | 
						|
  corrected.height = corrected.bottom - corrected.top;
 | 
						|
 | 
						|
  for (const edge in corrected) {
 | 
						|
    deltaRect[edge] = corrected[edge] - previous[edge];
 | 
						|
  }
 | 
						|
 | 
						|
  iEvent.edges = interaction.prepared.edges;
 | 
						|
  iEvent.rect = corrected;
 | 
						|
  iEvent.deltaRect = deltaRect;
 | 
						|
}
 | 
						|
 | 
						|
function end({
 | 
						|
  iEvent,
 | 
						|
  interaction
 | 
						|
}) {
 | 
						|
  if (interaction.prepared.name !== 'resize' || !interaction.prepared.edges) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  iEvent.edges = interaction.prepared.edges;
 | 
						|
  iEvent.rect = interaction._rects.corrected;
 | 
						|
  iEvent.deltaRect = interaction._rects.delta;
 | 
						|
}
 | 
						|
 | 
						|
function updateEventAxes({
 | 
						|
  iEvent,
 | 
						|
  interaction
 | 
						|
}) {
 | 
						|
  if (interaction.prepared.name !== ActionName.Resize || !interaction.resizeAxes) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  const options = interaction.interactable.options;
 | 
						|
 | 
						|
  if (options.resize.square) {
 | 
						|
    if (interaction.resizeAxes === 'y') {
 | 
						|
      iEvent.delta.x = iEvent.delta.y;
 | 
						|
    } else {
 | 
						|
      iEvent.delta.y = iEvent.delta.x;
 | 
						|
    }
 | 
						|
 | 
						|
    iEvent.axes = 'xy';
 | 
						|
  } else {
 | 
						|
    iEvent.axes = interaction.resizeAxes;
 | 
						|
 | 
						|
    if (interaction.resizeAxes === 'x') {
 | 
						|
      iEvent.delta.y = 0;
 | 
						|
    } else if (interaction.resizeAxes === 'y') {
 | 
						|
      iEvent.delta.x = 0;
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
const resize = {
 | 
						|
  id: 'actions/resize',
 | 
						|
  before: ['actions/drag'],
 | 
						|
  install,
 | 
						|
  listeners: {
 | 
						|
    'interactions:new': ({
 | 
						|
      interaction
 | 
						|
    }) => {
 | 
						|
      interaction.resizeAxes = 'xy';
 | 
						|
    },
 | 
						|
    'interactions:action-start': arg => {
 | 
						|
      start(arg);
 | 
						|
      updateEventAxes(arg);
 | 
						|
    },
 | 
						|
    'interactions:action-move': arg => {
 | 
						|
      move(arg);
 | 
						|
      updateEventAxes(arg);
 | 
						|
    },
 | 
						|
    'interactions:action-end': end,
 | 
						|
    'auto-start:check': resizeChecker
 | 
						|
  },
 | 
						|
  defaults: {
 | 
						|
    square: false,
 | 
						|
    preserveAspectRatio: false,
 | 
						|
    axis: 'xy',
 | 
						|
    // use default margin
 | 
						|
    margin: NaN,
 | 
						|
    // object with props left, right, top, bottom which are
 | 
						|
    // true/false values to resize when the pointer is over that edge,
 | 
						|
    // CSS selectors to match the handles for each direction
 | 
						|
    // or the Elements for each handle
 | 
						|
    edges: null,
 | 
						|
    // a value of 'none' will limit the resize rect to a minimum of 0x0
 | 
						|
    // 'negate' will alow the rect to have negative width/height
 | 
						|
    // 'reposition' will keep the width/height positive by swapping
 | 
						|
    // the top and bottom edges and/or swapping the left and right edges
 | 
						|
    invert: 'none'
 | 
						|
  },
 | 
						|
  cursors: null,
 | 
						|
 | 
						|
  getCursor({
 | 
						|
    edges,
 | 
						|
    axis,
 | 
						|
    name
 | 
						|
  }) {
 | 
						|
    const cursors = resize.cursors;
 | 
						|
    let result = null;
 | 
						|
 | 
						|
    if (axis) {
 | 
						|
      result = cursors[name + axis];
 | 
						|
    } else if (edges) {
 | 
						|
      let cursorKey = '';
 | 
						|
 | 
						|
      for (const edge of ['top', 'bottom', 'left', 'right']) {
 | 
						|
        if (edges[edge]) {
 | 
						|
          cursorKey += edge;
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      result = cursors[cursorKey];
 | 
						|
    }
 | 
						|
 | 
						|
    return result;
 | 
						|
  },
 | 
						|
 | 
						|
  defaultMargin: null
 | 
						|
};
 | 
						|
export default resize;
 | 
						|
//# sourceMappingURL=resize.js.map
 |