aboutsummaryrefslogtreecommitdiff
path: root/finder_menu.js
blob: 7dd276f764e031dde02d2a8555d9ece8cd1fb97f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
/*
 * ul2finder
 * written by Christian Heilmann (http://icant.co.uk)
 * turns the nested list with the ID "finder" into a dynamic list
 * uses the CSS classes defined in the variables
 */
function ul2finder()
{
  // Define variables used and classes to be applied/removed
  var i,uls,als,finder;
  var parentClass='parent';
  var showClass='shown';
  var hideClass='hidden';
  var openClass='open';
  window.finderOpened = new Object();

  // check if our finder list exists, if not, stop all activities
  finder=document.getElementById('finder');
  if(!finder){return;}

  // add the class domenabled to the body
  cssjs('add',document.body,'domenabled');

  // loop through all lists inside finder, position and hide them 
  // by applying the class hidden
  uls=finder.getElementsByTagName('ul');
  for(i=0;i<uls.length;i++)
  {
    cssjs('add',uls[i],hideClass);
  }	

  // loop through all links of inside finder
  lis=finder.getElementsByTagName('li');
  for(i=0;i<lis.length;i++)
  {
    // if the li containing the link has no nested list, skip this one
    if(!lis[i].getElementsByTagName('ul')[0])
    {
      continue;
    }

    // adjust the link
    var newa=document.createElement('a');
    newa.href='#';
    newa.appendChild(document.createTextNode(lis[i].firstChild.nodeValue));
    lis[i].replaceChild(newa,lis[i].firstChild);

    // otherwise apply the parent class
    cssjs('add',newa,parentClass);

    // setup the link
    ref = lis[i].getElementsByTagName('a')[0];
    ref.id = 'finder[' + i + ']';
    window.finderOpened[ref.id] = false;

    // if the user clicks on the link
    ref.onclick=function()
    {
      // loop through all lists inside finder
      ul = this.parentNode.getElementsByTagName('ul')[0];
      for(var i=0;i<uls.length;i++)
      {
        // hide unconnected or closing elements
        if (!connected(ul, uls[i]) || window.finderOpened[this.id] == true)
        {
          ref = uls[i].parentNode.getElementsByTagName('a')[0];
          if (ref != this && !isparent(uls[i],ul)) {
            window.finderOpened[ref.id] = false;
            cssjs('add',uls[i],hideClass);
            cssjs('remove',uls[i],showClass);
            cssjs('remove',ref,openClass);
            cssjs('add',ref,parentClass);
          }
        }
      }	

      parentUls = this.parentNode.getElementsByTagName('ul');
      if (window.finderOpened[this.id] == false) {
        window.finderOpened[this.id] = true;
        // change the current link from parent to open 	
        // and show the current nested list 
        cssjs('remove',this,parentClass);
        cssjs('add',this,openClass);
        cssjs('add',parentUls[0],showClass);
      } else {
        window.finderOpened[this.id] = false;
        // change the current link from open to parent
        // and hide the current nested list 
        cssjs('add',this,parentClass);
        cssjs('remove',this,openClass);
        for(var u=0;u<parentUls.length;u++) {
          cssjs('remove',parentUls[u],showClass);
        }
      }

      // don't follow the real HREF of the link
      return false;
    }
  }	

  /*
   * isparent
   * written by Silvio - s1lv10 at uol.com.br
   * checks if an element is parent of another via DOM
   * inspired by http://stackoverflow.com/questions/245241/jquery-ancestors-using-jquery-objects
   */
  function isparent(par, child) {
    if ($(child).parents().index(par) >= 0) {
      return true;
    }
    return false;
  }

  /*
   * connected
   * written by Silvio - s1lv10 at uol.com.br
   * checks if two elements are connect via DOM, either by one being
   * child of parent of the another.
   */
  function connected(a, b) {
    if (isparent(a, b) || isparent(b, a)) {
      return true;
    }
    return false;
  }

  /*
   * cssjs
   * written by Christian Heilmann (http://icant.co.uk)
   * eases the dynamic application of CSS classes via DOM
   * parameters: action a, object o and class names c1 and c2 (c2 optional)
   * actions: swap exchanges c1 and c2 in object o
   *			add adds class c1 to object o
   *			remove removes class c1 from object o
   *			check tests if class c1 is applied to object o
   * example:	cssjs('swap',document.getElementById('foo'),'bar','baz');
   */
  function cssjs(a,o,c1,c2)
  {
    switch (a){
      case 'swap':
        o.className=!cssjs('check',o,c1)?o.className.replace(c2,c1):o.className.replace(c1,c2);
        break;
      case 'add':
        if(!cssjs('check',o,c1)){o.className+=o.className?' '+c1:c1;}
        break;
      case 'remove':
        var rep=o.className.match(' '+c1)?' '+c1:c1;
        o.className=o.className.replace(rep,'');
        break;
      case 'check':
        return new RegExp('\\b'+c1+'\\b').test(o.className)
          break;
    }
  }
}

// Check if the browser supports DOM, and start the script if it does.
if(document.getElementById && document.createTextNode)
{
  window.onload=ul2finder;
}