FV Flowplayer Video Player - Version 6.5

Version Description

  • 2018/03/14 =

  • New feature - Video position saving for both guest and logged in users - see Settings -> FV Player -> Sidewide Flowplayer Defaults -> Remember video position

  • Custom video fields are now easy to add with the FV_Player_MetaBox PHP class

  • DASH - updating to latest tested Dash.js version

  • Bugfix - iframe embed code placing body closing tag in bad place

  • Bugfix - fix for PHP warnings on AMP pages

  • Bugfix - Shortcode editor bug when you select the subtitle language and it adds the subtitles twice

  • Bugfix - Subtitles in playlist - making sure multilingual subtitles work for the first item at least

Download this release

Release Info

Developer FolioVision
Plugin Icon 128x128 FV Flowplayer Video Player
Version 6.5
Comparing to
See all releases

Code changes from version 6.4.2 to 6.5

composer.json ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ {
2
+ "require-dev": {
3
+ "mockery/mockery": "dev-master"
4
+ }
5
+ }
controller/editor.php CHANGED
@@ -7,13 +7,18 @@ function fv_player_shortcode_editor_scripts( $page ) {
7
  return;
8
  }
9
 
 
 
 
 
 
 
 
10
  global $fv_wp_flowplayer_ver;
11
-
12
-
13
  wp_register_script('fvwpflowplayer-domwindow', flowplayer::get_plugin_url().'/js/jquery.colorbox-min.js',array('jquery'), $fv_wp_flowplayer_ver );
14
  wp_enqueue_script('fvwpflowplayer-domwindow');
15
 
16
- wp_register_script('fvwpflowplayer-shortcode-editor', flowplayer::get_plugin_url().'/js/shortcode-editor.js',array('jquery'), $fv_wp_flowplayer_ver );
17
  wp_register_script('fvwpflowplayer-shortcode-editor-old', flowplayer::get_plugin_url().'/js/shortcode-editor.old.js',array('jquery'), $fv_wp_flowplayer_ver );
18
 
19
  global $fv_fp;
7
  return;
8
  }
9
 
10
+ fv_player_shortcode_editor_scripts_enqueue();
11
+ }
12
+
13
+
14
+
15
+
16
+ function fv_player_shortcode_editor_scripts_enqueue() {
17
  global $fv_wp_flowplayer_ver;
 
 
18
  wp_register_script('fvwpflowplayer-domwindow', flowplayer::get_plugin_url().'/js/jquery.colorbox-min.js',array('jquery'), $fv_wp_flowplayer_ver );
19
  wp_enqueue_script('fvwpflowplayer-domwindow');
20
 
21
+ wp_register_script('fvwpflowplayer-shortcode-editor', flowplayer::get_plugin_url().'/js/shortcode-editor.js',array('jquery','jquery-ui-sortable'), $fv_wp_flowplayer_ver );
22
  wp_register_script('fvwpflowplayer-shortcode-editor-old', flowplayer::get_plugin_url().'/js/shortcode-editor.old.js',array('jquery'), $fv_wp_flowplayer_ver );
23
 
24
  global $fv_fp;
controller/frontend.php CHANGED
@@ -357,6 +357,12 @@ function flowplayer_prepare_scripts() {
357
  $aConf['mobile_native_fullscreen'] = $fv_fp->_get_option('mobile_native_fullscreen');
358
  $aConf['mobile_force_fullscreen'] = $fv_fp->_get_option('mobile_force_fullscreen');
359
 
 
 
 
 
 
 
360
  $aConf['sticky_video'] = $fv_fp->_get_option('sticky_video');
361
  $aConf['sticky_place'] = $fv_fp->_get_option('sticky_place');
362
  $aConf['sticky_width'] = $fv_fp->_get_option('sticky_width');
@@ -411,7 +417,7 @@ function flowplayer_prepare_scripts() {
411
  }
412
 
413
  global $FV_Player_lightbox;
414
- if( $FV_Player_lightbox->bLoad || $fv_fp->_get_option('lightbox_images') || $fv_fp->_get_option('js-everywhere') ) {
415
  $aConf = array();
416
  $aConf['lightbox_images'] = $fv_fp->_get_option('lightbox_images');
417
 
@@ -565,4 +571,3 @@ function fv_player_comment_text( $comment_text ) {
565
 
566
  return $comment_text;
567
  }
568
-
357
  $aConf['mobile_native_fullscreen'] = $fv_fp->_get_option('mobile_native_fullscreen');
358
  $aConf['mobile_force_fullscreen'] = $fv_fp->_get_option('mobile_force_fullscreen');
359
 
360
+ if ( $fv_fp->_get_option('video_position_save_enable') ) {
361
+ $aConf['video_position_save_enable'] = $fv_fp->_get_option('video_position_save_enable');
362
+ }
363
+
364
+ if( is_user_logged_in() ) $aConf['is_logged_in'] = true;
365
+
366
  $aConf['sticky_video'] = $fv_fp->_get_option('sticky_video');
367
  $aConf['sticky_place'] = $fv_fp->_get_option('sticky_place');
368
  $aConf['sticky_width'] = $fv_fp->_get_option('sticky_width');
417
  }
418
 
419
  global $FV_Player_lightbox;
420
+ if( isset($FV_Player_lightbox) && ( $FV_Player_lightbox->bLoad || $fv_fp->_get_option('lightbox_images') || $fv_fp->_get_option('js-everywhere') ) ) {
421
  $aConf = array();
422
  $aConf['lightbox_images'] = $fv_fp->_get_option('lightbox_images');
423
 
571
 
572
  return $comment_text;
573
  }
 
css/admin.css CHANGED
@@ -129,4 +129,6 @@ table.fv-player-popup-formats td:first-child { width: 72px }
129
  #fp-preview-wrapper>.flowplayer{position:relative; height:160px}
130
  #fp-preview-wrapper .fp-subtitle{height:50px}
131
 
132
- #dashboard-widgets .flowplayer-wrapper h3, #dashboard-widgets .flowplayer-wrapper h4 {color:inherit;margin:0 auto;padding:0;font-weight:700;font-size:inherit}
 
 
129
  #fp-preview-wrapper>.flowplayer{position:relative; height:160px}
130
  #fp-preview-wrapper .fp-subtitle{height:50px}
131
 
132
+ #dashboard-widgets .flowplayer-wrapper h3, #dashboard-widgets .flowplayer-wrapper h4 {color:inherit;margin:0 auto;padding:0;font-weight:700;font-size:inherit}
133
+
134
+ .fv-player-editor-wrapper { float: left }
css/flowplayer-beta.css CHANGED
@@ -1501,9 +1501,8 @@
1501
 
1502
 
1503
 
1504
- /* Alignment, todo: check! */
1505
- .flowplayer.alignleft { margin-left: 10px; margin-bottom: 10px; }
1506
- .flowplayer.alignright { margin-right: 10px; margin-bottom: 10px; }
1507
 
1508
 
1509
 
@@ -1872,7 +1871,6 @@ article .entry-content .fvfp_admin_error p { line-height: 18px }
1872
  .edd_form .fv-player-custom-video-list {
1873
  clear: both;
1874
  position: relative;
1875
- top: -26px;
1876
  }
1877
  a.fv-player-custom-video-add, a.fv-player-custom-video-remove {
1878
  margin: 0 6px 0 0;
@@ -1921,7 +1919,8 @@ body.fv_flowplayer_tabs_hide .fv_flowplayer_tabs_content > div.fv_flowplayer_tab
1921
  text-align: center;
1922
  }
1923
  .fv-fp-playlist .fvp-icon,
1924
- .fv-fp-playlist #fvp-playlist-play {
 
1925
  display: none;
1926
  }
1927
  .fv-fp-playlist.mode-repeat-playlist .fvp-icon.fvp-replay-list,
1501
 
1502
 
1503
 
1504
+ .flowplayer.alignleft { margin-right: 10px; margin-bottom: 10px; }
1505
+ .flowplayer.alignright { margin-left: 10px; margin-bottom: 10px; }
 
1506
 
1507
 
1508
 
1871
  .edd_form .fv-player-custom-video-list {
1872
  clear: both;
1873
  position: relative;
 
1874
  }
1875
  a.fv-player-custom-video-add, a.fv-player-custom-video-remove {
1876
  margin: 0 6px 0 0;
1919
  text-align: center;
1920
  }
1921
  .fv-fp-playlist .fvp-icon,
1922
+ .fv-fp-playlist #fvp-playlist-play,
1923
+ .flowplayer .fp-menu.fv-fp-playlist-menu .fp-selected::before {
1924
  display: none;
1925
  }
1926
  .fv-fp-playlist.mode-repeat-playlist .fvp-icon.fvp-replay-list,
css/flowplayer.css CHANGED
@@ -1068,7 +1068,6 @@ body.fv_flowplayer_tabs_hide .fv_flowplayer_tabs_content > div.fv_flowplayer_tab
1068
  .edd_form .fv-player-custom-video-list {
1069
  clear: both;
1070
  position: relative;
1071
- top: -26px;
1072
  }
1073
  a.fv-player-custom-video-add, a.fv-player-custom-video-remove {
1074
  margin: 0 6px 0 0;
1068
  .edd_form .fv-player-custom-video-list {
1069
  clear: both;
1070
  position: relative;
 
1071
  }
1072
  a.fv-player-custom-video-add, a.fv-player-custom-video-remove {
1073
  margin: 0 6px 0 0;
flowplayer-beta/fv-flowplayer.min.js CHANGED
@@ -10,6 +10,8 @@ for(n=0;n<t.length;n++)t[n]&&(e[t[n]]=1);return e}({},g(y+(f?w:""))),I=function(
10
  if(this instanceof r){var e=w.call(n,this,m.call(o,d.call(arguments)));return i(e)===e?e:this}return w.call(n,t,m.call(o,d.call(arguments)))},l=b(0,n.length-o.length),u=[],c=0;l>c;c++)h.call(u,"$"+c);return r=a("binder","return function ("+v.call(u,",")+"){ return binder.apply(this, arguments); }")(s),n.prototype&&(U.prototype=n.prototype,r.prototype=new U,U.prototype=null),r}});var J=y.bind(o.hasOwnProperty),B=y.bind(o.toString),F=y.bind(d),H=w.bind(d);if("object"==typeof document&&document&&document.documentElement)try{F(document.documentElement.childNodes)}catch(V){var X=F,_=H;F=function(e){for(var t=[],n=e.length;n-->0;)t[n]=e[n];return _(t,X(arguments,1))},H=function(e,t){return _(F(e),t)}}var K=y.bind(u.slice),Q=y.bind(u.split),q=y.bind(u.indexOf),$=y.bind(h),ee=y.bind(o.propertyIsEnumerable),te=y.bind(r.sort),ne=n.isArray||function(e){return"[object Array]"===B(e)},re=1!==[].unshift(0);O(r,{unshift:function(){return g.apply(this,arguments),this.length}},re),O(n,{isArray:ne});var ie=i("a"),oe="a"!==ie[0]||!(0 in ie),ae=function(e){var t=!0,n=!0,r=!1;if(e)try{e.call("foo",function(e,n,r){"object"!=typeof r&&(t=!1)}),e.call([1],function(){"use strict";n="string"==typeof this},"x")}catch(i){r=!0}return!!e&&!r&&t&&n};O(r,{forEach:function(t){var n,r=W.ToObject(this),i=oe&&Z(this)?Q(this,""):r,o=-1,a=W.ToUint32(i.length);if(arguments.length>1&&(n=arguments[1]),!e(t))throw new TypeError("Array.prototype.forEach callback must be a function");for(;++o<a;)o in i&&("undefined"==typeof n?t(i[o],o,r):t.call(n,i[o],o,r))}},!ae(r.forEach)),O(r,{map:function(t){var r,i=W.ToObject(this),o=oe&&Z(this)?Q(this,""):i,a=W.ToUint32(o.length),s=n(a);if(arguments.length>1&&(r=arguments[1]),!e(t))throw new TypeError("Array.prototype.map callback must be a function");for(var l=0;a>l;l++)l in o&&("undefined"==typeof r?s[l]=t(o[l],l,i):s[l]=t.call(r,o[l],l,i));return s}},!ae(r.map)),O(r,{filter:function(t){var n,r,i=W.ToObject(this),o=oe&&Z(this)?Q(this,""):i,a=W.ToUint32(o.length),s=[];if(arguments.length>1&&(r=arguments[1]),!e(t))throw new TypeError("Array.prototype.filter callback must be a function");for(var l=0;a>l;l++)l in o&&(n=o[l],("undefined"==typeof r?t(n,l,i):t.call(r,n,l,i))&&$(s,n));return s}},!ae(r.filter)),O(r,{every:function(t){var n,r=W.ToObject(this),i=oe&&Z(this)?Q(this,""):r,o=W.ToUint32(i.length);if(arguments.length>1&&(n=arguments[1]),!e(t))throw new TypeError("Array.prototype.every callback must be a function");for(var a=0;o>a;a++)if(a in i&&!("undefined"==typeof n?t(i[a],a,r):t.call(n,i[a],a,r)))return!1;return!0}},!ae(r.every)),O(r,{some:function(t){var n,r=W.ToObject(this),i=oe&&Z(this)?Q(this,""):r,o=W.ToUint32(i.length);if(arguments.length>1&&(n=arguments[1]),!e(t))throw new TypeError("Array.prototype.some callback must be a function");for(var a=0;o>a;a++)if(a in i&&("undefined"==typeof n?t(i[a],a,r):t.call(n,i[a],a,r)))return!0;return!1}},!ae(r.some));var se=!1;r.reduce&&(se="object"==typeof r.reduce.call("es5",function(e,t,n,r){return r})),O(r,{reduce:function(t){var n=W.ToObject(this),r=oe&&Z(this)?Q(this,""):n,i=W.ToUint32(r.length);if(!e(t))throw new TypeError("Array.prototype.reduce callback must be a function");if(0===i&&1===arguments.length)throw new TypeError("reduce of empty array with no initial value");var o,a=0;if(arguments.length>=2)o=arguments[1];else for(;;){if(a in r){o=r[a++];break}if(++a>=i)throw new TypeError("reduce of empty array with no initial value")}for(;i>a;a++)a in r&&(o=t(o,r[a],a,n));return o}},!se);var le=!1;r.reduceRight&&(le="object"==typeof r.reduceRight.call("es5",function(e,t,n,r){return r})),O(r,{reduceRight:function(t){var n=W.ToObject(this),r=oe&&Z(this)?Q(this,""):n,i=W.ToUint32(r.length);if(!e(t))throw new TypeError("Array.prototype.reduceRight callback must be a function");if(0===i&&1===arguments.length)throw new TypeError("reduceRight of empty array with no initial value");var o,a=i-1;if(arguments.length>=2)o=arguments[1];else for(;;){if(a in r){o=r[a--];break}if(--a<0)throw new TypeError("reduceRight of empty array with no initial value")}if(0>a)return o;do a in r&&(o=t(o,r[a],a,n));while(a--);return o}},!le);var ue=r.indexOf&&-1!==[0,1].indexOf(1,2);O(r,{indexOf:function(e){var t=oe&&Z(this)?Q(this,""):W.ToObject(this),n=W.ToUint32(t.length);if(0===n)return-1;var r=0;for(arguments.length>1&&(r=W.ToInteger(arguments[1])),r=r>=0?r:b(0,n+r);n>r;r++)if(r in t&&t[r]===e)return r;return-1}},ue);var ce=r.lastIndexOf&&-1!==[0,1].lastIndexOf(0,-3);O(r,{lastIndexOf:function(e){var t=oe&&Z(this)?Q(this,""):W.ToObject(this),n=W.ToUint32(t.length);if(0===n)return-1;var r=n-1;for(arguments.length>1&&(r=I(r,W.ToInteger(arguments[1]))),r=r>=0?r:n-Math.abs(r);r>=0;r--)if(r in t&&e===t[r])return r;return-1}},ce);var fe=function(){var e=[1,2],t=e.splice();return 2===e.length&&ne(t)&&0===t.length}();O(r,{splice:function(e,t){return 0===arguments.length?[]:p.apply(this,arguments)}},!fe);var de=function(){var e={};return r.splice.call(e,0,0,1),1===e.length}();O(r,{splice:function(e,t){if(0===arguments.length)return[];var n=arguments;return this.length=b(W.ToInteger(this.length),0),arguments.length>0&&"number"!=typeof t&&(n=F(arguments),n.length<2?$(n,this.length-e):n[1]=W.ToInteger(t)),p.apply(this,n)}},!de);var pe=function(){var e=new n(1e5);return e[8]="x",e.splice(1,1),7===e.indexOf("x")}(),he=function(){var e=256,t=[];return t[e]="a",t.splice(e+1,0,"b"),"a"===t[e]}();O(r,{splice:function(e,t){for(var n,r=W.ToObject(this),i=[],o=W.ToUint32(r.length),a=W.ToInteger(e),s=0>a?b(o+a,0):I(a,o),u=I(b(W.ToInteger(t),0),o-s),c=0;u>c;)n=l(s+c),J(r,n)&&(i[c]=r[n]),c+=1;var f,d=F(arguments,2),p=d.length;if(u>p){c=s;for(var h=o-u;h>c;)n=l(c+u),f=l(c+p),J(r,n)?r[f]=r[n]:delete r[f],c+=1;c=o;for(var g=o-u+p;c>g;)delete r[c-1],c-=1}else if(p>u)for(c=o-u;c>s;)n=l(c+u-1),f=l(c+p-1),J(r,n)?r[f]=r[n]:delete r[f],c-=1;c=s;for(var m=0;m<d.length;++m)r[c]=d[m],c+=1;return r.length=o-u+p,i}},!pe||!he);var ge,me=r.join;try{ge="1,2,3"!==Array.prototype.join.call("123",",")}catch(V){ge=!0}ge&&O(r,{join:function(e){var t="undefined"==typeof e?",":e;return me.call(Z(this)?Q(this,""):this,t)}},ge);var ve="1,2"!==[1,2].join(void 0);ve&&O(r,{join:function(e){var t="undefined"==typeof e?",":e;return me.call(this,t)}},ve);var ye=function(e){for(var t=W.ToObject(this),n=W.ToUint32(t.length),r=0;r<arguments.length;)t[n+r]=arguments[r],r+=1;return t.length=n+r,n+r},we=function(){var e={},t=Array.prototype.push.call(e,void 0);return 1!==t||1!==e.length||"undefined"!=typeof e[0]||!J(e,0)}();O(r,{push:function(e){return ne(this)?h.apply(this,arguments):ye.apply(this,arguments)}},we);var be=function(){var e=[],t=e.push(void 0);return 1!==t||1!==e.length||"undefined"!=typeof e[0]||!J(e,0)}();O(r,{push:ye},be),O(r,{slice:function(e,t){var n=Z(this)?Q(this,""):this;return H(n,arguments)}},oe);var Ie=function(){try{[1,2].sort(null)}catch(e){try{[1,2].sort({})}catch(t){return!1}}return!0}(),Me=function(){try{return[1,2].sort(/a/),!1}catch(e){}return!0}(),Ce=function(){try{return[1,2].sort(void 0),!0}catch(e){}return!1}();O(r,{sort:function(t){if("undefined"==typeof t)return te(this);if(!e(t))throw new TypeError("Array.prototype.sort callback must be a function");return te(this,t)}},Ie||!Ce||!Me);var Ae=!ee({toString:null},"toString"),Se=ee(function(){},"prototype"),Ee=!J("x","0"),je=function(e){var t=e.constructor;return t&&t.prototype===e},De={$window:!0,$console:!0,$parent:!0,$self:!0,$frame:!0,$frames:!0,$frameElement:!0,$webkitIndexedDB:!0,$webkitStorageInfo:!0,$external:!0,$width:!0,$height:!0,$top:!0,$localStorage:!0},Ne=function(){if("undefined"==typeof window)return!1;for(var e in window)try{!De["$"+e]&&J(window,e)&&null!==window[e]&&"object"==typeof window[e]&&je(window[e])}catch(t){return!0}return!1}(),Le=function(e){if("undefined"==typeof window||!Ne)return je(e);try{return je(e)}catch(t){return!1}},xe=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],Te=xe.length,Ze=function(e){return"[object Arguments]"===B(e)},Pe=function(t){return null!==t&&"object"==typeof t&&"number"==typeof t.length&&t.length>=0&&!ne(t)&&e(t.callee)},ke=Ze(arguments)?Ze:Pe;O(i,{keys:function(t){var n=e(t),r=ke(t),i=null!==t&&"object"==typeof t,o=i&&Z(t);if(!i&&!n&&!r)throw new TypeError("Object.keys called on a non-object");var a=[],s=Se&&n;if(o&&Ee||r)for(var u=0;u<t.length;++u)$(a,l(u));if(!r)for(var c in t)s&&"prototype"===c||!J(t,c)||$(a,l(c));if(Ae)for(var f=Le(t),d=0;Te>d;d++){var p=xe[d];f&&"constructor"===p||!J(t,p)||$(a,p)}return a}});var Ye=i.keys&&function(){return 2===i.keys(arguments).length}(1,2),ze=i.keys&&function(){var e=i.keys(arguments);return 1!==arguments.length||1!==e.length||1!==e[0]}(1),Oe=i.keys;O(i,{keys:function(e){return Oe(ke(e)?F(e):e)}},!Ye||ze);var Ge,Re,We=0!==new Date(-0xc782b5b342b24).getUTCMonth(),Ue=new Date(-0x55d318d56a724),Je=new Date(14496624e5),Be="Mon, 01 Jan -45875 11:59:59 GMT"!==Ue.toUTCString(),Fe=Ue.getTimezoneOffset();-720>Fe?(Ge="Tue Jan 02 -45875"!==Ue.toDateString(),Re=!/^Thu Dec 10 2015 \d\d:\d\d:\d\d GMT[-+]\d\d\d\d(?: |$)/.test(String(Je))):(Ge="Mon Jan 01 -45875"!==Ue.toDateString(),Re=!/^Wed Dec 09 2015 \d\d:\d\d:\d\d GMT[-+]\d\d\d\d(?: |$)/.test(String(Je)));var He=y.bind(Date.prototype.getFullYear),Ve=y.bind(Date.prototype.getMonth),Xe=y.bind(Date.prototype.getDate),_e=y.bind(Date.prototype.getUTCFullYear),Ke=y.bind(Date.prototype.getUTCMonth),Qe=y.bind(Date.prototype.getUTCDate),qe=y.bind(Date.prototype.getUTCDay),$e=y.bind(Date.prototype.getUTCHours),et=y.bind(Date.prototype.getUTCMinutes),tt=y.bind(Date.prototype.getUTCSeconds),nt=y.bind(Date.prototype.getUTCMilliseconds),rt=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],it=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],ot=function(e,t){return Xe(new Date(t,e,0))};O(Date.prototype,{getFullYear:function(){if(!(this&&this instanceof Date))throw new TypeError("this is not a Date object.");var e=He(this);return 0>e&&Ve(this)>11?e+1:e},getMonth:function(){if(!(this&&this instanceof Date))throw new TypeError("this is not a Date object.");var e=He(this),t=Ve(this);return 0>e&&t>11?0:t},getDate:function(){if(!(this&&this instanceof Date))throw new TypeError("this is not a Date object.");var e=He(this),t=Ve(this),n=Xe(this);if(0>e&&t>11){if(12===t)return n;var r=ot(0,e+1);return r-n+1}return n},getUTCFullYear:function(){if(!(this&&this instanceof Date))throw new TypeError("this is not a Date object.");var e=_e(this);return 0>e&&Ke(this)>11?e+1:e},getUTCMonth:function(){if(!(this&&this instanceof Date))throw new TypeError("this is not a Date object.");var e=_e(this),t=Ke(this);return 0>e&&t>11?0:t},getUTCDate:function(){if(!(this&&this instanceof Date))throw new TypeError("this is not a Date object.");var e=_e(this),t=Ke(this),n=Qe(this);if(0>e&&t>11){if(12===t)return n;var r=ot(0,e+1);return r-n+1}return n}},We),O(Date.prototype,{toUTCString:function(){if(!(this&&this instanceof Date))throw new TypeError("this is not a Date object.");var e=qe(this),t=Qe(this),n=Ke(this),r=_e(this),i=$e(this),o=et(this),a=tt(this);return rt[e]+", "+(10>t?"0"+t:t)+" "+it[n]+" "+r+" "+(10>i?"0"+i:i)+":"+(10>o?"0"+o:o)+":"+(10>a?"0"+a:a)+" GMT"}},We||Be),O(Date.prototype,{toDateString:function(){if(!(this&&this instanceof Date))throw new TypeError("this is not a Date object.");var e=this.getDay(),t=this.getDate(),n=this.getMonth(),r=this.getFullYear();return rt[e]+" "+it[n]+" "+(10>t?"0"+t:t)+" "+r}},We||Ge),(We||Re)&&(Date.prototype.toString=function(){if(!(this&&this instanceof Date))throw new TypeError("this is not a Date object.");var e=this.getDay(),t=this.getDate(),n=this.getMonth(),r=this.getFullYear(),i=this.getHours(),o=this.getMinutes(),a=this.getSeconds(),s=this.getTimezoneOffset(),l=Math.floor(Math.abs(s)/60),u=Math.floor(Math.abs(s)%60);return rt[e]+" "+it[n]+" "+(10>t?"0"+t:t)+" "+r+" "+(10>i?"0"+i:i)+":"+(10>o?"0"+o:o)+":"+(10>a?"0"+a:a)+" GMT"+(s>0?"-":"+")+(10>l?"0"+l:l)+(10>u?"0"+u:u)},z&&i.defineProperty(Date.prototype,"toString",{configurable:!0,enumerable:!1,writable:!0}));var at=-621987552e5,st="-000001",lt=Date.prototype.toISOString&&-1===new Date(at).toISOString().indexOf(st),ut=Date.prototype.toISOString&&"1969-12-31T23:59:59.999Z"!==new Date(-1).toISOString(),ct=y.bind(Date.prototype.getTime);O(Date.prototype,{toISOString:function(){if(!isFinite(this)||!isFinite(ct(this)))throw new RangeError("Date.prototype.toISOString called on non-finite value.");var e=_e(this),t=Ke(this);e+=Math.floor(t/12),t=(t%12+12)%12;var n=[t+1,Qe(this),$e(this),et(this),tt(this)];e=(0>e?"-":e>9999?"+":"")+K("00000"+Math.abs(e),e>=0&&9999>=e?-4:-6);for(var r=0;r<n.length;++r)n[r]=K("00"+n[r],-2);return e+"-"+F(n,0,2).join("-")+"T"+F(n,2).join(":")+"."+K("000"+nt(this),-3)+"Z"}},lt||ut);var ft=function(){try{return Date.prototype.toJSON&&null===new Date(NaN).toJSON()&&-1!==new Date(at).toJSON().indexOf(st)&&Date.prototype.toJSON.call({toISOString:function(){return!0}})}catch(e){return!1}}();ft||(Date.prototype.toJSON=function(t){var n=i(this),r=W.ToPrimitive(n);if("number"==typeof r&&!isFinite(r))return null;var o=n.toISOString;if(!e(o))throw new TypeError("toISOString property is not callable");return o.call(n)});var dt=1e15===Date.parse("+033658-09-27T01:46:40.000Z"),pt=!isNaN(Date.parse("2012-04-04T24:00:00.500Z"))||!isNaN(Date.parse("2012-11-31T23:59:59.000Z"))||!isNaN(Date.parse("2012-12-31T23:59:60.000Z")),ht=isNaN(Date.parse("2000-01-01T00:00:00.000Z"));if(ht||pt||!dt){var gt=Math.pow(2,31)-1,mt=R(new Date(1970,0,1,0,0,0,gt+1).getTime());Date=function(e){var t=function(n,r,i,o,a,s,u){var c,f=arguments.length;if(this instanceof e){var d=s,p=u;if(mt&&f>=7&&u>gt){var h=Math.floor(u/gt)*gt,g=Math.floor(h/1e3);d+=g,p-=1e3*g}c=1===f&&l(n)===n?new e(t.parse(n)):f>=7?new e(n,r,i,o,a,d,p):f>=6?new e(n,r,i,o,a,d):f>=5?new e(n,r,i,o,a):f>=4?new e(n,r,i,o):f>=3?new e(n,r,i):f>=2?new e(n,r):f>=1?new e(n instanceof e?+n:n):new e}else c=e.apply(this,arguments);return G(c)||O(c,{constructor:t},!0),c},n=new RegExp("^(\\d{4}|[+-]\\d{6})(?:-(\\d{2})(?:-(\\d{2})(?:T(\\d{2}):(\\d{2})(?::(\\d{2})(?:(\\.\\d{1,}))?)?(Z|(?:([-+])(\\d{2}):(\\d{2})))?)?)?)?$"),r=[0,31,59,90,120,151,181,212,243,273,304,334,365],i=function(e,t){var n=t>1?1:0;return r[t]+Math.floor((e-1969+n)/4)-Math.floor((e-1901+n)/100)+Math.floor((e-1601+n)/400)+365*(e-1970)},o=function(t){var n=0,r=t;if(mt&&r>gt){var i=Math.floor(r/gt)*gt,o=Math.floor(i/1e3);n+=o,r-=1e3*o}return c(new e(1970,0,1,0,0,n,r))};for(var a in e)J(e,a)&&(t[a]=e[a]);O(t,{now:e.now,UTC:e.UTC},!0),t.prototype=e.prototype,O(t.prototype,{constructor:t},!0);var s=function(t){var r=n.exec(t);if(r){var a,s=c(r[1]),l=c(r[2]||1)-1,u=c(r[3]||1)-1,f=c(r[4]||0),d=c(r[5]||0),p=c(r[6]||0),h=Math.floor(1e3*c(r[7]||0)),g=Boolean(r[4]&&!r[8]),m="-"===r[9]?1:-1,v=c(r[10]||0),y=c(r[11]||0),w=d>0||p>0||h>0;return(w?24:25)>f&&60>d&&60>p&&1e3>h&&l>-1&&12>l&&24>v&&60>y&&u>-1&&u<i(s,l+1)-i(s,l)&&(a=60*(24*(i(s,l)+u)+f+v*m),a=1e3*(60*(a+d+y*m)+p)+h,g&&(a=o(a)),a>=-864e13&&864e13>=a)?a:NaN}return e.parse.apply(this,arguments)};return O(t,{parse:s}),t}(Date)}Date.now||(Date.now=function(){return(new Date).getTime()});var vt=f.toFixed&&("0.000"!==8e-5.toFixed(3)||"1"!==.9.toFixed(0)||"1.25"!==1.255.toFixed(2)||"1000000000000000128"!==0xde0b6b3a7640080.toFixed(0)),yt={base:1e7,size:6,data:[0,0,0,0,0,0],multiply:function(e,t){for(var n=-1,r=t;++n<yt.size;)r+=e*yt.data[n],yt.data[n]=r%yt.base,r=Math.floor(r/yt.base)},divide:function(e){for(var t=yt.size,n=0;--t>=0;)n+=yt.data[t],yt.data[t]=Math.floor(n/e),n=n%e*yt.base},numToString:function(){for(var e=yt.size,t="";--e>=0;)if(""!==t||0===e||0!==yt.data[e]){var n=l(yt.data[e]);""===t?t=n:t+=K("0000000",0,7-n.length)+n}return t},pow:function Ot(e,t,n){return 0===t?n:t%2===1?Ot(e,t-1,n*e):Ot(e*e,t/2,n)},log:function(e){for(var t=0,n=e;n>=4096;)t+=12,n/=4096;for(;n>=2;)t+=1,n/=2;return t}},wt=function(e){var t,n,r,i,o,a,s,u;if(t=c(e),t=R(t)?0:Math.floor(t),0>t||t>20)throw new RangeError("Number.toFixed called with invalid number of decimals");if(n=c(this),R(n))return"NaN";if(-1e21>=n||n>=1e21)return l(n);if(r="",0>n&&(r="-",n=-n),i="0",n>1e-21)if(o=yt.log(n*yt.pow(2,69,1))-69,a=0>o?n*yt.pow(2,-o,1):n/yt.pow(2,o,1),a*=4503599627370496,o=52-o,o>0){for(yt.multiply(0,a),s=t;s>=7;)yt.multiply(1e7,0),s-=7;for(yt.multiply(yt.pow(10,s,1),0),s=o-1;s>=23;)yt.divide(1<<23),s-=23;yt.divide(1<<s),yt.multiply(1,1),yt.divide(2),i=yt.numToString()}else yt.multiply(0,a),yt.multiply(1<<-o,0),i=yt.numToString()+K("0.00000000000000000000",2,2+t);return t>0?(u=i.length,i=t>=u?r+K("0.0000000000000000000",0,t-u+2)+i:r+K(i,0,u-t)+"."+K(i,u-t)):i=r+i,i};O(f,{toFixed:wt},vt);var bt=function(){try{return"1"===1..toPrecision(void 0)}catch(e){return!0}}(),It=f.toPrecision;O(f,{toPrecision:function(e){return"undefined"==typeof e?It.call(this):It.call(this,e)}},bt),2!=="ab".split(/(?:ab)*/).length||4!==".".split(/(.?)(.?)/).length||"t"==="tesst".split(/(s)*/)[1]||4!=="test".split(/(?:)/,-1).length||"".split(/.?/).length||".".split(/()()/).length>1?!function(){var e="undefined"==typeof/()??/.exec("")[1],n=Math.pow(2,32)-1;u.split=function(r,i){var o=String(this);if("undefined"==typeof r&&0===i)return[];if(!t(r))return Q(this,r,i);var a,s,l,u,c=[],f=(r.ignoreCase?"i":"")+(r.multiline?"m":"")+(r.unicode?"u":"")+(r.sticky?"y":""),d=0,p=new RegExp(r.source,f+"g");e||(a=new RegExp("^"+p.source+"$(?!\\s)",f));var g="undefined"==typeof i?n:W.ToUint32(i);for(s=p.exec(o);s&&(l=s.index+s[0].length,!(l>d&&($(c,K(o,d,s.index)),!e&&s.length>1&&s[0].replace(a,function(){for(var e=1;e<arguments.length-2;e++)"undefined"==typeof arguments[e]&&(s[e]=void 0)}),s.length>1&&s.index<o.length&&h.apply(c,F(s,1)),u=s[0].length,d=l,c.length>=g)));)p.lastIndex===s.index&&p.lastIndex++,s=p.exec(o);return d===o.length?(u||!p.test(""))&&$(c,""):$(c,K(o,d)),c.length>g?F(c,0,g):c}}():"0".split(void 0,0).length&&(u.split=function(e,t){return"undefined"==typeof e&&0===t?[]:Q(this,e,t)});var Mt=u.replace,Ct=function(){var e=[];return"x".replace(/x(.)?/g,function(t,n){$(e,n)}),1===e.length&&"undefined"==typeof e[0]}();Ct||(u.replace=function(n,r){var i=e(r),o=t(n)&&/\)[*?]/.test(n.source);if(i&&o){var a=function(e){var t=arguments.length,i=n.lastIndex;n.lastIndex=0;var o=n.exec(e)||[];return n.lastIndex=i,$(o,arguments[t-2],arguments[t-1]),r.apply(this,o)};return Mt.call(this,n,a)}return Mt.call(this,n,r)});var At=u.substr,St="".substr&&"b"!=="0b".substr(-1);O(u,{substr:function(e,t){var n=e;return 0>e&&(n=b(this.length+e,0)),At.call(this,n,t)}},St);var Et=" \n\f\r   ᠎              \u2028\u2029\ufeff",jt="​",Dt="["+Et+"]",Nt=new RegExp("^"+Dt+Dt+"*"),Lt=new RegExp(Dt+Dt+"*$"),xt=u.trim&&(Et.trim()||!jt.trim());O(u,{trim:function(){if("undefined"==typeof this||null===this)throw new TypeError("can't convert "+this+" to object");return l(this).replace(Nt,"").replace(Lt,"")}},xt);var Tt=y.bind(String.prototype.trim),Zt=u.lastIndexOf&&-1!=="abcあい".lastIndexOf("あい",2);O(u,{lastIndexOf:function(e){if("undefined"==typeof this||null===this)throw new TypeError("can't convert "+this+" to object");for(var t=l(this),n=l(e),r=arguments.length>1?c(arguments[1]):NaN,i=R(r)?1/0:W.ToInteger(r),o=I(b(i,0),t.length),a=n.length,s=o+a;s>0;){s=b(0,s-a);var u=q(K(t,s,o+a),n);if(-1!==u)return s+u}return-1}},Zt);var Pt=u.lastIndexOf;if(O(u,{lastIndexOf:function(e){return Pt.apply(this,arguments)}},1!==u.lastIndexOf.length),(8!==parseInt(Et+"08")||22!==parseInt(Et+"0x16"))&&(parseInt=function(e){var t=/^[-+]?0[xX]/;return function(n,r){var i=Tt(String(n)),o=c(r)||(t.test(i)?16:10);return e(i,o)}}(parseInt)),1/parseFloat("-0")!==-(1/0)&&(parseFloat=function(e){return function(t){var n=Tt(String(t)),r=e(n);return 0===r&&"-"===K(n,0,1)?-0:r}}(parseFloat)),"RangeError: test"!==String(new RangeError("test"))){var kt=function(){if("undefined"==typeof this||null===this)throw new TypeError("can't convert "+this+" to object");var e=this.name;"undefined"==typeof e?e="Error":"string"!=typeof e&&(e=l(e));var t=this.message;return"undefined"==typeof t?t="":"string"!=typeof t&&(t=l(t)),e?t?e+": "+t:e:t};Error.prototype.toString=kt}if(z){var Yt=function(e,t){if(ee(e,t)){var n=Object.getOwnPropertyDescriptor(e,t);n.configurable&&(n.enumerable=!1,Object.defineProperty(e,t,n))}};Yt(Error.prototype,"message"),""!==Error.prototype.message&&(Error.prototype.message=""),Yt(Error.prototype,"name")}if("/a/gim"!==String(/a/gim)){var zt=function(){var e="/"+this.source+"/";return this.global&&(e+="g"),this.ignoreCase&&(e+="i"),this.multiline&&(e+="m"),e};RegExp.prototype.toString=zt}})},{}],39:[function(e,t,n){var r=[],i=r.forEach,o=r.slice;t.exports=function(e){return i.call(o.call(arguments,1),function(t){if(t)for(var n in t)e[n]=t[n]}),e}},{}],40:[function(e,t,n){n.read=function(e,t,n,r,i){var o,a,s=8*i-r-1,l=(1<<s)-1,u=l>>1,c=-7,f=n?i-1:0,d=n?-1:1,p=e[t+f];for(f+=d,o=p&(1<<-c)-1,p>>=-c,c+=s;c>0;o=256*o+e[t+f],f+=d,c-=8);for(a=o&(1<<-c)-1,o>>=-c,c+=r;c>0;a=256*a+e[t+f],f+=d,c-=8);if(0===o)o=1-u;else{if(o===l)return a?NaN:(p?-1:1)*(1/0);a+=Math.pow(2,r),o-=u}return(p?-1:1)*a*Math.pow(2,o-r)},n.write=function(e,t,n,r,i,o){var a,s,l,u=8*o-i-1,c=(1<<u)-1,f=c>>1,d=23===i?Math.pow(2,-24)-Math.pow(2,-77):0,p=r?0:o-1,h=r?1:-1,g=0>t||0===t&&0>1/t?1:0;for(t=Math.abs(t),isNaN(t)||t===1/0?(s=isNaN(t)?1:0,a=c):(a=Math.floor(Math.log(t)/Math.LN2),t*(l=Math.pow(2,-a))<1&&(a--,l*=2),t+=a+f>=1?d/l:d*Math.pow(2,1-f),t*l>=2&&(a++,l/=2),a+f>=c?(s=0,a=c):a+f>=1?(s=(t*l-1)*Math.pow(2,i),a+=f):(s=t*Math.pow(2,f-1)*Math.pow(2,i),a=0));i>=8;e[n+p]=255&s,p+=h,s/=256,i-=8);for(a=a<<i|s,u+=i;u>0;e[n+p]=255&a,p+=h,a/=256,u-=8);e[n+p-h]|=128*g}},{}],41:[function(e,t,n){var r=[].indexOf;t.exports=function(e,t){if(r)return e.indexOf(t);for(var n=0;n<e.length;++n)if(e[n]===t)return n;return-1}},{}],42:[function(e,t,n){function r(e){var t=i.call(e);return"[object Function]"===t||"function"==typeof e&&"[object RegExp]"!==t||"undefined"!=typeof window&&(e===window.setTimeout||e===window.alert||e===window.confirm||e===window.prompt)}t.exports=r;var i=Object.prototype.toString},{}],43:[function(e,t,n){var r={}.toString;t.exports=Array.isArray||function(e){return"[object Array]"==r.call(e)}},{}],44:[function(t,n,r){(function(t){!function(i){function o(e){throw new RangeError(P[e])}function a(e,t){for(var n=e.length,r=[];n--;)r[n]=t(e[n]);return r}function s(e,t){var n=e.split("@"),r="";n.length>1&&(r=n[0]+"@",e=n[1]),e=e.replace(Z,".");var i=e.split("."),o=a(i,t).join(".");return r+o}function l(e){for(var t,n,r=[],i=0,o=e.length;o>i;)t=e.charCodeAt(i++),t>=55296&&56319>=t&&o>i?(n=e.charCodeAt(i++),56320==(64512&n)?r.push(((1023&t)<<10)+(1023&n)+65536):(r.push(t),i--)):r.push(t);return r}function u(e){return a(e,function(e){var t="";return e>65535&&(e-=65536,t+=z(e>>>10&1023|55296),e=56320|1023&e),t+=z(e)}).join("")}function c(e){return 10>e-48?e-22:26>e-65?e-65:26>e-97?e-97:C}function f(e,t){return e+22+75*(26>e)-((0!=t)<<5)}function d(e,t,n){var r=0;for(e=n?Y(e/j):e>>1,e+=Y(e/t);e>k*S>>1;r+=C)e=Y(e/k);return Y(r+(k+1)*e/(e+E))}function p(e){var t,n,r,i,a,s,l,f,p,h,g=[],m=e.length,v=0,y=N,w=D;for(n=e.lastIndexOf(L),0>n&&(n=0),r=0;n>r;++r)e.charCodeAt(r)>=128&&o("not-basic"),g.push(e.charCodeAt(r));for(i=n>0?n+1:0;m>i;){for(a=v,s=1,l=C;i>=m&&o("invalid-input"),f=c(e.charCodeAt(i++)),(f>=C||f>Y((M-v)/s))&&o("overflow"),v+=f*s,p=w>=l?A:l>=w+S?S:l-w,!(p>f);l+=C)h=C-p,s>Y(M/h)&&o("overflow"),s*=h;t=g.length+1,w=d(v-a,t,0==a),Y(v/t)>M-y&&o("overflow"),y+=Y(v/t),v%=t,g.splice(v++,0,y)}return u(g)}function h(e){var t,n,r,i,a,s,u,c,p,h,g,m,v,y,w,b=[];for(e=l(e),m=e.length,t=N,n=0,a=D,s=0;m>s;++s)g=e[s],128>g&&b.push(z(g));for(r=i=b.length,i&&b.push(L);m>r;){for(u=M,s=0;m>s;++s)g=e[s],g>=t&&u>g&&(u=g);for(v=r+1,u-t>Y((M-n)/v)&&o("overflow"),n+=(u-t)*v,t=u,s=0;m>s;++s)if(g=e[s],t>g&&++n>M&&o("overflow"),g==t){for(c=n,p=C;h=a>=p?A:p>=a+S?S:p-a,!(h>c);p+=C)w=c-h,y=C-h,b.push(z(f(h+w%y,0))),c=Y(w/y);b.push(z(f(c,0))),a=d(n,v,r==i),n=0,++r}++n,++t}return b.join("")}function g(e){return s(e,function(e){return x.test(e)?p(e.slice(4).toLowerCase()):e})}function m(e){return s(e,function(e){return T.test(e)?"xn--"+h(e):e})}var v="object"==typeof r&&r&&!r.nodeType&&r,y="object"==typeof n&&n&&!n.nodeType&&n,w="object"==typeof t&&t;(w.global===w||w.window===w||w.self===w)&&(i=w);var b,I,M=2147483647,C=36,A=1,S=26,E=38,j=700,D=72,N=128,L="-",x=/^xn--/,T=/[^\x20-\x7E]/,Z=/[\x2E\u3002\uFF0E\uFF61]/g,P={overflow:"Overflow: input needs wider integers to process","not-basic":"Illegal input >= 0x80 (not a basic code point)","invalid-input":"Invalid input"},k=C-A,Y=Math.floor,z=String.fromCharCode;if(b={version:"1.4.1",ucs2:{decode:l,encode:u},decode:p,encode:h,toASCII:m,toUnicode:g},"function"==typeof e&&"object"==typeof e.amd&&e.amd)e("punycode",function(){return b});else if(v&&y)if(n.exports==v)y.exports=b;else for(I in b)b.hasOwnProperty(I)&&(v[I]=b[I]);else i.punycode=b}(this)}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],45:[function(t,n,r){!function(t,r){"undefined"!=typeof n&&n.exports?n.exports=r():"function"==typeof e&&e.amd?e(r):this[t]=r()}("$script",function(){function e(e,t){for(var n=0,r=e.length;r>n;++n)if(!t(e[n]))return l;return 1}function t(t,n){e(t,function(e){return!n(e)})}function n(o,a,s){function l(e){return e.call?e():d[e]}function c(){if(!--y){d[v]=1,m&&m();for(var n in h)e(n.split("|"),l)&&!t(h[n],l)&&(h[n]=[])}}o=o[u]?o:[o];var f=a&&a.call,m=f?a:s,v=f?o.join(""):a,y=o.length;return setTimeout(function(){t(o,function e(t,n){return null===t?c():(n||/^https?:\/\//.test(t)||!i||(t=-1===t.indexOf(".js")?i+t+".js":i+t),g[t]?(v&&(p[v]=1),2==g[t]?c():setTimeout(function(){e(t,!0)},0)):(g[t]=1,v&&(p[v]=1),void r(t,c)))})},0),n}function r(e,t){var n,r=a.createElement("script");r.onload=r.onerror=r[f]=function(){r[c]&&!/^c|loade/.test(r[c])||n||(r.onload=r[f]=null,n=1,g[e]=2,t())},r.async=1,r.src=o?e+(-1===e.indexOf("?")?"?":"&")+o:e,s.insertBefore(r,s.lastChild)}var i,o,a=document,s=a.getElementsByTagName("head")[0],l=!1,u="push",c="readyState",f="onreadystatechange",d={},p={},h={},g={};return n.get=r,n.order=function(e,t,r){!function i(o){o=e.shift(),e.length?n(o,i):n(o,t,r)}()},n.path=function(e){i=e},n.urlArgs=function(e){o=e},n.ready=function(r,i,o){r=r[u]?r:[r];var a=[];return!t(r,function(e){d[e]||a[u](e)})&&e(r,function(e){return d[e]})?i():!function(e){h[e]=h[e]||[],h[e][u](i),o&&o(a)}(r.join("|")),n},n.done=function(e){n([null],e)},n})},{}]},{},[32])(32)});
11
 
12
 
 
 
13
 
14
 
15
  /*
@@ -2270,4 +2272,293 @@ jQuery(function($) {
2270
  $(document).on('click', "div.flowplayer.is-unSticky", function() {
2271
  $("div.flowplayer").removeClass("is-unSticky");
2272
  });
2273
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  if(this instanceof r){var e=w.call(n,this,m.call(o,d.call(arguments)));return i(e)===e?e:this}return w.call(n,t,m.call(o,d.call(arguments)))},l=b(0,n.length-o.length),u=[],c=0;l>c;c++)h.call(u,"$"+c);return r=a("binder","return function ("+v.call(u,",")+"){ return binder.apply(this, arguments); }")(s),n.prototype&&(U.prototype=n.prototype,r.prototype=new U,U.prototype=null),r}});var J=y.bind(o.hasOwnProperty),B=y.bind(o.toString),F=y.bind(d),H=w.bind(d);if("object"==typeof document&&document&&document.documentElement)try{F(document.documentElement.childNodes)}catch(V){var X=F,_=H;F=function(e){for(var t=[],n=e.length;n-->0;)t[n]=e[n];return _(t,X(arguments,1))},H=function(e,t){return _(F(e),t)}}var K=y.bind(u.slice),Q=y.bind(u.split),q=y.bind(u.indexOf),$=y.bind(h),ee=y.bind(o.propertyIsEnumerable),te=y.bind(r.sort),ne=n.isArray||function(e){return"[object Array]"===B(e)},re=1!==[].unshift(0);O(r,{unshift:function(){return g.apply(this,arguments),this.length}},re),O(n,{isArray:ne});var ie=i("a"),oe="a"!==ie[0]||!(0 in ie),ae=function(e){var t=!0,n=!0,r=!1;if(e)try{e.call("foo",function(e,n,r){"object"!=typeof r&&(t=!1)}),e.call([1],function(){"use strict";n="string"==typeof this},"x")}catch(i){r=!0}return!!e&&!r&&t&&n};O(r,{forEach:function(t){var n,r=W.ToObject(this),i=oe&&Z(this)?Q(this,""):r,o=-1,a=W.ToUint32(i.length);if(arguments.length>1&&(n=arguments[1]),!e(t))throw new TypeError("Array.prototype.forEach callback must be a function");for(;++o<a;)o in i&&("undefined"==typeof n?t(i[o],o,r):t.call(n,i[o],o,r))}},!ae(r.forEach)),O(r,{map:function(t){var r,i=W.ToObject(this),o=oe&&Z(this)?Q(this,""):i,a=W.ToUint32(o.length),s=n(a);if(arguments.length>1&&(r=arguments[1]),!e(t))throw new TypeError("Array.prototype.map callback must be a function");for(var l=0;a>l;l++)l in o&&("undefined"==typeof r?s[l]=t(o[l],l,i):s[l]=t.call(r,o[l],l,i));return s}},!ae(r.map)),O(r,{filter:function(t){var n,r,i=W.ToObject(this),o=oe&&Z(this)?Q(this,""):i,a=W.ToUint32(o.length),s=[];if(arguments.length>1&&(r=arguments[1]),!e(t))throw new TypeError("Array.prototype.filter callback must be a function");for(var l=0;a>l;l++)l in o&&(n=o[l],("undefined"==typeof r?t(n,l,i):t.call(r,n,l,i))&&$(s,n));return s}},!ae(r.filter)),O(r,{every:function(t){var n,r=W.ToObject(this),i=oe&&Z(this)?Q(this,""):r,o=W.ToUint32(i.length);if(arguments.length>1&&(n=arguments[1]),!e(t))throw new TypeError("Array.prototype.every callback must be a function");for(var a=0;o>a;a++)if(a in i&&!("undefined"==typeof n?t(i[a],a,r):t.call(n,i[a],a,r)))return!1;return!0}},!ae(r.every)),O(r,{some:function(t){var n,r=W.ToObject(this),i=oe&&Z(this)?Q(this,""):r,o=W.ToUint32(i.length);if(arguments.length>1&&(n=arguments[1]),!e(t))throw new TypeError("Array.prototype.some callback must be a function");for(var a=0;o>a;a++)if(a in i&&("undefined"==typeof n?t(i[a],a,r):t.call(n,i[a],a,r)))return!0;return!1}},!ae(r.some));var se=!1;r.reduce&&(se="object"==typeof r.reduce.call("es5",function(e,t,n,r){return r})),O(r,{reduce:function(t){var n=W.ToObject(this),r=oe&&Z(this)?Q(this,""):n,i=W.ToUint32(r.length);if(!e(t))throw new TypeError("Array.prototype.reduce callback must be a function");if(0===i&&1===arguments.length)throw new TypeError("reduce of empty array with no initial value");var o,a=0;if(arguments.length>=2)o=arguments[1];else for(;;){if(a in r){o=r[a++];break}if(++a>=i)throw new TypeError("reduce of empty array with no initial value")}for(;i>a;a++)a in r&&(o=t(o,r[a],a,n));return o}},!se);var le=!1;r.reduceRight&&(le="object"==typeof r.reduceRight.call("es5",function(e,t,n,r){return r})),O(r,{reduceRight:function(t){var n=W.ToObject(this),r=oe&&Z(this)?Q(this,""):n,i=W.ToUint32(r.length);if(!e(t))throw new TypeError("Array.prototype.reduceRight callback must be a function");if(0===i&&1===arguments.length)throw new TypeError("reduceRight of empty array with no initial value");var o,a=i-1;if(arguments.length>=2)o=arguments[1];else for(;;){if(a in r){o=r[a--];break}if(--a<0)throw new TypeError("reduceRight of empty array with no initial value")}if(0>a)return o;do a in r&&(o=t(o,r[a],a,n));while(a--);return o}},!le);var ue=r.indexOf&&-1!==[0,1].indexOf(1,2);O(r,{indexOf:function(e){var t=oe&&Z(this)?Q(this,""):W.ToObject(this),n=W.ToUint32(t.length);if(0===n)return-1;var r=0;for(arguments.length>1&&(r=W.ToInteger(arguments[1])),r=r>=0?r:b(0,n+r);n>r;r++)if(r in t&&t[r]===e)return r;return-1}},ue);var ce=r.lastIndexOf&&-1!==[0,1].lastIndexOf(0,-3);O(r,{lastIndexOf:function(e){var t=oe&&Z(this)?Q(this,""):W.ToObject(this),n=W.ToUint32(t.length);if(0===n)return-1;var r=n-1;for(arguments.length>1&&(r=I(r,W.ToInteger(arguments[1]))),r=r>=0?r:n-Math.abs(r);r>=0;r--)if(r in t&&e===t[r])return r;return-1}},ce);var fe=function(){var e=[1,2],t=e.splice();return 2===e.length&&ne(t)&&0===t.length}();O(r,{splice:function(e,t){return 0===arguments.length?[]:p.apply(this,arguments)}},!fe);var de=function(){var e={};return r.splice.call(e,0,0,1),1===e.length}();O(r,{splice:function(e,t){if(0===arguments.length)return[];var n=arguments;return this.length=b(W.ToInteger(this.length),0),arguments.length>0&&"number"!=typeof t&&(n=F(arguments),n.length<2?$(n,this.length-e):n[1]=W.ToInteger(t)),p.apply(this,n)}},!de);var pe=function(){var e=new n(1e5);return e[8]="x",e.splice(1,1),7===e.indexOf("x")}(),he=function(){var e=256,t=[];return t[e]="a",t.splice(e+1,0,"b"),"a"===t[e]}();O(r,{splice:function(e,t){for(var n,r=W.ToObject(this),i=[],o=W.ToUint32(r.length),a=W.ToInteger(e),s=0>a?b(o+a,0):I(a,o),u=I(b(W.ToInteger(t),0),o-s),c=0;u>c;)n=l(s+c),J(r,n)&&(i[c]=r[n]),c+=1;var f,d=F(arguments,2),p=d.length;if(u>p){c=s;for(var h=o-u;h>c;)n=l(c+u),f=l(c+p),J(r,n)?r[f]=r[n]:delete r[f],c+=1;c=o;for(var g=o-u+p;c>g;)delete r[c-1],c-=1}else if(p>u)for(c=o-u;c>s;)n=l(c+u-1),f=l(c+p-1),J(r,n)?r[f]=r[n]:delete r[f],c-=1;c=s;for(var m=0;m<d.length;++m)r[c]=d[m],c+=1;return r.length=o-u+p,i}},!pe||!he);var ge,me=r.join;try{ge="1,2,3"!==Array.prototype.join.call("123",",")}catch(V){ge=!0}ge&&O(r,{join:function(e){var t="undefined"==typeof e?",":e;return me.call(Z(this)?Q(this,""):this,t)}},ge);var ve="1,2"!==[1,2].join(void 0);ve&&O(r,{join:function(e){var t="undefined"==typeof e?",":e;return me.call(this,t)}},ve);var ye=function(e){for(var t=W.ToObject(this),n=W.ToUint32(t.length),r=0;r<arguments.length;)t[n+r]=arguments[r],r+=1;return t.length=n+r,n+r},we=function(){var e={},t=Array.prototype.push.call(e,void 0);return 1!==t||1!==e.length||"undefined"!=typeof e[0]||!J(e,0)}();O(r,{push:function(e){return ne(this)?h.apply(this,arguments):ye.apply(this,arguments)}},we);var be=function(){var e=[],t=e.push(void 0);return 1!==t||1!==e.length||"undefined"!=typeof e[0]||!J(e,0)}();O(r,{push:ye},be),O(r,{slice:function(e,t){var n=Z(this)?Q(this,""):this;return H(n,arguments)}},oe);var Ie=function(){try{[1,2].sort(null)}catch(e){try{[1,2].sort({})}catch(t){return!1}}return!0}(),Me=function(){try{return[1,2].sort(/a/),!1}catch(e){}return!0}(),Ce=function(){try{return[1,2].sort(void 0),!0}catch(e){}return!1}();O(r,{sort:function(t){if("undefined"==typeof t)return te(this);if(!e(t))throw new TypeError("Array.prototype.sort callback must be a function");return te(this,t)}},Ie||!Ce||!Me);var Ae=!ee({toString:null},"toString"),Se=ee(function(){},"prototype"),Ee=!J("x","0"),je=function(e){var t=e.constructor;return t&&t.prototype===e},De={$window:!0,$console:!0,$parent:!0,$self:!0,$frame:!0,$frames:!0,$frameElement:!0,$webkitIndexedDB:!0,$webkitStorageInfo:!0,$external:!0,$width:!0,$height:!0,$top:!0,$localStorage:!0},Ne=function(){if("undefined"==typeof window)return!1;for(var e in window)try{!De["$"+e]&&J(window,e)&&null!==window[e]&&"object"==typeof window[e]&&je(window[e])}catch(t){return!0}return!1}(),Le=function(e){if("undefined"==typeof window||!Ne)return je(e);try{return je(e)}catch(t){return!1}},xe=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],Te=xe.length,Ze=function(e){return"[object Arguments]"===B(e)},Pe=function(t){return null!==t&&"object"==typeof t&&"number"==typeof t.length&&t.length>=0&&!ne(t)&&e(t.callee)},ke=Ze(arguments)?Ze:Pe;O(i,{keys:function(t){var n=e(t),r=ke(t),i=null!==t&&"object"==typeof t,o=i&&Z(t);if(!i&&!n&&!r)throw new TypeError("Object.keys called on a non-object");var a=[],s=Se&&n;if(o&&Ee||r)for(var u=0;u<t.length;++u)$(a,l(u));if(!r)for(var c in t)s&&"prototype"===c||!J(t,c)||$(a,l(c));if(Ae)for(var f=Le(t),d=0;Te>d;d++){var p=xe[d];f&&"constructor"===p||!J(t,p)||$(a,p)}return a}});var Ye=i.keys&&function(){return 2===i.keys(arguments).length}(1,2),ze=i.keys&&function(){var e=i.keys(arguments);return 1!==arguments.length||1!==e.length||1!==e[0]}(1),Oe=i.keys;O(i,{keys:function(e){return Oe(ke(e)?F(e):e)}},!Ye||ze);var Ge,Re,We=0!==new Date(-0xc782b5b342b24).getUTCMonth(),Ue=new Date(-0x55d318d56a724),Je=new Date(14496624e5),Be="Mon, 01 Jan -45875 11:59:59 GMT"!==Ue.toUTCString(),Fe=Ue.getTimezoneOffset();-720>Fe?(Ge="Tue Jan 02 -45875"!==Ue.toDateString(),Re=!/^Thu Dec 10 2015 \d\d:\d\d:\d\d GMT[-+]\d\d\d\d(?: |$)/.test(String(Je))):(Ge="Mon Jan 01 -45875"!==Ue.toDateString(),Re=!/^Wed Dec 09 2015 \d\d:\d\d:\d\d GMT[-+]\d\d\d\d(?: |$)/.test(String(Je)));var He=y.bind(Date.prototype.getFullYear),Ve=y.bind(Date.prototype.getMonth),Xe=y.bind(Date.prototype.getDate),_e=y.bind(Date.prototype.getUTCFullYear),Ke=y.bind(Date.prototype.getUTCMonth),Qe=y.bind(Date.prototype.getUTCDate),qe=y.bind(Date.prototype.getUTCDay),$e=y.bind(Date.prototype.getUTCHours),et=y.bind(Date.prototype.getUTCMinutes),tt=y.bind(Date.prototype.getUTCSeconds),nt=y.bind(Date.prototype.getUTCMilliseconds),rt=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],it=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],ot=function(e,t){return Xe(new Date(t,e,0))};O(Date.prototype,{getFullYear:function(){if(!(this&&this instanceof Date))throw new TypeError("this is not a Date object.");var e=He(this);return 0>e&&Ve(this)>11?e+1:e},getMonth:function(){if(!(this&&this instanceof Date))throw new TypeError("this is not a Date object.");var e=He(this),t=Ve(this);return 0>e&&t>11?0:t},getDate:function(){if(!(this&&this instanceof Date))throw new TypeError("this is not a Date object.");var e=He(this),t=Ve(this),n=Xe(this);if(0>e&&t>11){if(12===t)return n;var r=ot(0,e+1);return r-n+1}return n},getUTCFullYear:function(){if(!(this&&this instanceof Date))throw new TypeError("this is not a Date object.");var e=_e(this);return 0>e&&Ke(this)>11?e+1:e},getUTCMonth:function(){if(!(this&&this instanceof Date))throw new TypeError("this is not a Date object.");var e=_e(this),t=Ke(this);return 0>e&&t>11?0:t},getUTCDate:function(){if(!(this&&this instanceof Date))throw new TypeError("this is not a Date object.");var e=_e(this),t=Ke(this),n=Qe(this);if(0>e&&t>11){if(12===t)return n;var r=ot(0,e+1);return r-n+1}return n}},We),O(Date.prototype,{toUTCString:function(){if(!(this&&this instanceof Date))throw new TypeError("this is not a Date object.");var e=qe(this),t=Qe(this),n=Ke(this),r=_e(this),i=$e(this),o=et(this),a=tt(this);return rt[e]+", "+(10>t?"0"+t:t)+" "+it[n]+" "+r+" "+(10>i?"0"+i:i)+":"+(10>o?"0"+o:o)+":"+(10>a?"0"+a:a)+" GMT"}},We||Be),O(Date.prototype,{toDateString:function(){if(!(this&&this instanceof Date))throw new TypeError("this is not a Date object.");var e=this.getDay(),t=this.getDate(),n=this.getMonth(),r=this.getFullYear();return rt[e]+" "+it[n]+" "+(10>t?"0"+t:t)+" "+r}},We||Ge),(We||Re)&&(Date.prototype.toString=function(){if(!(this&&this instanceof Date))throw new TypeError("this is not a Date object.");var e=this.getDay(),t=this.getDate(),n=this.getMonth(),r=this.getFullYear(),i=this.getHours(),o=this.getMinutes(),a=this.getSeconds(),s=this.getTimezoneOffset(),l=Math.floor(Math.abs(s)/60),u=Math.floor(Math.abs(s)%60);return rt[e]+" "+it[n]+" "+(10>t?"0"+t:t)+" "+r+" "+(10>i?"0"+i:i)+":"+(10>o?"0"+o:o)+":"+(10>a?"0"+a:a)+" GMT"+(s>0?"-":"+")+(10>l?"0"+l:l)+(10>u?"0"+u:u)},z&&i.defineProperty(Date.prototype,"toString",{configurable:!0,enumerable:!1,writable:!0}));var at=-621987552e5,st="-000001",lt=Date.prototype.toISOString&&-1===new Date(at).toISOString().indexOf(st),ut=Date.prototype.toISOString&&"1969-12-31T23:59:59.999Z"!==new Date(-1).toISOString(),ct=y.bind(Date.prototype.getTime);O(Date.prototype,{toISOString:function(){if(!isFinite(this)||!isFinite(ct(this)))throw new RangeError("Date.prototype.toISOString called on non-finite value.");var e=_e(this),t=Ke(this);e+=Math.floor(t/12),t=(t%12+12)%12;var n=[t+1,Qe(this),$e(this),et(this),tt(this)];e=(0>e?"-":e>9999?"+":"")+K("00000"+Math.abs(e),e>=0&&9999>=e?-4:-6);for(var r=0;r<n.length;++r)n[r]=K("00"+n[r],-2);return e+"-"+F(n,0,2).join("-")+"T"+F(n,2).join(":")+"."+K("000"+nt(this),-3)+"Z"}},lt||ut);var ft=function(){try{return Date.prototype.toJSON&&null===new Date(NaN).toJSON()&&-1!==new Date(at).toJSON().indexOf(st)&&Date.prototype.toJSON.call({toISOString:function(){return!0}})}catch(e){return!1}}();ft||(Date.prototype.toJSON=function(t){var n=i(this),r=W.ToPrimitive(n);if("number"==typeof r&&!isFinite(r))return null;var o=n.toISOString;if(!e(o))throw new TypeError("toISOString property is not callable");return o.call(n)});var dt=1e15===Date.parse("+033658-09-27T01:46:40.000Z"),pt=!isNaN(Date.parse("2012-04-04T24:00:00.500Z"))||!isNaN(Date.parse("2012-11-31T23:59:59.000Z"))||!isNaN(Date.parse("2012-12-31T23:59:60.000Z")),ht=isNaN(Date.parse("2000-01-01T00:00:00.000Z"));if(ht||pt||!dt){var gt=Math.pow(2,31)-1,mt=R(new Date(1970,0,1,0,0,0,gt+1).getTime());Date=function(e){var t=function(n,r,i,o,a,s,u){var c,f=arguments.length;if(this instanceof e){var d=s,p=u;if(mt&&f>=7&&u>gt){var h=Math.floor(u/gt)*gt,g=Math.floor(h/1e3);d+=g,p-=1e3*g}c=1===f&&l(n)===n?new e(t.parse(n)):f>=7?new e(n,r,i,o,a,d,p):f>=6?new e(n,r,i,o,a,d):f>=5?new e(n,r,i,o,a):f>=4?new e(n,r,i,o):f>=3?new e(n,r,i):f>=2?new e(n,r):f>=1?new e(n instanceof e?+n:n):new e}else c=e.apply(this,arguments);return G(c)||O(c,{constructor:t},!0),c},n=new RegExp("^(\\d{4}|[+-]\\d{6})(?:-(\\d{2})(?:-(\\d{2})(?:T(\\d{2}):(\\d{2})(?::(\\d{2})(?:(\\.\\d{1,}))?)?(Z|(?:([-+])(\\d{2}):(\\d{2})))?)?)?)?$"),r=[0,31,59,90,120,151,181,212,243,273,304,334,365],i=function(e,t){var n=t>1?1:0;return r[t]+Math.floor((e-1969+n)/4)-Math.floor((e-1901+n)/100)+Math.floor((e-1601+n)/400)+365*(e-1970)},o=function(t){var n=0,r=t;if(mt&&r>gt){var i=Math.floor(r/gt)*gt,o=Math.floor(i/1e3);n+=o,r-=1e3*o}return c(new e(1970,0,1,0,0,n,r))};for(var a in e)J(e,a)&&(t[a]=e[a]);O(t,{now:e.now,UTC:e.UTC},!0),t.prototype=e.prototype,O(t.prototype,{constructor:t},!0);var s=function(t){var r=n.exec(t);if(r){var a,s=c(r[1]),l=c(r[2]||1)-1,u=c(r[3]||1)-1,f=c(r[4]||0),d=c(r[5]||0),p=c(r[6]||0),h=Math.floor(1e3*c(r[7]||0)),g=Boolean(r[4]&&!r[8]),m="-"===r[9]?1:-1,v=c(r[10]||0),y=c(r[11]||0),w=d>0||p>0||h>0;return(w?24:25)>f&&60>d&&60>p&&1e3>h&&l>-1&&12>l&&24>v&&60>y&&u>-1&&u<i(s,l+1)-i(s,l)&&(a=60*(24*(i(s,l)+u)+f+v*m),a=1e3*(60*(a+d+y*m)+p)+h,g&&(a=o(a)),a>=-864e13&&864e13>=a)?a:NaN}return e.parse.apply(this,arguments)};return O(t,{parse:s}),t}(Date)}Date.now||(Date.now=function(){return(new Date).getTime()});var vt=f.toFixed&&("0.000"!==8e-5.toFixed(3)||"1"!==.9.toFixed(0)||"1.25"!==1.255.toFixed(2)||"1000000000000000128"!==0xde0b6b3a7640080.toFixed(0)),yt={base:1e7,size:6,data:[0,0,0,0,0,0],multiply:function(e,t){for(var n=-1,r=t;++n<yt.size;)r+=e*yt.data[n],yt.data[n]=r%yt.base,r=Math.floor(r/yt.base)},divide:function(e){for(var t=yt.size,n=0;--t>=0;)n+=yt.data[t],yt.data[t]=Math.floor(n/e),n=n%e*yt.base},numToString:function(){for(var e=yt.size,t="";--e>=0;)if(""!==t||0===e||0!==yt.data[e]){var n=l(yt.data[e]);""===t?t=n:t+=K("0000000",0,7-n.length)+n}return t},pow:function Ot(e,t,n){return 0===t?n:t%2===1?Ot(e,t-1,n*e):Ot(e*e,t/2,n)},log:function(e){for(var t=0,n=e;n>=4096;)t+=12,n/=4096;for(;n>=2;)t+=1,n/=2;return t}},wt=function(e){var t,n,r,i,o,a,s,u;if(t=c(e),t=R(t)?0:Math.floor(t),0>t||t>20)throw new RangeError("Number.toFixed called with invalid number of decimals");if(n=c(this),R(n))return"NaN";if(-1e21>=n||n>=1e21)return l(n);if(r="",0>n&&(r="-",n=-n),i="0",n>1e-21)if(o=yt.log(n*yt.pow(2,69,1))-69,a=0>o?n*yt.pow(2,-o,1):n/yt.pow(2,o,1),a*=4503599627370496,o=52-o,o>0){for(yt.multiply(0,a),s=t;s>=7;)yt.multiply(1e7,0),s-=7;for(yt.multiply(yt.pow(10,s,1),0),s=o-1;s>=23;)yt.divide(1<<23),s-=23;yt.divide(1<<s),yt.multiply(1,1),yt.divide(2),i=yt.numToString()}else yt.multiply(0,a),yt.multiply(1<<-o,0),i=yt.numToString()+K("0.00000000000000000000",2,2+t);return t>0?(u=i.length,i=t>=u?r+K("0.0000000000000000000",0,t-u+2)+i:r+K(i,0,u-t)+"."+K(i,u-t)):i=r+i,i};O(f,{toFixed:wt},vt);var bt=function(){try{return"1"===1..toPrecision(void 0)}catch(e){return!0}}(),It=f.toPrecision;O(f,{toPrecision:function(e){return"undefined"==typeof e?It.call(this):It.call(this,e)}},bt),2!=="ab".split(/(?:ab)*/).length||4!==".".split(/(.?)(.?)/).length||"t"==="tesst".split(/(s)*/)[1]||4!=="test".split(/(?:)/,-1).length||"".split(/.?/).length||".".split(/()()/).length>1?!function(){var e="undefined"==typeof/()??/.exec("")[1],n=Math.pow(2,32)-1;u.split=function(r,i){var o=String(this);if("undefined"==typeof r&&0===i)return[];if(!t(r))return Q(this,r,i);var a,s,l,u,c=[],f=(r.ignoreCase?"i":"")+(r.multiline?"m":"")+(r.unicode?"u":"")+(r.sticky?"y":""),d=0,p=new RegExp(r.source,f+"g");e||(a=new RegExp("^"+p.source+"$(?!\\s)",f));var g="undefined"==typeof i?n:W.ToUint32(i);for(s=p.exec(o);s&&(l=s.index+s[0].length,!(l>d&&($(c,K(o,d,s.index)),!e&&s.length>1&&s[0].replace(a,function(){for(var e=1;e<arguments.length-2;e++)"undefined"==typeof arguments[e]&&(s[e]=void 0)}),s.length>1&&s.index<o.length&&h.apply(c,F(s,1)),u=s[0].length,d=l,c.length>=g)));)p.lastIndex===s.index&&p.lastIndex++,s=p.exec(o);return d===o.length?(u||!p.test(""))&&$(c,""):$(c,K(o,d)),c.length>g?F(c,0,g):c}}():"0".split(void 0,0).length&&(u.split=function(e,t){return"undefined"==typeof e&&0===t?[]:Q(this,e,t)});var Mt=u.replace,Ct=function(){var e=[];return"x".replace(/x(.)?/g,function(t,n){$(e,n)}),1===e.length&&"undefined"==typeof e[0]}();Ct||(u.replace=function(n,r){var i=e(r),o=t(n)&&/\)[*?]/.test(n.source);if(i&&o){var a=function(e){var t=arguments.length,i=n.lastIndex;n.lastIndex=0;var o=n.exec(e)||[];return n.lastIndex=i,$(o,arguments[t-2],arguments[t-1]),r.apply(this,o)};return Mt.call(this,n,a)}return Mt.call(this,n,r)});var At=u.substr,St="".substr&&"b"!=="0b".substr(-1);O(u,{substr:function(e,t){var n=e;return 0>e&&(n=b(this.length+e,0)),At.call(this,n,t)}},St);var Et=" \n\f\r   ᠎              \u2028\u2029\ufeff",jt="​",Dt="["+Et+"]",Nt=new RegExp("^"+Dt+Dt+"*"),Lt=new RegExp(Dt+Dt+"*$"),xt=u.trim&&(Et.trim()||!jt.trim());O(u,{trim:function(){if("undefined"==typeof this||null===this)throw new TypeError("can't convert "+this+" to object");return l(this).replace(Nt,"").replace(Lt,"")}},xt);var Tt=y.bind(String.prototype.trim),Zt=u.lastIndexOf&&-1!=="abcあい".lastIndexOf("あい",2);O(u,{lastIndexOf:function(e){if("undefined"==typeof this||null===this)throw new TypeError("can't convert "+this+" to object");for(var t=l(this),n=l(e),r=arguments.length>1?c(arguments[1]):NaN,i=R(r)?1/0:W.ToInteger(r),o=I(b(i,0),t.length),a=n.length,s=o+a;s>0;){s=b(0,s-a);var u=q(K(t,s,o+a),n);if(-1!==u)return s+u}return-1}},Zt);var Pt=u.lastIndexOf;if(O(u,{lastIndexOf:function(e){return Pt.apply(this,arguments)}},1!==u.lastIndexOf.length),(8!==parseInt(Et+"08")||22!==parseInt(Et+"0x16"))&&(parseInt=function(e){var t=/^[-+]?0[xX]/;return function(n,r){var i=Tt(String(n)),o=c(r)||(t.test(i)?16:10);return e(i,o)}}(parseInt)),1/parseFloat("-0")!==-(1/0)&&(parseFloat=function(e){return function(t){var n=Tt(String(t)),r=e(n);return 0===r&&"-"===K(n,0,1)?-0:r}}(parseFloat)),"RangeError: test"!==String(new RangeError("test"))){var kt=function(){if("undefined"==typeof this||null===this)throw new TypeError("can't convert "+this+" to object");var e=this.name;"undefined"==typeof e?e="Error":"string"!=typeof e&&(e=l(e));var t=this.message;return"undefined"==typeof t?t="":"string"!=typeof t&&(t=l(t)),e?t?e+": "+t:e:t};Error.prototype.toString=kt}if(z){var Yt=function(e,t){if(ee(e,t)){var n=Object.getOwnPropertyDescriptor(e,t);n.configurable&&(n.enumerable=!1,Object.defineProperty(e,t,n))}};Yt(Error.prototype,"message"),""!==Error.prototype.message&&(Error.prototype.message=""),Yt(Error.prototype,"name")}if("/a/gim"!==String(/a/gim)){var zt=function(){var e="/"+this.source+"/";return this.global&&(e+="g"),this.ignoreCase&&(e+="i"),this.multiline&&(e+="m"),e};RegExp.prototype.toString=zt}})},{}],39:[function(e,t,n){var r=[],i=r.forEach,o=r.slice;t.exports=function(e){return i.call(o.call(arguments,1),function(t){if(t)for(var n in t)e[n]=t[n]}),e}},{}],40:[function(e,t,n){n.read=function(e,t,n,r,i){var o,a,s=8*i-r-1,l=(1<<s)-1,u=l>>1,c=-7,f=n?i-1:0,d=n?-1:1,p=e[t+f];for(f+=d,o=p&(1<<-c)-1,p>>=-c,c+=s;c>0;o=256*o+e[t+f],f+=d,c-=8);for(a=o&(1<<-c)-1,o>>=-c,c+=r;c>0;a=256*a+e[t+f],f+=d,c-=8);if(0===o)o=1-u;else{if(o===l)return a?NaN:(p?-1:1)*(1/0);a+=Math.pow(2,r),o-=u}return(p?-1:1)*a*Math.pow(2,o-r)},n.write=function(e,t,n,r,i,o){var a,s,l,u=8*o-i-1,c=(1<<u)-1,f=c>>1,d=23===i?Math.pow(2,-24)-Math.pow(2,-77):0,p=r?0:o-1,h=r?1:-1,g=0>t||0===t&&0>1/t?1:0;for(t=Math.abs(t),isNaN(t)||t===1/0?(s=isNaN(t)?1:0,a=c):(a=Math.floor(Math.log(t)/Math.LN2),t*(l=Math.pow(2,-a))<1&&(a--,l*=2),t+=a+f>=1?d/l:d*Math.pow(2,1-f),t*l>=2&&(a++,l/=2),a+f>=c?(s=0,a=c):a+f>=1?(s=(t*l-1)*Math.pow(2,i),a+=f):(s=t*Math.pow(2,f-1)*Math.pow(2,i),a=0));i>=8;e[n+p]=255&s,p+=h,s/=256,i-=8);for(a=a<<i|s,u+=i;u>0;e[n+p]=255&a,p+=h,a/=256,u-=8);e[n+p-h]|=128*g}},{}],41:[function(e,t,n){var r=[].indexOf;t.exports=function(e,t){if(r)return e.indexOf(t);for(var n=0;n<e.length;++n)if(e[n]===t)return n;return-1}},{}],42:[function(e,t,n){function r(e){var t=i.call(e);return"[object Function]"===t||"function"==typeof e&&"[object RegExp]"!==t||"undefined"!=typeof window&&(e===window.setTimeout||e===window.alert||e===window.confirm||e===window.prompt)}t.exports=r;var i=Object.prototype.toString},{}],43:[function(e,t,n){var r={}.toString;t.exports=Array.isArray||function(e){return"[object Array]"==r.call(e)}},{}],44:[function(t,n,r){(function(t){!function(i){function o(e){throw new RangeError(P[e])}function a(e,t){for(var n=e.length,r=[];n--;)r[n]=t(e[n]);return r}function s(e,t){var n=e.split("@"),r="";n.length>1&&(r=n[0]+"@",e=n[1]),e=e.replace(Z,".");var i=e.split("."),o=a(i,t).join(".");return r+o}function l(e){for(var t,n,r=[],i=0,o=e.length;o>i;)t=e.charCodeAt(i++),t>=55296&&56319>=t&&o>i?(n=e.charCodeAt(i++),56320==(64512&n)?r.push(((1023&t)<<10)+(1023&n)+65536):(r.push(t),i--)):r.push(t);return r}function u(e){return a(e,function(e){var t="";return e>65535&&(e-=65536,t+=z(e>>>10&1023|55296),e=56320|1023&e),t+=z(e)}).join("")}function c(e){return 10>e-48?e-22:26>e-65?e-65:26>e-97?e-97:C}function f(e,t){return e+22+75*(26>e)-((0!=t)<<5)}function d(e,t,n){var r=0;for(e=n?Y(e/j):e>>1,e+=Y(e/t);e>k*S>>1;r+=C)e=Y(e/k);return Y(r+(k+1)*e/(e+E))}function p(e){var t,n,r,i,a,s,l,f,p,h,g=[],m=e.length,v=0,y=N,w=D;for(n=e.lastIndexOf(L),0>n&&(n=0),r=0;n>r;++r)e.charCodeAt(r)>=128&&o("not-basic"),g.push(e.charCodeAt(r));for(i=n>0?n+1:0;m>i;){for(a=v,s=1,l=C;i>=m&&o("invalid-input"),f=c(e.charCodeAt(i++)),(f>=C||f>Y((M-v)/s))&&o("overflow"),v+=f*s,p=w>=l?A:l>=w+S?S:l-w,!(p>f);l+=C)h=C-p,s>Y(M/h)&&o("overflow"),s*=h;t=g.length+1,w=d(v-a,t,0==a),Y(v/t)>M-y&&o("overflow"),y+=Y(v/t),v%=t,g.splice(v++,0,y)}return u(g)}function h(e){var t,n,r,i,a,s,u,c,p,h,g,m,v,y,w,b=[];for(e=l(e),m=e.length,t=N,n=0,a=D,s=0;m>s;++s)g=e[s],128>g&&b.push(z(g));for(r=i=b.length,i&&b.push(L);m>r;){for(u=M,s=0;m>s;++s)g=e[s],g>=t&&u>g&&(u=g);for(v=r+1,u-t>Y((M-n)/v)&&o("overflow"),n+=(u-t)*v,t=u,s=0;m>s;++s)if(g=e[s],t>g&&++n>M&&o("overflow"),g==t){for(c=n,p=C;h=a>=p?A:p>=a+S?S:p-a,!(h>c);p+=C)w=c-h,y=C-h,b.push(z(f(h+w%y,0))),c=Y(w/y);b.push(z(f(c,0))),a=d(n,v,r==i),n=0,++r}++n,++t}return b.join("")}function g(e){return s(e,function(e){return x.test(e)?p(e.slice(4).toLowerCase()):e})}function m(e){return s(e,function(e){return T.test(e)?"xn--"+h(e):e})}var v="object"==typeof r&&r&&!r.nodeType&&r,y="object"==typeof n&&n&&!n.nodeType&&n,w="object"==typeof t&&t;(w.global===w||w.window===w||w.self===w)&&(i=w);var b,I,M=2147483647,C=36,A=1,S=26,E=38,j=700,D=72,N=128,L="-",x=/^xn--/,T=/[^\x20-\x7E]/,Z=/[\x2E\u3002\uFF0E\uFF61]/g,P={overflow:"Overflow: input needs wider integers to process","not-basic":"Illegal input >= 0x80 (not a basic code point)","invalid-input":"Invalid input"},k=C-A,Y=Math.floor,z=String.fromCharCode;if(b={version:"1.4.1",ucs2:{decode:l,encode:u},decode:p,encode:h,toASCII:m,toUnicode:g},"function"==typeof e&&"object"==typeof e.amd&&e.amd)e("punycode",function(){return b});else if(v&&y)if(n.exports==v)y.exports=b;else for(I in b)b.hasOwnProperty(I)&&(v[I]=b[I]);else i.punycode=b}(this)}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],45:[function(t,n,r){!function(t,r){"undefined"!=typeof n&&n.exports?n.exports=r():"function"==typeof e&&e.amd?e(r):this[t]=r()}("$script",function(){function e(e,t){for(var n=0,r=e.length;r>n;++n)if(!t(e[n]))return l;return 1}function t(t,n){e(t,function(e){return!n(e)})}function n(o,a,s){function l(e){return e.call?e():d[e]}function c(){if(!--y){d[v]=1,m&&m();for(var n in h)e(n.split("|"),l)&&!t(h[n],l)&&(h[n]=[])}}o=o[u]?o:[o];var f=a&&a.call,m=f?a:s,v=f?o.join(""):a,y=o.length;return setTimeout(function(){t(o,function e(t,n){return null===t?c():(n||/^https?:\/\//.test(t)||!i||(t=-1===t.indexOf(".js")?i+t+".js":i+t),g[t]?(v&&(p[v]=1),2==g[t]?c():setTimeout(function(){e(t,!0)},0)):(g[t]=1,v&&(p[v]=1),void r(t,c)))})},0),n}function r(e,t){var n,r=a.createElement("script");r.onload=r.onerror=r[f]=function(){r[c]&&!/^c|loade/.test(r[c])||n||(r.onload=r[f]=null,n=1,g[e]=2,t())},r.async=1,r.src=o?e+(-1===e.indexOf("?")?"?":"&")+o:e,s.insertBefore(r,s.lastChild)}var i,o,a=document,s=a.getElementsByTagName("head")[0],l=!1,u="push",c="readyState",f="onreadystatechange",d={},p={},h={},g={};return n.get=r,n.order=function(e,t,r){!function i(o){o=e.shift(),e.length?n(o,i):n(o,t,r)}()},n.path=function(e){i=e},n.urlArgs=function(e){o=e},n.ready=function(r,i,o){r=r[u]?r:[r];var a=[];return!t(r,function(e){d[e]||a[u](e)})&&e(r,function(e){return d[e]})?i():!function(e){h[e]=h[e]||[],h[e][u](i),o&&o(a)}(r.join("|")),n},n.done=function(e){n([null],e)},n})},{}]},{},[32])(32)});
11
 
12
 
13
+ /*! js-cookie v2.2.0 | MIT */
14
+ !function(e){var n=!1;if("function"==typeof define&&define.amd&&(define(e),n=!0),"object"==typeof exports&&(module.exports=e(),n=!0),!n){var o=window.Cookies,t=window.Cookies=e();t.noConflict=function(){return window.Cookies=o,t}}}(function(){function e(){for(var e=0,n={};e<arguments.length;e++){var o=arguments[e];for(var t in o)n[t]=o[t]}return n}function n(o){function t(n,r,i){var c;if("undefined"!=typeof document){if(arguments.length>1){if("number"==typeof(i=e({path:"/"},t.defaults,i)).expires){var a=new Date;a.setMilliseconds(a.getMilliseconds()+864e5*i.expires),i.expires=a}i.expires=i.expires?i.expires.toUTCString():"";try{c=JSON.stringify(r),/^[\{\[]/.test(c)&&(r=c)}catch(e){}r=o.write?o.write(r,n):encodeURIComponent(r+"").replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g,decodeURIComponent),n=(n=(n=encodeURIComponent(n+"")).replace(/%(23|24|26|2B|5E|60|7C)/g,decodeURIComponent)).replace(/[\(\)]/g,escape);var s="";for(var f in i)i[f]&&(s+="; "+f,!0!==i[f]&&(s+="="+i[f]));return document.cookie=n+"="+r+s}n||(c={});for(var p=document.cookie?document.cookie.split("; "):[],d=/(%[0-9A-Z]{2})+/g,u=0;u<p.length;u++){var l=p[u].split("="),C=l.slice(1).join("=");this.json||'"'!==C.charAt(0)||(C=C.slice(1,-1));try{var m=l[0].replace(d,decodeURIComponent);if(C=o.read?o.read(C,m):o(C,m)||C.replace(d,decodeURIComponent),this.json)try{C=JSON.parse(C)}catch(e){}if(n===m){c=C;break}n||(c[m]=C)}catch(e){}}return c}}return t.set=t,t.get=function(e){return t.call(t,e)},t.getJSON=function(){return t.apply({json:!0},[].slice.call(arguments))},t.defaults={},t.remove=function(n,o){t(n,"",e(o,{expires:-1}))},t.withConverter=n,t}return n(function(){})});
15
 
16
 
17
  /*
2272
  $(document).on('click', "div.flowplayer.is-unSticky", function() {
2273
  $("div.flowplayer").removeClass("is-unSticky");
2274
  });
2275
+ });
2276
+
2277
+
2278
+ // Magnific Popup suppport
2279
+ jQuery(document).on('mfpClose', function() {
2280
+ if( typeof(jQuery('.flowplayer').data('flowplayer')) != "undefined" ) jQuery('.flowplayer').data('flowplayer').unload();
2281
+ } );
2282
+
2283
+
2284
+ /*
2285
+ * Video Position Store functionality
2286
+ */
2287
+ flowplayer( function(api,root) {
2288
+ // variables
2289
+ var
2290
+ // a jQuery representation of the root DIV element
2291
+ $root = jQuery(root),
2292
+ // whether or not we should enable position saving for this video only
2293
+ forceEnablePositionSaving = ($root.data('save-position') ? true : false),
2294
+ progressEventsCount = 0,
2295
+ // number of events to pass before we auto-send current video positions
2296
+ sendPositionsEvery = 60,
2297
+ // the actual AJAX object we use to send progress data, so we can cancel it,
2298
+ // should we encounter another timeout and the first AJAX did not complete yet
2299
+ // note: this is only used for logged-in users... everyone else will use cookie/localStorage
2300
+ ajaxCall = null,
2301
+ // maximum cookie size with saved video positions we should store
2302
+ maxCookieSize = 2500,
2303
+ // whether or not localStorage is enabled
2304
+ localStorageEnabled = null,
2305
+ // key name for cookie/localStorage lookup of video positions for guest visitors
2306
+ cookieKeyName = 'video_positions',
2307
+
2308
+ // methods
2309
+ // retrieves the original source of a video
2310
+ getOriginalSource = function(video) {
2311
+ // logged-in users will have position stored within that video
2312
+ return (
2313
+ (typeof(video.sources_original) != "undefined" && typeof(video.sources_original[0]) != "undefined") ?
2314
+ video.sources_original[0] :
2315
+ video.sources[0]
2316
+ );
2317
+ },
2318
+
2319
+ // calculates a cookie byte size
2320
+ getTextByteSize = function(txt) {
2321
+ return encodeURIComponent(txt).length;
2322
+ },
2323
+
2324
+ getCookieKey = function(key) {
2325
+ return (localStorageEnabled ? localStorage.getItem(key) : Cookies.get(key));
2326
+ },
2327
+
2328
+ setCookieKey = function(key, value) {
2329
+ return (localStorageEnabled ? localStorage.setItem(key, value) : Cookies.set(key, value));
2330
+ },
2331
+
2332
+ // stores currently played/paused/stopped video position
2333
+ storeVideoPosition = function (e, api) {
2334
+ if (api.video.sources) {
2335
+ if (typeof(flowplayer['playPositions']) == 'undefined') {
2336
+ flowplayer['playPositions'] = [];
2337
+ }
2338
+
2339
+ var
2340
+ originalVideoApiPath = getOriginalSource(api.video),
2341
+ playerSource = originalVideoApiPath.src,
2342
+ position = Math.round(api.video.time);
2343
+
2344
+ // only store position if we're going to save it somewhere
2345
+ if ((flowplayer.conf.video_position_save_enable || forceEnablePositionSaving)) {
2346
+ flowplayer['playPositions'][playerSource] = position;
2347
+ }
2348
+
2349
+ // store the new position in the instance itself as well
2350
+ if (originalVideoApiPath.position) {
2351
+ originalVideoApiPath.position = position;
2352
+ }
2353
+
2354
+ // make a call home every 30 seconds to make sure a browser crash doesn't affect the position save too much
2355
+ if (progressEventsCount++ >= sendPositionsEvery) {
2356
+ if ((flowplayer.conf.video_position_save_enable || forceEnablePositionSaving) && flowplayer.conf.is_logged_in == '1') {
2357
+ // cancel any old AJAX call that might be lingering in the air
2358
+ if (ajaxCall) {
2359
+ ajaxCall.abort();
2360
+ }
2361
+
2362
+ // send the call home
2363
+ ajaxCall = sendVideoPositions(true, function () {
2364
+ ajaxCall = null;
2365
+ });
2366
+ }
2367
+
2368
+ // reset counter
2369
+ progressEventsCount = 0;
2370
+ }
2371
+ }
2372
+ },
2373
+
2374
+ // used when video unloads and another video starts playing
2375
+ forceSavePosition = function (e, api) {
2376
+ var inPlaylist = false;
2377
+
2378
+ for (var i in api.conf.playlist) {
2379
+ inPlaylist = true;
2380
+ break;
2381
+ }
2382
+
2383
+ if (inPlaylist && !flowplayer.conf.closingPage) {
2384
+ progressEventsCount = sendPositionsEvery + 1;
2385
+ storeVideoPosition(e, api);
2386
+ sendVideoPositions();
2387
+ }
2388
+ },
2389
+
2390
+ // called when the video finishes playing - removes that video position from cache, as it's no longer needed
2391
+ removeVideoPosition = function (e, api) {
2392
+ if (api.video.sources) {
2393
+ if (typeof(flowplayer['playPositions']) == 'undefined') {
2394
+ flowplayer['playPositions'] = [];
2395
+ }
2396
+
2397
+ var
2398
+ originalVideoApiPath = getOriginalSource(api.video),
2399
+ playerSource = originalVideoApiPath.src,
2400
+ position = Math.round(api.video.time);
2401
+
2402
+ if ((flowplayer.conf.video_position_save_enable || forceEnablePositionSaving)) {
2403
+ flowplayer['playPositions'][playerSource] = 0;
2404
+ }
2405
+ }
2406
+ },
2407
+
2408
+ // used to seek into the desired last stored position when he video has started
2409
+ seekIntoPosition = function (e, api) {
2410
+ var
2411
+ originalVideoApiPath = getOriginalSource(api.video),
2412
+ position = originalVideoApiPath.position;
2413
+
2414
+ if (position) {
2415
+ var do_seek = setInterval( function() {
2416
+ if( api.loading ) return;
2417
+ api.seek(position);
2418
+ clearInterval(do_seek);
2419
+ }, 10 );
2420
+ } else {
2421
+ // try to lookup position of a guest visitor
2422
+ if ((flowplayer.conf.video_position_save_enable || forceEnablePositionSaving) && flowplayer.conf.is_logged_in != '1') {
2423
+ var data = getCookieKey(cookieKeyName);
2424
+
2425
+ if (data && typeof(data) !== 'undefined') {
2426
+ try {
2427
+ data = JSON.parse(data);
2428
+
2429
+ // check if we have the position
2430
+ if (data[originalVideoApiPath.src]) {
2431
+ var do_seek = setInterval( function() {
2432
+ if( api.loading ) return;
2433
+ api.seek(data[originalVideoApiPath.src]);
2434
+ clearInterval(do_seek);
2435
+ }, 10 );
2436
+ }
2437
+ } catch (e) {
2438
+ // something went wrong...
2439
+ // TODO: shall we try to reset guest data here?
2440
+ return;
2441
+ }
2442
+ }
2443
+ }
2444
+ }
2445
+ },
2446
+
2447
+ sendVideoPositions = function(async, callback) {
2448
+ if (async !== true) {
2449
+ async = false;
2450
+ }
2451
+
2452
+ if (!callback || typeof(callback) == 'undefined') {
2453
+ callback = function() {};
2454
+ }
2455
+
2456
+ postData = [];
2457
+
2458
+ for (var video_name in flowplayer['playPositions']) {
2459
+ postData.push({
2460
+ name: video_name,
2461
+ position: flowplayer['playPositions'][video_name]
2462
+ });
2463
+ }
2464
+
2465
+ if (!postData.length) {
2466
+ return;
2467
+ }
2468
+
2469
+ // decide between saving position with an AJAX request
2470
+ // or storing positions in a cookie / localStorage
2471
+ if ((flowplayer.conf.video_position_save_enable || forceEnablePositionSaving) && flowplayer.conf.is_logged_in == '1') {
2472
+ // logged-in user, store position in their metadata on server
2473
+ return jQuery.ajax({
2474
+ type: 'POST',
2475
+ async: async,
2476
+ url: fv_fp_ajaxurl,
2477
+ complete: callback,
2478
+ data: {
2479
+ action: 'fv_wp_flowplayer_video_position_save',
2480
+ videoTimes: postData
2481
+ }
2482
+ });
2483
+ } else if ((flowplayer.conf.video_position_save_enable || forceEnablePositionSaving) && flowplayer.conf.is_logged_in != '1') {
2484
+ // guest visitor, store position in a cookie / localStorage
2485
+ try {
2486
+ var data = getCookieKey(cookieKeyName);
2487
+
2488
+ // parse the stored JSON data or create a new object if empty
2489
+ if (data && typeof(data) !== 'undefined') {
2490
+ data = JSON.parse(data);
2491
+ } else {
2492
+ data = {};
2493
+ }
2494
+
2495
+ // add / edit our video positions
2496
+ for (var i in postData) {
2497
+ data[postData[i].name] = postData[i].position;
2498
+ }
2499
+
2500
+ // serialize
2501
+ var
2502
+ serialized = JSON.stringify(data),
2503
+ dataSize = getTextByteSize(serialized);
2504
+
2505
+ // check if we're not going over maximum cache size
2506
+ if (dataSize > maxCookieSize) {
2507
+ // we're over max cache size, let's delete some older videos
2508
+ while (dataSize > maxCookieSize) {
2509
+ // remove the first entry only
2510
+ for (var i in data) {
2511
+ delete data[i];
2512
+
2513
+ // re-serialize with the value removed
2514
+ serialized = JSON.stringify(data);
2515
+ // calculate new data size, so we can exit the while loop
2516
+ dataSize = getTextByteSize(serialized);
2517
+
2518
+ break;
2519
+ }
2520
+ }
2521
+ }
2522
+
2523
+ // store the serialize value
2524
+ setCookieKey(cookieKeyName, serialized);
2525
+ } catch (e) {
2526
+ // JSON object is native to all contemporary browsers
2527
+ // ... if somebody uses anything older, they would be missing out
2528
+ // on lot more features, so just don't bug them
2529
+ return;
2530
+ }
2531
+ }
2532
+ };
2533
+
2534
+ // pause/stop/progress events
2535
+ api.bind('progress', storeVideoPosition);
2536
+ api.bind('finish', removeVideoPosition);
2537
+
2538
+ // ready event, so we can seek into the last saved position
2539
+ api.bind('ready', seekIntoPosition);
2540
+
2541
+ // TODO: find out what event can be used to force saving of playlist video positions on video change
2542
+ //api.bind('finish', forceSavePosition);
2543
+
2544
+ jQuery(window).on('beforeunload', function () {
2545
+ flowplayer.conf.closingPage = true;
2546
+ sendVideoPositions();
2547
+ });
2548
+
2549
+ // check whether local storage is enabled
2550
+ if (localStorageEnabled !== null) {
2551
+ return localStorageEnabled;
2552
+ }
2553
+
2554
+ localStorageEnabled = true;
2555
+ try {
2556
+ localStorage.setItem('t', 't');
2557
+ if (localStorage.getItem('t') !== 't') {
2558
+ localStorageEnabled = false;
2559
+ }
2560
+ localStorage.removeItem('t');
2561
+ } catch (e) {
2562
+ localStorageEnabled = false;
2563
+ }
2564
+ });
flowplayer.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: FV Player
4
  Plugin URI: http://foliovision.com/wordpress/plugins/fv-wordpress-flowplayer
5
  Description: Formerly FV WordPress Flowplayer. Embed videos (MP4, WEBM, OGV, FLV) into posts or pages. Uses Flowplayer 6.
6
- Version: 6.4.2
7
  Author URI: http://foliovision.com/
8
  License: GPL-3.0
9
  License URI: http://www.gnu.org/licenses/gpl-3.0.txt
@@ -26,7 +26,7 @@ License URI: http://www.gnu.org/licenses/gpl-3.0.txt
26
  along with this program. If not, see <http://www.gnu.org/licenses/>.
27
  */
28
 
29
- $fv_wp_flowplayer_ver = '6.4.2';
30
  $fv_wp_flowplayer_core_ver = '6.0.5';
31
  $fv_wp_flowplayer_core_ver_beta = '7.2.4';
32
 
@@ -56,7 +56,7 @@ include_once(dirname( __FILE__ ) . '/models/widget.php');
56
 
57
  include_once(dirname( __FILE__ ) . '/models/conversion.php');
58
  include_once(dirname( __FILE__ ) . '/models/email-subscription.php');
59
-
60
 
61
 
62
  $fv_fp = new flowplayer_frontend();
3
  Plugin Name: FV Player
4
  Plugin URI: http://foliovision.com/wordpress/plugins/fv-wordpress-flowplayer
5
  Description: Formerly FV WordPress Flowplayer. Embed videos (MP4, WEBM, OGV, FLV) into posts or pages. Uses Flowplayer 6.
6
+ Version: 6.5
7
  Author URI: http://foliovision.com/
8
  License: GPL-3.0
9
  License URI: http://www.gnu.org/licenses/gpl-3.0.txt
26
  along with this program. If not, see <http://www.gnu.org/licenses/>.
27
  */
28
 
29
+ $fv_wp_flowplayer_ver = '6.5';
30
  $fv_wp_flowplayer_core_ver = '6.0.5';
31
  $fv_wp_flowplayer_core_ver_beta = '7.2.4';
32
 
56
 
57
  include_once(dirname( __FILE__ ) . '/models/conversion.php');
58
  include_once(dirname( __FILE__ ) . '/models/email-subscription.php');
59
+ include_once(dirname( __FILE__ ) . '/models/player-position-save.php');
60
 
61
 
62
  $fv_fp = new flowplayer_frontend();
flowplayer/fv-flowplayer.min.js CHANGED
@@ -9,8 +9,8 @@ e=e.toLowerCase();var n=e.split("."),r=n.length;if(2>r||/^\d+$/.test(n[r-1]))ret
9
  return A.test(e)?p(e.slice(4).toLowerCase()):e})}function g(e){return l(e,function(e){return _.test(e)?"xn--"+m(e):e})}var h="object"==typeof r&&r,y="object"==typeof n&&n&&n.exports==h&&n,b="object"==typeof t&&t;(b.global===b||b.window===b)&&(o=b);var w,x,E=2147483647,k=36,T=1,S=26,N=38,C=700,j=72,O=128,P="-",A=/^xn--/,_=/[^ -~]/,D=/\x2E|\u3002|\uFF0E|\uFF61/g,M={overflow:"Overflow: input needs wider integers to process","not-basic":"Illegal input >= 0x80 (not a basic code point)","invalid-input":"Invalid input"},L=k-T,I=Math.floor,F=String.fromCharCode;if(w={version:"1.2.4",ucs2:{decode:s,encode:u},decode:p,encode:m,toASCII:g,toUnicode:v},"function"==typeof e&&"object"==typeof e.amd&&e.amd)e("punycode",function(){return w});else if(h&&!h.nodeType)if(y)y.exports=w;else for(x in w)w.hasOwnProperty(x)&&(h[x]=w[x]);else o.punycode=w}(this)}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}]},{},[19])(19)});
10
 
11
 
12
-
13
-
14
 
15
 
16
  /*
@@ -1957,21 +1957,11 @@ flowplayer( function(api,root) {
1957
 
1958
  var bitrates = [];
1959
 
1960
- function dash_quality(api) {
1961
- var mediaPlayer = api.engine.dash;
1962
- mediaPlayer.retrieveManifest(mediaPlayer.getSource(), function(data) {
1963
- bitrates = mediaPlayer.getTracksForTypeFromManifest( 'video', data, mediaPlayer.getStreamsFromManifest(data)[0] )[0].bitrateList;
1964
- });
1965
- }
1966
-
1967
  api.bind('ready', function(e,api) {
1968
  if(api.engine.engineName == 'dash' ) {
1969
  api.engine.dash.setLimitBitrateByPortal(true);
1970
  api.engine.dash.setUsePixelRatioInLimitBitrateByPortal(true);
1971
-
1972
- //api.engine.dash.setQualityFor('video', 0);
1973
- // api.engine.dash.getQualityFor('video');
1974
- dash_quality(api);
1975
  }
1976
  });
1977
 
@@ -1980,7 +1970,9 @@ flowplayer( function(api,root) {
1980
  api.bind('progress', function(e,api) {
1981
  if(api.engine.engineName == 'dash' ) {
1982
  var stream_info = bitrates[api.engine.dash.getQualityFor('video')];
1983
- debug_log.html( "Using "+stream_info.width+"x"+stream_info.height+" at "+Math.round(stream_info.bandwidth/1024)+" kbps" );
 
 
1984
  }
1985
  })
1986
  }
@@ -2094,3 +2086,292 @@ jQuery(function($) {
2094
  $("div.flowplayer").removeClass("is-unSticky");
2095
  });
2096
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  return A.test(e)?p(e.slice(4).toLowerCase()):e})}function g(e){return l(e,function(e){return _.test(e)?"xn--"+m(e):e})}var h="object"==typeof r&&r,y="object"==typeof n&&n&&n.exports==h&&n,b="object"==typeof t&&t;(b.global===b||b.window===b)&&(o=b);var w,x,E=2147483647,k=36,T=1,S=26,N=38,C=700,j=72,O=128,P="-",A=/^xn--/,_=/[^ -~]/,D=/\x2E|\u3002|\uFF0E|\uFF61/g,M={overflow:"Overflow: input needs wider integers to process","not-basic":"Illegal input >= 0x80 (not a basic code point)","invalid-input":"Invalid input"},L=k-T,I=Math.floor,F=String.fromCharCode;if(w={version:"1.2.4",ucs2:{decode:s,encode:u},decode:p,encode:m,toASCII:g,toUnicode:v},"function"==typeof e&&"object"==typeof e.amd&&e.amd)e("punycode",function(){return w});else if(h&&!h.nodeType)if(y)y.exports=w;else for(x in w)w.hasOwnProperty(x)&&(h[x]=w[x]);else o.punycode=w}(this)}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}]},{},[19])(19)});
10
 
11
 
12
+ /*! js-cookie v2.2.0 | MIT */
13
+ !function(e){var n=!1;if("function"==typeof define&&define.amd&&(define(e),n=!0),"object"==typeof exports&&(module.exports=e(),n=!0),!n){var o=window.Cookies,t=window.Cookies=e();t.noConflict=function(){return window.Cookies=o,t}}}(function(){function e(){for(var e=0,n={};e<arguments.length;e++){var o=arguments[e];for(var t in o)n[t]=o[t]}return n}function n(o){function t(n,r,i){var c;if("undefined"!=typeof document){if(arguments.length>1){if("number"==typeof(i=e({path:"/"},t.defaults,i)).expires){var a=new Date;a.setMilliseconds(a.getMilliseconds()+864e5*i.expires),i.expires=a}i.expires=i.expires?i.expires.toUTCString():"";try{c=JSON.stringify(r),/^[\{\[]/.test(c)&&(r=c)}catch(e){}r=o.write?o.write(r,n):encodeURIComponent(r+"").replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g,decodeURIComponent),n=(n=(n=encodeURIComponent(n+"")).replace(/%(23|24|26|2B|5E|60|7C)/g,decodeURIComponent)).replace(/[\(\)]/g,escape);var s="";for(var f in i)i[f]&&(s+="; "+f,!0!==i[f]&&(s+="="+i[f]));return document.cookie=n+"="+r+s}n||(c={});for(var p=document.cookie?document.cookie.split("; "):[],d=/(%[0-9A-Z]{2})+/g,u=0;u<p.length;u++){var l=p[u].split("="),C=l.slice(1).join("=");this.json||'"'!==C.charAt(0)||(C=C.slice(1,-1));try{var m=l[0].replace(d,decodeURIComponent);if(C=o.read?o.read(C,m):o(C,m)||C.replace(d,decodeURIComponent),this.json)try{C=JSON.parse(C)}catch(e){}if(n===m){c=C;break}n||(c[m]=C)}catch(e){}}return c}}return t.set=t,t.get=function(e){return t.call(t,e)},t.getJSON=function(){return t.apply({json:!0},[].slice.call(arguments))},t.defaults={},t.remove=function(n,o){t(n,"",e(o,{expires:-1}))},t.withConverter=n,t}return n(function(){})});
14
 
15
 
16
  /*
1957
 
1958
  var bitrates = [];
1959
 
 
 
 
 
 
 
 
1960
  api.bind('ready', function(e,api) {
1961
  if(api.engine.engineName == 'dash' ) {
1962
  api.engine.dash.setLimitBitrateByPortal(true);
1963
  api.engine.dash.setUsePixelRatioInLimitBitrateByPortal(true);
1964
+ bitrates = api.engine.dash.getBitrateInfoListFor('video');
 
 
 
1965
  }
1966
  });
1967
 
1970
  api.bind('progress', function(e,api) {
1971
  if(api.engine.engineName == 'dash' ) {
1972
  var stream_info = bitrates[api.engine.dash.getQualityFor('video')];
1973
+ debug_log.html( "Using "+stream_info.width+"x"+stream_info.height+" at "+Math.round(stream_info.bitrate/1024)+" kbps" );
1974
+ } else {
1975
+ debug_log.remove();
1976
  }
1977
  })
1978
  }
2086
  $("div.flowplayer").removeClass("is-unSticky");
2087
  });
2088
  });
2089
+
2090
+
2091
+ // Magnific Popup suppport
2092
+ jQuery(document).on('mfpClose', function() {
2093
+ if( typeof(jQuery('.flowplayer').data('flowplayer')) != "undefined" ) jQuery('.flowplayer').data('flowplayer').unload();
2094
+ } );
2095
+
2096
+
2097
+ /*
2098
+ * Video Position Store functionality
2099
+ */
2100
+ flowplayer( function(api,root) {
2101
+ // variables
2102
+ var
2103
+ // a jQuery representation of the root DIV element
2104
+ $root = jQuery(root),
2105
+ // whether or not we should enable position saving for this video only
2106
+ forceEnablePositionSaving = ($root.data('save-position') ? true : false),
2107
+ progressEventsCount = 0,
2108
+ // number of events to pass before we auto-send current video positions
2109
+ sendPositionsEvery = 60,
2110
+ // the actual AJAX object we use to send progress data, so we can cancel it,
2111
+ // should we encounter another timeout and the first AJAX did not complete yet
2112
+ // note: this is only used for logged-in users... everyone else will use cookie/localStorage
2113
+ ajaxCall = null,
2114
+ // maximum cookie size with saved video positions we should store
2115
+ maxCookieSize = 2500,
2116
+ // whether or not localStorage is enabled
2117
+ localStorageEnabled = null,
2118
+ // key name for cookie/localStorage lookup of video positions for guest visitors
2119
+ cookieKeyName = 'video_positions',
2120
+
2121
+ // methods
2122
+ // retrieves the original source of a video
2123
+ getOriginalSource = function(video) {
2124
+ // logged-in users will have position stored within that video
2125
+ return (
2126
+ (typeof(video.sources_original) != "undefined" && typeof(video.sources_original[0]) != "undefined") ?
2127
+ video.sources_original[0] :
2128
+ video.sources[0]
2129
+ );
2130
+ },
2131
+
2132
+ // calculates a cookie byte size
2133
+ getTextByteSize = function(txt) {
2134
+ return encodeURIComponent(txt).length;
2135
+ },
2136
+
2137
+ getCookieKey = function(key) {
2138
+ return (localStorageEnabled ? localStorage.getItem(key) : Cookies.get(key));
2139
+ },
2140
+
2141
+ setCookieKey = function(key, value) {
2142
+ return (localStorageEnabled ? localStorage.setItem(key, value) : Cookies.set(key, value));
2143
+ },
2144
+
2145
+ // stores currently played/paused/stopped video position
2146
+ storeVideoPosition = function (e, api) {
2147
+ if (api.video.sources) {
2148
+ if (typeof(flowplayer['playPositions']) == 'undefined') {
2149
+ flowplayer['playPositions'] = [];
2150
+ }
2151
+
2152
+ var
2153
+ originalVideoApiPath = getOriginalSource(api.video),
2154
+ playerSource = originalVideoApiPath.src,
2155
+ position = Math.round(api.video.time);
2156
+
2157
+ // only store position if we're going to save it somewhere
2158
+ if ((flowplayer.conf.video_position_save_enable || forceEnablePositionSaving)) {
2159
+ flowplayer['playPositions'][playerSource] = position;
2160
+ }
2161
+
2162
+ // store the new position in the instance itself as well
2163
+ if (originalVideoApiPath.position) {
2164
+ originalVideoApiPath.position = position;
2165
+ }
2166
+
2167
+ // make a call home every 30 seconds to make sure a browser crash doesn't affect the position save too much
2168
+ if (progressEventsCount++ >= sendPositionsEvery) {
2169
+ if ((flowplayer.conf.video_position_save_enable || forceEnablePositionSaving) && flowplayer.conf.is_logged_in == '1') {
2170
+ // cancel any old AJAX call that might be lingering in the air
2171
+ if (ajaxCall) {
2172
+ ajaxCall.abort();
2173
+ }
2174
+
2175
+ // send the call home
2176
+ ajaxCall = sendVideoPositions(true, function () {
2177
+ ajaxCall = null;
2178
+ });
2179
+ }
2180
+
2181
+ // reset counter
2182
+ progressEventsCount = 0;
2183
+ }
2184
+ }
2185
+ },
2186
+
2187
+ // used when video unloads and another video starts playing
2188
+ forceSavePosition = function (e, api) {
2189
+ var inPlaylist = false;
2190
+
2191
+ for (var i in api.conf.playlist) {
2192
+ inPlaylist = true;
2193
+ break;
2194
+ }
2195
+
2196
+ if (inPlaylist && !flowplayer.conf.closingPage) {
2197
+ progressEventsCount = sendPositionsEvery + 1;
2198
+ storeVideoPosition(e, api);
2199
+ sendVideoPositions();
2200
+ }
2201
+ },
2202
+
2203
+ // called when the video finishes playing - removes that video position from cache, as it's no longer needed
2204
+ removeVideoPosition = function (e, api) {
2205
+ if (api.video.sources) {
2206
+ if (typeof(flowplayer['playPositions']) == 'undefined') {
2207
+ flowplayer['playPositions'] = [];
2208
+ }
2209
+
2210
+ var
2211
+ originalVideoApiPath = getOriginalSource(api.video),
2212
+ playerSource = originalVideoApiPath.src,
2213
+ position = Math.round(api.video.time);
2214
+
2215
+ if ((flowplayer.conf.video_position_save_enable || forceEnablePositionSaving)) {
2216
+ flowplayer['playPositions'][playerSource] = 0;
2217
+ }
2218
+ }
2219
+ },
2220
+
2221
+ // used to seek into the desired last stored position when he video has started
2222
+ seekIntoPosition = function (e, api) {
2223
+ var
2224
+ originalVideoApiPath = getOriginalSource(api.video),
2225
+ position = originalVideoApiPath.position;
2226
+
2227
+ if (position) {
2228
+ var do_seek = setInterval( function() {
2229
+ if( api.loading ) return;
2230
+ api.seek(position);
2231
+ clearInterval(do_seek);
2232
+ }, 10 );
2233
+ } else {
2234
+ // try to lookup position of a guest visitor
2235
+ if ((flowplayer.conf.video_position_save_enable || forceEnablePositionSaving) && flowplayer.conf.is_logged_in != '1') {
2236
+ var data = getCookieKey(cookieKeyName);
2237
+
2238
+ if (data && typeof(data) !== 'undefined') {
2239
+ try {
2240
+ data = JSON.parse(data);
2241
+
2242
+ // check if we have the position
2243
+ if (data[originalVideoApiPath.src]) {
2244
+ var do_seek = setInterval( function() {
2245
+ if( api.loading ) return;
2246
+ api.seek(data[originalVideoApiPath.src]);
2247
+ clearInterval(do_seek);
2248
+ }, 10 );
2249
+ }
2250
+ } catch (e) {
2251
+ // something went wrong...
2252
+ // TODO: shall we try to reset guest data here?
2253
+ return;
2254
+ }
2255
+ }
2256
+ }
2257
+ }
2258
+ },
2259
+
2260
+ sendVideoPositions = function(async, callback) {
2261
+ if (async !== true) {
2262
+ async = false;
2263
+ }
2264
+
2265
+ if (!callback || typeof(callback) == 'undefined') {
2266
+ callback = function() {};
2267
+ }
2268
+
2269
+ postData = [];
2270
+
2271
+ for (var video_name in flowplayer['playPositions']) {
2272
+ postData.push({
2273
+ name: video_name,
2274
+ position: flowplayer['playPositions'][video_name]
2275
+ });
2276
+ }
2277
+
2278
+ if (!postData.length) {
2279
+ return;
2280
+ }
2281
+
2282
+ // decide between saving position with an AJAX request
2283
+ // or storing positions in a cookie / localStorage
2284
+ if ((flowplayer.conf.video_position_save_enable || forceEnablePositionSaving) && flowplayer.conf.is_logged_in == '1') {
2285
+ // logged-in user, store position in their metadata on server
2286
+ return jQuery.ajax({
2287
+ type: 'POST',
2288
+ async: async,
2289
+ url: fv_fp_ajaxurl,
2290
+ complete: callback,
2291
+ data: {
2292
+ action: 'fv_wp_flowplayer_video_position_save',
2293
+ videoTimes: postData
2294
+ }
2295
+ });
2296
+ } else if ((flowplayer.conf.video_position_save_enable || forceEnablePositionSaving) && flowplayer.conf.is_logged_in != '1') {
2297
+ // guest visitor, store position in a cookie / localStorage
2298
+ try {
2299
+ var data = getCookieKey(cookieKeyName);
2300
+
2301
+ // parse the stored JSON data or create a new object if empty
2302
+ if (data && typeof(data) !== 'undefined') {
2303
+ data = JSON.parse(data);
2304
+ } else {
2305
+ data = {};
2306
+ }
2307
+
2308
+ // add / edit our video positions
2309
+ for (var i in postData) {
2310
+ data[postData[i].name] = postData[i].position;
2311
+ }
2312
+
2313
+ // serialize
2314
+ var
2315
+ serialized = JSON.stringify(data),
2316
+ dataSize = getTextByteSize(serialized);
2317
+
2318
+ // check if we're not going over maximum cache size
2319
+ if (dataSize > maxCookieSize) {
2320
+ // we're over max cache size, let's delete some older videos
2321
+ while (dataSize > maxCookieSize) {
2322
+ // remove the first entry only
2323
+ for (var i in data) {
2324
+ delete data[i];
2325
+
2326
+ // re-serialize with the value removed
2327
+ serialized = JSON.stringify(data);
2328
+ // calculate new data size, so we can exit the while loop
2329
+ dataSize = getTextByteSize(serialized);
2330
+
2331
+ break;
2332
+ }
2333
+ }
2334
+ }
2335
+
2336
+ // store the serialize value
2337
+ setCookieKey(cookieKeyName, serialized);
2338
+ } catch (e) {
2339
+ // JSON object is native to all contemporary browsers
2340
+ // ... if somebody uses anything older, they would be missing out
2341
+ // on lot more features, so just don't bug them
2342
+ return;
2343
+ }
2344
+ }
2345
+ };
2346
+
2347
+ // pause/stop/progress events
2348
+ api.bind('progress', storeVideoPosition);
2349
+ api.bind('finish', removeVideoPosition);
2350
+
2351
+ // ready event, so we can seek into the last saved position
2352
+ api.bind('ready', seekIntoPosition);
2353
+
2354
+ // TODO: find out what event can be used to force saving of playlist video positions on video change
2355
+ //api.bind('finish', forceSavePosition);
2356
+
2357
+ jQuery(window).on('beforeunload', function () {
2358
+ flowplayer.conf.closingPage = true;
2359
+ sendVideoPositions();
2360
+ });
2361
+
2362
+ // check whether local storage is enabled
2363
+ if (localStorageEnabled !== null) {
2364
+ return localStorageEnabled;
2365
+ }
2366
+
2367
+ localStorageEnabled = true;
2368
+ try {
2369
+ localStorage.setItem('t', 't');
2370
+ if (localStorage.getItem('t') !== 't') {
2371
+ localStorageEnabled = false;
2372
+ }
2373
+ localStorage.removeItem('t');
2374
+ } catch (e) {
2375
+ localStorageEnabled = false;
2376
+ }
2377
+ });
js/shortcode-editor.js CHANGED
@@ -14,7 +14,7 @@ var fv_wp_fp_shortcode;
14
  var fv_player_preview_single = -1;
15
  var fv_player_preview_window;
16
 
17
-
18
 
19
  var fv_player_shortcode_preview_unsupported = false;
20
 
@@ -24,7 +24,8 @@ jQuery(document).ready(function($){
24
  fv_player_shortcode_preview_unsupported = ua.match(/edge/i) || ua.match(/safari/i) && !ua.match(/chrome/i) ;
25
 
26
  if( jQuery().fv_player_box ) {
27
- $(document).on( 'click', '.fv-wordpress-flowplayer-button', function(e) {
 
28
  e.preventDefault();
29
  $.fv_player_box( {
30
  top: "100px",
@@ -386,7 +387,11 @@ function fv_wp_flowplayer_init() {
386
  fv_player_shortcode_preview = false;
387
  fv_player_shortcode_editor_last_url = false;
388
 
389
- if( jQuery('#widget-widget_fvplayer-'+FVFP_sWidgetId+'-text').length ){
 
 
 
 
390
  fv_wp_flowplayer_content = jQuery('#widget-widget_fvplayer-'+FVFP_sWidgetId+'-text').val();
391
  } else if( typeof(FCKeditorAPI) == 'undefined' && jQuery('#content:not([aria-hidden=true])').length){
392
  fv_wp_flowplayer_content = jQuery('#content:not([aria-hidden=true])').val();
@@ -443,7 +448,12 @@ function fv_wp_flowplayer_init() {
443
  * Sends new shortcode to editor
444
  */
445
  function fv_wp_flowplayer_insert( shortcode ) {
446
- if( typeof(FCKeditorAPI) == 'undefined' && jQuery('#content:not([aria-hidden=true])').length ) {
 
 
 
 
 
447
  fv_wp_flowplayer_content = fv_wp_flowplayer_content .replace(/#fvp_placeholder#/,shortcode);
448
  fv_wp_flowplayer_set_html( fv_wp_flowplayer_content );
449
  }else if( fv_wp_flowplayer_content.match( fv_wp_flowplayer_re_edit ) ) {
@@ -636,7 +646,9 @@ function fv_wp_flowplayer_edit() {
636
  jQuery("[name=fv_wp_flowplayer_field_splash_text]").each( function() { jQuery(this).val( '' ) } );
637
  jQuery(".fv_player_field_insert-button").attr( 'value', 'Insert' );
638
 
639
- if(jQuery('#widget-widget_fvplayer-'+FVFP_sWidgetId+'-text').length){
 
 
640
  if(fv_wp_flowplayer_content.match(/\[/) ) {
641
  fv_wp_flowplayer_content = '[<'+fvwpflowplayer_helper_tag+' rel="FCKFVWPFlowplayerPlaceholder">&shy;</'+fvwpflowplayer_helper_tag+'>'+fv_wp_flowplayer_content.replace('[','')+'';
642
  } else {
@@ -998,14 +1010,21 @@ function fv_wp_flowplayer_dialog_resize() {
998
 
999
 
1000
  function fv_wp_flowplayer_on_close() {
 
 
1001
  fv_wp_flowplayer_init();
1002
  fv_wp_flowplayer_set_html( fv_wp_flowplayer_content.replace( fv_wp_flowplayer_re_insert, '' ) );
1003
  jQuery('#fv-player-shortcode-editor-preview-target').html('');
1004
  }
1005
 
1006
 
1007
- function fv_wp_flowplayer_set_html( html ) {
1008
- if( jQuery('#widget-widget_fvplayer-'+FVFP_sWidgetId+'-text').length ){
 
 
 
 
 
1009
  jQuery('#widget-widget_fvplayer-'+FVFP_sWidgetId+'-text').val(html);
1010
  jQuery('#widget-widget_fvplayer-'+FVFP_sWidgetId+'-text').trigger('fv_flowplayer_shortcode_insert', [ html ] );
1011
  }else if( typeof(FCKeditorAPI) == 'undefined' && jQuery('#content:not([aria-hidden=true])').length ){
@@ -1158,7 +1177,14 @@ function fv_wp_flowplayer_submit( preview ) {
1158
 
1159
  aSplashText.push(jQuery('[name=fv_wp_flowplayer_field_splash_text]', this).attr('value').trim().replace(/\;/gi,'\\;').replace(/"/gi,'&amp;quot;') );
1160
 
1161
- aPlaylistSubtitles.push(jQuery('[name=fv_wp_flowplayer_field_subtitles]', jQuery('.fv-player-tab-subtitles table').eq(i)).attr('value').trim().replace(/\;/gi,'\\;').replace(/"/gi,'&amp;quot;') );
 
 
 
 
 
 
 
1162
 
1163
  if( i == 0 ) return;
1164
  var aPlaylistItem = new Array();
@@ -1500,4 +1526,80 @@ function fv_flowplayer_shortcode_editor_cleanup(sInput) {
1500
 
1501
  jQuery(document).on('fv_flowplayer_shortcode_insert', function(e) {
1502
  jQuery(e.target).siblings('.button.fv-wordpress-flowplayer-button').val('Edit');
1503
- })
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  var fv_player_preview_single = -1;
15
  var fv_player_preview_window;
16
 
17
+ var fv_player_editor_button_clicked = 0;
18
 
19
  var fv_player_shortcode_preview_unsupported = false;
20
 
24
  fv_player_shortcode_preview_unsupported = ua.match(/edge/i) || ua.match(/safari/i) && !ua.match(/chrome/i) ;
25
 
26
  if( jQuery().fv_player_box ) {
27
+ $(document).on( 'click', '.fv-wordpress-flowplayer-button, .fv-player-editor-button', function(e) {
28
+ fv_player_editor_button_clicked = this;
29
  e.preventDefault();
30
  $.fv_player_box( {
31
  top: "100px",
387
  fv_player_shortcode_preview = false;
388
  fv_player_shortcode_editor_last_url = false;
389
 
390
+ var field = jQuery(fv_player_editor_button_clicked).parents('.fv-player-editor-wrapper').find('.fv-player-editor-field');
391
+ if( field.length ) {
392
+ fv_wp_flowplayer_content = jQuery(field).val();
393
+
394
+ } else if( jQuery('#widget-widget_fvplayer-'+FVFP_sWidgetId+'-text').length ){
395
  fv_wp_flowplayer_content = jQuery('#widget-widget_fvplayer-'+FVFP_sWidgetId+'-text').val();
396
  } else if( typeof(FCKeditorAPI) == 'undefined' && jQuery('#content:not([aria-hidden=true])').length){
397
  fv_wp_flowplayer_content = jQuery('#content:not([aria-hidden=true])').val();
448
  * Sends new shortcode to editor
449
  */
450
  function fv_wp_flowplayer_insert( shortcode ) {
451
+ var field = jQuery(fv_player_editor_button_clicked).parents('.fv-player-editor-wrapper').find('.fv-player-editor-field');
452
+ if( field.length ) {
453
+ field.val(shortcode);
454
+ field.trigger('fv_flowplayer_shortcode_insert', [ shortcode ] );
455
+
456
+ } else if( typeof(FCKeditorAPI) == 'undefined' && jQuery('#content:not([aria-hidden=true])').length ) {
457
  fv_wp_flowplayer_content = fv_wp_flowplayer_content .replace(/#fvp_placeholder#/,shortcode);
458
  fv_wp_flowplayer_set_html( fv_wp_flowplayer_content );
459
  }else if( fv_wp_flowplayer_content.match( fv_wp_flowplayer_re_edit ) ) {
646
  jQuery("[name=fv_wp_flowplayer_field_splash_text]").each( function() { jQuery(this).val( '' ) } );
647
  jQuery(".fv_player_field_insert-button").attr( 'value', 'Insert' );
648
 
649
+ var field = jQuery(fv_player_editor_button_clicked).parents('.fv-player-editor-wrapper').find('.fv-player-editor-field');
650
+ if( field.length || jQuery('#widget-widget_fvplayer-'+FVFP_sWidgetId+'-text').length){
651
+ // this is a horrible hack as it adds the hidden marker to the otherwise clean text field value just to make sure the shortcode varible below is parsed properly. But it allows some extra text to be entered into the text widget, so for now - ok
652
  if(fv_wp_flowplayer_content.match(/\[/) ) {
653
  fv_wp_flowplayer_content = '[<'+fvwpflowplayer_helper_tag+' rel="FCKFVWPFlowplayerPlaceholder">&shy;</'+fvwpflowplayer_helper_tag+'>'+fv_wp_flowplayer_content.replace('[','')+'';
654
  } else {
1010
 
1011
 
1012
  function fv_wp_flowplayer_on_close() {
1013
+ //fv_player_editor_button_clicked = false; // todo: is it not too early?
1014
+
1015
  fv_wp_flowplayer_init();
1016
  fv_wp_flowplayer_set_html( fv_wp_flowplayer_content.replace( fv_wp_flowplayer_re_insert, '' ) );
1017
  jQuery('#fv-player-shortcode-editor-preview-target').html('');
1018
  }
1019
 
1020
 
1021
+ function fv_wp_flowplayer_set_html( html ) {
1022
+ var field = jQuery(fv_player_editor_button_clicked).parents('.fv-player-editor-wrapper').find('.fv-player-editor-field');
1023
+ if( field.length ) {
1024
+ field.val(html);
1025
+ field.trigger('fv_flowplayer_shortcode_insert', [ html ] );
1026
+
1027
+ } else if( jQuery('#widget-widget_fvplayer-'+FVFP_sWidgetId+'-text').length ){
1028
  jQuery('#widget-widget_fvplayer-'+FVFP_sWidgetId+'-text').val(html);
1029
  jQuery('#widget-widget_fvplayer-'+FVFP_sWidgetId+'-text').trigger('fv_flowplayer_shortcode_insert', [ html ] );
1030
  }else if( typeof(FCKeditorAPI) == 'undefined' && jQuery('#content:not([aria-hidden=true])').length ){
1177
 
1178
  aSplashText.push(jQuery('[name=fv_wp_flowplayer_field_splash_text]', this).attr('value').trim().replace(/\;/gi,'\\;').replace(/"/gi,'&amp;quot;') );
1179
 
1180
+ var video_subtitles = jQuery('.fv-player-tab-subtitles table').eq(i);
1181
+ video_subtitles.find('[name=fv_wp_flowplayer_field_subtitles]').each( function() {
1182
+ if( jQuery(this).prev('.fv_wp_flowplayer_field_subtitles_lang').val() ) {
1183
+ aPlaylistSubtitles.push('');
1184
+ return;
1185
+ }
1186
+ aPlaylistSubtitles.push( jQuery(this).attr('value').trim().replace(/\;/gi,'\\;').replace(/"/gi,'&amp;quot;') );
1187
+ });
1188
 
1189
  if( i == 0 ) return;
1190
  var aPlaylistItem = new Array();
1526
 
1527
  jQuery(document).on('fv_flowplayer_shortcode_insert', function(e) {
1528
  jQuery(e.target).siblings('.button.fv-wordpress-flowplayer-button').val('Edit');
1529
+ })
1530
+
1531
+
1532
+
1533
+ jQuery( function($) {
1534
+ $(document).ready( 'fv_wp_flowplayer_init' );
1535
+
1536
+ jQuery('.fv-player-editor-wrapper').each( function() { fv_show_video( jQuery(this) ) }); // show last add more button only
1537
+
1538
+ $(document).on( 'fv_flowplayer_shortcode_insert', '.fv-player-editor-field', function() {
1539
+ console.log('fv_flowplayer_shortcode_insert',fv_player_editor_button_clicked);
1540
+ fv_load_video_preview( jQuery(this).parents('.fv-player-editor-wrapper'));
1541
+ } );
1542
+
1543
+ function fv_show_video( wrapper ) {
1544
+ if( wrapper.find('.fv-player-editor-field').val() ) {
1545
+ wrapper.find('.edit-video').show();
1546
+ wrapper.find('.add-video').hide();
1547
+ }
1548
+ else {
1549
+ wrapper.find('.edit-video').hide();
1550
+ wrapper.find('.add-video').show();
1551
+ wrapper.find('.fv-player-editor-preview').html('');
1552
+ }
1553
+
1554
+ jQuery('[data-key='+wrapper.data('key')+'] .fv-player-editor-more').last().show(); // show last add more button only
1555
+ }
1556
+
1557
+ function fv_remove_video( id ) {
1558
+ $( '#widget-widget_fvplayer-'+id+'-text' ).val("");
1559
+ fv_show_video(id);
1560
+ $('#fv_edit_video-'+id+' .video-preview').html('');
1561
+ }
1562
+
1563
+ function fv_load_video_preview( wrapper ) {
1564
+ var shortcode = $(wrapper).find('.fv-player-editor-field').val();
1565
+ console.log('fv_load_video_preview',shortcode);
1566
+ if( shortcode && shortcode.length === 0 ) {
1567
+ return false;
1568
+ }
1569
+
1570
+ shortcode = shortcode.replace( /(width=[\'"])\d*([\'"])/, "$1320$2" ); // 320
1571
+ shortcode = shortcode.replace( /(height=[\'"])\d*([\'"])/, "$1240$2" ); // 240
1572
+
1573
+ var url = fv_Player_site_base + '?fv_player_embed=1&fv_player_preview=' + b64EncodeUnicode(shortcode);
1574
+ $.get(url, function(response) {
1575
+ wrapper.find('.fv-player-editor-preview').html( jQuery('#wrapper',response ) );
1576
+ $(document).trigger('fvp-preview-complete');
1577
+ } );
1578
+
1579
+ fv_show_video(wrapper);
1580
+ }
1581
+
1582
+ $(document).on('click','.fv-player-editor-remove', function(e) {console.log('.fv-player-editor-remove');
1583
+ var wrapper = $(this).parents('.fv-player-editor-wrapper');
1584
+ if( $('[data-key='+wrapper.data('key')+']').length == 1 ) { // if there is only single video
1585
+ wrapper.find('.fv-player-editor-field').val('');
1586
+ fv_show_video(wrapper);
1587
+ } else {
1588
+ wrapper.remove();
1589
+ jQuery('.fv-player-editor-wrapper').each( function() { fv_show_video( jQuery(this) ) }); // show last add more button only
1590
+ }
1591
+ return false;
1592
+ });
1593
+
1594
+ $(document).on('click','.fv-player-editor-more', function(e) {
1595
+ var wrapper = $(this).parents('.fv-player-editor-wrapper');
1596
+ var new_wrapper = wrapper.clone();
1597
+ new_wrapper.find('.fv-player-editor-field').val('');
1598
+ fv_show_video(new_wrapper);
1599
+ new_wrapper.insertAfter( $('[data-key='+wrapper.data('key')+']:last') ); // insert after last of the kind
1600
+ $(this).hide();
1601
+
1602
+ return false;
1603
+ });
1604
+
1605
+ });
models/custom-videos.php CHANGED
@@ -6,6 +6,8 @@ class FV_Player_Custom_Videos {
6
 
7
  var $id;
8
 
 
 
9
  public function __construct( $args ) {
10
  global $post;
11
 
@@ -18,11 +20,6 @@ class FV_Player_Custom_Videos {
18
  $this->id = $args['id'];
19
  $this->meta = $args['meta'];
20
  $this->type = $args['type'];
21
-
22
- }
23
-
24
- public function __get( $name ) {
25
- return $data;
26
  }
27
 
28
  private function esc_shortcode( $arg ) {
@@ -63,13 +60,13 @@ class FV_Player_Custom_Videos {
63
  add_filter( 'fv_flowplayer_playlist_splash', array( $FV_Player_Pro, 'youtube_splash' ), 10, 3 );
64
 
65
  add_action('admin_footer', array( $FV_Player_Pro, 'styles' ) );
66
- add_action('admin_footer', array( $FV_Player_Pro, 'scripts' ) );
67
  }
68
 
69
  add_action('admin_footer','flowplayer_prepare_scripts');
70
  }
71
 
72
- add_action('admin_footer', array( $fv_fp, 'css_enqueue' ) );
73
  }
74
 
75
  if( !is_admin() && !$args['no_form'] ) $html .= "<form method='POST'>";
@@ -82,7 +79,7 @@ class FV_Player_Custom_Videos {
82
 
83
  if( !is_admin() && !$args['no_form'] ) {
84
  $html .= "<input type='hidden' name='action' value='fv-player-custom-videos-save' />";
85
- $html .= "<input type='submit' value='Save Videos' />"; // todo: don't show when in post form
86
  $html .= "</form>";
87
  }
88
 
@@ -90,14 +87,31 @@ class FV_Player_Custom_Videos {
90
  $html .= '</div>';
91
  }
92
 
93
- if( $args['edit'] ) {
94
- if( is_admin() ) {
95
- add_action( 'admin_footer', array( $this, 'scripts' ) );
96
- } else {
97
- add_action( 'wp_footer', array( $this, 'scripts' ) );
98
- }
99
- }
100
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
  return $html;
102
  }
103
 
@@ -108,48 +122,27 @@ class FV_Player_Custom_Videos {
108
  $html = '';
109
  $count = 0;
110
  if( $this->have_videos() ) {
111
- foreach( $this->get_videos() AS $aVideo ) {
 
 
 
112
  $count++;
113
-
114
- if( $args['wrapper'] ) $html .= '<'.$args['wrapper'].' class="fv-player-custom-video">';
115
-
116
- if( $args['edit'] ) {
117
- $html .= do_shortcode('[fvplayer src="'.$this->esc_shortcode($aVideo['url']).'" autoplay="false"]');
118
- } else {
119
-
120
- $sExtra = '';
121
- if( is_array($args['shortcode']) && count($args['shortcode']) ) {
122
- foreach( $args['shortcode'] AS $key => $value ) {
123
- $sExtra .= ' '.$this->esc_shortcode($key).'="'.$this->esc_shortcode($value).'"';
124
- }
125
- }
126
- $html .= do_shortcode('[fvplayer src="'.$this->esc_shortcode($aVideo['url']).'" caption="'.$this->esc_shortcode($aVideo['title']).'"'.$sExtra.']');
127
- }
128
-
129
- if( $args['edit'] ) {
130
- $html .= '<p><input class="fv_player_custom_video fv_player_custom_video_url regular-text" type="text" name="fv_player_videos['.$this->meta.'][]" placeholder="Video URL" value="'.esc_attr($aVideo['url']).'" /></p>'."\n";
131
- $html .= '<p><input class="fv_player_custom_video regular-text" type="text" name="fv_player_videos_titles['.$this->meta.'][]" value="'.esc_attr($aVideo['title']).'" placeholder="Video title" /></p>'."\n";
132
- if( count($this->get_videos()) == $count && $count < $args['limit'] ) $html .= '<a class="fv-player-custom-video-add" href="#">Add more</a> ';
133
- $html .= '<a class="fv-player-custom-video-remove" href="#">Remove</a> ';
134
-
135
- }
136
-
137
- if( $args['wrapper'] ) $html .= '</'.$args['wrapper'].'>'."\n";
138
-
139
  }
140
 
 
 
 
 
141
  } else if( $args['edit'] ) {
142
  $html .= '<'.$args['wrapper'].' class="fv-player-custom-video">';
143
-
144
- $html .= "<input class='fv_player_custom_video fv_player_custom_video_url regular-text' placeholder='URL' type='text' name='fv_player_videos[".$this->meta."][]' /><br />\n";
145
- $html .= "<input class='fv_player_custom_video regular-text' placeholder='Title' type='text' name='fv_player_videos_titles[".$this->meta."][]' /><br />\n";
146
- if( 1 < $args['limit'] ) $html .= "<a class='fv-player-custom-video-add' href='#'>Add more</a>\n";
147
-
148
  $html .= '</'.$args['wrapper'].'>';
149
  }
150
 
151
  $html .= "<input type='hidden' name='fv-player-custom-videos-entity-id[".$this->meta."]' value='".esc_attr($this->id)."' />";
152
- $html .= "<input type='hidden' name='fv-player-custom-videos-entity-type[".$this->meta."]' value='".esc_attr($this->type)."' />";
153
 
154
  return $html;
155
  }
@@ -164,7 +157,11 @@ class FV_Player_Custom_Videos {
164
  $aVideos = array();
165
  if( is_array($aMeta) && count($aMeta) > 0 ) {
166
  foreach( $aMeta AS $aVideo ) {
167
- if( is_array($aVideo) && isset($aVideo['url']) && isset($aVideo['title']) ) $aVideos[] = $aVideo;
 
 
 
 
168
  }
169
  }
170
 
@@ -173,77 +170,13 @@ class FV_Player_Custom_Videos {
173
 
174
  public function have_videos() {
175
  return count($this->get_videos()) ? true : false;
176
- }
177
 
178
- public function scripts() {
179
- ?>
180
- <script>
181
- function fv_player_custom_video_add(row) {
182
- var row = jQuery(row);
183
- row.parents('.fv-player-custom-video').parent().append( row.parents('.fv-player-custom-video').clone() );
184
- row.parents('.fv-player-custom-video').parent().find('.fv-player-custom-video:last').find('input[type=text]').val('');
185
- row.parents('.fv-player-custom-video').parent().find('.fv-player-custom-video:last iframe').remove();
186
- row.parents('.fv-player-custom-video').parent().find('.fv-player-custom-video:last .flowplayer').remove();
187
- row.parents('.fv-player-custom-video').parent().find('.fv-player-custom-video:last .fv-player-custom-video-remove').remove();
188
- if( row.hasClass('fv-player-custom-video-add') ) row.remove();
189
- }
190
-
191
- jQuery(document).on('click','.fv-player-custom-video-remove', function(e) {
192
- e.preventDefault();
193
- if( jQuery(this).parents('.fv-player-custom-video-list').find('.fv-player-custom-video').length == 1 ) {
194
- fv_player_custom_video_add(this);
195
- }
196
- jQuery(this).parents('.fv-player-custom-video').remove();
197
- });
198
- jQuery(document).on('click','.fv-player-custom-video-add', function(e) {
199
- e.preventDefault();
200
-
201
- fv_player_custom_video_add(this);
202
- });
203
-
204
- var fv_player_preview = false;
205
- var fv_player_shortcode_preview_unsupported = false;
206
- jQuery(document).ready(function(){
207
- var ua = window.navigator.userAgent;
208
- fv_player_shortcode_preview_unsupported = ua.match(/edge/i) || ua.match(/safari/i) && !ua.match(/chrome/i) ;
209
- })
210
-
211
- jQuery(document).on('change', '.fv_player_custom_video_url', function() {
212
- if( !jQuery(this).val().match(/^(https?:)?\/\//) ){
213
- jQuery(this).siblings('iframe').remove();
214
- return;
215
- }
216
- if(fv_player_preview || fv_player_shortcode_preview_unsupported){
217
- return;
218
- }
219
- fv_player_preview = true;
220
-
221
- if( jQuery(this).siblings('iframe').length == 0 ) {
222
- jQuery(this).before('<iframe allowfullscreen class="fv_player_custom_video_preview" scrolling="no"></iframe>');
223
- jQuery(this).before('<p class="loading-preview"><?php _e('Loading preview...','fv-wordpress-flowplayer'); ?></p>');
224
- }
225
-
226
- jQuery(this).siblings('.flowplayer').remove();
227
-
228
- var url = '<?php echo home_url('/'); ?>?fv_player_embed=1&fv_player_preview=' + b64EncodeUnicode('[fvplayer src="'+jQuery(this).val()+'" embed="false"]');
229
- jQuery(this).siblings('iframe').attr('src',url).hide();
230
- jQuery(this).siblings('.loading-preview').show();
231
-
232
- });
233
-
234
- function b64EncodeUnicode(str) {
235
- return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function(match, p1) {
236
- return String.fromCharCode('0x' + p1);
237
- }));
238
- }
239
-
240
- jQuery(document).on('fvp-preview-complete', function() {
241
- jQuery('.fv_player_custom_video_preview').show();
242
- jQuery('.loading-preview').hide();
243
- fv_player_preview = false;
244
- });
245
- </script>
246
- <?php
247
  }
248
 
249
 
@@ -254,6 +187,8 @@ class FV_Player_Custom_Videos {
254
 
255
  class FV_Player_Custom_Videos_Master {
256
 
 
 
257
  function __construct() {
258
 
259
  add_action( 'init', array( $this, 'save' ) ); // saving of user profile, both front and back end
@@ -262,7 +197,7 @@ class FV_Player_Custom_Videos_Master {
262
  add_filter( 'show_password_fields', array( $this, 'user_profile' ), 10, 2 );
263
  add_action( 'add_meta_boxes', array( $this, 'add_meta_boxes' ), 999, 2 );
264
 
265
- add_filter( 'the_content', array( $this, 'show' ) );
266
  add_filter( 'get_the_author_description', array( $this, 'show_bio' ), 10, 2 );
267
 
268
  // EDD
@@ -270,14 +205,29 @@ class FV_Player_Custom_Videos_Master {
270
  add_action('edd_pre_update_user_profile', array($this, 'save'));
271
 
272
  // bbPress
273
- add_filter( 'bbp_template_after_user_profile', array( $this, 'bbpress_profile' ), 10, 2 );
274
  add_filter( 'bbp_user_edit_after_about', array( $this, 'bbpress_edit' ), 10, 2 );
275
  }
276
 
277
  function add_meta_boxes() {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
278
  global $fv_fp;
279
  if( isset($fv_fp->conf['profile_videos_enable_bio']) && $fv_fp->conf['profile_videos_enable_bio'] == 'true' ) {
280
- global $post;
281
  $aMeta = get_post_custom($post->ID);
282
  if( $aMeta ) {
283
  foreach( $aMeta AS $key => $aMetas ) {
@@ -308,12 +258,18 @@ class FV_Player_Custom_Videos_Master {
308
 
309
  <div>
310
  <?php
311
- $objVideos = new FV_Player_Custom_Videos(array( 'id' => bbp_get_displayed_user_field('id'), 'type' => 'user' ));
312
  echo $objVideos->get_form( array('no_form' => true) );
313
  ?>
314
  </div>
315
 
316
  <?php
 
 
 
 
 
 
317
  }
318
 
319
  function bbpress_profile() {
@@ -322,7 +278,7 @@ class FV_Player_Custom_Videos_Master {
322
  if( !isset($fv_fp->conf['profile_videos_enable_bio']) || $fv_fp->conf['profile_videos_enable_bio'] !== 'true' )
323
  return;
324
 
325
- $objVideos = new FV_Player_Custom_Videos(array( 'id' => bbp_get_displayed_user_field('id'), 'type' => 'user' ));
326
  if( $objVideos->have_videos() ) : ?>
327
  <div id="bbp-user-profile" class="bbp-user-profile">
328
  <h2 class="entry-title"><?php _e( 'Videos', 'bbpress' ); ?></h2>
@@ -337,31 +293,38 @@ class FV_Player_Custom_Videos_Master {
337
 
338
  function meta_box( $aPosts, $args ) {
339
  global $FV_Player_Custom_Videos_form_instances;
340
- unset($FV_Player_Custom_Videos_form_instances[$this->meta]);
341
-
342
- $objVideos = $args['args'];
343
  echo $objVideos->get_form();
344
  }
345
 
 
 
 
 
 
 
 
 
 
346
  function save() {
 
347
  if( !isset($_POST['fv_player_videos']) || !isset($_POST['fv-player-custom-videos-entity-type']) || !isset($_POST['fv-player-custom-videos-entity-id']) ) {
348
  return;
349
  }
350
 
351
- // todo: permission check!
352
 
353
- foreach( $_POST['fv_player_videos'] AS $meta => $aValues ) {
 
 
354
  if( $_POST['fv-player-custom-videos-entity-type'][$meta] == 'user' ) {
355
  delete_user_meta( $_POST['fv-player-custom-videos-entity-id'][$meta], $meta );
356
- foreach( $aValues AS $key => $value ) {
357
- if( strlen($value) == 0 ) continue;
358
- $aVideo = array(
359
- 'url' => trim(strip_tags($value)),
360
- 'title' => trim(htmlspecialchars($_POST['fv_player_videos_titles'][$meta][$key]))
361
- );
362
- add_user_meta( $_POST['fv-player-custom-videos-entity-id'][$meta], $meta, $aVideo );
363
  }
364
-
365
  }
366
 
367
  }
@@ -375,18 +338,17 @@ class FV_Player_Custom_Videos_Master {
375
 
376
  // todo: permission check!
377
 
378
- foreach( $_POST['fv_player_videos'] AS $meta => $aValues ) {
379
  if( $_POST['fv-player-custom-videos-entity-type'][$meta] == 'post' ) {
380
  delete_post_meta( $post_id, $meta );
381
- foreach( $aValues AS $key => $value ) {
382
- if( strlen($value) == 0 ) continue;
383
- $aVideo = array(
384
- 'url' => trim(strip_tags($value)),
385
- 'title' => trim(htmlspecialchars($_POST['fv_player_videos_titles'][$meta][$key]))
386
- );
387
- add_post_meta( $post_id, $meta, $aVideo );
388
  }
389
-
390
  }
391
 
392
  }
@@ -399,9 +361,11 @@ class FV_Player_Custom_Videos_Master {
399
  $aMeta = get_post_custom($post->ID);
400
  if( $aMeta ) {
401
  foreach( $aMeta AS $key => $aMetas ) {
402
- $objVideos = new FV_Player_Custom_Videos( array('id' => $post->ID, 'meta' => $key, 'type' => 'post' ) );
403
- if( $objVideos->have_videos() ) {
404
- $content .= $objVideos->get_html();
 
 
405
  }
406
  }
407
  }
@@ -459,9 +423,27 @@ class FV_Player_Custom_Videos_Master {
459
  <?php echo $user->get_form(array('no_form' => true));?>
460
  </p>
461
  <?php
 
 
 
 
 
 
462
  }
463
 
464
  }
465
 
466
 
467
  $FV_Player_Custom_Videos_Master = new FV_Player_Custom_Videos_Master;
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
  var $id;
8
 
9
+ var $instance_id;
10
+
11
  public function __construct( $args ) {
12
  global $post;
13
 
20
  $this->id = $args['id'];
21
  $this->meta = $args['meta'];
22
  $this->type = $args['type'];
 
 
 
 
 
23
  }
24
 
25
  private function esc_shortcode( $arg ) {
60
  add_filter( 'fv_flowplayer_playlist_splash', array( $FV_Player_Pro, 'youtube_splash' ), 10, 3 );
61
 
62
  add_action('admin_footer', array( $FV_Player_Pro, 'styles' ) );
63
+ add_action('admin_footer', array( $FV_Player_Pro, 'scripts' ) ); // todo: not just for FV Player Pro
64
  }
65
 
66
  add_action('admin_footer','flowplayer_prepare_scripts');
67
  }
68
 
69
+ add_action('admin_footer', array( $this, 'shortcode_editor_load' ), 0 );
70
  }
71
 
72
  if( !is_admin() && !$args['no_form'] ) $html .= "<form method='POST'>";
79
 
80
  if( !is_admin() && !$args['no_form'] ) {
81
  $html .= "<input type='hidden' name='action' value='fv-player-custom-videos-save' />";
82
+ $html .= "<input type='submit' value='Save Videos' />";
83
  $html .= "</form>";
84
  }
85
 
87
  $html .= '</div>';
88
  }
89
 
90
+ return $html;
91
+ }
92
+
93
+ public function get_html_part( $video, $edit = false ) {
94
+
95
+ // exp: what matters here is .fv-player-editor-field and .fv-player-editor-button wrapped in .fv-player-editor-wrapper and .fv-player-editor-preview
96
+ if( $edit ) {
97
+ $html = "<div class='fv-player-editor-wrapper' data-key='fv-player-editor-field-".$this->meta."'>
98
+ <div class='inside inside-child'>
99
+ <div class='fv-player-editor-preview'>".($video ? do_shortcode($video) : '')."</div>
100
+ <input class='attachement-shortcode fv-player-editor-field' name='fv_player_videos[".$this->meta."][]' type='hidden' value='".esc_attr($video)."' />
101
+ <div class='edit-video' ".(!$video ? 'style="display:none"' : '').">
102
+ <button class='button fv-player-editor-button'>Edit Video</button>
103
+ <button class='button fv-player-editor-remove'>Remove Video</button>
104
+ <button class='button fv-player-editor-more' style='display:none'>Add Another Video</button>
105
+ </div>
106
+
107
+ <div class='add-video' ".($video ? 'style="display:none"' : '').">
108
+ <button class='button fv-player-editor-button'>Add Video</button>
109
+ </div>
110
+ </div>
111
+ </div>";
112
+ } else {
113
+ $html = do_shortcode($video);
114
+ }
115
  return $html;
116
  }
117
 
122
  $html = '';
123
  $count = 0;
124
  if( $this->have_videos() ) {
125
+
126
+ if( $args['wrapper'] ) $html .= '<'.$args['wrapper'].' class="fv-player-custom-video">';
127
+
128
+ foreach( $this->get_videos() AS $video ) {
129
  $count++;
130
+ $html .= $this->get_html_part($video, $args['edit']);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
131
  }
132
 
133
+ $html .= '<div style="clear: both"></div>'."\n";
134
+
135
+ if( $args['wrapper'] ) $html .= '</'.$args['wrapper'].'>'."\n";
136
+
137
  } else if( $args['edit'] ) {
138
  $html .= '<'.$args['wrapper'].' class="fv-player-custom-video">';
139
+ $html .= $this->get_html_part(false, true);
140
+ $html .= '<div style="clear: both"></div>'."\n";
 
 
 
141
  $html .= '</'.$args['wrapper'].'>';
142
  }
143
 
144
  $html .= "<input type='hidden' name='fv-player-custom-videos-entity-id[".$this->meta."]' value='".esc_attr($this->id)."' />";
145
+ $html .= "<input type='hidden' name='fv-player-custom-videos-entity-type[".$this->meta."]' value='".esc_attr($this->type)."' />";
146
 
147
  return $html;
148
  }
157
  $aVideos = array();
158
  if( is_array($aMeta) && count($aMeta) > 0 ) {
159
  foreach( $aMeta AS $aVideo ) {
160
+ if( is_array($aVideo) && isset($aVideo['url']) && isset($aVideo['title']) ) {
161
+ $aVideos[] = '[fvplayer src="'.$this->esc_shortcode($aVideo['url']).'" caption="'.$this->esc_shortcode($aVideo['title']).'"]';
162
+ } else if( is_string($aVideo) && stripos($aVideo,'[fvplayer ') === 0 ) {
163
+ $aVideos[] = $aVideo;
164
+ }
165
  }
166
  }
167
 
170
 
171
  public function have_videos() {
172
  return count($this->get_videos()) ? true : false;
173
+ }
174
 
175
+ function shortcode_editor_load() {
176
+ if( !function_exists('fv_flowplayer_admin_select_popups') ) {
177
+ fv_wp_flowplayer_edit_form_after_editor();
178
+ fv_player_shortcode_editor_scripts_enqueue();
179
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
180
  }
181
 
182
 
187
 
188
  class FV_Player_Custom_Videos_Master {
189
 
190
+ var $aMetaBoxes = array();
191
+
192
  function __construct() {
193
 
194
  add_action( 'init', array( $this, 'save' ) ); // saving of user profile, both front and back end
197
  add_filter( 'show_password_fields', array( $this, 'user_profile' ), 10, 2 );
198
  add_action( 'add_meta_boxes', array( $this, 'add_meta_boxes' ), 999, 2 );
199
 
200
+ add_filter( 'the_content', array( $this, 'show' ) ); // adding post videos after content automatically
201
  add_filter( 'get_the_author_description', array( $this, 'show_bio' ), 10, 2 );
202
 
203
  // EDD
205
  add_action('edd_pre_update_user_profile', array($this, 'save'));
206
 
207
  // bbPress
208
+ add_action( 'bbp_template_after_user_profile', array( $this, 'bbpress_profile' ), 10 );
209
  add_filter( 'bbp_user_edit_after_about', array( $this, 'bbpress_edit' ), 10, 2 );
210
  }
211
 
212
  function add_meta_boxes() {
213
+ global $post;
214
+ if( !empty($this->aMetaBoxes[$post->post_type]) ) {
215
+ foreach( $this->aMetaBoxes[$post->post_type] AS $meta_key => $name ) {
216
+ $objVideos = new FV_Player_Custom_Videos( array('id' => $post->ID, 'meta' => $meta_key, 'type' => 'post' ) );
217
+ add_meta_box( 'fv_player_custom_videos-field_'.$meta_key,
218
+ $name,
219
+ array( $this, 'meta_box' ),
220
+ null,
221
+ 'normal',
222
+ 'high',
223
+ $objVideos );
224
+ }
225
+ }
226
+
227
+ // todo: following code should not add the meta boxes added by the above again!
228
+
229
  global $fv_fp;
230
  if( isset($fv_fp->conf['profile_videos_enable_bio']) && $fv_fp->conf['profile_videos_enable_bio'] == 'true' ) {
 
231
  $aMeta = get_post_custom($post->ID);
232
  if( $aMeta ) {
233
  foreach( $aMeta AS $key => $aMetas ) {
258
 
259
  <div>
260
  <?php
261
+ $objVideos = new FV_Player_Custom_Videos(array( 'id' => bbp_get_displayed_user_field('ID'), 'type' => 'user' ));
262
  echo $objVideos->get_form( array('no_form' => true) );
263
  ?>
264
  </div>
265
 
266
  <?php
267
+
268
+ if( !function_exists('is_plugin_active') ) include( ABSPATH . 'wp-admin/includes/plugin.php' );
269
+ if( !function_exists('fv_wp_flowplayer_edit_form_after_editor') ) include( dirname( __FILE__ ) . '/../controller/editor.php' );
270
+
271
+ fv_wp_flowplayer_edit_form_after_editor();
272
+ fv_player_shortcode_editor_scripts_enqueue();
273
  }
274
 
275
  function bbpress_profile() {
278
  if( !isset($fv_fp->conf['profile_videos_enable_bio']) || $fv_fp->conf['profile_videos_enable_bio'] !== 'true' )
279
  return;
280
 
281
+ $objVideos = new FV_Player_Custom_Videos(array( 'id' => bbp_get_displayed_user_field('ID'), 'type' => 'user' ));
282
  if( $objVideos->have_videos() ) : ?>
283
  <div id="bbp-user-profile" class="bbp-user-profile">
284
  <h2 class="entry-title"><?php _e( 'Videos', 'bbpress' ); ?></h2>
293
 
294
  function meta_box( $aPosts, $args ) {
295
  global $FV_Player_Custom_Videos_form_instances;
296
+ $objVideos = $args['args'];
297
+ unset($FV_Player_Custom_Videos_form_instances[$objVideos->meta]);
 
298
  echo $objVideos->get_form();
299
  }
300
 
301
+ function register_metabox( $name, $meta_key, $post_type, $display ) {
302
+ if( !isset($this->aMetaBoxes[$post_type]) ) $this->aMetaBoxes[$post_type] = array();
303
+ if( !isset($this->aMetaBoxesDisplay[$post_type]) ) $this->aMetaBoxesDisplay[$post_type] = array();
304
+
305
+ $this->aMetaBoxes[$post_type][$meta_key] = $name;
306
+ $this->aMetaBoxesDisplay[$post_type][$meta_key] = $display;
307
+ }
308
+
309
+
310
  function save() {
311
+
312
  if( !isset($_POST['fv_player_videos']) || !isset($_POST['fv-player-custom-videos-entity-type']) || !isset($_POST['fv-player-custom-videos-entity-id']) ) {
313
  return;
314
  }
315
 
 
316
 
317
+
318
+ // todo: permission check!
319
+ foreach( $_POST['fv_player_videos'] AS $meta => $videos ) {
320
  if( $_POST['fv-player-custom-videos-entity-type'][$meta] == 'user' ) {
321
  delete_user_meta( $_POST['fv-player-custom-videos-entity-id'][$meta], $meta );
322
+
323
+ foreach( $videos AS $video ) {
324
+ if( strlen($video) == 0 ) continue;
325
+
326
+ add_user_meta( $_POST['fv-player-custom-videos-entity-id'][$meta], $meta, $video );
 
 
327
  }
 
328
  }
329
 
330
  }
338
 
339
  // todo: permission check!
340
 
341
+ foreach( $_POST['fv_player_videos'] AS $meta => $value ) {
342
  if( $_POST['fv-player-custom-videos-entity-type'][$meta] == 'post' ) {
343
  delete_post_meta( $post_id, $meta );
344
+
345
+ if( is_array($value) && count($value) > 0 ) {
346
+ foreach( $value AS $k => $v ) {
347
+ if( strlen($v) == 0 ) continue;
348
+
349
+ add_post_meta( $post_id, $meta, $v );
350
+ }
351
  }
 
352
  }
353
 
354
  }
361
  $aMeta = get_post_custom($post->ID);
362
  if( $aMeta ) {
363
  foreach( $aMeta AS $key => $aMetas ) {
364
+ if( !empty($this->aMetaBoxesDisplay[$post->post_type][$key]) && $this->aMetaBoxesDisplay[$post->post_type][$key] ) {
365
+ $objVideos = new FV_Player_Custom_Videos( array('id' => $post->ID, 'meta' => $key, 'type' => 'post' ) );
366
+ if( $objVideos->have_videos() ) {
367
+ $content .= $objVideos->get_html();
368
+ }
369
  }
370
  }
371
  }
423
  <?php echo $user->get_form(array('no_form' => true));?>
424
  </p>
425
  <?php
426
+
427
+ if( !function_exists('is_plugin_active') ) include( ABSPATH . 'wp-admin/includes/plugin.php' );
428
+ if( !function_exists('fv_wp_flowplayer_edit_form_after_editor') ) include( dirname( __FILE__ ) . '/../controller/editor.php' );
429
+
430
+ fv_wp_flowplayer_edit_form_after_editor();
431
+ fv_player_shortcode_editor_scripts_enqueue();
432
  }
433
 
434
  }
435
 
436
 
437
  $FV_Player_Custom_Videos_Master = new FV_Player_Custom_Videos_Master;
438
+
439
+
440
+
441
+
442
+ class FV_Player_MetaBox {
443
+
444
+ function __construct( $name, $meta_key, $post_type, $display = false ) {
445
+ global $FV_Player_Custom_Videos_Master;
446
+ $FV_Player_Custom_Videos_Master->register_metabox( $name, $meta_key, $post_type, $display );
447
+ }
448
+
449
+ }
models/flowplayer-frontend.php CHANGED
@@ -980,7 +980,7 @@ class flowplayer_frontend extends flowplayer
980
  }
981
 
982
  $subtitles = explode( ";",$subtitles);
983
- if( empty($subtitles[$index]) ) return $aSubtitles;
984
 
985
  $subtitles = $subtitles[$index];
986
 
980
  }
981
 
982
  $subtitles = explode( ";",$subtitles);
983
+ if( empty($subtitles[$index]) ) continue;
984
 
985
  $subtitles = $subtitles[$index];
986
 
models/flowplayer.php CHANGED
@@ -572,6 +572,9 @@ class flowplayer extends FV_Wordpress_Flowplayer_Plugin {
572
 
573
  if( !isset( $conf['playlist-design'] ) ) $conf['playlist-design'] = '2017';
574
 
 
 
 
575
  // apply existing colors from old config values to the new, skin-based config array
576
  if (!isset($conf['skin-custom'])) {
577
  $conf['skin-custom'] = array();
@@ -1233,10 +1236,11 @@ class flowplayer extends FV_Wordpress_Flowplayer_Plugin {
1233
  }
1234
 
1235
  foreach( $posts AS $objPost ) {
1236
- if(
1237
- stripos($objPost->post_content,'[fvplayer') !== false ||
1238
- stripos($objPost->post_content,'[flowplayer') !== false ||
1239
- stripos($objPost->post_content,'[video') !== false
 
1240
  ) {
1241
  $bFound = true;
1242
  break;
@@ -1834,7 +1838,8 @@ class flowplayer extends FV_Wordpress_Flowplayer_Plugin {
1834
  if( stripos( __FILE__, '/themes/' ) !== false || stripos( __FILE__, '\\themes\\' ) !== false ) {
1835
  return get_template_directory_uri().'/fv-wordpress-flowplayer';
1836
  } else {
1837
- return plugins_url( '', str_replace( array('/models','\\models'), '', __FILE__ ) );
 
1838
  }
1839
  }
1840
 
@@ -1855,7 +1860,7 @@ class flowplayer extends FV_Wordpress_Flowplayer_Plugin {
1855
 
1856
 
1857
 
1858
- function get_video_src($media, $aArgs ) {
1859
  $aArgs = wp_parse_args( $aArgs, array(
1860
  'dynamic' => false,
1861
  'flash' => true,
@@ -2121,10 +2126,10 @@ class flowplayer extends FV_Wordpress_Flowplayer_Plugin {
2121
  </div>
2122
  </div>
2123
 
2124
- <?php else : ?>
2125
- <?php while ( have_posts() ) : the_post(); //is this needed? ?>
2126
- <?php
2127
-
2128
  $bFound = false;
2129
  $rewrite = get_option('rewrite_rules');
2130
  if( empty($rewrite) ) {
@@ -2133,10 +2138,7 @@ class flowplayer extends FV_Wordpress_Flowplayer_Plugin {
2133
  $sPostfix = get_query_var('fv_player_embed') > 1 ? 'fvp'.get_query_var('fv_player_embed') : 'fvp';
2134
  $sLink = user_trailingslashit( trailingslashit( get_permalink() ).$sPostfix );
2135
  }
2136
- //$content = apply_filters( 'the_content', get_the_content() );
2137
-
2138
-
2139
-
2140
  $aPlayers = explode( '<!--fv player end-->', $content );
2141
  if( $aPlayers ) {
2142
  foreach( $aPlayers AS $k => $v ) {
@@ -2152,33 +2154,31 @@ class flowplayer extends FV_Wordpress_Flowplayer_Plugin {
2152
  echo "<p>Player not found, see the full article: <a href='".get_permalink()."' target='_blank'>".get_the_title()."</a>.</p>";
2153
  }
2154
 
2155
- ?>
2156
- <?php endwhile;
2157
- endif;
2158
- ?>
2159
- </body>
2160
-
2161
- <?php wp_footer(); ?>
2162
-
2163
- <?php if( isset($_GET['fv_player_preview']) && !empty($_GET['fv_player_preview']) ) : ?>
2164
-
2165
- <script>
2166
- jQuery(document).ready( function(){
2167
- var parent = window.parent.jQuery(window.parent.document);
2168
- if( typeof(flowplayer) != "undefined" ) {
2169
- parent.trigger('fvp-preview-complete', [jQuery(document).width(),jQuery(document).height()]);
2170
-
2171
- } else {
2172
- parent.trigger('fvp-preview-error');
2173
  }
 
2174
 
2175
- });
2176
 
2177
- if (window.top===window.self) {
2178
- jQuery('#wrapper').css('margin','25px 50px 0 50px');
2179
- }
2180
- </script>
2181
- <?php endif; ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2182
 
2183
  </html>
2184
  <?php
@@ -2244,4 +2244,3 @@ function fv_wp_flowplayer_save_post( $post_id ) {
2244
  }
2245
  }
2246
  }
2247
-
572
 
573
  if( !isset( $conf['playlist-design'] ) ) $conf['playlist-design'] = '2017';
574
 
575
+ if (!isset($conf['skin-slim'])) $conf['skin-slim'] = array();
576
+ if (!isset($conf['skin-youtuby'])) $conf['skin-youtuby'] = array();
577
+
578
  // apply existing colors from old config values to the new, skin-based config array
579
  if (!isset($conf['skin-custom'])) {
580
  $conf['skin-custom'] = array();
1236
  }
1237
 
1238
  foreach( $posts AS $objPost ) {
1239
+ if( !empty($objPost->post_content) && (
1240
+ stripos($objPost->post_content,'[fvplayer') !== false ||
1241
+ stripos($objPost->post_content,'[flowplayer') !== false ||
1242
+ stripos($objPost->post_content,'[video') !== false
1243
+ )
1244
  ) {
1245
  $bFound = true;
1246
  break;
1838
  if( stripos( __FILE__, '/themes/' ) !== false || stripos( __FILE__, '\\themes\\' ) !== false ) {
1839
  return get_template_directory_uri().'/fv-wordpress-flowplayer';
1840
  } else {
1841
+ $plugin_folder = basename(dirname(dirname(__FILE__))); // make fv-wordpress-flowplayer out of {anything}/fv-wordpress-flowplayer/models/flowplayer.php
1842
+ return plugins_url($plugin_folder);
1843
  }
1844
  }
1845
 
1860
 
1861
 
1862
 
1863
+ function get_video_src($media, $aArgs = array() ) {
1864
  $aArgs = wp_parse_args( $aArgs, array(
1865
  'dynamic' => false,
1866
  'flash' => true,
2126
  </div>
2127
  </div>
2128
 
2129
+ <?php else :
2130
+
2131
+ if( stripos($content,'<!--fv player end-->') !== false ) {
2132
+
2133
  $bFound = false;
2134
  $rewrite = get_option('rewrite_rules');
2135
  if( empty($rewrite) ) {
2138
  $sPostfix = get_query_var('fv_player_embed') > 1 ? 'fvp'.get_query_var('fv_player_embed') : 'fvp';
2139
  $sLink = user_trailingslashit( trailingslashit( get_permalink() ).$sPostfix );
2140
  }
2141
+
 
 
 
2142
  $aPlayers = explode( '<!--fv player end-->', $content );
2143
  if( $aPlayers ) {
2144
  foreach( $aPlayers AS $k => $v ) {
2154
  echo "<p>Player not found, see the full article: <a href='".get_permalink()."' target='_blank'>".get_the_title()."</a>.</p>";
2155
  }
2156
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2157
  }
2158
+ endif;
2159
 
2160
+ wp_footer();
2161
 
2162
+ if( isset($_GET['fv_player_preview']) && !empty($_GET['fv_player_preview']) ) : ?>
2163
+ <script>
2164
+ jQuery(document).ready( function(){
2165
+ var parent = window.parent.jQuery(window.parent.document);
2166
+ if( typeof(flowplayer) != "undefined" ) {
2167
+ parent.trigger('fvp-preview-complete', [jQuery(document).width(),jQuery(document).height()]);
2168
+
2169
+ } else {
2170
+ parent.trigger('fvp-preview-error');
2171
+ }
2172
+
2173
+ });
2174
+
2175
+ if (window.top===window.self) {
2176
+ jQuery('#wrapper').css('margin','25px 50px 0 50px');
2177
+ }
2178
+ </script>
2179
+ <?php endif; ?>
2180
+
2181
+ </body>
2182
 
2183
  </html>
2184
  <?php
2244
  }
2245
  }
2246
  }
 
models/player-position-save.php ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class FV_Player_Position_Save {
3
+
4
+ public function __construct() {
5
+ add_action( 'wp_ajax_fv_wp_flowplayer_video_position_save', array($this, 'video_position_save') );
6
+ add_filter('fv_player_item', array($this, 'set_last_position') );
7
+ add_filter('fv_flowplayer_admin_default_options_after', array( $this, 'player_position_save_admin_default_options_html' ) );
8
+
9
+ add_filter( 'fv_flowplayer_attributes', array( $this, 'shortcode' ), 10, 3 );
10
+ }
11
+
12
+ private function get_extensionless_file_name($path) {
13
+ return pathinfo($path, PATHINFO_FILENAME);
14
+ }
15
+
16
+ public function set_last_position($aItemArray) {
17
+ // we only use the first source to check for stored position,
18
+ // since other sources would be alternatives (in quality, etc.)
19
+ if (
20
+ is_user_logged_in() &&
21
+ is_array($aItemArray) &&
22
+ isset($aItemArray['sources']) &&
23
+ isset($aItemArray['sources'][0]) &&
24
+ ($metaPosition = get_user_meta( get_current_user_id(), 'fv_wp_flowplayer_position_' . $this->get_extensionless_file_name($aItemArray['sources'][0]['src']), true ))
25
+ ) {
26
+ $aItemArray['sources'][0]['position'] = $metaPosition;
27
+ }
28
+ return $aItemArray;
29
+ }
30
+
31
+ public function video_position_save() {
32
+ // TODO: XSS filter for POST values?
33
+ if (is_user_logged_in() && isset($_POST['videoTimes']) && ($times = $_POST['videoTimes']) && count($times)) {
34
+ $uid = get_current_user_id();
35
+ foreach ($times as $record) {
36
+ update_user_meta($uid, 'fv_wp_flowplayer_position_'.$this->get_extensionless_file_name($record['name']), $record['position']);
37
+ }
38
+ wp_send_json_success();
39
+ } else {
40
+ wp_send_json_error();
41
+ }
42
+ }
43
+
44
+ function player_position_save_admin_default_options_html() {
45
+ global $fv_fp;
46
+ $fv_fp->_get_checkbox(__('Remember video position', 'fv-wordpress-flowplayer').' (beta)', 'video_position_save_enable', __('Stores the last video play position for users, so they can continue watching from where they left.'), __('It stored in usermeta for logged in users and in a localStorage or cookie for guest users.'));
47
+ }
48
+
49
+ function shortcode( $attributes, $media, $fv_fp ) {
50
+ if( isset($fv_fp->aCurArgs['saveposition']) && $fv_fp->aCurArgs['saveposition'] == 'true' ) {
51
+ $attributes['data-save-position'] = 'true';
52
+ }
53
+ return $attributes;
54
+ }
55
+
56
+ }
57
+ $FV_Player_Position_Save = new FV_Player_Position_Save();
models/widget.php CHANGED
@@ -1,5 +1,7 @@
1
  <?php
2
 
 
 
3
  class FV_Player_Widget extends WP_Widget {
4
 
5
  public function __construct() {
@@ -13,7 +15,7 @@ class FV_Player_Widget extends WP_Widget {
13
 
14
  function widget_init() {
15
  register_widget('FV_Player_widget');
16
- add_action('admin_footer-widgets.php', array($this, 'formFooter') );
17
  }
18
 
19
  /**
@@ -110,19 +112,17 @@ class FV_Player_Widget extends WP_Widget {
110
  }
111
 
112
  function formFooter() {
113
- if( function_exists('get_current_screen') ) { // fix for wp-page-widget
114
- $ojbScreen = get_current_screen();
115
- if( $ojbScreen && $ojbScreen->base == 'post' ) return;
116
  }
117
 
118
- include dirname(__FILE__) . '/../view/wizard.php';
119
- ?>
120
- <script src="<?php echo FV_FP_RELATIVE_PATH; ?>/js/shortcode-editor.js"></script>
121
- <script src="<?php echo FV_FP_RELATIVE_PATH; ?>/js/jquery.colorbox-min.js"></script>
122
- <link rel = "stylesheet" type = "text/css" href = "<?php echo FV_FP_RELATIVE_PATH; ?>/css/colorbox.css"/>
123
- <?php
124
  }
125
 
126
  }
127
 
128
  $FV_Player_Widget = new FV_Player_Widget();
 
 
1
  <?php
2
 
3
+ if( class_exists('WP_Widget') ) :
4
+
5
  class FV_Player_Widget extends WP_Widget {
6
 
7
  public function __construct() {
15
 
16
  function widget_init() {
17
  register_widget('FV_Player_widget');
18
+ add_action('admin_footer', array($this, 'formFooter'), 0 );
19
  }
20
 
21
  /**
112
  }
113
 
114
  function formFooter() {
115
+ if( function_exists('get_current_screen') ) {
116
+ $objScreen = get_current_screen();
117
+ if( $objScreen && $objScreen->base != 'widgets' ) return;
118
  }
119
 
120
+ fv_wp_flowplayer_edit_form_after_editor();
121
+ fv_player_shortcode_editor_scripts_enqueue();
 
 
 
 
122
  }
123
 
124
  }
125
 
126
  $FV_Player_Widget = new FV_Player_Widget();
127
+
128
+ endif;
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: FolioVision
3
  Donate link: https://foliovision.com/donate
4
  Tags: video player, flowplayer, mobile video, html5 video, Vimeo, html5 player, youtube player, youtube playlist, video playlist, RTMP, Cloudfront, HLS
5
  Requires at least: 3.5
6
- Tested up to: 4.9.2
7
  Stable tag: trunk
8
  License: GPLv3 or later
9
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
@@ -16,6 +16,8 @@ Custom HTML 5 video on your own site with Flash fallback for legacy browsers is
16
 
17
  FV Player is a free, easy-to-use, and complete solution for embedding FLV or MP4 videos into your posts or pages. With MP4 videos, FV Player offers 98% coverage even on mobile devices.
18
 
 
 
19
  * **NEW** easy AB looped playback for your visitors (great for teaching sites)
20
  * **NEW** improved and more powerful playlists (more playlist features coming soon).
21
  * Automated checking of video encoding for logged in admins
@@ -354,6 +356,16 @@ Thank you for being part of the HMTL 5 mobile video revolution!
354
 
355
  == Changelog ==
356
 
 
 
 
 
 
 
 
 
 
 
357
  = 6.4.2 - 2018/02/23 =
358
 
359
  * CSS - fixing the left and right alignment margin
@@ -382,7 +394,7 @@ Thank you for being part of the HMTL 5 mobile video revolution!
382
 
383
  = 6.3.11 - 2017/11/20 =
384
 
385
- * New feature - Sticky Video - lets your viewers continue watching the video as they scroll past it. It applies to desktop computer displays - minimal width of 1200 pixels. See Setting -> FV Player -> Skin -> Sticky Video
386
  * Lightbox - improving retina image parsing
387
 
388
  = 6.3.10 - 2017/11/13 =
3
  Donate link: https://foliovision.com/donate
4
  Tags: video player, flowplayer, mobile video, html5 video, Vimeo, html5 player, youtube player, youtube playlist, video playlist, RTMP, Cloudfront, HLS
5
  Requires at least: 3.5
6
+ Tested up to: 4.9.4
7
  Stable tag: trunk
8
  License: GPLv3 or later
9
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
16
 
17
  FV Player is a free, easy-to-use, and complete solution for embedding FLV or MP4 videos into your posts or pages. With MP4 videos, FV Player offers 98% coverage even on mobile devices.
18
 
19
+ * Remembering video position both both guest users and members
20
+ * API for custom video fields
21
  * **NEW** easy AB looped playback for your visitors (great for teaching sites)
22
  * **NEW** improved and more powerful playlists (more playlist features coming soon).
23
  * Automated checking of video encoding for logged in admins
356
 
357
  == Changelog ==
358
 
359
+ = 6.5 - 2018/03/14 =
360
+
361
+ * New feature - Video position saving for both guest and logged in users - see Settings -> FV Player -> Sidewide Flowplayer Defaults -> Remember video position
362
+ * Custom video fields are now easy to add with the FV_Player_MetaBox PHP class
363
+ * DASH - updating to latest tested Dash.js version
364
+ * Bugfix - iframe embed code placing body closing tag in bad place
365
+ * Bugfix - fix for PHP warnings on AMP pages
366
+ * Bugfix - Shortcode editor bug when you select the subtitle language and it adds the subtitles twice
367
+ * Bugfix - Subtitles in playlist - making sure multilingual subtitles work for the first item at least
368
+
369
  = 6.4.2 - 2018/02/23 =
370
 
371
  * CSS - fixing the left and right alignment margin
394
 
395
  = 6.3.11 - 2017/11/20 =
396
 
397
+ * New feature - Sticky Video - lets your viewers continue watching the video as they scroll past it. It applies to desktop computer displays - minimal width of 1200 pixels. See Setting -> FV Player -> Skin -> Sticky Video, thanks to Dan Hostettler
398
  * Lightbox - improving retina image parsing
399
 
400
  = 6.3.10 - 2017/11/13 =
test/integration/backend/profileVideosTest.php ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ require_once( dirname(__FILE__).'/../fv-player-unittest-case.php');
4
+
5
+ /**
6
+ * Tests WordPress integration of playlists without any advertisements present
7
+ * in the HTML markup.
8
+ */
9
+ final class FV_Player_ProfileVideosTestCase extends FV_Player_UnitTestCase {
10
+
11
+ public function testProfileScreen() {
12
+ global $fv_fp;
13
+ $fv_fp->conf['profile_videos_enable_bio'] = true;
14
+
15
+ // add new user and create last saved position metadata for this new user
16
+ $this->userID = $this->factory->user->create(array(
17
+ 'role' => 'admin'
18
+ ));
19
+
20
+ add_user_meta($this->userID, '_fv_player_user_video', '[fvplayer src="https://vimeo.com/255317467" playlist="https://vimeo.com/192934117" caption=";Talking about FV Player"]');
21
+ add_user_meta($this->userID, '_fv_player_user_video', '[fvplayer src="https://vimeo.com/255370388"]');
22
+ add_user_meta($this->userID, '_fv_player_user_video', '[fvplayer src="https://www.youtube.com/watch?v=6ZfuNTqbHE8"]]');
23
+
24
+ $profileuser = get_user_to_edit($this->userID);
25
+
26
+ ob_start();
27
+ apply_filters( 'show_password_fields', true, $profileuser );
28
+ $output = ob_get_clean();
29
+
30
+ $one = $this->fix_newlines(file_get_contents(dirname(__FILE__).'/testProfileScreen.html')); // this contains user ID of '4'
31
+ $two = explode("\n",$this->fix_newlines($output));
32
+ foreach( explode("\n",$one) as $k => $v ) {
33
+
34
+ /*if( $v != $two[$k]) {
35
+ for($i=0;$i<strlen($two[$k]);$i++) {
36
+ var_dump( $two[$k][$i].' '.ord($two[$k][$i]) );
37
+ }
38
+ }*/
39
+
40
+ //$this->assertEquals( $v, $two[$k] );
41
+ }
42
+
43
+ $this->assertEquals( $this->fix_newlines(file_get_contents(dirname(__FILE__).'/testProfileScreen.html')), $this->fix_newlines($output) );
44
+
45
+ }
46
+
47
+ }
test/integration/backend/settingsTest.php ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ require_once( dirname(__FILE__).'/../fv-player-unittest-case.php');
4
+
5
+ /**
6
+ * Tests WordPress integration of playlists without any advertisements present
7
+ * in the HTML markup.
8
+ */
9
+ final class FV_Player_SettingsTestCase extends FV_Player_UnitTestCase {
10
+
11
+ public function testSettingsScreen() {
12
+ include( '../../../fv-wordpress-flowplayer/controller/backend.php' );
13
+ include( '../../../fv-wordpress-flowplayer/controller/editor.php' );
14
+ include( '../../../fv-wordpress-flowplayer/controller/settings.php' );
15
+
16
+
17
+ ob_start();
18
+ fv_player_admin_page();
19
+ $output = ob_get_clean();
20
+
21
+ $one = $this->fix_newlines(file_get_contents(dirname(__FILE__).'/testSettingsScreen.html'));
22
+ $two = explode("\n",$this->fix_newlines($output));
23
+ foreach( explode("\n",$one) as $k => $v ) {
24
+
25
+ /*if( $v != $two[$k]) {
26
+ for($i=0;$i<strlen($two[$k]);$i++) {
27
+ var_dump( $two[$k][$i].' '.ord($two[$k][$i]) );
28
+ }
29
+ }*/
30
+
31
+ //$this->assertEquals( $v, $two[$k] );
32
+ }
33
+
34
+ $this->assertEquals( $this->fix_newlines(file_get_contents(dirname(__FILE__).'/testSettingsScreen.html')), $this->fix_newlines($output) );
35
+ }
36
+
37
+ }
test/integration/backend/testProfileScreen.html ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <tr class="user-videos">
2
+ <th>Videos</th>
3
+ <td>
4
+ <div class="fv-player-custom-video-list"><form method='POST'><div class="fv-player-custom-video"><div class='fv-player-editor-wrapper' data-key='fv-player-editor-field-_fv_player_user_video'>
5
+ <div class='inside inside-child'>
6
+ <div class='fv-player-editor-preview'><iframe id='fv_vimeo_40a1ea9c2827d8afc50536475564effe' src='//player.vimeo.com/video/255317467' width='640' height='360' frameborder='0' webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
7
+ </div>
8
+ <input class='attachement-shortcode fv-player-editor-field' name='fv_player_videos[_fv_player_user_video][]' type='hidden' value='[fvplayer src=&quot;https://vimeo.com/255317467&quot; playlist=&quot;https://vimeo.com/192934117&quot; caption=&quot;;Talking about FV Player&quot;]' />
9
+ <div class='edit-video' >
10
+ <button class='button fv-player-editor-button'>Edit Video</button>
11
+ <button class='button fv-player-editor-remove'>Remove Video</button>
12
+ <button class='button fv-player-editor-more' style='display:none'>Add Another Video</button>
13
+ </div>
14
+
15
+ <div class='add-video' style="display:none">
16
+ <button class='button fv-player-editor-button'>Add Video</button>
17
+ </div>
18
+ </div>
19
+ </div><div class='fv-player-editor-wrapper' data-key='fv-player-editor-field-_fv_player_user_video'>
20
+ <div class='inside inside-child'>
21
+ <div class='fv-player-editor-preview'><iframe id='fv_vimeo_611247c19e9196fbf9433d589da255e1' src='//player.vimeo.com/video/255370388' width='640' height='360' frameborder='0' webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
22
+ </div>
23
+ <input class='attachement-shortcode fv-player-editor-field' name='fv_player_videos[_fv_player_user_video][]' type='hidden' value='[fvplayer src=&quot;https://vimeo.com/255370388&quot;]' />
24
+ <div class='edit-video' >
25
+ <button class='button fv-player-editor-button'>Edit Video</button>
26
+ <button class='button fv-player-editor-remove'>Remove Video</button>
27
+ <button class='button fv-player-editor-more' style='display:none'>Add Another Video</button>
28
+ </div>
29
+
30
+ <div class='add-video' style="display:none">
31
+ <button class='button fv-player-editor-button'>Add Video</button>
32
+ </div>
33
+ </div>
34
+ </div><div class='fv-player-editor-wrapper' data-key='fv-player-editor-field-_fv_player_user_video'>
35
+ <div class='inside inside-child'>
36
+ <div class='fv-player-editor-preview'><iframe id='fv_ytplayer_5fc2c295c1c8d43b356a8b8ee0c122ca' type='text/html' width='640' height='360'
37
+ src='//www.youtube.com/embed/6ZfuNTqbHE8?origin=' frameborder='0' webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
38
+ ]</div>
39
+ <input class='attachement-shortcode fv-player-editor-field' name='fv_player_videos[_fv_player_user_video][]' type='hidden' value='[fvplayer src=&quot;https://www.youtube.com/watch?v=6ZfuNTqbHE8&quot;]]' />
40
+ <div class='edit-video' >
41
+ <button class='button fv-player-editor-button'>Edit Video</button>
42
+ <button class='button fv-player-editor-remove'>Remove Video</button>
43
+ <button class='button fv-player-editor-more' style='display:none'>Add Another Video</button>
44
+ </div>
45
+
46
+ <div class='add-video' style="display:none">
47
+ <button class='button fv-player-editor-button'>Add Video</button>
48
+ </div>
49
+ </div>
50
+ </div><div style="clear: both"></div>
51
+ </div>
52
+ <input type='hidden' name='fv-player-custom-videos-entity-id[_fv_player_user_video]' value='4' /><input type='hidden' name='fv-player-custom-videos-entity-type[_fv_player_user_video]' value='user' /><input type="hidden" id="fv-player-custom-videos-_fv_player_user_video-0" name="fv-player-custom-videos-_fv_player_user_video-0" value="0926bc6617" /><input type="hidden" name="_wp_http_referer" value="" /><input type='hidden' name='action' value='fv-player-custom-videos-save' /><input type='submit' value='Save Videos' /></form></div> <p class="description">You can put your Vimeo or YouTube links here. <abbr title="These show up as a part of the user bio. Licensed users get FV Player Pro which embeds these video types in FV Player interface without Vimeo or YouTube interface showing up."><span class="dashicons dashicons-editor-help"></span></abbr></p>
53
+ </td>
54
+ </tr>
test/integration/backend/testSettingsScreen.html ADDED
@@ -0,0 +1,1970 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ <div class="wrap">
3
+ <div style="position: absolute; margin-top: 10px; right: 10px;">
4
+ <a href="https://foliovision.com/wordpress/plugins/fv-wordpress-flowplayer" target="_blank" title="Documentation"><img alt="visit foliovision" src="//foliovision.com/shared/fv-logo.png" /></a>
5
+ </div>
6
+ <div>
7
+ <div id="icon-options-general" class="icon32"></div>
8
+ <h2>FV Player</h2>
9
+ </div>
10
+
11
+
12
+ <form id="wpfp_options" method="post" action="">
13
+
14
+ <p id="fv_flowplayer_admin_buttons">
15
+ <input type="button" class="button fv-license-inactive" onclick="fv_flowplayer_ajax_check('fv_wp_flowplayer_check_license'); return false" value="Apply Pro upgrade" />
16
+ <input type="button" class="button" onclick="fv_flowplayer_ajax_check('fv_wp_flowplayer_check_template'); return false" value="Check template" />
17
+ <input type="button" class="button" onclick="fv_flowplayer_ajax_check('fv_wp_flowplayer_check_files')" value="Check videos" />
18
+
19
+ <input type="text" name="key" id="key" placeholder="Commercial License Key" value="" /> <a title="Click here for license info" target="_blank" href="https://foliovision.com/player/download"><span class="dashicons dashicons-editor-help"></span></a>
20
+
21
+ <img class="fv_wp_flowplayer_check_license-spin" style="display: none; " src="http://example.org/wp-includes/images/wpspin.gif" width="16" height="16" />
22
+ <img class="fv_wp_flowplayer_check_template-spin" style="display: none; " src="http://example.org/wp-includes/images/wpspin.gif" width="16" height="16" />
23
+ <img class="fv_wp_flowplayer_check_files-spin" style="display: none; " src="http://example.org/wp-includes/images/wpspin.gif" width="16" height="16" />
24
+ </p>
25
+ <div id="fv_flowplayer_admin_notices">
26
+ </div>
27
+
28
+ <div id="fv_flowplayer_ad">
29
+ <div class="text-part">
30
+ <h2>FV Wordpress<strong>Flowplayer</strong></h2>
31
+ <span class="red-text">with your own branding</span>
32
+ <ul>
33
+ <li>Put up your own logo</li>
34
+ <li>Or remove the logo completely</li>
35
+ <li>The best video plugin for Wordpress</li>
36
+ </ul>
37
+ <a href="http://foliovision.com/wordpress/plugins/fv-wordpress-flowplayer/download" class="red-button"><strong>Easter sale!</strong><br />All Licenses 20% Off</a></p>
38
+ </div>
39
+ <div class="graphic-part">
40
+ <a href="http://foliovision.com/wordpress/plugins/fv-wordpress-flowplayer/buy">
41
+ <img width="297" height="239" border="0" src="http://example.org/wp-content/plugins/fv-wordpress-flowplayer/images/fv-wp-flowplayer-led-monitor.png"> </a>
42
+ </div>
43
+ </div>
44
+
45
+ <div id="fv_flowplayer_admin_tabs">
46
+ <h2 class="fv-nav-tab-wrapper nav-tab-wrapper">
47
+ <a href="#postbox-container-tab_basic" class="nav-tab nav-tab-active" style="outline: 0px;">Setup</a>
48
+ <a href="#postbox-container-tab_skin" class="nav-tab" style="outline: 0px;">Skin</a>
49
+ <a href="#postbox-container-tab_hosting" class="nav-tab" style="outline: 0px;">Hosting</a>
50
+ <a href="#postbox-container-tab_actions" class="nav-tab" style="outline: 0px;">Actions</a>
51
+ <a href="#postbox-container-tab_help" class="nav-tab" style="outline: 0px;">Help</a>
52
+ <div id="fv_player_js_warning" style=" margin: 8px 40px; display: inline-block; color: darkgrey;" >There Is a Problem with JavaScript.</div>
53
+ </h2>
54
+ </div>
55
+
56
+ <div id="dashboard-widgets" class="metabox-holder fv-metabox-holder columns-1">
57
+ <div id='postbox-container-tab_basic' class='postbox-container'>
58
+ <div id="normal-sortables" class="meta-box-sortables"><div id="fv_flowplayer_description" class="postbox " >
59
+ <button type="button" class="handlediv" aria-expanded="true"><span class="screen-reader-text">Toggle panel: </span><span class="toggle-indicator" aria-hidden="true"></span></button><h2 class='hndle'><span> </span></h2>
60
+ <div class="inside">
61
+ <table class="form-table">
62
+ <tr>
63
+ <td colspan="4">
64
+ <p>
65
+ FV Player is a free, easy-to-use, and complete solution for embedding <strong>MP4</strong>, <strong>WEBM</strong>, <strong>OGV</strong>, <strong>MOV</strong>
66
+ and <strong>FLV</strong>
67
+ videos into your posts or pages. With MP4 videos, FV Player offers 98&#37; coverage even on mobile devices. </p>
68
+ </td>
69
+ </tr>
70
+ </table>
71
+ </div>
72
+ </div>
73
+ <div id="fv_flowplayer_interface_options" class="postbox " >
74
+ <button type="button" class="handlediv" aria-expanded="true"><span class="screen-reader-text">Toggle panel: Post Interface Options</span><span class="toggle-indicator" aria-hidden="true"></span></button><h2 class='hndle'><span>Post Interface Options</span></h2>
75
+ <div class="inside">
76
+ <p>Which features should be available in shortcode editor?</p>
77
+ <table class="form-table2">
78
+ <tr>
79
+ <td><label for="interface[ads]">Ads:</label></td>
80
+ <td>
81
+ <p class="description">
82
+ <input type="hidden" name="interface[ads]" value="false"/>
83
+ <input type="checkbox" name="interface[ads]" id="interface[ads]" value="true" />
84
+ </p>
85
+ </td>
86
+ </tr>
87
+ <tr>
88
+ <td><label for="interface[align]">Align:</label></td>
89
+ <td>
90
+ <p class="description">
91
+ <input type="hidden" name="interface[align]" value="false"/>
92
+ <input type="checkbox" name="interface[align]" id="interface[align]" value="true" />
93
+ </p>
94
+ </td>
95
+ </tr>
96
+ <tr>
97
+ <td><label for="allowuploads">Allow Video Uploads:</label></td>
98
+ <td>
99
+ <p class="description">
100
+ <input type="hidden" name="allowuploads" value="false"/>
101
+ <input type="checkbox" name="allowuploads" id="allowuploads" value="true" checked="checked" />
102
+ Enables the WP Media Library integraton if you want to host videos on your own server </p>
103
+ </td>
104
+ </tr>
105
+ <tr>
106
+ <td><label for="interface[autoplay]">Autoplay:</label></td>
107
+ <td>
108
+ <p class="description">
109
+ <input type="hidden" name="interface[autoplay]" value="false"/>
110
+ <input type="checkbox" name="interface[autoplay]" id="interface[autoplay]" value="true" />
111
+ </p>
112
+ </td>
113
+ </tr>
114
+ <tr>
115
+ <td><label for="interface[controlbar]">Controlbar:</label></td>
116
+ <td>
117
+ <p class="description">
118
+ <input type="hidden" name="interface[controlbar]" value="false"/>
119
+ <input type="checkbox" name="interface[controlbar]" id="interface[controlbar]" value="true" />
120
+ </p>
121
+ </td>
122
+ </tr>
123
+ <tr>
124
+ <td><label for="interface[embed]">Embed:</label></td>
125
+ <td>
126
+ <p class="description">
127
+ <input type="hidden" name="interface[embed]" value="false"/>
128
+ <input type="checkbox" name="interface[embed]" id="interface[embed]" value="true" />
129
+ </p>
130
+ </td>
131
+ </tr>
132
+ <tr>
133
+ <td><label for="interface[live]">Live Stream:</label></td>
134
+ <td>
135
+ <p class="description">
136
+ <input type="hidden" name="interface[live]" value="false"/>
137
+ <input type="checkbox" name="interface[live]" id="interface[live]" value="true" />
138
+ </p>
139
+ </td>
140
+ </tr>
141
+ <tr>
142
+ <td><label for="interface[mobile]">Mobile Video:</label></td>
143
+ <td>
144
+ <p class="description">
145
+ <input type="hidden" name="interface[mobile]" value="false"/>
146
+ <input type="checkbox" name="interface[mobile]" id="interface[mobile]" value="true" />
147
+ </p>
148
+ </td>
149
+ </tr>
150
+ <tr>
151
+ <td><label for="interface[playlist_advance]">Playlist Auto Advance:</label></td>
152
+ <td>
153
+ <p class="description">
154
+ <input type="hidden" name="interface[playlist_advance]" value="false"/>
155
+ <input type="checkbox" name="interface[playlist_advance]" id="interface[playlist_advance]" value="true" />
156
+ </p>
157
+ </td>
158
+ </tr>
159
+ <tr>
160
+ <td><label for="interface[playlist]">Playlist Style:</label></td>
161
+ <td>
162
+ <p class="description">
163
+ <input type="hidden" name="interface[playlist]" value="false"/>
164
+ <input type="checkbox" name="interface[playlist]" id="interface[playlist]" value="true" />
165
+ </p>
166
+ </td>
167
+ </tr>
168
+ <tr>
169
+ <td><label for="interface[playlist_captions]">Playlist Captions:</label></td>
170
+ <td>
171
+ <p class="description">
172
+ <input type="hidden" name="interface[playlist_captions]" value="false"/>
173
+ <input type="checkbox" name="interface[playlist_captions]" id="interface[playlist_captions]" value="true" />
174
+ </p>
175
+ </td>
176
+ </tr>
177
+ <tr>
178
+ <td><label for="interface[share]">Sharing Buttons:</label></td>
179
+ <td>
180
+ <p class="description">
181
+ <input type="hidden" name="interface[share]" value="false"/>
182
+ <input type="checkbox" name="interface[share]" id="interface[share]" value="true" />
183
+ </p>
184
+ </td>
185
+ </tr>
186
+ <tr>
187
+ <td><label for="interface[speed]">Speed Buttons:</label></td>
188
+ <td>
189
+ <p class="description">
190
+ <input type="hidden" name="interface[speed]" value="false"/>
191
+ <input type="checkbox" name="interface[speed]" id="interface[speed]" value="true" />
192
+ </p>
193
+ </td>
194
+ </tr>
195
+ <tr>
196
+ <td><label for="interface[splash_text]">Splash Text:</label></td>
197
+ <td>
198
+ <p class="description">
199
+ <input type="hidden" name="interface[splash_text]" value="false"/>
200
+ <input type="checkbox" name="interface[splash_text]" id="interface[splash_text]" value="true" />
201
+ </p>
202
+ </td>
203
+ </tr>
204
+ <tr>
205
+ <td><label for="interface[subtitles]">Subtitles:</label></td>
206
+ <td>
207
+ <p class="description">
208
+ <input type="hidden" name="interface[subtitles]" value="false"/>
209
+ <input type="checkbox" name="interface[subtitles]" id="interface[subtitles]" value="true" />
210
+ </p>
211
+ </td>
212
+ </tr>
213
+ <tr>
214
+ <td><label for="interface[sticky]">Sticky:</label></td>
215
+ <td>
216
+ <p class="description">
217
+ <input type="hidden" name="interface[sticky]" value="false"/>
218
+ <input type="checkbox" name="interface[sticky]" id="interface[sticky]" value="true" />
219
+ </p>
220
+ </td>
221
+ </tr>
222
+ <tr>
223
+ <td><label for="interface[end_actions]">Video Actions:</label></td>
224
+ <td>
225
+ <p class="description">
226
+ <input type="hidden" name="interface[end_actions]" value="false"/>
227
+ <input type="checkbox" name="interface[end_actions]" id="interface[end_actions]" value="true" />
228
+ Enables end of playlist actions like Loop, Redirect, Show popup and Show splash screen </p>
229
+ </td>
230
+ </tr>
231
+
232
+ <tr>
233
+ <td><label for="interface[lightbox]">Enable video lightbox:</label></td>
234
+ <td>
235
+ <p class="description">
236
+ <input type="hidden" name="interface[lightbox]" value="false"/>
237
+ <input type="checkbox" name="interface[lightbox]" id="interface[lightbox]" value="true" />
238
+ You can also put in <code>&lt;a href="http://path.to.your/video.mp4" class="colorbox"&gt;Your link title&lt;/a&gt;</code> for a quick lightboxed video. </p>
239
+ </td>
240
+ </tr>
241
+
242
+ <tr>
243
+ <td><label for="interface[shortcode_editor_old]">Enable old interface:</label></td>
244
+ <td>
245
+ <p class="description">
246
+ <input type="hidden" name="interface[shortcode_editor_old]" value="false"/>
247
+ <input type="checkbox" name="interface[shortcode_editor_old]" id="interface[shortcode_editor_old]" value="true" />
248
+ Not recommended </p>
249
+ </td>
250
+ </tr>
251
+
252
+ <tr>
253
+ <td colspan="4">
254
+ <input type="submit" name="fv-wp-flowplayer-submit" class="button-primary" value="Save All Changes" />
255
+ </td>
256
+ </tr>
257
+ </table>
258
+ </div>
259
+ </div>
260
+ <div id="fv_flowplayer_default_options" class="postbox " >
261
+ <button type="button" class="handlediv" aria-expanded="true"><span class="screen-reader-text">Toggle panel: Sitewide FV Player Defaults</span><span class="toggle-indicator" aria-hidden="true"></span></button><h2 class='hndle'><span>Sitewide FV Player Defaults</span></h2>
262
+ <div class="inside">
263
+ <style>
264
+ p.description { font-style: normal; }
265
+ </style>
266
+ <table class="form-table2">
267
+
268
+ <tr>
269
+ <td><label for="autoplay">Autoplay:</label></td>
270
+ <td>
271
+ <p class="description">
272
+ <input type="hidden" name="autoplay" value="false"/>
273
+ <input type="checkbox" name="autoplay" id="autoplay" value="true" />
274
+ We make sure only one video per page autoplays. Note that mobile devices don't support autoplay. </p>
275
+ </td>
276
+ </tr>
277
+ <tr>
278
+ <td><label for="auto_buffering">Auto Buffering:</label></td>
279
+ <td>
280
+ <p class="description">
281
+ <input type="hidden" name="auto_buffering" value="false"/>
282
+ <input type="checkbox" name="auto_buffering" id="auto_buffering" value="true" />
283
+ Works for first 2 videos on the page only, to preserve your bandwidth. </p>
284
+ </td>
285
+ </tr>
286
+
287
+ <tr>
288
+ <td><label for="width">Default Video Size:</label></td>
289
+ <td>
290
+ <p class="description">
291
+ <label for="width">Width:</label>&nbsp;<input type="text" class="small" name="width" id="width" value="640" />
292
+ <label for="height">Height:</label>&nbsp;<input type="text" class="small" name="height" id="height" value="360" />
293
+ Enter values in pixels or 100%. </p>
294
+ </td>
295
+ </tr>
296
+ <tr>
297
+ <td><label for="volume">Default Volume:</label></td>
298
+ <td>
299
+ <p class="description">
300
+ <input id="volume" name="volume" type="range" min="0" max="1" step="0.1" value="0.7" class="medium" />
301
+ </p>
302
+ </td>
303
+ </tr>
304
+
305
+ <tr>
306
+ <td><label for="disable_videochecker">Disable Admin Video Checker:</label></td>
307
+ <td>
308
+ <p class="description">
309
+ <input type="hidden" name="disable_videochecker" value="false"/>
310
+ <input type="checkbox" name="disable_videochecker" id="disable_videochecker" value="true" />
311
+ Checks your video encoding when you open a post with video as admin. Notifies you about possible playback issues. </p>
312
+ </td>
313
+ </tr>
314
+ <tr>
315
+ <td><label for="disableembedding">Disable Embed Button:</label></td>
316
+ <td>
317
+ <p class="description">
318
+ <input type="hidden" name="disableembedding" value="false"/>
319
+ <input type="checkbox" name="disableembedding" id="disableembedding" value="true" />
320
+ Removes embed button from top bar. </p>
321
+ </td>
322
+ </tr>
323
+ <tr>
324
+ <td><label for="playlist_advance">Disable Playlist Autoadvance:</label></td>
325
+ <td>
326
+ <p class="description">
327
+ <input type="hidden" name="playlist_advance" value="false"/>
328
+ <input type="checkbox" name="playlist_advance" id="playlist_advance" value="true" />
329
+ Playlist won't play the next video automatically. </p>
330
+ </td>
331
+ </tr>
332
+ <tr>
333
+ <td><label for="disablesharing">Disable Sharing:</label></td>
334
+ <td>
335
+ <p class="description">
336
+ <input type="hidden" name="disablesharing" value="false"/>
337
+ <input type="checkbox" name="disablesharing" id="disablesharing" value="true" />
338
+ Removes sharing buttons from top bar. </p>
339
+ </td>
340
+ </tr>
341
+ <tr>
342
+ <td><label for="disable_video_hash_links">Disable Video Links:</label></td>
343
+ <td>
344
+ <p class="description">
345
+ <input type="hidden" name="disable_video_hash_links" value="false"/>
346
+ <input type="checkbox" name="disable_video_hash_links" id="disable_video_hash_links" value="true" />
347
+ Removes the "Link" item to the top bar. <span class="more">Clicking the video Link gives your visitors a link to the exact place in the video they are watching. If the post access is restricted, it won't make the video open to public.</span> <a href="#" class="show-more">(&hellip;)</a>
348
+ </p>
349
+ </td>
350
+ </tr>
351
+
352
+ <tr>
353
+ <td><label for="rtmp">Flash Streaming Server:</label></td>
354
+ <td>
355
+ <p class="description">
356
+ <input type="text" name="rtmp" id="rtmp" value="" placeholder="Enter your default RTMP streaming server (Amazon CloudFront domain)." />
357
+ </p>
358
+ </td>
359
+ </tr>
360
+
361
+ <tr>
362
+ <td><label for="allowfullscreen">Fullscreen Button:</label></td>
363
+ <td>
364
+ <p class="description">
365
+ <input type="hidden" name="allowfullscreen" value="false"/>
366
+ <input type="checkbox" name="allowfullscreen" id="allowfullscreen" value="true" checked="checked" />
367
+ Adds fullscreen button to player top bar. </p>
368
+ </td>
369
+ </tr>
370
+
371
+ <tr>
372
+ <td><label for="googleanalytics">Google Analytics ID:</label></td>
373
+ <td>
374
+ <p class="description">
375
+ <input type="text" name="googleanalytics" id="googleanalytics" value="" placeholder="Will be automatically loaded when playing a video." />
376
+ </p>
377
+ </td>
378
+ </tr>
379
+ <tr>
380
+ <td><label for="logo">Logo:</label></td>
381
+ <td>
382
+ <input type="text" name="logo" id="logo" value="" class="large" placeholder="You need to have a FV Flowplayer license to use it" />
383
+
384
+ <input id="upload_image_button" class="upload_image_button button no-margin small" type="button" value="Upload Image" alt="Select Logo" />
385
+
386
+ <select name="logoPosition" class="small">
387
+ <option value="bottom-left">Position</option>
388
+ <option selected value="bottom-left">Bottom-left</option>
389
+ <option value="bottom-right">Bottom-right</option>
390
+ <option value="top-left">Top-left</option>
391
+ <option value="top-right">Top-right</option>
392
+ </select>
393
+ </td>
394
+ </tr>
395
+
396
+ <tr>
397
+ <td><label for="ui_play_button">Play Button:</label></td>
398
+ <td>
399
+ <p class="description">
400
+ <input type="hidden" name="ui_play_button" value="false"/>
401
+ <input type="checkbox" name="ui_play_button" id="ui_play_button" value="true" checked="checked" />
402
+ Adds play button to player controlbar. </p>
403
+ </td>
404
+ </tr>
405
+
406
+ <tr>
407
+ <td><label for="liststyle">Playlist style:</label></td>
408
+ <td colspan="3">
409
+ <p class="description">
410
+ <select id="liststyle" name="liststyle">
411
+ <option value="horizontal" selected="selected" >Horizontal</option>
412
+ <option value="tabs" >Tabs</option>
413
+ <option value="prevnext" >Prev/Next</option>
414
+ <option value="vertical" >Vertical</option>
415
+ <option value="slider" >Slider</option>
416
+ </select>
417
+ Enter your default playlist style here </p>
418
+ </td>
419
+ </tr>
420
+
421
+ <tr>
422
+ <td><label for="popupbox">Popup Box:</label></td>
423
+ <td>
424
+ <p class="description">
425
+ <input type="hidden" name="popupbox" value="false"/>
426
+ <input type="checkbox" name="popupbox" id="popupbox" value="true" />
427
+ Shows a generic "Would you like to replay the video?" message at the end of each video. </p>
428
+ </td>
429
+ </tr>
430
+
431
+ <tr>
432
+ <td><label for="sharing_text">Sharing Text:</label></td>
433
+ <td>
434
+ <p class="description">
435
+ <input type="text" name="sharing_email_text" id="sharing_email_text" value="Check out the amazing video here" placeholder="Check out the amazing video here" />
436
+ </p>
437
+ </td>
438
+ </tr>
439
+
440
+ <tr>
441
+ <td><label for="ui_speed">Speed Buttons:</label></td>
442
+ <td>
443
+ <p class="description">
444
+ <input type="hidden" name="ui_speed" value="false"/>
445
+ <input type="checkbox" name="ui_speed" id="ui_speed" value="true" />
446
+ Speed buttons control playback speed and only work in HTML5 compatible browsers. </p>
447
+ </td>
448
+ </tr>
449
+
450
+ <tr>
451
+ <td><label for="ui_speed_increment">Speed Step:</label></td>
452
+ <td colspan="3">
453
+ <p class="description">
454
+ <select id="ui_speed_increment" name="ui_speed_increment">
455
+ <option value="0.1" >0.1</option>
456
+ <option value="0.25" selected="selected" >0.25</option>
457
+ <option value="0.5" >0.5</option>
458
+ </select>
459
+ Speed buttons will increase or decrease the speed in steps of selected value </p>
460
+ </td>
461
+ </tr>
462
+ <tr>
463
+ <td><label for="splash">Splash Image:</label></td>
464
+ <td>
465
+ <input type="text" name="splash" id="splash" value="" class="large" placeholder="Default which will be used for any player without its own splash image." />
466
+ <input id="upload_image_button" class="upload_image_button button no-margin small" type="button" value="Upload Image" alt="Select default Splash Screen" /></td>
467
+ </tr>
468
+
469
+ <tr>
470
+ <td><label for="subtitleOn">Subtitles On By Default:</label></td>
471
+ <td>
472
+ <p class="description">
473
+ <input type="hidden" name="subtitleOn" value="false"/>
474
+ <input type="checkbox" name="subtitleOn" id="subtitleOn" value="true" />
475
+ Normally you have to hit a button in controlbar to turn on subtitles. </p>
476
+ </td>
477
+ </tr>
478
+
479
+ <tr>
480
+ <td style="width: 250px"><label for="lightbox_images">Use video lightbox for images as well:</label></td>
481
+ <td>
482
+ <p class="description">
483
+ <input type="hidden" value="false" name="lightbox_images" />
484
+ <input type="checkbox" value="true" name="lightbox_images" id="lightbox_images" />
485
+ Will group images as well as videos into the same lightbox gallery. Turn <strong>off</strong> your lightbox plugin when using this. <span class="more">Also works with WordPress <code>[gallery]</code> galleries - these are automatically switched to link to image URLs rather than the attachment pages.</span> <a href="#" class="show-more">(&hellip;)</a>
486
+ </p>
487
+ </td>
488
+ </tr>
489
+ <tr id="lightbox-wp-galleries">
490
+ <td style="width: 250px"><label for="lightbox_improve_galleries">Use video lightbox for WP Galleries:</label></td>
491
+ <td>
492
+ <p class="description">
493
+ <input type="hidden" value="false" name="lightbox_improve_galleries" />
494
+ <input type="checkbox" value="true" name="lightbox_improve_galleries" id="lightbox_improve_galleries" />
495
+ Your gallery items will link to image files directly to allow this. </p>
496
+ </td>
497
+ </tr>
498
+ <script>
499
+ jQuery(document).ready(function(){
500
+ jQuery('[name="pro[interface][lightbox]"]').parents('td').replaceWith('<td><p>Setting <a href="#interface[live]">moved</a></p></td>');
501
+ jQuery('[name="pro[lightbox_images]"]').parents('td').replaceWith('<td><p>Setting <a href="#subtitleOn">moved</a></p></td>');
502
+ var lightbox_images = jQuery('#lightbox_images');
503
+ if(lightbox_images.attr('checked')){
504
+ jQuery('#lightbox-wp-galleries').show();
505
+ }else{
506
+ jQuery('#lightbox-wp-galleries').hide();
507
+ }
508
+ lightbox_images.on('click',function(){
509
+ if(jQuery(this).attr('checked')){
510
+ jQuery('#lightbox-wp-galleries').show();
511
+ }else{
512
+ jQuery('#lightbox-wp-galleries').hide();
513
+ }
514
+ })
515
+ })
516
+ </script>
517
+ <tr>
518
+ <td><label for="video_position_save_enable">Remember video position (beta):</label></td>
519
+ <td>
520
+ <p class="description">
521
+ <input type="hidden" name="video_position_save_enable" value="false"/>
522
+ <input type="checkbox" name="video_position_save_enable" id="video_position_save_enable" value="true" />
523
+ Stores the last video play position for users, so they can continue watching from where they left. <span class="more">It stored in usermeta for logged in users and in a localStorage or cookie for guest users.</span> <a href="#" class="show-more">(&hellip;)</a>
524
+ </p>
525
+ </td>
526
+ </tr>
527
+ </table>
528
+ <small class="alignright">
529
+ Missing settings? Check <a class="fv-settings-anchor" href="#fv_flowplayer_integrations">Integrations/Compatbility</a> box below. </small>
530
+ <table class="form-table2">
531
+ <tr>
532
+ <td colspan="4">
533
+ <input type="submit" name="fv-wp-flowplayer-submit" class="button-primary" value="Save All Changes" />
534
+ </td>
535
+ </tr>
536
+ </table>
537
+ <script>
538
+ jQuery(document).ready(function($) {
539
+ var fv_flowplayer_uploader;
540
+ var fv_flowplayer_uploader_button;
541
+
542
+ $(document).on( 'click', '.upload_image_button', function(e) {
543
+ e.preventDefault();
544
+
545
+ fv_flowplayer_uploader_button = jQuery(this);
546
+ jQuery('.fv_flowplayer_target').removeClass('fv_flowplayer_target' );
547
+ fv_flowplayer_uploader_button.parents('tr').find('input[type=text]').addClass('fv_flowplayer_target' );
548
+
549
+ //If the uploader object has already been created, reopen the dialog
550
+ if (fv_flowplayer_uploader) {
551
+ fv_flowplayer_uploader.open();
552
+ return;
553
+ }
554
+
555
+ //Extend the wp.media object
556
+ fv_flowplayer_uploader = wp.media.frames.file_frame = wp.media({
557
+ title: 'Pick the image',
558
+ button: {
559
+ text: 'Choose'
560
+ },
561
+ multiple: false
562
+ });
563
+
564
+ fv_flowplayer_uploader.on('open', function() {
565
+ jQuery('.media-frame-title h1').text(fv_flowplayer_uploader_button.attr('alt'));
566
+ });
567
+
568
+ //When a file is selected, grab the URL and set it as the text field's value
569
+ fv_flowplayer_uploader.on('select', function() {
570
+ attachment = fv_flowplayer_uploader.state().get('selection').first().toJSON();
571
+
572
+ $('.fv_flowplayer_target').val(attachment.url);
573
+ $('.fv_flowplayer_target').removeClass('fv_flowplayer_target' );
574
+
575
+ /*if( attachment.type == 'video' ) {
576
+ if( typeof(attachment.width) != "undefined" && attachment.width > 0 ) {
577
+ $('#fv_wp_flowplayer_field_width').val(attachment.width);
578
+ }
579
+ if( typeof(attachment.height) != "undefined" && attachment.height > 0 ) {
580
+ $('#fv_wp_flowplayer_field_height').val(attachment.height);
581
+ }
582
+ if( typeof(attachment.fileLength) != "undefined" ) {
583
+ $('#fv_wp_flowplayer_file_info').show();
584
+ $('#fv_wp_flowplayer_file_duration').html(attachment.fileLength);
585
+ }
586
+ if( typeof(attachment.filesizeHumanReadable) != "undefined" ) {
587
+ $('#fv_wp_flowplayer_file_info').show();
588
+ $('#fv_wp_flowplayer_file_size').html(attachment.filesizeHumanReadable);
589
+ }
590
+
591
+ } else if( attachment.type == 'image' && typeof(fv_flowplayer_set_post_thumbnail_id) != "undefined" ) {
592
+ if( jQuery('#remove-post-thumbnail').length > 0 ){
593
+ return;
594
+ }
595
+ jQuery.post(ajaxurl, {
596
+ action:"set-post-thumbnail",
597
+ post_id: fv_flowplayer_set_post_thumbnail_id,
598
+ thumbnail_id: attachment.id,
599
+ _ajax_nonce: fv_flowplayer_set_post_thumbnail_nonce,
600
+ cookie: encodeURIComponent(document.cookie)
601
+ }, function(str){
602
+ var win = window.dialogArguments || opener || parent || top;
603
+ if ( str == '0' ) {
604
+ alert( setPostThumbnailL10n.error );
605
+ } else {
606
+ jQuery('#postimagediv .inside').html(str);
607
+ jQuery('#postimagediv .inside #plupload-upload-ui').hide();
608
+ }
609
+ } );
610
+
611
+ }*/
612
+
613
+ });
614
+
615
+ //Open the uploader dialog
616
+ fv_flowplayer_uploader.open();
617
+
618
+ });
619
+
620
+ });
621
+ </script>
622
+ <div class="clear"></div>
623
+ </div>
624
+ </div>
625
+ <div id="fv_flowplayer_integrations" class="postbox " >
626
+ <button type="button" class="handlediv" aria-expanded="true"><span class="screen-reader-text">Toggle panel: Integrations/Compatibility</span><span class="toggle-indicator" aria-hidden="true"></span></button><h2 class='hndle'><span>Integrations/Compatibility</span></h2>
627
+ <div class="inside">
628
+ <p>Following options are suitable for web developers and programmers.</p>
629
+ <table class="form-table2">
630
+
631
+ <tr>
632
+ <td><label for="fixed_size">Always use fixed size player:</label></td>
633
+ <td>
634
+ <p class="description">
635
+ <input type="hidden" name="fixed_size" value="false"/>
636
+ <input type="checkbox" name="fixed_size" id="fixed_size" value="true" />
637
+ Enable to force video size at cost of loosing the video responsiveness. </p>
638
+ </td>
639
+ </tr>
640
+ <tr>
641
+ <td><label for="cbox_compatibility">Colorbox Compatibility:</label></td>
642
+ <td>
643
+ <p class="description">
644
+ <input type="hidden" name="cbox_compatibility" value="false"/>
645
+ <input type="checkbox" name="cbox_compatibility" id="cbox_compatibility" value="true" />
646
+ Enable if your theme is using colorbox lightbox to show content and clones the HTML content into it. </p>
647
+ </td>
648
+ </tr>
649
+ <tr>
650
+ <td><label for="css_disable">Disable saving of color settings into a static file:</label></td>
651
+ <td>
652
+ <p class="description">
653
+ <input type="hidden" name="css_disable" value="false"/>
654
+ <input type="checkbox" name="css_disable" id="css_disable" value="true" />
655
+ Normally the player CSS configuration is stored in wp-content/fv-player-custom/style-{blog_id}.css. <span class="more">We do this to avoid outputting CSS code into your site <head>. Don't edit this file though, as it will be overwritten by plugin update or saving its options!</span> <a href="#" class="show-more">(&hellip;)</a>
656
+ </p>
657
+ </td>
658
+ </tr>
659
+ <tr>
660
+ <td><label for="hlsjs">Enable HLS.js (beta):</label></td>
661
+ <td>
662
+ <p class="description">
663
+ <input type="hidden" name="hlsjs" value="false"/>
664
+ <input type="checkbox" name="hlsjs" id="hlsjs" value="true" />
665
+ Allows HLS playback in all modern browsers. <span class="more">HLS normally plays only on iOS, Mac Safari and new Android versions. FV Player increases the compatibility by using Flash engine for HLS. With this option you can go even further and modern browsers supporting MediaSource will play HLS even without Flash. Make sure you setup the required CORS headers.</span> <a href="#" class="show-more">(&hellip;)</a>
666
+ </p>
667
+ </td>
668
+ </tr>
669
+
670
+ <tr>
671
+ <td><label for="css_disable">Enable profile videos:</label></td>
672
+ <td>
673
+ <div class="description">
674
+ <p>
675
+ <input type="hidden" name="profile_videos_enable_bio" value="false" />
676
+ <input type="checkbox" name="profile_videos_enable_bio" id="profile_videos_enable_bio" value="true" />
677
+ Check your site carefully after enabling. Videos attached to the user profile will be showing as a part of the user bio. <a href="#" class="show-more">(&hellip;)</a>
678
+ </p>
679
+ <div class="more">
680
+ <p>This feature is designed for YouTube and Vimeo videos and works best for our licensed users who get these videos playing without YouTube or Vimeo branding.</p>
681
+ <p>Some themes show author bio on the author post archive automatically (Genesis framework and others). Or you can also just put this code into your theme archive.php template, right before <code>while ( have_posts() )</code> is called:</p>
682
+ <blockquote>
683
+ <pre>
684
+ &lt;?php if ( is_author() &amp;&amp; get_the_author_meta( 'description' ) ) : ?&gt;
685
+ &lt;div class=&quot;author-info&quot;&gt;
686
+ &lt;div class=&quot;author-avatar&quot;&gt;
687
+ &lt;?php echo get_avatar( get_the_author_meta( 'user_email' ) ); ?&gt;
688
+ &lt;/div&gt;
689
+
690
+ &lt;div class=&quot;author-description&quot;&gt;
691
+ &lt;?php the_author_meta( 'description' ); ?&gt;
692
+ &lt;/div&gt;
693
+ &lt;/div&gt;
694
+ &lt;?php endif; ?&gt;
695
+ </pre>
696
+ </blockquote>
697
+ <p>We will be adding integration for it for popular user profile plugins.</p>
698
+
699
+ </div>
700
+ </div>
701
+ </td>
702
+ </tr>
703
+
704
+ <tr>
705
+ <td><label for="scaling">Fit scaling:</label></td>
706
+ <td>
707
+ <p class="description">
708
+ <input type="hidden" name="scaling" value="false"/>
709
+ <input type="checkbox" name="scaling" id="scaling" value="true" checked="checked" />
710
+ Original aspect ratio of the video will be used to display the video - for troubleshooting of fullscreen issues. </p>
711
+ </td>
712
+ </tr>
713
+ <tr>
714
+ <td><label for="integrations[wp_core_video]">Handle WordPress <code><small>[video]</small></code> shortcodes:</label></td>
715
+ <td>
716
+ <p class="description">
717
+ <input type="hidden" name="integrations[wp_core_video]" value="false"/>
718
+ <input type="checkbox" name="integrations[wp_core_video]" id="integrations[wp_core_video]" value="true" />
719
+ </p>
720
+ </td>
721
+ </tr>
722
+ <tr>
723
+ <td><label for="js-everywhere">Load FV Flowplayer JS everywhere:</label></td>
724
+ <td>
725
+ <p class="description">
726
+ <input type="hidden" name="js-everywhere" value="false"/>
727
+ <input type="checkbox" name="js-everywhere" id="js-everywhere" value="true" />
728
+ If you use some special JavaScript integration you might prefer this option. <span class="more">Otherwise our JavaScript only loads if the shortcode is found in any of the posts being currently displayed.</span> <a href="#" class="show-more">(&hellip;)</a>
729
+ </p>
730
+ </td>
731
+ </tr>
732
+ <tr>
733
+ <td><label for="parse_commas">Parse old shortcodes with commas:</label></td>
734
+ <td>
735
+ <p class="description">
736
+ <input type="hidden" name="parse_commas" value="false"/>
737
+ <input type="checkbox" name="parse_commas" id="parse_commas" value="true" />
738
+ Older versions of this plugin used commas to sepparate shortcode parameters. <span class="more">This option will make sure it works with current version. Turn this off if you have some problems with display or other plugins which use shortcodes.</span> <a href="#" class="show-more">(&hellip;)</a>
739
+ </p>
740
+ </td>
741
+ </tr>
742
+ <tr>
743
+ <td><label for="parse_comments">Parse Vimeo and YouTube links:</label></td>
744
+ <td>
745
+ <p class="description">
746
+ <input type="hidden" name="parse_comments" value="false"/>
747
+ <input type="checkbox" name="parse_comments" id="parse_comments" value="true" />
748
+ Affects comments, bbPress and BuddyPress. These links will be displayed as videos. <span class="more">This option makes most sense together with FV Player Pro as it embeds these videos using FV Player. Enables use of shortcodes in comments and bbPress.</span> <a href="#" class="show-more">(&hellip;)</a>
749
+ </p>
750
+ </td>
751
+ </tr>
752
+ <tr>
753
+ <td><label for="postthumbnail">Post Thumbnail:</label></td>
754
+ <td>
755
+ <p class="description">
756
+ <input type="hidden" name="postthumbnail" value="false"/>
757
+ <input type="checkbox" name="postthumbnail" id="postthumbnail" value="true" />
758
+ Setting a video splash screen from the media library will automatically make it the splash image if there is none. </p>
759
+ </td>
760
+ </tr>
761
+ <tr>
762
+ <td><label for="engine">Prefer Flash player by default:</label></td>
763
+ <td>
764
+ <p class="description">
765
+ <input type="hidden" name="engine" value="false"/>
766
+ <input type="checkbox" name="engine" id="engine" value="true" />
767
+ Provides greater compatibility. <span class="more">We use Flash for MP4 files in IE9-10 and M4V files in Firefox regardless of this setting.</span> <a href="#" class="show-more">(&hellip;)</a>
768
+ </p>
769
+ </td>
770
+ </tr>
771
+ <tr>
772
+ <td><label for="rtmp-live-buffer">RTMP bufferTime tweak:</label></td>
773
+ <td>
774
+ <p class="description">
775
+ <input type="hidden" name="rtmp-live-buffer" value="false"/>
776
+ <input type="checkbox" name="rtmp-live-buffer" id="rtmp-live-buffer" value="true" />
777
+ Use if your live streams are not smooth. <span class="more">Adobe <a href="http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/NetStream.html#bufferTime">recommends</a> to set bufferTime to 0 for live streams, but if your stream is not smooth, you can use this setting.</span> <a href="#" class="show-more">(&hellip;)</a>
778
+ </p>
779
+ </td>
780
+ </tr>
781
+
782
+ <tr>
783
+ <td class="first"><label for="db_duration">Scan video length:</label></td>
784
+ <td>
785
+ <p class="description">
786
+ <input type="hidden" name="db_duration" value="false" />
787
+ <input type="checkbox" name="db_duration" id="db_duration" value="true" />
788
+ Turn off if you experience issues when saving posts! <span class="more">Turn on to enable video duration scanning. Currently posts in queue. </span> <a href="#" class="show-more">(&hellip;)</a>
789
+ </p>
790
+ </td>
791
+ </tr>
792
+ <!--<tr>
793
+ <td style="width: 350px"><label for="optimizepress2">Handle OptimizePress 2 videos (<abbr title="Following attributes are not currently supported: margin, border">?</abbr>):</label></td>
794
+ <td>
795
+ <input type="hidden" name="integrations[optimizepress2]" value="false" />
796
+ <input type="checkbox" name="integrations[optimizepress2]" id="optimizepress2" value="true" />
797
+ </td>
798
+ </tr>-->
799
+
800
+ <tr>
801
+ <td><label for="integrations[embed_iframe]">Use iframe embedding:</label></td>
802
+ <td>
803
+ <p class="description">
804
+ <input type="hidden" name="integrations[embed_iframe]" value="false"/>
805
+ <input type="checkbox" name="integrations[embed_iframe]" id="integrations[embed_iframe]" value="true" />
806
+ Beta version! New kind of embedding which supports all the features in embedded player. </p>
807
+ </td>
808
+ </tr>
809
+ <tr>
810
+ <td><label for="integrations[schema_org]">Use Schema.org markup:</label></td>
811
+ <td>
812
+ <p class="description">
813
+ <input type="hidden" name="integrations[schema_org]" value="false"/>
814
+ <input type="checkbox" name="integrations[schema_org]" id="integrations[schema_org]" value="true" />
815
+ Beta version! Adds the meta data information for google. </p>
816
+ </td>
817
+ </tr>
818
+ <tr>
819
+ <td><label for="old_code">Use old code:</label></td>
820
+ <td>
821
+ <p class="description">
822
+ <input type="hidden" name="old_code" value="false"/>
823
+ <input type="checkbox" name="old_code" id="old_code" value="true" />
824
+ Check this option if your videos suddenly don't play and report the issues to <a href="https://foliovision.com/support">Foliovision Support Forums</a> please! </p>
825
+ </td>
826
+ </tr>
827
+ <tr>
828
+ <td><label for="integrations[featured_img]">Add featured image automatically:</label></td>
829
+ <td>
830
+ <p class="description">
831
+ <input type="hidden" name="integrations[featured_img]" value="false"/>
832
+ <input type="checkbox" name="integrations[featured_img]" id="integrations[featured_img]" value="true" />
833
+ If the featured image is not set, splash image of the first player will be used. </p>
834
+ </td>
835
+ </tr>
836
+
837
+ <tr>
838
+ <td><label for="facebook_sharing">Facebook Video Sharing:</label></td>
839
+ <td>
840
+ <p class="description">
841
+ <input type="hidden" name="integrations[facebook_sharing]" value="false" />
842
+ <input type="checkbox" name="integrations[facebook_sharing]" id="facebook_sharing" value="true" />
843
+ When sharing your post to Facebook the first MP4 video will be shared directly rather than the post excerpt. <span class="more"><strong>Requirements</strong>: video has to be on https:// and splash screen has to be present. Videos with download protection are automatically excluded.</span> <a href="#" class="show-more">(&hellip;)</a>
844
+ </p>
845
+ </td>
846
+ </tr>
847
+ <tr>
848
+ <td colspan="4">
849
+ <input type="submit" name="fv-wp-flowplayer-submit" class="button-primary" value="Save All Changes" />
850
+ </td>
851
+ </tr>
852
+ </table>
853
+ </div>
854
+ </div>
855
+ <div id="fv_flowplayer_mobile" class="postbox " >
856
+ <button type="button" class="handlediv" aria-expanded="true"><span class="screen-reader-text">Toggle panel: Mobile Settings</span><span class="toggle-indicator" aria-hidden="true"></span></button><h2 class='hndle'><span>Mobile Settings</span></h2>
857
+ <div class="inside">
858
+
859
+ <table class="form-table2">
860
+ <tr>
861
+ <td><label for="mobile_native_fullscreen">Use native fullscreen on mobile:</label></td>
862
+ <td>
863
+ <p class="description">
864
+ <input type="hidden" name="mobile_native_fullscreen" value="false"/>
865
+ <input type="checkbox" name="mobile_native_fullscreen" id="mobile_native_fullscreen" value="true" />
866
+ Stops popups, ads or subtitles from working, but provides faster interface. We set this for Android < 4.4 and iOS < 7 automatically. </p>
867
+ </td>
868
+ </tr>
869
+ <tr>
870
+ <td><label for="mobile_force_fullscreen">Force fullscreen on mobile (beta):</label></td>
871
+ <td>
872
+ <p class="description">
873
+ <input type="hidden" name="mobile_force_fullscreen" value="false"/>
874
+ <input type="checkbox" name="mobile_force_fullscreen" id="mobile_force_fullscreen" value="true" />
875
+ Video playback will start in fullscreen. iPhone with iOS < 10 always forces fullscreen for video playback. </p>
876
+ </td>
877
+ </tr>
878
+ <tr>
879
+ <td colspan="4">
880
+ <input type="submit" name="fv-wp-flowplayer-submit" class="button-primary" value="Save All Changes" />
881
+ </td>
882
+ </tr>
883
+ </table>
884
+ </div>
885
+ </div>
886
+ <div id="fv_flowplayer_conversion" class="postbox " >
887
+ <button type="button" class="handlediv" aria-expanded="true"><span class="screen-reader-text">Toggle panel: Conversion</span><span class="toggle-indicator" aria-hidden="true"></span></button><h2 class='hndle'><span>Conversion</span></h2>
888
+ <div class="inside">
889
+ <p>This section allows you to convert videos posted using other plugins to FV Player shortcodes.</p>
890
+ <table class="form-table2" style="margin: 5px; ">
891
+ <tr>
892
+ <td>
893
+ <input type="button" class="button" value="Convert JW Player shortcodes" style="margin-top: 2ex;" onclick="if( confirm('This converts the [jwplayer] shortcodes into [fvplayer] shortcodes.\n\n Please make sure you backup your database before continuing. You can use revisions to get back to previos versions of your posts as well.') ) location.href='http://example.org/wp-admin/options-general.php?page=fvplayer&amp;convert_jwplayer=30f043bc86'; "/>
894
+ </td>
895
+ </tr>
896
+ </table>
897
+ </div>
898
+ </div>
899
+ <div id="fv_player_pro" class="postbox " >
900
+ <button type="button" class="handlediv" aria-expanded="true"><span class="screen-reader-text">Toggle panel: Pro Features</span><span class="toggle-indicator" aria-hidden="true"></span></button><h2 class='hndle'><span>Pro Features</span></h2>
901
+ <div class="inside">
902
+ <p><a href="http://foliovision.com/wordpress/plugins/fv-wordpress-flowplayer/download">Purchase FV Flowplayer license</a> to enable Pro features!</p>
903
+ <table class="form-table2">
904
+ <tr>
905
+ <td class="first"><label>Advanced Vimeo embeding:</label></td>
906
+ <td>
907
+ <p class="description">
908
+ <input type="checkbox" checked="checked" disabled="true" />
909
+ Use Vimeo as your video host and use all of FV Flowplayer features. </p>
910
+ </td>
911
+ </tr>
912
+ <tr>
913
+ <td><label>Advanced YouTube embeding:</label></td>
914
+ <td>
915
+ <p class="description">
916
+ <input type="checkbox" checked="checked" disabled="true" />
917
+ Use YouTube as your video host and use all of FV Flowplayer features. </p>
918
+ </td>
919
+ </tr>
920
+ <tr>
921
+ <td><label>Enable user defined AB loop:</label></td>
922
+ <td>
923
+ <p class="description">
924
+ <input type="checkbox" checked="checked" disabled="true" />
925
+ Let your users repeat the parts of the video which they like! </p>
926
+ </td>
927
+ </tr>
928
+ <tr>
929
+ <td><label>Enable video lightbox:</label></td>
930
+ <td>
931
+ <p class="description">
932
+ <input type="checkbox" checked="checked" disabled="true" />
933
+ Enables Lightbox video gallery to show videos in a lightbox popup! </p>
934
+ </td>
935
+ </tr>
936
+ <tr>
937
+ <td><label>Enable quality switching:</label></td>
938
+ <td>
939
+ <p class="description">
940
+ <input type="checkbox" checked="checked" disabled="true" />
941
+ Upload your videos in multiple quality for best user experience with YouTube-like quality switching! </p>
942
+ </td>
943
+ </tr>
944
+ <tr>
945
+ <td><label>Amazon CloudFront protected content:</label></td>
946
+ <td>
947
+ <p class="description">
948
+ <input type="checkbox" checked="checked" disabled="true" />
949
+ Protect your Amazon CDN hosted videos.
950
+ </p>
951
+ </td>
952
+ </tr>
953
+ <tr>
954
+ <td><label>Autoplay just once:</label></td>
955
+ <td>
956
+ <p class="description">
957
+ <input type="checkbox" disabled="true" />
958
+ Makes sure each video autoplays only once for each visitor. </p>
959
+ </td>
960
+ </tr>
961
+ <tr>
962
+ <td><label>Enable video ads:</label></td>
963
+ <td>
964
+ <p class="description">
965
+ <input type="checkbox" disabled="true" />
966
+ Define your own videos ads to play in together with your videos - postroll or prerool </p>
967
+ </td>
968
+ </tr>
969
+ </table>
970
+ <p><strong>Upcoming pro features</strong>:</p>
971
+ <table class="form-table2">
972
+ <tr>
973
+ <td class="first"><label>Enable PayWall:</label></td>
974
+ <td>
975
+ <p class="description">
976
+ <input type="checkbox" checked="checked" disabled="true" />
977
+ Monetize the video content on your membership site. </p>
978
+ </td>
979
+ </tr>
980
+ </table>
981
+ </div>
982
+ </div>
983
+ </div><input type="hidden" id="closedpostboxesnonce" name="closedpostboxesnonce" value="6513e6efc8" /><input type="hidden" id="meta-box-order-nonce" name="meta-box-order-nonce" value="8e68cff2f2" />
984
+ </div>
985
+ <div id='postbox-container-tab_skin' class='postbox-container' style="">
986
+ <div id="normal-sortables" class="meta-box-sortables"><div id="fv_flowplayer_description" class="postbox " >
987
+ <button type="button" class="handlediv" aria-expanded="true"><span class="screen-reader-text">Toggle panel: </span><span class="toggle-indicator" aria-hidden="true"></span></button><h2 class='hndle'><span> </span></h2>
988
+ <div class="inside">
989
+ <table class="form-table">
990
+ <tr>
991
+ <td colspan="4">
992
+ <p>
993
+ You can customize the colors of the player to match your website. </p>
994
+ </td>
995
+ </tr>
996
+ </table>
997
+ </div>
998
+ </div>
999
+ <div id="flowplayer-wrapper" class="postbox " >
1000
+ <button type="button" class="handlediv" aria-expanded="true"><span class="screen-reader-text">Toggle panel: Player Skin</span><span class="toggle-indicator" aria-hidden="true"></span></button><h2 class='hndle'><span>Player Skin</span></h2>
1001
+ <div class="inside">
1002
+ <style id="fv-style-preview"></style>
1003
+ <div class="flowplayer-wrapper">
1004
+ <div id="wpfp_b5bf849ccc1f648970d2fa7a432be230" class="flowplayer no-brand is-splash fvp-play-button" style="background-image: url(https://i.vimeocdn.com/video/609485450_1280.jpg);" data-ratio="0.5625">
1005
+ <div class="fp-ratio" style="padding-top: 56.25%"></div>
1006
+ <div class='fvp-share-bar'><ul class="fvp-sharing">
1007
+ <li><a class="sharing-facebook" href="https://www.facebook.com/sharer/sharer.php?u=" target="_blank">Facebook</a></li>
1008
+ <li><a class="sharing-twitter" href="https://twitter.com/home?status=Test+Blog+" target="_blank">Twitter</a></li>
1009
+ <li><a class="sharing-google" href="https://plus.google.com/share?url=" target="_blank">Google+</a></li>
1010
+ <li><a class="sharing-email" href="mailto:?body=Check%20out%20the%20amazing%20video%20here%3A%20" target="_blank">Email</a></li></ul><div><label><a class="embed-code-toggle" href="#"><strong>Embed</strong></a></label></div><div class="embed-code"><label>Copy and paste this HTML code into your webpage to embed.</label><textarea></textarea></div></div>
1011
+ </div>
1012
+ Hint: play the video to see live preview of the color settings </div>
1013
+ <table class="form-table2 flowplayer-settings fv-player-interface-form-group">
1014
+ <tr>
1015
+ <td><label for="hasBorder">Border</label></td>
1016
+ <td><input type="hidden" name="hasBorder" value="false" />
1017
+ <input type="checkbox" name="hasBorder" id="hasBorder" value="true"
1018
+ data-fv-preview=".flowplayer{border:%val%px solid!important;}"/>
1019
+ </td>
1020
+
1021
+ </tr>
1022
+ <tr>
1023
+ <td><label for="borderColor">Border color</label></td>
1024
+ <td><input class="color" id="borderColor" name="borderColor" type="text" value="#666666"
1025
+ data-fv-preview=".flowplayer{border-color:#%val%!important;}"/></td>
1026
+ </tr>
1027
+ <tr>
1028
+ <td><label for="marginBottom">Bottom Margin</label></td>
1029
+ <td><input id="marginBottom" name="marginBottom" title="Enter value in pixels" type="text" value="28"
1030
+ data-fv-preview=".flowplayer { margin: 0 auto %val%px auto!important; display: block!important; }
1031
+ .flowplayer.fixed-controls { margin: 0 auto calc(%val%px + 30px) auto!important; display: block!important; }
1032
+ .flowplayer.has-abloop { margin-bottom: %val%px!important; }
1033
+ .flowplayer.fixed-controls.has-abloop { margin-bottom: calc(%val%px + 30px)!important; }"/></td>
1034
+ </tr>
1035
+ <tr>
1036
+ <td><label for="bufferColor">Buffer</label></td>
1037
+ <td><input class="color" id="bufferColor" name="bufferColor" type="text" value="#eeeeee"
1038
+ data-fv-preview=".flowplayer .fp-volumeslider, .flowplayer .noUi-background { background-color: #%val% !important; }
1039
+ .flowplayer .fp-buffer, .flowplayer .fv-ab-loop .noUi-handle { background-color: #%val% !important; }" /></td>
1040
+ </tr>
1041
+ <tr>
1042
+ <td><label for="canvas">Canvas</label></td>
1043
+ <td><input class="color" id="canvas" name="canvas" type="text" value="#000000"
1044
+ data-fv-preview=".flowplayer { background-color: #%val%!important; }"/></td>
1045
+ </tr>
1046
+ <tr>
1047
+ <td><label for="backgroundColor">Controlbar</label></td>
1048
+ <td><input class="color" id="backgroundColor" name="backgroundColor" type="text" value="#333333"
1049
+ data-fv-preview=".flowplayer .fv-ab-loop .noUi-handle { color:#%val%!important; }
1050
+ .fv_player_popup { background: #%val%!important;}
1051
+ .fvfp_admin_error_content { background: #%val%!important; }
1052
+ .flowplayer .fp-controls, .flowplayer .fv-ab-loop, .fv-player-buttons a:active, .fv-player-buttons a { background-color: #%val% !important; }"/></td>
1053
+ </tr>
1054
+ <tr>
1055
+ <td><label for="font-face">Font Face</label></td>
1056
+ <td>
1057
+ <select id="font-face" name="font-face" data-fv-preview="#content .flowplayer, .flowplayer { font-family: %val%; }">
1058
+ <option value="inherit">(inherit from template)</option>
1059
+ <option value="&quot;Courier New&quot;, Courier, monospace">Courier New</option>
1060
+ <option value="Tahoma, Geneva, sans-serif" selected="selected">Tahoma, Geneva</option>
1061
+ </select>
1062
+ </td>
1063
+ </tr>
1064
+ <tr>
1065
+ <td class="second-column"><label for="player-position">Player position</label></td>
1066
+ <td>
1067
+ <select id="player-position" name="player-position" data-fv-preview=".flowplayer { margin-left: 0; }">
1068
+ <option value="" selected="selected">Centered</option>
1069
+ <option value="left">Left (no text-wrap)</option>
1070
+ </select>
1071
+ </td>
1072
+ </tr>
1073
+ <tr>
1074
+ <td><label for="progressColor">Progress</label></td>
1075
+ <td><input class="color" id="progressColor" name="progressColor" type="text" value="#bb0000"
1076
+ data-fv-preview=".flowplayer .fp-volumelevel { background-color: #%val%!important; }
1077
+ .flowplayer .fp-progress, .flowplayer .fv-ab-loop .noUi-connect, .fv-player-buttons a.current { background-color: #%val% !important; }
1078
+ .flowplayer .fp-dropdown li.active { background-color: #%val% !important }"/></td>
1079
+ </tr>
1080
+ <tr>
1081
+ <td><label for="timeColor">Time</label></td>
1082
+ <td><input class="color" id="timeColor" name="timeColor" type="text" value="#eeeeee"
1083
+ data-fv-preview=".flowplayer .fp-elapsed { color: #%val% !important; }
1084
+ .fv-wp-flowplayer-notice-small { color: #%val% !important; }"/></td>
1085
+ </tr>
1086
+ <tr>
1087
+ <td><label for="durationColor">Total time</label></td>
1088
+ <td><input class="color" id="durationColor" name="durationColor" type="text" value="#eeeeee"
1089
+ data-fv-preview=".flowplayer .fp-controls, .flowplayer .fv-ab-loop, .fv-player-buttons a:active, .fv-player-buttons a { color:#%val% !important; }"/></td>
1090
+ </tr>
1091
+ <tr>
1092
+ <td colspan="2">
1093
+ <input type="submit" name="fv-wp-flowplayer-submit" class="button-primary" value="Save All Changes" />
1094
+ </td>
1095
+ </tr>
1096
+ </table>
1097
+ <div style="clear: both"></div>
1098
+ </div>
1099
+ </div>
1100
+ <div id="fv_flowplayer_skin_playlist" class="postbox " >
1101
+ <button type="button" class="handlediv" aria-expanded="true"><span class="screen-reader-text">Toggle panel: Playlist</span><span class="toggle-indicator" aria-hidden="true"></span></button><h2 class='hndle'><span>Playlist</span></h2>
1102
+ <div class="inside">
1103
+ <div class="flowplayer-wrapper">
1104
+ <div class="fp-playlist-external fv-playlist-design-2017 fp-playlist-horizontal fp-playlist-has-captions" rel="wpfp_b5bf849ccc1f648970d2fa7a432be230">
1105
+ <a href='#' onclick='return false' data-item='{"sources":[{"src":"https:\/\/player.vimeo.com\/external\/196881410.hd.mp4?s=24645ecff21ff60079fc5b7715a97c00f90c6a18&profile_id=174&oauth2_token_id=3501005","type":"video\/mp4"}],"subtitles":[{"srclang":"en","label":"English","src":"http:\/\/example.org\/wp-content\/plugins\/fv-wordpress-flowplayer\/images\/test-subtitles.vtt"}]}'><div style='background-image: url("https://i.vimeocdn.com/video/608654918_295x166.jpg")'></div><h4><span>Foliovision Video</span></h4></a>
1106
+ <a href='#' onclick='return false' data-item='{"sources":[{"src":"https:\/\/player.vimeo.com\/external\/224781088.sd.mp4?s=face4dbb990b462826c8e1e43a9c66c6a9bb5585&profile_id=165&oauth2_token_id=3501005","type":"video\/mp4"}]}'><div style='background-image: url("https://i.vimeocdn.com/video/643908843_295x166.jpg")'></div><h4><span>Lapinthrope Extras - Roy Thompson Hall Dance</span></h4></a>
1107
+ <a href='#' onclick='return false' data-item='{"sources":[{"src":"https:\/\/player.vimeo.com\/external\/45864857.hd.mp4?s=94fddee594da3258c9e10355f5bad8173c4aee7b&profile_id=113&oauth2_token_id=3501005","type":"video\/mp4"}]}'><div style='background-image: url("https://i.vimeocdn.com/video/319116053_295x166.jpg")'></div><h4><span>Romeo and Juliet Ballet Schloss Kittsee</span></h4></a>
1108
+ </div>
1109
+ Hint: you can click the thumbnails to switch videos in the above player. This preview uses the horizontal playlist style.
1110
+ </div>
1111
+ <table class="form-table2 flowplayer-settings fv-player-interface-form-group">
1112
+ <tr>
1113
+ <td><label for="playlist-design">Playlist Design</label></td>
1114
+ <td>
1115
+ <select id="playlist-design" name="playlist-design" data-fv-preview="">
1116
+ <option value="2017" selected="selected">2017</option>
1117
+ <option value="2017 visible-captions">2017 with captions</option>
1118
+ <option value="2014">2014</option>
1119
+ </select>
1120
+ </td>
1121
+ </tr>
1122
+ <tr>
1123
+ <td><label for="playlistBgColor">Background Color</label></td>
1124
+ <td><input class="color" id="playlistBgColor" name="playlistBgColor" type="text" value="#808080"
1125
+ data-fv-preview=".fp-playlist-external > a > span { background-color:#%val%; }"/></td>
1126
+ </tr>
1127
+ <tr>
1128
+ <td><label for="playlistSelectedColor">Active Item</label></td>
1129
+ <td><input class="color" id="playlistSelectedColor" name="playlistSelectedColor" type="text" value="#bb0000"
1130
+ data-fv-preview=".fp-playlist-external.fv-playlist-design-2014 a.is-active,.fp-playlist-external.fv-playlist-design-2014 a.is-active h4,.fp-playlist-external.fp-playlist-only-captions a.is-active,.fp-playlist-external.fp-playlist-only-captions a.is-active h4 { color:#%val%; }"/></td>
1131
+ </tr>
1132
+ <tr>
1133
+ <td><label for="playlistFontColor-proxy">Font Color</label></td>
1134
+ <td>
1135
+ <input class="color" id="playlistFontColor-proxy" data-previous="" style="display:none;" type="text" value="" />
1136
+ <input id="playlistFontColor" name="playlistFontColor" type="hidden" value=""
1137
+ data-fv-preview=".fp-playlist-external > a { color:#%val%; } #dashboard-widgets .flowplayer-wrapper .fp-playlist-external h4{color: #%val% !important;}"/>
1138
+ <a class="playlistFontColor-show" >Use custom color</a>
1139
+ <a class="playlistFontColor-hide" style="display:none;">Inherit from theme</a>
1140
+ </td>
1141
+ </tr>
1142
+ <tr>
1143
+ <td colspan="2">
1144
+ <input type="submit" name="fv-wp-flowplayer-submit" class="button-primary" value="Save All Changes" />
1145
+ </td>
1146
+ </tr>
1147
+ </table>
1148
+ <div style="clear: both"></div>
1149
+ </div>
1150
+ </div>
1151
+ <div id="fv_flowplayer_skin_subtitles" class="postbox " >
1152
+ <button type="button" class="handlediv" aria-expanded="true"><span class="screen-reader-text">Toggle panel: Subtitles</span><span class="toggle-indicator" aria-hidden="true"></span></button><h2 class='hndle'><span>Subtitles</span></h2>
1153
+ <div class="inside">
1154
+ <table class="form-table2 flowplayer-settings fv-player-interface-form-group">
1155
+ <tr>
1156
+ <td><label for="subtitle-font-face">Font Face</label></td>
1157
+ <td>
1158
+ <select id="subtitle-font-face" name="subtitleFontFace" data-fv-preview=".flowplayer .fp-subtitle .fp-subtitle-line { font-family: %val%!important; }">
1159
+ <option value="inherit">(inherit)</option>
1160
+ <option value="&quot;Courier New&quot;, Courier, monospace">Courier New</option>
1161
+ <option value="Tahoma, Geneva, sans-serif">Tahoma, Geneva</option>
1162
+ </select>
1163
+ </td>
1164
+ </tr>
1165
+ <tr>
1166
+ <td><label for="subtitleSize">Font Size</label></td>
1167
+ <td><input id="subtitleSize" name="subtitleSize" title="Enter value in pixels" type="text" value="16"
1168
+ data-fv-preview=".flowplayer .fp-subtitle .fp-subtitle-line { font-size: %val%px!important; }"/></td>
1169
+ </tr>
1170
+ <tr>
1171
+ <td><label for="subtitleBgColor">Background Color</label></td>
1172
+ <td><input class="color" id="subtitleBgColor" name="subtitleBgColor" type="text" value="#000000"
1173
+ data-fv-preview=".flowplayer .fp-subtitle .fp-subtitle-line { background-color: rgba(%val%)!important; }"/></td>
1174
+ </tr>
1175
+ <tr>
1176
+ <td><label for="subtitleBgAlpha">Background Opacity</label></td>
1177
+ <td><input id="subtitleBgAlpha" name="subtitleBgAlpha" type="range" min="0" max="1" step="0.01" value="0.5"
1178
+ data-fv-preview=""/></td>
1179
+ </tr>
1180
+ <tr>
1181
+ <td colspan="2">
1182
+ <input type="submit" name="fv-wp-flowplayer-submit" class="button-primary" value="Save All Changes" />
1183
+ </td>
1184
+ </tr>
1185
+ </table>
1186
+ <div id="fp-preview-wrapper">
1187
+ <div class="flowplayer"id="preview">
1188
+ <div class="fp-subtitle fp-active">
1189
+ <span class="fp-subtitle-line">
1190
+ The quick brown fox jumps over the lazy dog. </span>
1191
+ </div>
1192
+ </div>
1193
+ </div>
1194
+ <div style="clear: both"></div>
1195
+ </div>
1196
+ </div>
1197
+ <div id="fv_flowplayer_skin_sticky" class="postbox " >
1198
+ <button type="button" class="handlediv" aria-expanded="true"><span class="screen-reader-text">Toggle panel: Sticky Video</span><span class="toggle-indicator" aria-hidden="true"></span></button><h2 class='hndle'><span>Sticky Video</span></h2>
1199
+ <div class="inside">
1200
+ <p>This feature lets your viewers continue watching the video as they scroll past it. It applies to desktop computer displays - minimal width of 1020 pixels.</p>
1201
+ <table class="form-table2 flowplayer-settings fv-player-interface-form-group">
1202
+ <tr>
1203
+ <td><label for="sticky_video">Enable:</label></td>
1204
+ <td>
1205
+ <p class="description">
1206
+ <input type="hidden" name="sticky_video" value="false"/>
1207
+ <input type="checkbox" name="sticky_video" id="sticky_video" value="true" />
1208
+ </p>
1209
+ </td>
1210
+ </tr>
1211
+ <tr>
1212
+ <td><label for="sticky_place">Placement</label></td>
1213
+ <td>
1214
+ <select id="sticky_place" name="sticky_place">
1215
+ <option value="right-bottom" selected="selected">Right, Bottom</option>
1216
+ <option value="left-bottom">Left, Bottom</option>
1217
+ <option value="left-top">Left, Top</option>
1218
+ <option value="right-top">Right, Top</option>
1219
+ </select>
1220
+ </td>
1221
+ </tr>
1222
+ <tr>
1223
+ <td><label for="sticky_width">Player width [px]</label></td>
1224
+ <td><input id="sticky_width" name="sticky_width" title="Enter value in pixels" type="text" value="380"/></td>
1225
+ </tr>
1226
+
1227
+
1228
+ <tr>
1229
+ <td colspan="2">
1230
+ <input type="submit" name="fv-wp-flowplayer-submit" class="button-primary" value="Save All Changes" />
1231
+ </td>
1232
+ </tr>
1233
+ </table>
1234
+ <div style="clear: both"></div>
1235
+ </div>
1236
+ </div>
1237
+ </div><input type="hidden" id="closedpostboxesnonce" name="closedpostboxesnonce" value="6513e6efc8" /><input type="hidden" id="meta-box-order-nonce" name="meta-box-order-nonce" value="8e68cff2f2" />
1238
+ </div>
1239
+ <div id='postbox-container-tab_hosting' class='postbox-container' style="">
1240
+ <div id="normal-sortables" class="meta-box-sortables"><div id="fv_flowplayer_description" class="postbox " >
1241
+ <button type="button" class="handlediv" aria-expanded="true"><span class="screen-reader-text">Toggle panel: </span><span class="toggle-indicator" aria-hidden="true"></span></button><h2 class='hndle'><span> </span></h2>
1242
+ <div class="inside">
1243
+ <table class="form-table">
1244
+ <tr>
1245
+ <td colspan="4">
1246
+ <p>
1247
+ Here you can enable and configure advanced hosting options. </p>
1248
+ </td>
1249
+ </tr>
1250
+ </table>
1251
+ </div>
1252
+ </div>
1253
+ <div id="fv_flowplayer_amazon_options" class="postbox " >
1254
+ <button type="button" class="handlediv" aria-expanded="true"><span class="screen-reader-text">Toggle panel: Amazon S3 Protected Content</span><span class="toggle-indicator" aria-hidden="true"></span></button><h2 class='hndle'><span>Amazon S3 Protected Content</span></h2>
1255
+ <div class="inside">
1256
+ <table class="form-table2">
1257
+ <tr>
1258
+ <td colspan="2">
1259
+ <p>Secured Amazon S3 URLs are recommended for member-only sections of the site. We check the video length and make sure the link expiration time is big enough for the video to buffer properly.</p>
1260
+ <p>If you use a cache plugin (such as Hyper Cache, WP Super Cache or W3 Total Cache), we recommend that you set the "Default Expiration Time" to twice as much as your cache timeout and check "Force the default expiration time". That way the video length won't be accounted and the video source URLs in your cached pages won't expire. Read more in the <a href="http://foliovision.com/wordpress/plugins/fv-wordpress-flowplayer/secure-amazon-s3-guide#wp-cache" target="_blank">Using Amazon S3 secure content in FV Flowplayer guide</a>.</p>
1261
+ </td>
1262
+ </tr>
1263
+ <tr>
1264
+ <td class="first"><label for="amazon_expire">Default Expiration Time [minutes] (<abbr title="Each video duration is stored on post save and then used as the expire time. If the duration is not available, this value is used.">?</abbr>):</label></td>
1265
+ <td>
1266
+ <input type="text" size="40" name="amazon_expire" id="amazon_expire" value="5" />
1267
+ </td>
1268
+ </tr>
1269
+
1270
+ <tr>
1271
+ <td><label for="amazon_expire_force">Force the default expiration time:</label></td>
1272
+ <td>
1273
+ <p class="description">
1274
+ <input type="hidden" name="amazon_expire_force" value="false"/>
1275
+ <input type="checkbox" name="amazon_expire_force" id="amazon_expire_force" value="true" />
1276
+ </p>
1277
+ </td>
1278
+ </tr>
1279
+
1280
+
1281
+ <tr class="amazon-s3-first">
1282
+ <td><label for="amazon_bucket[]">Amazon Bucket (<abbr title="We recommend that you simply put all of your protected video into a single bucket and enter its name here. All matching videos will use the protected URLs.">?</abbr>):</label></td>
1283
+ <td><input id="amazon_bucket[]" name="amazon_bucket[]" type="text" value="" /></td>
1284
+ </tr>
1285
+ <tr class="amazon-s3-first">
1286
+ <td><label for="amazon_region[]">Region</td>
1287
+ <td>
1288
+ <select id="amazon_region[]" name="amazon_region[]">
1289
+ <option value="">Select the region</option>
1290
+ <option value="us-east-1">US East (N. Virginia)</option>
1291
+ <option value="us-east-2">US East (Ohio)</option>
1292
+ <option value="us-west-1">US West (N. California)</option>
1293
+ <option value="us-west-2">US West (Oregon)</option>
1294
+ <option value="ca-central-1">Canada (Central)</option>
1295
+ <option value="ap-south-1">Asia Pacific (Mumbai)</option>
1296
+ <option value="ap-northeast-2">Asia Pacific (Seoul)</option>
1297
+ <option value="ap-southeast-1">Asia Pacific (Singapore)</option>
1298
+ <option value="ap-southeast-2">Asia Pacific (Sydney)</option>
1299
+ <option value="ap-northeast-1">Asia Pacific (Tokyo)</option>
1300
+ <option value="eu-central-1">EU (Frankfurt)</option>
1301
+ <option value="eu-west-1">EU (Ireland)</option>
1302
+ <option value="eu-west-2">EU (London)</option>
1303
+ <option value="sa-east-1">South America (S&atilde;o Paulo)</option>
1304
+ </select>
1305
+ </td>
1306
+ </tr>
1307
+ <tr class="amazon-s3-first">
1308
+ <td><label for="amazon_key[]">Access Key ID:</label></td>
1309
+ <td><input id="amazon_key[]" name="amazon_key[]" type="text" value="" /></td>
1310
+ </tr>
1311
+ <tr class="amazon-s3-first">
1312
+ <td><label for="amazon_secret[]">Secret Access Key:</label></td>
1313
+ <td><input id="amazon_secret[]" name="amazon_secret[]" type="text" value="" /></td>
1314
+ </tr>
1315
+ <tr class="amazon-s3-first">
1316
+ <td colspan="2">
1317
+ <div class="alignright fv_fp_amazon_remove">
1318
+ <a href="#" onclick="fv_fp_amazon_s3_remove(this); return false">remove</a>
1319
+ </div>
1320
+ <div class="clear"></div>
1321
+ <hr style="border: 0; border-top: 1px solid #ccc;" />
1322
+ </td>
1323
+ </tr>
1324
+
1325
+ <tr class="amazon-s3-last"><td colspan="2"></td></tr>
1326
+ <tr>
1327
+ <td colspan="4">
1328
+ <input type="submit" name="fv-wp-flowplayer-submit" class="button-primary" value="Save All Changes" />
1329
+ <input type="button" id="amazon-s3-add" class="button" value="Add more Amazon S3 secure buckets" />
1330
+ </td>
1331
+ </tr>
1332
+ </table>
1333
+ </div>
1334
+ </div>
1335
+ </div><input type="hidden" id="closedpostboxesnonce" name="closedpostboxesnonce" value="6513e6efc8" /><input type="hidden" id="meta-box-order-nonce" name="meta-box-order-nonce" value="8e68cff2f2" />
1336
+ </div>
1337
+ <div id='postbox-container-tab_actions' class='postbox-container' style="">
1338
+ <div id="normal-sortables" class="meta-box-sortables"><div id="fv_flowplayer_description" class="postbox " >
1339
+ <button type="button" class="handlediv" aria-expanded="true"><span class="screen-reader-text">Toggle panel: </span><span class="toggle-indicator" aria-hidden="true"></span></button><h2 class='hndle'><span> </span></h2>
1340
+ <div class="inside">
1341
+ <table class="form-table">
1342
+ <tr>
1343
+ <td colspan="4">
1344
+ <p>
1345
+ Here you can configure ads and banners that will be shown in the video. </p>
1346
+ </td>
1347
+ </tr>
1348
+ </table>
1349
+ </div>
1350
+ </div>
1351
+ <div id="fv_flowplayer_end_of_video" class="postbox " >
1352
+ <button type="button" class="handlediv" aria-expanded="true"><span class="screen-reader-text">Toggle panel: End of Video</span><span class="toggle-indicator" aria-hidden="true"></span></button><h2 class='hndle'><span>End of Video</span></h2>
1353
+ <div class="inside">
1354
+ <table class="form-table2" style="margin: 5px; ">
1355
+ <tr>
1356
+ <td style="width:150px;vertical-align:top;line-height:2.4em;"><label for="popups_default">Default Popup:</label></td>
1357
+ <td>
1358
+
1359
+ <p class="description"> <select id="popups_default" name="popups_default">
1360
+ <option selected value="no">None</option>
1361
+ <option value="random">Random</option>
1362
+ </select>
1363
+ You can set a default popup here and then skip it for individual videos.</p>
1364
+ </td>
1365
+ </tr>
1366
+ <tr>
1367
+ <td colspan="4">
1368
+ <input type="submit" name="fv-wp-flowplayer-submit" class="button-primary" value="Save All Changes" />
1369
+ </td>
1370
+ </tr>
1371
+ </table>
1372
+ </div>
1373
+ </div>
1374
+ <div id="fv_flowplayer_popups" class="postbox " >
1375
+ <button type="button" class="handlediv" aria-expanded="true"><span class="screen-reader-text">Toggle panel: Custom Popups</span><span class="toggle-indicator" aria-hidden="true"></span></button><h2 class='hndle'><span>Custom Popups</span></h2>
1376
+ <div class="inside">
1377
+ <p>Add any popups here which you would like to use with multiple videos.</p>
1378
+ <table class="form-table2" style="margin: 5px; ">
1379
+ <tr>
1380
+ <td>
1381
+ <table id="fv-player-popups-settings">
1382
+ <thead>
1383
+ <tr>
1384
+ <td>ID</td>
1385
+ <td></td>
1386
+ <td>Status</td>
1387
+ </tr>
1388
+ </thead>
1389
+ <tbody>
1390
+ <tr class='data' id="fv-player-popup-item-1">
1391
+ <td class='id'>1</td>
1392
+ <td>
1393
+ <table class='fv-player-popup-formats'>
1394
+ <tr>
1395
+ <td><label>Name:</label></td>
1396
+ <td><input type='text' maxlength="40" name='popups[1][name]' value='' placeholder='' /></td>
1397
+ </tr>
1398
+ <tr>
1399
+ <td><label>HTML:</label></td>
1400
+ <td><textarea class="large-text code" type='text' name='popups[1][html]' placeholder=''></textarea></td>
1401
+ </tr>
1402
+ <tr>
1403
+ <td><label>Custom<br />CSS:</label></td>
1404
+ <td><textarea class="large-text code" type='text' name='popups[1][css]' placeholder='.fv_player_popup-1 { }'></textarea></td>
1405
+ </tr>
1406
+ </table>
1407
+ </td>
1408
+ <td>
1409
+ <input type='hidden' name='popups[1][disabled]' value='0' />
1410
+ <input id='PopupAdDisabled-1' type='checkbox' name='popups[1][disabled]' value='1' />
1411
+ <label for='PopupAdDisabled-1'>Disable</label><br />
1412
+ <a class='fv-player-popup-remove' href=''>Remove</a></td>
1413
+ </tr>
1414
+ </tbody>
1415
+ </table>
1416
+ </td>
1417
+ </tr>
1418
+ <tr>
1419
+ <td>
1420
+ <input type="submit" name="fv-wp-flowplayer-submit" class="button-primary" value="Save All Changes" />
1421
+ <input type="button" value="Add more Popups" class="button" id="fv-player-popups-add" />
1422
+ </td>
1423
+ </tr>
1424
+ </table>
1425
+
1426
+ <script>
1427
+
1428
+ jQuery('#fv-player-popups-add').click( function() {
1429
+ var fv_player_popup_index = (parseInt( jQuery('#fv-player-popups-settings tr.data:last .id').html() ) || 0 ) + 1;
1430
+ jQuery('#fv-player-popups-settings').append(jQuery('#fv-player-popups-settings tr.data:first').prop('outerHTML').replace(/#fv_popup_dummy_key#/gi,fv_player_popup_index + ""));
1431
+ jQuery('#fv-player-popup-item-'+fv_player_popup_index).show();
1432
+ return false;
1433
+ } );
1434
+
1435
+ jQuery(document).on('click','.fv-player-popup-remove', false, function() {
1436
+ if( confirm('Are you sure you want to remove the popup ad?') ){
1437
+ jQuery(this).parents('.data').remove();
1438
+ if(jQuery('#fv-player-popups-settings .data').length === 1) {
1439
+ jQuery('#fv-player-popups-add').trigger('click');
1440
+ }
1441
+ }
1442
+ return false;
1443
+ } );
1444
+ </script>
1445
+ </div>
1446
+ </div>
1447
+ <div id="fv_flowplayer_email_lists" class="postbox " >
1448
+ <button type="button" class="handlediv" aria-expanded="true"><span class="screen-reader-text">Toggle panel: Email Popups</span><span class="toggle-indicator" aria-hidden="true"></span></button><h2 class='hndle'><span>Email Popups</span></h2>
1449
+ <div class="inside">
1450
+ <p>Lists defined here can be used for subscription box for each video or for Default Popup above.</p>
1451
+ <table class="form-table2" style="margin: 5px; ">
1452
+ <tr>
1453
+ <td>
1454
+ <table id="fv-player-email_lists-settings">
1455
+ <thead>
1456
+ <tr>
1457
+ <td>ID</td>
1458
+ <td style="width: 40%">Properties</td>
1459
+ <td>Export</td>
1460
+ <td>Options</td>
1461
+ <td>Status</td>
1462
+ <td></td>
1463
+ </tr>
1464
+ </thead>
1465
+ <tbody>
1466
+ <tr class='data' id="fv-player-list-item-#fv_list_dummy_key#"style="display:none">
1467
+ <td class='id'>#fv_list_dummy_key#</td>
1468
+ <td>
1469
+ <table>
1470
+ <tr>
1471
+ <td style="width:16%"><label>Header</label></td>
1472
+ <td><input type='text' name='email_lists[#fv_list_dummy_key#][title]' value='' /></td>
1473
+ </tr>
1474
+ <tr>
1475
+ <td><label>Message</label></td>
1476
+ <td><input type='text' name='email_lists[#fv_list_dummy_key#][description]' value='' /></td>
1477
+ </tr>
1478
+ </table>
1479
+ </td>
1480
+ <td>
1481
+ <a class='fv-player-list-export' href='http://example.org/wp-admin/options-general.php?page=fvplayer&fv-email-export=#fv_list_dummy_key#' target="_blank" >Download CSV</a>
1482
+ <br />
1483
+ <a class='fv-player-list-export' href='http://example.org/wp-admin/options-general.php?page=fvplayer&fv-email-export-screen=#fv_list_dummy_key#' target="_blank" >View list</a>
1484
+ </td>
1485
+ <td>
1486
+ <input type='hidden' name='email_lists[#fv_list_dummy_key#][first_name]' value='0' />
1487
+ <input id='list-first-name-#fv_list_dummy_key#' title="first name" type='checkbox' name='email_lists[#fv_list_dummy_key#][first_name]' value='1' />
1488
+ <label for='list-first-name-#fv_list_dummy_key#'>First Name</label>
1489
+ <br />
1490
+ <input type='hidden' name='email_lists[#fv_list_dummy_key#][last_name]' value='0' />
1491
+ <input id='list-last-name-#fv_list_dummy_key#' title="last name" type='checkbox' name='email_lists[#fv_list_dummy_key#][last_name]' value='1' />
1492
+ <label for='list-last-name-#fv_list_dummy_key#'>Last Name</label>
1493
+ </td>
1494
+ <td>
1495
+ <input type='hidden' name='email_lists[#fv_list_dummy_key#][disabled]' value='0' />
1496
+ <input id='ListAdDisabled-#fv_list_dummy_key#' type='checkbox' title="disable" name='email_lists[#fv_list_dummy_key#][disabled]' value='1' />
1497
+ <label for='ListAdDisabled-#fv_list_dummy_key#'>Disable</label>
1498
+ <br />
1499
+ <a class='fv-player-list-remove' href=''>Remove</a>
1500
+ </td>
1501
+ <td>
1502
+ <input type="button" style="visibility: hidden" class="fv_player_email_list_save button" value="Save & Preview" />
1503
+ </td>
1504
+ </tr>
1505
+ <tr class='data' id="fv-player-list-item-1">
1506
+ <td class='id'>1</td>
1507
+ <td>
1508
+ <table>
1509
+ <tr>
1510
+ <td style="width:16%"><label>Header</label></td>
1511
+ <td><input type='text' name='email_lists[1][title]' value='' /></td>
1512
+ </tr>
1513
+ <tr>
1514
+ <td><label>Message</label></td>
1515
+ <td><input type='text' name='email_lists[1][description]' value='' /></td>
1516
+ </tr>
1517
+ </table>
1518
+ </td>
1519
+ <td>
1520
+ <a class='fv-player-list-export' href='http://example.org/wp-admin/options-general.php?page=fvplayer&fv-email-export=1' target="_blank" >Download CSV</a>
1521
+ <br />
1522
+ <a class='fv-player-list-export' href='http://example.org/wp-admin/options-general.php?page=fvplayer&fv-email-export-screen=1' target="_blank" >View list</a>
1523
+ </td>
1524
+ <td>
1525
+ <input type='hidden' name='email_lists[1][first_name]' value='0' />
1526
+ <input id='list-first-name-1' title="first name" type='checkbox' name='email_lists[1][first_name]' value='1' />
1527
+ <label for='list-first-name-1'>First Name</label>
1528
+ <br />
1529
+ <input type='hidden' name='email_lists[1][last_name]' value='0' />
1530
+ <input id='list-last-name-1' title="last name" type='checkbox' name='email_lists[1][last_name]' value='1' />
1531
+ <label for='list-last-name-1'>Last Name</label>
1532
+ </td>
1533
+ <td>
1534
+ <input type='hidden' name='email_lists[1][disabled]' value='0' />
1535
+ <input id='ListAdDisabled-1' type='checkbox' title="disable" name='email_lists[1][disabled]' value='1' />
1536
+ <label for='ListAdDisabled-1'>Disable</label>
1537
+ <br />
1538
+ <a class='fv-player-list-remove' href=''>Remove</a>
1539
+ </td>
1540
+ <td>
1541
+ <input type="button" style="visibility: hidden" class="fv_player_email_list_save button" value="Save & Preview" />
1542
+ </td>
1543
+ </tr>
1544
+ </tbody>
1545
+ </table>
1546
+ </td>
1547
+ </tr>
1548
+ <tr>
1549
+ <td>
1550
+ <input type="button" value="Add More Lists" class="button" id="fv-player-email_lists-add" />
1551
+ </td>
1552
+ </tr>
1553
+ </table>
1554
+
1555
+ <script>
1556
+ jQuery('#fv-player-email_lists-add').click( function() {
1557
+ var fv_player_list_index = (parseInt( jQuery('#fv-player-email_lists-settings tr.data:last .id').html() ) || 0 ) + 1;
1558
+ jQuery('#fv-player-email_lists-settings').append(jQuery('#fv-player-email_lists-settings tr.data:first').prop('outerHTML').replace(/#fv_list_dummy_key#/gi,fv_player_list_index + ""));
1559
+ jQuery('#fv-player-list-item-' + fv_player_list_index).show();
1560
+ return false;
1561
+ } );
1562
+
1563
+ jQuery(document).on('click','.fv-player-list-remove', false, function() {
1564
+ if( confirm('Are you sure you want to remove the list?') ){
1565
+ jQuery(this).parents('.data').remove();
1566
+ if(jQuery('#fv-player-email_lists-settings .data').length === 1) {
1567
+ jQuery('#fv-player-email_lists-add').trigger('click');
1568
+ }
1569
+ }
1570
+ return false;
1571
+ } );
1572
+
1573
+ jQuery(document).on('keydown change', '#fv-player-email_lists-settings', function(e) {
1574
+ var row = jQuery(e.target).parents('[id^="fv-player-list-item-"]');
1575
+ row.find('.fv_player_email_list_save').css('visibility','visible');
1576
+ });
1577
+ jQuery(document).on('click', '#fv-player-email_lists-settings input[type=checkbox]', function(e) {
1578
+ var row = jQuery(e.target).parents('[id^="fv-player-list-item-"]');
1579
+ row.find('.fv_player_email_list_save').css('visibility','visible');
1580
+ });
1581
+
1582
+ jQuery(document).on('click', '.fv_player_email_list_save', function() {
1583
+ var button = jQuery(this);
1584
+ var row = button.parents('[id^="fv-player-list-item-"]');
1585
+ var aInputs = row.find('input, select');
1586
+ var key = row.attr('id').replace(/fv-player-list-item-/,'');
1587
+
1588
+ fv_player_open_preview_window(null,640,360+100);
1589
+
1590
+ button.prop('disabled',true);
1591
+ jQuery.ajax( {
1592
+ type: "POST",
1593
+ url: ajaxurl,
1594
+ data: aInputs.serialize()+'&key='+key+'&action=fv_player_email_subscription_save&_wpnonce=0076f76ad6',
1595
+ success: function(response) {
1596
+ button.css('visibility','hidden');
1597
+ button.prop('disabled', false);
1598
+
1599
+ row.replaceWith( jQuery('#'+row.attr('id'),response) );
1600
+
1601
+ var shortcode = '[fvplayer src="https://player.vimeo.com/external/196881410.hd.mp4?s=24645ecff21ff60079fc5b7715a97c00f90c6a18&profile_id=174&oauth2_token_id=3501005" splash="https://i.vimeocdn.com/video/609485450_1280.jpg" preroll="no" postroll="no" subtitles="http://example.org/wp-content/plugins/Users/martinv/github/fv-wordpress-flowplayer/images/test-subtitles.vtt" end_popup_preview="true" popup="email-#key#" caption="This is how the popup will appear at the end of a video"]';
1602
+ shortcode = shortcode.replace(/#key#/,key);
1603
+
1604
+ var url = 'http://example.org?fv_player_embed=1&fv_player_preview=' + b64EncodeUnicode(shortcode);
1605
+ fv_player_open_preview_window(url);
1606
+ },
1607
+ error: function() {
1608
+ button.val('Error saving!');
1609
+ }
1610
+ } );
1611
+ });
1612
+ </script>
1613
+ </div>
1614
+ </div>
1615
+ <div id="fv_flowplayer_email_integration" class="postbox " >
1616
+ <button type="button" class="handlediv" aria-expanded="true"><span class="screen-reader-text">Toggle panel: Email Integration</span><span class="toggle-indicator" aria-hidden="true"></span></button><h2 class='hndle'><span>Email Integration</span></h2>
1617
+ <div class="inside">
1618
+ <p>Enter your service API key and then assign it to a list which you create above.</p>
1619
+ <table class="form-table2" style="margin: 5px; ">
1620
+ <tr>
1621
+ <td style="width: 250px"><label for="mailchimp_api">Mailchimp API key:</label></td>
1622
+ <td>
1623
+ <p class="description">
1624
+ <input type="text" name="mailchimp_api" id="mailchimp_api" value="" />
1625
+ </p>
1626
+ </td>
1627
+ </tr>
1628
+ <tr>
1629
+ <td></td>
1630
+ <td>
1631
+ <input type="submit" name="fv-wp-flowplayer-submit" class="button-primary" value="Save All Changes" />
1632
+ </td>
1633
+ </tr>
1634
+ </table>
1635
+ </div>
1636
+ </div>
1637
+ <div id="fv_flowplayer_ads" class="postbox " >
1638
+ <button type="button" class="handlediv" aria-expanded="true"><span class="screen-reader-text">Toggle panel: Ads</span><span class="toggle-indicator" aria-hidden="true"></span></button><h2 class='hndle'><span>Ads</span></h2>
1639
+ <div class="inside">
1640
+ <table class="form-table2">
1641
+ <tr>
1642
+ <td colspan="2">
1643
+ <label for="ad">Default Ad Code:</label><br />
1644
+ <textarea id="ad" name="ad" class="large-text code"></textarea>
1645
+ </td>
1646
+ </tr>
1647
+ <tr>
1648
+ <td colspan="2"><label for="ad_width">Default set size [px]:</label>
1649
+ <label for="ad_width">W:</label>&nbsp; <input type="text" name="ad_width" id="ad_width" value="0" class="small" />
1650
+ <label for="ad_height">H:</label>&nbsp;<input type="text" name="ad_height" id="ad_height" value="0" class="small" />
1651
+ <label for="adTextColor">Ad text</label> <input class="color small" type="text" name="adTextColor" id="adTextColor" value="#888" />
1652
+ <label for="adLinksColor">Ad links</label> <input class="color small" type="text" name="adLinksColor" id="adLinksColor" value="#ff3333" />
1653
+ </td>
1654
+ </tr>
1655
+ <tr>
1656
+ <td>
1657
+ <label for="ad_show_after">Show After [s]:</label>&nbsp; <input type="text" name="ad_show_after" id="ad_show_after" value="0" class="small" />
1658
+ </td>
1659
+ </tr>
1660
+ <tr>
1661
+ <td colspan="2">
1662
+ <label for="ad_css_select">Ad CSS:</label>
1663
+ <a href="#" onclick="jQuery('.ad_css_wrap').show(); jQuery(this).hide(); return false">Show styling options</a>
1664
+ <div class="ad_css_wrap" style="display: none; ">
1665
+ <select id="ad_css_select">
1666
+ <option value="">Select your preset</option>
1667
+ <option value=".wpfp_custom_ad { position: absolute; bottom: 10%; z-index: 20; width: 100%; }
1668
+ .wpfp_custom_ad_content { background: white; margin: 0 auto; position: relative }" selected="selected">Default (white, centered above the control bar)</option>
1669
+ <option value=".wpfp_custom_ad { position: absolute; bottom: 0; z-index: 20; width: 100%; }
1670
+ .wpfp_custom_ad_content { background: white; margin: 0 auto; position: relative }">White, centered at the bottom of the video</option>
1671
+ </select>
1672
+ <br />
1673
+ <textarea rows="5" name="ad_css" id="ad_css" class="large-text code">.wpfp_custom_ad { position: absolute; bottom: 10%; z-index: 20; width: 100%; }
1674
+ .wpfp_custom_ad_content { background: white; margin: 0 auto; position: relative }</textarea>
1675
+ <p class="description">(Hint: put .wpfp_custom_ad_content before your own CSS selectors)</p>
1676
+ <script type="text/javascript">
1677
+ jQuery('#ad_css_select').change( function() {
1678
+ if( jQuery('#ad_css_select option:selected').val().length > 0 && jQuery('#ad_css_select option:selected').val() != jQuery('#ad_css').val() && confirm('Are you sure you want to apply the preset?') ) {
1679
+ jQuery('#ad_css').val( jQuery('#ad_css_select option:selected').val() );
1680
+ }
1681
+ } );
1682
+ </script>
1683
+ </div>
1684
+ </td>
1685
+ </tr>
1686
+ <tr>
1687
+ <td colspan="4">
1688
+ <input type="submit" name="fv-wp-flowplayer-submit" class="button-primary" value="Save All Changes" />
1689
+ </td>
1690
+ </tr>
1691
+ </table>
1692
+ </div>
1693
+ </div>
1694
+ </div><input type="hidden" id="closedpostboxesnonce" name="closedpostboxesnonce" value="6513e6efc8" /><input type="hidden" id="meta-box-order-nonce" name="meta-box-order-nonce" value="8e68cff2f2" />
1695
+ </div>
1696
+ <div id='postbox-container-tab_help' class='postbox-container' style="">
1697
+ <div id="normal-sortables" class="meta-box-sortables"><div id="fv_flowplayer_usage" class="postbox " >
1698
+ <button type="button" class="handlediv" aria-expanded="true"><span class="screen-reader-text">Toggle panel: Usage</span><span class="toggle-indicator" aria-hidden="true"></span></button><h2 class='hndle'><span>Usage</span></h2>
1699
+ <div class="inside">
1700
+ <table class="form-table">
1701
+ <tr>
1702
+ <td colspan="4">
1703
+ <div class="column">
1704
+ <div class="icon32" id="icon-users"><br></div>
1705
+ <p>Illustrated user guides:</p>
1706
+ <div class="clear"></div>
1707
+ <ul>
1708
+ <li><a target="_blank" href="https://foliovision.com/player/basic-setup/start-up-guide#insert-videos">Inserting videos</a>
1709
+ <li><a target="_blank" href="https://foliovision.com/player/basic-setup/start-up-guide">License key and custom logo</a></li>
1710
+ <li><a target="_blank" href="https://foliovision.com/player/basic-setup/creating-playlists">How to create a playlist</a></li>
1711
+ <li><a target="_blank" href="https://foliovision.com/player/ads">Using ads</a></li>
1712
+ <li><a target="_blank" href="https://foliovision.com/player/ads/incorporating-google-adsense">Using Google Ads</a></li>
1713
+ <li><a target="_blank" href="https://foliovision.com/player/video-hosting/securing-your-video/rtmp-streams">RTMP streams</a></li>
1714
+ <li><a target="_blank" href="https://foliovision.com/player/advanced/subtitles">Subtitles</a></li>
1715
+ <li><a target="_blank" href="https://foliovision.com/player/video-hosting/secure-amazon-s3-guide">Amazon S3 secure content guide</a></li>
1716
+ <li><a target="_blank" href="https://foliovision.com/player/video-hosting/securing-your-video/hls-stream">How to setup a HLS stream</a></li>
1717
+ <li><a target="_blank" href="https://foliovision.com/player/advanced/google-analytics-flowplayer">Google Analytics support</a></li>
1718
+ <li><a target="_blank" href="https://foliovision.com/player/basic-setup/using-lightbox">Video lightbox</a></li>
1719
+ <li><a target="_blank" href="https://foliovision.com/player/video-hosting/youtube-with-fv-player">YouTube integration</a></li>
1720
+ <li><a target="_blank" href="https://foliovision.com/player/basic-setup/setting-quality-switching">Quality Switching</a></li>
1721
+ <li><a target="_blank" href="https://foliovision.com/player/video-hosting/how-to-use-vimeo">Vimeo integration</a></li>
1722
+ <li><a target="_blank" href="https://foliovision.com/player/ads/using-preroll-postroll-ads">Custom video ads</a></li>
1723
+ <li><a target="_blank" href="https://foliovision.com/player/video-hosting/serving-private-cloudfront">CloudFront CDN - protected video downloads</a></li>
1724
+ </ul>
1725
+ </div>
1726
+ <div class="column">
1727
+ <div class="icon32" id="icon-tools"><br></div>
1728
+ <p>Troubleshooting:</p>
1729
+ <div class="clear"></div>
1730
+ <ul>
1731
+ <li><a target="_blank" href="https://foliovision.com/player/basic-setup/installation">Automated checks</a></li>
1732
+ <li><a target="_blank" href="https://foliovision.com/player/basic-setup/encoding">Video encoding tips</a></li>
1733
+ <li><a target="_blank" href="https://foliovision.com/player/basic-setup/encoding#flash-only">Video formats to avoid</a></li>
1734
+ <li><a target="_blank" href="https://foliovision.com/player/video-hosting/secure-amazon-s3-guide/fix-amazon-mime-type">Fixing mime type on Amazon S3</a></li>
1735
+ <li><a target="_blank" href="https://foliovision.com/player/basic-setup/faq">Plugin FAQ</a></li>
1736
+ <li><a target="_blank" href="http://foliovision.com/support/fv-wordpress-flowplayer/">Support forums</a></li>
1737
+ </ul>
1738
+ </div>
1739
+ <div class="clear"></div>
1740
+ <!--<p>
1741
+ To embed video "example.mp4", simply include the following code inside any post or page:
1742
+ <code>[fvplayer src=example.mp4]</code>
1743
+ </p>
1744
+ <p>
1745
+ <code>src</code> is the only compulsory parameter, specifying the video file. Its value can be either a full URL of the file,
1746
+ or just a filename (if it is located in the /videos/ directory in the root of the web).
1747
+ </p>
1748
+ <p>When user uploads are allowed, uploading or selecting video from WP Media Library is available. To insert selected video, simply use the 'Insert into Post' button.</p>
1749
+ <h4>Optional parameters:</h4>
1750
+ <ul style="text-align: left;">
1751
+ <li><code><strong>width</strong></code> and <code><strong>height</strong></code> specify the dimensions of played video in pixels. If they are not set, the default size is 320x240.<br />
1752
+ <i>Example</i>: <code>[fvplayer src='example.mp4' width=640 height=480]</code></li>
1753
+ <li><code><strong>splash</strong></code> parameter can be used to display a custom splash image before the video starts. Just like in case of <code>src</code>
1754
+ parameter, its value can be either complete URL, or filename of an image located in /videos/ folder.<br />
1755
+ <i>Example</i>: <code>[fvplayer src='example.mp4' splash=image.jpg]</code></li>
1756
+ <li><code><strong>splashend</strong></code> parameter can be used to display a custom splash image after the video ends.<br />
1757
+ <i>Example</i>: <code>[fvplayer src='example.mp4' splashend=show]</code></li>
1758
+ <li><code><strong>autoplay</strong></code> parameter specify wheter the video should start to play automaticaly after the page is loaded. This parameter overrides the default autoplay setting above. Its value can be either true or false.<br />
1759
+ <i>Example</i>: <code>[fvplayer src='example.mp4' autoplay=true]</code></li>
1760
+ <li><code><strong>loop</strong></code> parameter specify wheter the video starts again from the beginning when the video ends. Its value can be either true or false.<br />
1761
+ <i>Example</i>: <code>[fvplayer src='example.mp4' loop=true]</code></li>
1762
+ <li><code><strong>popup</strong></code> parameter can be used to display any HTML code after the video finishes (ideal for advertisment or links to similar videos).
1763
+ Content you want to display must be between simple quotes (<code>''</code>).<br />
1764
+ <i>Example</i>: <code>[fvplayer src='example.mp4' popup='&lt;p&gt;some HTML content&lt;/p&gt;']</code></li>
1765
+ <li><code><strong>redirect</strong></code> parameter can be used to redirect to another page (in a new tab) after the video ends.<br />
1766
+ <i>Example</i>: <code>[fvplayer src='example.mp4' redirect='http://www.site.com']</code></li>
1767
+ </ul>-->
1768
+ </td>
1769
+ <td></td>
1770
+ </tr>
1771
+ </table>
1772
+ </div>
1773
+ </div>
1774
+ </div><input type="hidden" id="closedpostboxesnonce" name="closedpostboxesnonce" value="6513e6efc8" /><input type="hidden" id="meta-box-order-nonce" name="meta-box-order-nonce" value="8e68cff2f2" />
1775
+ </div>
1776
+ <div style="clear: both"></div>
1777
+ </div>
1778
+ <input type="hidden" id="fv_flowplayer_settings_nonce" name="fv_flowplayer_settings_nonce" value="b5b463282b" /><input type="hidden" name="_wp_http_referer" value="" /> </form>
1779
+
1780
+ </div>
1781
+ <script type="text/javascript" >
1782
+ function flowplayer_conversion_script() {
1783
+ jQuery('#fv-flowplayer-loader').show();
1784
+
1785
+ var data = {
1786
+ action: 'flowplayer_conversion_script',
1787
+ run: true
1788
+ };
1789
+
1790
+ jQuery.post(ajaxurl, data, function(response) {
1791
+ jQuery('#fv-flowplayer-loader').hide();
1792
+ jQuery('#conversion-results').html(response);
1793
+ jQuery('#fvwpflowplayer_conversion_notice').hide();
1794
+ });
1795
+ }
1796
+
1797
+ function fv_flowplayer_ajax_check( type ) {
1798
+ jQuery('.'+type+'-spin').show();
1799
+ var ajaxurl = 'http://example.org/wp-admin/admin-ajax.php';
1800
+ jQuery.post( ajaxurl, { action: type }, function( response ) {
1801
+ response = response.replace( /[\s\S]*<FVFLOWPLAYER>/, '' );
1802
+ response = response.replace( /<\/FVFLOWPLAYER>[\s\S]*/, '' );
1803
+ try {
1804
+ var obj = (jQuery.parseJSON( response ) );
1805
+ var css_class = '';
1806
+ jQuery('#fv_flowplayer_admin_notices').html('');
1807
+ if( obj.errors && obj.errors.length > 0 ) {
1808
+ jQuery('#fv_flowplayer_admin_notices').append( '<div class="error"><p>'+obj.errors.join('</p><p>')+'</p></div>' );
1809
+ } else {
1810
+ css_class = ' green';
1811
+ }
1812
+
1813
+ if( obj.ok && obj.ok.length > 0 ) {
1814
+ jQuery('#fv_flowplayer_admin_notices').append( '<div class="updated'+css_class+'"><p>'+obj.ok.join('</p><p>')+'</p></div>' );
1815
+ }
1816
+
1817
+ } catch(err) {
1818
+ jQuery('#fv_flowplayer_admin_notices').append( jQuery('#wpbody', response ) );
1819
+
1820
+ }
1821
+
1822
+ jQuery('.'+type+'-spin').hide();
1823
+ } );
1824
+ }
1825
+
1826
+ var fv_flowplayer_amazon_s3_count = 0;
1827
+ jQuery('#amazon-s3-add').click( function() {
1828
+ var new_inputs = jQuery('tr.amazon-s3-first').clone();
1829
+ new_inputs.find('input').attr('value','');
1830
+ new_inputs.attr('class', new_inputs.attr('class') + '-' + fv_flowplayer_amazon_s3_count );
1831
+ new_inputs.insertBefore('.amazon-s3-last');
1832
+ fv_flowplayer_amazon_s3_count++;
1833
+ return false;
1834
+ } );
1835
+
1836
+ function fv_fp_amazon_s3_remove(a) {
1837
+ jQuery( '.'+jQuery(a).parents('tr').attr('class') ).remove();
1838
+ }
1839
+ </script>
1840
+
1841
+
1842
+ <script type="text/javascript">
1843
+ //<![CDATA[
1844
+ jQuery(document).ready( function($) {
1845
+ // close postboxes that should be closed
1846
+ $('.if-js-closed').removeClass('if-js-closed').addClass('closed');
1847
+ // postboxes setup
1848
+ postboxes.add_postbox_toggles('fv_flowplayer_settings');
1849
+
1850
+ jQuery('.fv_wp_flowplayer_activate_extension').click( function() { // todo: block multiple clicks
1851
+ var button = jQuery(this);
1852
+ button.siblings('img').eq(0).show();
1853
+
1854
+ jQuery.post( ajaxurl, { action: 'fv_wp_flowplayer_activate_extension', nonce: '83ea8ddd04', plugin: jQuery(this).attr("data-plugin") }, function( response ) {
1855
+ button.siblings('img').eq(0).hide();
1856
+
1857
+ var obj;
1858
+ try {
1859
+ response = response.replace( /[\s\S]*<FVFLOWPLAYER>/, '' );
1860
+ response = response.replace( /<\/FVFLOWPLAYER>[\s\S]*/, '' );
1861
+ obj = jQuery.parseJSON( response );
1862
+
1863
+ button.removeClass('fv_wp_flowplayer_activate_extension');
1864
+ button.attr('value',obj.message);
1865
+
1866
+ if( typeof(obj.error) == "undefined" ) {
1867
+ //window.location.hash = '#'+jQuery(button).attr("data-plugin");
1868
+ //window.location.reload(true);
1869
+ window.location.href = window.location.href;
1870
+ }
1871
+ } catch(e) { // todo: what if there is "<p>Plugin install failed.</p>"
1872
+ button.after('<p>Error parsing JSON</p>');
1873
+ return;
1874
+ }
1875
+
1876
+ } ).error(function() {
1877
+ button.siblings('img').eq(0).hide();
1878
+ button.after('<p>Error!</p>');
1879
+ });
1880
+ } );
1881
+
1882
+ jQuery('.fv-flowplayer-admin-addon-installed').click( function() {
1883
+ jQuery('html, body').animate({
1884
+ scrollTop: jQuery("#"+jQuery(this).attr("data-plugin") ).offset().top
1885
+ }, 1000);
1886
+ } );
1887
+
1888
+ jQuery('.show-more').click( function(e) {
1889
+ e.preventDefault();
1890
+
1891
+ var more = jQuery('.more', jQuery(this).parent() ).length ? jQuery('.more', jQuery(this).parent() ) : jQuery(this).parent().siblings('.more');
1892
+
1893
+ more.toggle();
1894
+
1895
+ if( jQuery(':visible', more ).length > 0 ) {
1896
+ jQuery(this).html('(hide)');
1897
+ } else {
1898
+ jQuery(this).html('(&hellip;)');
1899
+ }
1900
+ } );
1901
+
1902
+ /*
1903
+ * Coor Picker Default
1904
+ */
1905
+ jQuery('.playlistFontColor-show').click(function(e){
1906
+ e.preventDefault();
1907
+ jQuery(e.target).hide();
1908
+ jQuery('.playlistFontColor-hide').show();
1909
+
1910
+ jQuery('#playlistFontColor-proxy').show().val(jQuery('#playlistFontColor-proxy').data('previous'));
1911
+ jQuery('#playlistFontColor').val(jQuery('#playlistFontColor-proxy').data('previous'));
1912
+ });
1913
+
1914
+ jQuery('.playlistFontColor-hide').click(function(e){
1915
+ e.preventDefault();
1916
+ jQuery(e.target).hide();
1917
+ jQuery('.playlistFontColor-show').show();
1918
+
1919
+ jQuery('#playlistFontColor-proxy').data('previous',jQuery('#playlistFontColor-proxy').hide().val()).val('');
1920
+ jQuery('#playlistFontColor').val('');
1921
+ });
1922
+
1923
+ jQuery('#playlistFontColor-proxy').on('change',function(e){
1924
+ jQuery('#playlistFontColor').val(jQuery(e.target).val());
1925
+ });
1926
+ });
1927
+ //]]>
1928
+ </script>
1929
+
1930
+ <script>
1931
+ /* TABS */
1932
+ jQuery(document).ready(function(){
1933
+ jQuery('#fv_player_js_warning').hide();
1934
+
1935
+ var anchor = window.location.hash.substring(1);
1936
+ if( !anchor || !anchor.match(/tab_/) ) {
1937
+ anchor = 'postbox-container-tab_basic';
1938
+ }
1939
+
1940
+ jQuery('#fv_flowplayer_admin_tabs .nav-tab').removeClass('nav-tab-active');
1941
+ jQuery('[href=#'+anchor+']').addClass('nav-tab-active');
1942
+ jQuery('#dashboard-widgets .postbox-container').hide();
1943
+ jQuery('#' + anchor).show();
1944
+ });
1945
+ jQuery('#fv_flowplayer_admin_tabs a').on('click',function(e){
1946
+ e.preventDefault();
1947
+ window.location.hash = e.target.hash;
1948
+ var anchor = jQuery(this).attr('href').substring(1);
1949
+ jQuery('#fv_flowplayer_admin_tabs .nav-tab').removeClass('nav-tab-active');
1950
+ jQuery('[href=#'+anchor+']').addClass('nav-tab-active');
1951
+ jQuery('#dashboard-widgets .postbox-container').hide();
1952
+ jQuery('#' + anchor).show();
1953
+ });
1954
+
1955
+
1956
+ jQuery('a.fv-settings-anchor').on('click',function(e){
1957
+ var id = jQuery(this).attr('href');
1958
+ if( id.match(/^#./) ){
1959
+ var el = jQuery(id);
1960
+ if(el.length){
1961
+ var tab = el.parents('.postbox-container').attr('id');
1962
+ jQuery('#fv_flowplayer_admin_tabs').find('a[href=#'+tab+']').click()
1963
+ }
1964
+ }
1965
+ });
1966
+
1967
+
1968
+
1969
+
1970
+ </script>
test/integration/bootstrap.php ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Bootstrap the plugin unit testing environment.
4
+ *
5
+ * Edit 'active_plugins' setting below to point to your main plugin file.
6
+ *
7
+ * @package wordpress-plugin-tests
8
+ */
9
+
10
+ /**
11
+ * PLEASE NOTE - before this can be used, please checkout the latest WP TestSuite
12
+ * by using "svn checkout http://develop.svn.wordpress.org/trunk/ testSuite" and rename
13
+ * files "wp-config-sample.php" and "wp-tests-config-sample.php" by removing the "-sample"
14
+ * part from it. Then update those files to contain an EMPTY database and login information,
15
+ * as these tests will create a NEW WP INSTALLATION AND WIPE OUT EVERYTHING THERE IS IN THE DB.
16
+ *
17
+ * Also, please make sure to update the value of "WP_PHP_BINARY" constant to point to your PHP binary.
18
+ */
19
+
20
+ // let whoever is listening know we're in test mode
21
+ define('PHPUnitTestMode', true);
22
+
23
+ // Activates this plugin in WordPress so it can be tested.
24
+ $GLOBALS['wp_tests_options'] = array(
25
+ 'active_plugins' => array(
26
+ 'fv-wordpress-flowplayer/flowplayer.php',
27
+ ),
28
+ );
29
+
30
+ // If the develop repo location is defined (as WP_DEVELOP_DIR), use that
31
+ // location. Otherwise, we'll just assume that this plugin is installed in a
32
+ // WordPress develop SVN checkout.
33
+
34
+ if( false !== getenv( 'WP_DEVELOP_DIR' ) ) {
35
+ require getenv( 'WP_DEVELOP_DIR' ) . '/tests/phpunit/includes/bootstrap.php';
36
+ } else {
37
+ require '../testSuite/tests/phpunit/includes/bootstrap.php';
38
+ }
test/integration/frontend/shortcodesTest.php ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ require_once( dirname(__FILE__).'/../fv-player-unittest-case.php');
4
+
5
+ /**
6
+ * Tests WordPress integration of playlists without any advertisements present
7
+ * in the HTML markup.
8
+ */
9
+ final class FV_Player_ShortcodeTestCase extends FV_Player_UnitTestCase {
10
+
11
+ public function setUp() {
12
+ parent::setUp();
13
+
14
+ // create a post with playlist shortcode
15
+ $this->post_id_SimpleShortcode = $this->factory->post->create( array(
16
+ 'post_title' => 'Simple Shortcode',
17
+ 'post_content' => '[fvplayer src="https://cdn.site.com/video.mp4"]'
18
+ ) );
19
+
20
+ /*global $fv_fp;
21
+
22
+ include_once "../../../fv-wordpress-flowplayer/models/flowplayer.php";
23
+ include_once "../../../fv-wordpress-flowplayer/models/flowplayer-frontend.php";
24
+ $fv_fp = new flowplayer_frontend();
25
+
26
+ include_once "../../beta/fv-player-pro.class.php";
27
+ $this->fvPlayerProInstance = new FV_Player_Pro();*/
28
+ }
29
+
30
+ public function testSimpleShortcode() {
31
+ global $post;
32
+ $post = get_post( $this->post_id_SimpleShortcode );
33
+ $post->ID = 1234;
34
+
35
+ remove_action('wp_head', 'wp_generator');
36
+ remove_action( 'wp_head', 'print_emoji_detection_script', 7 );
37
+ remove_action( 'wp_print_styles', 'print_emoji_styles' );
38
+ add_filter( 'wp_resource_hints', '__return_empty_array' );
39
+
40
+ wp_deregister_script( 'wp-embed' );
41
+
42
+ ob_start();
43
+ wp_head();
44
+ echo apply_filters( 'the_content', $post->post_content );
45
+ wp_footer();
46
+ $output = ob_get_clean();
47
+
48
+ $this->assertEquals( $this->fix_newlines(file_get_contents(dirname(__FILE__).'/testSimpleShortcode.html')), $this->fix_newlines($output) );
49
+ }
50
+
51
+ }
test/integration/frontend/testSimpleShortcode.html ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <title>Test Blog</title>
2
+ <link rel='stylesheet' id='fv_flowplayer-css' href='http://example.org/wp-content/plugins/fv-wordpress-flowplayer/css/flowplayer.css' type='text/css' media='all' />
3
+ <link rel='https://api.w.org/' href='http://example.org/index.php?rest_route=/' />
4
+ <link rel="EditURI" type="application/rsd+xml" title="RSD" href="http://example.org/xmlrpc.php?rsd" />
5
+ <link rel="wlwmanifest" type="application/wlwmanifest+xml" href="http://example.org/wp-includes/wlwmanifest.xml" />
6
+ <style type="text/css">.recentcomments a{display:inline !important;padding:0 !important;margin:0 !important;}</style>
7
+ <style type="text/css">
8
+
9
+ .flowplayer { margin: 0 auto 28px auto; display: block; }
10
+ .flowplayer.fixed-controls { margin: 0 auto 58px auto; display: block; }
11
+ .flowplayer.has-abloop { margin-bottom: 52px; }
12
+ .flowplayer.fixed-controls.has-abloop { margin-bottom: 82px; }
13
+ .flowplayer.has-caption, flowplayer.has-caption * { margin: 0 auto; }
14
+ .flowplayer .fp-controls, .flowplayer .fv-ab-loop, .fv-player-buttons a:active, .fv-player-buttons a { color: #eeeeee !important; background-color: #333333 !important; }
15
+ .flowplayer { background-color: #000000 !important; }
16
+ .flowplayer .fp-duration, .flowplayer a.fp-play, .flowplayer a.fp-mute { color: #eeeeee !important; }
17
+ .flowplayer .fp-elapsed { color: #eeeeee !important; }
18
+ .flowplayer .fp-volumelevel { background-color: #bb0000 !important; }
19
+ .flowplayer .fp-volumeslider, .flowplayer .noUi-background { background-color: #eeeeee !important; }
20
+ .flowplayer .fp-timeline { background-color: #666666 !important; }
21
+ .flowplayer .fv-ab-loop .noUi-handle { color: #333333 !important; }
22
+ .flowplayer .fp-progress, .flowplayer .fv-ab-loop .noUi-connect, .fv-player-buttons a.current { background-color: #bb0000 !important; }
23
+ .flowplayer .fp-buffer, .flowplayer .fv-ab-loop .noUi-handle { background-color: #eeeeee !important; }
24
+ #content .flowplayer, .flowplayer { font-family: Tahoma, Geneva, sans-serif; }
25
+ .flowplayer .fp-dropdown li.active { background-color: #bb0000 !important }
26
+
27
+ .wpfp_custom_background { display: none; }
28
+ .wpfp_custom_popup { position: absolute; top: 10%; z-index: 20; text-align: center; width: 100%; color: #fff; }
29
+ .wpfp_custom_popup h1, .wpfp_custom_popup h2, .wpfp_custom_popup h3, .wpfp_custom_popup h4 { color: #fff; }
30
+ .is-finished .wpfp_custom_background { display: block; }
31
+ .fv_player_popup { background: #333333; padding: 1% 5%; width: 65%; margin: 0 auto; }
32
+
33
+ .wpfp_custom_ad { position: absolute; bottom: 10%; z-index: 20; width: 100%; }
34
+ .wpfp_custom_ad_content { background: white; margin: 0 auto; position: relative } .wpfp_custom_ad { color: #888; z-index: 20 !important; }
35
+ .wpfp_custom_ad a { color: #ff3333 }
36
+
37
+ .fv-wp-flowplayer-notice-small { color: #eeeeee !important; }
38
+
39
+ .fvfp_admin_error { color: #eeeeee; }
40
+ .fvfp_admin_error a { color: #eeeeee; }
41
+ #content .fvfp_admin_error a { color: #eeeeee; }
42
+ .fvfp_admin_error_content { background: #333333; opacity:0.75;filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=75); }
43
+
44
+ .fp-playlist-external > a > span { background-color:#808080; }
45
+ .fp-playlist-external > a.is-active > span { border-color:#bb0000; }
46
+ .fp-playlist-external.fv-playlist-design-2014 a.is-active,.fp-playlist-external.fv-playlist-design-2014 a.is-active h4,.fp-playlist-external.fp-playlist-only-captions a.is-active,.fp-playlist-external.fv-playlist-design-2014 a.is-active h4, .fp-playlist-external.fp-playlist-only-captions a.is-active h4 { color:#bb0000; }
47
+ .fp-playlist-vertical { background-color:#808080; }
48
+
49
+ .flowplayer .fp-subtitle span.fp-subtitle-line { font-size: 16px; } .flowplayer .fp-logo { bottom: 30px; left: 15px }
50
+ .flowplayer .fp-subtitle span.fp-subtitle-line { background-color: rgba(0,0,0,0.5); }
51
+
52
+ </style>
53
+ <div id="wpfp_a1bdb3435a9428cba781e51088d4960d" data-item="{&quot;sources&quot;:[{&quot;src&quot;:&quot;https:\/\/cdn.site.com\/video.mp4&quot;,&quot;type&quot;:&quot;video\/mp4&quot;}]}" class="flowplayer no-brand is-splash fvp-play-button" style="max-width: 640px; max-height: 360px; " data-ratio="0.5625">
54
+ <div class="fp-ratio" style="padding-top: 56.25%"></div>
55
+ <div class='fvp-share-bar'><ul class="fvp-sharing">
56
+ <li><a class="sharing-facebook" href="https://www.facebook.com/sharer/sharer.php?u=http%3A%2F%2Fexample.org%2F%3Fp%3D1234" target="_blank">Facebook</a></li>
57
+ <li><a class="sharing-twitter" href="https://twitter.com/home?status=Test+Blog+http%3A%2F%2Fexample.org%2F%3Fp%3D1234" target="_blank">Twitter</a></li>
58
+ <li><a class="sharing-google" href="https://plus.google.com/share?url=http%3A%2F%2Fexample.org%2F%3Fp%3D1234" target="_blank">Google+</a></li>
59
+ <li><a class="sharing-email" href="mailto:?body=Check%20out%20the%20amazing%20video%20here%3A%20http%3A%2F%2Fexample.org%2F%3Fp%3D1234" target="_blank">Email</a></li></ul><div><a class="sharing-link" href="http://example.org/?p=1234" target="_blank">Link</a></div><div><label><a class="embed-code-toggle" href="#"><strong>Embed</strong></a></label></div><div class="embed-code"><label>Copy and paste this HTML code into your webpage to embed.</label><textarea></textarea></div></div>
60
+ </div>
61
+
62
+ <script type='text/javascript' src='http://example.org/wp-includes/js/jquery/jquery.js?ver=1.12.4'></script>
63
+ <script type='text/javascript' src='http://example.org/wp-includes/js/jquery/jquery-migrate.js?ver=1.4.1'></script>
64
+ <script type='text/javascript'>
65
+ /* <![CDATA[ */
66
+ var fv_flowplayer_conf = {"fullscreen":"1","swf":"\/\/example.org\/wp-content\/plugins\/fv-wordpress-flowplayer\/flowplayer\/flowplayer.swf?ver=","swfHls":"\/\/example.org\/wp-content\/plugins\/fv-wordpress-flowplayer\/flowplayer\/flowplayerhls.swf?ver=","embed":{"library":"\/\/example.org\/wp-content\/plugins\/fv-wordpress-flowplayer\/flowplayer\/fv-flowplayer.min.js","script":"\/\/example.org\/wp-content\/plugins\/fv-wordpress-flowplayer\/flowplayer\/embed.min.js","skin":"\/\/example.org\/wp-content\/plugins\/fv-wordpress-flowplayer\/css\/flowplayer.css","swf":"\/\/example.org\/wp-content\/plugins\/fv-wordpress-flowplayer\/flowplayer\/flowplayer.swf?ver=","swfHls":"\/\/example.org\/wp-content\/plugins\/fv-wordpress-flowplayer\/flowplayer\/flowplayerhls.swf?ver="},"speeds":[0.25,0.5,0.75,1,1.25,1.5,1.75,2],"video_hash_links":"1","safety_resize":"1","volume":"0.7","mobile_native_fullscreen":"","mobile_force_fullscreen":"","sticky_video":"","sticky_place":"right-bottom","sticky_width":"380"};
67
+ var fv_flowplayer_translations = {"0":"","1":"Video loading aborted","2":"Network error","3":"Video not properly encoded","4":"Video file not found","5":"Unsupported video","6":"Skin not found","7":"SWF file not found","8":"Subtitles not found","9":"Invalid RTMP URL","10":"Unsupported video format. Try installing Adobe Flash.","11":"Click to watch the video","12":"[This post contains video, click to play]","video_expired":"<h2>Video file expired.<br \/>Please reload the page and play it again.<\/h2>","unsupported_format":"<h2>Unsupported video format.<br \/>Please use a Flash compatible device.<\/h2>","mobile_browser_detected_1":"Mobile browser detected, serving low bandwidth video.","mobile_browser_detected_2":"Click here","mobile_browser_detected_3":"for full quality.","live_stream_failed":"<h2>Live stream load failed.<\/h2><h3>Please try again later, perhaps the stream is currently offline.<\/h3>","live_stream_failed_2":"<h2>Live stream load failed.<\/h2><h3>Please try again later, perhaps the stream is currently offline.<\/h3>","what_is_wrong":"Please tell us what is wrong :","full_sentence":"Please give us more information (a full sentence) so we can help you better","error_JSON":"Admin: Error parsing JSON","no_support_IE9":"Admin: Video checker doesn't support IE 9.","check_failed":"Admin: Check failed.","playlist_current":"Now Playing","video_issues":"Video Issues","link_copied":"Video Link Copied to Clipboard","embed_copied":"Embed Code Copied to Clipboard","subtitles_disabled":"Subtitles disabled","subtitles_switched":"Subtitles switched to ","warning_iphone_subs":"This video has subtitles, that are not supported on your device.","warning_unstable_android":"You are using an old Android device. If you experience issues with the video please use <a href=\"https:\/\/play.google.com\/store\/apps\/details?id=org.mozilla.firefox\">Firefox<\/a>. <a target=\"_blank\" href=\"https:\/\/foliovision.com\/2017\/05\/issues-with-vimeo-on-android\">Why?<\/a>","warning_old_safari":"You are using an old Safari browser. If you experience issues with the video please use <a href=\"https:\/\/www.mozilla.org\/en-US\/firefox\/new\/\">Firefox<\/a> or other modern browser. <a target=\"_blank\" href=\"https:\/\/foliovision.com\/2017\/05\/issues-with-vimeo-on-android\">Why?<\/a>"};
68
+ var fv_fp_ajaxurl = "http:\/\/example.org\/wp-admin\/admin-ajax.php";
69
+ var fv_flowplayer_playlists = [];
70
+ /* ]]> */
71
+ </script>
72
+ <script type='text/javascript' src='http://example.org/wp-content/plugins/fv-wordpress-flowplayer/flowplayer/fv-flowplayer.min.js'></script>
test/integration/frontend/videoPositionSavingTest.php ADDED
@@ -0,0 +1,161 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ require_once( dirname(__FILE__).'/../fv-player-ajax-unittest-case.php');
4
+
5
+ /**
6
+ * Tests WordPress integration of playlists without any advertisements present
7
+ * in the HTML markup.
8
+ */
9
+ final class FV_Player_videoPositionSavingTestCase extends FV_Player_Ajax_UnitTestCase {
10
+
11
+ var $postID = -1;
12
+ var $userID = -1;
13
+
14
+ protected $backupGlobals = false;
15
+
16
+ public function setUp() {
17
+ parent::setUp();
18
+
19
+ // create a post with playlist shortcode
20
+ $this->postID = $this->factory->post->create( array(
21
+ 'post_title' => 'Playlist with Ads',
22
+ 'post_content' => '[fvplayer src="https://cdn.site.com/1.mp4" playlist="https://cdn.site.com/2.mp4;https://cdn.site.com/3.mp4"]'
23
+ ) );
24
+
25
+ global $fv_fp;
26
+
27
+ include_once "../../../fv-wordpress-flowplayer/models/flowplayer.php";
28
+ include_once "../../../fv-wordpress-flowplayer/models/flowplayer-frontend.php";
29
+ $fv_fp = new flowplayer_frontend();
30
+
31
+ // add new user and create last saved position metadata for this new user
32
+ $this->userID = $this->factory->user->create(array(
33
+ 'role' => 'admin'
34
+ ));
35
+
36
+ /*add_user_meta($this->userID, 'fv_wp_flowplayer_position_watch?v=1XiHhpGUmQg', '12');
37
+ var_export(get_user_meta($this->userID, 'fv_wp_flowplayer_position_watch?v=1XiHhpGUmQg', true ));*/
38
+
39
+ }
40
+
41
+ public function testNoSaveForNotLoggedInUsers() {
42
+ // is anybody listening out there?
43
+ $this->assertTrue( has_action('wp_ajax_fv_wp_flowplayer_video_position_save') );
44
+
45
+ // Spoof the nonce in the POST superglobal
46
+ //$_POST['_wpnonce'] = wp_create_nonce( 'anything-here-if-needed' );
47
+
48
+ // set up POST data for video resume times
49
+ $_POST['action'] = 'fv_wp_flowplayer_video_position_save';
50
+ $_POST['videoTimes'] = array(
51
+ array(
52
+ 'name' => 'https://cdn.site.com/2.mp4',
53
+ 'position' => 12
54
+ )
55
+ );
56
+
57
+ // call the AJAX which
58
+ try {
59
+ $this->_handleAjax( 'fv_wp_flowplayer_video_position_save' );
60
+ } catch ( WPAjaxDieContinueException $e ) {
61
+ $response = json_decode( $this->_last_response );
62
+ $this->assertInternalType( 'object', $response );
63
+ $this->assertObjectHasAttribute( 'success', $response );
64
+ $this->assertFalse( $response->success );
65
+ }
66
+
67
+ // check for clear playlist HTML without last player position data items
68
+ $post = get_post( $this->postID );
69
+ $output = apply_filters( 'the_content', $post->post_content );
70
+
71
+ $expect = "<div id=\"some-test-hash\" class=\"flowplayer no-brand is-splash fvp-play-button\" style=\"\" data-ratio=\"0.5625\">
72
+ <div class=\"fp-ratio\" style=\"padding-top: 56.25%\"></div>
73
+ <div class='fvp-share-bar'><ul class=\"fvp-sharing\">
74
+ <li><a class=\"sharing-facebook\" href=\"https://www.facebook.com/sharer/sharer.php?u=\" target=\"_blank\">Facebook</a></li>
75
+ <li><a class=\"sharing-twitter\" href=\"https://twitter.com/home?status=Test+Blog+\" target=\"_blank\">Twitter</a></li>
76
+ <li><a class=\"sharing-google\" href=\"https://plus.google.com/share?url=\" target=\"_blank\">Google+</a></li>
77
+ <li><a class=\"sharing-email\" href=\"mailto:?body=Check%20out%20the%20amazing%20video%20here%3A%20\" target=\"_blank\">Email</a></li></ul><div><label><a class=\"embed-code-toggle\" href=\"#\"><strong>Embed</strong></a></label></div><div class=\"embed-code\"><label>Copy and paste this HTML code into your webpage to embed.</label><textarea></textarea></div></div>
78
+ </div>
79
+ <div class=\"fp-playlist-external fv-playlist-design-2017 fp-playlist-horizontal\" rel=\"some-test-hash\">
80
+ <a href='#' onclick='return false' data-item='{\"sources\":[{\"src\":\"https:\/\/cdn.site.com\/1.mp4\",\"type\":\"video\/mp4\"}]}'><div></div></a>
81
+ <a href='#' onclick='return false' data-item='{\"sources\":[{\"src\":\"https:\/\/cdn.site.com\/2.mp4\",\"type\":\"video\/mp4\"}]}'><div></div></a>
82
+ <a href='#' onclick='return false' data-item='{\"sources\":[{\"src\":\"https:\/\/cdn.site.com\/3.mp4\",\"type\":\"video\/mp4\"}]}'><div></div></a>
83
+ </div>
84
+
85
+ ";
86
+
87
+ // replace the player's ID by a preset one, so we can actually test the output
88
+ $regex = '/(id|rel)="wpfp_[^"]+"/';
89
+ $substitution = '$1="some-test-hash"';
90
+ $output = preg_replace($regex, $substitution, $output);
91
+
92
+ // test the HTML
93
+ $this->assertEquals($expect, $output);
94
+ }
95
+
96
+ public function testSaveAndPlaylistHTMLForLoggedInUsers() {
97
+ // is anybody listening out there?
98
+ $this->assertTrue( has_action('wp_ajax_fv_wp_flowplayer_video_position_save') );
99
+
100
+ // Spoof the nonce in the POST superglobal
101
+ //$_POST['_wpnonce'] = wp_create_nonce( 'anything-here-if-needed' );
102
+
103
+ // set this user as the active one
104
+ global $current_user;
105
+ $restore_user = $current_user;
106
+ wp_set_current_user($this->userID);
107
+
108
+ // set up POST data for video resume times
109
+ $_POST['action'] = 'fv_wp_flowplayer_video_position_save';
110
+ $_POST['videoTimes'] = array(
111
+ array(
112
+ 'name' => 'https://cdn.site.com/2.mp4',
113
+ 'position' => 12
114
+ )
115
+ );
116
+
117
+ // call the AJAX which
118
+ try {
119
+ $this->_handleAjax( 'fv_wp_flowplayer_video_position_save' );
120
+ } catch ( WPAjaxDieContinueException $e ) {
121
+ $response = json_decode( $this->_last_response );
122
+ $this->assertInternalType( 'object', $response );
123
+ $this->assertObjectHasAttribute( 'success', $response );
124
+ $this->assertTrue( $response->success );
125
+ }
126
+
127
+ // check if metadata was saved correctly
128
+ $this->assertEquals(12, get_user_meta($this->userID, 'fv_wp_flowplayer_position_2', true ));
129
+
130
+ // check that the playlist HTML is being generated correctly, with the last player position taken into consideration
131
+ $post = get_post( $this->postID );
132
+ $output = apply_filters( 'the_content', $post->post_content );
133
+
134
+ $expect = "<div id=\"some-test-hash\" class=\"flowplayer no-brand is-splash fvp-play-button\" style=\"\" data-ratio=\"0.5625\">
135
+ <div class=\"fp-ratio\" style=\"padding-top: 56.25%\"></div>
136
+ <div class='fvp-share-bar'><ul class=\"fvp-sharing\">
137
+ <li><a class=\"sharing-facebook\" href=\"https://www.facebook.com/sharer/sharer.php?u=\" target=\"_blank\">Facebook</a></li>
138
+ <li><a class=\"sharing-twitter\" href=\"https://twitter.com/home?status=Test+Blog+\" target=\"_blank\">Twitter</a></li>
139
+ <li><a class=\"sharing-google\" href=\"https://plus.google.com/share?url=\" target=\"_blank\">Google+</a></li>
140
+ <li><a class=\"sharing-email\" href=\"mailto:?body=Check%20out%20the%20amazing%20video%20here%3A%20\" target=\"_blank\">Email</a></li></ul><div><label><a class=\"embed-code-toggle\" href=\"#\"><strong>Embed</strong></a></label></div><div class=\"embed-code\"><label>Copy and paste this HTML code into your webpage to embed.</label><textarea></textarea></div></div>
141
+ </div>
142
+ <div class=\"fp-playlist-external fv-playlist-design-2017 fp-playlist-horizontal\" rel=\"some-test-hash\">
143
+ <a href='#' onclick='return false' data-item='{\"sources\":[{\"src\":\"https:\/\/cdn.site.com\/1.mp4\",\"type\":\"video\/mp4\"}]}'><div></div></a>
144
+ <a href='#' onclick='return false' data-item='{\"sources\":[{\"src\":\"https:\/\/cdn.site.com\/2.mp4\",\"type\":\"video\/mp4\",\"position\":\"12\"}]}'><div></div></a>
145
+ <a href='#' onclick='return false' data-item='{\"sources\":[{\"src\":\"https:\/\/cdn.site.com\/3.mp4\",\"type\":\"video\/mp4\"}]}'><div></div></a>
146
+ </div>
147
+
148
+ ";
149
+
150
+ // replace the player's ID by a preset one, so we can actually test the output
151
+ $regex = '/(id|rel)="wpfp_[^"]+"/';
152
+ $substitution = '$1="some-test-hash"';
153
+ $output = preg_replace($regex, $substitution, $output);
154
+
155
+ // test the HTML
156
+ $this->assertEquals($expect, $output);
157
+
158
+ $current_user;
159
+ }
160
+
161
+ }
test/integration/fv-player-ajax-unittest-case.php ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ abstract class FV_Player_Ajax_UnitTestCase extends WP_Ajax_UnitTestCase {
4
+
5
+ protected $backupGlobals = false;
6
+
7
+ public function setUp() {
8
+ parent::setUp();
9
+
10
+ global $fv_fp;
11
+ $this->restore = $fv_fp->conf;
12
+ }
13
+
14
+ public function fix_newlines( $html ) {
15
+ $html = preg_replace( '/(id|rel)="wpfp_[^"]+"/', '$1="some-test-hash"', $html);
16
+ $html = preg_replace( '~<input type="hidden" id="([^"]*?)nonce" name="([^"]*?)nonce" value="([^"]*?)" />~', '<input type="hidden" id="$1nonce" name="$2nonce" value="XYZ" />', $html);
17
+ $html = preg_replace( "~nonce: '([^']*?)'~", "nonce: 'XYZ'", $html);
18
+
19
+ // testProfileScreen
20
+ $html = preg_replace( '~fv_ytplayer_[a-z0-9]+~', 'fv_ytplayer_XYZ', $html);
21
+ $html = preg_replace( '~fv_vimeo_[a-z0-9]+~', 'fv_vimeo_XYZ', $html);
22
+ $html = preg_replace( '~<input type="hidden" id="fv-player-custom-videos-_fv_player_user_video-0" name="fv-player-custom-videos-_fv_player_user_video-0" value="[^"]*?" />~', '<input type="hidden" id="fv-player-custom-videos-_fv_player_user_video-0" name="fv-player-custom-videos-_fv_player_user_video-0" value="XYZ" />', $html);
23
+
24
+ $html = explode("\n",$html);
25
+ $html = implode( "\n", array_map('trim',$html) );
26
+ return $html;
27
+ }
28
+
29
+ // we need to set up PRO player with an appropriate key, or the PRO player won't work
30
+ public static function wpSetUpBeforeClass() {
31
+ global $fv_fp;
32
+
33
+ // without this included, fv_wp_flowplayer_delete_extensions_transients() would not be found
34
+ //include_once "../../../fv-wordpress-flowplayer/controller/backend.php";
35
+
36
+ // include the flowplayer loader
37
+ include_once "../../../fv-wordpress-flowplayer/flowplayer.php";
38
+
39
+ // include the PRO plugin class, so it can intercept data saving
40
+ // and update the ads structure as needed for saving
41
+ //include_once "../../beta/fv-player-pro.class.php";
42
+
43
+ // save initial settings
44
+ //$fv_fp->_set_conf();
45
+ }
46
+
47
+ public function tearDown() {
48
+ parent::tearDown();
49
+
50
+ global $fv_fp;
51
+ $fv_fp->conf = $this->restore;
52
+ }
53
+
54
+ }
test/integration/fv-player-unittest-case.php ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ abstract class FV_Player_UnitTestCase extends WP_UnitTestCase {
4
+
5
+ protected $backupGlobals = false;
6
+
7
+ public function setUp() {
8
+ parent::setUp();
9
+
10
+ global $fv_fp;
11
+ $this->restore = $fv_fp->conf;
12
+ }
13
+
14
+ public function fix_newlines( $html ) {
15
+ $html = preg_replace( '/(id|rel)="wpfp_[^"]+"/', '$1="some-test-hash"', $html);
16
+ $html = preg_replace( '~<input type="hidden" id="([^"]*?)nonce" name="([^"]*?)nonce" value="([^"]*?)" />~', '<input type="hidden" id="$1nonce" name="$2nonce" value="XYZ" />', $html);
17
+ $html = preg_replace( "~nonce: '([^']*?)'~", "nonce: 'XYZ'", $html);
18
+
19
+ // testProfileScreen
20
+ $html = preg_replace( '~fv_ytplayer_[a-z0-9]+~', 'fv_ytplayer_XYZ', $html);
21
+ $html = preg_replace( '~fv_vimeo_[a-z0-9]+~', 'fv_vimeo_XYZ', $html);
22
+ $html = preg_replace( '~<input type="hidden" id="fv-player-custom-videos-_fv_player_user_video-0" name="fv-player-custom-videos-_fv_player_user_video-0" value="[^"]*?" />~', '<input type="hidden" id="fv-player-custom-videos-_fv_player_user_video-0" name="fv-player-custom-videos-_fv_player_user_video-0" value="XYZ" />', $html);
23
+
24
+ $html = preg_replace( '~convert_jwplayer=[a-z0-9]+~', 'convert_jwplayer=XYZ', $html);
25
+ $html = preg_replace( '~_wpnonce=[a-z0-9]+~', '_wpnonce=XYZ', $html);
26
+
27
+ $html = explode("\n",$html);
28
+ $html = implode( "\n", array_map('trim',$html) );
29
+ return $html;
30
+ }
31
+
32
+ // we need to set up PRO player with an appropriate key, or the PRO player won't work
33
+ public static function wpSetUpBeforeClass() {
34
+ global $fv_fp;
35
+
36
+ // without this included, fv_wp_flowplayer_delete_extensions_transients() would not be found
37
+ //include_once "../../../fv-wordpress-flowplayer/controller/backend.php";
38
+
39
+ // include the flowplayer loader
40
+ include_once "../../../fv-wordpress-flowplayer/flowplayer.php";
41
+
42
+ // include the PRO plugin class, so it can intercept data saving
43
+ // and update the ads structure as needed for saving
44
+ //include_once "../../beta/fv-player-pro.class.php";
45
+
46
+ // save initial settings
47
+ //$fv_fp->_set_conf();
48
+ }
49
+
50
+ public function tearDown() {
51
+ parent::tearDown();
52
+
53
+ global $fv_fp;
54
+ $fv_fp->conf = $this->restore;
55
+ }
56
+
57
+ }
test/integration/phpunit.xml ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ <phpunit bootstrap="bootstrap.php">
2
+ <testsuites>
3
+ <testsuite name="FVPlayer">
4
+ <directory suffix="Test.php">frontend</directory>
5
+ <directory suffix="Test.php">backend</directory>
6
+ </testsuite>
7
+ </testsuites>
8
+ </phpunit>
test/unit/bootstrap.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <?php
2
+ include_once('../../vendor/autoload.php');
3
+ include_once "../wp-global-empty-mocks.php";
test/unit/controller/frontendTest.php ADDED
@@ -0,0 +1,197 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ use PHPUnit\Framework\TestCase;
3
+
4
+ final class FV_Player_Controller extends PHPUnit_Framework_TestCase {
5
+
6
+ private $fvPlayerProInstance;
7
+
8
+ // playlist items
9
+ private $playlist_items = array(
10
+ 0 =>
11
+ array (
12
+ 'sources' =>
13
+ array (
14
+ 0 =>
15
+ array (
16
+ 'src' => 'https://youtu.be/7uY0Ab5HlZ0',
17
+ 'type' => 'video/youtube'
18
+ )
19
+ )
20
+ ),
21
+ 1 =>
22
+ array (
23
+ 'sources' =>
24
+ array (
25
+ 0 =>
26
+ array (
27
+ 'src' => 'https://www.youtube.com/watch?v=1XiHhpGUmQg',
28
+ 'type' => 'video/youtube'
29
+ )
30
+ )
31
+ ),
32
+ 2 =>
33
+ array (
34
+ 'sources' =>
35
+ array (
36
+ 0 =>
37
+ array (
38
+ 'src' => 'https://www.youtube.com/watch?v=Q1eR8pUM5iY',
39
+ 'type' => 'video/youtube'
40
+ )
41
+ )
42
+ )
43
+ );
44
+
45
+ // ads
46
+ private $adsMock = array(
47
+ array(
48
+ 'videos' => array(
49
+ 'mp4' => 'https://www.youtube.com/watch?v=tPEE9ZwTmy0'
50
+ ),
51
+ 'disabled' => '0',
52
+ 'name' => 'cat preroll',
53
+ 'click' => 'http://www.pobox.sk'
54
+ ),
55
+ array(
56
+ 'videos' => array(
57
+ 'mp4' => 'https://www.youtube.com/watch?v=bCGmUCDj4Nc'
58
+ ),
59
+ 'disabled' => '1',
60
+ 'name' => 'kids postroll',
61
+ 'click' => 'http://www.foliovision.com'
62
+ ),
63
+ array(
64
+ 'videos' => array(
65
+ 'mp4' => 'https://www.youtube.com/watch?v=OsAVRDo9znQ'
66
+ ),
67
+ 'disabled' => '0',
68
+ 'name' => 'funny whatroll',
69
+ 'click' => 'http://www.google.com'
70
+ )
71
+ );
72
+
73
+ public function setUp() {
74
+ // set an empty global return value to be used
75
+ // in all the mocked global WordPress functions
76
+ // like add_action() and the such
77
+ global $testReturnValue;
78
+ $testReturnValue = '';
79
+
80
+ include_once "../../models/flowplayer.php";
81
+ global $fv_fp;
82
+ $fv_fp = new flowplayer();
83
+
84
+ // todo: fix in core perhaps
85
+ $fv_fp->aAds = array();
86
+ $fv_fp->aPopups = array();
87
+
88
+ include_once "../../controller/frontend.php";
89
+ }
90
+
91
+ public function tearDown() {
92
+ Mockery::close();
93
+ }
94
+
95
+ public function test_flowplayer_prepare_scripts_js_everywhere() {
96
+ global $fv_fp;
97
+ $fv_fp->conf['js-everywhere'] = true;
98
+
99
+ ob_start();
100
+ flowplayer_prepare_scripts();
101
+ $output = ob_get_clean();
102
+
103
+ $expected = "Registering jquery-ui-tabs for ?ver=1.2.3.4 footer? 1
104
+ Registering fv_flowplayer for fv-wordpress-flowplayer/css/flowplayer.css?ver=1.2.3.4
105
+ Registering flowplayer for fv-wordpress-flowplayer/flowplayer/fv-flowplayer.min.js?ver=1.2.3.4 footer? 1
106
+ Localizing flowplayer with fv_flowplayer_conf = Array
107
+ (
108
+ [fullscreen] => 1
109
+ [swf] => fv-wordpress-flowplayer/flowplayer/flowplayer.swf?ver=1.2.3.4
110
+ [swfHls] => fv-wordpress-flowplayer/flowplayer/flowplayerhls.swf?ver=1.2.3.4
111
+ [embed] => Array
112
+ (
113
+ [library] => fv-wordpress-flowplayer/flowplayer/fv-flowplayer.min.js
114
+ [script] => fv-wordpress-flowplayer/flowplayer/embed.min.js
115
+ [skin] => fv-wordpress-flowplayer/css/flowplayer.css
116
+ [swf] => fv-wordpress-flowplayer/flowplayer/flowplayer.swf?ver=1.2.3.4
117
+ [swfHls] => fv-wordpress-flowplayer/flowplayer/flowplayerhls.swf?ver=1.2.3.4
118
+ )
119
+
120
+ [speeds] => Array
121
+ (
122
+ [0] => 0.25
123
+ [1] => 0.5
124
+ [2] => 0.75
125
+ [3] => 1
126
+ [4] => 1.25
127
+ [5] => 1.5
128
+ [6] => 1.75
129
+ [7] => 2
130
+ )
131
+
132
+ [video_hash_links] => 1
133
+ [safety_resize] => 1
134
+ [volume] => 0.7
135
+ [mobile_native_fullscreen] =>
136
+ [mobile_force_fullscreen] =>
137
+ [sticky_video] =>
138
+ [sticky_place] => right-bottom
139
+ [sticky_width] => 380
140
+ )
141
+
142
+ Localizing flowplayer with fv_flowplayer_translations = Array
143
+ (
144
+ [0] =>
145
+ [1] => Video loading aborted
146
+ [2] => Network error
147
+ [3] => Video not properly encoded
148
+ [4] => Video file not found
149
+ [5] => Unsupported video
150
+ [6] => Skin not found
151
+ [7] => SWF file not found
152
+ [8] => Subtitles not found
153
+ [9] => Invalid RTMP URL
154
+ [10] => Unsupported video format. Try installing Adobe Flash.
155
+ [11] => Click to watch the video
156
+ [12] => [This post contains video, click to play]
157
+ [video_expired] => <h2>Video file expired.<br />Please reload the page and play it again.</h2>
158
+ [unsupported_format] => <h2>Unsupported video format.<br />Please use a Flash compatible device.</h2>
159
+ [mobile_browser_detected_1] => Mobile browser detected, serving low bandwidth video.
160
+ [mobile_browser_detected_2] => Click here
161
+ [mobile_browser_detected_3] => for full quality.
162
+ [live_stream_failed] => <h2>Live stream load failed.</h2><h3>Please try again later, perhaps the stream is currently offline.</h3>
163
+ [live_stream_failed_2] => <h2>Live stream load failed.</h2><h3>Please try again later, perhaps the stream is currently offline.</h3>
164
+ [what_is_wrong] => Please tell us what is wrong :
165
+ [full_sentence] => Please give us more information (a full sentence) so we can help you better
166
+ [error_JSON] => Admin: Error parsing JSON
167
+ [no_support_IE9] => Admin: Video checker doesn't support IE 9.
168
+ [check_failed] => Admin: Check failed.
169
+ [playlist_current] => Now Playing
170
+ [video_issues] => Video Issues
171
+ [link_copied] => Video Link Copied to Clipboard
172
+ [embed_copied] => Embed Code Copied to Clipboard
173
+ [subtitles_disabled] => Subtitles disabled
174
+ [subtitles_switched] => Subtitles switched to
175
+ [warning_iphone_subs] => This video has subtitles, that are not supported on your device.
176
+ [warning_unstable_android] => You are using an old Android device. If you experience issues with the video please use <a href=\"https://play.google.com/store/apps/details?id=org.mozilla.firefox\">Firefox</a>. <a target=\"_blank\" href=\"https://foliovision.com/2017/05/issues-with-vimeo-on-android\">Why?</a>
177
+ [warning_old_safari] => You are using an old Safari browser. If you experience issues with the video please use <a href=\"https://www.mozilla.org/en-US/firefox/new/\">Firefox</a> or other modern browser. <a target=\"_blank\" href=\"https://foliovision.com/2017/05/issues-with-vimeo-on-android\">Why?</a>
178
+ )
179
+
180
+ Localizing flowplayer with fv_fp_ajaxurl = https://site.com/wp//wp-admin/admin-ajax.php
181
+ Localizing flowplayer with fv_flowplayer_playlists = Array
182
+ (
183
+ )
184
+
185
+ ";
186
+
187
+ /*$aOut = explode( "\n", preg_replace( '~\r\n~', "\n", $output) );
188
+ $aExpected = explode( "\n", preg_replace( '~\r\n~', "\n", $expected ) );
189
+
190
+ foreach( $aOut AS $k => $v ) {
191
+ $this->assertEquals( $v, $aExpected[$k] );
192
+ }*/
193
+
194
+ $this->assertEquals( preg_replace( '~\r\n~', "\n", $output), preg_replace( '~\r\n~', "\n", $expected ) );
195
+ }
196
+
197
+ }
test/unit/phpunit.xml ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <phpunit bootstrap="bootstrap.php">
2
+ <testsuites>
3
+ <testsuite name="controller">
4
+ <directory suffix="Test.php">controller</directory>
5
+ </testsuite>
6
+ </testsuites>
7
+ </phpunit>
test/wp-global-empty-mocks.php ADDED
@@ -0,0 +1,225 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // let whoever is listening know we're in test mode
4
+ define('PHPUnitTestMode', true);
5
+
6
+ // whatever classes we define and mock here, we'll make a list
7
+ // of these programmatically, so as nobody will forget to add
8
+ // new classed to the list of mocked ones if it was hard-coded here
9
+ function file_get_php_classes($filepath) {
10
+ $php_code = file_get_contents($filepath);
11
+ $classes = get_php_classes($php_code);
12
+ return $classes;
13
+ }
14
+
15
+ // complementary function to the one above
16
+ function get_php_classes($php_code) {
17
+ $classes = array();
18
+ $tokens = token_get_all($php_code);
19
+ $count = count($tokens);
20
+ for ($i = 2; $i < $count; $i++) {
21
+ if ( $tokens[$i - 2][0] == T_CLASS
22
+ && $tokens[$i - 1][0] == T_WHITESPACE
23
+ && $tokens[$i][0] == T_STRING) {
24
+
25
+ $class_name = $tokens[$i][1];
26
+ $classes[] = $class_name;
27
+ }
28
+ }
29
+ return $classes;
30
+ }
31
+
32
+ global $mocked_classes;
33
+ $mocked_classes = file_get_php_classes(__FILE__);
34
+
35
+ function get_calling_class() {
36
+ global $mocked_classes;
37
+
38
+ //get the trace
39
+ $trace = debug_backtrace();
40
+
41
+ // Get the class that is asking for who awoke it
42
+ // note: edited to say "$trace[3]" instead of "$trace[1]",
43
+ // since we're additionally going through
44
+ // get_calling_class() function as well as
45
+ // the checkAndReturnRequestedValue() function
46
+ // all the way to the actually mocked global function (add_action())
47
+ // note2: if we're coming from a class name in this mock file, we should handle that as well
48
+
49
+ // we're calling a method of a class in this mock file, handle it as such
50
+ if (isset($trace[2]['class']) && in_array($trace[2]['class'], $mocked_classes)) {
51
+ $class = $trace[4]['class'];
52
+ } else if (isset($trace[3]['class'])){
53
+ $class = $trace[3]['class'];
54
+ } else {
55
+ $class = false;
56
+ }
57
+
58
+ // +1 to i cos we have to account for calling this function
59
+ for ( $i=1; $i<count( $trace ); $i++ ) {
60
+ if ( isset( $trace[$i] ) ) { // is it set?
61
+ if ( isset( $trace[ $i ]['class'] ) && $class != $trace[ $i ]['class'] ) { // is it a different class
62
+ return $trace[ $i ]['class'];
63
+ }
64
+ }
65
+ }
66
+ }
67
+
68
+ function get_calling_mocked_global_function() {
69
+ global $mocked_classes;
70
+
71
+ $trace = debug_backtrace();
72
+ // we're calling a method of a class in this mock file, handle it as such
73
+ if (isset($trace[2]['class']) && in_array($trace[2]['class'], $mocked_classes)) {
74
+ return $trace[2]['class'].'::'.$trace[2]['function'];
75
+ } else {
76
+ return $trace[2]['function'];
77
+ }
78
+ }
79
+
80
+ function checkAndReturnRequestedValue() {
81
+ global $mocked_classes;
82
+ $cclass = get_calling_class();
83
+
84
+ // no need to do anything special for non-tested classes,
85
+ // just return nothing for them
86
+ // note: we still want to check for return values for methods
87
+ // called from mocked classes located in this file
88
+ if (substr($cclass, -4) !== 'Test' && !in_array($cclass, $mocked_classes)) {
89
+ return;
90
+ }
91
+
92
+ global $testReturnValue;
93
+
94
+ // if $testReturnValue is an array, check if we have a return value
95
+ // at the index of the calling class's function
96
+ if (is_array($testReturnValue)) {
97
+ $calling_function = get_calling_mocked_global_function();
98
+ if (isset($testReturnValue[$calling_function])) {
99
+ $retValue = $testReturnValue[$calling_function];
100
+ } else {
101
+ $retValue = '';
102
+ }
103
+ } else {
104
+ $retValue = $testReturnValue;
105
+ }
106
+
107
+ return $retValue;
108
+ }
109
+
110
+ function add_action() {
111
+ return checkAndReturnRequestedValue();
112
+ }
113
+
114
+ function add_filter() {
115
+ return checkAndReturnRequestedValue();
116
+ }
117
+
118
+ function apply_filters( $hook, $value ) {
119
+ return $value;
120
+ }
121
+
122
+ function current_user_can( $capability ) {
123
+ return false;
124
+ }
125
+
126
+ function get_option() {
127
+ return checkAndReturnRequestedValue();
128
+ }
129
+
130
+ function home_url( $url = false ) {
131
+ return 'https://site.com/'.$url;
132
+ }
133
+
134
+ function is_multisite() {
135
+ return false;
136
+ }
137
+
138
+ function is_user_logged_in() {
139
+ return false;
140
+ }
141
+
142
+ function sanitize_title( $title ) {
143
+ return preg_replace( '~[^a-z0-9_-]~', '-', $title );
144
+ }
145
+
146
+ function site_url( $url = false ) {
147
+ return 'https://site.com/wp/'.$url;
148
+ }
149
+
150
+ function wp_enqueue_script( $handle, $src = '', $deps = array(), $ver = false, $in_footer ) {
151
+ echo "Registering $handle for $src?ver=$ver footer? $in_footer\n";
152
+ }
153
+
154
+ function wp_enqueue_style( $handle, $src = '', $deps = array(), $ver = false, $media = 'all' ) {
155
+ echo "Registering $handle for $src?ver=$ver\n";
156
+ }
157
+
158
+ function wp_localize_script( $handle, $name, $data ) {
159
+ echo "Localizing $handle with $name = ".print_r($data,true)."\n";
160
+ }
161
+
162
+ function wp_remote_get() {
163
+ return checkAndReturnRequestedValue();
164
+ }
165
+
166
+ function is_wp_error() {
167
+ return checkAndReturnRequestedValue();
168
+ }
169
+
170
+ function add_shortcode() {
171
+ return checkAndReturnRequestedValue();
172
+ }
173
+
174
+ function is_admin() {
175
+ return checkAndReturnRequestedValue();
176
+ }
177
+
178
+ function plugins_url( $value, $file = false ) {
179
+ return $value;
180
+ }
181
+
182
+ function update_option() {
183
+ return checkAndReturnRequestedValue();
184
+ }
185
+
186
+ function wp_parse_args() {
187
+ return checkAndReturnRequestedValue();
188
+ }
189
+
190
+ function __($txt) {
191
+ // always return what was given for the translation function
192
+ return $txt;
193
+ }
194
+
195
+ function _e($txt) {
196
+ // always echo what was given for the translation function
197
+ echo $txt;
198
+ }
199
+
200
+ function esc_attr($value) {
201
+ // always return what was given for the attribute escaping function
202
+ return $value;
203
+ }
204
+
205
+ // mocks for the WPDB WordPress database manipulation class
206
+ class wpdb {
207
+
208
+ public $prefix = '';
209
+
210
+ public function get_charset_collate() {
211
+ return checkAndReturnRequestedValue();
212
+ }
213
+
214
+ public function query() {
215
+ return checkAndReturnRequestedValue();
216
+ }
217
+ }
218
+
219
+ global $wpdb;
220
+ $wpdb = new wpdb();
221
+
222
+ global $fv_wp_flowplayer_ver;
223
+ $fv_wp_flowplayer_ver = '1.2.3.4';
224
+
225
+ define( 'WP_CONTENT_URL', 'https://site.com/wp-content' );
view/admin.php CHANGED
@@ -596,7 +596,10 @@ function fv_flowplayer_admin_integrations() {
596
  $htmlQueue .= "<a href='".get_edit_post_link($k)."'>$k</a> ";
597
  }
598
  $htmlQueue .= ") <a href='".site_url()."/wp-admin/options-general.php?page=fvplayer&fv_flowplayer_checker'>Scan now!</a></span>";
 
 
599
  }
 
600
  if( $iCount && $iQueue ) {
601
  printf(__('Currently %d videos in database and %s posts in queue.', 'fv-wordpress-flowplayer'), $iCount, $htmlQueue);
602
  } else if( $iCount ) {
@@ -1020,7 +1023,7 @@ function fv_flowplayer_admin_skin() {
1020
  'autoplay' => false,
1021
  'preroll' => 'no',
1022
  'postroll' => 'no',
1023
- 'subtitles' => plugins_url('images/test-subtitles.vtt',dirname(__FILE__)),
1024
  'caption' => "Foliovision Video;Lapinthrope Extras - Roy Thompson Hall Dance;Romeo and Juliet Ballet Schloss Kittsee",
1025
  'playlist' => 'https://player.vimeo.com/external/224781088.sd.mp4?s=face4dbb990b462826c8e1e43a9c66c6a9bb5585&profile_id=165&oauth2_token_id=3501005,https://i.vimeocdn.com/video/643908843_295x166.jpg;https://player.vimeo.com/external/45864857.hd.mp4?s=94fddee594da3258c9e10355f5bad8173c4aee7b&profile_id=113&oauth2_token_id=3501005,https://i.vimeocdn.com/video/319116053_295x166.jpg',
1026
  'liststyle' => 'horizontal'
@@ -1489,7 +1492,8 @@ add_meta_box( 'fv_flowplayer_usage', __('Usage', 'fv-wordpress-flowplayer'), 'fv
1489
  wp_nonce_field( 'closedpostboxes', 'closedpostboxesnonce', false );
1490
  wp_nonce_field( 'meta-box-order-nonce', 'meta-box-order-nonce', false );
1491
  ?>
1492
- </div>
 
1493
  <?php endforeach;?>
1494
  <div style="clear: both"></div>
1495
  </div>
596
  $htmlQueue .= "<a href='".get_edit_post_link($k)."'>$k</a> ";
597
  }
598
  $htmlQueue .= ") <a href='".site_url()."/wp-admin/options-general.php?page=fvplayer&fv_flowplayer_checker'>Scan now!</a></span>";
599
+ } else {
600
+ $htmlQueue = '';
601
  }
602
+
603
  if( $iCount && $iQueue ) {
604
  printf(__('Currently %d videos in database and %s posts in queue.', 'fv-wordpress-flowplayer'), $iCount, $htmlQueue);
605
  } else if( $iCount ) {
1023
  'autoplay' => false,
1024
  'preroll' => 'no',
1025
  'postroll' => 'no',
1026
+ 'subtitles' => flowplayer::get_plugin_url().'/images/test-subtitles.vtt',
1027
  'caption' => "Foliovision Video;Lapinthrope Extras - Roy Thompson Hall Dance;Romeo and Juliet Ballet Schloss Kittsee",
1028
  'playlist' => 'https://player.vimeo.com/external/224781088.sd.mp4?s=face4dbb990b462826c8e1e43a9c66c6a9bb5585&profile_id=165&oauth2_token_id=3501005,https://i.vimeocdn.com/video/643908843_295x166.jpg;https://player.vimeo.com/external/45864857.hd.mp4?s=94fddee594da3258c9e10355f5bad8173c4aee7b&profile_id=113&oauth2_token_id=3501005,https://i.vimeocdn.com/video/319116053_295x166.jpg',
1029
  'liststyle' => 'horizontal'
1492
  wp_nonce_field( 'closedpostboxes', 'closedpostboxesnonce', false );
1493
  wp_nonce_field( 'meta-box-order-nonce', 'meta-box-order-nonce', false );
1494
  ?>
1495
+
1496
+ </div>
1497
  <?php endforeach;?>
1498
  <div style="clear: both"></div>
1499
  </div>