提交 281f5fc7 编写于 作者: D Dan Dascalescu

Improve Meteor demo

上级 d8e70a00
# RubaXa:Sortable Meteor demo
This demo showcases the two-way integration between the reorderable list
widget [Sortable](https://github.com/RubaXa/Sortable/) and Meteor.js. Meteor
Mongo collections are updated when items are added, removed or reordered, and
the order is persisted.
It also shows list grouping and control over what lists can give or receive
elements. You can only drag elements from the list to the left onto the list
to the right.
## Usage
The example uses the local package from the checkout, so it needs to wire
up some files (`package.js` and `package.json`). This is done by the handy
run script:
### Windows
git clone git@github.com:RubaXa/Sortable.git
cd Sortable
git checkout dev
cd meteor\example
run.bat
### Elsewhere
git clone git@github.com:RubaXa/Sortable.git
cd Sortable
git checkout dev
meteor/example./run.sh
## Prior art
### Differential
Differential wrote [a blog post on reorderable lists with
Meteor](differential.com/blog/sortable-lists-in-meteor-using-jquery-ui) and
[jQuery UI Sortable](http://jqueryui.com/sortable/). It served as inspiration
for integrating [rubaxa:sortable](rubaxa.github.io/Sortable/),
which uses the HTML5 native drag&drop API (not without [its
limitations](https://github.com/RubaXa/Sortable/issues/106)).
The reordering method used by the Differential example can lead to data loss
though, because it calculates the new order of a dropped element as the
arithmetic mean of the elements before and after it. This [runs into limitations
of floating point precision](http://programmers.stackexchange.com/questions/266451/maintain-ordered-collection-by-updating-as-few-order-fields-as-possible)
in JavaScript after <50 reorderings.
### Todos animated
http://todos-dnd-animated.meteor.com/ ([source](https://github.com/nleush/meteor-todos-sortable-animation))
is based on old Meteor Blaze (back then Spark) API, and won't work with current versions.
It does showcase some neat features, such as animation when collection elements
are reordered by another client. It uses jQuery UI Sortable as well, which lacks
some features vs. rubaxa:Sortable, e.g. text selection within the item.
## TODO
* Animation
* Indication that an item is being edited
<head>
<title>RubaXa:Sortable Demo</title>
<title>Reactive RubaXa:Sortable for Meteor</title>
</head>
<body>
{{> navbar}}
<div class="container">
<div class="page-header">
<h1>Custom attributes</h1>
<h1>RubaXa:Sortable - reactive reorderable lists for Meteor</h1>
<h2>Drag attribute types from the left to define an object type on the right</h2>
<h3>Drag the <i class="sortable-handle mdi-action-view-headline"></i> handle to reorder elements</h3>
</div>
{{> typeDefinition}}
......@@ -26,7 +30,7 @@
</div>
<div class="sortable target" id="object">
{{#sortable items=attributes animation="0" handle=".sortable-handle" ghostClass="sortable-ghost" options=attributesOptions}}
{{#sortable items=attributes animation="100" handle=".sortable-handle" ghostClass="sortable-ghost" options=attributesOptions}}
{{> sortableItemTarget}}
{{/sortable}}
</div>
......@@ -34,7 +38,6 @@
</div>
</div>
</template>
<template name="sortableItemTarget">
......@@ -48,3 +51,44 @@
</button>
</div>
</template>
<template name="navbar">
<div class="navbar navbar-inverse">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-inverse-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="https://atmospherejs.com/rubaxa/sortable">RubaXa:Sortable</a>
</div>
<div class="navbar-collapse collapse navbar-inverse-collapse">
<ul class="nav navbar-nav">
<li class="active"><a href="http://rubaxa-sortable.meteor.com">Meteor Demo</a></li>
<li><a href="https://rubaxa.github.io/Sortable/" target="_blank">Sortable standalone demo</a></li>
<li class="dropdown">
<a href="javascript:void(0)" class="dropdown-toggle" data-toggle="dropdown">Source <b class="caret"></b></a>
<ul class="dropdown-menu">
<li class="dropdown-header">GitHub</li>
<li><a href="https://github.com/RubaXa/Sortable/tree/dev/meteor/example" target="_blank">This demo</a></li>
<li><a href="https://github.com/RubaXa/Sortable/tree/dev/meteor" target="_blank">Meteor integration</a></li>
<li><a href="https://github.com/RubaXa/Sortable" target="_blank">rubaxa/sortable</a></li>
<li class="divider"></li>
<li><a href="https://atmospherejs.com/rubaxa/sortable">Star this package on Atmosphere!</a></li>
</ul>
</li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li class="dropdown">
<a href="javascript:void(0)" class="dropdown-toggle" data-toggle="dropdown">Resources <b class="caret"></b></a>
<ul class="dropdown-menu">
<li><a href="http://www.meteorpedia.com/read/Packaging_existing_Libraries">Packaging 3rd party libraries for Meteor</a></li>
<li><a href="https://twitter.com/dandv">Author: @dandv</a></li>
</ul>
</li>
</ul>
</div>
</div>
</template>
\ No newline at end of file
......@@ -32,12 +32,12 @@ Template.typeDefinition.helpers({
delete event.data._id; // Generate a new id when inserting in the Attributes collection. Otherwise, if we add the same type twice, we'll get an error that the ids are not unique.
delete event.data.icon;
event.data.type = event.data.name;
event.data.name = 'Rename me'
event.data.name = 'Rename me (double click)'
},
// event handler for reordering attributes
onSort: function (event) {
console.log('Moved object %d from %d to %d',
event.data.order, event.oldIndex, event.newIndex
console.log('Item %s went from #%d to #%d',
event.data.name, event.oldIndex, event.newIndex
);
}
}
......@@ -59,17 +59,23 @@ Template.sortableItemTarget.events({
input.focus();
},
'blur input[type=text]': function (event, template) {
// commit the change to the name
// commit the change to the name, if any
var input = template.$('input');
input.hide();
template.$('.name').show();
// TODO - what is the collection here? We'll hard-code for now.
// https://github.com/meteor/meteor/issues/3303
Attributes.update(this._id, {$set: {name: input.val()}});
if (this.name !== input.val() && this.name !== '')
Attributes.update(this._id, {$set: {name: input.val()}});
},
'keydown input[type=text]': function(event) {
// ESC or ENTER
if (event.which === 27 || event.which === 13) {
'keydown input[type=text]': function (event, template) {
if (event.which === 27) {
// ESC - discard edits and keep existing value
template.$('input').val(this.name);
event.preventDefault();
event.target.blur();
} else if (event.which === 13) {
// ENTER
event.preventDefault();
event.target.blur();
}
......@@ -81,5 +87,15 @@ Template.sortable.events({
'click .close': function (event, template) {
// `this` is the data context set by the enclosing block helper (#each, here)
template.collection.remove(this._id);
// custom code, working on a specific collection
if (Attributes.find().count() === 0) {
Meteor.setTimeout(function () {
Attributes.insert({
name: 'Not nice to delete the entire list! Add some attributes instead.',
type: 'String',
order: 0
})
}, 1000);
}
}
});
../../package.json
\ No newline at end of file
......@@ -7,8 +7,8 @@ int_trap() {
}
trap int_trap INT
ln -s "meteor/package.js" ../../package.js
ln -s "../../package.json" package.json
ln -s "meteor/package.js" ../../package.js 2>/dev/null
ln -s "../../package.json" package.json 2>/dev/null
meteor run "$@"
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册