Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
a49505f25d
2
Makefile
2
Makefile
|
@ -3,7 +3,7 @@ BROWSERIFY = ./node_modules/.bin/browserify
|
|||
UGLIFYJS = ./node_modules/.bin/uglifyjs
|
||||
EXORCIST = ./node_modules/.bin/exorcist
|
||||
DEPLOY_DIR = libs
|
||||
BROWSERIFY_FLAGS = -d -x jquery
|
||||
BROWSERIFY_FLAGS = -d
|
||||
OUTPUT_DIR = .
|
||||
|
||||
all: compile uglify deploy clean
|
||||
|
|
11
app.js
11
app.js
|
@ -1,6 +1,17 @@
|
|||
/* jshint -W117 */
|
||||
/* application specific logic */
|
||||
|
||||
require("jquery");
|
||||
require("jquery-ui");
|
||||
require("strophe");
|
||||
require("strophe-disco");
|
||||
require("strophe-caps");
|
||||
require("tooltip");
|
||||
require("popover");
|
||||
window.toastr = require("toastr");
|
||||
require("jQuery-Impromptu");
|
||||
require("autosize");
|
||||
|
||||
var APP =
|
||||
{
|
||||
init: function () {
|
||||
|
|
20
index.html
20
index.html
|
@ -10,15 +10,15 @@
|
|||
<meta itemprop="description" content="Join a WebRTC video conference powered by the Jitsi Videobridge"/>
|
||||
<meta itemprop="image" content="/images/jitsilogo.png"/>
|
||||
<script src="https://api.callstats.io/static/callstats.min.js"></script>
|
||||
<script src="libs/jquery-2.1.1.min.js"></script>
|
||||
<!--<script src="libs/jquery-2.1.1.min.js"></script>-->
|
||||
<script src="config.js?v=14"></script><!-- adapt to your needs, i.e. set hosts and bosh path -->
|
||||
<script src="libs/strophe/strophe.min.js?v=2"></script>
|
||||
<script src="libs/strophe/strophe.disco.min.js?v=1"></script>
|
||||
<script src="libs/strophe/strophe.caps.jsonly.min.js?v=1"></script>
|
||||
<script src="libs/jquery-ui.min.js"></script>
|
||||
<script src="libs/tooltip.min.js?v=1"></script><!-- bootstrap tooltip lib -->
|
||||
<script src="libs/popover.min.js?v=1"></script><!-- bootstrap tooltip lib -->
|
||||
<script src="libs/toastr.min.js?v=1"></script><!-- notifications lib -->
|
||||
<!--<script src="libs/strophe/strophe.min.js?v=2"></script>-->
|
||||
<!--<script src="libs/strophe/strophe.disco.min.js?v=1"></script>-->
|
||||
<!--<script src="libs/strophe/strophe.caps.jsonly.min.js?v=1"></script>-->
|
||||
<!--<script src="libs/jquery-ui.min.js"></script>-->
|
||||
<!--<script src="libs/tooltip.min.js?v=1"></script><!– bootstrap tooltip lib –>-->
|
||||
<!--<script src="libs/popover.min.js?v=1"></script><!– bootstrap tooltip lib –>-->
|
||||
<!--<script src="libs/toastr.min.js?v=1"></script><!– notifications lib –>-->
|
||||
<script src="interface_config.js?v=6"></script>
|
||||
<script src="libs/app.bundle.min.js?v=138"></script>
|
||||
<script src="analytics.js?v=1"></script><!-- google analytics plugin -->
|
||||
|
@ -42,8 +42,8 @@
|
|||
Link used for inline installation of chrome desktop streaming extension,
|
||||
is updated automatically from the code with the value defined in config.js -->
|
||||
<link rel="chrome-webstore-item" href="https://chrome.google.com/webstore/detail/diibjkoicjeejcmhdnailmkgecihlobk">
|
||||
<script src="libs/jquery-impromptu.min.js?v=2"></script>
|
||||
<script src="libs/jquery.autosize.min.js"></script>
|
||||
<!--<script src="libs/jquery-impromptu.min.js?v=2"></script>-->
|
||||
<!--<script src="libs/jquery.autosize.min.js"></script>-->
|
||||
<!--#include virtual="plugin.head.html" -->
|
||||
</head>
|
||||
<body>
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,863 +0,0 @@
|
|||
/*! jQuery-Impromptu - v6.0.0 - 2014-12-27
|
||||
* http://trentrichardson.com/Impromptu
|
||||
* Copyright (c) 2014 Trent Richardson; Licensed MIT */
|
||||
(function(root, factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
define(['jquery'], factory);
|
||||
} else {
|
||||
factory(root.jQuery);
|
||||
}
|
||||
}(this, function($) {
|
||||
'use strict';
|
||||
|
||||
// ########################################################################
|
||||
// Base object
|
||||
// ########################################################################
|
||||
|
||||
/**
|
||||
* Imp - Impromptu object - passing no params will not open, only return the instance
|
||||
* @param message String/Object - String of html or Object of states
|
||||
* @param options Object - Options to set the prompt
|
||||
* @return Imp - the instance of this Impromptu object
|
||||
*/
|
||||
var Imp = function(message, options){
|
||||
var t = this;
|
||||
t.id = Imp.count++;
|
||||
|
||||
Imp.lifo.push(t);
|
||||
|
||||
if(message){
|
||||
t.open(message, options);
|
||||
}
|
||||
return t;
|
||||
};
|
||||
|
||||
// ########################################################################
|
||||
// static properties and methods
|
||||
// ########################################################################
|
||||
|
||||
/**
|
||||
* defaults - the default options
|
||||
*/
|
||||
Imp.defaults = {
|
||||
prefix:'jqi',
|
||||
classes: {
|
||||
box: '',
|
||||
fade: '',
|
||||
prompt: '',
|
||||
form: '',
|
||||
close: '',
|
||||
title: '',
|
||||
message: '',
|
||||
buttons: '',
|
||||
button: '',
|
||||
defaultButton: ''
|
||||
},
|
||||
title: '',
|
||||
closeText: '×',
|
||||
buttons: {
|
||||
Ok: true
|
||||
},
|
||||
loaded: function(e){},
|
||||
submit: function(e,v,m,f){},
|
||||
close: function(e,v,m,f){},
|
||||
statechanging: function(e, from, to){},
|
||||
statechanged: function(e, to){},
|
||||
opacity: 0.6,
|
||||
zIndex: 999,
|
||||
overlayspeed: 'slow',
|
||||
promptspeed: 'fast',
|
||||
show: 'fadeIn',
|
||||
hide: 'fadeOut',
|
||||
focus: 0,
|
||||
defaultButton: 0,
|
||||
useiframe: false,
|
||||
top: '15%',
|
||||
position: {
|
||||
container: null,
|
||||
x: null,
|
||||
y: null,
|
||||
arrow: null,
|
||||
width: null
|
||||
},
|
||||
persistent: true,
|
||||
timeout: 0,
|
||||
states: {},
|
||||
state: {
|
||||
name: null,
|
||||
title: '',
|
||||
html: '',
|
||||
buttons: {
|
||||
Ok: true
|
||||
},
|
||||
focus: 0,
|
||||
defaultButton: 0,
|
||||
position: {
|
||||
container: null,
|
||||
x: null,
|
||||
y: null,
|
||||
arrow: null,
|
||||
width: null
|
||||
},
|
||||
submit: function(e,v,m,f){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* setDefaults - Sets the default options
|
||||
* @param o Object - Options to set as defaults
|
||||
* @return void
|
||||
*/
|
||||
Imp.setDefaults = function(o) {
|
||||
Imp.defaults = $.extend({}, Imp.defaults, o);
|
||||
};
|
||||
|
||||
/**
|
||||
* setStateDefaults - Sets the default options for a state
|
||||
* @param o Object - Options to set as defaults
|
||||
* @return void
|
||||
*/
|
||||
Imp.setStateDefaults = function(o) {
|
||||
Imp.defaults.state = $.extend({}, Imp.defaults.state, o);
|
||||
};
|
||||
|
||||
/**
|
||||
* @var Int - A counter used to provide a unique ID for new prompts
|
||||
*/
|
||||
Imp.count = 0;
|
||||
|
||||
/**
|
||||
* @var Array - An array of Impromptu intances in a LIFO queue (last in first out)
|
||||
*/
|
||||
Imp.lifo = [];
|
||||
|
||||
/**
|
||||
* getLast - get the last element from the queue (doesn't pop, just returns)
|
||||
* @return Imp - the instance of this Impromptu object or false if queue is empty
|
||||
*/
|
||||
Imp.getLast = function(){
|
||||
var l = Imp.lifo.length;
|
||||
return (l > 0)? Imp.lifo[l-1] : false;
|
||||
};
|
||||
|
||||
/**
|
||||
* removeFromStack - remove an element from the lifo stack by its id
|
||||
* @param id int - id of the instance to remove
|
||||
* @return api - The api of the element removed from the stack or void
|
||||
*/
|
||||
Imp.removeFromStack = function(id){
|
||||
for(var i=Imp.lifo.length-1; i>=0; i--){
|
||||
if(Imp.lifo[i].id === id){
|
||||
return Imp.lifo.splice(i,1)[0];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// ########################################################################
|
||||
// extend our object instance properties and methods
|
||||
// ########################################################################
|
||||
Imp.prototype = {
|
||||
|
||||
/**
|
||||
* @var Int - A unique id, simply an autoincremented number
|
||||
*/
|
||||
id: null,
|
||||
|
||||
/**
|
||||
* open - Opens the prompt
|
||||
* @param message String/Object - String of html or Object of states
|
||||
* @param options Object - Options to set the prompt
|
||||
* @return Imp - the instance of this Impromptu object
|
||||
*/
|
||||
open: function(message, options) {
|
||||
var t = this;
|
||||
|
||||
t.options = $.extend({},Imp.defaults,options);
|
||||
|
||||
// Be sure any previous timeouts are destroyed
|
||||
if(t.timeout){
|
||||
clearTimeout(t.timeout);
|
||||
}
|
||||
t.timeout = false;
|
||||
|
||||
var opts = t.options,
|
||||
$body = $(document.body),
|
||||
$window = $(window);
|
||||
|
||||
//build the box and fade
|
||||
var msgbox = '<div class="'+ opts.prefix +'box '+ opts.classes.box +'">';
|
||||
if(opts.useiframe && ($('object, applet').length > 0)) {
|
||||
msgbox += '<iframe src="javascript:false;" style="display:block;position:absolute;z-index:-1;" class="'+ opts.prefix +'fade '+ opts.classes.fade +'"></iframe>';
|
||||
} else {
|
||||
msgbox += '<div class="'+ opts.prefix +'fade '+ opts.classes.fade +'"></div>';
|
||||
}
|
||||
msgbox += '<div class="'+ opts.prefix +' '+ opts.classes.prompt +'">'+
|
||||
'<form action="javascript:false;" onsubmit="return false;" class="'+ opts.prefix +'form '+ opts.classes.form +'">'+
|
||||
'<div class="'+ opts.prefix +'close '+ opts.classes.close +'">'+ opts.closeText +'</div>'+
|
||||
'<div class="'+ opts.prefix +'states"></div>'+
|
||||
'</form>'+
|
||||
'</div>'+
|
||||
'</div>';
|
||||
|
||||
t.jqib = $(msgbox).appendTo($body);
|
||||
t.jqi = t.jqib.children('.'+ opts.prefix);
|
||||
t.jqif = t.jqib.children('.'+ opts.prefix +'fade');
|
||||
|
||||
//if a string was passed, convert to a single state
|
||||
if(message.constructor === String){
|
||||
message = {
|
||||
state0: {
|
||||
title: opts.title,
|
||||
html: message,
|
||||
buttons: opts.buttons,
|
||||
position: opts.position,
|
||||
focus: opts.focus,
|
||||
defaultButton: opts.defaultButton,
|
||||
submit: opts.submit
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
//build the states
|
||||
t.options.states = {};
|
||||
var k,v;
|
||||
for(k in message){
|
||||
v = $.extend({},Imp.defaults.state,{name:k},message[k]);
|
||||
t.addState(v.name, v);
|
||||
|
||||
if(t.currentStateName === ''){
|
||||
t.currentStateName = v.name;
|
||||
}
|
||||
}
|
||||
|
||||
//Events
|
||||
t.jqi.on('click', '.'+ opts.prefix +'buttons button', function(e){
|
||||
var $t = $(this),
|
||||
$state = $t.parents('.'+ opts.prefix +'state'),
|
||||
stateobj = t.options.states[$state.data('jqi-name')],
|
||||
msg = $state.children('.'+ opts.prefix +'message'),
|
||||
clicked = stateobj.buttons[$t.text()] || stateobj.buttons[$t.html()],
|
||||
forminputs = {};
|
||||
|
||||
// if for some reason we couldn't get the value
|
||||
if(clicked === undefined){
|
||||
for(var i in stateobj.buttons){
|
||||
if(stateobj.buttons[i].title === $t.text() || stateobj.buttons[i].title === $t.html()){
|
||||
clicked = stateobj.buttons[i].value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//collect all form element values from all states.
|
||||
$.each(t.jqi.children('form').serializeArray(),function(i,obj){
|
||||
if (forminputs[obj.name] === undefined) {
|
||||
forminputs[obj.name] = obj.value;
|
||||
} else if (typeof forminputs[obj.name] === Array || typeof forminputs[obj.name] === 'object') {
|
||||
forminputs[obj.name].push(obj.value);
|
||||
} else {
|
||||
forminputs[obj.name] = [forminputs[obj.name],obj.value];
|
||||
}
|
||||
});
|
||||
|
||||
// trigger an event
|
||||
var promptsubmite = new $.Event('impromptu:submit');
|
||||
promptsubmite.stateName = stateobj.name;
|
||||
promptsubmite.state = $state;
|
||||
$state.trigger(promptsubmite, [clicked, msg, forminputs]);
|
||||
|
||||
if(!promptsubmite.isDefaultPrevented()){
|
||||
t.close(true, clicked,msg,forminputs);
|
||||
}
|
||||
});
|
||||
|
||||
// if the fade is clicked blink the prompt
|
||||
var fadeClicked = function(){
|
||||
if(opts.persistent){
|
||||
var offset = (opts.top.toString().indexOf('%') >= 0? ($window.height()*(parseInt(opts.top,10)/100)) : parseInt(opts.top,10)),
|
||||
top = parseInt(t.jqi.css('top').replace('px',''),10) - offset;
|
||||
|
||||
//$window.scrollTop(top);
|
||||
$('html,body').animate({ scrollTop: top }, 'fast', function(){
|
||||
var i = 0;
|
||||
t.jqib.addClass(opts.prefix +'warning');
|
||||
var intervalid = setInterval(function(){
|
||||
t.jqib.toggleClass(opts.prefix +'warning');
|
||||
if(i++ > 1){
|
||||
clearInterval(intervalid);
|
||||
t.jqib.removeClass(opts.prefix +'warning');
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
}
|
||||
else {
|
||||
t.close(true);
|
||||
}
|
||||
};
|
||||
|
||||
// listen for esc or tab keys
|
||||
var keyDownEventHandler = function(e){
|
||||
var key = (window.event) ? event.keyCode : e.keyCode;
|
||||
|
||||
//escape key closes
|
||||
if(key === 27) {
|
||||
fadeClicked();
|
||||
}
|
||||
|
||||
//enter key pressed trigger the default button if its not on it, ignore if it is a textarea
|
||||
if(key === 13){
|
||||
var $defBtn = t.getCurrentState().find('.'+ opts.prefix +'defaultbutton');
|
||||
var $tgt = $(e.target);
|
||||
|
||||
if($tgt.is('textarea,.'+opts.prefix+'button') === false && $defBtn.length > 0){
|
||||
e.preventDefault();
|
||||
$defBtn.click();
|
||||
}
|
||||
}
|
||||
|
||||
//constrain tabs, tabs should iterate through the state and not leave
|
||||
if (key === 9){
|
||||
var $inputels = $('input,select,textarea,button',t.getCurrentState());
|
||||
var fwd = !e.shiftKey && e.target === $inputels[$inputels.length-1];
|
||||
var back = e.shiftKey && e.target === $inputels[0];
|
||||
if (fwd || back) {
|
||||
setTimeout(function(){
|
||||
if (!$inputels){
|
||||
return;
|
||||
}
|
||||
var el = $inputels[back===true ? $inputels.length-1 : 0];
|
||||
|
||||
if (el){
|
||||
el.focus();
|
||||
}
|
||||
},10);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
t.position();
|
||||
t.style();
|
||||
|
||||
// store copy of the window resize function for interal use only
|
||||
t._windowResize = function(e){
|
||||
t.position(e);
|
||||
};
|
||||
$window.resize({ animate: false }, t._windowResize);
|
||||
|
||||
t.jqif.click(fadeClicked);
|
||||
t.jqi.find('.'+ opts.prefix +'close').click(function(){ t.close(); });
|
||||
t.jqib.on("keydown",keyDownEventHandler)
|
||||
.on('impromptu:loaded', opts.loaded)
|
||||
.on('impromptu:close', opts.close)
|
||||
.on('impromptu:statechanging', opts.statechanging)
|
||||
.on('impromptu:statechanged', opts.statechanged);
|
||||
|
||||
// Show it
|
||||
t.jqif[opts.show](opts.overlayspeed);
|
||||
t.jqi[opts.show](opts.promptspeed, function(){
|
||||
|
||||
var $firstState = t.jqi.find('.'+ opts.prefix +'states .'+ opts.prefix +'state').eq(0);
|
||||
t.goToState($firstState.data('jqi-name'));
|
||||
|
||||
t.jqib.trigger('impromptu:loaded');
|
||||
});
|
||||
|
||||
// Timeout
|
||||
if(opts.timeout > 0){
|
||||
t.timeout = setTimeout(function(){ t.close(true); },opts.timeout);
|
||||
}
|
||||
|
||||
return t;
|
||||
},
|
||||
|
||||
/**
|
||||
* close - Closes the prompt
|
||||
* @param callback Function - called when the transition is complete
|
||||
* @param clicked String - value of the button clicked (only used internally)
|
||||
* @param msg jQuery - The state message body (only used internally)
|
||||
* @param forvals Object - key/value pairs of all form field names and values (only used internally)
|
||||
* @return Imp - the instance of this Impromptu object
|
||||
*/
|
||||
close: function(callCallback, clicked, msg, formvals){
|
||||
var t = this;
|
||||
Imp.removeFromStack(t.id);
|
||||
|
||||
if(t.timeout){
|
||||
clearTimeout(t.timeout);
|
||||
t.timeout = false;
|
||||
}
|
||||
|
||||
if(t.jqib){
|
||||
t.jqib[t.options.hide]('fast',function(){
|
||||
|
||||
t.jqib.trigger('impromptu:close', [clicked,msg,formvals]);
|
||||
|
||||
t.jqib.remove();
|
||||
|
||||
$(window).off('resize', t._windowResize);
|
||||
|
||||
if(typeof callCallback === 'function'){
|
||||
callCallback();
|
||||
}
|
||||
});
|
||||
}
|
||||
t.currentStateName = "";
|
||||
|
||||
return t;
|
||||
},
|
||||
|
||||
/**
|
||||
* addState - Injects a state into the prompt
|
||||
* @param statename String - Name of the state
|
||||
* @param stateobj Object - options for the state
|
||||
* @param afterState String - selector of the state to insert after
|
||||
* @return jQuery - the newly created state
|
||||
*/
|
||||
addState: function(statename, stateobj, afterState) {
|
||||
var t = this,
|
||||
state = '',
|
||||
$state = null,
|
||||
arrow = '',
|
||||
title = '',
|
||||
opts = t.options,
|
||||
$jqistates = $('.'+ opts.prefix +'states'),
|
||||
buttons = [],
|
||||
showHtml,defbtn,k,v,l,i=0;
|
||||
|
||||
stateobj = $.extend({},Imp.defaults.state, {name:statename}, stateobj);
|
||||
|
||||
if(stateobj.position.arrow !== null){
|
||||
arrow = '<div class="'+ opts.prefix + 'arrow '+ opts.prefix + 'arrow'+ stateobj.position.arrow +'"></div>';
|
||||
}
|
||||
if(stateobj.title && stateobj.title !== ''){
|
||||
title = '<div class="lead '+ opts.prefix + 'title '+ opts.classes.title +'">'+ stateobj.title +'</div>';
|
||||
}
|
||||
|
||||
showHtml = stateobj.html;
|
||||
if (typeof stateobj.html === 'function') {
|
||||
showHtml = 'Error: html function must return text';
|
||||
}
|
||||
|
||||
state += '<div class="'+ opts.prefix + 'state" data-jqi-name="'+ statename +'" style="display:none;">'+
|
||||
arrow + title +
|
||||
'<div class="'+ opts.prefix +'message '+ opts.classes.message +'">' + showHtml +'</div>'+
|
||||
'<div class="'+ opts.prefix +'buttons '+ opts.classes.buttons +'"'+ ($.isEmptyObject(stateobj.buttons)? 'style="display:none;"':'') +'>';
|
||||
|
||||
// state buttons may be in object or array, lets convert objects to arrays
|
||||
if($.isArray(stateobj.buttons)){
|
||||
buttons = stateobj.buttons;
|
||||
}
|
||||
else if($.isPlainObject(stateobj.buttons)){
|
||||
for(k in stateobj.buttons){
|
||||
if(stateobj.buttons.hasOwnProperty(k)){
|
||||
buttons.push({ title: k, value: stateobj.buttons[k] });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// iterate over each button and create them
|
||||
for(i=0, l=buttons.length; i<l; i++){
|
||||
v = buttons[i],
|
||||
defbtn = stateobj.focus === i || (isNaN(stateobj.focus) && stateobj.defaultButton === i) ? (opts.prefix + 'defaultbutton ' + opts.classes.defaultButton) : '';
|
||||
|
||||
state += '<button class="'+ opts.classes.button +' '+ opts.prefix + 'button '+ defbtn;
|
||||
|
||||
if(typeof v.classes !== "undefined"){
|
||||
state += ' '+ ($.isArray(v.classes)? v.classes.join(' ') : v.classes) + ' ';
|
||||
}
|
||||
|
||||
state += '" name="' + opts.prefix + '_' + statename + '_button' + v.title.replace(/[^a-z0-9]+/gi,'') + '" value="' + v.value + '">' + v.title + '</button>';
|
||||
}
|
||||
|
||||
state += '</div></div>';
|
||||
|
||||
$state = $(state);
|
||||
|
||||
$state.on('impromptu:submit', stateobj.submit);
|
||||
|
||||
if(afterState !== undefined){
|
||||
$jqistates.find('[data-jqi-name="'+afterState+'"]').after($state);
|
||||
}
|
||||
else{
|
||||
$jqistates.append($state);
|
||||
}
|
||||
|
||||
t.options.states[statename] = stateobj;
|
||||
|
||||
return $state;
|
||||
},
|
||||
|
||||
/**
|
||||
* removeState - Removes a state from the prompt
|
||||
* @param state String - Name of the state
|
||||
* @param newState String - Name of the state to transition to
|
||||
* @return Boolean - returns true on success, false on failure
|
||||
*/
|
||||
removeState: function(state, newState) {
|
||||
var t = this,
|
||||
$state = t.getState(state),
|
||||
rm = function(){ $state.remove(); };
|
||||
|
||||
if($state.length === 0){
|
||||
return false;
|
||||
}
|
||||
|
||||
// transition away from it before deleting
|
||||
if($state.css('display') !== 'none'){
|
||||
if(newState !== undefined && t.getState(newState).length > 0){
|
||||
t.goToState(newState, false, rm);
|
||||
}
|
||||
else if($state.next().length > 0){
|
||||
t.nextState(rm);
|
||||
}
|
||||
else if($state.prev().length > 0){
|
||||
t.prevState(rm);
|
||||
}
|
||||
else{
|
||||
t.close();
|
||||
}
|
||||
}
|
||||
else{
|
||||
$state.slideUp('slow', rm);
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* getApi - Get the api, so you can extract it from $.prompt stack
|
||||
* @return jQuery - the prompt
|
||||
*/
|
||||
getApi: function() {
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* getBox - Get the box containing fade and prompt
|
||||
* @return jQuery - the prompt
|
||||
*/
|
||||
getBox: function() {
|
||||
return this.jqib;
|
||||
},
|
||||
|
||||
/**
|
||||
* getPrompt - Get the prompt
|
||||
* @return jQuery - the prompt
|
||||
*/
|
||||
getPrompt: function() {
|
||||
return this.jqi;
|
||||
},
|
||||
|
||||
/**
|
||||
* getState - Get the state by its name
|
||||
* @param statename String - Name of the state
|
||||
* @return jQuery - the state
|
||||
*/
|
||||
getState: function(statename) {
|
||||
return this.jqi.find('[data-jqi-name="'+ statename +'"]');
|
||||
},
|
||||
|
||||
/**
|
||||
* getCurrentState - Get the current visible state
|
||||
* @return jQuery - the current visible state
|
||||
*/
|
||||
getCurrentState: function() {
|
||||
return this.getState(this.getCurrentStateName());
|
||||
},
|
||||
|
||||
/**
|
||||
* getCurrentStateName - Get the name of the current visible state/substate
|
||||
* @return String - the current visible state's name
|
||||
*/
|
||||
getCurrentStateName: function() {
|
||||
return this.currentStateName;
|
||||
},
|
||||
|
||||
/**
|
||||
* position - Repositions the prompt (Used internally)
|
||||
* @return void
|
||||
*/
|
||||
position: function(e){
|
||||
var t = this,
|
||||
restoreFx = $.fx.off,
|
||||
$state = t.getCurrentState(),
|
||||
stateObj = t.options.states[$state.data('jqi-name')],
|
||||
pos = stateObj? stateObj.position : undefined,
|
||||
$window = $(window),
|
||||
bodyHeight = document.body.scrollHeight, //$(document.body).outerHeight(true),
|
||||
windowHeight = $(window).height(),
|
||||
documentHeight = $(document).height(),
|
||||
height = bodyHeight > windowHeight ? bodyHeight : windowHeight,
|
||||
top = parseInt($window.scrollTop(),10) + (t.options.top.toString().indexOf('%') >= 0?
|
||||
(windowHeight*(parseInt(t.options.top,10)/100)) : parseInt(t.options.top,10));
|
||||
|
||||
// when resizing the window turn off animation
|
||||
if(e !== undefined && e.data.animate === false){
|
||||
$.fx.off = true;
|
||||
}
|
||||
|
||||
t.jqib.css({
|
||||
position: "absolute",
|
||||
height: height,
|
||||
width: "100%",
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0
|
||||
});
|
||||
t.jqif.css({
|
||||
position: "fixed",
|
||||
height: height,
|
||||
width: "100%",
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0
|
||||
});
|
||||
|
||||
// tour positioning
|
||||
if(pos && pos.container){
|
||||
var offset = $(pos.container).offset();
|
||||
|
||||
if($.isPlainObject(offset) && offset.top !== undefined){
|
||||
t.jqi.css({
|
||||
position: "absolute"
|
||||
});
|
||||
t.jqi.animate({
|
||||
top: offset.top + pos.y,
|
||||
left: offset.left + pos.x,
|
||||
marginLeft: 0,
|
||||
width: (pos.width !== undefined)? pos.width : null
|
||||
});
|
||||
top = (offset.top + pos.y) - (t.options.top.toString().indexOf('%') >= 0? (windowHeight*(parseInt(t.options.top,10)/100)) : parseInt(t.options.top,10));
|
||||
$('html,body').animate({ scrollTop: top }, 'slow', 'swing', function(){});
|
||||
}
|
||||
}
|
||||
// custom state width animation
|
||||
else if(pos && pos.width){
|
||||
t.jqi.css({
|
||||
position: "absolute",
|
||||
left: '50%'
|
||||
});
|
||||
t.jqi.animate({
|
||||
top: pos.y || top,
|
||||
left: pos.x || '50%',
|
||||
marginLeft: ((pos.width/2)*-1),
|
||||
width: pos.width
|
||||
});
|
||||
}
|
||||
// standard prompt positioning
|
||||
else{
|
||||
t.jqi.css({
|
||||
position: "absolute",
|
||||
top: top,
|
||||
left: '50%',//$window.width()/2,
|
||||
marginLeft: ((t.jqi.outerWidth(false)/2)*-1)
|
||||
});
|
||||
}
|
||||
|
||||
// restore fx settings
|
||||
if(e !== undefined && e.data.animate === false){
|
||||
$.fx.off = restoreFx;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* style - Restyles the prompt (Used internally)
|
||||
* @return void
|
||||
*/
|
||||
style: function(){
|
||||
var t = this;
|
||||
|
||||
t.jqif.css({
|
||||
zIndex: t.options.zIndex,
|
||||
display: "none",
|
||||
opacity: t.options.opacity
|
||||
});
|
||||
t.jqi.css({
|
||||
zIndex: t.options.zIndex+1,
|
||||
display: "none"
|
||||
});
|
||||
t.jqib.css({
|
||||
zIndex: t.options.zIndex
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* goToState - Goto the specified state
|
||||
* @param state String - name of the state to transition to
|
||||
* @param subState Boolean - true to be a sub state within the currently open state
|
||||
* @param callback Function - called when the transition is complete
|
||||
* @return jQuery - the newly active state
|
||||
*/
|
||||
goToState: function(state, subState, callback) {
|
||||
var t = this,
|
||||
$jqi = t.jqi,
|
||||
jqiopts = t.options,
|
||||
$state = t.getState(state),
|
||||
stateobj = jqiopts.states[$state.data('jqi-name')],
|
||||
promptstatechanginge = new $.Event('impromptu:statechanging'),
|
||||
opts = t.options;
|
||||
|
||||
if(stateobj !== undefined){
|
||||
|
||||
|
||||
if (typeof stateobj.html === 'function') {
|
||||
var contentLaterFunc = stateobj.html;
|
||||
$state.find('.' + opts.prefix +'message ').html(contentLaterFunc());
|
||||
}
|
||||
|
||||
// subState can be ommitted
|
||||
if(typeof subState === 'function'){
|
||||
callback = subState;
|
||||
subState = false;
|
||||
}
|
||||
|
||||
t.jqib.trigger(promptstatechanginge, [t.getCurrentStateName(), state]);
|
||||
|
||||
if(!promptstatechanginge.isDefaultPrevented() && $state.length > 0){
|
||||
t.jqi.find('.'+ opts.prefix +'parentstate').removeClass(opts.prefix +'parentstate');
|
||||
|
||||
if(subState){ // hide any open substates
|
||||
// get rid of any substates
|
||||
t.jqi.find('.'+ opts.prefix +'substate').not($state)
|
||||
.slideUp(jqiopts.promptspeed)
|
||||
.removeClass('.'+ opts.prefix +'substate')
|
||||
.find('.'+ opts.prefix +'arrow').hide();
|
||||
|
||||
// add parent state class so it can be visible, but blocked
|
||||
t.jqi.find('.'+ opts.prefix +'state:visible').addClass(opts.prefix +'parentstate');
|
||||
|
||||
// add substate class so we know it will be smaller
|
||||
$state.addClass(opts.prefix +'substate');
|
||||
}
|
||||
else{ // hide any open states
|
||||
t.jqi.find('.'+ opts.prefix +'state').not($state)
|
||||
.slideUp(jqiopts.promptspeed)
|
||||
.find('.'+ opts.prefix +'arrow').hide();
|
||||
}
|
||||
t.currentStateName = stateobj.name;
|
||||
|
||||
$state.slideDown(jqiopts.promptspeed,function(){
|
||||
var $t = $(this);
|
||||
|
||||
// if focus is a selector, find it, else its button index
|
||||
if(typeof(stateobj.focus) === 'string'){
|
||||
$t.find(stateobj.focus).eq(0).focus();
|
||||
}
|
||||
else{
|
||||
$t.find('.'+ opts.prefix +'defaultbutton').focus();
|
||||
}
|
||||
|
||||
$t.find('.'+ opts.prefix +'arrow').show(jqiopts.promptspeed);
|
||||
|
||||
if (typeof callback === 'function'){
|
||||
t.jqib.on('impromptu:statechanged', callback);
|
||||
}
|
||||
t.jqib.trigger('impromptu:statechanged', [state]);
|
||||
if (typeof callback === 'function'){
|
||||
t.jqib.off('impromptu:statechanged', callback);
|
||||
}
|
||||
});
|
||||
if(!subState){
|
||||
t.position();
|
||||
}
|
||||
} // end isDefaultPrevented()
|
||||
}// end stateobj !== undefined
|
||||
|
||||
return $state;
|
||||
},
|
||||
|
||||
/**
|
||||
* nextState - Transition to the next state
|
||||
* @param callback Function - called when the transition is complete
|
||||
* @return jQuery - the newly active state
|
||||
*/
|
||||
nextState: function(callback) {
|
||||
var t = this,
|
||||
$next = t.getCurrentState().next();
|
||||
if($next.length > 0){
|
||||
t.goToState( $next.data('jqi-name'), callback );
|
||||
}
|
||||
return $next;
|
||||
},
|
||||
|
||||
/**
|
||||
* prevState - Transition to the previous state
|
||||
* @param callback Function - called when the transition is complete
|
||||
* @return jQuery - the newly active state
|
||||
*/
|
||||
prevState: function(callback) {
|
||||
var t = this,
|
||||
$prev = t.getCurrentState().prev();
|
||||
if($prev.length > 0){
|
||||
t.goToState( $prev.data('jqi-name'), callback );
|
||||
}
|
||||
return $prev;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// ########################################################################
|
||||
// $.prompt will manage a queue of Impromptu instances
|
||||
// ########################################################################
|
||||
|
||||
/**
|
||||
* $.prompt create a new Impromptu instance and push it on the stack of instances
|
||||
* @param message String/Object - String of html or Object of states
|
||||
* @param options Object - Options to set the prompt
|
||||
* @return jQuery - the jQuery object of the prompt within the modal
|
||||
*/
|
||||
$.prompt = function(message, options){
|
||||
var api = new Imp(message, options);
|
||||
return api.jqi;
|
||||
};
|
||||
|
||||
/**
|
||||
* Copy over static methods
|
||||
*/
|
||||
$.each(Imp, function(k,v){
|
||||
$.prompt[k] = v;
|
||||
});
|
||||
|
||||
/**
|
||||
* Create a proxy for accessing all instance methods. The close method pops from queue.
|
||||
*/
|
||||
$.each(Imp.prototype, function(k,v){
|
||||
$.prompt[k] = function(){
|
||||
var api = Imp.getLast(); // always use the last instance on the stack
|
||||
|
||||
if(api && typeof api[k] === "function"){
|
||||
return api[k].apply(api, arguments);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
// ########################################################################
|
||||
// jQuery Plugin and public access
|
||||
// ########################################################################
|
||||
|
||||
/**
|
||||
* Enable using $('.selector').prompt({});
|
||||
* This will grab the html within the prompt as the prompt message
|
||||
*/
|
||||
$.fn.prompt = function(options){
|
||||
if(options === undefined){
|
||||
options = {};
|
||||
}
|
||||
if(options.withDataAndEvents === undefined){
|
||||
options.withDataAndEvents = false;
|
||||
}
|
||||
|
||||
$.prompt($(this).clone(options.withDataAndEvents).html(),options);
|
||||
};
|
||||
|
||||
/**
|
||||
* Export it as Impromptu and $.prompt
|
||||
* Can be used from here forth as new Impromptu(states, opts)
|
||||
*/
|
||||
window.Impromptu = Imp;
|
||||
|
||||
}));
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,250 +0,0 @@
|
|||
/*!
|
||||
Autosize v1.18.1 - 2013-11-05
|
||||
Automatically adjust textarea height based on user input.
|
||||
(c) 2013 Jack Moore - http://www.jacklmoore.com/autosize
|
||||
license: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
(function ($) {
|
||||
var
|
||||
defaults = {
|
||||
className: 'autosizejs',
|
||||
append: '',
|
||||
callback: false,
|
||||
resizeDelay: 10
|
||||
},
|
||||
|
||||
// border:0 is unnecessary, but avoids a bug in Firefox on OSX
|
||||
copy = '<textarea tabindex="-1" style="position:absolute; top:-999px; left:0; right:auto; bottom:auto; border:0; padding: 0; -moz-box-sizing:content-box; -webkit-box-sizing:content-box; box-sizing:content-box; word-wrap:break-word; height:0 !important; min-height:0 !important; overflow:hidden; transition:none; -webkit-transition:none; -moz-transition:none;"/>',
|
||||
|
||||
// line-height is conditionally included because IE7/IE8/old Opera do not return the correct value.
|
||||
typographyStyles = [
|
||||
'fontFamily',
|
||||
'fontSize',
|
||||
'fontWeight',
|
||||
'fontStyle',
|
||||
'letterSpacing',
|
||||
'textTransform',
|
||||
'wordSpacing',
|
||||
'textIndent'
|
||||
],
|
||||
|
||||
// to keep track which textarea is being mirrored when adjust() is called.
|
||||
mirrored,
|
||||
|
||||
// the mirror element, which is used to calculate what size the mirrored element should be.
|
||||
mirror = $(copy).data('autosize', true)[0];
|
||||
|
||||
// test that line-height can be accurately copied.
|
||||
mirror.style.lineHeight = '99px';
|
||||
if ($(mirror).css('lineHeight') === '99px') {
|
||||
typographyStyles.push('lineHeight');
|
||||
}
|
||||
mirror.style.lineHeight = '';
|
||||
|
||||
$.fn.autosize = function (options) {
|
||||
if (!this.length) {
|
||||
return this;
|
||||
}
|
||||
|
||||
options = $.extend({}, defaults, options || {});
|
||||
|
||||
if (mirror.parentNode !== document.body) {
|
||||
$(document.body).append(mirror);
|
||||
}
|
||||
|
||||
return this.each(function () {
|
||||
var
|
||||
ta = this,
|
||||
$ta = $(ta),
|
||||
maxHeight,
|
||||
minHeight,
|
||||
boxOffset = 0,
|
||||
callback = $.isFunction(options.callback),
|
||||
originalStyles = {
|
||||
height: ta.style.height,
|
||||
overflow: ta.style.overflow,
|
||||
overflowY: ta.style.overflowY,
|
||||
wordWrap: ta.style.wordWrap,
|
||||
resize: ta.style.resize
|
||||
},
|
||||
timeout,
|
||||
width = $ta.width();
|
||||
|
||||
if ($ta.data('autosize')) {
|
||||
// exit if autosize has already been applied, or if the textarea is the mirror element.
|
||||
return;
|
||||
}
|
||||
$ta.data('autosize', true);
|
||||
|
||||
if ($ta.css('box-sizing') === 'border-box' || $ta.css('-moz-box-sizing') === 'border-box' || $ta.css('-webkit-box-sizing') === 'border-box'){
|
||||
boxOffset = $ta.outerHeight() - $ta.height();
|
||||
}
|
||||
|
||||
// IE8 and lower return 'auto', which parses to NaN, if no min-height is set.
|
||||
minHeight = Math.max(parseInt($ta.css('minHeight'), 10) - boxOffset || 0, $ta.height());
|
||||
|
||||
$ta.css({
|
||||
overflow: 'hidden',
|
||||
overflowY: 'hidden',
|
||||
wordWrap: 'break-word', // horizontal overflow is hidden, so break-word is necessary for handling words longer than the textarea width
|
||||
resize: ($ta.css('resize') === 'none' || $ta.css('resize') === 'vertical') ? 'none' : 'horizontal'
|
||||
});
|
||||
|
||||
// The mirror width must exactly match the textarea width, so using getBoundingClientRect because it doesn't round the sub-pixel value.
|
||||
function setWidth() {
|
||||
var style, width;
|
||||
|
||||
if ('getComputedStyle' in window) {
|
||||
style = window.getComputedStyle(ta, null);
|
||||
width = ta.getBoundingClientRect().width;
|
||||
|
||||
$.each(['paddingLeft', 'paddingRight', 'borderLeftWidth', 'borderRightWidth'], function(i,val){
|
||||
width -= parseInt(style[val],10);
|
||||
});
|
||||
|
||||
mirror.style.width = width + 'px';
|
||||
}
|
||||
else {
|
||||
// window.getComputedStyle, getBoundingClientRect returning a width are unsupported and unneeded in IE8 and lower.
|
||||
mirror.style.width = Math.max($ta.width(), 0) + 'px';
|
||||
}
|
||||
}
|
||||
|
||||
function initMirror() {
|
||||
var styles = {};
|
||||
|
||||
mirrored = ta;
|
||||
mirror.className = options.className;
|
||||
maxHeight = parseInt($ta.css('maxHeight'), 10);
|
||||
|
||||
// mirror is a duplicate textarea located off-screen that
|
||||
// is automatically updated to contain the same text as the
|
||||
// original textarea. mirror always has a height of 0.
|
||||
// This gives a cross-browser supported way getting the actual
|
||||
// height of the text, through the scrollTop property.
|
||||
$.each(typographyStyles, function(i,val){
|
||||
styles[val] = $ta.css(val);
|
||||
});
|
||||
$(mirror).css(styles);
|
||||
|
||||
setWidth();
|
||||
|
||||
// Chrome-specific fix:
|
||||
// When the textarea y-overflow is hidden, Chrome doesn't reflow the text to account for the space
|
||||
// made available by removing the scrollbar. This workaround triggers the reflow for Chrome.
|
||||
if (window.chrome) {
|
||||
var width = ta.style.width;
|
||||
ta.style.width = '0px';
|
||||
var ignore = ta.offsetWidth;
|
||||
ta.style.width = width;
|
||||
}
|
||||
}
|
||||
|
||||
// Using mainly bare JS in this function because it is going
|
||||
// to fire very often while typing, and needs to very efficient.
|
||||
function adjust() {
|
||||
var height, original;
|
||||
|
||||
if (mirrored !== ta) {
|
||||
initMirror();
|
||||
} else {
|
||||
setWidth();
|
||||
}
|
||||
|
||||
mirror.value = ta.value + options.append;
|
||||
mirror.style.overflowY = ta.style.overflowY;
|
||||
original = parseInt(ta.style.height,10);
|
||||
|
||||
// Setting scrollTop to zero is needed in IE8 and lower for the next step to be accurately applied
|
||||
mirror.scrollTop = 0;
|
||||
|
||||
mirror.scrollTop = 9e4;
|
||||
|
||||
// Using scrollTop rather than scrollHeight because scrollHeight is non-standard and includes padding.
|
||||
height = mirror.scrollTop;
|
||||
|
||||
if (maxHeight && height > maxHeight) {
|
||||
ta.style.overflowY = 'scroll';
|
||||
height = maxHeight;
|
||||
} else {
|
||||
ta.style.overflowY = 'hidden';
|
||||
if (height < minHeight) {
|
||||
height = minHeight;
|
||||
}
|
||||
}
|
||||
|
||||
height += boxOffset;
|
||||
|
||||
if (original !== height) {
|
||||
ta.style.height = height + 'px';
|
||||
if (callback) {
|
||||
options.callback.call(ta,ta);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function resize () {
|
||||
clearTimeout(timeout);
|
||||
timeout = setTimeout(function(){
|
||||
var newWidth = $ta.width();
|
||||
|
||||
if (newWidth !== width) {
|
||||
width = newWidth;
|
||||
adjust();
|
||||
}
|
||||
}, parseInt(options.resizeDelay,10));
|
||||
}
|
||||
|
||||
if ('onpropertychange' in ta) {
|
||||
if ('oninput' in ta) {
|
||||
// Detects IE9. IE9 does not fire onpropertychange or oninput for deletions,
|
||||
// so binding to onkeyup to catch most of those occasions. There is no way that I
|
||||
// know of to detect something like 'cut' in IE9.
|
||||
$ta.on('input.autosize keyup.autosize', adjust);
|
||||
} else {
|
||||
// IE7 / IE8
|
||||
$ta.on('propertychange.autosize', function(){
|
||||
if(event.propertyName === 'value'){
|
||||
adjust();
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// Modern Browsers
|
||||
$ta.on('input.autosize', adjust);
|
||||
}
|
||||
|
||||
// Set options.resizeDelay to false if using fixed-width textarea elements.
|
||||
// Uses a timeout and width check to reduce the amount of times adjust needs to be called after window resize.
|
||||
|
||||
if (options.resizeDelay !== false) {
|
||||
$(window).on('resize.autosize', resize);
|
||||
}
|
||||
|
||||
// Event for manual triggering if needed.
|
||||
// Should only be needed when the value of the textarea is changed through JavaScript rather than user input.
|
||||
$ta.on('autosize.resize', adjust);
|
||||
|
||||
// Event for manual triggering that also forces the styles to update as well.
|
||||
// Should only be needed if one of typography styles of the textarea change, and the textarea is already the target of the adjust method.
|
||||
$ta.on('autosize.resizeIncludeStyle', function() {
|
||||
mirrored = null;
|
||||
adjust();
|
||||
});
|
||||
|
||||
$ta.on('autosize.destroy', function(){
|
||||
mirrored = null;
|
||||
clearTimeout(timeout);
|
||||
$(window).off('resize', resize);
|
||||
$ta
|
||||
.off('autosize')
|
||||
.off('.autosize')
|
||||
.css(originalStyles)
|
||||
.removeData('autosize');
|
||||
});
|
||||
|
||||
// Call adjust in case the textarea already contains text.
|
||||
adjust();
|
||||
});
|
||||
};
|
||||
}(window.jQuery || window.$)); // jQuery or jQuery-like library, such as Zepto
|
|
@ -1,2 +0,0 @@
|
|||
(function($){var defaults={className:"autosizejs",append:"",callback:false,resizeDelay:10},copy='<textarea tabindex="-1" style="position:absolute; top:-999px; left:0; right:auto; bottom:auto; border:0; padding: 0; -moz-box-sizing:content-box; -webkit-box-sizing:content-box; box-sizing:content-box; word-wrap:break-word; height:0 !important; min-height:0 !important; overflow:hidden; transition:none; -webkit-transition:none; -moz-transition:none;"/>',typographyStyles=["fontFamily","fontSize","fontWeight","fontStyle","letterSpacing","textTransform","wordSpacing","textIndent"],mirrored,mirror=$(copy).data("autosize",true)[0];mirror.style.lineHeight="99px";if($(mirror).css("lineHeight")==="99px"){typographyStyles.push("lineHeight")}mirror.style.lineHeight="";$.fn.autosize=function(options){if(!this.length){return this}options=$.extend({},defaults,options||{});if(mirror.parentNode!==document.body){$(document.body).append(mirror)}return this.each(function(){var ta=this,$ta=$(ta),maxHeight,minHeight,boxOffset=0,callback=$.isFunction(options.callback),originalStyles={height:ta.style.height,overflow:ta.style.overflow,overflowY:ta.style.overflowY,wordWrap:ta.style.wordWrap,resize:ta.style.resize},timeout,width=$ta.width();if($ta.data("autosize")){return}$ta.data("autosize",true);if($ta.css("box-sizing")==="border-box"||$ta.css("-moz-box-sizing")==="border-box"||$ta.css("-webkit-box-sizing")==="border-box"){boxOffset=$ta.outerHeight()-$ta.height()}minHeight=Math.max(parseInt($ta.css("minHeight"),10)-boxOffset||0,$ta.height());$ta.css({overflow:"hidden",overflowY:"hidden",wordWrap:"break-word",resize:$ta.css("resize")==="none"||$ta.css("resize")==="vertical"?"none":"horizontal"});function setWidth(){var style,width;if("getComputedStyle"in window){style=window.getComputedStyle(ta,null);width=ta.getBoundingClientRect().width;$.each(["paddingLeft","paddingRight","borderLeftWidth","borderRightWidth"],function(i,val){width-=parseInt(style[val],10)});mirror.style.width=width+"px"}else{mirror.style.width=Math.max($ta.width(),0)+"px"}}function initMirror(){var styles={};mirrored=ta;mirror.className=options.className;maxHeight=parseInt($ta.css("maxHeight"),10);$.each(typographyStyles,function(i,val){styles[val]=$ta.css(val)});$(mirror).css(styles);setWidth();if(window.chrome){var width=ta.style.width;ta.style.width="0px";var ignore=ta.offsetWidth;ta.style.width=width}}function adjust(){var height,original;if(mirrored!==ta){initMirror()}else{setWidth()}mirror.value=ta.value+options.append;mirror.style.overflowY=ta.style.overflowY;original=parseInt(ta.style.height,10);mirror.scrollTop=0;mirror.scrollTop=9e4;height=mirror.scrollTop;if(maxHeight&&height>maxHeight){ta.style.overflowY="scroll";height=maxHeight}else{ta.style.overflowY="hidden";if(height<minHeight){height=minHeight}}height+=boxOffset;if(original!==height){ta.style.height=height+"px";if(callback){options.callback.call(ta,ta)}}}function resize(){clearTimeout(timeout);timeout=setTimeout(function(){var newWidth=$ta.width();if(newWidth!==width){width=newWidth;adjust()}},parseInt(options.resizeDelay,10))}if("onpropertychange"in ta){if("oninput"in ta){$ta.on("input.autosize keyup.autosize",adjust)}else{$ta.on("propertychange.autosize",function(){if(event.propertyName==="value"){adjust()}})}}else{$ta.on("input.autosize",adjust)}if(options.resizeDelay!==false){$(window).on("resize.autosize",resize)}$ta.on("autosize.resize",adjust);$ta.on("autosize.resizeIncludeStyle",function(){mirrored=null;adjust()});$ta.on("autosize.destroy",function(){mirrored=null;clearTimeout(timeout);$(window).off("resize",resize);$ta.off("autosize").off(".autosize").css(originalStyles).removeData("autosize")});adjust()})}})(window.jQuery||window.$);
|
||||
//# sourceMappingURL=jquery.autosize.min.map
|
|
@ -1 +0,0 @@
|
|||
{"version":3,"file":"jquery.autosize.min.js","sources":["jquery.autosize.js"],"names":["$","defaults","className","append","callback","resizeDelay","copy","typographyStyles","mirrored","mirror","data","style","lineHeight","css","push","fn","autosize","options","this","length","extend","parentNode","document","body","each","ta","$ta","maxHeight","minHeight","boxOffset","isFunction","originalStyles","height","overflow","overflowY","wordWrap","resize","timeout","width","outerHeight","Math","max","parseInt","setWidth","window","getComputedStyle","getBoundingClientRect","i","val","initMirror","styles","chrome","ignore","offsetWidth","adjust","original","value","scrollTop","call","clearTimeout","setTimeout","newWidth","on","event","propertyName","off","removeData","jQuery"],"mappings":"CAMC,SAAUA,GACV,GACAC,WACCC,UAAW,aACXC,OAAQ,GACRC,SAAU,MACVC,YAAa,IAIdC,KAAO,oWAGPC,kBACC,aACA,WACA,aACA,YACA,gBACA,gBACA,cACA,cAIDC,SAGAC,OAAST,EAAEM,MAAMI,KAAK,WAAY,MAAM,EAGxCD,QAAOE,MAAMC,WAAa,MAC1B,IAAIZ,EAAES,QAAQI,IAAI,gBAAkB,OAAQ,CAC3CN,iBAAiBO,KAAK,cAEvBL,OAAOE,MAAMC,WAAa,EAE1BZ,GAAEe,GAAGC,SAAW,SAAUC,SACzB,IAAKC,KAAKC,OAAQ,CACjB,MAAOD,MAGRD,QAAUjB,EAAEoB,UAAWnB,SAAUgB,YAEjC,IAAIR,OAAOY,aAAeC,SAASC,KAAM,CACxCvB,EAAEsB,SAASC,MAAMpB,OAAOM,QAGzB,MAAOS,MAAKM,KAAK,WAChB,GACAC,IAAKP,KACLQ,IAAM1B,EAAEyB,IACRE,UACAC,UACAC,UAAY,EACZzB,SAAWJ,EAAE8B,WAAWb,QAAQb,UAChC2B,gBACCC,OAAQP,GAAGd,MAAMqB,OACjBC,SAAUR,GAAGd,MAAMsB,SACnBC,UAAWT,GAAGd,MAAMuB,UACpBC,SAAUV,GAAGd,MAAMwB,SACnBC,OAAQX,GAAGd,MAAMyB,QAElBC,QACAC,MAAQZ,IAAIY,OAEZ,IAAIZ,IAAIhB,KAAK,YAAa,CAEzB,OAEDgB,IAAIhB,KAAK,WAAY,KAErB,IAAIgB,IAAIb,IAAI,gBAAkB,cAAgBa,IAAIb,IAAI,qBAAuB,cAAgBa,IAAIb,IAAI,wBAA0B,aAAa,CAC3IgB,UAAYH,IAAIa,cAAgBb,IAAIM,SAIrCJ,UAAYY,KAAKC,IAAIC,SAAShB,IAAIb,IAAI,aAAc,IAAMgB,WAAa,EAAGH,IAAIM,SAE9EN,KAAIb,KACHoB,SAAU,SACVC,UAAW,SACXC,SAAU,aACVC,OAASV,IAAIb,IAAI,YAAc,QAAUa,IAAIb,IAAI,YAAc,WAAc,OAAS,cAIvF,SAAS8B,YACR,GAAIhC,OAAO2B,KAEX,IAAI,oBAAsBM,QAAQ,CACjCjC,MAAQiC,OAAOC,iBAAiBpB,GAAI,KACpCa,OAAQb,GAAGqB,wBAAwBR,KAEnCtC,GAAEwB,MAAM,cAAe,eAAgB,kBAAmB,oBAAqB,SAASuB,EAAEC,KACzFV,OAASI,SAAS/B,MAAMqC,KAAK,KAG9BvC,QAAOE,MAAM2B,MAAQA,MAAQ,SAEzB,CAEJ7B,OAAOE,MAAM2B,MAAQE,KAAKC,IAAIf,IAAIY,QAAS,GAAK,MAIlD,QAASW,cACR,GAAIC,UAEJ1C,UAAWiB,EACXhB,QAAOP,UAAYe,QAAQf,SAC3ByB,WAAYe,SAAShB,IAAIb,IAAI,aAAc,GAO3Cb,GAAEwB,KAAKjB,iBAAkB,SAASwC,EAAEC,KACnCE,OAAOF,KAAOtB,IAAIb,IAAImC,MAEvBhD,GAAES,QAAQI,IAAIqC,OAEdP,WAKA,IAAIC,OAAOO,OAAQ,CAClB,GAAIb,OAAQb,GAAGd,MAAM2B,KACrBb,IAAGd,MAAM2B,MAAQ,KACjB,IAAIc,QAAS3B,GAAG4B,WAChB5B,IAAGd,MAAM2B,MAAQA,OAMnB,QAASgB,UACR,GAAItB,QAAQuB,QAEZ,IAAI/C,WAAaiB,GAAI,CACpBwB,iBACM,CACNN,WAGDlC,OAAO+C,MAAQ/B,GAAG+B,MAAQvC,QAAQd,MAClCM,QAAOE,MAAMuB,UAAYT,GAAGd,MAAMuB,SAClCqB,UAAWb,SAASjB,GAAGd,MAAMqB,OAAO,GAGpCvB,QAAOgD,UAAY,CAEnBhD,QAAOgD,UAAY,GAGnBzB,QAASvB,OAAOgD,SAEhB,IAAI9B,WAAaK,OAASL,UAAW,CACpCF,GAAGd,MAAMuB,UAAY,QACrBF,QAASL,cACH,CACNF,GAAGd,MAAMuB,UAAY,QACrB,IAAIF,OAASJ,UAAW,CACvBI,OAASJ,WAIXI,QAAUH,SAEV,IAAI0B,WAAavB,OAAQ,CACxBP,GAAGd,MAAMqB,OAASA,OAAS,IAC3B,IAAI5B,SAAU,CACba,QAAQb,SAASsD,KAAKjC,GAAGA,MAK5B,QAASW,UACRuB,aAAatB,QACbA,SAAUuB,WAAW,WACpB,GAAIC,UAAWnC,IAAIY,OAEnB,IAAIuB,WAAavB,MAAO,CACvBA,MAAQuB,QACRP,YAECZ,SAASzB,QAAQZ,YAAY,KAGjC,GAAI,oBAAsBoB,IAAI,CAC7B,GAAI,WAAaA,IAAI,CAIpBC,IAAIoC,GAAG,gCAAiCR,YAClC,CAEN5B,IAAIoC,GAAG,0BAA2B,WACjC,GAAGC,MAAMC,eAAiB,QAAQ,CACjCV,iBAIG,CAEN5B,IAAIoC,GAAG,iBAAkBR,QAM1B,GAAIrC,QAAQZ,cAAgB,MAAO,CAClCL,EAAE4C,QAAQkB,GAAG,kBAAmB1B,QAKjCV,IAAIoC,GAAG,kBAAmBR,OAI1B5B,KAAIoC,GAAG,8BAA+B,WACrCtD,SAAW,IACX8C,WAGD5B,KAAIoC,GAAG,mBAAoB,WAC1BtD,SAAW,IACXmD,cAAatB,QACbrC,GAAE4C,QAAQqB,IAAI,SAAU7B,OACxBV,KACEuC,IAAI,YACJA,IAAI,aACJpD,IAAIkB,gBACJmC,WAAW,aAIdZ,eAGDV,OAAOuB,QAAUvB,OAAO5C"}
|
110
libs/popover.js
110
libs/popover.js
|
@ -1,110 +0,0 @@
|
|||
/* ========================================================================
|
||||
* Bootstrap: popover.js v3.1.1
|
||||
* http://getbootstrap.com/javascript/#popovers
|
||||
* ========================================================================
|
||||
* Copyright 2011-2014 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* ======================================================================== */
|
||||
|
||||
|
||||
+function ($) {
|
||||
'use strict';
|
||||
|
||||
// POPOVER PUBLIC CLASS DEFINITION
|
||||
// ===============================
|
||||
|
||||
var Popover = function (element, options) {
|
||||
this.init('popover', element, options)
|
||||
}
|
||||
|
||||
if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')
|
||||
|
||||
Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, {
|
||||
placement: 'right',
|
||||
trigger: 'click',
|
||||
content: '',
|
||||
template: '<div class="popover"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
|
||||
})
|
||||
|
||||
|
||||
// NOTE: POPOVER EXTENDS tooltip.js
|
||||
// ================================
|
||||
|
||||
Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)
|
||||
|
||||
Popover.prototype.constructor = Popover
|
||||
|
||||
Popover.prototype.getDefaults = function () {
|
||||
return Popover.DEFAULTS
|
||||
}
|
||||
|
||||
Popover.prototype.setContent = function () {
|
||||
var $tip = this.tip()
|
||||
var title = this.getTitle()
|
||||
var content = this.getContent()
|
||||
|
||||
$tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
|
||||
$tip.find('.popover-content')[ // we use append for html objects to maintain js events
|
||||
this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text'
|
||||
](content)
|
||||
|
||||
$tip.removeClass('fade top bottom left right in')
|
||||
|
||||
// IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do
|
||||
// this manually by checking the contents.
|
||||
if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide()
|
||||
}
|
||||
|
||||
Popover.prototype.hasContent = function () {
|
||||
return this.getTitle() || this.getContent()
|
||||
}
|
||||
|
||||
Popover.prototype.getContent = function () {
|
||||
var $e = this.$element
|
||||
var o = this.options
|
||||
|
||||
return $e.attr('data-content')
|
||||
|| (typeof o.content == 'function' ?
|
||||
o.content.call($e[0]) :
|
||||
o.content)
|
||||
}
|
||||
|
||||
Popover.prototype.arrow = function () {
|
||||
return this.$arrow = this.$arrow || this.tip().find('.arrow')
|
||||
}
|
||||
|
||||
Popover.prototype.tip = function () {
|
||||
if (!this.$tip) this.$tip = $(this.options.template)
|
||||
return this.$tip
|
||||
}
|
||||
|
||||
|
||||
// POPOVER PLUGIN DEFINITION
|
||||
// =========================
|
||||
|
||||
var old = $.fn.popover
|
||||
|
||||
$.fn.popover = function (option) {
|
||||
return this.each(function () {
|
||||
var $this = $(this)
|
||||
var data = $this.data('bs.popover')
|
||||
var options = typeof option == 'object' && option
|
||||
|
||||
if (!data && option == 'destroy') return
|
||||
if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
|
||||
if (typeof option == 'string') data[option]()
|
||||
})
|
||||
}
|
||||
|
||||
$.fn.popover.Constructor = Popover
|
||||
|
||||
|
||||
// POPOVER NO CONFLICT
|
||||
// ===================
|
||||
|
||||
$.fn.popover.noConflict = function () {
|
||||
$.fn.popover = old
|
||||
return this
|
||||
}
|
||||
|
||||
}(jQuery);
|
|
@ -1,2 +0,0 @@
|
|||
+function($){"use strict";var Popover=function(element,options){this.init("popover",element,options)};if(!$.fn.tooltip)throw new Error("Popover requires tooltip.js");Popover.DEFAULTS=$.extend({},$.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:'<div class="popover"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'});Popover.prototype=$.extend({},$.fn.tooltip.Constructor.prototype);Popover.prototype.constructor=Popover;Popover.prototype.getDefaults=function(){return Popover.DEFAULTS};Popover.prototype.setContent=function(){var $tip=this.tip();var title=this.getTitle();var content=this.getContent();$tip.find(".popover-title")[this.options.html?"html":"text"](title);$tip.find(".popover-content")[this.options.html?typeof content=="string"?"html":"append":"text"](content);$tip.removeClass("fade top bottom left right in");if(!$tip.find(".popover-title").html())$tip.find(".popover-title").hide()};Popover.prototype.hasContent=function(){return this.getTitle()||this.getContent()};Popover.prototype.getContent=function(){var $e=this.$element;var o=this.options;return $e.attr("data-content")||(typeof o.content=="function"?o.content.call($e[0]):o.content)};Popover.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")};Popover.prototype.tip=function(){if(!this.$tip)this.$tip=$(this.options.template);return this.$tip};var old=$.fn.popover;$.fn.popover=function(option){return this.each(function(){var $this=$(this);var data=$this.data("bs.popover");var options=typeof option=="object"&&option;if(!data&&option=="destroy")return;if(!data)$this.data("bs.popover",data=new Popover(this,options));if(typeof option=="string")data[option]()})};$.fn.popover.Constructor=Popover;$.fn.popover.noConflict=function(){$.fn.popover=old;return this}}(jQuery);
|
||||
//# sourceMappingURL=popover.min.map
|
|
@ -1 +0,0 @@
|
|||
{"version":3,"file":"popover.min.js","sources":["popover.js"],"names":["$","Popover","element","options","this","init","fn","tooltip","Error","DEFAULTS","extend","Constructor","placement","trigger","content","template","prototype","constructor","getDefaults","setContent","$tip","tip","title","getTitle","getContent","find","html","removeClass","hide","hasContent","$e","$element","o","attr","call","arrow","$arrow","old","popover","option","each","$this","data","noConflict","jQuery"],"mappings":"CASC,SAAUA,GACT,YAKA,IAAIC,SAAU,SAAUC,QAASC,SAC/BC,KAAKC,KAAK,UAAWH,QAASC,SAGhC,KAAKH,EAAEM,GAAGC,QAAS,KAAM,IAAIC,OAAM,8BAEnCP,SAAQQ,SAAWT,EAAEU,UAAWV,EAAEM,GAAGC,QAAQI,YAAYF,UACvDG,UAAW,QACXC,QAAS,QACTC,QAAS,GACTC,SAAU,0HAOZd,SAAQe,UAAYhB,EAAEU,UAAWV,EAAEM,GAAGC,QAAQI,YAAYK,UAE1Df,SAAQe,UAAUC,YAAchB,OAEhCA,SAAQe,UAAUE,YAAc,WAC9B,MAAOjB,SAAQQ,SAGjBR,SAAQe,UAAUG,WAAa,WAC7B,GAAIC,MAAUhB,KAAKiB,KACnB,IAAIC,OAAUlB,KAAKmB,UACnB,IAAIT,SAAUV,KAAKoB,YAEnBJ,MAAKK,KAAK,kBAAkBrB,KAAKD,QAAQuB,KAAO,OAAS,QAAQJ,MACjEF,MAAKK,KAAK,oBACRrB,KAAKD,QAAQuB,WAAeZ,UAAW,SAAW,OAAS,SAAY,QACvEA,QAEFM,MAAKO,YAAY,gCAIjB,KAAKP,KAAKK,KAAK,kBAAkBC,OAAQN,KAAKK,KAAK,kBAAkBG,OAGvE3B,SAAQe,UAAUa,WAAa,WAC7B,MAAOzB,MAAKmB,YAAcnB,KAAKoB,aAGjCvB,SAAQe,UAAUQ,WAAa,WAC7B,GAAIM,IAAK1B,KAAK2B,QACd,IAAIC,GAAK5B,KAAKD,OAEd,OAAO2B,IAAGG,KAAK,wBACFD,GAAElB,SAAW,WAClBkB,EAAElB,QAAQoB,KAAKJ,GAAG,IAClBE,EAAElB,SAGZb,SAAQe,UAAUmB,MAAQ,WACxB,MAAO/B,MAAKgC,OAAShC,KAAKgC,QAAUhC,KAAKiB,MAAMI,KAAK,UAGtDxB,SAAQe,UAAUK,IAAM,WACtB,IAAKjB,KAAKgB,KAAMhB,KAAKgB,KAAOpB,EAAEI,KAAKD,QAAQY,SAC3C,OAAOX,MAAKgB,KAOd,IAAIiB,KAAMrC,EAAEM,GAAGgC,OAEftC,GAAEM,GAAGgC,QAAU,SAAUC,QACvB,MAAOnC,MAAKoC,KAAK,WACf,GAAIC,OAAUzC,EAAEI,KAChB,IAAIsC,MAAUD,MAAMC,KAAK,aACzB,IAAIvC,eAAiBoC,SAAU,UAAYA,MAE3C,KAAKG,MAAQH,QAAU,UAAW,MAClC,KAAKG,KAAMD,MAAMC,KAAK,aAAeA,KAAO,GAAIzC,SAAQG,KAAMD,SAC9D,UAAWoC,SAAU,SAAUG,KAAKH,YAIxCvC,GAAEM,GAAGgC,QAAQ3B,YAAcV,OAM3BD,GAAEM,GAAGgC,QAAQK,WAAa,WACxB3C,EAAEM,GAAGgC,QAAUD,GACf,OAAOjC,QAGTwC"}
|
|
@ -1 +0,0 @@
|
|||
Strophe.addConnectionPlugin("caps",{HASH:"sha-1",node:"http://strophe.im/strophejs/",_ver:"",_connection:null,_knownCapabilities:{},_jidVerIndex:{},init:function(conn){this._connection=conn;Strophe.addNamespace("CAPS","http://jabber.org/protocol/caps");if(!this._connection.disco){throw"Caps plugin requires the disco plugin to be installed."}this._connection.disco.addFeature(Strophe.NS.CAPS);this._connection.addHandler(this._delegateCapabilities.bind(this),Strophe.NS.CAPS)},generateCapsAttrs:function(){return{xmlns:Strophe.NS.CAPS,hash:this.HASH,node:this.node,ver:this.generateVer()}},generateVer:function(){if(this._ver!==""){return this._ver}var ver="",identities=this._connection.disco._identities.sort(this._sortIdentities),identitiesLen=identities.length,features=this._connection.disco._features.sort(),featuresLen=features.length;for(var i=0;i<identitiesLen;i++){var curIdent=identities[i];ver+=curIdent.category+"/"+curIdent.type+"/"+curIdent.lang+"/"+curIdent.name+"<"}for(var i=0;i<featuresLen;i++){ver+=features[i]+"<"}this._ver=b64_sha1(ver);return this._ver},getCapabilitiesByJid:function(jid){if(this._jidVerIndex[jid]){return this._knownCapabilities[this._jidVerIndex[jid]]}return null},_delegateCapabilities:function(stanza){var from=stanza.getAttribute("from"),c=stanza.querySelector("c"),ver=c.getAttribute("ver"),node=c.getAttribute("node");if(!this._knownCapabilities[ver]){return this._requestCapabilities(from,node,ver)}else{this._jidVerIndex[from]=ver}if(!this._jidVerIndex[from]||!this._jidVerIndex[from]!==ver){this._jidVerIndex[from]=ver}return true},_requestCapabilities:function(to,node,ver){if(to!==this._connection.jid){var id=this._connection.disco.info(to,node+"#"+ver);this._connection.addHandler(this._handleDiscoInfoReply.bind(this),Strophe.NS.DISCO_INFO,"iq","result",id,to)}return true},_handleDiscoInfoReply:function(stanza){var query=stanza.querySelector("query"),node=query.getAttribute("node").split("#"),ver=node[1],from=stanza.getAttribute("from");if(!this._knownCapabilities[ver]){var childNodes=query.childNodes,childNodesLen=childNodes.length;this._knownCapabilities[ver]=[];for(var i=0;i<childNodesLen;i++){var node=childNodes[i];this._knownCapabilities[ver].push({name:node.nodeName,attributes:node.attributes})}this._jidVerIndex[from]=ver}else{if(!this._jidVerIndex[from]||!this._jidVerIndex[from]!==ver){this._jidVerIndex[from]=ver}}return false},_sortIdentities:function(a,b){if(a.category>b.category){return 1}if(a.category<b.category){return -1}if(a.type>b.type){return 1}if(a.type<b.type){return -1}if(a.lang>b.lang){return 1}if(a.lang<b.lang){return -1}return 0}});
|
|
@ -1 +0,0 @@
|
|||
Strophe.addConnectionPlugin("disco",{_connection:null,_identities:[],_features:[],_items:[],init:function(conn){this._connection=conn;this._identities=[];this._features=[];this._items=[];conn.addHandler(this._onDiscoInfo.bind(this),Strophe.NS.DISCO_INFO,"iq","get",null,null);conn.addHandler(this._onDiscoItems.bind(this),Strophe.NS.DISCO_ITEMS,"iq","get",null,null)},addIdentity:function(category,type,name,lang){for(var i=0;i<this._identities.length;i++){if(this._identities[i].category==category&&this._identities[i].type==type&&this._identities[i].name==name&&this._identities[i].lang==lang){return false}}this._identities.push({category:category,type:type,name:name,lang:lang});return true},addFeature:function(var_name){for(var i=0;i<this._features.length;i++){if(this._features[i]==var_name){return false}}this._features.push(var_name);return true},removeFeature:function(var_name){for(var i=0;i<this._features.length;i++){if(this._features[i]===var_name){this._features.splice(i,1);return true}}return false},addItem:function(jid,name,node,call_back){if(node&&!call_back){return false}this._items.push({jid:jid,name:name,node:node,call_back:call_back});return true},info:function(jid,node,success,error,timeout){var attrs={xmlns:Strophe.NS.DISCO_INFO};if(node){attrs.node=node}var info=$iq({from:this._connection.jid,to:jid,type:"get"}).c("query",attrs);this._connection.sendIQ(info,success,error,timeout)},items:function(jid,node,success,error,timeout){var attrs={xmlns:Strophe.NS.DISCO_ITEMS};if(node){attrs.node=node}var items=$iq({from:this._connection.jid,to:jid,type:"get"}).c("query",attrs);this._connection.sendIQ(items,success,error,timeout)},_buildIQResult:function(stanza,query_attrs){var id=stanza.getAttribute("id");var from=stanza.getAttribute("from");var iqresult=$iq({type:"result",id:id});if(from!==null){iqresult.attrs({to:from})}return iqresult.c("query",query_attrs)},_onDiscoInfo:function(stanza){var node=stanza.getElementsByTagName("query")[0].getAttribute("node");var attrs={xmlns:Strophe.NS.DISCO_INFO};if(node){attrs.node=node}var iqresult=this._buildIQResult(stanza,attrs);for(var i=0;i<this._identities.length;i++){var attrs={category:this._identities[i].category,type:this._identities[i].type};if(this._identities[i].name){attrs.name=this._identities[i].name}if(this._identities[i].lang){attrs["xml:lang"]=this._identities[i].lang}iqresult.c("identity",attrs).up()}for(var i=0;i<this._features.length;i++){iqresult.c("feature",{"var":this._features[i]}).up()}this._connection.send(iqresult.tree());return true},_onDiscoItems:function(stanza){var query_attrs={xmlns:Strophe.NS.DISCO_ITEMS};var node=stanza.getElementsByTagName("query")[0].getAttribute("node");if(node){query_attrs.node=node;var items=[];for(var i=0;i<this._items.length;i++){if(this._items[i].node==node){items=this._items[i].call_back(stanza);break}}}else{var items=this._items}var iqresult=this._buildIQResult(stanza,query_attrs);for(var i=0;i<items.length;i++){var attrs={jid:items[i].jid};if(items[i].name){attrs.name=items[i].name}if(items[i].node){attrs.node=items[i].node}iqresult.c("item",attrs).up()}this._connection.send(iqresult.tree());return true}});
|
File diff suppressed because one or more lines are too long
342
libs/toastr.js
342
libs/toastr.js
|
@ -1,342 +0,0 @@
|
|||
/*
|
||||
* Toastr
|
||||
* Copyright 2012-2014 John Papa and Hans Fjällemark.
|
||||
* All Rights Reserved.
|
||||
* Use, reproduction, distribution, and modification of this code is subject to the terms and
|
||||
* conditions of the MIT license, available at http://www.opensource.org/licenses/mit-license.php
|
||||
*
|
||||
* Author: John Papa and Hans Fjällemark
|
||||
* ARIA Support: Greta Krafsig
|
||||
* Project: https://github.com/CodeSeven/toastr
|
||||
*/
|
||||
; (function (define) {
|
||||
define(['jquery'], function ($) {
|
||||
return (function () {
|
||||
var $container;
|
||||
var listener;
|
||||
var toastId = 0;
|
||||
var toastType = {
|
||||
error: 'error',
|
||||
info: 'info',
|
||||
success: 'success',
|
||||
warning: 'warning'
|
||||
};
|
||||
|
||||
var toastr = {
|
||||
clear: clear,
|
||||
remove: remove,
|
||||
error: error,
|
||||
getContainer: getContainer,
|
||||
info: info,
|
||||
options: {},
|
||||
subscribe: subscribe,
|
||||
success: success,
|
||||
version: '2.0.3',
|
||||
warning: warning
|
||||
};
|
||||
|
||||
return toastr;
|
||||
|
||||
//#region Accessible Methods
|
||||
function error(message, title, optionsOverride) {
|
||||
return notify({
|
||||
type: toastType.error,
|
||||
iconClass: getOptions().iconClasses.error,
|
||||
message: message,
|
||||
optionsOverride: optionsOverride,
|
||||
title: title
|
||||
});
|
||||
}
|
||||
|
||||
function getContainer(options, create) {
|
||||
if (!options) { options = getOptions(); }
|
||||
$container = $('#' + options.containerId);
|
||||
if ($container.length) {
|
||||
return $container;
|
||||
}
|
||||
if(create) {
|
||||
$container = createContainer(options);
|
||||
}
|
||||
return $container;
|
||||
}
|
||||
|
||||
function info(message, title, optionsOverride) {
|
||||
return notify({
|
||||
type: toastType.info,
|
||||
iconClass: getOptions().iconClasses.info,
|
||||
message: message,
|
||||
optionsOverride: optionsOverride,
|
||||
title: title
|
||||
});
|
||||
}
|
||||
|
||||
function subscribe(callback) {
|
||||
listener = callback;
|
||||
}
|
||||
|
||||
function success(message, title, optionsOverride) {
|
||||
return notify({
|
||||
type: toastType.success,
|
||||
iconClass: getOptions().iconClasses.success,
|
||||
message: message,
|
||||
optionsOverride: optionsOverride,
|
||||
title: title
|
||||
});
|
||||
}
|
||||
|
||||
function warning(message, title, optionsOverride) {
|
||||
return notify({
|
||||
type: toastType.warning,
|
||||
iconClass: getOptions().iconClasses.warning,
|
||||
message: message,
|
||||
optionsOverride: optionsOverride,
|
||||
title: title
|
||||
});
|
||||
}
|
||||
|
||||
function clear($toastElement) {
|
||||
var options = getOptions();
|
||||
if (!$container) { getContainer(options); }
|
||||
if (!clearToast($toastElement, options)) {
|
||||
clearContainer(options);
|
||||
}
|
||||
}
|
||||
|
||||
function remove($toastElement) {
|
||||
var options = getOptions();
|
||||
if (!$container) { getContainer(options); }
|
||||
if ($toastElement && $(':focus', $toastElement).length === 0) {
|
||||
removeToast($toastElement);
|
||||
return;
|
||||
}
|
||||
if ($container.children().length) {
|
||||
$container.remove();
|
||||
}
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//#region Internal Methods
|
||||
|
||||
function clearContainer(options){
|
||||
var toastsToClear = $container.children();
|
||||
for (var i = toastsToClear.length - 1; i >= 0; i--) {
|
||||
clearToast($(toastsToClear[i]), options);
|
||||
};
|
||||
}
|
||||
|
||||
function clearToast($toastElement, options){
|
||||
if ($toastElement && $(':focus', $toastElement).length === 0) {
|
||||
$toastElement[options.hideMethod]({
|
||||
duration: options.hideDuration,
|
||||
easing: options.hideEasing,
|
||||
complete: function () { removeToast($toastElement); }
|
||||
});
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function createContainer(options) {
|
||||
$container = $('<div/>')
|
||||
.attr('id', options.containerId)
|
||||
.addClass(options.positionClass)
|
||||
.attr('aria-live', 'polite')
|
||||
.attr('role', 'alert');
|
||||
|
||||
$container.appendTo($(options.target));
|
||||
return $container;
|
||||
}
|
||||
|
||||
function getDefaults() {
|
||||
return {
|
||||
tapToDismiss: true,
|
||||
toastClass: 'toast',
|
||||
containerId: 'toast-container',
|
||||
debug: false,
|
||||
|
||||
showMethod: 'fadeIn', //fadeIn, slideDown, and show are built into jQuery
|
||||
showDuration: 300,
|
||||
showEasing: 'swing', //swing and linear are built into jQuery
|
||||
onShown: undefined,
|
||||
hideMethod: 'fadeOut',
|
||||
hideDuration: 1000,
|
||||
hideEasing: 'swing',
|
||||
onHidden: undefined,
|
||||
|
||||
extendedTimeOut: 1000,
|
||||
iconClasses: {
|
||||
error: 'toast-error',
|
||||
info: 'toast-info',
|
||||
success: 'toast-success',
|
||||
warning: 'toast-warning'
|
||||
},
|
||||
iconClass: 'toast-info',
|
||||
positionClass: 'toast-top-right',
|
||||
timeOut: 5000, // Set timeOut and extendedTimeout to 0 to make it sticky
|
||||
titleClass: 'toast-title',
|
||||
messageClass: 'toast-message',
|
||||
target: 'body',
|
||||
closeHtml: '<button>×</button>',
|
||||
newestOnTop: true
|
||||
};
|
||||
}
|
||||
|
||||
function publish(args) {
|
||||
if (!listener) { return; }
|
||||
listener(args);
|
||||
}
|
||||
|
||||
function notify(map) {
|
||||
var options = getOptions(),
|
||||
iconClass = map.iconClass || options.iconClass;
|
||||
|
||||
if (typeof (map.optionsOverride) !== 'undefined') {
|
||||
options = $.extend(options, map.optionsOverride);
|
||||
iconClass = map.optionsOverride.iconClass || iconClass;
|
||||
}
|
||||
|
||||
toastId++;
|
||||
|
||||
$container = getContainer(options, true);
|
||||
var intervalId = null,
|
||||
$toastElement = $('<div/>'),
|
||||
$titleElement = $('<div/>'),
|
||||
$messageElement = $('<div/>'),
|
||||
$closeElement = $(options.closeHtml),
|
||||
response = {
|
||||
toastId: toastId,
|
||||
state: 'visible',
|
||||
startTime: new Date(),
|
||||
options: options,
|
||||
map: map
|
||||
};
|
||||
|
||||
if (map.iconClass) {
|
||||
$toastElement.addClass(options.toastClass).addClass(iconClass);
|
||||
}
|
||||
|
||||
if (map.title) {
|
||||
$titleElement.append(map.title).addClass(options.titleClass);
|
||||
$toastElement.append($titleElement);
|
||||
}
|
||||
|
||||
if (map.message) {
|
||||
$messageElement.append(map.message).addClass(options.messageClass);
|
||||
$toastElement.append($messageElement);
|
||||
}
|
||||
|
||||
if (options.closeButton) {
|
||||
$closeElement.addClass('toast-close-button').attr("role", "button");
|
||||
$toastElement.prepend($closeElement);
|
||||
}
|
||||
|
||||
if (options.reposition) {
|
||||
options.reposition();
|
||||
}
|
||||
|
||||
$toastElement.hide();
|
||||
if (options.newestOnTop) {
|
||||
$container.prepend($toastElement);
|
||||
} else {
|
||||
$container.append($toastElement);
|
||||
}
|
||||
|
||||
|
||||
$toastElement[options.showMethod](
|
||||
{ duration: options.showDuration, easing: options.showEasing, complete: options.onShown }
|
||||
);
|
||||
|
||||
if (options.timeOut > 0) {
|
||||
intervalId = setTimeout(hideToast, options.timeOut);
|
||||
}
|
||||
|
||||
$toastElement.hover(stickAround, delayedHideToast);
|
||||
if (!options.onclick && options.tapToDismiss) {
|
||||
$toastElement.click(hideToast);
|
||||
}
|
||||
|
||||
if (options.closeButton && $closeElement) {
|
||||
$closeElement.click(function (event) {
|
||||
if( event.stopPropagation ) {
|
||||
event.stopPropagation();
|
||||
} else if( event.cancelBubble !== undefined && event.cancelBubble !== true ) {
|
||||
event.cancelBubble = true;
|
||||
}
|
||||
hideToast(true);
|
||||
});
|
||||
}
|
||||
|
||||
if (options.onclick) {
|
||||
$toastElement.click(function () {
|
||||
options.onclick();
|
||||
hideToast();
|
||||
});
|
||||
}
|
||||
|
||||
publish(response);
|
||||
|
||||
if (options.debug && console) {
|
||||
console.log(response);
|
||||
}
|
||||
|
||||
return $toastElement;
|
||||
|
||||
function hideToast(override) {
|
||||
if ($(':focus', $toastElement).length && !override) {
|
||||
return;
|
||||
}
|
||||
return $toastElement[options.hideMethod]({
|
||||
duration: options.hideDuration,
|
||||
easing: options.hideEasing,
|
||||
complete: function () {
|
||||
removeToast($toastElement);
|
||||
if (options.onHidden && response.state !== 'hidden') {
|
||||
options.onHidden();
|
||||
}
|
||||
response.state = 'hidden';
|
||||
response.endTime = new Date();
|
||||
publish(response);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function delayedHideToast() {
|
||||
if (options.timeOut > 0 || options.extendedTimeOut > 0) {
|
||||
intervalId = setTimeout(hideToast, options.extendedTimeOut);
|
||||
}
|
||||
}
|
||||
|
||||
function stickAround() {
|
||||
clearTimeout(intervalId);
|
||||
$toastElement.stop(true, true)[options.showMethod](
|
||||
{ duration: options.showDuration, easing: options.showEasing }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function getOptions() {
|
||||
return $.extend({}, getDefaults(), toastr.options);
|
||||
}
|
||||
|
||||
function removeToast($toastElement) {
|
||||
if (!$container) { $container = getContainer(); }
|
||||
if ($toastElement.is(':visible')) {
|
||||
return;
|
||||
}
|
||||
$toastElement.remove();
|
||||
$toastElement = null;
|
||||
if ($container.children().length === 0) {
|
||||
$container.remove();
|
||||
}
|
||||
}
|
||||
//#endregion
|
||||
|
||||
})();
|
||||
});
|
||||
}(typeof define === 'function' && define.amd ? define : function (deps, factory) {
|
||||
if (typeof module !== 'undefined' && module.exports) { //Node
|
||||
module.exports = factory(require('jquery'));
|
||||
} else {
|
||||
window['toastr'] = factory(window['jQuery']);
|
||||
}
|
||||
}));
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
422
libs/tooltip.js
422
libs/tooltip.js
|
@ -1,422 +0,0 @@
|
|||
/* ========================================================================
|
||||
* Bootstrap: tooltip.js v3.1.1
|
||||
* http://getbootstrap.com/javascript/#tooltip
|
||||
* Inspired by the original jQuery.tipsy by Jason Frame
|
||||
* ========================================================================
|
||||
* Copyright 2011-2014 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* ======================================================================== */
|
||||
|
||||
|
||||
+function ($) {
|
||||
'use strict';
|
||||
|
||||
// TOOLTIP PUBLIC CLASS DEFINITION
|
||||
// ===============================
|
||||
|
||||
var Tooltip = function (element, options) {
|
||||
this.type =
|
||||
this.options =
|
||||
this.enabled =
|
||||
this.timeout =
|
||||
this.hoverState =
|
||||
this.$element = null
|
||||
|
||||
this.init('tooltip', element, options)
|
||||
}
|
||||
|
||||
Tooltip.DEFAULTS = {
|
||||
animation: true,
|
||||
placement: 'top',
|
||||
selector: false,
|
||||
template: '<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
|
||||
trigger: 'hover focus',
|
||||
title: '',
|
||||
delay: 0,
|
||||
html: false,
|
||||
container: false
|
||||
}
|
||||
|
||||
Tooltip.prototype.init = function (type, element, options) {
|
||||
this.enabled = true
|
||||
this.type = type
|
||||
this.$element = $(element)
|
||||
this.options = this.getOptions(options)
|
||||
|
||||
var triggers = this.options.trigger.split(' ')
|
||||
|
||||
for (var i = triggers.length; i--;) {
|
||||
var trigger = triggers[i]
|
||||
|
||||
if (trigger == 'click') {
|
||||
this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
|
||||
} else if (trigger != 'manual') {
|
||||
var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin'
|
||||
var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'
|
||||
|
||||
this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
|
||||
this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
|
||||
}
|
||||
}
|
||||
|
||||
this.options.selector ?
|
||||
(this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
|
||||
this.fixTitle()
|
||||
}
|
||||
|
||||
Tooltip.prototype.getDefaults = function () {
|
||||
return Tooltip.DEFAULTS
|
||||
}
|
||||
|
||||
Tooltip.prototype.getOptions = function (options) {
|
||||
options = $.extend({}, this.getDefaults(), this.$element.data(), options)
|
||||
|
||||
if (options.delay && typeof options.delay == 'number') {
|
||||
options.delay = {
|
||||
show: options.delay,
|
||||
hide: options.delay
|
||||
}
|
||||
}
|
||||
|
||||
return options
|
||||
}
|
||||
|
||||
Tooltip.prototype.getDelegateOptions = function () {
|
||||
var options = {}
|
||||
var defaults = this.getDefaults()
|
||||
|
||||
this._options && $.each(this._options, function (key, value) {
|
||||
if (defaults[key] != value) options[key] = value
|
||||
})
|
||||
|
||||
return options
|
||||
}
|
||||
|
||||
Tooltip.prototype.enter = function (obj) {
|
||||
var self = obj instanceof this.constructor ?
|
||||
obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)
|
||||
|
||||
clearTimeout(self.timeout)
|
||||
|
||||
self.hoverState = 'in'
|
||||
|
||||
if (!self.options.delay || !self.options.delay.show) return self.show()
|
||||
|
||||
self.timeout = setTimeout(function () {
|
||||
if (self.hoverState == 'in') self.show()
|
||||
}, self.options.delay.show)
|
||||
}
|
||||
|
||||
Tooltip.prototype.leave = function (obj) {
|
||||
var self = obj instanceof this.constructor ?
|
||||
obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)
|
||||
|
||||
clearTimeout(self.timeout)
|
||||
|
||||
self.hoverState = 'out'
|
||||
|
||||
if (!self.options.delay || !self.options.delay.hide) return self.hide()
|
||||
|
||||
self.timeout = setTimeout(function () {
|
||||
if (self.hoverState == 'out') self.hide()
|
||||
}, self.options.delay.hide)
|
||||
}
|
||||
|
||||
Tooltip.prototype.show = function () {
|
||||
var e = $.Event('show.bs.' + this.type)
|
||||
|
||||
if (this.hasContent() && this.enabled) {
|
||||
this.$element.trigger(e)
|
||||
|
||||
if (e.isDefaultPrevented()) return
|
||||
var that = this;
|
||||
|
||||
var $tip = this.tip()
|
||||
|
||||
this.setContent()
|
||||
|
||||
if (this.options.animation) $tip.addClass('fade')
|
||||
|
||||
var placement = typeof this.options.placement == 'function' ?
|
||||
this.options.placement.call(this, $tip[0], this.$element[0]) :
|
||||
this.options.placement
|
||||
|
||||
var autoToken = /\s?auto?\s?/i
|
||||
var autoPlace = autoToken.test(placement)
|
||||
if (autoPlace) placement = placement.replace(autoToken, '') || 'top'
|
||||
|
||||
$tip
|
||||
.detach()
|
||||
.css({ top: 0, left: 0, display: 'block' })
|
||||
.addClass(placement)
|
||||
|
||||
this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
|
||||
|
||||
var pos = this.getPosition()
|
||||
var actualWidth = $tip[0].offsetWidth
|
||||
var actualHeight = $tip[0].offsetHeight
|
||||
|
||||
if (autoPlace) {
|
||||
var $parent = this.$element.parent()
|
||||
|
||||
var orgPlacement = placement
|
||||
var docScroll = document.documentElement.scrollTop || document.body.scrollTop
|
||||
var parentWidth = this.options.container == 'body' ? window.innerWidth : $parent.outerWidth()
|
||||
var parentHeight = this.options.container == 'body' ? window.innerHeight : $parent.outerHeight()
|
||||
var parentLeft = this.options.container == 'body' ? 0 : $parent.offset().left
|
||||
|
||||
placement = placement == 'bottom' && pos.top + pos.height + actualHeight - docScroll > parentHeight ? 'top' :
|
||||
placement == 'top' && pos.top - docScroll - actualHeight < 0 ? 'bottom' :
|
||||
placement == 'right' && pos.right + actualWidth > parentWidth ? 'left' :
|
||||
placement == 'left' && pos.left - actualWidth < parentLeft ? 'right' :
|
||||
placement
|
||||
|
||||
$tip
|
||||
.removeClass(orgPlacement)
|
||||
.addClass(placement)
|
||||
}
|
||||
|
||||
var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
|
||||
|
||||
this.applyPlacement(calculatedOffset, placement)
|
||||
this.hoverState = null
|
||||
|
||||
var complete = function() {
|
||||
that.$element.trigger('shown.bs.' + that.type)
|
||||
}
|
||||
|
||||
var deltas = {
|
||||
"bottom": $tip[0].getBoundingClientRect().bottom - window.innerHeight,
|
||||
"right": $tip[0].getBoundingClientRect().right - window.innerWidth,
|
||||
"left": -$tip[0].getBoundingClientRect().left,
|
||||
"top": -$tip[0].getBoundingClientRect().top
|
||||
};
|
||||
for(var direction in deltas) {
|
||||
if (deltas[direction] > 0) {
|
||||
var delta = deltas[direction];
|
||||
if(direction === "right" || direction === "bottom") {
|
||||
delta = -delta;
|
||||
}
|
||||
direction = direction === "top" || direction === "bottom" ? "top" : "left";
|
||||
var currentPosition = parseInt($tip.css(direction), 10);
|
||||
$tip.css(direction, currentPosition + delta);
|
||||
if(direction === "left") {
|
||||
$tip.children(".arrow").css(direction, parseInt($tip.children(".arrow").css(direction), 10) - delta);
|
||||
} else {
|
||||
$tip.children(".arrow").css(direction, 50 - $tip[0].getBoundingClientRect().height / delta + "%");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$.support.transition && this.$tip.hasClass('fade') ?
|
||||
$tip
|
||||
.one($.support.transition.end, complete)
|
||||
.emulateTransitionEnd(150) :
|
||||
complete()
|
||||
}
|
||||
}
|
||||
|
||||
Tooltip.prototype.applyPlacement = function (offset, placement) {
|
||||
var replace
|
||||
var $tip = this.tip()
|
||||
var width = $tip[0].offsetWidth
|
||||
var height = $tip[0].offsetHeight
|
||||
|
||||
// manually read margins because getBoundingClientRect includes difference
|
||||
var marginTop = parseInt($tip.css('margin-top'), 10)
|
||||
var marginLeft = parseInt($tip.css('margin-left'), 10)
|
||||
|
||||
// we must check for NaN for ie 8/9
|
||||
if (isNaN(marginTop)) marginTop = 0
|
||||
if (isNaN(marginLeft)) marginLeft = 0
|
||||
|
||||
offset.top = offset.top + marginTop
|
||||
offset.left = offset.left + marginLeft
|
||||
|
||||
// $.fn.offset doesn't round pixel values
|
||||
// so we use setOffset directly with our own function B-0
|
||||
$.offset.setOffset($tip[0], $.extend({
|
||||
using: function (props) {
|
||||
$tip.css({
|
||||
top: Math.round(props.top),
|
||||
left: Math.round(props.left)
|
||||
})
|
||||
}
|
||||
}, offset), 0)
|
||||
|
||||
$tip.addClass('in')
|
||||
|
||||
// check to see if placing tip in new offset caused the tip to resize itself
|
||||
var actualWidth = $tip[0].offsetWidth
|
||||
var actualHeight = $tip[0].offsetHeight
|
||||
|
||||
if (placement == 'top' && actualHeight != height) {
|
||||
replace = true
|
||||
offset.top = offset.top + height - actualHeight
|
||||
}
|
||||
|
||||
if (/bottom|top/.test(placement)) {
|
||||
var delta = 0
|
||||
|
||||
if (offset.left < 0) {
|
||||
delta = offset.left * -2
|
||||
offset.left = 0
|
||||
|
||||
$tip.offset(offset)
|
||||
|
||||
actualWidth = $tip[0].offsetWidth
|
||||
actualHeight = $tip[0].offsetHeight
|
||||
}
|
||||
|
||||
this.replaceArrow(delta - width + actualWidth, actualWidth, 'left')
|
||||
} else {
|
||||
this.replaceArrow(actualHeight - height, actualHeight, 'top')
|
||||
}
|
||||
|
||||
if (replace) $tip.offset(offset)
|
||||
}
|
||||
|
||||
Tooltip.prototype.replaceArrow = function (delta, dimension, position) {
|
||||
this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + '%') : '')
|
||||
}
|
||||
|
||||
Tooltip.prototype.setContent = function () {
|
||||
var $tip = this.tip()
|
||||
var title = this.getTitle()
|
||||
|
||||
$tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
|
||||
$tip.removeClass('fade in top bottom left right')
|
||||
}
|
||||
|
||||
Tooltip.prototype.hide = function () {
|
||||
var that = this
|
||||
var $tip = this.tip()
|
||||
var e = $.Event('hide.bs.' + this.type)
|
||||
|
||||
function complete() {
|
||||
if (that.hoverState != 'in') $tip.detach()
|
||||
that.$element.trigger('hidden.bs.' + that.type)
|
||||
}
|
||||
|
||||
this.$element.trigger(e)
|
||||
|
||||
if (e.isDefaultPrevented()) return
|
||||
|
||||
$tip.removeClass('in')
|
||||
|
||||
$.support.transition && this.$tip.hasClass('fade') ?
|
||||
$tip
|
||||
.one($.support.transition.end, complete)
|
||||
.emulateTransitionEnd(150) :
|
||||
complete()
|
||||
|
||||
this.hoverState = null
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
Tooltip.prototype.fixTitle = function () {
|
||||
var $e = this.$element
|
||||
if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {
|
||||
$e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
|
||||
}
|
||||
}
|
||||
|
||||
Tooltip.prototype.hasContent = function () {
|
||||
return this.getTitle()
|
||||
}
|
||||
|
||||
Tooltip.prototype.getPosition = function () {
|
||||
var el = this.$element[0]
|
||||
return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : {
|
||||
width: el.offsetWidth,
|
||||
height: el.offsetHeight
|
||||
}, this.$element.offset())
|
||||
}
|
||||
|
||||
Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
|
||||
return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } :
|
||||
placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } :
|
||||
placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
|
||||
/* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width }
|
||||
}
|
||||
|
||||
Tooltip.prototype.getTitle = function () {
|
||||
var title
|
||||
var $e = this.$element
|
||||
var o = this.options
|
||||
|
||||
title = $e.attr('data-original-title')
|
||||
|| (typeof o.title == 'function' ? o.title.call($e[0]) : o.title)
|
||||
|
||||
return title
|
||||
}
|
||||
|
||||
Tooltip.prototype.tip = function () {
|
||||
return this.$tip = this.$tip || $(this.options.template)
|
||||
}
|
||||
|
||||
Tooltip.prototype.arrow = function () {
|
||||
return this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow')
|
||||
}
|
||||
|
||||
Tooltip.prototype.validate = function () {
|
||||
if (!this.$element[0].parentNode) {
|
||||
this.hide()
|
||||
this.$element = null
|
||||
this.options = null
|
||||
}
|
||||
}
|
||||
|
||||
Tooltip.prototype.enable = function () {
|
||||
this.enabled = true
|
||||
}
|
||||
|
||||
Tooltip.prototype.disable = function () {
|
||||
this.enabled = false
|
||||
}
|
||||
|
||||
Tooltip.prototype.toggleEnabled = function () {
|
||||
this.enabled = !this.enabled
|
||||
}
|
||||
|
||||
Tooltip.prototype.toggle = function (e) {
|
||||
var self = e ? $(e.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) : this
|
||||
self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
|
||||
}
|
||||
|
||||
Tooltip.prototype.destroy = function () {
|
||||
clearTimeout(this.timeout)
|
||||
this.hide().$element.off('.' + this.type).removeData('bs.' + this.type)
|
||||
}
|
||||
|
||||
|
||||
// TOOLTIP PLUGIN DEFINITION
|
||||
// =========================
|
||||
|
||||
var old = $.fn.tooltip
|
||||
|
||||
$.fn.tooltip = function (option) {
|
||||
return this.each(function () {
|
||||
var $this = $(this)
|
||||
var data = $this.data('bs.tooltip')
|
||||
var options = typeof option == 'object' && option
|
||||
|
||||
if (!data && option == 'destroy') return
|
||||
if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
|
||||
if (typeof option == 'string') data[option]()
|
||||
})
|
||||
}
|
||||
|
||||
$.fn.tooltip.Constructor = Tooltip
|
||||
|
||||
|
||||
// TOOLTIP NO CONFLICT
|
||||
// ===================
|
||||
|
||||
$.fn.tooltip.noConflict = function () {
|
||||
$.fn.tooltip = old
|
||||
return this
|
||||
}
|
||||
|
||||
}(jQuery);
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -6,13 +6,12 @@ var MediaStreamType = require("../../service/RTC/MediaStreamTypes");
|
|||
*
|
||||
* @param data the data object from which we obtain the stream,
|
||||
* the peerjid, etc.
|
||||
* @param sid the session id
|
||||
* @param ssrc the ssrc corresponding to this MediaStream
|
||||
* @param mute the whether this MediaStream is muted
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
function MediaStream(data, sid, ssrc, browser, eventEmitter, mute) {
|
||||
function MediaStream(data, ssrc, browser, eventEmitter, muted) {
|
||||
|
||||
// XXX(gp) to minimize headaches in the future, we should build our
|
||||
// abstractions around tracks and not streams. ORTC is track based API.
|
||||
|
@ -24,14 +23,13 @@ function MediaStream(data, sid, ssrc, browser, eventEmitter, mute) {
|
|||
// Also, we should be able to associate multiple SSRCs with a MediaTrack as
|
||||
// a track might have an associated RTX and FEC sources.
|
||||
|
||||
this.sid = sid;
|
||||
this.stream = data.stream;
|
||||
this.peerjid = data.peerjid;
|
||||
this.videoType = data.videoType;
|
||||
this.ssrc = ssrc;
|
||||
this.type = (this.stream.getVideoTracks().length > 0)?
|
||||
MediaStreamType.VIDEO_TYPE : MediaStreamType.AUDIO_TYPE;
|
||||
this.muted = mute;
|
||||
this.muted = muted;
|
||||
this.eventEmitter = eventEmitter;
|
||||
}
|
||||
|
||||
|
|
|
@ -101,7 +101,7 @@ var RTC = {
|
|||
}
|
||||
}
|
||||
},
|
||||
createRemoteStream: function (data, sid, thessrc) {
|
||||
createRemoteStream: function (data, ssrc) {
|
||||
var jid = data.peerjid || APP.xmpp.myJid();
|
||||
|
||||
// check the video muted state from last stored presence if any
|
||||
|
@ -111,7 +111,7 @@ var RTC = {
|
|||
muted = pres.videoMuted;
|
||||
}
|
||||
|
||||
var remoteStream = new MediaStream(data, sid, thessrc,
|
||||
var remoteStream = new MediaStream(data, ssrc,
|
||||
RTCBrowserType.getBrowserType(), eventEmitter, muted);
|
||||
|
||||
if(!this.remoteStreams[jid]) {
|
||||
|
|
|
@ -259,8 +259,7 @@ function RTCUtils(RTCService, onTemasysPluginReady)
|
|||
attachMediaStream(elSel[0], stream);
|
||||
};
|
||||
self.getStreamID = function (stream) {
|
||||
var id = APP.xmpp.filter_special_chars(stream.label);
|
||||
return id;
|
||||
return APP.xmpp.filter_special_chars(stream.label);
|
||||
};
|
||||
self.getVideoSrc = function (element) {
|
||||
if (!element) {
|
||||
|
|
|
@ -129,7 +129,7 @@ var defaultToolbarButtons = {
|
|||
'invite': '#toolbar_button_link',
|
||||
'chat': '#toolbar_button_chat',
|
||||
'prezi': '#toolbar_button_prezi',
|
||||
'ethherpad': '#toolbar_button_etherpad',
|
||||
'etherpad': '#toolbar_button_etherpad',
|
||||
'fullscreen': '#toolbar_button_fullScreen',
|
||||
'settings': '#toolbar_button_settings',
|
||||
'hangup': '#toolbar_button_hangup'
|
||||
|
|
|
@ -168,6 +168,9 @@ RemoteVideo.prototype.removeRemoteStreamElement =
|
|||
RemoteVideo.prototype.remove = function () {
|
||||
console.log("Remove thumbnail", this.peerJid);
|
||||
this.removeConnectionIndicator();
|
||||
// Make sure that the large video is updated if are removing its
|
||||
// corresponding small video.
|
||||
this.VideoLayout.updateRemovedVideo(this.getResourceJid());
|
||||
// Remove whole container
|
||||
if (this.container.parentNode)
|
||||
this.container.parentNode.removeChild(this.container);
|
||||
|
@ -204,13 +207,13 @@ RemoteVideo.prototype.waitForPlayback = function (sel, stream) {
|
|||
sel[0].onplaying = onPlayingHandler;
|
||||
};
|
||||
|
||||
RemoteVideo.prototype.addRemoteStreamElement = function (sid, stream, thessrc) {
|
||||
RemoteVideo.prototype.addRemoteStreamElement = function (stream) {
|
||||
if (!this.container)
|
||||
return;
|
||||
|
||||
var self = this;
|
||||
var isVideo = stream.getVideoTracks().length > 0;
|
||||
var streamElement = SmallVideo.createStreamElement(sid, stream);
|
||||
var streamElement = SmallVideo.createStreamElement(stream);
|
||||
var newElementId = streamElement.id;
|
||||
|
||||
// Put new stream element always in front
|
||||
|
@ -233,19 +236,6 @@ RemoteVideo.prototype.addRemoteStreamElement = function (sid, stream, thessrc) {
|
|||
|
||||
};
|
||||
|
||||
/**
|
||||
* FF is missing onended event for remote streams. The problem we are fixing
|
||||
* here is when the last participant leaves the room the video element is
|
||||
* not updated. So the avatar or last video frame will stay, the fix updates
|
||||
* the video elem and switches to local video the same as behavior in other
|
||||
* browsers.
|
||||
*/
|
||||
if (RTCBrowserType.isFirefox()) {
|
||||
APP.xmpp.addListener(XMPPEvents.MUC_MEMBER_LEFT, function (jid) {
|
||||
self.removeRemoteStreamElement(stream, isVideo, newElementId);
|
||||
});
|
||||
}
|
||||
|
||||
// Add click handler.
|
||||
var onClickHandler = function (event) {
|
||||
|
||||
|
|
|
@ -102,20 +102,21 @@ SmallVideo.prototype.setPresenceStatus = function (statusMsg) {
|
|||
};
|
||||
|
||||
/**
|
||||
* Creates an audio or video stream element.
|
||||
* Creates an audio or video element for a particular MediaStream.
|
||||
*/
|
||||
SmallVideo.createStreamElement = function (sid, stream) {
|
||||
SmallVideo.createStreamElement = function (stream) {
|
||||
var isVideo = stream.getVideoTracks().length > 0;
|
||||
|
||||
var element = isVideo ? document.createElement('video')
|
||||
: document.createElement('audio');
|
||||
var id = (isVideo ? 'remoteVideo_' : 'remoteAudio_') + sid + '_' +
|
||||
APP.RTC.getStreamID(stream);
|
||||
|
||||
element.id = id;
|
||||
if (!RTCBrowserType.isIExplorer()) {
|
||||
element.autoplay = true;
|
||||
}
|
||||
|
||||
element.id = (isVideo ? 'remoteVideo_' : 'remoteAudio_') +
|
||||
APP.RTC.getStreamID(stream);
|
||||
|
||||
element.oncontextmenu = function () { return false; };
|
||||
|
||||
return element;
|
||||
|
|
|
@ -126,12 +126,11 @@ var VideoLayout = (function (my) {
|
|||
/**
|
||||
* Checks if removed video is currently displayed and tries to display
|
||||
* another one instead.
|
||||
* @param removedVideoSrc src stream identifier of the video.
|
||||
*/
|
||||
my.updateRemovedVideo = function(resourceJid) {
|
||||
var newResourceJid;
|
||||
|
||||
if (resourceJid === LargeVideo.getResourceJid()) {
|
||||
var newResourceJid;
|
||||
// We'll show user's avatar if he is the dominant speaker or if
|
||||
// his video thumbnail is pinned
|
||||
if (remoteVideos[resourceJid] &&
|
||||
|
@ -153,18 +152,32 @@ var VideoLayout = (function (my) {
|
|||
var pick = $('#remoteVideos>span[id!="mixedstream"]:visible:last');
|
||||
if (pick.length) {
|
||||
jid = VideoLayout.getPeerContainerResourceJid(pick[0]);
|
||||
} else {
|
||||
if (!remoteVideos[jid]) {
|
||||
// The RemoteVideo was removed (but the DOM elements may still
|
||||
// exist).
|
||||
jid = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (!jid) {
|
||||
console.info("Last visible video no longer exists");
|
||||
pick = $('#remoteVideos>span[id!="mixedstream"]');
|
||||
if (pick.length) {
|
||||
jid = VideoLayout.getPeerContainerResourceJid(pick[0]);
|
||||
if (!remoteVideos[jid]) {
|
||||
// The RemoteVideo was removed (but the DOM elements may
|
||||
// still exist).
|
||||
jid = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!jid) {
|
||||
// Go with local video
|
||||
console.info("Fallback to local video...");
|
||||
jid = APP.xmpp.myResource();
|
||||
}
|
||||
}
|
||||
|
||||
console.info("electLastVisibleVideo: " + jid);
|
||||
return jid;
|
||||
};
|
||||
|
@ -175,9 +188,7 @@ var VideoLayout = (function (my) {
|
|||
|
||||
var resourceJid = Strophe.getResourceFromJid(stream.peerjid);
|
||||
remoteVideos[resourceJid].addRemoteStreamElement(
|
||||
stream.sid,
|
||||
stream.getOriginalStream(),
|
||||
stream.ssrc);
|
||||
stream.getOriginalStream());
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -832,8 +843,7 @@ var VideoLayout = (function (my) {
|
|||
focusedVideoResourceJid = null;
|
||||
}
|
||||
|
||||
if (currentDominantSpeaker === resourceJid)
|
||||
{
|
||||
if (currentDominantSpeaker === resourceJid) {
|
||||
console.info("Dominant speaker has left the conference");
|
||||
currentDominantSpeaker = null;
|
||||
}
|
||||
|
@ -842,8 +852,8 @@ var VideoLayout = (function (my) {
|
|||
if (remoteVideo) {
|
||||
// Remove remote video
|
||||
console.info("Removing remote video: " + resourceJid);
|
||||
remoteVideo.remove();
|
||||
delete remoteVideos[resourceJid];
|
||||
remoteVideo.remove();
|
||||
} else {
|
||||
console.warn("No remote video for " + resourceJid);
|
||||
}
|
||||
|
|
|
@ -135,7 +135,8 @@ module.exports = {
|
|||
isUsingScreenStream = false;
|
||||
newStreamCreated(stream);
|
||||
},
|
||||
getVideoStreamFailed, config.resolution || '360'
|
||||
getVideoStreamFailed,
|
||||
config.resolution || '360'
|
||||
);
|
||||
}
|
||||
},
|
||||
|
|
|
@ -36,16 +36,33 @@ if (supportsLocalStorage()) {
|
|||
}
|
||||
|
||||
var Settings = {
|
||||
|
||||
/**
|
||||
* Sets the local user display name and saves it to local storage
|
||||
*
|
||||
* @param newDisplayName the new display name for the local user
|
||||
* @returns {string} the display name we just set
|
||||
*/
|
||||
setDisplayName: function (newDisplayName) {
|
||||
displayName = newDisplayName;
|
||||
window.localStorage.displayname = displayName;
|
||||
return displayName;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the currently used by the user
|
||||
* @returns {string} currently valid user display name.
|
||||
*/
|
||||
getDisplayName: function () {
|
||||
return displayName;
|
||||
},
|
||||
|
||||
setEmail: function (newEmail) {
|
||||
email = newEmail;
|
||||
window.localStorage.email = newEmail;
|
||||
return email;
|
||||
},
|
||||
|
||||
getSettings: function () {
|
||||
return {
|
||||
email: email,
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
/* global config, $, APP, Strophe, callstats */
|
||||
|
||||
var Settings = require('../settings/Settings');
|
||||
var jsSHA = require('jssha');
|
||||
var io = require('socket.io-client');
|
||||
var callStats = null;
|
||||
|
@ -20,6 +22,10 @@ var CallStats = {
|
|||
|
||||
this.userID = APP.xmpp.myResource();
|
||||
|
||||
//use whatever the user said to facilitate debugging
|
||||
if(Settings.getDisplayName())
|
||||
this.userID = Settings.getDisplayName();
|
||||
|
||||
var location = window.location;
|
||||
this.confID = location.hostname + location.pathname;
|
||||
|
||||
|
|
|
@ -108,21 +108,22 @@ JingleSessionPC.prototype.doInitialize = function () {
|
|||
self.sendIceCandidate(event.candidate);
|
||||
};
|
||||
this.peerconnection.onaddstream = function (event) {
|
||||
if (event.stream.id !== 'default') {
|
||||
console.log("REMOTE STREAM ADDED: ", event.stream , event.stream.id);
|
||||
self.remoteStreamAdded(event);
|
||||
} else {
|
||||
if (event.stream.id === 'default') {
|
||||
// This is a recvonly stream. Clients that implement Unified Plan,
|
||||
// such as Firefox use recvonly "streams/channels/tracks" for
|
||||
// receiving remote stream/tracks, as opposed to Plan B where there
|
||||
// are only 3 channels: audio, video and data.
|
||||
console.log("RECVONLY REMOTE STREAM IGNORED: " + event.stream + " - " + event.stream.id);
|
||||
console.log("RECVONLY REMOTE STREAM IGNORED: " + event.stream +
|
||||
" - " + event.stream.id);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log("REMOTE STREAM ADDED: ", event.stream, event.stream.id);
|
||||
self.remoteStreamAdded(event);
|
||||
};
|
||||
this.peerconnection.onremovestream = function (event) {
|
||||
// Remove the stream from remoteStreams
|
||||
// FIXME: remotestreamremoved.jingle not defined anywhere(unused)
|
||||
$(document).trigger('remotestreamremoved.jingle', [event, self.sid]);
|
||||
// Remove the stream from remoteStreams?
|
||||
console.log("We are ignoring a removestream event: " + event);
|
||||
};
|
||||
this.peerconnection.onsignalingstatechange = function (event) {
|
||||
if (!(self && self.peerconnection)) return;
|
||||
|
@ -857,7 +858,11 @@ JingleSessionPC.prototype.sendTerminate = function (reason, text) {
|
|||
}
|
||||
};
|
||||
|
||||
JingleSessionPC.prototype.addSource = function (elem, fromJid) {
|
||||
/**
|
||||
* Handles a Jingle source-add message for this Jingle session.
|
||||
* @param elem An array of Jingle "content" elements.
|
||||
*/
|
||||
JingleSessionPC.prototype.addSource = function (elem) {
|
||||
|
||||
var self = this;
|
||||
// FIXME: dirty waiting
|
||||
|
@ -865,7 +870,7 @@ JingleSessionPC.prototype.addSource = function (elem, fromJid) {
|
|||
console.warn("addSource - localDescription not ready yet");
|
||||
setTimeout(function()
|
||||
{
|
||||
self.addSource(elem, fromJid);
|
||||
self.addSource(elem);
|
||||
},
|
||||
200
|
||||
);
|
||||
|
@ -938,14 +943,18 @@ JingleSessionPC.prototype.addSource = function (elem, fromJid) {
|
|||
});
|
||||
};
|
||||
|
||||
JingleSessionPC.prototype.removeSource = function (elem, fromJid) {
|
||||
/**
|
||||
* Handles a Jingle source-remove message for this Jingle session.
|
||||
* @param elem An array of Jingle "content" elements.
|
||||
*/
|
||||
JingleSessionPC.prototype.removeSource = function (elem) {
|
||||
|
||||
var self = this;
|
||||
// FIXME: dirty waiting
|
||||
if (!this.peerconnection.localDescription) {
|
||||
console.warn("removeSource - localDescription not ready yet");
|
||||
setTimeout(function() {
|
||||
self.removeSource(elem, fromJid);
|
||||
self.removeSource(elem);
|
||||
},
|
||||
200
|
||||
);
|
||||
|
@ -1440,24 +1449,29 @@ function sendKeyframe(pc) {
|
|||
);
|
||||
}
|
||||
|
||||
|
||||
JingleSessionPC.prototype.remoteStreamAdded = function (data, times) {
|
||||
/**
|
||||
* Handles 'onaddstream' events from the RTCPeerConnection.
|
||||
* @param event the 'onaddstream' event.
|
||||
*/
|
||||
JingleSessionPC.prototype.remoteStreamAdded = function (event) {
|
||||
var self = this;
|
||||
var thessrc;
|
||||
var streamId = APP.RTC.getStreamID(data.stream);
|
||||
var ssrc;
|
||||
var ssrclines;
|
||||
var streamId = APP.RTC.getStreamID(event.stream);
|
||||
|
||||
// look up an associated JID for a stream id
|
||||
if (!streamId) {
|
||||
console.error("No stream ID for", data.stream);
|
||||
} else if (streamId && streamId.indexOf('mixedmslabel') === -1) {
|
||||
console.error("No stream ID for", event.stream);
|
||||
} else if (streamId.indexOf('mixedmslabel') === -1) {
|
||||
// look only at a=ssrc: and _not_ at a=ssrc-group: lines
|
||||
|
||||
var ssrclines
|
||||
= SDPUtil.find_lines(this.peerconnection.remoteDescription.sdp, 'a=ssrc:');
|
||||
ssrclines = SDPUtil.find_lines(
|
||||
this.peerconnection.remoteDescription.sdp,
|
||||
'a=ssrc:');
|
||||
ssrclines = ssrclines.filter(function (line) {
|
||||
// NOTE(gp) previously we filtered on the mslabel, but that property
|
||||
// is not always present.
|
||||
// return line.indexOf('mslabel:' + data.stream.label) !== -1;
|
||||
// return line.indexOf('mslabel:' + event.stream.label) !== -1;
|
||||
|
||||
if (RTCBrowserType.isTemasysPluginUsed()) {
|
||||
return ((line.indexOf('mslabel:' + streamId) !== -1));
|
||||
|
@ -1466,33 +1480,21 @@ JingleSessionPC.prototype.remoteStreamAdded = function (data, times) {
|
|||
}
|
||||
});
|
||||
if (ssrclines.length) {
|
||||
thessrc = ssrclines[0].substring(7).split(' ')[0];
|
||||
ssrc = ssrclines[0].substring(7).split(' ')[0];
|
||||
|
||||
if (!self.ssrcOwners[thessrc]) {
|
||||
console.error("No SSRC owner known for: " + thessrc);
|
||||
if (!self.ssrcOwners[ssrc]) {
|
||||
console.error("No SSRC owner known for: " + ssrc);
|
||||
return;
|
||||
}
|
||||
data.peerjid = self.ssrcOwners[thessrc];
|
||||
console.log('associated jid', self.ssrcOwners[thessrc]);
|
||||
event.peerjid = self.ssrcOwners[ssrc];
|
||||
console.log('Adding remote stream, SSRC ' + ssrc +
|
||||
', associated jid ' + event.peerjid);
|
||||
} else {
|
||||
console.error("No SSRC lines for ", streamId);
|
||||
}
|
||||
}
|
||||
|
||||
APP.RTC.createRemoteStream(data, this.sid, thessrc);
|
||||
|
||||
var isVideo = data.stream.getVideoTracks().length > 0;
|
||||
// an attempt to work around https://github.com/jitsi/jitmeet/issues/32
|
||||
// TODO: is this hack still needed now that we announce an SSRC for
|
||||
// receive-only streams?
|
||||
if (isVideo &&
|
||||
data.peerjid && this.peerjid === data.peerjid &&
|
||||
data.stream.getVideoTracks().length === 0 &&
|
||||
APP.RTC.localVideo.getTracks().length > 0) {
|
||||
window.setTimeout(function () {
|
||||
sendKeyframe(self.peerconnection);
|
||||
}, 3000);
|
||||
}
|
||||
APP.RTC.createRemoteStream(event, ssrc);
|
||||
};
|
||||
|
||||
module.exports = JingleSessionPC;
|
||||
|
|
|
@ -174,11 +174,11 @@ module.exports = function(XMPP, eventEmitter) {
|
|||
break;
|
||||
case 'addsource': // FIXME: proprietary, un-jingleish
|
||||
case 'source-add': // FIXME: proprietary
|
||||
sess.addSource($(iq).find('>jingle>content'), fromJid);
|
||||
sess.addSource($(iq).find('>jingle>content'));
|
||||
break;
|
||||
case 'removesource': // FIXME: proprietary, un-jingleish
|
||||
case 'source-remove': // FIXME: proprietary
|
||||
sess.removeSource($(iq).find('>jingle>content'), fromJid);
|
||||
sess.removeSource($(iq).find('>jingle>content'));
|
||||
break;
|
||||
default:
|
||||
console.warn('jingle action not implemented', action);
|
||||
|
|
85
package.json
85
package.json
|
@ -16,27 +16,84 @@
|
|||
"readmeFilename": "README.md",
|
||||
"//": "Callstats.io does not work with recent versions of jsSHA (2.0.1 in particular)",
|
||||
"dependencies": {
|
||||
"events": "*",
|
||||
"pako": "*",
|
||||
"i18next-client": "1.7.7",
|
||||
"sdp-interop": "0.1.10",
|
||||
"sdp-transform": "1.4.1",
|
||||
"sdp-simulcast": "0.1.0",
|
||||
"async": "0.9.0",
|
||||
"retry": "0.6.1",
|
||||
"autosize": "^1.18.13",
|
||||
"bootstrap": "^3.1.1",
|
||||
"events": "*",
|
||||
"i18next-client": "1.7.7",
|
||||
"jquery": "^2.1.1",
|
||||
"jQuery-Impromptu": "git+https://github.com/trentrichardson/jQuery-Impromptu.git#v6.0.0",
|
||||
"jquery-ui": "^1.10.5",
|
||||
"jssha": "1.5.0",
|
||||
"socket.io-client": "1.3.6"
|
||||
"pako": "*",
|
||||
"retry": "0.6.1",
|
||||
"sdp-interop": "0.1.10",
|
||||
"sdp-simulcast": "0.1.0",
|
||||
"sdp-transform": "1.4.1",
|
||||
"socket.io-client": "1.3.6",
|
||||
"strophe": "^1.2.2",
|
||||
"strophejs-plugins": "^0.0.6",
|
||||
"toastr": "^2.0.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"precommit-hook": "3.0.0",
|
||||
"jshint": "2.8.0",
|
||||
"uglify-js": "2.4.24",
|
||||
"browserify": "11.1.x",
|
||||
"exorcist": "*"
|
||||
"browserify-shim": "^3.8.10",
|
||||
"exorcist": "*",
|
||||
"jshint": "2.8.0",
|
||||
"precommit-hook": "3.0.0",
|
||||
"uglify-js": "2.4.24"
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"scripts": {
|
||||
"lint": "./node_modules/.bin/jshint ."
|
||||
"lint": "./node_modules/.bin/jshint .",
|
||||
"validate": "npm ls"
|
||||
},
|
||||
"pre-commit": ["lint"]
|
||||
"pre-commit": [
|
||||
"lint"
|
||||
],
|
||||
"browserify": {
|
||||
"transform": [
|
||||
"browserify-shim"
|
||||
]
|
||||
},
|
||||
"browser": {
|
||||
"jquery": "./node_modules/jquery/dist/jquery.js",
|
||||
"jquery-ui": "./node_modules/jquery-ui/jquery-ui.js",
|
||||
"strophe": "./node_modules/strophe/strophe.js",
|
||||
"strophe-disco": "./node_modules/strophejs-plugins/disco/strophe.disco.js",
|
||||
"strophe-caps": "./node_modules/strophejs-plugins/caps/strophe.caps.jsonly.js",
|
||||
"toastr": "./node_modules/toastr/toastr.js",
|
||||
"tooltip": "./node_modules/bootstrap/js/tooltip.js",
|
||||
"popover": "./node_modules/bootstrap/js/popover.js",
|
||||
"jQuery-Impromptu": "./node_modules/jQuery-Impromptu/dist/jquery-impromptu.js",
|
||||
"autosize": "./node_modules/autosize/build/jquery.autosize.js"
|
||||
},
|
||||
"browserify-shim": {
|
||||
"jquery": [
|
||||
"$"
|
||||
],
|
||||
"strophe": {
|
||||
"exports": "Strophe",
|
||||
"depends": [
|
||||
"jquery:$"
|
||||
]
|
||||
},
|
||||
"strophe-disco": {
|
||||
"depends": [
|
||||
"strophe:Strophe"
|
||||
]
|
||||
},
|
||||
"tooltip": {
|
||||
"depends": "jquery:jQuery"
|
||||
},
|
||||
"popover": {
|
||||
"depends": "jquery:jQuery"
|
||||
},
|
||||
"jQuery-Impromptu": {
|
||||
"depends": "jquery:jQuery"
|
||||
},
|
||||
"autosize": {
|
||||
"depends": "jquery:jQuery"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue