├── .gitignore ├── screenshot.png ├── includes └── README.md ├── assets ├── css │ ├── README.md │ └── sass │ │ ├── mixins.scss │ │ └── twenty_eleven_art_gallery.scss ├── js │ ├── vendor │ │ └── README.md │ ├── src │ │ ├── artwork_models.js │ │ ├── twenty_eleven_art_gallery.js │ │ └── artwork_views.js │ └── templates │ │ └── gallery_featured_image.tmpl └── build │ ├── twenty_eleven_art_gallery_templates.js │ ├── twenty_eleven_art_gallery.min.css │ ├── twenty_eleven_art_gallery.min.js │ ├── twenty_eleven_art_gallery.css │ └── twenty_eleven_art_gallery.js ├── images ├── src │ └── README.md └── README.md ├── style.css ├── humans.txt ├── .jshintrc ├── languages └── te_artgallery.pot ├── package.json ├── README.md ├── gallery.php ├── functions.php ├── Gruntfile.js └── header.php /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .sass-cache 3 | -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kadamwhite/backbone-wordpress-demo/HEAD/screenshot.png -------------------------------------------------------------------------------- /includes/README.md: -------------------------------------------------------------------------------- 1 | # Includes 2 | 3 | All theme classes, objects, and libraries should be hidden away in this `/includes` directory. -------------------------------------------------------------------------------- /assets/css/README.md: -------------------------------------------------------------------------------- 1 | # Styles 2 | 3 | Only CSS styles should exist in this folder. If you are using SASS, LESS, or some other pre-processor, please place your raw source folders in a subdirectory. -------------------------------------------------------------------------------- /images/src/README.md: -------------------------------------------------------------------------------- 1 | # Project Images 2 | 3 | Only source images (i.e. non-sprites, PSDs, raw photos) should be placed in this directory. Source files are meant to serve as a backup for any images that can be edited by an end user. -------------------------------------------------------------------------------- /images/README.md: -------------------------------------------------------------------------------- 1 | # Project Images 2 | 3 | Only images in-use by the project should be placed in this folder. Wherever possible, combine multiple small images into sprites to be used by CSS. Original (non-sprite) images should be placed in the `/src` subdirectory. -------------------------------------------------------------------------------- /assets/js/vendor/README.md: -------------------------------------------------------------------------------- 1 | # Vendor Scripts 2 | 3 | Place each vender JS project in a separate subdirectory of this folder. Vendor scripts are not run through JSHint by Grunt, but *can* be dynamically concatenated with other project scripts by adding them to the `contact` section of `Gruntfile.js`. -------------------------------------------------------------------------------- /assets/js/src/artwork_models.js: -------------------------------------------------------------------------------- 1 | this.artgallery = this.artgallery || {}; 2 | 3 | window.artgallery.models = (function( window, Backbone ) { 4 | 'use strict'; 5 | 6 | var models = {}; 7 | 8 | models.Artwork = Backbone.Model.extend({}); 9 | 10 | return models; 11 | 12 | })( this, Backbone ); 13 | -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Theme Name: Twenty Eleven Art Gallery 3 | * Theme URI: http://github.com/kadamwhite 4 | * Description: A child theme of Twenty Eleven, designed for displaying art 5 | * Author: K.Adam White 6 | * Author URI: http://www.kadamwhite.com 7 | * Template: twentyeleven 8 | * Version: 0.1.0 9 | * Tags: 10 | * 11 | * License: GPLv2+ 12 | * License URI: http://www.gnu.org/licenses/gpl-2.0.html 13 | */ -------------------------------------------------------------------------------- /humans.txt: -------------------------------------------------------------------------------- 1 | /* TEAM */ 2 | Developer: K.Adam White 3 | Contact: kadamwhite@gmail.com 4 | URI: http://www.kadamwhite.com 5 | 6 | /* THANKS */ 7 | Template Design: 10up 8 | URI: http://10up.com 9 | Twitter: @10up 10 | 11 | Template Design: Eric Mann 12 | URI: http://eamann.com 13 | Twitter: @ericmann 14 | 15 | /* SITE */ 16 | Created: 2013-06-22 17 | Template: https://github.com/10up/grunt-wp-theme -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "boss": true, 3 | "browser": true, 4 | "curly": true, 5 | "devel": true, 6 | "eqeqeq": true, 7 | "eqnull": true, 8 | "immed": true, 9 | "jquery": true, 10 | "latedef": true, 11 | "newcap": true, 12 | "noarg": true, 13 | "onevar": true, 14 | "quotmark": "single", 15 | "strict": true, 16 | "sub": true, 17 | "trailing": true, 18 | "undef": true, 19 | "globals": { 20 | "_": true, 21 | "Backbone": true, 22 | "module": true 23 | } 24 | } -------------------------------------------------------------------------------- /languages/te_artgallery.pot: -------------------------------------------------------------------------------- 1 | msgid "" 2 | msgstr "" 3 | "Project-Id-Version: Twenty Eleven Art Gallery\n" 4 | "POT-Creation-Date: 2013-06-22 16:50-0400\n" 5 | "PO-Revision-Date: 2013-06-22 16:50-0400\n" 6 | "Last-Translator: K.Adam White \n" 7 | "Language-Team: \n" 8 | "MIME-Version: 1.0\n" 9 | "Content-Type: text/plain; charset=UTF-8\n" 10 | "Content-Transfer-Encoding: 8bit\n" 11 | "X-Poedit-KeywordsList: _;gettext;gettext_noop;__;_e;_x;_n\n" 12 | "X-Poedit-Basepath: .\n" 13 | "X-Poedit-SearchPath-0: ..\n" 14 | 15 | -------------------------------------------------------------------------------- /assets/js/templates/gallery_featured_image.tmpl: -------------------------------------------------------------------------------- 1 | 2 | <%= image %> 3 | 4 |
5 |

6 | 7 | <%= title %> 8 | 9 |

10 | <% if ( content ) { %><%= content %><% } %> 11 | 16 |
17 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "twenty-eleven-art-gallery", 3 | "title": "Twenty Eleven Art Gallery", 4 | "description": "A child theme of Twenty Eleven, designed for displaying art", 5 | "version": "0.1.0", 6 | "homepage": "http://github.com/kadamwhite", 7 | "author": { 8 | "name": "K.Adam White", 9 | "email": "kadamwhite@gmail.com", 10 | "url": "http://www.kadamwhite.com" 11 | }, 12 | "devDependencies": { 13 | "grunt": "~0.4.1", 14 | "grunt-contrib-concat": "~0.1.2", 15 | "grunt-contrib-uglify": "~0.1.1", 16 | "grunt-contrib-cssmin": "~0.6.0", 17 | "grunt-contrib-jshint": "~0.1.1", 18 | "grunt-contrib-nodeunit": "~0.1.2", 19 | "grunt-contrib-watch": "~0.2.0", 20 | "grunt-contrib-sass": "~0.2.2", 21 | "grunt-contrib-jst": "~0.5.0" 22 | }, 23 | "keywords": [] 24 | } -------------------------------------------------------------------------------- /assets/js/src/twenty_eleven_art_gallery.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Twenty Eleven Art Gallery 3 | * http://github.com/kadamwhite 4 | * 5 | * Copyright (c) 2013 K.Adam White 6 | * Licensed under the GPLv2+ license. 7 | */ 8 | 9 | // Passing in modules off a namespace is The Poor Man's Require.js 10 | (function( window, $, models, views, undefined ) { 11 | 'use strict'; 12 | 13 | var artwork, featuredArtwork, banner, thumbnails; 14 | 15 | // Define our Backbone model 16 | artwork = new models.Artwork(); 17 | 18 | // Define the views for our little gallery. Note that these all use 19 | // the same model: `thumbnails` receives click events and sets the data, 20 | // `featuredArtwork` renders the featured artwork area, and `banner` 21 | // just hides the top banner the first time the gallery opens 22 | thumbnails = new views.Thumbnails({ 23 | el: '.artwork-thumbnails', 24 | model: artwork 25 | }); 26 | 27 | featuredArtwork = new views.FeaturedArtwork({ 28 | model: artwork 29 | }); 30 | 31 | banner = new views.Banner({ 32 | el: '#branding > a', 33 | model: artwork 34 | }); 35 | 36 | })( this, jQuery, this.artgallery.models, this.artgallery.views ); 37 | -------------------------------------------------------------------------------- /assets/build/twenty_eleven_art_gallery_templates.js: -------------------------------------------------------------------------------- 1 | this["artgallery"] = this["artgallery"] || {}; 2 | 3 | this["artgallery"]["assets/js/templates/gallery_featured_image.tmpl"] = function(obj) {obj || (obj = {});var __t, __p = '', __e = _.escape, __j = Array.prototype.join;function print() { __p += __j.call(arguments, '') }with (obj) {__p += '\n\t' +((__t = ( image )) == null ? '' : __t) +'\n\n
\n\t

\n\t\t\n\t\t\t' +((__t = ( title )) == null ? '' : __t) +'\n\t\t\n\t

\n\t'; if ( content ) { ;__p +=((__t = ( content )) == null ? '' : __t); } ;__p += '\n\t\n
\n';}return __p}; -------------------------------------------------------------------------------- /assets/css/sass/mixins.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Respond-To mixin 3 | * 4 | * Enables grouping of media query-oriented styles together within the relevant style definition: 5 | * ```scss 6 | * $break-small: 320px; 7 | * $break-large: 1024px; 8 | * 9 | * .profile-pic { 10 | * float: left; 11 | * width: 100%; 12 | * @include respond-to( handhelds ) { float: none; } 13 | * @include respond-to( medium-screens ) { width: 125px; } 14 | * @include respond-to( wide-screens ) { width: 250px; } 15 | * } 16 | * ``` 17 | * From [Responsive Web Design in Sass: Using Media Queries in Sass 3.2](http://thesassway.com/intermediate/responsive-web-design-in-sass-using-media-queries-in-sass-32#variables_in_queries_using_content) 18 | */ 19 | $break-small: 320px; 20 | $break-mid: 768px; 21 | $break-large: 1024px; 22 | 23 | @mixin respond-to( $media ) { 24 | @if $media == handhelds { 25 | @media only screen and ( max-width: $break-small ) { @content; } 26 | } 27 | @else if $media == small-tablets { 28 | @media only screen and ( min-width: $break-small + 1 ) and ( max-width: $break-mid - 1 ) { @content; } 29 | } 30 | @else if $media == large-tablets { 31 | @media only screen and ( min-width: $break-mid ) and ( max-width: $break-large - 1 ) { @content; } 32 | } 33 | @else if $media == wide-screens { 34 | @media only screen and ( min-width: $break-large ) { @content; } 35 | } 36 | } 37 | 38 | /** 39 | * Box Sizing browser-compatibility mixin 40 | */ 41 | @mixin box-sizing( $sizing ) { 42 | -moz-box-sizing: $sizing; 43 | box-sizing: $sizing; 44 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Refactoring WordPress PHP & jQuery code to use Backbone 2 | 3 | Inspired by [Step by Step from jQuery to Backbone](https://github.com/kjbekkelund/writings/blob/master/published/understanding-backbone.md), this is an example of how to take a small gallery component, primarily authored within the PHP of a WordPress theme and refactor it to render on the front-end, first with jQuery and then finally by using Backbone models and views. 4 | 5 | 1. Our baseline: an old-fashioned [PHP-heavy solution](https://github.com/kadamwhite/backbone-wordpress-demo/pull/7) 6 | 2. [Move gallery rendering to JS](https://github.com/kadamwhite/backbone-wordpress-demo/pull/8)): Reduce iteration within the PHP by adding `data-` attributes to the trigger links, and use that object's `.data()` to render out the featured image JS-side 7 | 3. [Get that HTML out of our JavaScript](https://github.com/kadamwhite/backbone-wordpress-demo/pull/9) by embedding the markup back in the .php file as an inline template and using `_.template` to render 8 | 4. [Move the markup into an HTML partial](https://github.com/kadamwhite/backbone-wordpress-demo/pull/10) and pre-compile the template with Grunt 9 | 5. Refactor the jQuery used to render the featured image [using a Backbone model and view](https://github.com/kadamwhite/backbone-wordpress-demo/pull/11) 10 | 6. [Move the model and view code into separate files](https://github.com/kadamwhite/backbone-wordpress-demo/pull/12) 11 | 7. [Refactor the remaining pure jQuery code into Backbone views](https://github.com/kadamwhite/backbone-wordpress-demo/pull/13) 12 | 13 | With the exception of the first step, each of those links will take you to the pull request where I walk through the code changes being made as we move from one step to the next. 14 | -------------------------------------------------------------------------------- /assets/build/twenty_eleven_art_gallery.min.css: -------------------------------------------------------------------------------- 1 | /*! Twenty Eleven Art Gallery - v0.1.0 - 2013-06-26 2 | * http://github.com/kadamwhite 3 | * Copyright (c) 2013; * Licensed GPLv2+ */ 4 | 5 | #branding{padding-bottom:0}#access{margin-bottom:0}.artwork-header-gallery{clear:both}@media only screen and (max-width:320px){header>a{display:none}}.artwork-featured{background-color:#2a2a2a;margin-bottom:6px}.artwork-image,.artwork-information{-moz-box-sizing:border-box;box-sizing:border-box;display:inline-block;overflow:hidden;width:100%;vertical-align:top}.artwork-image{height:300px}@media only screen and (min-width:768px) and (max-width:1023px){.artwork-image{width:66%}}@media only screen and (min-width:1024px){.artwork-image{width:66%}}.artwork-image img{width:100%}.artwork-information{padding:1em 0 1em 1em}@media only screen and (min-width:768px) and (max-width:1023px){.artwork-information{width:33%}}@media only screen and (min-width:1024px){.artwork-information{width:33%}}.artwork-information h3{font-size:1.3em;font-weight:700;margin-bottom:1em}.artwork-information a{color:#fff;text-shadow:0 2px #000}.artwork-information p{margin-bottom:.5em}.artwork-information .entry-meta,.artwork-information p{color:#aaa;font-size:1em}.artwork-thumbnails{background-color:#fff;border-bottom:double silver;padding-top:6px;text-align:center}.artwork-thumbnails a{-moz-box-sizing:border-box;box-sizing:border-box;display:inline-block;padding:0 5px;width:16%}@media only screen and (max-width:320px){.artwork-thumbnails a{width:49%}}@media only screen and (min-width:321px) and (max-width:767px){.artwork-thumbnails a{width:32%}}.artwork-thumbnails a img{border:1px solid silver;display:block;max-width:100%;transition:border-color .5s}.artwork-thumbnails a:hover img{border-color:#000}.artwork-thumbnails.open{border-top:double silver} -------------------------------------------------------------------------------- /assets/js/src/artwork_views.js: -------------------------------------------------------------------------------- 1 | this.artgallery = this.artgallery || {}; 2 | 3 | this.artgallery.views = (function( window, $, _, Backbone ) { 4 | 'use strict'; 5 | 6 | var views = {}; 7 | 8 | views.FeaturedArtwork = Backbone.View.extend({ 9 | el: '.artwork-featured', 10 | 11 | // Pull in our cached template 12 | template: window.artgallery['assets/js/templates/gallery_featured_image.tmpl'], 13 | 14 | render: function() { 15 | this.$el.html( this.template( this.model.attributes ) ); 16 | // Always return `this`, to enable chaining 17 | return this; 18 | }, 19 | 20 | show: function() { 21 | this.$el.slideDown(); 22 | }, 23 | 24 | initialize: function( options ) { 25 | // Automatically update when the data changes. `listenTo` and 26 | // `listenToOnce` are part of Backbone 1.0, so you must manually 27 | // re-register the latest Backbone.js (or be running WP 3.6). On the 28 | // version of Backbone in 3.5, you may use this syntax instead: 29 | // var render = _.bind( this.render, this ); 30 | // this.model.on( 'change', render ); 31 | this.listenTo( this.model, 'change', this.render ); 32 | this.listenToOnce( this.model, 'change', this.show ); 33 | } 34 | }); 35 | 36 | views.Banner = Backbone.View.extend({ 37 | initialize: function() { 38 | this.listenToOnce( this.model, 'change', this.hide ); 39 | }, 40 | 41 | show: function() { 42 | this.$el.slideDown(); 43 | }, 44 | 45 | hide: function() { 46 | this.$el.slideUp(); 47 | } 48 | }); 49 | 50 | views.Thumbnails = Backbone.View.extend({ 51 | // Backbone gives us a convenient syntax for defining 52 | // all of our view's delegated jQuery events: 53 | events: { 54 | 'click a': 'select' 55 | }, 56 | 57 | select: function( evt ) { 58 | // Have to go through evt.target: `this` is bound to the View object 59 | var imageData = $( evt.target ).parent('a').data(); 60 | 61 | evt.preventDefault(); 62 | 63 | if ( this.model.id !== imageData.id ) { 64 | this.model.set( imageData ); 65 | } 66 | }, 67 | 68 | initialize: function() { 69 | this.listenToOnce( this.model, 'change', function() { 70 | this.$el.addClass('open'); 71 | }); 72 | } 73 | }); 74 | 75 | return views; 76 | 77 | })( this, jQuery, _, Backbone ); 78 | -------------------------------------------------------------------------------- /assets/build/twenty_eleven_art_gallery.min.js: -------------------------------------------------------------------------------- 1 | /*! Twenty Eleven Art Gallery - v0.1.0 - 2013-06-26 2 | * http://github.com/kadamwhite 3 | * Copyright (c) 2013; * Licensed GPLv2+ */ 4 | this.artgallery=this.artgallery||{},this.artgallery["assets/js/templates/gallery_featured_image.tmpl"]=function(obj){obj||(obj={});var __t,__p="";with(_.escape,Array.prototype.join,obj)__p+='\n '+(null==(__t=image)?"":__t)+'\n\n
\n

\n \n '+(null==(__t=title)?"":__t)+"\n \n

\n ",content&&(__p+=null==(__t=content)?"":__t),__p+='\n \n
\n";return __p},this.artgallery=this.artgallery||{},window.artgallery.models=function(t,e){"use strict";var n={};return n.Artwork=e.Model.extend({}),n}(this,Backbone),this.artgallery=this.artgallery||{},this.artgallery.views=function(t,e,n,i){"use strict";var l={};return l.FeaturedArtwork=i.View.extend({el:".artwork-featured",template:t.artgallery["assets/js/templates/gallery_featured_image.tmpl"],render:function(){return this.$el.html(this.template(this.model.attributes)),this},show:function(){this.$el.slideDown()},initialize:function(){this.listenTo(this.model,"change",this.render),this.listenToOnce(this.model,"change",this.show)}}),l.Banner=i.View.extend({initialize:function(){this.listenToOnce(this.model,"change",this.hide)},show:function(){this.$el.slideDown()},hide:function(){this.$el.slideUp()}}),l.Thumbnails=i.View.extend({events:{"click a":"select"},select:function(t){var n=e(t.target).parent("a").data();t.preventDefault(),this.model.id!==n.id&&this.model.set(n)},initialize:function(){this.listenToOnce(this.model,"change",function(){this.$el.addClass("open")})}}),l}(this,jQuery,_,Backbone),function(t,e,n,i){"use strict";var l,a,r,s;l=new n.Artwork,s=new i.Thumbnails({el:".artwork-thumbnails",model:l}),a=new i.FeaturedArtwork({model:l}),r=new i.Banner({el:"#branding > a",model:l})}(this,jQuery,this.artgallery.models,this.artgallery.views); -------------------------------------------------------------------------------- /assets/css/sass/twenty_eleven_art_gallery.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Twenty Eleven Art Gallery 3 | * http://github.com/kadamwhite 4 | * 5 | * Copyright (c) 2013 K.Adam White 6 | * Licensed under the GPLv2+ license. 7 | */ 8 | 9 | @import "mixins.scss"; 10 | 11 | // Overrides for twentyeleven styles.css 12 | #branding { 13 | padding-bottom: 0; 14 | } 15 | #access { 16 | margin-bottom: 0; 17 | } 18 | 19 | // Homepage Art Gallery styles 20 | .artwork-header-gallery { 21 | clear: both; 22 | } 23 | // Hide the top banner at small sizes 24 | header > a { 25 | @include respond-to( handhelds ) { display: none; } 26 | } 27 | 28 | // Styles for the featured images 29 | .artwork-featured { 30 | background-color: #2a2a2a; 31 | margin-bottom: 6px; 32 | } 33 | 34 | .artwork-image, 35 | .artwork-information { 36 | @include box-sizing( border-box ); 37 | display: inline-block; 38 | overflow: hidden; 39 | width: 100%; 40 | vertical-align: top; 41 | } 42 | 43 | .artwork-image { 44 | height: 300px; 45 | 46 | @include respond-to( large-tablets ) { width: 66%; } 47 | @include respond-to( wide-screens ) { width: 66%; } 48 | 49 | img { 50 | // Match size of container 51 | width: 100%; 52 | } 53 | } // .artwork-image 54 | 55 | .artwork-information { 56 | padding: 1em 0 1em 1em; 57 | 58 | @include respond-to( large-tablets ) { width: 33%; } 59 | @include respond-to( wide-screens ) { width: 33%; } 60 | 61 | h3 { 62 | font-size: 1.3em; 63 | font-weight: bold; 64 | margin-bottom: 1em; 65 | } 66 | 67 | a { 68 | color: white; 69 | text-shadow: 0 2px black; 70 | } 71 | 72 | p { 73 | margin-bottom: 0.5em; 74 | } 75 | 76 | .entry-meta, 77 | p { 78 | color: #aaa; 79 | font-size: 1em; 80 | } 81 | } // .artwork-information 82 | 83 | .artwork-thumbnails { 84 | background-color: white; 85 | border-bottom: double silver; 86 | // width: 1000px; 87 | padding-top: 6px; 88 | text-align: center; 89 | 90 | a { 91 | @include box-sizing( border-box ); 92 | display: inline-block; 93 | padding: 0 5px; 94 | width: 16%; // 6 across 95 | 96 | @include respond-to( handhelds ) { width: 49%; } 97 | @include respond-to( small-tablets ) { width: 32%; } // 3 across 98 | 99 | img { 100 | border: 1px solid silver; 101 | display: block; 102 | max-width: 100%; 103 | transition: border-color 0.5s; 104 | } 105 | 106 | &:hover img { 107 | border-color: black; 108 | } 109 | } // a 110 | 111 | &.open { 112 | border-top: double silver; 113 | } 114 | } // .artwork-thumbnails 115 | -------------------------------------------------------------------------------- /gallery.php: -------------------------------------------------------------------------------- 1 | 'ag_artwork_item', 13 | 'posts_per_page' => 6 14 | ); 15 | $artwork_items = new WP_Query($args); 16 | 17 | if($artwork_items->have_posts()) : 18 | ?> 19 | 83 | -------------------------------------------------------------------------------- /functions.php: -------------------------------------------------------------------------------- 1 | element. 78 | */ 79 | function te_artgallery_header_meta() { 80 | $humans = ''; 81 | 82 | echo apply_filters( 'te_artgallery_humans', $humans ); 83 | } 84 | add_action( 'wp_head', 'te_artgallery_header_meta' ); 85 | -------------------------------------------------------------------------------- /assets/build/twenty_eleven_art_gallery.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Twenty Eleven Art Gallery 3 | * http://github.com/kadamwhite 4 | * 5 | * Copyright (c) 2013 K.Adam White 6 | * Licensed under the GPLv2+ license. 7 | */ 8 | /** 9 | * Respond-To mixin 10 | * 11 | * Enables grouping of media query-oriented styles together within the relevant style definition: 12 | * ```scss 13 | * $break-small: 320px; 14 | * $break-large: 1024px; 15 | * 16 | * .profile-pic { 17 | * float: left; 18 | * width: 100%; 19 | * @include respond-to( handhelds ) { float: none; } 20 | * @include respond-to( medium-screens ) { width: 125px; } 21 | * @include respond-to( wide-screens ) { width: 250px; } 22 | * } 23 | * ``` 24 | * From [Responsive Web Design in Sass: Using Media Queries in Sass 3.2](http://thesassway.com/intermediate/responsive-web-design-in-sass-using-media-queries-in-sass-32#variables_in_queries_using_content) 25 | */ 26 | /** 27 | * Box Sizing browser-compatibility mixin 28 | */ 29 | #branding { 30 | padding-bottom: 0; } 31 | 32 | #access { 33 | margin-bottom: 0; } 34 | 35 | .artwork-header-gallery { 36 | clear: both; } 37 | 38 | @media only screen and (max-width: 320px) { 39 | header > a { 40 | display: none; } } 41 | 42 | .artwork-featured { 43 | background-color: #2a2a2a; 44 | margin-bottom: 6px; } 45 | 46 | .artwork-image, 47 | .artwork-information { 48 | -moz-box-sizing: border-box; 49 | box-sizing: border-box; 50 | display: inline-block; 51 | overflow: hidden; 52 | width: 100%; 53 | vertical-align: top; } 54 | 55 | .artwork-image { 56 | height: 300px; } 57 | @media only screen and (min-width: 768px) and (max-width: 1023px) { 58 | .artwork-image { 59 | width: 66%; } } 60 | @media only screen and (min-width: 1024px) { 61 | .artwork-image { 62 | width: 66%; } } 63 | .artwork-image img { 64 | width: 100%; } 65 | 66 | .artwork-information { 67 | padding: 1em 0 1em 1em; } 68 | @media only screen and (min-width: 768px) and (max-width: 1023px) { 69 | .artwork-information { 70 | width: 33%; } } 71 | @media only screen and (min-width: 1024px) { 72 | .artwork-information { 73 | width: 33%; } } 74 | .artwork-information h3 { 75 | font-size: 1.3em; 76 | font-weight: bold; 77 | margin-bottom: 1em; } 78 | .artwork-information a { 79 | color: white; 80 | text-shadow: 0 2px black; } 81 | .artwork-information p { 82 | margin-bottom: 0.5em; } 83 | .artwork-information .entry-meta, 84 | .artwork-information p { 85 | color: #aaa; 86 | font-size: 1em; } 87 | 88 | .artwork-thumbnails { 89 | background-color: white; 90 | border-bottom: double silver; 91 | padding-top: 6px; 92 | text-align: center; } 93 | .artwork-thumbnails a { 94 | -moz-box-sizing: border-box; 95 | box-sizing: border-box; 96 | display: inline-block; 97 | padding: 0 5px; 98 | width: 16%; } 99 | @media only screen and (max-width: 320px) { 100 | .artwork-thumbnails a { 101 | width: 49%; } } 102 | @media only screen and (min-width: 321px) and (max-width: 767px) { 103 | .artwork-thumbnails a { 104 | width: 32%; } } 105 | .artwork-thumbnails a img { 106 | border: 1px solid silver; 107 | display: block; 108 | max-width: 100%; 109 | transition: border-color 0.5s; } 110 | .artwork-thumbnails a:hover img { 111 | border-color: black; } 112 | .artwork-thumbnails.open { 113 | border-top: double silver; } 114 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function( grunt ) { 2 | 'use strict'; 3 | 4 | // Project configuration 5 | grunt.initConfig( { 6 | pkg: grunt.file.readJSON( 'package.json' ), 7 | concat: { 8 | options: { 9 | stripBanners: true, 10 | banner: '/*! <%= pkg.title %> - v<%= pkg.version %> - <%= grunt.template.today("yyyy-mm-dd") %>\n' + 11 | ' * <%= pkg.homepage %>\n' + 12 | ' * Copyright (c) <%= grunt.template.today("yyyy") %>;' + 13 | ' * Licensed GPLv2+' + 14 | ' */\n' 15 | }, 16 | twenty_eleven_art_gallery: { 17 | src: [ 18 | 'assets/build/twenty_eleven_art_gallery_templates.js', 19 | 'assets/js/src/artwork_models.js', 20 | 'assets/js/src/artwork_views.js', 21 | 'assets/js/src/twenty_eleven_art_gallery.js' 22 | ], 23 | dest: 'assets/build/twenty_eleven_art_gallery.js' 24 | } 25 | }, 26 | jshint: { 27 | all: [ 28 | 'Gruntfile.js', 29 | 'assets/js/src/**/*.js', 30 | 'assets/js/test/**/*.js' 31 | ], 32 | options: { 33 | jshintrc: '.jshintrc' 34 | } 35 | }, 36 | jst: { 37 | options: { 38 | namespace: 'artgallery', 39 | prettify: true 40 | }, 41 | compile: { 42 | files: { 43 | 'assets/build/twenty_eleven_art_gallery_templates.js': ['assets/js/templates/**/*.tmpl'] 44 | } 45 | } 46 | }, 47 | uglify: { 48 | all: { 49 | files: { 50 | 'assets/build/twenty_eleven_art_gallery.min.js': ['assets/build/twenty_eleven_art_gallery.js'] 51 | }, 52 | options: { 53 | banner: '/*! <%= pkg.title %> - v<%= pkg.version %> - <%= grunt.template.today("yyyy-mm-dd") %>\n' + 54 | ' * <%= pkg.homepage %>\n' + 55 | ' * Copyright (c) <%= grunt.template.today("yyyy") %>;' + 56 | ' * Licensed GPLv2+' + 57 | ' */\n', 58 | mangle: { 59 | except: ['jQuery'] 60 | } 61 | } 62 | } 63 | }, 64 | test: { 65 | files: ['assets/js/test/**/*.js'] 66 | }, 67 | sass: { 68 | all: { 69 | files: { 70 | 'assets/build/twenty_eleven_art_gallery.css': 'assets/css/sass/twenty_eleven_art_gallery.scss' 71 | } 72 | } 73 | }, 74 | cssmin: { 75 | options: { 76 | banner: '/*! <%= pkg.title %> - v<%= pkg.version %> - <%= grunt.template.today("yyyy-mm-dd") %>\n' + 77 | ' * <%= pkg.homepage %>\n' + 78 | ' * Copyright (c) <%= grunt.template.today("yyyy") %>;' + 79 | ' * Licensed GPLv2+' + 80 | ' */\n' 81 | }, 82 | minify: { 83 | expand: true, 84 | 85 | cwd: 'assets/build/', 86 | src: ['twenty_eleven_art_gallery.css'], 87 | 88 | dest: 'assets/build/', 89 | ext: '.min.css' 90 | } 91 | }, 92 | watch: { 93 | 94 | sass: { 95 | files: ['assets/css/sass/*.scss'], 96 | tasks: ['sass', 'cssmin'], 97 | options: { 98 | debounceDelay: 500 99 | } 100 | }, 101 | 102 | scripts: { 103 | files: ['assets/js/src/**/*.js', 'assets/js/vendor/**/*.js'], 104 | tasks: ['jshint', 'concat', 'uglify'], 105 | options: { 106 | debounceDelay: 500 107 | } 108 | }, 109 | 110 | template: { 111 | files: ['assets/js/src/**/*.tmpl'], 112 | tasks: ['jst', 'concat', 'uglify'], 113 | options: { 114 | debounceDelay: 500 115 | } 116 | } 117 | } 118 | } ); 119 | 120 | // Load other tasks 121 | grunt.loadNpmTasks('grunt-contrib-jshint'); 122 | grunt.loadNpmTasks('grunt-contrib-jst'); 123 | grunt.loadNpmTasks('grunt-contrib-concat'); 124 | grunt.loadNpmTasks('grunt-contrib-uglify'); 125 | grunt.loadNpmTasks('grunt-contrib-cssmin'); 126 | 127 | grunt.loadNpmTasks('grunt-contrib-sass'); 128 | 129 | grunt.loadNpmTasks('grunt-contrib-watch'); 130 | 131 | // Default task. 132 | 133 | grunt.registerTask( 'default', ['jshint', 'jst', 'concat', 'uglify', 'sass', 'cssmin'] ); 134 | 135 | grunt.util.linefeed = '\n'; 136 | }; -------------------------------------------------------------------------------- /assets/build/twenty_eleven_art_gallery.js: -------------------------------------------------------------------------------- 1 | /*! Twenty Eleven Art Gallery - v0.1.0 - 2013-06-26 2 | * http://github.com/kadamwhite 3 | * Copyright (c) 2013; * Licensed GPLv2+ */ 4 | this["artgallery"] = this["artgallery"] || {}; 5 | 6 | this["artgallery"]["assets/js/templates/gallery_featured_image.tmpl"] = function(obj) {obj || (obj = {});var __t, __p = '', __e = _.escape, __j = Array.prototype.join;function print() { __p += __j.call(arguments, '') }with (obj) {__p += '\n\t' +((__t = ( image )) == null ? '' : __t) +'\n\n
\n\t

\n\t\t\n\t\t\t' +((__t = ( title )) == null ? '' : __t) +'\n\t\t\n\t

\n\t'; if ( content ) { ;__p +=((__t = ( content )) == null ? '' : __t); } ;__p += '\n\t\n
\n';}return __p}; 7 | this.artgallery = this.artgallery || {}; 8 | 9 | window.artgallery.models = (function( window, Backbone ) { 10 | 'use strict'; 11 | 12 | var models = {}; 13 | 14 | models.Artwork = Backbone.Model.extend({}); 15 | 16 | return models; 17 | 18 | })( this, Backbone ); 19 | 20 | this.artgallery = this.artgallery || {}; 21 | 22 | this.artgallery.views = (function( window, $, _, Backbone ) { 23 | 'use strict'; 24 | 25 | var views = {}; 26 | 27 | views.FeaturedArtwork = Backbone.View.extend({ 28 | el: '.artwork-featured', 29 | 30 | // Pull in our cached template 31 | template: window.artgallery['assets/js/templates/gallery_featured_image.tmpl'], 32 | 33 | render: function() { 34 | this.$el.html( this.template( this.model.attributes ) ); 35 | // Always return `this`, to enable chaining 36 | return this; 37 | }, 38 | 39 | show: function() { 40 | this.$el.slideDown(); 41 | }, 42 | 43 | initialize: function( options ) { 44 | // Automatically update when the data changes. `listenTo` and 45 | // `listenToOnce` are part of Backbone 1.0, so you must manually 46 | // re-register the latest Backbone.js (or be running WP 3.6). On the 47 | // version of Backbone in 3.5, you may use this syntax instead: 48 | // var render = _.bind( this.render, this ); 49 | // this.model.on( 'change', render ); 50 | this.listenTo( this.model, 'change', this.render ); 51 | this.listenToOnce( this.model, 'change', this.show ); 52 | } 53 | }); 54 | 55 | views.Banner = Backbone.View.extend({ 56 | initialize: function() { 57 | this.listenToOnce( this.model, 'change', this.hide ); 58 | }, 59 | 60 | show: function() { 61 | this.$el.slideDown(); 62 | }, 63 | 64 | hide: function() { 65 | this.$el.slideUp(); 66 | } 67 | }); 68 | 69 | views.Thumbnails = Backbone.View.extend({ 70 | // Backbone gives us a convenient syntax for defining 71 | // all of our view's delegated jQuery events: 72 | events: { 73 | 'click a': 'select' 74 | }, 75 | 76 | select: function( evt ) { 77 | // Have to go through evt.target: `this` is bound to the View object 78 | var imageData = $( evt.target ).parent('a').data(); 79 | 80 | evt.preventDefault(); 81 | 82 | if ( this.model.id !== imageData.id ) { 83 | this.model.set( imageData ); 84 | } 85 | }, 86 | 87 | initialize: function() { 88 | this.listenToOnce( this.model, 'change', function() { 89 | this.$el.addClass('open'); 90 | }); 91 | } 92 | }); 93 | 94 | return views; 95 | 96 | })( this, jQuery, _, Backbone ); 97 | 98 | // Passing in modules off a namespace is The Poor Man's Require.js 99 | (function( window, $, models, views, undefined ) { 100 | 'use strict'; 101 | 102 | var artwork, featuredArtwork, banner, thumbnails; 103 | 104 | // Define our Backbone model 105 | artwork = new models.Artwork(); 106 | 107 | // Define the views for our little gallery. Note that these all use 108 | // the same model: `thumbnails` receives click events and sets the data, 109 | // `featuredArtwork` renders the featured artwork area, and `banner` 110 | // just hides the top banner the first time the gallery opens 111 | thumbnails = new views.Thumbnails({ 112 | el: '.artwork-thumbnails', 113 | model: artwork 114 | }); 115 | 116 | featuredArtwork = new views.FeaturedArtwork({ 117 | model: artwork 118 | }); 119 | 120 | banner = new views.Banner({ 121 | el: '#branding > a', 122 | model: artwork 123 | }); 124 | 125 | })( this, jQuery, this.artgallery.models, this.artgallery.views ); 126 | -------------------------------------------------------------------------------- /header.php: -------------------------------------------------------------------------------- 1 | section and everything up till
6 | * 7 | * @package Twenty Eleven Art Gallery 8 | * @since 0.1.0 9 | */ 10 | ?> 11 | 14 | 17 | 20 | 21 | > 22 | 23 | 24 | 25 | 26 | <?php 27 | /* 28 | * Print the <title> tag based on what is being viewed. 29 | */ 30 | global $page, $paged; 31 | 32 | wp_title( '|', true, 'right' ); 33 | 34 | // Add the blog name. 35 | bloginfo( 'name' ); 36 | 37 | // Add the blog description for the home/front page. 38 | $site_description = get_bloginfo( 'description', 'display' ); 39 | if ( $site_description && ( is_home() || is_front_page() ) ) 40 | echo " | $site_description"; 41 | 42 | // Add a page number if necessary: 43 | if ( $paged >= 2 || $page >= 2 ) 44 | echo ' | ' . sprintf( __( 'Page %s', 'twentyeleven' ), max( $paged, $page ) ); 45 | 46 | ?> 47 | 48 | 49 | 50 | 53 | 61 | * tag of your theme, or you will break many plugins, which 62 | * generally use this hook to add elements to such 63 | * as styles, scripts, and meta tags. 64 | */ 65 | wp_head(); 66 | ?> 67 | 68 | 69 | > 70 |