How to: Sweet rotator in Drupal using Views, Flag, and Views Slideshow


Ever wanted to know how to make a sweet rotator in Drupal? Of course you have. I fooled around with a couple of different modules, followed some tutorials, and added some custom tweaks to get just what I was looking for. BELOW IS TEH AWESOMEZORZ. DRUPAL HACKERS IN TRAINING, PREPARE FOR GLORY!

First, grab the following modules:
Flag – This will allow us to flag content to be placed into the rotator.
Views – This allows us to create a “view” of the posts marked as featured. If you don’t know what the Views module does, I highly recommend playing around with it first (if anything, for your own benefit).
Views Slideshow – This allows us to display the posts within the view using a slideshow-esque presentation sequence.
Chaos Tools – Required by Views.
Libraries – Provides an API for Drupal to load libraries from the sites/all/libraries folder.

This might be as great a time as ever to download and use the command line tool Drush. Either way, download those modules and then enable them. Additionally, enable the “Views UI” module so that we can create views with the assistance of the views gui as well as the “Libraries API” and “Views Slideshow: Cycle” modules.

“Views Slideshow: Cycle” makes use of the “Libraries API” to load a jQuery library. This is what powers the slideshow. Grab that from here. Put this file into the folder `sites/all/libraries/jquery.cycle.` You may have to create this folder. (Quick Download link from GitHub).

Now, create whatever content type that you’re going to use in your slideshow. If you’re doing, for instance, a recipe website with pictures of your delicious dishes, you could name this “Recipes.” Do this at `admin/structure/types/add`. The only required fields that you add for the sake of this tutorial are a title, body, and image field. Make the image field whatever size you’d like, though I’d recommend getting one that will scale to 500×450 pixels (once again, only for the purposes of this tutorial). To be on the safe side, you should also require that the minimum size for an image be 500×450. This will ensure that we don’t have any funkiness when it comes to scaling and cropping the image for the slideshow.

Now go to `admin/config/media/image-styles/add` in order to add a new “style” of image. We’re going to use this style to make sure all of the images for the slideshow come out to be the same. This will make the slideshow look nice and smooth. Choose to “Scale and Crop” the image to 500×450 pixels.

Next, create a flag that will be used to mark our recipes as featured. Go to `admin/structure/flags/add`. This will be a “Node” type flag. Make it a global flag. Only allow your content managers (whatever role you may have assigned to them) flag recipes as such; you don’t wish to allow all authenticated users to make recipes featured or not. That’d be silly. Make sure you choose recipes as the content to flag.

Now, create a new block view with the slideshow format. Make sure you choose Recipe as your node type. First, under “Advanced” on the right side, Add a Relationship. Make sure “Include only flagged content” is checked. Choose “Flags: Node flag.” Choose the “Featured Recipe” flag. Make sure to choose “Any user.”

On the left, remove the only sort criteria there. We’re going to make it so that the Featured Recipe Rotator order is only determined by the time which the Recipe was flagged. If you want, you can obviously make a different sort order. This one makes the most sense, in my opinion, and gives content managers the most control. Add a sort criteria for “Flags: Flagged time.” Choose “descending.”

You can choose to filter by Node Type to be double sure that we’re only grabbing recipes. Add a filter for “Content: Type.” Select “Is one of” and “Recipe.”

Now for the interestin’ stuff. Add the following fields:
Content: Title
Content: Food Image
Content: Body
Global: View result counter

Go through the fields, deselecting “Label” for each, until you hit “Body.” Choose to “Trim” this (or Summary if you got fancy) to a given amount of characters. Under “REWRITE RESULTS,” choose to “Trim this field to a maximum length.” I chose the same value from the above “Trim.” I left “Trim this field to a maximum length” and “Add an ellipsis” checked. At “Food Image,” make sure you choose the Image Style that you created. At “Global: View result counter”, don’t display a label. Also, choose to exclude this from the display.

Under “Format” on the left, click “Settings” next to “Slideshow.” Scroll to the bottom of this window and select “Pager” under “Bottom Widget.” Choose “Global: View result counter” and “Activate Slide and Pause on Pager Hover.”

Save the view. Go to `admin/structure/block` and place your block somewhere you’ll be able to find it. I chose to put it into the “Content” area. I also went through little extra bits to only display it on the front page. To do this, select configure for that block and select “Only the listed pages.” Enter “” into the textarea. Save the block.

Anywho, we need to add some content and then flag it! Go to `node/add/recipe.` Get out your best recipes, folks. Spend a few hours baking, then take pictures of your results. Alternatively, if you’re lazy, Google image search for things like “Chicken Pot Pie” and “Stir Fry Chicken.” Save these posts. You will then be directed to the nodes themselves. Scroll to the bottom and “Flag” them. Rinse and repeat.

Now, go take a look at your pretty slideshow on your front page! Looks pretty nice, right? In order to make it look “even nicer,” we’ll apply some CSS styles:

/* This file will hold the main styles for your website. */
                                                                                                                                                               
/* Featured Recipe Rotator */
/* This should allow us to move stuff around within the block itself */
#block-views-featured-recipe-rotator-block .view-content {
  position: relative;
}
/* This puts a background slightly transparent and changes font sizes */
#block-views-featured-recipe-rotator-block .views-field-title {
  background-color: rgba(0,0,0,.65);
  padding: 10px;
  width: 480px;
  font-size: 1.3em;
  position: absolute;
}
#block-views-featured-recipe-rotator-block .views-field-title .field-content a {
  color: #f7f7f7;
}
/* Pager area */
#block-views-featured-recipe-rotator-block .view-content .views-field-counter .views-content-counter {
  background-color: rgba(0,0,0,.65);
  float: left;
  width: 20px;
  height: 20px;
  padding: 5px;
  color: #f7f7f7;
}
#block-views-featured-recipe-rotator-block .view-content .views-slideshow-controls-bottom {
  position: absolute;
  width: 584px;
  bottom: 58px;
  right: -5px;
  z-index: 10;
  text-align: center;
}
#block-views-featured-recipe-rotator-block .view-content .field-content img {
  height: 450px;
}
#block-views-featured-recipe-rotator-block .views-field-body {
  background-color: rgba(0,0,0,.65);
  padding: 10px;
  width: 480px;
  position: absolute;
  bottom: 0px;
}
#block-views-featured-recipe-rotator-block .views-field-body .field-content p {
  color: #f7f7f7;
  padding: 0px;
  margin: 0px;
}
view raw gistfile1.css This Gist brought to you by GitHub.
Posted in Uncategorized | Leave a comment

Loads of updates

Alright, wow.

I haven’t posted here in quite some time. A couple of things:

First off, I’m moving to California. “Wow,” right? I got a job with CrossFit doing web development. “WOW,” right? It’ll seriously be the perfect job for me. The only bad thing is that the next few weeks will be completely insane as I try to sell stuff and move across the country. I will definitely miss ONS, though.

Second off, I’ve begun writing my own Drupal modules. I feel like a big boy now. The process is actually pretty easy, so far; once you get used to the process, it doesn’t take very long at all to develop some really robust functionality. If you haven’t taken a whack at it before, I highly recommend doing so.

Mostly I’ve been working with the LDAP module. I made a few helper modules: LDAP populate (which is still choking a bit after I tried refactoring the code to make use of the batch api… I suggest using an old commit if you’re hoping to use it) and Services user ldap which branana actually rolled into Services user login methods. Sweet!

Third off, I’ve also begun looking into Symfony2 as a PHP framework. So far it looks really sweet. In particular, I love the way their Documentation is written. I once heard from someone that a true “master” of a subject is one that can explain the subject matter to someone who is brand new. These guys definitely take the cake with their documentation. Personally, I strive to be able to approach “master” status with certain areas of my life. I can appreciate, for this reason, a well written how-to or walkthrough.

Welp, I’m going back to reading Symfony docs. I’d really like to re-write Kremica under it.

Posted in Uncategorized | Tagged , , , | Leave a comment

Alpha Release of RPSNode

Yes, the interface design leaves much to be desired. I wanted to push this puppy out for the world to see. I was too anxious… I couldn’t help myself!

Dramatics aside, go check out the first official (as I’m calling it) Alpha release of Rock, Paper, Scissors, Node! Some of the changes in this release:

  • Rounds: Every week, a round begins. Each day of the round (Sunday through Friday), users are granted 10 round plays. They use these round plays against other players. On Saturday, no round plays are given and the winners are determined! 1st, 2nd, and 3rd place (as determined by whoever has the most wins) get trophies added to their stats page. Yay! How do they determine tie breakers? Heh… I don’t know yet. If you tie, you might get screwed out of a trophy for right now. Sorry! :)
  • Interface: This release bolsters a slightly improved interface. I made the CSS a little more manageable, though it still has a long way to go. I added a checkbox so that people using modern browsers could elect to hear a sound upon each count-down of the timer. The stats pages are a bit more fleshed out, though still lacking. I use the Google ChartAPI to show sweet graphs for each user.
  • OAuth Logins: Users can login with Twitter, GitHub, or site-specific password credentials. This once took me a while to understand even though it was wrapped up quite nicely in a node.js module called mongoose-auth.
  • Custom Trophies!: Trophies that you can win are going to be fairly unique in the future. The trophies that you can win while in this iteration, the alpha medals, are limited time only; these user profiles will be the only ones to win after I’m done with this phase. This will make the game a bit more enjoyable to play.

I made use of some pretty cool modules with this release. Go check out the code and see the Readme.md for credits.
As a side note, I’ve done some pretty cool stuff at ONS recently. I’ll post a bit about them next time.

Posted in Uncategorized | Leave a comment

“So what is this Google Huddle thing?”

I’m surprised that people haven’t messed around with Huddle yet. The easiest way I’ve come to think of it is a chatroom that you can share between yourself and your Google+ contacts. According to Google’s About Huddle:

With Huddle, you can text groups of people or individual friends in Google+ Mobile. When you receive a new message in Huddle, Google+ sends a push notification to your phone.

For example, the University of Pittsburgh’s CrossFit club, Panther CrossFit, often has weekend workouts which are organized over at their blog (see the above link). However, let’s say, for instance, the gym is closed that day. One of the club members happens to arrive at the gym 20 minute early to find the doors locked. In order to save some time, he or she can send out a Huddle message to his/her Panther CrossFit circle in Google+. That way, everyone who allows the Huddle message to go to their phone will know not to go to the gym. In fact, the club president can respond to that message and, therefore, to the rest of the group to let everyone know they should head to the local outdoor track. Even with 10-20 people, this can be a HUGE time saver.

Of course, the other members of that Huddle can send their groans about how sore their legs are in this Huddle, but the president (whoever he or she is at the time) will probably ignore their whining ;) .

Posted in Uncategorized | Tagged | Leave a comment

Don’t Delete Your Picasa Albums!

I’ve read an alarming amount of posts recently about people accidentally deleting their Google Picasa web albums because they see them show up in their photos within Google+. Don’t do this, sillies.

Instead, log into your Picasa web albums and change the permissions to “Only me” for the albums you wish to hide. “Limited” grants permissions to only certain people (circles). If you delete the web albums from within Google+, this will also delete the albums from within Picasa.

Although this is a warning, it also exposes a “feature”; we can better customize our Google+ albums from within Picasa. Instead of going through Picasa, though, the ability to upload photos to specific albums needs to be added to the Google+ phone app (along with a few other features).

Posted in Uncategorized | Tagged , | Leave a comment

Some interesting differences

Just playing on the node.js repl, I found this URL here: http://stackoverflow.com/questions/359494/javascript-vs-does-it-matter-which-equal-operator-i-use

The special case is when you compare a string literal with a string object created with the String constructor.

"abc" == new String("abc")    // true
"abc" === new String("abc")   // false

Here the == operator is checking the values of the two objects and returning true, but the === is seeing that they’re not the same type and returning false. Which one is correct? That really depends on what you’re trying to compare. My advice is to bypass the question entirely and just don’t use the String constructor to create string objects.

I thought this was interesting, so I tried it out on the node.js repl:

> typeof new String("test")
'object'
> typeof "test"
'string'
> var myString = new String("test")
> myString
{ '0': 't', '1': 'e', '2': 's', '3': 't' }
> var myOtherString = "test"
> myOtherString
'test'
view raw gistfile1.js This Gist brought to you by GitHub.

Interesting: creating a string with `new String()` creates an object, whereas creating a literal string creates a “string” type.

Posted in Uncategorized | Leave a comment

Rock, Paper, Scissors, Node! Finally!

Today was an interesting day. It started off on a high note; a good day at work, came home deposited some checks, then finally pushed out RPS to the interwebs and had some fellow noders test it out (Thanks guys!).

Then I crashed and burned when I became far too tired and tried trouble shooting an error for several hours when it turned out to be a missing right paren.

Anywho, check out the two repos:
https://github.com/rjohnston/rock-paper-scissors-node
https://github.com/rjohnston/svn-monitor-node

Also, check out the first release of RPS!
http://rockpaperscissors.nodester.com

Thanks, Nodester, for the free hosting!

Posted in Uncategorized | Leave a comment

Methods in Context

Wow. So I think I finally am starting to get the hang of how this whole “context” thing works. I never had to really think about this in PHP, so it took me some time to understand.

If you program in JavaScript, you know that you can pass along an object’s function as an argument to another function. For example, you have a Cat object, defined as:

Cat = {}
Cat.sound = 'meow!'
Cat.speak = function () {
  console.log(this.sound)
}
view raw gistfile1.js This Gist brought to you by GitHub.

Simple, right? So something like `SetTimeout(Cat.speak, 2000)` should work perfectly, right?

Wrooooong.

In JavaScript, when you pass a function to another method like this, it loses its context; aka, when it tries to reference ‘this’ (as in line 4 from above), it doesn’t know what ‘this’ you’re talking about. In order to tell it directly what ‘this’ you’re talking about:

setTimeout(Cat.speak.bind(Cat), 2000)

view raw gistfile1.js This Gist brought to you by GitHub.

Or, alternatively, you could have set up the Object like so:

var Animal = function(sound) {
    this.sound = sound
    self = this
}
Animal.prototype.speak = function() {
    console.log(self.sound)
}
var cat = new Animal('meow')
cat.speak()
setTimeout(cat.speak, 1000)
view raw gistfile1.js This Gist brought to you by GitHub.
Posted in Uncategorized | Tagged | Leave a comment

More confidence

Me and two other guys, Victor and Aleksey, have begun plans for a node.js project. I’m quite excited because this is mostly going to be an exercise in learning for me; I”m pretty sure these guys have a much better handle on what we’re doing than I do ;) . It’s hard to believe, but I really only started coding stuff in JavaScript a month ago. Already, though, I’ve messed around with more libs than I think I’ve dealt with in my life. Be on the lookout on this blog over the next few weeks (heh) for updates as far as that goes.

I’m starting to get settled in to my job at ONS. The staff is very friendly, my co-workers and boss are all very helpful and inviting, and it’s a big boy job! Yay!

Only thing to do now is plug forward. I need to find housing in the next few weeks; the lease on my current dwelling will be up come the end of July and I’m going to move closer to work.

Also, I lol’d when I heard “Ubuntu Natty.”

Posted in Uncategorized | Leave a comment

Hello Internet

This is my first blog in quite some time. If you choose to follow this blog, you’ll get my personal experiences with computers, coding, CrossFit, Minecraft, and life in between. For now, just think of this as a personal dumping grounds for what I may be working on at the time.

I missed my second PHP meetup in a row. Boo. Originally I had thought the meeting place was far closer to my home, but it turns out it was a bit further away, and time was not on my side. I’m really hoping I get the chance to go and talk/listen to some professional PHP programmers in the area come next meeting.

I just finished up Pedro Teixeira‘s Node video on sessions this evening. I’m hoping to play around with that a little bit tomorrow after work. Before that, I’m going to make a bit of headway into a small .Net project at work. It’ll be my first whack at hacking around with an actual .Net application. Woo woo!

I’m also attempting to learn a bit of C++ on the side. I never had a chance to learn it in school; high-school didn’t offer the right courses, and I mostly took Java and PHP courses in college. I had tried learning it in the past on my own, but I was much younger and the concept of pointers/references vs values eluded me. C++ seems like a really cool language, so I think I’ll enjoy hacking around with it in the future.

Sorry that this post is a bit boring. I’ll attempt to make future posts more lively and exciting.

Posted in Uncategorized | Leave a comment