javascript angular - Associazione Widget con Gridster e Knockout





example drag (5)


Aggiungi classe = "gs_w" a ur li in gridster dovrebbe funzionare

Sono nuovo di Javascript e sto provando ad usare Gridster con Knockout. Ho un database con gli oggetti, e io uso foreach knockout per legarli a un UL. L'UL è abbinato alla libreria Gridster. Tutto funziona alla grande a meno che non provi ad aggiungere ulteriori elementi all'UL tramite l'ObservableArray nel viewmodel.

Qualcuno può aiutarmi a capire la portata e l'ordine delle operazioni qui? Sembra che la libreria di Gridster non stia facendo il suo stile sui nuovi widget.

Questo jsfiddle mostra una demo funzionante del problema. Nota quando fai doppio clic su un widget, ne crea uno nuovo ma non lo posiziona nella griglia. Invece, è solo una specie di dietro.

Ecco l'HTML

   <div class="gridster">
        <ul data-bind="foreach: myData">
            <li data-bind="attr:{

              'data-row':datarow,
              'data-col':datacol,
              'data-sizex':datasizex,
              'data-sizey':datasizey

        },text:text, doubleClick: $parent.AddOne"></li>
        </ul>
    </div>

Ecco il Javascript

//This is some widget data to start the process
var gridData = [ {text:'Widget #1', datarow:1, datacol:1, datasizex:1, datasizey:1},
    {text:'Widget #2', datarow:2, datacol:1, datasizex:1, datasizey:1},
    {text:'Widget #3', datarow:1, datacol:2, datasizex:1, datasizey:1},
    {text:'Widget #4', datarow:2, datacol:2, datasizex:1, datasizey:1}];

// The viewmodel contains an observable array of widget data to be 
//    displayed on the gridster
var viewmodel = function () {

    var self = this;
    self.myData = ko.observableArray(gridData);
    //AddOne adds an element to the observable array 
    //   (called at runtime from doubleClick events)
    self.AddOne = function () {
        var self = this;
        myViewModel.myData.push({
            text: 'Widget Added After!',
            datarow: 1,
            datacol: 1,
            datasizex: 1,
            datasizey: 1
        });
    };

};


var myViewModel = new viewmodel();
ko.applyBindings(myViewModel);

$(".gridster ul").gridster({
    widget_margins: [5, 5],
    widget_base_dimensions: [140, 140]
});



Ecco una soluzione funzionante che ritengo sia più in linea con il modello MVVM:

http://jsfiddle.net/Be4cf/4/

//This is some widget data to start the process
var gridData = [
    {id: "1", text:'Widget #1', datarow:1, datacol:1, datasizex:1, datasizey:1},
    {id: "2", text:'Widget #2', datarow:1, datacol:2, datasizex:2, datasizey:1},
    {id: "3", text:'Widget #3', datarow:1, datacol:4, datasizex:1, datasizey:1},
    {id: "4", text:'Widget #4', datarow:2, datacol:1, datasizex:1, datasizey:2}];

// The viewmodel contains an observable array of widget data to be 
//    displayed on the gridster
var viewmodel = function () {

    var self = this;
    self.myData = ko.observableArray(gridData);
    self.nextId = 5;
    self.gridster = undefined;

    // AddOne adds an element to the observable array.
    // Notice how I'm not adding the element to gridster by hand here. This means  
    // that whatever the source of the add is (click, callback, web sockets event), 
    // the element will be added to gridster.
    self.addOne = function () {
    myViewModel.myData.push({
            text: 'Widget Added After!',
            datarow: 1,
            datacol: 1,
            datasizex: 1,
            datasizey: 1,
            id: self.nextId++
        });
    };

    // Called after the render of the initial list.
    // Gridster will add the existing widgets to its internal model.
    self.initializeGridster = function() {
        self.gridster = $(".gridster ul").gridster({
            widget_margins: [5, 5],
            widget_base_dimensions: [140, 140]
        }).data('gridster');
    };

    // Called after the render of the new element.
    self.addGridster = function(data, object) {
        // This bypasses the add if gridster has not been initialized.
        if (self.gridster) {
            var $item = $(data[0].parentNode);

            // The first afterRender event is fired 2 times. It appears to be a bug in knockout.
            // I'm pretty new to knockout myself, so it might be a feature too! :)
            // This skips the second call from the initial fired event.
            if (!$item.hasClass("gs-w"))
            {
                // This removes the binding from the new node, since gridster will re-add the element.
                ko.cleanNode(data[0].parentNode);
                // Adds the widget to gridster.
                self.gridster.add_widget($item);
                // We must update the model with the position determined by gridster
                object.datarow = parseInt($item.attr("data-row"));
                object.datacol = parseInt($item.attr("data-col"));
            }
        }
    };
};

var myViewModel = new viewmodel();
ko.applyBindings(myViewModel);

Devo ancora pensare agli eventi di rimozione e spostamento (una mossa in gridster dovrebbe aggiornare i valori xey dell'oggetto nel viewmodel). Ho iniziato a utilizzare knockout ieri, quindi qualsiasi aiuto sarebbe apprezzato.

Non sono riuscito a trovare un cdn per l'ultima versione di gridster. JSFiddle punta a un sito web temporaneo che ho aggiunto in Azure, lascerò perdere per alcuni giorni, ma sentitevi libero di aggiornarlo con il vostro link.

/------------------------------ AGGIORNARE ------------------ ---------------- /

Ho aggiornato il mio codice per supportare le eliminazioni e spostare i widget ( http://jsfiddle.net/Be4cf/11/ ), ma c'è un piccolo avvertimento: c'è un problema aperto ( https://github.com/knockout/knockout/issues / 1130 ) che elimina i dati jquery prima di chiamare l'evento beforeRemove. Ciò causa il crash di gridster poiché i dati necessari per spostare gli altri elementi in giro sono conservati in un elemento dati. Una soluzione alternativa potrebbe essere quella di conservare una copia dei dati e di aggiungerli nuovamente all'elemento in un secondo momento, ma ho scelto il modo pigro e ho commentato la riga incriminata in knockout.




Dovresti fare qualcosa come sotto. addNewGridElement è chiamato - con l'elemento DOM reso che è importante nel caso di gridster.add_widget quanto gridster.add_widget accetta un elemento DOM come primo argomento - una volta aggiunto qualcosa al Knockout osservabile. Dopo questo, è solo questione di aggiungere domNode a Gridster.

view.html:

   <div class="gridster">
        <ul data-bind="foreach: { myData, afterAdd: $root.addNewGridElement }">
            <li data-bind="attr:{

              'data-row':datarow,
              'data-col':datacol,
              'data-sizex':datasizex,
              'data-sizey':datasizey

        },text:text, doubleClick: $parent.AddOne"></li>
        </ul>
    </div>

view.js:

self.addNewGridElement = function (domNode, index, newTile) {
    // Filter non li items - this will remove comments etc. dom  nodes.
    var liItem = $(domNode).filter('li');
    if ( liItem.length > 0 ) {
        // Add new Widget to Gridster
        self.gridster.add_widget(domNode, newTile.x, newTile.y, newTile.row, newTile.col);
    }
};



Ecco un esempio completo in JSfiddle . Qui, ho evidenziato solo la funzione di cancellazione

self.deleteOne = function (item) {
    console.log(item);
    var widget = $("#" + item.id);
    console.log(widget);
    var column = widget.attr("data-col");
    if (column) {
        console.log('Removing ');
        // if this is commented out then the widgets won't re-arrange
        self.gridster.remove_widget(widget, function(){
            self.myData.remove(item);
            console.log('Tiles: '+self.myData().length);                
        });
    }
};

Il lavoro di rimozione dell'elemento dall'array osservabile viene eseguito all'interno del callback remove_widget. Vedi la documentazione di Gridster. Di conseguenza, l'hook removeGridster eseguito prima della rimozione di un widget non deve più eseguire la chiamata remove_widget effettiva.




Questa soluzione nativa ha funzionato meglio per me:

  1. Aggiungi un evento touchstart alle impostazioni del documento un touch = true globale touch = true .
  2. Nel gestore mouse / touchstart, previeni tutti gli eventi di mouse quando viene rilevato un touch screen: if (touch && e.type === 'mousedown') return;






javascript jquery knockout.js gridster