<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Learn dotCMS</title>
	
	<link>http://learndotcms.com</link>
	<description>Helpful hints, tip, tricks, and code so that you can master dotCMS</description>
	<lastBuildDate>Fri, 19 Apr 2013 03:03:16 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/LearnDotcms" /><feedburner:info uri="learndotcms" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>Geolocation Viewtool</title>
		<link>http://feedproxy.google.com/~r/LearnDotcms/~3/2wcFdf-VOxs/</link>
		<comments>http://learndotcms.com/2013/04/geolocation-viewtool/#comments</comments>
		<pubDate>Thu, 11 Apr 2013 21:58:11 +0000</pubDate>
		<dc:creator>Chris Falzone</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Plugins]]></category>
		<category><![CDATA[Viewtools]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[geolocation]]></category>
		<category><![CDATA[location]]></category>
		<category><![CDATA[maxmind]]></category>

		<guid isPermaLink="false">http://learndotcms.com/?p=572</guid>
		<description><![CDATA[Geolocation &#8211; The Options and Issues At Aquent, we have relied on being able to determine where our visitors are coming from for some time now. This allows us to target specific information to visitors based on where they are coming from. Getting that information is becoming easier and easier as there is no shortage [...]]]></description>
				<content:encoded><![CDATA[<div class="github-widget" data-repo="aquent/com.aquent.plugins.geolocation"></div>
<h3>Geolocation &#8211; The Options and Issues</h3>
<p>At <a href="http://aquent.com" title="Aquent">Aquent</a>, we have relied on being able to determine where our visitors are coming from for some time now.  This allows us to target specific information to visitors based on where they are coming from.  Getting that information is becoming easier and easier as there is no shortage of <a href="https://www.google.com/search?q=GeoIP+Lookup+Service&#038;aq=f&#038;oq=GeoIP+Lookup+Service&#038;aqs=chrome.0.57j0l3j62.595j0&#038;sourceid=chrome&#038;ie=UTF-8">GeoIP Lookup Services</a> available; from free services to paid, client-side and server-side, and in any programming language you could ask for.  A couple of these we have used to varying degrees of success.  The guys over at <a href="http://dotcms.org" title="dotCMS">dotCMS</a> have actually came up with a pretty nice example implementation on the <a href="http://demo.dotcms.com/">2.2 Demo Site</a>:</p>
<pre class="brush: xml; title: ; notranslate">
  #set($clickstream  = $session.getAttribute(&quot;clickstream&quot;))
  
  #set($geolocationFromSession = $session.getAttribute(&quot;geolocation&quot;))
 
  #if(!$UtilMethods.isSet($geolocationFromSession))
    #set($locationURL = &quot;http://www.geoplugin.net/json.gp?ip=$!clickstream.remoteAddress&quot;)
    #set($geolocation = $json.fetch(&quot;$!locationURL&quot;))
    $session.setAttribute(&quot;geolocation&quot;, $geolocation)
  #else
    #set($geolocation = $session.getAttribute(&quot;geolocation&quot;))
  #end
</pre>
<p>This code is using the <a href="http://dotcms.com/docs/latest/JSONObjects" target="_blank">JSON tool</a> to access <a href="http://www.geoplugin.com/" target="_blank">geoPlugin&#8217;s free service</a>.  It even goes as far as storing the data for the user&#8217;s session. At Aquent, we have used similar approaches.  However, there is one slightly annoying issue with this approach that we ran into.  What happens when geoPlugin&#8217;s service is not available?  Unfortunately the JSON tool is not very resilient here.  It holds on to the connection and will wait for it to timeout for a very long time.  No amount of configuration seems to get it to fail-over quickly.  On a busy site this quickly eats up HTTP connections and even has the potential to take your site down.  Anyone who has worked with the JSON or XML tools to pull in 3rd-party resources into their dotCMS implementation knows exactly what I am talking about.</p>
<h3>MaxMind Solution</h3>
<p>What we wanted to do at Aquent was come up with a solution that does not depend on connections to an external site, has fast and accurate data that is easy to keep up to date, and is simple for our front-end developers to use.  This is where <a href="http://www.maxmind.com/en/home" target="_blank">MaxMind</a> comes in.  MaxMind provides several databases that you can download that are kept up to date weekly.  Their <a href="https://github.com/maxmind/geoip-api-java" target="_blank">Open Source Java API</a> is lightning fast at looking up the data and very easy to use.  They also supply a way to <a href="http://www.maxmind.com/en/license_key">download the database files automatically</a>.  They offer both paid versions of the databases as well as free versions for public use (which aren&#8217;t updated quite as often, and will be a little less accurate as a result).  </p>
<p>We decided to go with the <a href="http://dev.maxmind.com/geoip/geolite" target="_blank">GeoLite City Database</a> for now, but plan on upgrading to the full version of the <a href="http://www.maxmind.com/en/city" target="_blank">City Lookup Database</a> in the near future.  We decided to go the City Database so that we would be able to access a wide array of information about the visitor including:</p>
<ul>
<li>Country Name/Code</li>
<li>Region</li>
<li>City Name</li>
<li>Postal Code (US only)</li>
<li>Latitude and Longitude</li>
<li>DMA, Area and Metro Codes (US only)</li>
</ul>
<p>The only problem left to solve was to provide a way for our front-end developers to access the database in Velocity. The easiest way to accomplish this is a viewtool.  You can pick up the viewtool over at our <a href="https://github.com/aquent/com.aquent.plugins.geolocation" target="_blank">GitHub</a> repo. </p>
<h3> Writing the plugin </h3>
<p>Writing the viewtool plugin was not very difficult.  Here is quick overview of what we needed to do:</p>
<p>First, we need to compile the MaxMind Java API into a JAR that we could include in the plugin.  There are some instructions in their readme file on how to do this and the resulting jar file goes into the <a href="https://github.com/aquent/com.aquent.plugins.geolocation/tree/master/lib" target="_blank">lib folder</a> of the plugin.  Every plugin needs a <a href="https://github.com/aquent/com.aquent.plugins.geolocation/blob/master/MANIFEST.MF" target="_blank">MANIFEST.MF</a> and <a href="https://github.com/aquent/com.aquent.plugins.geolocation/blob/master/build.xml" target="_blank">build.xml</a> which can be copied from the example configuration plugin.  </p>
<p><a href="#usage">Click Here</a> if you want to skip the java and jump into using the viewtool.  Now for <a href="https://github.com/aquent/com.aquent.plugins.geolocation/blob/master/src/com/aquent/viewtools/GeoIP.java" target="_blank">the core code</a>:</p>
<pre class="brush: java; title: ; notranslate">
public class GeoIP implements ViewTool {
	private LookupService cityLookup;
	private boolean inited = false;
	PluginAPI pluginAPI = APILocator.getPluginAPI(); 
</pre>
<p>Every Viewtool must implement the ViewTool Interface.  Then we start off by creating a LookupService.</p>
<pre class="brush: java; title: ; notranslate">	
	@Override
	public void init(Object initData) {
</pre>
<p>The init method of a viewtool gets executed when the viewtool is created.  This can be different depending on what scope you set your viewtool as in your toolbox.xml.  For this project, I want the tool to init once when dotCMS starts up.  This is why I made the tool application scoped.</p>
<pre class="brush: java; title: ; notranslate">
		String dbFileName = &quot;&quot;;
		try {
			dbFileName = pluginAPI.loadProperty(&quot;com.aquent.plugins.geolocation&quot;, &quot;maxmind.dbFileName&quot;);
		} catch (Exception e) {
			Logger.error(this,&quot;Unable to load plugin property - maxmind.dbFileName&quot;, e);
			return;
		}
	
		String dbPath = &quot;&quot;;
		if (UtilMethods.isSet(Config.getStringProperty(&quot;ASSET_REAL_PATH&quot;))) {
			dbPath = Config.getStringProperty(&quot;ASSET_REAL_PATH&quot;) + File.separator + dbFileName;
		} else {
			dbPath = Config.CONTEXT.getRealPath(File.separator + Config.getStringProperty(&quot;ASSET_PATH&quot;) + File.separator + dbFileName);
		}	
</pre>
<p>We decided it would be best to store the database file in the assets directory.  This means if you are running in a clustered environment you only need to maintain the file in one place.  We then use a property in the plugin.properties file to determine the filename of the database to load.</p>
<pre class="brush: java; title: ; notranslate">
		try {
			cityLookup = new LookupService(dbPath, LookupService.GEOIP_MEMORY_CACHE | LookupService.GEOIP_CHECK_CACHE);
		} catch (Exception e) {
			Logger.error(this,&quot;Unable to get a LookupService&quot;,e);
			return;
		}
</pre>
<p>Now we create the LookupService and point it at our db file.  We decided to use their Memory Cache option for caching the DB to make the lookups faster.  You could also use the Standard or index cache options.  I am not sure at this point how large the full database is in memory so we may have to move to a different cache method in the future.  You can read more about the options in <a href="https://github.com/maxmind/geoip-api-java/blob/master/README">MaxMind&#8217;s Java API readme</a>.</p>
<pre class="brush: java; title: ; notranslate">
		// A flag to let the viewtool know we are good to go
		inited = true;
	}
</pre>
<p>Finally if we got to this point and there were no errors then we know the viewtool is inited.  I set a boolean flag so in my methods I know if the viewtool is inited or not.</p>
<p>The last part threw me off a bit.  I thought since the Location object contained public properties I could just return the Location Object and those properties could be accessed in Velocity. So I tried this first:</p>
<pre class="brush: java; title: ; notranslate">
	public Location getLocation(String ip) {
		Logger.debug(this, &quot;MaxMind GeoIP Viewtool - getLocation called with ip &quot;+ip);

		// Get the Location from the LookupService
		Location loc = null;
		if(inited) {
			loc = cityLookup.getLocation(ip);
		} else {
			Logger.info(this,&quot;Attempt to Call getLocation and not inited&quot;);
		}

		return loc;	
	}
</pre>
<p>Unfortunately it seems that velocity cannot just access properties on an object without getters and setters.  So I needed to provide a method that returned a map with all of the properties:</p>
<pre class="brush: java; title: ; notranslate">
	public Map&lt;String, Object&gt; getLocationMap(String ip) {
		Logger.debug(this, &quot;MaxMind GeoIP Viewtool - getLocationMap called with ip &quot;+ip);

		// Get the Location from the LookupService
		Location loc = null;
		Map&lt;String, Object&gt; locMap = new HashMap&lt;String, Object&gt;();
		if(inited) {
			loc = cityLookup.getLocation(ip);
			locMap.put(&quot;countryCode&quot;, loc.countryCode);
			locMap.put(&quot;countryName&quot;, loc.countryName);
			locMap.put(&quot;region&quot;, loc.region);
			locMap.put(&quot;city&quot;, loc.city);
			locMap.put(&quot;postalCode&quot;, loc.postalCode);
			locMap.put(&quot;latitude&quot;, loc.latitude);
			locMap.put(&quot;longitude&quot;, loc.longitude);
			locMap.put(&quot;dma_code&quot;, loc.dma_code);
			locMap.put(&quot;area_code&quot;, loc.area_code);
			locMap.put(&quot;metro_code&quot;, loc.metro_code);
		} else {
			Logger.info(this,&quot;Attempt to Call getLocationMap and not inited&quot;);
		}

		return locMap;
	}
</pre>
<p>We decided to keep both methods because the Location Object has a nice distance method to compute the distance between 2 locations. We even decided to include a few helper methods so that you can pass in a latitude and longitude and get the distance as well.  I know our front-end developers will enjoy this as we have lat/long in some of our structures already.  </p>
<p>The last thing our plugin needed was the <a href="https://github.com/aquent/com.aquent.plugins.geolocation/blob/master/conf/toolbox-ext.xml">toolbox mapping</a>. Pretty simple, give it a key that will be used in velocity to map to the viewtool, a scope, and point it at your viewtool&#8217;s class.  As I stated before, for this project it made sense to make this an application scoped viewtool so that we only need to do the heavy operation of loading the database into memory once.  </p>
<p><a name="usage" /><br />
<h3> Using the plugin </h3>
<p>So you are probably wondering at this point how to use the viewtool. The first thing you will need to do is grab the source from GitHub. You can either clone the repository or download it in a <a href="https://github.com/aquent/com.aquent.plugins.geolocation/tags" target="_blank">tar or zip</a> form.  You are going to want to then extract or clone that thing into your dotCMS&#8217;s plugin directory.  </p>
<p>Next you will need to obtain the database file from MaxMind.  Remember that you will need the City Database for this as the Country database will not work.  You can either purchase the full version or download the <a href="http://dev.maxmind.com/geoip/geolite" target="_blank">Lite Version</a> for free.  Once you have the zip file you will want to extract this file into your shared assets directory.  Finally, don&#8217;t forget to change the filename in conf/plugin.properties to match what you are save the db file as.  </p>
<p>Now you are ready to stop dotCMS, run bin/deploy-plugins.sh (or bat), and startup dotCMS.  On startup if you are tailing the log file you should see a message like: &#8220;MaxMind GeoIP Viewtool Started&#8221;.  Now let&#8217;s dig into some velocity code:</p>
<h4> Getting the User&#8217;s IP address </h4>
<p>You have a couple options here.  Depending if you have a load balancer and how it sends the IP in the header one or more of the following options might work for you:</p>
<pre class="brush: xml; title: ; notranslate">
#set($ip = $request.getRemoteAddr())
#set($ip = $session.getAttribute(&quot;clickstream&quot;).remoteAddress)
#set($ip = $request.getHeader('x-forwarded-for'))
#set($ip = $request.getHeader('x-cluster-client-ip'))

## A trick to finding the right header
#foreach($key in $request.getHeaderNames) 
  &lt;b&gt;$key&lt;/b&gt; = $request.getHeader($key) &lt;br /&gt;
#end
</pre>
<h4> Getting the User&#8217;s Location </h4>
<p>Now that you have the user&#8217;s IP address you can get the LocationMap and access the various properties:</p>
<pre class="brush: xml; title: ; notranslate">
## We might as well take a hint from the dotCMS Folks and take advantage of caching the user's location in the session for later use
#set($locFromSession = $session.getAttribute(&quot;loc&quot;))
 
#if(!$UtilMethods.isSet($locFromSession))
  #set($loc = $geoip.getLocationMap($ip))
  $session.setAttribute(&quot;loc&quot;, $loc)
#else
  #set($loc = $session.getAttribute(&quot;loc&quot;))
#end

## Now you have access to the following data:
&lt;dl&gt; 
  &lt;dt&gt;IP:&lt;/dt&gt;
  &lt;dd&gt;${ip}&lt;/dd&gt;
  &lt;dt&gt;${loc}&lt;/dt&gt;
  &lt;dd&gt;&lt;/dd&gt;
  &lt;dt&gt;Country Code:&lt;/dt&gt;
  &lt;dd&gt;${loc.countryCode}&lt;/dd&gt;
  &lt;dt&gt;Country Name:&lt;/dt&gt;
  &lt;dd&gt;${loc.countryName}&lt;/dd&gt;
  &lt;dt&gt;Region:&lt;/dt&gt;
  &lt;dd&gt;${loc.region}&lt;/dd&gt;
  &lt;dt&gt;City:&lt;/dt&gt;
  &lt;dd&gt;${loc.city}&lt;/dd&gt;
  &lt;dt&gt;Postal Code:&lt;/dt&gt;
  &lt;dd&gt;${loc.postalCode}&lt;/dd&gt;
  &lt;dt&gt;Latitutde:&lt;/dt&gt;
  &lt;dd&gt;${loc.latitude}&lt;/dd&gt;
  &lt;dt&gt;Longitude:&lt;/dt&gt;
  &lt;dd&gt;${loc.longitude}&lt;/dd&gt;
  &lt;dt&gt;DMA Code:&lt;/dt&gt;
  &lt;dd&gt;${loc.dma_code}&lt;/dd&gt;
  &lt;dt&gt;Area Code:&lt;/dt&gt;
  &lt;dd&gt;${loc.area_code}&lt;/dd&gt;
  &lt;dt&gt;Metro Code:&lt;/dt&gt;
  &lt;dd&gt;${loc.metro_code}&lt;/dd&gt;
&lt;/dl&gt;
</pre>
<h4> Computing Distance </h4>
<p>Lastly, if you want to determine the distance between 2 locations you have a couple of options:</p>
<pre class="brush: xml; title: ; notranslate">
## First get a couple Location Objects or pull some latitude and longitude data from one of your structures:
#set($locObj  = $geoip.getLocation($ip))
#set($loc2    = $geoip.getLocationMap('213.52.50.8'))
#set($loc2Obj = $geoip.getLocation('213.52.50.8'))

## If you have two Location Objects you can get the distance using the Location Objects:
&lt;p&gt;Distance between ${esc.d}loc and ${esc.d}loc2 = ${locObj.distance($loc2Obj)} miles&lt;/p&gt;

## If you have one Location Object and a set of lat,long for a second location you can get the distance using the viewtool helper method:
&lt;p&gt;Distance between ${esc.d}loc and ${esc.d}loc2 = ${geoip.distance($locObj, $loc2.latitude, $loc2.longitude)} miles&lt;/p&gt;

## If you have two sets of lat,long you can use the viewtool helper method as well:
&lt;p&gt;Distance between ${esc.d}loc and ${esc.d}loc2 = ${geoip.distance($loc.latitude, $loc.longitude, $loc2.latitude, $loc2.longitude)} miles&lt;/p&gt;
</pre>
<h4> Keeping your database up-to-date </h4>
<p>MaxMind also provides a C Library that you can use to keep your database up-to-date.  Setting this up is fairly simple.  They have a <a href="http://www.maxmind.com/en/license_key">full set of instructions</a> over on their site.  Just don&#8217;t forget to pass the -d option to tell it to save your database file in your assets folder:</p>
<pre class="brush: plain; title: ; notranslate">
Usage: geoipupdate [-hv] [-f license_file] [-d custom directory]
</pre>
<h3> Compatibility </h3>
<p>Currently I have tested the code on 1.9.5.x and 2.2.1.  In the future we plan on converting the plugin to OSGI, but we wanted to maintain compatibility with the 1.9.5 folks.  Let us know either on GitHub or in a comment here if it useful for you or if you have feature requests or find any bugs.</p>
<img src="http://feeds.feedburner.com/~r/LearnDotcms/~4/2wcFdf-VOxs" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://learndotcms.com/2013/04/geolocation-viewtool/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://learndotcms.com/2013/04/geolocation-viewtool/</feedburner:origLink></item>
		<item>
		<title>Conditionalizing Structure Fields</title>
		<link>http://feedproxy.google.com/~r/LearnDotcms/~3/hapKlSKptNY/</link>
		<comments>http://learndotcms.com/2012/10/conditionalizing-structure-fields/#comments</comments>
		<pubDate>Fri, 26 Oct 2012 03:31:29 +0000</pubDate>
		<dc:creator>Michael Fienen</dc:creator>
				<category><![CDATA[Back End]]></category>
		<category><![CDATA[fields]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[structures]]></category>

		<guid isPermaLink="false">http://learndotcms.com/?p=542</guid>
		<description><![CDATA[Imagine a situation. You have a structure with a bunch of fields. But only certain fields are relevant at certain times, based on the answers to other fields. What&#8217;s an admin to do? Well, thanks to custom fields, a lot, actually. Using a custom field, we can include a little JavaScript that will allow you [...]]]></description>
				<content:encoded><![CDATA[<p>Imagine a situation. You have a structure with a bunch of fields. But only certain fields are relevant at certain times, based on the answers to other fields. What&#8217;s an admin to do? Well, thanks to custom fields, a lot, actually. Using a custom field, we can include a little JavaScript that will allow you to make certain fields conditional.</p>
<div id="attachment_545" class="wp-caption alignright" style="width: 160px"><a href="http://learndotcms.com/wp-content/uploads/2012/10/featured-field.png"><img class="size-thumbnail wp-image-545 colorbox-542" title="Featured Field Configuration" src="http://learndotcms.com/wp-content/uploads/2012/10/featured-field-150x150.png" alt="Featured Field Configuration" width="150" height="150" /></a><p class="wp-caption-text">Featured Field Configuration</p></div>
<p>Let&#8217;s start with a structure. In this case, the News article structure, since most people will be familiar with it. Let&#8217;s say you want to add some additional functionality like making something be &#8216;sticky&#8217; in WordPress. And let&#8217;s say that you want that to be for just a specific range of time. So obviously these date fields would only be important if you&#8217;ve set the news item to be featured, otherwise they&#8217;re just taking up space. Step one, let&#8217;s add the field that will control this featured state. I&#8217;ll use a radio button, and a basic boolean value.</p>
<p>Next, add a couple date fields, nothing special here. We&#8217;ll call them &#8220;Featured Start&#8221; and &#8220;Featured End.&#8221; The only important part is that at this point, these can&#8217;t be required (though with some extra JavaScript, you could manage that too &#8211; client side). In the end, you&#8217;ll have something similar to what&#8217;s below.</p>
<div id="attachment_546" class="wp-caption aligncenter" style="width: 610px"><a href="http://learndotcms.com/wp-content/uploads/2012/10/featured-fields.png"><img class=" wp-image-546  colorbox-542" title="All three fields" src="http://learndotcms.com/wp-content/uploads/2012/10/featured-fields.png" alt="All three fields" width="600" /></a><p class="wp-caption-text">All three fields</p></div>
<p>Now, let&#8217;s talk magic sauce. Add a custom field to the structure, and just drop it at the bottom (that&#8217;s probably where it is anyway after adding it). It&#8217;s not going to show anything, so it&#8217;s placement isn&#8217;t really important. We&#8217;ll call this field &#8220;Conditional Fields.&#8221; I&#8217;m going to do this with jQuery, because that&#8217;s what I happen to be better at. Hint: you can easily add jQuery to a custom field using my <a href="http://learndotcms.com/2012/10/the-resource-loader-plugin/">Resource Loader plugin</a>. In the value for the custom field, drop the following code in.</p>
<pre class="brush: jscript; title: ; notranslate">&lt;script src=&quot;//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js&quot;&gt;&lt;/script&gt;
&lt;script&gt;
  // Prevent namespace collisions with Dojo, etc
  var j = jQuery.noConflict();
  // Function to show/hide fields
  function toggleFields(val) {
    if(val == '0') {
      j(&quot;${esc.h}featuredStart_tag,${esc.h}featuredEnd_tag&quot;).parent().hide();
    } else {
      j(&quot;${esc.h}featuredStart_tag,${esc.h}featuredEnd_tag&quot;).parent().show();
    }
  }

  j(document).ready(function() {
    // Hide our custom field's label
    j('${esc.h}conditionalFields_tag').parent().hide();
    // Check the field state on load and show/hide our conditional fields as appropriate
    var startingVal = j(&quot;input:radio[name=bool1]&quot;).val();
    toggleFields(startingVal);

    // Add click handler to show/hide fields on controlling radio button
    j(&quot;input:radio[name=bool1]&quot;).click(function() {
      toggleFields(j(this).val());
    });
  });
&lt;/script&gt;</pre>
<p>It&#8217;s that simple. You can easily adapt this to other field types besides radio buttons, or toggle multiple sets of fields on a structure. If you want to make the fields required based on the on/off state, you can&#8217;t use the built in required setting on the field. Instead, you&#8217;ll have to add a click handler to the submit button and run your own validation for that. Otherwise, everything else like regex validation, default value, etc should work as normal. This is a great way to simplify your content forms and provide progressive discovery on fields so users don&#8217;t feel overwhelmed the first time they see a structure.</p>
<img src="http://feeds.feedburner.com/~r/LearnDotcms/~4/hapKlSKptNY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://learndotcms.com/2012/10/conditionalizing-structure-fields/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://learndotcms.com/2012/10/conditionalizing-structure-fields/</feedburner:origLink></item>
		<item>
		<title>The Resource Loader Plugin (1.0)</title>
		<link>http://feedproxy.google.com/~r/LearnDotcms/~3/EQy8kCPxtDI/</link>
		<comments>http://learndotcms.com/2012/10/the-resource-loader-plugin/#comments</comments>
		<pubDate>Tue, 23 Oct 2012 21:48:53 +0000</pubDate>
		<dc:creator>Michael Fienen</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Macros]]></category>
		<category><![CDATA[Plugins]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[js]]></category>
		<category><![CDATA[macro]]></category>
		<category><![CDATA[plugin]]></category>

		<guid isPermaLink="false">http://learndotcms.com/?p=512</guid>
		<description><![CDATA[After some discussions with a coworker, an idea took shape for a Velocity based alternative to framework loaders such as the JavaScript based RequireJS. The idea is that you can upload common or frequently used files for your templates to your dotCMS host or shared host and pull those en masse with a simple macro. [...]]]></description>
				<content:encoded><![CDATA[<div class="github-widget" data-repo="thequicksilver/com.learndotcms.plugins.resourceloader"></div>
<p>After some discussions with a coworker, an idea took shape for a Velocity based alternative to framework loaders such as the <a href="http://requirejs.org/">JavaScript based RequireJS</a>. The idea is that you can upload common or frequently used files for your templates to your dotCMS host or shared host and pull those en masse with a simple macro. Welcome to the <a href="https://github.com/thequicksilver/com.learndotcms.plugins.resourceloader/zipball/v1.0">Resource Loader</a> (<a href="https://github.com/thequicksilver/com.learndotcms.plugins.resourceloader">GitHub project page</a>).</p>
<div id="attachment_530" class="wp-caption alignright" style="width: 310px"><a href="http://learndotcms.com/wp-content/uploads/2012/10/Screen-Shot-2012-10-23-at-4.35.59-PM.png"><img class="size-medium wp-image-530 colorbox-512" title="A Web Resource file asset" src="http://learndotcms.com/wp-content/uploads/2012/10/Screen-Shot-2012-10-23-at-4.35.59-PM-300x249.png" alt="A Web Resource file asset" width="300" height="249" /></a><p class="wp-caption-text">A Web Resource file asset</p></div>
<p>First, how it works (jump down the page if you want to see an explanation of how it&#8217;s built). When you install the plugin, it does two specific things. First, it creates a macro called <code>loadResource()</code>. Then, it creates a File Asset structure called <em>Web Resource</em> (this is configurable in the plugin.properties file, if you want to change it). From there, you upload files that you want to be loader enabled using that structure, and give them a common resource ID. So, let&#8217;s say you use <a href="http://foundation.zurb.com/">Foundation</a> as the basis for your sites. You can upload the core CSS and JS files for that, and give them all the resource ID &#8216;foundation.&#8217; If you use the entire Foundation library, that&#8217;s at least a couple CSS files and several JS files. Then, in your template, all you have to do is run the code.</p>
<pre class="brush: xml; title: ; notranslate">## CALL ALL OUR LOCALLY STORED FOUNDATION LIBRARY FILES
#loadResource('foundation')</pre>
<p>Even better, out of the box the macro supports any JS library in the <a href="https://developers.google.com/speed/libraries/devguide#Libraries">Google Hosted Libraries</a> without needing to upload a local version at all. So, want to add jQuery on a fresh site? Just drop in:</p>
<pre class="brush: xml; title: ; notranslate">## GET JQUERY FROM GOOGLE'S CDN IF IT ISN'T AVAILABLE LOCALLY
#loadResource('jquery')</pre>
<p>If you prefer CDN based resources, when you upload your files, just include an external link to the CDN version and set it to default to that link.</p>
<p>There are several other options included as well, which you can just set as Velocity variable prior to calling the macro:</p>
<ul>
<li><code>$htmlDebug</code> (bool): Prints debug info out on each library as an HTML comment in the source.</li>
<li><code>$commentBreaks</code> (bool): Show HTML comments before and after loading the library files. Good for seeing the start and end of each library, especially if you&#8217;re loading several in a row.</li>
<li><code>$resourceCache</code> (int): Cache time for resources, in seconds. By default, once you call a resource, it will use <code>dotcache()</code> to save that for a day.</li>
<li><code>$boxJs</code>(bool): Enables the 3rd party caching proxy/CDN <a href="http://boxjs.com/">BoxJS</a>. This will take all the JS files for your resource library and combine and minify them, then serve it from their Amazon based CDN as a single file. Only works when used on local files.
<ul>
<li><code>$boxJsMinify</code> (bool): Enabled by default. Set to false to disable minification if it causes issues for your file.</li>
<li><code>$boxJsCache</code> (bool):  Enabled by default. Set to false to disable caching on the BoxJS CDN.</li>
<li><code>$boxJsVersion</code> (str): Allows you to create versioned packages on their CDN if you ever want to roll back for something.</li>
<li><code>$boxJsAppend</code> (bool): Enabled by default. Set to false to spit out the JS right where you place the macro (otherwise it&#8217;s added to the end of the page).</li>
<li><code>$boxJsDefer</code> (bool): Set to true if you want manual control over when, where, or how your JS is brought into the page. Requires you to manually call <code>box.get();</code> in JavaScript on the page where you want the code at.</li>
</ul>
</li>
<li><code>$boxCss</code>(bool): Like BoxJS above, this enables the 3rd party caching proxy/CDN <a href="http://boxcss.com/">BoxCSS</a>. This will take all the CSS files for your resource library and combine and minify them, then serve it from their Amazon based CDN as a single file. Only works when used on local files.
<ul>
<li><code>$boxJsMinify</code> (bool): Enabled by default. Set to false to disable minification if it causes issues for your file.</li>
<li><code>$boxJsCache</code> (bool):  Enabled by default. Set to false to disable caching on the BoxCSS CDN.</li>
<li><code>$boxJsVersion</code> (int)Allows you to create versioned packages on their CDN if you ever want to roll back for something.</li>
</ul>
</li>
</ul>
<p>So knowing all this, a more advanced example might be:</p>
<pre class="brush: xml; title: ; notranslate">## ENABLE DEBUGGING
#set($htmlDebug = true)
## DISABLE COMMENT BREAKS
#set($commentBreaks = false)
## TURN DOWN CACHE TIME TO ONE HOUR
#set($resourceCache = 3600)
## RUN ALL OUR CSS THROUGH BOXCSS
#set($boxCss = true)
## PULL IN OUR CUSTOM CSS LIBRARIES FOR THE SITE
#loadResource('all-the-css')</pre>
<p>That would be a good way, if you had a dozen common CSS files you use, to create a common shared library that gets combined and cached for an hour so that the end user ends up with just a single HTTP request for all twelve files.</p>
<h3>How It&#8217;s Built</h3>
<p>For those of you interested in doing something like this, the basic setup for the plugin is pretty easy. The hardest part is deploying a structure programatically, and even that&#8217;s pretty easy once you&#8217;ve seen the code. There are four files specifically you need to pay attention to for the most part on this:</p>
<ol>
<li>MANIFEST.MF</li>
<li>conf/plugin.properties</li>
<li>conf/macros-ext.vm</li>
<li>src/com/learndotcms/plugins/resourceloader/ResourceLoaderPluginDeployer.java</li>
</ol>
<p>The only thing to remember for the <code>MANIFEST.MF</code> file is line two, where you need to define the deployer class that needs to run when the plugin is installed. In this case, the class that builds our <em>Web Resource</em> structure.</p>
<pre class="brush: xml; title: ; notranslate">Manifest-Version: 1.0
Deploy-Class: com.learndotcms.plugins.resourceloader.ResourceLoaderPluginDeployer
Plugin-Name: Resource Loader Plugin
Plugin-Version: 1.0.121022
Author: Michael Fienen ( fienen@gmail.com - http://learndotcms.com/ )</pre>
<p>For our properties, we added three user configurable values, for the shared host ID, and the structure name and Velocity variable name.</p>
<pre class="brush: bash; title: ; notranslate">##The default for the reload.force is true.  If it is set to false the properties will only load once from the file.
##After that they will be stored and maintained in the database.  If true every time the server restart the properties
##will be cleared and reloaded.
reload.force = true

## Set the Structure and Velocity variable name for the resource loader's File Asset structure (DO NOT LEAVE BLANK)
webResourceName = Web Resource
webResourceVarName = WebResource

## Set the identifier for your shared host if used for sharing common elements between hosts (Uncomment it and give it a value if needed)
## sharedHostId =</pre>
<p>Now, due to its size, I&#8217;m not going to source the entire <code>macros-ext.vm</code> file here. Instead, you&#8217;re welcome to download it or <a href="https://github.com/thequicksilver/com.learndotcms.plugins.resourceloader/blob/master/conf/macros-ext.vm">view it on GitHub</a>. But, the basic structure holds true for it as with all macros. Also, I take into account the shared host ID if necessary. That uses a special viewtool (<code>$pluginapitool</code>) to get the property value from the plugin, which you can see on line 5 below.</p>
<pre class="brush: xml; title: ; notranslate">## BASIC MACRO STRUCTURE
## BLAH, BLAH, BLAH, COMMENTS EXPLAINING MACRO AND USAGE
#macro(loadResource $library)
    ## SET UP THE SHARED HOST FOR THE FILE QUERY, IF PROVIDED
    #if($UtilMethods.isSet($pluginapitool.loadProperty(&quot;com.learndotcms.plugins.resourceloader&quot;,&quot;sharedHostId&quot;)))
        #set($sharedHost = &quot; conhost:${pluginapitool.loadProperty('com.learndotcms.plugins.resourceloader','sharedHostId')}&quot;)
    #end

    ...do stuff using the passed variable $library when someone calls #loadResource('foobar')...
#end</pre>
<p>Lastly, the deployer class. Like with the macro, I&#8217;m just going to sample this for you. The <a href="https://github.com/thequicksilver/com.learndotcms.plugins.resourceloader/blob/master/src/com/learndotcms/plugins/resourceloader/ResourceLoaderPluginDeployer.java">full code is here</a>.</p>
<pre class="brush: java; title: ; notranslate">// This is all the overhead and such for this particular plugin
package com.learndotcms.plugins.resourceloader;

import com.dotmarketing.cache.FieldsCache;
import com.dotmarketing.business.DotStateException;
import com.dotmarketing.exception.DotDataException;
import com.dotmarketing.exception.DotRuntimeException;
import com.dotmarketing.plugin.business.PluginAPI;
import com.dotmarketing.plugin.business.PluginAPIImpl;
import com.dotmarketing.plugin.PluginDeployer;
import com.dotmarketing.portlets.structure.model.Field;
import com.dotmarketing.portlets.structure.model.Field.DataType;
import com.dotmarketing.portlets.structure.model.Field.FieldType;
import com.dotmarketing.portlets.structure.model.Structure;
import com.dotmarketing.portlets.structure.factories.FieldFactory;
import com.dotmarketing.portlets.structure.factories.StructureFactory;
import com.dotmarketing.util.Logger;

// Set up the deployer class name
public class ResourceLoaderPluginDeployer implements PluginDeployer {
  // This is what we do when the plugin is deployed
  public boolean deploy() {
    // Set up our Web Resource Structure. Note we're using the pluginAPI again for the property value.
    String structureName = pluginAPI.loadProperty(&quot;com.learndotcms.plugins.resourceloader&quot;, &quot;webResourceName&quot;);
    String structureVarName = pluginAPI.loadProperty(&quot;com.learndotcms.plugins.resourceloader&quot;, &quot;webResourceVarName&quot;);
    Structure st = new Structure();
    st.setName(structureName);
    st.setDescription(&quot;Common CSS/JS/VTL Files used for sharing and building templates.&quot;);
    st.setFixed(false);
    st.setSystem(false);
    st.setStructureType(Structure.STRUCTURE_TYPE_FILEASSET);
    st.setVelocityVarName(structureVarName);
	try {
		StructureFactory.saveStructure(st);
	} catch (Exception e) {
		Logger.error(this.getClass(), e.getMessage(), e);
		throw new DotRuntimeException(e.getMessage(), e);
	}

	Field field1 = new Field(&quot;Host or Folder&quot;, Field.FieldType.HOST_OR_FOLDER, Field.DataType.TEXT, st, true, false, true, 1, &quot;&quot;, &quot;&quot;, &quot;&quot;, true, false, true);
	field1.setVelocityVarName(&quot;hostFolder&quot;);
	try {
		FieldFactory.saveField(field1);
	} catch (Exception e) {
		Logger.error(this.getClass(), e.getMessage(), e);
		throw new DotRuntimeException(e.getMessage(), e);
	}

	Field field2 = new Field(&quot;File Asset&quot;, Field.FieldType.BINARY, Field.DataType.BINARY, st, true, false, false, 2, &quot;&quot;, &quot;&quot;, &quot;&quot;, true, false, false);
	field2.setVelocityVarName(&quot;fileAsset&quot;);
	try {
		FieldFactory.saveField(field2);
	} catch (Exception e) {
		Logger.error(this.getClass(), e.getMessage(), e);
		throw new DotRuntimeException(e.getMessage(), e);
	}

        // And we go on like this for the other eleven fields in the structure

        // Clear the field cache in dotCMS, just in case
	FieldsCache.clearCache();

    return true;
  }

  // We don't need to do anything when we redeploy
  public boolean redeploy(String version) {
    return true;
  }
}</pre>
<p>That&#8217;s the basic story here. All it needs is to be uploaded and deployed then, and you&#8217;re off and running. You can deploy any of the four core structure types (content, widget, form, file) this way, and include any of the standard field types.</p>
<img src="http://feeds.feedburner.com/~r/LearnDotcms/~4/EQy8kCPxtDI" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://learndotcms.com/2012/10/the-resource-loader-plugin/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://learndotcms.com/2012/10/the-resource-loader-plugin/</feedburner:origLink></item>
		<item>
		<title>Commonly Creative Code</title>
		<link>http://feedproxy.google.com/~r/LearnDotcms/~3/ophM_jpBtik/</link>
		<comments>http://learndotcms.com/2012/10/commonly-creative-code/#comments</comments>
		<pubDate>Thu, 18 Oct 2012 17:59:21 +0000</pubDate>
		<dc:creator>Michael Fienen</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Front End]]></category>
		<category><![CDATA[Velocity]]></category>
		<category><![CDATA[bootcamp12]]></category>
		<category><![CDATA[conference]]></category>
		<category><![CDATA[gallery]]></category>
		<category><![CDATA[library]]></category>
		<category><![CDATA[submission]]></category>

		<guid isPermaLink="false">http://learndotcms.com/?p=489</guid>
		<description><![CDATA[For those of you that attended dotCMS Boot Camp this year, you may have caught my presentation Creatively Common, looking at how to build your own light weight version of Flickr in dotCMS (or any kind of asset repository, really). As promised, I wanted to release that code to everyone for your own use or [...]]]></description>
				<content:encoded><![CDATA[<p>For those of you that attended dotCMS Boot Camp this year, you may have caught my presentation Creatively Common, looking at how to build your own light weight version of Flickr in dotCMS (or any kind of asset repository, really). As promised, I wanted to release that code to everyone for your own use or sharing. You&#8217;ll also find the slides at the bottom of this post, and I&#8217;ll link over to the audio once dotCMS has made that available from the conference.</p>
<p><strong><a href="http://learndotcms.com/wp-content/plugins/download-monitor/download.php?id=20">[ You can download the code here. ]</a></strong></p>
<p>There are three pieces to the zip file:</p>
<ol>
<li>A starter.zip file you can use locally on a fresh install of dotCMS that is a copy of the default Quest Financial site, but including the built out library in the /library directory. This starter has only been tested on version 2.1.1.</li>
<li>The /widget code directory contains just the Velocity and HTML from the three core widgets used on the index and detail page for library</li>
<li>The license: all the widget code is released under a CC by 3.0 license.</li>
</ol>
<p>Please take the code and use it to help you towards your own goals. See if you can find better ways to implement features. Think about ways to extend it: better meta data, different data types, permissioned submission, galleries, etc. There are a lot of ways this could be made to be much more than just a fancy photo gallery. Feel free to leave me any questions in the comments.</p>
<p><iframe src="http://www.slideshare.net/slideshow/embed_code/14800602" width="427" height="356" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC;border-width:1px 1px 0;margin-bottom:5px" allowfullscreen> </iframe>
<div style="margin-bottom:5px"> <strong> <a href="http://www.slideshare.net/fienen/creatively-common-bootcamp12" title="Creatively Common (#BootCamp12)" target="_blank">Creatively Common (#BootCamp12)</a> </strong> from <strong><a href="http://www.slideshare.net/fienen" target="_blank">Michael Fienen</a></strong> </div>
<img src="http://feeds.feedburner.com/~r/LearnDotcms/~4/ophM_jpBtik" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://learndotcms.com/2012/10/commonly-creative-code/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://learndotcms.com/2012/10/commonly-creative-code/</feedburner:origLink></item>
		<item>
		<title>We’re migrating to GitHub!</title>
		<link>http://feedproxy.google.com/~r/LearnDotcms/~3/m5xt0ZQUYkQ/</link>
		<comments>http://learndotcms.com/2012/06/were-migrating-to-github/#comments</comments>
		<pubDate>Sat, 02 Jun 2012 19:01:49 +0000</pubDate>
		<dc:creator>Michael Fienen</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Plugins]]></category>

		<guid isPermaLink="false">http://learndotcms.com/?p=486</guid>
		<description><![CDATA[Just a fast update today. As we move forward and start looking at current and future plugin opportunities, we&#8217;re going to take a cue from the core dotCMS team and start tracking things on GitHub. This will help us manage the coding, and also give you all the opportunity to help direct features, bugs, etc, [...]]]></description>
				<content:encoded><![CDATA[<p>Just a fast update today. As we move forward and start looking at current and future plugin opportunities, we&#8217;re going to take a cue from the core dotCMS team and start tracking things on GitHub. This will help us manage the coding, and also give you all the opportunity to help direct features, bugs, etc, and even contribute if you so desire.</p>
<p>To start things off, our IRC Support Portlet plugin (which <a href="http://learndotcms.com/2011/01/building-a-velocity-portlet-plugin-for-irc/">we wrote about here</a>) has been successfully set up and tagged in GitHub. You can <a href="https://github.com/thequicksilver/com.learndotcms.plugins.ircsupport">follow it here</a>. If you haven&#8217;t tried it out, download it and check it out. If you think we can make it better, feel free to log an issue on the project and we&#8217;ll check it out!</p>
<p>Hopefully you&#8217;ll find this a highly beneficial move, and we look forward to your feedback!</p>
<img src="http://feeds.feedburner.com/~r/LearnDotcms/~4/m5xt0ZQUYkQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://learndotcms.com/2012/06/were-migrating-to-github/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://learndotcms.com/2012/06/were-migrating-to-github/</feedburner:origLink></item>
		<item>
		<title>10 Things To See in dotCMS 2.0</title>
		<link>http://feedproxy.google.com/~r/LearnDotcms/~3/wO12nnUzthQ/</link>
		<comments>http://learndotcms.com/2012/04/10-things-to-see-in-dotcms-2-0/#comments</comments>
		<pubDate>Tue, 24 Apr 2012 16:16:00 +0000</pubDate>
		<dc:creator>Michael Fienen</dc:creator>
				<category><![CDATA[Back End]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[2.0]]></category>
		<category><![CDATA[features]]></category>
		<category><![CDATA[upgrade]]></category>

		<guid isPermaLink="false">http://learndotcms.com/?p=437</guid>
		<description><![CDATA[The public release beta of dotCMS 2.0 has been out since March. Prior to that, the current stable version, 1.9.5, was released. This month, they also made the long anticipated move away from traditional SVN over to Github. Needless to say, 2012 has been busy, and the 2.0 release has been a long time coming. [...]]]></description>
				<content:encoded><![CDATA[<p>The public release beta of dotCMS 2.0 has been out <a href="http://dotcms.com/about/press-release/dotcms-2-0-preview-release">since March</a>. Prior to that, the current stable version, 1.9.5, was released. This month, they also made the long anticipated move away from traditional SVN over to <a href="https://github.com/dotCMS/dotCMS">Github</a>. Needless to say, 2012 has been busy, and the 2.0 release has been a long time coming. With that said, if you&#8217;re looking at dotCMS for the first time or wondering if it&#8217;s worth upgrading from 1.9.5, I wanted to look at a few of the features coming in 2.0 that you&#8217;ll likely want to note. These are some of the bigger singular items, but there are countless other improvements, bugfixes, and tweaks as well that cumulatively are just as important.</p>
<p>So, in no particular order, we&#8217;ll start with the&#8230;</p>
<h3>1:) Multifile Uploader</h3>
<div id="attachment_465" class="wp-caption aligncenter" style="width: 610px"><a href="http://learndotcms.com/wp-content/uploads/2012/04/multifile.png"><img class=" wp-image-465  colorbox-437" title="Multifile Upload Popup" src="http://learndotcms.com/wp-content/uploads/2012/04/multifile.png" alt="Multifile Upload Popup" width="600" /></a><p class="wp-caption-text">Multifile Upload Popup</p></div>
<p>This is a personal victory for me. Not because I had anything to do with it, I&#8217;ve just been griping about the multifile upload tool since version 1.5. Prior to 2.0, users were limited to uploading only up to 19 files at a time (through the browser &#8211; not if you had WebDav access), and even then, it was through a form with 19 input fields. It was cludgy, slow, and not at all user friendly. This is a big step forward to much more efficiently facilitate the upload of large batches of files.</p>
<p>I&#8217;d like to see this tool continue to evolve, for instance emulating other systems&#8217; ability to do things like explode a zip file and selectively upload the contents. Maybe show image thumbnails, and let you edit metadata prior to saving. A progress bar or inline visual uploading (a la Flickr) would be nice for general UX. A lot of ways you could go, but this is a big step forward in the area of file management, and I&#8217;ll take it.</p>
<h3>2:) Files on Root</h3>
<p>Admittedly, this is a pretty simple addition, but for everyone that&#8217;s ever created vanity URLs or URLRewriteFilter rules to handle things like favicons or robot.txt files, this will be a welcome addition. Just like it sounds, you can now have files that live at the root level of a host. There are always reasons for this, whether the aforementioned, or other things like Google Webmaster Services, that allow you to authenticate ownership of a domain by placing a simple HTML file on your server.</p>
<h3>3:) Key/Value Pair Field</h3>
<div id="attachment_467" class="wp-caption aligncenter" style="width: 610px"><a href="http://learndotcms.com/wp-content/uploads/2012/04/keyvalue.png"><img class=" wp-image-467  colorbox-437" title="Key/Value Pair Content Field" src="http://learndotcms.com/wp-content/uploads/2012/04/keyvalue.png" alt="Key/Value Pair Content Field" width="600" /></a><p class="wp-caption-text">Key/Value Pair Content Field</p></div>
<p>If you&#8217;ve ever used <a href="http://codex.wordpress.org/Custom_Fields">Custom Fields in WordPress</a>, this new type of structure field should be very familiar to you. The key/value pair field is going to provide a great way to add custom additional data to contentlets that may not always warrant an entire field, or in cases where you don&#8217;t need to care as much about the UI as the data. Or, use it as a way to include debug data or test fields with a contentlet while you develop, without needing to expose your day-to-day users to additional interface weight. Better still, if you&#8217;re an e-commerce site or someone that has to deal with products or items that have varying specs, you can use this type of field to help easily build out things like feature tables.</p>
<p>One other use that comes to mind that has varying usefulness depending on your organizational structure is this: if you&#8217;re in a situation where you would benefit from being able to give certain people access to sets of data that might get repurposed and reused across the site, but you don&#8217;t want to convince them to edit Velocity variables, you could set up a &#8220;Dataset&#8221; structure with a title and key/value pair field that they can populate. Then, you pull the appropriate data set in to pages across your site (financial aid info, user demographics, sports statistics, etc).</p>
<p>I&#8217;ll look forward to possible improvements in the future, like inline editing and autosuggest for keys and values. All in all, this is a pretty raw way of dealing with data on a contentlet, but really, sometimes that&#8217;s just what you want.</p>
<h3>4:) Files as Content</h3>
<div id="attachment_470" class="wp-caption aligncenter" style="width: 610px"><a href="http://learndotcms.com/wp-content/uploads/2012/04/filecontent.png"><img class=" wp-image-470  colorbox-437" title="Setting up a new File content structure" src="http://learndotcms.com/wp-content/uploads/2012/04/filecontent-1024x416.png" alt="Setting up a new File content structure" width="600" /></a><p class="wp-caption-text">Setting up a new File content structure</p></div>
<p>Files as content is another natural evolution of one of the internal cogs of the system, and it won&#8217;t be the last. In 1.9, hosts and forms became content. At some point beyond 2.0, I suspect we&#8217;ll see users and pages as content as well. The content engine is really the heartbeat of dotCMS. The evolution we see is taking something that used to be rigid and static in the system previously, and allowing you to extend it as a structure. This dramatically improves dotCMS&#8217;s ability to serve as a lightweight <a href="http://en.wikipedia.org/wiki/Digital_asset_management">DAM</a> solution, as well as CMS. At the same time, it can give you access to additional file metadata you wouldn&#8217;t have otherwise when you include or link to it (besides what is now extracted automatically from files and indexed along with it, like image EXIF data). Now, you can pull and query for files in dotCMS just like content.</p>
<p>Don&#8217;t be fooled, this is a pretty significant step forward for asset storage in dotCMS. Just the fact that now meta data is extracted as key/value pairs by itself is pretty important (imagine the possibilities for file repositories, photo galleries, etc).</p>
<h3>5:) ElasticSearch</h3>
<p><a href="http://www.elasticsearch.org/">ElasticSearch</a> is a somewhat more invisible change for a lot of folks, but it&#8217;s important nonetheless. Why invisible? Because it sits on top of the Lucene engine, but in such a way as to be able to wrap the old queries (similar to how the move from 1.7 to 1.9 went with the newer syntax, and 1.9 just magically let the old syntax work). So, the syntax itself doesn&#8217;t need to change for any of your content pulls and queries. Where this becomes an important change though is for larger users, especially in clusters. Lucene by itself was, frankly, not awesome at replicating the index across several hosts. ElasticSearch is designed to handle that exact issue, providing excellent scaling across multiple nodes, not just a single node with more resources. It&#8217;s fast, lightweight, and error resistant.</p>
<p>What I really want to look in to though is that while ElasticSearch supports traditional Lucene syntax, it also supports JSON based queries as well. I&#8217;m not sure if this is exposed in 2.0, but the implications are pretty big, including the possibility for regular expression based queries, result scoring, and more. While it may not be readily accessible in dotCMS 2.0, it is a part of ElasticSearch, so it&#8217;s conceivable that we&#8217;d see it exposed in a future release.</p>
<h3>6:) Custom Workflows</h3>
<div id="attachment_472" class="wp-caption alignleft" style="width: 310px"><a href="http://learndotcms.com/wp-content/uploads/2012/04/workflows.png"><img class="size-medium wp-image-472 colorbox-437" title="Default Workflows in dotCMS 2.0" src="http://learndotcms.com/wp-content/uploads/2012/04/workflows-300x287.png" alt="Default Workflows in dotCMS 2.0" width="300" height="287" /></a><p class="wp-caption-text">Default Workflows in dotCMS 2.0</p></div>
<p>Workflows have always been a feature I&#8217;ve scoffed at. This is mainly because I see them as a feature that is more for marketing than actual use. It demos well, as I say. Ultimately, I&#8217;m not sure I&#8217;ve ever seen an organization implement a workflow within a CMS particularly well or consistently, whether in dotCMS or any other system. That said, the addition of custom workflows (for enterprise users) is a vast improvement over the prior implementation. Pre-2.0, workflows were little more than a system of tag for users &#8211; sending rough messages back and forth, possibly with a link to what you were supposed to do. Nothing else, and nothing about it was binding within the business logic.</p>
<p>Now, there is an actual rule system that allows you to create a process through which a contentlet or item must travel, and it&#8217;s tied to this workflow logic so that you can enforce the process. But, this is by no means a particularly simple system to set up, as the power brought with it the tradeoff of the complexity necessary to create all the rules and conditions content can go through at different steps.</p>
<p>Is it really a good enough improvement that I think people will flock to it and use them across their sites? No, probably not. That&#8217;s not because it&#8217;s a bad feature, but rather the result of the problem of meshing programmatic workflows with human workflows. But still, you should know what it does and how to leverage it, as there is a lot of upside if you can make it work within your people infrastructure. Even if it&#8217;s just forcing something like a proofreading step by a content strategist.</p>
<h3>7:) System Host</h3>
<p>Like being able to store files on the root of a host, this is a seemingly simple thing that just makes life happier for everyone. If you host multiple websites in one instance of dotCMS, you&#8217;ve no doubt played with how content lives on different hosts to silo it. Other folks have ran in to issues where they want to share things like VTL files across domains (which was possible pre-2.0 by doing something like a <code>#dotParse('//someotherhost.com/common/vtl/shared.vtl')</code>). But obviously this meant that your VTL had to live on one of your hosts, and that if you needed a shared resource pool, you had to permission accordingly &#8211; even if it didn&#8217;t make sense on the host where the pool was. Normally, where you saw the <code>SYSTEM_HOST</code> was in content queries. In 2.0 though, it&#8217;s an actual <em>thing</em>. This makes it a great tool for building a resource repository for all your other sites. You access it like any other host from the Website Browser &#8211; just click on the &#8220;Change Host&#8221; dropdown and select &#8220;shared.&#8221;</p>
<h3>8:) Content Locking</h3>
<div id="attachment_473" class="wp-caption alignright" style="width: 219px"><a href="http://learndotcms.com/wp-content/uploads/2012/04/locking.png"><img class="size-medium wp-image-473 colorbox-437" title="Locking panel and content actions." src="http://learndotcms.com/wp-content/uploads/2012/04/locking-209x300.png" alt="Locking panel and content actions." width="209" height="300" /></a><p class="wp-caption-text">Locking panel and content actions.</p></div>
<p>Prior to dotCMS 2.0, opening content for editing caused the content to lock. The problem was, this was little more than window dressing, as a single click allowed you to override a lock, regardless of who you were. So really, locked content was just more of a warning, than a lock. The other problem was that users could easily click in to a piece of content, but use the back button instead of the cancel button, thereby leaving a lock in place for days, weeks, or longer.</p>
<p>Now, you cannot edit a piece of content without taking the next step of locking the contentlet. You must do this as an actual action. Then, once locked, it is truly locked. Another using stumbling across it can&#8217;t accidentally open it while you have it open and edit and save it if you have it locked.</p>
<p>It&#8217;s all about helping to maintain integrity of the data in environments where multiple people might try to edit the same thing. While I think this is a good improvement, I hope the UI is improved. I can&#8217;t tell you how many times in testing I&#8217;ve clicked right on the content form out of habit expecting to update something, but instead get the red flash of the &#8220;Lock for Editing&#8221; button. I&#8217;d like to see the content form not look like a form when it isn&#8217;t locked (e.g. no borders on text fields, or a red shade to fields, or a light gray overlay &#8211; something that provides immediate, obvious visual feedback so you don&#8217;t forget). Sort of like the new category selector from 1.9, if you&#8217;re upgrading you can expect this feature to take some getting used to while users new to dotCMS in 2.0 will probably take it in stride. Personally, I don&#8217;t mind the trade off for the extra reinforcement within the data model.</p>
<h3>9:) Spring MVC</h3>
<p>I won&#8217;t dive too deeply into this, mainly because Will over at dotCMS has already <a href="http://dotcms.com/blog/post/spring-mvc-support-in-dotcms-2-0">done a good job explaining it</a>. But the gist of it is that it allows you to create functional plugins with only the use of a single class that gets mapped to a page in the /application/spring path on your site. This is somewhat similar to what you may have chosen to do in the past with Struts, but with less overhead.</p>
<p>Ultimately, this is just another option for folks that want to extend dotCMS. It&#8217;s somewhat less intimidating that Struts, and needs less configuration, which is nice. However, I&#8217;ve always felt one of the biggest barriers to the community extending the system wasn&#8217;t the framework, but simple availability of open source Java devs interested in helping out a project like this. Spring has the advantage of being easy in the right places though, which may spur some folks to start taking a serious look at new plugins.</p>
<h3>10:) Social Integration</h3>
<div id="attachment_476" class="wp-caption aligncenter" style="width: 610px"><a href="http://learndotcms.com/wp-content/uploads/2012/04/twitter.png"><img class=" wp-image-476  colorbox-437" title="Twitter update box from asset." src="http://learndotcms.com/wp-content/uploads/2012/04/twitter.png" alt="Twitter update box from asset." width="600" /></a><p class="wp-caption-text">Twitter update box from asset.</p></div>
<p>I said this was a list of ten things. Really it&#8217;s nine plus this bonus. I almost don&#8217;t want to count this because it&#8217;s a toy, in a way. When editing assets in 2.0, you&#8217;ll notice in the action sidebar where you lock, save, and publish assets, there&#8217;s now an option to &#8220;Tweet This!&#8221; It&#8217;ll generate a bit.ly link for you, and allow you to announce the publishing of your asset. The bit.ly link isn&#8217;t automatically inserted in the text field, which is a little frustrating, and it doesn&#8217;t appear to support broadcasting from multiple Twitter accounts a la Hootsuite. It&#8217;s just a simple addition to the system that is nice to see, if only to know that some thought is being given to how content in dotCMS is being spread, and how that may be facilitated as time goes on. There&#8217;s a lot of room for improvement and expansion on something like this: additional services (Facebook, Tumblr, LinkedIn, Google+, etc), using it on other elements (for instance, why isn&#8217;t this on pages in Edit Mode?), and maybe even serve as a way of getting some lightweight social analytics for the item you&#8217;re looking at (click tracking, RTs, etc).</p>
<p>So there you have it, ten things in dotCMS 2.0 that will likely make a few waves. Keep track of JIRA and now the Github issue tracker page for all the details regarding changes in the system, because there&#8217;s still a lot more that I haven&#8217;t talked about. Also, if you&#8217;re upgrading, make sure to take some time testing before launching live, as several of these new features will involve a lot of changes on the data model side of things. Plus, now that it&#8217;s on Github, be sure to take some time to contribute pull requests for things that you might be able to fix or improve. I think overall that&#8217;s a good move for them, as it exposes the platform to the overall open source community in a new way that SVN simply wasn&#8217;t capable of.</p>
<img src="http://feeds.feedburner.com/~r/LearnDotcms/~4/wO12nnUzthQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://learndotcms.com/2012/04/10-things-to-see-in-dotcms-2-0/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://learndotcms.com/2012/04/10-things-to-see-in-dotcms-2-0/</feedburner:origLink></item>
		<item>
		<title>Phone Number Formatting Macro</title>
		<link>http://feedproxy.google.com/~r/LearnDotcms/~3/IPm1sq_UaF0/</link>
		<comments>http://learndotcms.com/2012/04/phone-number-formatting-macro/#comments</comments>
		<pubDate>Fri, 20 Apr 2012 04:14:01 +0000</pubDate>
		<dc:creator>Michael Fienen</dc:creator>
				<category><![CDATA[Macros]]></category>
		<category><![CDATA[formatting]]></category>
		<category><![CDATA[macro]]></category>
		<category><![CDATA[phone number]]></category>
		<category><![CDATA[regex]]></category>

		<guid isPermaLink="false">http://learndotcms.com/?p=452</guid>
		<description><![CDATA[If you&#8217;ve ever had multiple people entering phone numbers into a field, you&#8217;ve no doubt discovered the varied formats they can provide. Perhaps you&#8217;re already enforcing field validation on it, which is a pretty good solution for the most part. But also, maybe you need to reformat that number for a page or get old [...]]]></description>
				<content:encoded><![CDATA[<p>If you&#8217;ve ever had multiple people entering phone numbers into a field, you&#8217;ve no doubt discovered the varied formats they can provide. Perhaps you&#8217;re already enforcing field validation on it, which is a pretty good solution for the most part. But also, maybe you need to reformat that number for a page or get old data to look the same.</p>
<p>Rather than building out a viewtool to handle it, which you then need to compile and deploy in a plugin, you can use something like this macro example. Just pass it a phone number string (such as &#8220;1-555-555-1234&#8243; or &#8220;555.555.1234,&#8221; it can handle different punctuation &#8211; that&#8217;s the point) and it does the rest. It defaults to US numbers, but you could easily change that or pass a different <code>$phoneCountry</code> value. If you want to include the country code in the number, just set <code>$addCountryCode</code> to <code>true</code> before using the macro (it will stick until set otherwise).</p>
<pre class="brush: xml; title: ; notranslate">## ###############################################################################
## Macro Name: Phone Number Normalizer
## Version: 1.0
## Author: Michael Fienen
## Email: fienen@gmail.com
## Description: Takes a phone number passed to it and attempts to parse it into
## a standard format. Can be used to supplement field validation on a structure.
##
## Required Parameters:
## - $phoneNum = Phone number you want to normalize (string)
##
## Optional Parameters:
## - $phoneCountry = Pass a phone number country code. Only needs to be
## set once unless country changes for different cases. Default: 1 (string)
## - $addCountryCode = Add the $phoneCountry code to the number. Default:
## false (boolean)
## ###############################################################################
#macro(normalizePhone $phoneNum)
   ## SET OPTIONAL VALUE DEFAULTS
   #if(!$UtilMethods.isSet($phoneCountry))
       #set($phoneCountry = '1')
   #end
   #if(!$UtilMethods.isSet($addCountryCode))
       #set($addCountryCode = false)
   #end

   ## CREATE THE INTERNATIONAL IDENTIFER HOLDER
   #if($addCountryCode)
       #set($countryCode = &quot;${phoneCountry} &quot;)
   #end

   #if($phoneCountry == '1')
       ## REMOVE ALL THE PUNCTUATION WE TEND TO SEE IN NUMBERS
       #set($strippedPhone = $phoneNum.replaceAll('\.|-|\(|\)|\s|\+',''))
       ## REMOVE LEADING +1, IF THERE
       #if($strippedPhone.length() == 11 &amp;&amp; $strippedPhone.substring(0,1) == &quot;1&quot;)
           #set($strippedPhone = $strippedPhone.substring(1))
       #end
       ## INCLUDE A FAILSAFE JUST IN CASE SOMETHING WENT SCREWY WITH THE NUMBER
       #if($strippedPhone.length() == 10)
           #set($normPhone = &quot;$!{countryCode}(${strippedPhone.substring(0,3)}) ${strippedPhone.substring(3,6)}-${strippedPhone.substring(6)}&quot;)
       #else
           #set($normPhone = $phoneNum)
       #end
   ## ADDITIONAL COUNTRY FORMATS CAN FOLLOW HERE
   #else
       #set($normPhone = $phoneNum)
   #end

   ## OUTPUT THE NUMBER
   $!{normPhone}

   ## RESET OPTIONAL VALUES
   #set($countryCode = '')
#end</pre>
<p>This will output the number directly, so you&#8217;d use the macro inline where you want the number. For example:</p>
<pre class="brush: xml; title: ; notranslate">#set($addCountryCode = true)
#if($URLMapContent)
&lt;div id=&quot;contactInfo&quot;&gt;
    &lt;ul&gt;
        &lt;li&gt;Address: $!{URLMapContent.address}&lt;/li&gt;
        &lt;li&gt;Phone: #normalizePhone($URLMapContent.phone)&lt;/li&gt;
    &lt;/ul&gt;
&lt;/div&gt;  &lt;!-- #contactInfo --&gt;
#end</pre>
<p>This particular case is set up to work with US phone numbers, but starting on line 47 you could easily add in additional country codes and patterns. Just use the US entry as an example. I would also highly recommend <a href="http://regexlib.com/(A(rWdQIog15jiBGGwOFUTjbRO3Ow_ov_pFaBz4OyH17BogmOi6CrNmlLw1uxMkBdtkEGqSIsQXL2q9ST2SoRodJLHpUO4zzcPZZqCkfeIToExCF5SQtUgKMeYj7zK0wDYsv30sCutpG-rZX7akMN9VsO6N91OMnIHia7sqveh8OE8SwIfBAE5pCNNK3Igbl5ZC0))/Search.aspx?k=Phone&amp;c=7&amp;m=3&amp;ps=20">adding field validation</a> to your structure field if you&#8217;re concerned about the general integrity of the data. Feel free to use and modify this code to fit your needs.</p>
<hr />
<p>Photo Credit: <a href="http://creativecommons.org/licenses/by-nc-sa/2.0/"><img class="colorbox-452"  style="border: 0px; vertical-align: middle;" title="Attribution" src="http://l.yimg.com/g/images/cc_icon_attribution_small.gif" alt="Attribution" width="15" height="15" border="0" /><img class="colorbox-452"  style="border: 0px; vertical-align: middle;" title="Noncommercial" src="http://l.yimg.com/g/images/cc_icon_noncomm_small.gif" alt="Noncommercial" width="15" height="15" border="0" /><img class="colorbox-452"  style="border: 0px; vertical-align: middle;" title="Share Alike" src="http://l.yimg.com/g/images/cc_icon_sharealike_small.gif" alt="Share Alike" width="15" height="15" border="0" /></a> <a title="Attribution-NonCommercial-ShareAlike License" href="http://creativecommons.org/licenses/by-nc-sa/2.0/">Some rights reserved</a> by <a href="http://www.flickr.com/photos/herzogbr/">herzogbr</a></p>
<img src="http://feeds.feedburner.com/~r/LearnDotcms/~4/IPm1sq_UaF0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://learndotcms.com/2012/04/phone-number-formatting-macro/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://learndotcms.com/2012/04/phone-number-formatting-macro/</feedburner:origLink></item>
		<item>
		<title>Creating a Color Picker Field</title>
		<link>http://feedproxy.google.com/~r/LearnDotcms/~3/nX1DY4NA3Vc/</link>
		<comments>http://learndotcms.com/2012/04/creating-a-color-picker-field/#comments</comments>
		<pubDate>Thu, 12 Apr 2012 01:29:28 +0000</pubDate>
		<dc:creator>Michael Fienen</dc:creator>
				<category><![CDATA[Back End]]></category>
		<category><![CDATA[color picker]]></category>
		<category><![CDATA[custom field]]></category>
		<category><![CDATA[fields]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://learndotcms.com/?p=439</guid>
		<description><![CDATA[As we rapidly approach the launch of dotCMS 2.0, we&#8217;ve seen the addition of a number of new structure fields to the system since its launch. And there&#8217;s still more to come too &#8211; personally, I see a lot of potential in the generic Key/Value Pair field, which is very similar to custom fields in [...]]]></description>
				<content:encoded><![CDATA[<p>As we rapidly approach the launch of dotCMS 2.0, we&#8217;ve seen the addition of a number of new structure fields to the system since its launch. And there&#8217;s still more to come too &#8211; personally, I see a lot of potential in the generic Key/Value Pair field, which is very similar to custom fields in WordPress. However, you&#8217;ll almost certainly run into situations where you need a field that isn&#8217;t available. That&#8217;s where custom fields can be very helpful. In this tutorial, I&#8217;ll show you how to add a color picker field to a structure. Why a color picker? Why not? It&#8217;s a fast and easy way to allow customization of a theme, template or tool in the system, and can be helpful when trying to give users more options when they may not know how to find hex values.</p>
<p>Before I start, I should mention that <a href="http://dojotoolkit.org/reference-guide/1.7/dojox/widget/ColorPicker.html">Dojo has a color picker widget</a> who&#8217;s library is included in dotCMS. But see, there&#8217;s two issues. One &#8211; I know jQuery better, so that&#8217;s what I&#8217;m using in this example, so just be aware that there is the extra script to load as a result. Two &#8211; I did try the Dojo color picker out, and got it mostly working, but the documentation for it isn&#8217;t very good and I simply couldn&#8217;t handle some of the use cases that I wanted to properly. So, jQuery all the way, and specifically, I&#8217;m using <a href="http://www.eyecon.ro/colorpicker/">this color picker plugin</a>. If anyone does it with Dojo and gets it working the same as here, I&#8217;d love to see it, since I&#8217;d prefer not load the extra JavaScript for jQuery if it&#8217;s avoidable.</p>
<div id="attachment_444" class="wp-caption alignright" style="width: 310px"><a href="http://learndotcms.com/wp-content/uploads/2012/04/Capture.png"><img class="size-medium wp-image-444 colorbox-439" title="Colorpicker Custom Field" src="http://learndotcms.com/wp-content/uploads/2012/04/Capture-300x128.png" alt="Colorpicker Custom Field" width="300" height="128" /></a><p class="wp-caption-text">Colorpicker Custom Field</p></div>
<p>In theory, by this point you caught that we&#8217;re going to use a custom field for this, so on your structure, go ahead and set one up. In this case, we&#8217;ll call it &#8220;<em>Background Color</em>.&#8221; We&#8217;ll then pull in jQuery, run noConflict() so that it won&#8217;t collide with Dojo in the back end, include the JS and CSS for the color picker, and apply it to a div. Additionally, you&#8217;ll see in the code I include a field called <em>colorPickerField. </em>This is so that you can manually control the color &#8211; and more specifically &#8211; unset the color if you don&#8217;t want it. Most of the color pickers don&#8217;t accept a null value for color, so if you rely just on the picker, then you will always have a value even if you don&#8217;t want one. If that&#8217;s not necessary in your case, by all means leave it out.</p>
<p>Since this is fairly straightforward, here&#8217;s all the code in one drop. The comments should pretty clearly explain what everything is doing. I also readily admit I&#8217;m not the world&#8217;s most awesome JavaScript ninja, so there may be some better ways to handle some of the stuff below. I&#8217;ll update code as people make recommendations.</p>
<pre class="brush: xml; title: ; notranslate">&lt;script type=&quot;text/javascript&quot; src=&quot;http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js&quot;&gt;&lt;/script&gt;
&lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;/common/js/jquery/plugins/colorpicker/css/colorpicker.css&quot; /&gt;
&lt;style&gt;
${esc.h}colorPicker {margin-bottom:1em;}
.colorpicker_submit,.colorpicker_hex {display:none;}
.invalid {background-color:${esc.h}ffcfcf;}
&lt;/style&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;/common/js/jquery/plugins/colorpicker/js/colorpicker.js&quot;&gt;&lt;/script&gt;
&lt;script&gt;
// Make sure we don't screw up Dojo
jQuery.noConflict();
jQuery(document).ready(function() {
    // Regular expression for matching hex value
    var colorRxp = /[0-9A-Fa-f]{6}/

    jQuery('${esc.h}colorPicker').ColorPicker({
## SET OUR SELECTED COLOR IF USED
#if($UtilMethods.isSet($backgroundColor))
        color:'${esc.h}$!{backgroundColor}',
#end
        flat:true,
        onChange: function (hsb, hex, rgb) {
            // Save hex value to display field and storage field and remove warnings
            jQuery('${esc.h}backgroundColor').val(hex);
            jQuery('${esc.h}colorPickerField').removeClass('invalid');
            jQuery('${esc.h}colorPickerField').val(hex);
        }
    });

    // Set up our manual field
    jQuery('${esc.h}colorPickerField').keyup(function() {
        // Do we match the regex for a hex value?
        if(this.value.match(colorRxp)) {
            // Remove any warning color
            jQuery(this).removeClass(&quot;invalid&quot;);
            // Push color to color picker
            jQuery('${esc.h}colorPicker').ColorPickerSetColor(this.value);
            // Save value to storage field
            jQuery('${esc.h}backgroundColor').val(this.value);
        // Did we remove the color?
        } else if(this.value == &quot;&quot;) {
            // Remove any warning color
            jQuery(this).removeClass(&quot;invalid&quot;);
            // Push white to the color picker (gotta give it something)
            jQuery('${esc.h}colorPicker').ColorPickerSetColor('ffffff');
            // Save a null to our storage field
            jQuery('${esc.h}backgroundColor').val('');
        // Otherwise, whatever is entered isn't a color
        } else {
            // Show a warning color on the field until it matches or is emptied
            jQuery(this).addClass(&quot;invalid&quot;);
        }
    });
});
&lt;/script&gt;

&lt;div id=&quot;colorPicker&quot;&gt;&lt;/div&gt;
&lt;input type=&quot;text&quot; id=&quot;colorPickerField&quot; maxlength=&quot;6&quot; value=&quot;$!{backgroundColor}&quot; /&gt;</pre>
<div id="attachment_445" class="wp-caption alignright" style="width: 310px"><a href="http://learndotcms.com/wp-content/uploads/2012/04/picker.jpg"><img class="size-medium wp-image-445  colorbox-439" title="Picker Comparison" src="http://learndotcms.com/wp-content/uploads/2012/04/picker-300x257.jpg" alt="Picker Comparison" width="300" height="257" /></a><p class="wp-caption-text">Top: Plain, unmodified usage. Bottom: Modified CSS to improve UI.</p></div>
<p>A couple other notes. I tweaked the CSS a little here to adjust things so that it made more sense in the context of our fields. So, you&#8217;ll note stuff like on lines 4 and 5 where I add some spacing and hide a couple tools. Also, in the screenshot up above the code, you&#8217;ll notice my colorpicker is light, while the normal one is dark. In the download, there&#8217;s a custom_background.png image that&#8217;s for lighter themes that you can switch to. I&#8217;ve also added in extra validation on our <em>colorPickerField</em> input so that we don&#8217;t send invalid color values to the picker.</p>
<p>Usage is simple. Either type in the hex value in the text box, which will update the color picker accordingly, or select a color in the picker, and it will set the value in the text box automatically. In this case, the extra validation will cause the text box to take on a red background if you type in a value that isn&#8217;t a valid hex color, and it won&#8217;t update the picker until you type one in correctly (I also apply the same regex to the field validation on the structure entry as well). In the  screenshot to the right, you can see I even adjusted the CSS further so that unlike the example above, my text box shows up inside the color picker, so it all feels like one nice, concise tool.</p>
<p>Hopefully this will give you some insight into just how easy it is to create unique types of custom fields that don&#8217;t already exist within dotCMS. If you have any questions, feel free to leave a comment below.</p>
<hr />
<p>Photo credit: <a href="http://creativecommons.org/licenses/by-nc-nd/2.0/"><img class="colorbox-439"  style="border-style: initial; border-color: initial; border-image: initial; border-width: 0px; vertical-align: middle;" title="Attribution" src="http://l.yimg.com/g/images/cc_icon_attribution_small.gif" alt="Attribution" width="15" height="15" border="0" /><img class="colorbox-439"  style="border-style: initial; border-color: initial; border-image: initial; border-width: 0px; vertical-align: middle;" title="Noncommercial" src="http://l.yimg.com/g/images/cc_icon_noncomm_small.gif" alt="Noncommercial" width="15" height="15" border="0" /><img class="colorbox-439"  style="border-style: initial; border-color: initial; border-image: initial; border-width: 0px; vertical-align: middle;" title="No Derivative Works" src="http://l.yimg.com/g/images/cc_icon_noderivs_small.gif" alt="No Derivative Works" width="15" height="15" border="0" /></a> <a title="Attribution-NonCommercial-NoDerivs License" href="http://creativecommons.org/licenses/by-nc-nd/2.0/">Some rights reserved</a> by <a href="http://www.flickr.com/photos/photonquantique/">PhOtOnQuAnTiQuE</a></p>
<img src="http://feeds.feedburner.com/~r/LearnDotcms/~4/nX1DY4NA3Vc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://learndotcms.com/2012/04/creating-a-color-picker-field/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://learndotcms.com/2012/04/creating-a-color-picker-field/</feedburner:origLink></item>
		<item>
		<title>dotCMS and Mobile Techniques: Notes from Boot Camp 2011</title>
		<link>http://feedproxy.google.com/~r/LearnDotcms/~3/1070_aJ7a-k/</link>
		<comments>http://learndotcms.com/2011/08/dotcms-and-mobile-techniques/#comments</comments>
		<pubDate>Thu, 18 Aug 2011 15:56:36 +0000</pubDate>
		<dc:creator>Michael Fienen</dc:creator>
				<category><![CDATA[Front End]]></category>
		<category><![CDATA[Velocity]]></category>
		<category><![CDATA[mobile]]></category>

		<guid isPermaLink="false">http://learndotcms.com/?p=427</guid>
		<description><![CDATA[At dotCMS Boot Camp 2011, I was invited to come and talk about mobile implementation techniques using dotCMS. Luckily, this isn&#8217;t as much as issue with trying to pull off clever dotCMS tricks as it is just knowing good mobile techniques. Below are a number of links and examples from my talk. This isn&#8217;t so [...]]]></description>
				<content:encoded><![CDATA[<p>At dotCMS Boot Camp 2011, I was invited to come and talk about mobile implementation techniques using dotCMS. Luckily, this isn&#8217;t as much as issue with trying to pull off clever dotCMS tricks as it is just knowing good mobile techniques. Below are a number of links and examples from my talk. This isn&#8217;t so much about a full blown tutorial, as much as it is just a quick reference for those that attended my session.  A more complete tutorial will come at a later date.</p>
<h3>Mobile Detection Using the Clickstream</h3>
<p>By accessing the user&#8217;s clickstream data, and pulling out the isMobile() flag, we can create a conditional environment to do redirects, apply different stylesheets, change layout, etc.</p>
<pre class="brush: xml; title: ; notranslate">## GET CLICKSTREAM SO WE CAN CHECK OUT THE DEVICE
#set($clickstream  = $session.getAttribute('clickstream'))
## IS THIS A MOBILE DEVICE?
#if($clickstream.mobileDevice &amp;&amp; $clickstream.mobileDevice == 'true')
  ## GET THE REDIRECT COOKIE
  #set($goToMobile = $cookietool.get('goToMobile').value)
  #if($goToMobile == 'true')
    ## SEND THE USER TO THE MOBILE SITE, THIS MUST BE DONE BEFORE
    ## ANY DATA IS SENT TO THE BROWSER
    #$response.sendRedirect('http://m.yoursite.com/')
  #else
    ## IF IT'S MOBILE, BUT THEY WANT THE NORMAL SITE, SEE IF IT
    ## SHOULD BE DISPLAYED LIKE MOBILE OR LIKE NORMAL
    #set($displayMobile = $cookietool.get('displayMobile').value)
  #end
#end</pre>
<p>By setting a cookie at the same time as the check, you can prevent users from having to go through the selection each time if they prefer the normal site over the mobile site. You could set the cookie with some simple JavaScript.</p>
<h3>Creating a Mobile Template</h3>
<p>Creating a mobile template is no different from any other template. If you&#8217;re using a framework like jQuery Mobile, you can build all the necessary parts right into the template.</p>
<pre class="brush: xml; title: ; notranslate">## Container: General Template Includes
#parseContainer('e97bda22-33e8-4b9d-9508-0aefb4c899d6')
&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot;&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot;&gt;
  &lt;meta name=&quot;apple-mobile-web-app-capable&quot; content=&quot;yes&quot; /&gt;
  &lt;meta name=&quot;apple-mobile-web-app-status-bar-style&quot; content=&quot;black&quot;/&gt;

  &lt;title&gt;$!{pageTitle}&lt;/title&gt;

  &lt;link rel=&quot;apple-touch-icon&quot; href=&quot;/global/images/app-icon.png&quot; /&gt;
  &lt;link rel=&quot;apple-touch-startup-image&quot;href=&quot;/global/images/app-splash.png&quot; /&gt;
  &lt;link rel=&quot;stylesheet&quot;href=&quot;http://code.jquery.com/mobile/1.0b2/jquery.mobile-1.0b2.min.css&quot; /&gt;
  &lt;link rel=&quot;stylesheet&quot; href=&quot;/global/css/custom.css&quot; /&gt;

  &lt;script src=&quot;http://code.jquery.com/jquery-1.6.2.min.js&quot;&gt;&lt;/script&gt;
  &lt;script src=&quot;http://code.jquery.com/mobile/1.0b2/jquery.mobile-1.0b2.min.js&quot;&gt;&lt;/script&gt;
&lt;/head&gt;

&lt;body&gt;
&lt;div data-role=&quot;page&quot;&gt;
  &lt;div data-role=&quot;header&quot;&gt;
    &lt;h1&gt;$!{pageTitle}&lt;/h1&gt;
  &lt;/div&gt;&lt;!-- /header --&gt;

  &lt;div data-role=&quot;content&quot;&gt;
    ##Body Container 1
    #parseContainer('93cf710e-fbbb-4d32-a5fb-974dcac38c96')
  &lt;/div&gt;&lt;!-- /content --&gt;

  &lt;div data-role=&quot;footer&quot;&gt;
    &lt;h4&gt;Copyright &amp;copy;2011&lt;/h4&gt;
  &lt;/div&gt;&lt;!-- /footer --&gt;

&lt;/div&gt;&lt;!-- /page --&gt;
&lt;/body&gt;
&lt;/html&gt;</pre>
<h3>jQuery Mobile and the #navigation() Macro</h3>
<p>If you want to use the #navigation() macro and take advantage of jQuery Mobile tooling, you just need to add a little extra JavaScript into the mix to ensure the list is picked up and styled correctly. A single line of JavaScript will get you rolling.</p>
<pre class="brush: jscript; html-script: true; title: ; notranslate">&lt;div id=&quot;navList&quot;&gt;
  #navigation(1 1)
&lt;/div&gt;  &lt;!-- ${esc.h}navList --&gt;
&lt;script&gt;
 $('${esc.h}navList&gt;ul').attr('data-role','listview');
&lt;/script&gt;</pre>
<p>By using the .attr() method, we can add in any of the data-roles or other attributes that can be used to control how the list navigation looks and behaves as a result of jQuery Mobile. (<em>Note: as seen in the above example, when writing code inline on the page and referencing ID&#8217;s, I replace all #s with ${esc.h}. This is the Velocity tool for printing out a hash, and is good for preventing accidental collisions in normal velocity code.</em>)</p>
<h3>Building a News Page</h3>
<p>In this example, I pull in a list of recent news headlines and spit them out readily formatted for my jQuery Mobile stylesheet (<em>Note: My code uses 1.7 syntax. However the principle remains unchanged for 1.9.</em>)</p>
<pre class="brush: xml; title: ; notranslate">#set($lastArticleDate = '0')
#set($today = $date.format('MM/dd/yyyy HH:mm:ss',$date.getDate()))
## FILTER DOWN TO A SPECIFIC SET OF NEWS CATEGORIES
#set($newsCatList = $categories.getChildrenCategoriesByKey('sections'))
#set($newsCats = &quot;+(&quot;)
#foreach($cat in $newsCatList)
  #set($newsCats = &quot;${newsCats}c${cat.inode}c:on &quot;)
#end
#set($newsCats = &quot;${newsCats})&quot;)
#set($query = &quot;+structureInode:5 ${newsCats} +date1:[1/1/2010 00:00:00 TO ${today}] +languageId:1* +deleted:false +live:true&quot;)
#pullContent(&quot;${query}&quot; '10' &quot;date1 desc&quot;)

&lt;div class=&quot;info&quot;&gt;
  The latest campus news from public relations.
&lt;/div&gt;

&lt;ul data-role=&quot;listview&quot;&gt;
#foreach($article in $list)
  ## SET DATE FOR COMPARISON
  #set($thisArticleDate = $date.format('EEEE, MMMM d, yyyy',$article.NewsPublishDate))
  ## IF CURRENT DATE IS DIFFERENT THAN THE LAST ARTICLE, PRINT OUT A DATE DIVIDER
  #if($thisArticleDate != $lastArticleDate)
	&lt;li data-role=&quot;list-divider&quot;&gt;${thisArticleDate}&lt;/li&gt;
  #end
	&lt;li&gt;&lt;a href=&quot;/news/detail.dot?id=${article.identifier}&quot;&gt;${article.NewsHeadline}&lt;/a&gt;&lt;/li&gt;
  #set($lastArticleDate = $date.format('EEEE, MMMM d, yyyy',$article.NewsPublishDate))
#end
&lt;/ul&gt;</pre>
<h3>Links, Tools, and Resources</h3>
<p>I mentioned several sites and tools when talking about mobile, here are many of them:</p>
<ul>
<li><a href="http://www.jquerymobile.com">jQuery Mobile</a> &#8211; A JavaScript framework that extends jQuery and helps add a number of mobile features to your site.</li>
<li><a href="http://www.phonegap.com/">PhoneGap</a> &#8211; Utility for compiling a web app into a wrapper so that you can deploy it as a native app for a number of mobile platforms.</li>
<li><a href="http://developer.android.com/sdk/index.html">Android SDK</a> &#8211; Free SDK for Android that comes with a mobile phone simulator, useful for testing.</li>
<li><a href="http://css-tricks.com/6731-css-media-queries/">CSS Media Queries &amp; Using Available Space</a> &#8211; Guide to how to implement CSS media queries for changing CSS rules based on display conditions reported by the browser.</li>
<li><a href="http://jquery-ui-map.googlecode.com/svn/trunk/demos/jquery-mobile-example.html">jQuery Mobile Google Maps Examples</a> &#8211; Nice list of ways to build on jQuery Mobile with Google Maps (i.e. pulling content from a buildings structure to populate a map)</li>
</ul>
<img src="http://feeds.feedburner.com/~r/LearnDotcms/~4/1070_aJ7a-k" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://learndotcms.com/2011/08/dotcms-and-mobile-techniques/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://learndotcms.com/2011/08/dotcms-and-mobile-techniques/</feedburner:origLink></item>
		<item>
		<title>Legacy Form Submission Security Patch</title>
		<link>http://feedproxy.google.com/~r/LearnDotcms/~3/M4SGKx31aIQ/</link>
		<comments>http://learndotcms.com/2011/06/legacy-form-submission-security-patch/#comments</comments>
		<pubDate>Mon, 27 Jun 2011 13:00:35 +0000</pubDate>
		<dc:creator>Michael Fienen</dc:creator>
				<category><![CDATA[Downloads]]></category>
		<category><![CDATA[Plugins]]></category>
		<category><![CDATA[exploit]]></category>
		<category><![CDATA[form]]></category>
		<category><![CDATA[patch]]></category>
		<category><![CDATA[plugin]]></category>
		<category><![CDATA[spam]]></category>

		<guid isPermaLink="false">http://learndotcms.com/?p=414</guid>
		<description><![CDATA[A while back, it was exposed that if using the legacy form submission struts path (e.g. /sendEmail, /submitWebForm, etc), a spammer could remotely invoke the tool and use it to send spam emails to people. While this wasn&#8217;t exactly a bug in the strictest sense, it could prove to be a headache for users should [...]]]></description>
				<content:encoded><![CDATA[<p>A while back, <a href="http://dotcms-users-forum-mailing-list.1045721.n5.nabble.com/dotCMS-hacked-We-are-under-attack-td3967554.html">it was exposed</a> that if using the legacy form submission struts path (e.g. /sendEmail, /submitWebForm, etc), a spammer could remotely invoke the tool and use it to send spam emails to people. While this wasn&#8217;t exactly a bug in the strictest sense, it could prove to be a headache for users should their server be targeted.</p>
<p>Enter <a href="http://costarica.com">costarica.com</a>. Thanks to their effort, a patch has been made available (for 1.9) that will force the server check the referring HTTP request against a list of approved server names and IPs. As a result, attempts to access the tool directly will be denied &#8211; the tool has to be invoked by a request originating from your site. This has been set up as a plugin for easy installation.</p>
<p><strong>Instructions:</strong></p>
<ol>
<li>Edit <code>conf/plugin.properties</code> to include your list of approved hostname (you&#8217;ll have to do this each time you add or remove hosts in dotCMS)</li>
<li>Copy the plugin to the <code>plugins/</code> folder of your dotCMS installation</li>
<li>Shut down dotCMS</li>
<li>Do an <code>ant clean-plugins deploy-plugins</code></li>
<li>Start up dotCMS</li>
</ol>
<p style="text-align: center;"><strong><a href="http://learndotcms.com/wp-content/plugins/download-monitor/download.php?id=18">[ DOWNLOAD Legacy Form Submission Security Patch 1.0 for dotCMS 1.9 ]</a></strong></p>
<img src="http://feeds.feedburner.com/~r/LearnDotcms/~4/M4SGKx31aIQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://learndotcms.com/2011/06/legacy-form-submission-security-patch/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://learndotcms.com/2011/06/legacy-form-submission-security-patch/</feedburner:origLink></item>
	</channel>
</rss>
