0

I've been doing a bit of basic web development recently and in order to implement some nice-looking navigation between 'pages' without an 'actual' page reload, I've used JavaScript to trigger transitions when the user clicks buttons on the page.

My page has got three 'content views': music, apps and stuff.

Here's my code—only 37 lines. At this stage it's perfectly manageable, but what changes could I make to help it scale up when my website gains more pages and content? All this clutter in the global scope seems a bit messy to me.

var musicContent, appsContent, stuffContent, currentlyShowingContent;

// Add event listener to initialise stuff once DOM has loaded
document.addEventListener('DOMContentLoaded', init, false);

function init() {
  // Load content wrappers from DOM
  musicContent = document.getElementById('music-content');
  appsContent = document.getElementById('apps-content');
  stuffContent = document.getElementById('stuff-content');

  // Set up intitial state (showing 'music' content)
  currentlyShowingContent = musicContent;
  appsContent.classList.add('not-showing');
  stuffContent.classList.add('not-showing');

  // Add event listeners for links to each page
  document.getElementById('music-button').addEventListener('click', function (){
    switchContentTo(musicContent);
  });
  document.getElementById('apps-button').addEventListener('click', function (){
    switchContentTo(appsContent);
  });
  document.getElementById('stuff-button').addEventListener('click', function (){
    switchContentTo(stuffContent);
  });
};

function switchContentTo(newContent) {
  // Hide current content
  currentlyShowingContent.classList.add('not-showing');

  // Show new content
  newContent.classList.remove('not-showing');

  currentlyShowingContent = newContent;
}

Whilst I am aware that there is nothing horribly wrong with the way I have programmed this, I am wondering if there is a better way of structuring my code. If my website were to grow and I wanted to add some more 'pages', I would have to go back into my code and manually insert lines that add event listeners for each button and handle them separately. This seems like an awful faff for simply wanting to add some content.

Is this kind of code normal in web development? I've read a lot about structuring JavaScript code including using patterns such as Modules but it all seems a bit too complicated for code that is in only in charge of a single web page. I've also read quite a lot about web development in general, but books and websites never seem to address structuring JavaScript code.

Can I write this in a better way that allows me to entirely separate content from web page logic?

j08691
  • 204,283
  • 31
  • 260
  • 272
  • 4
    Possibly a better fit for https://codereview.stackexchange.com/ – j08691 Aug 01 '17 at 16:41
  • This is one of the reason people use libraries like Vue.js — it takes some of the pain out this kind of work when projects start to get big. – Mark Aug 01 '17 at 16:42
  • 1
    Basically what Mark_M mentioned, this is why frameworks exist. Also may be worth looking at JavaScript Design Patterns – aug Aug 01 '17 at 16:43
  • it's look like a static web page, if so I advise you to keep only in html, could you give more information about you problem? – Claudio Santos Aug 01 '17 at 16:46
  • @ClaudioSantos It's a static web page apart from the animated transitioning between pages. I don't think such transitions would be possible using only HTML. Or are you advising me keep the JavaScript within a – 雨が好きな人 Aug 01 '17 at 16:52

2 Answers2

1

Making the code generic

The only page-specific part is where you find music-button and music-content and do magic with them. Those parts are duplicated for each page you have, so eventually that becomes a big chunk of repeating code.

You can solve this issue by making your code more generic. One simple way would be to have an array of terms ['music', 'apps', 'stuff'] and find the items from there. But then you'd still have that array.

So, could you store that array somehow in the page? If you'd use classes for the buttons and the content, it would be even easier to find all of them, so by adding class='button' to the buttons, you could find all the buttons. Then you need to tell your script which button it is. There are various ways to do that, but one I like is using data-attributes.

The end result, instead of writing:

<div id='music-content'></div>

You'd write:

<div class='content' data-page='music'></div>

You can find the classes 'content', get their 'page' data-attribute, and use that to find a matching button (again by class and type). You can do all the linking and handling of events in a loop, and the script doesn't have to know about particular music, apps and stuff pages. It just needs to know that there are pages and buttons, and that those with the same data-page belong together.

See MDN Web Docs for more information about data-attributes

Loading the content on demand

After you've solved the first pickle, you may worry about the content itself. Currently you may have all the content available in the page itself, but later on you probably want to dynamically load it. To do that, you can use Ajax (in one of its many forms). Since you've managed to go without jQuery so far, I seriously suggest continuing like that. JavaScript is maturing too and most browsers are standardized. Since you (hopefully) won't need any IE 6-8 support, most of it can be done with a couple of lines of code.

The content itself is probably static too, so you might consider just putting simple files with content snippets on the server. Using Ajax, you can fetch music.html from the server when you click the music button. Again, this is generic based on the attributes of the button.

Check vanilla-js.com for a nice handful of plain JavaScript versions of popular JQuery functionality.

Lazy loading images

The content may be just a small piece of text, and loading text is not a big issue because it can be heavily compressed. So while you still have a couple of pages (or even some dozens), you may want to have all the textual content available in the page already, and not use AJAX at all for it. Images and other binary content will add up much more quickly, though, so you may want to load textual content, in combination with a lazy loading mechanism for images.

Lazy loading is typically done for long, image-rich pages, to only load the images as soon as they become visible. I don't know if that would be useful for you (maybe your pages aren't long at all, or they don't have many images). But what would be useful is to only load the images of the visible page, and only start loading images of another page once a visitor has clicked the button for that page.

Lazy loading is a bit harder to implement though, and you may want to have a peek at existing libraries or examples like the one on CSS Tricks. Or you could just skip this solution altogether and just use the simpler Ajax request to load the text, which will in turn automatically trigger the browser to load any other content.

GolezTrol
  • 114,394
  • 18
  • 182
  • 210
0

It's look like a static web page.

My advise to you is to structure your pages by subject and create a folder for each one, then put each related page on each subject folder.

The problem of your solution needs, is the needy to load the entire website at the first access. So if the number of pages increase you have a downtime on the first access.

music\
    indie.html
    rock.html
apps\
    financial.html
    games.html
index.html

Then all of your site have a uri for each information, and this is SEO friendly.

UPDATE

To load dynamic content this answer could be helpful for you.

Then each link or button need to call the function bellow:

function loadContentFrom(urlContent) {
    // #content is the div that will show your information
    $('#content').load(urlContent);
}
Claudio Santos
  • 1,307
  • 13
  • 22
  • You're right about this, but I want to have a nice animation between page transitions. Is there a way of doing that using pure HTML and CSS? Splitting my website into 'actual' pages means that when the user clicks from one to the next they see an ugly brief white page and a hard-refresh. – 雨が好きな人 Aug 01 '17 at 17:04
  • yes, to avoid this you'll need to use ajax, and start use jquery. – Claudio Santos Aug 01 '17 at 17:05
  • You know that the jQuery library is probably as large as all the textual content you're going to add to your page in the near future? The minified version is **85KB**. For comparison, this Q&A page is about 13kb of plain text (Press Ctrl+A and paste in Notepad). So you can have about 7 times all this text (probably even more, since text can be compressed better than minified JS) before you break even with jQuery for loading additional pages. Then again, you can do the same thing with just 5 lines of plain JavaScript, and you *will* immediately have the benefit you're after. – GolezTrol Aug 02 '17 at 08:54