-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
175 lines (167 loc) · 5.37 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
export default {
install (Vue, opts) {
const States = {
CREATED: 'created',
LOADING: 'loading',
READY: 'ready'
}
Object.freeze(States)
const Types = {
IFRAME: 'iframe',
LOCATION: 'loc'
}
Object.freeze(Types)
/**
* Default options used when they are not provided on plugin installation
* @constant DEFAULT_OPTIONS {Object}
* @property {String} receiverApplicationId=5CB45E5A Receiver Application ID
* @property {Boolean} lazyLoading=true When true, the Chromecast SDK will not be automatically downloaded
* @property {String} className=google-cast-btn The class name of the Google Cast Button
* @property {String} chromecastSdkUrl=//www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1 Chromecast SDK script URL
*/
const DEFAULT_OPTIONS = {
receiverApplicationId: '5CB45E5A',
lazyLoading: false,
className: 'google-cast-btn',
chromecastSdkUrl: '//www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1'
}
opts = opts || {}
Object.assign(opts, DEFAULT_OPTIONS)
/**
* CastPlugin available in Vue instance
* @alias $cast
*/
const CastPlugin = {
/**
* Enum for connection states
* @readonly
* @enum {String}
* @property {String} CREATED not installed
* @property {String} LOADING fetching Chromecast SDK and initializing plugin
* @property {String} READY everything is ready to cast
*/
States,
/**
* Ways to send URL to Chromecast receiver application
* @readonly
* @enum {String}
* @property {String} IFRAME website is displayed in an iframe. It keeps the connection to chromecast
* @property {String} LOCATION Chromecast location is replaced and connection is lost
*/
Types,
/**
* Current plugin's state
* @type State
*/
state: States.CREATED,
/**
* Chromecast namespace used when sending message
* @type String
* @private
*/
_namespace: null,
/**
* Session used to send message
* @type CastSession
* @private
*/
_session: null,
/**
* Loads Chromecast SDK and initialize plugin
* @private
* @returns {Promise}
*/
_loadScript () {
return new Promise((resolve, reject) => {
if (this.state !== this.States.CREATED) {
return resolve()
}
this.state = States.LOADING
const el = document.createElement('script')
el.setAttribute('src', opts.chromecastSdkUrl)
window['__onGCastApiAvailable'] = (isAvailable) => {
if (isAvailable) {
this._initialize()
resolve()
} else {
reject()
}
}
el.addEventListener('error', reject)
document.body.appendChild(el)
})
},
/**
* Initialize plugin and button using loaded Chromecast SDK
* @returns Promise
* @private
*/
_initialize () {
return new Promise((resolve, reject) => {
this._addButton()
opts = opts || {}
this._namespace = opts.namespace || 'urn:x-cast:com.url.cast'
const castContext = cast.framework.CastContext.getInstance()
castContext.setOptions({
receiverApplicationId: opts.receiverApplicationId || DEFAULT_OPTIONS.receiverApplicationId,
autoJoinPolicy: opts.autoJoinPolicy || chrome.cast.AutoJoinPolicy.ORIGIN_SCOPED
})
const stateChanged = cast.framework.CastContextEventType.CAST_STATE_CHANGED
castContext.addEventListener(stateChanged, event => {
this.state = States.READY
resolve()
})
})
},
/**
* Add Google Cast Launcher component in container
* @private
*/
_addButton () {
let btnContainer = document.getElementsByClassName(opts.className)
if (btnContainer.length === 0) {
return console.warn(`Cannot find element with '${opts.className}' class`)
}
btnContainer = btnContainer[0]
const castBtn = document.createElement('google-cast-launcher')
btnContainer.appendChild(castBtn)
},
/**
* Get current session or initialize it if needed
* @returns {Promise<CastSession>}
* @private
*/
async _getSession () {
if (!this._session) {
await this._loadScript()
this._session = cast.framework.CastContext.getInstance().getCurrentSession()
}
return this._session
},
/**
* Send an URL to connected Chromecast
* @param {String} url URL of the website to load
* @param {String} type=Types.IFRAME way to load the URL
*/
send (url, type) {
return new Promise((resolve, reject) => {
type = type || Types.IFRAME
if (!url) {
throw new Error('You must provide an URL to cast as first argument')
}
const msg = {
type,
url
}
this._getSession().then(session => {
session.sendMessage(this._namespace, msg, resolve, reject)
})
})
}
}
if (!opts.lazyLoading) {
CastPlugin._loadScript()
}
Vue.prototype.$cast = CastPlugin
}
}