1

I operate a phpBB forum, on which I have installed this Syntax Highlighter MOD. Today, I started working on a feature that will use two DIVs to make the code box appear in full screen on the page. The DIV on which the user clicks to load the box in full screen will always have the same ID, but the syntax highlighter has a DIV ID which is random each time the page is loaded. I am having an issue with the DIV on which the user clicks always loading the first instance of the code box in full screen, regardless of which version of the DIV the user clicks on.

If you are have a hard time understanding what I am saying, here is an ugly, but usable demo. To make the ugly orange box load in full screen, click on the blue image above it. Each blue image is in its own DIV, both of which have the ID 'first'. The first ugly orange box has the ID 'testDIV' and the second has the ID 'testDIV2'. The code is written in such way that the DIV of each ugly orange box should be determined based on the DIV of the button. While my code works for this, it only works to find the first orange box.

Here is the code that I wrote that forms the demo.

<!-- HTML div Guniea Pigs -->
<div id="first" align="right"><img src="http://cdn2.iconfinder.com/data/icons/metro-uinvert-dock/128/Full_Screen.png" height="24" width="24" onclick="toggleFullScreen()" id="viewToggleImg" style="cursor:pointer"></div>
<div id="testDIV">DIV 1</div>

<!-- Round 2 -->
<div id="first" align="right"><img src="http://cdn2.iconfinder.com/data/icons/metro-uinvert-dock/128/Full_Screen.png" height="24" width="24" onclick="toggleFullScreen()" id="viewToggleImg" style="cursor:pointer"></div>
<div id="testDIV2">DIV 2</div>

<!-- div Styling, to help us see our guinea pigs. -->
<style>
    body{
        background:#000;
    }
    #testDIV{
        background:#F58B00;
        max-height:100px;
    }
    #testDIV2{
        background:#F58B00;
        max-height:100px;
    }
</style>

<!-- JavaScript that will control the way that the page behaves on page toggling. THIS IS WHAT IS MOST IMPORTANT! -->
<script>
    function toggleFullScreen(){
        var toggleDIV = document.getElementById("first"); // This stores the ID of the toggle DIV.
        var testDIV = document.getElementById("first").nextElementSibling; // Since the div ID will fluctuate each time during page load, this will acquire it for us using the previous div in relation to it.

        if (document.getElementById("viewToggleImg").src == "http://cdn2.iconfinder.com/data/icons/metro-uinvert-dock/128/Full_Screen.png")
        {
            // If we are in here, then we are toggling to full screen.
            document.getElementById("viewToggleImg").src='http://cdn2.iconfinder.com/data/icons/metro-uinvert-dock/128/Exit_Full_Screen.png';
            document.getElementById("viewToggleImg").style.marginRight ='20px';
            toggleDIV.style.position = 'fixed';
            toggleDIV.style.top = '0px';
            toggleDIV.style.bottom = '0px';
            toggleDIV.style.left = '0px';
            toggleDIV.style.right = '0px';
            toggleDIV.style.background = '#FFF';
            toggleDIV.style.paddingTop = '10px';
            testDIV.style.position = 'fixed';
            testDIV.style.top = '44px';
            testDIV.style.bottom = '1px';
            testDIV.style.left = '1px';
            testDIV.style.right = '1px';
            testDIV.style.maxHeight = 'none';
        }
        else
        {
            // If we are in here, then we are toggling back to original page view.
            document.getElementById("viewToggleImg").src='http://cdn2.iconfinder.com/data/icons/metro-uinvert-dock/128/Full_Screen.png';
            document.getElementById("viewToggleImg").style.marginRight = '0px';
            toggleDIV.style.position = 'static';
            toggleDIV.style.background = 'none';
            toggleDIV.style.paddingTop = '0px';
            testDIV.style.position = 'static';
            testDIV.style.maxHeight = '100px';
        }
    }
</script>

Could someone please offer some advice on how to resolve this issue?

Michael Celey
  • 12,645
  • 6
  • 57
  • 62
PWF
  • 115
  • 1
  • 4
  • 15
  • 7
    IDs MUST be unique. – Niet the Dark Absol Apr 01 '13 at 01:22
  • 1
    That's what classes are for (Ex. `
    `
    – JCOC611 Apr 01 '13 at 01:23
  • Since both divs have the same id, `document.getElementById("first")` always return the same div and that div will always have the same sibling element. Make your id's unique. – plalx Apr 01 '13 at 01:26
  • @JCOC611 I know that IDs are supposed to be unique.I know that you are supposed to use classes for things like this, but I will have no control over the DIVs since this code will be used in user posts, and all user posts that use this code will all have the same DIVs. – PWF Apr 01 '13 at 01:31
  • 1
    On a side note, it is nice to see that I'm not the only one to start the SO career with a phpBB question. On topic, as already said, you will need to use classes as duplicated IDs are simply not valid markup. That means, if your mod requires IDs, you will have to manually patch the mod. Though, with your current code structure, it is very possible to do without any ID or class. – Fabrício Matté Apr 01 '13 at 01:33
  • @FabrícioMatté Is it possible to generate a different DIV ID to match with each box using JavaScript or PHP? – PWF Apr 01 '13 at 01:39
  • Yes, though if the toggler, image and `testDIV`s are always close to each other like that, it is much easier to use DOM traversal methods. I'll try to wrap something up. – Fabrício Matté Apr 01 '13 at 01:41

1 Answers1

1

The easiest way to fix this would be passing a reference to clicked element (viewToggleImg) using the this keyword:

onclick="toggleFullScreen(this)"

Then get the related elements through DOM traversal methods:

function toggleFullScreen(viewToggleImg){
    var toggleDIV = viewToggleImg.parentNode;
    var testDIV = toggleDIV.nextElementSibling;

And use those variables throughout your function. Updated pen

Though, I'd suggest using jQuery for easily doing such tasks in a non-obtrusive way and shimming compatibility with older browsers (nextElementSibling does not work for IE<9, in case you need/want to support it).

Though, you don't need jQuery for something so small that is already working, so here's the patched version using feature detection for nextElementSibling else the shim outlined in this answer:

function nextElementSibling( el ) {
    do { el = el.nextSibling } while ( el && el.nodeType !== 1 );
    return el;
}
function toggleFullScreen(viewToggleImg){
    var toggleDIV = viewToggleImg.parentNode;
    var testDIV = toggleDIV.nextElementSibling || nextElementSibling(toggleDIV);
    //...

Pen & fullpage demo (tested in IE8)

Or with jQuery:

   var testDIV = $(toggleDIV).next()[0];
Community
  • 1
  • 1
Fabrício Matté
  • 69,329
  • 26
  • 129
  • 166
  • Okay, thanks! It works! I am not sure what exactly it was you did, but I am looking through the code for changes. I would +1 you, but I don't have enough reputation to do so. As for the nextElementSibling thing, how would you do that using jQuery? – PWF Apr 01 '13 at 02:03
  • @PWF Without breaking existing code, `var testDIV = $(toggleDIV).next()[0]` this way you use [`.next()`](http://api.jquery.com/next/) and retrieve the element from the jQuery object. You probably don't need jQuery for something so small, I'll update the answer. Also, though you can't upvote yet, you can mark an answer as accepted through the tick mark below the up/down votes. `=]` – Fabrício Matté Apr 01 '13 at 02:08
  • Thanks. I have used StackOverflow a ton from a Google standpoint, but I just decided to join tonight. I never really knew what the check mark meant. Thanks for helping a n00b. I know you should avoid using jQuery if possible, and I know you said that I do not necessarily need it in this case, but I will use it anyway. Better safe than sorry, and not only that, but I have jQuery installed on my site, and I only use it for one or two functions. I might as well get a little more use out of it. – PWF Apr 01 '13 at 02:15
  • @PWF updated answer with a non-jQuery solution and yes, I use jQuery on my phpBB board as well. All MODs I develop use it hence it is very useful in the long run, I'm sure you will find more uses for it and it will save a lot of development time in the long run as well. `=]` – Fabrício Matté Apr 01 '13 at 02:17
  • 1
    I just added another set of the toggler and the ugly orange box, changing nothing but HTML and CSS, and it still works! – PWF Apr 01 '13 at 02:21
  • Good news. `=]` When using jQuery, you usually don't use `onclick`s and such, but well, no need to edit something that is working. But if later you need help refactoring/matching the togglers and divs/adding functionality, you can post another question and I'll check as soon as I can if you don't get an answer in the meantime. `=]` – Fabrício Matté Apr 01 '13 at 02:30