<?xml version="1.0"?>

	<rss version="2.0">
	  <channel>
		<title>andrewembler.com</title>
		<link>http://andrewembler.com/feed</link>
		<description>The written words and audio of Andrew Embler, on topics such as concrete5, the web, personal computing, music and art.</description> 

	
			<item>
			  <title>concrete5 and the Zend Framework</title>
			  <link>http://andrewembler.com/concrete5/concrete5-and-the-zend-framework/</link>
			  <description>
			  <![CDATA[
				<p>concrete5 is a complex application. In addition to offering a pleasing, flexible, intuitive interface for managing web content, we provide functionality like drag and drop layout editing, theme importing and customization, powerful file management and manipulation, MVC frameworks for individual content types and full pages, events and extensions frameworks, complex and powerful permissions, extensive interface customization and complete localization for the entire application and is extensions.</p>

<p>Like most other applications of its size and purpose, we didn't <a href="http://www.concrete5.org/documentation/developers/system/3rd-party-libraries">write everything ourselves</a>. We're indebted to members of the open source community like jQuery, TinyMCE, ADODB and others. They're integral to what we do, and have been with us since the very beginning. But just recently we've started using several new third party libraries to help us accomplish some impressive things and move us toward wider adoption and greater performance.</p>

<p>What libraries? Those would be some choice components of the <a href="http://framework.zend.com">Zend Framework</a>. Yes, we've been using the Zend Framework since the very beginning as well, but its usage has become even more important in the latest release, concrete 5.4.</p>

<h2>Why'd we start using the Zend Framework?</h2>

<h3>Trusted</h3>

<p>Before we even take a look at the documentation for a particular library, we check out its history, its place in the web development world, and its track record. It's hard to go wrong with the PHP framework blessed by the language's founders. It also helps that every single proposal for each component of the framework can be found online, with feedback addressed publicly.</p>

<h3>Documented and Understandable</h3>

<p>In the first version of concrete5, we needed a solution for search that could be packaged up and shipped simply and quickly. We chose Zend&#95;Search&#95;Lucene, because its results were demonstrable and its code samples and API were easy to read and understand. </p>

<p>While we've since moved away from Lucene as a packaged-in solution – and instead have embraced search as a custom problem for custom sites – the lessons learned still resonate. </p>

<h3>Modularity</h3>

<p>Integrating Zend&#95;Search&#95;Lucene took all of an afternoon. While the Zend Framework is large and potentially imposing, it's a huge benefit that its components are modular and can be incorporated without also including everything and the kitchen sink. </p>

<h2>Localization and Caching in 5.4: concrete5's Primary Use of the Zend Framework</h2>

<p>Version 5.1 of concrete5 introduced localization of the concrete5 core, allowing translation of the application into other languages. It wasn't until version 5.4, however, that we provided a way for add-on developers to translate their add-ons as well, and provide their translations independently of the core. We wanted add-on developers to be able to make their add-ons translation-ready with the exact same syntax that the core team uses, and – if at all possible – be able to use strings already translated in the core.</p>

<p>This simply wasn't possible using PHP's built-in gettext localization library. So we switched to Zend&#95;Translate and the Zend Framework, which worked like a charm. I was able to make it happen inside of a day. When finished, all our existing translation files still worked, and new ones for specific add-ons could be easily loaded at runtime.</p>

<p>Moving to Zend&#95;Translate meant ditching our quickly-written, effective but inflexible cache backend for Zend_Cache, which instantly gave concrete5 support for many modern cache backends like APC, XCache, memcached, as well as standard file-system-based caching. This meant that, right out of the box, concrete5 installations on certain servers could receive significant performance improvements just by enabling some runtime options.</p>

<p>As we move forward toward concrete 5.4.1, the benefits are even clearer. With some application tuning and new caching options, plus the benefit of Zend&#95;Cache working with an APC cache backend, preliminary local testing shows concrete5 5.4.1 performing nearly five times faster at rendering the default home page than under 5.3.3.1, all while providing much greater localization flexibility and supporting many more caching layers than we ever could have on our own.</p>

<h2>Other Uses of the Zend Framework in concrete5</h2>

<p>While caching and localization are the most front-and-center uses of the Zend Framework in concrete5, we employ it elsewhere. Any time you import a file from another web server into concrete5, you're using Zend&#95;Mime. And switching to Zend&#95;Mail has allowed us great flexibility in the mail department, including the ability to process inbound messages, connect to external SMTP servers, and even send HTML mails with attachments, all without worrying about how to connect to different mail servers or speak POP/IMAP.</p>

<p>That's really the promise of the Zend Framework: we can't be experts in everything, and it's to our benefit that there are those out there willing to develop modular, tested frameworks for interacting with the things that are ancillary - but still important - to our applications. concrete5 isn't a caching application, a localization application or an email application: it's a system for building useful, attractive websites and providing a simple means to edit them. But in order for it to be effective at meeting this goal, it needs to be able to connect to mail servers, read mail, send mail, cache its data objects and translate its core and add-on files. Using the Zend Framework means we can more effectively focus on the things we have experience with, and spend our time working on what really matters to us as application architects, interface designers and web developers.</p>
<p><span class="byline">Andrew Embler thinks it's freaking awesome his software is in use all over the world.</span></p>				<br/><br/>
				<a href="http://andrewembler.com/concrete5/concrete5-and-the-zend-framework/">Comment on this at andrewembler.com</a>
			  ]]>
			  </description>
			  <pubDate>Wed, 23 Jun 2010 21:49:00 EDT</pubDate>
			</item>
		
			<item>
			  <title>concrete5 Add-On Developers: Create Your Own concrete5 Demo</title>
			  <link>http://andrewembler.com/concrete5/add-on-developers-create-your-own-concrete5-demo/</link>
			  <description>
			  <![CDATA[
				<p>This is a how-to geared especially toward our add-on developers, but it'll be useful to anyone who wants to create a cycling concrete5 demo that automatically resets. In this how-to I'll explain how to prepare a database for the demo, setup special demo-specific permissions overrides, create a demo administrative user, install one or more add-ons along with the demo, and provide a script that can be run at any time to reset the demo.</p>

<h2>Code</h2>

<p>This how-to references a reset script and permissions overrides. You can download these files here:</p>

<p><a href="http://www.concrete5.org/files/6212/7499/8749/addon_demo_code.zip">Reset Script and Permissions Overrides</a></p>

<h2>Database Setup</h2>

<p>It's important that you setup your demo install with its own database, database user, and database access. That way, if anything is ever disclosed or compromised, there is at least that sandbox in place. My demo will use the "concretedemo" user account, with the password "concretedemo," in the "concretedemo" database.</p>

<p>First I create the database:</p>
<div class="ccm-syntax-highlighter">
<pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">DATABASE</span> concretedemo;</pre></div><p>Then I grant permissions to the user on the database:</p>
<div class="ccm-syntax-highlighter">
<pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">GRANT</span> <span style="color: #993333; font-weight: bold;">ALL</span> <span style="color: #993333; font-weight: bold;">ON</span> concretedemo<span style="color: #66cc66;">.*</span> <span style="color: #993333; font-weight: bold;">TO</span> concretedemo@localhost <span style="color: #993333; font-weight: bold;">IDENTIFIED</span> <span style="color: #993333; font-weight: bold;">BY</span> <span style="color: #ff0000;">'concretedemo'</span>;</pre></div><h2>Install concrete5</h2>

<p>Download <a href="http://www.concrete5.org/download">the latest version of concrete5</a>, unzip it to the web directory that will house your demo, and install it.</p>

<h2>Lockdown Dashboard</h2>

<p>We want our demo user to be added to the Administrators group, so they can access the dashboard, but we don't want to give out full and complete access. We don't want sitewide settings to be looked at, or file access permissions to change, for example. Fortunately there's a little-used feature that allows us to lock down single page permissions at the time of their creation: access.xml files. These files live in the specific controllers/ directory for the given single page.</p>

<p>A sample access.xml file looks like this:</p>
<div class="ccm-syntax-highlighter">
<pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #FFFFFF; font-weight: bold;">&lt;access<span style="color: #FFFFFF; font-weight: bold;">&gt;</span></span></span>
   <span style="color: #009900;"><span style="color: #FFFFFF; font-weight: bold;">&lt;node</span> <span style="color: #6666ff;">handle</span>=<span style="color: #ff0000;">&quot;dashboard/files/access&quot;</span><span style="color: #FFFFFF; font-weight: bold;">&gt;</span></span>
      <span style="color: #009900;"><span style="color: #FFFFFF; font-weight: bold;">&lt;guests</span> <span style="color: #6666ff;">canRead</span>=<span style="color: #ff0000;">&quot;0&quot;</span> <span style="color: #FFFFFF; font-weight: bold;">&gt;</span><span style="color: #FFFFFF; font-weight: bold;">&lt;/guests<span style="color: #FFFFFF; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #FFFFFF; font-weight: bold;">&lt;registered</span> <span style="color: #6666ff;">canRead</span>=<span style="color: #ff0000;">&quot;0&quot;</span> <span style="color: #FFFFFF; font-weight: bold;">&gt;</span><span style="color: #FFFFFF; font-weight: bold;">&lt;/registered<span style="color: #FFFFFF; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #FFFFFF; font-weight: bold;">&lt;administrators</span> <span style="color: #6666ff;">canRead</span>=<span style="color: #ff0000;">&quot;0&quot;</span> <span style="color: #6666ff;">canWrite</span>=<span style="color: #ff0000;">&quot;0&quot;</span> <span style="color: #6666ff;">canAdmin</span>=<span style="color: #ff0000;">&quot;0&quot;</span> <span style="color: #FFFFFF; font-weight: bold;">&gt;</span><span style="color: #FFFFFF; font-weight: bold;">&lt;/administrators<span style="color: #FFFFFF; font-weight: bold;">&gt;</span></span></span>
   <span style="color: #009900;"><span style="color: #FFFFFF; font-weight: bold;">&lt;/node<span style="color: #FFFFFF; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #FFFFFF; font-weight: bold;">&lt;/access<span style="color: #FFFFFF; font-weight: bold;">&gt;</span></span></span></pre></div><p>This locks the admnistrators group out of accessing the /dashboard/files/access page.</p>

<p>In the .zip file above, you'll see a controllers/ directory. Copy the contents of this controllers/ directory into your root controllers/ directory. The next time your demo site is reset, these access restrictions will be in place.</p>

<h2>Install "Reset" Script</h2>

<p>Also contained within the .zip file above is a reset script. When run, this script does the following:</p>

<ol>
<li>Removes config/site.php</li>
<li>Removes all files in the files/ directory</li>
<li>Removes all tables in the demo database</li>
<li>Reinstalls concrete5 with the values specified in the reset script, and the database information that you originally installed concrete5 with. Permission overrides described in "Lockdown Dashboard" are applied</li>
<li>Creates a second administrative user in the Administrators group</li>
<li>Locks down file permissions</li>
<li>Disables site emails</li>
<li>Installs specified add-ons into the site.</li>
</ol>

<h3>Before you install</h3>

<p>Please, <strong>rename the reset script!</strong> Anyone who hits the URL of the reset script will be able to reset your demo.</p>

<h3>Configuration</h3>

<p>There are a number of values at the beginning of the script that deserve explanation.</p>

<ul>
<li><strong>DEMO&#95;SETUP&#95;SITE</strong>: This constant will determine the name of your site.</li>
<li><strong>DEMO&#95;DB&#95;SERVER</strong>: Your demo's MySQL server. Typically "localhost".</li>
<li><strong>DEMO&#95;DB&#95;USER</strong>: The username for your demo's MySQL user. e.g. "concretedemo".</li>
<li><strong>DEMO&#95;DB&#95;PASSWORD</strong>: The password for your demo's MySQL user. e.g. "concretedemo".</li>
<li><strong>DEMO&#95;DB&#95;DATABASE</strong>: Your demo's MySQL database. e.g. "concretedemo".</li>
<li><strong>DEMO&#95;ADMIN&#95;EMAIL</strong>: An email address for the admin account that will be created when your site is reset.</li>
<li><strong>DEMO&#95;ADMIN&#95;PASSWORD</strong>: The password for your "admin" user account.</li>
<li><strong>DEMO&#95;USER&#95;USERNAME</strong>: The username for your "demo" account. This is the account you will give out to users who wish to demo your software.</li>
<li><strong>DEMO&#95;USER&#95;PASSWORD</strong>: The password for the "demo" user.</li>
<li><strong>PASSWORD&#95;SALT</strong>, <strong>MANUAL&#95;PASSWORD&#95;SALT</strong>: A long string that needs to be in place in this script. </li>
<li><strong>PACKAGES&#95;TO&#95;INSTALL</strong>: A comma-separated list of package handles of all add-ons in the local packages/ directory you wish to install every time the demo site is reset.</li>
</ul>
<h3>Scheduling this Script</h3>
<p>It is easy to cron this script so that it will clean out data every hour. Something like this can be entered into a crontab on a Linux server. For example, if your reset script is</p>
<p style="padding-left: 30px;">http://www.yoursite.com/reset_128273282.php</p>
<p>You can can make it run every hour on the hour with</p><div class="ccm-syntax-highlighter">
<pre class="perl" style="font-family:monospace;"><span style="color: #cc66cc;">0</span> <span style="color: #339933;">*</span> <span style="color: #339933;">*</span> <span style="color: #339933;">*</span> <span style="color: #339933;">*</span> <span style="color: #339933;">/</span>usr<span style="color: #339933;">/</span>bin<span style="color: #339933;">/</span>wget <span style="color: #339933;">-</span>T <span style="color: #cc66cc;">0</span> <span style="color: #339933;">-</span><a href="http://perldoc.perl.org/functions/q.html"><span style="color: #000066;">q</span></a> http<span style="color: #339933;">://</span>www<span style="color: #339933;">.</span>yoursite<span style="color: #339933;">.</span>com<span style="color: #339933;">/</span>reset_128273282<span style="color: #339933;">.</span>php
&nbsp;</pre></div><p>in your crontab file.</p>

<h2>Finished</h2>

<p>That's it! Now you should have a fully functional concrete5 demo with a full admin account, a limited admin account, and any add-ons preinstalled that you wish to demonstrate.</p>
				<br/><br/>
				<a href="http://andrewembler.com/concrete5/add-on-developers-create-your-own-concrete5-demo/">Comment on this at andrewembler.com</a>
			  ]]>
			  </description>
			  <pubDate>Thu, 27 May 2010 20:38:00 EDT</pubDate>
			</item>
		
			<item>
			  <title>Review: Das Keyboard Professional</title>
			  <link>http://andrewembler.com/reviews/das-keyboard-professional/</link>
			  <description>
			  <![CDATA[
				<p>Our SXSW booth was nicely positioned for a few reasons: it was in a high traffic area; the bar was very, very close; we weren't right next to Rackspace or its infernal strength tester; and, finally, we were just a few steps away from the fine people who make <a href="http://daskeyboard.com/" target="_blank">Das Keyboard</a>, which means there was ample time for me to stop by, sample the keyboard, and ultimately decide to purchase it (with additional thanks to my employer concrete5, who foot the bill &ndash; a decision it&nbsp;<strong>may</strong>&nbsp;ultimately regret.)&nbsp;</p>
<p>While you may not be familiar with the amusingly-named Das Keyboard specifically, if you have any kind of affinity for touch typing you'll recognize what sets it apart from other keyboards: Das Keyboard is a rugged, good-looking keyboard with mechanical switches. This means serious speed for serious typists, and serious noise for anyone else (more on this later.) This keyboard <em>clicks</em>, both literally and figuratively.&nbsp;I took it for a test drive at SXSW, enjoyed it, and ordered it. It arrived awhile ago, and I've been putting it through its paces since.</p>
<h2>Background</h2>
<p>This isn't the first keyboard of its kind that I've owned. My favorite keyboard of all time was the Apple Extended keyboard, which used to be the standard keyboard to ship with Macs back in the mid-1990s. That keyboard featured mechanical switches and exceptionally rugged construction: I dropped it multiple times, and my college roommate spilled a 32oz soda on it, and it kept working til the end (although some keys were broken off and lost &ndash; and there was stickiness.) I suppose it's a testament to my fondness for that keyboard that I kept using it even in that state. It's to this high standard that I'm going to hold Das Keyboard.&nbsp;</p>
<h2>Appearance and Unboxing</h2>
<h2><span style="color: #efefef; font-size: 14px; line-height: normal;">Once the shipping container is opened, I took stock of the box that Das Keyboard comes in. No, this isn't Apple-level artistic packaging, but it's functional and nicely protects and presents your investment.&nbsp;</span></h2><div class="main-image">
<img border="0" class="ccm-image-block" alt="" src="/files/cache/0d6200196d0d31f1d220c3137a51885e.jpg"  width="550" height="412" /></div><div class="main-image">
<img border="0" class="ccm-image-block" alt="" src="/files/cache/003e01545ece9ad0a4201305f6fa57f6.jpg"  width="550" height="412" /></div><p>Along with the keyboard itself, you get a USB cable, simple instructions and a cleaning cloth. This comes in handy, as the keyboard's shiny glossy finish will become marred by dust and fingerprints.</p><div class="main-image">
<img border="0" class="ccm-image-block" alt="" src="/files/cache/48c9c30de0a9875eb7baf6292bd01f3e.jpg"  width="550" height="412" /></div><h2>Setup</h2>

<p>In 2010, setting up a keyboard shouldn't warrant a section in a review, but Das Keyboard makes some strange choices which I find fault with. </p>

<h3>What's up with the USB?</h3>

<p>The first thing I noticed that was strange about this keyboard is its USB cable. For some reason, Das Keyboard doesn't behave like every single other USB peripheral I've ever used. Instead of having a simple USB cable that extends from the keyboard and is plugged into your USB hub/computer/laptop, Das Keyboard's USB cable is actually <em>two</em> USB cables bound together. </p>

<p>Why? I have no idea - but without plugging in <em>both</em> cables to the host machine or hub, the keyboard's second USB port doesn't work. Ok, ok - what's the big deal? If you get a second powered USB port on the keyboard itself, what does it matter that you have to use two ports on the host machine or hub? I'll show you why it matters. Check out the initial setup of Das Keyboard on my MacBook Pro:</p>
<div class="main-image">
<img border="0" class="ccm-image-block" alt="" src="/files/cache/66e92257692ea3fdc1954d2e9b6d462f.jpg"  width="500" height="375" /></div><p>My MacBook Pro has two USB ports. Das Keyboard wanted both those ports to be used by the keyboard cable, leaving no ports on the computer free. Thankfully, my USB thumb drive fits well into the keyboard's second USB port, but I'm confused as to why this is even necessary. <strong>I had to purchase a USB extension cable in order for Das Keyboard's combined cable fit the MacBook Pro comfortably</strong>, and this means extra setup each time I connect and disconnect the machine. Obviously, not a huge deal, but mistifying and worthy of mention.</p>

<h3>Keyboard Settings</h3>

<p>My MacBook Pro runs OS X 10.4 Tiger. In order to get the keyboard to work with proper key placement (with the Control, Option and Command/Apple Keys in that order) I have to change settings every time I plug in the keyboard:</p>

<div class="main-image">
	<div><img src="/files/2212/7481/9224/Picture 1.png" class="footer-image" width="418" height="240" alt="footer image" /></div>


</div><p>Then I reverse those when I unplug the laptop and take it home with me.</p>

<h3>Windows Key</h3>

<p>Finally, as a Mac a user, I feel a slight twinge when I glance down at my keyboard:</p>
<div class="main-image">
<img border="0" class="ccm-image-block" alt="" src="/files/cache/ab87dbc1b62284d0b49039545fab9cfd.jpg"  width="500" height="375" /></div><p>Yes, Das Keyboard sells <a href="http://store.daskeyboard.com/Accessories-Products/b/2258669011?ie=UTF8&amp;title=Accessories">keyboard kits</a>, but I didn't feel like paying more than $20 (when including shipping) to add it to my order, which already cost north of $100.</p>

<h3>Overall</h3>

<p>Setup overall is a mixed bag. It's an area of keyboard usage that I had blithely anticipated wouldn't matter, but it actually accounts for most of my gripes with the product. Granted, they are small – quibbles, really – but a little irritating and confusing for a product that gets so much else right.</p>

<h2>Construction and Looks</h2>

<p>The construction of Das Keyboard seems sturdy enough. I haven't done anything foolish like spill a full soda on it, drop it in the ground or turn it over and bash it into a desk, but I have carted it a few places and been somewhat rough while cleaning it, all without incident. The lights on the keyboard are a satisfying blue, and the whole package is a very attractive one.</p>

<h2>Usage</h2>

<h3>Speed (and Sound)</h3>

<p>Here's where we get down to it. This keyboard is fast. Really fast. But it is <strong>not</strong> quiet. Check out this audio file of me speaking in a normal voice, and then as I continue to speak, I type the same sentence:</p>
﻿
		
		
	<script type="text/javascript">
		
		var flashvars = {};
		flashvars.audioPath = "/files/5612/7481/3632/das keyboard.mp3";
		flashvars.autoPlay = 0;
		flashvars.backgroundColor = "000000";
		flashvars.editMode = 0;
		
		var parameters = {};
		
				
		swfobject.embedSWF ("/packages/flash_audio/blocks/flash_audio/assets/AudioPlayer.swf", "flash_audio_614", "250", "25", "9.0.28", null, flashvars, parameters);
		
	</script>
	
	<div id="flash_audio_614"></div>
	<div style="font-size: 11px; padding-left: 5px">Download <a href="/files/5612/7481/3632/das keyboard.mp3">das keyboard.mp3</a></div><p>This will make enemies in an open office. Sadly, concrete5's office space is probably the absolutely <strong>worst</strong> work environment for this sort of keyboard, as we all inhabit one large room, but I think everyone puts up with it because I like it (which I very much appreciate.) There has been a noted increase in the use of headphones throughout the office, however.</p>

<p>Yes, Das Keyboard comes with a quiet version, but when I tried it at SXSW I didn't like it. It didn't seem as satisfying. Go loud or go home. </p>

<h2>Results</h2>

<p>My results are anecdotal in nature, but I think they're still impressive.</p>

<h3>Typing Maniac</h3>

<p><a href="http://apps.facebook.com/typing-maniac/">Typing Maniac</a> is a Facebook game where the goal is to type words as they appear on screen, before they fall from the top of the screen to the bottom. As the game progresses, the speed increases and the words become more complex.</p>

<p>Prior to Das Keyboard, my highest score was in the 400,000s. Once Das Keyboard arrived, I more than doubled it, in my first try:</p>

<div class="main-image">
	<div><img src="/files/1012/7497/6886/Picture 1.png" class="footer-image" width="64" height="179" alt="footer image" /></div>


</div><p>I <strong>will</strong> get to 1,000,000 points.</p>

<h3>Das Keyboard Typing Test</h3>

<p>Das Keyboard promotes its own typing test, and this was the test used at SXSW when it crowned the fastest touch typist in the world. This test is also available online at any time. Check out my results.</p>

<div class="main-image">
	<div><img src="/files/7012/7005/6496/7495361366_44hcL.jpg" class="footer-image" width="527" height="292" alt="footer image" /></div>


</div><p>Not too shabby.</p>

<h2>Cost</h2>

<p>The results don't lie. This is a keyboard for those who type. As a bonus, it looks great and has a nice, satisfying weight. With a premium product comes a premium price. Das Keyboard Professional lists for $129, with a quieter version costing $135. Don't forget to add shipping to that, too. I was fortunate, however, to be able to grab the keyboard for 25% off, with free shipping, thanks to a SXSW-only deal. Scour the web for coupons – you'll likely find some.</p>

<p>Price-wise, this isn't much more than the cost of classic mechanical switch keyboards like the IBM Model M or the Apple Extended. But there's a reason those keyboards went out of fashion: they're expensive! Keyboards have gotten much cheaper since, and for those who are happy with a $19.99 keyboard found at a local superstore, paying more than six times as much is going to be a tall order. If you can afford it, and you're a touch typist, you'll be willing to make the sacrifice.</p>

<h2>The Verdict</h2>

<p>If you're a great touch typist, you find yourself typing frequently during the day, and you have an enclosed office (or tolerant, headphone-wearing co-workers), buy buy buy.</p>
<p><span class="byline">Andrew Embler can probably type faster than you. He apologizes for the noise.</span></p>				<br/><br/>
				<a href="http://andrewembler.com/reviews/das-keyboard-professional/">Comment on this at andrewembler.com</a>
			  ]]>
			  </description>
			  <pubDate>Thu, 27 May 2010 15:16:00 EDT</pubDate>
			</item>
		
			<item>
			  <title>JavaScript, jQuery and concrete5</title>
			  <link>http://andrewembler.com/concrete5/javascript-jquery-and-concrete5/</link>
			  <description>
			  <![CDATA[
				<p>concrete5's rich user interface is one of the things that sets it apart from some of its open source competitors. With its emphasis on in-context editing, overlays, slide-down panes, AJAX form submission and the ability to add large amounts of content (including files) without ever leaving the page, concrete5 frequently behaves more like a desktop application than a typical web application. <strong>In this how-to, I'm going to show you how you can integrate a wide variety of rich JavaScript functionality into the front-end of your applications and blocks</strong>.</p>

<p>Note: this isn't meant to be the one tutorial to rule them all: this is merely an overview to show you some of the ways concrete5 integrates and works well with JavaScript, how you can start exploring further. </p>

<h2>jQuery: concrete5's JavaScript Framework</h2>

<p>Much of concrete5's interaction model would simply not be possible without <a href="http://www.jquery.com">jQuery</a>. One of the most popular extensions to JavaScript available, jQuery relieves much of the incompatibility and verbosity that has typically plagued the scripting of complex web applications.</p>

<p>We didn't always use an intermediary JavaScript framework (and – gulp – for a little while we flirted with Prototype), but jQuery makes so much about complex scripting easier than it used to be. And even better: jQuery's plugin model has been used to create great additions to the core library, including effects libraries and new widgets. Several of these plugins are also included in concrete5 core.</p>

<h2>An Overview of All jQuery Components Included in concrete 5.4</h2>

<p>The following jQuery libraries included with concrete 5.4:</p>

<ul>
<li>jQuery Core (1.4)</li>
<li>jQuery UI (1.7.2)</li>
<li>jQuery Scroll-To (1.3.3)</li>
<li>jQuery Rating (3.0)</li>
<li>jQuery Metadata</li>
<li>jQuery LiveUpdate </li>
<li>jQuery Form (2.12)</li>
<li>jQuery Cookie</li>
<li>jQuery Color Picker</li>
</ul>

<h3>jQuery UI</h3>

<p>The following <a href="http://www.jqueryui.com">jQuery UI</a> components are included in jquery.ui.js.</p>

<ul>
<li>jQuery UI Draggable</li>
<li>jQuery UI Droppable</li>
<li>jQuery UI Selectable</li>
<li>jQuery UI Sortable</li>
<li>jQuery UI Accordion</li>
<li>jQuery UI Slider</li>
<li>jQuery UI Progressbar</li>
<li>jQuery UI Effects</li>
<li>jQuery UI Datepicker</li>
</ul>

<h2>How to include jQuery and its Components in your Block or Single Page</h2>

<h3>Single Pages</h3>

<p>Including jQuery in your single pages or pages of a certain type is as easy as calling addHeaderItem in your page's controller method. Let's say you have a page accessed at </p>

<pre><code>http://www.yoursite.com/index.php/your_special_page/
</code></pre>

<p>That means you have a controller here at </p>

<pre><code>controllers/your_special_page.php

or

controllers/your_special_page/controller.php
</code></pre>

<p>And within that controller file, in your view() method, the following will include the jQuery UI library, its required stylesheet, the concrete5 dialog class (more on this in a moment) and its required stylesheet.</p>
<div class="ccm-syntax-highlighter">
<pre class="php" style="font-family:monospace;"><span style="color: #999999; font-weight: bold;">public</span> <span style="color: #999999; font-weight: bold;">function</span> view<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
   <span style="color: #6666FF;">$html</span> <span style="color: #339933;">=</span> Loader<span style="color: #339933;">::</span><span style="color: #00FF00;">helper</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'html'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
   <span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">addHeaderItem</span><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$html</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">css</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'jquery.ui.css'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
   <span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">addHeaderItem</span><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$html</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">css</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'ccm.dialog.css'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
   <span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">addHeaderItem</span><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$html</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">javascript</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'jquery.ui.js'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
   <span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">addHeaderItem</span><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$html</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">javascript</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'ccm.dialog.js'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;</pre></div><p>The HtmlHelper class takes care of locating the correct file and printing out the proper tag. The Controller::addHeaderItem() function makes sure only one instance of a given header item is added, and is properly output in the HEAD tag of the page.</p>

<h3>Blocks</h3>

<p>Calling CSS and JavaScript in your blocks is even easier. If you'd like a particular block's view layer to require certain JavaScript and CSS, simply add it to the block controller's on&#95;page&#95;view() function:</p>
<div class="ccm-syntax-highlighter">
<pre class="php" style="font-family:monospace;"><span style="color: #999999; font-weight: bold;">public</span> <span style="color: #999999; font-weight: bold;">function</span> on_page_view<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  <span style="color: #6666FF;">$html</span> <span style="color: #339933;">=</span> Loader<span style="color: #339933;">::</span><span style="color: #00FF00;">helper</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'html'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">addHeaderItem</span><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$html</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">css</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'jquery.ui.css'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">addHeaderItem</span><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$html</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">css</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'ccm.dialog.css'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">addHeaderItem</span><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$html</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">javascript</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'jquery.ui.js'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">addHeaderItem</span><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$html</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">javascript</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'ccm.dialog.js'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div><p><em>Note</em>: this is <em>not</em> the block's view() function. on&#95;page&#95;view() runs before the page is rendered, ensuring that the CSS and JavaScript files are added in the HEAD tag.</p>

<p>Once jQuery and jQuery UI are included in your page (and jQuery is typically included in themes by default) you'll be able to use all the great functionality described at jQuery.com. </p>

<h2>How to use the built-in concrete5 Dialog Class</h2>

<p>The built-in concrete5 dialog class is responsible for rendering all modal and non-modal dialog windows (<em>not</em> the slide-downs) that are positioned in the middle of the screen. This library is <em>not</em> the same as the jQuery UI dialog class. It was created before jQuery UI Dialog, and as such, currently conflicts with it. </p>

<h3>Example 1: Loading an external url into a dialog using on-link attributes</h3>

<p>The easiest way of calling a dialog window is by specifying certain attributes in the link you wish to use to call the window, and then calling the .dialog() function on that link.</p>
<div class="ccm-syntax-highlighter">
<pre class="html4strict" style="font-family:monospace;"><span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/a.html"><span style="color: #FFFFFF; font-weight: bold;">a</span></a> </span>
<span style="color: #009900;">   dialog-<span style="color: #6666FF;">title</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;This is the dialog title.&quot;</span> </span>
<span style="color: #009900;">   dialog-modal<span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;false&quot;</span></span>
<span style="color: #009900;">   dialog-<span style="color: #6666FF;">width</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;550&quot;</span> </span>
<span style="color: #009900;">   dialog-<span style="color: #6666FF;">height</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;380&quot;</span> </span>
<span style="color: #009900;">   <span style="color: #6666FF;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;myDialog&quot;</span> </span>
<span style="color: #009900;">   <span style="color: #6666FF;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;yourpage.php&quot;</span>&gt;</span>This is the link<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/a.html"><span style="color: #FFFFFF; font-weight: bold;">a</span></a>&gt;</span></pre></div><p>Now, run the dialog function:</p>
<div class="ccm-syntax-highlighter">
<pre class="javascript" style="font-family:monospace;"><span style="color: #339933;">&lt;</span>script type<span style="color: #339933;">=</span><span style="color: #3366CC;">&quot;text/javascript&quot;</span><span style="color: #339933;">&gt;</span>
   $<span style="color: #118811;">&#40;</span><span style="color: #006699; font-weight: bold;">function</span><span style="color: #118811;">&#40;</span><span style="color: #118811;">&#41;</span> <span style="color: #118811;">&#123;</span>
      $<span style="color: #118811;">&#40;</span><span style="color: #3366CC;">&quot;#myDialog&quot;</span><span style="color: #118811;">&#41;</span>.<span style="color: #996699;">dialog</span><span style="color: #118811;">&#40;</span><span style="color: #118811;">&#41;</span><span style="color: #339933;">;</span>
   <span style="color: #118811;">&#125;</span><span style="color: #118811;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #339933;">&lt;/</span>script<span style="color: #339933;">&gt;</span></pre></div><p>This will load yourpage.php via AJAX, create a new 550x380 dialog window with the proper title, make it non-modal, and load the content into it.</p>

<h3>Example 2: Loading an external url into a dialog from within a JavaScript function</h3>

<p>The same operation above can be run from within a JavaScript function</p>
<div class="ccm-syntax-highlighter">
<pre class="javascript" style="font-family:monospace;"><span style="color: #339933;">&lt;</span>script type<span style="color: #339933;">=</span><span style="color: #3366CC;">&quot;text/javascript&quot;</span><span style="color: #339933;">&gt;</span>
loadMyDialog <span style="color: #339933;">=</span> <span style="color: #006699; font-weight: bold;">function</span><span style="color: #118811;">&#40;</span><span style="color: #118811;">&#41;</span> <span style="color: #118811;">&#123;</span>
   jQuery.<span style="color: #996699;">fn</span>.<span style="color: #996699;">dialog</span>.<span style="color: #000066;">open</span><span style="color: #118811;">&#40;</span><span style="color: #118811;">&#123;</span>
      title<span style="color: #339933;">:</span> <span style="color: #3366CC;">'This is my title'</span><span style="color: #339933;">,</span>
      href<span style="color: #339933;">:</span> <span style="color: #3366CC;">'yourpage.php'</span><span style="color: #339933;">,</span>
      width<span style="color: #339933;">:</span> <span style="color: #CC0000;">550</span><span style="color: #339933;">,</span>
      modal<span style="color: #339933;">:</span> <span style="color: #006699; font-weight: bold;">false</span><span style="color: #339933;">,</span>
      height<span style="color: #339933;">:</span> <span style="color: #CC0000;">380</span><span style="color: #339933;">,</span>
      onClose<span style="color: #339933;">:</span> <span style="color: #006699; font-weight: bold;">function</span><span style="color: #118811;">&#40;</span><span style="color: #118811;">&#41;</span> <span style="color: #118811;">&#123;</span>
         <span style="color: #000066;">alert</span><span style="color: #118811;">&#40;</span><span style="color: #3366CC;">'This will fire when the dialog is closed.'</span><span style="color: #118811;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #118811;">&#125;</span>
   <span style="color: #118811;">&#125;</span><span style="color: #118811;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #118811;">&#125;</span>
<span style="color: #339933;">&lt;/</span>script<span style="color: #339933;">&gt;</span></pre></div><p>Simply run loadMyDialog() and the proper dialog will open. Note the "onClose" function that will run when the dialog is closed.</p>

<h3>Example 3: Loading the contents of an on-page element into a dialog from within a JavaScript function</h3>

<p>If you'd rather load a dialog and populate it with in-page content, you can do so using the syntax below:</p>
<div class="ccm-syntax-highlighter">
<pre class="html4strict" style="font-family:monospace;"><span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/div.html"><span style="color: #FFFFFF; font-weight: bold;">div</span></a> <span style="color: #6666FF;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;myDialogContent&quot;</span> <span style="color: #6666FF;">style</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;display: none&quot;</span>&gt;</span>
   This is the content of my dialog window.
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/div.html"><span style="color: #FFFFFF; font-weight: bold;">div</span></a>&gt;</span></pre></div><div class="ccm-syntax-highlighter">
<pre class="javascript" style="font-family:monospace;"><span style="color: #339933;">&lt;</span>script type<span style="color: #339933;">=</span><span style="color: #3366CC;">&quot;text/javascript&quot;</span><span style="color: #339933;">&gt;</span>
loadMyDialog <span style="color: #339933;">=</span> <span style="color: #006699; font-weight: bold;">function</span><span style="color: #118811;">&#40;</span><span style="color: #118811;">&#41;</span> <span style="color: #118811;">&#123;</span>
   jQuery.<span style="color: #996699;">fn</span>.<span style="color: #996699;">dialog</span>.<span style="color: #000066;">open</span><span style="color: #118811;">&#40;</span><span style="color: #118811;">&#123;</span>
      title<span style="color: #339933;">:</span> <span style="color: #3366CC;">'This is my title'</span><span style="color: #339933;">,</span>
      element<span style="color: #339933;">:</span> <span style="color: #3366CC;">'#myDialogContent'</span><span style="color: #339933;">,</span>
      width<span style="color: #339933;">:</span> <span style="color: #CC0000;">550</span><span style="color: #339933;">,</span>
      modal<span style="color: #339933;">:</span> <span style="color: #006699; font-weight: bold;">false</span><span style="color: #339933;">,</span>
      height<span style="color: #339933;">:</span> <span style="color: #CC0000;">380</span><span style="color: #339933;">,</span>
      onClose<span style="color: #339933;">:</span> <span style="color: #006699; font-weight: bold;">function</span><span style="color: #118811;">&#40;</span><span style="color: #118811;">&#41;</span> <span style="color: #118811;">&#123;</span>
         <span style="color: #000066;">alert</span><span style="color: #118811;">&#40;</span><span style="color: #3366CC;">'This will fire when the dialog is closed.'</span><span style="color: #118811;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #118811;">&#125;</span>
   <span style="color: #118811;">&#125;</span><span style="color: #118811;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #118811;">&#125;</span>
<span style="color: #339933;">&lt;/</span>script<span style="color: #339933;">&gt;</span></pre></div><h2>AJAX</h2>

<p>If you want to use jQuery to integrate some server-side processing into concrete5 (AJAX), it can be a little difficult to know where to start. There are basically two approaches available: 1) use a controller action and then exit from the action before rendering the page, or 2) use a tool script.</p>

<p>What's a tool script? A tool script is a simple PHP script either in your local tools/ directory or your block's tools/ directory. This script has no UI wrapped around it. It's lightweight, and simply loads a number of concrete5 objects and connects to the database. Otherwise, you're free to do what you wish inside it.</p>

<h3>Using an Action for Server-Side Processing in a Block</h3>

<p>From within the block's view layer, make the HREF of the link you wish to tie to the backend equal the value of an action method in your controller:</p>
<div class="ccm-syntax-highlighter">
<pre class="php" style="font-family:monospace;"><span style="color: #6666FF;">$action</span> <span style="color: #339933;">=</span> <span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">action</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'like'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div><p>This will create a link that will pass through to the block when the form is submitted, and then "action_like" action will be run.</p>

<p>Now, in HTML, we create the link:</p>
<div class="ccm-syntax-highlighter">
<pre class="html4strict" style="font-family:monospace;"><span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/a.html"><span style="color: #FFFFFF; font-weight: bold;">a</span></a> <span style="color: #6666FF;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;&lt;?=$action?&gt;</span></span>&quot; id=&quot;myActionLink&quot;&gt;Like!<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/a.html"><span style="color: #FFFFFF; font-weight: bold;">a</span></a>&gt;</span></pre></div><p>Now, in JavaScript, we make it so that the link in question submits to the backend:</p>
<div class="ccm-syntax-highlighter">
<pre class="javascript" style="font-family:monospace;">$<span style="color: #118811;">&#40;</span><span style="color: #3366CC;">'#myActionLink'</span><span style="color: #118811;">&#41;</span>.<span style="color: #996699;">click</span><span style="color: #118811;">&#40;</span><span style="color: #006699; font-weight: bold;">function</span><span style="color: #118811;">&#40;</span><span style="color: #118811;">&#41;</span> <span style="color: #118811;">&#123;</span>        
   <span style="color: #006699; font-weight: bold;">var</span> url <span style="color: #339933;">=</span> $<span style="color: #118811;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #118811;">&#41;</span>.<span style="color: #996699;">attr</span><span style="color: #118811;">&#40;</span><span style="color: #3366CC;">'href'</span><span style="color: #118811;">&#41;</span><span style="color: #339933;">;</span>
   $.<span style="color: #996699;">get</span><span style="color: #118811;">&#40;</span>url<span style="color: #339933;">,</span> <span style="color: #006699; font-weight: bold;">function</span><span style="color: #118811;">&#40;</span>r<span style="color: #118811;">&#41;</span> <span style="color: #118811;">&#123;</span>
      <span style="color: #000066;">alert</span><span style="color: #118811;">&#40;</span><span style="color: #3366CC;">'Success!'</span><span style="color: #118811;">&#41;</span><span style="color: #339933;">;</span>
   <span style="color: #118811;">&#125;</span><span style="color: #118811;">&#41;</span><span style="color: #339933;">;</span>
   <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #006699; font-weight: bold;">false</span><span style="color: #339933;">;</span>
<span style="color: #118811;">&#125;</span><span style="color: #118811;">&#41;</span><span style="color: #339933;">;</span></pre></div><p>Finally, the action_like() method in the block's controller processes, and then exits at the end.</p>

<h3>Tools</h3>

<p>Tools are another way to enable server-side processing. Using tools outside the block level is easy. For example, the JavaScript function ccm_dashboardRequestRemoteInformation runs every time the front page of the dashboard is hit:</p>
<div class="ccm-syntax-highlighter">
<pre class="javascript" style="font-family:monospace;">ccm_dashboardRequestRemoteInformation <span style="color: #339933;">=</span> <span style="color: #006699; font-weight: bold;">function</span><span style="color: #118811;">&#40;</span><span style="color: #118811;">&#41;</span> <span style="color: #118811;">&#123;</span>
   $.<span style="color: #996699;">get</span><span style="color: #118811;">&#40;</span>CCM_TOOLS_PATH <span style="color: #339933;">+</span> <span style="color: #3366CC;">'/dashboard/get_remote_information'</span><span style="color: #118811;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #118811;">&#125;</span></pre></div><p>This simply loads the "dashboard/get&#95;remote&#95;information.php" tool through AJAX. The tools path takes care of making sure the script in the correct location is loaded.</p>

<p>Loading a block-specific tool is nearly as easy. From within a block's view layer, the following will automatically load information from a tool found in the block's tools/ directory:</p>
<div class="ccm-syntax-highlighter">
<pre class="php" style="font-family:monospace;"><span style="color: #999999; font-weight: bold;">&lt;?php</span>
<span style="color: #6666FF;">$th</span> <span style="color: #339933;">=</span> Loader<span style="color: #339933;">::</span><span style="color: #00FF00;">helper</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'concrete/urls'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
<span style="color: #6666FF;">$bt</span> <span style="color: #339933;">=</span> <span style="color: #6666FF;">$b</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">getBlockTypeObject</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #999999; font-weight: bold;">?&gt;</span>
&nbsp;
<span style="color: #339933;">&lt;</span>script type<span style="color: #339933;">=</span><span style="color: #4444ff;">&quot;text/javascript&quot;</span><span style="color: #339933;">&gt;</span>
$<span style="color: #009900;">&#40;</span><span style="color: #999999; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
   $<span style="color: #339933;">.</span>get<span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'&lt;?=$th-&gt;getBlockTypeToolsURL($bt)?&gt;/load_information?&gt;'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #999999; font-weight: bold;">&lt;/script&gt;</span></pre></div><p>This will automatically find the "load_information.php" script within the block's tools directory, and load it silently. You can pass query string arguments to the script to obtain more functionality, and process them silently from within the script.</p>

<h3>JSON</h3>

<p>If you'd like to return JSON to your AJAX function, it's as easy as defining a simple PHP object within your tool or action function, instantiating the properties you want to pass back, and using the concrete5 JSON helper.</p>
<div class="ccm-syntax-highlighter">
<pre class="php" style="font-family:monospace;"><span style="color: #6666FF;">$obj</span> <span style="color: #339933;">=</span> <span style="color: #999999; font-weight: bold;">new</span> stdClass<span style="color: #339933;">;</span>
<span style="color: #6666FF;">$obj</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">favoriteColor</span> <span style="color: #339933;">=</span> <span style="color: #4444ff;">'red'</span><span style="color: #339933;">;</span>
<span style="color: #6666FF;">$obj</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">name</span> <span style="color: #339933;">=</span> <span style="color: #4444ff;">'Andrew'</span><span style="color: #339933;">;</span>
<span style="color: #6666FF;">$obj</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">isAwesome</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">;</span>
<span style="color: #6666FF;">$js</span> <span style="color: #339933;">=</span> Loader<span style="color: #339933;">::</span><span style="color: #00FF00;">helper</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'json'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">print</span> <span style="color: #6666FF;">$js</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">encode</span><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$obj</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<a href="http://www.php.net/exit"><span style="color: #990000;">exit</span></a><span style="color: #339933;">;</span></pre></div><p>This will print out</p>

<pre><code>{"favoriteColor":"red","name":"Andrew","isAwesome":true}
</code></pre>

<p>and exit, leaving you to use jQuery's $.getJSON function to parse the string into JavaScript objects that you can do with what you will.</p>

<h2>Putting it All Together: Building a "Like This!" Block</h2>

<p>Getting a feel for this functionality is hard without a concrete example. That's why I'm releasing a free "Likes This!" block, similar to one we use on concrete5.org. This is a very simple block: it allows logged-in users to say that they "like" a certain page. They are tied to the page, and a page attribute is also incremented to allow pages to be sorted easily by the number of likes that they have received. </p>

<div class="main-image">
	<div><img src="/files/1012/7436/9933/Picture 1.png" class="footer-image" width="245" height="63" alt="footer image" /></div>

<div class="main-image-caption">This is the default view for those not logged in.</div>

</div>
<div class="main-image">
	<div><img src="/files/4512/7436/9932/Picture 2.png" class="footer-image" width="243" height="57" alt="footer image" /></div>

<div class="main-image-caption">Logged in users receive the ability to like the page.</div>

</div>
<div class="main-image">
	<div><img src="/files/6712/7436/9933/Picture 3.png" class="footer-image" width="243" height="62" alt="footer image" /></div>

<div class="main-image-caption">If they click the link, the result happens inline, dynamically populating the view area and highlighting the div.</div>

</div><div class="main-image">
<img border="0" class="ccm-image-block" alt="Finally, you can view the full list of users who've favorited a page." src="/files/cache/75709f9239fde15516023ddcf5eaf263.png"  width="778" height="320" /><div class="main-image-caption">Finally, you can view the full list of users who've favorited a page.</div>
</div><p>This block is available for free from the marketplace here:</p>

<p><a href="http://www.concrete5.org/marketplace/addons/likes-this/">http://www.concrete5.org/marketplace/addons/likes-this/</a></p>
<p>This block is a good demonstration of concrete5's JavaScript abilities, because it features:</p>

<ol>
<li>jQuery UI and concrete5's dialog functionality are included intelligently on page load</li>
<li>The block view template intelligently references tools and controller actions.</li>
<li>The block automatically includes JavaScript by including view.js in its directory. This JavaScript is used by the block view template.</li>
<li>The dialog class is used to pull data in from a tools script, through AJAX.</li>
<li>The response from the block's controller action is loaded into the page seamlessly.</li>
<li>jQuery UI effects are used.</li>
<li>Everything will degrade gracefully even when JavaScript is disabled.</li>
</ol>

<h3>Including the Proper Header Items</h3>

<p>The following code in the block's controller file is responsible for including the dialog and jQuery UI code in the header.</p>
<div class="ccm-syntax-highlighter">
<pre class="php" style="font-family:monospace;"><span style="color: #999999; font-weight: bold;">public</span> <span style="color: #999999; font-weight: bold;">function</span> on_page_view<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
   <span style="color: #6666FF;">$u</span> <span style="color: #339933;">=</span> <span style="color: #999999; font-weight: bold;">new</span> User<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
   <span style="color: #6666FF;">$html</span> <span style="color: #339933;">=</span> Loader<span style="color: #339933;">::</span><span style="color: #00FF00;">helper</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'html'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
   <span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">addHeaderItem</span><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$html</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">javascript</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'jquery.js'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
   <span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">addHeaderItem</span><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$html</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">javascript</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'ccm.dialog.js'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
   <span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">addHeaderItem</span><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$html</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">css</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'ccm.dialog.css'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
   <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$u</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">isRegistered</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">addHeaderItem</span><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$html</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">javascript</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'jquery.ui.js'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">addHeaderItem</span><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$html</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">css</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'jquery.ui.css'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
   <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div><p>Notice, we only include the jQuery UI code if the user who is viewing the page is logged in. Why? Because user's who aren't logged in won't have the ability to "like" a page – so why should we slow their page loading down?</p>

<h3>The Block View Template</h3>

<p>The block view template is here:</p>
<div class="ccm-syntax-highlighter">
<pre class="php" style="font-family:monospace;"><span style="color: #999999; font-weight: bold;">&lt;?php</span> <span style="color: #6666FF;">$userLikesThis</span> <span style="color: #339933;">=</span> <span style="color: #6666FF;">$controller</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">userLikesThis</span><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$u</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #999999; font-weight: bold;">?&gt;</span>
<span style="color: #999999; font-weight: bold;">&lt;?php</span> <span style="color: #6666FF;">$c</span> <span style="color: #339933;">=</span> Page<span style="color: #339933;">::</span><span style="color: #00FF00;">getCurrentPage</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #999999; font-weight: bold;">?&gt;</span>
<span style="color: #339933;">&lt;</span>div <span style="color: #999999; font-weight: bold;">class</span><span style="color: #339933;">=</span><span style="color: #4444ff;">&quot;ccm-block-likes-this-wrapper&quot;</span><span style="color: #339933;">&gt;</span>
   <span style="color: #339933;">&lt;</span>p<span style="color: #339933;">&gt;</span>
&nbsp;
   <span style="color: #999999; font-weight: bold;">&lt;?</span> <span style="color: #6666FF;">$action</span> <span style="color: #339933;">=</span> <span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">action</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'like'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #999999; font-weight: bold;">?&gt;</span>
   <span style="color: #999999; font-weight: bold;">&lt;?</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #6666FF;">$userLikesThis</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <span style="color: #999999; font-weight: bold;">?&gt;</span><span style="color: #339933;">&lt;</span>a href<span style="color: #339933;">=</span><span style="color: #4444ff;">&quot;&lt;?=<span style="color: #006699; font-weight: bold;">$action</span>?&gt;&quot;</span> 
         <span style="color: #999999; font-weight: bold;">class</span><span style="color: #339933;">=</span><span style="color: #4444ff;">&quot;ccm-block-likes-this-link&quot;</span><span style="color: #339933;">&gt;</span><span style="color: #999999; font-weight: bold;">&lt;?</span> <span style="color: #009900;">&#125;</span> <span style="color: #999999; font-weight: bold;">?&gt;</span>
   <span style="color: #339933;">&lt;</span>img src<span style="color: #339933;">=</span><span style="color: #4444ff;">&quot;&lt;?php echo <span style="color: #006699; font-weight: bold;">$this-&gt;getBlockURL</span>().&quot;</span><span style="color: #339933;">/</span>images<span style="color: #339933;">/</span>heart<span style="color: #339933;">.</span>png<span style="color: #4444ff;">&quot;; ?&gt;&quot;</span>
       style<span style="color: #339933;">=</span><span style="color: #4444ff;">&quot;float: left; margin-right: 4px&quot;</span> <span style="color: #339933;">/&gt;</span>
   <span style="color: #999999; font-weight: bold;">&lt;?</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #6666FF;">$userLikesThis</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <span style="color: #999999; font-weight: bold;">?&gt;</span><span style="color: #339933;">&lt;/</span>a<span style="color: #339933;">&gt;</span><span style="color: #999999; font-weight: bold;">&lt;?</span> <span style="color: #009900;">&#125;</span> <span style="color: #999999; font-weight: bold;">?&gt;</span>
   <span style="color: #999999; font-weight: bold;">&lt;?</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$count</span> <span style="color: #339933;">&gt;</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <span style="color: #999999; font-weight: bold;">?&gt;</span>
      <span style="color: #999999; font-weight: bold;">&lt;?</span> <span style="color: #6666FF;">$th</span> <span style="color: #339933;">=</span> Loader<span style="color: #339933;">::</span><span style="color: #00FF00;">helper</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'concrete/urls'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
      <span style="color: #6666FF;">$bt</span> <span style="color: #339933;">=</span> <span style="color: #6666FF;">$b</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">getBlockTypeObject</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #999999; font-weight: bold;">?&gt;</span>
      <span style="color: #339933;">&lt;</span>a <span style="color: #999999; font-weight: bold;">class</span><span style="color: #339933;">=</span><span style="color: #4444ff;">&quot;ccm-block-likes-this-link-list&quot;</span> target<span style="color: #339933;">=</span><span style="color: #4444ff;">&quot;_blank&quot;</span> 
         title<span style="color: #339933;">=</span><span style="color: #4444ff;">&quot;&lt;?=t('View User List')?&gt;&quot;</span> 
         href<span style="color: #339933;">=</span><span style="color: #4444ff;">&quot;&lt;?=<span style="color: #006699; font-weight: bold;">$th-&gt;getBlockTypeToolsURL</span>(<span style="color: #006699; font-weight: bold;">$bt</span>)?&gt;/list?cID=&lt;?=<span style="color: #006699; font-weight: bold;">$c-&gt;getCollectionID</span>()?&gt;&quot;</span><span style="color: #339933;">&gt;</span>
      <span style="color: #999999; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$count</span> <span style="color: #339933;">==</span> <span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
         <span style="color: #b1b100;">echo</span> <a href="http://www.php.net/number_format"><span style="color: #990000;">number_format</span></a><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$count</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><span style="color: #999999; font-weight: bold;">?&gt;</span> person likes this page<span style="color: #339933;">.</span>
      <span style="color: #999999; font-weight: bold;">&lt;?php</span> <span style="color: #009900;">&#125;</span>  <span style="color: #b1b100;">elseif</span><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$count</span> <span style="color: #339933;">&gt;</span> <span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
         <span style="color: #b1b100;">echo</span> <a href="http://www.php.net/number_format"><span style="color: #990000;">number_format</span></a><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$count</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #999999; font-weight: bold;">?&gt;</span> people like this page<span style="color: #339933;">.</span>
      <span style="color: #999999; font-weight: bold;">&lt;?php</span> <span style="color: #009900;">&#125;</span> <span style="color: #999999; font-weight: bold;">?&gt;</span>
      <span style="color: #339933;">&lt;/</span>a<span style="color: #339933;">&gt;</span>
&nbsp;
   <span style="color: #999999; font-weight: bold;">&lt;?</span> <span style="color: #009900;">&#125;</span> <span style="color: #999999; font-weight: bold;">?&gt;</span>
&nbsp;
   <span style="color: #339933;">&lt;/</span>p<span style="color: #339933;">&gt;</span>
&nbsp;
   <span style="color: #339933;">&lt;</span>p<span style="color: #339933;">&gt;</span>
&nbsp;
   <span style="color: #999999; font-weight: bold;">&lt;?</span>
   <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$controller</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">userLikesThis</span><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$u</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <span style="color: #999999; font-weight: bold;">?&gt;</span>
      <span style="color: #339933;">&lt;</span>strong<span style="color: #339933;">&gt;</span><span style="color: #999999; font-weight: bold;">&lt;?=</span>t<span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'You like this!'</span><span style="color: #009900;">&#41;</span><span style="color: #999999; font-weight: bold;">?&gt;</span><span style="color: #339933;">&lt;/</span>strong<span style="color: #339933;">&gt;</span>
   <span style="color: #999999; font-weight: bold;">&lt;?</span> <span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$u</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">isRegistered</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <span style="color: #999999; font-weight: bold;">?&gt;</span>
      <span style="color: #339933;">&lt;</span>a href<span style="color: #339933;">=</span><span style="color: #4444ff;">&quot;&lt;?php echo <span style="color: #006699; font-weight: bold;">$action</span>;?&gt;&quot;</span> 
         <span style="color: #999999; font-weight: bold;">class</span><span style="color: #339933;">=</span><span style="color: #4444ff;">&quot;ccm-block-likes-this-link&quot;</span><span style="color: #339933;">&gt;</span>I like it<span style="color: #999999; font-weight: bold;">&lt;?</span>php <span style="color: #b1b100;">echo</span> <span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$count</span> <span style="color: #339933;">&gt;</span> <span style="color: #cc66cc;">0</span>?<span style="color: #4444ff;">&quot; too&quot;</span><span style="color: #339933;">:</span><span style="color: #4444ff;">&quot;&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><span style="color: #999999; font-weight: bold;">?&gt;</span><span style="color: #339933;">!&lt;/</span>a<span style="color: #339933;">&gt;</span>
   <span style="color: #999999; font-weight: bold;">&lt;?</span> <span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span> <span style="color: #999999; font-weight: bold;">?&gt;</span>
      <span style="color: #999999; font-weight: bold;">&lt;?=</span>t<span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'You must &lt;a href=&quot;%s&quot;&gt;sign in&lt;/a&gt; to 
         mark this page as one you like.'</span><span style="color: #339933;">,</span> <span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">url</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'/login'</span><span style="color: #339933;">,</span> <span style="color: #4444ff;">'forward'</span><span style="color: #339933;">,</span> <span style="color: #6666FF;">$c</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">getCollectionID</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><span style="color: #999999; font-weight: bold;">?&gt;</span>
   <span style="color: #999999; font-weight: bold;">&lt;?</span> <span style="color: #009900;">&#125;</span> <span style="color: #999999; font-weight: bold;">?&gt;</span>
   <span style="color: #339933;">&lt;/</span>p<span style="color: #339933;">&gt;</span>
&nbsp;
<span style="color: #339933;">&lt;/</span>div<span style="color: #339933;">&gt;</span></pre></div><p>The function of this template should be fairly self-explanatory. Basically, we don't include links to like the page if the user is not logged in, or if the user has already said they like the page. </p>

<h3>Including JavaScript when the Block is Included</h3>

<p>The "Likes This" includes view.js in its folder. By doing so, it ensures that the functions within the view.js file will be automatically included in the page when the block itself is. Here are its contents:</p>
<div class="ccm-syntax-highlighter">
<pre class="javascript" style="font-family:monospace;">ccm_blockLikesThisSetupList <span style="color: #339933;">=</span> <span style="color: #006699; font-weight: bold;">function</span><span style="color: #118811;">&#40;</span><span style="color: #118811;">&#41;</span> <span style="color: #118811;">&#123;</span>
   $<span style="color: #118811;">&#40;</span><span style="color: #3366CC;">'a.ccm-block-likes-this-link-list'</span><span style="color: #118811;">&#41;</span>.<span style="color: #996699;">each</span><span style="color: #118811;">&#40;</span><span style="color: #006699; font-weight: bold;">function</span><span style="color: #118811;">&#40;</span><span style="color: #118811;">&#41;</span> <span style="color: #118811;">&#123;</span>
      $<span style="color: #118811;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #118811;">&#41;</span>.<span style="color: #996699;">unbind</span><span style="color: #118811;">&#40;</span><span style="color: #118811;">&#41;</span><span style="color: #339933;">;</span>
      $<span style="color: #118811;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #118811;">&#41;</span>.<span style="color: #996699;">click</span><span style="color: #118811;">&#40;</span><span style="color: #006699; font-weight: bold;">function</span><span style="color: #118811;">&#40;</span><span style="color: #118811;">&#41;</span> <span style="color: #118811;">&#123;</span>
         <span style="color: #006699; font-weight: bold;">var</span> url <span style="color: #339933;">=</span> $<span style="color: #118811;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #118811;">&#41;</span>.<span style="color: #996699;">attr</span><span style="color: #118811;">&#40;</span><span style="color: #3366CC;">'href'</span><span style="color: #118811;">&#41;</span><span style="color: #339933;">;</span>
         jQuery.<span style="color: #996699;">fn</span>.<span style="color: #996699;">dialog</span>.<span style="color: #000066;">open</span><span style="color: #118811;">&#40;</span><span style="color: #118811;">&#123;</span>
            href<span style="color: #339933;">:</span> url<span style="color: #339933;">,</span>
            modal<span style="color: #339933;">:</span> <span style="color: #006699; font-weight: bold;">false</span><span style="color: #339933;">,</span>
            title<span style="color: #339933;">:</span> $<span style="color: #118811;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #118811;">&#41;</span>.<span style="color: #996699;">attr</span><span style="color: #118811;">&#40;</span><span style="color: #3366CC;">'title'</span><span style="color: #118811;">&#41;</span>
         <span style="color: #118811;">&#125;</span><span style="color: #118811;">&#41;</span><span style="color: #339933;">;</span>      
         <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #006699; font-weight: bold;">false</span><span style="color: #339933;">;</span>
      <span style="color: #118811;">&#125;</span><span style="color: #118811;">&#41;</span><span style="color: #339933;">;</span>
   <span style="color: #118811;">&#125;</span><span style="color: #118811;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #118811;">&#125;</span>
&nbsp;
$<span style="color: #118811;">&#40;</span><span style="color: #006699; font-weight: bold;">function</span><span style="color: #118811;">&#40;</span><span style="color: #118811;">&#41;</span> <span style="color: #118811;">&#123;</span>
   $<span style="color: #118811;">&#40;</span><span style="color: #3366CC;">'a.ccm-block-likes-this-link'</span><span style="color: #118811;">&#41;</span>.<span style="color: #996699;">each</span><span style="color: #118811;">&#40;</span><span style="color: #006699; font-weight: bold;">function</span><span style="color: #118811;">&#40;</span><span style="color: #118811;">&#41;</span> <span style="color: #118811;">&#123;</span>
      $<span style="color: #118811;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #118811;">&#41;</span>.<span style="color: #996699;">click</span><span style="color: #118811;">&#40;</span><span style="color: #006699; font-weight: bold;">function</span><span style="color: #118811;">&#40;</span><span style="color: #118811;">&#41;</span> <span style="color: #118811;">&#123;</span>       
         <span style="color: #006699; font-weight: bold;">var</span> url <span style="color: #339933;">=</span> $<span style="color: #118811;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #118811;">&#41;</span>.<span style="color: #996699;">attr</span><span style="color: #118811;">&#40;</span><span style="color: #3366CC;">'href'</span><span style="color: #118811;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #3366CC;">'&amp;ajax=1'</span><span style="color: #339933;">;</span>
         <span style="color: #006699; font-weight: bold;">var</span> elem <span style="color: #339933;">=</span> $<span style="color: #118811;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #118811;">&#41;</span>.<span style="color: #996699;">parent</span><span style="color: #118811;">&#40;</span><span style="color: #118811;">&#41;</span><span style="color: #339933;">;</span>
         $.<span style="color: #996699;">get</span><span style="color: #118811;">&#40;</span>url<span style="color: #339933;">,</span> <span style="color: #006699; font-weight: bold;">function</span><span style="color: #118811;">&#40;</span>r<span style="color: #118811;">&#41;</span> <span style="color: #118811;">&#123;</span>
            $<span style="color: #118811;">&#40;</span><span style="color: #3366CC;">'div.ccm-block-likes-this-wrapper'</span><span style="color: #118811;">&#41;</span>.<span style="color: #996699;">before</span><span style="color: #118811;">&#40;</span>r<span style="color: #118811;">&#41;</span>.<span style="color: #996699;">remove</span><span style="color: #118811;">&#40;</span><span style="color: #118811;">&#41;</span><span style="color: #339933;">;</span>
            $<span style="color: #118811;">&#40;</span><span style="color: #3366CC;">'div.ccm-block-likes-this-wrapper'</span><span style="color: #118811;">&#41;</span>.<span style="color: #996699;">effect</span><span style="color: #118811;">&#40;</span><span style="color: #3366CC;">&quot;highlight&quot;</span><span style="color: #339933;">,</span> <span style="color: #118811;">&#123;</span><span style="color: #118811;">&#125;</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">800</span><span style="color: #118811;">&#41;</span><span style="color: #339933;">;</span>
            ccm_blockLikesThisSetupList<span style="color: #118811;">&#40;</span><span style="color: #118811;">&#41;</span><span style="color: #339933;">;</span>
         <span style="color: #118811;">&#125;</span><span style="color: #118811;">&#41;</span><span style="color: #339933;">;</span>         
         <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #006699; font-weight: bold;">false</span><span style="color: #339933;">;</span>
      <span style="color: #118811;">&#125;</span><span style="color: #118811;">&#41;</span><span style="color: #339933;">;</span>
   <span style="color: #118811;">&#125;</span><span style="color: #118811;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
   ccm_blockLikesThisSetupList<span style="color: #118811;">&#40;</span><span style="color: #118811;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #118811;">&#125;</span><span style="color: #118811;">&#41;</span><span style="color: #339933;">;</span></pre></div><p>There is one function defined, and one block of code that automatically runs whenever this block is included in a page. The ccm_blockLikesThisSetupList function locates all links on the page with the ccm-block-likes-this-link class, and finds their URL, and loads them into a concrete5 dialog box. This uses the tools script referenced in the view template.</p>

<p>The automatically loaded event looks for all links with the class ccm-block-likes-this-link, and finds its URL. It appends &amp;ajax=1 to the end of the link, which is then used in the action&#95;like() function to separate those requests called through or AJAX or simply through a POST, and then uses jQuery's $.get() function to submit to the action<em>like() method defined in controller.php. Then the HTML rendered by the action</em>like() function is inserted into the page, allowing for an instant in-page update of the block itself. Finally, jQuery's highlight effect is used to inform the user that something has changed successfully when they say that they "like" a page.</p>

<h2>Learn More</h2>

<p>This is a quick introduction to using jQuery and JavaScript with concrete5 on the front-end, but hopefully it should pique your interest and help you start understanding what's possible with such a combination. Here are some links to further sites of interest</p>

<p><a href="http://www.jquery.com">http://www.jquery.com</a></p>

<p><a href="http://www.jqueryui.com">http://www.jqueryui.com</a></p>

<p><a href="http://www.concrete5.org/marketplace/addons/likes-this/">http://www.concrete5.org/marketplace/addons/likes-this/</a></p>

<p>I'll also be happy to answer questions in the comments.</p>
<p><span class="byline">Andrew Embler wonders how many precious, precious bytes were saved by the switch to jQuery.</span></p>				<br/><br/>
				<a href="http://andrewembler.com/concrete5/javascript-jquery-and-concrete5/">Comment on this at andrewembler.com</a>
			  ]]>
			  </description>
			  <pubDate>Thu, 20 May 2010 14:13:00 EDT</pubDate>
			</item>
		
			<item>
			  <title>concrete5 Primer: Auto-Nav Block</title>
			  <link>http://andrewembler.com/concrete5/concrete5-primer-auto-nav-block/</link>
			  <description>
			  <![CDATA[
				<h2><span style="color: #efefef; font-size: 14px; line-height: normal;">The content block was the first concrete block ever created &ndash; but immediately after that came the Auto-Nav, which persists to this day. It makes sense: beyond getting text out there, the web's foremost purpose is linking one page to another, and that's what the Auto-Nav is for. In this primer I'm going to tell you what the Auto-Nav does and what its options mean. Then I'll explore some practical examples, how you can control the way it displays and links pages, and how to theme and extend it.</span></h2>
<h2>Version History of this How-To</h2>
<ul>
<li>1.1 - Fixed the $bt-&gt;render() to $bt-&gt;render('view')</li>
<li>1.0 - Initial version</li>
</ul>
<h2>What Does It Do?</h2>
<p>The Auto-Nav block is designed to create lists of pages on your site. Based on your criteria, it determines where to pull pages from, how many pages to pull, and in what order to place them. Its stock templates display these pages in a simple unordered HTML list.</p>
<h2>Understanding Auto-Nav's Options</h2>
<p>The Auto-Nav block exposes the following options:</p>
<h3>Pages Should Appear</h3>
<p>This option determines the ordering of pages in the Auto-Nav block. The following options are available:</p>
<ul>
<li><strong>In their sitemap order / In reverse sitemap order</strong>&nbsp;<br />This lists all pages in every level of the resulting tree in the same order (or reverse order) that they are listed in the Dashboard sitemap. This is the most flexible option, as site administrators may reorder pages in the sitemap, and have those changes immediately take effect in all Auto-Nav blocks that are ordered by this option.<span>&nbsp;</span></li>
<li><strong>With the most recent first</strong><span> <br /></span>This option lists pages in descending order, with the page that has the greatest public date first. (Note: Public date is the date that the user may change in the Page Properties pane. It is *not* the date that the page was originally added.)&nbsp;</li>
<li><strong>With the earliest first</strong><br />Like the previous option, except pages are displayed in ascending order, starting with the earliest public date.</li>
<li><strong>In alphabetical order / In reverse alphabetical order<br /></strong>Pages are displayed alphabetically (or in reverse alphabetical order) by page name.&nbsp;</li>
</ul>
<h3>Display pages to users even when those users cannot access those pages</h3>
<p>By default, the Auto-Nav block hides any reference to pages that the current site visitor cannot access. This means that a page accessible only to registered users will not appear in an Auto-Nav block for users who are not logged in. This setting will override that behavior.</p>
<h3>Display Pages</h3>
<p>This option determines the first level at which the Auto-Nav begins showing pages.&nbsp;</p>
<ul>
<li><strong>Top</strong><span> <br /></span>The Auto-Nav will begin at the top level of the website. These are the pages directly added beneath the home page (which will automatically be prepended to the results.)</li>
<li><strong>Second Level / Third Level</strong><span> <br /></span>The Auto-Nav will begin at the second or third level of the website. (Note: This only produces results when the page to which the Auto-Nav block is added is at or below the specified level. )</li>
<li><strong>Above</strong><span> <br /></span>The Auto-Nav will begin at the level above the current page.</li>
<li><strong>Current</strong><span> <br /></span>The Auto-Nav will begin at the level of the current page.</li>
<li><strong>Below</strong><span> <br /></span>The Auto-Nav will begin at the level below the current page.<span>&nbsp;</span></li>
<li><strong>Beneath a particular page</strong><span> <br /></span>A sitemap selector widget will allow the administrator to determine where this particular Auto-Nav block starts.</li>
</ul>
<h3>Sub Pages to Display</h3>
<p>This option controls which sub-pages of the current level will be shown.&nbsp;</p>
<ul>
<li><strong>None<br /></strong>Pages at the current level (selected in the "Display Pages" section) will be shown, but no sub-pages beneath any of those pages will be displayed.</li>
<li><strong>Relevant sub-pages<br /></strong>Any pages that lead to the current page will be shown, but no others will be. *Note*: This option is only valid and useful when beginning the Auto-Nav at a level greater than the current page.</li>
<li><strong>Display breadcrumb trail<br /></strong>Only the direct parents of pages that lead to the current page will be shown. (Note: This option is only valid and useful when beginning the Auto-Nav at a level greater than the current page.)</li>
<li><strong>Display all<br /></strong>All sub-pages for all pages shown in the nav will be shown. (Note: The pages will still only be shown for as long as the "Sub-Page Levels" option (see next) is valid &ndash; so make sure that property is set correctly.)</li>
</ul>
<h3>Sub-Page Levels</h3>
<p>For Auto-Nav instances that display sub-pages, this parameter controls how many levels of sub-pages are shown.</p>
<ul>
<li><strong>Display sub pages to current<br /><span style="font-weight: normal;">Displays as many sub-pages as it takes to get to the current page.</span></strong></li>
<li><strong>Display sub pages to current + 1<br /><span style="font-weight: normal;">Displays as many sub-pages as it takes to get to the current page, and then displays the next level of sub-pages beneath the current page.</span></strong></li>
<li><strong>Display all<br /><span style="font-weight: normal;">Displays all sub pages for as long as "Sub Pages to Display" is valid.</span></strong></li>
<li><strong>Display a custom amount<br /><span style="font-weight: normal;">Allows the administrator to set a custom level of sub-pages to display.</span></strong></li>
</ul>
<h2>Auto-Nav's HTML Markup</h2>
<p>The markup created by the regular Auto-Nav is simply an unordered HTML list.</p><div class="ccm-syntax-highlighter">
<pre class="html4strict" style="font-family:monospace;"><span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/ul.html"><span style="color: #FFFFFF; font-weight: bold;">ul</span></a> <span style="color: #6666FF;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;nav&quot;</span>&gt;</span>
   <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/li.html"><span style="color: #FFFFFF; font-weight: bold;">li</span></a> <span style="color: #6666FF;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;nav-path-selected&quot;</span>&gt;&lt;<a href="http://december.com/html/4/element/a.html"><span style="color: #FFFFFF; font-weight: bold;">a</span></a> <span style="color: #6666FF;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;nav-path-selected&quot;</span> <span style="color: #6666FF;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;/&quot;</span>&gt;</span>Home<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/a.html"><span style="color: #FFFFFF; font-weight: bold;">a</span></a>&gt;&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/li.html"><span style="color: #FFFFFF; font-weight: bold;">li</span></a>&gt;</span>
   <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/li.html"><span style="color: #FFFFFF; font-weight: bold;">li</span></a>&gt;&lt;<a href="http://december.com/html/4/element/a.html"><span style="color: #FFFFFF; font-weight: bold;">a</span></a> <span style="color: #6666FF;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;/index.php/about/&quot;</span>&gt;</span>About<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/a.html"><span style="color: #FFFFFF; font-weight: bold;">a</span></a>&gt;</span>
   <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/ul.html"><span style="color: #FFFFFF; font-weight: bold;">ul</span></a>&gt;</span>
      <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/li.html"><span style="color: #FFFFFF; font-weight: bold;">li</span></a>&gt;&lt;<a href="http://december.com/html/4/element/a.html"><span style="color: #FFFFFF; font-weight: bold;">a</span></a> <span style="color: #6666FF;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;/index.php/about/press-room/&quot;</span>&gt;</span>Press Room<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/a.html"><span style="color: #FFFFFF; font-weight: bold;">a</span></a>&gt;</span>
      <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/ul.html"><span style="color: #FFFFFF; font-weight: bold;">ul</span></a>&gt;</span>
         <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/li.html"><span style="color: #FFFFFF; font-weight: bold;">li</span></a>&gt;&lt;<a href="http://december.com/html/4/element/a.html"><span style="color: #FFFFFF; font-weight: bold;">a</span></a> <span style="color: #6666FF;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;/index.php/about/press-room/re/&quot;</span>&gt;</span>April 1st, 2010 - 5:27 PM<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/a.html"><span style="color: #FFFFFF; font-weight: bold;">a</span></a>&gt;&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/li.html"><span style="color: #FFFFFF; font-weight: bold;">li</span></a>&gt;</span>
         <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/li.html"><span style="color: #FFFFFF; font-weight: bold;">li</span></a>&gt;&lt;<a href="http://december.com/html/4/element/a.html"><span style="color: #FFFFFF; font-weight: bold;">a</span></a> <span style="color: #6666FF;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;/index.php/about/press-room/white/&quot;</span>&gt;</span>April 8th, 2010 - 12:38 PM<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/a.html"><span style="color: #FFFFFF; font-weight: bold;">a</span></a>&gt;&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/li.html"><span style="color: #FFFFFF; font-weight: bold;">li</span></a>&gt;</span>
      <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/ul.html"><span style="color: #FFFFFF; font-weight: bold;">ul</span></a>&gt;</span>
      <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/li.html"><span style="color: #FFFFFF; font-weight: bold;">li</span></a>&gt;</span>
      <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/li.html"><span style="color: #FFFFFF; font-weight: bold;">li</span></a>&gt;&lt;<a href="http://december.com/html/4/element/a.html"><span style="color: #FFFFFF; font-weight: bold;">a</span></a> <span style="color: #6666FF;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;/index.php/about/guestbook/&quot;</span>&gt;</span>Guestbook<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/a.html"><span style="color: #FFFFFF; font-weight: bold;">a</span></a>&gt;&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/li.html"><span style="color: #FFFFFF; font-weight: bold;">li</span></a>&gt;</span>
      <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/li.html"><span style="color: #FFFFFF; font-weight: bold;">li</span></a>&gt;&lt;<a href="http://december.com/html/4/element/a.html"><span style="color: #FFFFFF; font-weight: bold;">a</span></a> <span style="color: #6666FF;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;/index.php/about/cool-page/&quot;</span>&gt;</span>Cool Page<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/a.html"><span style="color: #FFFFFF; font-weight: bold;">a</span></a>&gt;&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/li.html"><span style="color: #FFFFFF; font-weight: bold;">li</span></a>&gt;</span>
   <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/ul.html"><span style="color: #FFFFFF; font-weight: bold;">ul</span></a>&gt;</span>
   <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/li.html"><span style="color: #FFFFFF; font-weight: bold;">li</span></a>&gt;</span>
   <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/li.html"><span style="color: #FFFFFF; font-weight: bold;">li</span></a>&gt;&lt;<a href="http://december.com/html/4/element/a.html"><span style="color: #FFFFFF; font-weight: bold;">a</span></a> <span style="color: #6666FF;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;/index.php/search/&quot;</span>&gt;</span>Search<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/a.html"><span style="color: #FFFFFF; font-weight: bold;">a</span></a>&gt;&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/li.html"><span style="color: #FFFFFF; font-weight: bold;">li</span></a>&gt;</span>
   <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/li.html"><span style="color: #FFFFFF; font-weight: bold;">li</span></a>&gt;&lt;<a href="http://december.com/html/4/element/a.html"><span style="color: #FFFFFF; font-weight: bold;">a</span></a> <span style="color: #6666FF;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;/index.php/awesome-test/&quot;</span>&gt;</span>Awesome Test<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/a.html"><span style="color: #FFFFFF; font-weight: bold;">a</span></a>&gt;&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/li.html"><span style="color: #FFFFFF; font-weight: bold;">li</span></a>&gt;</span>
   <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/li.html"><span style="color: #FFFFFF; font-weight: bold;">li</span></a> <span style="color: #6666FF;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;nav-selected nav-path-selected&quot;</span>&gt;</span>
      <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/a.html"><span style="color: #FFFFFF; font-weight: bold;">a</span></a> <span style="color: #6666FF;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;nav-selected nav-path-selected&quot;</span> <span style="color: #6666FF;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;/index.php/sitemap/&quot;</span>&gt;</span>Sitemap<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/a.html"><span style="color: #FFFFFF; font-weight: bold;">a</span></a>&gt;</span>
   <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/li.html"><span style="color: #FFFFFF; font-weight: bold;">li</span></a>&gt;</span>
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/ul.html"><span style="color: #FFFFFF; font-weight: bold;">ul</span></a>&gt;</span></pre></div><p>A few classes of note:</p>
<ul>
<li><strong>ul.nav</strong><br /> The outer UL tag gets the "nav" class in the stock Auto-Nav template. </li>
<li><strong>ul.nav-header</strong><br /> The outer UL tag in the "Header Menu" custom template. </li>
<li><strong>li.nav-path-selected, a.nav-path-selected</strong><br /> These classes apply to any nodes that contain the current page, from the top on down. </li>
<li><strong>li.nav-selected, a.nav-selected</strong><br /> These classes apply to the LI and A tags for the currently active page. </li>
</ul>
<h2>Practical Examples</h2>
<p>Here are some common use cases for the Auto-Nav block.</p>
<h3>Header Menu</h3>
<p>The goal - to list all pages at the top level of a website, in sitemap order, toward the top of a page.</p>
<p>Here is the current setup of the example site in question:</p>
<div class="main-image">
	<div><img src="/files/9612/7370/6308/Picture 1.png" class="footer-image" width="393" height="190" alt="footer image" /></div>


</div><p>That means we'll want our navigation to list About, Search and Awesome Test, in our Header Nav area. To do this, setup the Auto-Nav block in this way:</p>
<div class="main-image">
	<div><img src="/files/7912/7370/6307/Picture 2.png" class="footer-image" width="503" height="442" alt="footer image" /></div>


</div><p>That creates the proper menu, but it is styled incorrectly (since our styles are setup to use the "nav-header" unordered list class, and the Auto-Nav typically outputs a list with the class "nav."&nbsp;</p>
<div class="main-image">
	<div><img src="/files/4512/7370/6292/Picture 3.png" class="footer-image" width="317" height="233" alt="footer image" /></div>


</div><p>Fortunately, the Header Nav custom Auto-Nav template is setup to output a list with the proper classes, so we change the custom template:</p>
<div class="main-image">
	<div><img src="/files/9512/7370/6301/Picture 4.png" class="footer-image" width="371" height="227" alt="footer image" /></div>


</div><p>And we get nice results:</p>
<div class="main-image">
	<div><img src="/files/3112/7370/6325/Picture 5.png" class="footer-image" width="376" height="102" alt="footer image" /></div>


</div><h3>Sidebar Sectional Navigation</h3>
<p>If we have an "About" page at the top level of our site, and a large amount of content beneath it, it makes sense that we might want to list all pages within the About section on pages beneath it. This is what I refer to as Sectional Navigation. Within this section, we want to show all pages and sub-pages to whatever current page we're on.</p>
<p>Here is an example of some sectional navigation on concrete5.org:</p><div class="main-image">
<img border="0" class="ccm-image-block" alt="" src="/files/cache/d102c3a0bbf115d84dc475b427c7385b.png"  width="778" height="505" /></div><p>This is a screenshot taken within our About section. Check out the right sidebar. Here we display all sub-pages of our current section (About), all the way on down to whatever current page we happen to be viewing ("concrete5 Adds eCommerce.") Here's how we accomplish that:</p>
<div class="main-image">
	<div><img src="/files/3212/7370/6327/Picture 7.png" class="footer-image" width="591" height="486" alt="footer image" /></div>


</div><h3>Breadcrumb</h3>
<p>That same page also contains a breadcrumb navigation element, which the Auto-Nav takes care of. We've wanted to setup the breadcrumb so that it displays parent pages down to the current page, but not the current page itself.&nbsp;</p><div class="main-image">
<img border="0" class="ccm-image-block" alt="" src="/files/cache/8bfdd5f26d940f71b00149de8a8a33c5.png"  width="778" height="107" /></div><p>For that, we start the pages at the top level, display only breadcrumb sub-pages, and display sub-pages to the current page.&nbsp;</p>
<div class="main-image">
	<div><img src="/files/4212/7370/6323/Picture 9.png" class="footer-image" width="553" height="462" alt="footer image" /></div>


</div><p>There is a problem, however: that option would *also* display the current page, which is something we don't want to do. Additionally, it would display the items in an unordered list, which &ndash; unless we have special styling setup &ndash; doesn't look good with a breadcrumb.</p><div class="main-image">
<img border="0" class="ccm-image-block" alt="" src="/files/cache/5933d4fdb8fab3b455546a6d7c4ea228.png"  width="650" height="132" /></div><p>The key, then, is to use the included "Breadcrumb" custom template. This will do two things:</p>
<ol>
<li>Ensure that the current page is *not* displayed in the navigation.</li>
<li>Print out pages in a row, with pipe signs between them:</li>
</ol>
<div class="main-image">
	<div><img src="/files/7612/7370/6297/Picture 11.png" class="footer-image" width="447" height="243" alt="footer image" /></div>


</div><div class="main-image">
<img border="0" class="ccm-image-block" alt="" src="/files/cache/eb00f1cf06542f93a23a386ccd70589c.png"  width="600" height="81" /></div><h3>Full Sitemap</h3>
<p>The Auto-Nav block is frequently used to print out the sitemap for an entire site.&nbsp;</p><div class="main-image">
<img border="0" class="ccm-image-block" alt="" src="/files/cache/8edc1d6c5a37c288dc67d77a262a1fb5.png"  width="778" height="436" /></div><p>Just display pages at the top level, and all sub-pages/sub-page levels beneath:</p>
<div class="main-image">
	<div><img src="/files/2112/7370/6310/Picture 13.png" class="footer-image" width="534" height="463" alt="footer image" /></div>


</div><h3>Alphabetical Reference</h3>
<p>The following example will show one level of sub-pages directly beneath the current page, sorted alphabetically.&nbsp;</p>
<div class="main-image">
	<div><img src="/files/6012/7370/6296/Picture 15.png" class="footer-image" width="558" height="480" alt="footer image" /></div>


</div><p>The result:</p>
<div class="main-image">
	<div><img src="/files/6512/7370/6214/Picture 16.png" class="footer-image" width="609" height="265" alt="footer image" /></div>


</div><h3>News Archive</h3>
<p>Let's say we want to show all pages beneath the Press Room section of our website, sorted with the most recent first.</p>
<div class="main-image">
	<div><img src="/files/1912/7370/6290/Picture 17.png" class="footer-image" width="546" height="462" alt="footer image" /></div>


</div><p>The Result:</p>
<div class="main-image">
	<div><img src="/files/2912/7370/6313/Picture 18.png" class="footer-image" width="658" height="242" alt="footer image" /></div>


</div><p>Since this block is pulling pages beneath a particular sub-page, it can be added to any area of the site.</p><h2>Page Attributes</h2>
<p>There are two page attributes which affect the behavior of the Auto-Nav. In general, these are all boolean/checkbox types, and are applied directly to the pages you wish to affect (whether from the page in question, or from the Dashboard Sitemap)</p>
<ul>
<li><strong>Handle:&nbsp;exclude_nav<br /></strong>When applied to a page, this page will not appear in the Auto-Nav block view template. It will still be passed to the template, but it will be skipped over.<br /><br /></li>
<li><strong>Handle:&nbsp;&nbsp;replace_link_with_first_in_nav</strong><br />When created and applied to a page, if this page is ever encountered in an Auto-Nav view template, the link to the page will be replaced with a link to the first child of the page in question. This is useful for creating pages where you wish to link <strong>into</strong>&nbsp;a section of a site, instead of being forced to create landing pages for your content.&nbsp;</li>
</ul><h2>Auto-Nav's Block Item Class</h2>
<p>At its core, the Auto-Nav block retrieves an array of concrete5 Page objects and makes them available to various templates to display. Each page object is wrapped in the Auto-Nav's custom AutonavBlockItem class, which adds a few extra methods, including the retrieval of which level the current navigation item exists, and the number of pages beneath it. These methods are</p>
<ul>
<li><strong>AutonavBlockItem::getName()</strong><br /> Returns the name of the page.</li>
<li><strong>AutonavBlockItem::getDescription()</strong><br /> Returns the page's short description.</li>
<li><strong>AutonavBlockItem::getURL()</strong><br /> Returns the URL of the page.</li>
<li><strong>AutonavBlockItem::getLevel()</strong><br /> Gets the current level of the navigation item within the nav itself.</li>
<li><strong>AutonavBlockItem::hasChildren()</strong><br /> Returns true if the navigation item has children within this navigation (note: currently this will return true even if the item does not display children since they have their exclude_from_nav flags set (see below.))</li>
</ul>
<p>(Note: Some of these methods did not work properly prior to concrete 5.4.0.6.)</p>
<p>The array of these AutonavBlockItem objects is made available through $controller-&gt;generateNav() in the Auto-Nav view template.</p>
<h2>Embedding the Auto-Nav Directly into Templates</h2>
<p>As with most other concrete5 blocks, the Auto-Nav can be embedded directly into your theme's templates. This can be useful when you'd like to force a header nav or a sidebar nav into your site without having to worry about adding it to every page. Before we switched to using the Superfish Menu, here's how we embedded the header into concrete5.org</p><div class="ccm-syntax-highlighter">
<pre class="php" style="font-family:monospace;"><span style="color: #6666FF;">$bt</span> <span style="color: #339933;">=</span> BlockType<span style="color: #339933;">::</span><span style="color: #00FF00;">getByHandle</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'autonav'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #6666FF;">$bt</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">controller</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">displayPages</span> <span style="color: #339933;">=</span> <span style="color: #4444ff;">'top'</span><span style="color: #339933;">;</span>
<span style="color: #6666FF;">$bt</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">controller</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">orderBy</span> <span style="color: #339933;">=</span> <span style="color: #4444ff;">'display_asc'</span><span style="color: #339933;">;</span>
<span style="color: #6666FF;">$bt</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">render</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'templates/header_menu'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div><p>And here's another example, embedding the breadcrumb menu:</p><div class="ccm-syntax-highlighter">
<pre class="php" style="font-family:monospace;"><span style="color: #6666FF;">$bt</span> <span style="color: #339933;">=</span> BlockType<span style="color: #339933;">::</span><span style="color: #00FF00;">getByHandle</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'autonav'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #6666FF;">$bt</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">controller</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">displayPages</span> <span style="color: #339933;">=</span> <span style="color: #4444ff;">'top_level'</span><span style="color: #339933;">;</span>
<span style="color: #6666FF;">$bt</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">controller</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">orderBy</span> <span style="color: #339933;">=</span> <span style="color: #4444ff;">'display_asc'</span><span style="color: #339933;">;</span>
<span style="color: #6666FF;">$bt</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">controller</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">displaySubPages</span> <span style="color: #339933;">=</span> <span style="color: #4444ff;">'relevant_breadcrumb'</span><span style="color: #339933;">;</span> 
<span style="color: #6666FF;">$bt</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">controller</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">displaySubPageLevels</span> <span style="color: #339933;">=</span> <span style="color: #4444ff;">'enough'</span><span style="color: #339933;">;</span>
<span style="color: #6666FF;">$bt</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">render</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'templates/breadcrumb'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> </pre></div><p>To use the stock view (rather than a custom template), just call render() with no arguments:</p><div class="ccm-syntax-highlighter">
<pre class="php" style="font-family:monospace;"><span style="color: #6666FF;">$bt</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">render</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'view'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> </pre></div><h2>Further Experimentation</h2>
<p>For those who want to experiment further with the Auto-Nav, I recommend doing the following.</p>
<ol>
<li>Create this file in your local blocks directory<br /><br />
<div style="padding-left: 30px;">blocks/autonav/templates/testing.php</div>
</li>
<li>Open concrete/blocks/autonav/view.php and copy its contents into the file above.</li>
<li>Add a new Auto-Nav block somewhere on your site, and apply the "Testing" custom template to it.</li>
<li>Hack away at testing.php and at the Auto-Nav block options for as long as you'd like!</li>
</ol>
<p>Seriously, that's probably the best advice I can give: this how-to should give you some background on the purpose and functionality of the Auto-Nav, but real experimentation is probably the only way you're going to get comfortable with it. But while it may take a little while to become familiar with, it will undoubtedly prove useful (after all, it's been there since the very beginning.)</p>
<p><span class="byline">Andrew Embler hopes your next sitemap can build itself.</span></p>				<br/><br/>
				<a href="http://andrewembler.com/concrete5/concrete5-primer-auto-nav-block/">Comment on this at andrewembler.com</a>
			  ]]>
			  </description>
			  <pubDate>Wed, 12 May 2010 21:59:00 EDT</pubDate>
			</item>
		
			<item>
			  <title>Build a Single-Page Powered Editing Interface for concrete5 Pages</title>
			  <link>http://andrewembler.com/concrete5/build-a-single-page-powered-editing-interface-for-concrete5/</link>
			  <description>
			  <![CDATA[
				<p><span class="byline">Learn how to build a simple FAQ system from scratch, including a single page interface for listing and sorting entries, a single page interface for editing entries, a page list template for displaying them.</span></p>
<p>One of concrete5's greatest strengths is the way that its pages support in-context editing. This mode is not an afterthought or a bolted-on feature; it is the way that concrete5 has always worked. Site administrators need only visit a particular page, put the page in edit mode, and click and edit to make changes to a page. Changes are made instantaneously. No administrative panel needs to be understood out of the gate.</p>
<p>However, there are times when this approach is not the best way to manage content. For example, when adding pages&nbsp;concrete5 presents itself much like a blank canvas. While this freedom is powerful, certain applications require a bit more structure, and concrete5's approach may take longer than necessary. The solution isn't to ignore concrete5's built-in objects like pages, attributes or page types, but instead to craft a custom interface for creating these pages in a more efficient manner. This tutorial will show you how to do just that.</p>
<h2>Required Version</h2>
<p>While this tutorial uses screenshots from concrete 5.4.0.5, its approach should work on concrete 5.3.3.1 and above.</p>
<h2>Download Code</h2>
<p>If you want to skip the tutorial and download the code, you can do so from here.</p>
<p style="padding-left: 30px;"><a href="http://www.concrete5.org/files/2012/7309/4756/example_faq_code.zip ">http://www.concrete5.org/files/2012/7309/4756/example_faq_code.zip</a>&nbsp;(10 KB)</p>
<p>This code is also available as a free add-on in our marketplace.</p>
<p style="padding-left: 30px;"><a href="http://www.concrete5.org/marketplace/addons/example-faq/">http://www.concrete5.org/marketplace/addons/example-faq/</a></p>
<h2>Components</h2>
<p>I'm going to show you how to build a simple FAQ system for your website. Here are the components of it:</p>
<h3>Multiple FAQ Sections</h3>
<p>Using a custom attribute, administrators can specify different sections of their site as possible FAQ Entry holders.&nbsp;</p>
<div class="main-image">
	<div><img src="/files/1712/7309/6091/Picture 1.png" class="footer-image" width="418" height="259" alt="footer image" /></div>


</div><h3>Dashboard Add/Edit Interface</h3>
<p>Administrators will be able to use a simplified dashboard interface to add FAQ Entries beneath these categories.&nbsp;</p><div class="main-image">
<img border="0" class="ccm-image-block" alt="" src="/files/cache/e1122f75583d3cc922cd5e5662a7b2f3.png"  width="500" height="375" /></div><p>These FAQ Entries can be pages of any type, leaving their presentation very flexible. Since they are pages, they can be returned in search results and have additional blocks attached to them.</p>
<div class="main-image">
	<div><img src="/files/9412/7309/6109/Picture 3.png" class="footer-image" width="358" height="360" alt="footer image" /></div>


</div><h3>Dashboard List/Filter Interface</h3>
<p>The dashboard single page interface lists all FAQ entries added to the site, and allows filtering by section:</p><div class="main-image">
<img border="0" class="ccm-image-block" alt="" src="/files/cache/e5abb8ce2524acc5a65d978e9d951b2e.png"  width="500" height="193" /></div><h3>Custom Page List</h3>
<p>A custom page list template allows administrators to display these pages in an attractive, FAQ-esque way.</p>
<div class="main-image">
	<div><img src="/files/2812/7309/6105/picture 5.png" class="footer-image" width="514" height="507" alt="footer image" /></div>


</div><h2>Specifying FAQ Sections</h2>
<p>The Example FAQ code detailed here uses a custom attribute to determine where FAQs can be added to a particular website. You'll need to create this attribute, then set it to true at one or more pages in your site. Then, those pages will show up as places where FAQ entries may be added.</p>
<h3>Create and Assign Required Custom Attributes</h3>
<p>From Dashboard &gt; Pages &amp; Themes &gt; Attributes, create a checkbox attribute with the handle "faq_section"</p><div class="main-image">
<img border="0" class="ccm-image-block" alt="" src="/files/cache/21b33eae566c5b7507bbb5f0bd9662c4.png"  width="500" height="178" /></div><p>Now, create a select element with the handle faq_tags. (Note: this attribute isn't used in any of our custom views - it is simply here to detail how you can include custom attribute forms in your single pages.)</p><div class="main-image">
<img border="0" class="ccm-image-block" alt="" src="/files/cache/2bd766d675a5f9271b2288f976970863.png"  width="500" height="228" /></div><p>Finally, assign the FAQ Section attribute to at least one page in your site.</p>
<div class="main-image">
	<div><img src="/files/1712/7309/6091/Picture 1.png" class="footer-image" width="418" height="259" alt="footer image" /></div>


</div><h2>Creating the Single Page</h2>
<p>Our dashboard interface for listing and editing FAQ entries will be found at</p>
<p style="padding-left: 30px;">http://www.yoursite.com/index.php/dashboard/example_faq/</p>
<p>The first thing we'll want to do is register this URL with concrete5. To do so, first we create code files for the single page's view layer, and its controller. These files can be empty at first &ndash; they just need to exist.</p>
<h3>Create the View Layer</h3>
<p>Within your site's single_pages/ directory, create a folder named "dashboard," then a folder named "example_faq", and within it, place an empty view.php file.</p>
<div class="main-image">
	<div><img src="/files/2612/7309/6090/Picture 6.png" class="footer-image" width="679" height="165" alt="footer image" /></div>


</div><h3>Create the Controller</h3>
<p>Within your site's controllers/ directory, create the same structure, but instead of creating a file named view.php, name it controller.php</p>
<div class="main-image">
	<div><img src="/files/1312/7309/6101/picture 7.png" class="footer-image" width="677" height="114" alt="footer image" /></div>


</div><h3>Add Controller Code to Your Controller</h3>
<p>Some code needs to be added to your controller file before we can proceed with the installation of your new single page. Add this code to your empty controller file:</p><div class="ccm-syntax-highlighter">
<pre class="php" style="font-family:monospace;"><span style="color: #999999; font-weight: bold;">&lt;?php</span>
    <span style="color: #999999; font-weight: bold;">class</span> DashboardExampleFaqController <span style="color: #999999; font-weight: bold;">extends</span> Controller <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #009900;">&#125;</span></pre></div><p>This code simply tells concrete5 the name of the controller class. It must be named and capitalized this way! (Note: capitalization is important.) Simply take the path of the directories you're using, replace any underscores with additional punctuation, and add Controller on the end of the class. Make sure it your class extends the Controller class.</p><h3>Install the Single Page</h3>
<p>Now that the code files are in their proper place, you need to register the single page with concrete5 before it shows up in the dashboard. This is done in the Dashboard &gt; Pages &amp; Themes &gt; Single Pages area of your dashboard. Simply scroll to the bottom and enter the path to your new single page in the form field:</p>
<div class="main-image">
	<div><img src="/files/1412/7309/6100/picture 8.png" class="footer-image" width="473" height="223" alt="footer image" /></div>


</div><p>Submit the form, and your page should show up in the dashboard in the left menu. Click on it, and you should have a blank page in the dashboard available to you.</p><div class="main-image">
<img border="0" class="ccm-image-block" alt="" src="/files/cache/7d51e45ea4b486366d15fd6e101859aa.png"  width="500" height="354" /></div><h2>Controller Code</h2>
<p>Now it's time to populate the DashboardExampleFaqController class with real code.</p>
<h3>Setup</h3>
<p>Now that you have blank controller and view files, it's time to add code to them, so that they can do things like retrieve pages, list pages, and add pages. Add the following methods to the controller.php file:</p><div class="ccm-syntax-highlighter">
<pre class="php" style="font-family:monospace;">    <span style="color: #999999; font-weight: bold;">public</span> <span style="color: #6666FF;">$helpers</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'html'</span><span style="color: #339933;">,</span><span style="color: #4444ff;">'form'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div><p>This declaration loads the Html and Form helpers found in concrete/helpers/, and sets them in the view.php file. This means that helper objects named $html and $form, respectively, will be available. (This is simply a shorthand way of specifying which helpers are available in a controller's associated view.)</p><div class="ccm-syntax-highlighter">
<pre class="php" style="font-family:monospace;">    <span style="color: #999999; font-weight: bold;">public</span> <span style="color: #999999; font-weight: bold;">function</span> on_start<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        Loader<span style="color: #339933;">::</span><span style="color: #00FF00;">model</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'page_list'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">error</span> <span style="color: #339933;">=</span> Loader<span style="color: #339933;">::</span><span style="color: #00FF00;">helper</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'validation/error'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;</pre></div><p>The on_start() method fires automatically every time the associated controller is run. (Note: this is slightly different than the __construct() method - on_start() will only ever be run when the page is actually rendered as a view. Here we load the PageList class, and setup ValidationErrorHelper object within our controller.</p>
<h3>View</h3><div class="ccm-syntax-highlighter">
<pre class="php" style="font-family:monospace;">    <span style="color: #999999; font-weight: bold;">public</span> <span style="color: #999999; font-weight: bold;">function</span> view<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">loadFAQSections</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #6666FF;">$faqList</span> <span style="color: #339933;">=</span> <span style="color: #999999; font-weight: bold;">new</span> PageList<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #6666FF;">$faqList</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">sortBy</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'cDateAdded'</span><span style="color: #339933;">,</span> <span style="color: #4444ff;">'desc'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><a href="http://www.php.net/isset"><span style="color: #990000;">isset</span></a><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$_GET</span><span style="color: #009900;">&#91;</span><span style="color: #4444ff;">'cParentID'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #6666FF;">$_GET</span><span style="color: #009900;">&#91;</span><span style="color: #4444ff;">'cParentID'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">&gt;</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #6666FF;">$faqList</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">filterByParentID</span><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$_GET</span><span style="color: #009900;">&#91;</span><span style="color: #4444ff;">'cParentID'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #6666FF;">$sections</span> <span style="color: #339933;">=</span> <span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">get</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'sections'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #6666FF;">$keys</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/array_keys"><span style="color: #990000;">array_keys</span></a><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$sections</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #6666FF;">$keys</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #339933;">-</span><span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span>
            <span style="color: #6666FF;">$faqList</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">filterByParentID</span><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$keys</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">set</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'faqList'</span><span style="color: #339933;">,</span> <span style="color: #6666FF;">$faqList</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">set</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'faqResults'</span><span style="color: #339933;">,</span> <span style="color: #6666FF;">$faqList</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">getPage</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    protected <span style="color: #999999; font-weight: bold;">function</span> loadFAQSections<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #6666FF;">$faqSectionList</span> <span style="color: #339933;">=</span> <span style="color: #999999; font-weight: bold;">new</span> PageList<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #6666FF;">$faqSectionList</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">filterByFaqSection</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #6666FF;">$faqSectionList</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">sortBy</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'cvName'</span><span style="color: #339933;">,</span> <span style="color: #4444ff;">'asc'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #6666FF;">$tmpSections</span> <span style="color: #339933;">=</span> <span style="color: #6666FF;">$faqSectionList</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">get</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #6666FF;">$sections</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$tmpSections</span> <span style="color: #b1b100;">as</span> <span style="color: #6666FF;">$_c</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #6666FF;">$sections</span><span style="color: #009900;">&#91;</span><span style="color: #6666FF;">$_c</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">getCollectionID</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #6666FF;">$_c</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">getCollectionName</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">set</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'sections'</span><span style="color: #339933;">,</span> <span style="color: #6666FF;">$sections</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span></pre></div><p>The first two methods we include in our controller are responsible for loading data within the view layer. The Controller::view() method is automatically run when a particular single page is viewed. That means the moment we come to index.php/dashboard/example_faq/, our view() method is run. First, it runs the loadFAQSections() method, which sets a $sections array filled with all pages that have been marked as FAQ Sections (using the faq_section attribute detailed earlier.) Then, it creates a new PageList object that retrieves all pages within any of these sections, and sets up paging on it. Finally, the list of pages and the PageList object itself are set within the view using Controller::set(), so those variables will be accessible within view.php</p>
<h3>Edit</h3>
<p>The edit() function will be fired when we edit a particular FAQ entry using this single page interface (e.g. http://www.yoursite.com/index.php/dashboard/example_faq/edit/200)</p><div class="ccm-syntax-highlighter">
<pre class="php" style="font-family:monospace;">    <span style="color: #999999; font-weight: bold;">public</span> <span style="color: #999999; font-weight: bold;">function</span> edit<span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$cID</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">setupForm</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #6666FF;">$faq</span> <span style="color: #339933;">=</span> Page<span style="color: #339933;">::</span><span style="color: #00FF00;">getByID</span><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$cID</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #6666FF;">$sections</span> <span style="color: #339933;">=</span> <span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">get</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'sections'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><a href="http://www.php.net/in_array"><span style="color: #990000;">in_array</span></a><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$faq</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">getCollectionParentID</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <a href="http://www.php.net/array_keys"><span style="color: #990000;">array_keys</span></a><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$sections</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">set</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'faq'</span><span style="color: #339933;">,</span> <span style="color: #6666FF;">$faq</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>    
        <span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">redirect</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'/dashboard/example_faq/'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    protected <span style="color: #999999; font-weight: bold;">function</span> setupForm<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">loadFAQSections</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        Loader<span style="color: #339933;">::</span><span style="color: #00FF00;">model</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">&quot;collection_types&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #6666FF;">$ctArray</span> <span style="color: #339933;">=</span> CollectionType<span style="color: #339933;">::</span><span style="color: #00FF00;">getList</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">''</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #6666FF;">$pageTypes</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$ctArray</span> <span style="color: #b1b100;">as</span> <span style="color: #6666FF;">$ct</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #6666FF;">$pageTypes</span><span style="color: #009900;">&#91;</span><span style="color: #6666FF;">$ct</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">getCollectionTypeID</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #6666FF;">$ct</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">getCollectionTypeName</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>      
        <span style="color: #009900;">&#125;</span>
        <span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">set</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'pageTypes'</span><span style="color: #339933;">,</span> <span style="color: #6666FF;">$pageTypes</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">addHeaderItem</span><span style="color: #009900;">&#40;</span>Loader<span style="color: #339933;">::</span><span style="color: #00FF00;">helper</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'html'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">javascript</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'tiny_mce/tiny_mce.js'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span></pre></div><p>First, we run setupForm(), which takes care of loading available FAQ sections, as well as getting an array of all page types installed on a site, and adding our rich text editor JavaScript. Then, we get information about the requested FAQ Entry, validate that it appears in the proper location, and set the $faq object in the view layer.</p>
<p><span style="color: #fcd63c; font-size: 18px; line-height: 22px;">Add/Update</span></p>
<p>The add() function is fired when the add interface is displayed and/or submitted (e.g. http://www.yoursite.com/index.php/dashboard/example_faq/add/).&nbsp;</p><div class="ccm-syntax-highlighter">
<pre class="php" style="font-family:monospace;">    <span style="color: #999999; font-weight: bold;">public</span> <span style="color: #999999; font-weight: bold;">function</span> add<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">setupForm</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">isPost</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">validate</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">error</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">has</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                <span style="color: #6666FF;">$parent</span> <span style="color: #339933;">=</span> Page<span style="color: #339933;">::</span><span style="color: #00FF00;">getByID</span><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">post</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'cParentID'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #6666FF;">$ct</span> <span style="color: #339933;">=</span> CollectionType<span style="color: #339933;">::</span><span style="color: #00FF00;">getByID</span><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">post</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'ctID'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>             
                <span style="color: #6666FF;">$data</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'cName'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">post</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'faqTitle'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> 
                <span style="color: #4444ff;">'cDescription'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">post</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'faqDescription'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> 
                <span style="color: #4444ff;">'cDatePublic'</span> <span style="color: #339933;">=&gt;</span> Loader<span style="color: #339933;">::</span><span style="color: #00FF00;">helper</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'form/date_time'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">translate</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'faqDate'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #6666FF;">$p</span> <span style="color: #339933;">=</span> <span style="color: #6666FF;">$parent</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">add</span><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$ct</span><span style="color: #339933;">,</span> <span style="color: #6666FF;">$data</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>  
                <span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">saveData</span><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$p</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">redirect</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'/dashboard/example_faq/'</span><span style="color: #339933;">,</span> <span style="color: #4444ff;">'faq_added'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;</pre></div><p>First, we setup the form. If we're not posting the form, then no further action is required. If the form is a post, however, that means we're submitting a new FAQ Entry into our system. That means we need to validate it using the validate() function (which will be shown later.) If the validate function passes, that means we're posting valid information, so we grab the parent page specified, grab the page type specified, and add a page of the specific type. Then we call a custom saveData() method (shown later) which takes care of setting up custom attributes like tags, and body content. Then we redirect the user to http://www.yoursite.com/index.php/dashboard/example_faq/faq_added/</p>
<p>The update() function is run when an existing FAQ Entry is updated. It is very similar to add() but takes an existing page ID:</p><div class="ccm-syntax-highlighter">
<pre class="php" style="font-family:monospace;">    <span style="color: #999999; font-weight: bold;">public</span> <span style="color: #999999; font-weight: bold;">function</span> update<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">edit</span><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">post</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'faqID'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">isPost</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">validate</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">error</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">has</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                <span style="color: #6666FF;">$p</span> <span style="color: #339933;">=</span> Page<span style="color: #339933;">::</span><span style="color: #00FF00;">getByID</span><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">post</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'faqID'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #6666FF;">$parent</span> <span style="color: #339933;">=</span> Page<span style="color: #339933;">::</span><span style="color: #00FF00;">getByID</span><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">post</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'cParentID'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #6666FF;">$ct</span> <span style="color: #339933;">=</span> CollectionType<span style="color: #339933;">::</span><span style="color: #00FF00;">getByID</span><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">post</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'ctID'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>             
                <span style="color: #6666FF;">$data</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'ctID'</span> <span style="color: #339933;">=&gt;</span><span style="color: #6666FF;">$ct</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">getCollectionTypeID</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> 
                    <span style="color: #4444ff;">'cDescription'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">post</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'faqDescription'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> 
                    <span style="color: #4444ff;">'cName'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">post</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'faqTitle'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> 
                    <span style="color: #4444ff;">'cDatePublic'</span> <span style="color: #339933;">=&gt;</span> Loader<span style="color: #339933;">::</span><span style="color: #00FF00;">helper</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'form/date_time'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">translate</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'faqDate'</span><span style="color: #009900;">&#41;</span>
                <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #6666FF;">$p</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">update</span><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$data</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$p</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">getCollectionParentID</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">!=</span> <span style="color: #6666FF;">$parent</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">getCollectionID</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                    <span style="color: #6666FF;">$p</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">move</span><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$parent</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #009900;">&#125;</span>
                <span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">saveData</span><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$p</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">redirect</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'/dashboard/example_faq/'</span><span style="color: #339933;">,</span> <span style="color: #4444ff;">'faq_updated'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span></pre></div><p>First we run the edit function on the posted faqID variable, then we run validate. If there are no errors, we update the page, move it if necessary, and handle redirection.</p>
<h3>Validation</h3><div class="ccm-syntax-highlighter">
<pre class="php" style="font-family:monospace;">    protected <span style="color: #999999; font-weight: bold;">function</span> validate<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #6666FF;">$vt</span> <span style="color: #339933;">=</span> Loader<span style="color: #339933;">::</span><span style="color: #00FF00;">helper</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'validation/strings'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #6666FF;">$vn</span> <span style="color: #339933;">=</span> Loader<span style="color: #339933;">::</span><span style="color: #00FF00;">Helper</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'validation/numbers'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #6666FF;">$dt</span> <span style="color: #339933;">=</span> Loader<span style="color: #339933;">::</span><span style="color: #00FF00;">helper</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">&quot;form/date_time&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #6666FF;">$vn</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">integer</span><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">post</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'cParentID'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">error</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">add</span><span style="color: #009900;">&#40;</span>t<span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'You must choose a parent page for this FAQ entry.'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>           
&nbsp;
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #6666FF;">$vn</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">integer</span><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">post</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'ctID'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">error</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">add</span><span style="color: #009900;">&#40;</span>t<span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'You must choose a page type for this FAQ entry.'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>           
&nbsp;
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #6666FF;">$vt</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">notempty</span><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">post</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'faqTitle'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">error</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">add</span><span style="color: #009900;">&#40;</span>t<span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'Title is required'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">error</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">has</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            Loader<span style="color: #339933;">::</span><span style="color: #00FF00;">model</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'collection_types'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #6666FF;">$ct</span> <span style="color: #339933;">=</span> CollectionType<span style="color: #339933;">::</span><span style="color: #00FF00;">getByID</span><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">post</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'ctID'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>             
            <span style="color: #6666FF;">$parent</span> <span style="color: #339933;">=</span> Page<span style="color: #339933;">::</span><span style="color: #00FF00;">getByID</span><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">post</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'cParentID'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>              
            <span style="color: #6666FF;">$parentPermissions</span> <span style="color: #339933;">=</span> <span style="color: #999999; font-weight: bold;">new</span> Permissions<span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$parent</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #6666FF;">$parentPermissions</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">canAddSubCollection</span><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$ct</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                <span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">error</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">add</span><span style="color: #009900;">&#40;</span>
                    t<span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'You do not have permission to add a page of that type to that area of the site.'</span><span style="color: #009900;">&#41;</span>
                <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;</pre></div><p>The validate function is run by both add() and update(), and checks the post array to ensure that the FAQ entry in question has valid properties. First, we check to ensure that a parent ID is passed through post, a valid page type ID is passed, a valid title, and then we check permissions to ensure that the user has the ability to add to the particular location. If any of these fail, we add a text error to the $this-&gt;error object we instantiated in on_start() above (more on this below.)</p>
<h3>saveData($p)</h3>
<p>This function is run by both add() and update(), and is responsible for saving body content, and setting custom attributes on the page in question. It is passed the page object.</p><div class="ccm-syntax-highlighter">
<pre class="php" style="font-family:monospace;">    <span style="color: #999999; font-weight: bold;">private</span> <span style="color: #999999; font-weight: bold;">function</span> saveData<span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$p</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #6666FF;">$blocks</span> <span style="color: #339933;">=</span> <span style="color: #6666FF;">$p</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">getBlocks</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'Main'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$blocks</span> <span style="color: #b1b100;">as</span> <span style="color: #6666FF;">$b</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #6666FF;">$b</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">deleteBlock</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #6666FF;">$bt</span> <span style="color: #339933;">=</span> BlockType<span style="color: #339933;">::</span><span style="color: #00FF00;">getByHandle</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'content'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #6666FF;">$data</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'content'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">post</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'faqBody'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #6666FF;">$p</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">addBlock</span><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$bt</span><span style="color: #339933;">,</span> <span style="color: #4444ff;">'Main'</span><span style="color: #339933;">,</span> <span style="color: #6666FF;">$data</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        Loader<span style="color: #339933;">::</span><span style="color: #00FF00;">model</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">&quot;attribute/categories/collection&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #6666FF;">$cak</span> <span style="color: #339933;">=</span> CollectionAttributeKey<span style="color: #339933;">::</span><span style="color: #00FF00;">getByHandle</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'faq_tags'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #6666FF;">$cak</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">saveAttributeForm</span><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$p</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>        
    <span style="color: #009900;">&#125;</span></pre></div><p>The first bit of code is responsible for clearing out any existing blocks in the Main area. The second saves a block of type content into the Main area array, and the third is responsible for grabbing the submitting 'faq_tags' attribute form, and saving it against the page.</p>
<h3>Error and Success Display</h3>
<p>The following methods are those that display success and error messages to the end user.</p><div class="ccm-syntax-highlighter">
<pre class="php" style="font-family:monospace;">    <span style="color: #999999; font-weight: bold;">public</span> <span style="color: #999999; font-weight: bold;">function</span> faq_added<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">set</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'message'</span><span style="color: #339933;">,</span> t<span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'FAQ added.'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">view</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #999999; font-weight: bold;">public</span> <span style="color: #999999; font-weight: bold;">function</span> faq_updated<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">set</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'message'</span><span style="color: #339933;">,</span> t<span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'FAQ updated.'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">view</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #999999; font-weight: bold;">public</span> <span style="color: #999999; font-weight: bold;">function</span> on_before_render<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">set</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'error'</span><span style="color: #339933;">,</span> <span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">error</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;</pre></div><p>The faq_added() and faq_updated() methods are automatically run when the user is redirect to http://www.yoursite.com/index.php/dashboard/example_faq/faq_added or http://www.yoursite.com/index.php/dashboard/example_faq/faq_updated/, respectively. They simply set the $message variable in the view layer, which is automatically displayed in a nice fashion by our dashboard theme. Beyond setting this variable, no further action is required. Finally, the on_before_render() function will be called immediately prior to exiting the controller and rendering the view. It sets the $error variable in the Dashboard theme. If this error object has any errors &ndash; such as those tripped by the validate() function above &ndash; they will be displayed in a nice list automatically.</p>
<h2>View Code</h2>
<p>The following code goes into view.php. It directly interacts with any variables set within the controller.</p>
<h3>Create view vs. add/update sections</h3>
<p>The same view.php file will be displayed whether a user is listing all FAQs or add/updating one. That means we need to create a single outer loop which displays certain content depending on the current task.</p><div class="ccm-syntax-highlighter">
<pre class="php" style="font-family:monospace;">    <span style="color: #999999; font-weight: bold;">&lt;?</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">controller</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">getTask</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #4444ff;">'update'</span> <span style="color: #339933;">||</span> 
         <span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">controller</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">getTask</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #4444ff;">'edit'</span> <span style="color: #339933;">||</span> 
         <span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">controller</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">getTask</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #4444ff;">'add'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <span style="color: #999999; font-weight: bold;">?&gt;</span>
&nbsp;
    <span style="color: #999999; font-weight: bold;">&lt;?</span> <span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span> <span style="color: #999999; font-weight: bold;">?&gt;</span>
&nbsp;
    <span style="color: #999999; font-weight: bold;">&lt;?</span> <span style="color: #009900;">&#125;</span><span style="color: #999999; font-weight: bold;">?&gt;</span>
&nbsp;</pre></div><p>The top half of the if statement will show in add/edit/update mode, and the bottom half will show in all other cases. We place the adding/editing form in the first section, and the listing form in the second.</p>
<h3>Add/Edit/Update Form</h3>
<p>This code should be pasted within the first section of the loop above.</p><div class="ccm-syntax-highlighter">
<pre class="php" style="font-family:monospace;">    <span style="color: #999999; font-weight: bold;">&lt;?</span> 
    <span style="color: #6666FF;">$title</span> <span style="color: #339933;">=</span> <span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">controller</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">getTask</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #4444ff;">'add'</span> ? t<span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'Add'</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">:</span> t<span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'Update'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #6666FF;">$df</span> <span style="color: #339933;">=</span> Loader<span style="color: #339933;">::</span><span style="color: #00FF00;">helper</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'form/date_time'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><a href="http://www.php.net/is_object"><span style="color: #990000;">is_object</span></a><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$faq</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> 
        <span style="color: #6666FF;">$faqTitle</span> <span style="color: #339933;">=</span> <span style="color: #6666FF;">$faq</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">getCollectionName</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #6666FF;">$faqDescription</span> <span style="color: #339933;">=</span> <span style="color: #6666FF;">$faq</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">getCollectionDescription</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #6666FF;">$faqDate</span> <span style="color: #339933;">=</span> <span style="color: #6666FF;">$faq</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">getCollectionDatePublic</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #6666FF;">$cParentID</span> <span style="color: #339933;">=</span> <span style="color: #6666FF;">$faq</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">getCollectionParentID</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #6666FF;">$ctID</span> <span style="color: #339933;">=</span> <span style="color: #6666FF;">$faq</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">getCollectionTypeID</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #6666FF;">$faqBody</span> <span style="color: #339933;">=</span> <span style="color: #4444ff;">''</span><span style="color: #339933;">;</span>
        <span style="color: #6666FF;">$eb</span> <span style="color: #339933;">=</span> <span style="color: #6666FF;">$faq</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">getBlocks</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'Main'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><a href="http://www.php.net/is_object"><span style="color: #990000;">is_object</span></a><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$eb</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #6666FF;">$faqBody</span> <span style="color: #339933;">=</span> <span style="color: #6666FF;">$eb</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">getInstance</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">getContent</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #6666FF;">$task</span> <span style="color: #339933;">=</span> <span style="color: #4444ff;">'update'</span><span style="color: #339933;">;</span>
        <span style="color: #6666FF;">$buttonText</span> <span style="color: #339933;">=</span> t<span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'Update Entry'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #6666FF;">$task</span> <span style="color: #339933;">=</span> <span style="color: #4444ff;">'add'</span><span style="color: #339933;">;</span>
        <span style="color: #6666FF;">$buttonText</span> <span style="color: #339933;">=</span> t<span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'Add FAQ Entry'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #999999; font-weight: bold;">?&gt;</span>
&nbsp;
    <span style="color: #339933;">&lt;</span>div style<span style="color: #339933;">=</span><span style="color: #4444ff;">&quot;width: 760px&quot;</span><span style="color: #339933;">&gt;</span>
&nbsp;
    <span style="color: #339933;">&lt;</span>h1<span style="color: #339933;">&gt;&lt;</span>span<span style="color: #339933;">&gt;</span><span style="color: #999999; font-weight: bold;">&lt;?=</span>t<span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'FAQs'</span><span style="color: #009900;">&#41;</span><span style="color: #999999; font-weight: bold;">?&gt;</span><span style="color: #339933;">&lt;/</span>span<span style="color: #339933;">&gt;&lt;/</span>h1<span style="color: #339933;">&gt;</span>
    <span style="color: #339933;">&lt;</span>div <span style="color: #999999; font-weight: bold;">class</span><span style="color: #339933;">=</span><span style="color: #4444ff;">&quot;ccm-dashboard-inner&quot;</span><span style="color: #339933;">&gt;</span>
&nbsp;
    <span style="color: #339933;">&lt;</span>h2<span style="color: #339933;">&gt;&lt;</span>span<span style="color: #339933;">&gt;</span><span style="color: #999999; font-weight: bold;">&lt;?=</span><span style="color: #6666FF;">$title</span><span style="color: #999999; font-weight: bold;">?&gt;</span> FAQ Entry<span style="color: #339933;">&lt;/</span>span<span style="color: #339933;">&gt;&lt;/</span>h2<span style="color: #339933;">&gt;</span>
&nbsp;
    <span style="color: #339933;">&lt;</span>form method<span style="color: #339933;">=</span><span style="color: #4444ff;">&quot;post&quot;</span> action<span style="color: #339933;">=</span><span style="color: #4444ff;">&quot;&lt;?=<span style="color: #006699; font-weight: bold;">$this-&gt;action</span>(<span style="color: #006699; font-weight: bold;">$task</span>)?&gt;&quot;</span> id<span style="color: #339933;">=</span><span style="color: #4444ff;">&quot;faq-form&quot;</span><span style="color: #339933;">&gt;</span>
    <span style="color: #999999; font-weight: bold;">&lt;?</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">controller</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">getTask</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">!=</span> <span style="color: #4444ff;">'add'</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <span style="color: #999999; font-weight: bold;">?&gt;</span>
        <span style="color: #999999; font-weight: bold;">&lt;?=</span><span style="color: #6666FF;">$form</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">hidden</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'faqID'</span><span style="color: #339933;">,</span> <span style="color: #6666FF;">$faq</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">getCollectionID</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #999999; font-weight: bold;">?&gt;</span>
    <span style="color: #999999; font-weight: bold;">&lt;?</span> <span style="color: #009900;">&#125;</span> <span style="color: #999999; font-weight: bold;">?&gt;</span>
&nbsp;
    <span style="color: #339933;">&lt;</span>strong<span style="color: #339933;">&gt;</span><span style="color: #999999; font-weight: bold;">&lt;?=</span><span style="color: #6666FF;">$form</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">label</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'faqTitle'</span><span style="color: #339933;">,</span> t<span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'Question'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #999999; font-weight: bold;">?&gt;</span><span style="color: #339933;">&lt;/</span>strong<span style="color: #339933;">&gt;</span>
    <span style="color: #339933;">&lt;</span>div<span style="color: #339933;">&gt;</span><span style="color: #999999; font-weight: bold;">&lt;?=</span><span style="color: #6666FF;">$form</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">text</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'faqTitle'</span><span style="color: #339933;">,</span> <span style="color: #6666FF;">$faqTitle</span><span style="color: #339933;">,</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'style'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #4444ff;">'width: 730px'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #999999; font-weight: bold;">?&gt;</span><span style="color: #339933;">&lt;/</span>div<span style="color: #339933;">&gt;</span>
    <span style="color: #339933;">&lt;</span>br<span style="color: #339933;">/&gt;</span>
    <span style="color: #339933;">&lt;</span>strong<span style="color: #339933;">&gt;</span><span style="color: #999999; font-weight: bold;">&lt;?=</span><span style="color: #6666FF;">$form</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">label</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'faqDescription'</span><span style="color: #339933;">,</span> t<span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'Brief Answer'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #999999; font-weight: bold;">?&gt;</span><span style="color: #339933;">&lt;/</span>strong<span style="color: #339933;">&gt;</span>
    <span style="color: #339933;">&lt;</span>div<span style="color: #339933;">&gt;</span><span style="color: #999999; font-weight: bold;">&lt;?=</span><span style="color: #6666FF;">$form</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">textarea</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'faqDescription'</span><span style="color: #339933;">,</span> <span style="color: #6666FF;">$faqDescription</span><span style="color: #339933;">,</span> 
              <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'style'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #4444ff;">'width: 730px; height: 100px'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #999999; font-weight: bold;">?&gt;</span><span style="color: #339933;">&lt;/</span>div<span style="color: #339933;">&gt;</span>
    <span style="color: #339933;">&lt;</span>br<span style="color: #339933;">/&gt;</span>           
    <span style="color: #339933;">&lt;</span>strong<span style="color: #339933;">&gt;</span><span style="color: #999999; font-weight: bold;">&lt;?=</span><span style="color: #6666FF;">$form</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">label</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'cParentID'</span><span style="color: #339933;">,</span> t<span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'Section'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #999999; font-weight: bold;">?&gt;</span><span style="color: #339933;">&lt;/</span>strong<span style="color: #339933;">&gt;</span>
    <span style="color: #999999; font-weight: bold;">&lt;?</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><a href="http://www.php.net/count"><span style="color: #990000;">count</span></a><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$sections</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <span style="color: #999999; font-weight: bold;">?&gt;</span>
        <span style="color: #339933;">&lt;</span>div<span style="color: #339933;">&gt;</span><span style="color: #999999; font-weight: bold;">&lt;?=</span>t<span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'No sections defined. 
            Please create a page with the attribute &quot;faq_entry&quot; set to true.'</span><span style="color: #009900;">&#41;</span><span style="color: #999999; font-weight: bold;">?&gt;</span><span style="color: #339933;">&lt;/</span>div<span style="color: #339933;">&gt;</span>
    <span style="color: #999999; font-weight: bold;">&lt;?</span> <span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span> <span style="color: #999999; font-weight: bold;">?&gt;</span>
        <span style="color: #339933;">&lt;</span>div<span style="color: #339933;">&gt;</span><span style="color: #999999; font-weight: bold;">&lt;?=</span><span style="color: #6666FF;">$form</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">select</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'cParentID'</span><span style="color: #339933;">,</span> <span style="color: #6666FF;">$sections</span><span style="color: #339933;">,</span> <span style="color: #6666FF;">$cParentID</span><span style="color: #009900;">&#41;</span><span style="color: #999999; font-weight: bold;">?&gt;</span><span style="color: #339933;">&lt;/</span>div<span style="color: #339933;">&gt;</span>
    <span style="color: #999999; font-weight: bold;">&lt;?</span> <span style="color: #009900;">&#125;</span> <span style="color: #999999; font-weight: bold;">?&gt;</span>
<span style="color: #339933;">&lt;</span>br<span style="color: #339933;">/&gt;</span>
&nbsp;
    <span style="color: #339933;">&lt;</span>strong<span style="color: #339933;">&gt;</span><span style="color: #999999; font-weight: bold;">&lt;?=</span><span style="color: #6666FF;">$form</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">label</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'ctID'</span><span style="color: #339933;">,</span> t<span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'Page Type'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #999999; font-weight: bold;">?&gt;</span><span style="color: #339933;">&lt;/</span>strong<span style="color: #339933;">&gt;</span>
    <span style="color: #339933;">&lt;</span>div<span style="color: #339933;">&gt;</span><span style="color: #999999; font-weight: bold;">&lt;?=</span><span style="color: #6666FF;">$form</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">select</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'ctID'</span><span style="color: #339933;">,</span> <span style="color: #6666FF;">$pageTypes</span><span style="color: #339933;">,</span> <span style="color: #6666FF;">$ctID</span><span style="color: #009900;">&#41;</span><span style="color: #999999; font-weight: bold;">?&gt;</span><span style="color: #339933;">&lt;/</span>div<span style="color: #339933;">&gt;</span>
    <span style="color: #339933;">&lt;</span>br<span style="color: #339933;">/&gt;</span>
    <span style="color: #339933;">&lt;</span>strong<span style="color: #339933;">&gt;</span><span style="color: #999999; font-weight: bold;">&lt;?=</span><span style="color: #6666FF;">$form</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">label</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'faqDate'</span><span style="color: #339933;">,</span> t<span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'Date/Time'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #999999; font-weight: bold;">?&gt;</span><span style="color: #339933;">&lt;/</span>strong<span style="color: #339933;">&gt;</span>
    <span style="color: #339933;">&lt;</span>div<span style="color: #339933;">&gt;</span><span style="color: #999999; font-weight: bold;">&lt;?=</span><span style="color: #6666FF;">$df</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">datetime</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'faqDate'</span><span style="color: #339933;">,</span> <span style="color: #6666FF;">$faqDate</span><span style="color: #009900;">&#41;</span><span style="color: #999999; font-weight: bold;">?&gt;</span><span style="color: #339933;">&lt;/</span>div<span style="color: #339933;">&gt;</span>
    <span style="color: #339933;">&lt;</span>br<span style="color: #339933;">/&gt;</span>
    <span style="color: #339933;">&lt;</span>strong<span style="color: #339933;">&gt;</span><span style="color: #999999; font-weight: bold;">&lt;?=</span>t<span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'Full Answer'</span><span style="color: #009900;">&#41;</span><span style="color: #999999; font-weight: bold;">?&gt;</span><span style="color: #339933;">&lt;/</span>strong<span style="color: #339933;">&gt;</span>
    <span style="color: #999999; font-weight: bold;">&lt;?php</span> Loader<span style="color: #339933;">::</span><span style="color: #00FF00;">element</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'editor_init'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #999999; font-weight: bold;">?&gt;</span>
    <span style="color: #999999; font-weight: bold;">&lt;?php</span> Loader<span style="color: #339933;">::</span><span style="color: #00FF00;">element</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'editor_config'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #999999; font-weight: bold;">?&gt;</span>
    <span style="color: #999999; font-weight: bold;">&lt;?php</span> Loader<span style="color: #339933;">::</span><span style="color: #00FF00;">element</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'editor_controls'</span><span style="color: #339933;">,</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'mode'</span><span style="color: #339933;">=&gt;</span><span style="color: #4444ff;">'full'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #999999; font-weight: bold;">?&gt;</span>
    <span style="color: #999999; font-weight: bold;">&lt;?=</span><span style="color: #6666FF;">$form</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">textarea</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'faqBody'</span><span style="color: #339933;">,</span> <span style="color: #6666FF;">$faqBody</span><span style="color: #339933;">,</span> 
          <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'style'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #4444ff;">'width: 100%; height: 150px'</span><span style="color: #339933;">,</span> <span style="color: #4444ff;">'class'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #4444ff;">'ccm-advanced-editor'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #999999; font-weight: bold;">?&gt;</span>
    <span style="color: #339933;">&lt;</span>br<span style="color: #339933;">/&gt;</span>
    <span style="color: #999999; font-weight: bold;">&lt;?</span> 
    Loader<span style="color: #339933;">::</span><span style="color: #00FF00;">model</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">&quot;attribute/categories/collection&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #6666FF;">$akt</span> <span style="color: #339933;">=</span> CollectionAttributeKey<span style="color: #339933;">::</span><span style="color: #00FF00;">getByHandle</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'faq_tags'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><a href="http://www.php.net/is_object"><span style="color: #990000;">is_object</span></a><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$faq</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #6666FF;">$tvalue</span> <span style="color: #339933;">=</span> <span style="color: #6666FF;">$faq</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">getAttributeValueObject</span><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$akt</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #999999; font-weight: bold;">?&gt;</span>
    <span style="color: #339933;">&lt;</span>div <span style="color: #999999; font-weight: bold;">class</span><span style="color: #339933;">=</span><span style="color: #4444ff;">&quot;faq-attributes&quot;</span><span style="color: #339933;">&gt;</span>
        <span style="color: #339933;">&lt;</span>div<span style="color: #339933;">&gt;</span>
            <span style="color: #339933;">&lt;</span>strong<span style="color: #339933;">&gt;</span><span style="color: #999999; font-weight: bold;">&lt;?=</span><span style="color: #6666FF;">$akt</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">render</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'label'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><span style="color: #999999; font-weight: bold;">?&gt;</span><span style="color: #339933;">&lt;/</span>strong<span style="color: #339933;">&gt;</span>
            <span style="color: #999999; font-weight: bold;">&lt;?=</span><span style="color: #6666FF;">$akt</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">render</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'form'</span><span style="color: #339933;">,</span> <span style="color: #6666FF;">$tvalue</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><span style="color: #999999; font-weight: bold;">?&gt;</span>
        <span style="color: #339933;">&lt;/</span>div<span style="color: #339933;">&gt;</span>
    <span style="color: #339933;">&lt;/</span>div<span style="color: #339933;">&gt;</span>
&nbsp;
    <span style="color: #339933;">&lt;</span>br<span style="color: #339933;">/&gt;</span>
&nbsp;
    <span style="color: #999999; font-weight: bold;">&lt;?</span>
&nbsp;
    <span style="color: #6666FF;">$ih</span> <span style="color: #339933;">=</span> Loader<span style="color: #339933;">::</span><span style="color: #00FF00;">helper</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'concrete/interface'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">print</span> <span style="color: #6666FF;">$ih</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">button</span><span style="color: #009900;">&#40;</span>t<span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'Cancel'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #6666FF;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">url</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'/dashboard/example_faq/'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #4444ff;">'left'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">print</span> <span style="color: #6666FF;">$ih</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">submit</span><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$buttonText</span><span style="color: #339933;">,</span> <span style="color: #4444ff;">'faq-form'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #999999; font-weight: bold;">?&gt;</span>
    <span style="color: #339933;">&lt;</span>div <span style="color: #999999; font-weight: bold;">class</span><span style="color: #339933;">=</span><span style="color: #4444ff;">&quot;ccm-spacer&quot;</span><span style="color: #339933;">&gt;</span> <span style="color: #339933;">&lt;/</span>div<span style="color: #339933;">&gt;</span>
&nbsp;
    <span style="color: #339933;">&lt;/</span>form<span style="color: #339933;">&gt;</span>
&nbsp;
    <span style="color: #339933;">&lt;/</span>div<span style="color: #339933;">&gt;</span>
    <span style="color: #339933;">&lt;/</span>div<span style="color: #339933;">&gt;</span></pre></div><p>This code is responsible for creating the add/update interface. It is unified for both add and update, meaning that if a valid $faq object is present, the fields will be loaded in, otherwise they will be blank. This code provides good examples of using our form helper to create textarea and text elements, loading the rich text editor, and rendering the form view for a custom attribute. While we include just the FAQ Tags custom attribute, any number and any type of custom attribute can be included in a single page interface. The code provided here will display any of the attribute types, and save them properly against the page automatically.</p>
<p>Finally, we load the concrete interface helper to present submit and cancel buttons to the user in the concrete5 style.</p>
<h3>View List</h3>
<p>The second bit of code in view.php is responsible for listing all existing FAQs. Paste this code within the second half of the loop created above.</p><div class="ccm-syntax-highlighter">
<pre class="php" style="font-family:monospace;">    <span style="color: #339933;">&lt;</span>h1<span style="color: #339933;">&gt;&lt;</span>span<span style="color: #339933;">&gt;</span><span style="color: #999999; font-weight: bold;">&lt;?=</span>t<span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'FAQs'</span><span style="color: #009900;">&#41;</span><span style="color: #999999; font-weight: bold;">?&gt;</span><span style="color: #339933;">&lt;/</span>span<span style="color: #339933;">&gt;&lt;/</span>h1<span style="color: #339933;">&gt;</span>
    <span style="color: #339933;">&lt;</span>div <span style="color: #999999; font-weight: bold;">class</span><span style="color: #339933;">=</span><span style="color: #4444ff;">&quot;ccm-dashboard-inner&quot;</span><span style="color: #339933;">&gt;</span>
    <span style="color: #339933;">&lt;</span>h2<span style="color: #339933;">&gt;</span><span style="color: #999999; font-weight: bold;">&lt;?=</span>t<span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'New FAQ'</span><span style="color: #009900;">&#41;</span><span style="color: #999999; font-weight: bold;">?&gt;</span><span style="color: #339933;">&lt;/</span>h2<span style="color: #339933;">&gt;</span>
    <span style="color: #339933;">&lt;</span>a href<span style="color: #339933;">=</span><span style="color: #4444ff;">&quot;&lt;?=<span style="color: #006699; font-weight: bold;">$this-&gt;action</span>('add')?&gt;&quot;</span><span style="color: #339933;">&gt;</span><span style="color: #999999; font-weight: bold;">&lt;?=</span>t<span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'Click here to add a new FAQ Entry &gt;'</span><span style="color: #009900;">&#41;</span><span style="color: #999999; font-weight: bold;">?&gt;</span><span style="color: #339933;">&lt;/</span>a<span style="color: #339933;">&gt;</span>
    <span style="color: #339933;">&lt;</span>Br<span style="color: #339933;">/&gt;&lt;</span>br<span style="color: #339933;">/&gt;</span>
&nbsp;
    <span style="color: #339933;">&lt;</span>h2<span style="color: #339933;">&gt;</span><span style="color: #999999; font-weight: bold;">&lt;?=</span>t<span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'View/Search FAQs'</span><span style="color: #009900;">&#41;</span><span style="color: #999999; font-weight: bold;">?&gt;</span><span style="color: #339933;">&lt;/</span>h2<span style="color: #339933;">&gt;</span>
&nbsp;
    <span style="color: #339933;">&lt;</span>form method<span style="color: #339933;">=</span><span style="color: #4444ff;">&quot;get&quot;</span> action<span style="color: #339933;">=</span><span style="color: #4444ff;">&quot;&lt;?=<span style="color: #006699; font-weight: bold;">$this-&gt;action</span>('view')?&gt;&quot;</span><span style="color: #339933;">&gt;</span>
    <span style="color: #999999; font-weight: bold;">&lt;?</span>
    <span style="color: #6666FF;">$sections</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #4444ff;">'** All'</span><span style="color: #339933;">;</span>
    <a href="http://www.php.net/asort"><span style="color: #990000;">asort</span></a><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$sections</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #999999; font-weight: bold;">?&gt;</span>
&nbsp;
    <span style="color: #339933;">&lt;</span>strong<span style="color: #339933;">&gt;</span><span style="color: #999999; font-weight: bold;">&lt;?=</span><span style="color: #6666FF;">$form</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">label</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'cParentID'</span><span style="color: #339933;">,</span> t<span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'Section'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #999999; font-weight: bold;">?&gt;</span><span style="color: #339933;">&lt;/</span>strong<span style="color: #339933;">&gt;</span>
    <span style="color: #339933;">&lt;</span>div<span style="color: #339933;">&gt;</span><span style="color: #999999; font-weight: bold;">&lt;?=</span><span style="color: #6666FF;">$form</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">select</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'cParentID'</span><span style="color: #339933;">,</span> <span style="color: #6666FF;">$sections</span><span style="color: #339933;">,</span> <span style="color: #6666FF;">$cParentID</span><span style="color: #009900;">&#41;</span><span style="color: #999999; font-weight: bold;">?&gt;</span>
    <span style="color: #999999; font-weight: bold;">&lt;?=</span><span style="color: #6666FF;">$form</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">submit</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'submit'</span><span style="color: #339933;">,</span> <span style="color: #4444ff;">'Search'</span><span style="color: #009900;">&#41;</span><span style="color: #999999; font-weight: bold;">?&gt;</span>
    <span style="color: #339933;">&lt;/</span>div<span style="color: #339933;">&gt;</span>
    <span style="color: #339933;">&lt;/</span>form<span style="color: #339933;">&gt;</span>
    <span style="color: #339933;">&lt;</span>br<span style="color: #339933;">/&gt;</span>
    <span style="color: #999999; font-weight: bold;">&lt;?</span>
    <span style="color: #6666FF;">$nh</span> <span style="color: #339933;">=</span> Loader<span style="color: #339933;">::</span><span style="color: #00FF00;">helper</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'navigation'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$faqList</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">getTotal</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&gt;</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> 
        <span style="color: #6666FF;">$faqList</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">displaySummary</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #999999; font-weight: bold;">?&gt;</span>
&nbsp;
    <span style="color: #339933;">&lt;</span>table border<span style="color: #339933;">=</span><span style="color: #4444ff;">&quot;0&quot;</span> <span style="color: #999999; font-weight: bold;">class</span><span style="color: #339933;">=</span><span style="color: #4444ff;">&quot;ccm-results-list&quot;</span> cellspacing<span style="color: #339933;">=</span><span style="color: #4444ff;">&quot;0&quot;</span> cellpadding<span style="color: #339933;">=</span><span style="color: #4444ff;">&quot;0&quot;</span><span style="color: #339933;">&gt;</span>
        <span style="color: #339933;">&lt;</span>tr<span style="color: #339933;">&gt;</span>
            <span style="color: #339933;">&lt;</span>th <span style="color: #999999; font-weight: bold;">class</span><span style="color: #339933;">=</span><span style="color: #4444ff;">&quot;&lt;?=<span style="color: #006699; font-weight: bold;">$faqList-&gt;getSearchResultsClass</span>('cvName')?&gt;&quot;</span><span style="color: #339933;">&gt;</span>
                <span style="color: #339933;">&lt;</span>a href<span style="color: #339933;">=</span><span style="color: #4444ff;">&quot;&lt;?=<span style="color: #006699; font-weight: bold;">$faqList-&gt;getSortByURL</span>('cvName', 'asc')?&gt;&quot;</span><span style="color: #339933;">&gt;</span><span style="color: #999999; font-weight: bold;">&lt;?=</span>t<span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'Name'</span><span style="color: #009900;">&#41;</span><span style="color: #999999; font-weight: bold;">?&gt;</span><span style="color: #339933;">&lt;/</span>a<span style="color: #339933;">&gt;</span>
            <span style="color: #339933;">&lt;/</span>th<span style="color: #339933;">&gt;</span>
            <span style="color: #339933;">&lt;</span>th <span style="color: #999999; font-weight: bold;">class</span><span style="color: #339933;">=</span><span style="color: #4444ff;">&quot;&lt;?=<span style="color: #006699; font-weight: bold;">$faqList-&gt;getSearchResultsClass</span>('cDateAdded')?&gt;&quot;</span><span style="color: #339933;">&gt;</span>
                <span style="color: #339933;">&lt;</span>a href<span style="color: #339933;">=</span><span style="color: #4444ff;">&quot;&lt;?=<span style="color: #006699; font-weight: bold;">$faqList-&gt;getSortByURL</span>('cDateAdded', 'asc')?&gt;&quot;</span><span style="color: #339933;">&gt;</span><span style="color: #999999; font-weight: bold;">&lt;?=</span>t<span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'Date Added'</span><span style="color: #009900;">&#41;</span><span style="color: #999999; font-weight: bold;">?&gt;</span><span style="color: #339933;">&lt;/</span>a<span style="color: #339933;">&gt;</span>
            <span style="color: #339933;">&lt;/</span>th<span style="color: #339933;">&gt;</span>
            <span style="color: #339933;">&lt;</span>th <span style="color: #999999; font-weight: bold;">class</span><span style="color: #339933;">=</span><span style="color: #4444ff;">&quot;&lt;?=<span style="color: #006699; font-weight: bold;">$faqList-&gt;getSearchResultsClass</span>('cvDatePublic')?&gt;&quot;</span><span style="color: #339933;">&gt;</span>
                <span style="color: #339933;">&lt;</span>a href<span style="color: #339933;">=</span><span style="color: #4444ff;">&quot;&lt;?=<span style="color: #006699; font-weight: bold;">$faqList-&gt;getSortByURL</span>('cvDatePublic', 'asc')?&gt;&quot;</span><span style="color: #339933;">&gt;</span><span style="color: #999999; font-weight: bold;">&lt;?=</span>t<span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'Public Date'</span><span style="color: #009900;">&#41;</span><span style="color: #999999; font-weight: bold;">?&gt;</span><span style="color: #339933;">&lt;/</span>a<span style="color: #339933;">&gt;</span>
            <span style="color: #339933;">&lt;/</span>th<span style="color: #339933;">&gt;</span>
            <span style="color: #339933;">&lt;</span>th<span style="color: #339933;">&gt;</span><span style="color: #999999; font-weight: bold;">&lt;?=</span>t<span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'Page Owner'</span><span style="color: #009900;">&#41;</span><span style="color: #999999; font-weight: bold;">?&gt;</span><span style="color: #339933;">&lt;/</span>th<span style="color: #339933;">&gt;</span>
            <span style="color: #339933;">&lt;</span>th<span style="color: #339933;">&gt;</span> <span style="color: #339933;">&lt;/</span>th<span style="color: #339933;">&gt;</span>
        <span style="color: #339933;">&lt;/</span>tr<span style="color: #339933;">&gt;</span>
        <span style="color: #999999; font-weight: bold;">&lt;?</span>
        <span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$faqResults</span> <span style="color: #b1b100;">as</span> <span style="color: #6666FF;">$cobj</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <span style="color: #999999; font-weight: bold;">?&gt;</span>
        <span style="color: #339933;">&lt;</span>tr<span style="color: #339933;">&gt;</span>
            <span style="color: #339933;">&lt;</span>td<span style="color: #339933;">&gt;&lt;</span>a href<span style="color: #339933;">=</span><span style="color: #4444ff;">&quot;&lt;?=<span style="color: #006699; font-weight: bold;">$nh-&gt;getLinkToCollection</span>(<span style="color: #006699; font-weight: bold;">$cobj</span>)?&gt;&quot;</span><span style="color: #339933;">&gt;</span>
                 <span style="color: #999999; font-weight: bold;">&lt;?=</span><span style="color: #6666FF;">$cobj</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">getCollectionName</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #999999; font-weight: bold;">?&gt;</span><span style="color: #339933;">&lt;/</span>a<span style="color: #339933;">&gt;</span>
            <span style="color: #339933;">&lt;/</span>td<span style="color: #339933;">&gt;</span>
            <span style="color: #339933;">&lt;</span>td<span style="color: #339933;">&gt;</span><span style="color: #999999; font-weight: bold;">&lt;?=</span><span style="color: #6666FF;">$cobj</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">getCollectionDateAdded</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #999999; font-weight: bold;">?&gt;</span><span style="color: #339933;">&lt;/</span>td<span style="color: #339933;">&gt;</span>
            <span style="color: #339933;">&lt;</span>td<span style="color: #339933;">&gt;</span><span style="color: #999999; font-weight: bold;">&lt;?=</span><span style="color: #6666FF;">$cobj</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">getCollectionDatePublic</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #999999; font-weight: bold;">?&gt;</span><span style="color: #339933;">&lt;/</span>td<span style="color: #339933;">&gt;</span>
            <span style="color: #339933;">&lt;</span>td<span style="color: #339933;">&gt;</span>
                <span style="color: #999999; font-weight: bold;">&lt;?</span> 
                <span style="color: #6666FF;">$user</span> <span style="color: #339933;">=</span> UserInfo<span style="color: #339933;">::</span><span style="color: #00FF00;">getByID</span><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$cobj</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">getCollectionUserID</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #b1b100;">print</span> <span style="color: #6666FF;">$user</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">getUserName</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #999999; font-weight: bold;">?&gt;</span>
            <span style="color: #339933;">&lt;/</span>td<span style="color: #339933;">&gt;</span>
            <span style="color: #339933;">&lt;</span>td<span style="color: #339933;">&gt;&lt;</span>A href<span style="color: #339933;">=</span><span style="color: #4444ff;">&quot;&lt;?=<span style="color: #006699; font-weight: bold;">$this-&gt;url</span>('/dashboard/example_faq', 'edit', 
                  <span style="color: #006699; font-weight: bold;">$cobj-&gt;getCollectionID</span>())?&gt;&quot;</span><span style="color: #339933;">&gt;</span><span style="color: #999999; font-weight: bold;">&lt;?=</span>t<span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'Edit'</span><span style="color: #009900;">&#41;</span><span style="color: #999999; font-weight: bold;">?&gt;</span><span style="color: #339933;">&lt;/</span>a<span style="color: #339933;">&gt;</span>
            <span style="color: #339933;">&lt;/</span>td<span style="color: #339933;">&gt;</span>
        <span style="color: #339933;">&lt;/</span>tr<span style="color: #339933;">&gt;</span>
        <span style="color: #999999; font-weight: bold;">&lt;?</span> <span style="color: #009900;">&#125;</span> <span style="color: #999999; font-weight: bold;">?&gt;</span>
&nbsp;
        <span style="color: #339933;">&lt;/</span>table<span style="color: #339933;">&gt;</span>
        <span style="color: #339933;">&lt;</span>br<span style="color: #339933;">/&gt;</span>
        <span style="color: #999999; font-weight: bold;">&lt;?</span>
        <span style="color: #6666FF;">$faqList</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">displayPaging</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">print</span> t<span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'No FAQ entries found.'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #999999; font-weight: bold;">?&gt;</span>
    <span style="color: #339933;">&lt;/</span>div<span style="color: #339933;">&gt;</span></pre></div><p>Here we can see links to the add interface, a list for filtering, and finally a table that shows all selected pages and offers some basic sorting.</p>
<h2>A Custom Page List Template</h2>
<p>Finally, let's create a custom FAQ-styled template for the Page List block. That way, anywhere we add the Page List block, we'll be able to style it like this:</p>
<div class="main-image">
	<div><img src="/files/2812/7309/6105/picture 5.png" class="footer-image" width="514" height="507" alt="footer image" /></div>


</div><p>By clicking on the title of a FAQ entry, the short description will display, along with a link to the full answer.</p>
<h3>Create a Custom Template Directory</h3>
<p>In the root of your site, create a directory named blocks/page_list/templates/example_faq_page_list/, and within it a file named view.php</p>
<div class="main-image">
	<div><img src="/files/2012/7309/6106/picture 12.png" class="footer-image" width="688" height="88" alt="footer image" /></div>


</div><p>The following code goes into view.php</p><div class="ccm-syntax-highlighter">
<pre class="php" style="font-family:monospace;">    <span style="color: #999999; font-weight: bold;">&lt;?php</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><a href="http://www.php.net/count"><span style="color: #990000;">count</span></a><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$cArray</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&gt;</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <span style="color: #999999; font-weight: bold;">?&gt;</span>
&nbsp;
    <span style="color: #339933;">&lt;</span>table border<span style="color: #339933;">=</span><span style="color: #4444ff;">&quot;0&quot;</span> cellspacing<span style="color: #339933;">=</span><span style="color: #4444ff;">&quot;0&quot;</span> cellpadding<span style="color: #339933;">=</span><span style="color: #4444ff;">&quot;0&quot;</span><span style="color: #339933;">&gt;</span>
    <span style="color: #999999; font-weight: bold;">&lt;?</span> <span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$cArray</span> <span style="color: #b1b100;">as</span> <span style="color: #6666FF;">$cobj</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <span style="color: #999999; font-weight: bold;">?&gt;</span>
&nbsp;
    <span style="color: #339933;">&lt;</span>tr id<span style="color: #339933;">=</span><span style="color: #4444ff;">&quot;f&lt;?=<span style="color: #006699; font-weight: bold;">$cobj-&gt;getCollectionID</span>()?&gt;&quot;</span><span style="color: #339933;">&gt;</span>
        <span style="color: #339933;">&lt;</span>td valign<span style="color: #339933;">=</span><span style="color: #4444ff;">&quot;top&quot;</span><span style="color: #339933;">&gt;</span>
            <span style="color: #339933;">&lt;</span>div style<span style="color: #339933;">=</span><span style="color: #4444ff;">&quot;width: 20px; text-align: center&quot;</span><span style="color: #339933;">&gt;&lt;</span>strong<span style="color: #339933;">&gt;</span>Q<span style="color: #339933;">.&lt;/</span>strong<span style="color: #339933;">&gt;&lt;/</span>div<span style="color: #339933;">&gt;</span>
        <span style="color: #339933;">&lt;/</span>td<span style="color: #339933;">&gt;</span>
        <span style="color: #339933;">&lt;</span>td valign<span style="color: #339933;">=</span><span style="color: #4444ff;">&quot;top&quot;</span> style<span style="color: #339933;">=</span><span style="color: #4444ff;">&quot;width: 100%&quot;</span><span style="color: #339933;">&gt;</span>
            <span style="color: #339933;">&lt;</span>a href<span style="color: #339933;">=</span><span style="color: #4444ff;">&quot;javascript:void(0)&quot;</span> onclick<span style="color: #339933;">=</span><span style="color: #4444ff;">&quot;toggleFAQEntry('&lt;?=<span style="color: #006699; font-weight: bold;">$cobj-&gt;getCollectionID</span>()?&gt;')&quot;</span><span style="color: #339933;">&gt;</span>
                <span style="color: #999999; font-weight: bold;">&lt;?=</span><span style="color: #6666FF;">$cobj</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">getCollectionName</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #999999; font-weight: bold;">?&gt;</span>
            <span style="color: #339933;">&lt;/</span>a<span style="color: #339933;">&gt;</span>
        <span style="color: #339933;">&lt;/</span>td<span style="color: #339933;">&gt;</span>
    <span style="color: #339933;">&lt;/</span>tr<span style="color: #339933;">&gt;</span>
    <span style="color: #339933;">&lt;</span>tr id<span style="color: #339933;">=</span><span style="color: #4444ff;">&quot;fa&lt;?=<span style="color: #006699; font-weight: bold;">$cobj-&gt;getCollectionID</span>()?&gt;&quot;</span> style<span style="color: #339933;">=</span><span style="color: #4444ff;">&quot;display: none&quot;</span><span style="color: #339933;">&gt;</span>
        <span style="color: #339933;">&lt;</span>td valign<span style="color: #339933;">=</span><span style="color: #4444ff;">&quot;top&quot;</span><span style="color: #339933;">&gt;&lt;</span>div style<span style="color: #339933;">=</span><span style="color: #4444ff;">&quot;width: 20px; text-align: center&quot;</span><span style="color: #339933;">&gt;</span>
                <span style="color: #339933;">&lt;</span>strong style<span style="color: #339933;">=</span><span style="color: #4444ff;">&quot;color: #666&quot;</span><span style="color: #339933;">&gt;</span>A<span style="color: #339933;">.&lt;/</span>strong<span style="color: #339933;">&gt;&lt;/</span>div<span style="color: #339933;">&gt;&lt;/</span>td<span style="color: #339933;">&gt;</span>
        <span style="color: #339933;">&lt;</span>td<span style="color: #339933;">&gt;</span>
        <span style="color: #339933;">&lt;</span>div <span style="color: #999999; font-weight: bold;">class</span><span style="color: #339933;">=</span><span style="color: #4444ff;">&quot;faq-entry-description&quot;</span><span style="color: #339933;">&gt;</span>
            <span style="color: #999999; font-weight: bold;">&lt;?=</span><span style="color: #6666FF;">$cobj</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">getCollectionDescription</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #999999; font-weight: bold;">?&gt;</span>
            <span style="color: #339933;">&lt;</span>a href<span style="color: #339933;">=</span><span style="color: #4444ff;">&quot;&lt;?=<span style="color: #006699; font-weight: bold;">$nh-&gt;getLinkToCollection</span>(<span style="color: #006699; font-weight: bold;">$cobj</span>)?&gt;&quot;</span> 
                style<span style="color: #339933;">=</span><span style="color: #4444ff;">&quot;font-weight: bold&quot;</span><span style="color: #339933;">&gt;</span>Read More <span style="color: #339933;">&gt;&lt;/</span>a<span style="color: #339933;">&gt;</span>
        <span style="color: #339933;">&lt;/</span>div<span style="color: #339933;">&gt;</span>
        <span style="color: #339933;">&lt;/</span>td<span style="color: #339933;">&gt;</span>
    <span style="color: #339933;">&lt;/</span>tr<span style="color: #339933;">&gt;</span>
    <span style="color: #339933;">&lt;</span>tr<span style="color: #339933;">&gt;</span>
        <span style="color: #339933;">&lt;</span>td colspan<span style="color: #339933;">=</span><span style="color: #4444ff;">&quot;2&quot;</span><span style="color: #339933;">&gt;&lt;</span>br<span style="color: #339933;">/&gt;&lt;/</span>td<span style="color: #339933;">&gt;</span>
    <span style="color: #339933;">&lt;/</span>tr<span style="color: #339933;">&gt;</span>
&nbsp;
    <span style="color: #999999; font-weight: bold;">&lt;?</span> <span style="color: #009900;">&#125;</span> <span style="color: #999999; font-weight: bold;">?&gt;</span>
&nbsp;
    <span style="color: #339933;">&lt;/</span>table<span style="color: #339933;">&gt;</span>
&nbsp;
    <span style="color: #999999; font-weight: bold;">&lt;?</span> <span style="color: #009900;">&#125;</span> <span style="color: #999999; font-weight: bold;">?&gt;</span>
&nbsp;</pre></div><p>Followed by</p><div class="ccm-syntax-highlighter">
<pre class="javascript" style="font-family:monospace;">    <span style="color: #339933;">&lt;</span>script type<span style="color: #339933;">=</span><span style="color: #3366CC;">&quot;text/javascript&quot;</span><span style="color: #339933;">&gt;</span>
    toggleFAQEntry <span style="color: #339933;">=</span> <span style="color: #006699; font-weight: bold;">function</span><span style="color: #118811;">&#40;</span><span style="color: #000066; font-weight: bold;">item</span><span style="color: #118811;">&#41;</span> <span style="color: #118811;">&#123;</span>
        <span style="color: #006699; font-weight: bold;">var</span> desc <span style="color: #339933;">=</span> $<span style="color: #118811;">&#40;</span><span style="color: #3366CC;">'#fa'</span> <span style="color: #339933;">+</span> <span style="color: #000066; font-weight: bold;">item</span><span style="color: #118811;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #118811;">&#40;</span>desc.<span style="color: #996699;">css</span><span style="color: #118811;">&#40;</span><span style="color: #3366CC;">'display'</span><span style="color: #118811;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #3366CC;">'none'</span><span style="color: #118811;">&#41;</span> <span style="color: #118811;">&#123;</span>
            desc.<span style="color: #996699;">fadeIn</span><span style="color: #118811;">&#40;</span><span style="color: #CC0000;">200</span><span style="color: #118811;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #118811;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #118811;">&#123;</span>
            desc.<span style="color: #996699;">hide</span><span style="color: #118811;">&#40;</span><span style="color: #118811;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #118811;">&#125;</span>
    <span style="color: #118811;">&#125;</span>
    <span style="color: #339933;">&lt;/</span>script<span style="color: #339933;">&gt;</span>
&nbsp;</pre></div><p>This is simply a repurposed view.php from the existing core Page List block. Instead of showing the description, we keep the description hidden and create a custom JavaScript method that fires when clicking on the FAQ question.</p>
<h3>Add a Page List and Apply the Custom Template</h3>
<p>Add the Page List block on your various FAQ Section pages, configure them to show their child pages, and then assign this custom template to them.&nbsp;</p>
<div class="main-image">
	<div><img src="/files/5012/7309/6094/Picture 13.png" class="footer-image" width="417" height="245" alt="footer image" /></div>


</div><p>And that's it!</p>
<h2>Conclusion</h2>
<p>At this point you should see easy it is for a developer to create a fully interactive, full-featured editing interface for pages, using the concrete5 single page approach. Your administrative users will be able to add and edit FAQ entries without interacting with the front-end interface at all. Pages are still created, meaning that they can be moved, updated, tweaked and customized using existing concrete5 editing interfaces, themes and add-ons.&nbsp;</p>
<h3>Download</h3>
<p style="padding-left: 30px;"><a href="http://www.concrete5.org/files/2012/7309/4756/example_faq_code.zip ">Click here to download the code found in this example.</a> (10 KB)</p>
<p>This code is also available as free add-on in our marketplace</p>
<p style="padding-left: 30px;"><a href="http://www.concrete5.org/marketplace/addons/example-faq/" target="_blank">http://www.concrete5.org/marketplace/addons/example-faq/ </a></p>
<p><span class="byline">Andrew Embler likes showing off what can be done with concrete5.</span></p>				<br/><br/>
				<a href="http://andrewembler.com/concrete5/build-a-single-page-powered-editing-interface-for-concrete5/">Comment on this at andrewembler.com</a>
			  ]]>
			  </description>
			  <pubDate>Wed, 05 May 2010 19:56:00 EDT</pubDate>
			</item>
		
			<item>
			  <title>SEO Tip: Force concrete5 Pages to Display at One URL</title>
			  <link>http://andrewembler.com/concrete5/seo-tip-force-concrete5-pages-to-display-at-one-url/</link>
			  <description>
			  <![CDATA[
				<div class="tweetmeme_button" style="float: right; margin-left: 15px; margin-right: 5px;">
<iframe src="http://api.tweetmeme.com/button.js?url=http%3A%2F%2Fandrewembler.com%2Ffeed%2F&source=&style=normal&service=default" height="61" width="50" frameborder="0" scrolling="no">
</iframe>
</div><p>I use <a href="http://www.disqus.com" target="_blank">Disqus</a> web comments on this site. They're great: they handle threading, login from multiple sources, monitoring and post by email, user avatars, and some other things that I'm glad I don't have to deal with. Each page contains a snippet of JavaScript that, when loaded, sends the page's URL to the Disqus servers, and retrieves any comments posted against that URL.</p>
<p>I'd had no problems with this setup until just the other day, when I received notification of a new comment to an article, and I could not for the life of me locate the comment on the page. The article had fourteen comments, and yet only thirteen displayed, the latest from a month or two ago. I was apparently dealing with a phantom comment. Frustrated, I logged into the main disqus.com website, where I was able to locate the comment, alongside all the others. According to Disqus, it was approved and active on the page. But where was it?!</p>
<p>The clue came when I looked at the story to which the comment was attached. All fourteen comments were attached to "andrewembler.com :: Optimizing your concrete5 Website for the iPhone" &ndash; but the thirteen that displayed linked to that story here:</p>
<p style="padding-left: 30px;">http://andrewembler.com/concrete5/optimizing-your-concrete5-website-for-the-iphone/</p>
<p>While the orphaned comment linked to it here:</p>
<div id="HTMLBlock410" class="HTMLBlock">
<p style="padding-left: 30px;">http://andrewembler.com/index.php?cID=87</p></div><p style="text-align: left;">Sure enough, when I visited that URL, the same article rendered, but with one comment &ndash; the new comment &ndash; instead of the other thirteen. Since Disqus provides no move tools, this comment is stuck on this page. But I <strong>can</strong>&nbsp;make sure that this doesn't happen again.</p>
<p style="text-align: left;"><span style="color: #ffffff; font-size: 24px; line-height: 31px;">Background: the cID</span></p>
<p>Every page of content added to a concrete5 website has one unique ID attached to it. This is referred to as the collection ID, and is frequently abbreviated in functions and URLs as "cID." Why "collection" ID, rather than "page" ID? Originally, when concrete5 first came into being in late 2003, its pages were referred to as Collections &ndash; since they were thought of as collections of blocks. As concrete5 matured and started using attributes, themes, page types and more complex objects, we thought just calling them pages &ndash; which is, after, what they are &ndash; was less of a barrier to entry. The "cID" parameter is still actively used, however, and it's this cID which makes its unsightly appearance in the URL above.&nbsp;</p>
<p>Basically, my concrete5 iPhone article can be accessed at <strong>two </strong>URLs. The cID URL, which loads the article based on its ID in the database, and the full SEO-friendly URL. (<strong>Note</strong>: you may have more than one URL as well, but since concrete5 5.3 they redirect to the canonical URL.) Why? In concrete5, pages can be created well before their actual canonical URL is chosen. Most concrete5 navigation and linking tools will link directly to the canonical URL, but somehow, if a user stumbles on the cID URL, the page will still render without redirection. Usually this isn't a problem, but as we've seen in my example, it can lead to some very undesirable situations. I'm going to show you how to fix that.</p>
<h2>The Task</h2>
<p>I want to ensure that a comment can never be mis-posted again. I've already fixed as many areas in the concrete5 core that link to the cID URL of pages, but there's still no telling what people might accidentally link to or stumble upon. I need something that will redirect them if they land on a page via its cID URL.</p>
<p>This can't be too greedy, however: the cID-powered URL is used very, very frequently while concrete5 sites are in edit mode. What I really want is this: if a user comes to any page on my site by way of the cID URL, and they are <strong>not </strong>logged in (i.e - they're not editing a page), they should be redirected to that page's canonical URL via a 301 redirect.</p>
<h2>Step 1: create config/site_post.php</h2>
<p>There are a number of ways to accomplish our goal. I've already mentioned concrete5's events system in previous articles, so here I'm going to take an even simpler approach, and introduce you to config/site_post.php. This is an optional file that site owners may create in their local config/ directory that will automatically be loaded after all configuration files and database connections have been made. This lets us hook into concrete5's loading process relatively early. Note: theme information and some other core information about a request will <strong>not</strong>&nbsp;be available this early, but for our purposes it should work nicely.</p>
<h2>Step 2: Add Code</h2>
<p>Once you have an empty file at config/site_post.php, add this code to it:</p><div class="ccm-syntax-highlighter">
<pre class="php" style="font-family:monospace;"><ol><li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;"><span style="color: #999999; font-weight: bold;">&lt;?php</span></div></li><li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">   <span style="color: #6666FF;">$req</span> <span style="color: #339933;">=</span> Request<span style="color: #339933;">::</span><span style="color: #00FF00;">get</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></li><li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">      <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$req</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">getRequestCollectionID</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&gt;</span> <span style="color: #cc66cc;">1</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #6666FF;">$req</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">getRequestPath</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #4444ff;">''</span> </div></li><li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">         <span style="color: #339933;">&amp;&amp;</span> <span style="color: #6666FF;">$_SERVER</span><span style="color: #009900;">&#91;</span><span style="color: #4444ff;">'REQUEST_METHOD'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">!=</span> <span style="color: #4444ff;">'POST'</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span></div></li><li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">      <span style="color: #999999; font-style: italic;">// This is a request that is directly for the cID, rather than the path</span></div></li><li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">      <span style="color: #6666FF;">$u</span> <span style="color: #339933;">=</span> <span style="color: #999999; font-weight: bold;">new</span> User<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></li><li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">      <span style="color: #999999; font-style: italic;">// If the user is logged in we do NOT redirect</span></div></li><li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">      <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #6666FF;">$u</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">isRegistered</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span></div></li><li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">         <span style="color: #999999; font-style: italic;">// Get the page object for the current cID</span></div></li><li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">         <span style="color: #6666FF;">$c</span> <span style="color: #339933;">=</span> Page<span style="color: #339933;">::</span><span style="color: #00FF00;">getByID</span><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$req</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">getRequestCollectionID</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></li><li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">         <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #6666FF;">$c</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">isError</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span></div></li><li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">            <span style="color: #6666FF;">$nav</span> <span style="color: #339933;">=</span> Loader<span style="color: #339933;">::</span><span style="color: #00FF00;">helper</span><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'navigation'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></li><li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">            <a href="http://www.php.net/header"><span style="color: #990000;">header</span></a> <span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'HTTP/1.1 301 Moved Permanently'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></li><li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">            <a href="http://www.php.net/header"><span style="color: #990000;">header</span></a><span style="color: #009900;">&#40;</span><span style="color: #4444ff;">'Location: '</span> <span style="color: #339933;">.</span> <span style="color: #6666FF;">$nav</span><span style="color: #339933;">-&gt;</span><span style="color: #00FF00;">getLinkToCollection</span><span style="color: #009900;">&#40;</span><span style="color: #6666FF;">$c</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></li><li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">            <a href="http://www.php.net/exit"><span style="color: #990000;">exit</span></a><span style="color: #339933;">;</span></div></li><li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">         <span style="color: #009900;">&#125;</span></div></li><li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">      <span style="color: #009900;">&#125;</span></div></li><li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">   <span style="color: #009900;">&#125;</span></div></li><li style="font-weight: normal; vertical-align:top;"><div style="font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;">&nbsp;</div></li></ol></pre></div><p>Let's walk through exactly what's happening here:</p>
<ul>
<li><strong>Lines 1-4: </strong>First, we grab the concrete5 <a href="http://www.concrete5.org/documentation/developers/system/request/" target="_blank">Request</a> object. Then, we check that object to see if the current request is for a cID, and the current request has a null path. We ensure that the current request's cID is greater than one, so that our home page (which is always a cID request, since it has no path) will be ignored in this check. <strong>Update: we also check to make sure we're not doing a POST (see note in the comment).</strong></li>
<li><strong>Lines 5-8: </strong>If this is the case, we want to proceed with our redirection. We then instantiate the <a href="http://www.concrete5.org/documentation/developers/permissions/users" target="_blank">User</a>&nbsp;object, and check to see that the current User object is not logged in. If the user is not logged in, we proceed with our redirection routine.</li>
<li><strong>Lines 9-11: </strong>Now, we grab the page object for the current requested page ID, and check to ensure that there's no error associated with this page object. Additionally, we make sure that the page object does, in fact, have a valid path (since if it didn't, we'd get stuck in an infinite redirect loop.) If that's the case, then...</li>
<li><strong>Lines 12-15: </strong>We load up our navigation helper, issue a permanently moved header (for the benefits of any search engines following these links) and we redirect the URL to the canonical URL for the page.</li>
</ul>
<h2>Step 3: Profit!</h2>
<p>Try it for yourself:</p>
<div id="HTMLBlock414" class="HTMLBlock">
<p style="padding-left: 30px"><a href="http://andrewembler.com/index.php?cID=87" target="_blank">http://andrewembler.com/index.php?cID=87</a></p></div><p>This is the URL that was causing so many problems before. Hopefully the orphaned comments are a thing of the past.</p>
<p>Yes, we ought to include something like this in the core &ndash; but as you've seen here, it's not a perfect solution, and could cause problems for certain sites. For example, this wouldn't work on sites that include community functionality that use logged-in users frequently. But on a blog or a site where the only logged-users are those who edit the site, it should be a nice, useful snippet of code to keep you, your readers and your search engine robots happy.</p>
<p><span class="byline">Andrew Embler hopes you're reading this at one &ndash; and only one &ndash; URL.</span></p>				<br/><br/>
				<a href="http://andrewembler.com/concrete5/seo-tip-force-concrete5-pages-to-display-at-one-url/">Comment on this at andrewembler.com</a>
			  ]]>
			  </description>
			  <pubDate>Tue, 20 Apr 2010 14:10:00 EDT</pubDate>
			</item>
		
			<item>
			  <title>Dear Apple: It's Time to Listen to the Canary in the Coal Mine</title>
			  <link>http://andrewembler.com/apple/dear-apple/</link>
			  <description>
			  <![CDATA[
				<div class="tweetmeme_button" style="float: right; margin-left: 15px; margin-right: 5px;">
<iframe src="http://api.tweetmeme.com/button.js?url=http%3A%2F%2Fandrewembler.com%2Ffeed%2F&source=&style=normal&service=default" height="61" width="50" frameborder="0" scrolling="no">
</iframe>
</div><p>Apple and its iTunes App Store have been getting a lot of negative press amongst developers lately. Its stance against the use of private APIs, the introduction of its own ad network, and its <a href="http://daringfireball.net/2010/04/iphone_agreement_bans_flash_compiler" target="_blank">rewording of the iPhone Developer agreement to exclude third party runtimes and cross-compilation tools</a> has gotten a lot of people angry. Gizmodo calls ads an iPhone user's "<a href="http://gizmodo.com/5512772/apple-wants-18th-of-your-iphone-backdont-give-it-to-them" target="_blank">worst enemy</a>"; an official Adobe representative invited Apple to "<a href="http://theflashblog.com/?p=1888" target="_blank">go screw itself</a>". Apparently, even Steve Jobs could sense something was brewing, and he <a href="http://www.taoeffect.com/blog/2010/04/steve-jobs-response-on-section-3-3-1/" target="_blank">actively responded to one of the more reasonable pleas regarding the situation</a>.&nbsp;</p>
<p>Do I agree with all of the criticism coming Apple's way? Hardly. In fact, <a title="Apple iPad, Private APIs, and a Tempest in a Teapot" href="/apple/apple-ipad-private-apis-and-a-tempest/">I just published an article in which I defend Apple on its stance regarding private APIs</a>. I'm sympathetic to what they're trying to do, and I understand the challenges inherent in it. I don't dismiss advertising out of hand. Additionally, I'm not one to blindly dismiss a company's choices without trying to understand why they make them.&nbsp;</p>
<p>In fact, I was going to let the situation blow over without comment, content that the entire thing was a ginned-up&nbsp;controversy for the sake of page views (*cough* Gizmodo *cough*), until I stumbled on to this:</p>
<p><a href="http://arstechnica.com/staff/fatbits/2010/04/apples-wager.ars" target="_blank">Ars Technica: Apple's Wager, by John Siracusa</a></p>
<p>I didn't agree with everything in it, and many of the comments attached to it are inane, but I felt compelled to read it regardless, as its by the estimable Siracusa. He's always been one of Apple and Mac OS's greatest ambassadors and thoughtful technology writers, a fact to which anyone who's read his fantastic reviews of every OS release can attest. And yet, in this article he describes the development environment created by Apple as "shoddy" and full of "hardships."&nbsp;</p>
<p>That, my friends, is troubling. When the reasonable and thoughtful defenders of your platform start to become concerned with your direction and methods, it may not matter whether your concerns are ultimately right.&nbsp;Apple would do well to take a step back and listen to the concerns of some of these folks. It's not like they <a href="http://daringfireball.net/2009/08/phil_schiller_app_store" target="_blank">haven't done so before</a>.&nbsp;</p>
<p><span class="byline">Andrew Embler still wants an iPad.</span></p>				<br/><br/>
				<a href="http://andrewembler.com/apple/dear-apple/">Comment on this at andrewembler.com</a>
			  ]]>
			  </description>
			  <pubDate>Tue, 13 Apr 2010 04:40:00 EDT</pubDate>
			</item>
		
			<item>
			  <title>Apple iPad, Private APIs, and a Tempest in a Teapot</title>
			  <link>http://andrewembler.com/apple/apple-ipad-private-apis-and-a-tempest/</link>
			  <description>
			  <![CDATA[
				<div class="tweetmeme_button" style="float: right; margin-left: 15px; margin-right: 5px;">
<iframe src="http://api.tweetmeme.com/button.js?url=http%3A%2F%2Fandrewembler.com%2Ffeed%2F&source=&style=normal&service=default" height="61" width="50" frameborder="0" scrolling="no">
</iframe>
</div><p>In the wake of the <a href="http://ptech.allthingsd.com/20100331/apple-ipad-review/" target="_blank">generally</a> <a href="http://www.suntimes.com/technology/ihnatko/2134139,ihnatko-ipad-apple-review-033110.article" target="_blank">positive</a> <a href="http://www.apple.com/ipad" target="_blank">iPad</a> <a href="http://www.nytimes.com/2010/04/01/technology/personaltech/01pogue.html?ref=technology&amp;pagewanted=all" target="_parent">reviews</a> circulating the web, a light developer backlash has occurred, in the form of <a href="http://www.marco.org/500743718" target="_blank">grousing about private APIs</a>. Of course, developer backlash around recent Apple products is not new: the moment the iPhone was announced, developers went ballistic that the recommended platform of choice was web apps; after a native app store was released, the protests turned to the byzantine and often arbitrary nature of its approval process.&nbsp;Now, with the iPad, it appears that there is something new to contest.&nbsp;</p>
<h2>Background: what are "Private APIs" ?</h2>
<p>Software systems that open themselves up to third party development provide ways by which developers may use built-in frameworks and libraries to build their applications. These are "application programming interfaces," or APIs. Public APIs are publicly accessible and documented, whereas private APIs &ndash; while still perhaps technically available to third party developers &ndash; are not.&nbsp;</p>
<p>It's important to note that there is very little that separates a public API from a private one, beyond the fact that the public is documented, and "blessed." By blessed, I mean that that interface has been documented and described in the hopes that developers will use it, and with the implicit understanding that it is not likely to change in an incompatible way any time soon. Private APIs offer no such guarantee. If developers can find them, they can technically use them &ndash; but there is nothing stating that they won't just disappear the next time the core software is updated. For their own safety, third party developers ought to tread lightly. Private APIs are generally regarded as unfinished, half-baked, and likely subject to change.</p>
<p>Software products that encourage add-ons don't want their third party developers to use private APIs, because that frequently leads to third party software that requires frequent updates, any time the underlying core is changed. For example, on Mac OS X there are a number of "haxies" &ndash; software programs which modify OS X's appearance or low level behavior in ways Apple hasn't foreseen or blessed. Users install this software because they aren't completely happy with the way OS X functions. To do what they do, these programs take advantage of functionality that Apple hasn't documented for the outside world. The result? Whenever updating OS X, make damn sure you check to see that there's an update to all this third party software first, because it's quite likely that the private APIs have changed in some way, and updating the core will lead to an unstable or unworking system.</p>
<h3>Enter the App Store</h3>
<p>The micromanagement of the updating process as described above is tedious. Even worse, most computer users will fault the OS for breaking their favorite extensions, when in fact their extensions are built on a shifting foundation. But with the iPhone and iPad app store, Apple has implicitly guaranteed that their device is more an appliance than a typical computer system, and appliances can't require this same level of maintenance. They have to "just work." That's why Apple has rejected apps from the app store which use private APIs. Most developers will tell you that's reasonable.&nbsp;</p>
<h2>Do as I say (not as a I do)</h2>
<p>Then what's the problem? Apple has apps, within the app store, <strong>which use private APIs!</strong>&nbsp;Why does Apple get to play by a different set of rules than third party developers?!&nbsp;</p>
<p>This seems like a reasonable complaint, right? Obviously, Apple can do what they want with their store, but isn't that somewhat skeezy (for lack of a better term?)</p>
<h2>No. It's necessary.</h2>
<p>If you'll permit me, I'm going to proceed with a tangent. In concrete5 version 5.2, we introduced a new class named PageList. This class was meant to provide an object-oriented and extendable way to search and filter pages, and replace the ailing, old and poorly thought-out CollectionSearch class. While we did have portions of the PageList class documented when it was released, we didn't release official documentation for it until <a href="http://www.concrete5.org/documentation/developers/pages/searching-and-filtering" target="_blank">just recently</a>.</p>
<p>Why? Simply put, the class wasn't ready. It was 80% of the way, but we knew that underlying frameworks that the class referenced weren't totally stable, and that the class and its API were likely to change. It wouldn't be smart for us to recommend third party developers use and rely on this API when we know its still in flux.&nbsp;</p>
<p>And yet, did that stop us from using the class in production and throughout the core, where applicable? No. Why? Two reasons: 1) we needed to put it through its paces, and 2) <strong>real artists ship! </strong>We needed to get 5.2 out there, and we couldn't spend the time exhaustively documenting and planning the entirety of the class, especially as we knew it would eventually interact with entire libraries and objects that hadn't even been planned yet. We needed to use code in projects and add-ons to see where the class fell short, and what it needed.</p>
<p>Fundamentally, I imagine Apple &ndash; and the iPad project in particular &ndash; is no different. When the word comes from on high that the project, including its apps, must be ready, who's going to tell Steve Jobs that the APIs used by the iBooks app need to be completely set in stone, documented, and shared with the developer community? Heh, you first! Instead, the team packages up what they have and uses it as a starting point, and the <strong>private APIs evolve organically into the public ones</strong>! Ship first, refine, improve, and then publish. That way, you'll see where you application interface needs tweaking and fixing. Far better to iron out the kinks before the API is published and made available to third party developers, than release the documentation too early, and have a slew of apps that require updates when an update to the API breaks them.&nbsp;</p>
<h2>In Conclusion</h2>
<p>To the developers bashing Apple over this, I'd ask you to consider the position of the framework manager, or the manager of the entire iPhone OS ecosystem. Step outside of the ideal world and start thinking pragmatically. Yes, there are some very valid concerns regarding Apple and its handling of the app store, but I don't think this is one of them. Besides &ndash; it sounds like there's <a href="http://blogs.adobe.com/conversations/2010/04/cs5_countdown_is_on.html" target="_blank">already something brewing that makes this seem like small potatoes</a>.</p>
<p><span class="byline">Andrew Embler loves having enough time to completely and thoroughly design every single aspect of concrete5's third party interfaces &ndash; but rarely, rarely gets it.</span></p>				<br/><br/>
				<a href="http://andrewembler.com/apple/apple-ipad-private-apis-and-a-tempest/">Comment on this at andrewembler.com</a>
			  ]]>
			  </description>
			  <pubDate>Tue, 13 Apr 2010 01:27:00 EDT</pubDate>
			</item>
		
			<item>
			  <title>6 Things I Learned As an Exhibitor at SXSW Interactive 2010</title>
			  <link>http://andrewembler.com/web/6-things-i-learned-sxsw-interactive-2010/</link>
			  <description>
			  <![CDATA[
				<p>This year, concrete5 was able to do something we'd never done before: attend SXSW Interactive, which is probably one of the most important events out there for a company like us. The event is over. I'm tired, beat up, homesick and getting on a plane in an hour, but none of that matters: right now, the most important thing is to share some knowledge with you. (Note: if this interests you at all, make sure you catch <a href="http://www.concrete5.org/community/forums/chat/sxsw-wrapup/" target="_blank">Franz's eloquent thoughts on the subject as well</a>.)</p>
<h2>Make Time for Lunch</h2>
<p>So, we get into Austin on Friday. We set up. Everything is ready. Saturday, the trade show opens, and we're rocking it. Giving away stickers. People are interested in our CMS. Making connections. Truly, having it all. Well, with the exception of lunch, which completely dropped off our radar.&nbsp;</p>
<p>This was a mistake.&nbsp;Yeah, we had some energy bars, but those don't count.&nbsp;In spite of all the material we'd read, the trade show actually ended at 6:00 PM, rather than 5:00 PM. Turns out this extra hour matters: at 6:30 we were so tired that we ate in silence. Didn't derail the entire evening, but it came damn close.</p>
<p>However, with this in mind, note the following sub-tip:</p>
<h3>Monster&reg; Brand Energy Drink is not an Acceptable Substitute for Lunch or a more Modest Cocktail Mixer</h3>
<p>It will, however, totally fulfill its intended purpose. But this blast of energy comes with a terrible price (and not just the $5.50 an entire can costs from the vendor): when the time comes that you want to sleep, you will be unable to do so. And should you actually fall into some semblance of slumber, your dreams will be dizzying, frenetic affairs replete with visceral altercations. After the opening night party, during which I drank a fair amount of Vodka mixed with this crazy chemical, I had no fewer than four dreams featuring fights, brawls, wrestling, slamming and generally boorish behavior.&nbsp;At least, I'm pretty sure those were dreams.&nbsp;</p>
<p>Mark my words: nights after enjoying this concoction are no respite.&nbsp;</p>
<p><span style="color: #ffffff; font-size: 24px; line-height: 31px; ">Wear Comfortable Shoes</span></p>
<p>This seems obvious, but I'm going to state it anyway. There's going to be a lot of standing around in your future, and your feet will thank you. Again: <strong>comfortable </strong>doesn't mean that you can wear them without them causing problems. Comfortable means comfortable. I wore some shoes that I didn't think twice about, and at the end of the first day my legs were nothing but knots. By contrast, throughout the rest of the trade show I wore shoes I actively consider comfortable (but still stylish, natch), and these problems were greatly lessened.</p>
<div><span style="color: #ffffff; font-size: 24px; line-height: 31px;">Don't Worry too much About your Pitch</span></div>
<p>I'm going to retreat from the general advice and get deep into some business. Some might disagree with me on this, but hear me out: your pitch doesn't really matter. For example, we had some carefully scripted demos planned, including a scheduled time to show off the interface to a larger group of people. We never did this. And even the individual demos became something we worked with as a last resort. Instead, it's better to engage with a person, figure out what they do, and inform them how your stuff can improve that experience. If it can't, be honest and move on.&nbsp;</p>
<p>I know this advice isn't terribly insightful, but given my stroll around the trade show floor, I know there are those out there who'd benefit from it.&nbsp;</p>
<h2>If you can, Stay Near the Action</h2>
<p>This year, the four of us stayed at a vacation rental about five miles outside the city center. I'd consider this a mistake. In truth, I'm torn on this, because the rental was nice. But I feel like we made this choice considering Austin similar to Portland, which, when it comes to transportation, it definitely is not. The website for the bus is pretty nice, but the actual buses themselves looked a little dubious to our eyes. Additionally, the traffic during rush hour is maddening, as are the highways themselves. Staying in downtown gives you so much flexibility that next time I'd really have to be persuaded to do otherwise.&nbsp;</p>
<p>Granted, we needed a car to ferry equipment to the exhibit hall, which means we couldn't get by without renting one. Additionally, I am (thankfully!) fairly removed from the specifics of the financials as they differ from hotel to rental, but I can imagine the savings were substantial. I will however still state that they are not without their own alternate cost.</p>
<p><span style="color: #ffffff; font-size: 24px; line-height: 31px;">Try and Catch a Session Or Two</span></p>
<p>We were busy. Actually, hold on: we were<strong>&nbsp;very</strong>&nbsp;busy. So it's not surprising that I wasn't able to make it to any of the sessions. But I do have a bit of regret regarding that decision. True, we are pretty certain we have this industry figured out, especially regarding our own corner of it, but that's no excuse to get complacent. Companies do that, and they get beaten. So keeping an open mind, an open calendar, and taking a chance to network outside of the exhibit hall probably would have been valuable in some way.</p>
<p><span style="color: #ffffff; font-size: 24px; line-height: 31px;">Be Flexible</span></p>
<p>This relates to my previous point: please, please, <strong>please</strong>, above all else, be flexible. I didn't go to any sessions, even though I had specifically marked them in my handy SXSW calendar. But you know what? I didn't do <strong>anything</strong>&nbsp;that I had put in my calendar! Not various keynotes, nor the parties. Yes, we went to parties, met some great people and generally had a great time, but nothing seemed to ensure me <strong>not</strong>&nbsp;doing something quite as well as me taking the time to put it in my calendar.&nbsp;</p>
<p>The lines are long, and there's so much to do that if you try and stack up a calendar to catch everything, you're either going to spend very little time at each of the things you want to do, or you're going to miss certain things. It's going to happen. Roll with it and enjoy yourself. We did.</p>				<br/><br/>
				<a href="http://andrewembler.com/web/6-things-i-learned-sxsw-interactive-2010/">Comment on this at andrewembler.com</a>
			  ]]>
			  </description>
			  <pubDate>Sat, 20 Mar 2010 23:00:00 EDT</pubDate>
			</item>
				
		</channel>
	</rss>
	
	