JQSortable with LI that I do not render myself

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

JQSortable with LI that I do not render myself

Mariano Martinez Peck
Hi guys,

I have a html select list that then I convert to a UL / LI kind of list using Bootstrap select: https://github.com/silviomoreto/bootstrap-select

I want to make it sortable (which I could) but I cannot correctly hook onto the stop of the drop so that I can update my model/backend side. 

I am trying to do something like:

html script:  ((html jQuery id: '#myULList')
sortable
onStop: (html jQuery ajax
                   callback: [ :values | values asOrderedCollection inspect ]
                   passengers: (html jQuery this find: 'li')))

Basically...I need to get 'values' with my real objects. The problem is that since I am not rendering the LI items myself (but bootstrap select does), I cannot specify the passenger..I mean...I cannot do something like "html listItem passenger: each"  or whatever...

Any ideas how can I make it work?

Thanks in advance, 

--

_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: JQSortable with LI that I do not render myself

Johan Brichau-2
Hi Mariano,

My first question is why are you using the bootstrap select to render a list of items? If it’s not a select that you want but a sortable list, why not generate it immediately?

The bootstrap plugin is generating the html based on the html you generated in Seaside. 
In this client-side conversion step, the ids and scripts generated from Seaside are not (or cannot be) copied.

You need options in the plugin to pass callbacks. I took a quick look but I don’t see any.
If there are such options (there exist other such plugins), it still is a lot of fiddling on the client-side to hook up the right js callbacks to server-side callbacks, especially if you have more than one select to handle.

But there’s probably a good reason you are trying to do this. If that’s the case, I would try to use event delegation and put event handlers on the parent element of the select.
The plugin is probably generating the li right next to existing select but with the same parent. If that is the case, you can put jQuery event handlers on that parent element (which you generate from Seaside.
Something like:

html div
script: (html jQuery this) on: ‘click’ do: (html jQuery ajax callback:[ … ])
       with: [ self renderSelectOn: html ]

It probably will require some more complex handling with respect to getting the correct events sorted out…
I did not try these things, so I hope this helps

cheers,
Johan

On 16 Jan 2015, at 16:54, Mariano Martinez Peck <[hidden email]> wrote:

Hi guys,

I have a html select list that then I convert to a UL / LI kind of list using Bootstrap select: https://github.com/silviomoreto/bootstrap-select

I want to make it sortable (which I could) but I cannot correctly hook onto the stop of the drop so that I can update my model/backend side. 

I am trying to do something like:

html script:  ((html jQuery id: '#myULList')
sortable
onStop: (html jQuery ajax
                   callback: [ :values | values asOrderedCollection inspect ]
                   passengers: (html jQuery this find: 'li')))

Basically...I need to get 'values' with my real objects. The problem is that since I am not rendering the LI items myself (but bootstrap select does), I cannot specify the passenger..I mean...I cannot do something like "html listItem passenger: each"  or whatever...

Any ideas how can I make it work?

Thanks in advance, 

--
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside


_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: JQSortable with LI that I do not render myself

Mariano Martinez Peck


On Sat, Jan 17, 2015 at 6:26 AM, Johan Brichau <[hidden email]> wrote:
Hi Mariano,

My first question is why are you using the bootstrap select to render a list of items? If it’s not a select that you want but a sortable list, why not generate it immediately?

Hi Johan,

Good question. Originally I was using plain HMTL selects. Then it become a requirement to also have a kind of multi-selection list but not that one that looks like a area and that uses a lot of height space. The ideal was a kind of dropdown list with multiselect support. And finally, if that would be sortable, that would be even cooler because we also needed that. We were already using http://silviomoreto.github.io/bootstrap-select/  because it makes lists nicer. And then I found out that such a lib also supports multiselection and filtering. I just needed to add sorting. Then...all my previous code that I had using lists... could be very easily updated to use this. 
 

The bootstrap plugin is generating the html based on the html you generated in Seaside. 
In this client-side conversion step, the ids and scripts generated from Seaside are not (or cannot be) copied.

You need options in the plugin to pass callbacks. I took a quick look but I don’t see any.
If there are such options (there exist other such plugins), it still is a lot of fiddling on the client-side to hook up the right js callbacks to server-side callbacks, especially if you have more than one select to handle.

Indeed, I searched for callbacks too in the lib....
 

But there’s probably a good reason you are trying to do this. If that’s the case, I would try to use event delegation and put event handlers on the parent element of the select.
The plugin is probably generating the li right next to existing select but with the same parent. If that is the case, you can put jQuery event handlers on that parent element (which you generate from Seaside.
Something like:

html div
script: (html jQuery this) on: ‘click’ do: (html jQuery ajax callback:[ … ])
       with: [ self renderSelectOn: html ]

It probably will require some more complex handling with respect to getting the correct events sorted out…
I did not try these things, so I hope this helps

That's something I didn't think about. Thanks for sharing. 

That being said...I did find a "workaround" (or hack?) that did work...I will share it in case someone finds it useful.

1) First I render the html select and I apply the bootstrap lib (from here http://silviomoreto.github.io/bootstrap-select/), setting the mutliselection option and the filter capability. 

2) Then, this hack:

"this is a hack because Bootstrap-select does not set an ID to the LI elements and I need those in order to associate 
passengers to my target objects for the events. "
html script: '
($(''#', select id, ''').parent().find(''.inner li'')).each(function(i, item) {
  $(this).attr(''id'', ''', select id, '_'' + ($(item).attr(''data-original-index'')) );
});
'.

Basically....I manually assign an ID to each generated LI. 

3) Then....another hack:

"This is another hack because I DO NOT render myself each LI element but instead it is automaticallty done by
Bootstrap-select from our html select. So....I must explicitly register a passenger for each LI"
self availableListInOrder doWithIndex: [ :each :index | 
html callbacks registerPassenger: each named: (select id, '_', (index-1) asString) ].
Basically...I register my objects as passengers at the IDs I have just assigned above.


Then...for the sorting feature, I do something like this:

html script:  (((html jQuery id: select id) parent find: '.inner')
sortable
onBeforeStop: (html jQuery ajax
callback: [ :values | 
self availableListInOrder: values.
self reSortListSelectedWith: values.
]
                 passengers: (((html jQuery id: select id) parent find: '.inner') find: 'li')

);

Here the magic is to use #callback:passengers:  

And the same must be used for the onChange: of the select list:

select
onChange:  
               (html jQuery ajax
serializeForm;
      script: [ :s |  
self listChangeCallback ifNotNilDo: [ :aBlock | aBlock value: s ].
self reRenderEditorScriptUsing: s.
];
callback: [ :values | self setSelectedItemsBlock value: values ]
    passengers: ((((html jQuery id: select id) parent find: '.inner') find: 'li') filter: '.selected')
);

 


So...it's kind of a black magic I think...but I encapsulated everything in a MultiSelectionComponent where I can hook everything so it works nicely. 

Too much hacky? 



cheers,
Johan

On 16 Jan 2015, at 16:54, Mariano Martinez Peck <[hidden email]> wrote:

Hi guys,

I have a html select list that then I convert to a UL / LI kind of list using Bootstrap select: https://github.com/silviomoreto/bootstrap-select

I want to make it sortable (which I could) but I cannot correctly hook onto the stop of the drop so that I can update my model/backend side. 

I am trying to do something like:

html script:  ((html jQuery id: '#myULList')
sortable
onStop: (html jQuery ajax
                   callback: [ :values | values asOrderedCollection inspect ]
                   passengers: (html jQuery this find: 'li')))

Basically...I need to get 'values' with my real objects. The problem is that since I am not rendering the LI items myself (but bootstrap select does), I cannot specify the passenger..I mean...I cannot do something like "html listItem passenger: each"  or whatever...

Any ideas how can I make it work?

Thanks in advance, 

--
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside


_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside




--

_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside