Skip to content

Commit

Permalink
Merge branch 'solival-master'
Browse files Browse the repository at this point in the history
  • Loading branch information
akserg committed Apr 7, 2017
2 parents cda6c50 + 6157320 commit aecbbbc
Show file tree
Hide file tree
Showing 9 changed files with 364 additions and 24 deletions.
100 changes: 92 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,48 @@ export class SimpleDndComponent {
}
```

#### 4. Restriction Drag-and-Drop operations with drop zones
#### 4. Add handle to restrict draggable zone of component

```js
import {Component} from '@angular/core';

@Component({
selector: 'simple-dnd-handle',
template: `
<h4>Simple Drag-and-Drop with handle</h4>
<div class="row">
<div class="col-sm-3">
<div class="panel panel-success">
<div class="panel-heading">Available to drag</div>
<div class="panel-body">
<div class="panel panel-default" dnd-draggable [dragEnabled]="true">
<div class="panel-body">
<div>
<span dnd-draggable-handle>=</span>&nbsp;
Drag Handle
</div>
</div>
</div>
</div>
</div>
</div>
<div class="col-sm-3">
<div dnd-droppable class="panel panel-info" (onDropSuccess)="simpleDrop=$event">
<div class="panel-heading">Place to drop</div>
<div class="panel-body">
<div *ngIf="simpleDrop">Item was dropped here</div>
</div>
</div>
</div>
</div>`
})
export class SimpleDndHandleComponent {
simpleDrop: any = null;
}simpleDrop: any = null;
}
```

#### 5. Restriction Drag-and-Drop operations with drop zones
You can use property *dropZones* (actually an array) to specify in which place you would like to drop the draggable element:

```js
Expand Down Expand Up @@ -172,7 +213,7 @@ export class ZoneDndComponent {
}
```

#### 5. Transfer custom data via Drag-and-Drop
#### 6. Transfer custom data via Drag-and-Drop
You can transfer data from draggable to droppable component via *dragData* property of Draggable component:

```js
Expand Down Expand Up @@ -216,7 +257,7 @@ export class CustomDataDndComponent {
}
```

#### 6. Use a custom function to determine where dropping is allowed
#### 7. Use a custom function to determine where dropping is allowed
For use-cases when a static set of `dropZone`s is not possible, a custom function can be used to dynamically determine whether an item can be dropped or not. To achieve that, set the `allowDrop` property to this boolean function.

In the following example, we have two containers that only accept numbers that are multiples of a user-input base integer. `dropZone`s are not helpful here because they are static, whereas the user input is dynamic.
Expand Down Expand Up @@ -300,7 +341,7 @@ export class CustomFunctionDndComponent {
}
```

#### 7. Shopping basket with Drag-and-Drop
#### 8. Shopping basket with Drag-and-Drop
Here is an example of shopping backet with products adding via drag and drop operation:

```js
Expand Down Expand Up @@ -386,7 +427,7 @@ class Product {
}
```

#### 8. Simple sortable with Drag-and-Drop
#### 9. Simple sortable with Drag-and-Drop
Here is an example of simple sortable of favorite drinks moving in container via drag and drop operation:

```js
Expand Down Expand Up @@ -424,7 +465,49 @@ export class SimpleSortableComponent {
}
```

#### 9. Simple sortable With Drop into recycle bin

#### 10. Simple sortable with Drag-and-Drop handle
Add handle to restict grip zone of sortable component.

```js
import {Component} from '@angular/core';

@Component({
selector: 'simple-sortable-handle',
template: `
<h4>Simple sortable handle</h4>
<div class="row">
<div class="col-sm-3">
<div class="panel panel-success">
<div class="panel-heading">
Favorite drinks
</div>
<div class="panel-body">
<ul class="list-group" dnd-sortable-container [sortableData]="listOne">
<li *ngFor="let item of listOne; let i = index" class="list-group-item" dnd-sortable [sortableIndex]="i">
<span dnd-sortable-handle>=</span>&nbsp;
{{item}}
</li>
</ul>
</div>
</div>
</div>
<div class="col-sm-6">
<div class="panel panel-default">
<div class="panel-body">
My prefences:<br/>
<span *ngFor="let item of listOne; let i = index">{{i + 1}}) {{item}}<br/></span>
</div>
</div>
</div>
</div>`
})
export class SimpleSortableHandleComponent {
listOne: Array<string> = ['Coffee', 'Orange Juice', 'Red Wine', 'Unhealty drink!', 'Water'];
}
```

#### 11. Simple sortable With Drop into recycle bin
Here is an example of multi list sortable of boxers moving in container and between containers via drag and drop operation:

```js
Expand Down Expand Up @@ -466,7 +549,7 @@ export class RecycleMultiSortableComponent {
}
```

#### 10. Simple sortable With Drop into something, without delete it
#### 12. Simple sortable With Drop into something, without delete it
Here is an example of simple sortable list of items copying in target container:

```js
Expand Down Expand Up @@ -523,7 +606,7 @@ class Widget {
}
```

#### 11. Multi list sortable between containers
#### 13. Multi list sortable between containers
Here is an example of multi list sortable of boxers moving in container and between containers via drag and drop operation:

```js
Expand Down Expand Up @@ -598,6 +681,7 @@ class Widget {

# Credits
- [Francesco Cina](https://github.com/ufoscout)
- [Valerii Kuznetsov](https://github.com/solival)

# License
[MIT](/LICENSE)
10 changes: 5 additions & 5 deletions index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import { NgModule, ModuleWithProviders } from "@angular/core";

import {DragDropConfig} from './src/dnd.config';
import {DragDropService, DragDropSortableService, dragDropServiceFactory, dragDropSortableServiceFactory} from './src/dnd.service';
import {DraggableComponent} from './src/draggable.component';
import {DraggableComponent, DraggableHandleComponent} from './src/draggable.component';
import {DroppableComponent} from './src/droppable.component';
import {SortableContainer, SortableComponent} from './src/sortable.component';
import {SortableContainer, SortableComponent, SortableHandleComponent} from './src/sortable.component';

export * from './src/abstract.component';
export * from './src/dnd.config';
Expand All @@ -24,8 +24,8 @@ export let providers = [
];

@NgModule({
declarations: [DraggableComponent, DroppableComponent, SortableContainer, SortableComponent],
exports : [DraggableComponent, DroppableComponent, SortableContainer, SortableComponent],
declarations: [DraggableComponent, DraggableHandleComponent, DroppableComponent, SortableContainer, SortableComponent, SortableHandleComponent],
exports : [DraggableComponent, DraggableHandleComponent, DroppableComponent, SortableContainer, SortableComponent, SortableHandleComponent],

})
export class DndModule {
Expand All @@ -35,4 +35,4 @@ export class DndModule {
providers: providers
};
}
}
}
42 changes: 37 additions & 5 deletions src/abstract.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,15 @@ import {isString, isFunction, isPresent, createImage, callFun} from './dnd.utils
@Injectable()
export abstract class AbstractComponent {
_elem: HTMLElement;
_dragHandle: HTMLElement;
_dragHelper: HTMLElement;
_defaultCursor: string;

/**
* Last element that was mousedown'ed
*/
_target: EventTarget;

/**
* Whether the object is draggable. Default is true.
*/
Expand Down Expand Up @@ -113,8 +119,17 @@ export abstract class AbstractComponent {
//
// Drag events
//
this._elem.onmousedown = (event: MouseEvent) => {
this._target = event.target;
};
this._elem.ondragstart = (event: DragEvent) => {
// console.log('ondragstart', event.target);
if (this._dragHandle) {
if (!this._dragHandle.contains(<Element>this._target)) {
event.preventDefault();
return;
}
}

this._onDragStart(event);
//
if (event.dataTransfer != null) {
Expand Down Expand Up @@ -143,25 +158,33 @@ export abstract class AbstractComponent {
this._elem.parentElement.appendChild(this._dragHelper);
(<any>event.dataTransfer).setDragImage(this._dragHelper, event.offsetX, event.offsetY);
}

// Change drag cursor
let cursorelem = (this._dragHandle) ? this._dragHandle : this._elem;

if (this._dragEnabled) {
this._elem.style.cursor = this.effectCursor ? this.effectCursor : this._config.dragCursor;
cursorelem.style.cursor = this.effectCursor ? this.effectCursor : this._config.dragCursor;
} else {
this._elem.style.cursor = this._defaultCursor;
cursorelem.style.cursor = this._defaultCursor;
}
}
};

this._elem.ondragend = (event: Event) => {
if (this._elem.parentElement && this._dragHelper) {
this._elem.parentElement.removeChild(this._dragHelper);
}
// console.log('ondragend', event.target);
this._onDragEnd(event);
// Restore style of dragged element
this._elem.style.cursor = this._defaultCursor;
let cursorelem = (this._dragHandle) ? this._dragHandle : this._elem;
cursorelem.style.cursor = this._defaultCursor;
};
}

public setDragHandle(elem: HTMLElement) {
this._dragHandle = elem;
}
/******* Change detection ******/

detectChanges() {
Expand Down Expand Up @@ -245,7 +268,7 @@ export abstract class AbstractComponent {
//*********** Draggable **********//

private _onDragStart(event: Event): void {
// console.log('ondragstart.dragEnabled', this._dragEnabled);
//console.log('ondragstart.dragEnabled', this._dragEnabled);
if (this._dragEnabled) {
this._dragDropService.allowedDropZones = this.dropZones;
// console.log('ondragstart.allowedDropZones', this._dragDropService.allowedDropZones);
Expand All @@ -269,3 +292,12 @@ export abstract class AbstractComponent {
_onDragStartCallback(event: Event) { }
_onDragEndCallback(event: Event) { }
}

export class AbstractHandleComponent {
_elem: HTMLElement;
constructor(elemRef: ElementRef, public _dragDropService: DragDropService, public _config: DragDropConfig,
private _Component: AbstractComponent, private _cdr: ChangeDetectorRef) {
this._elem = elemRef.nativeElement;
this._Component.setDragHandle(this._elem);
}
}
14 changes: 12 additions & 2 deletions src/draggable.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import {ChangeDetectorRef} from '@angular/core';
import {Directive, Input, Output, EventEmitter, ElementRef} from '@angular/core';

import {AbstractComponent} from './abstract.component';
import {AbstractComponent, AbstractHandleComponent} from './abstract.component';
import {DragDropConfig, DragImage} from './dnd.config';
import {DragDropService, DragDropData} from './dnd.service';

Expand Down Expand Up @@ -104,4 +104,14 @@ export class DraggableComponent extends AbstractComponent {
//
this.onDragEnd.emit({dragData: this.dragData, mouseEvent: event});
}
}
}


@Directive({ selector: '[dnd-draggable-handle]' })
export class DraggableHandleComponent extends AbstractHandleComponent {
constructor(elemRef: ElementRef, dragDropService: DragDropService, config:DragDropConfig, _Component: DraggableComponent,
cdr:ChangeDetectorRef) {

super(elemRef, dragDropService, config, _Component, cdr);
}
}
13 changes: 10 additions & 3 deletions src/sortable.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import {ChangeDetectorRef} from '@angular/core';
import {Directive, Input, Output, EventEmitter, ElementRef} from '@angular/core';

import {AbstractComponent} from './abstract.component';
import {AbstractComponent, AbstractHandleComponent} from './abstract.component';
import {DragDropConfig} from './dnd.config';
import {DragDropService, DragDropSortableService} from './dnd.service';

Expand Down Expand Up @@ -109,9 +109,7 @@ export class SortableComponent extends AbstractComponent {
private _sortableContainer: SortableContainer,
private _sortableDataService: DragDropSortableService,
cdr:ChangeDetectorRef) {

super(elemRef, dragDropService, config, cdr);

this.dropZones = this._sortableContainer.dropZones;
this.dragEnabled = true;
this.dropEnabled = true;
Expand Down Expand Up @@ -192,3 +190,12 @@ export class SortableComponent extends AbstractComponent {
}
}
}

@Directive({ selector: '[dnd-sortable-handle]' })
export class SortableHandleComponent extends AbstractHandleComponent {
constructor(elemRef: ElementRef, dragDropService: DragDropService, config:DragDropConfig, _Component: SortableComponent,
cdr:ChangeDetectorRef) {

super(elemRef, dragDropService, config, _Component, cdr);
}
}
45 changes: 45 additions & 0 deletions tests/dnd.component.factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,3 +124,48 @@ export class Container4 {
@Input() multiOneList:Array<string> = [];
@Input() multiTwoList:Array<string> = [];
}

@Component({
selector: 'test-container-five',
template: `
<div id='dragId' dnd-draggable [dragEnabled]="dragEnabled" [dragData]="dragData" [dropZones]="['test1']" (onDragSuccess)="dragSuccessCallback($event)">
<span id="handle" dnd-draggable-handle>=</span>
<span id="non-handle">Not handle</span>
</div>
<div id='dropId' dnd-droppable [dropZones]="['test1']" (onDropSuccess)="dropSuccessCallback($event)"></div>
`
})
export class Container5 {
@Input() dragEnabled:boolean = true;
@Input() dragData:any = "Hello World at " + new Date().toString();

@Output() drag:EventEmitter<any> = new EventEmitter<any>();
@Output() drop:EventEmitter<any> = new EventEmitter<any>();

// tslint:disable-next-line
private dragSuccessCallback($event:any) {
this.drag.emit($event);
}

// tslint:disable-next-line
private dropSuccessCallback($event:any) {
this.drop.emit($event);
}
}

@Component({
selector: 'test-container-six',
template: `
<div>
<ul class="list-group" dnd-sortable-container [sortableData]="sortableList">
<li *ngFor="let item of sortableList; let i = index" dnd-sortable [sortableIndex]="i">
<span class="handle" dnd-sortable-handle>=</span>
<span class="non-handle">{{item}}</span>
</li>
</ul>
</div>
`
})
export class Container6 {
@Input() sortableList:Array<string> = [];
}
Loading

0 comments on commit aecbbbc

Please sign in to comment.