Skip to content

Instantly share code, notes, and snippets.

@katryo
Last active August 29, 2015 14:23
Show Gist options
  • Save katryo/4fb196d0971281045eb6 to your computer and use it in GitHub Desktop.
Save katryo/4fb196d0971281045eb6 to your computer and use it in GitHub Desktop.
Reactでdrag and dropでソートするサンプル。 http://webcloud.se/sortable-list-component-react-js/ をもとに作った
var AddingFeaturingButton = React.createClass({
propTypes: {
addToFeatured: React.PropTypes.func.isRequired
},
_addToFeatured: function() {
this.props.addToFeatured(this.props.position);
},
render: function() {
return(
<button className={this.props.isFeatured ? 'flat-button-success': 'flat-button'} onClick={this._addToFeatured}>
おすすめに入れる
</button>
);
}
});
var RemoveFeaturingButton = React.createClass({
_removeFromFeatured: function() {
this.props.removeFromFeatured(this.props.position);
},
render: function() {
return(
<button className="flat-button-danger" onClick={this._removeFromFeatured}>
おすすめから外す
</button>
);
}
});
var NotFeaturedStories = React.createClass({
_addToFeatured: function(position) {
this.props.addToFeatured(position);
},
render: function() {
var that = this;
var notFeaturedStories = this.props.stories
.map(function(story, index, stories) {
return(
<li key={ story.id }>
<h4>
{ story.title }
</h4>
<AddingFeaturingButton addToFeatured={ that._addToFeatured } position={ index } isFeatured={ story.isFeatured }/>
</li>
)
});
return (
<div className="col-md-6">
<ul className="list-unstyled">{notFeaturedStories}</ul>
</div>
);
}
});
var sortableListItemPlaceholder = (function() {
var p = document.createElement('li');
p.className = 'js-react-placeholder sortableList__item--placeholder';
return p;
}());
var FeaturedStories = React.createClass({
_removeFromFeatured: function(position) {
this.props.removeFromFeatured(position);
},
dragStartHandler: function(e) {
this.dragged = e.currentTarget;
e.dataTransfer.effectAllowed = 'move';
e.dataTransfer.setData("text/html", e.currentTarget);
},
dragEndHandler: function(e) {
this.dragged.style.display = "block";
if (sortableListItemPlaceholder.parentNode === this.dragged.parentNode) {
this.dragged.parentNode.removeChild(sortableListItemPlaceholder)
}
var stories = this.props.stories;
var from = Number(this.dragged.dataset.index);
var to = Number(this.over.dataset.index);
if (from < to) { to-- };
if (this.nodePlacement == 'after') { to++ };
var fromStory = stories.splice(from, 1)[0];
stories.splice(to, 0, fromStory);
this.props.updateFeaturedStories(stories);
},
dragOver: function(e) {
e.preventDefault();
this.dragged.style.display = 'none';
if (e.target.className == 'js-react-placeholder sortableList__item--placeholder') return;
if (e.target.parentNode.nodeName === 'UL') {
this.over = e.target;
e.target.parentNode.insertBefore(sortableListItemPlaceholder, e.target);
var relY = e.clientY - this.over.offsetTop;
var height = this.over.offsetHeight / 2;
var parent = e.target.parentNode;
if (relY > height) {
this.nodePlacement = 'after';
parent.insertBefore(sortableListItemPlaceholder, e.target.nextElementSibling);
} else if (relY < height) {
this.nodePlacement = 'before';
parent.insertBefore(sortableListItemPlaceholder, e.target);
}
}
},
render: function() {
var that = this;
var featuredStories = this.props.stories
.map(function(story, index, stories) {
return(
<li data-index={ index }
key={ story.id }
draggable="true"
onDragEnd={ that.dragEndHandler }
onDragStart={ that.dragStartHandler }
>
<h4>
{ story.title }
</h4>
<p>
更新前の順番: { story.position }
</p>
<p>
更新後の順番: { index }
</p>
<RemoveFeaturingButton removeFromFeatured={ that._removeFromFeatured } position={ index } isFeatured={ story.isFeatured }/>
<input name="all_story_featurings[story_featurings][][story_id]" value={story.id} type="hidden"/>
<input name="all_story_featurings[story_featurings][][position]" value={index} type="hidden"/>
</li>
)
});
return(
<div className="col-md-6">
<form action="/story_featurings/update_all" method="post">
<input type="submit" />
<ul className="list-unstyled" id="js-featuredStories" onDragOver={ this.dragOver }>{featuredStories}</ul>
</form>
</div>
);
}
});
var StoryFeaturings = React.createClass({
getInitialState: function() {
var nfs = this.props.notFeaturedStories;
if (nfs === null) { nfs = [] };
var fs = this.props.featuredStories;
if (fs === null) { fs = [] };
return {
notFeaturedStories: nfs,
featuredStories: fs
};
},
addToFeatured: function(position) {
var resultNotFeaturedStories = this.state.notFeaturedStories;
var addedStory = resultNotFeaturedStories.splice(position, 1);
var resultFeaturedStories = this.state.featuredStories.concat(addedStory);
this.setState({
notFeaturedStories: resultNotFeaturedStories,
featuredStories: resultFeaturedStories
});
},
removeFromFeatured: function(position) {
var featuredStories = this.state.featuredStories;
var removedStory = featuredStories.splice(position, 1);
var resultNotFeaturedStories = this.state.notFeaturedStories.concat(removedStory).sort(
function(a, b) {
if (a.id < b.id) {
return -1;
} else if (a.id === b.id) {
return 0;
} else {
return 1;
}
}
);
this.setState({
notFeaturedStories: resultNotFeaturedStories,
featuredStories: featuredStories
});
},
updateFeaturedStories: function(featuredStories) {
this.setState({ featuredStories: featuredStories });
},
render: function() {
var notFeatured = <NotFeaturedStories
stories={ this.state.notFeaturedStories }
addToFeatured={ this.addToFeatured }
/>;
var featured = <FeaturedStories
stories={ this.state.featuredStories }
removeFromFeatured={ this.removeFromFeatured }
updateFeaturedStories={ this.updateFeaturedStories }
/>;
return (
<div className="col-md-12">
{notFeatured}
{featured}
</div>
);
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment