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:Name | Field Type |
---|---|
Search | Custom Field |
Author | Text |
Length | Text |
Thumbnail | Text |
Thumbnail2 | Text |
Published | Text |
URL | Text |
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).
#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
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>
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); } }
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).
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"); }
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); }); } }
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>
Maintaining or achieving a global presence requires effective use of resources, time and money. Single-tenant CMS solutions were once the go-to choices for enterprises to reach out to different market...
What’s the difference between a headless CMS and a hybrid CMS, and which one is best suited for an enterprise?
What is cloud computing, and what benefits does the cloud bring to brands who are entering into the IoT era?