Greasy Fork

Greasy Fork is available in English.

YouTube Enhancer from YouTube2009Year

Download Link + Quality Selector + Rollover Preview + Media Controller

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// <![CDATA[
// ==UserScript==
// @name          YouTube Enhancer from YouTube2009Year
// @fullname      YouTube Enhancer from YouTube2009Year
// @author        VoxelBeet129
// @version       2014-12-29
// @licence       (CC) by-nc-sa
// @namespace     http://greasyfork.org/scripts/show/33042
// @description   Download Link + Quality Selector + Rollover Preview + Media Controller
// @include       http://youtube2009year.weebly.com
// ==/UserScript==

// fmt=0  -> flv:  320x240 (flv1) / mp3 1.0 22KHz
// fmt=5  -> flv:  320x240 (flv1) / mp3 1.0 22KHz
// fmt=6  -> flv:  480x360 (flv1) / mp3 1.0 44KHz (No more...)
// fmt=13 -> 3gp:  176x144 (mpg4) / ??? 2.0  8KHz
// fmt=17 -> 3gp:  176x144 (mpg4) / ??? 1.0 22KHz
// fmt=18 -> mp4:  480x360 (H264) / AAC 2.0 44KHz
// fmt=22 -> mp4: 1280x720 (H264) / AAC 2.0 44KHz
// fmt=34 -> flv:  320x180 (flv?) / ??? 2.0 44KHz (default now)
// fmt=35 -> flv:  640x380 (flv?) / ??? 2.0 44KHz

// YouTube URL: http://www.youtube.com/watch?v=[video_id] &fmt=[selected_fmt] &hl=[lang]
// YouTube download link: http://www.youtube.com/get_video?video_id=[video_id]&t=[t_id]&fmt=[download_fmt]

( function() {

//======================================== USER SETTING ==================================================//

// Updater
const YOUTUBE_ENHANCER_UPDATER_STATUS = 0; // -1=Disable / 0=No change / 1=Enable

// Cleanning flashvars...
const CLEAN_FLASHVARS            = 1; // 0=disable / 1=enable cleanning
const DISABLE_ANNOTATIONS        = 0; // work only when CLEAN_FLASHVARS is enabled
const DISABLE_SUBTITLES          = 0; // work only when CLEAN_FLASHVARS is enabled

// Video display Config
const ENABLE_4DV3_VIDEO_RESIZING = 1; // 0=Normal size / 1=More height  / 2=Largest size
const ENABLE_WIDE_VIDEO_RESIZING = 1; // 0=Normal size / 1=Largest size
const ENABLE_TITLE_HIDING        = 1; // 0=Show Title  / 1=Hide Title



//======================================== ADVANCED SETTING ==============================================//

// light or dark ? // false=Light colors / true=Dark colors
const USE_DARK_COLORS=(GetLuminosity(window.getComputedStyle(document.body, null).backgroundColor)<128);

// Color for Download Link
var COLOR_DL_OPTIONS_BORDER     = '#DDDDDD';
var COLOR_DL_OPTIONS_BACKGROUND = '#F8E0E0';
var COLOR_DL_OPTIONS_TEXT       = '#6666FF';
var COLOR_DL_POPUP_BORDER       = '#000000';
var COLOR_DL_POPUP_ARROW        = '#000000';
var COLOR_DL_POPUP_TEXT         = '#000000';
var COLOR_DL_POPUP_BG_BLUE_OUT  = '#DDDDFF';
var COLOR_DL_POPUP_BG_BLUE_IN   = '#CCCCFF';
var COLOR_DL_POPUP_BG_RED_OUT   = '#FFDDDD';
var COLOR_DL_POPUP_BG_RED_IN    = '#FFCCCC';
// Color for Media Controller
var COLOR_MC_BORDER         = '#CCCCCC';
var COLOR_MC_BACKGROUND     = '#E8E8E8';
var COLOR_MC_TEXT_OUT       = '#000000';
var COLOR_MC_TEXT_ACTION_IN = '#E00000';
var COLOR_MC_TEXT_TOGGLE_IN = '#00C040';
var COLOR_MC_TOGGLE_BEG_END = '#FFDD00';
var COLOR_MC_TOGGLE_LOOP    = '#BBBBFF';
var COLOR_MC_BG_RED         = '#FFF0F0';
var COLOR_MC_BG_BLUE_OUT    = '#F0F0FF';
var COLOR_MC_BG_BLUE_IN     = '#E0E0FF';
var COLOR_MC_TEXT_BLUE      = '#0033CC';

if (USE_DARK_COLORS==true) {
  // Color for Download Link
  COLOR_DL_OPTIONS_BORDER     = '#666666';
  COLOR_DL_OPTIONS_BACKGROUND = '#5C3C3C';
  COLOR_DL_OPTIONS_TEXT       = '#9999FF';
  COLOR_DL_POPUP_BORDER       = '#888888';
  COLOR_DL_POPUP_ARROW        = '#FFFFFF';
  COLOR_DL_POPUP_TEXT         = '#FFFFFF';
  COLOR_DL_POPUP_BG_BLUE_OUT  = '#444466';
  COLOR_DL_POPUP_BG_BLUE_IN   = '#222266';
  COLOR_DL_POPUP_BG_RED_OUT   = '#664444';
  COLOR_DL_POPUP_BG_RED_IN    = '#662222';
  // Color for Media Controller
  COLOR_MC_BORDER         = '#666666';
  COLOR_MC_BACKGROUND     = '#3C3C3C';
  COLOR_MC_TEXT_OUT       = '#B06000';
  COLOR_MC_TEXT_ACTION_IN = '#FF0000';
  COLOR_MC_TEXT_TOGGLE_IN = '#00C040';
  COLOR_MC_TOGGLE_BEG_END = '#888800';
  COLOR_MC_TOGGLE_LOOP    = '#4444BB';
  COLOR_MC_BG_RED         = '#5C3C3C';
  COLOR_MC_BG_BLUE_OUT    = '#3C3C5C';
  COLOR_MC_BG_BLUE_IN     = '#3C3C8C';
  COLOR_MC_TEXT_BLUE      = '#0066FF';
}

// RollOver Config
const ROLLOVER_DELAY_INIT = 200; // Initial delay
const ROLLOVER_DELAY_LOAD =  50; // Small delay for testing if all images is loaded
const ROLLOVER_DELAY_CONT = 800; // Normal delay of the rollover

// Constants (Not important)
const WATCH_VIDEO_INFO   = 'watch-channel-vids-div';          // To get his background and border color
const WATCH_MORE_FROM    = 'watch-channel-vids-body';         // To add a load event in change_link()
const WATCH_RELATED_VIDS = 'watch-related-vids-body';         // To add a load event in change_link()
const PLAYLIST_PANEL     = 'playlist-panel';                  // To add a load event in change_link()
const WATCH_SEARCH_RES   = 'watch_search_results';            // To add a load event in change_link()
const WATCH_PROMOTED     = 'watch-promoted-videos-container'; // Used to remove the parent
const WATCH_QUAL_SETTING = 'watch-video-quality-setting';     // Used to remove it
const DEFAULT_LANG_BOX   = 'default-language-box';            // Used to remove it
const WATCH_URL_FIELD    = 'watch-url-field';                 // Add fmt

// Constants (Better to have)
const WATCH_PLAYER_DIV   = 'watch-player-div'; // Used to retrieve the Video Embed if not found
const WATCH_RATINGS_VIEW = 'watch-main-area';  // Used to append the Quality Selector

// Constants (Important)
const WATCH_TITLE_DIV = 'watch-vid-title'; // Div id of the video title
const YT_PLAYER_EMBED = 'movie_player';    // Default Video Embed id
const FMT_HIGH_QUALITY_FLV = 35;


//*************************************** Languages support **********************************************//
function get_text_DL(lang,variable) {
  switch(variable) {
    case "dlink": switch (lang) {
        // from Youtube Setting or Youtube URL (17 Languages actually)
        case "zh-cn": return "&#19979;&#36733;";
        case "zh-tw": return "&#19979;&#36617;";
        case "ja": return "&#12480;&#12454;&#12531;&#12525;&#12540;&#12489;";
        case "ko": return "&#45796;&#50868;&#47196;&#46300;";
        case "de": return "Herunterladen";
        default: // Default is set to English
        case "en": case "en-gb": return "Download";
        case "es": case "es-mx": return "Descargar";
        case "fr": return "T&#233;l&#233;charger";
        case "it": return "Scaricare";
        case "nl": return "Downloaden";
        case "pl": return "Pobra&#263;";
        case "pt": return "Baixar";
        case "ru": return "&#1089;&#1082;&#1072;&#1095;&#1072;&#1090;&#1100;";
        case "cs": return "St&#225;hnout";
        case "sv": return "H&#228;mta";
        // from Browser Setting...
        case "ar": return "&#1578;&#1581;&#1605;&#1610;&#1604;";
    }
    case "omenu": switch (lang) {
        case "zh-cn": return "&#36873;&#39033;";
        case "zh-tw": return "&#36984;&#38917;";
        case "ja": return "&#12458;&#12503;&#12471;&#12519;&#12531;";
        case "ko": return "&#50741;&#49496;";
        case "de": return "Optionen";
        default:
        case "en": case "en-gb": return "Options";
        case "es": case "es-mx": return "Opciones";
        case "fr": return "Options";
        case "it": return "Opzioni";
        case "nl": return "Opties";
        case "pl": return "Opcje";
        case "pt": return "Op&#231;&#245;es";
        case "ru": return "&#1042;&#1072;&#1088;&#1080;&#1072;&#1085;&#1090;&#1086;&#1074;";
        case "ar": return "&#1582;&#1610;&#1575;&#1585;&#1575;&#1578;";
    }
    case "qual1": switch (lang) {
        case "zh-cn": return "1: &#38598;&#19979;&#36733;&#38142;&#25509;&#21040;&#21516;&#19968;&#36136;&#37327;&#30340;&#35270;&#39057;&#35266;&#30475;";
        case "zh-tw": return "1: &#38598;&#19979;&#36617;&#37832;&#25509;&#21040;&#21516;&#19968;&#36074;&#37327;&#30340;&#35222;&#38971;&#35264;&#30475;";
        case "ja": return "1: &#12480;&#12454;&#12531;&#12525;&#12540;&#12489;&#12522;&#12531;&#12463;&#12434;&#35373;&#23450;&#12377;&#12427;&#12398;&#38322;&#35239;&#12289;&#12499;&#12487;&#12458;&#12398;&#21697;&#36074;&#12392;&#21516;&#12376;";
        case "ko": return "1: &#49444;&#51221; &#45796;&#50868;&#47196;&#46300; &#47553;&#53356;&#47484; &#48380; &#48708;&#46356;&#50724;&#51032; &#54408;&#51656;&#51008; &#46041;&#51068;";
        case "de": return "1: Gesetzte Downloadverbindung zur gleichen Qualit&#228;t des gesehenen Videos";
        default:
        case "en": case "en-gb": return "1: Set download link to the same Quality of the viewed video";
        case "es": case "es-mx": return "1: Acoplamiento de la transferencia directa a la misma calidad del v&#237;deo visto";
        case "fr": return "1: Lien de t&#233;l&#233;chargement vers la vid&#233;o de m&#234;me qualit&#233; que celle affich&#233;";
        case "it": return "1: Impostare link per scaricare la stessa qualit&#224; dei video visualizzati";
        case "nl": return "1: Stel download link naar dezelfde kwaliteit van de video bekeken";
        case "pl": return "1: Ustaw link do pobierania takiej samej jako&#347;ci na ogl&#261;dany film wideo";
        case "pt": return "1: Liga&#231;&#227;o ajustada de transfer&#234;ncia &#224; mesma qualidade do v&#237;deo visto";
        case "ru": return "1: &#1059;&#1089;&#1090;&#1072;&#1085;&#1086;&#1074;&#1080;&#1090;&#1100; &#1089;&#1089;&#1099;&#1083;&#1082;&#1091; &#1085;&#1072; &#1090;&#1086;&#1090; &#1078;&#1077; &#1082;&#1072;&#1095;&#1077;&#1089;&#1090;&#1074;&#1072; &#1088;&#1072;&#1089;&#1089;&#1084;&#1072;&#1090;&#1088;&#1080;&#1074;&#1072;&#1077;&#1090;&#1089;&#1103; &#1074;&#1080;&#1076;&#1077;&#1086;";
        case "ar": return "1: &#1578;&#1581;&#1605;&#1610;&#1604; &#1606;&#1601;&#1587; &#1606;&#1608;&#1593;&#1610;&#1577; &#1605;&#1604;&#1601; &#1575;&#1604;&#1601;&#1610;&#1583;&#1610;&#1608; &#1575;&#1604;&#1581;&#1575;&#1604;&#1610;&#1607;";
    }
    case "qual2": switch (lang) {
        case "zh-cn": return "2: &#38598;&#19979;&#36733;&#38142;&#25509;&#21040;&#19968;&#20010;&#39640;&#21697;&#36136;&#30340;&#35270;&#39057;&#25991;&#20214;&#65288;&#30340;FLV&#25110;&#30340;MP4&#65289;";
        case "zh-tw": return "2: &#38598;&#19979;&#36617;&#37832;&#25509;&#21040;&#19968;&#20491;&#39640;&#21697;&#36074;&#30340;&#35222;&#38971;&#25991;&#20214;&#65288;&#30340;FLV&#25110;&#30340;MP4&#65289;";
        case "ja": return "2: &#39640;&#21697;&#36074;&#12398;&#12499;&#12487;&#12458;&#12501;&#12449;&#12452;&#12523;&#65288;FLV&#12398;&#12458;&#12524;&#12468;&#12531;&#12398;MP4&#65289;&#12395;&#35373;&#23450;&#12480;&#12454;&#12531;&#12525;&#12540;&#12489;&#12522;&#12531;&#12463;";
        case "ko": return "2: &#45458;&#51008; &#54408;&#51656;&#51032; &#48708;&#46356;&#50724; &#54028;&#51068; (&#45824;&#54620; FLV &#46608;&#45716;&#45716; MP4)&#47196; &#49444;&#51221; &#45796;&#50868;&#47196;&#46300; &#47553;&#53356;";
        case "de": return "2: Gesetzte Downloadverbindung zu einer videoakte der Qualit&#228;ts (FLV oder MP4)";
        default:
        case "en": case "en-gb": return "2: Set download link to a High Quality video file (FLV or MP4)";
        case "es": case "es-mx": return "2: Acoplamiento de la transferencia directa a un archivo video de la alta calidad (FLV o MP4)";
        case "fr": return "2: Lien de t&#233;l&#233;chargement vers la vid&#233;o en haute qualit&#233; (FLV ou MP4)";
        case "it": return "2: Impostare il download link ad un alta qualit&#224; di file video (FLV o MP4)";
        case "nl": return "2: Stel download link naar een High Quality video bestand (of MP4 FLV)";
        case "pl": return "2: Ustaw link do wysokiej jako&#347;ci plik&#243;w wideo (MP4 lub FLV)";
        case "pt": return "2: Liga&#231;&#227;o ajustada de transfer&#234;ncia a uma lima video da alta qualidade (FLV ou MP4)";
        case "ru": return "2: &#1059;&#1089;&#1090;&#1072;&#1085;&#1086;&#1074;&#1082;&#1072; &#1089;&#1077;&#1090;&#1080; &#1089;&#1074;&#1103;&#1079;&#1080; &#1089; &#1074;&#1099;&#1089;&#1086;&#1082;&#1080;&#1084; &#1082;&#1072;&#1095;&#1077;&#1089;&#1090;&#1074;&#1086;&#1084; &#1074;&#1080;&#1076;&#1077;&#1086; &#1092;&#1072;&#1081;&#1083;&#1086;&#1074; (FLV &#1080;&#1083;&#1080; MP4)";
        case "ar": return "2: &#1578;&#1581;&#1605;&#1610;&#1604; &#1580;&#1608;&#1583;&#1577; &#1593;&#1575;&#1604;&#1610;&#1577; &#1604;&#1605;&#1604;&#1601; &#1575;&#1604;&#1601;&#1610;&#1583;&#1610;&#1608; &#1576;&#1589;&#1610;&#1594;&#1577; (FLV &#1571;&#1608; MP4)";
    }
    case "qual3": switch (lang) {
        case "zh-cn": return "3: &#38598;&#19979;&#36733;&#38142;&#25509;&#21040;&#19968;&#20010;&#39640;&#21697;&#36136;&#30340;MP4&#35270;&#39057;&#25991;&#20214;";
        case "zh-tw": return "3: &#38598;&#19979;&#36617;&#37832;&#25509;&#21040;&#19968;&#20491;&#39640;&#21697;&#36074;&#30340;MP4&#35222;&#38971;&#25991;&#20214;";
        case "ja": return "3: &#12399;&#12289;&#39640;&#21697;&#36074;&#12398;&#12499;&#12487;&#12458;&#12434;&#35373;&#23450;&#12377;&#12427;&#12398;MP4&#12501;&#12449;&#12452;&#12523;&#12398;&#12480;&#12454;&#12531;&#12525;&#12540;&#12489;&#12522;&#12531;&#12463;";
        case "ko": return "3: a&#45716; MP4 &#44256;&#54408;&#51656; &#46041;&#50689;&#49345;&#51004;&#47196; &#49444;&#51221; &#54028;&#51068; &#45796;&#50868;&#47196;&#46300; &#47553;&#53356;";
        case "de": return "3: Gesetzte Downloadverbindung zu einer videoakte der Qualit&#228;ts MP4";
        default:
        case "en": case "en-gb": return "3: Set download link to a MP4 High Quality video file";
        case "es": case "es-mx": return "3: Acoplamiento de la transferencia directa a un archivo video de la alta calidad MP4";
        case "fr": return "3: Lien de t&#233;l&#233;chargement vers la vid&#233;o en MP4 de haute qualit&#233;";
        case "it": return "3: Impostare il download link a un MP4 alta qualit&#224; di file video";
        case "nl": return "3: Stel download link naar een MP4 High Quality video bestand";
        case "pl": return "3: Ustaw link do pobrania MP4 wysokiej jako&#347;ci plik&#243;w wideo";
        case "pt": return "3: Liga&#231;&#227;o ajustada de transfer&#234;ncia a uma lima video da alta qualidade MP4";
        case "ru": return "3: &#1059;&#1089;&#1090;&#1072;&#1085;&#1086;&#1074;&#1080;&#1090;&#1100; &#1089;&#1089;&#1099;&#1083;&#1082;&#1091; &#1085;&#1072; MP4 &#1074;&#1099;&#1089;&#1086;&#1082;&#1086;&#1075;&#1086; &#1082;&#1072;&#1095;&#1077;&#1089;&#1090;&#1074;&#1072; &#1074;&#1080;&#1076;&#1077;&#1086;-&#1092;&#1072;&#1081;&#1083;";
        case "ar": return "3: &#1578;&#1581;&#1605;&#1610;&#1604; &#1575;&#1604;&#1605;&#1604;&#1601; &#1576;&#1580;&#1608;&#1583;&#1577; &#1593;&#1575;&#1604;&#1610;&#1577; &#1576;&#1589;&#1610;&#1594;&#1577; MP4";
    }
    case "auto1": switch (lang) {
        case "zh-cn": return "1: &#25163;&#20876;";
        case "zh-tw": return "1: &#25163;&#20874;";
        case "ja": return "1: &#12510;&#12491;&#12517;&#12450;&#12523;";
        case "ko": return "1: &#47588;&#45684;&#50620;";
        case "de": return "1: Manueller Start";
        default:
        case "en": case "en-gb": return "1: Set Autoplay to OFF";
        case "es": case "es-mx": return "1: Comienzo manual";
        case "fr": return "1: D&#233;marrage manuel";
        case "it": return "1: Avviamento manuale";
        case "nl": return "1: Zet autoplay uit";
        case "pl": return "1: Podr&#281;cznik";
        case "pt": return "1: Arranque manual";
        case "ru": return "1: &#1056;&#1091;&#1082;&#1086;&#1074;&#1086;&#1076;&#1089;&#1090;&#1074;&#1086;";
        case "ar": return "1: &#1578;&#1588;&#1594;&#1610;&#1604; &#1578;&#1604;&#1602;&#1575;&#1574;&#1610; &#1610;&#1593;&#1605;&#1604;";
    }
    case "auto2": switch (lang) {
        default:
        case "en": case "en-gb": return "2: Set Autoplay to Buffering";
        case "fr": return "2: Mise en buffer";
    }
    case "auto3": switch (lang) {
        case "zh-cn": return "3: &#33258;&#21160;";
        case "zh-tw": return "3: &#33258;&#21205;";
        case "ja": return "3: &#33258;&#21205;&#36215;&#21205;";
        case "ko": return "3: &#51088;&#46041;";
        case "de": return "3: Automatischer Start";
        default:
        case "en": case "en-gb": return "3: Set Autoplay to ON";
        case "es": case "es-mx": return "3: Comienzo autom&#225;tico";
        case "fr": return "3: D&#233;marrage automatique";
        case "it": return "3: Avviamento automatico";
        case "nl": return "3: Zet autoplay aan";
        case "pl": return "3: automatyczne rozpocz&#281;cie";
        case "pt": return "3: Arranque autom&#225;tico";
        case "ru": return "3: &#1040;&#1074;&#1090;&#1086;&#1084;&#1072;&#1090;&#1080;&#1095;&#1077;&#1089;&#1082;&#1080;&#1081; &#1087;&#1091;&#1089;&#1082;";
        case "ar": return "3: &#1578;&#1588;&#1594;&#1610;&#1604; &#1578;&#1604;&#1602;&#1575;&#1574;&#1610; &#1604;&#1575;&#1610;&#1593;&#1605;&#1604;";
    }
  }
  return "";
}
function get_text_QS(lang,variable) {
  switch(variable) {
    case "link1": switch (lang) {
        case "zh-cn": return "&#26597;&#30475;&#20302;&#36136;&#37327; (flv)";
        case "zh-tw": return "&#26597;&#30475;&#20302;&#36074;&#37327; (flv)";
        case "ja": return "&#23550;&#35937;&#20302;&#21697;&#36074; (flv)";
        case "ko": return "&#51200;&#44032;&#50640; &#54408;&#51656;&#48372;&#44592; (flv)";
        case "de": return "Ansicht in niedrige Qualit&#228;t (flv)";
        default:
        case "en": case "en-gb": return "View in Low Quality (flv)";
        case "es": case "es-mx": return "Visi&#243;n en la baja calidad (flv)";
        case "fr": return "Voir en Basse Qualit&#233; (flv)";
        case "it": return "Visualizza in bassa qualit&#224; (flv)";
        case "nl": return "Bekijk in lage kwaliteit (flv)";
        case "pl": return "Widok w niskiej jako&#347;ci (flv)";
        case "pt": return "Vista na m&#225; qualidade (flv)";
        case "ru": return "&#1055;&#1086;&#1089;&#1084;&#1086;&#1090;&#1088;&#1077;&#1090;&#1100; &#1089; &#1085;&#1080;&#1079;&#1082;&#1080;&#1084; &#1082;&#1072;&#1095;&#1077;&#1089;&#1090;&#1074;&#1086;&#1084; (flv)";
        case "ar": return "&#1593;&#1585;&#1590; &#1580;&#1608;&#1583;&#1577; &#1605;&#1606;&#1582;&#1601;&#1590;&#1577; (flv)";
    }
    case "link2": switch (lang) {
        case "zh-cn": return "&#35266;&#39640;&#21697;&#36136; (flv)";
        case "zh-tw": return "&#35264;&#39640;&#21697;&#36074; (flv)";
        case "ja": return "&#39640;&#21697;&#36074;&#34920;&#31034; (flv)";
        case "ko": return "&#48372;&#44592;&#50640; &#54408;&#51656; &#45458;&#51008; (flv)";
        case "de": return "Ansicht in hoher Qualit&#228;t (flv)";
        default:
        case "en": case "en-gb": return "View in High Quality (flv)";
        case "es": case "es-mx": return "Visi&#243;n en la alta calidad (flv)";
        case "fr": return "Voir en Haute Qualit&#233; (flv)";
        case "it": return "Visualizza in alta qualit&#224; (flv)";
        case "nl": return "Bekijk in hoge kwaliteit (flv)";
        case "pl": return "Widok w wysokiej jako&#347;ci (flv)";
        case "pt": return "Vista na alta qualidade (flv)";
        case "ru": return "&#1055;&#1086;&#1089;&#1084;&#1086;&#1090;&#1088;&#1077;&#1090;&#1100; &#1089; &#1074;&#1099;&#1089;&#1086;&#1082;&#1080;&#1084; &#1082;&#1072;&#1095;&#1077;&#1089;&#1090;&#1074;&#1086;&#1084; (flv))";
        case "ar": return "&#1593;&#1585;&#1590; &#1580;&#1608;&#1583;&#1577; &#1593;&#1575;&#1604;&#1610;&#1607; (flv)";
    }
    case "link3": switch (lang) {
        case "zh-cn": return "&#35266;&#39640;&#21697;&#36136; (mp4)";
        case "zh-tw": return "&#35264;&#39640;&#21697;&#36074; (mp4)";
        case "ja": return "&#39640;&#21697;&#36074;&#34920;&#31034; (mp4)";
        case "ko": return "&#48372;&#44592;&#50640; &#54408;&#51656; &#45458;&#51008; (mp4)";
        case "de": return "Ansicht in hoher Qualit&#228;t (mp4)";
        default:
        case "en": case "en-gb": return "View in High Quality (mp4)";
        case "es": case "es-mx": return "Visi&#243;n en la alta calidad (mp4)";
        case "fr": return "Voir en Haute Qualit&#233; (mp4)";
        case "it": return "Visualizza in alta qualit&#224; (mp4)";
        case "nl": return "Bekijk in hoge kwaliteit (mp4)";
        case "pl": return "Widok w wysokiej jako&#347;ci (mp4)";
        case "pt": return "Vista na alta qualidade (mp4)";
        case "ru": return "&#1055;&#1086;&#1089;&#1084;&#1086;&#1090;&#1088;&#1077;&#1090;&#1100; &#1089; &#1074;&#1099;&#1089;&#1086;&#1082;&#1080;&#1084; &#1082;&#1072;&#1095;&#1077;&#1089;&#1090;&#1074;&#1086;&#1084; (mp4)";
        case "ar": return "&#1593;&#1585;&#1590; &#1580;&#1608;&#1583;&#1577; &#1593;&#1575;&#1604;&#1610;&#1607; (mp4)";
    }
    case "link4": switch (lang) {
        case "zh-cn": return "&#26816;&#35270;HD&#36136;&#37327; (mp4)";
        case "zh-tw": return "&#27298;&#35222;HD&#36074;&#37327; (mp4)";
        case "ja": return "HD&#12391;&#12398;&#34920;&#31034;&#21697;&#36074; (mp4)";
        case "ko": return "HD&#50640;&#49436; &#54408;&#51656; &#54217;&#44032;&#48372;&#44592; (mp4)";
        case "de": return "Ansicht in HD-Qualit&#228;t (mp4)";
        default:
        case "en": case "en-gb": return "View in HD Quality (mp4)";
        case "es": case "es-mx": return "Visi&#243;n en la HD calidad (mp4)";
        case "fr": return "Voir en Qualit&#233; HD (mp4)";
        case "it": return "Visualizza in qualit&#224; HD (mp4)";
        case "nl": return "Bekijk in HD kwaliteit (mp4)";
        case "pl": return "Wy&#347;wietl w jako&#347;ci HD (mp4)";
        case "pt": return "Ver na qualidade HD (mp4)";
        case "ru": return "&#1055;&#1086;&#1089;&#1084;&#1086;&#1090;&#1088;&#1077;&#1090;&#1100; &#1074; HD &#1082;&#1072;&#1095;&#1077;&#1089;&#1090;&#1074;&#1072; (mp4)";
        case "ar": return "&#1585;&#1571;&#1610; &#1601;&#1610; &#1606;&#1608;&#1593;&#1610;&#1577; HD (mp4)"
    }
  }
  return "";
}
function get_text_MC(lang,variable) {
  switch(variable) {
    case "stepback": switch (lang) {
        case "zh-cn": return "&#36864;&#21518;&#19968;&#27493;";
        case "zh-tw": return "&#36864;&#24460;&#19968;&#27493;";
        case "ja": return "&#24460;&#36864;";
        case "ko": return "&#46244;&#47196; &#47932;&#47084;&#49436;";
        case "de": return "Schritt zur&#252;ck";
        default:
        case "en": case "en-gb": return "Step back";
        case "es": case "es-mx": return "Paso atr&#225;s";
        case "fr": return "Pas arri&#232;re";
        case "it": return "Passo indietro";
        case "nl": return "Stap terug";
        case "pl": return "Krok wstecz";
        case "pt": return "Passo para tr&#225;s";
        case "ru": return "&#1096;&#1072;&#1075; &#1085;&#1072;&#1079;&#1072;&#1076;";
        case "ar": return "&#1582;&#1591;&#1608;&#1577; &#1573;&#1604;&#1609; &#1575;&#1604;&#1608;&#1585;&#1575;&#1569;";
    }
    case "stop": switch (lang) {
        case "zh-cn": return "&#20572;&#27490;";
        case "zh-tw": return "&#20572;&#27490;";
        case "ja": return "&#20572;&#27490;&#12377;&#12427;";
        case "ko": return "&#47688;&#52628;&#45796;";
        case "de": return "Erlass";
        default:
        case "en": case "en-gb": return "Stop";
        case "es": case "es-mx": return "Paro";
        case "fr": return "Arr&#234;t";
        case "it": return "Arresto";
        case "nl": return "Stop";
        case "pl": return "Zatrzyma&#263;";
        case "pt": return "Ac&#243;rd&#227;o";
        case "ru": return "&#1054;&#1089;&#1090;&#1072;&#1085;&#1086;&#1074;&#1082;&#1072;";
        case "ar": return "&#1578;&#1608;&#1602;&#1601;";
    }
    case "step": switch (lang) {
        case "zh-cn": return "&#21521;&#21069;&#36808;&#20986;&#30340;&#19968;&#27493;";
        case "zh-tw": return "&#21521;&#21069;&#36993;&#20986;&#30340;&#19968;&#27493;";
        case "ja": return "&#19968;&#27497;&#21069;&#36914;";
        case "ko": return "&#50526;&#51004;&#47196;";
        case "de": return "Schritt nach vorn";
        default:
        case "en": case "en-gb": return "Step forward";
        case "es": case "es-mx": return "Paso adelante";
        case "fr": return "Pas avant";
        case "it": return "Passo in avanti";
        case "nl": return "Stap voorwaarts";
        case "pl": return "Krok naprz&#243;d";
        case "pt": return "Passo em frente";
        case "ru": return "&#1096;&#1072;&#1075; &#1074;&#1087;&#1077;&#1088;&#1077;&#1076;";
        case "ar": return "&#1582;&#1591;&#1608;&#1577; &#1573;&#1604;&#1609; &#1575;&#1604;&#1571;&#1605;&#1575;&#1605;";
    }
    case "play": switch (lang) {
        case "zh-cn": return "&#35835; / &#37325;&#26032;&#21551;&#21160;";
        case "zh-tw": return "&#35712; / &#37325;&#26032;&#21855;&#21205;";
        case "ja": return "&#35501;&#21462;&#12426; / &#20877;&#36215;&#21205;";
        case "ko": return "&#51069;&#44592; / &#45796;&#49884; &#49884;&#51089;";
        case "de": return "Lesen / ankurbeln";
        default:
        case "en": case "en-gb": return "Play / Revive";
        case "es": case "es-mx": return "Leer / Reactivar";
        case "fr": return "Lire / Relancer";
        case "it": return "Giochi / Faccia rivivere";
        case "nl": return "Lees / Restart";
        case "pl": return "Odczyt / Uruchom";
        case "pt": return "Ler / relan&#231;ar";
        case "ru": return "&#1055;&#1088;&#1086;&#1095;&#1080;&#1090;&#1072;&#1090;&#1100; / &#1055;&#1077;&#1088;&#1077;&#1079;&#1072;&#1075;&#1088;&#1091;&#1079;&#1082;&#1072;";
        case "ar": return "&#1578;&#1588;&#1594;&#1610;&#1604; / &#1575;&#1587;&#1578;&#1574;&#1606;&#1575;&#1601;";
    }
    case "pause": switch (lang) {
        case "zh-cn": return "&#20241;&#24687;";
        case "zh-tw": return "&#20241;&#24687;";
        case "ja": return "&#22730;&#12377;";
        case "ko": return "&#55092;&#49885;";
        case "de": return "Pause";
        default:
        case "en": case "en-gb": return "Pause";
        case "es": case "es-mx": return "Pausa";
        case "fr": return "Pause";
        case "it": return "Pausa";
        case "nl": return "Pauze";
        case "pl": return "Z&#322;ama&#263;";
        case "pt": return "Pausa";
        case "ru": return "&#1055;&#1077;&#1088;&#1077;&#1088;&#1099;&#1074;";
        case "ar": return "&#1575;&#1610;&#1602;&#1575;&#1601; &#1605;&#1572;&#1602;&#1578;";
    }
    case "begin": switch (lang) {
        case "zh-cn": return "&#24320;&#22987;";
        case "zh-tw": return "&#38283;&#22987;";
        case "ja": return "&#38283;&#22987;&#12377;&#12427;";
        case "ko": return "&#49884;&#51089;";
        case "de": return "Beginn";
        default:
        case "en": case "en-gb": return "Begin";
        case "es": case "es-mx": return "Comience";
        case "fr": return "D&#233;but";
        case "it": return "Cominci";
        case "nl": return "Beginnen";
        case "pl": return "Zacz&#261;&#263;";
        case "pt": return "Comece";
        case "ru": return "&#1053;&#1072;&#1095;&#1072;&#1090;&#1100;";
        case "ar": return "&#1610;&#1576;&#1583;&#1571;";
    }
    case "loop": switch (lang) {
        case "zh-cn": return "&#29615;";
        case "zh-tw": return "&#29872;";
        case "ja": return "&#12523;&#12540;&#12503;";
        case "ko": return "&#47336;&#54532;";
        case "de": return "Schleife";
        default:
        case "en": case "en-gb": return "Loop";
        case "es": case "es-mx": return "Lazo";
        case "fr": return "En boucle";
        case "it": return "Ciclo";
        case "nl": return "Loop";
        case "pl": return "P&#281;tla";
        case "pt": return "La&#231;o";
        case "ru": return "&#1055;&#1077;&#1090;&#1083;&#1103;";
        case "ar": return "&#1575;&#1604;&#1578;&#1601;&#1575;&#1601;";
    }
    case "rewind": switch (lang) {
        case "zh-cn": return "&#20498;&#24102;";
        case "zh-tw": return "&#20498;&#24118;";
        case "ja": return "&#24059;&#12365;&#25147;&#12375;";
        case "ko": return "&#46104;&#44048;&#44592;";
        case "de": return "R&#252;ckspulen";
        default:
        case "en": case "en-gb": return "Rewind";
        case "es": case "es-mx": return "Rebobinado";
        case "fr": return "Retour arri&#232;re";
        case "it": return "Riavvolgere";
        case "nl": return "Rewind";
        case "pl": return "Rewind";
        case "pt": return "Rebobina&#231;&#227;o";
        case "ru": return "&#1055;&#1077;&#1088;&#1077;&#1084;&#1086;&#1090;&#1082;&#1072;";
        case "ar": return "&#1585;&#1580;&#1608;&#1593;";
    }
    case "end": switch (lang) {
        case "zh-cn": return "&#23436;";
        case "zh-tw": return "&#23436;";
        case "ja": return "&#32066;&#12431;&#12426;";
        case "ko": return "&#45149;";
        case "de": return "Ende";
        default:
        case "en": case "en-gb": return "End";
        case "es": case "es-mx": return "Final";
        case "fr": return "Fin";
        case "it": return "Fine";
        case "nl": return "Eindigen";
        case "pl": return "Koniec";
        case "pt": return "Fim";
        case "ru": return "&#1050;&#1086;&#1085;&#1077;&#1094;";
        case "ar": return "&#1575;&#1604;&#1606;&#1607;&#1575;&#1610;&#1577;";
    }
    case "kill": switch (lang) {
        case "zh-cn": return "&#21452;&#20987;&#26432;&#23475;&#32593;&#27969;&#21644;&#25773;&#25918;&#22120;";
        case "zh-tw": return "&#38617;&#25802;&#27578;&#23475;&#32178;&#27969;&#21644;&#25773;&#25918;&#22120;";
        case "ja": return "&#12480;&#12502;&#12523;&#12463;&#12522;&#12483;&#12463;&#12377;&#12427;&#12392;&#12289; NetStream&#12392;&#12399;&#12289;&#12503;&#12524;&#12540;&#12516;&#12540;&#12434;&#27578;&#12377;&#12383;&#12417;&#12395;";
        case "ko": return "NetStream&#51012; &#45908;&#48660; &#53364;&#47533;&#54616;&#44256; &#54540;&#47112;&#51060;&#50612;&#47484; &#51453;&#51060;&#44256;";
        case "de": return "Doppeltes Klicken, zum des NetStream und des Spielers zu t&#246;ten";
        default:
        case "en": case "en-gb": return "Double click to kill the NetStream and the player";
        case "es": case "es-mx": return "Tecleo doble para matar el NetStream y al jugador";
        case "fr": return "Double click pour stopper le NetStream et le lecteur Vid&#233;o";
        case "it": return "Fare doppio clic su di uccidere il NetStream e il giocatore";
        case "nl": return "Dubbelklik tot de dood van de NetStream en de speler";
        case "pl": return "Dwukrotnie kliknij, aby zabi&#263; NetStream i odtwarzacz";
        case "pt": return "Clique dobro para matar o NetStream e o jogador";
        case "ru": return "&#1044;&#1074;&#1072;&#1078;&#1076;&#1099; &#1097;&#1077;&#1083;&#1082;&#1085;&#1080;&#1090;&#1077; &#1091;&#1073;&#1080;&#1090;&#1100; NetStream &#1080; &#1080;&#1075;&#1088;&#1086;&#1082;";
        case "ar": return "&#1575;&#1606;&#1602;&#1585; &#1606;&#1602;&#1585;&#1607; &#1605;&#1586;&#1583;&#1608;&#1580;&#1607; &#1604;&#1575;&#1610;&#1602;&#1575;&#1601; &#1575;&#1604;&#1593;&#1585;&#1590;";
    }
    case "embed": switch (lang) {
        case "zh-cn": return "Embed &#38142;&#25509;";
        case "zh-tw": return "Embed &#37832;&#25509;";
        case "ja": return "Embed &#12522;&#12531;&#12463;";
        case "ko": return "Embed &#47553;&#53356;";
        case "de": return "Embed Verbindung";
        default:
        case "en": case "en-gb": return "Embed Link";
        case "es": case "es-mx": return "Acoplamiento de Embed";
        case "fr": return "Lien Embed";
        case "it": return "Collegamento di Embed";
        case "nl": return "Embed Koppelen";
        case "pl": return "Embed &#321;&#261;cze";
        case "pt": return "Ligação de Embed";
        case "ru": return "Embed &#1057;&#1089;&#1099;&#1083;&#1082;&#1072;";
        case "ar": return "&#1601;&#1578;&#1581; &#1601;&#1610; &#1604;&#1587;&#1575;&#1606; &#1580;&#1583;&#1610;&#1583;";
    }
    case "fscr": switch (lang) {
        case "zh-cn": return "&#20840;&#23631;&#38142;&#25509;";
        case "zh-tw": return "&#20840;&#23631;&#37832;&#25509;";
        case "ja": return "&#12501;&#12523;&#12473;&#12463;&#12522;&#12540;&#12531;&#12398;&#12522;&#12531;&#12463;";
        case "ko": return "&#51204;&#52404; &#47553;&#53356;";
        case "de": return "Auf dem ganzen Bildschirmverbindung";
        default:
        case "en": case "en-gb": return "Fullscreen Link";
        case "es": case "es-mx": return "Acoplamiento de plena pantalla";
        case "fr": return "Lien plein &#233;cran";
        case "it": return "Collegamento a schermo pieno";
        case "nl": return "Fullscreen Link";
        case "pl": return "Link do fullscreen";
        case "pt": return "Liga&#231;&#227;o da tela cheia";
        case "ru": return "Fullscreen &#1089;&#1089;&#1099;&#1083;&#1082;&#1072;";
        case "ar": return "&#1605;&#1604;&#1569; &#1575;&#1604;&#1588;&#1575;&#1588;&#1577;";
    }
  }
  return "";
}

function get_text_Updater(lang,variable) {
  switch(variable) {
    case "disa": switch (lang) {
        default:
        case "en": case "en-gb": return "Updater Is Now Disabled";
        case "fr": return "La mise à jour est maintenant désactivé";
    }
    case "enab": switch (lang) {
        default:
        case "en": case "en-gb": return "Updater Is Now Enabled";
        case "fr": return "La mise à jour est maintenant activé";
    }
    case "foun": switch (lang) {
        default:
        case "en": case "en-gb": return "New Update Found";
        case "fr": return "Nouvelle mise &#224; jour trouv&#233;e";
    }
    case "dnow": switch (lang) {
        default:
        case "en": case "en-gb": return "Visit&nbsp;Install&nbsp;Page";
        case "fr": return "Visiter&nbsp;la&nbsp;page&nbsp;d'installation";
    }
    case "dlat": switch (lang) {
        default:
        case "en": case "en-gb": return "Later";
        case "fr": return "Plus&nbsp;tard";
    }
  }
  return "";
}


function test_lang(lang) {
  switch(lang) {
    case "zh-cn": case "zh-tw": case "ja": case "ko": case "de":
    case "en": case "en-gb": case "es": case "es-mx": case "fr":
    case "it": case "nl": case "pl": case "pt": case "ru":
    case "cs": case "sv": // Tchèque & Suédois
    case "ar": case "www": return true;
  }
  return false;
}

//***************************************** Page settings ************************************************//
// Get youtube locale (for languages support)
function get_page_lang() {
  //== Use Mozilla browser language when youtube don't support it...
  var lang=String.substr(window.navigator.language,0,2).toLowerCase();
  if(lang=="ar") { // Arabic (ar)
    return lang;
  } 

  //== via URL
  var language=window.location.search.match(/[?&]hl=([^(\&|$)]*)/i);
  if(language!=null) {
    lang=language[1].replace(/_/,"-").toLowerCase();
    if(test_lang(lang)) {
	  GM_setValue("Youtube_Download_Locale_Setting",lang);
      return lang;
    }
    lang=String.substr(lang,0,2);
    if(test_lang(lang)) {
	  GM_setValue("Youtube_Download_Locale_Setting",lang);
      return lang;
    }
  }

  //== via watch page
  var language=unsafeWindow.ytLocale;
  if(isDefined(language)) {
    lang=language.replace(/_/,"-").toLowerCase();
    if(test_lang(lang)) {
      GM_setValue("Youtube_Download_Locale_Setting",lang);
      return lang;
    }
    lang=String.substr(lang,0,2);
    if(test_lang(lang)) {
      GM_setValue("Youtube_Download_Locale_Setting",lang);
      return lang;
    }
  }

  //== via old watch page setting
  lang=GM_getValue("Youtube_Download_Locale_Setting","www");
  return lang;
}

function get_page_fmt() {
  var selected_fmt=window.location.search.match(/[?&]fmt=(\d*)/i);
  if(selected_fmt==null) { selected_fmt=0; } else { selected_fmt=selected_fmt[1]; }
  if(!(isPositiveInteger(selected_fmt))) { selected_fmt=0; }
  return(selected_fmt);
}

function check_on_youtube() {
  if(window.location.host.match(/^\w+?\.youtube\.\w+$/i)) { return 1; }
  return 0;
}
function check_on_watchpage() {
  if(window.location.pathname.match(/^\/watch$/i)) { return 1; }
  return 0;
}
function check_on_youtubewatchpage() {
  return check_on_youtube() && check_on_watchpage();
}
function get_PlayerEmbed_element() {
  var playerEmbed = document.getElementById(YT_PLAYER_EMBED);
  if(playerEmbed) { return playerEmbed; }
  var wpd = document.getElementById(WATCH_PLAYER_DIV);
  if(wpd) {
    var temp=null;
    try { temp=wpd.getElementsByTagName("embed"); } catch(err) { temp=null; }
    if(temp && temp[0]) { temp[0].setAttribute('id',YT_PLAYER_EMBED); return temp[0]; }
  }
  return null;
}

//************************************************************
//***** Download Link ****************************************
//************************************************************
function clean_filename(filename) {
  // Clean filename (UNICODE Method)
  //filename = filename.replace(/\ /g,String.fromCharCode(65279));
  filename = filename.replace(/\:/g,String.fromCharCode(65306));
  filename = filename.replace(/\\/g,String.fromCharCode(65340));
  filename = filename.replace(/\//g,String.fromCharCode(65295));
  filename = filename.replace(/\</g,String.fromCharCode(65308));
  filename = filename.replace(/\>/g,String.fromCharCode(65310));
  filename = filename.replace(/\*/g,String.fromCharCode(65290));
  filename = filename.replace(/\?/g,String.fromCharCode(65311));
  filename = filename.replace(/\"/g,String.fromCharCode(65282));
  filename = filename.replace(/\|/g,String.fromCharCode(65372));
  // Clean filename (Underline Method)
  //filename = filename.replace(/[\:\\\/\<\>\?\*\"\|]/g, "_");
  return filename;
}

function get_clean_flashvars(flashvars) {
  if(CLEAN_FLASHVARS<=0) { return flashvars; }

  flashvars=flashvars+'&';
  var res; var res_annotations; var res_subtitles; var newfv='';
  do {
    res=flashvars.match(/^([^=]+?)\=([^\&]*?)\&(.*?)$/i);
    if(!res) { break; }
    var variable=res[1];
    var value=res[2];
    flashvars=res[3];
    if(DISABLE_ANNOTATIONS>0) { res_annotations=false; } else { res_annotations=variable.match(/^(iv_module|iv_storage_server)$/i); }
    if(DISABLE_SUBTITLES>0) { res_subtitles=false; } else { res_subtitles=variable.match(/^(subtitle_module|ttsurl)$/i); }
    res=variable.match(/^(BASE_YT_URL|rel|vq|ftm_map|video_id|t|sk|hl|fs|playnext|enablejsapi|autoplay)$/i)
    if(res || res_annotations || res_subtitles) {
      if(newfv!='') newfv+='&';
      newfv+=variable+'='+value;
    }
  } while(true);

  return newfv;
}

function add_ext(filename,fmt) {
  if(fmt==13 || fmt==17) { return(filename+".3gp"); }
  if(fmt==18 || fmt==22) { return(filename+".mp4"); }
  return(filename+".flv");
}

function url_fmt(fmt) {
  if(fmt==0) { return(""); }
  return("&fmt="+fmt);
}

function get_fmt_array(flashvars) {
  var fmt_array=[]; fmt_array[0]=true;
  if(!flashvars) { return fmt_array; }
  var fmt_map = flashvars.match(/fmt_map\=([^(\&|$)]*)/i);
  if(!fmt_map) { return fmt_array; }
  if(fmt_map[1]=='') { return fmt_array; }
  fmt_array[0]=false;
  fmt_map = fmt_map[1]+',';
  while(fmt_map=fmt_map.match(/^(\d+)[^,]*,(.*)$/)) {
    fmt_array[fmt_map[1]]=true;
    fmt_map=fmt_map[2];
  }
  return fmt_array;
}

function get_dl_fmt(fmt,flashvars,quality_setting) {
  var wide=(unsafeWindow.isWidescreen==true);
  var HDAvailable=(unsafeWindow.isHDAvailable==true);
  var fmt_first = flashvars.match(/fmt_map\=(\d+)/i);
  if(fmt_first) { fmt_first=fmt_first[1]; } else { fmt_first=0; }
  var fmt_array=get_fmt_array(flashvars);
  var dl_fmt=fmt;
  switch(quality_setting) {
    case 1:
      if(fmt_array[ 0]) { dl_fmt= 0; } // If no fmt_map, then the displayed video is LQ-FLV1
      if(fmt_array[ 5]) { dl_fmt= 5; }
      if(fmt_array[34]) { dl_fmt=34; } // fmt_map=34 is the new default
      break;
    case 2:
      dl_fmt=fmt_first; // Set the quality to the first one detected in the fmt_map
      if(HDAvailable || fmt_array[22]) { dl_fmt=22; } // Set to HD if available
      break;
    case 3:
      dl_fmt=18; // Default -> Set HQ-MPG4
      if((fmt==22) && (!fmt_array[22])) { dl_fmt=18; } // No HD-MPG4 -> Set HQ-MPG4
      if((fmt==18) && (!fmt_array[18])) { dl_fmt=FMT_HIGH_QUALITY_FLV; } // No HQ-MPG4 -> Set HQ-FLV1
      if(fmt_array[22] || HDAvailable)  { dl_fmt=22; } // HD Available -> Set HD-MPG4
      break;
  }
  return dl_fmt;
}

function add_dl_qual_links(page_lang, selected_fmt) {
  var wvt = document.getElementById(WATCH_TITLE_DIV);
  if(!(wvt)) { show_alert('Download Link Disabled : "'+WATCH_TITLE_DIV+'" not found'); return; }
  var playerEmbed = get_PlayerEmbed_element();
  var flashvars='';
  if(playerEmbed) { // Get flashvars from the embed video
    flashvars = playerEmbed.getAttribute('flashvars');
  } else { // Get flashvars from the fullscreen link
    flashvars = get_fullscreenURL();
  }
  if(!flashvars) { show_alert('Download Link Disabled : "flashvars" not found'); return; }

  var Options_title = HtmlUnicodeDecode(get_text_DL(page_lang,"omenu"));

  var t_id      = flashvars.match(/\&t=([^(\&|$)]*)/i)[1];
  var video_id  = flashvars.match(/video_id=([^(\&|$)]*)/i)[1];
  var video_url = window.location.protocol+'//'+window.location.host+'/get_video?video_id='+video_id+'&t='+t_id;

  // Retrieve fmt
  var download_fmt = get_dl_fmt(selected_fmt,flashvars,GM_getValue("Youtube_Download_Quality_Setting",2));

  // === Add the download link and the filename ready to copy
  // Retrieve filename
  var filename = clean_filename(wvt.getElementsByTagName("h1")[0].textContent);
  if(filename.length<1) {filename="video";}

  // Getting BackgroundColor and BorderColor
  var title_bg_color="#EEEEEE";
  var title_border_color="#CCCCCC";
  var wcvd = document.getElementById(WATCH_VIDEO_INFO);
  if (wcvd) {
    title_bg_color=window.getComputedStyle(wcvd, null).backgroundColor;
    title_border_color=window.getComputedStyle(wcvd, null).borderTopColor;
  }

  // Insert the new element code
  var newElement = document.createElement('div');
  newElement.setAttribute('style','margin:6px 0 6px 0; padding:3px 2px; border: 1px solid transparent');
  newElement.style.backgroundColor=title_bg_color;
  newElement.style.borderColor=title_border_color;
  var newElement1 = document.createElement('div');
  newElement1.setAttribute('style','position:absolute');
  newElement.appendChild(newElement1);
  var newElement2 = document.createElement('table');
  //newElement2.setAttribute('class','vListBox');
  newElement2.setAttribute('style','width:100%; height:18px; padding:0px');
  var newElement2tr = document.createElement('tr');
  var newElement2td1 = document.createElement('td');
  newElement2td1.setAttribute('style','width:18px; padding-left:2px;');
  newElement2td1.setAttribute('lang','fr');
  var newElement2td1Div = document.createElement('div');
  newElement2td1Div.setAttribute('title',Options_title);
  newElement2td1Div.setAttribute('style','line-height:18px;font-size:18px;cursor:pointer; color:'+COLOR_DL_OPTIONS_TEXT+' !important; background:'+COLOR_DL_OPTIONS_BACKGROUND+' !important; border: 1px solid '+COLOR_DL_OPTIONS_BORDER+' !important; margin:-2px;');
  newElement2td1Div.textContent=String.fromCharCode(10070);
  user_select(newElement2td1,'none');
  newElement2td1.appendChild(newElement2td1Div);
  newElement2tr.appendChild(newElement2td1);
  var newElement2td2 = document.createElement('td');
  newElement2td2.setAttribute('style','width:auto; padding:0 3px 0 5px; white-space:nowrap;');
  var newElement2td2A = document.createElement('a');
  newElement2td2A.setAttribute('target','_blank');
  newElement2td2A.setAttribute('class','hLink');
  newElement2td2A.setAttribute('title',filename);
  newElement2td2A.setAttribute('href',video_url+url_fmt(download_fmt));
  newElement2td2A.textContent=HtmlUnicodeDecode(get_text_DL(page_lang,"dlink"));
  newElement2td2.appendChild(newElement2td2A);
  user_select(newElement2td2,'none');
  newElement2tr.appendChild(newElement2td2);
  var newElement2td3 = document.createElement('td');
  newElement2td3.setAttribute('style','width:100%;');
  var newElement2td3Div = document.createElement('div');
  var newElement2td3Input = document.createElement('input');
  newElement2td3Input.setAttribute('style','border:0; width:500px; background:inherit !important; color:inherit !important;');
  newElement2td3Input.setAttribute('type','text');
  newElement2td3Input.setAttribute('readonly','readonly');
  newElement2td3Input.setAttribute('onClick','this.focus();this.select();');
  newElement2td3Input.setAttribute('value',add_ext(filename,download_fmt));
  //user_select(newElement2td3Input,'all');
  newElement2td3Div.appendChild(newElement2td3Input);
  newElement2td3.appendChild(newElement2td3Div);
  newElement2tr.appendChild(newElement2td3);
  newElement2.appendChild(newElement2tr);
  newElement.appendChild(newElement2);
  wvt.parentNode.insertBefore(newElement, wvt);
  // Resize the inputbox
  newElement2td3Input.style.width=newElement2td3Input.parentNode.clientWidth+"px";

  // Hiding the title
  if (ENABLE_TITLE_HIDING) { wvt.style.display = 'none'; }

  return Array(newElement1,newElement2td1);
}

function set_quality(quality, download_link_table, selected_fmt) {
  // Set new quality value
  GM_setValue("Youtube_Download_Quality_Setting",quality);

  // Retrieve fmt
  var download_fmt=0;
  var playerEmbed = get_PlayerEmbed_element();
  var flashvars='';
  if(playerEmbed) { // Get flashvars from the embed video
    flashvars = playerEmbed.getAttribute('flashvars');
  } else { // Get flashvars from the fullscreen link
    flashvars = get_fullscreenURL();
  }
  if(flashvars) {
    download_fmt = get_dl_fmt(selected_fmt,flashvars,quality);
  }

  // Change download link
  var linkdl = download_link_table.getElementsByTagName('a')[0];
  if (linkdl) {
    var linktext = linkdl.href.replace(/(\&?fmt\=\d+)/gi,"");
    linkdl.href=linktext+url_fmt(download_fmt);
  }

  // Change filename
  var YDF = download_link_table.getElementsByTagName('input')[0];
  if (YDF) {
    var filename= YDF.value.match(/^(.*)\.[\w\d]{3,4}$/);
    if(filename!=null) { YDF.value=add_ext(filename[1],download_fmt); }
  }
}

function menu_quality(quality_menu, quality) {
  // Change the position of the ">" in the menu box and close it
  if(quality_menu) {
    var div_Elem=quality_menu.getElementsByTagName("div");
    div_Elem[0].style.visibility="hidden";
    div_Elem[1].style.visibility="hidden";
    div_Elem[2].style.visibility="hidden";
    div_Elem[quality-1].style.visibility="visible";
  }
}

function menu_autoplay(autoplay_menu, select) {
  // Change the position of the ">" in the menu box and close it
  if(autoplay_menu) {
    var div_Elem=autoplay_menu.getElementsByTagName("div");
    div_Elem[0].style.visibility="hidden";
    div_Elem[1].style.visibility="hidden";
    div_Elem[2].style.visibility="hidden";
    div_Elem[select].style.visibility="visible";
  }
}

function event_setQuality(quality_select, selected_fmt) {
  var quality=quality_select.value;
  var quality_menu=quality_select.parentNode;
  switch (quality) {
    case 1: case 2: case 3:
      menu_quality(quality_menu, quality);
      set_quality(quality, quality_menu.parentNode.parentNode.nextSibling, selected_fmt);
      quality_menu.parentNode.style.display="none";
  }
}

function event_autoplay(autoplay_select) {
  var select=autoplay_select.value;
  var autoplay_menu=autoplay_select.parentNode;
  switch (select) {
    case 0: case 1: case 2:
      menu_autoplay(autoplay_menu, select);
      GM_setValue("Youtube_Download_Autoplay_Setting",select);
      autoplay_menu.parentNode.style.display="none";
  }
}

function make_options_menu(page_lang, selected_fmt, posMenuelem, OpenMenuElem) {
  if(posMenuelem && OpenMenuElem) {
    //== Make a menubox for Quality setting
    var MenuElem = document.createElement('div');
    MenuElem.setAttribute("style", "display:none; position: absolute; z-index: 99; margin:0; padding:0; width: 890px");

    var arrow = document.createElement('div')
    arrow.setAttribute('style','float:left; width:1em; font-weight:bold; color:'+COLOR_DL_POPUP_ARROW+' !important;');
    arrow.textContent='>';

    var u1_Elem = document.createElement('ul');
    u1_Elem.setAttribute("style","float:left; list-style-type:none; cursor:pointer; margin:1px; padding:0; border: 1px solid "+COLOR_DL_POPUP_BORDER+" !important; background-color: "+COLOR_DL_POPUP_BG_BLUE_OUT+";width:540px;");
    var li_Elem1=new Array();
    for(var h=0;h<=2;h++) {
      li_Elem1[h] = document.createElement('li');
      li_Elem1[h].setAttribute("style","margin:0; padding:5px; color:"+COLOR_DL_POPUP_TEXT+" !important;");
      li_Elem1[h].appendChild(arrow.cloneNode(true));
      li_Elem1[h].appendChild(document.createTextNode(HtmlUnicodeDecode(get_text_DL(page_lang,"qual"+(h+1)))));
      li_Elem1[h].addEventListener('mouseover' , function() { this.style.backgroundColor=COLOR_DL_POPUP_BG_BLUE_IN; }, true);
      li_Elem1[h].addEventListener('mouseout'  , function() { this.style.backgroundColor=""; }, true);
      li_Elem1[h].setAttribute('value',h+1);
      li_Elem1[h].addEventListener('click'     , function() { event_setQuality(this, selected_fmt); }, true);
      u1_Elem.appendChild(li_Elem1[h]);
    }
    MenuElem.appendChild(u1_Elem);

    //== Make a menubox for autostart
    var u2_Elem = document.createElement('ul');
    u2_Elem.setAttribute("style","float:left; list-style-type:none; cursor:pointer; margin:1px; padding:0; border: 1px solid "+COLOR_DL_POPUP_BORDER+" !important; background-color: "+COLOR_DL_POPUP_BG_RED_OUT+"; width:340px;");
    var li_Elem2=new Array();
    for(var h=0;h<=2;h++) {
      li_Elem2[h] = document.createElement('li');
      li_Elem2[h].setAttribute("style","margin:0; padding:5px; color:"+COLOR_DL_POPUP_TEXT+" !important;");
      if(h<2) { li_Elem2[h].appendChild(arrow.cloneNode(true)); } else { li_Elem2[h].appendChild(arrow); }
      li_Elem2[h].appendChild(document.createTextNode(HtmlUnicodeDecode(get_text_DL(page_lang,"auto"+(h+1)))));
      li_Elem2[h].addEventListener('mouseover' , function() { this.style.backgroundColor=COLOR_DL_POPUP_BG_RED_IN; }, true);
      li_Elem2[h].addEventListener('mouseout'  , function() { this.style.backgroundColor=""; }, true);
      li_Elem2[h].setAttribute('value',h);
      li_Elem2[h].addEventListener('click'     , function() { event_autoplay(this); }, true);
      u2_Elem.appendChild(li_Elem2[h]);
    }
    MenuElem.appendChild(u2_Elem);

    // Select position of the menubox on top of the button
    user_select(MenuElem,'none');
    posMenuelem.appendChild(MenuElem);
    MenuElem.style.left = "-4px";
    MenuElem.style.top  = (-2-getDisplayHeight(MenuElem))+"px";

    //== Make the openbutton to link to the menubox (with display update of the autoplay setting)
    OpenMenuElem.addEventListener('click', function() { menu_autoplay(u2_Elem, GM_getValue("Youtube_Download_Autoplay_Setting",2)); swap_display(MenuElem); }, true);

    // Update the menubox from the setting
    menu_quality (u1_Elem, GM_getValue("Youtube_Download_Quality_Setting" ,2));
    menu_autoplay(u2_Elem, GM_getValue("Youtube_Download_Autoplay_Setting",2));
  }
}

//** === Download Link === **//
function add_download_link(page_lang, selected_fmt) {
  if(check_on_youtubewatchpage()) {
    els=add_dl_qual_links(page_lang, selected_fmt);
    if(els) { make_options_menu(page_lang, selected_fmt, els[0], els[1]); }
  }
}

//************************************************************
//***** Quality Selector *************************************
//************************************************************
function add_quality_selector(page_lang, selected_fmt) {
  if(!check_on_youtubewatchpage()) { return; }
  var playerEmbed = get_PlayerEmbed_element();
  var wrv=document.getElementById(WATCH_RATINGS_VIEW);
  if(!wrv && playerEmbed) { wrv=playerEmbed.parentNode.nextSibling; }
  if(!wrv) { show_alert('Quality Selector Disabled : "'+WATCH_RATINGS_VIEW+'" and "'+YT_PLAYER_EMBED+'" not found'); return; }

  // Delete the original video quality setting switch (Cosmetic change)
  remove_watch_element(WATCH_QUAL_SETTING);

  // Clean URL
  var vurl = window.location.href;
  //vurl=vurl.replace(/\#$/,"");
  vurl=vurl.replace(/\&?fmt\=\d+(\&|$)/gi,"");
  vurl=vurl.replace(/\&?feature\=(channel|relate|user|search)[^(\&|$)]*/gi,"");

  var flashvars='';
  if(playerEmbed) { // Get flashvars from the embed video
    flashvars = playerEmbed.getAttribute('flashvars');
  } else { // Get flashvars from the fullscreen link
    flashvars = get_fullscreenURL();
  }
  var fmt_array=get_fmt_array(flashvars);

  // Create links
  var HDAvailable=(unsafeWindow.isHDAvailable==true);
  var link1=null; var link2=null; var link3=null; var link4=null;
  if(selected_fmt!=0) {
    link1=document.createElement("a");
    link1.setAttribute('class','hLink');
    link1.setAttribute('href',vurl+url_fmt(0));
  } else { link1=document.createElement("span"); link1.style.setProperty('color','inherit','important'); }
  if(selected_fmt!=FMT_HIGH_QUALITY_FLV) {
    link2=document.createElement("a");
    if((fmt_array[FMT_HIGH_QUALITY_FLV]) || (selected_fmt!=0)) {
      link2.setAttribute('class','hLink');
    } else {
      link2.style.setProperty('color',window.getComputedStyle(window.document.body,null).color,'important');
    }
    link2.setAttribute('href',vurl+url_fmt(FMT_HIGH_QUALITY_FLV));
  } else { link2=document.createElement("span"); link2.style.setProperty('color','inherit','important'); }
  if(selected_fmt!=18) {
    link3=document.createElement("a");
    link3.setAttribute('class','hLink');
    link3.setAttribute('href',vurl+url_fmt(18));
  } else { link3=document.createElement("span"); link3.style.setProperty('color','inherit','important'); }
  if(selected_fmt!=22) {
    link4=document.createElement("a");
    if(fmt_array[22] || HDAvailable || (selected_fmt!=0)) { 
      link4.setAttribute('class','hLink');
    } else {
      link4.style.setProperty('color',window.getComputedStyle(window.document.body,null).color,'important');
    }
    link4.setAttribute('href',vurl+url_fmt(22));
  } else { link4=document.createElement("span"); link4.style.setProperty('color','inherit','important'); }

  link1.textContent = HtmlUnicodeDecode(get_text_QS(page_lang,"link1"));
  link2.textContent = HtmlUnicodeDecode(get_text_QS(page_lang,"link2"));
  link3.textContent = HtmlUnicodeDecode(get_text_QS(page_lang,"link3"));
  link4.textContent = HtmlUnicodeDecode(get_text_QS(page_lang,"link4"));

  link1.style.setProperty('font-weight','normal','important');
  link2.style.setProperty('font-weight','normal','important');
  link3.style.setProperty('font-weight','normal','important');
  link4.style.setProperty('font-weight','normal','important');

  if((selected_fmt== 0                  ) ||  (!fmt_array[selected_fmt])) { link1.style.setProperty('font-weight','bold','important'); }
  if((selected_fmt==FMT_HIGH_QUALITY_FLV) &&  (fmt_array[selected_fmt] )) { link2.style.setProperty('font-weight','bold','important'); }
  if((selected_fmt==18                  ) &&  (fmt_array[selected_fmt] )) { link3.style.setProperty('font-weight','bold','important'); }
  if((selected_fmt==22                  ) &&  (fmt_array[selected_fmt] )) { link4.style.setProperty('font-weight','bold','important'); }

  // Change video size
  var wide=(unsafeWindow.isWidescreen==true);
  var low_quality=(selected_fmt<=6) || (selected_fmt==13) || (selected_fmt==17) || (selected_fmt==34);
  if(playerEmbed) {
    if(wide) {
      if(ENABLE_WIDE_VIDEO_RESIZING && !(low_quality)) {
        playerEmbed.parentNode.parentNode.style.width ='960px';
        playerEmbed.parentNode.parentNode.style.height='606px';
        playerEmbed.style.width ='960px';
        playerEmbed.style.height='566px';
      }
    } else {
      if(ENABLE_4DV3_VIDEO_RESIZING) {
        if((ENABLE_4DV3_VIDEO_RESIZING==1) || (low_quality)) {
          playerEmbed.style.height='505px';
        } else {
          playerEmbed.parentNode.parentNode.style.width ='960px';
          playerEmbed.parentNode.parentNode.style.height='785px';
          playerEmbed.style.width ='960px';
          playerEmbed.style.height='745px';
        }
      }
    }
  }

  // Add the Quality Video links
  var newElement = document.createElement('div');
  newElement.setAttribute('style','width:100%; margin:3px 0 10px 0;');
  var table = document.createElement('table');
  table.setAttribute('class','watch-comment-head');
  table.setAttribute('style','text-align:center; width:100%; color:#880000 !important; border: 1px solid transparent');
  table.style.backgroundColor="#F8F8F8";
  table.style.borderColor="#CCCCCC";
  newElement.appendChild(table);
  var tr1 = document.createElement('tr');
  tr1.setAttribute('style','color:inherit !important; border: none');
  table.appendChild(tr1);
  var td1 = document.createElement('td'); td1.appendChild(link1); tr1.appendChild(td1);
  td1.setAttribute('style','color:inherit !important; padding-top:3px !important; padding-bottom:2px !important');
  var td2 = document.createElement('td'); td2.appendChild(link3); tr1.appendChild(td2);
  td2.setAttribute('style','color:inherit !important; padding-top:3px !important; padding-bottom:2px !important');

  var tr2 = document.createElement('tr');
  tr2.setAttribute('style','color:inherit !important');
  table.appendChild(tr2);
  var td3 = document.createElement('td'); td3.appendChild(link2); tr2.appendChild(td3);
  td3.setAttribute('style','color:inherit !important; padding-bottom:3px !important; padding-top:2px !important');
  var td4 = document.createElement('td'); td4.appendChild(link4); tr2.appendChild(td4);
  td4.setAttribute('style','color:inherit !important; padding-bottom:3px !important; padding-top:2px !important');
  user_select(newElement,'none');
  wrv.parentNode.insertBefore(newElement, wrv);
}

//******************************
//*** Image Preview Rollover ***
//******************************
var image_state=new Array;
var image_count=new Array;
var image_cache=new Array;

function change_image(element)  {
  const MAX_IMG=3;
  const colorlist=["#CC88FF","#CC0000","#00AA00","#0000DD"];
  var idvideo=element.getAttribute('qlicon');
  if(!idvideo) { return; }

  image_count[idvideo]=(image_count[idvideo] % 3)+1;

  if(isUndefined(image_cache[idvideo])) {
    var url_img=element.getAttribute('src');
    var imgpath=url_img.match(/^(.*\/).*?(\.jpg)$/i);
    if(!imgpath) { return; }

    image_cache[idvideo]=new Array;
    image_cache[idvideo][0]=false;
    for(var h=1;h<=MAX_IMG;h++) {
      url_img=imgpath[1]+h+imgpath[2];
      image_cache[idvideo][h]=new Image();
      image_cache[idvideo][h].src=url_img;
    }
  }

  if(!(image_cache[idvideo][0])) {
    var nbcomplete=0;
    for(var h=1;h<=MAX_IMG;h++) { if (image_cache[idvideo][h].complete == true) { nbcomplete++; } }
    if(nbcomplete==0) {
      image_count[idvideo]=0;
    } else {
      if(nbcomplete>=MAX_IMG) {
        image_cache[idvideo][0]=true;
      } else {
        while (image_cache[idvideo][image_count[idvideo]].complete != true) { image_count[idvideo]=(image_count[idvideo] % 3)+1; }
      }
    }
  }

  element.style.borderColor="#F0F0F0";
  if(element.className=='vimg50') { element.parentNode.parentNode.style.borderColor=colorlist[image_count[idvideo]]; }
  else { element.parentNode.parentNode.parentNode.style.borderColor=colorlist[image_count[idvideo]]; }


  if(image_count[idvideo]>0) {
    element.src=image_cache[idvideo][image_count[idvideo]].src;
    if(image_state[idvideo]) { image_state[idvideo]=setTimeout( function() { change_image(element); }, ROLLOVER_DELAY_CONT); }
  } else {
    if(image_state[idvideo]) { image_state[idvideo]=setTimeout( function() { change_image(element); }, ROLLOVER_DELAY_LOAD); }
  }
}

function start_rollover_event() {
  var elImg=this;
  var idvideo=elImg.getAttribute('qlicon');
  if(!idvideo) { return; }
  if(!(image_state[idvideo])) { image_state[idvideo]=setTimeout( function() { change_image(elImg); }, ROLLOVER_DELAY_INIT); }
}

function stop_rollover_event() {
  var elImg=this;
  var idvideo=elImg.getAttribute('qlicon');
  if(!idvideo) { return; }
  image_state[idvideo]=clearTimeout(image_state[idvideo]);
}

function bind_image_preview_rollover(elImg) {
  var idvideo=elImg.getAttribute('qlicon');
  if(!idvideo) {
    var imgpath=elImg.getAttribute('src');
    if(!imgpath) { return; }
    var temp=imgpath.match(/^.*\/(.*?)\/default\.jpg$/);
    if(!temp) { return; }
    idvideo=temp[1];
    elImg.setAttribute('qlicon',idvideo);
  }
  if(idvideo) {
    elImg.setAttribute('title',''); // Clear title
    if(isUndefined(image_state[idvideo])) { image_state[idvideo]=0; }
    if(isUndefined(image_count[idvideo])) { image_count[idvideo]=0; }
    elImg.addEventListener('mouseover' , start_rollover_event, true);
    elImg.addEventListener('mouseout'  , stop_rollover_event , true);
  }
}

function image_preview_rollover(element) {
  if(!(element)) { return; }
  var links=null;
  try { links=document.evaluate('.//img[@src]',element,null,XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,null); } catch(err) { links=null; }
  if(links) {
    var links_lg=links.snapshotLength;
    for(var h=0;h<links_lg;h++) {
      var image=links.snapshotItem(h);
      if(image) { bind_image_preview_rollover(image); }
    }
    return;
  }
  try { links=element.getElementsByTagName("img"); } catch(err) { links=null; }
  if(links) {
    var links_nb=links.length;
    for(var h=0;h<links_nb;h++) {
      var image=links[h];
      if(image) { bind_image_preview_rollover(image); }
   }
    return;
  }
  var msg="image_preview_rollover: Impossible to get links (XPath and getElementsByTagName failed)";
  if(arguments.callee.getlink_fail) { show_alert(msg,0); }
  else { arguments.callee.getlink_fail=1; show_alert(msg,1); }
}

//**********************
//*** change_links() ***
//**********************
function clean_link_and_add_fmt(link,fmt) {
  // Clean URL
  //link=link.replace(/\#$/,'');
  link=link.replace(/\&?fmt\=\d+(\&|$)/gi,'');
  link=link.replace(/\&?search\=[^(\&|$)]*/gi,'');
  link=link.replace(/\&?feature\=(channel|relate|user|search)[^(\&|$)]*/gi,'');
  // Add fmt to URL
  return link+url_fmt(fmt);
}

function change_links_with_fmt(element,fmt) {
  if(!(element)) { return; }
  var links=null;
  try { links=document.evaluate('.//a[@href]',element,null,XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,null); } catch(err) { links=null; }
  if(links) {
    var links_lg=links.snapshotLength;
    for(var h=0;h<links_lg;h++) {
      var link=links.snapshotItem(h).href;
      if(link.match(/youtube\.\w+\/watch\?/i)) { links.snapshotItem(h).href=clean_link_and_add_fmt(link,fmt); }
    }
    return;
  }
  try { links=element.getElementsByTagName("a"); } catch(err) { links=null; }
  if(links) {
    var links_nb=links.length;
    for(var h=0;h<links_nb;h++) {
      var link=links[h].href;
      if(link.match(/youtube\.\w+\/watch\?/i)) { links[h].href=clean_link_and_add_fmt(link,fmt); }
    }
    return;
  }
  var msg="change_links: Impossible to get links (XPath and getElementsByTagName failed)";
  if(arguments.callee.getlink_fail) { show_alert(msg,0); }
  else { arguments.callee.getlink_fail=1; show_alert(msg,1); }
}

function change_links_event() {
  var el=this;
  var fmt=GM_getValue("Youtube_Download_fmt",0);
  change_links_with_fmt(el,fmt);
  image_preview_rollover(el);
}

//** === change_links & image_preview_rollover === **//
function change_links(selected_fmt) {
  var last_fmt=GM_getValue("Youtube_Download_fmt",0);
  if(check_on_youtubewatchpage()) { //== Watch pages
    if(last_fmt!=0) {
      var wurl=window.location.href;
      // Link from the Flash player ? (NR=1)
      if (wurl.search(/[?&]NR\=\d+/i)>=0) {
        wurl=wurl.replace(/\&?NR\=\d+(\&|$)/gi,'');
        wurl=clean_link_and_add_fmt(wurl,last_fmt);
        window.location.replace(wurl);
        return;
      }
    }
    GM_setValue("Youtube_Download_fmt",selected_fmt);
    // Add fmt to watch-url-field
    var wuf=document.getElementById(WATCH_URL_FIELD);
    if(wuf) { wuf.setAttribute('value',clean_link_and_add_fmt(wuf.getAttribute('value'),selected_fmt)); }
    // Change all links in the page
    change_links_with_fmt(window.document.body, selected_fmt);
    // Change links of User videos after loading it
    var wmf=document.getElementById(WATCH_MORE_FROM);
    if(wmf)  { wmf.addEventListener ('load', change_links_event, true); }
    // Change links of Related videos box after loading it
    var wrvb=document.getElementById(WATCH_RELATED_VIDS);
    if(wrvb) { wrvb.addEventListener('load', change_links_event, true); }
    // Change links of Search box after loading it
    var wsr=document.getElementById(WATCH_SEARCH_RES);
    if(wsr)  { wsr.addEventListener ('load', change_links_event, true); }
    // Playlist panel support
    var plst=document.getElementById(PLAYLIST_PANEL);
    if(plst) { plst.addEventListener('load', change_links_event, true); }
    image_preview_rollover(window.document.body);
  } else { //== Other pages
    // Change all links in the page
    if(last_fmt!=0) { change_links_with_fmt(window.document.body, last_fmt); }
    // == Youtube
    if(check_on_youtube()) { image_preview_rollover(window.document.body); }
  }
}

//************************************************************
//***** Media Controller *************************************
//************************************************************

function get_movie_player(ytplayer_name) {
  if(!ytplayer_name) { ytplayer_name=YT_PLAYER_EMBED; } 
  ytplayer=unsafeWindow.document.getElementById(ytplayer_name);
  if(!ytplayer) {
    var msg='Media Controller warning : "'+ytplayer_name+'" not found';
    if(arguments.callee.movie_player_fail) { show_alert(msg,0); }
    else { arguments.callee.movie_player_fail=1; show_alert(msg); }
  }
  return ytplayer;
}

// N/A (-2), unstarted (-1), ended (0), playing (1), paused (2), buffering (3), video cued (5). 
function get_player_state(ytplayer) {
  var state=-1; try { state=ytplayer.getPlayerState(); } catch(err) { state=-2; }
  if(state<=-2) {
    show_alert('Media Controller warning : "'+ytplayer.id+'" state not available',0);
    if(ytplayer.getAttribute('mc_embedtype')==1) {
      // Check allowscriptaccess (must be 'always')
      var allowScript=ytplayer.getAttribute('allowscriptaccess');
      if(!(allowScript) || !(allowScript.match(/^always$/i))) {
        ytplayer.setAttribute('allowscriptaccess','always');
        show_alert('Media Controller Notice: Reloading the player "'+ytplayer.id+'" to allow script access');
        player_revive(ytplayer.id); // Revive it...
      }
    }
  }
  return state;
}

// §§§ Step back §§§
var player_Step_back_timerid=new Array;
function player_stepback(ytplayer_name) {
  if(player_Step_back_timerid[ytplayer_name]) { return; }
  function player_stepback_check(ytplayer_name,frame_cursor,new_frame_cursor) {
    player_Step_back_timerid[ytplayer_name]=null;
    var ytplayer=get_movie_player(ytplayer_name);
    if(ytplayer) {
      var state=get_player_state(ytplayer);
      if(state!=0 && state<2) { return; }
      cur_frame_cursor=ytplayer.getCurrentTime();
      if(cur_frame_cursor<frame_cursor) { return; }
      new_frame_cursor=new_frame_cursor-0.05; if(new_frame_cursor<0) { new_frame_cursor=0; }
      ytplayer.seekTo(new_frame_cursor,0);
      if(new_frame_cursor<=0) { return; }
      if(frame_cursor-new_frame_cursor>5) { return; } // Test for the Loading-start of the video
      player_Step_back_timerid[ytplayer_name]=window.setTimeout( function() { player_stepback_check(ytplayer_name,frame_cursor,new_frame_cursor); }, 50);
    }
  }
  var ytplayer=get_movie_player(ytplayer_name);
  if(ytplayer) {
    var state=get_player_state(ytplayer);
    if(state<0) { return; }
    ytplayer.pauseVideo();
    state=get_player_state(ytplayer);
    if(state!=0 && state<2) { return; }
    frame_cursor=ytplayer.getCurrentTime();
    if(frame_cursor<=0) { return; }
    new_frame_cursor=frame_cursor-0.05; if(new_frame_cursor<0) { new_frame_cursor=0; }
    ytplayer.seekTo(new_frame_cursor,0);
    ytplayer.pauseVideo();
    if(new_frame_cursor<=0) { return; }
    player_Step_back_timerid[ytplayer_name]=window.setTimeout( function() { player_stepback_check(ytplayer_name,frame_cursor,new_frame_cursor); }, 50);
  }
}

// §§§ Stop §§§
function player_stop(ytplayer_name) {
  var ytplayer=get_movie_player(ytplayer_name);
  if(ytplayer) {
    var state=get_player_state(ytplayer);
    if(state==-1) { window.setTimeout( function() { player_stop(); }, 50); return; }
    if(state<0 || state>3) { return; }
    ytplayer.pauseVideo(); ytplayer.seekTo(0,1); player_pause(ytplayer_name);
  }
}

// §§§ Step forward §§§
function player_frame(ytplayer_name) {
  var frame_cursor=0;
  var ytplayer=get_movie_player(ytplayer_name);

  function player_frame_pause(ytplayer) {
    var state=get_player_state(ytplayer);
    if(state<=0) { return; }
    var new_pos=ytplayer.getCurrentTime();
    //show_alert(frame_cursor+"/"+new_pos,0);
    if(new_pos==frame_cursor || state==3) {
      window.setTimeout( function() { player_frame_pause(ytplayer); }, 2);
      return;
    }
    ytplayer.pauseVideo(ytplayer.id);
  }

  if(ytplayer) {
    var state=get_player_state(ytplayer);
    if(state<=0 || state==3) { return; }
    frame_cursor=ytplayer.getCurrentTime();
    ytplayer.playVideo(ytplayer_name);
    player_frame_pause(ytplayer);
  }
}

// §§§ Play §§§
function player_play(ytplayer_name) {
  if(player_killed[ytplayer_name]==1) { player_revive(ytplayer_name); return; }
  var ytplayer=get_movie_player(ytplayer_name);
  if(ytplayer) {
    var state=get_player_state(ytplayer);
    if(state==-1) { window.setTimeout( function() { player_play(); }, 50); return; }
    if(state<0) { return; }
    ytplayer.playVideo();
  }
}
// Revive the player
var player_killed=new Array;
function player_revive(ytplayer_name) {
  var ytplayer = document.getElementById(ytplayer_name);
  if(!(ytplayer)) { show_alert('Revive Failed : "'+ytplayer_name+'" not found'); return; }

  // Make autoplay on
  if(ytplayer.getAttribute('mc_embedtype')==1) {
    var flashvars = ytplayer.getAttribute('flashvars');
    var autoplay  = flashvars.match(/autoplay\=(\d+)/i);
    if(autoplay) { flashvars=flashvars.replace(/autoplay\=\d+/i,"autoplay=1"); }
    else { flashvars=flashvars+'&autoplay=1'; }
    ytplayer.setAttribute('flashvars',flashvars);
  } else { // mc_embedtype==2
    var srcvars = ytplayer.getAttribute('src');
    var autoplay  = srcvars.match(/autoplay\=(\d+)/i);
    if(autoplay) { srcvars=srcvars.replace(/autoplay\=\d+/i,"autoplay=1"); }
    else { srcvars=srcvars+'&autoplay=1'; }
    ytplayer.setAttribute('src',srcvars);
  }

  // Revive the video player
  flushNode(ytplayer);
  player_killed[ytplayer_name]=0;

  // Test if a loop is set
  player_check_limit(ytplayer_name);
}

// §§§ Pause §§§
function player_pause(ytplayer_name) {
  var ytplayer=get_movie_player(ytplayer_name);
  if(ytplayer) {
    var state=get_player_state(ytplayer);
    if(state==-1 || state==3) { window.setTimeout( function() { player_pause(ytplayer_name); }, 50); return; }
    if(state<=0) { return; }
    ytplayer.pauseVideo();
  }
}


// §§§ Begin §§§
function player_memo(ytplayer_name) {
  var ytplayer=get_movie_player(ytplayer_name);
  if(get_player_state(ytplayer)<-1) { return; }
  var bt_state=document.getElementById(ytplayer_name+'-Memo_state');
  if(ytplayer && bt_state) {
    if(get_player_state(ytplayer)<=0) {
      bt_state.style.display="none";
      bt_state.setAttribute('value',0);
      return;
    }
    if(bt_state.style.display=="none") {
      var new_pos=ytplayer.getCurrentTime();
      ytplayer.seekTo(new_pos,1); // Get real seek time
      new_pos=ytplayer.getCurrentTime();
      if(new_pos<0) { new_pos=0; }
      bt_state.style.display="block";
      bt_state.setAttribute('value',new_pos.toString());
    } else {
      bt_state.style.display="none";
      bt_state.setAttribute('value',0);
    }
  }
}

// §§§ Loop §§§
function player_loop(ytplayer_name) {
  var bt_state=document.getElementById(ytplayer_name+'-Loop_state');
  if(bt_state) {
    if(bt_state.style.display=="none") {
      var ytplayer=get_movie_player(ytplayer_name);
      if(!ytplayer) { return; }
      if(get_player_state(ytplayer)<-1) { return; }
      bt_state.style.display="block";
      player_check_limit(ytplayer_name);
    } else {
      bt_state.style.display="none";
    }
  }
}

// §§§ Rewind §§§
function player_rewind(ytplayer_name) {
  var ytplayer=get_movie_player(ytplayer_name);
  if(ytplayer) {
    var state=get_player_state(ytplayer);
    if(state<0) { return; }
    var memo_pos=0;
    var memo_state=document.getElementById(ytplayer_name+'-Memo_state');
    if(memo_state) { memo_pos=parseFloat(memo_state.getAttribute('value'),9); }
    var player_pos=ytplayer.getCurrentTime();
    if(memo_pos>=player_pos) {
      ytplayer.seekTo(0,1);
    } else {
      ytplayer.seekTo(memo_pos,1);
    }
  }
}

// §§§ End §§§
function player_limit(ytplayer_name) {
  var ytplayer=get_movie_player(ytplayer_name);
  if(get_player_state(ytplayer)<-1) { return; }
  var bt_state=document.getElementById(ytplayer_name+'-Limit_state');
  if(ytplayer && bt_state) {
    if(get_player_state(ytplayer)<0) {
      bt_state.style.display="none";
      bt_state.setAttribute('value',0);
      return;
    }
    if(bt_state.style.display=="none") {
      var new_pos=ytplayer.getCurrentTime();
      if(new_pos<0) { new_pos=0; }
      bt_state.style.display="block";
      bt_state.setAttribute('value',new_pos.toString());
      player_check_limit(ytplayer_name);
    } else {
      bt_state.style.display="none";
      bt_state.setAttribute('value',0);
    }
  }
}

// §§§ Kill §§§ (Double click for this one)
function player_freeze(ytplayer_name) {
  if(isUndefined(ytplayer_name)) { arguments.callee.freeze=0; return; }
  if(arguments.callee.freeze==1) {
    var ytplayer=get_movie_player(ytplayer_name);
    if(!ytplayer) { return; }
    if(get_player_state(ytplayer)>=-1) { ytplayer.pauseVideo(); ytplayer.stopVideo(); }
    player_killed[ytplayer_name]=1;
    return;
  }
  arguments.callee.freeze=1; window.setTimeout( function() { player_freeze(); }, 250);
}

// Need a serial of interrupts to check the end of the selection
var player_check_limit_timerid=new Array;
function player_check_limit_routine(ytplayer_name) {
  if(player_killed[ytplayer_name]==1) { return; }
  var ytplayer=get_movie_player(ytplayer_name);
  if(!ytplayer) { return; }

  var M_state=document.getElementById(ytplayer_name+'-Memo_state');
  var L_state=document.getElementById(ytplayer_name+'-Limit_state');
  var Loop_state=document.getElementById(ytplayer_name+'-Loop_state');
  if(L_state && M_state && Loop_state) {
    if(Loop_state.style.display=='none') { return; }

    var state=get_player_state(ytplayer);
    if(state<0) { player_check_limit_timerid[ytplayer_name]=window.setTimeout( function() { player_check_limit_timerid[ytplayer_name]=null; player_check_limit_routine(ytplayer_name); }, 1000); return; }

    var pos=ytplayer.getCurrentTime();
    // Test Infinite buffering
    if(state==3) { // video buffering
      if(pos>ytplayer.getDuration()-0.5) {
        if(ytplayer.getVideoStartBytes()+ytplayer.getVideoBytesLoaded()>=ytplayer.getVideoBytesTotal())
          { state=0; }
      }
    }

    var vmemo=parseFloat(M_state.getAttribute('value'),9);
    var vlimit=parseFloat(L_state.getAttribute('value'),9);
    if((pos>=vlimit && L_state.style.display!='none') || state==0) { ytplayer.seekTo(vmemo,1); if(state==0) { player_play(ytplayer_name); } }

    // On watch page, onMediaControllerPlayerStateChange take care of the video end, so we end here
    if(L_state.style.display=='none' && check_on_youtubewatchpage()) { return; }
    player_check_limit_timerid[ytplayer_name]=window.setTimeout( function() { player_check_limit_timerid[ytplayer_name]=null; player_check_limit_routine(ytplayer_name); }, 50);
    return;
  }
}
function player_check_limit(ytplayer_name) {
  window.clearTimeout(player_check_limit_timerid[ytplayer_name]);
  player_check_limit_routine(ytplayer_name);
}



function get_fullscreenURL() {
  var url=unsafeWindow.fullscreenUrl;
  if(url) { return window.location.protocol+"//"+window.location.host+url.toString(); }
  return null;
}

function get_embedURL() {
  var url=unsafeWindow.embedUrl;
  if(url) { return url.toString(); }
  return null;
}

// *********************************************************************************************************** //
// Bind Player Event for the End of video
function bind_movie_player_event() {
  // Only for youtube watch pages
  if(!check_on_youtubewatchpage()) { return; }

  //~~~~~~~~ Startof innerscript ~~~~~~//
  var innerscript = function() {

function check_movie_player() {
  var playerEmbed = document.getElementById('__movie_player');
  var wpd = document.getElementById('__watch-player-div');
  if(wpd) {wpd.style.setProperty('padding-left','0','important');}
  if(playerEmbed) { return; }
  if(!wpd) { return; }
  var temp=null;
  try { temp=wpd.getElementsByTagName("embed"); } catch(err) { temp=null; }
  if(temp && temp[0]) { temp[0].setAttribute('id','__movie_player'); }
}

function check_allowscriptaccess(ytplayer) { // Check for allowscriptaccess (must be 'always')
  allowScript=ytplayer.getAttribute('allowscriptaccess');
  if(!(allowScript) || !(allowScript.match(/^always$/i))) {
    ytplayer.setAttribute('allowscriptaccess','always');
    return 1;
  }
  return 0;
}

function set_autoplay(ytplayer,new_autoplay) {
  var flashvars = ytplayer.getAttribute('flashvars');
  var autoplay=flashvars.match(/autoplay\=(\d+)/i);
  if(new_autoplay=="0") {
    if(!(autoplay)) {
      ytplayer.setAttribute('flashvars',flashvars+'&autoplay=0');
      return 1;
    } else if (autoplay[1]!=0) {
      ytplayer.setAttribute('flashvars',flashvars.replace(/autoplay\=\d+/i,"autoplay=0"));
      return 1;
    }
  } else {
    if(new_autoplay=="1") { // Mode: Buffering at start...
      try { ytplayer.pauseVideo(); } catch(err) {} 
      onMediaControllerPlayerStateChange.Buffering_StopPlayer=true;
    }
    if(autoplay) {
      if(autoplay[1]!=1) {
        ytplayer.setAttribute('flashvars',flashvars.replace(/autoplay\=\d+/i,"autoplay=1"));
        return 1;
      }
    }
  }
  return 0;
}

function check_for_loop(ytplayer) {
  var loop_state=window.document.getElementById('__movie_player-Loop_state');
  if(loop_state.style.display!="none") {
    var memo_state=window.document.getElementById('__movie_player-Memo_state');
    if(memo_state) {
      var memo_pos=parseFloat(memo_state.getAttribute('value'),9);
      ytplayer.seekTo(memo_pos,1);
      ytplayer.playVideo();
      window.setTimeout( function() { ytplayer.pauseVideo(); ytplayer.playVideo(); }, 100);
      return 1;
    }
  }
  return 0;
}

function check_still_buffering() {
  var player=window.document.getElementById('__movie_player');
  if(!player) { return; }
  var state=-1; try { state=player.getPlayerState(); } catch(err) { state=-2; }
  if(state==3) {
    if(player.getCurrentTime()>player.getDuration()-0.5) {
      if(check_for_loop(player)) { return; }
      // Original Youtube Script (if no loop)
      try { handleWatchPagePlayerStateChange(0); } catch(err) {}
    }
  }
}

onMediaControllerPlayerStateChange = function(newState) {
  var player=window.document.getElementById('__movie_player');
  if(!player) { return; }
  if(arguments.callee.Buffering_StopPlayer==true) { // Mode: Buffering at start...
    if(newState<0 || newState>=3) {
      try { ytplayer.pauseVideo(); } catch(err) {} 
    } else {
      arguments.callee.Buffering_StopPlayer=false;
    }
  }
  // Test Infinite buffering
  if(newState==3) { // video is buffering
    if(player.getCurrentTime()>player.getDuration()-0.5) {
      if(player.getVideoStartBytes()+player.getVideoBytesLoaded()>=player.getVideoBytesTotal()) {
        newState=0;
      } else {
        window.setTimeout( function() { check_still_buffering(); }, 1500);
      }
    }
  }
  // Check for Loop
  if(newState==0) { if(check_for_loop(player)) { return; } }
  // Original Youtube Script (if no loop)
  try { handleWatchPagePlayerStateChange(newState); } catch(err) {}
}

function bind_MediaControllerPlayerStateChange() {
  function isUndefined(x) { return x == null && x !== null; }
  check_movie_player();
  var ytplayer=window.document.getElementById('__movie_player');
  if(ytplayer) {
    // Flush to remove the initial event since there no removeEventListener ?
    if(isUndefined(arguments.callee.initialflush)) { arguments.callee.initialflush=0; } // Don't do it since i see no problem :p
    var flush=arguments.callee.initialflush; arguments.callee.initialflush=0;
    flush += check_allowscriptaccess(ytplayer);
    flush += set_autoplay(ytplayer,'__autoplay');
    if(flush) { ytplayer.parentNode.replaceChild(ytplayer.cloneNode(true),ytplayer); }
    var state=-1; try { state=ytplayer.getPlayerState(); } catch(err) { state=-2; }
    if(state<0) { // Still loading the player...
      window.setTimeout( function() { bind_MediaControllerPlayerStateChange(); }, 500);
    } else { // Loaded, so add an event
      try { g_YouTubePlayerIsReady=true; pollLocationHash(); if ('__autoplay'!=2) { ytplayer.pauseVideo(); } } catch(err) {}
      ytplayer.addEventListener("onStateChange", "onMediaControllerPlayerStateChange");
      try { ytplayer.addEventListener("onPlaybackQualityChange","onPlayerFormatChanged"); } catch(err) {}
    }
  }
}

// Redefine onYouTubePlayerReady (warning: can cause conflict with an other script)
onYouTubePlayerReady = function(playerid) {
  bind_MediaControllerPlayerStateChange();
}
bind_MediaControllerPlayerStateChange();
  } //~~~~~~~ Endof innerscript ~~~~~~~//

  innerscript=innerscript.toString().replace(/__movie_player/g,YT_PLAYER_EMBED)
             .replace(/__watch-player-div/,WATCH_PLAYER_DIV)
             .replace(/__autoplay/g,GM_getValue("Youtube_Download_Autoplay_Setting",2));

  var script=document.createElement("script");
  //script.setAttribute('id','Youtube_Enhancer-PlayerStateChange');
  script.setAttribute('type','text/javascript');
  script.textContent="("+innerscript+")();";
  document.body.appendChild(script);
}
// *********************************************************************************************************** //


//** === Media Controller === **//
function media_controller(page_lang,ytplayer_name,tag) {
  var ytplayer = document.getElementById(ytplayer_name);
  if(!ytplayer) { show_alert('Media Controller Disabled : "'+ytplayer_name+'" not found'); return; }
  ytplayer.setAttribute('mc_embedtype',tag);

  // Media Controller display mode
  var lgref=480;
  var ytplayer_width=getWidth(ytplayer);
  if (check_on_youtubewatchpage()) { lgref=ytplayer_width; }

  var MC_height=26; var MC_leftB2=167; var MC_topB2=-1; var MC_leftB3=lgref-166;
  if(ytplayer_width<lgref-126) { MC_leftB2=(ytplayer_width-244)/2+117; MC_leftB3=ytplayer_width-30; }
  if(ytplayer_width<300) { MC_leftB2=19; MC_leftB3=145; MC_topB2=26; }

  var yt_p=ytplayer.parentNode; var yt_ns; var yt_c=ytplayer;
  if(yt_p.tagName=="OBJECT") { yt_c=yt_p; yt_p.setAttribute('mc_embedtype',3); yt_ns=yt_p.nextSibling; yt_p=yt_p.parentNode; }
  else { yt_ns=ytplayer.nextSibling; }

  mediabar=document.createElement('div');
  //mediabar.setAttribute('id','Media_Controller-'+ytplayer_name);
  mediabar.setAttribute('style','position:relative; width:'+ytplayer_width+'px; margin-bottom:3px; padding-bottom:3px; '
                       +'height:'+(MC_height+MC_topB2-1)+'px; border:0px; font-family:Arial,sans-serif !important; color:'+COLOR_MC_TEXT_OUT+' !important;');
  mediabar.setAttribute('lang','fr');

  var loop_display_init='none'; // use 'block' (loop enabled at start) or 'none' (loop disabled at start)

  // === Unicode player buttons ===

  // Stop
  var buttonStopDiv=document.createElement('div');
  buttonStopDiv.setAttribute('style','position:absolute; top:-9px; left:6px; font-size:26px; line-height:38px; color:inherit !important;');
  buttonStopDiv.textContent=String.fromCharCode(9632);

  // Step back
  var buttonDiv1=document.createElement('div');
  buttonDiv1.setAttribute('style','position:absolute; top:0px; left:2px; font-size:18px; line-height:26px; color:inherit !important;');
  buttonDiv1.textContent=String.fromCharCode(9668);
  var buttonDiv2=document.createElement('div');
  buttonDiv2.setAttribute('style','position:absolute; top:0px; left:20px; font-size:12px; line-height:26px; color:inherit !important;');
  buttonDiv2.textContent=String.fromCharCode(9613);
  var buttonStepBackDiv=document.createElement('div');
  buttonStepBackDiv.setAttribute('style','color:inherit !important;');
  buttonStepBackDiv.appendChild(buttonDiv1);
  buttonStepBackDiv.appendChild(buttonDiv2);

  // Step forward
  var buttonDiv1=document.createElement('div');
  buttonDiv1.setAttribute('style','position:absolute; top:0px; left:5px; font-size:12px; line-height:26px; color:inherit !important;');
  buttonDiv1.textContent=String.fromCharCode(9613);
  var buttonDiv2=document.createElement('div');
  buttonDiv2.setAttribute('style','position:absolute; top:0px; left:8px; font-size:18px; line-height:26px; color:inherit !important;');
  buttonDiv2.textContent=String.fromCharCode(9658);
  var buttonStepForwardDiv=document.createElement('div');
  buttonStepForwardDiv.setAttribute('style','color:inherit !important;');
  buttonStepForwardDiv.appendChild(buttonDiv1);
  buttonStepForwardDiv.appendChild(buttonDiv2);

  // Play
  var buttonPlayDiv=document.createElement('div');
  buttonPlayDiv.setAttribute('style','position:absolute; top:-2px; left:5px; font-size:20px; line-height:30px; color:inherit !important;');
  buttonPlayDiv.textContent=String.fromCharCode(9658);

  // Pause
  var buttonDiv1=document.createElement('div');
  buttonDiv1.setAttribute('style','position:absolute; top:3px; left:8px; font-size:16px; line-height:21px; color:inherit !important;');
  buttonDiv1.textContent=String.fromCharCode(9613);
  var buttonDiv2=document.createElement('div');
  buttonDiv2.setAttribute('style','position:absolute; top:3px; left:16px; font-size:16px; line-height:21px; color:inherit !important;');
  buttonDiv2.textContent=String.fromCharCode(9613);
  var buttonPauseDiv=document.createElement('div');
  buttonPauseDiv.setAttribute('style','color:inherit !important;');
  buttonPauseDiv.appendChild(buttonDiv1);
  buttonPauseDiv.appendChild(buttonDiv2);

  // Begin
  var buttonDiv1=document.createElement('div');
  buttonDiv1.setAttribute('style','position:absolute; top:-1px; left:6px; font-size:18px; line-height:28px; z-index:2; color:inherit !important;');
  buttonDiv1.textContent=String.fromCharCode(12302);
  var buttonDiv2=document.createElement('div');
  buttonDiv2.setAttribute('id',ytplayer_name+'-Memo_state');
  buttonDiv2.setAttribute('style','display:none; position:absolute; left:1px; top:1px; width:26px; height:'+(MC_height-2)+'px; z-index:1; background:'+COLOR_MC_TOGGLE_BEG_END+';');
  buttonDiv2.setAttribute('value',0);
  var buttonBeginDiv=document.createElement('div');
  buttonBeginDiv.setAttribute('style','color:inherit !important;');
  buttonBeginDiv.appendChild(buttonDiv1);
  buttonBeginDiv.appendChild(buttonDiv2);

  // Loop
  var buttonDiv1=document.createElement('div');
  buttonDiv1.setAttribute('style','position:absolute; top:1px; width:35px; left:4px; font-size:42px; line-height:28px; height:26px; text-align:left; z-index:2; color:inherit !important;');
  buttonDiv1.textContent=String.fromCharCode(8617);
  var buttonDiv2=document.createElement('div');
  buttonDiv2.setAttribute('id',ytplayer_name+'-Loop_state');
  buttonDiv2.setAttribute('style','display:'+loop_display_init+'; position:absolute; left:1px; top:1px; width:35px; height:'+(MC_height-2)+'px; z-index:1; background:'+COLOR_MC_TOGGLE_LOOP+';');
  var buttonLoopDiv=document.createElement('div');
  buttonLoopDiv.setAttribute('style','color:inherit !important;');
  buttonLoopDiv.appendChild(buttonDiv1);
  buttonLoopDiv.appendChild(buttonDiv2);

  // Rewind
  var buttonDiv1=document.createElement('div');
  buttonDiv1.setAttribute('style','position:absolute; top:-1px; left:7px; font-size:14px; line-height:25px; color:inherit !important;');
  buttonDiv1.textContent='|';
  var buttonDiv2=document.createElement('div');
  buttonDiv2.setAttribute('style','position:absolute; top:1px; left:9px; font-size:24px; line-height:26px; color:inherit !important;');
  buttonDiv2.textContent=String.fromCharCode(9664);
  var buttonRewindDiv=document.createElement('div');
  buttonRewindDiv.setAttribute('style','color:inherit !important;');
  buttonRewindDiv.appendChild(buttonDiv1);
  buttonRewindDiv.appendChild(buttonDiv2);

  // End
  var buttonDiv1=document.createElement('div');
  buttonDiv1.setAttribute('style','position:absolute; top:-1px; left:14px; font-size:18px; line-height:26px; z-index:2; color:inherit !important;');
  buttonDiv1.textContent=String.fromCharCode(12303);
  var buttonDiv2=document.createElement('div');
  buttonDiv2.setAttribute('id',ytplayer_name+'-Limit_state');
  buttonDiv2.setAttribute('style','display:none; position:absolute; left:1px; top:1px; width:26px; height:'+(MC_height-2)+'px; z-index:1; background:'+COLOR_MC_TOGGLE_BEG_END+';');
  buttonDiv2.setAttribute('value',0);
  var buttonEndDiv=document.createElement('div');
  buttonEndDiv.setAttribute('style','color:inherit !important;');
  buttonEndDiv.appendChild(buttonDiv1);
  buttonEndDiv.appendChild(buttonDiv2);

  // Kill
  var buttonKillDiv=document.createElement('div');
  buttonKillDiv.setAttribute('style','position:absolute; top:0px; left:2px; font-size:24px; line-height:27px; color:inherit !important;');
  buttonKillDiv.textContent=String.fromCharCode(9760);


  // === Media Controller Bar ===
  // 1st group
  var buttonStop=document.createElement('div');
  buttonStop.setAttribute('title',HtmlUnicodeDecode(get_text_MC(page_lang,"stop")));
  buttonStop.setAttribute('style','left: 0px; position:absolute; width:28px; height:'+MC_height+'px; border: 1px solid '+COLOR_MC_BORDER+' !important; cursor:pointer; background:'+COLOR_MC_BACKGROUND+' !important; color:inherit !important; border-top:0; overflow:hidden;');
  buttonStop.appendChild(buttonStopDiv);
  buttonStop.addEventListener('mouseover', function() { this.style.setProperty("color", COLOR_MC_TEXT_ACTION_IN, "important"); }, true);
  buttonStop.addEventListener('mouseout',  function() { this.style.setProperty("color", "inherit", "important"); }, true);
  buttonStop.addEventListener('click',     function() { player_stop(ytplayer_name); }, true);
  user_select(buttonStop,'none');
  mediabar.appendChild(buttonStop);

  var buttonStepBack=document.createElement('div');
  buttonStepBack.setAttribute('title',HtmlUnicodeDecode(get_text_MC(page_lang,"stepback")));
  buttonStepBack.setAttribute('style','left:29px; position:absolute; width:28px; height:'+MC_height+'px; border: 1px solid '+COLOR_MC_BORDER+' !important; cursor:pointer; background:'+COLOR_MC_BACKGROUND+' !important; color:inherit !important; border-top:0; overflow:hidden;');
  buttonStepBack.appendChild(buttonStepBackDiv);
  buttonStepBack.addEventListener('mouseover', function() { this.style.setProperty("color", COLOR_MC_TEXT_ACTION_IN, "important"); }, true);
  buttonStepBack.addEventListener('mouseout',  function() { this.style.setProperty("color", "inherit", "important"); }, true);
  buttonStepBack.addEventListener('click',     function() { player_stepback(ytplayer_name); }, true);
  user_select(buttonStepBack,'none');
  mediabar.appendChild(buttonStepBack);

  var buttonFrame=document.createElement('div');
  buttonFrame.setAttribute('title',HtmlUnicodeDecode(get_text_MC(page_lang,"step")));
  buttonFrame.setAttribute('style','left:58px; position:absolute; width:28px; height:'+MC_height+'px; border: 1px solid '+COLOR_MC_BORDER+' !important; cursor:pointer; background:'+COLOR_MC_BACKGROUND+' !important; color:inherit !important; border-top:0; overflow:hidden;');
  buttonFrame.appendChild(buttonStepForwardDiv);
  buttonFrame.addEventListener('mouseover', function() { this.style.setProperty("color", COLOR_MC_TEXT_ACTION_IN, "important"); }, true);
  buttonFrame.addEventListener('mouseout',  function() { this.style.setProperty("color", "inherit", "important"); }, true);
  buttonFrame.addEventListener('click',     function() { player_frame(ytplayer_name); }, true);
  user_select(buttonFrame,'none');
  mediabar.appendChild(buttonFrame);

  var buttonPlay=document.createElement('div');
  buttonPlay.setAttribute('title',HtmlUnicodeDecode(get_text_MC(page_lang,"play")));
  buttonPlay.setAttribute('style','left:87px; position:absolute; width:28px; height:'+MC_height+'px; border: 1px solid '+COLOR_MC_BORDER+' !important; cursor:pointer; background:'+COLOR_MC_BACKGROUND+' !important; color:inherit !important; border-top:0; overflow:hidden;');
  buttonPlay.appendChild(buttonPlayDiv);
  buttonPlay.addEventListener('mouseover', function() { this.style.setProperty("color", COLOR_MC_TEXT_ACTION_IN, "important"); }, true);
  buttonPlay.addEventListener('mouseout',  function() { this.style.setProperty("color", "inherit", "important"); }, true);
  buttonPlay.addEventListener('click',     function() { player_play(ytplayer_name); }, true);
  user_select(buttonPlay,'none');
  mediabar.appendChild(buttonPlay);

  var buttonPause=document.createElement('div');
  buttonPause.setAttribute('title',HtmlUnicodeDecode(get_text_MC(page_lang,"pause")));
  buttonPause.setAttribute('style','left:116px; position:absolute; width:28px; height:'+MC_height+'px; border: 1px solid '+COLOR_MC_BORDER+' !important; cursor:pointer; background:'+COLOR_MC_BACKGROUND+' !important; color:inherit !important; border-top:0; overflow:hidden;');
  buttonPause.appendChild(buttonPauseDiv);
  buttonPause.addEventListener('mouseover', function() { this.style.setProperty("color", COLOR_MC_TEXT_ACTION_IN, "important"); }, true);
  buttonPause.addEventListener('mouseout',  function() { this.style.setProperty("color", "inherit", "important"); }, true);
  buttonPause.addEventListener('click',     function() { player_pause(ytplayer_name); }, true);
  user_select(buttonPause,'none');
  mediabar.appendChild(buttonPause);


  // 2nd group
  var buttonMemo=document.createElement('div');
  buttonMemo.setAttribute('title',HtmlUnicodeDecode(get_text_MC(page_lang,"begin")));
  buttonMemo.setAttribute('style','left:'+MC_leftB2+'px; top:'+(MC_topB2+1)+'px; position:absolute; width:28px; height:'+MC_height+'px; border: 1px solid '+COLOR_MC_BORDER+' !important; cursor:pointer; background:'+COLOR_MC_BACKGROUND+' !important; color:inherit !important; border-top:0; overflow:hidden;');
  buttonMemo.appendChild(buttonBeginDiv);
  buttonMemo.addEventListener('mouseover', function() { this.style.setProperty("color", COLOR_MC_TEXT_TOGGLE_IN, "important"); }, true);
  buttonMemo.addEventListener('mouseout',  function() { this.style.setProperty("color", "inherit", "important"); }, true);
  buttonMemo.addEventListener('click',     function() { player_memo(ytplayer_name); }, true);
  user_select(buttonMemo,'none');
  mediabar.appendChild(buttonMemo);

  var buttonLoop=document.createElement('div');
  buttonLoop.setAttribute('title',HtmlUnicodeDecode(get_text_MC(page_lang,"loop")));
  buttonLoop.setAttribute('style','left:'+(MC_leftB2+29)+'px; top:'+(MC_topB2+1)+'px; position:absolute; width:37px; height:'+MC_height+'px; border: 1px solid '+COLOR_MC_BORDER+' !important; cursor:pointer; background:'+COLOR_MC_BACKGROUND+' !important; color:inherit !important; border-top:0; overflow:hidden;');
  buttonLoop.appendChild(buttonLoopDiv);
  buttonLoop.addEventListener('mouseover', function() { this.style.setProperty("color", COLOR_MC_TEXT_TOGGLE_IN, "important"); }, true);
  buttonLoop.addEventListener('mouseout',  function() { this.style.setProperty("color", "inherit", "important"); }, true);
  buttonLoop.addEventListener('click',     function() { player_loop(ytplayer_name); }, true);
  user_select(buttonLoop,'none');
  mediabar.appendChild(buttonLoop);

  var buttonRewind=document.createElement('div');
  buttonRewind.setAttribute('title',HtmlUnicodeDecode(get_text_MC(page_lang,"rewind")));
  buttonRewind.setAttribute('style','left:'+(MC_leftB2+67)+'px; top:'+(MC_topB2+1)+'px; position:absolute; width:28px; height:'+MC_height+'px; border: 1px solid '+COLOR_MC_BORDER+' !important; cursor:pointer; background:'+COLOR_MC_BACKGROUND+' !important; color:inherit !important; border-top:0; overflow:hidden;');
  buttonRewind.appendChild(buttonRewindDiv);
  buttonRewind.addEventListener('mouseover', function() { this.style.setProperty("color", COLOR_MC_TEXT_ACTION_IN, "important"); }, true);
  buttonRewind.addEventListener('mouseout',  function() { this.style.setProperty("color", "inherit", "important"); }, true);
  buttonRewind.addEventListener('click',     function() { player_rewind(ytplayer_name); }, true);
  user_select(buttonRewind,'none');
  mediabar.appendChild(buttonRewind);

  var buttonLimit=document.createElement('div');
  buttonLimit.setAttribute('title',HtmlUnicodeDecode(get_text_MC(page_lang,"end")));
  buttonLimit.setAttribute('style','left:'+(MC_leftB2+96)+'px; top:'+(MC_topB2+1)+'px; position:absolute; width:28px; height:'+MC_height+'px; border: 1px solid '+COLOR_MC_BORDER+' !important; cursor:pointer; background:'+COLOR_MC_BACKGROUND+' !important; color:inherit !important; border-top:0; overflow:hidden;');
  buttonLimit.appendChild(buttonEndDiv);
  buttonLimit.addEventListener('mouseover', function() { this.style.setProperty("color", COLOR_MC_TEXT_TOGGLE_IN, "important"); }, true);
  buttonLimit.addEventListener('mouseout',  function() { this.style.setProperty("color", "inherit", "important"); }, true);
  buttonLimit.addEventListener('click',     function() { player_limit(ytplayer_name); }, true);
  user_select(buttonLimit,'none');
  mediabar.appendChild(buttonLimit);


  // 3rd group
  var buttonFreeze=document.createElement('div');
  buttonFreeze.setAttribute('title',HtmlUnicodeDecode(get_text_MC(page_lang,"kill")));
  buttonFreeze.setAttribute('style','left:'+MC_leftB3+'px; position:absolute; width:28px; height:'+MC_height+'px; border: 1px solid '+COLOR_MC_BORDER+' !important; cursor:pointer; background:'+COLOR_MC_BG_RED+' !important; color:inherit !important; border-top:0; overflow:hidden;');
  buttonFreeze.appendChild(buttonKillDiv);
  buttonFreeze.addEventListener('mouseover', function() { this.style.setProperty("color", COLOR_MC_TEXT_ACTION_IN, "important"); }, true);
  buttonFreeze.addEventListener('mouseout',  function() { this.style.setProperty("color", "inherit", "important"); }, true);
  buttonFreeze.addEventListener('click',     function() { player_freeze(ytplayer_name); }, true);
  user_select(buttonFreeze,'none');
  mediabar.appendChild(buttonFreeze);


  // 4th group
  if(check_on_youtubewatchpage()) {
    var eurl=get_embedURL();
    if(eurl) {
      var buttonEUInner=document.createElement('div');
      buttonEUInner.setAttribute('title',HtmlUnicodeDecode(get_text_MC(page_lang,"embed")));
      buttonEUInner.setAttribute('style','color:#0000F0; font-size:14px; position:absolute; top:-1px; left:1px; width:38px; text-align:center; line-height:28px; color:'+COLOR_MC_TEXT_BLUE+' !important; text-decoration:none !important;');
      buttonEUInner.textContent=String.fromCharCode(10065);

      var buttonEU=document.createElement('div');
      buttonEU.setAttribute('style','left:'+(lgref-108)+'px; position:absolute; width:39px; height:'+MC_height+'px; border: 1px solid '+COLOR_MC_BORDER+' !important; cursor:pointer; background:'+COLOR_MC_BG_BLUE_OUT+' !important; border-top:0;');
      buttonEU.appendChild(buttonEUInner);
      buttonEU.addEventListener('mouseover' , function() { this.style.setProperty("background",COLOR_MC_BG_BLUE_IN ,'important'); buttonEUInner.style.setProperty("text-decoration","underline","important"); }, true);
      buttonEU.addEventListener('mouseout'  , function() { this.style.setProperty("background",COLOR_MC_BG_BLUE_OUT,'important'); buttonEUInner.style.setProperty("text-decoration","none","important"); }, true);
      buttonEU.addEventListener('click'     , function() { player_pause(ytplayer_name); }, true);
      user_select(buttonEU,'none');

      var buttonEULink=document.createElement('a');
      buttonEULink.setAttribute('href',eurl);
      buttonEULink.setAttribute('target','_blank');
      buttonEULink.appendChild(buttonEU);
      mediabar.appendChild(buttonEULink);
    } else { show_alert('Media Controller : Global variable for "Embed URL" not found',0); }

    var fsurl=get_fullscreenURL();
    if(fsurl) {
      var buttonFSInner=document.createElement('div');
      buttonFSInner.setAttribute('title',HtmlUnicodeDecode(get_text_MC(page_lang,"fscr")));
      buttonFSInner.setAttribute('style','color:#0000F0; font-size:14px; position:absolute; top:-1px; left:1px; width:60px; text-align:center; line-height:28px; color:'+COLOR_MC_TEXT_BLUE+' !important; text-decoration:none !important;');
      buttonFSInner.textContent=String.fromCharCode(8738,8194,8194,8194,10065);

      var buttonFS=document.createElement('div');
      buttonFS.setAttribute('style','left:'+(lgref-68)+'px; position:absolute; width:66px; height:'+MC_height+'px; border: 1px solid '+COLOR_MC_BORDER+' !important; cursor:pointer; background:'+COLOR_MC_BG_BLUE_OUT+' !important; border-top:0;');
      buttonFS.appendChild(buttonFSInner);
      buttonFS.addEventListener('mouseover' , function() { this.style.setProperty("background",COLOR_MC_BG_BLUE_IN ,'important'); buttonFSInner.style.setProperty("text-decoration","underline","important"); }, true);
      buttonFS.addEventListener('mouseout'  , function() { this.style.setProperty("background",COLOR_MC_BG_BLUE_OUT,'important'); buttonFSInner.style.setProperty("text-decoration","none","important"); }, true);
      buttonFS.addEventListener('click'     , function() { player_pause(ytplayer_name); }, true);
      user_select(buttonFS,'none');

      var buttonFSLink=document.createElement('a');
      buttonFSLink.setAttribute('href',fsurl);
      buttonFSLink.setAttribute('target','_blank');
      buttonFSLink.appendChild(buttonFS);
      mediabar.appendChild(buttonFSLink);
    } else { show_alert('Media Controller : Global variable for "Fullscreen URL" not found',0); }
  }
  yt_p.insertBefore(mediabar, yt_ns);

  // Horizontal offset fix
  var leftdiff=getAbsoluteLeft(mediabar)-getAbsoluteLeft(ytplayer);
  if(leftdiff!=0) { mediabar.style.left=(-leftdiff)+'px'; }

  // Vertical offset fix
  var ytplayer_height=getHeight(ytplayer);
  var topdiff=getAbsoluteTop(mediabar)-ytplayer_height-getAbsoluteTop(ytplayer);
  if(topdiff!=0) { mediabar.style.top=(-topdiff)+'px'; }

  player_check_limit(ytplayer_name);
}

function check_jsapi(vars) { // Force enabling JS
  var temp=vars.match(/enablejsapi\s*\=\s*(\d+)/i);
  if(temp) { if(temp[1]!="1") { return vars.replace(/enablejsapi\s*\=\s*\d+/i,'enablejsapi=1'); } }
  else { return vars+'&enablejsapi=1'; }
  return vars;
}

function check_autoplay(vars) { // If autoplay_setting = manual -> Force autoplay to manual
  if(GM_getValue("Youtube_Download_Autoplay_Setting",2)==0) {
    var temp=vars.match(/autoplay\s*\=\s*(\d+)/i);
    if(temp) { if(temp[1]!="0") { return vars.replace(/autoplay\s*\=\s*\d+/i,'autoplay=0'); } }
    else { return vars+'&autoplay=0'; }
  }
  return vars;
}

function bind_player_with_media_controller(page_lang,player,number) {
  if(player.getAttribute('mc_embedtype')) { return; } // Already binded
  var src_name="src"; // EMBED and VIDEO Tag
  if(player.nodeName.toUpperCase()=="OBJECT") { src_name="data"; } // OBJECT Tag
  var player_src=player.getAttribute(src_name);
  var needflush=false;
  if(player_src.match(/^http\:\/\/(\w+\.)?youtube\.com\/\w+\//i)) { // Object Embeded youtube video
    if(!player.id) { player.setAttribute('id','Youtube_movie-'+number); }
    var new_player_src=check_autoplay(check_jsapi(player_src));
    if(new_player_src!=player_src) { player.setAttribute(src_name,new_player_src); needflush=true; }
    var asa = player.getAttribute('allowscriptaccess');
    if (asa!='always') { player.setAttribute('allowscriptaccess','always'); needflush=true; }
    if (needflush) { flushNode(player); }
    media_controller(page_lang,player.id,2);
  } else if(player_src.match(/^http\:\/\/(\w+\.)?ytimg\.com\//i)) { // Normal youtube video
    if(!player.id) { player.setAttribute('id','Youtube_movie-'+number); }
    var flashvars = player.getAttribute('flashvars');
    var new_flashvars = get_clean_flashvars(flashvars);
    new_flashvars = check_autoplay(check_jsapi(new_flashvars));
    if(new_flashvars!=flashvars) { player.setAttribute('flashvars',new_flashvars); needflush=true; } 
    var asa = player.getAttribute('allowscriptaccess');
    if (asa!='always') { player.setAttribute('allowscriptaccess','always'); needflush=true; }
    if (needflush) { flushNode(player); }
    media_controller(page_lang,player.id,1);
  }
}

function bind_media_players(page_lang) {
  var players=null;
  try { players=document.evaluate('//embed[@src]',document,null,XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,null); } catch(err) { players=null; }
  if(players) {
    var players_lg=players.snapshotLength;
    for(var h=0;h<players_lg;h++) { bind_player_with_media_controller(page_lang,players.snapshotItem(h),h); }
    return;
  }
  try { players=document.getElementsByTagName("embed"); } catch(err) { players=null; }
  if(players) {
    var players_lg=players.length;
    for(var h=0;h<players_lg;h++) { bind_player_with_media_controller(page_lang,players[h],h); }
    return;
  }
  var msg="Media Controller: Impossible to get media players (XPath and getElementsByTagName failed)";
  show_alert(msg,1);
}

function add_media_controller(page_lang) {
  bind_media_players(page_lang);
}

//******************************************** Updater ***************************************************//
function YouTube_Enhancer_Update_install(updateelem,Date_Now,Updater_url_dl) {
  GM_setValue("Youtube_Enhancer_Updater_Date", Date_Now)
  remove_element(updateelem);
  //GM_openInTab(Updater_url_dl);
  document.location.href=Updater_url_dl;
}

function YouTube_Enhancer_Update_later(updateelem,Date_Now) {
  GM_setValue("Youtube_Enhancer_Updater_Date", Date_Now)
  remove_element(updateelem);
}

function YouTube_Enhancer_Update_Display(page_lang,Updater_url_dl,Date_Now) {
  if ( top.location.href!=window.location.href ) { return; }
  var updateelem=document.createElement('div');
  updateelem.setAttribute('lang','fr');
  updateelem.setAttribute("style","position:fixed; top:0px; left:0px; right:0px; z-index:9998; color:#FFFFFF !important; background:#C080C0 !important; width:auto; text-align:center; font-family:arial,sans-serif; font-size:24px; line-height:24px; margin:2px; border: 3px solid #CC0088; border-right-width:24px;");
  updateelem.textContent='Youtube Enhancer - '+HtmlUnicodeDecode(get_text_Updater(page_lang,"foun"))+': ';
  var aelem1=document.createElement('a');
  aelem1.setAttribute('style','text-decoration:none; cursor:pointer; color:#0000CC !important; font-weight: normal; font-style:normal;');
  aelem1.setAttribute('title',Updater_url_dl);
  //aelem1.setAttribute('href',Updater_url_dl);
  aelem1.textContent=HtmlUnicodeDecode(get_text_Updater(page_lang,"dnow"));
  updateelem.appendChild(aelem1);
  var textelem=document.createTextNode(' / ');
  updateelem.appendChild(textelem);
  var aelem2=document.createElement('a');
  aelem2.setAttribute('style','text-decoration:none; cursor:pointer; color:#0000CC !important; font-weight: normal; font-style:normal;');
  aelem2.textContent=HtmlUnicodeDecode(get_text_Updater(page_lang,"dlat"));
  updateelem.appendChild(aelem2);
  var aelemX=document.createElement('a');
  aelemX.setAttribute('style','position:absolute; top:0px; height:26px; width: 20px; right:-21px; text-decoration:none; cursor:pointer; color:#0000CC !important; background:#CC0088 !important;');
  aelemX.textContent='X';
  updateelem.appendChild(aelemX);
  user_select(updateelem,'none');
  document.body.appendChild(updateelem);
  aelem1.addEventListener('click', function() { YouTube_Enhancer_Update_install(updateelem,Date_Now,Updater_url_dl); }, true);
  aelem2.addEventListener('click', function() { YouTube_Enhancer_Update_later(updateelem,Date_Now); }, true);
  aelemX.addEventListener('click', function() { remove_element(updateelem); }, true);
}

function YouTube_Enhancer_Updater(page_lang) {
  const scriptid='33042';
  if(YOUTUBE_ENHANCER_UPDATER_STATUS<0) {
    var LastVersion=GM_getValue("Youtube_Enhancer_Updater_Version", YOUTUBE_ENHANCER_UPDATER_STATUS);
    if(LastVersion>=0) {
      if(typeof GM_deleteValue == 'function') { GM_deleteValue("Youtube_Enhancer_Updater_Version"); GM_deleteValue("Youtube_Enhancer_Updater_Date"); }
      else { GM_setValue("Youtube_Enhancer_Updater", -1); GM_setValue("Youtube_Enhancer_Updater_Date", 0); }
      show_alert('Youtube Enhancer - Updater Disabled / Last_Version='+LastVersion,0);
      show_messageBox('Youtube Enhancer - '+HtmlUnicodeDecode(get_text_Updater(page_lang,"disa")));
    }
    return;
  }
  var Updater_Version=GM_getValue("Youtube_Enhancer_Updater_Version", YOUTUBE_ENHANCER_UPDATER_STATUS);
  if(Updater_Version<=0) { return; }
  GM_setValue("Youtube_Enhancer_Updater_Version",Updater_Version);
  var Updater_Date=GM_getValue("Youtube_Enhancer_Updater_Date", 0);
  var Date_Now=new Date();
  Date_Now=Date_Now.getFullYear()*10000+Date_Now.getMonth()*100+Date_Now.getDate();
  if(Updater_Date>Date_Now) { GM_setValue("Youtube_Enhancer_Updater_Date", Date_Now); return; }
  //var Updater_url_dl='https://userscripts.org/scripts/source/'+scriptid+'.user.js';
  var Updater_url_dl='https://userscripts.org/scripts/show/'+scriptid;
  if(Updater_Date<0) {
    show_alert('Youtube Enhancer - Update Was Found: Last='+Math.abs(Updater_Date)+' / Now='+Date_Now,0);
    YouTube_Enhancer_Update_Display(page_lang,Updater_url_dl,Date_Now);
    return;
  }
  if(Date_Now-Updater_Date<1) { return; }

  // Checking meta.js...
  var Updater_url_check='https://userscripts.org/scripts/source/'+scriptid+'.meta.js';
  GM_xmlhttpRequest({
    method: 'GET',
	url: Updater_url_check,
	headers: { 'User-agent': 'GM_xmlhttpRequest Updater', 'Accept': 'text/*' },
	onload: function(data) {
      show_alert('Youtube Enhancer - Check Update: Last='+Updater_Date+' / Now='+Date_Now,0);
      if(data.status!=200) { show_alert('Update check failed: HTTP Error '+data.status,0); return; }
      res=data.responseText.match(/\@name\s+YouTube\s+Enhancer/i);
      if(!res) { GM_setValue("Youtube_Enhancer_Updater_Date", Date_Now); return; }
      res=data.responseText.match(/\@namespace\s+https?\:\/\/userscripts\.org\/scripts\/show\/(\d+)/i);
      if(!res) { GM_setValue("Youtube_Enhancer_Updater_Date", Date_Now); return; }
      if(res[1]!=scriptid) { return; }
      res=data.responseText.match(/\@uso\:script\s+(\d+)/i);
      if(!res) { return; }
      if(res[1]!=scriptid) { return; }
      res=data.responseText.match(/\@uso\:version\s+(\d+)/i);
      if(!res) { return; }
      res=res[1];
      if(res==Updater_Version) {
        show_alert('Youtube Enhancer - No change / Current_Version='+res,0);
        GM_setValue("Youtube_Enhancer_Updater_Date", Date_Now)
        return;
      }

      if(Updater_Version==YOUTUBE_ENHANCER_UPDATER_STATUS) {
        show_alert('Youtube Enhancer - Updater Enabled / Current_Version='+res,0);
        GM_setValue("Youtube_Enhancer_Updater_Version", res)
        GM_setValue("Youtube_Enhancer_Updater_Date", Date_Now)
        show_messageBox('Youtube Enhancer - '+HtmlUnicodeDecode(get_text_Updater(page_lang,"enab")));
      } else {
        show_alert('Youtube Enhancer - Update Found / Version: '+Updater_Version+' -> '+res,0);
        GM_setValue("Youtube_Enhancer_Updater_Version", res)
        GM_setValue("Youtube_Enhancer_Updater_Date", -Math.abs(Date_Now))
        YouTube_Enhancer_Update_Display(page_lang,Updater_url_dl,Date_Now);
      }
    }
  });
}

//************************************** Useful Sub-routines *********************************************//
function remove_watch_element(elementname) {
  if(check_on_youtube()) {
    var el=document.getElementById(elementname);
    if(el) { el.parentNode.removeChild(el); }
  }
}

function remove_watch_parent_element(elementname) {
  if(check_on_youtube()) {
    var el=document.getElementById(elementname);
    if(el) { var elp=el.parentNode; elp.parentNode.removeChild(elp); }
  }
}

function HtmlUnicodeDecode(str) {
  // Change HTML code "&#xxxxx;" to Unicode
  var out="";
  if(str==null) { return(out); }
  var l=str.length;
  for (var i=0; i<l; i++) {
    var ch=str.charAt(i);
    if(ch=='&') {
      var sci=str.indexOf(';',i+1);
      if(sci>0) {
        var entity=str.substring(i+1,sci);
        if(entity.length>1 && entity.charAt(0)=='#') {
          entity=entity.substring(1);
          if(entity.charAt(0).toLowerCase()=='x') { ch=String.fromCharCode(parseInt('0'+entity)); }
          else { ch=String.fromCharCode(parseInt(entity)); }
        } else {
          switch(entity) {
            case "nbsp": ch=String.fromCharCode(160);
          }
        }
        i=sci;
      }
    }
    out+=ch;
  }
  return out;
}

function getDisplayHeight(element) {
  var els = element.style;
  var oVisibility = els.visibility;
  var oPosition = els.position;
  var oDisplay = els.display;
  els.visibility = 'hidden';
  els.position = 'absolute';
  els.display = 'block';
  var Result = element.clientHeight;
  els.display = oDisplay;
  els.position = oPosition;
  els.visibility = oVisibility;
  return Result;
}

function getHeight(element) {
  //var Result=window.getComputedStyle(element,null).height.replace('px','');
  //if (Result=='auto') { Result = element.clientHeight; }
  return element.clientHeight;
}

function getWidth(element) {
  var Result = window.getComputedStyle(element,null).width.replace('px','');
  if (Result=='auto') { Result = element.clientWidth; }
  return Result;
}

function getAbsoluteLeft(element) {
  var AbsLeft = 0;
  while (element) { AbsLeft = AbsLeft + element.offsetLeft; element = element.offsetParent; }
  return(AbsLeft);
}

function getAbsoluteTop(element) {
  var AbsTop = 0;
  while (element) { AbsTop = AbsTop + element.offsetTop; element = element.offsetParent; }
  return(AbsTop);
}

function isPositiveInteger(value) { return (value.toString().search(/^\d+$/)==0); }

function isDefined(x)   { return !(x == null && x !== null); }
function isUndefined(x) { return x == null && x !== null;    }

function flushNode(el) { el.parentNode.replaceChild(el.cloneNode(true),el); }

function swap_display(element) {
  var els = element.style;
  if(els.display=="none") { els.display="block"; } else { els.display="none"; }
}

function user_select(element,value) {
  var els = element.style;
  if(isDefined(els.userSelect)) {els.userSelect=value;} // CSS3
  else if (isDefined(els.MozUserSelect)) {els.MozUserSelect=value;} // Mozilla
}

function GetLuminosity(color) {
  var rgb=color.match(/rgb\s*\(\s*(\d+)\s*\,\s*(\d+)\s*\,\s*(\d+)\s*\)/i);
  if (rgb) { return (rgb[1]+rgb[2]+rgb[3])/3; }
  rgb=color.match(/\#\s*([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})/i);
  if (rgb) { return (parseInt('0x'+rgb[1])+parseInt('0x'+rgb[2])+parseInt('0x'+rgb[3]))/3; }
  return 255;
}

function remove_element(element) { element.parentNode.removeChild(element); }

function show_messageBox(msg) {
  if ( top.location.href!=window.location.href ) { return; }
  var element=document.createElement('div');
  element.setAttribute('lang','fr');
  element.setAttribute("style","position:fixed; top:0px; left:0px; right:0px; z-index:9998; height:26px; font-family:arial,sans-serif; font-size:24px; line-height:24px; text-align:center; vertical-align:middle; color:#FFFFFF !important; background:#C080C0 !important; margin:2px; border: 3px solid #CC0088; border-right-width:24px;");
  element.textContent=msg;
  var aelem=document.createElement('a');
  aelem.setAttribute('style','position:absolute; top:0px; height:26px; width: 20px; right:-21px; text-decoration:none; cursor:pointer; color:#0000CC !important; background:#CC0088 !important;');
  aelem.textContent='X';
  element.appendChild(aelem);
  user_select(element,'none');
  document.body.appendChild(element);
  aelem.addEventListener('click', function() { remove_element(element); }, true);
}

function show_alert(msg, force) {
  if(arguments.callee.counter) { arguments.callee.counter++; } else { arguments.callee.counter=1; }
  GM_log('('+arguments.callee.counter+') '+msg);
  if(force==0) { return; }
  // Show a HTML alert box (only for watch pages or if forced)
  if(force==1 || check_on_youtubewatchpage()) {
    warningelem=document.createElement('div');
    warningelem.setAttribute("style","color:#FFFFFF; background:#FF8000; width:auto; text-align:center; font-size:24px; border: 3px solid #CC0088; margin:2px;");
    warningelem.textContent=msg;
    document.body.insertBefore(warningelem, document.body.firstChild);
  }
}

/******************************************** Licence ******************************************************
*** Creative Commons 3.0                                                                                 ***
*** by: BY-attribution (Requirement to acknowledge or credit the author "GIJoe")                         ***
*** nc: Non-Commercial (Use for commercial purpose is forbidden)                                         ***
*** sa: Share Alike    (Derivative works must be under the same or similar license to this one)          ***
***********************************************************************************************************/

//******************************************* Main() *****************************************************//
function mediacontrollermenu() {
  var page_lang="www";
  try { page_lang=get_page_lang();       } catch(err) { show_alert('Initialisation failed: '+err); }
  try { add_media_controller(page_lang); } catch(err) { show_alert('media_controller => '   +err); }
}

function main() {
  // Clear onYouTubePlayerReady
  unsafeWindow.onYouTubePlayerReady=function() {};

  // Bind event for loop and autoplay (YouTube Watch pages only)
  try { bind_movie_player_event(); } catch(err) { show_alert('bind_movie_player_event => '+err); }

  // Get page info
  var page_lang="www"; var page_fmt=0;
  try { page_fmt=get_page_fmt(); page_lang=get_page_lang(); } catch(err) { show_alert('Initialisation failed: '+err); }

  // Miscellaneous (remove unneeded items)
  remove_watch_parent_element(WATCH_PROMOTED);
  remove_watch_element(DEFAULT_LANG_BOX);

  // change_links (part of Quality Selector) (image_preview_rollover included) (change_links must be the first to run)
  try { change_links(page_fmt);                    } catch(err) { show_alert('change_links => '    +err); }
  // Download Link    (YouTube Watch pages only)
  try { add_download_link(page_lang, page_fmt);    } catch(err) { show_alert('download_link => '   +err); }
  // Quality Selector (YouTube Watch pages only)
  try { add_quality_selector(page_lang, page_fmt); } catch(err) { show_alert('quality_selector => '+err); }
  // Media Controller
  try { add_media_controller(page_lang);           } catch(err) { show_alert('media_controller => '+err); }

  // Add menu to rebind Media Controller
  GM_registerMenuCommand("Media Controller - Rebind", mediacontrollermenu );

  // Update check
  try { YouTube_Enhancer_Updater(page_lang);       } catch(err) { show_alert('YouTube_Enhancer_Updater => '+err); }
}
main();

} )();
// ]]>