By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
443,974 Members | 1,834 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 443,974 IT Pros & Developers. It's quick & easy.

Iterate through partial JSON property list

RMWChaos
100+
P: 137
As usual, an overly-long, overly-explanatory post. Better too much info than too little, right?

A couple weeks ago, I asked for some assistance iterating through a JSON property list so that my code would either select the next value in the member list or the single value. The original post can be found here.

This is the code gits helped me write:

Expand|Select|Wrap|Line Numbers
  1. for (var i = 0; i < attribList.id.length; i++)
  2.      {
  3.      var attrib = {};
  4.      for (var index in attribList)
  5.           {
  6.           if (attribList[index] != null)
  7.                {
  8.                var value = attribList[index];
  9.                attrib[index] = value instanceof Array ? value[i] : value;
  10.                };
  11.           };
  12.      };
  13.  
  14. // Example JSON property list
  15. createDOM({
  16.      'id'     :   'idOne', 'idTwo', 'idThree', 'idFour'],
  17.      'dom'    :   ['img', 'script', 'div', 'span']
  18.      'parent' :   'body',
  19.      'alt'    :   ['Click me.', null, null, null]
  20.      });
  21.  
This code works great if I want to iterate through all the values in the member list. Now, I want to adapt the code for another task. This time, instead of iterating through all the value members, I want to only select the first value member [0] or the second value member [1] individually and do no more. However, if I select the third value member [2], then I want it to iterate through the remaining value members, "if (i = 2; i < arrayName.id.length; i++)". This really sounds like it should be pretty darned simple to do...but apparently not for me.

So here's what I've got so far:

Expand|Select|Wrap|Line Numbers
  1. function loadLogin(isUserLoggedIn)
  2.      {
  3.      var i = isUserLoggedIn;
  4.      var click;
  5.      var createLogin = {};
  6.      var login = new Array("login", "logout", "submit");
  7.      var imageId = "image" + login[i];
  8.      var logCapital = login[i].capitalize();
  9.      var divLogExist = document.getElementById(imageId);
  10.      var pathHover = "../images/hover" + login[i] + ".jpg";
  11.      var pathDefault = "../images/default" + login[i] + ".jpg";
  12.      var mouseOver = new Function("mouseHover('" + pathHover + "', '" + imageId + "')");
  13.      var mouseOut = new Function("mouseHover('" + pathDefault + "', '" + imageId + "')");
  14.      var logClick = new Function("loadLogin(click)");
  15.      var UserId = 'to be determined';
  16.      var URI = 'http://api.eve-online.com/account/Characters.xml.aspx';
  17.      var APIKey = 'to be determined';
  18.      var loginList = {
  19.           'id'          :  [imageId, imageId, imageId, "formlogin", "userid", "useridinput", "apikey", "apikeyinput"],
  20.           'dom'         :  ["img", "img", "input", "form", "text", "input", "text", "input"],
  21.           'parent'      :  "content",
  22.           'alt'         :  [logCapital, logCapital, logCapital, null, null, null, null, null],
  23.           'title'       :  [logCapital, logCapital, logCapital, null, null, null, null, null],
  24.           'src'         :  [pathDefault, pathDefault, pathDefault, null, null, null, null, null],
  25.           'onmouseover' :  [mouseOver, mouseOver, mouseOver, null, null, null, null, null],
  26.           'onmouseout'  :  [mouseOut, mouseOut, mouseOut, null, null, null, null, null],
  27.           'onclick'     :  [logClick, logClick, null, null, null, null, null, null],
  28.           'form'        :  [null, null, "formlogin", "formlogin", "formlogin", "formlogin", "formlogin", "formlogin"],
  29.           'action'      :  [null, null, null, URI, null, null, null, null],
  30.           'method'      :  [null, null, null, "post", null, null, null, null],    
  31.           'name'        :  [null, null, null,"formlogin", null, null, null, null],
  32.           'size'        :  [null, null, null, null, null, 6, null, 85],
  33.           'value'       :  [null, null, logCapital, null, null, null, null, null],
  34.           'defaultvalue':  [null, null, null, null, null, UserId, null, APIKey],
  35.           'text'        :  [null, null, null, null, null, "User ID:", null, "API Key:"],
  36.           'type'        :  [null, null, "image", null, null, "text", null, "text"]
  37.           };
  38.      if (i == 0)
  39.           {
  40.           click = 2;
  41.           createAttribList();
  42.           }
  43.      else if (i == 1)
  44.           {
  45.           logClick = new Function('confirm("Are you sure you want to logout?")');
  46.           if (confirm == false)
  47.                {
  48.                alert('You are still logged in.')
  49.                pageLoader(0);
  50.                return;
  51.                }
  52.           else if (confirm == true)
  53.                {
  54.                isUserLoggedIn = 0;
  55.                createAttribList();
  56.                };
  57.           }
  58.      else if (i > 1)
  59.           {
  60.           var click = 1;
  61.           var isUserLoggedIn = 1; // remove this after creating cookie processing //
  62.           for (i = 2; i < loginList.id.length; i++)
  63.                {
  64.                createAttribList();
  65.                };
  66.           };
  67.      function createAttribList()
  68.           {
  69.           var attribList = {};
  70.           for (i in loginList)
  71.                {
  72.                var value = loginList[i];
  73.                attribList[i] = value instanceof Array ? value[i] : value;
  74.                };
  75.           createDOM(attribList);
  76.           };
  77.      };
  78.  
[old problem description:]
I need to figure out why it keeps going through the entire list of value members and beyond; instead of stopping at the last item in 'id' it continues on to 8, which has no value. It shouldn't even do this initially. It should only create the first item in id until I click on the login image, where it will then create the login form.
[/old]

Well, I realized as I was typing this and confirming that I had copied all my code over correctly, that I had incorrectly coded function createAttribList(). It should read like this:

Expand|Select|Wrap|Line Numbers
  1. function createAttribList()
  2.      {
  3.      var attribList = {};
  4.      for (var index in loginList)
  5.           {
  6.           var value = loginList[i];
  7.           attribList[index] = value instanceof Array ? value[index] : value;
  8.           };
  9.      createDOM(attribList);
  10.      };
  11.  
So now it works as designed. However, if you are inclined to review the code and make any suggestions, I welcome your feedback.
Nov 23 '07 #1
Share this Question
Share on Google+
15 Replies


RMWChaos
100+
P: 137
Previously, I asked how to iterate through a JSON property list. gits helped out considerably with that, and I have a working script. Now I want to modify it further.

I want to iterate through only part of the property list. Currently, I have managed to accomplish this partially by incorporating a 'split' (or splice) variable, which defines where to begin iterating from. As I type this, I just realized that I can add further functionality by incorporating an 'end split' variable as well. But I will address that later.

Here's the problem. When I am iterating through the entire list (no split), it works great. When I use the split, the first values in the property list work as designed, that is individually, not iterated through. However, the iteration portion of the split only displays the very last value. I suspect what is happening is that each value is being displayed, but the next value removes the previous one. I suspect this because the non-iterated values that display first disappear when the iteration begins, which is what I want. For the life of me, I can't figure out why the other values are going away. =(

Now in case none of that makes sense, here is my code with notation to explain.
Expand|Select|Wrap|Line Numbers
  1. // (A)dd, (R)emove, or (C)hange node attributes //
  2. function arcAttrib(idExist, createElem, attr, value, state)
  3.      {
  4.      var exceptions = 
  5.           {
  6.           'onclick'    :  1,
  7.           'onmouseover':  1,
  8.           'onmouseout' :  1
  9.           };
  10.      if (attr in exceptions)
  11.           {
  12.        /*
  13.        *  // (A/R/C) with addEvent method //
  14.        *  addEvent(idExist, attr, value);
  15.        *  // Not bloody well working! //
  16.        */
  17.           // (A/R/C) with JS method //
  18.           id[attr] = value;
  19.           }
  20.      // (A/C) with DOM method //
  21.      else if (state)
  22.           {
  23.           id.setAttribute(attr, value);
  24.           }
  25.      else // (R) with DOM method //
  26.           {
  27.           id.removeAttribute(attr);
  28.           };
  29.      };
  30.  
  31. /*
  32. *  attribList is the JSON property list itself
  33. *  split is where to begin iteration
  34. *  i is which value to display
  35. */
  36. function createDOM(attribList, split, i)
  37.      {
  38.      // if i is before split, create only attribList[i] //
  39.      if (i < split)
  40.           {
  41.           createNode();
  42.           }
  43.      // if i is at or after split, iterate through the remaining values //
  44.      else if (i >= split)
  45.           {
  46.           for (i = split; i < attribList.id.length; i++)
  47.                {
  48.                createNode();
  49.                };
  50.           };
  51.      // the remainder of this code sets attribs and creates the node //
  52.      function createNode()
  53.           {
  54.           var attrib = {};
  55.           for (var index in attribList)
  56.                {
  57.                if (attribList[index] != null)
  58.                     {
  59.                     var value = attribList[index];
  60.                     attrib[index] = value instanceof Array ? value[i] : value;
  61.                     };
  62.                };
  63.           var defaultAttribs = 
  64.                {
  65.                'dom'   : 'div',
  66.                'parent': 'body'
  67.                };
  68.           for (index in defaultAttribs)
  69.                {
  70.                if(typeof attrib[index] == 'undefined')
  71.                     {
  72.                     attrib[index] = defaultAttribs[index];
  73.                     };
  74.                };
  75.           var idExist = document.getElementById(attrib.id);
  76.           var createElem = document.createElement(attrib.dom);
  77.           var parentExist = document.getElementById(attrib.parent);
  78.           if (typeof attrib.id == 'undefined')
  79.                {
  80.                alert("There is no 'id' to create the node.");
  81.                return;
  82.                };
  83.           if (attrib.dom == 'text')
  84.                {
  85.                createElem = document.createTextNode(attrib.text);
  86.                parentExist = document.getElementById(attrib.id);
  87.                }
  88.           else if ((attrib.dom == 'script') && ((attrib.parent == 'undefined') || (attrib.parent == 'head')))
  89.                {
  90.                parentExist = document.getElementsByTagName('HEAD')[0];
  91.                };
  92.           if (attrib.parent == 'body')
  93.                {
  94.                if (document.getElementsByTagName)
  95.                     {
  96.                     parentExist = document.getElementsByTagName('BODY')[0];
  97.                     }
  98.                else if (document.body)
  99.                     {
  100.                     parentExist = document.body;
  101.                     }
  102.                else if (document.layers)
  103.                     {
  104.                     parentExist = document.tags['BODY'];
  105.                     };
  106.                }
  107.           else if (!parentExist)
  108.                {
  109.                var body = document.getElementsByTagName('BODY')[0];
  110.                var createParent = document.createElement('div');
  111.                createParent.id = attrib.parent;
  112.                body.appendChild(createParent);
  113.                if (attrib.dom != 'text')
  114.                     {
  115.                     parentExist = document.getElementById(attrib.parent);
  116.                     };
  117.                };
  118.           if (parentExist)
  119.                {
  120.                if (attrib.dom != 'text')
  121.                     {
  122.                     createElem = document.createElement(attrib.dom);
  123.                     };
  124.                for (index in attrib)
  125.                     {
  126.                     // util-method to determine how to (A/R/C) attribs
  127.                     arcAttrib(idExist, createElem, index, attrib[index], true);
  128.                     };
  129.                parentExist.appendChild(createElem);
  130.                };
  131.           };
  132.      };
  133.  
  134. // Actual JSON list from Login script//
  135. createDOM({
  136.      'id'         :  [imageId, imageId, imageId, "formlogin", "userid", "useridinput", "apikey", "apikeyinput"],
  137.      'dom'        :  ["img", "img", "input", "form", "text", "input", "text", "input"],
  138.      'parent'     :  "content",
  139.      'alt'        :  [logCapital, logCapital, logCapital, null, "User ID", null, "API Key", null],
  140.      'title'      :  [logCapital, logCapital, logCapital, null, "User ID", null, "API Key", null],
  141.      'src'        :  [pathDefault, pathDefault, pathDefault, null, null, null, null, null],
  142.      'onmouseover':  [mouseOver, mouseOver, mouseOver, null, null, null, null, null],
  143.      'onmouseout' :  [mouseOut, mouseOut, mouseOut, null, null, null, null, null],
  144.      'onclick'    :  [logClick, logClick, logClick, null, null, null, null, null],
  145.      'form'       :  [null, null, null, "formlogin", "formlogin", "formlogin", "formlogin", "formlogin"],
  146.      'action'     :  [null, null, null, URI, null, null, null, null],
  147.      'method'     :  [null, null, null, "post", null, null, null, null],    
  148.      'name'       :  [null, null, null, "formlogin", null, null, null, null],
  149.      'size'       :  [null, null, null, null, null, 6, null, 85],
  150.      'value'      :  [null, null, logCapital, null, null, null, null, null],
  151.      'text'       :  [null, null, null, null, null, "User ID:", null, "API Key:"],
  152.      'type'       :  [null, null, "image", null, null, "text", null, "text"]
  153.      }, 2, i);
  154. // 2 is where split occurs, i changes with selections //
  155.  
It's entirely possible that the problem is within my login script itself--that would make sense considering it is the only script affected by this problem. However, it is the only script that uses the split variable so far. I am going to check out my login script to be sure.
Nov 24 '07 #2

gits
Expert Mod 5K+
P: 5,371
hi ...

as far as could see at a first quickshot ... you cannot simply use the compare operator as you did ... have a look at the following example:

Expand|Select|Wrap|Line Numbers
  1. var obj = { foo: 'bar', foobar: 'barfoo', a: 'b' };
  2.  
  3. for (var i in obj) {
  4.     if (i < 'foobar') {
  5.         alert(':\)');
  6.     }
  7. }
  8.  
it alerts everytime when the condition becomes true ... and 'a' < 'foobar' -> true since it compares the stringvalues of the keys not the positions ... and i understood your question as it should compare the positions? for that case you have to loop through the obj and when finding your 'split' key you have to build a new obj with that and all following keys and their values ... and then use that list for further processing ... which means, you have to split the list physically into two lists ... ok? i hope i made myself clear :)

kind regards
Nov 24 '07 #3

RMWChaos
100+
P: 137
you cannot simply use the compare operator as you did ... you have to loop through the obj and when finding your 'split' key you have to build a new obj with that and all following keys and their values ... and then use that list for further processing ... which means, you have to split the list physically into two lists.
GASP! OMG!! Say it ain't so, gits! I actually ... <GULP!> ... dis- ... disa- ... disagree with you (that was so hard to say!) ... not once, but twice even!! My image of my beloved scripting mentor has been tarnished forever. Whatever shall I do!? =D

Ok, ok, so maybe I didn't explain it very well the first time around, but in my effort to clarify, I may have resolved the problem with the test code below--just need to apply it to createDOM() and test.

The compare operator may not be comparing what you think it is. You only took a quick look; so that is totally understandable. 'i' and 'split' are both numerical values determined by input into the loadLogin() function and a static number respectively; they are not part of the JSON list.

If you notice at the end of the property list example in the original post, there is an 'i' and a 'split' listed after the JSON list is closed. So essentially, it is passing three separate objects to createDOM(): 'attribList', 'split', and 'i'. From now on, I will set the JSON property list to a variable, and then pass the var to createDOM(). That should be less confusing.

Here is my test code, which works in IE, FF, and NN:

Expand|Select|Wrap|Line Numbers
  1. function loadLogin(logStat)
  2.      {
  3.      var list = ({
  4.           'uno' : ['foo', 'bar', 'foobar', 'barfoo'],
  5.           'dos' : ['oof', 'rab', 'raboof', 'oofrab']
  6.           });
  7.      createDOM(list, 1, logStat);
  8.      };
  9. function createDOM(attribList, split, i)
  10.      {
  11.      if (split > i)
  12.           {
  13.           // replace with "buildAttribList(attribList[index]);"
  14.           for (var index in attribList)
  15.                {
  16.                var value = attribList[index];
  17.                alert(index + " is " + value[i]);
  18.                }
  19.           // replace to here
  20.           }
  21.      else if (split <= i)
  22.           {
  23.           for (i = split; i < attribList.uno.length; i++)
  24.                {
  25.                // replace with "buildAttribList(attribList[index]);"
  26.                for (var index in attribList)
  27.                     {
  28.                     var value = attribList[index];
  29.                     alert(index + " is " + value[i]);
  30.                     };
  31.               // replace to here
  32.               };
  33.           };
  34.      };
  35.  
  36. /*
  37. *  In HTML:
  38. *  Initial value of 'i' is 0, where it stops.
  39. *     <body onload="loadLogin(0)">
  40. *  Onclick, 'i' becomes 1, then iterates to end
  41. *     <button onclick="loadLogin(1)">Click Me!</button>
  42. *
  43. *  Simply by setting split to '0', createDOM() code
  44. *  will iterate through the entire list for other JSON
  45. *  lists in other scripts. Totally modular, dude! =)
  46. *
  47. *  Initial output should show on page load, you will
  48. *  see the 'Click Me!' button and two alerts showing
  49. *  the first value in 'uno' and the first value in 'dos'.
  50. *  When you click the button, you will see 6 more
  51. *  alerts, each showing the next values alternating
  52. *  between 'uno' and 'dos'.
  53. */
  54.  
I will have to replace the two duplicate sections in the test code above with a reference to 'buildAttribList()'. Maybe this is what you meant by "splitting into two physically separate lists"?

Expand|Select|Wrap|Line Numbers
  1. function buildAttribList(splitList)
  2.      {
  3.      for (var index in list)
  4.           {
  5.           var value = splitList[index];
  6.           if (value[i] != null)
  7.                {
  8.                attrib[index] = value instanceof Array ? value[i] : value;
  9.                };
  10.           };
  11.      createNode(attrib);
  12.      };
  13.  
Nov 25 '07 #4

gits
Expert Mod 5K+
P: 5,371
*lol* ... yes! shame on me ... i didn't look very carefully at it ... forgive me ... it simply is a little bit intransparent to me what the code should do ... but now its more clear :)
Nov 25 '07 #5

RMWChaos
100+
P: 137
*lol* ... yes! shame on me ... i didn't look very carefully at it ... forgive me ... it simply is a little bit intransparent to me what the code should do ... but now its more clear :)
You know I still love ya, gits. =D

You think my code isn't transparent? Puh-leeeze. I've seen some of the code you code-junkies write, and it makes my head spin!

It's really quite simple in principle what I am trying to accomplish. I want compact, efficient, and centralized code to eliminate redundancy in the coding of my other scripts. So the whole point of continuing to tinker with my createDOM() script is to make it as flexible a tool as possible; cross-browser, fast, etc.

It should be capable of creating, modifying, and deleting any and all DOM elements, and it should also be capable of receiving and parsing data from as many JavaScript Object Notation structures as possible.

That's not too much to ask, is it? Yeah, I know, quite a monumental task for a newb to be taking on, but that's what I have you guys for. =D
Nov 26 '07 #6

gits
Expert Mod 5K+
P: 5,371
;) ... what is hard to read must have been hard to write :) ...

you are right ... some code is really a mess to read ... but why? our main principle is to write as less lines of code as possible ... because less lines is less code to parse, to maintain, to transfer to the client etc. ... but less lines are not always the best in case you have to maintain code of another programmer ... imagine a code that uses very advanced regExp, much of callbacks and tricky variable-handling (hashmaps etc.) ... and there is no documentation. most of the programmers would be lost with such code ... but we always say: best docu is the code itself :) ... but we never say ... how it should look like ;) ... so that everybody is able to understand it without learning concepts or tricks only the original-code-writer knows. so in case you want someone to learn your code ... you should write some comments when the code is ready and tested ... even when there is a drawback of comments: you always leave them as they are ... even when changing/fixing something in you code ... so that makes the readers head spinning :)

i understand your goal and you are doing very well ... but as i said: a function that is as mutlifunctional as it could be is not very transparent for others ... because you pass something to it and it produces very different things ... in the worst case! ... and i don't say that your code is doing that ... i simply didn't look very caryfully and now i understand what you want to do ... and as i said: you do it welll :)

kind regards
Nov 27 '07 #7

RMWChaos
100+
P: 137
Wow, that's very nice of you to say, gits. But I bet you say that to all the newbs. ;-)

As far as my code is concerned, I will fully document the 'master' version and provide that as a download free to use/modify/share from my site. But my working version will be 'minified' using the Minify app that removes all comments, unnecessary spaces, tabs, line breaks, etc. That is never pretty, but it is very compact and quick to download, especially for those still working in the Dark Ages on 56.6Kbps modems (poor bastards).

Here is what I've come up with so far, and this works 90%:

Expand|Select|Wrap|Line Numbers
  1. function splitAttribList(attribList, iterate, split)
  2.      {
  3.      var splitList = {};
  4.      // if only split is listed, default iterate to 0 //
  5.      if (split && !iterate)
  6.           {
  7.           iterate = 0;
  8.           };
  9.      // if neither split nor iterate, create entire attribList (no split) //
  10.      if (!iterate && !split)
  11.           {
  12.           createNode(attribList);
  13.           }
  14.      // if iterate is less that split or split is null, create splitList with 1 value [iterate] per index //
  15.      else if ((split > iterate) || (split = null))
  16.           {
  17.           for (var index in attribList)
  18.                {
  19.                var value = attribList[index];
  20.                splitList[index] = value instanceof Array ? value[iterate] : value;
  21.                };
  22.           createNode(splitList);
  23.           }
  24.      // if iterate matches or exceeds split, create the remainder of values //
  25.      else if (split <= iterate)
  26.           {
  27.           for (var i = iterate; i < attribList.id.length; i++)
  28.                {
  29.                for (var index in attribList)
  30.                     {
  31.                     var value = attribList[index];
  32.                     splitList[index] = value instanceof Array ? value[i] : value;
  33.                     };
  34.                createNode(splitList);
  35.                };
  36.            };
  37.      };
  38. function createDOM(attribList)
  39.      {
  40.      for (var i = 0; i < attribList.id.length; i++)
  41.           {
  42.           var attrib = {};
  43.           for (var index in attribList)
  44.                {
  45.                var value = attribList[index];
  46.                if (value instanceof Array ? value[i] : value != null)
  47.                     {
  48.                     attrib[index] = value instanceof Array ? value[i] : value;
  49.                     };
  50.                };
  51.            var attribDefaults = 
  52.                {
  53.                'dom'   :  'div',
  54.                'parent' :  'body'
  55.                };
  56.           // Assign default attribs to 'undefined' values //
  57.           for (index in attribDefaults)
  58.                {
  59.                if(typeof attrib[index] == 'undefined')
  60.                     {
  61.                     attrib[index] = attribDefaults[index];
  62.                     };
  63.                };
  64.  
So as you can see, the splitAttribList() function first splits the JSON list, then createDOM() does the actual DOM creation with the 'new' split Attrib list. As far as createDOM() is concerned, the list it receives is the only list there is.

The way this is designed, if you never need to split the JSON property list, then you can just always use createDOM() directly. Otherwise, if you sometimes or always need to split the list first, you can use splitList().

I am considering combining these two into one function, called createDOM(), as splitList() will simply pass on the original attribList transparently anyway. So perhaps there is really no need to separate the two. I suppose it makes sense to just wrap the two in one function. Your thoughts?

The problem I still face with this createDOM() code is that it still improperly handles my loadLogin() script. It's as if each time a new DOM node is created, it deletes the previous one. At one point in my development of this new code to handle splits in the JSON list, it actually created my login form correctly with all the fields; although, it did so without stopping at the split.Weird. Something is goofy here.
Nov 27 '07 #8

gits
Expert Mod 5K+
P: 5,371
:P nope ... first you are no newbie anymore ... and i only say that to those who 'loves me' :)

wrapping the two functions into one is not a bad solution ... as i mentioned already ... but as i mentioned already too ... i would always follow the following pattern:

Expand|Select|Wrap|Line Numbers
  1. function one(params2) {
  2.     // some code that returns params3
  3.  
  4.     return params3;
  5. }
  6.  
  7. function two(params, params3) {
  8.     return result;
  9. }
  10.  
  11. function common_call_one_two(params, params2) {
  12.     // first we have to decide how the two functions have to be called
  13.     // from here, may be we need some defaults that we may create
  14.     // the following way, you already know that :)
  15.  
  16.     if (typeof params2 == 'undefined') {
  17.         params3 = 'something_dflt_for_params3';
  18.     } else {
  19.         params3 = one(params2);
  20.     }
  21.  
  22.     // now we may call two with params and params3
  23.     return two(params, params3);
  24. }
hmmm ... problems with your splitted list? we should have a closer look at it :)

kind regards
Nov 27 '07 #9

gits
Expert Mod 5K+
P: 5,371
in your line 15 of your last posted code you have an error:

Expand|Select|Wrap|Line Numbers
  1. // mistyped (split = null) as an assignment in your example
  2. // it should be:
  3. else if ((split > iterate) || (split == null)) {
Nov 27 '07 #10

RMWChaos
100+
P: 137
in your line 15 of your last posted code you have an error:

Expand|Select|Wrap|Line Numbers
  1. // mistyped (split = null) as an assignment in your example
  2. // it should be:
  3. else if ((split > iterate) || (split == null)) {
Yes, caught that with firebug in my code, just forgot to correct it here. Thank you!
Nov 27 '07 #11

RMWChaos
100+
P: 137
wrapping the two functions into one is not a bad solution ... as i mentioned already ... but as i mentioned already too ... i would always follow the following pattern:

Expand|Select|Wrap|Line Numbers
  1. var sBrain = "My brain is bleeding trying to understand your code.\n ";
  2. var sEyes = "As usual, I have to read it 100 time until I get it or until my eyes melt out of my head!\n ";
  3. var sFirst = "Whichever comes first.";
  4. alert(sBrain + sEyes + sFirst)
  5.  
Sorry, I understand real-world examples better because in my mind I can see how the code will function. It just takes me longer to convert your abstract examples into practical applications. =/

Here is what I was thinking (but I didn't want to break your rule about keeping functions that accomplish different things separate):

Expand|Select|Wrap|Line Numbers
  1. function createDOM(attribList, split, iterate)
  2.      {
  3.      var splitList = {};
  4.      // if only split is listed, default iterate to 0 //
  5.      if (split && !iterate)
  6.           {
  7.           iterate = 0;
  8.           };
  9.      // if neither split nor iterate, create entire attribList (no split) //
  10.      if (!split && !iterate)
  11.           {
  12.           createNode(attribList);
  13.           }
  14.      // if iterate is less that split or if split is null, create only value [iterate] per index //
  15.      else if ((split > iterate) || (split == null))
  16.           {
  17.           for (var index in attribList)
  18.                {
  19.                var value = attribList[index];
  20.                splitList[index] = value instanceof Array ? value[iterate] : value;
  21.                };
  22.           createNode(splitList);
  23.           }
  24.      // if iterate matches or exceeds split, create the remainder of values //
  25.      else if (split <= iterate)
  26.           {
  27.           for (var i = iterate; i < attribList.id.length; i++)
  28.                {
  29.                for (var index in attribList)
  30.                     {
  31.                     var value = attribList[index];
  32.                     splitList[index] = value instanceof Array ? value[i] : value;
  33.                          };
  34.                     createNode(splitList);
  35.                     };
  36.                 };
  37.      function createNode(attribList)
  38.           {
  39.           for (var i = 0; i < attribList.id.length; i++)
  40.                {
  41.                var attrib = {};
  42.                for (var index in attribList)
  43.                     {
  44.                     var value = attribList[index];
  45.                     // Filter out null values //
  46.                     if (value instanceof Array ? value[i] : value != null)
  47.                          {
  48.                          attrib[index] = value instanceof Array ? value[i] : value;
  49.                          };
  50.                     };
  51.                 var attribDefaults = 
  52.                     {
  53.                     'dom'   :  'div',
  54.                     'parent' :  'body'
  55.                     };
  56.                // Assign default attribs to 'undefined' values //
  57.                for (index in attribDefaults)
  58.                     {
  59.                     if(typeof attrib[index] == 'undefined')
  60.                          {
  61.                          attrib[index] = attribDefaults[index];
  62.                          };
  63.                     };
  64. // etc...
  65.  
So here you can see there is no real coding change at all, except that the two functions are now merged into one, and you always call createDOM() whether you are splitting the JSON list or not. The attribList vs. splitList is handled transparently to the user. Just seemed simpler from a practical point of view rather than having to choose between splitAttribList() or createNode().

I did, however, split out arcAttrib() (your util-method) from the main code of createDOM() as you suggested. It immediately made sense when I did that I could add, remove, or change (the 'arc' in my function name) DOM attributes easily with this function. So, you were right yet again. =D

hmmm ... problems with your splitted list? we should have a closer look at it :)
Yeah, so what happens is that the splitList()/createDOM() function combo correctly creates the first node, which is the login icon, attribList[index][0], and the logout icon, attribList[index][1].

When I click the login icon, splitList() starts passing the next values [index][2] through [index][7] and iterating through them, as designed. However, it creates the first element, then the second element replaces the first, and so on until only the last element [index][7] remains displayed. It should show all the elements at the same time.

It might be somewhere else in my code, because the login image should be removed when the login form is created. I need to go back and find that piece of code.

Does that make sense? You may have to see it for yourself.
Nov 27 '07 #12

RMWChaos
100+
P: 137
wrapping the two functions into one is not a bad solution ... as i mentioned already ... but as i mentioned already too ... i would always follow the following pattern:

Expand|Select|Wrap|Line Numbers
  1. function one(params2) {
  2.     // some code that returns params3
  3.  
  4.     return params3;
  5. }
  6.  
  7. function two(params, params3) {
  8.     return result;
  9. }
  10.  
  11. function common_call_one_two(params, params2) {
  12.     // first we have to decide how the two functions have to be called
  13.     // from here, may be we need some defaults that we may create
  14.     // the following way, you already know that :)
  15.  
  16.     if (typeof params2 == 'undefined') {
  17.         params3 = 'something_dflt_for_params3';
  18.     } else {
  19.         params3 = one(params2);
  20.     }
  21.  
  22.     // now we may call two with params and params3
  23.     return two(params, params3);
  24. }
Okay, let's see if I can wrap my meager little brain around what you are saying...

Initiate with common_call_one_two() giving it 'params1' and optional 'params2'. If 'params2' is not provided, set 'params3' to a default value. If 'params2' exists, pass it to one() for processing , which returns 'params3'. Now pass 'params' and 'params3', to two() for the final result. So your point is to use a centralized function, which essentially triages processing out to other single-prupose functions.

Here's why I don't particularly like this method. If the single-purpose function has no other job in life than to respond only to the call of the one central function (remember the "@private" notation), why make it separate at all? I guess I see that as at best unnecessary and at worst resulting in convoluted code that is hard to follow (non-linear), inefficient, and possibly duplicating code. I do have to admit, though, that part of me likes to keep everything separated into nice, neat, little packages rather than all jumbled up into one big holy mess

On the other hand, if a function handles calls from multiple functions, then it makes perfect sense to keep it separate. In fact, the genesis of my createDOM() function was because I was repeating code to add/remove dom elements in several other scripts. When I started seeing this redundant code pattern, I realized that I could centralize the code into one function, then just call that function from any other script, eliminating redundant processes and reducing the total size of the code that is downloaded to the browser.

So, convince me otherwise; what is the value of separating the code, (other than troubleshooting perhaps, and I find that a dubious assertion)? You have the experience that I do not, particularly with real-world application of code. What am I not seeing that makes the method you suggest (centralized code calling independent single-purpose functions) more useful, efficient, or just plain better than what I am suggesting (make functions independent only if more than one function makes calls to it)? There has got to be something I am missing. =?

Now I say all this, but look at my new code I posted in the previous post...there are three places where I code something like "attrib[index] = value instanceof Arrray ? value[index] : value;" and I HATE that. It drives me up the wall. I wish I could just write the code once and then call it ... duh <slaps head>. Seems like a really good place to use your divide and conquer method.

Sigh. See, if I talk long enough, I usually end up answering my own question.

I guess you can ignore this whole post now; so you don't have to read it after all. Lucky you! >:-}
Nov 28 '07 #13

gits
Expert Mod 5K+
P: 5,371
Here's why I don't particularly like this method. If the single-purpose function has no other job in life than to respond only to the call of the one central function (remember the "@private" notation), why make it separate at all? I guess I see that as at best unnecessary and at worst resulting in convoluted code that is hard to follow (non-linear), inefficient, and possibly duplicating code. I do have to admit, though, that part of me likes to keep everything separated into nice, neat, little packages rather than all jumbled up into one big holy mess

On the other hand, if a function handles calls from multiple functions, then it makes perfect sense to keep it separate. In fact, the genesis of my createDOM() function was because I was repeating code to add/remove dom elements in several other scripts. When I started seeing this redundant code pattern, I realized that I could centralize the code into one function, then just call that function from any other script, eliminating redundant processes and reducing the total size of the code that is downloaded to the browser.

So, convince me otherwise; what is the value of separating the code, (other than troubleshooting perhaps, and I find that a dubious assertion)? You have the experience that I do not, particularly with real-world application of code. What am I not seeing that makes the method you suggest (centralized code calling independent single-purpose functions) more useful, efficient, or just plain better than what I am suggesting (make functions independent only if more than one function makes calls to it)? There has got to be something I am missing. =?
:) it is NOT

inefficient: in most cases you write code that could/should be seperated in smaller functions because you never know whether you have to reuse it or not ... you don't write a software that is a monolithic block ... may be you have to reuse an array_split_method for example for new features of the current project or in another one ... that is what i called util-functions earlier ... of course it may be not linear but ajax itself is not linear since it is async and so i don't think that linearity is a strong argument. when you have seperated util-methods already you may SIMPLY reuse them ... without adapting the current and running code where you may build in new bugs due to rebuild it or even worse ... copy the part of code to a new util-method and don't use that method in your code but leave it as it is ... later on you change the util method due to a bug but your code that don't use the util has the bug and is unchanged ... i hope i made it clear?

resulting in duplicated code: as you may see from my words above: it AVOIDS duplicate code very easyly ... building huge functions that are selfcontained may, and probably will, result in duplicating code since a lot of constructs are used everywhere ... and beeing prepared with your code for that is always good practice

so as you can see ... there is not only the 'troubleshooting'-argument ... its basically a matter of reusable components together with maintainance-aspects ... sometimes you have a bunch of such util-methods that you may use for a lot of projects. when discovering a bug you will understand that fixing one method and so every application that uses it at once is much better then fixing every application seperatly ...

but now one more note: it is no dogma ... simply a pattern you may follow or not and of course sometimes when you are sure about things you may/should use other patterns ... i'm not an old wise man that knows all answers ... and even when i say something ... i could be wrong :) ... but i always find it an interesting discussion with you and the things you always point out ... :)

kind regards
Nov 28 '07 #14

RMWChaos
100+
P: 137
Alright, java-master gits. You win yet again. While I may see no use for separating createDOM() from splitAttribList() right now, that may not be the case down the road.

The duplicated code I was referring to was smaller than you were suggesting. You meant rewriting a similar function in another script rather than just reusing the one I've already written. I was thinking more about re-declaring vars and such. But the benefits of making a change in one single place outweighs any negatives I can see.

Now I need to go back through my code and see where else I might break out large chunks into smaller, more modular functions. See what you do? You just made more work for me. =D
Nov 28 '07 #15

gits
Expert Mod 5K+
P: 5,371
:) only at the moment ... but you will have less work later on ... believe me ...

kind regards
Nov 28 '07 #16

Post your reply

Sign in to post your reply or Sign up for a free account.