Developing a Dynamic YouTube Search Widget

$URLMapContent.title

Developing a Dynamic YouTube Search Widget Posted: 08.02.2012

This article will walk you through how to build a dynamic YouTube widget in dotCMS. We will use the YouTube API to search for videos on YouTube and Dojo to set the fields in our structure. In this article you will learn how to search asynchronous for YouTube videos, parse the JSON response and get the attributes you need such as video URL, author, play length, thumbnail, etc and set those values in your widget.

Before we get started lets first download the completed files:

Creating the Widget Structure [ Open Screen Shot ]

  1. Click on the Structures tab in the backend of the dotCMS.
  2. Click the Add New Structure button
  3. Make sure you select Widget type and name your widget structure before saving it.
  4. Now you will need to create the following fields and types in your new widget structure.
Name Field Type
Search Custom Field
Author Text
Length Text
Thumbnail Text
Thumbnail2 Text
Published Text
URL Text
NOTE: if you name your fields differently than we have, you’ll need to change the variable names in the JavaScript function setFields.

Creating the Custom Search field (youtube-search.vtl)

When creating custom fields the first thing I like to do is to create a blank VTL file on my desktop. I then upload the VTL to the dotCMS server I’m working on. In this example, I created a VTL file called youtube-search.vtl and uploaded it to the //shared/vtl/custom-fields/ folder on the dotCMS 2.0 starter. Once the VTL file is on the server I need to include it in my custom field (Search).

  1. Go to your widget you just created and click on the pencil next to the “Search” label.
  2. Insert the dotParse code into the Value field. In this example the dotParse code would look like this
#dotParse('//shared/vtl/custom-fields/youtube-search.vtl')
NOTE: if you saved your VTL in a different directory you will need to change the pathing

Now that we have our VTL on the server and its being include in our custom field, we need to connect to the serve through WebDav (if you can’t use webdav you can edit the VTL through the dotCMS interface). Open the VTL file (youtube-search.vtl) in your preferred text editor (I use Aptana). NOTE:  To learn more about WebDav visit: http://dotcms.com/docs/latest/WebDAV


Creating the Search Box

Now we need to create the search box our users will type their keywords into. Here is the code we need.

<input name="searchStr" id="inputSearchStrId" type="text" dojoType="dijit.form.TextBox" style="width:400px;" placeHolder="Search for Videos on YouTube" />
<button dojoType="dijit.form.Button" onClick="searchClicked()" iconClass="searchIcon">Search</button>

This will create a Dojo text box and button. We included the search icon in the button and taken advantage of the Dojo placeHolder feature in the text box. When the user clicks the search button it will call the JavaScript function searchClicked.

We should also create two more div that will be used later in this article.

The first DIV we need to create will be used to display our results. In this example I used a Dojo dialog box for my results.

<div id="videoResultsDiv" dojoType="dijit.Dialog" style="display: none">
  <div id="myResults"></div>
</div>

The Second DIV will display a thumbnail of the video that will alway the user to preview the video before saving.

<div class="imageWrapper">
  <a href="#" onClick="playVideo()" class="playButton"></a>
  <div id="thumbnailImage"></div>
</div>

Creating the function for the Dynamic Search Request

Setting up a dynamic search request to YouTube:

function searchClicked(){
  var mySearch = document.getElementById("inputSearchStrId").value;
  if(mySearch.length < 1){
    alert("Please Enter Search Term");
    document.getElementById('inputSearchStrId').focus();
  }else{
    dijit.byId('videoResultsDiv').show();
    document.getElementById("myResults").innerHTML = 'Loading YouTube videos ...';
    var script = document.createElement('script');
    script.setAttribute('id', 'jsonScript');
    script.setAttribute('type', 'text/javascript');
    script.setAttribute('src', 'http://gdata.youtube.com/feeds/' + 
      'videos?vq=' + mySearch + '&max-results=25&' + 
      'alt=json-in-script&callback=showMyVideos&' + 
      'orderby=relevance&sortorder=descending&format=5&fmt=18');
    document.documentElement.firstChild.appendChild(script);
   }
}
  1. Get the value of the search box (inputSearchStrId)
  2. Make sure the user has typed something into the search box. If they have not prompt them with an Alert.
  3. Once we have the search string we can create the JavaScript element that will return the JSON data
  4. We then need to attach the script to the current page. This will submit an asynchronous search request.
  5. After the JSON data is returned we call a function to parse the results (callback=showMyVideos)
  6. You can see this function also opens the Dojo dialog called (videoResultsDiv) we created earlier. This is where we will push the results once we have parsed the data.

Parsing the Results

The search request (searchClicked) will call asynchronously showMyVideos(data) when the results are returned. Now we need to parsing and output the attributes we need from the response data. Here is the code we use to do that:

function showMyVideos(data){
    var feed = data.feed;
    var entries = feed.entry || [];
    var html = ['<ul>'];
    for (var i = 0; i < entries.length; i++)
    {
        var entry = entries[i];
        var playCount = entry.yt$statistics.viewCount.valueOf();
        var title = entry.title.$t;
        var lnk = entry.link[0].href;
        var published = entry.published.$t;
        var length = entry.media$group.media$thumbnail[1].time;
        var by = entry.author[0].name.$t;
        var picSm = entry.media$group.media$thumbnail[1].url;
        var picLg = entry.media$group.media$thumbnail[0].url;
    var passVar = " ' " + lnk + " ' , ' " + picSm + "' , '" + picLg + "' , '" + title + "' , '" + by + "' , '" + length + "' , '" + published + " ' ";
        html.push('<li onclick=\"setFields(', passVar , ');\"><span style=\"background:url(', picSm, ') no-repeat;\"></span><b>' , title , '</b><br><b>Author: </b>', by ,'<br><b>Length: </b>', length, '<br><b>Published: </b>', published , '<br><b>Views: </b>', playCount ,'</li>');
    }
    html.push('</ul>');
    document.getElementById('myResults').innerHTML = html.join('');  
}

You can see we can traverse the JSON data like you traverse objects, arrays etc., much the same way you use variables in Java. This is because JSON is embedded into the JavaScript language. Were the response in XML, you would have to implement a parser yourself.

The last thing this function does is join the parsed results to the div (myResults).


Capturing the Users selection

Now we need to populate the variables in our widget structure based on the user’s selection. In the function above (showMyVideos) we attached an onClick event to each <li> that will call the (setFields) function and pass it the variables we parse from the JSON object. This is what that function looks like:

function setFields(lnk,picSm,picLg,title,by,length,published){
  dijit.byId('videoResultsDiv').hide();
  dojo.byId("widgetTitle").value=title;
  dojo.byId("author").value=by;
  dojo.byId("length").value=length;
  dojo.byId("thumbnail").value=picSm;
  dojo.byId("thumbnail2").value=picLg;
  dojo.byId("published").value=published;
  dojo.byId("url").value=lnk;
  dojo.byId("inputSearchStrId").value="";
  dojo.style(dojo.byId("thumbnailImage"), "background", "url(" + picLg + ") center center no-repeat");
}  
NOTE: The last line of the function sets the background image of a the thumbnailImage Div

The Finishing Touches

Almost done! Last we need to write the function that will create a dialog window and play the video. This will take a little JavaScript string formatting because the data provided by the YouTube API does not include the correct URL for the embed video version. However, no worries, the code is very simple.

We need to change our URL string from this:
http://www.youtube.com/watch?v=aYKElzlLfEU&feature=youtube_gdata

To This:
http://www.youtube.com/embed/aYKElzlLfEU

First we need to replace the “watch?v=” with “embed/”

var y = dojo.byId("url").value;
y = y.replace('watch?v=', 'embed/');

Next we need to trim off everything after the "&"

y = y.substring(0, y.indexOf("&"));

Now we need to programmatically create a Dojo dialog window that will play the video and pass it the url (y). We need to do this programmatically because we need to destroy the element from the DOM on close. If you close it or hide it without destroying the element from the DOM the video will continue to play even though it is hidden from view.

Here is the complete function:

function playVideo(){
  var y = dojo.byId("url").value;
  if(y.length < 1){
    document.getElementById('inputSearchStrId').focus();
  }else{
    y = y.replace('watch?v=', 'embed/');
    y = y.substring(0, y.indexOf("&"));
    var videoPlayer = new dijit.Dialog({
      title: "dotCMS Player",
      content: "<iframe id='myIframe' src='" + y + "' width='560' height='315' style='border: 0 none;margin:-10px;'></iframe>",
      loadingMessage: "Loading...",
      style: "width:560px;height:341px;padding:0;",
    });
    videoPlayer.show();
    videoPlayer.connect(videoPlayer, 'onHide', function() {
        setTimeout(function() { videoPlayer.destroyRecursive(); }, 0);
    });
  }
}  

Take a look at what the finished VTL should look like now.


Conclusion

If you’re using the new dotCMS starter that came with dotCMS 2.0+, you can add this code to the the Widget Code field. This will allow you to place your video in any container in your site using the PrettyPhoto jQuery plugin that ships with the starter.

<div class="feat-video">
  <a href="$url" class="hoverVideo prettyPhoto" title="$!{widgetTitle}" style="width:100%">
    #if ($UtilMethods.isSet($thumbnail2))
      <img src="$!{thumbnail2}" alt="$!{widgetTitle}" style="width:98%;margin:0 6px 0 0;"/>
    #else
      $!{widgetTitle}
    #end
  </a>
</div>


New report from Digital Clarity Group notes that a majority of digital marketing teams don’t or can’t use all the software capabilities they have, creating “shelfware” or “underused” software. Gain fresh perspective on the challenges facing digital marketers. Download Now.