Jump to content

Question about remembering what has been dragged/dropped (using MooTools)


kratsg

Recommended Posts

So, this is more of a "thought experiment" on how to design the script. It'll have limited number of 'items' that can be dragged and dropped into different 'rooms'. Then, when the user finishes sorting all the items they want to sort, they submit the form (via POST) to go to the next page which will move the 'items' to the selected 'rooms' they were dropped in.

 

My question is how to determine what has been dropped in that 'room' (a running list so to speak). I can probably handle the dragging and dropping, as well as submitting the data... but I dunno how to keep a running list of what items have been dropped into each room.

Link to comment
Share on other sites

Well, there's two basic ways you could look at it (I explain the following in OOP, but it could just as easily be done with plain arrays):

 

 

-You could have an item object and have a location property where the location property would correspond to a room.

-Or, you could have room objects that have item objects inside of them.

 

Both of them have advantages and disadvantages, and I'm really not sure which one I would go with >.<.

Link to comment
Share on other sites

Never used Mootools before, so I can't help you there.

 

 

As for passing it through POST, I would just pass what ever data you need.  Like the item ID and location or something.

 

You'll need some way to identify locations both server and client side.  I guess an ID or something.

Link to comment
Share on other sites

How would you do it in terms of classes/objects?

 

Let's say i have 3 rooms: A,B,C.

 

var rooms = new Rooms('A','B','C');

 

Considering that I don't know how many 'items' I would have, but I know I have "X" number of locations, this makes more sense (then initiating a new object for every item, holy hell).

 

Then, using a drag/drop, I can then be like:

 

//code for determing which object it dropped into (IE: grab some value from it)
rooms.addItem(dropped.get('room'),item);

 

So it adds on to my "rooms" object. (note, make sure I have the right terminology, I'm not too particularly good with OOP in any way or form).

 

Then when I submit my form...

//submit the form via post with
var data = rooms.getResult();//somehow grabs all items added (possibly an array of items inside the object) and puts it into a serialized array or a string?
//somehow post this data (should I update a form element with value=data or is there a way to submit a form directly like how AJAX can...?)

 

Does that seem feasible?

Link to comment
Share on other sites

If you're going to go with the rooms containing items approach (which is probably how I would do it) I would create an array of room objects (one object per room ID), and then store item objects inside of the room objects through an addItem() method or something.

 

Then, when it comes time to get all of the info, I would loop through the array that contains the room objects have have something like a getItemIds() function that returns an array of the item objects (or item ids would be easier).

 

Then you have to format it into a POST string....  You could make the script format it like:

 

 

room1[]=1&room1[]=3&room1[]=17&room2[]=5&room2[]=6&room3[]=42

 

 

Then the $_POST['roomx'] variables in PHP would be arrays of the item IDs.

 

Or you could do it comma separated:

 

room1=1,3,17&....

Link to comment
Share on other sites

"If you're going to go with the rooms containing items approach (which is probably how I would do it) I would create an array of room objects (one object per room ID), and then store item objects inside of the room objects through an addItem() method or something."

 

So (and I assume objects are instantiations of a class), would I create one class to set-up the room objects and one to store room objects:

 

class Rooms {

initialize: function() {
rooms.each(function(item){
this.rooms[item] = new Room(item);
});

}

}

class Room {

initialize: function() {
this.room = room;
}

}

 

Also, why would we want to store item objects instead of just the item ID inside the room objects? We use objects when we want to store more information about something, but the only information we would need about the item is its ID.

 

I'm not particularly seeing how I'm going to be setting my classes or how I will POST this data.

Link to comment
Share on other sites

If you're going to do this the mootools way have a look at a class template by one of the mootools developers http://davidwalsh.name/mootools-12-class-template

 

 

Also, why would we want to store item objects instead of just the item ID inside the room objects? We use objects when we want to store more information about something, but the only information we would need about the item is its ID.

 

I'm not particularly seeing how I'm going to be setting my classes or how I will POST this data.

I think the logic behind this would be to have a method for the Item objects that checks in what room it is once it is dropped inside a room.

 

As find this topic kinda interesting I made a small start with your classes.

// the room class
var Room = new Class({
//implements
//implements
Implements: [Options],

//options
options: {
	id: '',
	name: '',
	items:[]
},

//initialization
initialize: function(options) {
	//set options
	this.setOptions(options);

	//set the option attributes as internal vars
	this.id = this.options.id;		
	this.name = this.options.name;
	this.items = this.options.items;


},
// place an item in the room
setItem: function(item){
	// put the item in the internal array
	this.items.push(item);	
},
// get an item by id 
getItem: function(id){
	return this.items[id];
},
//get all items inside the room
getItems: function() {
	return this.items;
}

});
// the item class
var Item = new Class({
//implements
Implements: [Options],

//options
options: {
	id: '',
	name: ''
},

//initialization
initialize: function(options) {
	//set options
	this.setOptions(options);

	//set the option attributes as internal vars
	this.id = this.options.id;		
	this.name = this.options.name;
},

});

// instantiate new room
var room = new Room({
id:1,
name:"darkroom"
});
// instantiate new item
var item1 = new Item({
id:1,
name:'banana'
});
// instantiate new item
var item2 = new Item({
id:2,
name:'katana'
});

room.setItem(item1);
room.setItem(item2);
console.log(room.getItems());

Link to comment
Share on other sites

// the room class
var Room = new Class({
//implements
   //implements
   Implements: [Options],

   //options
   options: {
      id: '',
      name: '',
      items:[]
   },
   
   //initialization
   initialize: function(options) {
      //set options
      this.setOptions(options);

      //set the option attributes as internal vars
      this.id = this.options.id;      
      this.name = this.options.name;
      this.items = this.options.items;


   },
   // place an item in the room
   setItem: function(item){
      // put the item in the internal array
      this.items.push(item);   
   },
   // get an item by id
   getItem: function(id){
      return this.items[id];
   },
   //get all items inside the room
   getItems: function() {
      return this.items;
   }
   
});
// the item class
var Item = new Class({
   //implements
   Implements: [Options],

   //options
   options: {
      id: '',
      name: ''
   },
   
   //initialization
   initialize: function(options) {
      //set options
      this.setOptions(options);
      
      //set the option attributes as internal vars
      this.id = this.options.id;      
      this.name = this.options.name;
   },
   
});

// instantiate new room
var room = new Room({
   id:1,
   name:"darkroom"
});
// instantiate new item
var item1 = new Item({
   id:1,
   name:'banana'
});
// instantiate new item
var item2 = new Item({
   id:2,
   name:'katana'
});

room.setItem(item1);
room.setItem(item2);
console.log(room.getItems());

 

I'm starting to see how it works. If you don't mind me asking >.<

 

   //initialization
   initialize: function(options) {
      //set options
      this.setOptions(options);

      //set the option attributes as internal vars
      this.id = this.options.id;      
      this.name = this.options.name;
      this.items = this.options.items;

 

Two questions: does setOptions only save the values into $options.[option] or doesn't it automatically put this.[option] = [option] as in the second portion of the above code? If it doesn't, then why even use setOptions at all or is it just a way to separate out an object that has been passed through the class initiation?

 

Second question is about the line this.items = this.options.items;

 

How would you be able to push a single item through the class instantiation? Wouldn't there either be an error due to trying to store a string into an array, or an error in trying to array.push() a string?

 

// instantiate new room
var room = new Room({
   id:1,
   name:"darkroom",
   item:['banana','orange','grape']
});

//versus

// instantiate new room
var room = new Room({
   id:1,
   name:"darkroom",
   item:"banana"
});

 

PS: I love how you double comment //implement :-D It lets us know both that you're gonna comment implement in the next line, and then tell us that you're gonna implement the following classes ;-)

Link to comment
Share on other sites

Two questions: does setOptions only save the values into $options.[option] or doesn't it automatically put this.[option] = [option] as in the second portion of the above code? If it doesn't, then why even use setOptions at all or is it just a way to separate out an object that has been passed through the class initiation?

Let me clarify that with some code.

In the following example I assign the options from the constructor to this.options instead of using this.setOptions() which is nearly the same


var yourClass = new Class({
    options:{
        color: "#FFF" // start value for color
    },
    initialize: function(options){
        // assign options to this.options instead of the setOptions() method
        this.options = options;
    }
}

How ever in the above code you will lose the color value #FFF that's why setOptions is used instead. You also might want to check out what the manual says about setOptions http://www.mootools.net/docs/core/Class/Class.Extras#Options:setOptions

 

 

Second question is about the line this.items = this.options.items;

 

How would you be able to push a single item through the class instantiation? Wouldn't there either be an error due to trying to store a string into an array, or an error in trying to array.push() a string?

What about passing an array with a single value inside it? I think that would solve it. Ofcource you could also write something in your constructor method which checks the data type passed

var room = new Room({
    items:[
        new Item({
            id:1,
            name:'banana'
        })
    ]
});

// or using new Array
var room = new Room({
    items:new Array(
        new Item({
            id:1,
            name:'banana'
        })
    )
});

I'd use a Item object over simple strings btw. Your Item objects will be drag-able so you probably want to build in some methods for the Item objects later on.

 

PS: I love how you double comment //implement :-D It lets us know both that you're gonna comment implement in the next line, and then tell us that you're gonna implement the following classes ;-)

:facepalm: That was a mistake it should have been commented only once. Hope it all made sense though

Link to comment
Share on other sites

Two questions: does setOptions only save the values into $options.[option] or doesn't it automatically put this.[option] = [option] as in the second portion of the above code? If it doesn't, then why even use setOptions at all or is it just a way to separate out an object that has been passed through the class initiation?

Let me clarify that with some code.

In the following example I assign the options from the constructor to this.options instead of using this.setOptions() which is nearly the same


var yourClass = new Class({
    options:{
        color: "#FFF" // start value for color
    },
    initialize: function(options){
        // assign options to this.options instead of the setOptions() method
        this.options = options;
    }
}

How ever in the above code you will lose the color value #FFF that's why setOptions is used instead. You also might want to check out what the manual says about setOptions http://www.mootools.net/docs/core/Class/Class.Extras#Options:setOptions

 

      //set the option attributes as internal vars
      this.id = this.options.id;     
      this.name = this.options.name;
      this.items = this.options.items;

 

Then why do you have this code? Wouldn't setOptions(options) automatically merge the default options set in the class with what you pass in? So isn't it redundant?

 

Second question is about the line this.items = this.options.items;

 

How would you be able to push a single item through the class instantiation? Wouldn't there either be an error due to trying to store a string into an array, or an error in trying to array.push() a string?

What about passing an array with a single value inside it? I think that would solve it. Ofcource you could also write something in your constructor method which checks the data type passed

var room = new Room({
    items:[
        new Item({
            id:1,
            name:'banana'
        })
    ]
});

// or using new Array
var room = new Room({
    items:new Array(
        new Item({
            id:1,
            name:'banana'
        })
    )
});

I'd use a Item object over simple strings btw. Your Item objects will be drag-able so you probably want to build in some methods for the Item objects later on.

 

Right. So you're saying when I use the PHP to pull a list of items from the database and create the div containers for each item, I will also execute a code that creates a new object for each div container?

 

IE:

 

// the item class
var Item = new Class({
   //implements
   Implements: [Drag],//Note: according to the Doc, Drag implements [Options]

   //options
   options: {
      id: '',
      name: ''
   },
   
   //initialization
   initialize: function(options) {
      //set options
      this.setOptions(options);
      new Drag.Move(this.id, {'container': $('container'), 'droppables': Rooms.getRooms()});
     
   },
   
});

 

I just wonder if it will work. The idea is that you create the div container with the id of that div being set into the item class. It should be called generally after the rooms have been created.

 

But then I wonder, wait a minute, why would I care about setting a draggable for every specific item object? It seems like it would take up some memory, and with large amounts of item objects (around 60-ish possibly), this could get a bit weird. So maybe it's better to simply set the draggables all at once rather than through object instantiation...

IE:

var items = $$('items');//class = 'items'
var container = $('container');//id = 'container'
var rooms = $$('rooms');//class = 'rooms';

items.each(function(item){
    new Drag.Move(item, {'container': container, 'droppables': rooms});
});

 

Is there any forseeable differences? *Side Note: when I instantiate the class, I cannot just use "this" for the element reference in Drag.Move, which means I would have to pass the id of the div when I instantiate the class, correct?

Link to comment
Share on other sites

      //set the option attributes as internal vars
      this.id = this.options.id;     
      this.name = this.options.name;
      this.items = this.options.items;

 

Then why do you have this code? Wouldn't setOptions(options) automatically merge the default options set in the class with what you pass in? So isn't it redundant?

Actually remove that code it's a old bad habbit of mine that I used since mootools 1.0

 

But then I wonder, wait a minute, why would I care about setting a draggable for every specific item object? It seems like it would take up some memory, and with large amounts of item objects (around 60-ish possibly), this could get a bit weird. So maybe it's better to simply set the draggables all at once rather than through object instantiation...

IE:

var items = $$('items');//class = 'items'
var container = $('container');//id = 'container'
var rooms = $$('rooms');//class = 'rooms';

items.each(function(item){
    new Drag.Move(item, {'container': container, 'droppables': rooms});
});

 

Is there any forseeable differences? *Side Note: when I instantiate the class, I cannot just use "this" for the element reference in Drag.Move, which means I would have to pass the id of the div when I instantiate the class, correct?

Hmmm that probably is the way to go still you'd be having a couple of draggable object, I don't think you will gain performance. With "this" do you mean inside the Drag class and for what would you like to use it?

 

Out of curiosity are you going to get these items from a database? I remember trying to create something similar a long time ago. The thing I got stuck with was connecting the Item Id's from the database to these draggables somehow. If so maybe you got an idea how to do this.

 

Link to comment
Share on other sites

 

Hmmm that probably is the way to go still you'd be having a couple of draggable object, I don't think you will gain performance. With "this" do you mean inside the Drag class and for what would you like to use it?

 

 

I think I was saying something like, let's say we take a div and create it using the element creation/injection in mootools.

oncreate(function(){
var container = $('container');//id = 'container'
var rooms = $$('rooms');//class = 'rooms';

new Drag.Move(this, {'container': container, 'droppables': rooms});
});

 

Yet, it feels like having to keep re-calling the function over and over for every single item creation will drag the script, maybe too much load. At first, when I was writing that post, I was thinking about having a "div" be an object of the "items class". So that "this" referred to the "div" that stores the "object" per se? Maybe I'm confusing myself >.< I'll probably just use a $$ class selector to grab the rooms and items. It seems like it would work much more effectively.

 

Out of curiosity are you going to get these items from a database? I remember trying to create something similar a long time ago. The thing I got stuck with was connecting the Item Id's from the database to these draggables somehow. If so maybe you got an idea how to do this.

 

My idea was the following (at least initially thinking about it):

 

Each item just needs to have the item name, item id, and item quantity (**see discussion below this curr. discussion). So when I do a loop to create my divs, each div will have an id that references the unique id in the database. I can use a "toggler.get('id')" function when dropped over to grab the div that was dropped to get the item id that was used and add it into the rooms object. I'll also have an item="itemname" which isn't unique and references the actual item details (such as image, name, description, rarity, etc..) from database as well.

 

**So, my idea for the quantities was to create "X" number of absolutely positioned divs in one spot for each item. Look at this url for what I mean: http://demos111.mootools.net/DragDrop

 

At first, I thought they just kept repetitively cloning the draggable thing until 10 clones were reached. But they didn't. They simply had 10 divs (absolutely positioned) to auto-stack on top of each other. So, I would loop through and do something similar...

 

Or perhaps you have an idea on how to restrict the number of times I can clone? See the example on cloning. It would be kind of hard to track how many clones have been made... wasn't sure if I should do this through the divs, or a javascript object or what >.< (again, this requires having to create multiple item objects which may be the best option) depending on vulnerabilties (IE: can anyone hack and change the "clone number" as to just get more clones of that item [even though the php-side will stop them from moving items they don't have]).

http://demos111.mootools.net/Drag.Cart

 

My idea, if we were using absolutely positioned divs:

- on drag, drag the div around.

- on 'emptydrop' (drop somewhere not in one of the rooms), put the div back in it's starting position

- on 'drop', update the total quantity of that item, add the item id into the room object

 

The idea, if we were using "limited" cloning:

- on drag, drag the div around.

- on 'emptydrop', put the div back in it's starting position

- on 'drop', update the total quantity of that item, add the item id into the room object, update the cloning number

 

Summary:

Each div will contain:

- id="unique_row_id" (this is the row id from the table)

- item="itemname" (this is the item name of the item with such-and-such item id)

- <span class="itemname"></span> (so we can update the quantity using the sizeof($$('items[itemname=itemname]'))

Every time we have a new item, we will instantiate a new Items object for that item, the Items object will hold an array of the "unique_row_id".

 

Side note: that special selector does work :-D Although I dunno about the quotes.. but you are able to reference specific html elements based on specific attribute values as well...

 

Each items class will be instantiated by doing:

var itemname = new Items({'name': itemname, 'id':[12,49,98]});

Where itemname is from the actual PHP. Question: Since we can grab the "itemname" value from the dropped div, how can we call the object with the same itemname for updating the item list and quantities?

 

Each room will be instantiated and will have pretty much what we talked about above: id/name, array of items. I want a feature to be a merged version of the two demos above that I reference. You're able to drag-and-drop into a room, see that the item is there, but also limit the number of times the item can be cloned! At this point, we can ignore being able to drag items back out of a room (it's not saved until the php processes their selections).

 

Side note again: So, this sounds fun >.< I can't actually wait to get started... I'm just going to wait until I feel satisfied that I understand how to handle most of the behavior of the script at least client side. The PHP side should be simple enough as we're just grabbing the data, looping through, and doing the updates.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.