Search code examples
javascriptarraysjavascript-objects

access to object arrasy and values with loops


I have a problem with handling the access to my object array values, I've tried using different forms of loops, trying to get the values with forEach, includes, tried to use the object properties but I jest end up with spaghetti code and I can manage test if th values exist but if they dont they are also passed.

var target;

var itemValue;

function item_obj(name, type, exists) {
    this.name   = name;
    this.type   = type;
    this.exists = exists;
}

function getItemValue(itm) {

    var gm_obj = game_obj[0].item[0].name,
        i, values = [];

    console.log('getItemValue: testing:', itm);

    for (var i in gm_obj.length) {

        if(gm_obj[i].includes(itm)) {

            itm = gm_obj[i];
    console.log(itm);
        } else {

            itm = null;
        }
    }

    if (itm != null) {
        itm = new item_obj(itm, 'item', true);
        console.log('getItemValue: found:', itm);

  document.getElementById('cout').innerHTML = 'found item' + itm;

        return itm;
    } else {
        return false;
    }
}   

the code should output the target as an object so I can us the values later, I've tried separate variables too but it seems like the loop only returns the first value.

this works but returning false does not. it should set the item exists to false so I can pass it through a similar function until I find the type and use a switch statement to treat it accordingly.

here is a pen : https://codepen.io/silconsystem/pen/oNXoBJo?editors=1111

and here is the whole thing, I'm more ahead in the development branch.

This is kicking my ass, can anyone give me some pointers?

Cheers Rob..


Solution

  • There are many aspects to polish in your approach, but regarding the search function itself:

    var gm_obj = game_obj[0].item[0].name,
        i, values = [];
    

    gm_obj is an array of arrays:

    name: 
    [
      ["nothing"],["potion"],["ether"],["revive"],["helmet"],
      ["coins"], ["medals"],["crown"],["robes"]
    ]
    

    gm_obj.length is 1, therefore for (var i in gm_obj.length) means nothing.

    I believe your previous attempt was

    for(var i=0; i<gm_obj.length; i++) {
        // check gm_obj[i]
    }
    

    Anyway, you could iterate through the names using for...of

    for (var obj of gm_obj) {
      // obj is [nothing], then [potion], then etc...
      // for example:
      if(["medals"].includes(itm)) {
        ...
      }
    }
    

    That's checking for exact match. If that's ok, the assignement you do

     itm = obj; // in your code, itm = gm_obj[i]
    

    Turns itm from string to array. I don't believe that's your goal. It should be

     itm = obj[0];  // still a string.
    

    Further in the code, if you got a match in one loop, and nothing in the next, you wipe the found value:

        } else {
            itm = null;
        }
    

    You should have a break

       if(obj.includes(itm)) {
         itm = obj[0];
         break;
       }
    

    Or use a temporary variable to store the result. Initialize it as null, so you don't need an else

      let result=null;
      for(obj of gm_obj) {
        if(obj.includes(itm)) {
          result = obj[0];
        }
      }
    

    If it's fine to skip the other elements once there's a match, just return:

       if(obj.includes(itm)) {
         itm = obj[0];
         return new item_obj(itm, 'item', true);
       }
    

    Finally, I believe this is just a POC, because your onclick handler doesn't store the search result.

    submitBtn.onclick = function(event) {
      target = textBox.value;
    
      getItemValue(target); // not storing
    
      document.getElementById('cout').innerHTML = target;
    
    }
    

    As the others have told you, you need to work with data that fits your use case. If you have no control over it source, transform it. (mapping and or reducing), because I believe your end goal is to get an object that represent each item attribute. Therefore, I would work with a game object like:

    let  game_obj = {
      item: 
        [ 
    
          {name:"nothing", description:"none", game:"none", url:'#'},
          {name:"potion", description:"small boost", game:"HP +10", url:'#'},
          {name:"ether", description:"MP boost", game:"MP +10", url:'#'},
          {name:"revive", description:"alive", game:"HP +100", url:'#'},
          {name:"helmet", description:"protect head", game:"evd +3", url:'#'},
          {name:"coins", description:"player coin", game:"coins +10", url:'#'},
          {name:"medals", description:"luck plus", game:"luc +5", url:'#'},
          {name:"crown", description:"strenght plus", game:"str +5", url:'#'},
          {name:"robes", description:"strenght plus", game:"str +1", url:'#'},
        ]
      };
    

    And then perform the search like

    for(obj of game_obj.item) {
      if(obj.name.includes(itm) {
         // found matching obj
      }
    }
    

    It's way simpler to understand at first sight. Here's my solution.

    let  game_obj = 
      {
        item: 
        [ 
          
              {name:"nothing", description:"none", game:"none", url:'#'},
              {name:"potion", description:"small boost", game:"HP +10", url:'#'},
              {name:"ether", description:"MP boost", game:"MP +10", url:'#'},
              {name:"revive", description:"alive", game:"HP +100", url:'#'},
              {name:"helmet", description:"protect head", game:"evd +3", url:'#'},
              {name:"coins", description:"player coin", game:"coins +10", url:'#'},
              {name:"medals", description:"luck plus", game:"luc +5", url:'#'},
              {name:"crown", description:"strenght plus", game:"str +5", url:'#'},
              {name:"robes", description:"strenght plus", game:"str +1", url:'#'},
            ]
        };
    /*----------------------------------------------------------------------------------------------------------------------------*/
    var target;
    
    var itemValue;
    var list = document.getElementById('list'),
     cout=document.getElementById('cout'),
     submitBtn = document.getElementById('button'),
     textBox = document.getElementById('input');
    
    function item_obj(attributes, type='', exists=false) {
    		let {
         name, description,game,url 
        }=attributes;
        this.name 	= name;
      this.description 	= description;
      this.game 	= game;
      this.url 	= url;
    		this.type 	= type;
    		this.exists = exists;
    	}
    
    function getItemValue(itm) {
    
    		var gm_obj = game_obj.item,
    			i, values = [], foundvalue=null;
       
          list.innerHTML = '';// gm_obj.join(', ');
    		  console.log('getItemValue: testing:', itm);
       
    		for (var obj of gm_obj) {
          let resultMsg=`${obj.name}: nope`,
              span=document.createElement('span');
             console.log({obj});
       		if(obj.name.includes(itm)) {
            resultMsg=`found item: <b>${obj.name}</b>`;
            
            cout.innerHTML = resultMsg;
            span.className='found'
            span.innerHTML=resultMsg;
            list.appendChild(span);
            return new item_obj(obj,'item',true);
    			}
          span.innerHTML=resultMsg;
          list.appendChild(span);
    		}
        return false;
    	}	
    
    
    
    //itemValue = new item_obj(target, 'item', true);
    
    
    
    
    submitBtn.onclick = function(event) {
      target = textBox.value;
      console.log({target});
      cout.innerHTML = `searching for: ${target}... `;
      window.setTimeout(()=>{
         itemValue=getItemValue(target);
         console.log(itemValue);
    },1000);
      
      
    }
    @import url('https://fonts.googleapis.com/css?family=Sulphur+Point&display=swap');
    
    body {
      margin: 20px;
      background: #888;
      font-family: 'Sulphur Point';
      
    }
    #list span {
    flex-grow: 0;
        white-space: no-wrap;
        padding: 0 4px;
        border: 1px solid #999;
        border-radius: 3px;
        font-size: 0.8em;
        margin: 2px 5px;
        color: #000;
        background: #ccc;
    }
    #list span.found {
       border:2px solid #090;
       color:#080;background:#333
    }
    #input {
      margin: 20px 20px 20px 0;
      border:4px solid #365683;
    }
    
    #list {
          flex-wrap: wrap;
        margin-left: 20px;
        display: flex;
        border: 7px solid #654;
        border-radius: 12px;
        max-width: 200px;
        background: #000;
        width: 200px;
        height: 165px;
        padding-left: 10px;
        color: #fff;
        align-content: flex-start;
    }
    
    #button {
      border: 4px solid #567;
      border-radius: 4px;
    }
    #button:hover {
      border: 4px solid #000;
      color: #fff;
      background: #000;
    }
    #button:active {  
      border: 4px solid #000;
      color: #000;
      background: #fff;
      font-weigth: bold;
    }
    
    #out {
      display:flex;
      font-family: 'Sulphur Point';
      color: #fff;
      border: 7px solid #654;
      border-radius: 12px;
      font-weight: bold;
      font-size: 20px;
      background: #000;
      max-width: 200px;
      height: 60px;
      padding: 20px;
    }
    .column div,.column button,.column input {
      display:inline-flex;
    }
    
    container {
      display:flex;
      align-items:middle;
    }
    .column {
      
      flex-grow:0 1;
    }
    <container>
      <div class="column">
    <input type="text" id="input"></input>
    <button id="button">submit</button>
    <div id="out">
      <span id="cout"></span>
    </div>
      </div>
    <div class="column" id="list"></div>
    </container>