Persisting DragSortable Lists

93 views
Skip to first unread message

Tobias Beer

unread,
Mar 7, 2013, 8:02:54 AM3/7/13
to tiddly...@googlegroups.com
Hi everyone,

Dragging and sorting (nested) lists has been available in jQuery for quite some time via plugins.

Following PMario's post here [1]...

...the topics / questions for this discussion are:

A) Are there existing implementations for persisting the sort order of draggable lists TW?

B) What are the methods for persisting the sort order? What seems generally required, method-wise?

C) Are these methods generic enough to be reused by the core and plugins?


...and for @PMario...

D) What are these (proposed / implemented / core) methods (of yours) and where are they implemented?


Cheers, Tobias.


[1]
Am Donnerstag, 7. März 2013 11:55:37 UTC+1 schrieb PMario:
Hi Tobias, 
I'd want to talk with you about this. I did similar things with my 
XListPlugin [1], but made it compatible to core list macro, so it can 
handle the sort order. There is no need for someone to use XListPlugin 
to get the desired result. Which makes it good to use with eg: 
TiddlySpace. 

I did also contribute some code to the core, that was accepted, that 
lets you do drag and drop sorting without any additional <<list>> 
plugins like XListPlugin. There is enough information in the default 
rendering now to get it to work. 

For the @chat project (a year ago), I did introduce a uniqe id for 
tiddlers, that isn't changed, even if you do change its name. 

It would be nice, if we could make our stuff compatible, otherwise we 
will end up having a lot of custom fields that don't play together, 
and implement redundant functionality. 

-m 
[1] http://apm-plugins.tiddlyspot.com/#XListPlugin 
[2] http://chat.tiddlyspace.com/ 

Tobias Beer

unread,
Mar 7, 2013, 8:06:43 AM3/7/13
to tiddly...@googlegroups.com
As I suggested to Adam here...

...this would be my approach to tackle persistence:
  1. save an unchangeable hash (as a custom field) to each tiddler
    • so as to be able to identify a tiddler even after name changes
  2. save order as well as state information in (a custom field of the) list tiddler containing references to hashes in 1)
    • could be a simple field with multi-line content like...
    • item order:
      • hash1
      • hash2
      • hash3
Things to notice:
  1. There may be multiple lists, so the tiddler containing them may need a number of custom 'item-order' fields
    • I would suggest some generic way to generate a unique id
    • or let the user define a unique I just as he would for chkSomeSlider or txtSomeTabs
  2. Saving an ordered list for the first time may reuire to write changes to a number of tiddlers
    • how can this be achieved with maximum usability / optimized performance in mind
    • is there even a performance issue?
Cheers, Tobias.

Tobias Beer

unread,
Mar 7, 2013, 8:14:34 AM3/7/13
to tiddly...@googlegroups.com
@PMario,

I can't seem to find any documentation or example on...

...that demonstrates it, not to mention dragsorting and persistence.

Cheers, Tobias.

whatever

unread,
Mar 7, 2013, 9:06:23 AM3/7/13
to tiddly...@googlegroups.com
Hi!

The examples are sort of hidden, but they are there. Open the StylingPackage (1) tiddler and look under Bookmarks section. It contains the actual controls for starting drag-sorting. Once you activate the styling and start sorting, open the XListPluginTest (2) tiddler and drag-sort the lists. Then cancel or save the sort order with the controls in the StylingPackage tiddler. The plugin uses custom fields to persist the sort order.

(1) http://apm-plugins.tiddlyspot.com/#StylingPackage
(2) http://apm-plugins.tiddlyspot.com/#XListPluginTest

w

Tobias Beer

unread,
Mar 7, 2013, 9:36:06 AM3/7/13
to tiddly...@googlegroups.com
Hi whatever,

I see, seems very complicated as compared to using dragsort like TiddlyKanban [1]... which however doesn't persist changes.

I am pretty sure that I don't want to ...
  • use browser bookmarks for managing lists
  • depend on lazy-loading the jQuery-UI heavy-weight
Quickly skimming through the code, I see some sortField variable but I can't find how the list order is persisted at all.

By the way, somehow clicking on a tiddlyLink in the story column, the view doesn't actually scroll to the tiddler but only runs the animation on the currently displayed tiddler on top while opening the tiddler at the bottom... very weird.

Cheers, Tobias.

whatever

unread,
Mar 7, 2013, 10:10:42 AM3/7/13
to TiddlyWikiDev
Hi,

The plugin actually creates a custom field defined in the parameters.
That field is added to all the tiddlers that are listed in that list.
It contains a four-digit number.
For example:
<<xList xCase "sort." "." "[tag[with spaces]]">>
adds the "sort.with.spaces" field to the all the tiddlers in that
list. That field contains a sequential four-digit number that changes
if you drag-sort.
Obviously, you need to specify a unique field name for each list.

As for activating bookmarks and stuff, I simply transcluded the
Bookmarks section.

hth
w

On Mar 7, 3:36 pm, Tobias Beer <beertob...@gmail.com> wrote:
> Hi whatever,
>
> I see, seems very complicated as compared to using dragsort like
> TiddlyKanban [1]... which however doesn't persist changes.
>
> I am pretty sure that I don't want to ...
>
>    - use browser bookmarks for managing lists
>    - depend on lazy-loading the jQuery-UI heavy-weight
>
> Quickly skimming through the code, I see some sortField variable but I
> can't find how the list order is persisted at all.http://apm-plugins.tiddlyspot.com/#XListPlugin
>
> By the way, somehow clicking on a tiddlyLink in the story column, the view
> doesn't actually scroll to the tiddler but only runs the animation on the
> currently displayed tiddler on top while opening the tiddler at the
> bottom... very weird.http://apm-plugins.tiddlyspot.com/#XListPluginTest

Tobias Beer

unread,
Mar 7, 2013, 10:22:05 AM3/7/13
to tiddly...@googlegroups.com
Hi w,

The plugin actually creates a custom field defined in the parameters.
That field is added to all the tiddlers that are listed in that list.
It contains a four-digit number.
 
I could swear I have looked for just that and couldn't find it. Now it kind of dawn's on me why: I probably never hit that save bookmark.

Anyhow, from my perspective, this approach is not so good as it involves saving each tiddler every time the list order is changed. Also, retrieving the order involves fetching the field from a number of tiddlers.

The method I described above, the 'hash' field would only need to be created the first time it is needed. The sort order would be saved at the tiddler where the list is actually being used. I find that more intuitive, I must say... and it avoids a lot of excessive saving changes to listed tiddlers... that are actually not affected other than being sorted in some remote list.

Cheers, Tobias.

whatever

unread,
Mar 7, 2013, 11:07:34 AM3/7/13
to TiddlyWikiDev
I'm just telling you how it works since I've used it before.:D You'll
have to talk details with Mario.
Anyway, yours is an interesting solution. I look forward to seeing
what you come up with.
w

On 7 mar., 16:22, Tobias Beer <beertob...@gmail.com> wrote:
> Hi w,
>
> The plugin actually creates a custom field defined in the parameters.
>
> > That field is added to all the tiddlers that are listed in that list.
> > It contains a four-digit number.
>
> I could swear I have looked for just that and couldn't find it. Now it kind
> of dawn's on me why: I probably never hit that save bookmark.
>
> Anyhow, from my perspective, this approach is not so good as it involves
> saving each tiddler every time the list order is changed. Also, retrieving
> the order involves fetching the field from a number of tiddlers.
>
> The method I described above, the '*hash*' field would only need to be

Yakov

unread,
Mar 7, 2013, 3:25:57 PM3/7/13
to tiddly...@googlegroups.com
Hi Tobias,

that's a very intersting topic, although I don't know any existing code to suggest. My view on how this should work is based on the fact that there are different way to create lists (for instance, forEachTiddlerPlugin). That's why I'd expect manual sorting to be somewhat external for the list-creating engine (it can be "wikitext list" or list macro or any other macro). So the idea is that it can either a macro to be put before/after the list:

<<sortList>>
* first item
* second item

<<sortList>>
<<list filter "...">>

etc or an engine that is applied to each list and doesn't require any wiki markup at all. Second design question is where and how (in what format) to store the list order. In the case of a <<sortList>> macro that's quite simple: either as a param: <<sortList someParamDescribingCurrentOrder>> or in a cookie: <<sortList txtOrderOfThisList>>. But more puzzling question is how to store the data about the order? Even if that's a wikitext list, the order can be some sort of hashmap:

<<sortList {{ {
i1: "fir",
i2: "sec"
} }}>>

actually, in this example that's enough to store just "f" and "s" to distinguish; but what if the list is changed?

* first
* forth

what order to apply? And if the list is auto-aggregated, this becomes even harder to figure how to store the order..

Although, when the length of the list is fixed, the order can be stored as a permutation:

<<sortList {{ {
i1: 2,
i2: 1
} }}>>

but things like <<list filter "[tag[myTag]]">> won't work well with this..

Best regards,
Yakov.

четверг, 7 марта 2013 г., 17:02:54 UTC+4 пользователь Tobias Beer написал:

PMario

unread,
Mar 7, 2013, 6:28:28 PM3/7/13
to tiddly...@googlegroups.com


On Thursday, March 7, 2013 4:22:05 PM UTC+1, Tobias Beer wrote:
I could swear I have looked for just that and couldn't find it. Now it kind of dawn's on me why: I probably never hit that save bookmark.

You are right. The last time I did upload the stuff to TiddlySpot, it seems I didn't create the sort fields first. So they are gone. :/ I'll need to fix that.

I did create a 3min video, that shows how it works. https://www.youtube.com/watch?v=jfXAACS2TGk

I did the lazy loading, because sorting isn't used all the time and I don't want to include jQueryUI because of its size.

-m


Adam S.

unread,
Mar 7, 2013, 6:44:35 PM3/7/13
to tiddly...@googlegroups.com
I was able to create a sortable list using the jQuery sortable() method. I could not find documentation on creating/accessing custom tiddler fields in JS.  so instead, I created a hidden div to store the sort order.  Something like this:

<html>
<style>
.hidden {
    display:none;
}
</style>

<ul id="sortable"></ul>
<div id="sortOrder" class="hidden"></div>
</html>


I then access the list with:

var arr = jQuery("#sortOrder").html().split("|");

and write changes back with:

var data = jQuery("#sortable li").map(function() { return jQuery(this).html(); }).get();
var serialStr = data.join("|");   
jQuery("#sortOrder").html(serialStr);


I suppose using the hidden div is a bit of a hack—but it seams to works fine.

Adam S.

unread,
Mar 8, 2013, 1:26:05 PM3/8/13
to tiddly...@googlegroups.com
Hi Tobias,

Does TW have methods for reading/writing to custom fields? Or is this the nature of the plugin your are working on?

Thanks,
-Adam

Eric Shulman

unread,
Mar 8, 2013, 3:08:31 PM3/8/13
to TiddlyWikiDev
> Does TW have methods for reading/writing to custom fields?

store.getValue(tiddler,fieldName)
* returns stored string value for the given fieldname
* returns undefined if fieldname does not exist

store.setValue(tiddler,fieldName,value)
* sets the value of the given field of the tiddler to the value
* fieldnames are case sensitive
* all values are converted and stored as strings
* use a value of null or undefined to remove the field.
* setting a namespace[1] to undefined removes all fields of that
namespace

[1] custom tiddler fields allow for "grouping" fields into
"namespaces" by adding a "spacename." prefix before the fieldname,
like this:
store.setValue("SomeTiddler","somespace.foo","...");
store.setValue("SomeTiddler","somespace.bar","...");
store.setValue("SomeTiddler","somespace.baz","...");
The above code creates three custom fields, all starting with the same
"namespace" prefix.

For most uses, fieldnames that have a namespace prefix are handled the
same as other fields... the prefix is treat as just another part of
the fieldname. However, in addition to simply setting/clearing values
by referencing the individual custom fields one at a time, like this:
store.setValue("SomeTiddler","somespace.foo",null);
store.setValue("SomeTiddler","somespace.bar",null);
store.setValue("SomeTiddler","somespace.baz",null);
you can also use store.setValue(...) to clear an entire namespace in
one call, like this:
store.setValue("SomeTiddler","somespace",null);

enjoy,
-e
Eric Shulman
TiddlyTools / ELS Design Studios

HELP ME TO HELP YOU - MAKE A CONTRIBUTION TO MY "TIP JAR"...
http://www.TiddlyTools.com/#Donations

Professional TiddlyWiki Consulting Services...
Analysis, Design, and Custom Solutions:
http://www.TiddlyTools.com/#Contact

Adam S.

unread,
Mar 8, 2013, 10:53:07 PM3/8/13
to tiddly...@googlegroups.com
Thanks Eric! That's exactly what I needed.

Best,
-Adam
Reply all
Reply to author
Forward
0 new messages