Jump to content

Guides

Making it interactive with Javascript

We can now tie everything together with some Javascript. It's with the Javascript that everything will feel snappy and interactive. Begin by heading over to the template editor, and editing the Javascript file we created earlier.

The Javascript controller we write will do two things:

  • Load the first record when the page is loaded
  • Handle click events on the other records to load the ones the user clicks

Here's the final Javascript code you need to insert into the file. We'll explain it shortly:

Spoiler

/**
 * IPS Social Suite 4
 * (c) 2013 Invision Power Services - http://www.invisionpower.com
 *
 * ips.releaseNotes.main.js - Release notes controller
 *
 * Author: Rikki Tissier
 */
;( function($, _, undefined){
	"use strict";

	ips.controller.register('pages.front.releaseNotes.main', {

		_ajaxObj: null,

		initialize: function () {
			this.on( 'click', '[data-releaseID]', this.showRelease );
			this.setup();
		},

		setup: function () {
			// Find the current release if available
			var showFirst = this.scope.find('[data-role="releases"] [data-currentRelease]');

			if( !showFirst.length ) {
				showFirst = this.scope.find('[data-role="releases"] [data-releaseID]').first();
			}

			if( showFirst.length ){
				showFirst.click();
			}
		},

		showRelease: function (e) {
			e.preventDefault();
			
			var self = this;
			var link = $( e.currentTarget ).attr('href');
			var infoPanel = this.scope.find('[data-role="releaseInfo"]');

			// Cancel any current requests
			if( this._ajaxObj && _.isFunction( this._ajaxObj.abort ) ){
				this._ajaxObj.abort();
			}

			// Set panel to loading
			infoPanel
				.css({
					height: infoPanel.height() + 'px'
				})
				.html( $('<div/>').addClass('ipsLoading').css({ height: '100px' }) );

			// Unhighlight all others, then highlight this one
			this.scope.find('[data-releaseID]').removeClass('cRelease_active');
			$( e.currentTarget ).addClass('cRelease_active');

			this._ajaxObj = ips.getAjax()( link, {
				data: {
					rating_submitted: 1
				}
			})
				.done( function (response) {
					var responseContent = $("<div>" + response + "</div>");
					var content = responseContent.find('#elCmsPageWrap');

					infoPanel.html( content ).css({ height: 'auto' });

					$( document ).trigger( 'contentChange', [ infoPanel ] );
				});
		}
	});
}(jQuery, _));

 

 

This is a standard IPS4 javascript controller; refer to the controller documentation for more information.

In our initialize method (called automatically when the controller is initialized), we set up an event handler for clicking on elements with the data-releaseID attribute (if you remember, we gave items in our record listing this attribute). We bind this handler to the showRelease method.

We then call the setup method. The logic in this method selects a record to load automatically, so that the page has content in it when the user first loads it. It tries to find a record with the data-currentRelease attribute, but if one doesn't exist, it will load the first item in the list instead.

Finally, there's the showRelease method which has the job of loading and displaying the record view, pulled dynamically via AJAX. To do this, we find the relevant URL from the record row and then fire an AJAX request. In the done handler, we update the div that holds our record content.

When a Pages URL is called via AJAX (whether it's a normal page, or a database), it will only return the page content - it won't include the complete site wrapper. This makes it a little easier to implement dynamic page loading. However, in our case, the HTML we need is actually even narrower - we want just the record content, not any of the surrounding page from Pages. For this reason, in the done handler we select just the contents of the #elCmsPageWrap element, and use that as our record content.


  Report Guide


×