danta 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE +22 -0
- data/README.md +102 -0
- data/bin/danta +5 -0
- data/lib/danta/api.rb +17 -0
- data/lib/danta/app.rb +20 -0
- data/lib/danta/dispatcher.rb +90 -0
- data/lib/danta/library/node.rb +57 -0
- data/lib/danta/library/null_node.rb +31 -0
- data/lib/danta/library/tree.rb +85 -0
- data/lib/danta/public/css/bootstrap-treeview.min.css +1 -0
- data/lib/danta/public/css/danta.css +15 -0
- data/lib/danta/public/index.html +49 -0
- data/lib/danta/public/js/bootstrap-treeview.min.js +1 -0
- data/lib/danta/public/js/danta.js +22 -0
- data/lib/danta/public/js/jquery-2.1.4.min.js +4 -0
- data/lib/danta/public/js/jquery.mobile.custom.min.js +3 -0
- data/lib/danta/public/js/player_actions.js +62 -0
- data/lib/danta/public/js/player_modal.js +16 -0
- data/lib/danta/public/js/response_dispatcher.js +26 -0
- data/lib/danta/public/js/video_library.js +45 -0
- data/lib/danta/public/js/video_tree.js +22 -0
- data/lib/danta/public/js/videos_response.js +14 -0
- data/lib/danta/public/js/web_socket_client.js +62 -0
- data/lib/danta/public/ws.html +50 -0
- data/lib/danta/request_handler.rb +50 -0
- data/lib/danta/root.rb +44 -0
- data/lib/danta/version.rb +3 -0
- data/lib/danta/video_library.rb +63 -0
- data/lib/danta.rb +3 -0
- metadata +73 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 04256810a41ebae351de08e5a2d03e45813eddf5
|
4
|
+
data.tar.gz: 6c8275981d760bbde30eaeee46c5f638b11a3300
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a8b52d0972003071f25444929a0af4f4ea07b72141d6a2962dd70e940dba61337cd11ee95961d9109e9bc9a796809b9fc456cbd24a8e63e0e640e9e4eda41cf8
|
7
|
+
data.tar.gz: b1f0432b0d712234d80705b5f02a65584d98ca8fc036b7b088bca83d7131dcf2ec025b8310d8dcd32736e01a3c1a292e72d12797990c3def6b09a067ca3af214
|
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2015 Carlos Chacon
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
22
|
+
|
data/README.md
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
# Danta
|
2
|
+
Danta is a web app for easy video playing in your Raspberry Pi.
|
3
|
+
|
4
|
+
## Installation
|
5
|
+
|
6
|
+
### Install ruby
|
7
|
+
|
8
|
+
We're going to use [RVM](https://rvm.io/rvm/install) to install Ruby.
|
9
|
+
|
10
|
+
```
|
11
|
+
\curl -sSL https://get.rvm.io | bash -s stable --ruby
|
12
|
+
```
|
13
|
+
|
14
|
+
### Install xdotool and omxplayer
|
15
|
+
|
16
|
+
Danta uses [Pecari](https://github.com/caedocha/pecari) to play videos, so install the following packages:
|
17
|
+
|
18
|
+
```
|
19
|
+
sudo apt-get install xdotool omxplayer
|
20
|
+
```
|
21
|
+
|
22
|
+
### Add Video Library file
|
23
|
+
|
24
|
+
Danta needs to know where is your video library. Add a `video_library.yml` file in the home directory.
|
25
|
+
|
26
|
+
```
|
27
|
+
cd ~
|
28
|
+
vim video_library.yml # Add your video library path here.
|
29
|
+
```
|
30
|
+
|
31
|
+
With the following data:
|
32
|
+
|
33
|
+
```
|
34
|
+
--
|
35
|
+
videos:
|
36
|
+
- '/path/to/videos/directory/'
|
37
|
+
|
38
|
+
```
|
39
|
+
|
40
|
+
### Install Danta gem
|
41
|
+
|
42
|
+
```
|
43
|
+
gem install danta
|
44
|
+
```
|
45
|
+
|
46
|
+
## Start Danta
|
47
|
+
|
48
|
+
Just call the danta command and the app will be ready to use.
|
49
|
+
|
50
|
+
```
|
51
|
+
danta
|
52
|
+
```
|
53
|
+
|
54
|
+
Access it with your smartphone's browser using the RPi's IP address. This is mine, for example:
|
55
|
+
|
56
|
+
```
|
57
|
+
192.168.1.10:9292
|
58
|
+
```
|
59
|
+
|
60
|
+
### Danta Environment Variables
|
61
|
+
|
62
|
+
Danta's behavior can be customized with the following environment variables:
|
63
|
+
|
64
|
+
```
|
65
|
+
DANTA_HOST # Overrides the default host, 0.0.0.0
|
66
|
+
DANTA_PORT # Overrides the default port, 9292
|
67
|
+
DANTA_VIDEO_LIBRARY # Overrides the default video library directory, the current user's home directory (~)
|
68
|
+
```
|
69
|
+
|
70
|
+
Examples:
|
71
|
+
|
72
|
+
```
|
73
|
+
export DANTA_HOST=localhost
|
74
|
+
export DANTA_PORT=9999
|
75
|
+
export DANTA_VIDEO_LIBRARY=/Other/video/library/directory
|
76
|
+
```
|
77
|
+
|
78
|
+
## Starting Danta at boot
|
79
|
+
|
80
|
+
Probably, you want to have Danta starting during boot time. In order to do this, edit the `rc.local` file:
|
81
|
+
|
82
|
+
```
|
83
|
+
sudo vim /etc/rc.local
|
84
|
+
```
|
85
|
+
|
86
|
+
Add the following line at the end of the file:
|
87
|
+
|
88
|
+
```
|
89
|
+
danta &
|
90
|
+
```
|
91
|
+
|
92
|
+
Save, exit and reboot the RPi.
|
93
|
+
|
94
|
+
## Supported Formats
|
95
|
+
|
96
|
+
Danta only supports `mkv`, `mov` and `mp4` videos. Any other video type is filtered out.
|
97
|
+
|
98
|
+
For more information, check [Pecari Usage Guide](https://github.com/caedocha/pecari#usage)
|
99
|
+
|
100
|
+
## Contact
|
101
|
+
|
102
|
+
You can send me an email to caedo.00 at gmail dot com. All feedback or questions are welcomed.
|
data/bin/danta
ADDED
data/lib/danta/api.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'sinatra-websocket'
|
3
|
+
require_relative 'request_handler'
|
4
|
+
|
5
|
+
module Danta
|
6
|
+
|
7
|
+
class Api < Sinatra::Base
|
8
|
+
|
9
|
+
get '/ws' do
|
10
|
+
RequestHandler.new(request: request).process
|
11
|
+
end
|
12
|
+
|
13
|
+
run! if __FILE__ == $0
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
data/lib/danta/app.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
module Danta
|
2
|
+
|
3
|
+
class App < Sinatra::Base
|
4
|
+
|
5
|
+
set :status, true
|
6
|
+
set :public_folder, public_dir
|
7
|
+
|
8
|
+
get '/' do
|
9
|
+
send_file(File.join(public_dir, 'index.html'))
|
10
|
+
end
|
11
|
+
|
12
|
+
def public_dir
|
13
|
+
File.join(File.dirname(__FILE__), 'public')
|
14
|
+
end
|
15
|
+
|
16
|
+
run! if __FILE__ == $0
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'pecari'
|
3
|
+
require_relative 'video_library'
|
4
|
+
|
5
|
+
class Dispatcher
|
6
|
+
|
7
|
+
attr_reader :raw_data
|
8
|
+
|
9
|
+
def initialize(raw_data:)
|
10
|
+
@raw_data = raw_data
|
11
|
+
end
|
12
|
+
|
13
|
+
def dispatch
|
14
|
+
case action
|
15
|
+
when 'videos'
|
16
|
+
videos_response
|
17
|
+
when 'launch'
|
18
|
+
launch_action
|
19
|
+
when 'exec'
|
20
|
+
exec_action
|
21
|
+
else
|
22
|
+
unrecognized_response
|
23
|
+
end
|
24
|
+
rescue StandardError => e
|
25
|
+
invalid_response(e)
|
26
|
+
end
|
27
|
+
|
28
|
+
def videos_response
|
29
|
+
{
|
30
|
+
action: action,
|
31
|
+
status: 'success',
|
32
|
+
data: Danta::VideoLibrary.new.videos.to_json
|
33
|
+
}.to_json
|
34
|
+
end
|
35
|
+
|
36
|
+
def launch_action
|
37
|
+
Pecari::Player.launch(CGI.unescape(params['video']))
|
38
|
+
launch_response
|
39
|
+
end
|
40
|
+
|
41
|
+
def launch_response
|
42
|
+
{
|
43
|
+
action: action,
|
44
|
+
status: 'success',
|
45
|
+
data: "playing #{params['video']}"
|
46
|
+
}.to_json
|
47
|
+
end
|
48
|
+
|
49
|
+
def exec_action
|
50
|
+
Pecari::Player.send(params['command'])
|
51
|
+
exec_response
|
52
|
+
end
|
53
|
+
|
54
|
+
def exec_response
|
55
|
+
{
|
56
|
+
action: action,
|
57
|
+
status: 'success',
|
58
|
+
data: "executing #{params['command']}"
|
59
|
+
}.to_json
|
60
|
+
end
|
61
|
+
|
62
|
+
def unrecognized_response
|
63
|
+
{
|
64
|
+
action: unrecognized_action,
|
65
|
+
status: 'fail',
|
66
|
+
data: ''
|
67
|
+
}.to_json
|
68
|
+
end
|
69
|
+
|
70
|
+
def invalid_response(exception)
|
71
|
+
{
|
72
|
+
action: 'invalid_action',
|
73
|
+
status: 'fail',
|
74
|
+
data: exception.message
|
75
|
+
}.to_json
|
76
|
+
end
|
77
|
+
|
78
|
+
def data
|
79
|
+
@data ||= JSON.parse(raw_data)
|
80
|
+
end
|
81
|
+
|
82
|
+
def action
|
83
|
+
@action ||= data['action']
|
84
|
+
end
|
85
|
+
|
86
|
+
def params
|
87
|
+
@params ||= data['params']
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module Library
|
4
|
+
|
5
|
+
class Node
|
6
|
+
|
7
|
+
attr_accessor :name
|
8
|
+
attr_accessor :nodes
|
9
|
+
attr_accessor :path
|
10
|
+
attr_accessor :parent
|
11
|
+
|
12
|
+
def initialize(name:, parent: nil, nodes: [])
|
13
|
+
@name = name
|
14
|
+
@nodes = nodes
|
15
|
+
@parent = parent
|
16
|
+
end
|
17
|
+
|
18
|
+
def root?
|
19
|
+
parent.empty?
|
20
|
+
end
|
21
|
+
|
22
|
+
def leaf?
|
23
|
+
nodes.empty?
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_h
|
27
|
+
{
|
28
|
+
name: name,
|
29
|
+
path: path,
|
30
|
+
nodes: nodes.map(&:to_h)
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
def to_json
|
35
|
+
to_h.to_json
|
36
|
+
end
|
37
|
+
|
38
|
+
def path
|
39
|
+
@path ||= build_path
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def build_path
|
45
|
+
next_parent = parent
|
46
|
+
parent_paths = [name]
|
47
|
+
while next_parent
|
48
|
+
parent_paths << next_parent.name
|
49
|
+
next_parent = next_parent.parent
|
50
|
+
end
|
51
|
+
parent_paths.reverse.join('/')
|
52
|
+
File.join(['/', parent_paths.reverse].flatten)
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Library
|
2
|
+
|
3
|
+
class NullNode
|
4
|
+
|
5
|
+
def name
|
6
|
+
"nodeless"
|
7
|
+
end
|
8
|
+
|
9
|
+
def root?
|
10
|
+
false
|
11
|
+
end
|
12
|
+
|
13
|
+
def leaf?
|
14
|
+
true
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_h
|
18
|
+
{}
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_json
|
22
|
+
to_h.to_json
|
23
|
+
end
|
24
|
+
|
25
|
+
def path
|
26
|
+
''
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require_relative 'node'
|
2
|
+
require_relative 'null_node'
|
3
|
+
|
4
|
+
module Library
|
5
|
+
|
6
|
+
class Tree
|
7
|
+
|
8
|
+
attr_reader :nodes
|
9
|
+
attr_accessor :paths
|
10
|
+
|
11
|
+
def initialize(paths:)
|
12
|
+
@paths = paths
|
13
|
+
end
|
14
|
+
|
15
|
+
def nodes
|
16
|
+
@nodes ||= root_nodes
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_h
|
20
|
+
nodes.map(&:to_h)
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_json
|
24
|
+
to_h.to_json
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def splitted_paths
|
30
|
+
paths.map { |path| path.split('/').reject { |path| path.empty? } }
|
31
|
+
end
|
32
|
+
|
33
|
+
def unlinked_nodes
|
34
|
+
@unlinked_nodes ||= splitted_paths
|
35
|
+
.map do |paths|
|
36
|
+
paths.map do |path|
|
37
|
+
Node.new(name: path)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def linked_nodes
|
43
|
+
@linked_nodes ||= unlinked_nodes.map do |unlinked_nodes|
|
44
|
+
root_nodes = []
|
45
|
+
unlinked_nodes.each_cons(2).each_with_index do |(parent, child), index|
|
46
|
+
if(index == 0)
|
47
|
+
root_nodes << parent
|
48
|
+
end
|
49
|
+
child.parent = parent
|
50
|
+
parent.nodes << child
|
51
|
+
end
|
52
|
+
root_nodes
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def root_nodes
|
57
|
+
backup_nodes = linked_nodes.dup
|
58
|
+
temp_nodes = backup_nodes.first.dup
|
59
|
+
backup_nodes.shift
|
60
|
+
backup_nodes.each_with_object(temp_nodes) do |nod, tmp|
|
61
|
+
rewire_nodes(node: nod.first, base_node: tmp.first)
|
62
|
+
end
|
63
|
+
temp_nodes
|
64
|
+
end
|
65
|
+
|
66
|
+
def rewire_nodes(node:, base_node:, backup_parent: nil)
|
67
|
+
if(node.name == base_node.name)
|
68
|
+
x = base_node.nodes.detect { |n| n.name == node.nodes.first.name } || base_node.nodes.first || NullNode.new
|
69
|
+
if x.name == "nodeless"
|
70
|
+
rewire_nodes(node: node.nodes.first, base_node: x, backup_parent: base_node)
|
71
|
+
else
|
72
|
+
rewire_nodes(node: node.nodes.first, base_node: x)
|
73
|
+
end
|
74
|
+
elsif(base_node.name == "nodeless")
|
75
|
+
node.parent = backup_parent
|
76
|
+
backup_parent.nodes << node
|
77
|
+
else
|
78
|
+
node.parent = base_node.parent
|
79
|
+
base_node.parent.nodes << node
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
.treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.icon{width:12px;margin-right:5px}.treeview .node-disabled{color:silver;cursor:not-allowed}
|
@@ -0,0 +1,49 @@
|
|
1
|
+
<html>
|
2
|
+
<head>
|
3
|
+
<title>Danta Video Player</title>
|
4
|
+
<meta charset="utf-8">
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
6
|
+
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
|
7
|
+
<link rel="stylesheet" href="css/bootstrap-treeview.min.css">
|
8
|
+
<link rel="stylesheet" href="css/danta.css">
|
9
|
+
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
|
10
|
+
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
|
11
|
+
<script src="https://cdn.jsdelivr.net/lodash/4.17.2/lodash.min.js"></script>
|
12
|
+
<script src="js/bootstrap-treeview.min.js"></script>
|
13
|
+
<script src="js/web_socket_client.js"></script>
|
14
|
+
<script src="js/response_dispatcher.js"></script>
|
15
|
+
<script src="js/videos_response.js"></script>
|
16
|
+
<script src="js/video_tree.js"></script>
|
17
|
+
<script src="js/video_library.js"></script>
|
18
|
+
<script src="js/player_actions.js"></script>
|
19
|
+
<script src="js/player_modal.js"></script>
|
20
|
+
<script src="js/danta.js"></script>
|
21
|
+
</head>
|
22
|
+
<body>
|
23
|
+
<div class="container">
|
24
|
+
<h1>Danta Video Player</h1>
|
25
|
+
<div id="tree"></div>
|
26
|
+
<div id="player" class="modal" role="dialog">
|
27
|
+
<div class="modal-dialog">
|
28
|
+
<div class="modal-content">
|
29
|
+
<div class="modal-header">
|
30
|
+
Player
|
31
|
+
</div>
|
32
|
+
<div class="modal-body">
|
33
|
+
<div id="controls">
|
34
|
+
<button type="button" class="btn btn-default btn-lg" onclick="playerActions.play()"><span class="glyphicon glyphicon-play"></span></button>
|
35
|
+
<button type="button" class="btn btn-default btn-lg" onclick="playerActions.pause()"><span class="glyphicon glyphicon-pause"></span></button>
|
36
|
+
<button type="button" class="btn btn-default btn-lg" onclick="playerActions.fastBackward()"><span class="glyphicon glyphicon-fast-backward"></span></button>
|
37
|
+
<button type="button" class="btn btn-default btn-lg" onclick="playerActions.fastForward()"><span class="glyphicon glyphicon-fast-forward"></span></button>
|
38
|
+
<button type="button" class="btn btn-default btn-lg" onclick="playerActions.mute()"><span class="glyphicon glyphicon-volume-off"></span></button>
|
39
|
+
<button type="button" class="btn btn-default btn-lg" onclick="playerActions.turnVolumeDown()"><span class="glyphicon glyphicon-volume-down"></span></button>
|
40
|
+
<button type="button" class="btn btn-default btn-lg" onclick="playerActions.turnVolumeUp()"><span class="glyphicon glyphicon-volume-up"></span></button>
|
41
|
+
<button type="button" class="btn btn-default btn-lg" onclick="playerActions.quit()"><span class="glyphicon glyphicon-off"></span></button>
|
42
|
+
</div>
|
43
|
+
</div>
|
44
|
+
</div>
|
45
|
+
</div>
|
46
|
+
</div>
|
47
|
+
</div>
|
48
|
+
</body>
|
49
|
+
</html>
|
@@ -0,0 +1 @@
|
|
1
|
+
!function(a,b,c,d){"use strict";var e="treeview",f={};f.settings={injectStyle:!0,levels:2,expandIcon:"glyphicon glyphicon-plus",collapseIcon:"glyphicon glyphicon-minus",emptyIcon:"glyphicon",nodeIcon:"",selectedIcon:"",checkedIcon:"glyphicon glyphicon-check",uncheckedIcon:"glyphicon glyphicon-unchecked",color:d,backColor:d,borderColor:d,onhoverColor:"#F5F5F5",selectedColor:"#FFFFFF",selectedBackColor:"#428bca",searchResultColor:"#D9534F",searchResultBackColor:d,enableLinks:!1,highlightSelected:!0,highlightSearchResults:!0,showBorder:!0,showIcon:!0,showCheckbox:!1,showTags:!1,multiSelect:!1,onNodeChecked:d,onNodeCollapsed:d,onNodeDisabled:d,onNodeEnabled:d,onNodeExpanded:d,onNodeSelected:d,onNodeUnchecked:d,onNodeUnselected:d,onSearchComplete:d,onSearchCleared:d},f.options={silent:!1,ignoreChildren:!1},f.searchOptions={ignoreCase:!0,exactMatch:!1,revealResults:!0};var g=function(b,c){return this.$element=a(b),this.elementId=b.id,this.styleId=this.elementId+"-style",this.init(c),{options:this.options,init:a.proxy(this.init,this),remove:a.proxy(this.remove,this),getNode:a.proxy(this.getNode,this),getParent:a.proxy(this.getParent,this),getSiblings:a.proxy(this.getSiblings,this),getSelected:a.proxy(this.getSelected,this),getUnselected:a.proxy(this.getUnselected,this),getExpanded:a.proxy(this.getExpanded,this),getCollapsed:a.proxy(this.getCollapsed,this),getChecked:a.proxy(this.getChecked,this),getUnchecked:a.proxy(this.getUnchecked,this),getDisabled:a.proxy(this.getDisabled,this),getEnabled:a.proxy(this.getEnabled,this),selectNode:a.proxy(this.selectNode,this),unselectNode:a.proxy(this.unselectNode,this),toggleNodeSelected:a.proxy(this.toggleNodeSelected,this),collapseAll:a.proxy(this.collapseAll,this),collapseNode:a.proxy(this.collapseNode,this),expandAll:a.proxy(this.expandAll,this),expandNode:a.proxy(this.expandNode,this),toggleNodeExpanded:a.proxy(this.toggleNodeExpanded,this),revealNode:a.proxy(this.revealNode,this),checkAll:a.proxy(this.checkAll,this),checkNode:a.proxy(this.checkNode,this),uncheckAll:a.proxy(this.uncheckAll,this),uncheckNode:a.proxy(this.uncheckNode,this),toggleNodeChecked:a.proxy(this.toggleNodeChecked,this),disableAll:a.proxy(this.disableAll,this),disableNode:a.proxy(this.disableNode,this),enableAll:a.proxy(this.enableAll,this),enableNode:a.proxy(this.enableNode,this),toggleNodeDisabled:a.proxy(this.toggleNodeDisabled,this),search:a.proxy(this.search,this),clearSearch:a.proxy(this.clearSearch,this)}};g.prototype.init=function(b){this.tree=[],this.nodes=[],b.data&&("string"==typeof b.data&&(b.data=a.parseJSON(b.data)),this.tree=a.extend(!0,[],b.data),delete b.data),this.options=a.extend({},f.settings,b),this.destroy(),this.subscribeEvents(),this.setInitialStates({nodes:this.tree},0),this.render()},g.prototype.remove=function(){this.destroy(),a.removeData(this,e),a("#"+this.styleId).remove()},g.prototype.destroy=function(){this.initialized&&(this.$wrapper.remove(),this.$wrapper=null,this.unsubscribeEvents(),this.initialized=!1)},g.prototype.unsubscribeEvents=function(){this.$element.off("click"),this.$element.off("nodeChecked"),this.$element.off("nodeCollapsed"),this.$element.off("nodeDisabled"),this.$element.off("nodeEnabled"),this.$element.off("nodeExpanded"),this.$element.off("nodeSelected"),this.$element.off("nodeUnchecked"),this.$element.off("nodeUnselected"),this.$element.off("searchComplete"),this.$element.off("searchCleared")},g.prototype.subscribeEvents=function(){this.unsubscribeEvents(),this.$element.on("click",a.proxy(this.clickHandler,this)),"function"==typeof this.options.onNodeChecked&&this.$element.on("nodeChecked",this.options.onNodeChecked),"function"==typeof this.options.onNodeCollapsed&&this.$element.on("nodeCollapsed",this.options.onNodeCollapsed),"function"==typeof this.options.onNodeDisabled&&this.$element.on("nodeDisabled",this.options.onNodeDisabled),"function"==typeof this.options.onNodeEnabled&&this.$element.on("nodeEnabled",this.options.onNodeEnabled),"function"==typeof this.options.onNodeExpanded&&this.$element.on("nodeExpanded",this.options.onNodeExpanded),"function"==typeof this.options.onNodeSelected&&this.$element.on("nodeSelected",this.options.onNodeSelected),"function"==typeof this.options.onNodeUnchecked&&this.$element.on("nodeUnchecked",this.options.onNodeUnchecked),"function"==typeof this.options.onNodeUnselected&&this.$element.on("nodeUnselected",this.options.onNodeUnselected),"function"==typeof this.options.onSearchComplete&&this.$element.on("searchComplete",this.options.onSearchComplete),"function"==typeof this.options.onSearchCleared&&this.$element.on("searchCleared",this.options.onSearchCleared)},g.prototype.setInitialStates=function(b,c){if(b.nodes){c+=1;var d=b,e=this;a.each(b.nodes,function(a,b){b.nodeId=e.nodes.length,b.parentId=d.nodeId,b.hasOwnProperty("selectable")||(b.selectable=!0),b.state=b.state||{},b.state.hasOwnProperty("checked")||(b.state.checked=!1),b.state.hasOwnProperty("disabled")||(b.state.disabled=!1),b.state.hasOwnProperty("expanded")||(!b.state.disabled&&c<e.options.levels&&b.nodes&&b.nodes.length>0?b.state.expanded=!0:b.state.expanded=!1),b.state.hasOwnProperty("selected")||(b.state.selected=!1),e.nodes.push(b),b.nodes&&e.setInitialStates(b,c)})}},g.prototype.clickHandler=function(b){this.options.enableLinks||b.preventDefault();var c=a(b.target),d=this.findNode(c);if(d&&!d.state.disabled){var e=c.attr("class")?c.attr("class").split(" "):[];-1!==e.indexOf("expand-icon")?(this.toggleExpandedState(d,f.options),this.render()):-1!==e.indexOf("check-icon")?(this.toggleCheckedState(d,f.options),this.render()):(d.selectable?this.toggleSelectedState(d,f.options):this.toggleExpandedState(d,f.options),this.render())}},g.prototype.findNode=function(a){var b=a.closest("li.list-group-item").attr("data-nodeid"),c=this.nodes[b];return c||console.log("Error: node does not exist"),c},g.prototype.toggleExpandedState=function(a,b){a&&this.setExpandedState(a,!a.state.expanded,b)},g.prototype.setExpandedState=function(b,c,d){c!==b.state.expanded&&(c&&b.nodes?(b.state.expanded=!0,d.silent||this.$element.trigger("nodeExpanded",a.extend(!0,{},b))):c||(b.state.expanded=!1,d.silent||this.$element.trigger("nodeCollapsed",a.extend(!0,{},b)),b.nodes&&!d.ignoreChildren&&a.each(b.nodes,a.proxy(function(a,b){this.setExpandedState(b,!1,d)},this))))},g.prototype.toggleSelectedState=function(a,b){a&&this.setSelectedState(a,!a.state.selected,b)},g.prototype.setSelectedState=function(b,c,d){c!==b.state.selected&&(c?(this.options.multiSelect||a.each(this.findNodes("true","g","state.selected"),a.proxy(function(a,b){this.setSelectedState(b,!1,d)},this)),b.state.selected=!0,d.silent||this.$element.trigger("nodeSelected",a.extend(!0,{},b))):(b.state.selected=!1,d.silent||this.$element.trigger("nodeUnselected",a.extend(!0,{},b))))},g.prototype.toggleCheckedState=function(a,b){a&&this.setCheckedState(a,!a.state.checked,b)},g.prototype.setCheckedState=function(b,c,d){c!==b.state.checked&&(c?(b.state.checked=!0,d.silent||this.$element.trigger("nodeChecked",a.extend(!0,{},b))):(b.state.checked=!1,d.silent||this.$element.trigger("nodeUnchecked",a.extend(!0,{},b))))},g.prototype.setDisabledState=function(b,c,d){c!==b.state.disabled&&(c?(b.state.disabled=!0,this.setExpandedState(b,!1,d),this.setSelectedState(b,!1,d),this.setCheckedState(b,!1,d),d.silent||this.$element.trigger("nodeDisabled",a.extend(!0,{},b))):(b.state.disabled=!1,d.silent||this.$element.trigger("nodeEnabled",a.extend(!0,{},b))))},g.prototype.render=function(){this.initialized||(this.$element.addClass(e),this.$wrapper=a(this.template.list),this.injectStyle(),this.initialized=!0),this.$element.empty().append(this.$wrapper.empty()),this.buildTree(this.tree,0)},g.prototype.buildTree=function(b,c){if(b){c+=1;var d=this;a.each(b,function(b,e){for(var f=a(d.template.item).addClass("node-"+d.elementId).addClass(e.state.checked?"node-checked":"").addClass(e.state.disabled?"node-disabled":"").addClass(e.state.selected?"node-selected":"").addClass(e.searchResult?"search-result":"").attr("data-nodeid",e.nodeId).attr("style",d.buildStyleOverride(e)),g=0;c-1>g;g++)f.append(d.template.indent);var h=[];if(e.nodes?(h.push("expand-icon"),h.push(e.state.expanded?d.options.collapseIcon:d.options.expandIcon)):h.push(d.options.emptyIcon),f.append(a(d.template.icon).addClass(h.join(" "))),d.options.showIcon){var h=["node-icon"];h.push(e.icon||d.options.nodeIcon),e.state.selected&&(h.pop(),h.push(e.selectedIcon||d.options.selectedIcon||e.icon||d.options.nodeIcon)),f.append(a(d.template.icon).addClass(h.join(" ")))}if(d.options.showCheckbox){var h=["check-icon"];h.push(e.state.checked?d.options.checkedIcon:d.options.uncheckedIcon),f.append(a(d.template.icon).addClass(h.join(" ")))}return f.append(d.options.enableLinks?a(d.template.link).attr("href",e.href).append(e.text):e.text),d.options.showTags&&e.tags&&a.each(e.tags,function(b,c){f.append(a(d.template.badge).append(c))}),d.$wrapper.append(f),e.nodes&&e.state.expanded&&!e.state.disabled?d.buildTree(e.nodes,c):void 0})}},g.prototype.buildStyleOverride=function(a){if(a.state.disabled)return"";var b=a.color,c=a.backColor;return this.options.highlightSelected&&a.state.selected&&(this.options.selectedColor&&(b=this.options.selectedColor),this.options.selectedBackColor&&(c=this.options.selectedBackColor)),this.options.highlightSearchResults&&a.searchResult&&!a.state.disabled&&(this.options.searchResultColor&&(b=this.options.searchResultColor),this.options.searchResultBackColor&&(c=this.options.searchResultBackColor)),"color:"+b+";background-color:"+c+";"},g.prototype.injectStyle=function(){this.options.injectStyle&&!c.getElementById(this.styleId)&&a('<style type="text/css" id="'+this.styleId+'"> '+this.buildStyle()+" </style>").appendTo("head")},g.prototype.buildStyle=function(){var a=".node-"+this.elementId+"{";return this.options.color&&(a+="color:"+this.options.color+";"),this.options.backColor&&(a+="background-color:"+this.options.backColor+";"),this.options.showBorder?this.options.borderColor&&(a+="border:1px solid "+this.options.borderColor+";"):a+="border:none;",a+="}",this.options.onhoverColor&&(a+=".node-"+this.elementId+":not(.node-disabled):hover{background-color:"+this.options.onhoverColor+";}"),this.css+a},g.prototype.template={list:'<ul class="list-group"></ul>',item:'<li class="list-group-item"></li>',indent:'<span class="indent"></span>',icon:'<span class="icon"></span>',link:'<a href="#" style="color:inherit;"></a>',badge:'<span class="badge"></span>'},g.prototype.css=".treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.icon{width:12px;margin-right:5px}.treeview .node-disabled{color:silver;cursor:not-allowed}",g.prototype.getNode=function(a){return this.nodes[a]},g.prototype.getParent=function(a){var b=this.identifyNode(a);return this.nodes[b.parentId]},g.prototype.getSiblings=function(a){var b=this.identifyNode(a),c=this.getParent(b),d=c?c.nodes:this.tree;return d.filter(function(a){return a.nodeId!==b.nodeId})},g.prototype.getSelected=function(){return this.findNodes("true","g","state.selected")},g.prototype.getUnselected=function(){return this.findNodes("false","g","state.selected")},g.prototype.getExpanded=function(){return this.findNodes("true","g","state.expanded")},g.prototype.getCollapsed=function(){return this.findNodes("false","g","state.expanded")},g.prototype.getChecked=function(){return this.findNodes("true","g","state.checked")},g.prototype.getUnchecked=function(){return this.findNodes("false","g","state.checked")},g.prototype.getDisabled=function(){return this.findNodes("true","g","state.disabled")},g.prototype.getEnabled=function(){return this.findNodes("false","g","state.disabled")},g.prototype.selectNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setSelectedState(a,!0,b)},this)),this.render()},g.prototype.unselectNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setSelectedState(a,!1,b)},this)),this.render()},g.prototype.toggleNodeSelected=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.toggleSelectedState(a,b)},this)),this.render()},g.prototype.collapseAll=function(b){var c=this.findNodes("true","g","state.expanded");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setExpandedState(a,!1,b)},this)),this.render()},g.prototype.collapseNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setExpandedState(a,!1,b)},this)),this.render()},g.prototype.expandAll=function(b){if(b=a.extend({},f.options,b),b&&b.levels)this.expandLevels(this.tree,b.levels,b);else{var c=this.findNodes("false","g","state.expanded");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setExpandedState(a,!0,b)},this))}this.render()},g.prototype.expandNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setExpandedState(a,!0,b),a.nodes&&b&&b.levels&&this.expandLevels(a.nodes,b.levels-1,b)},this)),this.render()},g.prototype.expandLevels=function(b,c,d){d=a.extend({},f.options,d),a.each(b,a.proxy(function(a,b){this.setExpandedState(b,c>0?!0:!1,d),b.nodes&&this.expandLevels(b.nodes,c-1,d)},this))},g.prototype.revealNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){for(var c=this.getParent(a);c;)this.setExpandedState(c,!0,b),c=this.getParent(c)},this)),this.render()},g.prototype.toggleNodeExpanded=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.toggleExpandedState(a,b)},this)),this.render()},g.prototype.checkAll=function(b){var c=this.findNodes("false","g","state.checked");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setCheckedState(a,!0,b)},this)),this.render()},g.prototype.checkNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setCheckedState(a,!0,b)},this)),this.render()},g.prototype.uncheckAll=function(b){var c=this.findNodes("true","g","state.checked");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setCheckedState(a,!1,b)},this)),this.render()},g.prototype.uncheckNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setCheckedState(a,!1,b)},this)),this.render()},g.prototype.toggleNodeChecked=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.toggleCheckedState(a,b)},this)),this.render()},g.prototype.disableAll=function(b){var c=this.findNodes("false","g","state.disabled");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setDisabledState(a,!0,b)},this)),this.render()},g.prototype.disableNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setDisabledState(a,!0,b)},this)),this.render()},g.prototype.enableAll=function(b){var c=this.findNodes("true","g","state.disabled");this.forEachIdentifier(c,b,a.proxy(function(a,b){this.setDisabledState(a,!1,b)},this)),this.render()},g.prototype.enableNode=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setDisabledState(a,!1,b)},this)),this.render()},g.prototype.toggleNodeDisabled=function(b,c){this.forEachIdentifier(b,c,a.proxy(function(a,b){this.setDisabledState(a,!a.state.disabled,b)},this)),this.render()},g.prototype.forEachIdentifier=function(b,c,d){c=a.extend({},f.options,c),b instanceof Array||(b=[b]),a.each(b,a.proxy(function(a,b){d(this.identifyNode(b),c)},this))},g.prototype.identifyNode=function(a){return"number"==typeof a?this.nodes[a]:a},g.prototype.search=function(b,c){c=a.extend({},f.searchOptions,c),this.clearSearch({render:!1});var d=[];if(b&&b.length>0){c.exactMatch&&(b="^"+b+"$");var e="g";c.ignoreCase&&(e+="i"),d=this.findNodes(b,e),a.each(d,function(a,b){b.searchResult=!0})}return c.revealResults?this.revealNode(d):this.render(),this.$element.trigger("searchComplete",a.extend(!0,{},d)),d},g.prototype.clearSearch=function(b){b=a.extend({},{render:!0},b);var c=a.each(this.findNodes("true","g","searchResult"),function(a,b){b.searchResult=!1});b.render&&this.render(),this.$element.trigger("searchCleared",a.extend(!0,{},c))},g.prototype.findNodes=function(b,c,d){c=c||"g",d=d||"text";var e=this;return a.grep(this.nodes,function(a){var f=e.getNodeValue(a,d);return"string"==typeof f?f.match(new RegExp(b,c)):void 0})},g.prototype.getNodeValue=function(a,b){var c=b.indexOf(".");if(c>0){var e=a[b.substring(0,c)],f=b.substring(c+1,b.length);return this.getNodeValue(e,f)}return a.hasOwnProperty(b)?a[b].toString():d};var h=function(a){b.console&&b.console.error(a)};a.fn[e]=function(b,c){var d;return this.each(function(){var f=a.data(this,e);"string"==typeof b?f?a.isFunction(f[b])&&"_"!==b.charAt(0)?(c instanceof Array||(c=[c]),d=f[b].apply(f,c)):h("No such method : "+b):h("Not initialized, can not call method : "+b):"boolean"==typeof b?d=f:a.data(this,e,new g(this,a.extend(!0,{},b)))}),d||this}}(jQuery,window,document);
|
@@ -0,0 +1,22 @@
|
|
1
|
+
$(document).ready(function() {
|
2
|
+
danta.init();
|
3
|
+
});
|
4
|
+
|
5
|
+
var danta = {
|
6
|
+
init: function() {
|
7
|
+
this.connectWebSocketClient();
|
8
|
+
this.initTree();
|
9
|
+
this.initPlayer();
|
10
|
+
},
|
11
|
+
connectWebSocketClient: function() {
|
12
|
+
webSocketClient.connect();
|
13
|
+
},
|
14
|
+
initTree: function() {
|
15
|
+
videoLibrary.get();
|
16
|
+
},
|
17
|
+
initPlayer: function() {
|
18
|
+
playerModal.init(
|
19
|
+
function() { videoTree.deselectAllNodes(); }
|
20
|
+
);
|
21
|
+
}
|
22
|
+
};
|