EzDevInfo.com

knockout-sortable

A Knockout.js binding to connect observableArrays with jQuery UI sortable functionality

Knockout.js nested sortable bindings

I am working with the knockout.js sortable plugin; however, I ran into a problem that I have so far been unable to solve. I have two sortable bindings, one for buckets and another for bucketItems. I am able to reorder bucketItems between buckets; however, I am unable to reorder buckets. Would you have any idea why this would be? I am also using nested with bindings, but as far as I can tell, this is not what is causing problems.

I would greatly appreciate any insight you have to offer.


Source: (StackOverflow)

Knockout "if" binding doesn't work with expression in a sortable list?

I just run into another problem with my To-do-like sortable list made with Knockout and Knockout-sortable plugin.

I need to put a red delimiter under the element placed in the current time and cancel the sort if a element is dropped before that delimiter.

I tried with a "visible" binding and it works in some way, but the visibile binding just hide the DOM element and it mess up the sortable arrayIndex, adding unnecessary element to it.

<div class="delimiter" data-bind="visible: time() == $root.limit()"></div>

The "if" binding would be better because it insert DOM element only if necessary, but the expression I used with visible is always evaluated to true and I can't figure out why...

<div class="delimiter" data-bind="if: time() == $root.limit()"></div>

Here is the fiddle: http://jsfiddle.net/ingro/VaqqF/

Any help is appreciated, thank you!


Source: (StackOverflow)

Advertisements

Require a single module from a bundled library (i.e. jquery-ui)

I am creating an application with durandal, which means I'm using requirejs. I decided to use the mighty knockout-sortable plugin. As it turns out, it uses jquery-ui features internally, which is nice. I also have defined the whole jquery-ui package in my app, so in my requirejs configuration it figures as

"jqueryui": "../Scripts/jquery-ui-1.10.3.custom",

What is more, the plugins author is using AMD loading to get jquery.ui.sortable, and here's the problem. The jquery-ui doesn't seem to define itself with requirejs, neither the whole package nor single modules.

Do I have to import any module from jquery-ui separately and for each define path in requirejs config so it is explicitly visible or is there a way to tell requirejs that there's already this jquery.ui.sortable module around inside jquery-ui that the plugin is asking for?


Source: (StackOverflow)

Observable array of draggable items and dropping values onto sortable list items

I've been playing with Ryan Niemeyer's excellent knockout-sortable plugin and the draggable example in particular.

I'm looking to achieve two things:

  1. Create an observable array of draggable items.
  2. Rather than drag items into the sortable list, I want to drop dragged items onto items in the sortable list and replace their value.

In the below fiddle, I've begun the first objective but the Text: name binding doesn't work. I'd appreciate any guidance with this and the second objective.

http://jsfiddle.net/AC49j/125/


Source: (StackOverflow)

Trigger a click event from jQuery UI to knockout.js

Using the code example from Jquery-ui sortable doesn't work on touch devices based on Android or IOS to touch enable jQuery UI sortables on iOS devices, there is a problem when registering a knockout.js click handler as well as the jQuery UI sortable on the same elements. The knockout.js handler doesn't fire on touch enabled devices, but does on desktops/laptops.

Adding a flag called moved it is possible to track when a click handler needs triggered, marked with // TRIGGER HERE below:

/*
 * Content-Type:text/javascript
 *
 * A bridge between iPad and iPhone touch events and jquery draggable,
 * sortable etc. mouse interactions.
 * @author Oleg Slobodskoi
 *
 * modified by John Hardy to use with any touch device
 * fixed breakage caused by jquery.ui so that mouseHandled internal flag is reset
 * before each touchStart event
 *
 */
(function( $ ) {

  $.support.touch = typeof Touch === 'object';

  if (!$.support.touch) {
      return;
  }

  var proto =  $.ui.mouse.prototype,
  _mouseInit = proto._mouseInit
  moved = true;

  $.extend( proto, {
    _mouseInit: function() {
      this.element
      .bind( "touchstart." + this.widgetName, $.proxy( this, "_touchStart" ) );
      _mouseInit.apply( this, arguments );
    },

    _touchStart: function( event ) {
      if ( event.originalEvent.targetTouches.length != 1 ) {
        return false;
      }

      this.element
      .bind( "touchmove." + this.widgetName, $.proxy( this, "_touchMove" ) )
      .bind( "touchend." + this.widgetName, $.proxy( this, "_touchEnd" ) );

      this._modifyEvent( event );

      $( document ).trigger($.Event("mouseup")); //reset mouseHandled flag in ui.mouse
      this._mouseDown( event );

      moved = false;

      return false;
    },

    _touchMove: function( event ) {
      this._modifyEvent( event );
      this._mouseMove( event );
      moved = true;
    },

    _touchEnd: function( event ) {
      this.element
      .unbind( "touchmove." + this.widgetName )
      .unbind( "touchend." + this.widgetName );
      this._mouseUp( event );
      if (! moved) {
        // TRIGGER HERE
      }
    },

    _modifyEvent: function( event ) {
      event.which = 1;
      var target = event.originalEvent.targetTouches[0];
      event.pageX = target.clientX;
      event.pageY = target.clientY;
    }

  });

})( jQuery );

The problem is, how do you trigger a click event to knockout.js from jQuery UI?

I've tried this.element.click(), this.element.get().click(), this.element.trigger("click"), etc to no avail.

Update:

Hacked the code to:

  • track the actual target as html.element doesn't appear to be the correct one
  • trigger click events on the correct target

Now it works fine with knockout.js's click event.

/*
 * Content-Type:text/javascript
 *
 * A bridge between iPad and iPhone touch events and jquery draggable,
 * sortable etc. mouse interactions.
 * @author Oleg Slobodskoi
 *
 * modified by John Hardy to use with any touch device
 * fixed breakage caused by jquery.ui so that mouseHandled internal flag is reset
 * before each touchStart event
 *
 */
(function( $ ) {

  $.support.touch = typeof Touch === 'object';

  if (!$.support.touch) {
      return;
  }

  var proto =  $.ui.mouse.prototype,
  _mouseInit = proto._mouseInit
  moved = true,
  currentTarget = null;

  $.extend( proto, {
    _mouseInit: function() {
      this.element
      .bind( "touchstart." + this.widgetName, $.proxy( this, "_touchStart" ) );
      _mouseInit.apply( this, arguments );
    },

    _touchStart: function( event ) {
      if ( event.originalEvent.targetTouches.length != 1 ) {
        return false
      }

      this.element
      .bind( "touchmove." + this.widgetName, $.proxy( this, "_touchMove" ) )
      .bind( "touchend." + this.widgetName, $.proxy( this, "_touchEnd" ) );

      this._modifyEvent( event );

      $( document ).trigger($.Event("mouseup")); //reset mouseHandled flag in ui.mouse
      this._mouseDown( event );

      moved = false;

      return false;
    },

    _touchMove: function( event ) {
      this._modifyEvent( event );
      this._mouseMove( event );
      moved = true;
    },

    _touchEnd: function( event ) {
      this.element
      .unbind( "touchmove." + this.widgetName )
      .unbind( "touchend." + this.widgetName );
      this._mouseUp( event );
      if (! moved) {
        $(currentTarget).click();
      }
    },

    _modifyEvent: function( event ) {
      event.which = 1;
      var target = event.originalEvent.targetTouches[0];
      currentTarget = target.target;
      event.pageX = target.clientX;
      event.pageY = target.clientY;
    }

  });

})( jQuery );

Source: (StackOverflow)

How to use jquery ui with requireJS and knockout-sortable?

I'm trying to use requireJS to manage dependencies in my first ever single-page javascript app. Having never used requireJS before, I'm struggling with something that I think is quit basic.

My project uses knockoutJS, and an addon called knockout-sortable, which provides knockout bindings for the jquery ui 'sortable' plugin. It all works fine when I just load jquery ui, knockout and everything else without requireJS.

My require main.js looks like this:

require.config({
    baseUrl: '/Scripts',
    paths: {
        jQuery: 'jquery-2.1.3',
        jQueryUI: 'jquery-ui-1.10.2',
        knockout: 'knockout-3.3.0',
        knockoutSortable: 'knockout-sortable',
        AppViewModel: 'app/AppViewModel'
    },
    shim: {
        "jQueryUI": {
            export: "$",
            deps: ['jQuery']
        },
        "knockoutSortable": {
            export: ["ko"],
            deps: ['jQuery','jQueryUI']
        },
    }
});


require(['jQuery', 'jQueryUI', 'knockoutSortable', 'AppViewModel'], function ($, ui, ko, AppViewModel) {
    ko.applyBindings(new AppViewModel());
});

But I get an error in my javascript that states:

GET http://localhost:8020/Scripts/jquery-ui/draggable.js 
require.js:166 Uncaught Error: Script error for: jquery-ui/draggable
http://requirejs.org/docs/errors.html#scripterror
require.js:1910 GET http://localhost:8020/Scripts/jquery-ui/sortable.js 
require.js:166 Uncaught Error: Script error for: jquery-ui/sortable
http://requirejs.org/docs/errors.html#scripterror

I'm guessing that knockout-sortable somehow requires the dependency jquery.ui/sortable.js, but that file doesn't exist, since jquery-ui is only one file!

This page https://learn.jquery.com/jquery-ui/environments/amd/ also suggests that I should organize my jquery ui files into some kind of folder structure, but I just have one jquery ui file, so I have no idea how to do that.

By the way: I'm using ASP.NET MVC 5 in visual studio, that why my scripts are in a 'Script' folder and not in a 'JS' folder. I've updated jquery, jquery ui and knockout to the latest versions using NuGet, and I've manually upgraded knockout-sortable to version 0.11, since that was released 4 days ago and is not yet available on nuget.

Does someone know what is going on here and how to fix it?


Source: (StackOverflow)

Add one last tab to a sortable tabbed list

I'm using twitter bootstrap, knockout, knockout-sortable, and JQuery UI (also haml but it's inconsequential to the question). I display a tabbed list like the following. It adds a final tab with a button inside.

%ul.nav.nav-tabs
  /ko foreach: pages
  %li
    %span{ "data-bind" => "text: name()" }
  / /ko
  %li
    %button.btn
      %i.icon-plus

I'm trying to make the tabs sortable (via dragging) but I'm running into problems with the button:

%ul.nav.nav-tabs{ "data-bind" => "sortable: pages" }
  %li
    %span{ "data-bind" => "text: name()" }
  /%li
  /  %button.btn
  /    %i.icon-plus

I can't use /ko sortable: pages because it doesn't work (The binding 'sortable' cannot be used with virtual elements). How can I achieve the same effect (last tab being a button) with sortable? Can't move the final tab/button though.

The answer may not have to be adding a tab, it could be adding an element that appears at the end of the tabs.

Update:

JSFiddle: http://jsfiddle.net/pbNvz/6/


Source: (StackOverflow)

Knockout-Sortable catch complex Objects

I'm using Knockout.js for my page. My ViewModel contains an Array of Objects. Each Object contains an Array of Childs. More general this should represent a table containing columns and the column-contents.

first i'm dealing with foreach:itemArray to get the Columns. Then i'm using a nested foreach:childs, where childs is the array of column-contents.

My Childs should be draggable between the Columns. Therefore i replaced the nested foreach with a js i found

https://github.com/rniemeyer/knockout-sortable

http://jsfiddle.net/rniemeyer/Jr2rE/

Again with code - first stage:

<div id="lanesContainer" data-bind="foreach: lanes">

Then following the nested foreach (within #lanesContainer)

<ul data-bind="sortable: { template: 'laneTemplate', data: childs, afterMove: $root.dropCallback }">

My Items are now draggable, but dropping is somehow failing. My Debugger breaks at the following part of the js:

//take destroyed items into consideration
if (!templateOptions.includeDestroyed) {
  targetUnwrapped = targetParent();
  for (i = 0; i < targetIndex; i++) {
    //add one for every destroyed item we find before the targetIndex in the target array
    if (targetUnwrapped[i] && targetUnwrapped[i]._destroy) {
      targetIndex++;
    }
  }
}

It breaks at third line, because targetParent is an Object, not a function. How can i solve the Problem?


Source: (StackOverflow)

CancelDrop with KnockoutSortable

I'm trying to get the cancelDrop option to work with the Knockout sortable binding. Right now, just for debugging, I'm trying to cancel all moves.

This is my markup

<ol class="toc-child" 
     data-bind="sortable: {template: 'listTemplate', data:children, isEnabled: $root.allowEditing, beforeMove: beforeMove }"></ol>

and this is my beforeMove function

this.beforeMove = function(arg, b, c){
    //debugger;
    arg.cancelDrop = true;
};

When I un-comment the debugger statement, I can see the function hit, I can see the cancelDrop property get set, and I even see

if (arg.cancelDrop) {
    $(ui.sender).sortable('cancel');
    return;
}

execute as it should. But the move stays.

What's especially odd is that the beforeMove function seems to get called after the moved item has been planted in its new spot. Should I expect to see this get called before that point?


Source: (StackOverflow)

Knockout sortable array not displaying nested elements correctly

I'm new to Knockout.js, and recently I've started working with JQuery and the knockout-sortable project. For my project, I'm using a complex data structure to display some forms. At one point, I'm trying to make a nested sortable array of pages that contain questions. I am able to get a container that holds all of the pages and their information, but I am having trouble getting the container to show the questions correctly.

I the following is in the HTML:

                <h2><span data-bind="text: DiscoveryFormUpdateLabel"></span></h2>
                <div class="pagesList" data-bind="foreach:discoveryForm">
                    <div class="row">
                        <div class="text-area">
                            <label>Discovery Form Name: </label>
                            <input data-bind="value:Name" width="400" />
                        </div>
                    </div>
                    <br />
                    <br />
                    <br />
                    <div class="row">
                        <div class="text-area">
                            <label>Welcome (HTML):</label>
                            <textarea data-bind="value: Welcome" rows="12" cols="89"></textarea>
                        </div>
                    </div>
                </div>

                <ul data-bind="sortable: {template: 'pages', data:discoveryFormPages}"></ul>

                 <script type="text/html" id="pages">
                    <li>
                        <div class="row">
                            <label>Name: </label>
                            <input data-bind="value:Name" />
                        </div>

                        <div class="row">
                            <label>Questions:</label>
                        </div>

                        <ul data-bind="sortable: {foreach:Questions}">
                            <li>Foo</li>
                        </ul>

                        <ul data-bind="foreach:Questions">
                            <li>Foo</li>
                        </ul>

                        <ul data-bind="sortable: { template: 'questions', foreach:Questions}" width="80%"></ul>
                    </li>
                </script>

                <script type="text/html" id="questions">
                    <li>
                        <div class="row">
                            <label>Subject:</label>
                            <textarea data-bind="value:Subject" cols="45"></textarea>
                        </div>
                        <div class="row">
                            <label>Type:</label>
                            <select data-bind="options: $root.questionTypes, optionsText:'Description', value:Type"></select>
                        </div>
                        <div class="row">
                            <label>Tagline:</label>
                            <textarea data-bind="value: Tagline" cols="45"></textarea>
                        </div>
                        <div class="row">
                            <label>Visible:</label>
                            <input type="checkbox" data-bind="checked:Visible" />
                        </div>
                    </li>
                </script>

In the pages template, I use three different ways of trying to display the questions. The first method displays one sortable Foo, the second one displays the correct number of Foos, and the third one displays a blank sortable area with no items. I am working on a JS Fiddle, but I have to get the complex information from the database, so it's taking time. Any help there would also be welcome :).

My question, then, is why am I getting three different things, and where am I going wrong?

EDIT: I based my templates off of this.

I'm using this project.

I envision the end result being somewhat similar to this.


Source: (StackOverflow)

Copying an item rather than moving in the knockout sortable seating chart example

This is the seating chart example of knockout sortable: http://jsfiddle.net/UdXr4/ Based on the answers of this and this, I tried to change the seating chart example such that the items from available students copied rather than moved as in the jsfiddle here

The changes are shown below :

......
......
<div class="seats" data-bind="sortable: { data: students, allowDrop: $root.isTableFull, dragged: handleDraggedItem }">
......
......
<div class="new" data-bind="sortable: availableStudents">
        <div class="student available" data-bind="text: name"></div>
    </div>
.......
.......
Student.prototype.clone = function() {
    return new Student(this.id,this.name(),this.gender);
};
.......
.......
this.handleDraggedItem = function(item, event, ui) {
        console.log("handleDraggedItem");
        **return new Student(0,ui.item.text(),'');**
    };
.......
.......
$(".available").draggable({
    connectToSortable: ".seats",
    helper: "clone",
    start: function(event, ui) {
        ko.utils.domData.set(event.target, "ko_dragItem", true);
    }
});

The code that I'm unable to solve is the handledraggeditem [return new Student(0,ui.item.text(),'')]. How can I get the other values (id and gender) except name(this I'm able to get from text) such that I can send them here..

Due to this the $data for the dragged items have 0 as id and '' as gender as below..

{
          "id": 9,
          "name": "Kylie",
          "gender": "female",
          "group": "griffindor"
        },
        {
          "id": 0,
          "name": "Angel",
          "gender": "",
          "group": ""
        }

Any help is sincerely appreciated

Thanks


Source: (StackOverflow)

Controlling Flash Plugins with Knockout.js, Conflicting jQuery.tmpl and Knockout-Sortable

I'm trying to render HTML for embedding Flash objects using Knockout.js' native templating faculties. jQuery.tmpl does the job perfectly well, however I cannot use it due to conflicts with the Knockout-sortable plugin.

Here's an example of flash plugins quirking with the native templating: http://jsfiddle.net/7y3ub/35/
In Chrome, the player just never shows up. In Firefox, the player will show up if you change the channel while the checkbox is checked. Rechecking the box however makes the player vanish again.

The 'if' binding is necessary due to the fact that there may be many instances of flash plugins loading and unloading over the duration of the page.

From what I can tell, the HTML needs to all be in place by the time the object/embed tags enter into the visible DOM. This is why jQuery.tmpl would be great in my case. I've tried forming the HTML string myself, but I do not know how to apply and maintain the bindings that the new markup contains.

Bottom line, I either need a way to instantly render the HTML while still supporting bindings, or find a way to make jQuery.tmpl and Knockout-sortable compatable with each other.


Here's an example of the incompatability: http://jsfiddle.net/7y3ub/41/
The code in that example will work perfectly if you simply unreference jQuery.tmpl. http://jsfiddle.net/7y3ub/42/

The error message in the console seems to imply that the context is not being adjusted properly, or rather the implied foreach is not executing. The message becomes even more unusual in this tweak where the SubItem objects are replaced with simple strings: http://jsfiddle.net/7y3ub/43/


Source: (StackOverflow)

Displaying observableArray items based off property

What I'm trying to accomplish is having items within an observableArray display based off a property (i.e. category), for example:

Basic project setup:

var Project = function(id, name, stage){
    this.id = ko.observable(id);
    this.name = ko.observable(name);
    this.stage = ko.observable(stage);
}

self.projects = ko.observableArray([
    new Project(1, "Sample Project 1", "Planning"),
    new Project(2, "Sample Project 2", "Design"),
    new Project(3, "Sample Project 3", "Development"),
]);

Basic view:

<div class="large-2 columns planning">
    <h2>Planning</h2>
    <div class="project-holder" data-bind="sortable: { template: 'projectTemplate', data: projects, afterMove: dropCallback }">
        <!-- Projects go here -->
    </div> <!-- /project-holder -->
</div> <!-- /columns -->

The plan is to have a column for each "stage", i.e. "Planning", "Design", "Development", and each would display projects in that specific stage, however I'm not sure how to set it up. Is there a method for splitting up that array and displaying the items in separate columns based off their "stage" property, or is there another way of doing things that I should be looking into? Should I have a separate array that handles each of the categories individually?

I've been using individual arrays to handle things a la http://jsfiddle.net/rniemeyer/Jr2rE/ however it seemed that maybe there was a better way of handling things on a larger scale.

Any help/insight is appreciated.


Source: (StackOverflow)

using a draggable as a source list links items added to a sortable together?

excuse the hacked together sample

http://jsfiddle.net/marcmeans/SqrBf/1/

If you add an item from the available students to Table3 twice and then try and move one from Table3 to Table2, both disappear.

I note as well that when I'm generating a new guid for the item added to Table3, the arg.item seems be a reference to the item in the source list and not a clone. This creates a link in knockout where if I update one I update them all.

I'm assuming that I am doing something wrong here, but I'm having a hard time figuring out what.


Source: (StackOverflow)

if binding without container element not working for sortable

I modified a JSFiddle from rniemeyer to illustrate the problem: http://jsfiddle.net/mTqMt/1/

  <div class="container" data-bind="sortable: groupOrItems">
    <!--ko if: type=='Group'-->
    <div>
      <div class="title" data-bind="text: name()"></div>
      <!--here I would actually have a nested sortable-->
    </div>
    <!--/ko-->
    <!--ko if: type=='Item'-->
    <div class="item" data-bind="text: name()"></div>
    <!--/ko-->
  </div>

Firebug says: "TypeError: node is null" line 546 in knockout-latest.debug.js

I tried it with "foreach" instead of "sortable" and then it worked.

Any ideas?


Source: (StackOverflow)