Merge pull request #284 from ArthurHoaro/plugin-playvideos
PLUGIN playvideos
This commit is contained in:
commit
245432e796
7 changed files with 10715 additions and 0 deletions
71
plugins/playvideos/README.md
Normal file
71
plugins/playvideos/README.md
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
### ► Play Videos plugin for Shaarli
|
||||||
|
This plugin adds a `► Play Videos` button to [Shaarli](https://github.com/shaarli/Shaarli)'s toolbar. Click this button to play all videos on the page in an overlay HTML5 player. Nice for continuous stream of music, documentaries, talks...
|
||||||
|
|
||||||
|
This uses code from https://zaius.github.io/youtube_playlist/ and is currently only compatible with Youtube videos.
|
||||||
|
|
||||||
|
![](https://cdn.mediacru.sh/D_izf0zjAtxy.png)
|
||||||
|
|
||||||
|
#### Installation and setup
|
||||||
|
Place the files in the `tpl/plugins/playvideos/` directory of your Shaarli.
|
||||||
|
This is a default Shaarli plugin, you just have to enable it.
|
||||||
|
|
||||||
|
To enable the plugin, add `playvideos` to the `TOOLBAR_PLUGINS` config option in your `index.php` or `data/options.php`. Example:
|
||||||
|
|
||||||
|
$GLOBALS['config']['TOOLBAR_PLUGINS'] = array('aplugins', 'anotherone', 'playvideos');
|
||||||
|
|
||||||
|
#### Troubleshooting
|
||||||
|
If your server has [Content Security Policy](http://content-security-policy.com/) headers enabled, this may prevent the script from loading fully. You should relax the CSP in your server settings. Example CSP rule for apache2:
|
||||||
|
`Header set Content-Security-Policy "script-src 'self' 'unsafe-inline' https://www.youtube.com https://s.ytimg.com 'unsafe-eval'"`
|
||||||
|
|
||||||
|
### License
|
||||||
|
```
|
||||||
|
File: youtube_playlist.js
|
||||||
|
Copyright: (c) 2010-2014, David Kelso <david@kelso.id.au>
|
||||||
|
License: The ISC License (http://opensource.org/licenses/ISC)
|
||||||
|
|
||||||
|
Files: jquery*.js
|
||||||
|
License: MIT License (http://opensource.org/licenses/MIT)
|
||||||
|
Copyright: (C) jQuery Foundation and other contributors, https://jquery.com/download/
|
||||||
|
|
||||||
|
-----------------------------------------------------
|
||||||
|
|
||||||
|
The ISC License (http://opensource.org/licenses/ISC)
|
||||||
|
|
||||||
|
Copyright (c) 2010-2014, David Kelso (david at kelso dot id dot au)
|
||||||
|
Copyright (c) 2010-2014, nodiscc (nodiscc at gmail dot com)
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE
|
||||||
|
|
||||||
|
----------------------------------------------------
|
||||||
|
MIT LICENSE
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
|
||||||
|
----------------------------------------------------
|
||||||
|
```
|
10346
plugins/playvideos/jquery-1.11.2.js
vendored
Normal file
10346
plugins/playvideos/jquery-1.11.2.js
vendored
Normal file
File diff suppressed because it is too large
Load diff
BIN
plugins/playvideos/jquery-1.11.2.min.js
vendored
Normal file
BIN
plugins/playvideos/jquery-1.11.2.min.js
vendored
Normal file
Binary file not shown.
1
plugins/playvideos/playvideos.html
Normal file
1
plugins/playvideos/playvideos.html
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<a href="#" id="playvideos">► Play Videos</a>
|
40
plugins/playvideos/playvideos.php
Normal file
40
plugins/playvideos/playvideos.php
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Plugin PlayVideos
|
||||||
|
*
|
||||||
|
* Add a button in the toolbar allowing to watch all videos.
|
||||||
|
* Note: this plugin adds jQuery.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When linklist is displayed, add play videos to header's toolbar.
|
||||||
|
*
|
||||||
|
* @param array $data - header data.
|
||||||
|
*
|
||||||
|
* @return mixed - header data with playvideos toolbar item.
|
||||||
|
*/
|
||||||
|
function hook_playvideos_render_header($data)
|
||||||
|
{
|
||||||
|
if ($data['_PAGE_'] == Router::$PAGE_LINKLIST) {
|
||||||
|
$data['buttons_toolbar'][] = file_get_contents(PluginManager::$PLUGINS_PATH . '/playvideos/playvideos.html');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When linklist is displayed, include playvideos JS files.
|
||||||
|
*
|
||||||
|
* @param array $data - footer data.
|
||||||
|
*
|
||||||
|
* @return mixed - footer data with playvideos JS files added.
|
||||||
|
*/
|
||||||
|
function hook_playvideos_render_footer($data)
|
||||||
|
{
|
||||||
|
if ($data['_PAGE_'] == Router::$PAGE_LINKLIST) {
|
||||||
|
$data['js_files'][] = PluginManager::$PLUGINS_PATH . '/playvideos/jquery-1.11.2.min.js';
|
||||||
|
$data['js_files'][] = PluginManager::$PLUGINS_PATH . '/playvideos/youtube_playlist.js';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
196
plugins/playvideos/youtube_playlist.js
Normal file
196
plugins/playvideos/youtube_playlist.js
Normal file
|
@ -0,0 +1,196 @@
|
||||||
|
var run_playideos = (function () {
|
||||||
|
var e, n, t, o, r, i = [].indexOf || function (e) {
|
||||||
|
for (var n = 0, t = this.length; n < t; n++) {
|
||||||
|
if (n in this && this[n] === e) return n
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
};
|
||||||
|
if (!window.console) {
|
||||||
|
window.console = {
|
||||||
|
log: function () {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
n = {
|
||||||
|
shadow: {
|
||||||
|
"background-color": "black",
|
||||||
|
position: "fixed",
|
||||||
|
left: 0,
|
||||||
|
top: 0,
|
||||||
|
width: "100%",
|
||||||
|
height: "100%",
|
||||||
|
"z-index": 1e3,
|
||||||
|
opacity: .8
|
||||||
|
},
|
||||||
|
player_box: {
|
||||||
|
position: "fixed",
|
||||||
|
left: "50%",
|
||||||
|
top: "50%",
|
||||||
|
width: 640,
|
||||||
|
height: 480,
|
||||||
|
"margin-left": -320,
|
||||||
|
"margin-top": -240,
|
||||||
|
"z-index": 1001
|
||||||
|
},
|
||||||
|
prev_button: {
|
||||||
|
"float": "left"
|
||||||
|
},
|
||||||
|
next_button: {
|
||||||
|
"float": "right"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
t = function (e, n) {
|
||||||
|
var t, o, r;
|
||||||
|
r = document.createElement("script");
|
||||||
|
r.src = e;
|
||||||
|
o = document.getElementsByTagName("head")[0];
|
||||||
|
t = false;
|
||||||
|
r.onload = r.onreadystatechange = function () {
|
||||||
|
var e, i;
|
||||||
|
e = !this.readyState || (i = this.readyState) === "loaded" || i === "complete";
|
||||||
|
if (!t && e) {
|
||||||
|
t = true;
|
||||||
|
n();
|
||||||
|
r.onload = r.onreadystatechange = null;
|
||||||
|
return o.removeChild(r)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return o.appendChild(r)
|
||||||
|
};
|
||||||
|
e = function (e) {
|
||||||
|
var t, o, r, a, u, l, d, c, f, p, s, y, h, g, v, m, w;
|
||||||
|
e.getScript("//www.youtube.com/iframe_api");
|
||||||
|
d = [];
|
||||||
|
w = new RegExp("https?://(www.)?youtube.com/");
|
||||||
|
e('a[href^="http"]').each(function () {
|
||||||
|
var n;
|
||||||
|
if (!e(this).attr("href").match(w)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
n = this.href.replace(/^.*v=/, "").replace(/\&.*$/, "");
|
||||||
|
if (i.call(d, n) < 0) {
|
||||||
|
return d.push(n)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
console.log("video ids", d);
|
||||||
|
c = 0;
|
||||||
|
y = null;
|
||||||
|
g = "playlist_player";
|
||||||
|
f = function () {
|
||||||
|
console.log("Playing", c, d[c]);
|
||||||
|
return y.loadVideoById(d[c])
|
||||||
|
};
|
||||||
|
p = function () {
|
||||||
|
c++;
|
||||||
|
if (c >= d.length) {
|
||||||
|
c -= d.length
|
||||||
|
}
|
||||||
|
return f()
|
||||||
|
};
|
||||||
|
s = function () {
|
||||||
|
c--;
|
||||||
|
if (c < 0) {
|
||||||
|
c += d.length
|
||||||
|
}
|
||||||
|
return f()
|
||||||
|
};
|
||||||
|
l = function () {
|
||||||
|
e("#shadow, #player_box").remove();
|
||||||
|
return e(document).unbind("keyup.player")
|
||||||
|
};
|
||||||
|
e(document).bind("keyup.player", function (e) {
|
||||||
|
if (e.keyCode === 27) {
|
||||||
|
l()
|
||||||
|
}
|
||||||
|
if (e.keyCode === 39) {
|
||||||
|
p()
|
||||||
|
}
|
||||||
|
if (e.keyCode === 37) {
|
||||||
|
return s()
|
||||||
|
}
|
||||||
|
});
|
||||||
|
u = e("<div />", {
|
||||||
|
id: "shadow",
|
||||||
|
css: n.shadow,
|
||||||
|
click: l
|
||||||
|
});
|
||||||
|
r = e("<div />", {
|
||||||
|
id: "player_box",
|
||||||
|
css: n.player_box
|
||||||
|
});
|
||||||
|
o = e("<div />", {
|
||||||
|
id: g
|
||||||
|
});
|
||||||
|
a = e("<a />", {
|
||||||
|
href: "javascript:;",
|
||||||
|
text: "previous",
|
||||||
|
css: n.prev_button,
|
||||||
|
click: s
|
||||||
|
});
|
||||||
|
t = e("<a />", {
|
||||||
|
href: "javascript:;",
|
||||||
|
text: "next",
|
||||||
|
css: n.next_button,
|
||||||
|
click: p
|
||||||
|
});
|
||||||
|
r.append(o).append(a).append(t);
|
||||||
|
e("body").append(u).append(r);
|
||||||
|
v = function (e) {
|
||||||
|
console.log("player ready");
|
||||||
|
return e.target.playVideo()
|
||||||
|
};
|
||||||
|
h = function (e) {
|
||||||
|
var n, t;
|
||||||
|
n = {
|
||||||
|
2: "invalid video id",
|
||||||
|
5: "video not supported in html5",
|
||||||
|
100: "video removed or private",
|
||||||
|
101: "video not embedable",
|
||||||
|
150: "video not embedable"
|
||||||
|
};
|
||||||
|
t = n[e.data] || "unknown error";
|
||||||
|
console.log("Error", t);
|
||||||
|
d.splice(c, 1);
|
||||||
|
if (c >= d.length) {
|
||||||
|
c = 0
|
||||||
|
}
|
||||||
|
return f()
|
||||||
|
};
|
||||||
|
m = function (e) {
|
||||||
|
if (e.data === YT.PlayerState.ENDED) {
|
||||||
|
return p()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return window.onYouTubeIframeAPIReady = function () {
|
||||||
|
return y = new YT.Player(g, {
|
||||||
|
height: "390",
|
||||||
|
width: "640",
|
||||||
|
videoId: d[0],
|
||||||
|
events: {
|
||||||
|
onReady: v,
|
||||||
|
onError: h,
|
||||||
|
onStateChange: m
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
o = false;
|
||||||
|
if (typeof jQuery !== "undefined" && jQuery !== null && jQuery.fn && jQuery.fn.jquery) {
|
||||||
|
r = jQuery.fn.jquery.split(".");
|
||||||
|
if (r.length === 3 && parseInt(r[1]) > 3) {
|
||||||
|
console.log("using in page jquery version", jQuery.fn.jquery);
|
||||||
|
e(jQuery);
|
||||||
|
o = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!o) {
|
||||||
|
t("plugins/playvideos/jquery-1.11.2.min.js", function () {
|
||||||
|
return e(jQuery.noConflict(true))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var input = document.querySelector('#playvideos');
|
||||||
|
input.addEventListener('click', function()
|
||||||
|
{
|
||||||
|
run_playideos();
|
||||||
|
});
|
61
tests/plugins/PluginPlayvideosTest.php
Normal file
61
tests/plugins/PluginPlayvideosTest.php
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PluginPlayvideosTest.php
|
||||||
|
*/
|
||||||
|
|
||||||
|
require_once 'plugins/playvideos/playvideos.php';
|
||||||
|
require_once 'application/Router.php';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class PluginPlayvideosTest
|
||||||
|
* Unit test for the PlayVideos plugin
|
||||||
|
*/
|
||||||
|
class PluginPlayvideosTest extends PHPUnit_Framework_TestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Reset plugin path
|
||||||
|
*/
|
||||||
|
function setUp()
|
||||||
|
{
|
||||||
|
PluginManager::$PLUGINS_PATH = 'plugins';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test render_linklist hook.
|
||||||
|
*/
|
||||||
|
function testPlayvideosHeader()
|
||||||
|
{
|
||||||
|
$str = 'stuff';
|
||||||
|
$data = array($str => $str);
|
||||||
|
$data['_PAGE_'] = Router::$PAGE_LINKLIST;
|
||||||
|
|
||||||
|
$data = hook_playvideos_render_header($data);
|
||||||
|
$this->assertEquals($str, $data[$str]);
|
||||||
|
$this->assertEquals(1, count($data['buttons_toolbar']));
|
||||||
|
|
||||||
|
$data = array($str => $str);
|
||||||
|
$data['_PAGE_'] = $str;
|
||||||
|
$this->assertEquals($str, $data[$str]);
|
||||||
|
$this->assertArrayNotHasKey('buttons_toolbar', $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test render_footer hook.
|
||||||
|
*/
|
||||||
|
function testPlayvideosFooter()
|
||||||
|
{
|
||||||
|
$str = 'stuff';
|
||||||
|
$data = array($str => $str);
|
||||||
|
$data['_PAGE_'] = Router::$PAGE_LINKLIST;
|
||||||
|
|
||||||
|
$data = hook_playvideos_render_footer($data);
|
||||||
|
$this->assertEquals($str, $data[$str]);
|
||||||
|
$this->assertEquals(2, count($data['js_files']));
|
||||||
|
|
||||||
|
$data = array($str => $str);
|
||||||
|
$data['_PAGE_'] = $str;
|
||||||
|
$this->assertEquals($str, $data[$str]);
|
||||||
|
$this->assertArrayNotHasKey('js_files', $data);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue