0

I'm trying to shorten my function that contains a number of if statements into a loop function but just can't seem to get it to work. It is currently working in Google Tag Manager as a Custom Javascript Macro.

I'm not a developer or very good at Javascript so any help will be greatly appreciated.

Code:

  function()
  {
  if(document.getElementById('bfPage1').style.display !== "none")
     {return document.getElementById('bfPage1').getAttribute('id');
     }
  else
     if(document.getElementById('bfPage2').style.display !== "none")
        {return document.getElementById('bfPage2').getAttribute('id');
        }
     else
        if(document.getElementById('bfPage3').style.display !== "none")
           {return document.getElementById('bfPage3').getAttribute('id');
           }
        else
           {return document.getElementById('bfPage4').getAttribute('id')
           }
  }

Thanks in advance.

1
  • better for codereview.stackexchange.com Commented Jul 17, 2014 at 15:55

3 Answers 3

1

TLDR:

// with jQuery
var allPages = $('[id^=bfPage]')
var activeId = allPages.filter(':visible').attr('id')

// with ES6
const allPages = [].slice.apply(document.querySelectorAll('[id^=bfPage]'));
let activeId = allPages.find( e => e.style.display !== "none").id;

First of all you do not need to nest your ifs using else statements, because you are using return statement inside each of them. So after first refactoring you are going to have:

function()
{
  if(document.getElementById('bfPage1').style.display !== "none")
   {return document.getElementById('bfPage1').getAttribute('id');
  }

  if(document.getElementById('bfPage2').style.display !== "none")
    {return document.getElementById('bfPage2').getAttribute('id');
    }

  if(document.getElementById('bfPage3').style.display !== "none")
       {return document.getElementById('bfPage3').getAttribute('id');
       }
  if(document.getElementById('bfPage4').style.display !== "none")
       {return document.getElementById('bfPage4').getAttribute('id')
       }
}

Next step is to notice that that each time you are quering element twice:

function()
{
  var page
  page = document.getElementById('bfPage1')
  if(page.style.display !== "none")
  {
    return page.getAttribute('id');
  }
  page = document.getElementById('bfPage2')
  if(page.style.display !== "none")
  {
    return page.getAttribute('id');
  }
  page = document.getElementById('bfPage3')
  if(page.style.display !== "none")
  {
    return page.getAttribute('id');
  }
  page = document.getElementById('bfPage4')
  if(page.style.display !== "none")
  {
    return page.getAttribute('id')
  }
}

Now you clearly see that you can use loop instead of repeating statements

function()
{
  var pages = ['bfPage1','bfPage2','bfPage3','bfPage4']
  for (var i in pages) {
    page = document.getElementById(pages[i])
    if(page.style.display !== "none")
    {
      return page.getAttribute('id');
    }
  }
}    

Oh and you already know id

function()
{
  var pages = ['bfPage1','bfPage2','bfPage3','bfPage4']
  for (var i in pages) {
    page = document.getElementById(pages[i])
    if(page.style.display !== "none")
    {
      return pages[i];
    }
  }
} 

Which is quite nice.

You can use jquery and make one-liner out of it:

$('[id^=bgPage]:visible]').attr('id') 

This is good result but lets think why do we need to do this in the first place?

You have some logic to show and hide elements of the page and you want to check which one is visible.

Instead of doing that with styles of elements, lets do two things.

  • add new class for every element .bfPage

  • lets add class visible or active to the only visible element

This way your code to get id will be changed to:

$('.bfPage.active').attr('id')

Which in case of real application will be split on two parts:

somewhere in the beginning you will have

var allPages = $('.bfPages')

and somewhere where you need to find that element

var activeId =  allPages.filter('.active').attr('id')

Of course if it is not the case you still can improve performance caching all bfPages

var allPages = $('[id^=bfPage]')

...

var activeId = allPages.filter(':visible').attr('id')
Sign up to request clarification or add additional context in comments.

Comments

0

You could create an array of all your element ids and loop over that and return the id of the first visible one:

var pageIds = ['bfPage1', 'bfPage2', 'bfPage3', 'bfPage4'];
for(var i=0;i<pageIds.length;i++){
    var elemId = pageIds[i];
    if(document.getElementById(elemId).style.display !== 'none')
    {
        return elemId;
    }
}

Comments

0

Is this what you're trying to do?

function(){
    for (var i = 0; i < 4; i++){
        var id = "bfPage" + i;
        if(document.getElementById(id).style.display !== "none"){
            return id;
        }
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.