0

I'm trying to deal with a problem whose name I can't quite place (and hence have trouble googling).

It deals with a set of 'switch'-like checkboxes.

Here are the specifics:

  • I am using the image mapster plugin with a checkbox setup similar to that demo.
  • Checkboxes are generated from state names and clicking them calls mapster to turn on/off the states.
  • I am using an additional set of checkboxes called "Northeast USA", "Southeast USA" and so on.
  • Clicking on "Northeast" must turn on all the states in that region. Clicking again should turn it off. Simple enough.

Complications:

  • There are overlapping states between the regions.
  • Clicking on Northeast US, then turning off one of the states, and then clicking on Southeast, etc., confuses my simple straightforward logic right now.

Possible solution:

  • I need these third-level checkboxes to act as 'switches', tracking the state of the checkboxes and the mapster areas.
  • Northeast must be intelligent enough to switch itself off when one of the checkboxes is manually clicked.
  • Clicking Southeast mustn't confuse the data state of NE because of overlapping states... and so on.

I am looking for a design pattern that has dealt with this kind of problem before. If someone knows a solution pattern that doesn't really have a name, that knowledge is also most welcome.

Thanks for reading!

Aditya M P
  • 5,127
  • 7
  • 41
  • 72
  • you're making it too complex. Just put there a checkbox named `Northeast USA` and, on its click, check all mapster checkboxes that are for the states that fall under said region. – Ejaz Apr 14 '13 at 08:47
  • perhaps the word you are looking for is "toggle". – didierc Apr 14 '13 at 09:06
  • Hi Ejay, indeed that's how it works now... NE *et al* are just 'dumb togglers' that just nuke all selection data from the checkboxes and toggle them 'on'. But I really need the switch functionality to work. @didierc I believe this is something *more* than toggle... – Aditya M P Apr 14 '13 at 12:40
  • 1
    In maths that would be set theory would it not? – hookenz Apr 14 '13 at 21:49
  • I don't think I understand every detail of what you're trying to accomplish but ImageMapster has some built in capabilities for managing area groups independent of the state of each area, e.g.: http://jsfiddle.net/eaf2G/ – Jamie Treworgy Apr 15 '13 at 12:26
  • @JamieTreworgy Thanks for taking time to comment here! The example is close to what I need, however imagine 'New England' was a checkbox, and when I check it, and then deselect 'Vermont' in the map, 'New England' gets de-checked... can mapster do that too? – Aditya M P May 26 '13 at 19:42

2 Answers2

1

I believe that you simply need to rely on the javascript onclick events of checkboxen.

There are 2 situations:

  • the checkbox is being unchecked (ie. it's on). It must lookup all the boxen depending on it, and if they are checked, call their click methods.
  • the checkbox is being checked on. It must look up all the boxen it depends on, and if they are unchecked, call their click methods.

The dependency graph can be described as a matrix, with the column and row indices denoting the box number, and the matrix cell whether the row box depends, is dependent, or bear no relationship with the column box.

You may want to use an separate array to keep the map between box names and indices.

Of course you will have to make sure that there are no cycle in your dependency graph, otherwise you'll end up having events triggers calling themselves recursively.


Update:

I tried my own solution to see how well it works.

Html document:

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
 <table>
  <thead>
    <colgroup>
    <col width='80'>
    <col width='20'>
    </colgroup>
    <colgroup>
    <col width='80'>
    <col width='20'>
    </colgroup>
    <colgroup>
    <col width='80'>
    <col width='20'>
    </colgroup>
    <tr>
    <th colspan="2">Level 1</th>
    <th colspan="2">Level 2</th>
    <th colspan="2">Level 3</th>
    </tr>
  <tbody>
    <tr>
      <td colspan='4'></td>
      <td rowspan='0'><label for='top' >top</label></td>
      <td rowspan='0'><input type='checkbox' id='top' value=''/></td>
    </tr>
    <tr>
      <td colspan='2'></td>
      <td rowspan='3'><label for='grp1' >grp1</label></td>
      <td rowspan='3'><input type='checkbox' id='grp1' value=''/></td>
    </tr>
    <tr>
      <td><label for='id1' >id1</label></td>
      <td><input type='checkbox' id='id1' value='abc'/></td>
    </tr>
    <tr>
      <td><label for='id2' >id2</label></td>
      <td><input type='checkbox' id='id2' value='def'/></td>
    </tr>
    <tr>
      <td><label for='id3' >id3</label></td>
      <td><input type='checkbox' id='id3' value='ghi'/></td>
    </tr>
    <tr>
      <td colspan='2'></td>
      <td rowspan='3'><label for='grp2' >grp2</label></td>
      <td rowspan='3'><input type='checkbox' id='grp2' value=''/></td>
    </tr>
    <tr>
      <td><label for='id4' >id4</label></td>
      <td><input type='checkbox' id='id4' value='klm'/></td>
    </tr>
    <tr>
      <td><label for='id5' >id5</label></td>
      <td><input type='checkbox' id='id5' value='nop'/></td>
    </tr>
    <tr>
      <td><label for='id6' >id6</label></td>
      <td><input type='checkbox' id='id6' value='qrs'/></td>
    </tr>
  </tbody>
</table>
<hr>
<script src="js/jquery.js" type="text/javascript"></script>
<script src="js/multicheck.js" type="text/javascript"></script>
</body>
</html>

and javascript file:

var data = {
    depends: {
        id1 : ['grp1'],
        id2 : ['grp1'],
        id3 : ['grp1', 'grp2'],
        id4 : ['grp2'],
        id5 : ['grp2', 'grp1'],
        id6 : ['grp2'],
        grp1 : ['top'],
        grp2 : ['top']
    },
    owns : {
        grp1 : ['id1','id2','id3', 'id5'],
        grp2 : ['id4','id5','id6', 'id3'],
        top  : ['grp1','grp2']
    }    
};

function check(elt){
    var target = elt.target;
    if (!target.checked) {
        // unchecking -> uncheck depends
        for (e in data.depends[target.id]) {
            $("input#"+data.depends[target.id][e]).each(
                function(){
                    if (this.checked)
                        this.click();
                });
        }
    }
    else {
        // checking -> check owns
        for (e in data.owns[target.id]) {
            $("input#"+data.owns[target.id][e]).each(
                function (){
                    if (!this.checked)
                        this.click();
                });
        }
    }
    return true;
}

(function(){
     $(document).ready(function(){
         $("input[type='checkbox']").bind('click',check);
     });
})();

The data object contains all the dependency information: depends lists all the "directly depends on" relationship, and owns lists the reverse relationship.

While it represents the dependency graph, I used directly the ids of the boxen as indices, and split it two.

Example:

  • Whenever top s checked, all the other boxen get checked as well in cascade (grp1 first, which check all the ids it owns, then grp2 likewise).
  • Whenever id5 is unchecked, grp1, top and grp2 are unchecked in this cascading order.

_Remark: I am not jquery proficient, so there might be a more concise way of getting the same result. _

didierc
  • 14,572
  • 3
  • 32
  • 52
1

This is where set theory comes in.

And you can represent part selections using tristate checkboxes. See here. tristate checkboxes in html

There is a jQuery tristate checkbox plugin here

Community
  • 1
  • 1
hookenz
  • 36,432
  • 45
  • 177
  • 286