Jump to content

Pushing Javascript to the Limits


Monkuar
Go to solution Solved by kicken,

Recommended Posts

I've think I actually pushed javascript to the limits where what I'm trying to do isn't even actually feasible.

 

I'm using interactJS for drag and drop. Upon the drag event, I simply call a function to make 1x2 div's inside the inventory. (For places for the sword to be placed).

 

The limitation is:

 

d619e7f149b095502a217fb6c5365c4f.gif

 

Watch the last 2 seconds of this gif. It's impossible to have it be placed at position X1, Y1.

 

Edit: This is the code to loop through all the boxes and show the green placeholder.

 

itest = qsa('.iBoxes2');
			itemtype = event.target.getAttribute('slot-size');
				  
			console.log('  Width: '+itemtype[0]+' | Height: '+itemtype[2]+'  ');
				iwidth=(itemtype[0]*25.5);
				iheight=(itemtype[2]*24.5);
				
				console.log(iwidth);
				counter=0;
				for(i=0; i < itest.length; i++){
			
						cslot = itest[i].getAttribute('data-slot');
						
					if ( counter % 2 ==0 && cslot != 9 && cslot != 18 && cslot != 27 && cslot != 36 && cslot != 45 && cslot != 54 && cslot != 63) {
					
					 itest[i].style.position='relative';
					 itest[i].style.display="inline-block";
					 itest[i].style.width=""+iwidth+"px";
					 itest[i].style.background='#D8FFDA';
					 itest[i].style.height=""+iheight+"px"
					}
					
					 counter++;
				}
qsa is function qsa(e){return document.querySelectorAll(e)} Edited by Monkuar
Link to comment
Share on other sites

  • Solution

I'd suggest that rather than try to highlight everywhere that it could be placed, just show a highlight over the areas that would be used if it were placed where they are currently hovering (or no highlight if invalid placement).

 

There's really no reason to try and highlight every possible placement area. The user can see where the empty slots are and how many are needed by the size of the graphic. Your highlighting isn't even accurate as if you have more than the necessary space in a single area, you can place it anywhere in that area so you'd have to just highlight the entire space which ultimately means you're highlighting nearly every open slot.

 

The way you'd want to handle the drag and drop is that on every drag (and final drop) you:

- Determine which slot the cursor/image top-left is over

- Using that as your placement slot, determine if there is enough space in that area for the item

- If so, draw the placeholder. If not, indicate impossibility (eg, set cursor: no-drop and/or a red highlight).

 

For the drop event rather than draw the placeholder you'd move the item. If your test determines the area to be invalid, cancel and leave the item in it's original location.

Link to comment
Share on other sites

I'd suggest that rather than try to highlight everywhere that it could be placed, just show a highlight over the areas that would be used if it were placed where they are currently hovering (or no highlight if invalid placement).

 

There's really no reason to try and highlight every possible placement area. The user can see where the empty slots are and how many are needed by the size of the graphic. Your highlighting isn't even accurate as if you have more than the necessary space in a single area, you can place it anywhere in that area so you'd have to just highlight the entire space which ultimately means you're highlighting nearly every open slot.

 

The way you'd want to handle the drag and drop is that on every drag (and final drop) you:

- Determine which slot the cursor/image top-left is over

- Using that as your placement slot, determine if there is enough space in that area for the item

- If so, draw the placeholder. If not, indicate impossibility (eg, set cursor: no-drop and/or a red highlight).

 

For the drop event rather than draw the placeholder you'd move the item. If your test determines the area to be invalid, cancel and leave the item in it's original location.

Good.

 

I made it so every slot is droppable when the user starts to drag the item (green background) [ Although, will not show it when we go live because like you said, the user can already see where to place it because of the borders and boxes]. Then, when the user drops the elements, just check to see if it overlaps, and if it does, revert the image back to the original position, right?

 

That's what I'm doing now, it's just going to be hard because if an item is 2x2, and a user is moving a item that is 1x1, it will only revert if the user tries to drag it on the 1x1 of the 2x2 slot. If that makes sense.

 

For example, let me show u:

 

8080ce36d2ed44e3b3f6e27545caaf9d.gif

 

I need to DETECT the padding around an image based on their dimensions and fill in the appropiate boxes below:

 

c1885b2d0b23411cbabb2d6ce32b1b6e.png

 

For example.. That belt has the dimensions 2x1 2width and 1 height. I need to edit the <div class="InventoryTest"> classes with a "PADDING" that is one to the right of the item, so it will revert back on my image instead. It's reverting back if it checks if their is a parent node on that InventoryTest (And there is it's the belt), but the BELT is only in 1 SLOT, but has 2boxes of an dimension. There is essentially a false position slot. How do I creating a PADDING around the box slots (InventoryTest divs) via the DOM?

 

TLDR.. All items are essentially in 1 SLOT position. 1,100 (I have 99 slots). But if an image is in 1 SLOT that is 2x WITH, it's actually taking up 2 HORIZONTAL slots, but the slot next to it, isn't actually holding any data.. that's the problem. I need to HAVE A PADDING around them based on their dimensions.

 

So if that belt is in slot position 60, it should be taking up 60 and 61. Because it's a width of 2. But it's only taking up position 60. I need some type of padding function / formula.

 

But it's not, because it's 1 item in 1 slot and the image is just showing it like because it's 55px horizontal.

Edited by Monkuar
Link to comment
Share on other sites

Wrote some beautiful code (well that can be subjective). But to me anyways, this code checks if the item is placed on a box and that if the dimensions of the item will overlap the outside container = Out of bounds:

 

	csz= tempitemdata.getAttribute('slot-size');
	 
				sgo = parseInt( this.getAttribute('data-slot') );
						if (csz[2]> 1){ // Bottoms Rows Disabled X Positions
							for (e=0; e < slots; e++){
								 
									limitX=(csz[2])? (csz[2]*9-9):0;
									if(sgo > ( slots - limitX ) ){
									notify('Item out of bounds ~ ');
									return;
									}
							}
						}if (csz[0] == 2){ // 0,2++ Bottoms Rows Disabled Y Positions
								
								multi = new Array,c=0;
								while(c<slots){
								multi.push( 9 * c);
								c++;
								}
		 
						 
							if(multi.indexOf(sgo)!=-1){
							 
							notify('Item out of bounds ~ ');
							return;
							}
						}
						
I love the indexOf short hand function. It's literally insane. It's not EXACTLY like the in_array function in php, but it's pretty damn close.

 

As you can see on this code. I'm pushing my multi array of multiples of 9. So if the slot_Size of an item is 1x2 or greater, it checks down the Y row every 9th slot. And if a user trys to put an item at that slot they cannot because the width would be out of bounds.

 

I just need a good way to do this serverside now. I guess I'll convert the code above into php and check it against the database too.

 

The issue is... the padding or SCOPE of items dimensions need to be checked dynamically so they don't overlap.... This can be done clientside with javascript, but serverside, I'm not too sure. mac_quer posted some code to help, but his code didn't check the dimensions of an item (padding).

 

In any event. I'm only going to have 1x3, 1x2 and 1x1 dimensions and 2x2 (For armor) right now. I'll have a reset button in the inventory to clear the slots if we got script kiddies playing with live HTTP headers trying to fool around with item positioning though, so I'll be fine. The user experience will still be 99% working just like Path of Exile and Diablo 2! I am extremely happy!

 

I scratched interactJS too! I'm just using basic Diablo 2 inventory movement with basic javascript:

 

hasitem=0;
tempitemdata = 0;
tempitemdata2 = 0;
slots = 99;
 
 
 


 function checkinventory(){
ibox = qsa('.InventoryTest');
			for(i=0; i < ibox.length; i++){
				ibox[i].onclick=function(){
						//console.log( tempitemdata );
			if(hasitem == 1){
			/*
					if (this.childNodes[1]){
						//swap?
						 
						 console.log(tempitemdata);
							
							this.childNodes[1].style.display='none';
							tempitemdata.style.display='inline-block';
							this.appendChild(tempitemdata);
							tempitemdata=this.childNodes[1];
							setTimeout(function(){ hasitem = 1; }, 100);
							
					 
							
							
					  
							qs('#InventoryWindow').style.cursor="url("+this.childNodes[1].getAttribute('item-image')+"),auto";
							
					
					return;
					}
			*/
		 
				if (this.childNodes[1] || this.childNodes[0]){
				hasitem = 0;
				tempitemdata.style.display='inline-block';
				notify('An item already exists here.');
				qs('#InventoryWindow').style.cursor="default";
				return;
				}
				csz= tempitemdata.getAttribute('slot-size');
	 
				sgo = parseInt( this.getAttribute('data-slot') );
						if (csz[2]> 1){ // Bottoms Rows Disabled X Positions
							for (e=0; e < slots; e++){
								 
									limitX=(csz[2])? (csz[2]*9-9):0;
									if(sgo > ( slots - limitX ) ){
									notify('Item out of bounds ~ ');
									return;
									}
							}
						}if (csz[0] == 2){ // 0,2++ Bottoms Rows Disabled Y Positions
								
								multi = new Array,c=0;
								while(c<slots){
								multi.push( 9 * c);
								c++;
								}
		 
						 
							if(multi.indexOf(sgo)!=-1){
							 
							notify('Item out of bounds ~ ');
							return;
							}
						}
						
				
				tempitemdata2.innerHTML='';
				tempitemdata.style.display='inline-block';
					
					 
	 
			 
				if(hasitem == 1){
				
				
				
				qs('#InventoryWindow').style.cursor="default";
				setTimeout(function(){ hasitem = 0 }, 50);
				this.appendChild(tempitemdata);
				}
				 
		 
				 
			} 
			
			}
			}
}
 
			
iitems = qsa('.itemdrag');
			
			 
			for(i=0; i < iitems.length; i++){
				iitems[i].onclick=function(){
				
					if (hasitem == 0){
					 
					
					itemimage = this.childNodes[1].childNodes[1].src;
					this.style.display='none';
					 
					tempitemdata=this;
					tempitemdata2=this.parentNode;
					 
					 
					 
					qs('#InventoryWindow').style.cursor="url("+itemimage+"),auto";
					setTimeout(function(){ checkinventory(); hasitem = 1 }, 100);
					}
					
					}
					
			}
It's awesome and intuitive in my opinion and works just like D3's. I can add more styling later to make it sexier, but for now it's fine.

 

109175236858950c535ab0ae6fe2f17b.gif

 

Gyzo makes the images upon clicking really weird, ignore that. But your cursor changes to the item itself upon clicking, it's just like D2's, so awesome! I am so happy too!! So lightweight no interactJS, or plugins. Love it. :wub:  :wub:  :wub:  :wub:

Edited by Monkuar
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.