Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

HirshHorn theme: how I created it

2,839 views

Published on

Slides from the talk I gave at WordCamp toronto 2012 full of snippets of code and techniques I used to create the HIshHorh Sliding WordPress Theme

  • Be the first to comment

  • Be the first to like this

HirshHorn theme: how I created it

  1. 1. The HirshHorn Theme How I created itSnippets of code and techniques I used
  2. 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. 3. This might not be the only or bestway! 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. 4. Notes At the end I am going to ask what you found the most useful Slides @ http://www.slideshare.net/pbearne
  5. 5. Overview Demo
  6. 6. Wire frame Layout menuPrev page … Current page Next page … footer Screen
  7. 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. 8. <div id="home" data-id="1349" title="Home" class="hhh_T_7 jsf_Loaded post-1349 collection type-collection status-publishhentry" <div id="page10" class="jst_BoxContanerhhh_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_box8hhh_item_3"> http://youtu.be/DeYZVBzty0w </div>
  9. 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. 10. Changes to smoothdevscrollswapLastToFirst: 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("swappedElement")); el.data("scrollWrapper") .scrollLeft(el.data("scrollWrapper") .scrollLeft() + el.ata("swappedElement") .outerWidth(true));el.data("getNextElementWidth", true);el.data("enabled", true);self._showHideHotSpots();
  11. 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. 12. Keeping state and bookmarkswww.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. 13. JQUERY BBQ: BACK BUTTON & QUERYLIBRARY 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. 14. Over riding the menu URLsjQuery(#menu a).live(click, function(e) { var href = this.href; // does the clicked URL and current URL have /collection/ inthe 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. 15. Example hashchange functionjQuery(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. 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. 17. Example wall click action// add the scroll to action to wall linksjQuery(.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 onclickse.stopImmediatePropagation()return false;}); Note: no hashchange this is done in the move finished callback from smoothDivScroll
  18. 18. Using a menu to store the orderregister_nav_menu( „collection‟, Select the slider contentmenu.);
  19. 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 andupdate the div before and 4 dev‟s after so that content weloaded on page loadforeach ( (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 postif ($post->ID == $id) { Next slide……
  20. 20. Collection page PHPif ($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. 21. Collection page PHP}else{ if ($jsf_ajaxOnLoad > 0){ // 4 div after the loadedcontent $jsf_ajaxOnLoad -- ; $extra_class_test =$templateId."jsf_ajaxOnLoad "; }else{ $extra_class_test =$templateId."jsf_LoadViaAjax "; } $div_text = <divid=".basename(get_permalink($id))." title=".$id."class=".$extra_class_test.implode("",get_post_class("",$id))." ></div> ;
  22. 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. 23. Now to call AJAX in WordPressURL: /wp-admin/admin-ajax.php?action=show_content_ajax_calladd_action(wp_ajax_show_content_ajax_call,array( $this, jsf_show_content_ajax));add_action(wp_ajax_nopriv_show_content_ajax_call, array( $this, jsf_show_content_ajax));
  24. 24. Content fetch AJAX PHP functionfunction 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. 25. Content fetch AJAX functionscrollerRightLimitReached: 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. 26. Custom content in TinyMCE
  27. 27. TinyMCE editor cssCreate a editor-style.css file in your theme rootadd_editor_style();Tip: use the same style sheet in the themewp_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. 28. Injecting code into the TinyMCEeditor Server sideadd_filter(default_content, my_editor_content);function my_editor_content( $content ) { $content = "If you enjoyed this post, make sure to subscribe to myrss feed."; return $content;} Client sidevar jsf_ed = tinyMCE.activeEditor;jsf_ed.selection.select(jsf_ed.getBody(), true);window.send_to_editor(“<div>content);
  29. 29. How to add button to tinyMCE editor// Add only in Rich Editor modeif ( 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. 30. How to add button to tinyMCE editorfunction 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. 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 : PaulBearne,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. 32. How to add button to full screeneditorfunction 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 );
  33. 33. Slides @ http://www.slideshare.net/pbearne
  34. 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 dowhile (-1 ==HighlightDialog.local_ed.selection.getContent().indexOf("hhh_box")) ){ tinyMCEPopup.execCommand(mceSelectNodeDepth,false,1);}tinyMCEPopup.resizeToInnerSize();}, Cont on next
  35. 35. How to write to TinyMCE editorCont. 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 allcontent tinyMCEPopup.execCommand(mceInsertRawHTML, false, output); tinyMCEPopup.close(); // all done close the popup};// call on load function tinyMCEPopup.onInit.add(HighlightDialog.init,
  36. 36. PopUp pages in dialogs Used to provide extended detail
  37. 37. If is a detail page then show in adialogdialog = 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. 38. If not an AJAX call then redirectif(!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. 39. The links Slides @ http://www.slideshare.net/pbearne @pbearne pbearne@gmail.com

×