<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[1566] sites/trunk/wordcamp.org/public_html/wp-content/themes/wordcamp-central-2012: Central Theme: Add the `[wcc_map]` shortcode to show a Google Map of WordCamps.</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="http://meta.trac.wordpress.org/changeset/1566">1566</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"http://meta.trac.wordpress.org/changeset/1566","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>iandunn</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2015-05-12 22:41:20 +0000 (Tue, 12 May 2015)</dd>
</dl>

<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>Central Theme: Add the `[wcc_map]` shortcode to show a Google Map of WordCamps.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentthemeswordcampcentral2012functionsphp">sites/trunk/wordcamp.org/public_html/wp-content/themes/wordcamp-central-2012/functions.php</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentthemeswordcampcentral2012jscentraljs">sites/trunk/wordcamp.org/public_html/wp-content/themes/wordcamp-central-2012/js/central.js</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentthemeswordcampcentral2012stylecss">sites/trunk/wordcamp.org/public_html/wp-content/themes/wordcamp-central-2012/style.css</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentthemeswordcampcentral2012imagesiconmarkerclusteredpng">sites/trunk/wordcamp.org/public_html/wp-content/themes/wordcamp-central-2012/images/icon-marker-clustered.png</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentthemeswordcampcentral2012imagesiconmarkerpast2xpng">sites/trunk/wordcamp.org/public_html/wp-content/themes/wordcamp-central-2012/images/icon-marker-past-2x.png</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentthemeswordcampcentral2012imagesiconmarkerupcoming2xpng">sites/trunk/wordcamp.org/public_html/wp-content/themes/wordcamp-central-2012/images/icon-marker-upcoming-2x.png</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentthemeswordcampcentral2012shortcodeaboutmapphp">sites/trunk/wordcamp.org/public_html/wp-content/themes/wordcamp-central-2012/shortcode-about-map.php</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentthemeswordcampcentral2012functionsphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: sites/trunk/wordcamp.org/public_html/wp-content/themes/wordcamp-central-2012/functions.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/themes/wordcamp-central-2012/functions.php        2015-05-12 21:50:55 UTC (rev 1565)
+++ sites/trunk/wordcamp.org/public_html/wp-content/themes/wordcamp-central-2012/functions.php  2015-05-12 22:41:20 UTC (rev 1566)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -43,6 +43,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                add_filter( 'nav_menu_css_class', array( __CLASS__, 'nav_menu_css_class' ), 10, 3 );
</span><span class="cx" style="display: block; padding: 0 10px">                add_filter( 'wp_nav_menu_items', array( __CLASS__, 'add_rss_links_to_footer_menu' ), 10, 2 );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                add_shortcode( 'wcc_map',         array( __CLASS__, 'shortcode_map'         ) );
</ins><span class="cx" style="display: block; padding: 0 10px">                 add_shortcode( 'wcc_about_stats', array( __CLASS__, 'shortcode_about_stats' ) );
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -183,10 +184,10 @@
</span><span class="cx" style="display: block; padding: 0 10px">         * Enqueue scripts and styles.
</span><span class="cx" style="display: block; padding: 0 10px">         */
</span><span class="cx" style="display: block; padding: 0 10px">        static function enqueue_scripts() {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                wp_enqueue_style( 'central', get_stylesheet_uri(), array(), 5 );
-               wp_enqueue_script( 'wordcamp-central', get_stylesheet_directory_uri() . '/js/central.js', array( 'jquery', 'underscore' ), 1, true );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         wp_enqueue_style( 'central', get_stylesheet_uri(), array(), 6 );
+               wp_enqueue_script( 'wordcamp-central', get_stylesheet_directory_uri() . '/js/central.js', array( 'jquery', 'underscore' ), 2, true );
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                wp_localize_script( 'wordcamp-central', 'wordcampCentralOptions', array( 'ajaxURL' => admin_url( 'admin-ajax.php' ) ) );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         wp_localize_script( 'wordcamp-central', 'wordcampCentralOptions', self::get_javascript_options() );
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                /* We add some JavaScript to pages with the comment form
</span><span class="cx" style="display: block; padding: 0 10px">                 * to support sites with threaded comments (when in use).
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -199,9 +200,130 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        wp_enqueue_script( 'jquery-cycle', get_stylesheet_directory_uri() . '/js/jquery.cycle.min.js', array( 'jquery' ) );
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                if ( is_page( 'about' ) || is_page( 'schedule' ) ) {
+                       wp_enqueue_script( 'google-maps', 'https://maps.googleapis.com/maps/api/js', array(), false, true );
+               }
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         * Build the array of options to pass to the client side
+        *
+        * @return array
+        */
+       protected static function get_javascript_options() {
+               global $post;
+
+               $options = array( 'ajaxURL' => admin_url( 'admin-ajax.php' ) );
+
+               if ( $map_id = self::get_map_id( $post->post_content ) ) {
+                       $options['mapContainer']            = "wcc-map-$map_id";
+                       $options['markerIconBaseURL']       = get_stylesheet_directory_uri() . '/images/';
+                       $options['markerClusterIcon']       = 'icon-marker-clustered.png';
+                       $options['markerIconAnchorXOffset'] = 24;
+                       $options['markerIconHeight']        = 94;
+                       $options['markerIconWidth']         = 122;
+
+                       if ( $map_markers = self::get_map_markers( $map_id ) ) {
+                               $options['mapMarkers'] = $map_markers;
+                       }
+               }
+
+               return $options;
+       }
+
+       /**
+        * Get the ID of the map called in the given page
+        *
+        * @param string $post_content
+        *
+        * @return mixed A string of the map name on success, or false on failure
+        */
+       protected static function get_map_id( $post_content ) {
+               $map_id = false;
+
+               if ( has_shortcode( $post_content, 'wcc_map' ) ) {
+                       preg_match_all( '/' . get_shortcode_regex() . '/s', $post_content, $shortcodes, PREG_SET_ORDER );
+
+                       foreach ( $shortcodes as $shortcode ) {
+                               if ( 'wcc_map' == $shortcode[2] ) {
+                                       $attributes = shortcode_parse_atts( $shortcode[3] );
+                                       $map_id     = sanitize_text_field( $attributes['id'] );
+                                       break;
+                               }
+                       }
+               }
+
+               return $map_id;
+       }
+
+       /**
+        * Get the markers assigned to the given map
+        *
+        * @param string $map_id
+        *
+        * @return array
+        */
+       protected static function get_map_markers( $map_id ) {
+               $transient_key = "wcc_map_markers_$map_id";
+
+               if ( $markers = get_transient( $transient_key ) ) {
+                       return $markers;
+               } else {
+                       $markers = array();
+               }
+
+               // Get the raw marker posts for the given map
+               $parameters = array(
+                       'post_type'      => 'wordcamp',
+                       'posts_per_page' => -1,
+               );
+
+               switch( $map_id ) {
+                       case 'schedule':
+                               $parameters['post_status'][] = array( 'publish', 'pending' );
+                               $parameters['meta_query'][] = array(
+                                       'key'     => 'Start Date (YYYY-mm-dd)',
+                                       'value'   => strtotime( '-2 days' ),
+                                       'compare' => '>',
+                               );
+                               break;
+               }
+
+               $raw_markers = get_posts( $parameters );
+
+               // Convert the raw markers into prepared objects that are ready to be used on the JavaScript side
+               foreach ( $raw_markers as $marker ) {
+                       if ( 'schedule' == $map_id ) {
+                               $marker_type = 'upcoming';
+                       } else {
+                               $marker_type = get_post_meta( $marker->ID, 'Start Date (YYYY-mm-dd)', true ) > strtotime( '-2 days' ) ? 'upcoming' : 'past';
+                       }
+
+                       if ( ! $coordinates = get_post_meta( $marker->ID, '_venue_coordinates', true ) ) {
+                               continue;
+                       }
+
+                       $markers[ $marker->ID ] = array(
+                               'id'          => $marker->ID,
+                               'name'        => wcpt_get_wordcamp_title( $marker->ID ),
+                               'dates'       => wcpt_get_wordcamp_start_date( $marker->ID ),
+                               'location'    => get_post_meta( $marker->ID, 'Location', true ),
+                               'venueName'   => get_post_meta( $marker->ID, 'Venue Name', true ),
+                               'url'         => self::get_best_wordcamp_url( $marker->ID ),
+                               'latitude'    => $coordinates['latitude'],
+                               'longitude'   => $coordinates['longitude'],
+                               'iconURL'     => "icon-marker-{$marker_type}-2x.png",
+                       );
+               }
+
+               $markers = apply_filters( 'wcc_get_map_markers', $markers );
+
+               set_transient( $transient_key, $markers, WEEK_IN_SECONDS );
+
+               return $markers;
+       }
+
+       /**
</ins><span class="cx" style="display: block; padding: 0 10px">          * Filters excerpt_more.
</span><span class="cx" style="display: block; padding: 0 10px">         */
</span><span class="cx" style="display: block; padding: 0 10px">        static function excerpt_more( $more ) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -648,6 +770,21 @@
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         * Render the [wcc_map] shortcode
+        *
+        * @param array $attributes
+        *
+        * @return string
+        */
+       public static function shortcode_map( $attributes ) {
+               $attributes = shortcode_atts( array( 'id' => '' ), $attributes );
+
+               ob_start();
+               require( __DIR__ . '/shortcode-about-map.php' );
+               return ob_get_clean();
+       }
+
+       /**
</ins><span class="cx" style="display: block; padding: 0 10px">          * Render the [wcc_about_stats] shortcode
</span><span class="cx" style="display: block; padding: 0 10px">         *
</span><span class="cx" style="display: block; padding: 0 10px">         * @param array $attributes
</span></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentthemeswordcampcentral2012imagesiconmarkerclusteredpng"></a>
<div class="binary"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/themes/wordcamp-central-2012/images/icon-marker-clustered.png</h4>
<pre class="diff"><span>
<span class="cx">(Binary files differ)
</span></span></pre></div>
<span class="cx" style="display: block; padding: 0 10px">Index: sites/trunk/wordcamp.org/public_html/wp-content/themes/wordcamp-central-2012/images/icon-marker-clustered.png
</span><span class="cx" style="display: block; padding: 0 10px">===================================================================
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">--- sites/trunk/wordcamp.org/public_html/wp-content/themes/wordcamp-central-2012/images/icon-marker-clustered.png        2015-05-12 21:50:55 UTC (rev 1565)
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+++ sites/trunk/wordcamp.org/public_html/wp-content/themes/wordcamp-central-2012/images/icon-marker-clustered.png 2015-05-12 22:41:20 UTC (rev 1566)
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: sites/trunk/wordcamp.org/public_html/wp-content/themes/wordcamp-central-2012/images/icon-marker-clustered.png
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span><a id="svnmimetype"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:mime-type</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+image/png
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="sitestrunkwordcamporgpublic_htmlwpcontentthemeswordcampcentral2012imagesiconmarkerpast2xpng"></a>
<div class="binary"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/themes/wordcamp-central-2012/images/icon-marker-past-2x.png</h4>
<pre class="diff"><span>
<span class="cx">(Binary files differ)
</span></span></pre></div>
<span class="cx" style="display: block; padding: 0 10px">Index: sites/trunk/wordcamp.org/public_html/wp-content/themes/wordcamp-central-2012/images/icon-marker-past-2x.png
</span><span class="cx" style="display: block; padding: 0 10px">===================================================================
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">--- sites/trunk/wordcamp.org/public_html/wp-content/themes/wordcamp-central-2012/images/icon-marker-past-2x.png  2015-05-12 21:50:55 UTC (rev 1565)
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+++ sites/trunk/wordcamp.org/public_html/wp-content/themes/wordcamp-central-2012/images/icon-marker-past-2x.png   2015-05-12 22:41:20 UTC (rev 1566)
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: sites/trunk/wordcamp.org/public_html/wp-content/themes/wordcamp-central-2012/images/icon-marker-past-2x.png
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span><a id="svnmimetype"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:mime-type</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+image/png
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="sitestrunkwordcamporgpublic_htmlwpcontentthemeswordcampcentral2012imagesiconmarkerupcoming2xpng"></a>
<div class="binary"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/themes/wordcamp-central-2012/images/icon-marker-upcoming-2x.png</h4>
<pre class="diff"><span>
<span class="cx">(Binary files differ)
</span></span></pre></div>
<span class="cx" style="display: block; padding: 0 10px">Index: sites/trunk/wordcamp.org/public_html/wp-content/themes/wordcamp-central-2012/images/icon-marker-upcoming-2x.png
</span><span class="cx" style="display: block; padding: 0 10px">===================================================================
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">--- sites/trunk/wordcamp.org/public_html/wp-content/themes/wordcamp-central-2012/images/icon-marker-upcoming-2x.png      2015-05-12 21:50:55 UTC (rev 1565)
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+++ sites/trunk/wordcamp.org/public_html/wp-content/themes/wordcamp-central-2012/images/icon-marker-upcoming-2x.png       2015-05-12 22:41:20 UTC (rev 1566)
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: sites/trunk/wordcamp.org/public_html/wp-content/themes/wordcamp-central-2012/images/icon-marker-upcoming-2x.png
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span><a id="svnmimetype"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:mime-type</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+image/png
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="sitestrunkwordcamporgpublic_htmlwpcontentthemeswordcampcentral2012jscentraljs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: sites/trunk/wordcamp.org/public_html/wp-content/themes/wordcamp-central-2012/js/central.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/themes/wordcamp-central-2012/js/central.js        2015-05-12 21:50:55 UTC (rev 1565)
+++ sites/trunk/wordcamp.org/public_html/wp-content/themes/wordcamp-central-2012/js/central.js  2015-05-12 22:41:20 UTC (rev 1566)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,5 +1,40 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * @name MarkerClusterer for Google Maps v3
+ * @version version 1.0
+ * @author Luke Mahe
+ *
+ * The library creates and manages per-zoom-level clusters for large amounts of
+ * markers.
+ */
+(function(){var d=null;function e(a){return function(b){this[a]=b}}function h(a){return function(){return this[a]}}var j;
+       function k(a,b,c){this.extend(k,google.maps.OverlayView);this.c=a;this.a=[];this.f=[];this.ca=[53,56,66,78,90];this.j=[];this.A=!1;c=c||{};this.g=c.gridSize||60;this.l=c.minimumClusterSize||2;this.J=c.maxZoom||d;this.j=c.styles||[];this.X=c.imagePath||this.Q;this.W=c.imageExtension||this.P;this.O=!0;if(c.zoomOnClick!=void 0)this.O=c.zoomOnClick;this.r=!1;if(c.averageCenter!=void 0)this.r=c.averageCenter;l(this);this.setMap(a);this.K=this.c.getZoom();var f=this;google.maps.event.addListener(this.c,
+               "zoom_changed",function(){var a=f.c.getZoom();if(f.K!=a)f.K=a,f.m()});google.maps.event.addListener(this.c,"idle",function(){f.i()});b&&b.length&&this.C(b,!1)}j=k.prototype;j.Q="http://google-maps-utility-library-v3.googlecode.com/svn/trunk/markerclusterer/images/m";j.P="png";j.extend=function(a,b){return function(a){for(var b in a.prototype)this.prototype[b]=a.prototype[b];return this}.apply(a,[b])};j.onAdd=function(){if(!this.A)this.A=!0,n(this)};j.draw=function(){};
+       function l(a){if(!a.j.length)for(var b=0,c;c=a.ca[b];b++)a.j.push({url:a.X+(b+1)+"."+a.W,height:c,width:c})}j.S=function(){for(var a=this.o(),b=new google.maps.LatLngBounds,c=0,f;f=a[c];c++)b.extend(f.getPosition());this.c.fitBounds(b)};j.z=h("j");j.o=h("a");j.V=function(){return this.a.length};j.ba=e("J");j.I=h("J");j.G=function(a,b){for(var c=0,f=a.length,g=f;g!==0;)g=parseInt(g/10,10),c++;c=Math.min(c,b);return{text:f,index:c}};j.$=e("G");j.H=h("G");
+       j.C=function(a,b){for(var c=0,f;f=a[c];c++)q(this,f);b||this.i()};function q(a,b){b.s=!1;b.draggable&&google.maps.event.addListener(b,"dragend",function(){b.s=!1;a.L()});a.a.push(b)}j.q=function(a,b){q(this,a);b||this.i()};function r(a,b){var c=-1;if(a.a.indexOf)c=a.a.indexOf(b);else for(var f=0,g;g=a.a[f];f++)if(g==b){c=f;break}if(c==-1)return!1;b.setMap(d);a.a.splice(c,1);return!0}j.Y=function(a,b){var c=r(this,a);return!b&&c?(this.m(),this.i(),!0):!1};
+       j.Z=function(a,b){for(var c=!1,f=0,g;g=a[f];f++)g=r(this,g),c=c||g;if(!b&&c)return this.m(),this.i(),!0};j.U=function(){return this.f.length};j.getMap=h("c");j.setMap=e("c");j.w=h("g");j.aa=e("g");
+       j.v=function(a){var b=this.getProjection(),c=new google.maps.LatLng(a.getNorthEast().lat(),a.getNorthEast().lng()),f=new google.maps.LatLng(a.getSouthWest().lat(),a.getSouthWest().lng()),c=b.fromLatLngToDivPixel(c);c.x+=this.g;c.y-=this.g;f=b.fromLatLngToDivPixel(f);f.x-=this.g;f.y+=this.g;c=b.fromDivPixelToLatLng(c);b=b.fromDivPixelToLatLng(f);a.extend(c);a.extend(b);return a};j.R=function(){this.m(!0);this.a=[]};
+       j.m=function(a){for(var b=0,c;c=this.f[b];b++)c.remove();for(b=0;c=this.a[b];b++)c.s=!1,a&&c.setMap(d);this.f=[]};j.L=function(){var a=this.f.slice();this.f.length=0;this.m();this.i();window.setTimeout(function(){for(var b=0,c;c=a[b];b++)c.remove()},0)};j.i=function(){n(this)};
+       function n(a){if(a.A)for(var b=a.v(new google.maps.LatLngBounds(a.c.getBounds().getSouthWest(),a.c.getBounds().getNorthEast())),c=0,f;f=a.a[c];c++)if(!f.s&&b.contains(f.getPosition())){for(var g=a,u=4E4,o=d,v=0,m=void 0;m=g.f[v];v++){var i=m.getCenter();if(i){var p=f.getPosition();if(!i||!p)i=0;else var w=(p.lat()-i.lat())*Math.PI/180,x=(p.lng()-i.lng())*Math.PI/180,i=Math.sin(w/2)*Math.sin(w/2)+Math.cos(i.lat()*Math.PI/180)*Math.cos(p.lat()*Math.PI/180)*Math.sin(x/2)*Math.sin(x/2),i=6371*2*Math.atan2(Math.sqrt(i),
+                       Math.sqrt(1-i));i<u&&(u=i,o=m)}}o&&o.F.contains(f.getPosition())?o.q(f):(m=new s(g),m.q(f),g.f.push(m))}}function s(a){this.k=a;this.c=a.getMap();this.g=a.w();this.l=a.l;this.r=a.r;this.d=d;this.a=[];this.F=d;this.n=new t(this,a.z(),a.w())}j=s.prototype;
+       j.q=function(a){var b;a:if(this.a.indexOf)b=this.a.indexOf(a)!=-1;else{b=0;for(var c;c=this.a[b];b++)if(c==a){b=!0;break a}b=!1}if(b)return!1;if(this.d){if(this.r)c=this.a.length+1,b=(this.d.lat()*(c-1)+a.getPosition().lat())/c,c=(this.d.lng()*(c-1)+a.getPosition().lng())/c,this.d=new google.maps.LatLng(b,c),y(this)}else this.d=a.getPosition(),y(this);a.s=!0;this.a.push(a);b=this.a.length;b<this.l&&a.getMap()!=this.c&&a.setMap(this.c);if(b==this.l)for(c=0;c<b;c++)this.a[c].setMap(d);b>=this.l&&a.setMap(d);
+               a=this.c.getZoom();if((b=this.k.I())&&a>b)for(a=0;b=this.a[a];a++)b.setMap(this.c);else if(this.a.length<this.l)z(this.n);else{b=this.k.H()(this.a,this.k.z().length);this.n.setCenter(this.d);a=this.n;a.B=b;a.ga=b.text;a.ea=b.index;if(a.b)a.b.innerHTML=b.text;b=Math.max(0,a.B.index-1);b=Math.min(a.j.length-1,b);b=a.j[b];a.da=b.url;a.h=b.height;a.p=b.width;a.M=b.textColor;a.e=b.anchor;a.N=b.textSize;a.D=b.backgroundPosition;this.n.show()}return!0};
+       j.getBounds=function(){for(var a=new google.maps.LatLngBounds(this.d,this.d),b=this.o(),c=0,f;f=b[c];c++)a.extend(f.getPosition());return a};j.remove=function(){this.n.remove();this.a.length=0;delete this.a};j.T=function(){return this.a.length};j.o=h("a");j.getCenter=h("d");function y(a){a.F=a.k.v(new google.maps.LatLngBounds(a.d,a.d))}j.getMap=h("c");
+       function t(a,b,c){a.k.extend(t,google.maps.OverlayView);this.j=b;this.fa=c||0;this.u=a;this.d=d;this.c=a.getMap();this.B=this.b=d;this.t=!1;this.setMap(this.c)}j=t.prototype;
+       j.onAdd=function(){this.b=document.createElement("DIV");if(this.t)this.b.style.cssText=A(this,B(this,this.d)),this.b.innerHTML=this.B.text;this.getPanes().overlayMouseTarget.appendChild(this.b);var a=this;google.maps.event.addDomListener(this.b,"click",function(){var b=a.u.k;google.maps.event.trigger(b,"clusterclick",a.u);b.O&&a.c.fitBounds(a.u.getBounds())})};function B(a,b){var c=a.getProjection().fromLatLngToDivPixel(b);c.x-=parseInt(a.p/2,10);c.y-=parseInt(a.h/2,10);return c}
+       j.draw=function(){if(this.t){var a=B(this,this.d);this.b.style.top=a.y+"px";this.b.style.left=a.x+"px"}};function z(a){if(a.b)a.b.style.display="none";a.t=!1}j.show=function(){if(this.b)this.b.style.cssText=A(this,B(this,this.d)),this.b.style.display="";this.t=!0};j.remove=function(){this.setMap(d)};j.onRemove=function(){if(this.b&&this.b.parentNode)z(this),this.b.parentNode.removeChild(this.b),this.b=d};j.setCenter=e("d");
+       function A(a,b){var c=[];c.push("background-image:url("+a.da+");");c.push("background-position:"+(a.D?a.D:"0 0")+";");typeof a.e==="object"?(typeof a.e[0]==="number"&&a.e[0]>0&&a.e[0]<a.h?c.push("height:"+(a.h-a.e[0])+"px; padding-top:"+a.e[0]+"px;"):c.push("height:"+a.h+"px; line-height:"+a.h+"px;"),typeof a.e[1]==="number"&&a.e[1]>0&&a.e[1]<a.p?c.push("width:"+(a.p-a.e[1])+"px; padding-left:"+a.e[1]+"px;"):c.push("width:"+a.p+"px; text-align:center;")):c.push("height:"+a.h+"px; line-height:"+a.h+
+       "px; width:"+a.p+"px; text-align:center;");c.push("cursor:pointer; top:"+b.y+"px; left:"+b.x+"px; color:"+(a.M?a.M:"black")+"; position:absolute; font-size:"+(a.N?a.N:11)+"px; font-family:Arial,sans-serif; font-weight:bold");return c.join("")}window.MarkerClusterer=k;k.prototype.addMarker=k.prototype.q;k.prototype.addMarkers=k.prototype.C;k.prototype.clearMarkers=k.prototype.R;k.prototype.fitMapToMarkers=k.prototype.S;k.prototype.getCalculator=k.prototype.H;k.prototype.getGridSize=k.prototype.w;
+       k.prototype.getExtendedBounds=k.prototype.v;k.prototype.getMap=k.prototype.getMap;k.prototype.getMarkers=k.prototype.o;k.prototype.getMaxZoom=k.prototype.I;k.prototype.getStyles=k.prototype.z;k.prototype.getTotalClusters=k.prototype.U;k.prototype.getTotalMarkers=k.prototype.V;k.prototype.redraw=k.prototype.i;k.prototype.removeMarker=k.prototype.Y;k.prototype.removeMarkers=k.prototype.Z;k.prototype.resetViewport=k.prototype.m;k.prototype.repaint=k.prototype.L;k.prototype.setCalculator=k.prototype.$;
+       k.prototype.setGridSize=k.prototype.aa;k.prototype.setMaxZoom=k.prototype.ba;k.prototype.onAdd=k.prototype.onAdd;k.prototype.draw=k.prototype.draw;s.prototype.getCenter=s.prototype.getCenter;s.prototype.getSize=s.prototype.T;s.prototype.getMarkers=s.prototype.o;t.prototype.onAdd=t.prototype.onAdd;t.prototype.draw=t.prototype.draw;t.prototype.onRemove=t.prototype.onRemove;
+})();
+
+
+/**
+ * WordCampCentral
+ *
+ * Custom client-side behaviors for the Central theme
+ */
</ins><span class="cx" style="display: block; padding: 0 10px"> var WordCampCentral = ( function( $ ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><span class="cx" style="display: block; padding: 0 10px">         // templateOptions is copied from Core in order to avoid an extra HTTP request just to get wp.template
</span><span class="cx" style="display: block; padding: 0 10px">        var options,
</span><span class="cx" style="display: block; padding: 0 10px">                templateOptions = {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -10,6 +45,8 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><span class="cx" style="display: block; padding: 0 10px">         * Initialization that runs as soon as this file has loaded
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         *
+        * @param {object} initOptions
</ins><span class="cx" style="display: block; padding: 0 10px">          */
</span><span class="cx" style="display: block; padding: 0 10px">        function immediateInit( initOptions ) {
</span><span class="cx" style="display: block; padding: 0 10px">                options = initOptions;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -22,6 +59,13 @@
</span><span class="cx" style="display: block; padding: 0 10px">         * Initialization that runs when the document has fully loaded
</span><span class="cx" style="display: block; padding: 0 10px">         */
</span><span class="cx" style="display: block; padding: 0 10px">        function documentReadyInit() {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                try {
+                       if ( options.hasOwnProperty( 'mapContainer' ) && options.hasOwnProperty( 'mapMarkers' ) ) {
+                               loadMap( options.mapContainer, options.mapMarkers );
+                       }
+               } catch ( exception ) {
+                       log( exception );
+               }
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -103,11 +147,311 @@
</span><span class="cx" style="display: block; padding: 0 10px">                );
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * Build a Google Map in the given container with the given marker data
+        *
+        * @param {string} container
+        * @param {object} markers
+        */
+       function loadMap( container, markers ) {
+               if ( ! $( '#' + container ).length ) {
+                       throw "Map container element isn't present in the DOM.";
+               }
+
+               if ( 'undefined' === typeof( google ) || ! google.hasOwnProperty( 'maps' ) ) {
+                       throw 'Google Maps library is not loaded.';
+               }
+
+               var map, markerCluster,
+                       mapOptions = {
+                               center            : new google.maps.LatLng( 15.000, 7.000 ),
+                               zoom              : 2,
+                               zoomControl       : true,
+                               mapTypeControl    : false,
+                               streetViewControl : false
+               };
+
+               map     = new google.maps.Map( document.getElementById( container ), mapOptions );
+               markers = createMarkers(  map, markers );
+
+               /*
+                * The About map contains all camps, past and present, so there will be camps from different years that
+                * are located in the same venue, and their markers will overlap.
+                */
+               if ( 'wcc-map-about' == container ) {
+                       markers = repositionOverlappingMarkers( markers );
+               }
+
+               markerCluster = clusterMarkers( map, markers );
+       }
+
+       /**
+        * Create markers on a map with the given marker data
+        *
+        * Normally the markers would be assigned to the map at this point, but we'll run them through MarkerClusterer
+        * later on, so adding them to the map now is unnecessary and negatively affects performance.
+        *
+        * @param {google.maps.Map} map
+        * @param {object}          markers
+        *
+        * @return {object}
+        */
+       function createMarkers( map, markers ) {
+               var markerID,
+                       infoWindowTemplate = _.template( $( '#tmpl-wcc-map-marker' ).html(), null, templateOptions ),
+                       infoWindow         = new google.maps.InfoWindow( {
+                               pixelOffset: new google.maps.Size( -options.markerIconAnchorXOffset, 0 )
+                       } );
+
+               for ( markerID in markers ) {
+                       if ( ! markers.hasOwnProperty( markerID ) ) {
+                               continue;
+                       }
+
+                       markers[ markerID ] = new google.maps.Marker( {
+                               wccID     : markerID,
+                               wccURL    : markers[ markerID ].url,
+                               wccDates  : markers[ markerID ].dates,
+                               location  : markers[ markerID ].location,
+                               venueName : markers[ markerID ].venueName,
+                               title     : markers[ markerID ].name,
+
+                               icon : {
+                                       url        : options.markerIconBaseURL + markers[ markerID ].iconURL,
+                                       size       : new google.maps.Size(  options.markerIconHeight,        options.markerIconWidth ),
+                                       anchor     : new google.maps.Point( options.markerIconAnchorXOffset, options.markerIconWidth / 2 ),
+                                       scaledSize : new google.maps.Size(  options.markerIconHeight / 2,    options.markerIconWidth / 2 )
+                               },
+
+                               position : new google.maps.LatLng(
+                                       markers[ markerID ].latitude,
+                                       markers[ markerID ].longitude
+                               )
+                       } );
+
+                       google.maps.event.addListener( markers[ markerID ], 'click', function() {
+                               try {
+                                       infoWindow.setContent( infoWindowTemplate( { wordcamp: markers[ this.wccID ] } ) );
+                                       infoWindow.open( map, markers[ this.wccID ] );
+                               } catch ( exception ) {
+                                       log( exception );
+                               }
+                       } );
+               }
+
+               return markers;
+       }
+
+       /**
+        * Offset the position of overlapping markers
+        *
+        * Often camps will use the same venue for multiple years, and those map pins would be placed in the exact same
+        * spot by default, making it impossible to open the overlaid pins, or even know that they're there. This
+        * function will spread overlapping pins out in a circle around the original point.
+        *
+        * @todo It'd be nice to adjust the distance on the fly based on the zoom level, so that you could always see
+        *       that there are multiple markers at a given location, rather than having to zoom in to the neighborhood
+        *       level to know that.
+        *
+        * @param {object} markers
+        *
+        * @returns {object}
+        */
+       function repositionOverlappingMarkers( markers ) {
+               var groupedMarkers = groupMarkersByCoordinates( markers );
+
+               _.each( groupedMarkers, function( markerGroup ) {
+                       var markerGroupSize = _.size( markerGroup );
+
+                       if ( markerGroupSize > 1 ) {
+                               var currentMarkerIndex = 1,
+                                       distance           = markerGroupSize == 2 ? .1 : .5;  // when there are only 2 markers, it's not as obvious that they're centered around a point in the middle
+
+                               _.each( markerGroup, function( marker, markerID ) {
+                                       var bearing     = currentMarkerIndex / markerGroupSize * 360 + 90,
+                                               newPosition = calculateDestinationPoint( marker.getPosition(), bearing, distance );
+
+                                       markers[ markerID ].setPosition( newPosition );
+                                       currentMarkerIndex++;
+                               } );
+                       }
+               } );
+
+               return markers;
+       }
+
+       /**
+        * Group markers by their coordinates
+        *
+        * @param {object} markers
+        *
+        * @returns {object}
+        */
+       function groupMarkersByCoordinates( markers ) {
+               var groupedMarkers = {};
+
+               _.each( markers, function( marker, markerID ) {
+                       var position    = marker.getPosition(),
+                               coordinates = position.lat() + '|' + position.lng();
+
+                       if ( ! groupedMarkers.hasOwnProperty( coordinates ) ) {
+                               groupedMarkers[ coordinates ] = {};
+                       }
+
+                       groupedMarkers[ coordinates ][ markerID ] = marker;
+               } );
+
+               return groupedMarkers;
+       }
+
+       /**
+        * Calculate the destination point after moving a distance with a bearing from a starting point
+        *
+        * Based on http://www.movable-type.co.uk/scripts/latlong.html
+        *
+        * @param {google.maps.LatLng} startPosition
+        * @param {number}             bearing in degrees
+        * @param {number}             distance in kilometers
+        *
+        * @returns {google.maps.LatLng}
+        */
+       function calculateDestinationPoint( startPosition, bearing, distance ) {
+               var startLatitude, startLongitude, newLatitude, newLongitude,
+                       earthRadius = 6371; // in kilometers
+
+               startLatitude  = startPosition.lat().toRadians();
+               startLongitude = startPosition.lng().toRadians();
+               bearing        = bearing.toRadians();
+
+               newLatitude = Math.asin(
+                       Math.sin( startLatitude )          *
+                       Math.cos( distance / earthRadius ) +
+                       Math.cos( startLatitude )          *
+                       Math.sin( distance / earthRadius ) *
+                       Math.cos( bearing )
+               );
+
+               newLongitude = startLongitude + Math.atan2(
+                       Math.sin( bearing )                *
+                       Math.sin( distance / earthRadius ) *
+                       Math.cos( startLatitude ),
+
+                       Math.cos( distance / earthRadius ) -
+                       Math.sin( startLatitude )          *
+                       Math.sin( newLatitude )
+               );
+
+               return new google.maps.LatLng( newLatitude.toDegrees(), newLongitude.toDegrees() );
+       }
+
+       /**
+        * Cluster the markers into groups for improved performance and UX
+        *
+        * options.markerClusterIcon is just 1x size, because MarkerClusterer doesn't support retina images.
+        * MarkerClusterer Plus does, but it doesn't seem as official, so I'm not as confident that it's secure,
+        * stable, etc.
+        *
+        * @todo the location of clustered pins is shifted off the center of where it should be when zoomed out,
+        *       and shifts closer to the actual location each time you zoom in
+        *
+        * @param {google.maps.Map} map
+        * @param {object}          markers
+        *
+        * @return MarkerClusterer
+        */
+       function clusterMarkers( map, markers ) {
+               var clusterOptions,
+                       markersArray = [];
+
+               /*
+                * We're storing markers in an object so that they can be accessed directly by ID, rather than having to
+                * loop through them to find one. MarkerClusterer requires them to be passed in as an object, though, so
+                * we need to convert them here.
+                */
+               for ( var m in markers ) {
+                       markersArray.push( markers[ m ] );
+               }
+
+               clusterOptions = {
+                       maxZoom:  13,
+                       gridSize: 40,
+                       styles:   [
+                               {
+                                       url:       options.markerIconBaseURL + options.markerClusterIcon,
+                                       height:    options.markerIconWidth  / 2,
+                                       width:     options.markerIconHeight / 2,
+                                       anchor:    [ 5, -0 ],
+                                       textColor: '#ffffff',
+                                       textSize:  22
+                               },
+
+                               {
+                                       url:       options.markerIconBaseURL + options.markerClusterIcon,
+                                       height:    options.markerIconWidth  / 2,
+                                       width:     options.markerIconHeight / 2,
+                                       anchor:    [ 5, -5 ],
+                                       textColor: '#ffffff',
+                                       textSize:  18
+                               },
+
+                               {
+                                       url:       options.markerIconBaseURL + options.markerClusterIcon,
+                                       height:    options.markerIconWidth  / 2,
+                                       width:     options.markerIconHeight / 2,
+                                       anchor:    [ 5, -5 ],
+                                       textColor: '#ffffff',
+                                       textSize:  18
+                               }
+                       ]
+               };
+
+               return new MarkerClusterer( map, markersArray, clusterOptions );
+       }
+
+       /**
+        * Log a message to the console
+        *
+        * @param {*} message
+        */
+       function log( message ) {
+               if ( ! window.console ) {
+                       return;
+               }
+
+               if ( 'string' == typeof( message ) ) {
+                       console.log( 'WordCampCentral: ' + message );
+               } else {
+                       console.log( 'WordCampCentral: ', message );
+               }
+       }
+
</ins><span class="cx" style="display: block; padding: 0 10px">         return {
</span><span class="cx" style="display: block; padding: 0 10px">                immediateInit:     immediateInit,
</span><span class="cx" style="display: block; padding: 0 10px">                documentReadyInit: documentReadyInit
</span><span class="cx" style="display: block; padding: 0 10px">        };
</span><span class="cx" style="display: block; padding: 0 10px"> } )( jQuery );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+if ( 'undefined' === typeof( Number.prototype.toRadians ) ) {
+       /**
+        * Convert degrees to radians
+        *
+        * @returns {number}
+        */
+       Number.prototype.toRadians = function() {
+               return this * Math.PI / 180;
+       };
+}
+
+if ( 'undefined' === typeof( Number.prototype.toDegrees ) ) {
+       /**
+        * Convert radians to degrees
+        *
+        * @returns {number}
+        */
+       Number.prototype.toDegrees = function() {
+               return this * 180 / Math.PI;
+       };
+}
+
</ins><span class="cx" style="display: block; padding: 0 10px"> WordCampCentral.immediateInit( wordcampCentralOptions );
</span><span class="cx" style="display: block; padding: 0 10px"> jQuery( document ).ready( WordCampCentral.documentReadyInit );
</span></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentthemeswordcampcentral2012shortcodeaboutmapphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/themes/wordcamp-central-2012/shortcode-about-map.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/themes/wordcamp-central-2012/shortcode-about-map.php                              (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/themes/wordcamp-central-2012/shortcode-about-map.php        2015-05-12 22:41:20 UTC (rev 1566)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,21 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<div id="wcc-map-<?php echo esc_attr( $attributes['id'] ); ?>" class="wcc-map">
+       <div id="wcc-map-spinner" class="spinner spinner-visible"></div>
+</div>
+
+<script id="tmpl-wcc-map-marker" type="text/html">
+       <# var items = [ 'wccDates', 'location', 'venueName' ]; #>
+
+       <div id="wcc-map-marker-{{wordcamp.wccID}}" class="wcc-map-marker">
+               <h3>
+                       <a href="{{wordcamp.wccURL}}">{{wordcamp.title}}</a>
+               </h3>
+
+               <ul>
+                       <# for ( var item in items ) { #>
+                               <# if ( '' != wordcamp[ items[ item ] ] ) { #>
+                                       <li>{{wordcamp[ items[ item ] ]}}</li>
+                               <# } #>
+                       <# } #>
+               </ul>
+       </div>
+</script>
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentthemeswordcampcentral2012stylecss"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: sites/trunk/wordcamp.org/public_html/wp-content/themes/wordcamp-central-2012/style.css</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/themes/wordcamp-central-2012/style.css    2015-05-12 21:50:55 UTC (rev 1565)
+++ sites/trunk/wordcamp.org/public_html/wp-content/themes/wordcamp-central-2012/style.css      2015-05-12 22:41:20 UTC (rev 1566)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1965,14 +1965,6 @@
</span><span class="cx" style="display: block; padding: 0 10px">        margin: 12px;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-.about-page .about-map {
-       float: left;
-       margin: -4px 20px 40px 0;
-       padding: 12px;
-       box-shadow: 0 1px 3px 1px rgba(0,0,0,.3);
-       -webkit-box-shadow: 0 1px 3px 1px rgba(0,0,0,.3);
-}
-
</del><span class="cx" style="display: block; padding: 0 10px"> #content .about-stats {
</span><span class="cx" style="display: block; padding: 0 10px">        margin: 0;
</span><span class="cx" style="display: block; padding: 0 10px">        background-color: #f1f6f9;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2041,6 +2033,31 @@
</span><span class="cx" style="display: block; padding: 0 10px">        margin-top: 5px;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/* !03f. Maps */
+/* ------------------------------------- */
+
+.wcc-map {
+       position: relative;
+       height: 325px;
+       background-color: #E5E3DF;
+}
+
+#wcc-map-spinner {
+       position: absolute;
+       float: none;
+       top: 50%;
+       left: 50%;
+       margin: -10px 0 0 0;    /* take half the height of the spinner off the top, so that it's perfectly centered */
+}
+
+.wcc-map-marker ul {
+       margin-left: 0;
+}
+
+.wcc-map-marker ul li {
+       list-style-type: none;
+}
+
</ins><span class="cx" style="display: block; padding: 0 10px"> /* !04. Posts */
</span><span class="cx" style="display: block; padding: 0 10px"> /* ============================================= */
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span></span></pre>
</div>
</div>

</body>
</html>