Loop to create variables, function/array loop

Viewed 64

I coded a program to highlight a selected button when clicked and to un-highlight it when another button is clicked. It is working, but I need to make it less repetitive (using maybe loops).

var txt = $(".txt");
var xls = $(".xls");
var jpg = $(".jpg");
var png = $(".png");
var pdf = $(".pdf");
var mp3 = $(".mp3");
var mp4 = $(".mp4");
var gif = $(".gif");
var flac = $(".flac");
var html = $(".html");
var js = $(".js");
var aac = $(".aac");
var ai = $(".ai");
var avi = $(".avi");
var psd = $(".psd");
var tiff = $(".tiff");

var fileTypes = [txt, xls, jpg, png, pdf, mp3, mp4, gif, flac, html, js, aac, ai, avi, psd, tiff];

$(fileTypes[0]).click( function() {
    for(i=0; i<fileTypes.length; i++) 
    {
        fileTypes[i].removeClass("selected");
        fileTypes[i].addClass("not-selected");
    }

    fileTypes[0].removeClass("not-selected");
    fileTypes[0].addClass("selected");
});

$(fileTypes[1]).click( function() {
    for(i=0; i<fileTypes.length; i++) 
    {
        fileTypes[i].removeClass("selected");
        fileTypes[i].addClass("not-selected");
    }

    fileTypes[1].removeClass("not-selected");
    fileTypes[1].addClass("selected");

});

$(fileTypes[2]).click( function() {
    for(i=0; i<fileTypes.length; i++) 
    {
        fileTypes[i].removeClass("selected");
        fileTypes[i].addClass("not-selected");
    }

    fileTypes[2].removeClass("not-selected");
    fileTypes[2].addClass("selected");

});  // It does this 16 times, the length of the fileTypes array

I have tried using a for loop to solve this problem, but I have been unsuccessful. Please help. Thanks.

3 Answers

Perhaps you could simplify you script by doing something along the lines of the following:

var extensions = ['.txt',
'.xls',
'.jpg',
'.png',
'.pdf',
'.mp3',
'.mp4',
'.gif',
'.flac',
'.html',
'.js',
'.aac',
'.ai',
'.avi',
'.psd',
'.tiff']

// Create a selector that selects all classes in
// the extensions array
var selector = extensions.join(',');

// Assign a click handler to each element in the
// selected string
$(selector).click(function() {

  // When clicked, remove the selected 
  // class, and add not-selected to all 
  // elements in the selector
  $(selector)
  .removeClass('selected')
  .addClass('not-selected')

  // For this item, remove not-selected
  // class and add selected class
  $(this)
  .removeClass('not-selected')
  .addClass('selected')

})
.selected {
background:red;
}

.not-selected {
background:white;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<button class="txt">txt</button>
<button class="xls">xls</button>
<button class="jpg">jpg</button>
<button class="png">png</button>
<button class="pdf">pdf</button>
<button class="mp3">mp3</button>
<button class="mp4">mp4</button>
<button class="gif">gif</button>
<button class="flac">flac</button>
<button class="html">html</button>
<button class="js">js</button>
<button class="aac">aac</button>
<button class="ai">ai</button>
<button class="avi">avi</button>
<button class="psd">psd</button>
<button class="tiff">tiff</button>

Something like this?

var toggelf = function(event) {
    for(i=0; i<fileTypes.length; i++) 
    {
        fileTypes[i].switchClass("selected","not-selected");
    }
    $(event.currentTarget).switchClass("not-selected","selected");
}

for(i=0; i<fileTypes.length; i++) 
{
    $(fileTypes[i]).click(toggelf);
}

I did not test it but it should work. Basically I create an anonymous function assign it to a variable and use it as a handler for clicks on all your objects.

I would prefer to not have to define every type in javascript, and use the dom itself to define the types (however you like). This can be achieved by wrapping your objects in a container. For example:

const buttons = '.buttons button'

$(buttons).click(function() {
  $(buttons).removeClass('selected')
  $(this).addClass('selected')
})
.selected {
  background:red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<div class="buttons">
  <button>txt</button>
  <button>xls</button>
  <button>jpg</button>
  <button>png</button>
  <button>pdf</button>
  <button>mp3</button>
  <button>mp4</button>
  <button>gif</button>
  <button>flac</button>
  <button>html</button>
  <button>js</button>
  <button>aac</button>
  <button>ai</button>
  <button>avi</button>
  <button>psd</button>
  <button>tiff</button>
</div>

I also wouldn't have both selected and not selected classes, as one is redundant.


Just note that my reasoning for this is that you shouldn't be duplicating the set of filetypes in both dom and javascript; just pick one place. Ultimately I would prefer to do this completely data driven from within javascript, using something like react, but with jquery it makes sense to describe in the dom.

Related