回答編集履歴

2

複数クエリを考慮するコードを追記

2017/09/12 08:27

投稿

Tomak
Tomak

スコア1652

test CHANGED
@@ -115,3 +115,259 @@
115
115
  ```
116
116
 
117
117
 
118
+
119
+ #### 追記
120
+
121
+
122
+
123
+ `hoge.html?A=1`などのクエリストリングありの時に、マッチしないというコメントを頂いたので追記しておきます。
124
+
125
+
126
+
127
+ 多分考えられる原因は、他のクエリまたはハッシュが入っているということだと思います。下記の「&他のクエリ=1#ハッシュ」がなければ、普通に完全一致します。
128
+
129
+
130
+
131
+ ■ページ
132
+
133
+ http://ドメイン/hoge.html?A=1&他のクエリ=1#ハッシュ
134
+
135
+
136
+
137
+ ■ナビのリンク
138
+
139
+ http://ドメイン/hoge.html?A=1
140
+
141
+
142
+
143
+ JavaScriptでURLをパースしようとすると結構めんどくさいです。今回はクエリストリングをパースできる関数を作成してからクエリストリングを比較する方針にします。
144
+
145
+
146
+
147
+ 下記コードはハッシュの違いを無視します。また、相対パスは考慮していません。
148
+
149
+
150
+
151
+ ```js
152
+
153
+ $(function(){
154
+
155
+ function getQueryString (url)
156
+
157
+ {
158
+
159
+ if (url !== undefined && url === '') {
160
+
161
+ return [];
162
+
163
+ }
164
+
165
+
166
+
167
+ var vars = [], hash;
168
+
169
+ var path = url === undefined ? window.location.href : $('<a href="'+ url +'"/>').get(0).href;
170
+
171
+
172
+
173
+ if (path.indexOf('?') >= 0 && path.length != path.indexOf('?') + 1) {
174
+
175
+ var hashes = path.indexOf('#') >= 0
176
+
177
+ ? path.slice(path.indexOf('?') + 1, path.indexOf('#')).split('&')
178
+
179
+ : path.slice(path.indexOf('?') + 1).split('&');
180
+
181
+
182
+
183
+ for(var i = 0; i < hashes.length; i++) {
184
+
185
+ hash = hashes[i].split('=');
186
+
187
+ vars.push(hash[0]);
188
+
189
+ vars[hash[0]] = hash[1];
190
+
191
+ }
192
+
193
+ }
194
+
195
+
196
+
197
+ return vars;
198
+
199
+ }
200
+
201
+
202
+
203
+ function escapeRegExp (str)
204
+
205
+ {
206
+
207
+ return str.replace(/([.*+?^=!:${}()|[\]\/\\])/g, "\\$1");
208
+
209
+ }
210
+
211
+
212
+
213
+
214
+
215
+ //現在表示ページのURLのクエリストリングをパース
216
+
217
+ var currentURI = location.href;
218
+
219
+
220
+
221
+ // http://ドメイン/xxx.html? 最後が?のみのURI
222
+
223
+ if (currentURI.length == currentURI.indexOf('?') + 1) {
224
+
225
+ currentURI = currentURI.replace('?', '');
226
+
227
+ }
228
+
229
+
230
+
231
+ var currentQueries = getQueryString(currentURI);
232
+
233
+
234
+
235
+ // http://ドメイン/xxx.html#hash 最後がハッシュのみのURI
236
+
237
+ if (currentQueries.length == 0 && currentURI.indexOf('#')) {
238
+
239
+ currentURI = currentURI.replace(/\#.*/, '');
240
+
241
+ }
242
+
243
+
244
+
245
+ //console.log(currentURI, currentQueries);
246
+
247
+
248
+
249
+ //ナビゲーションリンクからすべての.currentクラスを削除してから.currentを追加
250
+
251
+ $('#gNav li a')
252
+
253
+ .removeClass('current')
254
+
255
+ .each(function(){
256
+
257
+ var nav = $(this).attr('href');
258
+
259
+ var navQueries = getQueryString(nav); //ナビゲーションhrefのクエリストリングをパース
260
+
261
+
262
+
263
+ if (currentQueries.length > 0) {
264
+
265
+ for (var i = 0; i < currentQueries.length; i++) {
266
+
267
+ //最初のクエリストリングのみ調査
268
+
269
+ if ($.inArray(currentQueries[i], navQueries) >= 0 &&
270
+
271
+ currentQueries[currentQueries[i]] == navQueries[currentQueries[i]])
272
+
273
+ {
274
+
275
+ $(this).addClass('current');
276
+
277
+ return false; //break
278
+
279
+ }
280
+
281
+ }
282
+
283
+ } else {
284
+
285
+ if (currentURI.match(new RegExp('^'+ escapeRegExp(nav) +'$', 'i'))) {
286
+
287
+ $(this).addClass('current');
288
+
289
+ return false; //break
290
+
291
+ }
292
+
293
+ }
294
+
295
+ });
296
+
297
+ });
298
+
299
+ ```
300
+
301
+
302
+
303
+ すべてのクエリストリングがマッチしているかを調べる場合は下記にようにすれば調べられます。
304
+
305
+
306
+
307
+ ```js
308
+
309
+ var currentFlag = false;
310
+
311
+
312
+
313
+ //ナビゲーションリンクからすべての.currentクラスを削除してから.currentを追加
314
+
315
+ $('#gNav li a')
316
+
317
+ .removeClass('current')
318
+
319
+ .each(function(){
320
+
321
+ var nav = $(this).attr('href');
322
+
323
+ var navQueries = getQueryString(nav); //ナビゲーションhrefのクエリストリングをパース
324
+
325
+
326
+
327
+ if (currentQueries.length > 0) {
328
+
329
+ for (var i = 0; i < currentQueries.length; i++) {
330
+
331
+ //すべてのクエリストリングを調査
332
+
333
+ if ($.inArray(currentQueries[i], navQueries) >= 0 &&
334
+
335
+ currentQueries[currentQueries[i]] == navQueries[currentQueries[i]])
336
+
337
+ {
338
+
339
+ currentFlag = true;
340
+
341
+ } else {
342
+
343
+ return true; //continue
344
+
345
+ }
346
+
347
+ }
348
+
349
+ if (currentFlag) {
350
+
351
+ $(this).addClass('current');
352
+
353
+ return false; //break
354
+
355
+ }
356
+
357
+ } else {
358
+
359
+ if (currentURI.match(new RegExp('^'+ escapeRegExp(nav) +'$', 'i'))) {
360
+
361
+ $(this).addClass('current');
362
+
363
+ return false; //break
364
+
365
+ }
366
+
367
+ }
368
+
369
+ });
370
+
371
+ ```
372
+
373
+

1

勘違いしてた回答を修正

2017/09/12 08:27

投稿

Tomak
Tomak

スコア1652

test CHANGED
@@ -1,4 +1,92 @@
1
+ > スタンダード:hoge.html
2
+
3
+ Aタイプ :hoge.html?A=1
4
+
5
+ Bタイプ :hoge.html?B=1
6
+
7
+ Cタイプ :hoge.html?C=1
8
+
9
+
10
+
11
+ ちょっと質問を勘違いしていたみたなので、回答を書き直します。
12
+
13
+ 下記のような場合で、「現在hoge.htmlの時」にすべてのナビゲーションリンクでMatchしてしまうのを解決したいということでしょうか?
14
+
15
+
16
+
17
+ **■現在hoge.htmlの時**
18
+
19
+ | ナビリンク | match() | 結果 | 一致 |
20
+
21
+ |---------------|----------------------------|:------:|---------|
22
+
23
+ | hoge.html | location.href.match($href) | Match | 完全一致 |
24
+
25
+ | hoge.html?A=1 | location.href.match($href) | Match | 前方一致 |
26
+
27
+ | hoge.html?B=1 | location.href.match($href) | Match | 前方一致 |
28
+
29
+ | hoge.html?C=1 | location.href.match($href) | Match | 前方一致 |
30
+
31
+
32
+
33
+ **■現在hoge.html?A=1の時**
34
+
35
+ | ナビリンク | match() | 結果 | 一致 |
36
+
37
+ |---------------|----------------------------|:------:|---------|
38
+
39
+ | hoge.html | location.href.match($href) | × |   |
40
+
41
+ | hoge.html?A=1 | location.href.match($href) | Match | 完全一致 |
42
+
43
+ | hoge.html?B=1 | location.href.match($href) | × |   |
44
+
45
+ | hoge.html?C=1 | location.href.match($href) | × |   |
46
+
47
+
48
+
49
+ **■現在hoge.html?B=1の時**
50
+
51
+ | ナビリンク | match() | 結果 | 一致 |
52
+
53
+ |---------------|----------------------------|:------:|---------|
54
+
55
+ | hoge.html | location.href.match($href) | × |   |
56
+
57
+ | hoge.html?A=1 | location.href.match($href) | × |   |
58
+
59
+ | hoge.html?B=1 | location.href.match($href) | Match | 完全一致 |
60
+
61
+ | hoge.html?C=1 | location.href.match($href) | × |   |
62
+
63
+
64
+
65
+ **■現在hoge.html?C=1の時**
66
+
67
+ | ナビリンク | match() | 結果 | 一致 |
68
+
69
+ |---------------|----------------------------|:------:|---------|
70
+
71
+ | hoge.html | location.href.match($href) | × |   |
72
+
73
+ | hoge.html?A=1 | location.href.match($href) | × |   |
74
+
75
+ | hoge.html?B=1 | location.href.match($href) | × |   |
76
+
77
+ | hoge.html?C=1 | location.href.match($href) | Match | 完全一致 |
78
+
79
+
80
+
81
+
82
+
83
+ 正規表現で完全一致するようにします。このとき、正規表現のメタ文字をエスケープしてから`RegExp()`で正規表現オブジェクトを作成します。
84
+
85
+
86
+
1
- 「クエリストリングがなっかたら」をif文の条件に追加すばいいます
87
+ もうちょしこい方法があるかもしませんが、りあえず下記でかがでしょうか
88
+
89
+ 正規表現のメタ文字エスケープ`.replace()`部分は関数にしたほうがいいかもしれません。
2
90
 
3
91
 
4
92
 
@@ -8,9 +96,9 @@
8
96
 
9
97
  $('#gNav li a').each(function(){
10
98
 
11
- var $href = $(this).attr('href');
99
+ var $href = new RegExp('^'+ $(this).attr('href').replace(/([.*+?^=!:${}()|[\]\/\\])/g, "\\$1") +'$', 'i');
12
100
 
13
- if(location.href.match($href) && location.href.match(/\?/) === null) {
101
+ if(location.href.match($href)) {
14
102
 
15
103
  $(this).addClass('current');
16
104
 
@@ -25,3 +113,5 @@
25
113
  });
26
114
 
27
115
  ```
116
+
117
+