Giter Site home page Giter Site logo

eriklieben / aurelia-interactjs Goto Github PK

View Code? Open in Web Editor NEW
13.0 9.0 7.0 138 KB

Plugin to use interact.js with Aurelia http://interactjs.io/ Inspired by a blog post from Matthew James Davis http://davismj.me/blog/aurelia-drag-and-drop/

License: MIT License

JavaScript 45.78% TypeScript 54.22%
aurelia-plugins interactjs

aurelia-interactjs's Introduction

aurelia-interactjs

Aurelia plugin to use the interact.js library.

Inspired by a blog post from Matthew James Davis Drag-and-drop in Aurelia.

Installation

JSPM

Install the package:

jspm i aurelia-interactjs

Add the following line to src/main.js or src/main.ts:

export function configure(aurelia) {
  aurelia.use
    .standardConfiguration()
    .developmentLogging()
+    .plugin("aurelia-interactjs");

Aurelia-CLI

Install the package:

npm i aurelia-interactjs --save

And perform the following command to add the configuration for aurelia-interactjs to the aurelia.json config:

au interact

Add the following line to src/main.js or src/main.ts:

export function configure(aurelia: Aurelia) {
  aurelia.use
    .standardConfiguration()
    .feature('resources')
+    .plugin('aurelia-interactjs');

  if (environment.debug) {
    aurelia.use.developmentLogging();
  }

Generic attributes

Each attribute can be supplied with custom options that will be pased to interactjs, and are split into 2 types. These are Interactable options and Action options.

See the interactjs documentation for the Action options.

Interactable options are described in the code. See the default values here.

Prior to v2.0.7 only, action options were supported by the wrapper, for example:

Usage:

Action options only (pre and post 2.0.7)

<div interact-draggable.bind="actionOptions" />
let actionOptions = {
  overlap: 0.1
} 

Action and Intreactable options usage:

In v2.0.7 and above both types are supported, for example:

<div interact-draggable.bind="options" />
let options = {
  action: { overlap: 0.1 }, 
  interactable: { preventDefault: 'never' }
} 

NOTE: If you use more than one custom attribute on a HTML element (e.g. draggable and dropzone on the same DIV) you should duplicate the interactable options on both as the fist one that is evaluated creates the interactable which is subsequently cached.

Each event can be used in the following way:

<div interact-draggable interact-dragmove.delegate="func($event)" />
export class Home {
  public func(customEvent: CustomEvent) {
    let event = customEvent.detail;
    console.log("event", event);
  }
}

interact-draggable

The following attributes can be set to catch events

Attribute Interact.js event
interact-dragstart dragstart
interact-dragmove dragmove
interact-draginertiastart draginertiastart
interact-dragend dragend

interact-dropzone

Attribute Interact.js event
interact-dropactivate dropactivate
interact-dragenter dragenter
interact-dragleave dragleave
interact-drop drop
interact-dropdeactivate dropdeactivate

interact-gesturable

Attribute Interact.js event
interact-gesturestart gesturestart
interact-gesturemove gesturemove
interact-gestureend gestureend

interact-resizable

Attribute Interact.js event
interact-resizestart resizestart
interact-resizemove resizemove
interact-resizeinertiastart resizeinertiastart
interact-resizeend resizeend

Custom attributes draggable and dropzone

By default the attributes draggable and dropzone are not loaded (because the use global names).

You can load them by providing the option enableDragDropAttributes in src\main.js or src\main.ts :

export function configure(aurelia) {
  aurelia.use
    .standardConfiguration()
    .developmentLogging()
+    .plugin("aurelia-interactjs", { enableDragDropAttributes: true });
<div draggable.bind="item" style="width: 25px; height: 25px; background-color:${color}; border: 5px solid yellow">drag me</div>

<div dropzone drop.trigger="itemDropped($event.detail, 'green')" style="width:300px; height: 300px; background-color: green"></div>
<div dropzone drop.trigger="itemDropped($event.detail, 'red')" style="width:300px; height: 300px; background-color: red"></div>
export class App {
  item = { name: "some", color: "yellow"};

  updateColor(item, color) {
    item.color = color;
  }

}

By default it will add the following css classes to the element in the following states:

draggable

class state
getting--dragged draggable is getting dragged
drop--me draggable entered a dropzone and can be dropped here

dropzone

class state
can--drop draggable target can be dropped in the dropzone
can-catch draggable entered this zone and can be dropped here
caught--it draggable element is dropped in this zone

aurelia-interactjs's People

Contributors

erik-lieben avatar jfstephe avatar martonsagi avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

aurelia-interactjs's Issues

Adding interact-draggable etc attributes to dom element via the templatingEngine doesn't work as attached() isn't called

I'm submitting a bug report

  • Framework Version:
    1.0.10

Please tell us about your environment:

  • Operating System:
    linux docker container on virtualbox on windows10

  • Node Version:
    6.9.1

  • NPM Version:
    3.10.8

  • JSPM OR Webpack AND Version
    JSPM 0.16.48

  • Browser:
    Chrome latest

  • Language:
    TypeScript latest

Current behavior:
Adding the interact attributes to an existing dom element and calling templatingEngine.enhance() means that attached() isn't called and so the necessary interactjs code in the plugin isn't run.

Background:
I'm trying to implement row drag+drop behaviour in my app for the grid in the https://github.com/ceolter/ag-grid-aurelia project. It doesn't support it by default so I have to add a cell renderer in my gridWrapper component which looks like:

this.columnDefinitions = [
  {
    headerName: 'dragger', width: 200, field: undefined, children: undefined, cellRenderer: function() {
      var span = document.createElement('span');
      span.setAttribute('interact-dropzone', '');
      span.setAttribute('interact-draggable', '');
      span.setAttribute('interact-dragend.delegate', 'dragEnd($event)');
      span.setAttribute('style', 'border:solid 2px red; margin:5px; padding:5px');
      templatingEngine.enhance({element: span, bindingContext: vm});
      return span;
    }
.......
];

I have limited control over the grid itself, but after debugging this, and after a lot of trial and error, I can get it working if I move the code that is in interact-draggable.js from attached() to bind().

Expected/desired behavior:
As described above

  • What is the expected behavior?
    As described above. I'm happy to create a PR for this. Please let me know if you are ok with it in theory.

  • What is the motivation / use case for changing the behavior?
    More generic solution. I can't see any downsides to this, but happy to be corrected :-)

Bindable options are not working

I'm submitting a bug report

  • Framework Version:
    aurelia-framework: 1.0.0
    aurelia-cli: 0.21.0
    aurelia-interactjs: 1.0.9
    interact.js: 1.2.6

Please tell us about your environment:

  • Operating System:
    OSX 10.11.6
  • Node Version:
    6.8.1
  • NPM Version:
    3.10.8
  • JSPM OR Webpack AND Version
    JSPM 0.16.46
  • Browser:
    Chrome 54.0.2840.71 (64-bit)
    Safari 9.1.2 (11601.7.7)
  • Language:
    ESNext

Current behavior:
interact-draggable.bind="dragOptions" does not work. Even though this.dragOptions is set in the constructor, this.options is undefined in the attached() method of the InteractDraggableCustomAttribute class.

Expected/desired behavior:
Demo: https://github.com/jeffgrann/aurelia-interactjs-test2

Enabling Webpack Support

For others like me who are using Webpack with Aurelia, I've gotten Webpack support to work with this, but I think it will require either forking the project or downloading it and copying it as a local feature based plugin. Not an ideal situation of course but it is what it is. I'm not sure if there is something that can be done to automate the checking of whether or not the user is using Webpack to bundle and then potentially referencing a different build of the plugin that has the changes to the plugin's src files as I detail below.

For a quick reference, an issue has been created in the Aurelia-Webpack plugin repository aurelia/webpack-plugin#80 that details the root cause of the issue. Basically, with the interact.js library, you have to alias the package from interact.js to interact (as shown with the Aurelia CLI config in the Readme) and the current version of the Aurelia-Plugin doesn't support aliasing but will in the future 2.0 release.

Until then to get this plugin working you either have to put in a <script> tag in your index.html (and lose the advantage of webpack bundling) or you can do a couple of things:

  1. In your webpack.config.js you can add an object in the config:
    externals: { 'interact.js/dist/interact': 'interact' }
  2. in each of the Aurelia-Interactjs plugin src files, you need to change the Interact import statement from: import * as interact from 'interact'; to this: import { interact } from 'interact.js';

After resize event, my target element's either width or height is automatically increasing

I am trying to implement interact-draggable and interact-resizeable on same element
providing ActionOptions different( i tried same Action Options too).

My problem is after Resizing the element, sometimes my element's either height or width is automatically increasing respective value

Note: As per my observation, the reason for increase in Height or Width is due to increase in dx or dy value
----------Action Options----------------------

draggableOption = {
action: {
inertia : true,
restrict: {
restriction: ".parentClass",
endOnly: true,
elementRect: { top: 0, left: 0, bottom: 1, right: 1 }
},
autoScroll: true
}
}
resizeableOption = {
action: {

  edges: { right: true, bottom: true, top: false, left: false },
  // keep the edges inside the parent
  restrict: {
    restriction: ".parentClass",
    endOnly: true,
    elementRect: { top: 0, left: 0, bottom: 1, right: 1 }
  }
}

};

--------------Interact Events-------------------
reizeMove(customEvent) {

var event = customEvent.detail;
var target = event.target, x = (parseFloat(target.getAttribute('data-x')) || 0), y = (parseFloat(target.getAttribute('data-y')) || 0);
target.style.width = event.rect.width + 'px';
target.style.height = event.rect.height + 'px';

x += event.deltaRect.left;
y += event.deltaRect.top;
target.style.webkitTransform = target.style.transform =
  'translate(' + x + 'px,' + y + 'px)';
target.setAttribute('data-x', x);
target.setAttribute('data-y', y);
target.textContent = Math.round(event.rect.width) + '\u00D7' + Math.round(event.rect.height);

}
dragMove(customEvent) {

var event = customEvent.detail;
var parent = customEvent.srcElement;
var target = event.target,
  x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx,
  y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy;
target.style.transform = 'translate(' + x + 'px, ' + y + 'px)';
target.setAttribute('data-x', x);
target.setAttribute('data-y', y);
target.classList.add('getting--dragged');

}

Would like to use interact('.tap-target') . onTab

I'm submitting a feature request
I would like to use interact('.tap-target') .onTab en onHold. I can add it to the code with a pull request, but would like some guidelines on the implementation.

  • What attributes would you add to support this?
  • would it be part of dragable or resizable or dropzone or something new ?
  • What is the expected behavior?
    Happy use of tab, doubletab and hold

  • What is the motivation / use case for changing the behavior?
    I want to start an editor when i hold or tab on a draggable/resizable element.

Thanks for making this library available.

Array with dropzones and reordering of array causes dropzones to not be initialized

The problem is as follows: If I take one image and drag it from the top to the bottom slowly, and then back up, it will not go up properly. Dragging it down works fine. I suspect that this is because the dropzones are active. When I move it up again, the dropzones are not properly initialized, and because of this it won't move up the same way it were moved down.

I am using Aurelia with [email protected] and I have this is the html I am using:

<template>
<style>
    .dragArea {
        border: black dashed 1px;
        width: 200px;
        min-height: 20px
    }
    .movingEntity {
        width: 100%;
    }
</style>

<div repeat.for="draggable of draggableData">

    <div interact-dropzone
         interact-drop.delegate="drop($event, $index)"
         interact-dragenter.delegate="dragEnter($event,$index,draggable.id)"
         interact-dragleave.delegate="dragLeave($event, $index,draggable.id)"
         class="dragArea">
        <span interact-draggable
              interact-dragmove.delegate="dragMove($event,draggable.id)"
              interact-dragstart.delegate="dragStart($event, $index, draggable.id)">
            <img class="movingEntity" src="${draggable.imageUrl}" />
        </span>
    </div>
</div>

My class looks like this:

export class App {
draggableData: IDraggable[] = new Array();

constructor() {
    this.draggableData.push({
            id: 1,
            gettingDragged: false,
            imageUrl:
                "https://s14-eu5.ixquick.com/cgi-bin/serveimage?url=https%3A%2F%2Flh4.ggpht.com%2FvkgYSVCsnqGCkvMfifD5fvoVecY6nIvyPy4UWMUafUoZDzbp-QYo5BPuTvTwyK-PPJ8%3Dh900&sp=98612b1aaae4ae68e64a8b6a35d60dbf"
        });

    this.draggableData.push({
            id: 2,
            gettingDragged: false,
            imageUrl:
                "http://animals.sandiegozoo.org/sites/default/files/2016-10/animals_hero_fennec2.jpg"
        });
    this.draggableData.push({
            id: 3,
            gettingDragged: false,
            imageUrl:
                "http://animals.sandiegozoo.org/sites/default/files/2016-09/animals_hero_armadillo_0.jpg"
        });
    this.draggableData.push({
            id: 4,
            gettingDragged: false,
            imageUrl:
                "http://news.nationalgeographic.com/content/dam/news/photos/000/744/74436.jpg"
        });
}


pickedUpElement = null;

movePickedElementToPosition(index) {
    var elementToSwitchWith = this.draggableData[index];
    var pickedUpElementIndex = this.draggableData.findIndex(x => x.id === this.pickedUpElement.id);

    this.draggableData.splice(pickedUpElementIndex, 1, elementToSwitchWith);
    this.draggableData.splice(index, 1, this.pickedUpElement);
}

drop(event, index) {
    //console.log("drop", index);
}

dragEnter(event, index, id) {
    if (index === this.draggableData.findIndex(x => x.id === this.pickedUpElement.id))
        return;

    this.movePickedElementToPosition(index);
}

dragLeave(event, index, id) {
    //console.log("dragLeave",index,id);
}

dragMove(event, index, id) {
    //console.log("dragMove",event, index,id);
}

dragStart(event, index, id) {
    this.pickedUpElement = this.draggableData.find(x => x.id === id);
}
}

interface IDraggable {
    imageUrl: string;
    id: number;
    gettingDragged: boolean;
}

The problem can also be provoked if one ads the line
this.draggableData = JSON.parse(JSON.stringify(this.draggableData));
in movePickedElementToPosition(index) at the bottom. It will then only move the image one time, because the dropzones are messed up.

Naturally then the question becomes; "Is there any way of going around this? Or fix it?"

https://stackoverflow.com/questions/44900862/aurelia-aurelia-interactjs-array-with-dropzones-and-reordering-of-array-causes

Unhandled rejection Error: key/value cannot be null or undefined

I'm submitting a bug report
Followed the given instruction. but ended up with this error. "Unhandled rejection Error: key/value cannot be null or undefined"

  • Framework Version:
    2.0.7

Please tell us about your environment:

  • Operating System:
    OSX 10.x

  • Node Version:
    7.4.0

  • NPM Version:
    4.0.5
  • JSPM OR Webpack AND Version
    Aurelia CLI 0.24.0

  • Browser:
    Chrome XX

  • Language:
    ESNext

Current behavior:
Unhandled rejection Error: key/value cannot be null or undefined. Are you trying to inject/register something that doesn't exist with DI?

Followed your instruction to install the plugin. when importing that using aurelia.use.plugin(). getting the error.

Expected/desired behavior:

  • What is the expected behavior?
    Error free.

  • What is the motivation / use case for changing the behavior?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.