Index: media_youtube.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/media_youtube/media_youtube.module,v
retrieving revision 1.1.4.43
diff -u -p -r1.1.4.43 media_youtube.module
--- media_youtube.module	7 Oct 2010 16:32:34 -0000	1.1.4.43
+++ media_youtube.module	22 Oct 2010 21:20:30 -0000
@@ -244,31 +262,93 @@ function theme_media_youtube_embed($vari
         $in_browser = TRUE;
         $thumbnail = TRUE;
       }
-    }
+    }   
     $width = isset($width) ? $width : 560;
     $height = isset($height) ? $height : 340;
+    $video_id = check_plain($parts['v']);
     if ($thumbnail) {
-      $output = theme('image', array(
+      // @todo Clean this up.
+      $image_variables = array(
         'path' => 'http://img.youtube.com/vi/'. check_plain($parts['v']) .'/0.jpg',
         'alt' => $variables['alt'],
         'title' => $variables['title'],
-        'attributes' => array('width' => $width, 'height' => $height),
         'getsize' => FALSE,
-      ));
+      );
+      if (isset($preset['image_style'])) {
+        $local_path = 'public://media-youtube/' . check_plain($parts['v']) . '.jpg';
+        if (!file_exists($local_path)) {
+          $dirname = drupal_dirname($local_path);
+          file_prepare_directory($dirname, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
+          @copy($image_variables['path'], $local_path);
+        }
+        $image_variables['path'] = $local_path;
+        $image_variables['style_name'] = $preset['image_style'];
+        $output = theme('image_style', $image_variables);
+      }
+      else {
+        // We need to add this style attribute here so that it doesn't get lost
+        // If you resize a video in a node, save it, edit it, but don't adjust
+        // the sizing of the video while editing, the size will revert to the
+        // default.  Adding the specific size here retains the original resizing
+        $WYSIWYG = isset($variables['object']->override['style']) ? $variables['object']->override['style'] : '';
+        $image_variables['attributes'] = array('width' => $width, 'height' => $height, 'style' => $WYSIWYG);
+        $output = theme('image', $image_variables);
+      }
       if ($in_browser) {
         // Add an overlay that says 'YouTube' to media library browser thumbnails.
         $output .= '<span />';
       }
     }
     else {
-      $id = 'media-youtube-preview';
-      $div_id = 'media-youtube-preview-wrapper';
-      $flashvars = check_plain(drupal_http_build_query(array('playerMode' => 'embedded')));
-      // <object width="425" height="344"><param name="movie" value="http://www.youtube.com/v/lZ-s3DRZJKY&hl=en&fs=1&"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/lZ-s3DRZJKY&hl=en&fs=1&" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"></embed></object>
-      $output = <<<OUTPUT
-<div id="$div_id"><object type="application/x-shockwave-flash" height="$height" width="$width" data="$url" id="$id"><param name="movie" value="$url" /><param name="allowScriptAcess" value="sameDomain"/><param name="quality" value="best"/><param name="allowFullScreen" value="$fullscreen_value"/><param name="bgcolor" value="#FFFFFF"/><param name="scale" value="noScale"/><param name="salign" value="TL"/><param name="FlashVars" value="$flashvars" /><param name="wmode" value="transparent" /></object></div>
-OUTPUT;
+      // This extra wrapper around the video allows the video to be resized to fit
+      // dimensions set in a WYSIWYG.  Otherwise the styles set will be overridden
+      // by the JS fluid width resizing method.
+      $WYSIWYG = isset($variables['object']->override['style']) ? $variables['object']->override['style'] : '';
+      $output = '<div class="media-youtube-outer-wrapper" style="' . $WYSIWYG . '"><div id="video_'. $video_id .'" class="media-youtube-preview-wrapper" style="width: ' . $width . 'px; height: ' . $height . 'px;">';
+
+      // For users with JavaScript, these object and embed tags will be replaced
+      // by an iframe, so that we can support users without Flash.
+      $output .= '<object width="' . $width . '" height="' . $height . '">';
+      $output .= '<param name="movie" value="http://www.youtube.com/v/' . $video_id . '"></param>';
+      $output .= '<param name="allowFullScreen" value="true"></param>';
+      $output .= '<embed src="http://www.youtube.com/v/' . $video_id .'" type="application/x-shockwave-flash" width="' . $width . '" height="' . $height . '" allowfullscreen="true"></embed>';
+      $output .= '</object>';
+      $output .= '</div></div>';
+
+      $media_youtube_preview = array();
+      $media_youtube_preview['media_youtube']['width'] = $width;
+      $media_youtube_preview['media_youtube']['height'] = $height;
+      $media_youtube_preview['media_youtube']['video_id'] = $video_id;
+      $media_youtube_preview['media_youtube']['fullscreen'] = $fullscreen_value;
+      $media_youtube_preview['media_youtube']['id'] = 'media-youtube-preview';
+
+      // @todo Replace this inline JavaScript with at least calls to
+      //   drupal_add_js()/drupal_get_js(), and ideally, with a behavior. Keep
+      //   in mind that the solution needs to work when inside a colorbox or
+      //   otherwise in an AJAX response, but that should now be possible in D7.
+      $video_id_json = drupal_json_encode($video_id);
+      $prefixed_video_id_json = drupal_json_encode('video_' . $video_id);
+      $JSObject = 'Drupal.settings.media_youtube[' . $prefixed_video_id_json . ']';
+      $output .= '<script type="text/javascript">
+        <!--//--><![CDATA[//><!--
+        if (Drupal.settings && Drupal.media_youtube) {
+          if (!Drupal.settings.media_youtube) {
+            Drupal.settings.media_youtube = {};
+          }
+          ' . $JSObject . ' = {};
+          ' . $JSObject . '.width = '. $width . ';
+          ' . $JSObject . '.height = '. $height . ';
+          ' . $JSObject . '.video_id = "'. check_plain($parts['v']) . '";
+          ' . $JSObject . '.fullscreen = '. $fullscreen_value . ';
+          ' . $JSObject . '.id = ' . $video_id_json . ';
+          Drupal.media_youtube.insertEmbed(' . $prefixed_video_id_json . ');
+        }
+        //--><!]]>
+        </script>';
     }
+    drupal_add_js(drupal_get_path('module', 'media_youtube') . '/js/media_youtube.js');
+    drupal_add_css(drupal_get_path('module', 'media_youtube') . '/css/media_youtube.css');
+    drupal_add_js(drupal_get_path('module', 'media_youtube') . '/js/flash_detect_min.js');
   }
   return $output;
 }
Index: css/media_youtube.css
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/media_youtube/css/Attic/media_youtube.css,v
retrieving revision 1.1.2.1
diff -u -p -r1.1.2.1 media_youtube.css
--- css/media_youtube.css	22 Oct 2010 20:54:55 -0000	1.1.2.1
+++ css/media_youtube.css	22 Oct 2010 21:20:30 -0000
@@ -1,3 +1,22 @@
 // $Id: media_youtube.css $
 
-/* Empty for now. */
+.media-youtube-preview-wrapper {
+  max-width: 100%;
+  min-height: 50px;
+  position: relative;
+}
+
+.media-youtube-preview-wrapper object,
+.media-youtube-preview-wrapper iframe {
+  max-width: 100%;
+  position: absolute;
+}
+
+.media-youtube-preview-wrapper .js-fallback {
+  left: 0;
+  margin-top: -0.5em;
+  position: absolute;
+  right: 0;
+  text-align: center;
+  top: 50%;
+}
Index: js/flash_detect_min.js
===================================================================
RCS file: js/flash_detect_min.js
diff -N js/flash_detect_min.js
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ js/flash_detect_min.js	22 Oct 2010 21:20:30 -0000
@@ -0,0 +1,5 @@
+//http://www.featureblend.com/license.txt
+var FlashDetect=new function(){var self=this;self.installed=false;self.raw="";self.major=-1;self.minor=-1;self.revision=-1;self.revisionStr="";var activeXDetectRules=[{"name":"ShockwaveFlash.ShockwaveFlash.7","version":function(obj){return getActiveXVersion(obj);}},{"name":"ShockwaveFlash.ShockwaveFlash.6","version":function(obj){var version="6,0,21";try{obj.AllowScriptAccess="always";version=getActiveXVersion(obj);}catch(err){}
+return version;}},{"name":"ShockwaveFlash.ShockwaveFlash","version":function(obj){return getActiveXVersion(obj);}}];var getActiveXVersion=function(activeXObj){var version=-1;try{version=activeXObj.GetVariable("$version");}catch(err){}
+return version;};var getActiveXObject=function(name){var obj=-1;try{obj=new ActiveXObject(name);}catch(err){obj={activeXError:true};}
+return obj;};var parseActiveXVersion=function(str){var versionArray=str.split(",");return{"raw":str,"major":parseInt(versionArray[0].split(" ")[1],10),"minor":parseInt(versionArray[1],10),"revision":parseInt(versionArray[2],10),"revisionStr":versionArray[2]};};var parseStandardVersion=function(str){var descParts=str.split(/ +/);var majorMinor=descParts[2].split(/\./);var revisionStr=descParts[3];return{"raw":str,"major":parseInt(majorMinor[0],10),"minor":parseInt(majorMinor[1],10),"revisionStr":revisionStr,"revision":parseRevisionStrToInt(revisionStr)};};var parseRevisionStrToInt=function(str){return parseInt(str.replace(/[a-zA-Z]/g,""),10)||self.revision;};self.majorAtLeast=function(version){return self.major>=version;};self.minorAtLeast=function(version){return self.minor>=version;};self.revisionAtLeast=function(version){return self.revision>=version;};self.versionAtLeast=function(major){var properties=[self.major,self.minor,self.revision];var len=Math.min(properties.length,arguments.length);for(i=0;i<len;i++){if(properties[i]>=arguments[i]){if(i+1<len&&properties[i]==arguments[i]){continue;}else{return true;}}else{return false;}}};self.FlashDetect=function(){if(navigator.plugins&&navigator.plugins.length>0){var type='application/x-shockwave-flash';var mimeTypes=navigator.mimeTypes;if(mimeTypes&&mimeTypes[type]&&mimeTypes[type].enabledPlugin&&mimeTypes[type].enabledPlugin.description){var version=mimeTypes[type].enabledPlugin.description;var versionObj=parseStandardVersion(version);self.raw=versionObj.raw;self.major=versionObj.major;self.minor=versionObj.minor;self.revisionStr=versionObj.revisionStr;self.revision=versionObj.revision;self.installed=true;}}else if(navigator.appVersion.indexOf("Mac")==-1&&window.execScript){var version=-1;for(var i=0;i<activeXDetectRules.length&&version==-1;i++){var obj=getActiveXObject(activeXDetectRules[i].name);if(!obj.activeXError){self.installed=true;version=activeXDetectRules[i].version(obj);if(version!=-1){var versionObj=parseActiveXVersion(version);self.raw=versionObj.raw;self.major=versionObj.major;self.minor=versionObj.minor;self.revision=versionObj.revision;self.revisionStr=versionObj.revisionStr;}}}}}();};FlashDetect.JS_RELEASE="1.0.4";
\ No newline at end of file
Index: js/media_youtube.js
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/media_youtube/js/Attic/media_youtube.js,v
retrieving revision 1.1.2.2
diff -u -p -r1.1.2.2 media_youtube.js
--- js/media_youtube.js	26 Nov 2009 12:46:55 -0000	1.1.2.2
+++ js/media_youtube.js	22 Oct 2010 21:20:30 -0000
@@ -1,184 +1,94 @@
-// $Id: media_youtube.js,v 1.1.2.2 2009/11/26 12:46:55 aaron Exp $
-
-/**
- *  @file
- *  JavaScript for the Media: YouTube module.
- *
- *  This will send a YouTube link or embed code back to the module,
- *  which will return an embedded clip and fill in the uri on the main form.
- */
 (function ($) {
 
-/**
- *  Send the link back to the module, and fill in elements w/ correct info.
- */
-Drupal.behaviors.mediaYoutubeLink = {
+Drupal.media_youtube = {};
+Drupal.behaviors.media_youtube = {
   attach: function (context, settings) {
-    var ytdb = [];
-    $('.form-item-media-youtube-url input', context).once('mediaYoutubeLink', function () {
-      var uri = this.value;
-      if (!ytdb[uri]) {
-        ytdb[uri] = new Drupal.YTDB(uri);
+    // Check the browser to see if it supports html5 video.
+    var video = document.createElement('video');
+    var html5 = video.canPlayType ? true : false;
+
+    // If it has video, does it support the correct codecs?
+    if (html5) {
+      html5 = false;
+      if (video.canPlayType( 'video/webm; codecs="vp8, vorbis"' ) || video.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"')) {
+        html5 = true;
       }
-      var input = $(this);
-      new Drupal.mediaYoutubeBind(input, ytdb[uri]);
-    });
+    }
+
+    // Put a prompt in the video wrappers to let users know they need flash
+    if (!FlashDetect.installed && !html5){
+      $('.media-youtube-preview-wrapper').each(Drupal.media_youtube.needFlash);
+    }
   }
 };
 
-/**
- * An AutoComplete object.
- */
-Drupal.mediaYoutubeBind = function (input, db) {
-  var yt = this;
-  this.input = input;
-  this.db = db;
-  this.parsing = false;
-  $(this.input)
-    .keyup(function () { yt.parseurl(this); })
-    .blur(function () { yt.parseurl(this); });
-
+Drupal.media_youtube.needFlash = function () {
+  var id = $(this).attr('id');
+  var wrapper = $('.media-youtube-preview-wrapper');
+  var hw = Drupal.settings.media_youtube[id].height / Drupal.settings.media_youtube[id].width;
+  wrapper.html('<div class="js-fallback">' + Drupal.t('You need Flash to watch this video. <a href="@flash">Get Flash</a>', {'@flash':'http://get.adobe.com/flashplayer'}) + '</div>');
+  wrapper.height(wrapper.width() * hw);
 };
 
-Drupal.mediaYoutubeBind.prototype.parseurl = function (input) {
-  input.delay = 500;
-  // Initiate delayed parse.
-  if (input.timer) {
-    clearTimeout(input.timer);
-  }
-  if (input.value.length == 0) {
-    return;
-  }
-  if (input.value == input.current_value) {
-    return;
-  }
-  input.current_value = input.value;
-  input.url = Drupal.settings.mediaYoutube.parse_url + '?parse=' + Drupal.encodePath(input.value);
-  input.timer = setTimeout(function () {
-
-    // Ajax GET request for autocompletion.
-    $.ajax({
-      type: 'GET',
-      url: input.url,
-      dataType: 'json',
-      success: function (val) {
-        if (val.status == 'ok') {
-          $('input.media-file-uri').val(val.uri);
-          $('.media-youtube-preview-markup').html(val.preview);
-        }
-        else {
-          $('input.media-file-uri').val('');
-        }
-      },
-      error: function (xmlhttp) {
-        alert(Drupal.ajaxError(xmlhttp, input.url));
-      }
-    });
-  }, input.delay);
-}
-
-/**
- * Handler for the "keyup" event.
- */
-Drupal.mediaYoutubeBind.prototype.onkeyup = function (input, e) {
-  if (!e) {
-    e = window.event;
-  }
-  switch (e.keyCode) {
-    case 16: // shift.
-    case 17: // ctrl.
-    case 18: // alt.
-    case 20: // caps lock.
-    case 33: // page up.
-    case 34: // page down.
-    case 35: // end.
-    case 36: // home.
-    case 37: // left arrow.
-    case 38: // up arrow.
-    case 39: // right arrow.
-    case 40: // down arrow.
-      return true;
-
-    case 9:  // tab.
-    case 13: // enter.
-    case 27: // esc.
-      this.hidePopup(e.keyCode);
-      return true;
-
-    default: // All other keys.
-      if (input.value.length > 0)
-        this.populatePopup();
-      else
-        this.hidePopup(e.keyCode);
-      return true;
-  }
-};
+Drupal.media_youtube.insertEmbed = function (embed_id) {
+  var videoWrapper = $('#' + embed_id + '.media-youtube-preview-wrapper');
+  var settings = Drupal.settings.media_youtube[embed_id];
 
+  // Calculate the ratio of the dimensions of the embed.
+  settings.hw = settings.height / settings.width;
 
-/**
- * An AutoComplete DataBase object.
- */
-Drupal.YTDB = function (uri) {
-  this.uri = uri;
-  this.delay = 300;
-  this.cache = {};
-};
+  // Replace the object embed with YouTube's iframe. This isn't done by the
+  // theme function because YouTube doesn't have a no-JS or no-Flash fallback.
+  var video = $('<iframe class="youtube-player" type="text/html" frameborder="0"></iframe>');
+  var src = 'http://www.youtube.com/embed/' + settings.video_id;
 
-/**
- * Performs a cached and delayed search.
- */
-Drupal.YTDB.prototype.search = function (searchString) {
-  var db = this;
-  this.searchString = searchString;
-
-  // See if this string needs to be searched for anyway.
-  searchString = searchString.replace(/^\s+|\s+$/, '');
-  if (searchString.length <= 0 ||
-    searchString.charAt(searchString.length - 1) == ',') {
-    return;
-  }
+  // Allow other modules to modify the video settings.
+  settings.options = {wmode : 'opaque'};
+  $(window).trigger('media_youtube_load', settings);
 
-  // See if this key has been searched for before.
-  if (this.cache[searchString]) {
-    return this.owner.found(this.cache[searchString]);
+  // Merge YouTube options (such as autoplay) into the source URL.
+  var query = $.param(settings.options);
+  if (query) {
+    src += '?' + query;
   }
 
-  // Initiate delayed search.
-  if (this.timer) {
-    clearTimeout(this.timer);
+  // Set up the iframe with its contents and add it to the page.
+  video
+    .attr('id', settings.id)
+    .attr('width', settings.height)
+    .attr('height', settings.width)
+    .attr('src', src);
+  videoWrapper.html(video);
+
+  // Bind a resize event to handle fluid layouts.
+  $(window).bind('resize', Drupal.media_youtube.resizeEmbeds);
+
+  // For some reason Chrome does not properly size the container around the
+  // embed and it will just render the embed at full size unless we set this
+  // timeout.
+  if (!$('.lightbox-stack').length) {
+    setTimeout(Drupal.media_youtube.resizeEmbeds, 1);
   }
-  this.timer = setTimeout(function () {
-    db.owner.setStatus('begin');
+};
 
-    // Ajax GET request for autocompletion.
-    $.ajax({
-      type: 'GET',
-      url: Drupal.settings.mediaYoutube.parse_url + '/' + Drupal.encodePath(searchString),
-      dataType: 'json',
-      success: function (matches) {
-        if (typeof matches.status == 'undefined' || matches.status != 0) {
-          db.cache[searchString] = matches;
-          // Verify if these are still the matches the user wants to see.
-          if (db.searchString == searchString) {
-            db.owner.found(matches);
-          }
-          db.owner.setStatus('found');
-        }
-      },
-      error: function (xmlhttp) {
-        alert(Drupal.ajaxError(xmlhttp, db.uri));
-      }
-    });
-  }, this.delay);
+Drupal.media_youtube.resizeEmbeds = function () {
+  $('.media-youtube-preview-wrapper').each(Drupal.media_youtube.resizeEmbed);
 };
 
-/**
- * Cancels the current autocomplete request.
- */
-Drupal.YTDB.prototype.cancel = function () {
-  if (this.owner) this.owner.setStatus('cancel');
-  if (this.timer) clearTimeout(this.timer);
-  this.searchString = '';
+Drupal.media_youtube.resizeEmbed = function () {
+  var context = $(this).parent();
+  var video = $(this).children(':first-child');
+  var hw = Drupal.settings.media_youtube[$(this).attr('id')].hw;
+  // Change the height of the wrapper that was given a fixed height by the
+  // YouTube theming function.
+  $(this)
+    .height(context.width() * hw)
+    .width(context.width());
+
+  // Change the attributes on the embed to match the new size.
+  video
+    .height(context.width() * hw)
+    .width(context.width());
 };
 
-})(jQuery);
+})(jQuery);
\ No newline at end of file
Index: js/media_youtube.old.js
===================================================================
RCS file: js/media_youtube.old.js
diff -N js/media_youtube.old.js
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ js/media_youtube.old.js	22 Oct 2010 21:20:30 -0000
@@ -0,0 +1,184 @@
+// $Id: media_youtube.js,v 1.1.2.2 2009/11/26 12:46:55 aaron Exp $
+
+/**
+ *  @file
+ *  JavaScript for the Media: YouTube module.
+ *
+ *  This will send a YouTube link or embed code back to the module,
+ *  which will return an embedded clip and fill in the uri on the main form.
+ */
+(function ($) {
+
+/**
+ *  Send the link back to the module, and fill in elements w/ correct info.
+ */
+Drupal.behaviors.mediaYoutubeLink = {
+  attach: function (context, settings) {
+    var ytdb = [];
+    $('.form-item-media-youtube-url input', context).once('mediaYoutubeLink', function () {
+      var uri = this.value;
+      if (!ytdb[uri]) {
+        ytdb[uri] = new Drupal.YTDB(uri);
+      }
+      var input = $(this);
+      new Drupal.mediaYoutubeBind(input, ytdb[uri]);
+    });
+  }
+};
+
+/**
+ * An AutoComplete object.
+ */
+Drupal.mediaYoutubeBind = function (input, db) {
+  var yt = this;
+  this.input = input;
+  this.db = db;
+  this.parsing = false;
+  $(this.input)
+    .keyup(function () { yt.parseurl(this); })
+    .blur(function () { yt.parseurl(this); });
+
+};
+
+Drupal.mediaYoutubeBind.prototype.parseurl = function (input) {
+  input.delay = 500;
+  // Initiate delayed parse.
+  if (input.timer) {
+    clearTimeout(input.timer);
+  }
+  if (input.value.length == 0) {
+    return;
+  }
+  if (input.value == input.current_value) {
+    return;
+  }
+  input.current_value = input.value;
+  input.url = Drupal.settings.mediaYoutube.parse_url + '?parse=' + Drupal.encodePath(input.value);
+  input.timer = setTimeout(function () {
+
+    // Ajax GET request for autocompletion.
+    $.ajax({
+      type: 'GET',
+      url: input.url,
+      dataType: 'json',
+      success: function (val) {
+        if (val.status == 'ok') {
+          $('input.media-file-uri').val(val.uri);
+          $('.media-youtube-preview-markup').html(val.preview);
+        }
+        else {
+          $('input.media-file-uri').val('');
+        }
+      },
+      error: function (xmlhttp) {
+        alert(Drupal.ajaxError(xmlhttp, input.url));
+      }
+    });
+  }, input.delay);
+}
+
+/**
+ * Handler for the "keyup" event.
+ */
+Drupal.mediaYoutubeBind.prototype.onkeyup = function (input, e) {
+  if (!e) {
+    e = window.event;
+  }
+  switch (e.keyCode) {
+    case 16: // shift.
+    case 17: // ctrl.
+    case 18: // alt.
+    case 20: // caps lock.
+    case 33: // page up.
+    case 34: // page down.
+    case 35: // end.
+    case 36: // home.
+    case 37: // left arrow.
+    case 38: // up arrow.
+    case 39: // right arrow.
+    case 40: // down arrow.
+      return true;
+
+    case 9:  // tab.
+    case 13: // enter.
+    case 27: // esc.
+      this.hidePopup(e.keyCode);
+      return true;
+
+    default: // All other keys.
+      if (input.value.length > 0)
+        this.populatePopup();
+      else
+        this.hidePopup(e.keyCode);
+      return true;
+  }
+};
+
+
+/**
+ * An AutoComplete DataBase object.
+ */
+Drupal.YTDB = function (uri) {
+  this.uri = uri;
+  this.delay = 300;
+  this.cache = {};
+};
+
+/**
+ * Performs a cached and delayed search.
+ */
+Drupal.YTDB.prototype.search = function (searchString) {
+  var db = this;
+  this.searchString = searchString;
+
+  // See if this string needs to be searched for anyway.
+  searchString = searchString.replace(/^\s+|\s+$/, '');
+  if (searchString.length <= 0 ||
+    searchString.charAt(searchString.length - 1) == ',') {
+    return;
+  }
+
+  // See if this key has been searched for before.
+  if (this.cache[searchString]) {
+    return this.owner.found(this.cache[searchString]);
+  }
+
+  // Initiate delayed search.
+  if (this.timer) {
+    clearTimeout(this.timer);
+  }
+  this.timer = setTimeout(function () {
+    db.owner.setStatus('begin');
+
+    // Ajax GET request for autocompletion.
+    $.ajax({
+      type: 'GET',
+      url: Drupal.settings.mediaYoutube.parse_url + '/' + Drupal.encodePath(searchString),
+      dataType: 'json',
+      success: function (matches) {
+        if (typeof matches.status == 'undefined' || matches.status != 0) {
+          db.cache[searchString] = matches;
+          // Verify if these are still the matches the user wants to see.
+          if (db.searchString == searchString) {
+            db.owner.found(matches);
+          }
+          db.owner.setStatus('found');
+        }
+      },
+      error: function (xmlhttp) {
+        alert(Drupal.ajaxError(xmlhttp, db.uri));
+      }
+    });
+  }, this.delay);
+};
+
+/**
+ * Cancels the current autocomplete request.
+ */
+Drupal.YTDB.prototype.cancel = function () {
+  if (this.owner) this.owner.setStatus('cancel');
+  if (this.timer) clearTimeout(this.timer);
+  this.searchString = '';
+};
+
+})(jQuery);
