Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@viselect/vanilla

Package Overview
Dependencies
Maintainers
1
Versions
37
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@viselect/vanilla

Simple, lightweight and modern library library for making visual DOM Selections.

  • 3.7.0
  • latest
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
25K
increased by10.25%
Maintainers
1
Weekly downloads
 
Created
Source

Logo

Viselect - Vanilla

License MIT No dependencies Support me Buy me a coffee Build Status gzip size brotli size Vue support Preact support React support Svelte support Lit-Element support Lit-Element support


Installation

Via package manager

Install using your package manager of choice:

npm install @viselect/vanilla
Via script tags

<script src="https://cdn.jsdelivr.net/npm/@viselect/vanilla/dist/viselect.umd.js"></script>
Via ES6 import
import SelectionArea from "https://cdn.jsdelivr.net/npm/@viselect/vanilla/dist/viselect.mjs"

Getting started

Last but not least, you'll need to add some basic styles to make your selection-area visible:

.selection-area {
    background: rgba(46, 115, 252, 0.11);
    border: 2px solid rgba(98, 155, 255, 0.81);
    border-radius: 0.1em;
}

Additionally, to not interfere with text-selection, selection-js won't prevent any default events anymore (as of v2.0.3). This, however, can cause problems with the actual selection ("introduced" by #99, reported in #103). If you don't care about text-selection, add the following to the container where all your selectables are located:

.container {
    user-select: none;
}

Configuration

const selection = new SelectionArea({

    // Class for the selection-area itself (the element).
    selectionAreaClass: 'selection-area',

    // Class for the selection-area container.
    selectionContainerClass: 'selection-area-container',

    // Query selector or dom-node to set up container for the selection-area element.
    container: 'body',

    // document object - if you want to use it within an embed document (or iframe).
    // If you're inside of a shadow-dom make sure to specify the shadow root here.
    document: window.document,

    // Query selectors for elements which can be selected.
    selectables: [],

    // Query selectors for elements from where a selection can be started from.
    startareas: ['html'],

    // Query selectors for elements which will be used as boundaries for the selection.
    // The boundary will also be the scrollable container if this is the case.
    boundaries: ['html'],

    // Behaviour related options.
    behaviour: {

        // Specifies what should be done if already selected elements get selected again.
        //   invert: Invert selection for elements which were already selected
        //   keep: Keep selected elements (use clearSelection() to remove those)
        //   drop: Remove stored elements after they have been touched
        overlap: 'invert',

        // On which point an element should be selected.
        // Available modes are cover (cover the entire element), center (touch the center) or
        // the default mode is touch (just touching it).
        intersect: 'touch',

        // px, how many pixels the point should move before starting the selection (combined distance).
        // Or specifiy the threshold for each axis by passing an object like {x: <number>, y: <number>}.
        startThreshold: 10,

        // List of triggers that should cause the selection to begin.
        // Each element in the list can be one of the following
        //      - a MouseButton (numbers 0 through 4)
        //        see https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button#value
        //      - an object of shape { button: MouseButton, modifiers: Modifier[] }
        //        where a Modifier is ( 'ctrl' | 'meta' | 'alt' | 'shift' )
        //
        // To trigger the selection with e.g. <CTRL + SHIFT + LEFT-CLICK> OR <RIGHT-CLICK> the
        // trigger property should look like
        //
        // triggers: [ { button: 0, modifiers: [ "ctrl", "shift" ] }, 2 ]
        // 
        // The default value is [0], enabling only the main mouse button (usually left click).
        // On mac the ctrl will act as the meta key.
        triggers: [0],

        // Scroll configuration.
        scrolling: {

            // On scrollable areas the number on px per frame is devided by this amount.
            // Default is 10 to provide a enjoyable scroll experience.
            speedDivider: 10,

            // Browsers handle mouse-wheel events differently, this number will be used as 
            // numerator to calculate the mount of px while scrolling manually: manualScrollSpeed / scrollSpeedDivider.
            manualSpeed: 750,

            // This property defines the virtual inset margins from the borders of the container
            // component that, when crossed by the mouse/touch, trigger the scrolling. Useful for
            // fullscreen containers.
            startScrollMargins: {x: 0, y: 0}
        }
    },

    // Features.
    features: {

        // Enable / disable touch support.
        touch: true,

        // Range selection.
        range: true,

        // De-select all if user clicks clicks outside selectables.
        // Disabled by default because it is not possible to reliably detect if the user clicked on a scrollbar.
        deselectOnBlur: false,

        // Configuration in case a selectable gets just clicked.
        singleTap: {

            // Enable single-click selection (Also disables range-selection via shift + ctrl).
            allow: true,

            // 'native' (element was mouse-event target) or 'touch' (element visually touched).
            intersect: 'native'
        }
    }
});

Events

Use the on(event, cb) and off(event, cb) functions to bind / unbind event-listener.

EventDescription
beforestartThe user tapped one of the areas within the specified boundaries. Return false to cancel selection immediatly.
beforedragSame as beforestart but before the user starts selecting by dragging the mouse. Can be used to conditionally allow a selection by dragging. Return false to cancel the selection.
startSelection started, here you can decide if you want to keep your previously selected elements.
moveSelection is active, user is moving the pointer around.
stopSelection has stopped.

Functions

FunctionDescription
resolveSelectables(): voidUpdates the list of selectables, useful if new elements have been added during a selection.
getSelection(): Element[]Returns currently selected element. Use it in the stop event to collect selected elements.
getSelectionArea(): HTMLElementReturns the selection area element.
cancel(keepEvent = false): voidCancel the currently active selection, pass true to trigger the stop event afterwards.
destroy(): voidDestroy the SelectionArea-instance, removes all event-listeners and the selection-area element from the DOM.
disable(): voidDisables the selection-area temporarily.
enable(): voidEnables the selection-area.
select(query: SelectAllSelectors, quiet = false): Element[]Manually select elements, if quiet is set to true this will not fire the move & stop event.
deselect(query: SelectAllSelectors, quiet = false): Element[]Manually deselect elements, if quiet is set to true this will not fire the move & stop event.
clearSelection(includeStored = true, quiet = false): voidClears the selection, pass false to keep previously selected elements. If quiet is set to true this will not fire the move & stop event.
trigger(evt: MouseEvent / TouchEvent, silent = true): voidManually trigger a selection.

Example

selection.on('beforestart', evt => {

    // Use this event to decide whether a selection should take place or not.
    // For example if the user should be able to normally interact with input-elements you 
    // may want to prevent a selection if the user clicks such a element:
    // selection.on('beforestart', ({event}) => {
    //   return event.target.tagName !== 'INPUT'; // Returning false prevents a selection
    // });

    console.log('beforestart', evt);
}).on('beforedrag', evt => {

    // Same as 'beforestart' but before a selection via dragging happens.
    console.log('beforedrag', evt);
}).on('start', evt => {

    // A selection got initiated, you could now clear the previous selection or
    // keep it if in case of multi-selection.
    console.log('start', evt);
}).on('move', evt => {

    // Here you can update elements based on their state.
    console.log('move', evt);
}).on('stop', evt => {

    // Do something with the selected elements.
    console.log('stop', evt);
});
Virtual / dynamic lists

In some cases you may add / remove selectables during a selection. Especially when it comes to scrolling. In this case make sure to call selection.resolveSelectables() every time you add / remove a selectable so that viselect is aware of the change.

Event properties

Every event comes with the following properties:

{
    selection: SelectionArea // Current instance
    event: TouchEvent | MouseEvent | null // TouchEvent, MouseEvent, or `null` if triggered manually
    store: {
        touched: Element[] // Touched elements
        selected: Element[] // Elements from the currently active selection (each click, drag counts as a single "selection") 
        stored: Element[] // Elements currently selected (in total, not just an instant)
        changed: {
            added: Element[] // Added elements since last change
            removed: Element[] // Removed elements since last change
        }
    }
}

Common recipes can be found under recipes.

Keywords

FAQs

Package last updated on 22 Nov 2024

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc