_table.html.erb 5.8 KB
Newer Older
1
<% content_for :style do %>
2
  #route_table {
3
    margin: 0;
4 5 6
    border-collapse: collapse;
  }

7 8 9 10 11 12
  #route_table thead tr {
    border-bottom: 2px solid #ddd;
  }

  #route_table thead tr.bottom {
    border-bottom: none;
13 14
  }

15 16
  #route_table thead tr.bottom th {
    padding: 10px 0;
17 18 19
    line-height: 15px;
  }

20 21 22 23 24 25 26 27
  #route_table tbody tr {
    border-bottom: 1px solid #ddd;
  }

  #route_table tbody tr:nth-child(odd) {
    background: #f2f2f2;
  }

28 29
  #route_table tbody.exact_matches,
  #route_table tbody.fuzzy_matches {
30
    background-color: LightGoldenRodYellow;
31
    border-bottom: solid 2px SlateGrey;
32 33
  }

34 35
  #route_table tbody.exact_matches tr,
  #route_table tbody.fuzzy_matches tr {
36 37 38 39 40 41
    background: none;
    border-bottom: none;
  }

  #route_table td {
    padding: 4px 30px;
42 43 44 45 46 47
  }

  #path_search {
    width: 80%;
    font-size: inherit;
  }
48
<% end %>
S
schneems 已提交
49 50 51 52

<table id='route_table' class='route_table'>
  <thead>
    <tr>
53 54 55 56 57 58 59
      <th>Helper</th>
      <th>HTTP Verb</th>
      <th>Path</th>
      <th>Controller#Action</th>
    </tr>
    <tr class='bottom'>
      <th><%# Helper %>
S
schneems 已提交
60 61 62
        <%= link_to "Path", "#", 'data-route-helper' => '_path',
                    title: "Returns a relative path (without the http or domain)" %> /
        <%= link_to "Url", "#", 'data-route-helper' => '_url',
63 64 65 66 67
                    title: "Returns an absolute url (with the http and domain)"   %>
      </th>
      <th><%# HTTP Verb %>
      </th>
      <th><%# Path %>
68
        <%= search_field(:path, nil, id: 'search', placeholder: "Path Match") %>
69 70
      </th>
      <th><%# Controller#action %>
S
schneems 已提交
71 72 73
      </th>
    </tr>
  </thead>
74 75 76
  <tbody class='exact_matches' id='exact_matches'>
  </tbody>
  <tbody class='fuzzy_matches' id='fuzzy_matches'>
77
  </tbody>
S
schneems 已提交
78 79 80 81 82 83
  <tbody>
    <%= yield %>
  </tbody>
</table>

<script type='text/javascript'>
84
  // Iterates each element through a function
S
schneems 已提交
85
  function each(elems, func) {
86
    if (!elems instanceof Array) { elems = [elems]; }
87
    for (var i = 0, len = elems.length; i < len; i++) {
S
schneems 已提交
88
      func(elems[i]);
89
    }
S
schneems 已提交
90 91
  }

92 93 94
  // Sets innerHTML for an element
  function setContent(elem, text) {
    elem.innerHTML = text;
S
schneems 已提交
95 96
  }

97 98 99 100 101 102
  // Enables path search functionality
  function setupMatchPaths() {
    // Check if the user input (sanitized as a path) matches the regexp data attribute
    function checkExactMatch(section, elem, value) {
      var string = sanitizePath(value),
          regexp = elem.getAttribute("data-regexp");
S
schneems 已提交
103

104 105
      showMatch(string, regexp, section, elem);
    }
S
schneems 已提交
106

107 108 109 110
    // Check if the route path data attribute contains the user input
    function checkFuzzyMatch(section, elem, value) {
      var string = elem.getAttribute("data-route-path"),
          regexp = value;
111

112 113
      showMatch(string, regexp, section, elem);
    }
114

115 116 117 118 119 120 121 122 123 124 125 126 127
    // Display the parent <tr> element in the appropriate section when there's a match
    function showMatch(string, regexp, section, elem) {
      if(string.match(RegExp(regexp))) {
        section.appendChild(elem.parentNode.cloneNode(true));
      }
    }

    // Check if there are any matched results in a section
    function checkNoMatch(section, defaultText, noMatchText) {
      if (section.innerHTML === defaultText) {
        setContent(section, defaultText + noMatchText);
      }
    }
128

129 130 131 132 133
    // Ensure path always starts with a slash "/" and remove params or fragments
    function sanitizePath(path) {
      var path = path.charAt(0) == '/' ? path : "/" + path;
      return path.replace(/\#.*|\?.*/, '');
    }
134

135 136 137 138 139 140 141 142 143 144 145
    var regexpElems     = document.querySelectorAll('#route_table [data-regexp]'),
        searchElem      = document.querySelector('#search'),
        exactMatches    = document.querySelector('#exact_matches'),
        fuzzyMatches    = document.querySelector('#fuzzy_matches');

    // Remove matches when no search value is present
    searchElem.onblur = function(e) {
      if (searchElem.value === "") {
        setContent(exactMatches, "");
        setContent(fuzzyMatches, "");
      }
146 147 148
    }

    // On key press perform a search for matching paths
149 150
    searchElem.onkeyup = function(e){
      var userInput         = searchElem.value,
151 152
          defaultExactMatch = '<tr><th colspan="4">Paths Matching (' + escape(sanitizePath(userInput)) +'):</th></tr>',
          defaultFuzzyMatch = '<tr><th colspan="4">Paths Containing (' + escape(userInput) +'):</th></tr>',
153 154
          noExactMatch      = '<tr><th colspan="4">No Exact Matches Found</th></tr>',
          noFuzzyMatch      = '<tr><th colspan="4">No Fuzzy Matches Found</th></tr>';
155 156

      // Clear out results section
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
      setContent(exactMatches, defaultExactMatch);
      setContent(fuzzyMatches, defaultFuzzyMatch);

      // Display exact matches and fuzzy matches
      each(regexpElems, function(elem) {
        checkExactMatch(exactMatches, elem, userInput);
        checkFuzzyMatch(fuzzyMatches, elem, userInput);
      })

      // Display 'No Matches' message when no matches are found
      checkNoMatch(exactMatches, defaultExactMatch, noExactMatch);
      checkNoMatch(fuzzyMatches, defaultFuzzyMatch, noFuzzyMatch);
    }
  }

  // Enables functionality to toggle between `_path` and `_url` helper suffixes
  function setupRouteToggleHelperLinks() {
174

175 176 177 178
    // Sets content for each element
    function setValOn(elems, val) {
      each(elems, function(elem) {
        setContent(elem, val);
179
      });
180
    }
181

182 183 184 185 186
    // Sets onClick event for each element
    function onClick(elems, func) {
      each(elems, function(elem) {
        elem.onclick = func;
      });
187
    }
188 189 190 191 192 193 194 195

    var toggleLinks = document.querySelectorAll('#route_table [data-route-helper]');
    onClick(toggleLinks, function(){
      var helperTxt   = this.getAttribute("data-route-helper"),
          helperElems = document.querySelectorAll('[data-route-name] span.helper');

      setValOn(helperElems, helperTxt);
    });
196 197 198
  }

  setupMatchPaths();
S
schneems 已提交
199 200
  setupRouteToggleHelperLinks();
</script>