+sub sortable_element {
+ my ($self, $selector, %params) = _hashify(2, @_);
+
+ my %attributes = ( distance => 5,
+ helper => <<'JAVASCRIPT' );
+ function(event, ui) {
+ ui.children().each(function() {
+ $(this).width($(this).width());
+ });
+ return ui;
+ }
+JAVASCRIPT
+
+ my $stop_event = '';
+
+ if ($params{url} && $params{with}) {
+ my $as = $params{as} || $params{with};
+ my $filter = ".filter(function(idx) { return this.substr(0, " . length($params{with}) . ") == '$params{with}'; })";
+ $filter .= ".map(function(idx, str) { return str.replace('$params{with}_', ''); })";
+
+ my $params_js = $params{params} ? qq| + ($params{params})| : '';
+ my $ajax_return = '';
+ if ($params{ajax_return}) {
+ $ajax_return = 'kivi.eval_json_result';
+ }
+
+ $stop_event = <<JAVASCRIPT;
+ \$.post('$params{url}'${params_js}, { '${as}[]': \$(\$('${selector}').sortable('toArray'))${filter}.toArray() }, $ajax_return);
+JAVASCRIPT
+ }
+
+ if (!$params{dont_recolor}) {
+ $stop_event .= <<JAVASCRIPT;
+ \$('${selector}>*:odd').removeClass('listrow1').removeClass('listrow0').addClass('listrow0');
+ \$('${selector}>*:even').removeClass('listrow1').removeClass('listrow0').addClass('listrow1');
+JAVASCRIPT
+ }
+
+ if ($stop_event) {
+ $attributes{stop} = <<JAVASCRIPT;
+ function(event, ui) {
+ ${stop_event}
+ return ui;
+ }
+JAVASCRIPT
+ }
+
+ $params{handle} = '.dragdrop' unless exists $params{handle};
+ $attributes{handle} = "'$params{handle}'" if $params{handle};
+
+ my $attr_str = join(', ', map { "${_}: $attributes{$_}" } keys %attributes);
+
+ my $code = <<JAVASCRIPT;
+<script type="text/javascript">
+ \$(function() {
+ \$( "${selector}" ).sortable({ ${attr_str} })
+ });
+</script>
+JAVASCRIPT
+
+ return $code;
+}
+
+sub dump {
+ my $self = shift;
+ return '<pre>' . Data::Dumper::Dumper(@_) . '</pre>';
+}
+
+sub sortable_table_header {
+ my ($self, $by, %params) = _hashify(2, @_);
+
+ my $controller = $self->{CONTEXT}->stash->get('SELF');
+ my $models = $params{models} || $self->{CONTEXT}->stash->get('MODELS');
+ my $sort_spec = $models->get_sort_spec;
+ my $by_spec = $sort_spec->{$by};
+ my %current_sort_params = $models->get_current_sort_params;
+ my ($image, $new_dir) = ('', $current_sort_params{dir});
+ my $title = delete($params{title}) || $::locale->text($by_spec->{title});
+
+ if ($current_sort_params{sort_by} eq $by) {
+ my $current_dir = $current_sort_params{sort_dir} ? 'up' : 'down';
+ $image = '<img border="0" src="image/' . $current_dir . '.png">';
+ $new_dir = 1 - ($current_sort_params{sort_dir} || 0);
+ }
+
+ $params{ $models->sorted->form_params->[0] } = $by;
+ $params{ $models->sorted->form_params->[1] } = ($new_dir ? '1' : '0');
+
+ return '<a href="' . $models->get_callback(%params) . '">' . _H($title) . $image . '</a>';
+}
+
+sub paginate_controls {
+ my ($self, %params) = _hashify(1, @_);
+
+ my $controller = $self->{CONTEXT}->stash->get('SELF');
+ my $models = $params{models} || $self->{CONTEXT}->stash->get('MODELS');
+ my $pager = $models->paginated;
+# my $paginate_spec = $controller->get_paginate_spec;
+
+ my %paginate_params = $models->get_paginate_args;
+
+ my %template_params = (
+ pages => \%paginate_params,
+ url_maker => sub {
+ my %url_params = _hashify(0, @_);
+ $url_params{ $pager->form_params->[0] } = delete $url_params{page};
+ $url_params{ $pager->form_params->[1] } = delete $url_params{per_page} if exists $url_params{per_page};
+
+ return $models->get_callback(%url_params);
+ },
+ %params,
+ );
+
+ return SL::Presenter->get->render('common/paginate', %template_params);
+}
+