mirror of
https://github.com/hyperion-project/hyperion.ng.git
synced 2025-03-01 10:33:28 +00:00
Initial WebUI design and structure with JSON sample function (#170)
* Initial WebUI with sample functions * Changed folder structure * Light Reset Button and Translation fixing in Links * Indentation fixed * Reorganized menu and new function for setting effects * Styling fix
This commit is contained in:
@@ -1,37 +0,0 @@
|
||||
/*global define, chrome */
|
||||
define(['api/LocalStorage'], function (LocalStorage) {
|
||||
'use strict';
|
||||
return LocalStorage.subclass(/** @lends ChromeLocalStorage.prototype */{
|
||||
|
||||
/**
|
||||
* @class ChromeLocalStorage
|
||||
* @classdesc Chrome's persistent storage
|
||||
* @constructs
|
||||
* @extends LocalStorage
|
||||
*/
|
||||
constructor: function () {
|
||||
},
|
||||
|
||||
get: function () {
|
||||
chrome.storage.local.get('data', function (entry) {
|
||||
if (chrome.runtime.lastError) {
|
||||
this.emit('error', chrome.runtime.lastError.message);
|
||||
} else {
|
||||
this.emit('got', entry.data);
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
set: function (data) {
|
||||
var entry = {};
|
||||
entry.data = data;
|
||||
chrome.storage.local.set(entry, function () {
|
||||
if (chrome.runtime.lastError) {
|
||||
this.emit('error', chrome.runtime.lastError.message);
|
||||
} else {
|
||||
this.emit('set');
|
||||
}
|
||||
}.bind(this));
|
||||
}
|
||||
});
|
||||
});
|
@@ -1,57 +0,0 @@
|
||||
/*global chrome */
|
||||
define(['api/Network'], function (Network) {
|
||||
'use strict';
|
||||
|
||||
return Network.subclass(/** @lends ChromeNetwork.prototype */{
|
||||
|
||||
/**
|
||||
* @class ChromeNetwork
|
||||
* @extends Network
|
||||
* @classdesc Network functions for chrome apps
|
||||
* @constructs
|
||||
*/
|
||||
constructor: function () {
|
||||
},
|
||||
|
||||
/**
|
||||
* @overrides
|
||||
* @param onSuccess
|
||||
* @param onError
|
||||
*/
|
||||
getLocalInterfaces: function (onSuccess, onError) {
|
||||
var ips = [];
|
||||
|
||||
chrome.system.network.getNetworkInterfaces(function (networkInterfaces) {
|
||||
var i;
|
||||
|
||||
if (chrome.runtime.lastError) {
|
||||
if (onError) {
|
||||
onError('Could not get network interfaces');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < networkInterfaces.length; i++) {
|
||||
// check only ipv4
|
||||
if (networkInterfaces[i].address.indexOf('.') === -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ips.push(networkInterfaces[i].address);
|
||||
}
|
||||
|
||||
if (onSuccess) {
|
||||
onSuccess(ips);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* @overrides
|
||||
* @return {boolean}
|
||||
*/
|
||||
canDetectLocalAddress: function () {
|
||||
return true;
|
||||
}
|
||||
}, true);
|
||||
});
|
@@ -1,307 +0,0 @@
|
||||
/*global chrome */
|
||||
define(['lib/stapes', 'api/Socket', 'utils/Tools'], function (Stapes, Socket, tools) {
|
||||
'use strict';
|
||||
return Socket.subclass(/** @lends ChromeTcpSocket.prototype */{
|
||||
DEBUG: false,
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
handle: null,
|
||||
|
||||
/**
|
||||
* @type {function}
|
||||
*/
|
||||
currentResponseCallback: null,
|
||||
|
||||
/**
|
||||
* @type {function}
|
||||
*/
|
||||
currentErrorCallback: null,
|
||||
|
||||
/**
|
||||
* Temporary buffer for incoming data
|
||||
* @type {Uint8Array}
|
||||
*/
|
||||
inputBuffer: null,
|
||||
inputBufferIndex: 0,
|
||||
readBufferTimerId: null,
|
||||
|
||||
/**
|
||||
* @class ChromeTcpSocket
|
||||
* @extends Socket
|
||||
* @constructs
|
||||
*/
|
||||
constructor: function () {
|
||||
this.inputBuffer = new Uint8Array(4096);
|
||||
this.inputBufferIndex = 0;
|
||||
|
||||
chrome.sockets.tcp.onReceive.addListener(this.onDataReceived.bind(this));
|
||||
chrome.sockets.tcp.onReceiveError.addListener(this.onError.bind(this));
|
||||
},
|
||||
|
||||
create: function (onSuccess, onError) {
|
||||
if (this.DEBUG) {
|
||||
console.log('[DEBUG] Creating socket...');
|
||||
}
|
||||
chrome.sockets.tcp.create({bufferSize: 4096}, function (createInfo) {
|
||||
if (this.DEBUG) {
|
||||
console.log('[DEBUG] Socket created: ' + createInfo.socketId);
|
||||
}
|
||||
this.handle = createInfo.socketId;
|
||||
if (onSuccess) {
|
||||
onSuccess();
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
isConnected: function (resultCallback) {
|
||||
if (this.DEBUG) {
|
||||
console.log('[DEBUG] Checking if socket is connected...');
|
||||
}
|
||||
|
||||
if (!this.handle) {
|
||||
if (this.DEBUG) {
|
||||
console.log('[DEBUG] Socket not created');
|
||||
}
|
||||
|
||||
if (resultCallback) {
|
||||
resultCallback(false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
chrome.sockets.tcp.getInfo(this.handle, function (socketInfo) {
|
||||
if (this.DEBUG) {
|
||||
console.log('[DEBUG] Socket connected: ' + socketInfo.connected);
|
||||
}
|
||||
|
||||
if (socketInfo.connected) {
|
||||
if (resultCallback) {
|
||||
resultCallback(true);
|
||||
}
|
||||
} else {
|
||||
if (resultCallback) {
|
||||
resultCallback(false);
|
||||
}
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
connect: function (server, onSuccess, onError) {
|
||||
var timeoutHandle;
|
||||
|
||||
if (this.DEBUG) {
|
||||
console.log('[DEBUG] Connecting to peer ' + server.address + ':' + server.port);
|
||||
}
|
||||
|
||||
if (!this.handle) {
|
||||
if (this.DEBUG) {
|
||||
console.log('[DEBUG] Socket not created');
|
||||
}
|
||||
|
||||
if (onError) {
|
||||
onError('Socket handle is invalid');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// FIXME for some reason chrome blocks if peer is not reachable
|
||||
timeoutHandle = setTimeout(function () {
|
||||
chrome.sockets.tcp.getInfo(this.handle, function (socketInfo) {
|
||||
if (!socketInfo.connected) {
|
||||
// let the consumer decide if to close or not?
|
||||
// this.close();
|
||||
onError('Could not connect to ' + server.address + ':' + server.port);
|
||||
}
|
||||
}.bind(this));
|
||||
}.bind(this), 500);
|
||||
|
||||
chrome.sockets.tcp.connect(this.handle, server.address, server.port, function (result) {
|
||||
if (this.DEBUG) {
|
||||
console.log('[DEBUG] Connect result: ' + result);
|
||||
}
|
||||
clearTimeout(timeoutHandle);
|
||||
|
||||
if (chrome.runtime.lastError) {
|
||||
if (onError) {
|
||||
onError('Could not connect to ' + server.address + ':' + server.port);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (result !== 0) {
|
||||
if (onError) {
|
||||
onError('Could not connect to ' + server.address + ':' + server.port);
|
||||
}
|
||||
} else if (onSuccess) {
|
||||
onSuccess();
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
close: function (onSuccess, onError) {
|
||||
if (this.DEBUG) {
|
||||
console.log('[DEBUG] Closing socket...');
|
||||
}
|
||||
|
||||
if (this.handle) {
|
||||
chrome.sockets.tcp.close(this.handle, function () {
|
||||
this.handle = null;
|
||||
if (onSuccess) {
|
||||
onSuccess();
|
||||
}
|
||||
}.bind(this));
|
||||
} else {
|
||||
if (this.DEBUG) {
|
||||
console.log('[DEBUG] Socket not created');
|
||||
}
|
||||
|
||||
if (onError) {
|
||||
onError('Socket handle is invalid');
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
write: function (data, onSuccess, onError) {
|
||||
var dataToSend = null, dataType = typeof (data);
|
||||
|
||||
if (this.DEBUG) {
|
||||
console.log('[DEBUG] writing to socket...');
|
||||
}
|
||||
|
||||
if (!this.handle) {
|
||||
if (this.DEBUG) {
|
||||
console.log('[DEBUG] Socket not created');
|
||||
}
|
||||
|
||||
if (onError) {
|
||||
onError('Socket handle is invalid');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
this.isConnected(function (connected) {
|
||||
if (connected) {
|
||||
if (dataType === 'string') {
|
||||
if (this.DEBUG) {
|
||||
console.log('> ' + data);
|
||||
}
|
||||
dataToSend = tools.str2ab(data);
|
||||
} else {
|
||||
if (this.DEBUG) {
|
||||
console.log('> ' + tools.ab2hexstr(data));
|
||||
}
|
||||
dataToSend = data;
|
||||
}
|
||||
|
||||
chrome.sockets.tcp.send(this.handle, tools.a2ab(dataToSend), function (sendInfo) {
|
||||
if (this.DEBUG) {
|
||||
console.log('[DEBUG] Socket write result: ' + sendInfo.resultCode);
|
||||
}
|
||||
|
||||
if (sendInfo.resultCode !== 0) {
|
||||
onError('Socket write error: ' + sendInfo.resultCode);
|
||||
} else if (onSuccess) {
|
||||
onSuccess();
|
||||
}
|
||||
}.bind(this));
|
||||
} else {
|
||||
if (onError) {
|
||||
onError('No connection to peer');
|
||||
}
|
||||
}
|
||||
}.bind(this));
|
||||
|
||||
},
|
||||
|
||||
read: function (onSuccess, onError) {
|
||||
if (this.DEBUG) {
|
||||
console.log('[DEBUG] reading from socket...');
|
||||
}
|
||||
|
||||
if (!this.handle) {
|
||||
if (this.DEBUG) {
|
||||
console.log('[DEBUG] socket not created');
|
||||
}
|
||||
|
||||
if (onError) {
|
||||
onError('Socket handle is invalid');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
this.isConnected(function (connected) {
|
||||
if (!connected) {
|
||||
this.currentResponseCallback = null;
|
||||
this.currentErrorCallback = null;
|
||||
|
||||
if (onError) {
|
||||
onError('No connection to peer');
|
||||
}
|
||||
}
|
||||
}.bind(this));
|
||||
|
||||
if (onSuccess) {
|
||||
this.currentResponseCallback = onSuccess;
|
||||
}
|
||||
|
||||
if (onError) {
|
||||
this.currentErrorCallback = onError;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Data receiption callback
|
||||
* @private
|
||||
* @param info
|
||||
*/
|
||||
onDataReceived: function (info) {
|
||||
if (this.DEBUG) {
|
||||
console.log('[DEBUG] received data...');
|
||||
}
|
||||
|
||||
if (info.socketId === this.handle && info.data) {
|
||||
if (this.readBufferTimerId) {
|
||||
clearTimeout(this.readBufferTimerId);
|
||||
}
|
||||
if (this.readTimeoutTimerId) {
|
||||
clearTimeout(this.readTimeoutTimerId);
|
||||
this.readTimeoutTimerId = null;
|
||||
}
|
||||
this.inputBuffer.set(new Uint8Array(info.data), this.inputBufferIndex);
|
||||
this.inputBufferIndex += info.data.byteLength;
|
||||
|
||||
if (this.DEBUG) {
|
||||
console.log('< ' + tools.ab2hexstr(info.data));
|
||||
}
|
||||
|
||||
if (this.currentResponseCallback) {
|
||||
this.readBufferTimerId = setTimeout(function () {
|
||||
this.currentResponseCallback(this.inputBuffer.subarray(0, this.inputBufferIndex));
|
||||
this.inputBufferIndex = 0;
|
||||
this.currentResponseCallback = null;
|
||||
}.bind(this), 200);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Error callback
|
||||
* @private
|
||||
* @param info
|
||||
*/
|
||||
onError: function (info) {
|
||||
if (this.DEBUG) {
|
||||
console.log('[ERROR]: ' + info.resultCode);
|
||||
}
|
||||
|
||||
if (info.socketId === this.handle) {
|
||||
if (this.currentErrorCallback) {
|
||||
this.currentErrorCallback(info.resultCode);
|
||||
this.currentErrorCallback = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}, true);
|
||||
});
|
@@ -1,49 +0,0 @@
|
||||
/*global define */
|
||||
define(['lib/stapes'], function (Stapes) {
|
||||
'use strict';
|
||||
return Stapes.subclass(/** @lends LocalStorage.prototype */{
|
||||
|
||||
/**
|
||||
* @class LocalStorage
|
||||
* @classdesc LocalStorage handler using HTML5 localStorage
|
||||
* @constructs
|
||||
*
|
||||
* @fires got
|
||||
* @fires error
|
||||
* @fires set
|
||||
*/
|
||||
constructor: function () {
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets stored data
|
||||
*/
|
||||
get: function () {
|
||||
var data;
|
||||
|
||||
if (!window.localStorage) {
|
||||
this.emit('error', 'Local Storage not supported');
|
||||
return;
|
||||
}
|
||||
|
||||
if (localStorage.data) {
|
||||
data = JSON.parse(localStorage.data);
|
||||
this.emit('got', data);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Stores settings
|
||||
* @param {object} data - Data object to store
|
||||
*/
|
||||
set: function (data) {
|
||||
if (!window.localStorage) {
|
||||
this.emit('error', 'Local Storage not supported');
|
||||
return;
|
||||
}
|
||||
|
||||
localStorage.data = JSON.stringify(data);
|
||||
this.emit('set');
|
||||
}
|
||||
});
|
||||
});
|
@@ -1,57 +0,0 @@
|
||||
/*global define */
|
||||
define(['lib/stapes'], function (Stapes) {
|
||||
'use strict';
|
||||
return Stapes.subclass(/** @lends Network.prototype */{
|
||||
detectTimerId: null,
|
||||
|
||||
/**
|
||||
* @class Network
|
||||
* @classdesc Empty network functions handler
|
||||
* @constructs
|
||||
*/
|
||||
constructor: function () {
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the list of known local interfaces (ipv4)
|
||||
* @param {function(string[])} [onSuccess] - Callback to call on success
|
||||
* @param {function(error:string)} [onError] - Callback to call on error
|
||||
*/
|
||||
getLocalInterfaces: function (onSuccess, onError) {
|
||||
var ips = [], RTCPeerConnection;
|
||||
|
||||
// https://developer.mozilla.org/de/docs/Web/API/RTCPeerConnection
|
||||
RTCPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection || window.msRTCPeerConnection;
|
||||
|
||||
var rtc = new RTCPeerConnection({iceServers: []});
|
||||
rtc.onicecandidate = function (event) {
|
||||
var parts;
|
||||
|
||||
if (this.detectTimerId) {
|
||||
clearTimeout(this.detectTimerId);
|
||||
}
|
||||
|
||||
if (event.candidate) {
|
||||
parts = event.candidate.candidate.split(' ');
|
||||
if (ips.indexOf(parts[4]) === -1) {
|
||||
console.log(event.candidate);
|
||||
ips.push(parts[4]);
|
||||
}
|
||||
}
|
||||
|
||||
this.detectTimerId = setTimeout(function () {
|
||||
if (onSuccess) {
|
||||
onSuccess(ips);
|
||||
}
|
||||
}, 200);
|
||||
}.bind(this);
|
||||
|
||||
rtc.createDataChannel('');
|
||||
rtc.createOffer(rtc.setLocalDescription.bind(rtc), onError);
|
||||
},
|
||||
|
||||
canDetectLocalAddress: function () {
|
||||
return window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection || window.msRTCPeerConnection;
|
||||
}
|
||||
}, true);
|
||||
});
|
@@ -1,68 +0,0 @@
|
||||
/*global define */
|
||||
define(['lib/stapes'], function (Stapes) {
|
||||
'use strict';
|
||||
return Stapes.subclass(/** @lends Socket.prototype */{
|
||||
|
||||
/**
|
||||
* @class Socket
|
||||
* @abstract
|
||||
*/
|
||||
constructor: function () {
|
||||
},
|
||||
|
||||
/**
|
||||
* Create the socket
|
||||
* @param onSuccess
|
||||
* @param onError
|
||||
* @abstract
|
||||
*/
|
||||
create: function (onSuccess, onError) {
|
||||
},
|
||||
|
||||
/**
|
||||
* Check if a connection is opened.
|
||||
* @abstract
|
||||
*/
|
||||
isConnected: function () {
|
||||
return false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Connect to another peer
|
||||
* @param {Object} peer Port object
|
||||
* @param {function} [onSuccess] Callback to call on success
|
||||
* @param {function(error:string)} [onError] Callback to call on error
|
||||
* @abstract
|
||||
*/
|
||||
connect: function (peer, onSuccess, onError) {
|
||||
},
|
||||
|
||||
/**
|
||||
* Close the current connection
|
||||
* @param {function} [onSuccess] Callback to call on success
|
||||
* @param {function(error:string)} [onError] Callback to call on error
|
||||
* @abstract
|
||||
*/
|
||||
close: function (onSuccess, onError) {
|
||||
},
|
||||
|
||||
/**
|
||||
* Read data from the socket
|
||||
* @param {function} [onSuccess] Callback to call on success
|
||||
* @param {function(error:string)} [onError] Callback to call on error
|
||||
* @abstract
|
||||
*/
|
||||
read: function (onSuccess, onError) {
|
||||
},
|
||||
|
||||
/**
|
||||
* Writes data to the socket
|
||||
* @param {string | Array} data Data to send.
|
||||
* @param {function} [onSuccess] Callback to call if data was sent successfully
|
||||
* @param {function(error:string)} [onError] Callback to call on error
|
||||
* @abstract
|
||||
*/
|
||||
write: function (data, onSuccess, onError) {
|
||||
}
|
||||
}, true);
|
||||
});
|
@@ -1,229 +0,0 @@
|
||||
define(['lib/stapes', 'api/Socket', 'utils/Tools'], function (Stapes, Socket, tools) {
|
||||
'use strict';
|
||||
return Socket.subclass(/** @lends WebSocket.prototype */{
|
||||
DEBUG: false,
|
||||
|
||||
handle: null,
|
||||
|
||||
/**
|
||||
* @type {function}
|
||||
*/
|
||||
currentResponseCallback: null,
|
||||
|
||||
/**
|
||||
* @type {function}
|
||||
*/
|
||||
currentErrorCallback: null,
|
||||
|
||||
/**
|
||||
* Temporary buffer for incoming data
|
||||
* @type {Uint8Array}
|
||||
*/
|
||||
inputBuffer: null,
|
||||
inputBufferIndex: 0,
|
||||
readBufferTimerId: null,
|
||||
|
||||
/**
|
||||
* @class WebSocket
|
||||
* @extends Socket
|
||||
* @constructs
|
||||
*/
|
||||
constructor: function () {
|
||||
this.inputBuffer = new Uint8Array(4096);
|
||||
this.inputBufferIndex = 0;
|
||||
},
|
||||
|
||||
create: function (onSuccess, onError) {
|
||||
if (this.DEBUG) {
|
||||
console.log('[DEBUG] Creating socket...');
|
||||
}
|
||||
|
||||
if (onSuccess) {
|
||||
onSuccess();
|
||||
}
|
||||
},
|
||||
|
||||
isConnected: function (resultCallback) {
|
||||
if (this.DEBUG) {
|
||||
console.log('[DEBUG] Checking if socket is connected...');
|
||||
}
|
||||
|
||||
if (!this.handle) {
|
||||
if (this.DEBUG) {
|
||||
console.log('[DEBUG] Socket not created');
|
||||
}
|
||||
|
||||
if (resultCallback) {
|
||||
resultCallback(false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (resultCallback) {
|
||||
if (this.handle.readyState === WebSocket.OPEN) {
|
||||
resultCallback(true);
|
||||
} else {
|
||||
resultCallback(false);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
connect: function (server, onSuccess, onError) {
|
||||
if (this.DEBUG) {
|
||||
console.log('[DEBUG] Connecting to peer ' + server.address + ':' + server.port);
|
||||
}
|
||||
|
||||
this.currentErrorCallback = onError;
|
||||
|
||||
this.handle = new WebSocket('ws://' + server.address + ':' + server.port);
|
||||
this.handle.onmessage = this.onDataReceived.bind(this);
|
||||
this.handle.onclose = function () {
|
||||
if (this.DEBUG) {
|
||||
console.log('onClose');
|
||||
}
|
||||
}.bind(this);
|
||||
this.handle.onerror = function () {
|
||||
if (this.DEBUG) {
|
||||
console.log('[ERROR]: ');
|
||||
}
|
||||
|
||||
if (this.currentErrorCallback) {
|
||||
this.currentErrorCallback('WebSocket error');
|
||||
this.currentErrorCallback = null;
|
||||
}
|
||||
}.bind(this);
|
||||
this.handle.onopen = function () {
|
||||
if (onSuccess) {
|
||||
onSuccess();
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
close: function (onSuccess, onError) {
|
||||
if (this.DEBUG) {
|
||||
console.log('[DEBUG] Closing socket...');
|
||||
}
|
||||
|
||||
if (this.handle) {
|
||||
this.handle.close();
|
||||
if (onSuccess) {
|
||||
onSuccess();
|
||||
}
|
||||
} else {
|
||||
if (this.DEBUG) {
|
||||
console.log('[DEBUG] Socket not created');
|
||||
}
|
||||
|
||||
if (onError) {
|
||||
onError('Socket handle is invalid');
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
write: function (data, onSuccess, onError) {
|
||||
var dataToSend = null, dataType = typeof (data);
|
||||
|
||||
if (this.DEBUG) {
|
||||
console.log('[DEBUG] writing to socket...');
|
||||
}
|
||||
|
||||
if (!this.handle) {
|
||||
if (this.DEBUG) {
|
||||
console.log('[DEBUG] Socket not created');
|
||||
}
|
||||
|
||||
if (onError) {
|
||||
onError('Socket handle is invalid');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
this.isConnected(function (connected) {
|
||||
if (connected) {
|
||||
if (dataType === 'string') {
|
||||
if (this.DEBUG) {
|
||||
console.log('> ' + data);
|
||||
}
|
||||
//dataToSend = tools.str2ab(data);
|
||||
dataToSend = data;
|
||||
} else {
|
||||
if (this.DEBUG) {
|
||||
console.log('> ' + tools.ab2hexstr(data));
|
||||
}
|
||||
dataToSend = data;
|
||||
}
|
||||
|
||||
this.currentErrorCallback = onError;
|
||||
this.handle.send(dataToSend);
|
||||
|
||||
if (onSuccess) {
|
||||
onSuccess();
|
||||
}
|
||||
} else {
|
||||
if (onError) {
|
||||
onError('No connection to peer');
|
||||
}
|
||||
}
|
||||
}.bind(this));
|
||||
|
||||
},
|
||||
|
||||
read: function (onSuccess, onError) {
|
||||
if (this.DEBUG) {
|
||||
console.log('[DEBUG] reading from socket...');
|
||||
}
|
||||
|
||||
if (!this.handle) {
|
||||
if (this.DEBUG) {
|
||||
console.log('[DEBUG] socket not created');
|
||||
}
|
||||
|
||||
if (onError) {
|
||||
onError('Socket handle is invalid');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
this.isConnected(function (connected) {
|
||||
if (!connected) {
|
||||
this.currentResponseCallback = null;
|
||||
this.currentErrorCallback = null;
|
||||
|
||||
if (onError) {
|
||||
onError('No connection to peer');
|
||||
}
|
||||
}
|
||||
}.bind(this));
|
||||
|
||||
if (onSuccess) {
|
||||
this.currentResponseCallback = onSuccess;
|
||||
}
|
||||
|
||||
if (onError) {
|
||||
this.currentErrorCallback = onError;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Data receiption callback
|
||||
* @private
|
||||
* @param event
|
||||
*/
|
||||
onDataReceived: function (event) {
|
||||
if (this.DEBUG) {
|
||||
console.log('[DEBUG] received data...');
|
||||
}
|
||||
|
||||
if (this.handle && event.data) {
|
||||
if (this.DEBUG) {
|
||||
console.log('< ' + event.data);
|
||||
}
|
||||
|
||||
if (this.currentResponseCallback) {
|
||||
this.currentResponseCallback(tools.str2ab(event.data));
|
||||
this.currentResponseCallback = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}, true);
|
||||
});
|
@@ -1,534 +0,0 @@
|
||||
/*global define */
|
||||
define([
|
||||
'lib/stapes', 'views/MainView', 'models/Settings', 'views/SettingsView', 'views/EffectsView', 'views/TransformView', 'data/ServerControl', 'api/Socket', 'api/Network'
|
||||
], function (Stapes, MainView, Settings, SettingsView, EffectsView, TransformView, ServerControl, Socket, Network) {
|
||||
'use strict';
|
||||
var network = new Network();
|
||||
|
||||
return Stapes.subclass(/** @lends AppController.prototype */{
|
||||
/**
|
||||
* @type MainView
|
||||
*/
|
||||
mainView: null,
|
||||
/**
|
||||
* @type SettingsView
|
||||
*/
|
||||
settingsView: null,
|
||||
/**
|
||||
* @type EffectsView
|
||||
*/
|
||||
effectsView: null,
|
||||
/**
|
||||
* @type TransformView
|
||||
*/
|
||||
transformView: null,
|
||||
/**
|
||||
* @type Settings
|
||||
*/
|
||||
settings: null,
|
||||
/**
|
||||
* @type ServerControl
|
||||
*/
|
||||
serverControl: null,
|
||||
color: {
|
||||
r: 25,
|
||||
g: 25,
|
||||
b: 25
|
||||
},
|
||||
effects: [],
|
||||
transform: {},
|
||||
selectedServer: null,
|
||||
|
||||
/**
|
||||
* @class AppController
|
||||
* @constructs
|
||||
*/
|
||||
constructor: function () {
|
||||
this.mainView = new MainView();
|
||||
this.settingsView = new SettingsView();
|
||||
this.effectsView = new EffectsView();
|
||||
this.transformView = new TransformView();
|
||||
|
||||
this.settings = new Settings();
|
||||
|
||||
this.bindEventHandlers();
|
||||
this.mainView.setColor(this.color);
|
||||
|
||||
if (!network.canDetectLocalAddress()) {
|
||||
this.settingsView.enableDetectButton(false);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Do initialization
|
||||
*/
|
||||
init: function () {
|
||||
this.settings.load();
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
bindEventHandlers: function () {
|
||||
this.settings.on({
|
||||
'loaded': function () {
|
||||
var i;
|
||||
|
||||
for (i = 0; i < this.settings.servers.length; i++) {
|
||||
if (this.settings.servers[i].selected) {
|
||||
this.selectedServer = this.settings.servers[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this.settingsView.fillServerList(this.settings.servers);
|
||||
|
||||
if (!this.selectedServer) {
|
||||
this.gotoArea('settings');
|
||||
} else {
|
||||
this.connectToServer(this.selectedServer);
|
||||
}
|
||||
},
|
||||
'error': function (message) {
|
||||
this.showError(message);
|
||||
},
|
||||
'serverAdded': function (server) {
|
||||
var i;
|
||||
for (i = 0; i < this.settings.servers.length; i++) {
|
||||
if (this.settings.servers[i].selected) {
|
||||
this.selectedServer = this.settings.servers[i];
|
||||
this.connectToServer(server);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this.settingsView.fillServerList(this.settings.servers);
|
||||
},
|
||||
'serverChanged': function (server) {
|
||||
var i;
|
||||
for (i = 0; i < this.settings.servers.length; i++) {
|
||||
if (this.settings.servers[i].selected) {
|
||||
this.selectedServer = this.settings.servers[i];
|
||||
this.connectToServer(server);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this.settingsView.fillServerList(this.settings.servers);
|
||||
this.connectToServer(server);
|
||||
},
|
||||
'serverRemoved': function () {
|
||||
var i, removedSelected = true;
|
||||
this.settingsView.fillServerList(this.settings.servers);
|
||||
|
||||
for (i = 0; i < this.settings.servers.length; i++) {
|
||||
if (this.settings.servers[i].selected) {
|
||||
removedSelected = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (removedSelected) {
|
||||
this.selectedServer = null;
|
||||
if (this.serverControl) {
|
||||
this.serverControl.disconnect();
|
||||
}
|
||||
this.effectsView.clear();
|
||||
this.transformView.clear();
|
||||
}
|
||||
}
|
||||
}, this);
|
||||
|
||||
this.mainView.on({
|
||||
'barClick': function (id) {
|
||||
if (id !== 'settings') {
|
||||
if (!this.selectedServer) {
|
||||
this.showError('No server selected');
|
||||
} else if (!this.serverControl) {
|
||||
this.connectToServer(this.selectedServer);
|
||||
}
|
||||
}
|
||||
this.gotoArea(id);
|
||||
},
|
||||
'colorChange': function (color) {
|
||||
this.color = color;
|
||||
|
||||
if (!this.selectedServer) {
|
||||
this.showError('No server selected');
|
||||
} else if (!this.serverControl) {
|
||||
this.connectToServer(this.selectedServer, function () {
|
||||
this.serverControl.setColor(color, this.selectedServer.duration);
|
||||
}.bind(this));
|
||||
} else {
|
||||
this.serverControl.setColor(color, this.selectedServer.duration);
|
||||
}
|
||||
},
|
||||
'clear': function () {
|
||||
if (!this.selectedServer) {
|
||||
this.showError('No server selected');
|
||||
} else if (!this.serverControl) {
|
||||
this.connectToServer(this.selectedServer, function () {
|
||||
this.serverControl.clear();
|
||||
}.bind(this));
|
||||
} else {
|
||||
this.serverControl.clear();
|
||||
}
|
||||
},
|
||||
'clearall': function () {
|
||||
if (!this.selectedServer) {
|
||||
this.showError('No server selected');
|
||||
} else if (!this.serverControl) {
|
||||
this.connectToServer(this.selectedServer, function () {
|
||||
this.serverControl.clearall();
|
||||
this.mainView.setColor({r: 0, g: 0, b: 0});
|
||||
}.bind(this));
|
||||
} else {
|
||||
this.serverControl.clearall();
|
||||
this.mainView.setColor({r: 0, g: 0, b: 0});
|
||||
}
|
||||
}
|
||||
}, this);
|
||||
|
||||
this.settingsView.on({
|
||||
'serverAdded': function (server) {
|
||||
if (server.address && server.port) {
|
||||
server.priority = server.priority || 50;
|
||||
this.settings.addServer(server);
|
||||
this.lockSettingsView(false);
|
||||
} else {
|
||||
this.showError('Invalid server data');
|
||||
}
|
||||
},
|
||||
'serverAddCanceled': function () {
|
||||
this.lockSettingsView(false);
|
||||
this.settingsView.fillServerList(this.settings.servers);
|
||||
},
|
||||
'serverEditCanceled': function () {
|
||||
this.lockSettingsView(false);
|
||||
this.settingsView.fillServerList(this.settings.servers);
|
||||
},
|
||||
'serverSelected': function (index) {
|
||||
this.lockSettingsView(false);
|
||||
this.settings.setSelectedServer(index);
|
||||
},
|
||||
'serverRemoved': function (index) {
|
||||
this.settings.removeServer(index);
|
||||
},
|
||||
'serverChanged': function (data) {
|
||||
if (data.server.address && data.server.port) {
|
||||
data.server.priority = data.server.priority || 50;
|
||||
this.settings.updateServer(data.index, data.server);
|
||||
this.lockSettingsView(false);
|
||||
} else {
|
||||
this.showError('Invalid server data');
|
||||
}
|
||||
},
|
||||
'editServer': function (index) {
|
||||
var server = this.settings.servers[index];
|
||||
this.settingsView.editServer({index: index, server: server});
|
||||
},
|
||||
'durationChanged': function (value) {
|
||||
this.settings.duration = value;
|
||||
this.settings.save();
|
||||
},
|
||||
'detect': function () {
|
||||
this.lockSettingsView(true);
|
||||
this.settingsView.showWaiting(true);
|
||||
this.searchForServer(function (server) {
|
||||
this.settings.addServer(server);
|
||||
}.bind(this), function () {
|
||||
this.lockSettingsView(false);
|
||||
this.settingsView.showWaiting(false);
|
||||
}.bind(this));
|
||||
}
|
||||
}, this);
|
||||
|
||||
this.effectsView.on({
|
||||
'effectSelected': function (effectId) {
|
||||
if (!this.serverControl) {
|
||||
this.connectToServer(this.selectedServer, function () {
|
||||
this.serverControl.runEffect(this.effects[parseInt(effectId)]);
|
||||
}.bind(this));
|
||||
} else {
|
||||
this.serverControl.runEffect(this.effects[parseInt(effectId)]);
|
||||
}
|
||||
}
|
||||
}, this);
|
||||
|
||||
this.transformView.on({
|
||||
'gamma': function (data) {
|
||||
if (data.r) {
|
||||
this.transform.gamma[0] = data.r;
|
||||
} else if (data.g) {
|
||||
this.transform.gamma[1] = data.g;
|
||||
} else if (data.b) {
|
||||
this.transform.gamma[2] = data.b;
|
||||
}
|
||||
|
||||
if (this.serverControl) {
|
||||
this.serverControl.setTransform(this.transform);
|
||||
}
|
||||
},
|
||||
'whitelevel': function (data) {
|
||||
if (data.r) {
|
||||
this.transform.whitelevel[0] = data.r;
|
||||
} else if (data.g) {
|
||||
this.transform.whitelevel[1] = data.g;
|
||||
} else if (data.b) {
|
||||
this.transform.whitelevel[2] = data.b;
|
||||
}
|
||||
|
||||
if (this.serverControl) {
|
||||
this.serverControl.setTransform(this.transform);
|
||||
}
|
||||
},
|
||||
'blacklevel': function (data) {
|
||||
if (data.r) {
|
||||
this.transform.blacklevel[0] = data.r;
|
||||
} else if (data.g) {
|
||||
this.transform.blacklevel[1] = data.g;
|
||||
} else if (data.b) {
|
||||
this.transform.blacklevel[2] = data.b;
|
||||
}
|
||||
|
||||
if (this.serverControl) {
|
||||
this.serverControl.setTransform(this.transform);
|
||||
}
|
||||
},
|
||||
'threshold': function (data) {
|
||||
if (data.r) {
|
||||
this.transform.threshold[0] = data.r;
|
||||
} else if (data.g) {
|
||||
this.transform.threshold[1] = data.g;
|
||||
} else if (data.b) {
|
||||
this.transform.threshold[2] = data.b;
|
||||
}
|
||||
|
||||
if (this.serverControl) {
|
||||
this.serverControl.setTransform(this.transform);
|
||||
}
|
||||
},
|
||||
'hsv': function (data) {
|
||||
if (data.valueGain) {
|
||||
this.transform.valueGain = data.valueGain;
|
||||
} else if (data.saturationGain) {
|
||||
this.transform.saturationGain = data.saturationGain;
|
||||
}
|
||||
|
||||
if (this.serverControl) {
|
||||
this.serverControl.setTransform(this.transform);
|
||||
}
|
||||
}
|
||||
}, this);
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param id
|
||||
*/
|
||||
gotoArea: function (id) {
|
||||
this.mainView.scrollToArea(id);
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param server
|
||||
*/
|
||||
connectToServer: function (server, onConnected) {
|
||||
if (this.serverControl) {
|
||||
if (this.serverControl.isConnecting()) {
|
||||
return;
|
||||
}
|
||||
this.serverControl.off();
|
||||
this.serverControl.disconnect();
|
||||
this.transformView.clear();
|
||||
this.effectsView.clear();
|
||||
}
|
||||
|
||||
this.serverControl = new ServerControl(server, Socket);
|
||||
this.serverControl.on({
|
||||
connected: function () {
|
||||
this.serverControl.getServerInfo();
|
||||
},
|
||||
serverInfo: function (info) {
|
||||
var index;
|
||||
if (!this.selectedServer.name || this.selectedServer.name.length === 0) {
|
||||
this.selectedServer.name = info.hostname;
|
||||
index = this.settings.indexOfServer(this.selectedServer);
|
||||
this.settings.updateServer(index, this.selectedServer);
|
||||
this.settingsView.fillServerList(this.settings.servers);
|
||||
}
|
||||
this.effects = info.effects;
|
||||
this.transform = info.transform[0];
|
||||
this.updateView();
|
||||
this.showStatus('Connected to ' + this.selectedServer.name);
|
||||
if (onConnected) {
|
||||
onConnected();
|
||||
}
|
||||
},
|
||||
error: function (message) {
|
||||
this.serverControl = null;
|
||||
this.showError(message);
|
||||
}
|
||||
}, this);
|
||||
this.serverControl.connect();
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
updateView: function () {
|
||||
var i, effects = [];
|
||||
if (this.effects) {
|
||||
for (i = 0; i < this.effects.length; i++) {
|
||||
effects.push({id: i, name: this.effects[i].name});
|
||||
}
|
||||
}
|
||||
|
||||
this.effectsView.clear();
|
||||
this.effectsView.fillList(effects);
|
||||
|
||||
this.transformView.clear();
|
||||
this.transformView.fillList(this.transform);
|
||||
},
|
||||
|
||||
/**
|
||||
* Shows the error text
|
||||
* @param {string} error - Error message
|
||||
*/
|
||||
showError: function (error) {
|
||||
this.mainView.showError(error);
|
||||
},
|
||||
|
||||
/**
|
||||
* Shows a message
|
||||
* @param {string} message - Text to show
|
||||
*/
|
||||
showStatus: function (message) {
|
||||
this.mainView.showStatus(message);
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param lock
|
||||
*/
|
||||
lockSettingsView: function (lock) {
|
||||
if (network.canDetectLocalAddress()) {
|
||||
this.settingsView.enableDetectButton(!lock);
|
||||
}
|
||||
this.settingsView.lockList(lock);
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param onFound
|
||||
* @param onEnd
|
||||
*/
|
||||
searchForServer: function (onFound, onEnd) {
|
||||
network.getLocalInterfaces(function (ips) {
|
||||
if (ips.length === 0) {
|
||||
onEnd();
|
||||
return;
|
||||
}
|
||||
|
||||
function checkInterface (localInterfaceAddress, ciOnFinished) {
|
||||
var index, ipParts, addr;
|
||||
|
||||
index = 1;
|
||||
ipParts = localInterfaceAddress.split('.');
|
||||
ipParts[3] = index;
|
||||
addr = ipParts.join('.');
|
||||
|
||||
function checkAddressRange (startAddress, count, carOnFinished) {
|
||||
var ipParts, i, addr, cbCounter = 0, last;
|
||||
|
||||
function checkAddress (address, port, caOnFinished) {
|
||||
var server = new ServerControl({'address': address, 'port': port}, Socket);
|
||||
server.on({
|
||||
'error': function () {
|
||||
server.disconnect();
|
||||
caOnFinished();
|
||||
},
|
||||
'connected': function () {
|
||||
server.getServerInfo();
|
||||
},
|
||||
'serverInfo': function (result) {
|
||||
var serverInfo = {
|
||||
'address': address,
|
||||
'port': port,
|
||||
'priority': 50
|
||||
};
|
||||
server.disconnect();
|
||||
|
||||
if (result.hostname) {
|
||||
serverInfo.name = result.hostname;
|
||||
}
|
||||
|
||||
caOnFinished(serverInfo);
|
||||
}
|
||||
});
|
||||
server.connect();
|
||||
}
|
||||
|
||||
function checkAddressDoneCb (serverInfo) {
|
||||
var ipParts, nextAddr;
|
||||
|
||||
if (serverInfo && onFound) {
|
||||
onFound(serverInfo);
|
||||
}
|
||||
|
||||
cbCounter++;
|
||||
if (cbCounter === count) {
|
||||
ipParts = startAddress.split('.');
|
||||
ipParts[3] = parseInt(ipParts[3]) + count;
|
||||
nextAddr = ipParts.join('.');
|
||||
carOnFinished(nextAddr);
|
||||
}
|
||||
}
|
||||
|
||||
ipParts = startAddress.split('.');
|
||||
last = parseInt(ipParts[3]);
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
ipParts[3] = last + i;
|
||||
addr = ipParts.join('.');
|
||||
|
||||
checkAddress(addr, 19444, checkAddressDoneCb);
|
||||
}
|
||||
}
|
||||
|
||||
function checkAddressRangeCb (nextAddr) {
|
||||
var ipParts, count = 64, lastPart;
|
||||
|
||||
ipParts = nextAddr.split('.');
|
||||
lastPart = parseInt(ipParts[3]);
|
||||
if (lastPart === 255) {
|
||||
ciOnFinished();
|
||||
return;
|
||||
} else if (lastPart + 64 > 254) {
|
||||
count = 255 - lastPart;
|
||||
}
|
||||
|
||||
checkAddressRange(nextAddr, count, checkAddressRangeCb);
|
||||
}
|
||||
|
||||
// do search in chunks because the dispatcher used in the ios socket plugin can handle only 64 threads
|
||||
checkAddressRange(addr, 64, checkAddressRangeCb);
|
||||
}
|
||||
|
||||
function checkInterfaceCb () {
|
||||
if (ips.length === 0) {
|
||||
onEnd();
|
||||
} else {
|
||||
checkInterface(ips.pop(), checkInterfaceCb);
|
||||
}
|
||||
}
|
||||
|
||||
checkInterface(ips.pop(), checkInterfaceCb);
|
||||
|
||||
}.bind(this), function (error) {
|
||||
this.showError(error);
|
||||
}.bind(this));
|
||||
}
|
||||
});
|
||||
});
|
@@ -1,201 +0,0 @@
|
||||
/*global define */
|
||||
define(['lib/stapes', 'utils/Tools'], function (Stapes, tools) {
|
||||
'use strict';
|
||||
|
||||
return Stapes.subclass(/** @lends ServerControl.prototype */{
|
||||
/** @type Socket */
|
||||
socket: null,
|
||||
server: null,
|
||||
connecting: false,
|
||||
|
||||
/**
|
||||
* @class ServerControl
|
||||
* @classdesc Interface for the hyperion server control. All commands are sent directly to hyperion's server.
|
||||
* @constructs
|
||||
* @param {object} server - Hyperion server parameter
|
||||
* @param {string} server.address - Server address
|
||||
* @param {number} server.port - Hyperion server port
|
||||
* @param {function} Socket - constructor of the socket to use for communication
|
||||
*
|
||||
* @fires connected
|
||||
* @fires error
|
||||
* @fires serverInfo
|
||||
* @fires cmdSent
|
||||
*/
|
||||
constructor: function (server, Socket) {
|
||||
this.server = server;
|
||||
this.socket = new Socket();
|
||||
this.connecting = false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Try to connect to the server
|
||||
*/
|
||||
connect: function () {
|
||||
if (!this.server) {
|
||||
this.emit('error', 'Missing server info');
|
||||
} else {
|
||||
this.connecting = true;
|
||||
this.socket.create(function () {
|
||||
this.socket.connect(this.server, function () {
|
||||
this.emit('connected');
|
||||
this.connecting = false;
|
||||
}.bind(this), function (error) {
|
||||
this.socket.close();
|
||||
this.emit('error', error);
|
||||
this.connecting = false;
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Disconnect from the server
|
||||
*/
|
||||
disconnect: function () {
|
||||
this.socket.close();
|
||||
},
|
||||
|
||||
/**
|
||||
* Sends the color command to the server
|
||||
* @param {object} color - Color to set
|
||||
* @param {number} color.r - Red value
|
||||
* @param {number} color.g - Green value
|
||||
* @param {number} color.b - Blue value
|
||||
* @param {number} duration - Duration in seconds
|
||||
*/
|
||||
setColor: function (color, duration) {
|
||||
var intColor, cmd;
|
||||
|
||||
intColor = [
|
||||
Math.floor(color.r), Math.floor(color.g), Math.floor(color.b)
|
||||
];
|
||||
cmd = {
|
||||
command: 'color',
|
||||
color: intColor,
|
||||
priority: this.server.priority
|
||||
};
|
||||
|
||||
if (duration) {
|
||||
cmd.duration = duration * 1000;
|
||||
}
|
||||
|
||||
this.sendCommand(cmd);
|
||||
},
|
||||
|
||||
clear: function () {
|
||||
var cmd = {
|
||||
command: 'clear',
|
||||
priority: this.server.priority
|
||||
};
|
||||
this.sendCommand(cmd);
|
||||
},
|
||||
|
||||
clearall: function () {
|
||||
var cmd = {
|
||||
command: 'clearall'
|
||||
};
|
||||
this.sendCommand(cmd);
|
||||
},
|
||||
|
||||
/**
|
||||
* Sends a command to rund specified effect
|
||||
* @param {object} effect - Effect object
|
||||
*/
|
||||
runEffect: function (effect) {
|
||||
var cmd;
|
||||
|
||||
if (!effect) {
|
||||
return;
|
||||
}
|
||||
|
||||
cmd = {
|
||||
command: 'effect',
|
||||
effect: {
|
||||
name: effect.name,
|
||||
args: effect.args
|
||||
},
|
||||
priority: this.server.priority
|
||||
};
|
||||
this.sendCommand(cmd);
|
||||
},
|
||||
|
||||
/**
|
||||
* Sends a command for color transformation
|
||||
* @param {object} transform
|
||||
*/
|
||||
setTransform: function (transform) {
|
||||
var cmd;
|
||||
|
||||
if (!transform) {
|
||||
return;
|
||||
}
|
||||
|
||||
cmd = {
|
||||
'command': 'transform',
|
||||
'transform': transform
|
||||
};
|
||||
|
||||
this.sendCommand(cmd);
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param command
|
||||
*/
|
||||
sendCommand: function (command) {
|
||||
var data;
|
||||
|
||||
if (!command) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof command === 'string') {
|
||||
data = command;
|
||||
} else {
|
||||
data = JSON.stringify(command);
|
||||
}
|
||||
|
||||
this.socket.isConnected(function (connected) {
|
||||
if (connected) {
|
||||
this.socket.write(data + '\n', function () {
|
||||
this.emit('cmdSent', command);
|
||||
}.bind(this), function (error) {
|
||||
this.emit('error', error);
|
||||
}.bind(this));
|
||||
} else {
|
||||
this.emit('error', 'No server connection');
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the information about the hyperion server
|
||||
*/
|
||||
getServerInfo: function () {
|
||||
var cmd = {command: 'serverinfo'};
|
||||
|
||||
this.socket.isConnected(function (connected) {
|
||||
if (connected) {
|
||||
this.socket.write(JSON.stringify(cmd) + '\n', function () {
|
||||
this.socket.read(function (result) {
|
||||
var dataobj, str = tools.ab2str(result);
|
||||
dataobj = JSON.parse(str);
|
||||
this.emit('serverInfo', dataobj.info);
|
||||
}.bind(this), function (error) {
|
||||
this.emit('error', error);
|
||||
}.bind(this));
|
||||
}.bind(this), function (error) {
|
||||
this.emit('error', error);
|
||||
}.bind(this));
|
||||
} else {
|
||||
this.emit('error', 'No server connection');
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
isConnecting: function () {
|
||||
return this.connecting;
|
||||
}
|
||||
});
|
||||
});
|
@@ -1,150 +0,0 @@
|
||||
/*global require, requirejs */
|
||||
|
||||
requirejs.config({
|
||||
baseUrl: 'js/app',
|
||||
paths: {
|
||||
'lib': '../vendor'
|
||||
},
|
||||
map: {
|
||||
'controllers/AppController': {
|
||||
'api/Socket': 'api/WebSocket'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @param {HTMLElement} dom
|
||||
* @param {function} handler
|
||||
*/
|
||||
window.addPointerDownHandler = function (dom, handler) {
|
||||
'use strict';
|
||||
dom.addEventListener('touchstart', handler, false);
|
||||
dom.addEventListener('mousedown', handler, false);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {HTMLElement} dom
|
||||
* @param {function} handler
|
||||
*/
|
||||
window.removePointerDownHandler = function (dom, handler) {
|
||||
'use strict';
|
||||
dom.removeEventListener('touchstart', handler, false);
|
||||
dom.removeEventListener('mousedown', handler, false);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {HTMLElement} dom
|
||||
* @param {function} handler
|
||||
*/
|
||||
window.addPointerUpHandler = function (dom, handler) {
|
||||
'use strict';
|
||||
dom.addEventListener('touchend', handler, false);
|
||||
dom.addEventListener('mouseup', handler, false);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {HTMLElement} dom
|
||||
* @param {function} handler
|
||||
*/
|
||||
window.removePointerUpHandler = function (dom, handler) {
|
||||
'use strict';
|
||||
dom.removeEventListener('touchend', handler, false);
|
||||
dom.removeEventListener('mouseup', handler, false);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {HTMLElement} dom
|
||||
* @param {function} handler
|
||||
*/
|
||||
window.addPointerMoveHandler = function (dom, handler) {
|
||||
'use strict';
|
||||
dom.addEventListener('touchmove', handler, false);
|
||||
dom.addEventListener('mousemove', handler, false);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {HTMLElement} dom
|
||||
* @param {function} handler
|
||||
*/
|
||||
window.removePointerMoveHandler = function (dom, handler) {
|
||||
'use strict';
|
||||
dom.removeEventListener('touchmove', handler, false);
|
||||
dom.removeEventListener('mousemove', handler, false);
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {HTMLElement} dom
|
||||
* @param {function} handler
|
||||
*/
|
||||
window.addClickHandler = function (dom, handler) {
|
||||
'use strict';
|
||||
var toFire = false;
|
||||
|
||||
dom.addEventListener('touchstart', function (event) {
|
||||
if (event.touches.length > 1) {
|
||||
return;
|
||||
}
|
||||
toFire = true;
|
||||
}, false);
|
||||
|
||||
dom.addEventListener('touchmove', function () {
|
||||
toFire = false;
|
||||
}, false);
|
||||
|
||||
dom.addEventListener('touchend', function (event) {
|
||||
var focused;
|
||||
if (toFire) {
|
||||
handler.apply(this, arguments);
|
||||
|
||||
focused = document.querySelector(':focus');
|
||||
|
||||
if (focused && event.target !== focused) {
|
||||
focused.blur();
|
||||
}
|
||||
|
||||
if (event.target.tagName !== 'INPUT') {
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
}, false);
|
||||
|
||||
dom.addEventListener('click', function () {
|
||||
handler.apply(this, arguments);
|
||||
}, false);
|
||||
};
|
||||
|
||||
function checkInstallFirefoxOS() {
|
||||
'use strict';
|
||||
var manifest_url, installCheck;
|
||||
|
||||
manifest_url = [location.protocol, '//', location.host, location.pathname.replace('index.html',''), 'manifest.webapp'].join('');
|
||||
installCheck = navigator.mozApps.checkInstalled(manifest_url);
|
||||
|
||||
installCheck.onerror = function() {
|
||||
alert('Error calling checkInstalled: ' + installCheck.error.name);
|
||||
};
|
||||
|
||||
installCheck.onsuccess = function() {
|
||||
var installLoc;
|
||||
if(!installCheck.result) {
|
||||
if (confirm('Do you want to install hyperion remote contorl on your device?')) {
|
||||
installLoc = navigator.mozApps.install(manifest_url);
|
||||
installLoc.onsuccess = function(data) {
|
||||
};
|
||||
installLoc.onerror = function() {
|
||||
alert(installLoc.error.name);
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
require(['controllers/AppController'], function (AppController) {
|
||||
'use strict';
|
||||
var app = new AppController();
|
||||
app.init();
|
||||
if (navigator.mozApps && navigator.userAgent.indexOf('Mozilla/5.0 (Mobile;') !== -1) {
|
||||
checkInstallFirefoxOS();
|
||||
}
|
||||
});
|
@@ -1,108 +0,0 @@
|
||||
/*global require, requirejs */
|
||||
|
||||
requirejs.config({
|
||||
baseUrl: '../js/app',
|
||||
paths: {
|
||||
'lib': '../vendor'
|
||||
},
|
||||
map: {
|
||||
'controllers/AppController': {
|
||||
'api/Socket': 'api/ChromeTcpSocket',
|
||||
'api/Network': 'api/ChromeNetwork'
|
||||
},
|
||||
'models/Settings': {
|
||||
'api/LocalStorage': 'api/ChromeLocalStorage'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {HTMLElement} dom
|
||||
* @param {function} handler
|
||||
*/
|
||||
window.addPointerDownHandler = function (dom, handler) {
|
||||
'use strict';
|
||||
dom.addEventListener('touchstart', function (event) {
|
||||
handler.apply(this, arguments);
|
||||
event.preventDefault();
|
||||
}, false);
|
||||
|
||||
dom.addEventListener('mousedown', function () {
|
||||
handler.apply(this, arguments);
|
||||
}, false);
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {HTMLElement} dom
|
||||
* @param {function} handler
|
||||
*/
|
||||
window.addPointerUpHandler = function (dom, handler) {
|
||||
'use strict';
|
||||
dom.addEventListener('touchend', function (event) {
|
||||
handler.apply(this, arguments);
|
||||
event.preventDefault();
|
||||
}, false);
|
||||
|
||||
dom.addEventListener('mouseup', function () {
|
||||
handler.apply(this, arguments);
|
||||
}, false);
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {HTMLElement} dom
|
||||
* @param {function} handler
|
||||
*/
|
||||
window.addPointerMoveHandler = function (dom, handler) {
|
||||
'use strict';
|
||||
dom.addEventListener('touchmove', function (event) {
|
||||
handler.apply(this, arguments);
|
||||
event.preventDefault();
|
||||
}, false);
|
||||
|
||||
dom.addEventListener('mousemove', function () {
|
||||
handler.apply(this, arguments);
|
||||
}, false);
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {HTMLElement} dom
|
||||
* @param {function} handler
|
||||
*/
|
||||
window.addClickHandler = function (dom, handler) {
|
||||
'use strict';
|
||||
var toFire = false;
|
||||
|
||||
dom.addEventListener('touchstart', function (event) {
|
||||
if (event.touches.length > 1) {
|
||||
return;
|
||||
}
|
||||
toFire = true;
|
||||
}, false);
|
||||
|
||||
dom.addEventListener('touchmove', function () {
|
||||
toFire = false;
|
||||
}, false);
|
||||
|
||||
dom.addEventListener('touchend', function (event) {
|
||||
if (toFire) {
|
||||
handler.apply(this, arguments);
|
||||
if (event.target.tagName !== 'INPUT') {
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
}, false);
|
||||
|
||||
dom.addEventListener('click', function () {
|
||||
handler.apply(this, arguments);
|
||||
}, false);
|
||||
};
|
||||
|
||||
require(['controllers/AppController'], function (AppController) {
|
||||
'use strict';
|
||||
var app = new AppController();
|
||||
app.init();
|
||||
});
|
@@ -1,124 +0,0 @@
|
||||
/*global define */
|
||||
define(['lib/stapes', 'api/LocalStorage'], function (Stapes, LocalStorage) {
|
||||
'use strict';
|
||||
|
||||
return Stapes.subclass(/** @lends Settings.prototype */{
|
||||
storage: null, servers: [],
|
||||
|
||||
/**
|
||||
* @class Settings
|
||||
* @classdesc Local application settings
|
||||
* @constructs
|
||||
* @fires saved
|
||||
* @fires loaded
|
||||
* @fires error
|
||||
* @fires serverAdded
|
||||
* @fires serverChanged
|
||||
* @fires serverRemoved
|
||||
*/
|
||||
constructor: function () {
|
||||
this.storage = new LocalStorage();
|
||||
this.storage.on({
|
||||
error: function (message) {
|
||||
this.emit('error', message);
|
||||
}, got: function (settings) {
|
||||
if (settings) {
|
||||
this.servers = settings.servers || [];
|
||||
}
|
||||
this.emit('loaded');
|
||||
}, set: function () {
|
||||
this.emit('saved');
|
||||
}
|
||||
}, this);
|
||||
},
|
||||
|
||||
/**
|
||||
* Save current settings
|
||||
*/
|
||||
save: function () {
|
||||
this.storage.set({
|
||||
servers: this.servers
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Loads persistent settings
|
||||
*/
|
||||
load: function () {
|
||||
this.storage.get();
|
||||
},
|
||||
|
||||
/**
|
||||
* Add a server definition
|
||||
* @param {object} server - Server information
|
||||
*/
|
||||
addServer: function (server) {
|
||||
if (this.indexOfServer(server) === -1) {
|
||||
if (this.servers.length === 0) {
|
||||
server.selected = true;
|
||||
}
|
||||
|
||||
this.servers.push(server);
|
||||
this.save();
|
||||
this.emit('serverAdded', server);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets a server as a default server
|
||||
* @param {number} index - Index of the server in the server list to set as default one
|
||||
*/
|
||||
setSelectedServer: function (index) {
|
||||
var i;
|
||||
for (i = 0; i < this.servers.length; i++) {
|
||||
delete this.servers[i].selected;
|
||||
}
|
||||
this.servers[index].selected = true;
|
||||
this.save();
|
||||
this.emit('serverChanged', this.servers[index]);
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove a server from the list
|
||||
* @param {number} index - Index of the server in the list to remove
|
||||
*/
|
||||
removeServer: function (index) {
|
||||
this.servers.splice(index, 1);
|
||||
this.save();
|
||||
this.emit('serverRemoved');
|
||||
},
|
||||
|
||||
/**
|
||||
* Update server information
|
||||
* @param {number} index - Index of the server to update
|
||||
* @param {object} server - New server information
|
||||
*/
|
||||
updateServer: function (index, server) {
|
||||
if (index >= 0 && index < this.servers.length) {
|
||||
this.servers[index] = server;
|
||||
this.save();
|
||||
this.emit('serverChanged', server);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Find the server in the list.
|
||||
* @param {object} server - Server to search index for
|
||||
* @returns {number} - Index of the server in the list. -1 if server not found
|
||||
*/
|
||||
indexOfServer: function (server) {
|
||||
var i, tmp;
|
||||
|
||||
for (i = 0; i < this.servers.length; i++) {
|
||||
tmp = this.servers[i];
|
||||
|
||||
if (tmp.port === server.port && tmp.address === server.address) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
});
|
||||
});
|
@@ -1,56 +0,0 @@
|
||||
define([], function () {
|
||||
'use strict';
|
||||
|
||||
return {
|
||||
/**
|
||||
* Convert a string to ArrayBuffer
|
||||
* @param {string} str String to convert
|
||||
* @returns {ArrayBuffer} Result
|
||||
*/
|
||||
str2ab: function (str) {
|
||||
var i, buf = new ArrayBuffer(str.length), bufView = new Uint8Array(buf);
|
||||
for (i = 0; i < str.length; i++) {
|
||||
bufView[i] = str.charCodeAt(i);
|
||||
}
|
||||
return buf;
|
||||
},
|
||||
|
||||
/**
|
||||
* Convert an array to ArrayBuffer
|
||||
* @param array
|
||||
* @returns {ArrayBuffer} Result
|
||||
*/
|
||||
a2ab: function (array) {
|
||||
return new Uint8Array(array).buffer;
|
||||
},
|
||||
|
||||
/**
|
||||
* Convert ArrayBuffer to string
|
||||
* @param {ArrayBuffer} buffer Buffer to convert
|
||||
* @returns {string}
|
||||
*/
|
||||
ab2hexstr: function (buffer) {
|
||||
var i, str = '', ua = new Uint8Array(buffer);
|
||||
for (i = 0; i < ua.length; i++) {
|
||||
str += this.b2hexstr(ua[i]);
|
||||
}
|
||||
return str;
|
||||
},
|
||||
|
||||
/**
|
||||
* Convert byte to hexstr.
|
||||
* @param {number} byte Byte to convert
|
||||
*/
|
||||
b2hexstr: function (byte) {
|
||||
return ('00' + byte.toString(16)).substr(-2);
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {ArrayBuffer} buffer
|
||||
* @returns {string}
|
||||
*/
|
||||
ab2str: function (buffer) {
|
||||
return String.fromCharCode.apply(null, new Uint8Array(buffer));
|
||||
}
|
||||
};
|
||||
});
|
@@ -1,64 +0,0 @@
|
||||
/**
|
||||
* hyperion remote
|
||||
* MIT License
|
||||
*/
|
||||
|
||||
define(['lib/stapes'], function (Stapes) {
|
||||
'use strict';
|
||||
|
||||
return Stapes.subclass(/** @lends EffectsView.prototype */{
|
||||
/**
|
||||
* @class EffectsView
|
||||
* @constructs
|
||||
*/
|
||||
constructor: function () {
|
||||
this.bindEventHandlers();
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
bindEventHandlers: function () {
|
||||
window.addClickHandler(document.querySelector('#effects ul'), function (event) {
|
||||
var selected = event.target.parentNode.querySelector('.selected');
|
||||
if (selected) {
|
||||
selected.classList.remove('selected');
|
||||
}
|
||||
event.target.classList.add('selected');
|
||||
this.emit('effectSelected', event.target.dataset.id);
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
/**
|
||||
* Clear the list
|
||||
*/
|
||||
clear: function () {
|
||||
document.querySelector('#effects ul').innerHTML = '';
|
||||
document.querySelector('#effects .info').classList.add('hidden');
|
||||
},
|
||||
|
||||
/**
|
||||
* Fill the list
|
||||
* @param {object} effects - Object containing effect information
|
||||
*/
|
||||
fillList: function (effects) {
|
||||
var dom, el, i;
|
||||
|
||||
dom = document.createDocumentFragment();
|
||||
|
||||
for (i = 0; i < effects.length; i++) {
|
||||
el = document.createElement('li');
|
||||
el.innerHTML = effects[i].name;
|
||||
el.dataset.id = effects[i].id;
|
||||
dom.appendChild(el);
|
||||
}
|
||||
|
||||
document.querySelector('#effects ul').appendChild(dom);
|
||||
|
||||
if (effects.length === 0) {
|
||||
document.querySelector('#effects .info').classList.remove('hidden');
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@@ -1,402 +0,0 @@
|
||||
define([
|
||||
'lib/stapes',
|
||||
'lib/tinycolor',
|
||||
'utils/Tools',
|
||||
'views/Slider'
|
||||
], function (Stapes, Tinycolor, tools, Slider) {
|
||||
'use strict';
|
||||
var timer;
|
||||
|
||||
function showMessageField (text, type) {
|
||||
var dom, wrapper;
|
||||
|
||||
dom = document.querySelector('.work .msg');
|
||||
|
||||
if (!dom) {
|
||||
dom = document.createElement('div');
|
||||
dom.classList.add('msg');
|
||||
dom.classList.add(type);
|
||||
wrapper = document.createElement('div');
|
||||
wrapper.classList.add('wrapper_msg');
|
||||
wrapper.classList.add('invisible');
|
||||
wrapper.appendChild(dom);
|
||||
|
||||
document.querySelector('.work').appendChild(wrapper);
|
||||
setTimeout(function () {
|
||||
wrapper.classList.remove('invisible');
|
||||
}, 0);
|
||||
}
|
||||
|
||||
if (!dom.classList.contains(type)) {
|
||||
dom.className = 'msg';
|
||||
dom.classList.add(type);
|
||||
}
|
||||
dom.innerHTML = text;
|
||||
if (timer) {
|
||||
clearTimeout(timer);
|
||||
}
|
||||
timer = setTimeout(function () {
|
||||
var error = document.querySelector('.work .wrapper_msg');
|
||||
if (error) {
|
||||
error.parentNode.removeChild(error);
|
||||
}
|
||||
}, 1600);
|
||||
}
|
||||
|
||||
return Stapes.subclass(/** @lends MainView.prototype*/{
|
||||
pointer: null,
|
||||
colorpicker: null,
|
||||
slider: null,
|
||||
sliderinput: null,
|
||||
cpradius: 0,
|
||||
cpcenter: 0,
|
||||
drag: false,
|
||||
color: null,
|
||||
brightness: 1.0,
|
||||
inputbox: null,
|
||||
|
||||
/**
|
||||
* @class MainView
|
||||
* @construct
|
||||
* @fires barClick
|
||||
* @fires colorChange
|
||||
*/
|
||||
constructor: function () {
|
||||
var ev;
|
||||
this.pointer = document.querySelector('#colorpicker #pointer');
|
||||
this.colorpicker = document.querySelector('#colorpicker #colorwheelbg');
|
||||
this.slider = new Slider({
|
||||
element: document.getElementById('brightness'),
|
||||
min: 0,
|
||||
max: 1,
|
||||
step: 0.02,
|
||||
value: 1
|
||||
});
|
||||
this.inputbox = document.querySelector('#color input.value');
|
||||
|
||||
this.cpradius = this.colorpicker.offsetWidth / 2;
|
||||
this.cpcenter = this.colorpicker.offsetLeft + this.cpradius;
|
||||
|
||||
this.bindEventHandlers();
|
||||
|
||||
ev = document.createEvent('Event');
|
||||
ev.initEvent('resize', true, true);
|
||||
window.dispatchEvent(ev);
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
bindEventHandlers: function () {
|
||||
var cptouchrect;
|
||||
|
||||
window.addEventListener('resize', function () {
|
||||
var attrW, attrH, side, w = this.colorpicker.parentNode.clientWidth, h = this.colorpicker.parentNode.clientHeight;
|
||||
|
||||
attrW = this.colorpicker.getAttribute('width');
|
||||
attrH = this.colorpicker.getAttribute('height');
|
||||
side = attrW === 'auto' ? attrH : attrW;
|
||||
if (w > h) {
|
||||
if (attrH !== side) {
|
||||
this.colorpicker.setAttribute('height', side);
|
||||
this.colorpicker.setAttribute('width', 'auto');
|
||||
}
|
||||
} else if (attrW !== side) {
|
||||
this.colorpicker.setAttribute('height', 'auto');
|
||||
this.colorpicker.setAttribute('width', side);
|
||||
}
|
||||
|
||||
this.cpradius = this.colorpicker.offsetWidth / 2;
|
||||
this.cpcenter = this.colorpicker.offsetLeft + this.cpradius;
|
||||
if (this.color) {
|
||||
this.updatePointer();
|
||||
}
|
||||
}.bind(this));
|
||||
|
||||
window.addClickHandler(document.querySelector('.footer'), function (event) {
|
||||
this.emit('barClick', event.target.parentNode.dataset.area);
|
||||
}.bind(this));
|
||||
|
||||
|
||||
this.slider.on('changeValue', function (value) {
|
||||
this.brightness = value.value;
|
||||
this.updateInput();
|
||||
this.fireColorEvent();
|
||||
}, this);
|
||||
|
||||
this.inputbox.addEventListener('input', function (event) {
|
||||
var bright, rgb = new Tinycolor(event.target.value).toRgb();
|
||||
|
||||
if (rgb.r === 0 && rgb.g === 0 && rgb.b === 0) {
|
||||
this.brightness = 0;
|
||||
this.color = new Tinycolor({
|
||||
r: 0xff,
|
||||
g: 0xff,
|
||||
b: 0xff
|
||||
});
|
||||
} else {
|
||||
bright = Math.max(rgb.r, rgb.g, rgb.b) / 256;
|
||||
rgb.r = Math.round(rgb.r / bright);
|
||||
rgb.g = Math.round(rgb.g / bright);
|
||||
rgb.b = Math.round(rgb.b / bright);
|
||||
this.brightness = bright;
|
||||
this.color = new Tinycolor(rgb);
|
||||
}
|
||||
|
||||
this.fireColorEvent();
|
||||
this.updatePointer();
|
||||
this.updateSlider();
|
||||
}.bind(this), false);
|
||||
|
||||
this.inputbox.addEventListener('keydown', function (event) {
|
||||
switch (event.keyCode) {
|
||||
case 8:
|
||||
case 9:
|
||||
case 16:
|
||||
case 37:
|
||||
case 38:
|
||||
case 39:
|
||||
case 40:
|
||||
case 46:
|
||||
break;
|
||||
default:
|
||||
{
|
||||
if (event.target.value.length >= 6 && (event.target.selectionEnd - event.target.selectionStart) === 0) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
} else if (event.keyCode < 48 || event.keyCode > 71) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
cptouchrect = document.querySelector('#colorpicker .touchrect');
|
||||
window.addPointerDownHandler(cptouchrect, function (event) {
|
||||
this.leaveInput();
|
||||
this.drag = true;
|
||||
this.handleEvent(event);
|
||||
}.bind(this));
|
||||
|
||||
window.addPointerMoveHandler(cptouchrect, function (event) {
|
||||
if (this.drag) {
|
||||
this.handleEvent(event);
|
||||
event.preventDefault();
|
||||
}
|
||||
}.bind(this));
|
||||
|
||||
window.addPointerUpHandler(cptouchrect, function () {
|
||||
this.drag = false;
|
||||
}.bind(this));
|
||||
|
||||
window.addClickHandler(document.querySelector('#clear_button'), function () {
|
||||
this.emit('clear');
|
||||
}.bind(this));
|
||||
|
||||
window.addClickHandler(document.querySelector('#clearall_button'), function () {
|
||||
this.emit('clearall');
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param event
|
||||
*/
|
||||
handleEvent: function (event) {
|
||||
var point, x, y;
|
||||
|
||||
if (event.touches) {
|
||||
x = event.touches[0].clientX;
|
||||
y = event.touches[0].clientY;
|
||||
} else {
|
||||
x = event.clientX;
|
||||
y = event.clientY;
|
||||
}
|
||||
point = this.getCirclePoint(x, y);
|
||||
this.color = this.getColorFromPoint(point);
|
||||
|
||||
this.updatePointer();
|
||||
this.updateSlider();
|
||||
this.updateInput();
|
||||
|
||||
this.fireColorEvent();
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {number} x
|
||||
* @param {number} y
|
||||
* @returns {{x: number, y: number}}
|
||||
*/
|
||||
getCirclePoint: function (x, y) {
|
||||
var p = {
|
||||
x: x,
|
||||
y: y
|
||||
}, c = {
|
||||
x: this.colorpicker.offsetLeft + this.cpradius,
|
||||
y: this.colorpicker.offsetTop + this.cpradius
|
||||
}, n;
|
||||
|
||||
n = Math.sqrt(Math.pow((x - c.x), 2) + Math.pow((y - c.y), 2));
|
||||
|
||||
if (n > this.cpradius) {
|
||||
p.x = (c.x) + this.cpradius * ((x - c.x) / n);
|
||||
p.y = (c.y) + this.cpradius * ((y - c.y) / n);
|
||||
}
|
||||
|
||||
return p;
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {{x: number, y: number}} p
|
||||
* @returns {Tinycolor}
|
||||
*/
|
||||
getColorFromPoint: function (p) {
|
||||
var h, t, s, x, y;
|
||||
x = p.x - this.colorpicker.offsetLeft - this.cpradius;
|
||||
y = this.cpradius - p.y + this.colorpicker.offsetTop;
|
||||
t = Math.atan2(y, x);
|
||||
h = (t * (180 / Math.PI) + 360) % 360;
|
||||
s = Math.min(Math.sqrt(x * x + y * y) / this.cpradius, 1);
|
||||
|
||||
return new Tinycolor({
|
||||
h: h,
|
||||
s: s,
|
||||
v: 1
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param color
|
||||
* @returns {{x: number, y: number}}
|
||||
*/
|
||||
getPointFromColor: function (color) {
|
||||
var t, x, y, p = {};
|
||||
|
||||
t = color.h * (Math.PI / 180);
|
||||
y = Math.sin(t) * this.cpradius * color.s;
|
||||
x = Math.cos(t) * this.cpradius * color.s;
|
||||
|
||||
p.x = Math.round(x + this.colorpicker.offsetLeft + this.cpradius);
|
||||
p.y = Math.round(this.cpradius - y + this.colorpicker.offsetTop);
|
||||
|
||||
return p;
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
fireColorEvent: function () {
|
||||
var rgb = this.color.toRgb();
|
||||
rgb.r = Math.round(rgb.r * this.brightness);
|
||||
rgb.g = Math.round(rgb.g * this.brightness);
|
||||
rgb.b = Math.round(rgb.b * this.brightness);
|
||||
this.emit('colorChange', rgb);
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* @param rgb
|
||||
*/
|
||||
setColor: function (rgb) {
|
||||
var bright;
|
||||
|
||||
if (rgb.r === 0 && rgb.g === 0 && rgb.b === 0) {
|
||||
this.brightness = 0;
|
||||
this.color = new Tinycolor({
|
||||
r: 0xff,
|
||||
g: 0xff,
|
||||
b: 0xff
|
||||
});
|
||||
} else {
|
||||
bright = Math.max(rgb.r, rgb.g, rgb.b) / 256;
|
||||
rgb.r = Math.round(rgb.r / bright);
|
||||
rgb.g = Math.round(rgb.g / bright);
|
||||
rgb.b = Math.round(rgb.b / bright);
|
||||
this.brightness = bright;
|
||||
this.color = new Tinycolor(rgb);
|
||||
}
|
||||
|
||||
this.updatePointer();
|
||||
this.updateSlider();
|
||||
this.updateInput();
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
updateSlider: function () {
|
||||
this.slider.setValue(this.brightness);
|
||||
this.slider.dom.style.backgroundImage = '-webkit-linear-gradient(left, #000000 0%, ' + this.color.toHexString() + ' 100%)';
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
updatePointer: function () {
|
||||
var point = this.getPointFromColor(this.color.toHsv());
|
||||
|
||||
this.pointer.style.left = (point.x - this.pointer.offsetWidth / 2) + 'px';
|
||||
this.pointer.style.top = (point.y - this.pointer.offsetHeight / 2) + 'px';
|
||||
this.pointer.style.backgroundColor = this.color.toHexString();
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
updateInput: function () {
|
||||
var rgb = this.color.toRgb();
|
||||
rgb.r = Math.round(rgb.r * this.brightness);
|
||||
rgb.g = Math.round(rgb.g * this.brightness);
|
||||
rgb.b = Math.round(rgb.b * this.brightness);
|
||||
|
||||
this.inputbox.value = this.inputbox.style.backgroundColor = (
|
||||
'#'
|
||||
+ tools.b2hexstr(rgb.r)
|
||||
+ tools.b2hexstr(rgb.g)
|
||||
+ tools.b2hexstr(rgb.b)
|
||||
);
|
||||
this.inputbox.style.color = (rgb.r + rgb.g + rgb.b) < 384 ? '#fff' : '#000';
|
||||
},
|
||||
|
||||
/**
|
||||
* Scroll to the specific tab content
|
||||
* @param {string} id - Id of the tab to scroll to
|
||||
*/
|
||||
scrollToArea: function (id) {
|
||||
var area, index;
|
||||
document.querySelector('.footer .selected').classList.remove('selected');
|
||||
document.querySelector('.footer .button[data-area =' + id + ']').classList.add('selected');
|
||||
|
||||
area = document.getElementById(id);
|
||||
index = area.offsetLeft / area.clientWidth;
|
||||
area.parentNode.style.left = (-index * 100) + '%';
|
||||
},
|
||||
|
||||
/**
|
||||
* Shows a status message
|
||||
* @param {string} message - Text to show
|
||||
*/
|
||||
showStatus: function (message) {
|
||||
showMessageField(message, 'status');
|
||||
},
|
||||
|
||||
/**
|
||||
* Shows the error text
|
||||
* @param {string} error - Error message
|
||||
*/
|
||||
showError: function (error) {
|
||||
showMessageField(error, 'error');
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
leaveInput: function () {
|
||||
this.inputbox.blur();
|
||||
}
|
||||
});
|
||||
});
|
@@ -1,199 +0,0 @@
|
||||
define(['lib/stapes'], function (Stapes) {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
*
|
||||
* @param params
|
||||
* @returns {HTMLElement}
|
||||
*/
|
||||
function buildDom (params) {
|
||||
var dom, label, ul, li, i, header;
|
||||
|
||||
dom = document.createElement('div');
|
||||
dom.classList.add('grouplist');
|
||||
dom.id = params.id;
|
||||
|
||||
header = document.createElement('div');
|
||||
header.classList.add('header');
|
||||
dom.appendChild(header);
|
||||
label = document.createElement('div');
|
||||
label.innerHTML = params.label;
|
||||
label.classList.add('title');
|
||||
header.appendChild(label);
|
||||
label = document.createElement('div');
|
||||
label.innerHTML = '';
|
||||
label.classList.add('callout');
|
||||
header.appendChild(label);
|
||||
|
||||
ul = document.createElement('ul');
|
||||
dom.appendChild(ul);
|
||||
if (params.list) {
|
||||
for (i = 0; i < params.list.length; i++) {
|
||||
li = createLine(params.list[i]);
|
||||
ul.appendChild(li);
|
||||
}
|
||||
}
|
||||
|
||||
return dom;
|
||||
}
|
||||
|
||||
function createLine (params) {
|
||||
var dom, el, horiz, box, touch;
|
||||
|
||||
dom = document.createDocumentFragment();
|
||||
|
||||
horiz = document.createElement('div');
|
||||
horiz.classList.add('horizontal');
|
||||
dom.appendChild(horiz);
|
||||
|
||||
touch = document.createElement('div');
|
||||
touch.classList.add('horizontal');
|
||||
horiz.appendChild(touch);
|
||||
|
||||
el = document.createElement('div');
|
||||
el.classList.add('checkbox');
|
||||
touch.appendChild(el);
|
||||
|
||||
box = document.createElement('div');
|
||||
box.classList.add('titlebox');
|
||||
touch.appendChild(box);
|
||||
|
||||
el = document.createElement('label');
|
||||
el.classList.add('title');
|
||||
el.innerHTML = params.title || '';
|
||||
box.appendChild(el);
|
||||
|
||||
el = document.createElement('label');
|
||||
el.classList.add('subtitle');
|
||||
el.innerHTML = params.subtitle;
|
||||
box.appendChild(el);
|
||||
|
||||
el = document.createElement('div');
|
||||
el.classList.add('touchrect');
|
||||
touch.appendChild(el);
|
||||
|
||||
el = document.createElement('div');
|
||||
el.classList.add('edit_icon');
|
||||
el.innerHTML = '';
|
||||
horiz.appendChild(el);
|
||||
|
||||
el = document.createElement('div');
|
||||
el.classList.add('delete_icon');
|
||||
el.innerHTML = '';
|
||||
horiz.appendChild(el);
|
||||
|
||||
return dom;
|
||||
}
|
||||
|
||||
return Stapes.subclass(/** @lends ServerList.prototype */{
|
||||
/**
|
||||
* @private
|
||||
* @type {HTMLElement}
|
||||
*/
|
||||
dom: null,
|
||||
|
||||
/**
|
||||
* @class ServerList
|
||||
* @constructs
|
||||
* @param {object} params - List parameter
|
||||
* @param {string} params.id - List id
|
||||
* @param {string} params.label - List title
|
||||
* @param {{title: string, subtitle: string, c}[]} [params.list] - List elements
|
||||
*
|
||||
* @fires add
|
||||
* @fires remove
|
||||
* @fires select
|
||||
* @fires edit
|
||||
*/
|
||||
constructor: function (params) {
|
||||
this.dom = buildDom(params || {});
|
||||
this.bindEventHandlers();
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
bindEventHandlers: function () {
|
||||
window.addClickHandler(this.dom.querySelector('.callout'), function () {
|
||||
this.emit('add');
|
||||
}.bind(this));
|
||||
|
||||
window.addClickHandler(this.dom.querySelector('ul'), function (event) {
|
||||
if (event.target.classList.contains('delete_icon')) {
|
||||
this.emit('remove', event.target.parentNode.parentNode.id);
|
||||
} else if (event.target.classList.contains('edit_icon')) {
|
||||
this.emit('edit', event.target.parentNode.parentNode.id);
|
||||
} else if (event.target.classList.contains('touchrect')) {
|
||||
this.emit('select', event.target.parentNode.parentNode.parentNode.id);
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the DOM of the list
|
||||
* @returns {HTMLElement}
|
||||
*/
|
||||
getDom: function () {
|
||||
return this.dom;
|
||||
},
|
||||
|
||||
/**
|
||||
* Append a line
|
||||
* @param id
|
||||
* @param selected
|
||||
* @param element
|
||||
*/
|
||||
append: function (id, selected, element) {
|
||||
var li = document.createElement('li');
|
||||
li.id = id;
|
||||
if (selected) {
|
||||
li.classList.add('selected');
|
||||
}
|
||||
li.appendChild(element);
|
||||
this.dom.querySelector('ul').appendChild(li);
|
||||
},
|
||||
|
||||
/**
|
||||
* Replace a line
|
||||
* @param index
|
||||
* @param element
|
||||
*/
|
||||
replace: function (index, element) {
|
||||
var child = this.dom.querySelector('ul li:nth-child(' + (index + 1) + ')'), li;
|
||||
if (child) {
|
||||
li = document.createElement('li');
|
||||
li.appendChild(element);
|
||||
this.dom.querySelector('ul').replaceChild(li, child);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Add a line
|
||||
* @param lineParam
|
||||
*/
|
||||
addLine: function (lineParam) {
|
||||
var line = createLine(lineParam);
|
||||
this.append(lineParam.id, lineParam.selected, line);
|
||||
},
|
||||
|
||||
/**
|
||||
* Clear the list
|
||||
*/
|
||||
clear: function () {
|
||||
this.dom.querySelector('ul').innerHTML = '';
|
||||
},
|
||||
|
||||
/**
|
||||
* Hide or show the Add button in the header
|
||||
* @param {boolean} show - True to show, false to hide
|
||||
*/
|
||||
showAddButton: function (show) {
|
||||
if (show) {
|
||||
this.dom.querySelector('.callout').classList.remove('invisible');
|
||||
} else {
|
||||
this.dom.querySelector('.callout').classList.add('invisible');
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@@ -1,259 +0,0 @@
|
||||
define(['lib/stapes', 'views/ServerList'], function (Stapes, ServerList) {
|
||||
'use strict';
|
||||
|
||||
function createLabelInputLine (params) {
|
||||
var dom, el;
|
||||
|
||||
dom = document.createElement('div');
|
||||
dom.classList.add('inputline');
|
||||
dom.id = params.id;
|
||||
|
||||
el = document.createElement('label');
|
||||
el.innerHTML = params.label;
|
||||
dom.appendChild(el);
|
||||
|
||||
el = document.createElement('input');
|
||||
if (typeof params.value === 'number') {
|
||||
el.type = 'number';
|
||||
}
|
||||
el.value = params.value || '';
|
||||
el.autocomplete='off';
|
||||
el.autocorrect='off';
|
||||
el.autocapitalize='off';
|
||||
dom.appendChild(el);
|
||||
|
||||
return dom;
|
||||
}
|
||||
|
||||
function createButtonLine (params) {
|
||||
var dom, el;
|
||||
|
||||
dom = document.createElement('div');
|
||||
dom.classList.add('inputline');
|
||||
|
||||
el = document.createElement('button');
|
||||
el.innerHTML = params.label;
|
||||
el.classList.add('OK');
|
||||
dom.appendChild(el);
|
||||
|
||||
el = document.createElement('button');
|
||||
el.innerHTML = 'Cancel';
|
||||
el.classList.add('CANCEL');
|
||||
dom.appendChild(el);
|
||||
|
||||
return dom;
|
||||
}
|
||||
|
||||
function createDetectLine () {
|
||||
var dom, el;
|
||||
|
||||
dom = document.createElement('div');
|
||||
dom.classList.add('line');
|
||||
|
||||
el = document.createElement('button');
|
||||
el.id = 'detect_button';
|
||||
el.innerHTML = 'Detect';
|
||||
dom.appendChild(el);
|
||||
|
||||
el = document.createElement('div');
|
||||
el.classList.add('spinner');
|
||||
el.classList.add('hidden');
|
||||
dom.appendChild(el);
|
||||
|
||||
return dom;
|
||||
}
|
||||
|
||||
return Stapes.subclass(/** @lends SettingsView.prototype */{
|
||||
dom: null,
|
||||
serverList: null,
|
||||
|
||||
/**
|
||||
* @class SettingsView
|
||||
* @classdesc View for the settings
|
||||
* @constructs
|
||||
*/
|
||||
constructor: function () {
|
||||
var list = [], el;
|
||||
|
||||
this.dom = document.querySelector('#settings');
|
||||
|
||||
this.serverList = new ServerList({
|
||||
id: 'serverList',
|
||||
label: 'Server',
|
||||
list: list
|
||||
});
|
||||
|
||||
this.serverList.on({
|
||||
add: function () {
|
||||
var line, box;
|
||||
|
||||
this.enableDetectButton(false);
|
||||
this.lockList(true);
|
||||
|
||||
box = document.createDocumentFragment();
|
||||
|
||||
line = createLabelInputLine({id: 'name', label: 'Name:'});
|
||||
box.appendChild(line);
|
||||
line = createLabelInputLine({id: 'address', label: 'Address:'});
|
||||
box.appendChild(line);
|
||||
line = createLabelInputLine({id: 'port', label: 'Port:', value: 19444});
|
||||
box.appendChild(line);
|
||||
line = createLabelInputLine({id: 'priority', label: 'Priority:', value: 50});
|
||||
box.appendChild(line);
|
||||
line = createLabelInputLine({id: 'duration', label: 'Duration (sec):', value: 0});
|
||||
box.appendChild(line);
|
||||
|
||||
line = createButtonLine({label: 'Add'});
|
||||
|
||||
window.addClickHandler(line.firstChild, function (event) {
|
||||
var server = {}, i, inputs = event.target.parentNode.parentNode.querySelectorAll('input');
|
||||
|
||||
for (i = 0; i < inputs.length; i++) {
|
||||
server[inputs[i].parentNode.id] = inputs[i].value;
|
||||
}
|
||||
|
||||
server.port = parseInt(server.port);
|
||||
server.priority = parseInt(server.priority);
|
||||
server.duration = parseInt(server.duration);
|
||||
|
||||
this.emit('serverAdded', server);
|
||||
}.bind(this));
|
||||
|
||||
window.addClickHandler(line.lastChild, function () {
|
||||
this.emit('serverAddCanceled');
|
||||
}.bind(this));
|
||||
box.appendChild(line);
|
||||
this.serverList.append(null, false, box);
|
||||
},
|
||||
select: function (id) {
|
||||
if (!this.dom.classList.contains('locked')) {
|
||||
this.emit('serverSelected', parseInt(id.replace('server_', '')));
|
||||
}
|
||||
},
|
||||
remove: function (id) {
|
||||
this.emit('serverRemoved', parseInt(id.replace('server_', '')));
|
||||
},
|
||||
edit: function (id) {
|
||||
this.emit('editServer', parseInt(id.replace('server_', '')));
|
||||
}
|
||||
}, this);
|
||||
|
||||
this.dom.appendChild(this.serverList.getDom());
|
||||
|
||||
el = createDetectLine();
|
||||
|
||||
window.addClickHandler(el.querySelector('button'), function () {
|
||||
this.emit('detect');
|
||||
}.bind(this));
|
||||
|
||||
this.dom.appendChild(el);
|
||||
},
|
||||
|
||||
/**
|
||||
* Fills the list of known servers
|
||||
* @param {Array} servers
|
||||
*/
|
||||
fillServerList: function (servers) {
|
||||
var i, server, params;
|
||||
this.serverList.clear();
|
||||
for (i = 0; i < servers.length; i++) {
|
||||
server = servers[i];
|
||||
params = {id: 'server_' + i, title: server.name, subtitle: server.address + ':' + server.port};
|
||||
if (server.selected) {
|
||||
params.selected = true;
|
||||
}
|
||||
this.serverList.addLine(params);
|
||||
}
|
||||
this.serverList.showAddButton(true);
|
||||
},
|
||||
|
||||
/**
|
||||
* Shows or hides the spinner as progress indicator
|
||||
* @param {boolean} show True to show, false to hide
|
||||
*/
|
||||
showWaiting: function (show) {
|
||||
if (show) {
|
||||
this.dom.querySelector('.spinner').classList.remove('hidden');
|
||||
} else {
|
||||
this.dom.querySelector('.spinner').classList.add('hidden');
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Enables or disables the detect button
|
||||
* @param {Boolean} enabled True to enable, false to disable
|
||||
*/
|
||||
enableDetectButton: function (enabled) {
|
||||
if (enabled) {
|
||||
this.dom.querySelector('#detect_button').classList.remove('hidden');
|
||||
} else {
|
||||
this.dom.querySelector('#detect_button').classList.add('hidden');
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Locks the list for editing/deleting
|
||||
* @param {Boolean} lock True to lock, false to unlock
|
||||
*/
|
||||
lockList: function (lock) {
|
||||
if (!lock) {
|
||||
this.dom.classList.remove('locked');
|
||||
this.serverList.showAddButton(true);
|
||||
} else {
|
||||
this.dom.classList.add('locked');
|
||||
this.serverList.showAddButton(false);
|
||||
}
|
||||
},
|
||||
|
||||
editServer: function (serverInfo) {
|
||||
var line, box;
|
||||
|
||||
this.lockList(true);
|
||||
this.enableDetectButton(false);
|
||||
|
||||
box = document.createDocumentFragment();
|
||||
|
||||
line = createLabelInputLine({id: 'name', label: 'Name:', value: serverInfo.server.name});
|
||||
box.appendChild(line);
|
||||
line = createLabelInputLine({id: 'address', label: 'Address:', value: serverInfo.server.address});
|
||||
box.appendChild(line);
|
||||
line = createLabelInputLine({id: 'port', label: 'Port:', value: serverInfo.server.port});
|
||||
box.appendChild(line);
|
||||
line = createLabelInputLine({id: 'priority', label: 'Priority:', value: serverInfo.server.priority});
|
||||
box.appendChild(line);
|
||||
line = createLabelInputLine({id: 'duration', label: 'Duration (sec):', value: serverInfo.server.duration});
|
||||
box.appendChild(line);
|
||||
|
||||
line = createButtonLine({label: 'Done'});
|
||||
|
||||
window.addClickHandler(line.querySelector('button.OK'), function (event) {
|
||||
var server = {}, i, inputs = event.target.parentNode.parentNode.querySelectorAll('input');
|
||||
|
||||
for (i = 0; i < inputs.length; i++) {
|
||||
server[inputs[i].parentNode.id] = inputs[i].value;
|
||||
}
|
||||
|
||||
server.port = parseInt(server.port);
|
||||
server.priority = parseInt(server.priority);
|
||||
server.duration = parseInt(server.duration);
|
||||
if (serverInfo.server.selected) {
|
||||
server.selected = true;
|
||||
}
|
||||
|
||||
this.emit('serverChanged', {index: serverInfo.index, server: server});
|
||||
}.bind(this));
|
||||
|
||||
window.addClickHandler(line.querySelector('button.CANCEL'), function () {
|
||||
this.emit('serverEditCanceled');
|
||||
}.bind(this));
|
||||
box.appendChild(line);
|
||||
|
||||
window.addClickHandler(box.querySelector('input'), function (event) {
|
||||
event.stopPropagation();
|
||||
});
|
||||
|
||||
this.serverList.replace(serverInfo.index, box);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@@ -1,134 +0,0 @@
|
||||
define(['lib/stapes'], function (Stapes) {
|
||||
'use strict';
|
||||
|
||||
function syncView (slider) {
|
||||
var left = (slider.value - slider.min) * 100 / (slider.max - slider.min);
|
||||
slider.dom.lastElementChild.style.left = left + '%';
|
||||
}
|
||||
|
||||
function handleEvent(event, slider) {
|
||||
var x, left, ratio, value, steppedValue;
|
||||
if (event.touches) {
|
||||
x = event.touches[0].clientX;
|
||||
} else {
|
||||
x = event.clientX;
|
||||
}
|
||||
|
||||
left = x - slider.dom.getBoundingClientRect().left;
|
||||
ratio = left / slider.dom.offsetWidth;
|
||||
value = (slider.max - slider.min) * ratio;
|
||||
|
||||
steppedValue = (value - slider.min) % slider.step;
|
||||
if (steppedValue <= slider.step / 2) {
|
||||
value = value - steppedValue;
|
||||
} else {
|
||||
value = value + (slider.step - steppedValue);
|
||||
}
|
||||
|
||||
value = Math.max(value, slider.min);
|
||||
value = Math.min(value, slider.max);
|
||||
slider.value = value;
|
||||
slider.emit('changeValue', {
|
||||
'value': value,
|
||||
'target': slider.dom
|
||||
});
|
||||
}
|
||||
|
||||
return Stapes.subclass(/** @lends Slider.prototype */{
|
||||
/**
|
||||
* @private
|
||||
* @type {Element}
|
||||
*/
|
||||
dom: null,
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Number}
|
||||
*/
|
||||
min: 0,
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Number}
|
||||
*/
|
||||
max: 100,
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Number}
|
||||
*/
|
||||
value: 0,
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Number}
|
||||
*/
|
||||
step: 1,
|
||||
|
||||
/**
|
||||
* @class Slider
|
||||
* @constructs
|
||||
* @fires change
|
||||
*/
|
||||
constructor: function (params) {
|
||||
this.dom = params.element;
|
||||
this.setValue(params.value);
|
||||
this.setMin(params.min);
|
||||
this.setMax(params.max);
|
||||
this.setStep(params.step);
|
||||
|
||||
this.bindEventHandlers();
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
bindEventHandlers: function () {
|
||||
var that = this;
|
||||
|
||||
function pointerMoveEventHandler(event) {
|
||||
if (that.drag) {
|
||||
handleEvent(event, that);
|
||||
syncView(that);
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
function pointerUpEventHandler() {
|
||||
that.drag = false;
|
||||
syncView(that);
|
||||
window.removePointerMoveHandler(document, pointerMoveEventHandler);
|
||||
window.removePointerUpHandler(document, pointerUpEventHandler);
|
||||
}
|
||||
|
||||
window.addPointerDownHandler(this.dom, function (event) {
|
||||
this.drag = true;
|
||||
handleEvent(event, this);
|
||||
syncView(this);
|
||||
window.addPointerMoveHandler(document, pointerMoveEventHandler);
|
||||
window.addPointerUpHandler(document, pointerUpEventHandler);
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
setValue: function(value) {
|
||||
this.value = value || 0;
|
||||
syncView(this);
|
||||
},
|
||||
|
||||
setMin: function(value) {
|
||||
this.min = value || 0;
|
||||
syncView(this);
|
||||
},
|
||||
|
||||
setMax: function(value) {
|
||||
this.max = value || 100;
|
||||
syncView(this);
|
||||
},
|
||||
|
||||
setStep: function(value) {
|
||||
this.step = value || 1;
|
||||
syncView(this);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@@ -1,375 +0,0 @@
|
||||
/**
|
||||
* hyperion remote
|
||||
* MIT License
|
||||
*/
|
||||
|
||||
define([
|
||||
'lib/stapes',
|
||||
'views/Slider'
|
||||
], function (Stapes, Slider) {
|
||||
'use strict';
|
||||
|
||||
function onHeaderClick (event) {
|
||||
var list = event.target.parentNode.parentNode.querySelector('ul');
|
||||
|
||||
if (list.clientHeight === 0) {
|
||||
list.style.maxHeight = list.scrollHeight + 'px';
|
||||
event.target.parentNode.parentNode.setAttribute('collapsed', 'false');
|
||||
} else {
|
||||
list.style.maxHeight = 0;
|
||||
event.target.parentNode.parentNode.setAttribute('collapsed', 'true');
|
||||
}
|
||||
}
|
||||
|
||||
function createLine (id, type, icon, caption, value, min, max) {
|
||||
var dom, el, el2, label, wrapper;
|
||||
|
||||
dom = document.createElement('li');
|
||||
dom.className = type;
|
||||
|
||||
label = document.createElement('label');
|
||||
label.innerHTML = caption;
|
||||
dom.appendChild(label);
|
||||
|
||||
wrapper = document.createElement('div');
|
||||
wrapper.classList.add('wrapper');
|
||||
wrapper.id = id;
|
||||
|
||||
el = document.createElement('div');
|
||||
el.classList.add('icon');
|
||||
el.innerHTML = icon;
|
||||
wrapper.appendChild(el);
|
||||
|
||||
el = document.createElement('div');
|
||||
el.classList.add('slider');
|
||||
el2 = document.createElement('div');
|
||||
el2.classList.add('track');
|
||||
el.appendChild(el2);
|
||||
el2 = document.createElement('div');
|
||||
el2.classList.add('thumb');
|
||||
el.appendChild(el2);
|
||||
el.dataset.min = min;
|
||||
el.dataset.max = max;
|
||||
el.dataset.value = value;
|
||||
el.dataset.step = 0.01;
|
||||
wrapper.appendChild(el);
|
||||
|
||||
el = document.createElement('input');
|
||||
el.classList.add('value');
|
||||
el.type = 'number';
|
||||
el.min = min;
|
||||
el.max = max;
|
||||
el.step = 0.01;
|
||||
el.value = parseFloat(Math.round(value * 100) / 100).toFixed(2);
|
||||
wrapper.appendChild(el);
|
||||
|
||||
dom.appendChild(wrapper);
|
||||
|
||||
return dom;
|
||||
}
|
||||
|
||||
function createGroup (groupInfo) {
|
||||
var group, node, subnode, i, member;
|
||||
group = document.createElement('div');
|
||||
group.classList.add('group');
|
||||
if (groupInfo.collapsed) {
|
||||
group.setAttribute('collapsed', 'true');
|
||||
}
|
||||
group.id = groupInfo.id;
|
||||
|
||||
node = document.createElement('div');
|
||||
node.classList.add('header');
|
||||
group.appendChild(node);
|
||||
subnode = document.createElement('label');
|
||||
subnode.innerHTML = groupInfo.title;
|
||||
node.appendChild(subnode);
|
||||
subnode = document.createElement('label');
|
||||
subnode.innerHTML = groupInfo.subtitle;
|
||||
node.appendChild(subnode);
|
||||
|
||||
node = document.createElement('ul');
|
||||
group.appendChild(node);
|
||||
for (i = 0; i < groupInfo.members.length; i++) {
|
||||
member = groupInfo.members[i];
|
||||
subnode = createLine(member.id, member.type, member.icon, member.label, member.value, member.min,
|
||||
member.max);
|
||||
node.appendChild(subnode);
|
||||
}
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
return Stapes.subclass(/** @lends TransformView.prototype */{
|
||||
sliders: {},
|
||||
|
||||
/**
|
||||
* @class TransformView
|
||||
* @constructs
|
||||
*/
|
||||
constructor: function () {
|
||||
},
|
||||
|
||||
/**
|
||||
* Clear the list
|
||||
*/
|
||||
clear: function () {
|
||||
document.querySelector('#transform .values').innerHTML = '';
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param change
|
||||
*/
|
||||
onSliderChange: function (event) {
|
||||
var data = {}, idparts, value;
|
||||
|
||||
idparts = event.target.parentNode.id.split('_');
|
||||
value = parseFloat(Math.round(parseFloat(event.value) * 100) / 100);
|
||||
|
||||
event.target.parentNode.querySelector('.value').value = value.toFixed(2);
|
||||
|
||||
data[idparts[1]] = value;
|
||||
this.emit(idparts[0], data);
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param change
|
||||
*/
|
||||
onValueChange: function (event) {
|
||||
var data = {}, idparts, value;
|
||||
|
||||
idparts = event.target.parentNode.id.split('_');
|
||||
value = parseFloat(Math.round(parseFloat(event.target.value) * 100) / 100);
|
||||
|
||||
if (parseFloat(event.target.value) < parseFloat(event.target.min)) {
|
||||
event.target.value = event.target.min;
|
||||
} else if (parseFloat(event.target.value) > parseFloat(event.target.max)) {
|
||||
event.target.value = event.target.max;
|
||||
}
|
||||
this.sliders[event.target.parentNode.id].setValue(value);
|
||||
|
||||
data[idparts[1]] = value;
|
||||
this.emit(idparts[0], data);
|
||||
},
|
||||
|
||||
/**
|
||||
* fill the list
|
||||
* @param {object} transform - Object containing transform information
|
||||
*/
|
||||
fillList: function (transform) {
|
||||
var dom, group, els, i, slider;
|
||||
|
||||
if (!transform) {
|
||||
document.querySelector('#transform .info').classList.remove('hidden');
|
||||
return;
|
||||
}
|
||||
|
||||
dom = document.createDocumentFragment();
|
||||
|
||||
group = createGroup({
|
||||
collapsed: true,
|
||||
id: 'HSV',
|
||||
title: 'HSV',
|
||||
subtitle: 'HSV color corrections',
|
||||
members: [
|
||||
{
|
||||
id: 'hsv_saturationGain',
|
||||
type: 'saturation',
|
||||
icon: '',
|
||||
label: 'Saturation gain',
|
||||
value: transform.saturationGain,
|
||||
min: 0,
|
||||
max: 5
|
||||
},
|
||||
{
|
||||
id: 'hsv_valueGain',
|
||||
type: 'value',
|
||||
icon: '',
|
||||
label: 'Value gain',
|
||||
value: transform.valueGain,
|
||||
min: 0,
|
||||
max: 5
|
||||
}
|
||||
]
|
||||
});
|
||||
dom.appendChild(group);
|
||||
|
||||
group = createGroup({
|
||||
collapsed: true,
|
||||
id: 'Gamma',
|
||||
title: 'Gamma',
|
||||
subtitle: 'Gamma correction',
|
||||
members: [
|
||||
{
|
||||
id: 'gamma_r',
|
||||
type: 'red',
|
||||
icon: '',
|
||||
label: 'Red',
|
||||
value: transform.gamma[0],
|
||||
min: 0,
|
||||
max: 5
|
||||
},
|
||||
{
|
||||
id: 'gamma_g',
|
||||
type: 'green',
|
||||
icon: '',
|
||||
label: 'Green',
|
||||
value: transform.gamma[1],
|
||||
min: 0,
|
||||
max: 5
|
||||
},
|
||||
{
|
||||
id: 'gamma_b',
|
||||
type: 'blue',
|
||||
icon: '',
|
||||
label: 'Blue',
|
||||
value: transform.gamma[2],
|
||||
min: 0,
|
||||
max: 5
|
||||
}
|
||||
]
|
||||
});
|
||||
dom.appendChild(group);
|
||||
|
||||
group = createGroup({
|
||||
collapsed: true,
|
||||
id: 'Whitelevel',
|
||||
title: 'Whitelevel',
|
||||
subtitle: 'Value when RGB channel is fully on',
|
||||
members: [
|
||||
{
|
||||
id: 'whitelevel_r',
|
||||
type: 'red',
|
||||
icon: '',
|
||||
label: 'Red',
|
||||
value: transform.whitelevel[0],
|
||||
min: 0,
|
||||
max: 1
|
||||
},
|
||||
{
|
||||
id: 'whitelevel_g',
|
||||
type: 'green',
|
||||
icon: '',
|
||||
label: 'Green',
|
||||
value: transform.whitelevel[1],
|
||||
min: 0,
|
||||
max: 1
|
||||
},
|
||||
{
|
||||
id: 'whitelevel_b',
|
||||
type: 'blue',
|
||||
icon: '',
|
||||
label: 'Blue',
|
||||
value: transform.whitelevel[2],
|
||||
min: 0,
|
||||
max: 1
|
||||
}
|
||||
]
|
||||
});
|
||||
dom.appendChild(group);
|
||||
|
||||
group = createGroup({
|
||||
collapsed: true,
|
||||
id: 'Blacklevel',
|
||||
title: 'Blacklevel',
|
||||
subtitle: 'Value when RGB channel is fully off',
|
||||
members: [
|
||||
{
|
||||
id: 'blacklevel_r',
|
||||
type: 'red',
|
||||
icon: '',
|
||||
label: 'Red',
|
||||
value: transform.blacklevel[0],
|
||||
min: 0,
|
||||
max: 1
|
||||
},
|
||||
{
|
||||
id: 'blacklevel_g',
|
||||
type: 'green',
|
||||
icon: '',
|
||||
label: 'Green',
|
||||
value: transform.blacklevel[1],
|
||||
min: 0,
|
||||
max: 1
|
||||
},
|
||||
{
|
||||
id: 'blacklevel_b',
|
||||
type: 'blue',
|
||||
icon: '',
|
||||
label: 'Blue',
|
||||
value: transform.blacklevel[2],
|
||||
min: 0,
|
||||
max: 1
|
||||
}
|
||||
]
|
||||
});
|
||||
dom.appendChild(group);
|
||||
|
||||
group = createGroup({
|
||||
collapsed: true,
|
||||
id: 'Threshold',
|
||||
title: 'Threshold',
|
||||
subtitle: 'Threshold for a channel',
|
||||
members: [
|
||||
{
|
||||
id: 'threshold_r',
|
||||
type: 'red',
|
||||
icon: '',
|
||||
label: 'Red',
|
||||
value: transform.threshold[0],
|
||||
min: 0,
|
||||
max: 1
|
||||
},
|
||||
{
|
||||
id: 'threshold_g',
|
||||
type: 'green',
|
||||
icon: '',
|
||||
label: 'Green',
|
||||
value: transform.threshold[1],
|
||||
min: 0,
|
||||
max: 1
|
||||
},
|
||||
{
|
||||
id: 'threshold_b',
|
||||
type: 'blue',
|
||||
icon: '',
|
||||
label: 'Blue',
|
||||
value: transform.threshold[2],
|
||||
min: 0,
|
||||
max: 1
|
||||
}
|
||||
]
|
||||
});
|
||||
dom.appendChild(group);
|
||||
|
||||
els = dom.querySelectorAll('.slider');
|
||||
for (i = 0; i < els.length; i++) {
|
||||
slider = new Slider({
|
||||
element: els[i],
|
||||
min: els[i].dataset.min,
|
||||
max: els[i].dataset.max,
|
||||
step: els[i].dataset.step,
|
||||
value: els[i].dataset.value
|
||||
});
|
||||
slider.on('changeValue', this.onSliderChange, this);
|
||||
this.sliders[els[i].parentNode.id] = slider;
|
||||
}
|
||||
|
||||
els = dom.querySelectorAll('input');
|
||||
for (i = 0; i < els.length; i++) {
|
||||
els[i].addEventListener('input', this.onValueChange.bind(this), false);
|
||||
}
|
||||
|
||||
els = dom.querySelectorAll('.header');
|
||||
for (i = 0; i < els.length; i++) {
|
||||
window.addClickHandler(els[i], onHeaderClick);
|
||||
}
|
||||
|
||||
document.querySelector('#transform .info').classList.add('hidden');
|
||||
document.querySelector('#transform .values').appendChild(dom);
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
|
@@ -1,17 +0,0 @@
|
||||
/*global chrome */
|
||||
chrome.app.runtime.onLaunched.addListener(function () {
|
||||
'use strict';
|
||||
chrome.app.window.create('index.html', {
|
||||
'id': 'fakeIdForSingleton',
|
||||
'innerBounds': {
|
||||
'width': 320,
|
||||
'height': 480,
|
||||
'minWidth': 320,
|
||||
'minHeight': 480
|
||||
},
|
||||
resizable: false
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
1106
assets/webconfig/js/bootstrap-colorpicker.js
vendored
Normal file
1106
assets/webconfig/js/bootstrap-colorpicker.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
7
assets/webconfig/js/bootstrap.min.js
vendored
Normal file
7
assets/webconfig/js/bootstrap.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
675
assets/webconfig/js/jquery-lang.js
vendored
Normal file
675
assets/webconfig/js/jquery-lang.js
vendored
Normal file
@@ -0,0 +1,675 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Irrelon Software Limited
|
||||
http://www.irrelon.com
|
||||
|
||||
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, url 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.
|
||||
|
||||
Source: https://github.com/irrelon/jquery-lang-js
|
||||
|
||||
Changelog: See readme.md
|
||||
*/
|
||||
var Lang = (function () {
|
||||
"use strict";
|
||||
|
||||
var Lang = function () {
|
||||
// Enable firing events
|
||||
this._fireEvents = true;
|
||||
|
||||
// Allow storage of dynamic language pack data
|
||||
this._dynamic = {};
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialise the library with the library options.
|
||||
* @param {Object} options The options to init the library with.
|
||||
* See the readme.md for the details of the options available.
|
||||
*/
|
||||
Lang.prototype.init = function (options) {
|
||||
var self = this,
|
||||
cookieLang,
|
||||
defaultLang,
|
||||
currentLang,
|
||||
allowCookieOverride;
|
||||
|
||||
options = options || {};
|
||||
options.cookie = options.cookie || {};
|
||||
|
||||
defaultLang = options.defaultLang;
|
||||
currentLang = options.currentLang;
|
||||
allowCookieOverride = options.allowCookieOverride;
|
||||
|
||||
// Set cookie settings
|
||||
this.cookieName = options.cookie.name || 'langCookie';
|
||||
this.cookieExpiry = options.cookie.expiry || 365;
|
||||
this.cookiePath = options.cookie.path || '/';
|
||||
|
||||
// Store existing mutation methods so we can auto-run
|
||||
// translations when new data is added to the page
|
||||
this._mutationCopies = {
|
||||
append: $.fn.append,
|
||||
appendTo: $.fn.appendTo,
|
||||
prepend: $.fn.prepend,
|
||||
before: $.fn.before,
|
||||
after: $.fn.after,
|
||||
html: $.fn.html
|
||||
};
|
||||
|
||||
// Now override the existing mutation methods with our own
|
||||
$.fn.append = function () { return self._mutation(this, 'append', arguments) };
|
||||
$.fn.appendTo = function () { return self._mutation(this, 'appendTo', arguments) };
|
||||
$.fn.prepend = function () { return self._mutation(this, 'prepend', arguments) };
|
||||
$.fn.before = function () { return self._mutation(this, 'before', arguments) };
|
||||
$.fn.after = function () { return self._mutation(this, 'after', arguments) };
|
||||
$.fn.html = function () { return self._mutation(this, 'html', arguments) };
|
||||
|
||||
// Set default and current language to the default one
|
||||
// to start with
|
||||
this.defaultLang = defaultLang || 'en';
|
||||
this.currentLang = defaultLang || 'en';
|
||||
|
||||
// Check for cookie support when no current language is specified
|
||||
if ((allowCookieOverride || !currentLang) && typeof Cookies !== 'undefined') {
|
||||
// Check for an existing language cookie
|
||||
cookieLang = Cookies.get(this.cookieName);
|
||||
|
||||
if (cookieLang) {
|
||||
// We have a cookie language, set the current language
|
||||
currentLang = cookieLang;
|
||||
}
|
||||
}
|
||||
|
||||
$(function () {
|
||||
// Setup data on the language items
|
||||
self._start();
|
||||
|
||||
// Check if the current language is not the same as our default
|
||||
if (currentLang && currentLang !== self.defaultLang) {
|
||||
// Switch to the current language
|
||||
self.change(currentLang);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Object that holds the language packs.
|
||||
* @type {{}}
|
||||
*/
|
||||
Lang.prototype.pack = {};
|
||||
|
||||
/**
|
||||
* Array of translatable attributes to check for on elements.
|
||||
* @type {string[]}
|
||||
*/
|
||||
Lang.prototype.attrList = [
|
||||
'title',
|
||||
'alt',
|
||||
'placeholder',
|
||||
'href'
|
||||
];
|
||||
|
||||
/**
|
||||
* Defines a language pack that can be dynamically loaded and the
|
||||
* path to use when doing so.
|
||||
* @param {String} lang The language two-letter iso-code.
|
||||
* @param {String} path The path to the language pack js file.
|
||||
*/
|
||||
Lang.prototype.dynamic = function (lang, path) {
|
||||
if (lang !== undefined && path !== undefined) {
|
||||
this._dynamic[lang] = path;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Loads a new language pack for the given language.
|
||||
* @param {string} lang The language to load the pack for.
|
||||
* @param {Function=} callback Optional callback when the file has loaded.
|
||||
*/
|
||||
Lang.prototype.loadPack = function (lang, callback) {
|
||||
var self = this;
|
||||
|
||||
if (lang && self._dynamic[lang]) {
|
||||
$.ajax({
|
||||
dataType: "json",
|
||||
url: self._dynamic[lang],
|
||||
success: function (data) {
|
||||
self.pack[lang] = data;
|
||||
|
||||
// Process the regex list
|
||||
if (self.pack[lang].regex) {
|
||||
var packRegex = self.pack[lang].regex,
|
||||
regex,
|
||||
i;
|
||||
|
||||
for (i = 0; i < packRegex.length; i++) {
|
||||
regex = packRegex[i];
|
||||
if (regex.length === 2) {
|
||||
// String, value
|
||||
regex[0] = new RegExp(regex[0]);
|
||||
} else if (regex.length === 3) {
|
||||
// String, modifiers, value
|
||||
regex[0] = new RegExp(regex[0], regex[1]);
|
||||
|
||||
// Remove modifier
|
||||
regex.splice(1, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//console.log('Loaded language pack: ' + self._dynamic[lang]);
|
||||
if (callback) { callback(false, lang, self._dynamic[lang]); }
|
||||
},
|
||||
error: function () {
|
||||
if (callback) { callback(true, lang, self._dynamic[lang]); }
|
||||
throw('Error loading language pack' + self._dynamic[lang]);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
throw('Cannot load language pack, no file path specified!');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Scans the DOM for elements with [lang] selector and saves translate data
|
||||
* for them for later use.
|
||||
* @private
|
||||
*/
|
||||
Lang.prototype._start = function (selector) {
|
||||
// Get the page HTML
|
||||
var arr = selector !== undefined ? $(selector).find('[lang]') : $(':not(html)[lang]'),
|
||||
arrCount = arr.length,
|
||||
elem;
|
||||
|
||||
while (arrCount--) {
|
||||
elem = $(arr[arrCount]);
|
||||
this._processElement(elem);
|
||||
}
|
||||
};
|
||||
|
||||
Lang.prototype._processElement = function (elem) {
|
||||
// Only store data if the element is set to our default language
|
||||
if (elem.attr('lang') === this.defaultLang) {
|
||||
// Store translatable attributes
|
||||
this._storeAttribs(elem);
|
||||
|
||||
// Store translatable content
|
||||
this._storeContent(elem);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Stores the translatable attribute values in their default language.
|
||||
* @param {object} elem The jQuery selected element.
|
||||
* @private
|
||||
*/
|
||||
Lang.prototype._storeAttribs = function (elem) {
|
||||
var attrIndex,
|
||||
attr,
|
||||
attrObj;
|
||||
|
||||
for (attrIndex = 0; attrIndex < this.attrList.length; attrIndex++) {
|
||||
attr = this.attrList[attrIndex];
|
||||
if (elem.attr(attr)) {
|
||||
// Grab the existing attribute store or create a new object
|
||||
attrObj = elem.data('lang-attr') || {};
|
||||
|
||||
// Add the attribute and value to the store
|
||||
attrObj[attr] = elem.attr(attr);
|
||||
|
||||
// Save the attribute data to the store
|
||||
elem.data('lang-attr', attrObj);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Reads the existing content from the element and stores it for
|
||||
* later use in translation.
|
||||
* @param elem
|
||||
* @private
|
||||
*/
|
||||
Lang.prototype._storeContent = function (elem) {
|
||||
// Check if the element is an input element
|
||||
if (elem.is('input')) {
|
||||
switch (elem.attr('type')) {
|
||||
case 'button':
|
||||
case 'submit':
|
||||
case 'hidden':
|
||||
case 'reset':
|
||||
elem.data('lang-val', elem.val());
|
||||
break;
|
||||
}
|
||||
} else if (elem.is('img')) {
|
||||
elem.data('lang-src', elem.attr('src'));
|
||||
} else {
|
||||
// Get the text nodes immediately inside this element
|
||||
var nodes = this._getTextNodes(elem);
|
||||
if (nodes) {
|
||||
elem.data('lang-text', nodes);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieves the text nodes from an element and returns them in array wrap into
|
||||
* object with two properties:
|
||||
* - node - which corresponds to text node,
|
||||
* - langDefaultText - which remember current data of text node
|
||||
* @param elem
|
||||
* @returns {Array|*}
|
||||
* @private
|
||||
*/
|
||||
Lang.prototype._getTextNodes = function (elem) {
|
||||
var nodes = elem.contents(), nodeObjArray = [], nodeObj = {},
|
||||
nodeArr, that = this, map = Array.prototype.map;
|
||||
|
||||
$.each(nodes, function (index, node) {
|
||||
if ( node.nodeType !== 3 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
nodeObj = {
|
||||
node : node,
|
||||
langDefaultText : node.data
|
||||
};
|
||||
|
||||
nodeObjArray.push(nodeObj);
|
||||
});
|
||||
|
||||
// If element has only one text node and data-lang-token is defined
|
||||
// set langContentKey property to use as a token
|
||||
if(nodes.length == 1){
|
||||
nodeObjArray[0].langToken = elem.data('langToken');
|
||||
}
|
||||
|
||||
return nodeObjArray;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets text nodes of an element translated based on the passed language.
|
||||
* @param elem
|
||||
* @param {Array|*} nodes array of objecs with text node and defaultText returned from _getTextNodes
|
||||
* @param lang
|
||||
* @private
|
||||
*/
|
||||
Lang.prototype._setTextNodes = function (elem, nodes, lang) {
|
||||
var index,
|
||||
textNode,
|
||||
defaultText,
|
||||
translation,
|
||||
langNotDefault = lang !== this.defaultLang;
|
||||
|
||||
for (index = 0; index < nodes.length; index++) {
|
||||
textNode = nodes[index];
|
||||
|
||||
if (langNotDefault) {
|
||||
// If langToken is set, use it as a token
|
||||
defaultText = textNode.langToken || $.trim(textNode.langDefaultText);
|
||||
|
||||
if (defaultText) {
|
||||
// Translate the langDefaultText
|
||||
translation = this.translate(defaultText, lang);
|
||||
|
||||
if (translation) {
|
||||
try {
|
||||
// Replace the text with the translated version
|
||||
textNode.node.data = textNode.node.data.split($.trim(textNode.node.data)).join(translation);
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
} else {
|
||||
if (console && console.log) {
|
||||
console.log('Translation for "' + defaultText + '" not found!');
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Replace with original text
|
||||
try {
|
||||
textNode.node.data = textNode.langDefaultText;
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Translates and sets the attributes of an element to the passed language.
|
||||
* @param elem
|
||||
* @param lang
|
||||
* @private
|
||||
*/
|
||||
Lang.prototype._translateAttribs = function (elem, lang) {
|
||||
var attr,
|
||||
attrObj = elem.data('lang-attr') || {},
|
||||
translation;
|
||||
|
||||
for (attr in attrObj) {
|
||||
if (attrObj.hasOwnProperty(attr)) {
|
||||
// Check the element still has the attribute
|
||||
if (elem.attr(attr)) {
|
||||
if (lang !== this.defaultLang) {
|
||||
// Get the translated value
|
||||
translation = this.translate(attrObj[attr], lang);
|
||||
|
||||
// Check we actually HAVE a translation
|
||||
if (translation) {
|
||||
// Change the attribute to the translated value
|
||||
elem.attr(attr, translation);
|
||||
}
|
||||
} else {
|
||||
// Set default language value
|
||||
elem.attr(attr, attrObj[attr]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Translates and sets the contents of an element to the passed language.
|
||||
* @param elem
|
||||
* @param lang
|
||||
* @private
|
||||
*/
|
||||
Lang.prototype._translateContent = function (elem, lang) {
|
||||
var langNotDefault = lang !== this.defaultLang,
|
||||
translation,
|
||||
nodes;
|
||||
|
||||
// Check if the element is an input element
|
||||
if (elem.is('input')) {
|
||||
switch (elem.attr('type')) {
|
||||
case 'button':
|
||||
case 'submit':
|
||||
case 'hidden':
|
||||
case 'reset':
|
||||
if (langNotDefault) {
|
||||
// Get the translated value
|
||||
translation = this.translate(elem.data('lang-val'), lang);
|
||||
|
||||
// Check we actually HAVE a translation
|
||||
if (translation) {
|
||||
// Set translated value
|
||||
elem.val(translation);
|
||||
}
|
||||
} else {
|
||||
// Set default language value
|
||||
elem.val(elem.data('lang-val'));
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else if (elem.is('img')) {
|
||||
if (langNotDefault) {
|
||||
// Get the translated value
|
||||
translation = this.translate(elem.data('lang-src'), lang);
|
||||
|
||||
// Check we actually HAVE a translation
|
||||
if (translation) {
|
||||
// Set translated value
|
||||
elem.attr('src', translation);
|
||||
}
|
||||
} else {
|
||||
// Set default language value
|
||||
elem.attr('src', elem.data('lang-src'));
|
||||
}
|
||||
} else {
|
||||
// Set text node translated text
|
||||
nodes = elem.data('lang-text');
|
||||
if (nodes) {
|
||||
this._setTextNodes(elem, nodes, lang);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Call this to change the current language on the page.
|
||||
* @param {String} lang The new two-letter language code to change to.
|
||||
* @param {String=} selector Optional selector to find language-based
|
||||
* elements for updating.
|
||||
* @param {Function=} callback Optional callback function that will be
|
||||
* called once the language change has been successfully processed. This
|
||||
* is especially useful if you are using dynamic language pack loading
|
||||
* since you will get a callback once it has been loaded and changed.
|
||||
* Your callback will be passed three arguments, a boolean to denote if
|
||||
* there was an error (true if error), the second will be the language
|
||||
* you passed in the change call (the lang argument) and the third will
|
||||
* be the selector used in the change update.
|
||||
*/
|
||||
Lang.prototype.change = function (lang, selector, callback) {
|
||||
var self = this;
|
||||
|
||||
if (lang === this.defaultLang || this.pack[lang] || this._dynamic[lang]) {
|
||||
// Check if the language pack is currently loaded
|
||||
if (lang !== this.defaultLang) {
|
||||
if (!this.pack[lang] && this._dynamic[lang]) {
|
||||
// The language pack needs loading first
|
||||
//console.log('Loading dynamic language pack: ' + this._dynamic[lang] + '...');
|
||||
this.loadPack(lang, function (err, loadingLang, fromUrl) {
|
||||
if (!err) {
|
||||
// Process the change language request
|
||||
self.change.call(self, lang, selector, callback);
|
||||
} else {
|
||||
// Call the callback with the error
|
||||
if (callback) { callback('Language pack could not load from: ' + fromUrl, lang, selector); }
|
||||
}
|
||||
});
|
||||
|
||||
return;
|
||||
} else if (!this.pack[lang] && !this._dynamic[lang]) {
|
||||
// Pack not loaded and no dynamic entry
|
||||
if (callback) { callback('Language pack not defined for: ' + lang, lang, selector); }
|
||||
throw('Could not change language to ' + lang + ' because no language pack for this language exists!');
|
||||
}
|
||||
}
|
||||
|
||||
var fireAfterUpdate = false,
|
||||
currLang = this.currentLang;
|
||||
|
||||
if (this.currentLang != lang) {
|
||||
this.beforeUpdate(currLang, lang);
|
||||
fireAfterUpdate = true;
|
||||
}
|
||||
|
||||
this.currentLang = lang;
|
||||
|
||||
// Get the page HTML
|
||||
var arr = selector !== undefined ? $(selector).find('[lang]') : $(':not(html)[lang]'),
|
||||
arrCount = arr.length,
|
||||
elem;
|
||||
|
||||
while (arrCount--) {
|
||||
elem = $(arr[arrCount]);
|
||||
|
||||
if (elem.attr('lang') !== lang) {
|
||||
this._translateElement(elem, lang);
|
||||
}
|
||||
}
|
||||
|
||||
if (fireAfterUpdate) {
|
||||
this.afterUpdate(currLang, lang);
|
||||
}
|
||||
|
||||
// Check for cookie support
|
||||
if (typeof Cookies !== "undefined") {
|
||||
// Set a cookie to remember this language setting with 1 year expiry
|
||||
Cookies.set(self.cookieName, lang, {
|
||||
expires: self.cookieExpiry,
|
||||
path: self.cookiePath
|
||||
});
|
||||
}
|
||||
|
||||
if (callback) { callback(false, lang, selector); }
|
||||
} else {
|
||||
if (callback) { callback('No language pack defined for: ' + lang, lang, selector); }
|
||||
throw('Attempt to change language to "' + lang + '" but no language pack for that language is loaded!');
|
||||
}
|
||||
};
|
||||
|
||||
Lang.prototype._translateElement = function (elem, lang) {
|
||||
// Translate attributes
|
||||
this._translateAttribs(elem, lang);
|
||||
|
||||
// Translate content
|
||||
if (elem.attr('data-lang-content') != 'false') {
|
||||
this._translateContent(elem, lang);
|
||||
}
|
||||
|
||||
// Update the element's current language
|
||||
elem.attr('lang', lang);
|
||||
};
|
||||
|
||||
/**
|
||||
* Translates text from the default language into the passed language.
|
||||
* @param {String} text The text to translate.
|
||||
* @param {String} lang The two-letter language code to translate to.
|
||||
* @returns {*}
|
||||
*/
|
||||
Lang.prototype.translate = function (text, lang) {
|
||||
lang = lang || this.currentLang;
|
||||
|
||||
if (this.pack[lang]) {
|
||||
var translation = '';
|
||||
|
||||
if (lang != this.defaultLang) {
|
||||
// Check for a direct token translation
|
||||
translation = this.pack[lang].token[text];
|
||||
|
||||
if (!translation) {
|
||||
// No token translation was found, test for regex match
|
||||
translation = this._regexMatch(text, lang);
|
||||
}
|
||||
|
||||
if (!translation) {
|
||||
if (console && console.log) {
|
||||
console.log('Translation for "' + text + '" not found in language pack: ' + lang);
|
||||
}
|
||||
}
|
||||
|
||||
return translation || text;
|
||||
} else {
|
||||
return text;
|
||||
}
|
||||
} else {
|
||||
return text;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks the regex items for a match against the passed text and
|
||||
* if a match is made, translates to the given replacement.
|
||||
* @param {String} text The text to test regex matches against.
|
||||
* @param {String} lang The two-letter language code to translate to.
|
||||
* @returns {string}
|
||||
* @private
|
||||
*/
|
||||
Lang.prototype._regexMatch = function (text, lang) {
|
||||
// Loop the regex array and test them against the text
|
||||
var arr,
|
||||
arrCount,
|
||||
arrIndex,
|
||||
item,
|
||||
regex,
|
||||
expressionResult;
|
||||
|
||||
arr = this.pack[lang].regex;
|
||||
|
||||
if (arr) {
|
||||
arrCount = arr.length;
|
||||
|
||||
for (arrIndex = 0; arrIndex < arrCount; arrIndex++) {
|
||||
item = arr[arrIndex];
|
||||
regex = item[0];
|
||||
|
||||
// Test regex
|
||||
expressionResult = regex.exec(text);
|
||||
|
||||
if (expressionResult && expressionResult[0]) {
|
||||
return text.split(expressionResult[0]).join(item[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
};
|
||||
|
||||
Lang.prototype.beforeUpdate = function (currentLang, newLang) {
|
||||
if (this._fireEvents) {
|
||||
$(this).triggerHandler('beforeUpdate', [currentLang, newLang, this.pack[currentLang], this.pack[newLang]]);
|
||||
}
|
||||
};
|
||||
|
||||
Lang.prototype.afterUpdate = function (currentLang, newLang) {
|
||||
if (this._fireEvents) {
|
||||
$(this).triggerHandler('afterUpdate', [currentLang, newLang, this.pack[currentLang], this.pack[newLang]]);
|
||||
}
|
||||
};
|
||||
|
||||
Lang.prototype.refresh = function () {
|
||||
// Process refresh on the page
|
||||
this._fireEvents = false;
|
||||
this.change(this.currentLang);
|
||||
this._fireEvents = true;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
// Mutation overrides
|
||||
////////////////////////////////////////////////////
|
||||
Lang.prototype._mutation = function (context, method, args) {
|
||||
var result = this._mutationCopies[method].apply(context, args),
|
||||
currLang = this.currentLang,
|
||||
rootElem = $(context);
|
||||
|
||||
if (rootElem.attr('lang')) {
|
||||
// Switch off events for the moment
|
||||
this._fireEvents = false;
|
||||
|
||||
// Check if the root element is currently set to another language from current
|
||||
//if (rootElem.attr('lang') !== this.currentLang) {
|
||||
this._translateElement(rootElem, this.defaultLang);
|
||||
this.change(this.defaultLang, rootElem);
|
||||
|
||||
// Calling change above sets the global currentLang but this is supposed to be
|
||||
// an isolated change so reset the global value back to what it was before
|
||||
this.currentLang = currLang;
|
||||
|
||||
// Record data on the default language from the root element
|
||||
this._processElement(rootElem);
|
||||
|
||||
// Translate the root element
|
||||
this._translateElement(rootElem, this.currentLang);
|
||||
//}
|
||||
}
|
||||
|
||||
// Record data on the default language from the root's children
|
||||
this._start(rootElem);
|
||||
|
||||
// Process translation on any child elements of this element
|
||||
this.change(this.currentLang, rootElem);
|
||||
|
||||
// Switch events back on
|
||||
this._fireEvents = true;
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
return Lang;
|
||||
})();
|
5
assets/webconfig/js/jquery.min.js
vendored
Normal file
5
assets/webconfig/js/jquery.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
145
assets/webconfig/js/js.cookie.js
Normal file
145
assets/webconfig/js/js.cookie.js
Normal file
@@ -0,0 +1,145 @@
|
||||
/*!
|
||||
* JavaScript Cookie v2.0.4
|
||||
* https://github.com/js-cookie/js-cookie
|
||||
*
|
||||
* Copyright 2006, 2015 Klaus Hartl & Fagner Brack
|
||||
* Released under the MIT license
|
||||
*/
|
||||
(function (factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
define(factory);
|
||||
} else if (typeof exports === 'object') {
|
||||
module.exports = factory();
|
||||
} else {
|
||||
var _OldCookies = window.Cookies;
|
||||
var api = window.Cookies = factory();
|
||||
api.noConflict = function () {
|
||||
window.Cookies = _OldCookies;
|
||||
return api;
|
||||
};
|
||||
}
|
||||
}(function () {
|
||||
function extend () {
|
||||
var i = 0;
|
||||
var result = {};
|
||||
for (; i < arguments.length; i++) {
|
||||
var attributes = arguments[ i ];
|
||||
for (var key in attributes) {
|
||||
result[key] = attributes[key];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function init (converter) {
|
||||
function api (key, value, attributes) {
|
||||
var result;
|
||||
|
||||
// Write
|
||||
|
||||
if (arguments.length > 1) {
|
||||
attributes = extend({
|
||||
path: '/'
|
||||
}, api.defaults, attributes);
|
||||
|
||||
if (typeof attributes.expires === 'number') {
|
||||
var expires = new Date();
|
||||
expires.setMilliseconds(expires.getMilliseconds() + attributes.expires * 864e+5);
|
||||
attributes.expires = expires;
|
||||
}
|
||||
|
||||
try {
|
||||
result = JSON.stringify(value);
|
||||
if (/^[\{\[]/.test(result)) {
|
||||
value = result;
|
||||
}
|
||||
} catch (e) {}
|
||||
|
||||
if (!converter.write) {
|
||||
value = encodeURIComponent(String(value))
|
||||
.replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent);
|
||||
} else {
|
||||
value = converter.write(value, key);
|
||||
}
|
||||
|
||||
key = encodeURIComponent(String(key));
|
||||
key = key.replace(/%(23|24|26|2B|5E|60|7C)/g, decodeURIComponent);
|
||||
key = key.replace(/[\(\)]/g, escape);
|
||||
|
||||
return (document.cookie = [
|
||||
key, '=', value,
|
||||
attributes.expires && '; expires=' + attributes.expires.toUTCString(), // use expires attribute, max-age is not supported by IE
|
||||
attributes.path && '; path=' + attributes.path,
|
||||
attributes.domain && '; domain=' + attributes.domain,
|
||||
attributes.secure ? '; secure' : ''
|
||||
].join(''));
|
||||
}
|
||||
|
||||
// Read
|
||||
|
||||
if (!key) {
|
||||
result = {};
|
||||
}
|
||||
|
||||
// To prevent the for loop in the first place assign an empty array
|
||||
// in case there are no cookies at all. Also prevents odd result when
|
||||
// calling "get()"
|
||||
var cookies = document.cookie ? document.cookie.split('; ') : [];
|
||||
var rdecode = /(%[0-9A-Z]{2})+/g;
|
||||
var i = 0;
|
||||
|
||||
for (; i < cookies.length; i++) {
|
||||
var parts = cookies[i].split('=');
|
||||
var name = parts[0].replace(rdecode, decodeURIComponent);
|
||||
var cookie = parts.slice(1).join('=');
|
||||
|
||||
if (cookie.charAt(0) === '"') {
|
||||
cookie = cookie.slice(1, -1);
|
||||
}
|
||||
|
||||
try {
|
||||
cookie = converter.read ?
|
||||
converter.read(cookie, name) : converter(cookie, name) ||
|
||||
cookie.replace(rdecode, decodeURIComponent);
|
||||
|
||||
if (this.json) {
|
||||
try {
|
||||
cookie = JSON.parse(cookie);
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
if (key === name) {
|
||||
result = cookie;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!key) {
|
||||
result[name] = cookie;
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
api.get = api.set = api;
|
||||
api.getJSON = function () {
|
||||
return api.apply({
|
||||
json: true
|
||||
}, [].slice.call(arguments));
|
||||
};
|
||||
api.defaults = {};
|
||||
|
||||
api.remove = function (key, attributes) {
|
||||
api(key, '', extend(attributes, {
|
||||
expires: -1
|
||||
}));
|
||||
};
|
||||
|
||||
api.withConverter = init;
|
||||
|
||||
return api;
|
||||
}
|
||||
|
||||
return init(function () {});
|
||||
}));
|
9
assets/webconfig/js/metisMenu.min.js
vendored
Normal file
9
assets/webconfig/js/metisMenu.min.js
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
/*
|
||||
* metismenu - v1.1.3
|
||||
* Easy menu jQuery plugin for Twitter Bootstrap 3
|
||||
* https://github.com/onokumus/metisMenu
|
||||
*
|
||||
* Made by Osman Nuri Okumus
|
||||
* Under MIT License
|
||||
*/
|
||||
!function(a,b,c){function d(b,c){this.element=a(b),this.settings=a.extend({},f,c),this._defaults=f,this._name=e,this.init()}var e="metisMenu",f={toggle:!0,doubleTapToGo:!1};d.prototype={init:function(){var b=this.element,d=this.settings.toggle,f=this;this.isIE()<=9?(b.find("li.active").has("ul").children("ul").collapse("show"),b.find("li").not(".active").has("ul").children("ul").collapse("hide")):(b.find("li.active").has("ul").children("ul").addClass("collapse in"),b.find("li").not(".active").has("ul").children("ul").addClass("collapse")),f.settings.doubleTapToGo&&b.find("li.active").has("ul").children("a").addClass("doubleTapToGo"),b.find("li").has("ul").children("a").on("click."+e,function(b){return b.preventDefault(),f.settings.doubleTapToGo&&f.doubleTapToGo(a(this))&&"#"!==a(this).attr("href")&&""!==a(this).attr("href")?(b.stopPropagation(),void(c.location=a(this).attr("href"))):(a(this).parent("li").toggleClass("active").children("ul").collapse("toggle"),void(d&&a(this).parent("li").siblings().removeClass("active").children("ul.in").collapse("hide")))})},isIE:function(){for(var a,b=3,d=c.createElement("div"),e=d.getElementsByTagName("i");d.innerHTML="<!--[if gt IE "+ ++b+"]><i></i><![endif]-->",e[0];)return b>4?b:a},doubleTapToGo:function(a){var b=this.element;return a.hasClass("doubleTapToGo")?(a.removeClass("doubleTapToGo"),!0):a.parent().children("ul").length?(b.find(".doubleTapToGo").removeClass("doubleTapToGo"),a.addClass("doubleTapToGo"),!1):void 0},remove:function(){this.element.off("."+e),this.element.removeData(e)}},a.fn[e]=function(b){return this.each(function(){var c=a(this);c.data(e)&&c.data(e).remove(),c.data(e,new d(this,b))}),this}}(jQuery,window,document);
|
44
assets/webconfig/js/sb-admin-2.js
Normal file
44
assets/webconfig/js/sb-admin-2.js
Normal file
@@ -0,0 +1,44 @@
|
||||
$(function() {
|
||||
|
||||
$('#side-menu').metisMenu();
|
||||
|
||||
});
|
||||
|
||||
//Loads the correct sidebar on window load,
|
||||
//collapses the sidebar on window resize.
|
||||
// Sets the min-height of #page-wrapper to window size
|
||||
$(function() {
|
||||
$(window).bind("load resize", function() {
|
||||
var topOffset = 50;
|
||||
var width = (this.window.innerWidth > 0) ? this.window.innerWidth : this.screen.width;
|
||||
if (width < 768) {
|
||||
$('div.navbar-collapse').addClass('collapse');
|
||||
topOffset = 100; // 2-row-menu
|
||||
} else {
|
||||
$('div.navbar-collapse').removeClass('collapse');
|
||||
}
|
||||
|
||||
var height = ((this.window.innerHeight > 0) ? this.window.innerHeight : this.screen.height) - 1;
|
||||
height = height - topOffset;
|
||||
if (height < 1) height = 1;
|
||||
if (height > topOffset) {
|
||||
$("#page-wrapper").css("min-height", (height) + "px");
|
||||
}
|
||||
});
|
||||
|
||||
var url = window.location;
|
||||
// var element = $('ul.nav a').filter(function() {
|
||||
// return this.href == url;
|
||||
// }).addClass('active').parent().parent().addClass('in').parent();
|
||||
var element = $('ul.nav a').filter(function() {
|
||||
return this.href == url;
|
||||
}).addClass('active').parent();
|
||||
|
||||
while(true){
|
||||
if (element.is('li')){
|
||||
element = element.parent().addClass('in').parent();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
2054
assets/webconfig/js/vendor/require.js
vendored
2054
assets/webconfig/js/vendor/require.js
vendored
File diff suppressed because it is too large
Load Diff
594
assets/webconfig/js/vendor/stapes.js
vendored
594
assets/webconfig/js/vendor/stapes.js
vendored
@@ -1,594 +0,0 @@
|
||||
//
|
||||
// ____ _ _
|
||||
// / ___|| |_ __ _ _ __ ___ ___ (_)___ (*)
|
||||
// \___ \| __/ _` | '_ \ / _ \/ __| | / __|
|
||||
// ___) | || (_| | |_) | __/\__ \_ | \__ \
|
||||
// |____/ \__\__,_| .__/ \___||___(_)/ |___/
|
||||
// |_| |__/
|
||||
//
|
||||
// (*) a (really) tiny Javascript MVC microframework
|
||||
//
|
||||
// (c) Hay Kranen < hay@bykr.org >
|
||||
// Released under the terms of the MIT license
|
||||
// < http://en.wikipedia.org/wiki/MIT_License >
|
||||
//
|
||||
// Stapes.js : http://hay.github.com/stapes
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
var VERSION = "0.8.0";
|
||||
|
||||
// Global counter for all events in all modules (including mixed in objects)
|
||||
var guid = 1;
|
||||
|
||||
// Makes _.create() faster
|
||||
if (!Object.create) {
|
||||
var CachedFunction = function(){};
|
||||
}
|
||||
|
||||
// So we can use slice.call for arguments later on
|
||||
var slice = Array.prototype.slice;
|
||||
|
||||
// Private attributes and helper functions, stored in an object so they
|
||||
// are overwritable by plugins
|
||||
var _ = {
|
||||
// Properties
|
||||
attributes : {},
|
||||
|
||||
eventHandlers : {
|
||||
"-1" : {} // '-1' is used for the global event handling
|
||||
},
|
||||
|
||||
guid : -1,
|
||||
|
||||
// Methods
|
||||
addEvent : function(event) {
|
||||
// If we don't have any handlers for this type of event, add a new
|
||||
// array we can use to push new handlers
|
||||
if (!_.eventHandlers[event.guid][event.type]) {
|
||||
_.eventHandlers[event.guid][event.type] = [];
|
||||
}
|
||||
|
||||
// Push an event object
|
||||
_.eventHandlers[event.guid][event.type].push({
|
||||
"guid" : event.guid,
|
||||
"handler" : event.handler,
|
||||
"scope" : event.scope,
|
||||
"type" : event.type
|
||||
});
|
||||
},
|
||||
|
||||
addEventHandler : function(argTypeOrMap, argHandlerOrScope, argScope) {
|
||||
var eventMap = {},
|
||||
scope;
|
||||
|
||||
if (typeof argTypeOrMap === "string") {
|
||||
scope = argScope || false;
|
||||
eventMap[ argTypeOrMap ] = argHandlerOrScope;
|
||||
} else {
|
||||
scope = argHandlerOrScope || false;
|
||||
eventMap = argTypeOrMap;
|
||||
}
|
||||
|
||||
for (var eventString in eventMap) {
|
||||
var handler = eventMap[eventString];
|
||||
var events = eventString.split(" ");
|
||||
|
||||
for (var i = 0, l = events.length; i < l; i++) {
|
||||
var eventType = events[i];
|
||||
_.addEvent.call(this, {
|
||||
"guid" : this._guid || this._.guid,
|
||||
"handler" : handler,
|
||||
"scope" : scope,
|
||||
"type" : eventType
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
addGuid : function(object, forceGuid) {
|
||||
if (object._guid && !forceGuid) return;
|
||||
|
||||
object._guid = guid++;
|
||||
|
||||
_.attributes[object._guid] = {};
|
||||
_.eventHandlers[object._guid] = {};
|
||||
},
|
||||
|
||||
// This is a really small utility function to save typing and produce
|
||||
// better optimized code
|
||||
attr : function(guid) {
|
||||
return _.attributes[guid];
|
||||
},
|
||||
|
||||
clone : function(obj) {
|
||||
var type = _.typeOf(obj);
|
||||
|
||||
if (type === 'object') {
|
||||
return _.extend({}, obj);
|
||||
}
|
||||
|
||||
if (type === 'array') {
|
||||
return obj.slice(0);
|
||||
}
|
||||
},
|
||||
|
||||
create : function(proto) {
|
||||
if (Object.create) {
|
||||
return Object.create(proto);
|
||||
} else {
|
||||
CachedFunction.prototype = proto;
|
||||
return new CachedFunction();
|
||||
}
|
||||
},
|
||||
|
||||
createSubclass : function(props, includeEvents) {
|
||||
props = props || {};
|
||||
includeEvents = includeEvents || false;
|
||||
|
||||
var superclass = props.superclass.prototype;
|
||||
|
||||
// Objects always have a constructor, so we need to be sure this is
|
||||
// a property instead of something from the prototype
|
||||
var realConstructor = props.hasOwnProperty('constructor') ? props.constructor : function(){};
|
||||
|
||||
function constructor() {
|
||||
// Be kind to people forgetting new
|
||||
if (!(this instanceof constructor)) {
|
||||
throw new Error("Please use 'new' when initializing Stapes classes");
|
||||
}
|
||||
|
||||
// If this class has events add a GUID as well
|
||||
if (this.on) {
|
||||
_.addGuid( this, true );
|
||||
}
|
||||
|
||||
realConstructor.apply(this, arguments);
|
||||
}
|
||||
|
||||
if (includeEvents) {
|
||||
_.extend(superclass, Events);
|
||||
}
|
||||
|
||||
constructor.prototype = _.create(superclass);
|
||||
constructor.prototype.constructor = constructor;
|
||||
|
||||
_.extend(constructor, {
|
||||
extend : function() {
|
||||
return _.extendThis.apply(this, arguments);
|
||||
},
|
||||
|
||||
// We can't call this 'super' because that's a reserved keyword
|
||||
// and fails in IE8
|
||||
'parent' : superclass,
|
||||
|
||||
proto : function() {
|
||||
return _.extendThis.apply(this.prototype, arguments);
|
||||
},
|
||||
|
||||
subclass : function(obj) {
|
||||
obj = obj || {};
|
||||
obj.superclass = this;
|
||||
return _.createSubclass(obj);
|
||||
}
|
||||
});
|
||||
|
||||
// Copy all props given in the definition to the prototype
|
||||
for (var key in props) {
|
||||
if (key !== 'constructor' && key !== 'superclass') {
|
||||
constructor.prototype[key] = props[key];
|
||||
}
|
||||
}
|
||||
|
||||
return constructor;
|
||||
},
|
||||
|
||||
emitEvents : function(type, data, explicitType, explicitGuid) {
|
||||
explicitType = explicitType || false;
|
||||
explicitGuid = explicitGuid || this._guid;
|
||||
|
||||
// #30: make a local copy of handlers to prevent problems with
|
||||
// unbinding the event while unwinding the loop
|
||||
var handlers = slice.call(_.eventHandlers[explicitGuid][type]);
|
||||
|
||||
for (var i = 0, l = handlers.length; i < l; i++) {
|
||||
// Clone the event to prevent issue #19
|
||||
var event = _.extend({}, handlers[i]);
|
||||
var scope = (event.scope) ? event.scope : this;
|
||||
|
||||
if (explicitType) {
|
||||
event.type = explicitType;
|
||||
}
|
||||
|
||||
event.scope = scope;
|
||||
event.handler.call(event.scope, data, event);
|
||||
}
|
||||
},
|
||||
|
||||
// Extend an object with more objects
|
||||
extend : function() {
|
||||
var args = slice.call(arguments);
|
||||
var object = args.shift();
|
||||
|
||||
for (var i = 0, l = args.length; i < l; i++) {
|
||||
var props = args[i];
|
||||
for (var key in props) {
|
||||
object[key] = props[key];
|
||||
}
|
||||
}
|
||||
|
||||
return object;
|
||||
},
|
||||
|
||||
// The same as extend, but uses the this value as the scope
|
||||
extendThis : function() {
|
||||
var args = slice.call(arguments);
|
||||
args.unshift(this);
|
||||
return _.extend.apply(this, args);
|
||||
},
|
||||
|
||||
// from http://stackoverflow.com/a/2117523/152809
|
||||
makeUuid : function() {
|
||||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
|
||||
var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
|
||||
return v.toString(16);
|
||||
});
|
||||
},
|
||||
|
||||
removeAttribute : function(keys, silent) {
|
||||
silent = silent || false;
|
||||
|
||||
// Split the key, maybe we want to remove more than one item
|
||||
var attributes = _.trim(keys).split(" ");
|
||||
|
||||
// Actually delete the item
|
||||
for (var i = 0, l = attributes.length; i < l; i++) {
|
||||
var key = _.trim(attributes[i]);
|
||||
|
||||
if (key) {
|
||||
delete _.attr(this._guid)[key];
|
||||
|
||||
// If 'silent' is set, do not throw any events
|
||||
if (!silent) {
|
||||
this.emit('change', key);
|
||||
this.emit('change:' + key);
|
||||
this.emit('remove', key);
|
||||
this.emit('remove:' + key);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
removeEventHandler : function(type, handler) {
|
||||
var handlers = _.eventHandlers[this._guid];
|
||||
|
||||
if (type && handler) {
|
||||
// Remove a specific handler
|
||||
handlers = handlers[type];
|
||||
if (!handlers) return;
|
||||
|
||||
for (var i = 0, l = handlers.length, h; i < l; i++) {
|
||||
h = handlers[i].handler;
|
||||
if (h && h === handler) {
|
||||
handlers.splice(i--, 1);
|
||||
l--;
|
||||
}
|
||||
}
|
||||
} else if (type) {
|
||||
// Remove all handlers for a specific type
|
||||
delete handlers[type];
|
||||
} else {
|
||||
// Remove all handlers for this module
|
||||
_.eventHandlers[this._guid] = {};
|
||||
}
|
||||
},
|
||||
|
||||
setAttribute : function(key, value, silent) {
|
||||
silent = silent || false;
|
||||
|
||||
// We need to do this before we actually add the item :)
|
||||
var itemExists = this.has(key);
|
||||
var oldValue = _.attr(this._guid)[key];
|
||||
|
||||
// Is the value different than the oldValue? If not, ignore this call
|
||||
if (value === oldValue) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Actually add the item to the attributes
|
||||
_.attr(this._guid)[key] = value;
|
||||
|
||||
// If 'silent' flag is set, do not throw any events
|
||||
if (silent) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Throw a generic event
|
||||
this.emit('change', key);
|
||||
|
||||
// And a namespaced event as well, NOTE that we pass value instead of
|
||||
// key here!
|
||||
this.emit('change:' + key, value);
|
||||
|
||||
// Throw namespaced and non-namespaced 'mutate' events as well with
|
||||
// the old value data as well and some extra metadata such as the key
|
||||
var mutateData = {
|
||||
"key" : key,
|
||||
"newValue" : value,
|
||||
"oldValue" : oldValue || null
|
||||
};
|
||||
|
||||
this.emit('mutate', mutateData);
|
||||
this.emit('mutate:' + key, mutateData);
|
||||
|
||||
// Also throw a specific event for this type of set
|
||||
var specificEvent = itemExists ? 'update' : 'create';
|
||||
|
||||
this.emit(specificEvent, key);
|
||||
|
||||
// And a namespaced event as well, NOTE that we pass value instead of key
|
||||
this.emit(specificEvent + ':' + key, value);
|
||||
},
|
||||
|
||||
trim : function(str) {
|
||||
return str.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
|
||||
},
|
||||
|
||||
typeOf : function(val) {
|
||||
if (val === null || typeof val === "undefined") {
|
||||
// This is a special exception for IE, in other browsers the
|
||||
// method below works all the time
|
||||
return String(val);
|
||||
} else {
|
||||
return Object.prototype.toString.call(val).replace(/\[object |\]/g, '').toLowerCase();
|
||||
}
|
||||
},
|
||||
|
||||
updateAttribute : function(key, fn, silent) {
|
||||
var item = this.get(key);
|
||||
|
||||
// In previous versions of Stapes we didn't have the check for object,
|
||||
// but still this worked. In 0.7.0 it suddenly doesn't work anymore and
|
||||
// we need the check. Why? I have no clue.
|
||||
var type = _.typeOf(item);
|
||||
|
||||
if (type === 'object' || type === 'array') {
|
||||
item = _.clone(item);
|
||||
}
|
||||
|
||||
var newValue = fn.call(this, item, key);
|
||||
_.setAttribute.call(this, key, newValue, silent || false);
|
||||
}
|
||||
};
|
||||
|
||||
// Can be mixed in later using Stapes.mixinEvents(object);
|
||||
var Events = {
|
||||
emit : function(types, data) {
|
||||
data = (typeof data === "undefined") ? null : data;
|
||||
|
||||
var splittedTypes = types.split(" ");
|
||||
|
||||
for (var i = 0, l = splittedTypes.length; i < l; i++) {
|
||||
var type = splittedTypes[i];
|
||||
|
||||
// First 'all' type events: is there an 'all' handler in the
|
||||
// global stack?
|
||||
if (_.eventHandlers[-1].all) {
|
||||
_.emitEvents.call(this, "all", data, type, -1);
|
||||
}
|
||||
|
||||
// Catch all events for this type?
|
||||
if (_.eventHandlers[-1][type]) {
|
||||
_.emitEvents.call(this, type, data, type, -1);
|
||||
}
|
||||
|
||||
if (typeof this._guid === 'number') {
|
||||
// 'all' event for this specific module?
|
||||
if (_.eventHandlers[this._guid].all) {
|
||||
_.emitEvents.call(this, "all", data, type);
|
||||
}
|
||||
|
||||
// Finally, normal events :)
|
||||
if (_.eventHandlers[this._guid][type]) {
|
||||
_.emitEvents.call(this, type, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
off : function() {
|
||||
_.removeEventHandler.apply(this, arguments);
|
||||
},
|
||||
|
||||
on : function() {
|
||||
_.addEventHandler.apply(this, arguments);
|
||||
}
|
||||
};
|
||||
|
||||
_.Module = function() {
|
||||
|
||||
};
|
||||
|
||||
_.Module.prototype = {
|
||||
each : function(fn, ctx) {
|
||||
var attr = _.attr(this._guid);
|
||||
for (var key in attr) {
|
||||
var value = attr[key];
|
||||
fn.call(ctx || this, value, key);
|
||||
}
|
||||
},
|
||||
|
||||
extend : function() {
|
||||
return _.extendThis.apply(this, arguments);
|
||||
},
|
||||
|
||||
filter : function(fn) {
|
||||
var filtered = [];
|
||||
var attributes = _.attr(this._guid);
|
||||
|
||||
for (var key in attributes) {
|
||||
if ( fn.call(this, attributes[key], key)) {
|
||||
filtered.push( attributes[key] );
|
||||
}
|
||||
}
|
||||
|
||||
return filtered;
|
||||
},
|
||||
|
||||
get : function(input) {
|
||||
if (typeof input === "string") {
|
||||
return this.has(input) ? _.attr(this._guid)[input] : null;
|
||||
} else if (typeof input === "function") {
|
||||
var items = this.filter(input);
|
||||
return (items.length) ? items[0] : null;
|
||||
}
|
||||
},
|
||||
|
||||
getAll : function() {
|
||||
return _.clone( _.attr(this._guid) );
|
||||
},
|
||||
|
||||
getAllAsArray : function() {
|
||||
var arr = [];
|
||||
var attributes = _.attr(this._guid);
|
||||
|
||||
for (var key in attributes) {
|
||||
var value = attributes[key];
|
||||
|
||||
if (_.typeOf(value) === "object" && !value.id) {
|
||||
value.id = key;
|
||||
}
|
||||
|
||||
arr.push(value);
|
||||
}
|
||||
|
||||
return arr;
|
||||
},
|
||||
|
||||
has : function(key) {
|
||||
return (typeof _.attr(this._guid)[key] !== "undefined");
|
||||
},
|
||||
|
||||
map : function(fn, ctx) {
|
||||
var mapped = [];
|
||||
this.each(function(value, key) {
|
||||
mapped.push( fn.call(ctx || this, value, key) );
|
||||
}, ctx || this);
|
||||
return mapped;
|
||||
},
|
||||
|
||||
// Akin to set(), but makes a unique id
|
||||
push : function(input, silent) {
|
||||
if (_.typeOf(input) === "array") {
|
||||
for (var i = 0, l = input.length; i < l; i++) {
|
||||
_.setAttribute.call(this, _.makeUuid(), input[i], silent || false);
|
||||
}
|
||||
} else {
|
||||
_.setAttribute.call(this, _.makeUuid(), input, silent || false);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
remove : function(input, silent) {
|
||||
if (typeof input === 'undefined') {
|
||||
// With no arguments, remove deletes all attributes
|
||||
_.attributes[this._guid] = {};
|
||||
this.emit('change remove');
|
||||
} else if (typeof input === "function") {
|
||||
this.each(function(item, key) {
|
||||
if (input(item)) {
|
||||
_.removeAttribute.call(this, key, silent);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// nb: checking for exists happens in removeAttribute
|
||||
_.removeAttribute.call(this, input, silent || false);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
set : function(objOrKey, valueOrSilent, silent) {
|
||||
if (typeof objOrKey === "object") {
|
||||
for (var key in objOrKey) {
|
||||
_.setAttribute.call(this, key, objOrKey[key], valueOrSilent || false);
|
||||
}
|
||||
} else {
|
||||
_.setAttribute.call(this, objOrKey, valueOrSilent, silent || false);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
size : function() {
|
||||
var size = 0;
|
||||
var attr = _.attr(this._guid);
|
||||
|
||||
for (var key in attr) {
|
||||
size++;
|
||||
}
|
||||
|
||||
return size;
|
||||
},
|
||||
|
||||
update : function(keyOrFn, fn, silent) {
|
||||
if (typeof keyOrFn === "string") {
|
||||
_.updateAttribute.call(this, keyOrFn, fn, silent || false);
|
||||
} else if (typeof keyOrFn === "function") {
|
||||
this.each(function(value, key) {
|
||||
_.updateAttribute.call(this, key, keyOrFn);
|
||||
});
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
};
|
||||
|
||||
var Stapes = {
|
||||
"_" : _, // private helper functions and properties
|
||||
|
||||
"extend" : function() {
|
||||
return _.extendThis.apply(_.Module.prototype, arguments);
|
||||
},
|
||||
|
||||
"mixinEvents" : function(obj) {
|
||||
obj = obj || {};
|
||||
|
||||
_.addGuid(obj);
|
||||
|
||||
return _.extend(obj, Events);
|
||||
},
|
||||
|
||||
"on" : function() {
|
||||
_.addEventHandler.apply(this, arguments);
|
||||
},
|
||||
|
||||
"subclass" : function(obj, classOnly) {
|
||||
classOnly = classOnly || false;
|
||||
obj = obj || {};
|
||||
obj.superclass = classOnly ? function(){} : _.Module;
|
||||
return _.createSubclass(obj, !classOnly);
|
||||
},
|
||||
|
||||
"version" : VERSION
|
||||
};
|
||||
|
||||
// This library can be used as an AMD module, a Node.js module, or an
|
||||
// old fashioned global
|
||||
if (typeof exports !== "undefined") {
|
||||
// Server
|
||||
if (typeof module !== "undefined" && module.exports) {
|
||||
exports = module.exports = Stapes;
|
||||
}
|
||||
exports.Stapes = Stapes;
|
||||
} else if (typeof define === "function" && define.amd) {
|
||||
// AMD
|
||||
define(function() {
|
||||
return Stapes;
|
||||
});
|
||||
} else {
|
||||
// Global scope
|
||||
window.Stapes = Stapes;
|
||||
}
|
||||
})();
|
1107
assets/webconfig/js/vendor/tinycolor.js
vendored
1107
assets/webconfig/js/vendor/tinycolor.js
vendored
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user