Current Path : /storage/v11800/affypharma/public_html/wp-content/plugins/caxton/assets/es6/ |
Linux v11800 5.3.0-1023-aws #25~18.04.1-Ubuntu SMP Fri Jun 5 15:19:18 UTC 2020 aarch64
|
Current File : /storage/v11800/affypharma/public_html/wp-content/plugins/caxton/assets/es6/react-sortable-list.es6 |
/**
* Sortable List module
* A sortable list component using html5 drag and drop api.
* @param {array} data Array of data to resort
* @param {function} renderItem Callback function to render item element from data item
* @param {function} onChange Callback function called with newly ordered data
**/
export default class SortableItems extends wp.element.Component {
constructor(props) {
super(props);
let placeholder = document.createElement('div');
placeholder.className = 'placeholder';
this.state = {
data: [...props.data],
placeholder: placeholder
};
this.dragEnd = this.dragEnd.bind(this);
this.dragStart = this.dragStart.bind(this);
this.dragOver = this.dragOver.bind(this);
}
componentWillMount() {
this.setState( {data: [...this.props.data]} );
}
componentDidUpdate( prevProps ) {
if (
this.props.data.length !== this.state.data.length ||
JSON.stringify( this.props.data ) !== JSON.stringify( prevProps.data )
) {
this.setState( {data: [...this.props.data]} );
}
}
sortData(from, to) {
let data = [...this.state.data];
data.splice(to, 0, data.splice(from, 1)[0]);
let onChange = this.props.onChange || (items => null);
onChange(data);
this.setState({
data
});
}
/**
* On drag start, set data.
**/
dragStart(e) {
this.dragged = e.currentTarget;
e.dataTransfer.effectAllowed = 'move';
e.dataTransfer.setData('text/html', e.currentTarget);
this.state.placeholder.style.height = this.dragged.offsetHeight + 'px';
}
/**
* On drag end, update the data state.
**/
dragEnd(e) {
this.dragged.style.display = 'block';
this.dragged.parentNode.removeChild(this.state.placeholder);
let from = Number(this.dragged.dataset.ind);
let to = Number(this.over.dataset.ind);
if (from < to) to--;
if (this.nodePlacement == 'after') to++;
this.sortData(from, to);
}
/**
* On drag over, update items.
**/
dragOver(e) {
e.preventDefault();
this.dragged.style.display = 'none';
if (e.target.className == 'placeholder') {
return;
}
this.over = e.target;
while ( ! this.over.classList.contains( 'sortable-items--item' ) ) {
if ( this.over.classList.contains( 'sortable-items--wrap' ) ) {
return;
}
this.over = this.over.parentNode;
}
let relY = this.dragged.offsetTop - this.over.offsetTop;
let mid = this.over.offsetHeight / 2;
let parent = this.over.parentNode;
if (relY > mid) {
this.nodePlacement = 'after';
parent.insertBefore(this.state.placeholder, this.over.nextElementSibling);
} else if (relY < mid) {
this.nodePlacement = 'before';
parent.insertBefore(this.state.placeholder, this.over);
}
}
renderItem(item, i) {
const {el} = window.Caxton;
let {
renderItem
} = this.props;
if (!renderItem) {
renderItem = item => item;
}
const props = {
key: i,
draggable: "true",
onDragEnd: this.dragEnd,
onDragStart: this.dragStart,
className: '',
'data-ind': i,
...(this.props.itemProps || {})
};
props.className += ' sortable-items--item';
return el("div", props, renderItem(item));
}
render() {
const {el} = window.Caxton;
const {data} = this.state;
const listItems = data.map((item, i) => this.renderItem(item, i));
const props = {
onDragOver: this.dragOver,
className: '',
...(this.props.wrapProps || {})
};
props.className += ' sortable-items--wrap';
return el("div", props, listItems);
}
}