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 .= ''; } } else { - $id = 'media-youtube-preview'; - $div_id = 'media-youtube-preview-wrapper'; - $flashvars = check_plain(drupal_http_build_query(array('playerMode' => 'embedded'))); - // - $output = << -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 = ''; + + // For users with JavaScript, these object and embed tags will be replaced + // by an iframe, so that we can support users without Flash. + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + + $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 .= ''; } + 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=arguments[i]){if(i+10){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' + Drupal.t('You need Flash to watch this video. Get Flash', {'@flash':'http://get.adobe.com/flashplayer'}) + ''); + 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 = $(''); + 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);