HirshHorn theme: how I created it

Paul Bearne
Paul BearneFreelance Senior WordPress Full Stack Developer at Paul & Gina Bearne
The HirshHorn Theme

           How I created it

Snippets of code and techniques I used
Credits

 Client: Hirshhorn Museum and Sculpture Garden
 ,          Smithsonian, Washington, D.C.

 Design: Bruce Mau Design


 Media Agency: Art & Science (formerly Juice).
   Technical director: Spencer Saunders
   WordPress coding: Paul Bearne
This might not be the only or best
way!
 What you will see is how I solved the problems at
 the point in time (Sept 2011) when I did this
 project.

 There is a lot of WordPress code in this talk; I am
 assuming that you can read and understand the
 code!

 I am using code snippets so that I can get them
 on the slides, so not all the comments or code are
 shown!
Notes

 At the end I am going to ask what you found the
 most useful

 Slides @ http://www.slideshare.net/pbearne
Overview Demo
Wire frame Layout

                      menu




Prev page …        Current page   Next page …




                      footer

                      Screen
Viewsource
<body class="single single-collection postid-1349">
<div id="wrapper" class="hfeed">
   <div id="header">
       Standard WP menu header
   </div><!-- #header-->
  <div id="main">
      <div id="container">
         <div id="content">
             <div class="entry-content" id="makeMeScrollable">
               <div id="detail-of..." data-id="7639" title="Detail of..."
                       class="hhh_T_6 jsf_LoadViaAjax post-7639
                                  collection type-collection status-publish hentry" ></div>
            <div id="..." data-id="3734" title="...“
                       class="hhh_T_3 jsf_LoadViaAjax post-3734
                                  collection type-collection status-publish hentry"></div>
                                                        ......
            </div>
         </div>
      </div>
  </div>
</div>
</body>
<div id="home" data-id="1349" title="Home"
       class="hhh_T_7 jsf_Loaded post-1349
                     collection type-collection status-publish
hentry"
       <div id="page10" class="jst_BoxContaner
hhh_template10">
              <div class="hhh_link hhh_box13 hhh_item_1">
                     <a href="http://link to bio">
                             <img src="...." /></a>
              </div>
              <div class="hhh_box2 hhh_item_2">
                     <h4>Headline text</h4>
                     <p>Random text</p>
              </div>
              <div class="hhh_videoInline hhh_box8
hhh_item_3">
                     http://youtu.be/DeYZVBzty0w
              </div>
The scrolling plugin
 http://www.smoothdivscroll.com (forked version)


$(document).ready(function () {
     $("#makeMeScrollable").smoothDivScroll({
     mousewheelScrolling: "allDirections",
     manualContinuousScrolling: true,
     autoScrollingMode: "onStart" });
});

                            Note: not all the settings I used are shown
Changes to smoothdevscroll
swapLastToFirst: function(){
 var self = this, el = this.element, o = this.options;
  el.data("swappedElement", el.data("scrollableArea")
       .children(":last").detach());

el.data("scrollableArea").prepend(el.data("swappedElem
ent"));
  el.data("scrollWrapper")
        .scrollLeft(el.data("scrollWrapper")
        .scrollLeft() + el.ata("swappedElement")
        .outerWidth(true));
el.data("getNextElementWidth", true);
el.data("enabled", true);
self._showHideHotSpots();
Changes to smoothdevscroll
_updateHash : function(){
var self = this, el = this.element, o = this.options, allBoxContaners=[], CurrentScrollLeft, currentDivId = 0

$('#makeMeScrollable
.scrollableArea').children('div').each(function(index,element){
allBoxContaners.push([$(element).attr('id'), Math.round(
$(element).position().left)])
});
CurrentScrollLeft = $(".scrollWrapper").scrollLeft()
if(allBoxContaners.length > 0){
                  while(allBoxContaners[currentDivId][1] < CurrentScrollLeft -
                            ($(window).width()/2)+100 ){
                           currentDivId ++;
             }
             var wall = allBoxContaners[i][0]
             if ($.bbq.getState("collection") != wall){
                           $.bbq.pushState({collection : wall });
                           }
Keeping state and bookmarks

www.hirshhorn.si.edu/collection/home/#collection=home


#collection=doug-aitken-2
&detail=http%3A//www.hirshhorn.si.edu/bio/doug-aitken-interviews/
&title=Doug+Aitken+Interviews
JQUERY BBQ: BACK BUTTON & QUERY
LIBRARY

 HTTP://BENALMAN.COM/PROJECTS/JQUERY-BBQ-PLUGIN


// PUSH THIS URL "STATE" ONTO THE HISTORY HASH.
$.BBQ.PUSHSTATE({ URL: HREF });

$(WINDOW).BIND( "HASHCHANGE", FUNCTION(E) {
      PUT THE ACTION CODE HERE
}

$(WINDOW).TRIGGER( "HASHCHANGE" );
Over riding the menu URLs
jQuery('#menu a').live('click', function(e) {
   var href = this.href;
   // does the clicked URL and current URL have '/collection/' in
the path?
   if (href.indexOf('/collection/') > 0 &&
document.URL.indexOf('/collection/') > 0){
          var clickId = href.toLowerCase().split('/');
           // remove any current state
          jQuery.bbq.removeState("wall", "title", "detail");
          // and set new state
          jQuery.bbq.pushState({ collection: clickId });
          // stop any other on-clicks
          e.stopImmediatePropagation();
          return false;
    }
Example hashchange function
jQuery(window).bind("hashchange", function(e) {
          collectionURL = jQuery.bbq.getState("collection");
          // try to get an title from somewhere.
          title = jQuery.bbq.getState("title") ? jQuery.bbq.getState("title")
                              : jQuery('#' + collectionURL).attr('title');
          document.title = title;
          if (undefined === collectionURL) {
                     collectionURL = jQuery('.jsf_Loaded').attr('id');
          }
jQuery("div#makeMeScrollable").smoothDivScroll("scrollToElement",
"id", collectionURL);
}
Example wall fragment


<div class="hhh_link hhh_box13 hhh_item_1">
         <a href="http://www.hirshhorn.si.edu/collection/dark-
matters/">

              <img src="...." />
         </a>
</div>
Example wall click action
// add the scroll to action to wall links
jQuery('.hhh_link a').on('click', function(e) {
           var clickId = this.href.toLowerCase().split('/');
           var l = clickId.length
           if ( clickId[l-1].length > 1){
                        var         scrollToId = clickId[l-1]
           }else{
                        var         scrollToId = clickId[l-2]
           }
jQuery("div#makeMeScrollable").smoothDivScroll("scrollToElement", "id",scrollToId);
// stop any other onclicks
e.stopImmediatePropagation()
return false;
});

                Note: no hashchange this is done in the move finished callback from
                                                                   smoothDivScroll
Using a menu to store the order




register_nav_menu( „collection‟, 'Select the slider content
menu.');
Collection page PHP
// get the menu object for theme menu location “collection”
$menu_items =
wp_get_nav_menu_items($locations['collection';]);

// loop the menu object again to insert the current page and
update the div before and 4 dev‟s after so that content we
loaded on page load

foreach ( (array) $menu_items as $key => $menu_item ) {
           $title = $menu_item->title;
           $url = $menu_item->url;
           $id = $menu_item->object_id;
           $templateId= 'hhh_T_'.get_post_meta($id, 'hhh_template_Id',
true).' ';
           $slug = basename(get_permalink($id));
// is this post in the menu the current post
if ($post->ID == $id) {
           Next slide……
Collection page PHP
if ($post->ID == $id) {
          //check it not a single post to handle preview
          if(count($array_of_divs)>0){
                               $last_id = $array_of_divs[count($array_of_divs)-
1][0];
          $div_text = '<div id="'.basename(get_permalink($last_id)).'"
                    title="'.$last_id.'" class="'.$templateId.implode("
          ",get_post_class("jsf_ajaxOnLoad",$last_id)).'" ></div>' ;

          array_pop($array_of_divs); // remove the last empty div
          array_push( $array_of_divs , array($last_id , $div_text) );
           // add it back in with extra class "jsf_ajaxOnLoad"
          } // load the content into a div
          $div_text = '<div id="'.basename(get_permalink($id)).'" title="'.$id.'"
class="'.$templateId.'jsf_Loaded '.implode(" ",get_post_class("",$id)).'"
>'.get_the_content().'</div>' ;
          $jsf_ajaxOnLoad = 5;
}else{
Collection page PHP
}else{
       if ($jsf_ajaxOnLoad > 0){ // 4 div after the loaded
content
                $jsf_ajaxOnLoad -- ;
                $extra_class_test =
$templateId."jsf_ajaxOnLoad ";
       }else{
                $extra_class_test =
$templateId."jsf_LoadViaAjax ";
       }
       $div_text = '<div
id="'.basename(get_permalink($id)).'" title="'.$id.'"
class="'.$extra_class_test.implode("
",get_post_class("",$id)).'" ></div>' ;
Collection page PHP
<div class="entry-content" id="makeMeScrollable">
       <?php
       foreach ( (array)$array_of_divs as $jsf_div){
             echo($jsf_div[1]);
             }
       ?>
</div><!-- .entry-content -->
Now to call AJAX in WordPress

URL: /wp-admin/admin-
ajax.php?action=show_content_ajax_call


add_action('wp_ajax_show_content_ajax_call',
array( $this, 'jsf_show_content_ajax'));

add_action('wp_ajax_nopriv_show_content_ajax_c
all', array( $this, 'jsf_show_content_ajax'));
Content fetch AJAX PHP function
function jsf_show_content_ajax($id){
       $postID = $_POST['postID'];
       $content_post = get_post($postID);
       $content = $content_post->post_content;
       $content = apply_filters('the_content', $content);
       $jsonpost = array();
       $jsonpost["id"] = $postID;
       $jsonpost["slug"] = basename(get_permalink($postID)
       $jsonpost["content"] = str_replace(']]>', ']]>', $content);
       header( 'Content-Type: application/json' );
       echo json_encode($jsonpost);;
       exit;
}
Content fetch AJAX function
scrollerRightLimitReached: function() {
    $("div#makeMeScrollable").smoothDivScroll("swapFirstToLast");
    if($('#makeMeScrollable .scrollableArea').children(":last").html().length <= 1){
            var id = $('#makeMeScrollable .scrollableArea').children(":last").attr("id")
            $.ajax({
                 url:"/wp-admin/admin-ajax.php",
                 type:'POST',
                 dataType: 'json',
                 data:'action=show_content_ajax_call&postID='+$('#'+id).attr("title")+'&t=3&slu
+ id,
                 success:function(results){// load into div
                       $('#' + results['slug']).html(results['content']);
                       $('#' + results['slug']+' .jst_BoxContaner').hide().fadeIn();;
                       $('#' + results['slug']).removeClass('jsf_ajaxOnLoad');
                 }
            })
        }
}
Custom content in TinyMCE
TinyMCE editor css

Create a editor-style.css file in your theme root
add_editor_style();

Tip: use the same style sheet in the theme

wp_register_style('jsf_BoxStyles', get_stylesheet_directory_uri().'/editor-
style.css');
wp_enqueue_style( 'jsf_BoxStyles')


http://codex.wordpress.org/Function_Reference/add_editor_style
Injecting code into the TinyMCE
editor
 Server side
add_filter('default_content', 'my_editor_content');
function my_editor_content( $content ) {
      $content = "If you enjoyed this post, make sure to subscribe to my
rss feed.";
      return $content;
}


 Client side
var jsf_ed = tinyMCE.activeEditor;
jsf_ed.selection.select(jsf_ed.getBody(), true);
window.send_to_editor(“<div>content);
How to add button to tinyMCE editor



// Add only in Rich Editor mode
if ( get_user_option('rich_editing') == 'true') {
         add_filter("mce_external_plugins",
"add_hhh_custom_tinymce_plugin");
         add_filter('mce_buttons', register_hhh_custom_button');
}
How to add button to tinyMCE editor

function register_hhh_custom_button($buttons) {
       array_push($buttons, "|", "hhh_highlight");
       return $buttons;
}

function add_hhh_custom_tinymce_plugin($plugin_array)
{
       $plugin_array['hhh_highlight'] =
get_stylesheet_directory_uri().'/mce/editor_plugin.js';
       return $plugin_array;
}
editor_plugin.js
(function() {

                tinymce.create('tinymce.plugins.hhh_highlightPlugin', {
                init : function(ed, url) {            ed.addCommand('mceHighlight', function() {
                                        ed.windowManager.open({
                                        file : url + '/set_behavior.htm',
                                        width : 400,height : 600 ,inline : 1
                            }, {plugin_url : url});
                });
            ed.addButton('hhh_highlight', {title : 'Highlight', cmd : 'mceHighlight', image:
url + '/hhhicon.gif' });
                },
           getInfo : function() {return {longname : 'Set Behavior',author : 'Paul
Bearne',authorurl : 'http://www.bearne.ca',infourl :
'http://www.thejuiceagency.com',version : tinymce.majorVersion + "." +
tinymce.minorVersion              };
                }
                });
tinymce.PluginManager.add('hhh_highlight', tinymce.plugins.hhh_highlightPlugin);
})();
How to add button to full screen
editor
function hhh_fullscreen_buttons($buttons){
   $buttons[] = 'separator'; // add a separator
   $buttons['hhh_highlight'] = array(
        'title' => __('Highlighter'), // Title of the button
        'onclick' =>
"tinyMCE.execCommand('mceHighlight');",                 'both' =>
false// Show on visual AND html mode
        );
        return $buttons;
}
add_filter( 'wp_fullscreen_buttons',
'hhh_fullscreen_buttons' );
Slides @ http://www.slideshare.net/pbearne
How to read from TinyMCE editor
<script type="text/javascript" src="/wp-admin/load-
scripts.php?c=1&load=jquery &ver=XXXX"></script>
<script type="text/javascript" src="/wp-
includes/js/tinymce/tiny_mce_popup.js?v=3211"></script>
var HighlightDialog = {
         local_ed : 'ed',
         init : function(ed) {
                   HighlightDialog.local_ed = ed;
          if (jQuery.trim( HighlightDialog.local_ed.selection.getContent()
).length < 1){

         tinyMCEPopup.execCommand('mceSelectNodeDepth',false,0);}
         // if we did get with above if lets walk out untill we do
while (-1 ==
HighlightDialog.local_ed.selection.getContent().indexOf("hhh_box")) ){
         tinyMCEPopup.execCommand('mceSelectNodeDepth',false,1);}
tinyMCEPopup.resizeToInnerSize();
},                                                                   Cont on next
How to write to TinyMCE editor
Cont. from last slide..
insert : function insertHighlightSection(ed) {
         // get selected text
         output =
HighlightDialog.local_ed.selection.getContent();
….. Change it as needed ……………
         // write the value back to the editor replace all
content
         tinyMCEPopup.execCommand('mceInsertRawHTM
L', false, output);
         tinyMCEPopup.close(); // all done close the popup
};
// call on load function
 tinyMCEPopup.onInit.add(HighlightDialog.init,
PopUp pages in dialogs
 Used to provide extended detail
If is a detail page then show in a
dialog
dialog = jQuery('<div class="hhh_dialog" id="dialog“
style="display:hidden"></div>').appendTo('body');


dialog.load( jQuery.bbq.getState("detail"),{},
         function(responseText, textStatus, XMLHttpRequest) {
         dialog.dialog({
            modal: true,height: 720,width: 1050,position: 'top',
closeText: 'X' ,
            open: function(event, ui) {

jQuery("div#makeMeScrollable").smoothDivScroll("scrollToElement
", "id",
                                    jQuery.bbq.getState("collection") );
             },
             close: function(event, ui) {
                   jQuery.bbq.removeState("detail");
             },
         });
If not an AJAX call then redirect
if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) &&
strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) ==
'xmlhttprequest') {
          $ajaxcall = true;
}
if(!$ajaxcall){
          $hhh_rediect_url =
get_post_meta(get_the_ID(),'_hhh_rediect_url',TRUE);
          if (strlen($hhh_rediect_url) > 0){
                     $hhh_rediect_url .= '#detail='. get_permalink();
                             ?><script type="text/javascript">/* <![CDATA[ */
                             window.location = "<?php echo
$hhh_rediect_url ?>"
                             /* ]]> */</script><?php
          }
}else{
          the_post()
}
The links
 Slides @ http://www.slideshare.net/pbearne




 @pbearne
 pbearne@gmail.com
1 of 39

Recommended

jQuery Presentasion by
jQuery PresentasionjQuery Presentasion
jQuery PresentasionMohammad Usman
328 views89 slides
jQuery: Tips, tricks and hints for better development and Performance by
jQuery: Tips, tricks and hints for better development and PerformancejQuery: Tips, tricks and hints for better development and Performance
jQuery: Tips, tricks and hints for better development and PerformanceJonas De Smet
3.5K views33 slides
Bacbkone js by
Bacbkone jsBacbkone js
Bacbkone jsАртём Курапов
483 views32 slides
Propel sfugmd by
Propel sfugmdPropel sfugmd
Propel sfugmdiKlaus
464 views22 slides
Building iPhone Web Apps using "classic" Domino by
Building iPhone Web Apps using "classic" DominoBuilding iPhone Web Apps using "classic" Domino
Building iPhone Web Apps using "classic" DominoRob Bontekoe
1.6K views21 slides
Organizing Code with JavascriptMVC by
Organizing Code with JavascriptMVCOrganizing Code with JavascriptMVC
Organizing Code with JavascriptMVCThomas Reynolds
2.9K views56 slides

More Related Content

What's hot

jQuery Basic API by
jQuery Basic APIjQuery Basic API
jQuery Basic APIHyeonseok Shin
1.3K views98 slides
Virtual Madness @ Etsy by
Virtual Madness @ EtsyVirtual Madness @ Etsy
Virtual Madness @ EtsyNishan Subedi
524 views28 slides
Windows Azure Storage & Sql Azure by
Windows Azure Storage & Sql AzureWindows Azure Storage & Sql Azure
Windows Azure Storage & Sql AzureMaarten Balliauw
5.1K views46 slides
Bag Of Tricks From Iusethis by
Bag Of Tricks From IusethisBag Of Tricks From Iusethis
Bag Of Tricks From IusethisMarcus Ramberg
6.4K views88 slides
Jquery by
JqueryJquery
JqueryGirish Srivastava
5.2K views57 slides
jQuery: Nuts, Bolts and Bling by
jQuery: Nuts, Bolts and BlingjQuery: Nuts, Bolts and Bling
jQuery: Nuts, Bolts and BlingDoug Neiner
7.1K views31 slides

What's hot(20)

Windows Azure Storage & Sql Azure by Maarten Balliauw
Windows Azure Storage & Sql AzureWindows Azure Storage & Sql Azure
Windows Azure Storage & Sql Azure
Maarten Balliauw5.1K views
Bag Of Tricks From Iusethis by Marcus Ramberg
Bag Of Tricks From IusethisBag Of Tricks From Iusethis
Bag Of Tricks From Iusethis
Marcus Ramberg6.4K views
jQuery: Nuts, Bolts and Bling by Doug Neiner
jQuery: Nuts, Bolts and BlingjQuery: Nuts, Bolts and Bling
jQuery: Nuts, Bolts and Bling
Doug Neiner7.1K views
Decouple Your Code For Reusability (International PHP Conference / IPC 2008) by Fabien Potencier
Decouple Your Code For Reusability (International PHP Conference / IPC 2008)Decouple Your Code For Reusability (International PHP Conference / IPC 2008)
Decouple Your Code For Reusability (International PHP Conference / IPC 2008)
Fabien Potencier4.2K views
J query b_dotnet_ug_meet_12_may_2012 by ghnash
J query b_dotnet_ug_meet_12_may_2012J query b_dotnet_ug_meet_12_may_2012
J query b_dotnet_ug_meet_12_may_2012
ghnash1.1K views
logic321 by logic321
logic321logic321
logic321
logic321358 views
Doctrine For Beginners by Jonathan Wage
Doctrine For BeginnersDoctrine For Beginners
Doctrine For Beginners
Jonathan Wage1.5K views
jQuery UI Widgets, Drag and Drop, Drupal 7 Javascript by Darren Mothersele
jQuery UI Widgets, Drag and Drop, Drupal 7 JavascriptjQuery UI Widgets, Drag and Drop, Drupal 7 Javascript
jQuery UI Widgets, Drag and Drop, Drupal 7 Javascript
Darren Mothersele12.5K views
Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011 by Alessandro Nadalin
 Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011 Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011
Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011
Alessandro Nadalin9.4K views
Jquery In Rails by shen liu
Jquery In RailsJquery In Rails
Jquery In Rails
shen liu1.6K views
Dig Deeper into WordPress - WD Meetup Cairo by Mohamed Mosaad
Dig Deeper into WordPress - WD Meetup CairoDig Deeper into WordPress - WD Meetup Cairo
Dig Deeper into WordPress - WD Meetup Cairo
Mohamed Mosaad934 views

Viewers also liked

Sarah's Case by
Sarah's CaseSarah's Case
Sarah's Caseangeladh
870 views14 slides
Using WordPress as your application stack by
Using WordPress as your application stackUsing WordPress as your application stack
Using WordPress as your application stackPaul Bearne
1.2K views22 slides
Professional Frontend Engineering by
Professional Frontend EngineeringProfessional Frontend Engineering
Professional Frontend EngineeringCheton Wu
505 views201 slides
WordPress overloading Gravityforms using hooks, filters and extending classes by
WordPress overloading Gravityforms using hooks, filters and extending classes WordPress overloading Gravityforms using hooks, filters and extending classes
WordPress overloading Gravityforms using hooks, filters and extending classes Paul Bearne
3.7K views21 slides
Daughter Themes by
Daughter ThemesDaughter Themes
Daughter ThemesPaul Bearne
1.5K views18 slides
High Performance Web Sites - Tips for faster pages by
High Performance Web Sites - Tips for faster pagesHigh Performance Web Sites - Tips for faster pages
High Performance Web Sites - Tips for faster pagesCheton Wu
891 views126 slides

Viewers also liked(8)

Sarah's Case by angeladh
Sarah's CaseSarah's Case
Sarah's Case
angeladh870 views
Using WordPress as your application stack by Paul Bearne
Using WordPress as your application stackUsing WordPress as your application stack
Using WordPress as your application stack
Paul Bearne1.2K views
Professional Frontend Engineering by Cheton Wu
Professional Frontend EngineeringProfessional Frontend Engineering
Professional Frontend Engineering
Cheton Wu505 views
WordPress overloading Gravityforms using hooks, filters and extending classes by Paul Bearne
WordPress overloading Gravityforms using hooks, filters and extending classes WordPress overloading Gravityforms using hooks, filters and extending classes
WordPress overloading Gravityforms using hooks, filters and extending classes
Paul Bearne3.7K views
Daughter Themes by Paul Bearne
Daughter ThemesDaughter Themes
Daughter Themes
Paul Bearne1.5K views
High Performance Web Sites - Tips for faster pages by Cheton Wu
High Performance Web Sites - Tips for faster pagesHigh Performance Web Sites - Tips for faster pages
High Performance Web Sites - Tips for faster pages
Cheton Wu891 views
Vagrant WordCamp Hamilton by Paul Bearne
Vagrant  WordCamp HamiltonVagrant  WordCamp Hamilton
Vagrant WordCamp Hamilton
Paul Bearne739 views

Similar to HirshHorn theme: how I created it

Separation of concerns - DPC12 by
Separation of concerns - DPC12Separation of concerns - DPC12
Separation of concerns - DPC12Stephan Hochdörfer
2.3K views62 slides
Php by
PhpPhp
PhpLinh Tran
537 views13 slides
jQuery secrets by
jQuery secretsjQuery secrets
jQuery secretsBastian Feder
2.3K views27 slides
WordPress Theme Design and Development Workshop - Day 3 by
WordPress Theme Design and Development Workshop - Day 3WordPress Theme Design and Development Workshop - Day 3
WordPress Theme Design and Development Workshop - Day 3Mizanur Rahaman Mizan
894 views16 slides
jQuery by
jQueryjQuery
jQueryIvano Malavolta
3.2K views67 slides
Introducing jQuery by
Introducing jQueryIntroducing jQuery
Introducing jQueryWildan Maulana
1.1K views17 slides

Similar to HirshHorn theme: how I created it(20)

international PHP2011_Bastian Feder_jQuery's Secrets by smueller_sandsmedia
international PHP2011_Bastian Feder_jQuery's Secretsinternational PHP2011_Bastian Feder_jQuery's Secrets
international PHP2011_Bastian Feder_jQuery's Secrets
Scala based Lift Framework by vhazrati
Scala based Lift FrameworkScala based Lift Framework
Scala based Lift Framework
vhazrati1.3K views
Overview of The Scala Based Lift Web Framework by IndicThreads
Overview of The Scala Based Lift Web FrameworkOverview of The Scala Based Lift Web Framework
Overview of The Scala Based Lift Web Framework
IndicThreads1.9K views
Grok Drupal (7) Theming by PINGV
Grok Drupal (7) ThemingGrok Drupal (7) Theming
Grok Drupal (7) Theming
PINGV25.6K views
Apostrophe by tompunk
ApostropheApostrophe
Apostrophe
tompunk5.4K views
Understanding backbonejs by Nick Lee
Understanding backbonejsUnderstanding backbonejs
Understanding backbonejs
Nick Lee2.6K views
Introduction to jQuery - Barcamp London 9 by Jack Franklin
Introduction to jQuery - Barcamp London 9Introduction to jQuery - Barcamp London 9
Introduction to jQuery - Barcamp London 9
Jack Franklin612 views
Jquery presentation by Mevin Mohan
Jquery presentationJquery presentation
Jquery presentation
Mevin Mohan44 views

HirshHorn theme: how I created it

  • 1. The HirshHorn Theme How I created it Snippets of code and techniques I used
  • 2. Credits  Client: Hirshhorn Museum and Sculpture Garden , Smithsonian, Washington, D.C.  Design: Bruce Mau Design  Media Agency: Art & Science (formerly Juice).  Technical director: Spencer Saunders  WordPress coding: Paul Bearne
  • 3. This might not be the only or best way!  What you will see is how I solved the problems at the point in time (Sept 2011) when I did this project.  There is a lot of WordPress code in this talk; I am assuming that you can read and understand the code!  I am using code snippets so that I can get them on the slides, so not all the comments or code are shown!
  • 4. Notes  At the end I am going to ask what you found the most useful  Slides @ http://www.slideshare.net/pbearne
  • 6. Wire frame Layout menu Prev page … Current page Next page … footer Screen
  • 7. Viewsource <body class="single single-collection postid-1349"> <div id="wrapper" class="hfeed"> <div id="header"> Standard WP menu header </div><!-- #header--> <div id="main"> <div id="container"> <div id="content"> <div class="entry-content" id="makeMeScrollable"> <div id="detail-of..." data-id="7639" title="Detail of..." class="hhh_T_6 jsf_LoadViaAjax post-7639 collection type-collection status-publish hentry" ></div> <div id="..." data-id="3734" title="...“ class="hhh_T_3 jsf_LoadViaAjax post-3734 collection type-collection status-publish hentry"></div> ...... </div> </div> </div> </div> </div> </body>
  • 8. <div id="home" data-id="1349" title="Home" class="hhh_T_7 jsf_Loaded post-1349 collection type-collection status-publish hentry" <div id="page10" class="jst_BoxContaner hhh_template10"> <div class="hhh_link hhh_box13 hhh_item_1"> <a href="http://link to bio"> <img src="...." /></a> </div> <div class="hhh_box2 hhh_item_2"> <h4>Headline text</h4> <p>Random text</p> </div> <div class="hhh_videoInline hhh_box8 hhh_item_3"> http://youtu.be/DeYZVBzty0w </div>
  • 9. The scrolling plugin  http://www.smoothdivscroll.com (forked version) $(document).ready(function () { $("#makeMeScrollable").smoothDivScroll({ mousewheelScrolling: "allDirections", manualContinuousScrolling: true, autoScrollingMode: "onStart" }); }); Note: not all the settings I used are shown
  • 10. Changes to smoothdevscroll swapLastToFirst: function(){ var self = this, el = this.element, o = this.options; el.data("swappedElement", el.data("scrollableArea") .children(":last").detach()); el.data("scrollableArea").prepend(el.data("swappedElem ent")); el.data("scrollWrapper") .scrollLeft(el.data("scrollWrapper") .scrollLeft() + el.ata("swappedElement") .outerWidth(true)); el.data("getNextElementWidth", true); el.data("enabled", true); self._showHideHotSpots();
  • 11. Changes to smoothdevscroll _updateHash : function(){ var self = this, el = this.element, o = this.options, allBoxContaners=[], CurrentScrollLeft, currentDivId = 0 $('#makeMeScrollable .scrollableArea').children('div').each(function(index,element){ allBoxContaners.push([$(element).attr('id'), Math.round( $(element).position().left)]) }); CurrentScrollLeft = $(".scrollWrapper").scrollLeft() if(allBoxContaners.length > 0){ while(allBoxContaners[currentDivId][1] < CurrentScrollLeft - ($(window).width()/2)+100 ){ currentDivId ++; } var wall = allBoxContaners[i][0] if ($.bbq.getState("collection") != wall){ $.bbq.pushState({collection : wall }); }
  • 12. Keeping state and bookmarks www.hirshhorn.si.edu/collection/home/#collection=home #collection=doug-aitken-2 &detail=http%3A//www.hirshhorn.si.edu/bio/doug-aitken-interviews/ &title=Doug+Aitken+Interviews
  • 13. JQUERY BBQ: BACK BUTTON & QUERY LIBRARY  HTTP://BENALMAN.COM/PROJECTS/JQUERY-BBQ-PLUGIN // PUSH THIS URL "STATE" ONTO THE HISTORY HASH. $.BBQ.PUSHSTATE({ URL: HREF }); $(WINDOW).BIND( "HASHCHANGE", FUNCTION(E) { PUT THE ACTION CODE HERE } $(WINDOW).TRIGGER( "HASHCHANGE" );
  • 14. Over riding the menu URLs jQuery('#menu a').live('click', function(e) { var href = this.href; // does the clicked URL and current URL have '/collection/' in the path? if (href.indexOf('/collection/') > 0 && document.URL.indexOf('/collection/') > 0){ var clickId = href.toLowerCase().split('/'); // remove any current state jQuery.bbq.removeState("wall", "title", "detail"); // and set new state jQuery.bbq.pushState({ collection: clickId }); // stop any other on-clicks e.stopImmediatePropagation(); return false; }
  • 15. Example hashchange function jQuery(window).bind("hashchange", function(e) { collectionURL = jQuery.bbq.getState("collection"); // try to get an title from somewhere. title = jQuery.bbq.getState("title") ? jQuery.bbq.getState("title") : jQuery('#' + collectionURL).attr('title'); document.title = title; if (undefined === collectionURL) { collectionURL = jQuery('.jsf_Loaded').attr('id'); } jQuery("div#makeMeScrollable").smoothDivScroll("scrollToElement", "id", collectionURL); }
  • 16. Example wall fragment <div class="hhh_link hhh_box13 hhh_item_1"> <a href="http://www.hirshhorn.si.edu/collection/dark- matters/"> <img src="...." /> </a> </div>
  • 17. Example wall click action // add the scroll to action to wall links jQuery('.hhh_link a').on('click', function(e) { var clickId = this.href.toLowerCase().split('/'); var l = clickId.length if ( clickId[l-1].length > 1){ var scrollToId = clickId[l-1] }else{ var scrollToId = clickId[l-2] } jQuery("div#makeMeScrollable").smoothDivScroll("scrollToElement", "id",scrollToId); // stop any other onclicks e.stopImmediatePropagation() return false; }); Note: no hashchange this is done in the move finished callback from smoothDivScroll
  • 18. Using a menu to store the order register_nav_menu( „collection‟, 'Select the slider content menu.');
  • 19. Collection page PHP // get the menu object for theme menu location “collection” $menu_items = wp_get_nav_menu_items($locations['collection';]); // loop the menu object again to insert the current page and update the div before and 4 dev‟s after so that content we loaded on page load foreach ( (array) $menu_items as $key => $menu_item ) { $title = $menu_item->title; $url = $menu_item->url; $id = $menu_item->object_id; $templateId= 'hhh_T_'.get_post_meta($id, 'hhh_template_Id', true).' '; $slug = basename(get_permalink($id)); // is this post in the menu the current post if ($post->ID == $id) { Next slide……
  • 20. Collection page PHP if ($post->ID == $id) { //check it not a single post to handle preview if(count($array_of_divs)>0){ $last_id = $array_of_divs[count($array_of_divs)- 1][0]; $div_text = '<div id="'.basename(get_permalink($last_id)).'" title="'.$last_id.'" class="'.$templateId.implode(" ",get_post_class("jsf_ajaxOnLoad",$last_id)).'" ></div>' ; array_pop($array_of_divs); // remove the last empty div array_push( $array_of_divs , array($last_id , $div_text) ); // add it back in with extra class "jsf_ajaxOnLoad" } // load the content into a div $div_text = '<div id="'.basename(get_permalink($id)).'" title="'.$id.'" class="'.$templateId.'jsf_Loaded '.implode(" ",get_post_class("",$id)).'" >'.get_the_content().'</div>' ; $jsf_ajaxOnLoad = 5; }else{
  • 21. Collection page PHP }else{ if ($jsf_ajaxOnLoad > 0){ // 4 div after the loaded content $jsf_ajaxOnLoad -- ; $extra_class_test = $templateId."jsf_ajaxOnLoad "; }else{ $extra_class_test = $templateId."jsf_LoadViaAjax "; } $div_text = '<div id="'.basename(get_permalink($id)).'" title="'.$id.'" class="'.$extra_class_test.implode(" ",get_post_class("",$id)).'" ></div>' ;
  • 22. Collection page PHP <div class="entry-content" id="makeMeScrollable"> <?php foreach ( (array)$array_of_divs as $jsf_div){ echo($jsf_div[1]); } ?> </div><!-- .entry-content -->
  • 23. Now to call AJAX in WordPress URL: /wp-admin/admin- ajax.php?action=show_content_ajax_call add_action('wp_ajax_show_content_ajax_call', array( $this, 'jsf_show_content_ajax')); add_action('wp_ajax_nopriv_show_content_ajax_c all', array( $this, 'jsf_show_content_ajax'));
  • 24. Content fetch AJAX PHP function function jsf_show_content_ajax($id){ $postID = $_POST['postID']; $content_post = get_post($postID); $content = $content_post->post_content; $content = apply_filters('the_content', $content); $jsonpost = array(); $jsonpost["id"] = $postID; $jsonpost["slug"] = basename(get_permalink($postID) $jsonpost["content"] = str_replace(']]>', ']]>', $content); header( 'Content-Type: application/json' ); echo json_encode($jsonpost);; exit; }
  • 25. Content fetch AJAX function scrollerRightLimitReached: function() { $("div#makeMeScrollable").smoothDivScroll("swapFirstToLast"); if($('#makeMeScrollable .scrollableArea').children(":last").html().length <= 1){ var id = $('#makeMeScrollable .scrollableArea').children(":last").attr("id") $.ajax({ url:"/wp-admin/admin-ajax.php", type:'POST', dataType: 'json', data:'action=show_content_ajax_call&postID='+$('#'+id).attr("title")+'&t=3&slu + id, success:function(results){// load into div $('#' + results['slug']).html(results['content']); $('#' + results['slug']+' .jst_BoxContaner').hide().fadeIn();; $('#' + results['slug']).removeClass('jsf_ajaxOnLoad'); } }) } }
  • 26. Custom content in TinyMCE
  • 27. TinyMCE editor css Create a editor-style.css file in your theme root add_editor_style(); Tip: use the same style sheet in the theme wp_register_style('jsf_BoxStyles', get_stylesheet_directory_uri().'/editor- style.css'); wp_enqueue_style( 'jsf_BoxStyles') http://codex.wordpress.org/Function_Reference/add_editor_style
  • 28. Injecting code into the TinyMCE editor  Server side add_filter('default_content', 'my_editor_content'); function my_editor_content( $content ) { $content = "If you enjoyed this post, make sure to subscribe to my rss feed."; return $content; }  Client side var jsf_ed = tinyMCE.activeEditor; jsf_ed.selection.select(jsf_ed.getBody(), true); window.send_to_editor(“<div>content);
  • 29. How to add button to tinyMCE editor // Add only in Rich Editor mode if ( get_user_option('rich_editing') == 'true') { add_filter("mce_external_plugins", "add_hhh_custom_tinymce_plugin"); add_filter('mce_buttons', register_hhh_custom_button'); }
  • 30. How to add button to tinyMCE editor function register_hhh_custom_button($buttons) { array_push($buttons, "|", "hhh_highlight"); return $buttons; } function add_hhh_custom_tinymce_plugin($plugin_array) { $plugin_array['hhh_highlight'] = get_stylesheet_directory_uri().'/mce/editor_plugin.js'; return $plugin_array; }
  • 31. editor_plugin.js (function() { tinymce.create('tinymce.plugins.hhh_highlightPlugin', { init : function(ed, url) { ed.addCommand('mceHighlight', function() { ed.windowManager.open({ file : url + '/set_behavior.htm', width : 400,height : 600 ,inline : 1 }, {plugin_url : url}); }); ed.addButton('hhh_highlight', {title : 'Highlight', cmd : 'mceHighlight', image: url + '/hhhicon.gif' }); }, getInfo : function() {return {longname : 'Set Behavior',author : 'Paul Bearne',authorurl : 'http://www.bearne.ca',infourl : 'http://www.thejuiceagency.com',version : tinymce.majorVersion + "." + tinymce.minorVersion }; } }); tinymce.PluginManager.add('hhh_highlight', tinymce.plugins.hhh_highlightPlugin); })();
  • 32. How to add button to full screen editor function hhh_fullscreen_buttons($buttons){ $buttons[] = 'separator'; // add a separator $buttons['hhh_highlight'] = array( 'title' => __('Highlighter'), // Title of the button 'onclick' => "tinyMCE.execCommand('mceHighlight');", 'both' => false// Show on visual AND html mode ); return $buttons; } add_filter( 'wp_fullscreen_buttons', 'hhh_fullscreen_buttons' );
  • 34. How to read from TinyMCE editor <script type="text/javascript" src="/wp-admin/load- scripts.php?c=1&load=jquery &ver=XXXX"></script> <script type="text/javascript" src="/wp- includes/js/tinymce/tiny_mce_popup.js?v=3211"></script> var HighlightDialog = { local_ed : 'ed', init : function(ed) { HighlightDialog.local_ed = ed; if (jQuery.trim( HighlightDialog.local_ed.selection.getContent() ).length < 1){ tinyMCEPopup.execCommand('mceSelectNodeDepth',false,0);} // if we did get with above if lets walk out untill we do while (-1 == HighlightDialog.local_ed.selection.getContent().indexOf("hhh_box")) ){ tinyMCEPopup.execCommand('mceSelectNodeDepth',false,1);} tinyMCEPopup.resizeToInnerSize(); }, Cont on next
  • 35. How to write to TinyMCE editor Cont. from last slide.. insert : function insertHighlightSection(ed) { // get selected text output = HighlightDialog.local_ed.selection.getContent(); ….. Change it as needed …………… // write the value back to the editor replace all content tinyMCEPopup.execCommand('mceInsertRawHTM L', false, output); tinyMCEPopup.close(); // all done close the popup }; // call on load function tinyMCEPopup.onInit.add(HighlightDialog.init,
  • 36. PopUp pages in dialogs  Used to provide extended detail
  • 37. If is a detail page then show in a dialog dialog = jQuery('<div class="hhh_dialog" id="dialog“ style="display:hidden"></div>').appendTo('body'); dialog.load( jQuery.bbq.getState("detail"),{}, function(responseText, textStatus, XMLHttpRequest) { dialog.dialog({ modal: true,height: 720,width: 1050,position: 'top', closeText: 'X' , open: function(event, ui) { jQuery("div#makeMeScrollable").smoothDivScroll("scrollToElement ", "id", jQuery.bbq.getState("collection") ); }, close: function(event, ui) { jQuery.bbq.removeState("detail"); }, });
  • 38. If not an AJAX call then redirect if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') { $ajaxcall = true; } if(!$ajaxcall){ $hhh_rediect_url = get_post_meta(get_the_ID(),'_hhh_rediect_url',TRUE); if (strlen($hhh_rediect_url) > 0){ $hhh_rediect_url .= '#detail='. get_permalink(); ?><script type="text/javascript">/* <![CDATA[ */ window.location = "<?php echo $hhh_rediect_url ?>" /* ]]> */</script><?php } }else{ the_post() }
  • 39. The links  Slides @ http://www.slideshare.net/pbearne  @pbearne  pbearne@gmail.com