Forum for discussing general topics related to Couch.
9 posts Page 1 of 1
I'm curious if anyone here has successfully implemented AJAX with cloned pages using the gallery template. Anyone use it with cloned pages that have comments enabled? I'd love to see some sample code to see what I might be getting into if I try to go down this path. My alternative right now is iFrames - non public pages, strictly backend stuff, so I can get away with the approach, but it feels very web 0.1 and generally kinda backwards thinking.

Can the original cloneable PHP page itself be used to server up the requested data? I've been curious about how that might work, or if it's best to make a separate PHP file to do that.

Thanks!
I use ajax to load cloned pages into popup overlays pretty often. It's pretty straightforward. When you load the external file, the server builds the Couch-based page before serving it. There's no conflict in that sense. I don't think that Couch is going to add any problems to using ajax. I generally keep the page view super-simple, just the most minimal html, because it's not really meant to stand on its own.

I've never used the gallery template, but it's essentially just a clonable template with a bulk upload feature. It shouldn't be any different from an ordinary clonable template. As far as comments go, all ajax does is use javascript to load external content, so showing the comments themselves shouldn't be a problem. But I don't have any experience with it. Of course, any action (like a form) that requires reloading the page will reset everything and could cause issues.

Here's a simplified ajax gallery template. (Sorry it's not a Couch-gallery-type template. You could modify it, though.) It has thumbnails in the list view and a larger image in the page view that is loaded into a popup when the thumbnail is clicked. It uses jQuery, which makes loading external pages very simple among other things.

The css includes a close button and a loading gif which you can provide for yourself. But the page still functions without them.

II hope this might be some help.
thumbs.jpg
thumbs.jpg (112.64 KiB) Viewed 3764 times

overlay.jpg
overlay.jpg (140.88 KiB) Viewed 3764 times

Code: Select all
<?php require_once( 'couch/cms.php' ); ?>
<cms:template title='Gallery' clonable='1' >
<!-- BEGINNING OF COUCH CMS TEMPLATE -->

    <!-- Hide Thumbnail Regions -->
    <cms:editable name='hide' type='message'>
        <style>#k_element_artwork_thumb, #k_element_artwork_large{display:none;}</style>
    </cms:editable>
       
    <!-- PHOTO -->
   <cms:editable name='artwork'
      label="Image"
      quality='100'
      show_preview='1'
        preview_width='250'
      type='image' />

   <!-- THUMBNAIL -->
   <cms:editable name='artwork_thumb'
      assoc_field='artwork'
      width='150'
      height='150'
      quality='100'
      enforce_max='1'
      type='thumbnail' />

   <!-- LARGE IMAGE -->
   <cms:editable name='artwork_large'
      assoc_field='artwork'
      width='800'
      height='600'
      quality='100'
      enforce_max='1'
      type='thumbnail' />

   <!-- CAPTION -->
   <cms:editable name='caption' label="Caption" type='text' />

<!-- =================================================================== -->
   <!-- END OF COUCH CMS TEMPLATE -->
</cms:template>

<cms:if k_is_page><!-- GALLERY OVERLAY -->

    <p style="text-align:center; margin:0;"><img src="<cms:show artwork_large />" alt="<cms:show k_page_title/>"/><br/><strong><cms:show k_page_title /></strong><br/><cms:show caption/></p>

<!-- END GALLERY OVERLAY -->
<cms:else/>
   
<!DOCTYPE html>

<html lang="en">

<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="description" content="This is my gallery." />

<title>My Gallery</title>

<style>
h1, p {
    margin:0;
    text-align:center;
}
p {
    margin-bottom:20px;
}
img {
    max-width:99%;
}
/*Thumbnails*/
.gallery-thumbs {
    text-align:center;
    padding:0 20px 20px;
    line-height:1em;
    width:180px;
     height:180px;
     float:left;
}
.gallery-thumbs img {
    border:1px solid #333;
}
.gallery-thumbs .title {
   font-size:13px;
    color:#333;
}
.gallery-thumbs a {
    text-decoration:none;
}
.gallery-thumbs a:hover {
    text-decoration:underline;
}
   
/*Popup Overlay*/
.overlay-bg {
   display: none;
   position: absolute;
   top: 0;
   left: 0;
   height:100%;
   width: 100%;
   cursor: pointer;
   z-index: 1000;
   background: #000; /* fallback */
   background:  rgba(0,0,0,0.5) url(loading.gif) 0px 0px no-repeat; /* loading gif in case of slow loading */
}
.overlay-content {
    display: none;
    background: #fff;
    padding: 1%;
    width: 60%;
    position: absolute;
    top: 15%;
    left: 50%;
    margin: 0 0 0 -30%; /* negative left margin is half of the width to center the div */
    border-radius: 4px;
    box-shadow: 0 0 5px rgba(0,0,0,0.9);
    cursor: default;
    z-index: 10001;
}
.overlay-content img {
    border:1px solid #888;
}

.close-btn {
   background-image:url(close.png);
   position:absolute;
   left:-15px;
   top:-15px;
   cursor:pointer;
   height:35px;
   width:35px;
}

@media (max-width: 480px){
    .overlay-content {
        width: 94%;
        margin: 0 2%;
        left: 0;
    }
}   
</style>
</head>

<body>
   
<h1>Welcome to My Gallery.</h1>
<p>Click or tap for a larger image.</p>
               
<cms:pages>
    <div class="gallery-thumbs">
        <a href="<cms:show k_page_link/>" class="show-popup">
            <img src="<cms:show artwork_thumb/>" alt="<cms:show k_page_title/>" /><br/>
                <span class="title"><cms:show k_page_title/></span>
        </a>       
    </div>
</cms:pages>
   
<!--Empty Divs for Overlays-->
<div class="overlay-bg">
</div>
<div class="overlay-content">
</div>
   
<!-- Script to load external files into overlay -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script>
$(document).ready(function(){

//function to show overlays   
function showPopup() {   
    // show popup when you click on the link
    $('.show-popup').click(function(event){
        event.preventDefault(); // disable normal link function so that it doesn't refresh the page
        var docHeight = $(document).height(); //grab the height of the page
        var scrollTop = $(window).scrollTop(); //grab the px value from the top of the page to where you're scrolling
        var loaderPos = scrollTop + 200; //position loading gif
        var pageurl = $(this).attr('href'); //grab the href value from the anchor tag
        $('.overlay-bg').fadeIn(800).css({'height' : docHeight, 'background-position': 'center ' + loaderPos+'px'}); //display bacckground mask
        $('.overlay-content').css({'top': scrollTop+20+'px'}); //set the content 20px from the window top
       
        // Close actions precede loading external file to allow an escape from slow loading and errors
        // hide popup when user clicks anywhere outside the container
        $('.overlay-bg').click(function(){
             closePopup();
        });         
        // hide the popup when user presses the esc key
        $(document).keyup(function(e) {
            if (e.keyCode == 27) {
                closePopup();
            }
        });       
       
        //load the page from the url and open overlay
        $('.overlay-content').load(pageurl, function() {
            $('.overlay-content').find('img').load( function() { //allow image to preload
                $('.overlay-content').prepend('<a class="close-btn"></a>');//add close button
                $('.overlay-content').fadeIn(600); //show popup
           
                // hide popup when user clicks the close button
                $('.close-btn').click(function(){
                    closePopup();
                });
            });
        });
    });
}
showPopup();

// function to close overlays
function closePopup(){
    $('.overlay-bg, .overlay-content').fadeOut(200, function(){ //hide the overlay
    $('.overlay-content').html(''); //clear content of overlay
    $('.show-popup'); //refresh popup link
    });
}   
});   
</script>

</body>
</html>
</cms:if>
<?php COUCH::invoke(); ?>
Tim, thanks for the code! I read over it, are you essentially loading the entire page inside the lightbox overlay?
are you essentially loading the entire page inside the lightbox overlay?

Yes. Create the template, populate a few pictures, and run it. Click a thumbnail to open the popup. Use your browser tools to inspect the element. You'll see that <div class="overlay-content"></div> now has the exact code from the cloned page inside it.

The code in plain English goes something like this:

$('.overlay-content').load(pageurl, function() {
-> Load pageurl into the 'overlay-content' object then perform the following function:

$('.overlay-content').find('img').load( function() { //allow image to preload
-> Find img tags in 'overlay-content' and load them, then perform the following function:

$('.overlay-content').prepend('<a class="close-btn"></a>');//add close button
-> add the close button code to the beginning of 'overlay-content'

$('.overlay-content').fadeIn(600); //show popup
-> display 'overlay-content' with a fade in of 600ms duration

Like I said, jQuery makes ajax almost trivially easy. (https://api.jquery.com/load/) All you really need is the .load method. The rest of the code has to do with the popup.
This might actually work with some html design tweaks. Right now, the way I see it, it's still similar to an iFrame, but without all the baggage iFrames come with (like resizing on the fly to content changes without additional scripts, better JS interaction with the parent page, etc.). :)
I just loaded the template as a commentable version, I can't get comments to submit successfully when pages load in the lightbox. I can however get them to post when I open them up in their own browser tab.

EDIT: I just noticed this was being added to the end of the URL when submitting: #kformname0
Yeah. This is what I mentioned about how an action that refreshes the page can cause issues.

The typical way that Couch forms function is that on submitting, the page refreshes with the new form data posted to the page. The k_success or k_error conditional clause then takes some action. The problem here is that when the page refreshes, the form is gone! No can process.

That doesn't have to be a problem. I've had forms inside this sort of ajax overlay and they work fine. The thing is, the form has to send the action from submitting the form to a different page for processing. Couch allows this by putting the name of the processing page in the action atribute: <cms:form method="post" action="process-comments.php">

Now I'm getting into the deep end of the pool, so hopefully the lifeguards are watching and will step in if we get into trouble.

I've never used comments, and I don't have much experience with Couch forms, so I don't have something ready-made in my back pocket. But I think you can basically slice the comment processing code out of the form and put it into another template where you send the form data for processing. Or maybe have the processing code on the primary page itself rather than inside the comment form on the external page. Javascript in the processing code could reload the external page if needed. You could also send the completed form to the external page for processing, like this: <cms:form method="post" action="<cms:show k_page_link />">. I think I like this last idea best. But it all depends on your situation.

The other thing to think about is whether you really need to use ajax in this way at all. For instance, you could have the cloned pages already loaded on the page inside of hidden divs, and use javascript to show and hide them as necessary. You haven't given many details about what you're trying to do, so it's hard to offer any more than general ideas.
Thanks for the ideas! I kinda figured it was trying to refresh the page once I saw the URL being appended. I need AJAX because the galleries are so large. Hundreds of images. I'm building a client proofing gallery for commercial clients, so there's way too much content to load into hidden divs etc... unless of course you mean only loading the page comments into the hidden divs. It still feels less optimal. I know there is another post on here about form validation using a new <cms: is_ajax/> tag that you have to install yourself - it's coming in the new release, but I have yet to figure out how to make that work.
If you wish for a form, upon submission, to not reload the page (browser default action), you must listen for the form submission, stop it, and launch your own AJAX request. We do just this, for example, in the shopping cart demo (see the cart-modal.js file).

The is_ajax tag, while useful, is not required to target AJAX requests. You could just append a querystring to give you similar functionality - template.php?ajax=1 - <cms:if "<cms:gpc method='get' var='ajax'/>">AJAX<cms:else/>NOT AJAX</cms:if>.

That URL hash (#kformname0) is normal. Set parameter anchor='0' on the cms:form to get rid of it if you like...
9 posts Page 1 of 1
cron