Reputation: 4492
I'm messing around with dat.gui for my first time ever to create a search system for TV Shows I'm interested in. I started by creating an object with the show title as key and search query as value. Everything worked all fine until I put it into practice and it searches for the last key every time. I was worried about this happening when I did this but couldn't think of anyway around it. I thought about using window['string']
to set the variable name from a string but couldn't work out how it'd work in my case.
I'm using a userscript so I have some limits. My script is below:
NodeList.prototype.forEach = Array.prototype.forEach;
var shows = {
'Agents of S.H.I.E.L.D.' : 'marvels agents of s.h.i.e.l.d.',
'Arrow' : 'arrow s',
'Brooklyn Nine-Nine' : 'brooklyn nine-nine',
'Castle' : 'castle 2009',
'Chicago Fire' : 'chicago fire',
'Chicago P.D.' : 'chicago p.d.',
'Constantine' : 'contanstine s',
'Doctor Who' : 'doctor who',
'Gotham' : 'gotham s',
'Grimm' : 'grimm s',
'Madam Secretary' : 'madam secretary',
'NCIS LA' : 'ncis los angeles',
'Resurrection' : 'resurrection',
'Saturday Night Live' : 'saturday night live',
'Scandal' : 'scandal s',
'Scorpion' : 'scorpion s',
'Stalker' : 'stalker s',
'The 100' : 'the 100 s',
'The Big Bang Theory' : 'the big bang theory',
'The Blacklist' : 'the blacklist',
'The Flash' : 'the flash',
'The Tonight Show Starring Jimmy Fallon' : 'jimmy fallon',
'Z Nation' : 'z nation'
},
show = function() {
for (var k in shows) {
this[k] = function() {
document.getElementById('tsstac').value = shows[k].replace(/ /g, '.');
document.querySelectorAll('[type=submit]')[0].click();
};
}
};
window.onload = function() {
var text = new show(),
gui = new dat.GUI({
resizable : false,
hideable : false
});
for (var k in shows) {
gui.add(text, k);
}
document.querySelectorAll('li.cr>div>span.property-name').forEach(function(v) {
v.style.width = '100%';
});
};
<script src="http://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.5/dat.gui.min.js"></script>
<input type="text" id="tsstac" />
<input type="submit" />
<p>Regardless of which button is pressed, it'll always be the last query.</p>
Regardless of what button is pressed, the last query (Z Nation) is always searched. How can I fix this problem?
EDIT:
I've updated the code a bit but still doesn't work.
EDIT:
The code no longer creates checkboxes but instead a list of buttons. The problem still exists and there is now a demonstration.
Upvotes: 1
Views: 879
Reputation: 20230
You are getting this issue due to a javascript closure issue (check out this answer for more information); each of your anonymous functions is bound to the same variable outside of the function (in your case the final value of k in your "for (var k in shows)" loop).
To get around this issue you can create the dat.GUI button's function outside of the for loop. I've created a CodePen of this working here:
http://codepen.io/BenSmith/pen/LEwje
Clicking on "Gotham", for example, will now populate the input control with the value "gotham.s", as per the behaviour you defined in your example.
The code to achieve this is:
NodeList.prototype.forEach = Array.prototype.forEach;
var shows = {
'Agents of S.H.I.E.L.D.' : 'marvels agents of s.h.i.e.l.d.',
'Arrow' : 'arrow s',
'Brooklyn Nine-Nine' : 'brooklyn nine-nine'
// Object shortened for brevity
};
showsProperties = {
shows: "shows"
};
window.onload = function() {
var gui = new dat.GUI();
// Get around the closure issue by implementing
// the dat.GUI button handler outside of the for loop
var showHandler = function(show)
{
return function(){
return show.replace(/ /g, '.');
}
}
for(var key in shows)
{
showsProperties[key] = showHandler(shows[key]);
var showController = gui.add(showsProperties, key );
showController.onFinishChange(function(value) {
document.getElementById('showSearchField').value = value();
});
};
document.querySelectorAll('li.cr>div>span.property-name').forEach(function(v) {
v.style.width = '100%';
});
};
Upvotes: 1