Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lightbox issue when loading dynamic image name

Tags:

javascript

php

Ok i have a lightbox which works quite well except for 1 issue. The images are dynamically built, it gets a list of say 10 images and loops through each displaying each image on a row. So i can see what is going wrong. No matter which image i select its showing the first image in the lightbox so i need to pass it a variable with the image path or image name.

I really dont have that much javascript experience but what im hoping to do is put the $popup_item->attributes()->name into a variable, pass it via the onclick event and then inside div with id="light" instead of passing $popup_item->attributes()->name i pass the variable but not sure if that is the best approach or even where to start

There is a loop like this which loops through and prints out the popup container a bunch of times:

foreach($xml->config->popup as $popup_item){

}

and the html

<div id="popup_container">
    <!-- We use a lightbox to show the image in full size since large popups are scaled -->
    <a href = "javascript:void(0)" onclick = "document.getElementById('light').style.display='block';document.getElementById('fade').style.display='block'">
        <!-- This is the scaled image -->
        <!--popups are stored in images/popups/images/ in the following format -->
        <!--id_popupname.png which we build dynamically below because -->
        <!-- the popup name will always be same name as the popupimage with the user id preceeding it -->
        <img src="images/popups/images/<?php echo $item_id . "_" .  strtolower($popup_item->attributes()->name) . ".png" ;?>" alt="Popup Image"/>
    </a>

    <!--This holds the un-scaled image in the popup box which is hidden initially until you click the image-->
    <div id="light" class="white_content"> 
        <img src="images/popups/images/<?php echo $item_id . "_" .  strtolower($popup_item->attributes()->name) . ".png" ;?>" alt="Popup Image"/></a>
        <!--This allows you to close the lightbox window from within the lightbox window-->
        <a href = "javascript:void(0)" onclick = "document.getElementById('light').style.display='none';document.getElementById('fade').style.display='none'">Close</a>
    </div>
    <div id="fade" class="black_overlay"></div>
</div> <!--end of popup container-->

And the lightbox css in case it helps:

.black_overlay{
    display: none;
    position: fixed;
    top: 0%;
    left: 0%;
    width: 100%;
    height: 100%;
    background-color: black;
    z-index:1001;
    -moz-opacity: 0.8;
    opacity:.80;
    filter: alpha(opacity=60);
}

.white_content {
    display: none;
    position: fixed;
    top: 25%;
    left: 25%;
    width: 50%;
    height: 50%;
    padding: 16px;
    border: 16px solid orange;
    background-color: white;
    z-index:1002;
    overflow: auto;
}

EDIT: Actually i would need to pass 2 variables, the $item_id and the $popup_item->attributes()->name but concept is the same

like image 826
user1547410 Avatar asked Nov 23 '13 00:11

user1547410


4 Answers

You're getting the same image every time because the DOM is selecting the first element it finds with the id of 'light'. ID's should be unique in HTML. Instead try this...

<div id="popup_container">
    <a href = "javascript:void(0)" onclick = "document.getElementById('light_<?php echo $item_id ?>').style.display='block';document.getElementById('fade').style.display='block'">
        <img src="images/popups/images/<?php echo $item_id . "_" .  strtolower($popup_item->attributes()->name) . ".png" ;?>" alt="Popup Image"/>
    </a>

    <div id="light_<?php echo $item_id ?>" class="white_content"> 
        <img src="images/popups/images/<?php echo $item_id . "_" .  strtolower($popup_item->attributes()->name) . ".png" ;?>" alt="Popup Image"/></a>
        <a href = "javascript:void(0)" onclick = "document.getElementById('light_<?php echo $item_id ?>').style.display='none';document.getElementById('fade').style.display='none'">Close</a>
    </div>
</div>

Also, move the fade div outside of your loop. You only need one instance of it, not 10...

So if you were building this in raw PHP rather than using a templating engine it would look like...

echo '<div id="popup_container">';

foreach($xml->config->popup as $popup_item){
    echo '<a href = "javascript:void(0)" onclick = "document.getElementById(\'light_'.$popup_item->attributes()->item_id.'\').style.display=\'block\';document.getElementById(\'fade\').style.display=\'block\'">
            <img src="images/popups/images/'.$popup_item->attributes()->item_id."_".strtolower($popup_item->attributes()->name).'.png" alt="Popup Image"/>
        </a>

        <div id="light_'.$popup_item->attributes()->item_id.'" class="white_content"> 
            <img src="images/popups/images/'.$popup_item->attributes()->item_id."_".strtolower($popup_item->attributes()->name).'.png" alt="Popup Image"/></a>
            <a href = "javascript:void(0)" onclick = "document.getElementById(\'light_'.$popup_item->attributes()->item_id.'\').style.display=\'none\';document.getElementById(\'fade\').style.display=\'none\'">Close</a>
        </div>';
}

echo '</div>';
echo '<div id="fade" class="black_overlay"></div>';

EDIT: I would look at a few of the other answers below. Some of them give a much better way of achieving this effect, however, my answer dealt with the question at hand, how to get the original code working.

like image 121
Garry Welding Avatar answered Nov 13 '22 10:11

Garry Welding


You say that your loop prints out the popup container a bunch of times..

An issue with this approach is that you will end with duplicate id on html elements..

This will cause the document.getElementById to return only the first one that matches (as seems to be your problem)

You need to make your id's unique (and the javascript that targets them)

like image 31
Gabriele Petrioli Avatar answered Nov 13 '22 10:11

Gabriele Petrioli


You can use the ID of the div in CSS.

<style>
#dark {
    display: none;
    position: fixed;
    top: 0%;
    left: 0%;
    width: 100%;
    height: 100%;
    background-color: black;
    z-index:1001;
    -moz-opacity: 0.8;
    opacity:.80;
    filter: alpha(opacity=60);
}
#light {
    display: none;
    position: fixed;
    top: 25%;
    left: 25%;
    width: 50%;
    height: 50%;
    padding: 16px;
    border: 16px solid orange;
    background-color: white;
    z-index:1002;
    overflow: auto;
}
</style>

I have made a nice function here that will do the job.

<script>
function display_lightbox(path) {
    var image = '<img src="' + path + '" alt="Large Image"/>';
    document.getElementById('lightimg').innerHTML=image;
    document.getElementById('light').style.display='block';
    document.getElementById('dark').style.display='block';
}
</script>

The lightbox code with an extra container for the img tag generated by JavaScript.

<div id="light"> 
    <div id="lightimg"></div>
    <a href = "javascript:void(0)" onclick = "document.getElementById('light').style.display='none';document.getElementById('fade').style.display='none'">Close</a>
</div>
<div id="dark"></div>

Your thumb display code using the JavaScript function.

<div id="popup_container">
    <a href="javascript:void(0)" onclick="display_lightbox('images/popups/images/<?php echo $item_id . "_" .  strtolower($popup_item->attributes()->name) . ".png" ;?>');">
        <img src="images/popups/images/<?php echo $item_id . "_" .  strtolower($popup_item->attributes()->name) . ".png" ;?>" alt="Popup Image"/>
    </a>
</div>

Or you can implement this little lightbox.

http://www.laptoptips.ca/javascripts/shutter-reloaded/

like image 29
transilvlad Avatar answered Nov 13 '22 08:11

transilvlad


I know this is a late submission but I wanted to give it a try.

I modified many parts of this so it might not adjust to your css but it's more an exercise in reflection on javascript and the importance of clean code and separation

Some features

  • use of event delegation, one event handler for the entire popup container
  • separation of behaviour and content
  • easy maintenance, very descriptive code (it doesn't actually need any comments)

Some caveats

  • I changed things in the html, changes will be required in the css
  • If there are further changes in the html, the javascript will have to accomodate to those changes
  • it doesn't take care of the second variable to pass (I don't understand what it is, if someone cares to explain...)
  • more but I forgot... sorry

and now... ze code

<script>
  (function () {
    var
      onDelegatedClick,
      onLoad,
      onUnload,
      enlighten,
      revert;
    enlighten = function (node) {
      var lightbox = document.getElementById('light');
      // pass the clicked image source to our lightbox
      lightbox.querySelector('img').src = node.querySelector('img').src;
      // make it all visible
      lightbox.style.display = 'block';
      document.getElementById('fade').style.display = 'block';
    };
    revert = function () {
      document.getElementById('light').style.display = 'none';
      document.getElementById('fade').style.display = 'none';
    };
    onDelegatedClick = function (event) {
      // find out where we need behaviour
      var targetNode = event.target;
      if (targetNode.tagName !== 'SPAN') {return;}
      // clicked on the close button
      if (targetNode.id) revert();
      // clicked on any of the images, pass the <span>
      else enlighten(targetNode);
    };
    onLoad = function () {
      // add the delegator
      document.getElementById('popup_container').addEventListener('click',onDelegatedClick,false);
    };
    onUnload = function () {
      // dont forget to remove the listener
      document.getElementById('popup_container').removeEventListener('click',onDelegatedClick,false);
    };
    window.addEventListener('load',onLoad,true);
    window.addEventListener('unload',onUnload,true);
  }());
</script>
<div id="popup_container">
<!-- foreach image -->
  <!-- clicks have been delegated, no need for anchors, just delegate all clicks -->
  <span class="lightBoxEnlightener">
    <img src="images/popups/images/<?php echo $item_id."_".strtolower($popup_item->attributes()->name).".png" ;?>" alt="Popup Image"/>
  </span>
<!-- end foreach -->
  <!-- only one lightbox and darkbox required -->
  <div id="light" class="white_content">
    <!-- img src is empty, when the enlightening happens, it'll be populated from the clicked span -->
    <img src="" alt="Popup Image"/>
    <!-- clicks have been delegated -->
    <span id="reverter">Close</span>
  </div>
  <div id="fade" class="black_overlay"></div>
</div>

the script tag may be moved anywhere or to a separate file, the behaviour of the spans will become patent on document load. I chose spans because having to deal with actual anchor tags is sometimes cumbersome.

like image 1
hanzo2001 Avatar answered Nov 13 '22 10:11

hanzo2001