mirror of
https://github.com/ossrs/srs.git
synced 2025-02-13 03:41:55 +00:00
SquashSRS4: Add console. Disable cherrypy by default.
This commit is contained in:
parent
c95bfc4a46
commit
d4a8a72388
62 changed files with 38537 additions and 111 deletions
|
@ -197,6 +197,8 @@ Other documents:
|
|||
|
||||
## V4 changes
|
||||
|
||||
* v4.0, 2021-04-24, Player: Change the default from RTMP to HTTP-FLV.
|
||||
* v4.0, 2021-04-24, Disable CherryPy by --cherrypy=off. 4.0.90
|
||||
* v4.0, 2021-04-01, RTC: Refine TWCC and SDP exchange. 4.0.88
|
||||
* v4.0, 2021-03-24, RTC: Support WebRTC re-publish stream. 4.0.87
|
||||
* v4.0, 2021-03-24, RTC: Use fast parse TWCC-ID, ignore in packet parsing. 4.0.86
|
||||
|
@ -274,6 +276,9 @@ Other documents:
|
|||
|
||||
## V3 changes
|
||||
|
||||
* <strong>v3.0, 2021-04-24, [3.0 release4(3.0.160)][r3.0r4] released. 122750 lines.</strong>
|
||||
* v3.0, 2021-04-24, Package players and console to zip and docker. 3.0.160
|
||||
* v3.0, 2021-04-24, Add srs-console to research/console. 3.0.159
|
||||
* v3.0, 2021-03-05, Refine usage to docker by default. 3.0.158
|
||||
* v3.0, 2021-01-07, Change id from int to string for the statistics. 3.0.157
|
||||
* <strong>v3.0, 2021-01-02, [3.0 release3(3.0.156)][r3.0r3] released. 122736 lines.</strong>
|
||||
|
@ -909,6 +914,7 @@ Other documents:
|
|||
|
||||
## Releases
|
||||
|
||||
* 2021-04-24, [Release v3.0-r4][r3.0r4], 3.0 release4, 3.0.160, 122750 lines.
|
||||
* 2021-01-02, [Release v3.0-r3][r3.0r3], 3.0 release3, 3.0.156, 122736 lines.
|
||||
* 2020-10-31, [Release v3.0-r2][r3.0r2], 3.0 release2, 3.0.153, 122663 lines.
|
||||
* 2020-10-10, [Release v3.0-r1][r3.0r1], 3.0 release1, 3.0.144, 122674 lines.
|
||||
|
@ -1899,6 +1905,7 @@ Winlin
|
|||
|
||||
[exo #828]: https://github.com/google/ExoPlayer/pull/828
|
||||
|
||||
[r3.0r4]: https://github.com/ossrs/srs/releases/tag/v3.0-r4
|
||||
[r3.0r3]: https://github.com/ossrs/srs/releases/tag/v3.0-r3
|
||||
[r3.0r2]: https://github.com/ossrs/srs/releases/tag/v3.0-r2
|
||||
[r3.0r1]: https://github.com/ossrs/srs/releases/tag/v3.0-r1
|
||||
|
|
|
@ -430,6 +430,14 @@ ln -sf `pwd`/research/players/crossdomain.xml ${SRS_OBJS}/nginx/html/crossdomain
|
|||
rm -rf ${SRS_OBJS}/nginx/html/favicon.ico &&
|
||||
ln -sf `pwd`/research/api-server/static-dir/favicon.ico ${SRS_OBJS}/nginx/html/favicon.ico
|
||||
|
||||
# For srs-console.
|
||||
rm -rf ${SRS_OBJS}/nginx/html/console &&
|
||||
ln -sf `pwd`/research/console ${SRS_OBJS}/nginx/html/console
|
||||
|
||||
# For home page index.html
|
||||
rm -rf ${SRS_OBJS}/nginx/html/index.html &&
|
||||
ln -sf `pwd`/research/api-server/static-dir/index.html ${SRS_OBJS}/nginx/html/index.html
|
||||
|
||||
# nginx.html to detect whether nginx is alive
|
||||
echo "Nginx is ok." > ${SRS_OBJS}/nginx/html/nginx.html
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ SRS_HTTP_API=YES
|
|||
SRS_HTTP_CORE=YES
|
||||
SRS_HLS=YES
|
||||
SRS_DVR=YES
|
||||
SRS_CHERRYPY=YES
|
||||
SRS_CHERRYPY=NO
|
||||
#
|
||||
################################################################
|
||||
# FFmpeg stub is the stub code in SRS for ingester or encoder.
|
||||
|
|
46
trunk/configure
vendored
46
trunk/configure
vendored
|
@ -455,7 +455,7 @@ mv ${SRS_WORKDIR}/${SRS_MAKEFILE} ${SRS_WORKDIR}/${SRS_MAKEFILE}.bk
|
|||
|
||||
# generate phony header
|
||||
cat << END > ${SRS_WORKDIR}/${SRS_MAKEFILE}
|
||||
.PHONY: default _default install install-api help clean destroy server srs_ingest_hls utest _prepare_dir $__mphonys
|
||||
.PHONY: default _default install help clean destroy server srs_ingest_hls utest _prepare_dir $__mphonys
|
||||
.PHONY: clean_srs clean_modules clean_openssl clean_nginx clean_cherrypy clean_srtp2 clean_opus clean_ffmpeg clean_st
|
||||
.PHONY: st ffmpeg
|
||||
|
||||
|
@ -474,14 +474,13 @@ _default: server srs_ingest_hls utest $__mdefaults
|
|||
@bash objs/_srs_build_summary.sh
|
||||
|
||||
help:
|
||||
@echo "Usage: make <help>|<clean>|<destroy>|<server>|<utest>|<install>|<install-api>|<uninstall>"
|
||||
@echo "Usage: make <help>|<clean>|<destroy>|<server>|<utest>|<install>|<uninstall>"
|
||||
@echo " help Display this help menu"
|
||||
@echo " clean Cleanup project and all depends"
|
||||
@echo " destroy Cleanup all files for this platform in ${SRS_OBJS_DIR}/${SRS_PLATFORM}"
|
||||
@echo " server Build the srs and other modules in main"
|
||||
@echo " utest Build the utest for srs"
|
||||
@echo " install Install srs to the prefix path"
|
||||
@echo " install-api Install srs and api-server to the prefix path"
|
||||
@echo " uninstall Uninstall srs from prefix path"
|
||||
@echo "To rebuild special module:"
|
||||
@echo " st Rebuild st-srs in ${SRS_OBJS_DIR}/${SRS_PLATFORM}/st-srs"
|
||||
|
@ -503,7 +502,6 @@ doclean:
|
|||
(cd research/api-server/static-dir && rm -rf crossdomain.xml forward live players)
|
||||
|
||||
clean: clean_srs clean_modules
|
||||
@echo "You can clean each some components, see make help"
|
||||
|
||||
destroy:
|
||||
(cd ${SRS_OBJS_DIR} && rm -rf ${SRS_PLATFORM})
|
||||
|
@ -557,7 +555,7 @@ END
|
|||
|
||||
cat << END >> ${SRS_WORKDIR}/${SRS_MAKEFILE}
|
||||
server: _prepare_dir
|
||||
@echo "Build the srs(simple rtmp server) over ST(state-threads)"
|
||||
@echo "Build the SRS server"
|
||||
\$(MAKE) -f ${SRS_OBJS_DIR}/${SRS_MAKEFILE} srs
|
||||
|
||||
END
|
||||
|
@ -578,30 +576,6 @@ uninstall:
|
|||
@echo "rmdir \$(SRS_PREFIX)"
|
||||
@rm -rf \$(SRS_PREFIX)
|
||||
|
||||
install-api: install
|
||||
@echo "Now mkdir \$(__REAL_INSTALL)"
|
||||
@mkdir -p \$(__REAL_INSTALL)
|
||||
@echo "Now copy binary files"
|
||||
@mkdir -p \$(__REAL_INSTALL)/research/api-server
|
||||
@cp research/api-server/server.py \$(__REAL_INSTALL)/research/api-server
|
||||
@mkdir -p \$(__REAL_INSTALL)/objs/ffmpeg/bin
|
||||
@cp objs/ffmpeg/bin/ffmpeg \$(__REAL_INSTALL)/objs/ffmpeg/bin
|
||||
@echo "Now copy html files"
|
||||
@mkdir -p \$(__REAL_INSTALL)/research/api-server/static-dir/players
|
||||
@cp research/api-server/static-dir/crossdomain.xml \$(__REAL_INSTALL)/research/api-server/static-dir
|
||||
@cp research/api-server/static-dir/index.html \$(__REAL_INSTALL)/research/api-server/static-dir
|
||||
@cp -r research/api-server/static-dir/players/* \$(__REAL_INSTALL)/research/api-server/static-dir/players
|
||||
@echo "Now copy init.d script files"
|
||||
@mkdir -p \$(__REAL_INSTALL)/etc/init.d
|
||||
@cp etc/init.d/srs-api \$(__REAL_INSTALL)/etc/init.d
|
||||
@sed -i "s|^ROOT=.*|ROOT=\"\$(SRS_PREFIX)\"|g" \$(__REAL_INSTALL)/etc/init.d/srs-api
|
||||
@echo ""
|
||||
@echo "The api installed, to link and start api:"
|
||||
@echo " sudo ln -sf \$(SRS_PREFIX)/etc/init.d/srs-api /etc/init.d/srs-api"
|
||||
@echo " /etc/init.d/srs-api start"
|
||||
@echo " http://\$(shell bash auto/local_ip.sh):8085"
|
||||
@echo "@see: https://github.com/ossrs/srs/wiki/v1_CN_LinuxService"
|
||||
|
||||
install:
|
||||
@echo "Now mkdir \$(__REAL_INSTALL)"
|
||||
@mkdir -p \$(__REAL_INSTALL)
|
||||
|
@ -800,20 +774,22 @@ done
|
|||
# Do cleanup when configure done.
|
||||
#####################################################################################
|
||||
if [[ $SRS_CLEAN == YES && -f Makefile ]]; then
|
||||
echo "Do full cleanup, you can disable it by: --clean=off"
|
||||
#echo "Do full cleanup, you can disable it by: --clean=off"
|
||||
make clean
|
||||
fi
|
||||
|
||||
#####################################################################################
|
||||
# next step
|
||||
#####################################################################################
|
||||
echo ""
|
||||
echo "You can run 3rdparty applications:"
|
||||
if [ $SRS_HTTP_CALLBACK = YES ]; then
|
||||
if [[ $SRS_CHERRYPY == YES ]]; then
|
||||
echo ""
|
||||
echo "You can run 3rdparty applications:"
|
||||
if [ $SRS_HTTP_CALLBACK = YES ]; then
|
||||
echo -e "\" python ./research/api-server/server.py 8085 \" to start the api-server"
|
||||
fi
|
||||
fi
|
||||
echo ""
|
||||
echo "You can build SRS:"
|
||||
echo "\" make \" to build the srs(simple rtmp server)."
|
||||
echo "\" make help \" to get the usage of make"
|
||||
echo "\" make \" to build the SRS server"
|
||||
echo "\" make help \" to get some help"
|
||||
|
||||
|
|
|
@ -1,50 +1,26 @@
|
|||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>SRS</title>
|
||||
<meta charset="utf-8">
|
||||
<link rel="stylesheet" type="text/css" href="players/css/bootstrap.min.css"/>
|
||||
<script type="text/javascript" src="players/js/jquery-1.10.2.min.js"></script>
|
||||
<script type="text/javascript" src="players/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="players/js/swfobject.js"></script>
|
||||
<script type="text/javascript" src="players/js/srs.page.js"></script>
|
||||
<style>
|
||||
body{
|
||||
padding-top: 55px;
|
||||
}
|
||||
</style>
|
||||
<script type="text/javascript">
|
||||
$(function(){
|
||||
update_nav();
|
||||
|
||||
// direct to the default vhost for players.
|
||||
window.location.href = "players/index.html" + window.location.search;
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar navbar-fixed-top">
|
||||
<div class="navbar-inner">
|
||||
<div class="container">
|
||||
<a class="brand" href="index.html">SRS</a>
|
||||
<div class="nav-collapse collapse">
|
||||
<ul class="nav">
|
||||
<li><a id="nav_srs_player" href="srs_player.html">SRS播放器</a></li>
|
||||
<li><a id="nav_srs_publisher" href="srs_publisher.html">SRS编码器</a></li>
|
||||
<li><a id="nav_srs_chat" href="srs_chat.html">SRS会议</a></li>
|
||||
<li><a id="nav_srs_bwt" href="srs_bwt.html">SRS测网速</a></li>
|
||||
<li><a id="nav_jwplayer6" href="jwplayer6.html">JWPlayer6播放器</a></li>
|
||||
<li><a id="nav_osmf" href="osmf.html">AdobeOSMF播放器</a></li>
|
||||
<li><a id="nav_vlc" href="vlc.html">VLC播放器</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<hr>
|
||||
<footer>
|
||||
<p><a href="https://github.com/ossrs/srs">SRS Team © 2013</a></p>
|
||||
</footer>
|
||||
</div>
|
||||
<h3><a href="https://github.com/ossrs/srs">SRS</a> works!</h3>
|
||||
<p>
|
||||
Click <a id="en" href="#">here</a> to enter SRS console.<br/>
|
||||
点击进入<a id="cn" href="#">SRS控制台</a>
|
||||
</p>
|
||||
<p>
|
||||
Click <a href="players/">here</a> to start SRS player.<br/>
|
||||
点击进入<a href="players/">SRS播放器</a>
|
||||
</p>
|
||||
<p><a href="https://github.com/ossrs/srs">SRS Team © 2021</a></p>
|
||||
<script type="text/javascript">
|
||||
// http://localhost:8080/console/ng_index.html#/connect?port=1985
|
||||
// http://localhost:8080/console/ng_index.html#/summaries?port=1985
|
||||
var en_url = window.location.protocol + "//" + window.location.host + "/console/en_index.html#/summaries?port=1985";
|
||||
var cn_url = window.location.protocol + "//" + window.location.host + "/console/ng_index.html#/summaries?port=1985";
|
||||
document.getElementById("en").setAttribute('href', en_url);
|
||||
document.getElementById("cn").setAttribute('href', cn_url);
|
||||
</script>
|
||||
</body>
|
||||
|
|
68
trunk/research/console/en_index.html
Normal file
68
trunk/research/console/en_index.html
Normal file
|
@ -0,0 +1,68 @@
|
|||
<!DOCTYPE html>
|
||||
<html ng-app="scApp">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<title>SRS控制台</title>
|
||||
<link rel="stylesheet" type="text/css" href="js/3rdparty/bootstrap.min.css"/>
|
||||
<link rel="stylesheet" type="text/css" href="js/srs.console.css"/>
|
||||
<style>
|
||||
body {
|
||||
padding-top: 50px;
|
||||
}
|
||||
</style>
|
||||
<script type="text/javascript" src="js/3rdparty/angular.min.js"></script>
|
||||
<script type="text/javascript" src="js/3rdparty/angular-route.min.js"></script>
|
||||
<script type="text/javascript" src="js/3rdparty/angular-resource.min.js"></script>
|
||||
<script type="text/javascript" src="js/winlin.utility.js"></script>
|
||||
<script type="text/javascript" src="js/bravo_alert/alert.js"></script>
|
||||
<script type="text/javascript" src="js/bravo_popover/popover.js"></script>
|
||||
<script type="text/javascript" src="js/srs.en.js"></script>
|
||||
<script type="text/javascript" src="js/srs.console.js"></script>
|
||||
</head>
|
||||
<body ng-controller="CSCMain">
|
||||
<img src='https://ossrs.net:8443/gif/v1/sls.gif?site=ossrs.net&path=/console/enindex'/>
|
||||
<div class="navbar navbar-inverse navbar-fixed-top">
|
||||
<div class="navbar-inner">
|
||||
<div class="container">
|
||||
<a class="brand" href="https://github.com/ossrs/srs" target="_blank">SRS</a>
|
||||
<ul class="nav">
|
||||
<li class="{{'/console'| sc_filter_nav_active}}"><a href="javascript:void(0)" ng-click="gogogo('/connect')">ConnectSRS</a></li>
|
||||
<li class="{{'/summaries'| sc_filter_nav_active}}"><a href="javascript:void(0)" ng-click="gogogo('/summaries')">Overview</a></li>
|
||||
<li class="{{'/vhosts'| sc_filter_nav_active}}"><a href="javascript:void(0)" ng-click="gogogo('/vhosts')">Vhosts</a></li>
|
||||
<li class="{{'/streams'| sc_filter_nav_active}}"><a href="javascript:void(0)" ng-click="gogogo('/streams')">Streams</a></li>
|
||||
<li class="{{'/clients'| sc_filter_nav_active}}"><a href="javascript:void(0)" ng-click="gogogo('/clients')">Clients</a></li>
|
||||
<li class="{{'/configs'| sc_filter_nav_active}}"><a href="javascript:void(0)" ng-click="gogogo('/configs')">Config</a></li>
|
||||
<li class="{{'/dvr'| sc_filter_nav_active}}"><a href="javascript:void(0)" ng-click="gogogo('/dvr')">DVR</a></li>
|
||||
<li><a href="javascript:void(0)" ng-click="redirect('en_index.html', 'ng_index.html')">Chinese</a></li>
|
||||
<li>
|
||||
<a href="https://github.com/ossrs/srs-console">
|
||||
<img alt="GitHub Repo stars" src="https://img.shields.io/github/stars/ossrs/srs-console?style=social">
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container-fluid">
|
||||
<div ng-view></div>
|
||||
<div bravo-alert ng-repeat="log in logs" class="alert fade in {{log.level|sc_filter_log_level}}">
|
||||
<button type="button" class="close" data-dismiss="alert">×</button>
|
||||
<strong>{{log.level}}:</strong> {{log.msg}}
|
||||
</div>
|
||||
</div>
|
||||
<footer class="footer">
|
||||
<div class="container">
|
||||
<ul class="footer-links">
|
||||
<li>© SRS 2020</li>
|
||||
<li class="muted">|</li>
|
||||
<li><a href="http://ossrs.net/" target="_blank">Releases</a></li>
|
||||
<li class="muted">|</li>
|
||||
<li><a href="https://github.com/ossrs/srs" target="_blank">SRS</a></li>
|
||||
<li class="muted">|</li>
|
||||
<li><a href="https://github.com/ossrs/srs-console" target="_blank">Github</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
|
12
trunk/research/console/index.html
Normal file
12
trunk/research/console/index.html
Normal file
|
@ -0,0 +1,12 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<title>SrsConsole</title>
|
||||
<script type="text/javascript">
|
||||
window.location.href = "ng_index.html#/summaries?port=1985";
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
610
trunk/research/console/js/3rdparty/angular-resource.js
vendored
Normal file
610
trunk/research/console/js/3rdparty/angular-resource.js
vendored
Normal file
|
@ -0,0 +1,610 @@
|
|||
/**
|
||||
* @license AngularJS v1.2.17
|
||||
* (c) 2010-2014 Google, Inc. http://angularjs.org
|
||||
* License: MIT
|
||||
*/
|
||||
(function(window, angular, undefined) {'use strict';
|
||||
|
||||
var $resourceMinErr = angular.$$minErr('$resource');
|
||||
|
||||
// Helper functions and regex to lookup a dotted path on an object
|
||||
// stopping at undefined/null. The path must be composed of ASCII
|
||||
// identifiers (just like $parse)
|
||||
var MEMBER_NAME_REGEX = /^(\.[a-zA-Z_$][0-9a-zA-Z_$]*)+$/;
|
||||
|
||||
function isValidDottedPath(path) {
|
||||
return (path != null && path !== '' && path !== 'hasOwnProperty' &&
|
||||
MEMBER_NAME_REGEX.test('.' + path));
|
||||
}
|
||||
|
||||
function lookupDottedPath(obj, path) {
|
||||
if (!isValidDottedPath(path)) {
|
||||
throw $resourceMinErr('badmember', 'Dotted member path "@{0}" is invalid.', path);
|
||||
}
|
||||
var keys = path.split('.');
|
||||
for (var i = 0, ii = keys.length; i < ii && obj !== undefined; i++) {
|
||||
var key = keys[i];
|
||||
obj = (obj !== null) ? obj[key] : undefined;
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a shallow copy of an object and clear other fields from the destination
|
||||
*/
|
||||
function shallowClearAndCopy(src, dst) {
|
||||
dst = dst || {};
|
||||
|
||||
angular.forEach(dst, function(value, key){
|
||||
delete dst[key];
|
||||
});
|
||||
|
||||
for (var key in src) {
|
||||
if (src.hasOwnProperty(key) && !(key.charAt(0) === '$' && key.charAt(1) === '$')) {
|
||||
dst[key] = src[key];
|
||||
}
|
||||
}
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ngdoc module
|
||||
* @name ngResource
|
||||
* @description
|
||||
*
|
||||
* # ngResource
|
||||
*
|
||||
* The `ngResource` module provides interaction support with RESTful services
|
||||
* via the $resource service.
|
||||
*
|
||||
*
|
||||
* <div doc-module-components="ngResource"></div>
|
||||
*
|
||||
* See {@link ngResource.$resource `$resource`} for usage.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ngdoc service
|
||||
* @name $resource
|
||||
* @requires $http
|
||||
*
|
||||
* @description
|
||||
* A factory which creates a resource object that lets you interact with
|
||||
* [RESTful](http://en.wikipedia.org/wiki/Representational_State_Transfer) server-side data sources.
|
||||
*
|
||||
* The returned resource object has action methods which provide high-level behaviors without
|
||||
* the need to interact with the low level {@link ng.$http $http} service.
|
||||
*
|
||||
* Requires the {@link ngResource `ngResource`} module to be installed.
|
||||
*
|
||||
* @param {string} url A parametrized URL template with parameters prefixed by `:` as in
|
||||
* `/user/:username`. If you are using a URL with a port number (e.g.
|
||||
* `http://example.com:8080/api`), it will be respected.
|
||||
*
|
||||
* If you are using a url with a suffix, just add the suffix, like this:
|
||||
* `$resource('http://example.com/resource.json')` or `$resource('http://example.com/:id.json')`
|
||||
* or even `$resource('http://example.com/resource/:resource_id.:format')`
|
||||
* If the parameter before the suffix is empty, :resource_id in this case, then the `/.` will be
|
||||
* collapsed down to a single `.`. If you need this sequence to appear and not collapse then you
|
||||
* can escape it with `/\.`.
|
||||
*
|
||||
* @param {Object=} paramDefaults Default values for `url` parameters. These can be overridden in
|
||||
* `actions` methods. If any of the parameter value is a function, it will be executed every time
|
||||
* when a param value needs to be obtained for a request (unless the param was overridden).
|
||||
*
|
||||
* Each key value in the parameter object is first bound to url template if present and then any
|
||||
* excess keys are appended to the url search query after the `?`.
|
||||
*
|
||||
* Given a template `/path/:verb` and parameter `{verb:'greet', salutation:'Hello'}` results in
|
||||
* URL `/path/greet?salutation=Hello`.
|
||||
*
|
||||
* If the parameter value is prefixed with `@` then the value of that parameter will be taken
|
||||
* from the corresponding key on the data object (useful for non-GET operations).
|
||||
*
|
||||
* @param {Object.<Object>=} actions Hash with declaration of custom action that should extend
|
||||
* the default set of resource actions. The declaration should be created in the format of {@link
|
||||
* ng.$http#usage_parameters $http.config}:
|
||||
*
|
||||
* {action1: {method:?, params:?, isArray:?, headers:?, ...},
|
||||
* action2: {method:?, params:?, isArray:?, headers:?, ...},
|
||||
* ...}
|
||||
*
|
||||
* Where:
|
||||
*
|
||||
* - **`action`** – {string} – The name of action. This name becomes the name of the method on
|
||||
* your resource object.
|
||||
* - **`method`** – {string} – HTTP request method. Valid methods are: `GET`, `POST`, `PUT`,
|
||||
* `DELETE`, and `JSONP`.
|
||||
* - **`params`** – {Object=} – Optional set of pre-bound parameters for this action. If any of
|
||||
* the parameter value is a function, it will be executed every time when a param value needs to
|
||||
* be obtained for a request (unless the param was overridden).
|
||||
* - **`url`** – {string} – action specific `url` override. The url templating is supported just
|
||||
* like for the resource-level urls.
|
||||
* - **`isArray`** – {boolean=} – If true then the returned object for this action is an array,
|
||||
* see `returns` section.
|
||||
* - **`transformRequest`** –
|
||||
* `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –
|
||||
* transform function or an array of such functions. The transform function takes the http
|
||||
* request body and headers and returns its transformed (typically serialized) version.
|
||||
* - **`transformResponse`** –
|
||||
* `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –
|
||||
* transform function or an array of such functions. The transform function takes the http
|
||||
* response body and headers and returns its transformed (typically deserialized) version.
|
||||
* - **`cache`** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the
|
||||
* GET request, otherwise if a cache instance built with
|
||||
* {@link ng.$cacheFactory $cacheFactory}, this cache will be used for
|
||||
* caching.
|
||||
* - **`timeout`** – `{number|Promise}` – timeout in milliseconds, or {@link ng.$q promise} that
|
||||
* should abort the request when resolved.
|
||||
* - **`withCredentials`** - `{boolean}` - whether to set the `withCredentials` flag on the
|
||||
* XHR object. See
|
||||
* [requests with credentials](https://developer.mozilla.org/en/http_access_control#section_5)
|
||||
* for more information.
|
||||
* - **`responseType`** - `{string}` - see
|
||||
* [requestType](https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType).
|
||||
* - **`interceptor`** - `{Object=}` - The interceptor object has two optional methods -
|
||||
* `response` and `responseError`. Both `response` and `responseError` interceptors get called
|
||||
* with `http response` object. See {@link ng.$http $http interceptors}.
|
||||
*
|
||||
* @returns {Object} A resource "class" object with methods for the default set of resource actions
|
||||
* optionally extended with custom `actions`. The default set contains these actions:
|
||||
* ```js
|
||||
* { 'get': {method:'GET'},
|
||||
* 'save': {method:'POST'},
|
||||
* 'query': {method:'GET', isArray:true},
|
||||
* 'remove': {method:'DELETE'},
|
||||
* 'delete': {method:'DELETE'} };
|
||||
* ```
|
||||
*
|
||||
* Calling these methods invoke an {@link ng.$http} with the specified http method,
|
||||
* destination and parameters. When the data is returned from the server then the object is an
|
||||
* instance of the resource class. The actions `save`, `remove` and `delete` are available on it
|
||||
* as methods with the `$` prefix. This allows you to easily perform CRUD operations (create,
|
||||
* read, update, delete) on server-side data like this:
|
||||
* ```js
|
||||
* var User = $resource('/user/:userId', {userId:'@id'});
|
||||
* var user = User.get({userId:123}, function() {
|
||||
* user.abc = true;
|
||||
* user.$save();
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* It is important to realize that invoking a $resource object method immediately returns an
|
||||
* empty reference (object or array depending on `isArray`). Once the data is returned from the
|
||||
* server the existing reference is populated with the actual data. This is a useful trick since
|
||||
* usually the resource is assigned to a model which is then rendered by the view. Having an empty
|
||||
* object results in no rendering, once the data arrives from the server then the object is
|
||||
* populated with the data and the view automatically re-renders itself showing the new data. This
|
||||
* means that in most cases one never has to write a callback function for the action methods.
|
||||
*
|
||||
* The action methods on the class object or instance object can be invoked with the following
|
||||
* parameters:
|
||||
*
|
||||
* - HTTP GET "class" actions: `Resource.action([parameters], [success], [error])`
|
||||
* - non-GET "class" actions: `Resource.action([parameters], postData, [success], [error])`
|
||||
* - non-GET instance actions: `instance.$action([parameters], [success], [error])`
|
||||
*
|
||||
* Success callback is called with (value, responseHeaders) arguments. Error callback is called
|
||||
* with (httpResponse) argument.
|
||||
*
|
||||
* Class actions return empty instance (with additional properties below).
|
||||
* Instance actions return promise of the action.
|
||||
*
|
||||
* The Resource instances and collection have these additional properties:
|
||||
*
|
||||
* - `$promise`: the {@link ng.$q promise} of the original server interaction that created this
|
||||
* instance or collection.
|
||||
*
|
||||
* On success, the promise is resolved with the same resource instance or collection object,
|
||||
* updated with data from server. This makes it easy to use in
|
||||
* {@link ngRoute.$routeProvider resolve section of $routeProvider.when()} to defer view
|
||||
* rendering until the resource(s) are loaded.
|
||||
*
|
||||
* On failure, the promise is resolved with the {@link ng.$http http response} object, without
|
||||
* the `resource` property.
|
||||
*
|
||||
* If an interceptor object was provided, the promise will instead be resolved with the value
|
||||
* returned by the interceptor.
|
||||
*
|
||||
* - `$resolved`: `true` after first server interaction is completed (either with success or
|
||||
* rejection), `false` before that. Knowing if the Resource has been resolved is useful in
|
||||
* data-binding.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* # Credit card resource
|
||||
*
|
||||
* ```js
|
||||
// Define CreditCard class
|
||||
var CreditCard = $resource('/user/:userId/card/:cardId',
|
||||
{userId:123, cardId:'@id'}, {
|
||||
charge: {method:'POST', params:{charge:true}}
|
||||
});
|
||||
|
||||
// We can retrieve a collection from the server
|
||||
var cards = CreditCard.query(function() {
|
||||
// GET: /user/123/card
|
||||
// server returns: [ {id:456, number:'1234', name:'Smith'} ];
|
||||
|
||||
var card = cards[0];
|
||||
// each item is an instance of CreditCard
|
||||
expect(card instanceof CreditCard).toEqual(true);
|
||||
card.name = "J. Smith";
|
||||
// non GET methods are mapped onto the instances
|
||||
card.$save();
|
||||
// POST: /user/123/card/456 {id:456, number:'1234', name:'J. Smith'}
|
||||
// server returns: {id:456, number:'1234', name: 'J. Smith'};
|
||||
|
||||
// our custom method is mapped as well.
|
||||
card.$charge({amount:9.99});
|
||||
// POST: /user/123/card/456?amount=9.99&charge=true {id:456, number:'1234', name:'J. Smith'}
|
||||
});
|
||||
|
||||
// we can create an instance as well
|
||||
var newCard = new CreditCard({number:'0123'});
|
||||
newCard.name = "Mike Smith";
|
||||
newCard.$save();
|
||||
// POST: /user/123/card {number:'0123', name:'Mike Smith'}
|
||||
// server returns: {id:789, number:'0123', name: 'Mike Smith'};
|
||||
expect(newCard.id).toEqual(789);
|
||||
* ```
|
||||
*
|
||||
* The object returned from this function execution is a resource "class" which has "static" method
|
||||
* for each action in the definition.
|
||||
*
|
||||
* Calling these methods invoke `$http` on the `url` template with the given `method`, `params` and
|
||||
* `headers`.
|
||||
* When the data is returned from the server then the object is an instance of the resource type and
|
||||
* all of the non-GET methods are available with `$` prefix. This allows you to easily support CRUD
|
||||
* operations (create, read, update, delete) on server-side data.
|
||||
|
||||
```js
|
||||
var User = $resource('/user/:userId', {userId:'@id'});
|
||||
User.get({userId:123}, function(user) {
|
||||
user.abc = true;
|
||||
user.$save();
|
||||
});
|
||||
```
|
||||
*
|
||||
* It's worth noting that the success callback for `get`, `query` and other methods gets passed
|
||||
* in the response that came from the server as well as $http header getter function, so one
|
||||
* could rewrite the above example and get access to http headers as:
|
||||
*
|
||||
```js
|
||||
var User = $resource('/user/:userId', {userId:'@id'});
|
||||
User.get({userId:123}, function(u, getResponseHeaders){
|
||||
u.abc = true;
|
||||
u.$save(function(u, putResponseHeaders) {
|
||||
//u => saved user object
|
||||
//putResponseHeaders => $http header getter
|
||||
});
|
||||
});
|
||||
```
|
||||
*
|
||||
* You can also access the raw `$http` promise via the `$promise` property on the object returned
|
||||
*
|
||||
```
|
||||
var User = $resource('/user/:userId', {userId:'@id'});
|
||||
User.get({userId:123})
|
||||
.$promise.then(function(user) {
|
||||
$scope.user = user;
|
||||
});
|
||||
```
|
||||
|
||||
* # Creating a custom 'PUT' request
|
||||
* In this example we create a custom method on our resource to make a PUT request
|
||||
* ```js
|
||||
* var app = angular.module('app', ['ngResource', 'ngRoute']);
|
||||
*
|
||||
* // Some APIs expect a PUT request in the format URL/object/ID
|
||||
* // Here we are creating an 'update' method
|
||||
* app.factory('Notes', ['$resource', function($resource) {
|
||||
* return $resource('/notes/:id', null,
|
||||
* {
|
||||
* 'update': { method:'PUT' }
|
||||
* });
|
||||
* }]);
|
||||
*
|
||||
* // In our controller we get the ID from the URL using ngRoute and $routeParams
|
||||
* // We pass in $routeParams and our Notes factory along with $scope
|
||||
* app.controller('NotesCtrl', ['$scope', '$routeParams', 'Notes',
|
||||
function($scope, $routeParams, Notes) {
|
||||
* // First get a note object from the factory
|
||||
* var note = Notes.get({ id:$routeParams.id });
|
||||
* $id = note.id;
|
||||
*
|
||||
* // Now call update passing in the ID first then the object you are updating
|
||||
* Notes.update({ id:$id }, note);
|
||||
*
|
||||
* // This will PUT /notes/ID with the note object in the request payload
|
||||
* }]);
|
||||
* ```
|
||||
*/
|
||||
angular.module('ngResource', ['ng']).
|
||||
factory('$resource', ['$http', '$q', function($http, $q) {
|
||||
|
||||
var DEFAULT_ACTIONS = {
|
||||
'get': {method:'GET'},
|
||||
'save': {method:'POST'},
|
||||
'query': {method:'GET', isArray:true},
|
||||
'remove': {method:'DELETE'},
|
||||
'delete': {method:'DELETE'}
|
||||
};
|
||||
var noop = angular.noop,
|
||||
forEach = angular.forEach,
|
||||
extend = angular.extend,
|
||||
copy = angular.copy,
|
||||
isFunction = angular.isFunction;
|
||||
|
||||
/**
|
||||
* We need our custom method because encodeURIComponent is too aggressive and doesn't follow
|
||||
* http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path
|
||||
* segments:
|
||||
* segment = *pchar
|
||||
* pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
|
||||
* pct-encoded = "%" HEXDIG HEXDIG
|
||||
* unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
|
||||
* sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
|
||||
* / "*" / "+" / "," / ";" / "="
|
||||
*/
|
||||
function encodeUriSegment(val) {
|
||||
return encodeUriQuery(val, true).
|
||||
replace(/%26/gi, '&').
|
||||
replace(/%3D/gi, '=').
|
||||
replace(/%2B/gi, '+');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method is intended for encoding *key* or *value* parts of query component. We need a
|
||||
* custom method because encodeURIComponent is too aggressive and encodes stuff that doesn't
|
||||
* have to be encoded per http://tools.ietf.org/html/rfc3986:
|
||||
* query = *( pchar / "/" / "?" )
|
||||
* pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
|
||||
* unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
|
||||
* pct-encoded = "%" HEXDIG HEXDIG
|
||||
* sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
|
||||
* / "*" / "+" / "," / ";" / "="
|
||||
*/
|
||||
function encodeUriQuery(val, pctEncodeSpaces) {
|
||||
return encodeURIComponent(val).
|
||||
replace(/%40/gi, '@').
|
||||
replace(/%3A/gi, ':').
|
||||
replace(/%24/g, '$').
|
||||
replace(/%2C/gi, ',').
|
||||
replace(/%20/g, (pctEncodeSpaces ? '%20' : '+'));
|
||||
}
|
||||
|
||||
function Route(template, defaults) {
|
||||
this.template = template;
|
||||
this.defaults = defaults || {};
|
||||
this.urlParams = {};
|
||||
}
|
||||
|
||||
Route.prototype = {
|
||||
setUrlParams: function(config, params, actionUrl) {
|
||||
var self = this,
|
||||
url = actionUrl || self.template,
|
||||
val,
|
||||
encodedVal;
|
||||
|
||||
var urlParams = self.urlParams = {};
|
||||
forEach(url.split(/\W/), function(param){
|
||||
if (param === 'hasOwnProperty') {
|
||||
throw $resourceMinErr('badname', "hasOwnProperty is not a valid parameter name.");
|
||||
}
|
||||
if (!(new RegExp("^\\d+$").test(param)) && param &&
|
||||
(new RegExp("(^|[^\\\\]):" + param + "(\\W|$)").test(url))) {
|
||||
urlParams[param] = true;
|
||||
}
|
||||
});
|
||||
url = url.replace(/\\:/g, ':');
|
||||
|
||||
params = params || {};
|
||||
forEach(self.urlParams, function(_, urlParam){
|
||||
val = params.hasOwnProperty(urlParam) ? params[urlParam] : self.defaults[urlParam];
|
||||
if (angular.isDefined(val) && val !== null) {
|
||||
encodedVal = encodeUriSegment(val);
|
||||
url = url.replace(new RegExp(":" + urlParam + "(\\W|$)", "g"), function(match, p1) {
|
||||
return encodedVal + p1;
|
||||
});
|
||||
} else {
|
||||
url = url.replace(new RegExp("(\/?):" + urlParam + "(\\W|$)", "g"), function(match,
|
||||
leadingSlashes, tail) {
|
||||
if (tail.charAt(0) == '/') {
|
||||
return tail;
|
||||
} else {
|
||||
return leadingSlashes + tail;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// strip trailing slashes and set the url
|
||||
url = url.replace(/\/+$/, '') || '/';
|
||||
// then replace collapse `/.` if found in the last URL path segment before the query
|
||||
// E.g. `http://url.com/id./format?q=x` becomes `http://url.com/id.format?q=x`
|
||||
url = url.replace(/\/\.(?=\w+($|\?))/, '.');
|
||||
// replace escaped `/\.` with `/.`
|
||||
config.url = url.replace(/\/\\\./, '/.');
|
||||
|
||||
|
||||
// set params - delegate param encoding to $http
|
||||
forEach(params, function(value, key){
|
||||
if (!self.urlParams[key]) {
|
||||
config.params = config.params || {};
|
||||
config.params[key] = value;
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
function resourceFactory(url, paramDefaults, actions) {
|
||||
var route = new Route(url);
|
||||
|
||||
actions = extend({}, DEFAULT_ACTIONS, actions);
|
||||
|
||||
function extractParams(data, actionParams){
|
||||
var ids = {};
|
||||
actionParams = extend({}, paramDefaults, actionParams);
|
||||
forEach(actionParams, function(value, key){
|
||||
if (isFunction(value)) { value = value(); }
|
||||
ids[key] = value && value.charAt && value.charAt(0) == '@' ?
|
||||
lookupDottedPath(data, value.substr(1)) : value;
|
||||
});
|
||||
return ids;
|
||||
}
|
||||
|
||||
function defaultResponseInterceptor(response) {
|
||||
return response.resource;
|
||||
}
|
||||
|
||||
function Resource(value){
|
||||
shallowClearAndCopy(value || {}, this);
|
||||
}
|
||||
|
||||
forEach(actions, function(action, name) {
|
||||
var hasBody = /^(POST|PUT|PATCH)$/i.test(action.method);
|
||||
|
||||
Resource[name] = function(a1, a2, a3, a4) {
|
||||
var params = {}, data, success, error;
|
||||
|
||||
/* jshint -W086 */ /* (purposefully fall through case statements) */
|
||||
switch(arguments.length) {
|
||||
case 4:
|
||||
error = a4;
|
||||
success = a3;
|
||||
//fallthrough
|
||||
case 3:
|
||||
case 2:
|
||||
if (isFunction(a2)) {
|
||||
if (isFunction(a1)) {
|
||||
success = a1;
|
||||
error = a2;
|
||||
break;
|
||||
}
|
||||
|
||||
success = a2;
|
||||
error = a3;
|
||||
//fallthrough
|
||||
} else {
|
||||
params = a1;
|
||||
data = a2;
|
||||
success = a3;
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
if (isFunction(a1)) success = a1;
|
||||
else if (hasBody) data = a1;
|
||||
else params = a1;
|
||||
break;
|
||||
case 0: break;
|
||||
default:
|
||||
throw $resourceMinErr('badargs',
|
||||
"Expected up to 4 arguments [params, data, success, error], got {0} arguments",
|
||||
arguments.length);
|
||||
}
|
||||
/* jshint +W086 */ /* (purposefully fall through case statements) */
|
||||
|
||||
var isInstanceCall = this instanceof Resource;
|
||||
var value = isInstanceCall ? data : (action.isArray ? [] : new Resource(data));
|
||||
var httpConfig = {};
|
||||
var responseInterceptor = action.interceptor && action.interceptor.response ||
|
||||
defaultResponseInterceptor;
|
||||
var responseErrorInterceptor = action.interceptor && action.interceptor.responseError ||
|
||||
undefined;
|
||||
|
||||
forEach(action, function(value, key) {
|
||||
if (key != 'params' && key != 'isArray' && key != 'interceptor') {
|
||||
httpConfig[key] = copy(value);
|
||||
}
|
||||
});
|
||||
|
||||
if (hasBody) httpConfig.data = data;
|
||||
route.setUrlParams(httpConfig,
|
||||
extend({}, extractParams(data, action.params || {}), params),
|
||||
action.url);
|
||||
|
||||
var promise = $http(httpConfig).then(function(response) {
|
||||
var data = response.data,
|
||||
promise = value.$promise;
|
||||
|
||||
if (data) {
|
||||
// Need to convert action.isArray to boolean in case it is undefined
|
||||
// jshint -W018
|
||||
if (angular.isArray(data) !== (!!action.isArray)) {
|
||||
throw $resourceMinErr('badcfg', 'Error in resource configuration. Expected ' +
|
||||
'response to contain an {0} but got an {1}',
|
||||
action.isArray?'array':'object', angular.isArray(data)?'array':'object');
|
||||
}
|
||||
// jshint +W018
|
||||
if (action.isArray) {
|
||||
value.length = 0;
|
||||
forEach(data, function(item) {
|
||||
value.push(new Resource(item));
|
||||
});
|
||||
} else {
|
||||
shallowClearAndCopy(data, value);
|
||||
value.$promise = promise;
|
||||
}
|
||||
}
|
||||
|
||||
value.$resolved = true;
|
||||
|
||||
response.resource = value;
|
||||
|
||||
return response;
|
||||
}, function(response) {
|
||||
value.$resolved = true;
|
||||
|
||||
(error||noop)(response);
|
||||
|
||||
return $q.reject(response);
|
||||
});
|
||||
|
||||
promise = promise.then(
|
||||
function(response) {
|
||||
var value = responseInterceptor(response);
|
||||
(success||noop)(value, response.headers);
|
||||
return value;
|
||||
},
|
||||
responseErrorInterceptor);
|
||||
|
||||
if (!isInstanceCall) {
|
||||
// we are creating instance / collection
|
||||
// - set the initial promise
|
||||
// - return the instance / collection
|
||||
value.$promise = promise;
|
||||
value.$resolved = false;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
// instance call
|
||||
return promise;
|
||||
};
|
||||
|
||||
|
||||
Resource.prototype['$' + name] = function(params, success, error) {
|
||||
if (isFunction(params)) {
|
||||
error = success; success = params; params = {};
|
||||
}
|
||||
var result = Resource[name].call(this, params, this, success, error);
|
||||
return result.$promise || result;
|
||||
};
|
||||
});
|
||||
|
||||
Resource.bind = function(additionalParamDefaults){
|
||||
return resourceFactory(url, extend({}, paramDefaults, additionalParamDefaults), actions);
|
||||
};
|
||||
|
||||
return Resource;
|
||||
}
|
||||
|
||||
return resourceFactory;
|
||||
}]);
|
||||
|
||||
|
||||
})(window, window.angular);
|
13
trunk/research/console/js/3rdparty/angular-resource.min.js
vendored
Normal file
13
trunk/research/console/js/3rdparty/angular-resource.min.js
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
/*
|
||||
AngularJS v1.2.17
|
||||
(c) 2010-2014 Google, Inc. http://angularjs.org
|
||||
License: MIT
|
||||
*/
|
||||
(function(H,a,A){'use strict';function D(p,g){g=g||{};a.forEach(g,function(a,c){delete g[c]});for(var c in p)!p.hasOwnProperty(c)||"$"===c.charAt(0)&&"$"===c.charAt(1)||(g[c]=p[c]);return g}var v=a.$$minErr("$resource"),C=/^(\.[a-zA-Z_$][0-9a-zA-Z_$]*)+$/;a.module("ngResource",["ng"]).factory("$resource",["$http","$q",function(p,g){function c(a,c){this.template=a;this.defaults=c||{};this.urlParams={}}function t(n,w,l){function r(h,d){var e={};d=x({},w,d);s(d,function(b,d){u(b)&&(b=b());var k;if(b&&
|
||||
b.charAt&&"@"==b.charAt(0)){k=h;var a=b.substr(1);if(null==a||""===a||"hasOwnProperty"===a||!C.test("."+a))throw v("badmember",a);for(var a=a.split("."),f=0,c=a.length;f<c&&k!==A;f++){var g=a[f];k=null!==k?k[g]:A}}else k=b;e[d]=k});return e}function e(a){return a.resource}function f(a){D(a||{},this)}var F=new c(n);l=x({},B,l);s(l,function(h,d){var c=/^(POST|PUT|PATCH)$/i.test(h.method);f[d]=function(b,d,k,w){var q={},n,l,y;switch(arguments.length){case 4:y=w,l=k;case 3:case 2:if(u(d)){if(u(b)){l=
|
||||
b;y=d;break}l=d;y=k}else{q=b;n=d;l=k;break}case 1:u(b)?l=b:c?n=b:q=b;break;case 0:break;default:throw v("badargs",arguments.length);}var t=this instanceof f,m=t?n:h.isArray?[]:new f(n),z={},B=h.interceptor&&h.interceptor.response||e,C=h.interceptor&&h.interceptor.responseError||A;s(h,function(a,b){"params"!=b&&("isArray"!=b&&"interceptor"!=b)&&(z[b]=G(a))});c&&(z.data=n);F.setUrlParams(z,x({},r(n,h.params||{}),q),h.url);q=p(z).then(function(b){var d=b.data,k=m.$promise;if(d){if(a.isArray(d)!==!!h.isArray)throw v("badcfg",
|
||||
h.isArray?"array":"object",a.isArray(d)?"array":"object");h.isArray?(m.length=0,s(d,function(b){m.push(new f(b))})):(D(d,m),m.$promise=k)}m.$resolved=!0;b.resource=m;return b},function(b){m.$resolved=!0;(y||E)(b);return g.reject(b)});q=q.then(function(b){var a=B(b);(l||E)(a,b.headers);return a},C);return t?q:(m.$promise=q,m.$resolved=!1,m)};f.prototype["$"+d]=function(b,a,k){u(b)&&(k=a,a=b,b={});b=f[d].call(this,b,this,a,k);return b.$promise||b}});f.bind=function(a){return t(n,x({},w,a),l)};return f}
|
||||
var B={get:{method:"GET"},save:{method:"POST"},query:{method:"GET",isArray:!0},remove:{method:"DELETE"},"delete":{method:"DELETE"}},E=a.noop,s=a.forEach,x=a.extend,G=a.copy,u=a.isFunction;c.prototype={setUrlParams:function(c,g,l){var r=this,e=l||r.template,f,p,h=r.urlParams={};s(e.split(/\W/),function(a){if("hasOwnProperty"===a)throw v("badname");!/^\d+$/.test(a)&&(a&&RegExp("(^|[^\\\\]):"+a+"(\\W|$)").test(e))&&(h[a]=!0)});e=e.replace(/\\:/g,":");g=g||{};s(r.urlParams,function(d,c){f=g.hasOwnProperty(c)?
|
||||
g[c]:r.defaults[c];a.isDefined(f)&&null!==f?(p=encodeURIComponent(f).replace(/%40/gi,"@").replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,"%20").replace(/%26/gi,"&").replace(/%3D/gi,"=").replace(/%2B/gi,"+"),e=e.replace(RegExp(":"+c+"(\\W|$)","g"),function(a,c){return p+c})):e=e.replace(RegExp("(/?):"+c+"(\\W|$)","g"),function(a,c,d){return"/"==d.charAt(0)?d:c+d})});e=e.replace(/\/+$/,"")||"/";e=e.replace(/\/\.(?=\w+($|\?))/,".");c.url=e.replace(/\/\\\./,"/.");s(g,function(a,
|
||||
e){r.urlParams[e]||(c.params=c.params||{},c.params[e]=a)})}};return t}])})(window,window.angular);
|
||||
//# sourceMappingURL=angular-resource.min.js.map
|
8
trunk/research/console/js/3rdparty/angular-resource.min.js.map
vendored
Normal file
8
trunk/research/console/js/3rdparty/angular-resource.min.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
927
trunk/research/console/js/3rdparty/angular-route.js
vendored
Normal file
927
trunk/research/console/js/3rdparty/angular-route.js
vendored
Normal file
|
@ -0,0 +1,927 @@
|
|||
/**
|
||||
* @license AngularJS v1.2.17
|
||||
* (c) 2010-2014 Google, Inc. http://angularjs.org
|
||||
* License: MIT
|
||||
*/
|
||||
(function(window, angular, undefined) {'use strict';
|
||||
|
||||
/**
|
||||
* @ngdoc module
|
||||
* @name ngRoute
|
||||
* @description
|
||||
*
|
||||
* # ngRoute
|
||||
*
|
||||
* The `ngRoute` module provides routing and deeplinking services and directives for angular apps.
|
||||
*
|
||||
* ## Example
|
||||
* See {@link ngRoute.$route#example $route} for an example of configuring and using `ngRoute`.
|
||||
*
|
||||
*
|
||||
* <div doc-module-components="ngRoute"></div>
|
||||
*/
|
||||
/* global -ngRouteModule */
|
||||
var ngRouteModule = angular.module('ngRoute', ['ng']).
|
||||
provider('$route', $RouteProvider);
|
||||
|
||||
/**
|
||||
* @ngdoc provider
|
||||
* @name $routeProvider
|
||||
* @kind function
|
||||
*
|
||||
* @description
|
||||
*
|
||||
* Used for configuring routes.
|
||||
*
|
||||
* ## Example
|
||||
* See {@link ngRoute.$route#example $route} for an example of configuring and using `ngRoute`.
|
||||
*
|
||||
* ## Dependencies
|
||||
* Requires the {@link ngRoute `ngRoute`} module to be installed.
|
||||
*/
|
||||
function $RouteProvider(){
|
||||
function inherit(parent, extra) {
|
||||
return angular.extend(new (angular.extend(function() {}, {prototype:parent}))(), extra);
|
||||
}
|
||||
|
||||
var routes = {};
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name $routeProvider#when
|
||||
*
|
||||
* @param {string} path Route path (matched against `$location.path`). If `$location.path`
|
||||
* contains redundant trailing slash or is missing one, the route will still match and the
|
||||
* `$location.path` will be updated to add or drop the trailing slash to exactly match the
|
||||
* route definition.
|
||||
*
|
||||
* * `path` can contain named groups starting with a colon: e.g. `:name`. All characters up
|
||||
* to the next slash are matched and stored in `$routeParams` under the given `name`
|
||||
* when the route matches.
|
||||
* * `path` can contain named groups starting with a colon and ending with a star:
|
||||
* e.g.`:name*`. All characters are eagerly stored in `$routeParams` under the given `name`
|
||||
* when the route matches.
|
||||
* * `path` can contain optional named groups with a question mark: e.g.`:name?`.
|
||||
*
|
||||
* For example, routes like `/color/:color/largecode/:largecode*\/edit` will match
|
||||
* `/color/brown/largecode/code/with/slashes/edit` and extract:
|
||||
*
|
||||
* * `color: brown`
|
||||
* * `largecode: code/with/slashes`.
|
||||
*
|
||||
*
|
||||
* @param {Object} route Mapping information to be assigned to `$route.current` on route
|
||||
* match.
|
||||
*
|
||||
* Object properties:
|
||||
*
|
||||
* - `controller` – `{(string|function()=}` – Controller fn that should be associated with
|
||||
* newly created scope or the name of a {@link angular.Module#controller registered
|
||||
* controller} if passed as a string.
|
||||
* - `controllerAs` – `{string=}` – A controller alias name. If present the controller will be
|
||||
* published to scope under the `controllerAs` name.
|
||||
* - `template` – `{string=|function()=}` – html template as a string or a function that
|
||||
* returns an html template as a string which should be used by {@link
|
||||
* ngRoute.directive:ngView ngView} or {@link ng.directive:ngInclude ngInclude} directives.
|
||||
* This property takes precedence over `templateUrl`.
|
||||
*
|
||||
* If `template` is a function, it will be called with the following parameters:
|
||||
*
|
||||
* - `{Array.<Object>}` - route parameters extracted from the current
|
||||
* `$location.path()` by applying the current route
|
||||
*
|
||||
* - `templateUrl` – `{string=|function()=}` – path or function that returns a path to an html
|
||||
* template that should be used by {@link ngRoute.directive:ngView ngView}.
|
||||
*
|
||||
* If `templateUrl` is a function, it will be called with the following parameters:
|
||||
*
|
||||
* - `{Array.<Object>}` - route parameters extracted from the current
|
||||
* `$location.path()` by applying the current route
|
||||
*
|
||||
* - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should
|
||||
* be injected into the controller. If any of these dependencies are promises, the router
|
||||
* will wait for them all to be resolved or one to be rejected before the controller is
|
||||
* instantiated.
|
||||
* If all the promises are resolved successfully, the values of the resolved promises are
|
||||
* injected and {@link ngRoute.$route#$routeChangeSuccess $routeChangeSuccess} event is
|
||||
* fired. If any of the promises are rejected the
|
||||
* {@link ngRoute.$route#$routeChangeError $routeChangeError} event is fired. The map object
|
||||
* is:
|
||||
*
|
||||
* - `key` – `{string}`: a name of a dependency to be injected into the controller.
|
||||
* - `factory` - `{string|function}`: If `string` then it is an alias for a service.
|
||||
* Otherwise if function, then it is {@link auto.$injector#invoke injected}
|
||||
* and the return value is treated as the dependency. If the result is a promise, it is
|
||||
* resolved before its value is injected into the controller. Be aware that
|
||||
* `ngRoute.$routeParams` will still refer to the previous route within these resolve
|
||||
* functions. Use `$route.current.params` to access the new route parameters, instead.
|
||||
*
|
||||
* - `redirectTo` – {(string|function())=} – value to update
|
||||
* {@link ng.$location $location} path with and trigger route redirection.
|
||||
*
|
||||
* If `redirectTo` is a function, it will be called with the following parameters:
|
||||
*
|
||||
* - `{Object.<string>}` - route parameters extracted from the current
|
||||
* `$location.path()` by applying the current route templateUrl.
|
||||
* - `{string}` - current `$location.path()`
|
||||
* - `{Object}` - current `$location.search()`
|
||||
*
|
||||
* The custom `redirectTo` function is expected to return a string which will be used
|
||||
* to update `$location.path()` and `$location.search()`.
|
||||
*
|
||||
* - `[reloadOnSearch=true]` - {boolean=} - reload route when only `$location.search()`
|
||||
* or `$location.hash()` changes.
|
||||
*
|
||||
* If the option is set to `false` and url in the browser changes, then
|
||||
* `$routeUpdate` event is broadcasted on the root scope.
|
||||
*
|
||||
* - `[caseInsensitiveMatch=false]` - {boolean=} - match routes without being case sensitive
|
||||
*
|
||||
* If the option is set to `true`, then the particular route can be matched without being
|
||||
* case sensitive
|
||||
*
|
||||
* @returns {Object} self
|
||||
*
|
||||
* @description
|
||||
* Adds a new route definition to the `$route` service.
|
||||
*/
|
||||
this.when = function(path, route) {
|
||||
routes[path] = angular.extend(
|
||||
{reloadOnSearch: true},
|
||||
route,
|
||||
path && pathRegExp(path, route)
|
||||
);
|
||||
|
||||
// create redirection for trailing slashes
|
||||
if (path) {
|
||||
var redirectPath = (path[path.length-1] == '/')
|
||||
? path.substr(0, path.length-1)
|
||||
: path +'/';
|
||||
|
||||
routes[redirectPath] = angular.extend(
|
||||
{redirectTo: path},
|
||||
pathRegExp(redirectPath, route)
|
||||
);
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param path {string} path
|
||||
* @param opts {Object} options
|
||||
* @return {?Object}
|
||||
*
|
||||
* @description
|
||||
* Normalizes the given path, returning a regular expression
|
||||
* and the original path.
|
||||
*
|
||||
* Inspired by pathRexp in visionmedia/express/lib/utils.js.
|
||||
*/
|
||||
function pathRegExp(path, opts) {
|
||||
var insensitive = opts.caseInsensitiveMatch,
|
||||
ret = {
|
||||
originalPath: path,
|
||||
regexp: path
|
||||
},
|
||||
keys = ret.keys = [];
|
||||
|
||||
path = path
|
||||
.replace(/([().])/g, '\\$1')
|
||||
.replace(/(\/)?:(\w+)([\?\*])?/g, function(_, slash, key, option){
|
||||
var optional = option === '?' ? option : null;
|
||||
var star = option === '*' ? option : null;
|
||||
keys.push({ name: key, optional: !!optional });
|
||||
slash = slash || '';
|
||||
return ''
|
||||
+ (optional ? '' : slash)
|
||||
+ '(?:'
|
||||
+ (optional ? slash : '')
|
||||
+ (star && '(.+?)' || '([^/]+)')
|
||||
+ (optional || '')
|
||||
+ ')'
|
||||
+ (optional || '');
|
||||
})
|
||||
.replace(/([\/$\*])/g, '\\$1');
|
||||
|
||||
ret.regexp = new RegExp('^' + path + '$', insensitive ? 'i' : '');
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name $routeProvider#otherwise
|
||||
*
|
||||
* @description
|
||||
* Sets route definition that will be used on route change when no other route definition
|
||||
* is matched.
|
||||
*
|
||||
* @param {Object} params Mapping information to be assigned to `$route.current`.
|
||||
* @returns {Object} self
|
||||
*/
|
||||
this.otherwise = function(params) {
|
||||
this.when(null, params);
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
this.$get = ['$rootScope',
|
||||
'$location',
|
||||
'$routeParams',
|
||||
'$q',
|
||||
'$injector',
|
||||
'$http',
|
||||
'$templateCache',
|
||||
'$sce',
|
||||
function($rootScope, $location, $routeParams, $q, $injector, $http, $templateCache, $sce) {
|
||||
|
||||
/**
|
||||
* @ngdoc service
|
||||
* @name $route
|
||||
* @requires $location
|
||||
* @requires $routeParams
|
||||
*
|
||||
* @property {Object} current Reference to the current route definition.
|
||||
* The route definition contains:
|
||||
*
|
||||
* - `controller`: The controller constructor as define in route definition.
|
||||
* - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for
|
||||
* controller instantiation. The `locals` contain
|
||||
* the resolved values of the `resolve` map. Additionally the `locals` also contain:
|
||||
*
|
||||
* - `$scope` - The current route scope.
|
||||
* - `$template` - The current route template HTML.
|
||||
*
|
||||
* @property {Object} routes Object with all route configuration Objects as its properties.
|
||||
*
|
||||
* @description
|
||||
* `$route` is used for deep-linking URLs to controllers and views (HTML partials).
|
||||
* It watches `$location.url()` and tries to map the path to an existing route definition.
|
||||
*
|
||||
* Requires the {@link ngRoute `ngRoute`} module to be installed.
|
||||
*
|
||||
* You can define routes through {@link ngRoute.$routeProvider $routeProvider}'s API.
|
||||
*
|
||||
* The `$route` service is typically used in conjunction with the
|
||||
* {@link ngRoute.directive:ngView `ngView`} directive and the
|
||||
* {@link ngRoute.$routeParams `$routeParams`} service.
|
||||
*
|
||||
* @example
|
||||
* This example shows how changing the URL hash causes the `$route` to match a route against the
|
||||
* URL, and the `ngView` pulls in the partial.
|
||||
*
|
||||
* Note that this example is using {@link ng.directive:script inlined templates}
|
||||
* to get it working on jsfiddle as well.
|
||||
*
|
||||
* <example name="$route-service" module="ngRouteExample"
|
||||
* deps="angular-route.js" fixBase="true">
|
||||
* <file name="index.html">
|
||||
* <div ng-controller="MainController">
|
||||
* Choose:
|
||||
* <a href="Book/Moby">Moby</a> |
|
||||
* <a href="Book/Moby/ch/1">Moby: Ch1</a> |
|
||||
* <a href="Book/Gatsby">Gatsby</a> |
|
||||
* <a href="Book/Gatsby/ch/4?key=value">Gatsby: Ch4</a> |
|
||||
* <a href="Book/Scarlet">Scarlet Letter</a><br/>
|
||||
*
|
||||
* <div ng-view></div>
|
||||
*
|
||||
* <hr />
|
||||
*
|
||||
* <pre>$location.path() = {{$location.path()}}</pre>
|
||||
* <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>
|
||||
* <pre>$route.current.params = {{$route.current.params}}</pre>
|
||||
* <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>
|
||||
* <pre>$routeParams = {{$routeParams}}</pre>
|
||||
* </div>
|
||||
* </file>
|
||||
*
|
||||
* <file name="book.html">
|
||||
* controller: {{name}}<br />
|
||||
* Book Id: {{params.bookId}}<br />
|
||||
* </file>
|
||||
*
|
||||
* <file name="chapter.html">
|
||||
* controller: {{name}}<br />
|
||||
* Book Id: {{params.bookId}}<br />
|
||||
* Chapter Id: {{params.chapterId}}
|
||||
* </file>
|
||||
*
|
||||
* <file name="script.js">
|
||||
* angular.module('ngRouteExample', ['ngRoute'])
|
||||
*
|
||||
* .controller('MainController', function($scope, $route, $routeParams, $location) {
|
||||
* $scope.$route = $route;
|
||||
* $scope.$location = $location;
|
||||
* $scope.$routeParams = $routeParams;
|
||||
* })
|
||||
*
|
||||
* .controller('BookController', function($scope, $routeParams) {
|
||||
* $scope.name = "BookController";
|
||||
* $scope.params = $routeParams;
|
||||
* })
|
||||
*
|
||||
* .controller('ChapterController', function($scope, $routeParams) {
|
||||
* $scope.name = "ChapterController";
|
||||
* $scope.params = $routeParams;
|
||||
* })
|
||||
*
|
||||
* .config(function($routeProvider, $locationProvider) {
|
||||
* $routeProvider
|
||||
* .when('/Book/:bookId', {
|
||||
* templateUrl: 'book.html',
|
||||
* controller: 'BookController',
|
||||
* resolve: {
|
||||
* // I will cause a 1 second delay
|
||||
* delay: function($q, $timeout) {
|
||||
* var delay = $q.defer();
|
||||
* $timeout(delay.resolve, 1000);
|
||||
* return delay.promise;
|
||||
* }
|
||||
* }
|
||||
* })
|
||||
* .when('/Book/:bookId/ch/:chapterId', {
|
||||
* templateUrl: 'chapter.html',
|
||||
* controller: 'ChapterController'
|
||||
* });
|
||||
*
|
||||
* // configure html5 to get links working on jsfiddle
|
||||
* $locationProvider.html5Mode(true);
|
||||
* });
|
||||
*
|
||||
* </file>
|
||||
*
|
||||
* <file name="protractor.js" type="protractor">
|
||||
* it('should load and compile correct template', function() {
|
||||
* element(by.linkText('Moby: Ch1')).click();
|
||||
* var content = element(by.css('[ng-view]')).getText();
|
||||
* expect(content).toMatch(/controller\: ChapterController/);
|
||||
* expect(content).toMatch(/Book Id\: Moby/);
|
||||
* expect(content).toMatch(/Chapter Id\: 1/);
|
||||
*
|
||||
* element(by.partialLinkText('Scarlet')).click();
|
||||
*
|
||||
* content = element(by.css('[ng-view]')).getText();
|
||||
* expect(content).toMatch(/controller\: BookController/);
|
||||
* expect(content).toMatch(/Book Id\: Scarlet/);
|
||||
* });
|
||||
* </file>
|
||||
* </example>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ngdoc event
|
||||
* @name $route#$routeChangeStart
|
||||
* @eventType broadcast on root scope
|
||||
* @description
|
||||
* Broadcasted before a route change. At this point the route services starts
|
||||
* resolving all of the dependencies needed for the route change to occur.
|
||||
* Typically this involves fetching the view template as well as any dependencies
|
||||
* defined in `resolve` route property. Once all of the dependencies are resolved
|
||||
* `$routeChangeSuccess` is fired.
|
||||
*
|
||||
* @param {Object} angularEvent Synthetic event object.
|
||||
* @param {Route} next Future route information.
|
||||
* @param {Route} current Current route information.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ngdoc event
|
||||
* @name $route#$routeChangeSuccess
|
||||
* @eventType broadcast on root scope
|
||||
* @description
|
||||
* Broadcasted after a route dependencies are resolved.
|
||||
* {@link ngRoute.directive:ngView ngView} listens for the directive
|
||||
* to instantiate the controller and render the view.
|
||||
*
|
||||
* @param {Object} angularEvent Synthetic event object.
|
||||
* @param {Route} current Current route information.
|
||||
* @param {Route|Undefined} previous Previous route information, or undefined if current is
|
||||
* first route entered.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ngdoc event
|
||||
* @name $route#$routeChangeError
|
||||
* @eventType broadcast on root scope
|
||||
* @description
|
||||
* Broadcasted if any of the resolve promises are rejected.
|
||||
*
|
||||
* @param {Object} angularEvent Synthetic event object
|
||||
* @param {Route} current Current route information.
|
||||
* @param {Route} previous Previous route information.
|
||||
* @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ngdoc event
|
||||
* @name $route#$routeUpdate
|
||||
* @eventType broadcast on root scope
|
||||
* @description
|
||||
*
|
||||
* The `reloadOnSearch` property has been set to false, and we are reusing the same
|
||||
* instance of the Controller.
|
||||
*/
|
||||
|
||||
var forceReload = false,
|
||||
$route = {
|
||||
routes: routes,
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name $route#reload
|
||||
*
|
||||
* @description
|
||||
* Causes `$route` service to reload the current route even if
|
||||
* {@link ng.$location $location} hasn't changed.
|
||||
*
|
||||
* As a result of that, {@link ngRoute.directive:ngView ngView}
|
||||
* creates new scope, reinstantiates the controller.
|
||||
*/
|
||||
reload: function() {
|
||||
forceReload = true;
|
||||
$rootScope.$evalAsync(updateRoute);
|
||||
}
|
||||
};
|
||||
|
||||
$rootScope.$on('$locationChangeSuccess', updateRoute);
|
||||
|
||||
return $route;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* @param on {string} current url
|
||||
* @param route {Object} route regexp to match the url against
|
||||
* @return {?Object}
|
||||
*
|
||||
* @description
|
||||
* Check if the route matches the current url.
|
||||
*
|
||||
* Inspired by match in
|
||||
* visionmedia/express/lib/router/router.js.
|
||||
*/
|
||||
function switchRouteMatcher(on, route) {
|
||||
var keys = route.keys,
|
||||
params = {};
|
||||
|
||||
if (!route.regexp) return null;
|
||||
|
||||
var m = route.regexp.exec(on);
|
||||
if (!m) return null;
|
||||
|
||||
for (var i = 1, len = m.length; i < len; ++i) {
|
||||
var key = keys[i - 1];
|
||||
|
||||
var val = 'string' == typeof m[i]
|
||||
? decodeURIComponent(m[i])
|
||||
: m[i];
|
||||
|
||||
if (key && val) {
|
||||
params[key.name] = val;
|
||||
}
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
function updateRoute() {
|
||||
var next = parseRoute(),
|
||||
last = $route.current;
|
||||
|
||||
if (next && last && next.$$route === last.$$route
|
||||
&& angular.equals(next.pathParams, last.pathParams)
|
||||
&& !next.reloadOnSearch && !forceReload) {
|
||||
last.params = next.params;
|
||||
angular.copy(last.params, $routeParams);
|
||||
$rootScope.$broadcast('$routeUpdate', last);
|
||||
} else if (next || last) {
|
||||
forceReload = false;
|
||||
$rootScope.$broadcast('$routeChangeStart', next, last);
|
||||
$route.current = next;
|
||||
if (next) {
|
||||
if (next.redirectTo) {
|
||||
if (angular.isString(next.redirectTo)) {
|
||||
$location.path(interpolate(next.redirectTo, next.params)).search(next.params)
|
||||
.replace();
|
||||
} else {
|
||||
$location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))
|
||||
.replace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$q.when(next).
|
||||
then(function() {
|
||||
if (next) {
|
||||
var locals = angular.extend({}, next.resolve),
|
||||
template, templateUrl;
|
||||
|
||||
angular.forEach(locals, function(value, key) {
|
||||
locals[key] = angular.isString(value) ?
|
||||
$injector.get(value) : $injector.invoke(value);
|
||||
});
|
||||
|
||||
if (angular.isDefined(template = next.template)) {
|
||||
if (angular.isFunction(template)) {
|
||||
template = template(next.params);
|
||||
}
|
||||
} else if (angular.isDefined(templateUrl = next.templateUrl)) {
|
||||
if (angular.isFunction(templateUrl)) {
|
||||
templateUrl = templateUrl(next.params);
|
||||
}
|
||||
templateUrl = $sce.getTrustedResourceUrl(templateUrl);
|
||||
if (angular.isDefined(templateUrl)) {
|
||||
next.loadedTemplateUrl = templateUrl;
|
||||
template = $http.get(templateUrl, {cache: $templateCache}).
|
||||
then(function(response) { return response.data; });
|
||||
}
|
||||
}
|
||||
if (angular.isDefined(template)) {
|
||||
locals['$template'] = template;
|
||||
}
|
||||
return $q.all(locals);
|
||||
}
|
||||
}).
|
||||
// after route change
|
||||
then(function(locals) {
|
||||
if (next == $route.current) {
|
||||
if (next) {
|
||||
next.locals = locals;
|
||||
angular.copy(next.params, $routeParams);
|
||||
}
|
||||
$rootScope.$broadcast('$routeChangeSuccess', next, last);
|
||||
}
|
||||
}, function(error) {
|
||||
if (next == $route.current) {
|
||||
$rootScope.$broadcast('$routeChangeError', next, last, error);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @returns {Object} the current active route, by matching it against the URL
|
||||
*/
|
||||
function parseRoute() {
|
||||
// Match a route
|
||||
var params, match;
|
||||
angular.forEach(routes, function(route, path) {
|
||||
if (!match && (params = switchRouteMatcher($location.path(), route))) {
|
||||
match = inherit(route, {
|
||||
params: angular.extend({}, $location.search(), params),
|
||||
pathParams: params});
|
||||
match.$$route = route;
|
||||
}
|
||||
});
|
||||
// No route matched; fallback to "otherwise" route
|
||||
return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {string} interpolation of the redirect path with the parameters
|
||||
*/
|
||||
function interpolate(string, params) {
|
||||
var result = [];
|
||||
angular.forEach((string||'').split(':'), function(segment, i) {
|
||||
if (i === 0) {
|
||||
result.push(segment);
|
||||
} else {
|
||||
var segmentMatch = segment.match(/(\w+)(.*)/);
|
||||
var key = segmentMatch[1];
|
||||
result.push(params[key]);
|
||||
result.push(segmentMatch[2] || '');
|
||||
delete params[key];
|
||||
}
|
||||
});
|
||||
return result.join('');
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
ngRouteModule.provider('$routeParams', $RouteParamsProvider);
|
||||
|
||||
|
||||
/**
|
||||
* @ngdoc service
|
||||
* @name $routeParams
|
||||
* @requires $route
|
||||
*
|
||||
* @description
|
||||
* The `$routeParams` service allows you to retrieve the current set of route parameters.
|
||||
*
|
||||
* Requires the {@link ngRoute `ngRoute`} module to be installed.
|
||||
*
|
||||
* The route parameters are a combination of {@link ng.$location `$location`}'s
|
||||
* {@link ng.$location#search `search()`} and {@link ng.$location#path `path()`}.
|
||||
* The `path` parameters are extracted when the {@link ngRoute.$route `$route`} path is matched.
|
||||
*
|
||||
* In case of parameter name collision, `path` params take precedence over `search` params.
|
||||
*
|
||||
* The service guarantees that the identity of the `$routeParams` object will remain unchanged
|
||||
* (but its properties will likely change) even when a route change occurs.
|
||||
*
|
||||
* Note that the `$routeParams` are only updated *after* a route change completes successfully.
|
||||
* This means that you cannot rely on `$routeParams` being correct in route resolve functions.
|
||||
* Instead you can use `$route.current.params` to access the new route's parameters.
|
||||
*
|
||||
* @example
|
||||
* ```js
|
||||
* // Given:
|
||||
* // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby
|
||||
* // Route: /Chapter/:chapterId/Section/:sectionId
|
||||
* //
|
||||
* // Then
|
||||
* $routeParams ==> {chapterId:'1', sectionId:'2', search:'moby'}
|
||||
* ```
|
||||
*/
|
||||
function $RouteParamsProvider() {
|
||||
this.$get = function() { return {}; };
|
||||
}
|
||||
|
||||
ngRouteModule.directive('ngView', ngViewFactory);
|
||||
ngRouteModule.directive('ngView', ngViewFillContentFactory);
|
||||
|
||||
|
||||
/**
|
||||
* @ngdoc directive
|
||||
* @name ngView
|
||||
* @restrict ECA
|
||||
*
|
||||
* @description
|
||||
* # Overview
|
||||
* `ngView` is a directive that complements the {@link ngRoute.$route $route} service by
|
||||
* including the rendered template of the current route into the main layout (`index.html`) file.
|
||||
* Every time the current route changes, the included view changes with it according to the
|
||||
* configuration of the `$route` service.
|
||||
*
|
||||
* Requires the {@link ngRoute `ngRoute`} module to be installed.
|
||||
*
|
||||
* @animations
|
||||
* enter - animation is used to bring new content into the browser.
|
||||
* leave - animation is used to animate existing content away.
|
||||
*
|
||||
* The enter and leave animation occur concurrently.
|
||||
*
|
||||
* @scope
|
||||
* @priority 400
|
||||
* @param {string=} onload Expression to evaluate whenever the view updates.
|
||||
*
|
||||
* @param {string=} autoscroll Whether `ngView` should call {@link ng.$anchorScroll
|
||||
* $anchorScroll} to scroll the viewport after the view is updated.
|
||||
*
|
||||
* - If the attribute is not set, disable scrolling.
|
||||
* - If the attribute is set without value, enable scrolling.
|
||||
* - Otherwise enable scrolling only if the `autoscroll` attribute value evaluated
|
||||
* as an expression yields a truthy value.
|
||||
* @example
|
||||
<example name="ngView-directive" module="ngViewExample"
|
||||
deps="angular-route.js;angular-animate.js"
|
||||
animations="true" fixBase="true">
|
||||
<file name="index.html">
|
||||
<div ng-controller="MainCtrl as main">
|
||||
Choose:
|
||||
<a href="Book/Moby">Moby</a> |
|
||||
<a href="Book/Moby/ch/1">Moby: Ch1</a> |
|
||||
<a href="Book/Gatsby">Gatsby</a> |
|
||||
<a href="Book/Gatsby/ch/4?key=value">Gatsby: Ch4</a> |
|
||||
<a href="Book/Scarlet">Scarlet Letter</a><br/>
|
||||
|
||||
<div class="view-animate-container">
|
||||
<div ng-view class="view-animate"></div>
|
||||
</div>
|
||||
<hr />
|
||||
|
||||
<pre>$location.path() = {{main.$location.path()}}</pre>
|
||||
<pre>$route.current.templateUrl = {{main.$route.current.templateUrl}}</pre>
|
||||
<pre>$route.current.params = {{main.$route.current.params}}</pre>
|
||||
<pre>$route.current.scope.name = {{main.$route.current.scope.name}}</pre>
|
||||
<pre>$routeParams = {{main.$routeParams}}</pre>
|
||||
</div>
|
||||
</file>
|
||||
|
||||
<file name="book.html">
|
||||
<div>
|
||||
controller: {{book.name}}<br />
|
||||
Book Id: {{book.params.bookId}}<br />
|
||||
</div>
|
||||
</file>
|
||||
|
||||
<file name="chapter.html">
|
||||
<div>
|
||||
controller: {{chapter.name}}<br />
|
||||
Book Id: {{chapter.params.bookId}}<br />
|
||||
Chapter Id: {{chapter.params.chapterId}}
|
||||
</div>
|
||||
</file>
|
||||
|
||||
<file name="animations.css">
|
||||
.view-animate-container {
|
||||
position:relative;
|
||||
height:100px!important;
|
||||
position:relative;
|
||||
background:white;
|
||||
border:1px solid black;
|
||||
height:40px;
|
||||
overflow:hidden;
|
||||
}
|
||||
|
||||
.view-animate {
|
||||
padding:10px;
|
||||
}
|
||||
|
||||
.view-animate.ng-enter, .view-animate.ng-leave {
|
||||
-webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s;
|
||||
transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s;
|
||||
|
||||
display:block;
|
||||
width:100%;
|
||||
border-left:1px solid black;
|
||||
|
||||
position:absolute;
|
||||
top:0;
|
||||
left:0;
|
||||
right:0;
|
||||
bottom:0;
|
||||
padding:10px;
|
||||
}
|
||||
|
||||
.view-animate.ng-enter {
|
||||
left:100%;
|
||||
}
|
||||
.view-animate.ng-enter.ng-enter-active {
|
||||
left:0;
|
||||
}
|
||||
.view-animate.ng-leave.ng-leave-active {
|
||||
left:-100%;
|
||||
}
|
||||
</file>
|
||||
|
||||
<file name="script.js">
|
||||
angular.module('ngViewExample', ['ngRoute', 'ngAnimate'])
|
||||
.config(['$routeProvider', '$locationProvider',
|
||||
function($routeProvider, $locationProvider) {
|
||||
$routeProvider
|
||||
.when('/Book/:bookId', {
|
||||
templateUrl: 'book.html',
|
||||
controller: 'BookCtrl',
|
||||
controllerAs: 'book'
|
||||
})
|
||||
.when('/Book/:bookId/ch/:chapterId', {
|
||||
templateUrl: 'chapter.html',
|
||||
controller: 'ChapterCtrl',
|
||||
controllerAs: 'chapter'
|
||||
});
|
||||
|
||||
// configure html5 to get links working on jsfiddle
|
||||
$locationProvider.html5Mode(true);
|
||||
}])
|
||||
.controller('MainCtrl', ['$route', '$routeParams', '$location',
|
||||
function($route, $routeParams, $location) {
|
||||
this.$route = $route;
|
||||
this.$location = $location;
|
||||
this.$routeParams = $routeParams;
|
||||
}])
|
||||
.controller('BookCtrl', ['$routeParams', function($routeParams) {
|
||||
this.name = "BookCtrl";
|
||||
this.params = $routeParams;
|
||||
}])
|
||||
.controller('ChapterCtrl', ['$routeParams', function($routeParams) {
|
||||
this.name = "ChapterCtrl";
|
||||
this.params = $routeParams;
|
||||
}]);
|
||||
|
||||
</file>
|
||||
|
||||
<file name="protractor.js" type="protractor">
|
||||
it('should load and compile correct template', function() {
|
||||
element(by.linkText('Moby: Ch1')).click();
|
||||
var content = element(by.css('[ng-view]')).getText();
|
||||
expect(content).toMatch(/controller\: ChapterCtrl/);
|
||||
expect(content).toMatch(/Book Id\: Moby/);
|
||||
expect(content).toMatch(/Chapter Id\: 1/);
|
||||
|
||||
element(by.partialLinkText('Scarlet')).click();
|
||||
|
||||
content = element(by.css('[ng-view]')).getText();
|
||||
expect(content).toMatch(/controller\: BookCtrl/);
|
||||
expect(content).toMatch(/Book Id\: Scarlet/);
|
||||
});
|
||||
</file>
|
||||
</example>
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @ngdoc event
|
||||
* @name ngView#$viewContentLoaded
|
||||
* @eventType emit on the current ngView scope
|
||||
* @description
|
||||
* Emitted every time the ngView content is reloaded.
|
||||
*/
|
||||
ngViewFactory.$inject = ['$route', '$anchorScroll', '$animate'];
|
||||
function ngViewFactory( $route, $anchorScroll, $animate) {
|
||||
return {
|
||||
restrict: 'ECA',
|
||||
terminal: true,
|
||||
priority: 400,
|
||||
transclude: 'element',
|
||||
link: function(scope, $element, attr, ctrl, $transclude) {
|
||||
var currentScope,
|
||||
currentElement,
|
||||
previousElement,
|
||||
autoScrollExp = attr.autoscroll,
|
||||
onloadExp = attr.onload || '';
|
||||
|
||||
scope.$on('$routeChangeSuccess', update);
|
||||
update();
|
||||
|
||||
function cleanupLastView() {
|
||||
if(previousElement) {
|
||||
previousElement.remove();
|
||||
previousElement = null;
|
||||
}
|
||||
if(currentScope) {
|
||||
currentScope.$destroy();
|
||||
currentScope = null;
|
||||
}
|
||||
if(currentElement) {
|
||||
$animate.leave(currentElement, function() {
|
||||
previousElement = null;
|
||||
});
|
||||
previousElement = currentElement;
|
||||
currentElement = null;
|
||||
}
|
||||
}
|
||||
|
||||
function update() {
|
||||
var locals = $route.current && $route.current.locals,
|
||||
template = locals && locals.$template;
|
||||
|
||||
if (angular.isDefined(template)) {
|
||||
var newScope = scope.$new();
|
||||
var current = $route.current;
|
||||
|
||||
// Note: This will also link all children of ng-view that were contained in the original
|
||||
// html. If that content contains controllers, ... they could pollute/change the scope.
|
||||
// However, using ng-view on an element with additional content does not make sense...
|
||||
// Note: We can't remove them in the cloneAttchFn of $transclude as that
|
||||
// function is called before linking the content, which would apply child
|
||||
// directives to non existing elements.
|
||||
var clone = $transclude(newScope, function(clone) {
|
||||
$animate.enter(clone, null, currentElement || $element, function onNgViewEnter () {
|
||||
if (angular.isDefined(autoScrollExp)
|
||||
&& (!autoScrollExp || scope.$eval(autoScrollExp))) {
|
||||
$anchorScroll();
|
||||
}
|
||||
});
|
||||
cleanupLastView();
|
||||
});
|
||||
|
||||
currentElement = clone;
|
||||
currentScope = current.scope = newScope;
|
||||
currentScope.$emit('$viewContentLoaded');
|
||||
currentScope.$eval(onloadExp);
|
||||
} else {
|
||||
cleanupLastView();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// This directive is called during the $transclude call of the first `ngView` directive.
|
||||
// It will replace and compile the content of the element with the loaded template.
|
||||
// We need this directive so that the element content is already filled when
|
||||
// the link function of another directive on the same element as ngView
|
||||
// is called.
|
||||
ngViewFillContentFactory.$inject = ['$compile', '$controller', '$route'];
|
||||
function ngViewFillContentFactory($compile, $controller, $route) {
|
||||
return {
|
||||
restrict: 'ECA',
|
||||
priority: -400,
|
||||
link: function(scope, $element) {
|
||||
var current = $route.current,
|
||||
locals = current.locals;
|
||||
|
||||
$element.html(locals.$template);
|
||||
|
||||
var link = $compile($element.contents());
|
||||
|
||||
if (current.controller) {
|
||||
locals.$scope = scope;
|
||||
var controller = $controller(current.controller, locals);
|
||||
if (current.controllerAs) {
|
||||
scope[current.controllerAs] = controller;
|
||||
}
|
||||
$element.data('$ngControllerController', controller);
|
||||
$element.children().data('$ngControllerController', controller);
|
||||
}
|
||||
|
||||
link(scope);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
})(window, window.angular);
|
14
trunk/research/console/js/3rdparty/angular-route.min.js
vendored
Normal file
14
trunk/research/console/js/3rdparty/angular-route.min.js
vendored
Normal file
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
AngularJS v1.2.17
|
||||
(c) 2010-2014 Google, Inc. http://angularjs.org
|
||||
License: MIT
|
||||
*/
|
||||
(function(n,e,A){'use strict';function x(s,g,k){return{restrict:"ECA",terminal:!0,priority:400,transclude:"element",link:function(a,c,b,f,w){function y(){p&&(p.remove(),p=null);h&&(h.$destroy(),h=null);l&&(k.leave(l,function(){p=null}),p=l,l=null)}function v(){var b=s.current&&s.current.locals;if(e.isDefined(b&&b.$template)){var b=a.$new(),d=s.current;l=w(b,function(d){k.enter(d,null,l||c,function(){!e.isDefined(t)||t&&!a.$eval(t)||g()});y()});h=d.scope=b;h.$emit("$viewContentLoaded");h.$eval(u)}else y()}
|
||||
var h,l,p,t=b.autoscroll,u=b.onload||"";a.$on("$routeChangeSuccess",v);v()}}}function z(e,g,k){return{restrict:"ECA",priority:-400,link:function(a,c){var b=k.current,f=b.locals;c.html(f.$template);var w=e(c.contents());b.controller&&(f.$scope=a,f=g(b.controller,f),b.controllerAs&&(a[b.controllerAs]=f),c.data("$ngControllerController",f),c.children().data("$ngControllerController",f));w(a)}}}n=e.module("ngRoute",["ng"]).provider("$route",function(){function s(a,c){return e.extend(new (e.extend(function(){},
|
||||
{prototype:a})),c)}function g(a,e){var b=e.caseInsensitiveMatch,f={originalPath:a,regexp:a},k=f.keys=[];a=a.replace(/([().])/g,"\\$1").replace(/(\/)?:(\w+)([\?\*])?/g,function(a,e,b,c){a="?"===c?c:null;c="*"===c?c:null;k.push({name:b,optional:!!a});e=e||"";return""+(a?"":e)+"(?:"+(a?e:"")+(c&&"(.+?)"||"([^/]+)")+(a||"")+")"+(a||"")}).replace(/([\/$\*])/g,"\\$1");f.regexp=RegExp("^"+a+"$",b?"i":"");return f}var k={};this.when=function(a,c){k[a]=e.extend({reloadOnSearch:!0},c,a&&g(a,c));if(a){var b=
|
||||
"/"==a[a.length-1]?a.substr(0,a.length-1):a+"/";k[b]=e.extend({redirectTo:a},g(b,c))}return this};this.otherwise=function(a){this.when(null,a);return this};this.$get=["$rootScope","$location","$routeParams","$q","$injector","$http","$templateCache","$sce",function(a,c,b,f,g,n,v,h){function l(){var d=p(),m=r.current;if(d&&m&&d.$$route===m.$$route&&e.equals(d.pathParams,m.pathParams)&&!d.reloadOnSearch&&!u)m.params=d.params,e.copy(m.params,b),a.$broadcast("$routeUpdate",m);else if(d||m)u=!1,a.$broadcast("$routeChangeStart",
|
||||
d,m),(r.current=d)&&d.redirectTo&&(e.isString(d.redirectTo)?c.path(t(d.redirectTo,d.params)).search(d.params).replace():c.url(d.redirectTo(d.pathParams,c.path(),c.search())).replace()),f.when(d).then(function(){if(d){var a=e.extend({},d.resolve),c,b;e.forEach(a,function(d,c){a[c]=e.isString(d)?g.get(d):g.invoke(d)});e.isDefined(c=d.template)?e.isFunction(c)&&(c=c(d.params)):e.isDefined(b=d.templateUrl)&&(e.isFunction(b)&&(b=b(d.params)),b=h.getTrustedResourceUrl(b),e.isDefined(b)&&(d.loadedTemplateUrl=
|
||||
b,c=n.get(b,{cache:v}).then(function(a){return a.data})));e.isDefined(c)&&(a.$template=c);return f.all(a)}}).then(function(c){d==r.current&&(d&&(d.locals=c,e.copy(d.params,b)),a.$broadcast("$routeChangeSuccess",d,m))},function(c){d==r.current&&a.$broadcast("$routeChangeError",d,m,c)})}function p(){var a,b;e.forEach(k,function(f,k){var q;if(q=!b){var g=c.path();q=f.keys;var l={};if(f.regexp)if(g=f.regexp.exec(g)){for(var h=1,p=g.length;h<p;++h){var n=q[h-1],r="string"==typeof g[h]?decodeURIComponent(g[h]):
|
||||
g[h];n&&r&&(l[n.name]=r)}q=l}else q=null;else q=null;q=a=q}q&&(b=s(f,{params:e.extend({},c.search(),a),pathParams:a}),b.$$route=f)});return b||k[null]&&s(k[null],{params:{},pathParams:{}})}function t(a,c){var b=[];e.forEach((a||"").split(":"),function(a,d){if(0===d)b.push(a);else{var e=a.match(/(\w+)(.*)/),f=e[1];b.push(c[f]);b.push(e[2]||"");delete c[f]}});return b.join("")}var u=!1,r={routes:k,reload:function(){u=!0;a.$evalAsync(l)}};a.$on("$locationChangeSuccess",l);return r}]});n.provider("$routeParams",
|
||||
function(){this.$get=function(){return{}}});n.directive("ngView",x);n.directive("ngView",z);x.$inject=["$route","$anchorScroll","$animate"];z.$inject=["$compile","$controller","$route"]})(window,window.angular);
|
||||
//# sourceMappingURL=angular-route.min.js.map
|
8
trunk/research/console/js/3rdparty/angular-route.min.js.map
vendored
Normal file
8
trunk/research/console/js/3rdparty/angular-route.min.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
21674
trunk/research/console/js/3rdparty/angular.js
vendored
Normal file
21674
trunk/research/console/js/3rdparty/angular.js
vendored
Normal file
File diff suppressed because it is too large
Load diff
212
trunk/research/console/js/3rdparty/angular.min.js
vendored
Normal file
212
trunk/research/console/js/3rdparty/angular.min.js
vendored
Normal file
|
@ -0,0 +1,212 @@
|
|||
/*
|
||||
AngularJS v1.2.17
|
||||
(c) 2010-2014 Google, Inc. http://angularjs.org
|
||||
License: MIT
|
||||
*/
|
||||
(function(P,V,s){'use strict';function u(b){return function(){var a=arguments[0],c,a="["+(b?b+":":"")+a+"] http://errors.angularjs.org/1.2.17/"+(b?b+"/":"")+a;for(c=1;c<arguments.length;c++)a=a+(1==c?"?":"&")+"p"+(c-1)+"="+encodeURIComponent("function"==typeof arguments[c]?arguments[c].toString().replace(/ \{[\s\S]*$/,""):"undefined"==typeof arguments[c]?"undefined":"string"!=typeof arguments[c]?JSON.stringify(arguments[c]):arguments[c]);return Error(a)}}function db(b){if(null==b||Da(b))return!1;
|
||||
var a=b.length;return 1===b.nodeType&&a?!0:C(b)||K(b)||0===a||"number"===typeof a&&0<a&&a-1 in b}function q(b,a,c){var d;if(b)if(Q(b))for(d in b)"prototype"==d||("length"==d||"name"==d||b.hasOwnProperty&&!b.hasOwnProperty(d))||a.call(c,b[d],d);else if(b.forEach&&b.forEach!==q)b.forEach(a,c);else if(db(b))for(d=0;d<b.length;d++)a.call(c,b[d],d);else for(d in b)b.hasOwnProperty(d)&&a.call(c,b[d],d);return b}function Wb(b){var a=[],c;for(c in b)b.hasOwnProperty(c)&&a.push(c);return a.sort()}function Sc(b,
|
||||
a,c){for(var d=Wb(b),e=0;e<d.length;e++)a.call(c,b[d[e]],d[e]);return d}function Xb(b){return function(a,c){b(c,a)}}function eb(){for(var b=ja.length,a;b;){b--;a=ja[b].charCodeAt(0);if(57==a)return ja[b]="A",ja.join("");if(90==a)ja[b]="0";else return ja[b]=String.fromCharCode(a+1),ja.join("")}ja.unshift("0");return ja.join("")}function Yb(b,a){a?b.$$hashKey=a:delete b.$$hashKey}function E(b){var a=b.$$hashKey;q(arguments,function(a){a!==b&&q(a,function(a,c){b[c]=a})});Yb(b,a);return b}function Y(b){return parseInt(b,
|
||||
10)}function Zb(b,a){return E(new (E(function(){},{prototype:b})),a)}function w(){}function Ea(b){return b}function aa(b){return function(){return b}}function H(b){return"undefined"===typeof b}function z(b){return"undefined"!==typeof b}function U(b){return null!=b&&"object"===typeof b}function C(b){return"string"===typeof b}function zb(b){return"number"===typeof b}function Ma(b){return"[object Date]"===wa.call(b)}function K(b){return"[object Array]"===wa.call(b)}function Q(b){return"function"===typeof b}
|
||||
function fb(b){return"[object RegExp]"===wa.call(b)}function Da(b){return b&&b.document&&b.location&&b.alert&&b.setInterval}function Tc(b){return!(!b||!(b.nodeName||b.prop&&b.attr&&b.find))}function Uc(b,a,c){var d=[];q(b,function(b,f,g){d.push(a.call(c,b,f,g))});return d}function Na(b,a){if(b.indexOf)return b.indexOf(a);for(var c=0;c<b.length;c++)if(a===b[c])return c;return-1}function Oa(b,a){var c=Na(b,a);0<=c&&b.splice(c,1);return a}function Fa(b,a,c,d){if(Da(b)||b&&b.$evalAsync&&b.$watch)throw Pa("cpws");
|
||||
if(a){if(b===a)throw Pa("cpi");c=c||[];d=d||[];if(U(b)){var e=Na(c,b);if(-1!==e)return d[e];c.push(b);d.push(a)}if(K(b))for(var f=a.length=0;f<b.length;f++)e=Fa(b[f],null,c,d),U(b[f])&&(c.push(b[f]),d.push(e)),a.push(e);else{var g=a.$$hashKey;q(a,function(b,c){delete a[c]});for(f in b)e=Fa(b[f],null,c,d),U(b[f])&&(c.push(b[f]),d.push(e)),a[f]=e;Yb(a,g)}}else(a=b)&&(K(b)?a=Fa(b,[],c,d):Ma(b)?a=new Date(b.getTime()):fb(b)?a=RegExp(b.source):U(b)&&(a=Fa(b,{},c,d)));return a}function ka(b,a){if(K(b)){a=
|
||||
a||[];for(var c=0;c<b.length;c++)a[c]=b[c]}else if(U(b))for(c in a=a||{},b)!Ab.call(b,c)||"$"===c.charAt(0)&&"$"===c.charAt(1)||(a[c]=b[c]);return a||b}function xa(b,a){if(b===a)return!0;if(null===b||null===a)return!1;if(b!==b&&a!==a)return!0;var c=typeof b,d;if(c==typeof a&&"object"==c)if(K(b)){if(!K(a))return!1;if((c=b.length)==a.length){for(d=0;d<c;d++)if(!xa(b[d],a[d]))return!1;return!0}}else{if(Ma(b))return Ma(a)&&b.getTime()==a.getTime();if(fb(b)&&fb(a))return b.toString()==a.toString();if(b&&
|
||||
b.$evalAsync&&b.$watch||a&&a.$evalAsync&&a.$watch||Da(b)||Da(a)||K(a))return!1;c={};for(d in b)if("$"!==d.charAt(0)&&!Q(b[d])){if(!xa(b[d],a[d]))return!1;c[d]=!0}for(d in a)if(!c.hasOwnProperty(d)&&"$"!==d.charAt(0)&&a[d]!==s&&!Q(a[d]))return!1;return!0}return!1}function $b(){return V.securityPolicy&&V.securityPolicy.isActive||V.querySelector&&!(!V.querySelector("[ng-csp]")&&!V.querySelector("[data-ng-csp]"))}function gb(b,a){var c=2<arguments.length?ya.call(arguments,2):[];return!Q(a)||a instanceof
|
||||
RegExp?a:c.length?function(){return arguments.length?a.apply(b,c.concat(ya.call(arguments,0))):a.apply(b,c)}:function(){return arguments.length?a.apply(b,arguments):a.call(b)}}function Vc(b,a){var c=a;"string"===typeof b&&"$"===b.charAt(0)?c=s:Da(a)?c="$WINDOW":a&&V===a?c="$DOCUMENT":a&&(a.$evalAsync&&a.$watch)&&(c="$SCOPE");return c}function qa(b,a){return"undefined"===typeof b?s:JSON.stringify(b,Vc,a?" ":null)}function ac(b){return C(b)?JSON.parse(b):b}function Qa(b){"function"===typeof b?b=!0:
|
||||
b&&0!==b.length?(b=J(""+b),b=!("f"==b||"0"==b||"false"==b||"no"==b||"n"==b||"[]"==b)):b=!1;return b}function ha(b){b=y(b).clone();try{b.empty()}catch(a){}var c=y("<div>").append(b).html();try{return 3===b[0].nodeType?J(c):c.match(/^(<[^>]+>)/)[1].replace(/^<([\w\-]+)/,function(a,b){return"<"+J(b)})}catch(d){return J(c)}}function bc(b){try{return decodeURIComponent(b)}catch(a){}}function cc(b){var a={},c,d;q((b||"").split("&"),function(b){b&&(c=b.split("="),d=bc(c[0]),z(d)&&(b=z(c[1])?bc(c[1]):!0,
|
||||
a[d]?K(a[d])?a[d].push(b):a[d]=[a[d],b]:a[d]=b))});return a}function Bb(b){var a=[];q(b,function(b,d){K(b)?q(b,function(b){a.push(za(d,!0)+(!0===b?"":"="+za(b,!0)))}):a.push(za(d,!0)+(!0===b?"":"="+za(b,!0)))});return a.length?a.join("&"):""}function hb(b){return za(b,!0).replace(/%26/gi,"&").replace(/%3D/gi,"=").replace(/%2B/gi,"+")}function za(b,a){return encodeURIComponent(b).replace(/%40/gi,"@").replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,a?"%20":"+")}function Wc(b,
|
||||
a){function c(a){a&&d.push(a)}var d=[b],e,f,g=["ng:app","ng-app","x-ng-app","data-ng-app"],h=/\sng[:\-]app(:\s*([\w\d_]+);?)?\s/;q(g,function(a){g[a]=!0;c(V.getElementById(a));a=a.replace(":","\\:");b.querySelectorAll&&(q(b.querySelectorAll("."+a),c),q(b.querySelectorAll("."+a+"\\:"),c),q(b.querySelectorAll("["+a+"]"),c))});q(d,function(a){if(!e){var b=h.exec(" "+a.className+" ");b?(e=a,f=(b[2]||"").replace(/\s+/g,",")):q(a.attributes,function(b){!e&&g[b.name]&&(e=a,f=b.value)})}});e&&a(e,f?[f]:[])}
|
||||
function dc(b,a){var c=function(){b=y(b);if(b.injector()){var c=b[0]===V?"document":ha(b);throw Pa("btstrpd",c);}a=a||[];a.unshift(["$provide",function(a){a.value("$rootElement",b)}]);a.unshift("ng");c=ec(a);c.invoke(["$rootScope","$rootElement","$compile","$injector","$animate",function(a,b,c,d,e){a.$apply(function(){b.data("$injector",d);c(b)(a)})}]);return c},d=/^NG_DEFER_BOOTSTRAP!/;if(P&&!d.test(P.name))return c();P.name=P.name.replace(d,"");Ra.resumeBootstrap=function(b){q(b,function(b){a.push(b)});
|
||||
c()}}function ib(b,a){a=a||"_";return b.replace(Xc,function(b,d){return(d?a:"")+b.toLowerCase()})}function Cb(b,a,c){if(!b)throw Pa("areq",a||"?",c||"required");return b}function Sa(b,a,c){c&&K(b)&&(b=b[b.length-1]);Cb(Q(b),a,"not a function, got "+(b&&"object"==typeof b?b.constructor.name||"Object":typeof b));return b}function Aa(b,a){if("hasOwnProperty"===b)throw Pa("badname",a);}function fc(b,a,c){if(!a)return b;a=a.split(".");for(var d,e=b,f=a.length,g=0;g<f;g++)d=a[g],b&&(b=(e=b)[d]);return!c&&
|
||||
Q(b)?gb(e,b):b}function Db(b){var a=b[0];b=b[b.length-1];if(a===b)return y(a);var c=[a];do{a=a.nextSibling;if(!a)break;c.push(a)}while(a!==b);return y(c)}function Yc(b){var a=u("$injector"),c=u("ng");b=b.angular||(b.angular={});b.$$minErr=b.$$minErr||u;return b.module||(b.module=function(){var b={};return function(e,f,g){if("hasOwnProperty"===e)throw c("badname","module");f&&b.hasOwnProperty(e)&&(b[e]=null);return b[e]||(b[e]=function(){function b(a,d,e){return function(){c[e||"push"]([a,d,arguments]);
|
||||
return n}}if(!f)throw a("nomod",e);var c=[],d=[],l=b("$injector","invoke"),n={_invokeQueue:c,_runBlocks:d,requires:f,name:e,provider:b("$provide","provider"),factory:b("$provide","factory"),service:b("$provide","service"),value:b("$provide","value"),constant:b("$provide","constant","unshift"),animation:b("$animateProvider","register"),filter:b("$filterProvider","register"),controller:b("$controllerProvider","register"),directive:b("$compileProvider","directive"),config:l,run:function(a){d.push(a);
|
||||
return this}};g&&l(g);return n}())}}())}function Zc(b){E(b,{bootstrap:dc,copy:Fa,extend:E,equals:xa,element:y,forEach:q,injector:ec,noop:w,bind:gb,toJson:qa,fromJson:ac,identity:Ea,isUndefined:H,isDefined:z,isString:C,isFunction:Q,isObject:U,isNumber:zb,isElement:Tc,isArray:K,version:$c,isDate:Ma,lowercase:J,uppercase:Ga,callbacks:{counter:0},$$minErr:u,$$csp:$b});Ta=Yc(P);try{Ta("ngLocale")}catch(a){Ta("ngLocale",[]).provider("$locale",ad)}Ta("ng",["ngLocale"],["$provide",function(a){a.provider({$$sanitizeUri:bd});
|
||||
a.provider("$compile",gc).directive({a:cd,input:hc,textarea:hc,form:dd,script:ed,select:fd,style:gd,option:hd,ngBind:id,ngBindHtml:jd,ngBindTemplate:kd,ngClass:ld,ngClassEven:md,ngClassOdd:nd,ngCloak:od,ngController:pd,ngForm:qd,ngHide:rd,ngIf:sd,ngInclude:td,ngInit:ud,ngNonBindable:vd,ngPluralize:wd,ngRepeat:xd,ngShow:yd,ngStyle:zd,ngSwitch:Ad,ngSwitchWhen:Bd,ngSwitchDefault:Cd,ngOptions:Dd,ngTransclude:Ed,ngModel:Fd,ngList:Gd,ngChange:Hd,required:ic,ngRequired:ic,ngValue:Id}).directive({ngInclude:Jd}).directive(Eb).directive(jc);
|
||||
a.provider({$anchorScroll:Kd,$animate:Ld,$browser:Md,$cacheFactory:Nd,$controller:Od,$document:Pd,$exceptionHandler:Qd,$filter:kc,$interpolate:Rd,$interval:Sd,$http:Td,$httpBackend:Ud,$location:Vd,$log:Wd,$parse:Xd,$rootScope:Yd,$q:Zd,$sce:$d,$sceDelegate:ae,$sniffer:be,$templateCache:ce,$timeout:de,$window:ee,$$rAF:fe,$$asyncCallback:ge})}])}function Ua(b){return b.replace(he,function(a,b,d,e){return e?d.toUpperCase():d}).replace(ie,"Moz$1")}function Fb(b,a,c,d){function e(b){var e=c&&b?[this.filter(b)]:
|
||||
[this],m=a,k,l,n,p,r,A;if(!d||null!=b)for(;e.length;)for(k=e.shift(),l=0,n=k.length;l<n;l++)for(p=y(k[l]),m?p.triggerHandler("$destroy"):m=!m,r=0,p=(A=p.children()).length;r<p;r++)e.push(Ba(A[r]));return f.apply(this,arguments)}var f=Ba.fn[b],f=f.$original||f;e.$original=f;Ba.fn[b]=e}function M(b){if(b instanceof M)return b;C(b)&&(b=ba(b));if(!(this instanceof M)){if(C(b)&&"<"!=b.charAt(0))throw Gb("nosel");return new M(b)}if(C(b)){var a=b;b=V;var c;if(c=je.exec(a))b=[b.createElement(c[1])];else{var d=
|
||||
b,e;b=d.createDocumentFragment();c=[];if(Hb.test(a)){d=b.appendChild(d.createElement("div"));e=(ke.exec(a)||["",""])[1].toLowerCase();e=da[e]||da._default;d.innerHTML="<div> </div>"+e[1]+a.replace(le,"<$1></$2>")+e[2];d.removeChild(d.firstChild);for(a=e[0];a--;)d=d.lastChild;a=0;for(e=d.childNodes.length;a<e;++a)c.push(d.childNodes[a]);d=b.firstChild;d.textContent=""}else c.push(d.createTextNode(a));b.textContent="";b.innerHTML="";b=c}Ib(this,b);y(V.createDocumentFragment()).append(this)}else Ib(this,
|
||||
b)}function Jb(b){return b.cloneNode(!0)}function Ha(b){lc(b);var a=0;for(b=b.childNodes||[];a<b.length;a++)Ha(b[a])}function mc(b,a,c,d){if(z(d))throw Gb("offargs");var e=la(b,"events");la(b,"handle")&&(H(a)?q(e,function(a,c){Va(b,c,a);delete e[c]}):q(a.split(" "),function(a){H(c)?(Va(b,a,e[a]),delete e[a]):Oa(e[a]||[],c)}))}function lc(b,a){var c=b[jb],d=Wa[c];d&&(a?delete Wa[c].data[a]:(d.handle&&(d.events.$destroy&&d.handle({},"$destroy"),mc(b)),delete Wa[c],b[jb]=s))}function la(b,a,c){var d=
|
||||
b[jb],d=Wa[d||-1];if(z(c))d||(b[jb]=d=++me,d=Wa[d]={}),d[a]=c;else return d&&d[a]}function nc(b,a,c){var d=la(b,"data"),e=z(c),f=!e&&z(a),g=f&&!U(a);d||g||la(b,"data",d={});if(e)d[a]=c;else if(f){if(g)return d&&d[a];E(d,a)}else return d}function Kb(b,a){return b.getAttribute?-1<(" "+(b.getAttribute("class")||"")+" ").replace(/[\n\t]/g," ").indexOf(" "+a+" "):!1}function kb(b,a){a&&b.setAttribute&&q(a.split(" "),function(a){b.setAttribute("class",ba((" "+(b.getAttribute("class")||"")+" ").replace(/[\n\t]/g,
|
||||
" ").replace(" "+ba(a)+" "," ")))})}function lb(b,a){if(a&&b.setAttribute){var c=(" "+(b.getAttribute("class")||"")+" ").replace(/[\n\t]/g," ");q(a.split(" "),function(a){a=ba(a);-1===c.indexOf(" "+a+" ")&&(c+=a+" ")});b.setAttribute("class",ba(c))}}function Ib(b,a){if(a){a=a.nodeName||!z(a.length)||Da(a)?[a]:a;for(var c=0;c<a.length;c++)b.push(a[c])}}function oc(b,a){return mb(b,"$"+(a||"ngController")+"Controller")}function mb(b,a,c){b=y(b);9==b[0].nodeType&&(b=b.find("html"));for(a=K(a)?a:[a];b.length;){for(var d=
|
||||
b[0],e=0,f=a.length;e<f;e++)if((c=b.data(a[e]))!==s)return c;b=y(d.parentNode||11===d.nodeType&&d.host)}}function pc(b){for(var a=0,c=b.childNodes;a<c.length;a++)Ha(c[a]);for(;b.firstChild;)b.removeChild(b.firstChild)}function qc(b,a){var c=nb[a.toLowerCase()];return c&&rc[b.nodeName]&&c}function ne(b,a){var c=function(c,e){c.preventDefault||(c.preventDefault=function(){c.returnValue=!1});c.stopPropagation||(c.stopPropagation=function(){c.cancelBubble=!0});c.target||(c.target=c.srcElement||V);if(H(c.defaultPrevented)){var f=
|
||||
c.preventDefault;c.preventDefault=function(){c.defaultPrevented=!0;f.call(c)};c.defaultPrevented=!1}c.isDefaultPrevented=function(){return c.defaultPrevented||!1===c.returnValue};var g=ka(a[e||c.type]||[]);q(g,function(a){a.call(b,c)});8>=S?(c.preventDefault=null,c.stopPropagation=null,c.isDefaultPrevented=null):(delete c.preventDefault,delete c.stopPropagation,delete c.isDefaultPrevented)};c.elem=b;return c}function Ia(b){var a=typeof b,c;"object"==a&&null!==b?"function"==typeof(c=b.$$hashKey)?c=
|
||||
b.$$hashKey():c===s&&(c=b.$$hashKey=eb()):c=b;return a+":"+c}function Xa(b){q(b,this.put,this)}function sc(b){var a,c;"function"==typeof b?(a=b.$inject)||(a=[],b.length&&(c=b.toString().replace(oe,""),c=c.match(pe),q(c[1].split(qe),function(b){b.replace(re,function(b,c,d){a.push(d)})})),b.$inject=a):K(b)?(c=b.length-1,Sa(b[c],"fn"),a=b.slice(0,c)):Sa(b,"fn",!0);return a}function ec(b){function a(a){return function(b,c){if(U(b))q(b,Xb(a));else return a(b,c)}}function c(a,b){Aa(a,"service");if(Q(b)||
|
||||
K(b))b=n.instantiate(b);if(!b.$get)throw Ya("pget",a);return l[a+h]=b}function d(a,b){return c(a,{$get:b})}function e(a){var b=[],c,d,f,h;q(a,function(a){if(!k.get(a)){k.put(a,!0);try{if(C(a))for(c=Ta(a),b=b.concat(e(c.requires)).concat(c._runBlocks),d=c._invokeQueue,f=0,h=d.length;f<h;f++){var g=d[f],m=n.get(g[0]);m[g[1]].apply(m,g[2])}else Q(a)?b.push(n.invoke(a)):K(a)?b.push(n.invoke(a)):Sa(a,"module")}catch(l){throw K(a)&&(a=a[a.length-1]),l.message&&(l.stack&&-1==l.stack.indexOf(l.message))&&
|
||||
(l=l.message+"\n"+l.stack),Ya("modulerr",a,l.stack||l.message||l);}}});return b}function f(a,b){function c(d){if(a.hasOwnProperty(d)){if(a[d]===g)throw Ya("cdep",m.join(" <- "));return a[d]}try{return m.unshift(d),a[d]=g,a[d]=b(d)}catch(e){throw a[d]===g&&delete a[d],e;}finally{m.shift()}}function d(a,b,e){var f=[],h=sc(a),g,m,k;m=0;for(g=h.length;m<g;m++){k=h[m];if("string"!==typeof k)throw Ya("itkn",k);f.push(e&&e.hasOwnProperty(k)?e[k]:c(k))}a.$inject||(a=a[g]);return a.apply(b,f)}return{invoke:d,
|
||||
instantiate:function(a,b){var c=function(){},e;c.prototype=(K(a)?a[a.length-1]:a).prototype;c=new c;e=d(a,c,b);return U(e)||Q(e)?e:c},get:c,annotate:sc,has:function(b){return l.hasOwnProperty(b+h)||a.hasOwnProperty(b)}}}var g={},h="Provider",m=[],k=new Xa,l={$provide:{provider:a(c),factory:a(d),service:a(function(a,b){return d(a,["$injector",function(a){return a.instantiate(b)}])}),value:a(function(a,b){return d(a,aa(b))}),constant:a(function(a,b){Aa(a,"constant");l[a]=b;p[a]=b}),decorator:function(a,
|
||||
b){var c=n.get(a+h),d=c.$get;c.$get=function(){var a=r.invoke(d,c);return r.invoke(b,null,{$delegate:a})}}}},n=l.$injector=f(l,function(){throw Ya("unpr",m.join(" <- "));}),p={},r=p.$injector=f(p,function(a){a=n.get(a+h);return r.invoke(a.$get,a)});q(e(b),function(a){r.invoke(a||w)});return r}function Kd(){var b=!0;this.disableAutoScrolling=function(){b=!1};this.$get=["$window","$location","$rootScope",function(a,c,d){function e(a){var b=null;q(a,function(a){b||"a"!==J(a.nodeName)||(b=a)});return b}
|
||||
function f(){var b=c.hash(),d;b?(d=g.getElementById(b))?d.scrollIntoView():(d=e(g.getElementsByName(b)))?d.scrollIntoView():"top"===b&&a.scrollTo(0,0):a.scrollTo(0,0)}var g=a.document;b&&d.$watch(function(){return c.hash()},function(){d.$evalAsync(f)});return f}]}function ge(){this.$get=["$$rAF","$timeout",function(b,a){return b.supported?function(a){return b(a)}:function(b){return a(b,0,!1)}}]}function se(b,a,c,d){function e(a){try{a.apply(null,ya.call(arguments,1))}finally{if(A--,0===A)for(;D.length;)try{D.pop()()}catch(b){c.error(b)}}}
|
||||
function f(a,b){(function T(){q(x,function(a){a()});t=b(T,a)})()}function g(){v=null;N!=h.url()&&(N=h.url(),q(ma,function(a){a(h.url())}))}var h=this,m=a[0],k=b.location,l=b.history,n=b.setTimeout,p=b.clearTimeout,r={};h.isMock=!1;var A=0,D=[];h.$$completeOutstandingRequest=e;h.$$incOutstandingRequestCount=function(){A++};h.notifyWhenNoOutstandingRequests=function(a){q(x,function(a){a()});0===A?a():D.push(a)};var x=[],t;h.addPollFn=function(a){H(t)&&f(100,n);x.push(a);return a};var N=k.href,B=a.find("base"),
|
||||
v=null;h.url=function(a,c){k!==b.location&&(k=b.location);l!==b.history&&(l=b.history);if(a){if(N!=a)return N=a,d.history?c?l.replaceState(null,"",a):(l.pushState(null,"",a),B.attr("href",B.attr("href"))):(v=a,c?k.replace(a):k.href=a),h}else return v||k.href.replace(/%27/g,"'")};var ma=[],L=!1;h.onUrlChange=function(a){if(!L){if(d.history)y(b).on("popstate",g);if(d.hashchange)y(b).on("hashchange",g);else h.addPollFn(g);L=!0}ma.push(a);return a};h.baseHref=function(){var a=B.attr("href");return a?
|
||||
a.replace(/^(https?\:)?\/\/[^\/]*/,""):""};var O={},ca="",F=h.baseHref();h.cookies=function(a,b){var d,e,f,h;if(a)b===s?m.cookie=escape(a)+"=;path="+F+";expires=Thu, 01 Jan 1970 00:00:00 GMT":C(b)&&(d=(m.cookie=escape(a)+"="+escape(b)+";path="+F).length+1,4096<d&&c.warn("Cookie '"+a+"' possibly not set or overflowed because it was too large ("+d+" > 4096 bytes)!"));else{if(m.cookie!==ca)for(ca=m.cookie,d=ca.split("; "),O={},f=0;f<d.length;f++)e=d[f],h=e.indexOf("="),0<h&&(a=unescape(e.substring(0,
|
||||
h)),O[a]===s&&(O[a]=unescape(e.substring(h+1))));return O}};h.defer=function(a,b){var c;A++;c=n(function(){delete r[c];e(a)},b||0);r[c]=!0;return c};h.defer.cancel=function(a){return r[a]?(delete r[a],p(a),e(w),!0):!1}}function Md(){this.$get=["$window","$log","$sniffer","$document",function(b,a,c,d){return new se(b,d,a,c)}]}function Nd(){this.$get=function(){function b(b,d){function e(a){a!=n&&(p?p==a&&(p=a.n):p=a,f(a.n,a.p),f(a,n),n=a,n.n=null)}function f(a,b){a!=b&&(a&&(a.p=b),b&&(b.n=a))}if(b in
|
||||
a)throw u("$cacheFactory")("iid",b);var g=0,h=E({},d,{id:b}),m={},k=d&&d.capacity||Number.MAX_VALUE,l={},n=null,p=null;return a[b]={put:function(a,b){if(k<Number.MAX_VALUE){var c=l[a]||(l[a]={key:a});e(c)}if(!H(b))return a in m||g++,m[a]=b,g>k&&this.remove(p.key),b},get:function(a){if(k<Number.MAX_VALUE){var b=l[a];if(!b)return;e(b)}return m[a]},remove:function(a){if(k<Number.MAX_VALUE){var b=l[a];if(!b)return;b==n&&(n=b.p);b==p&&(p=b.n);f(b.n,b.p);delete l[a]}delete m[a];g--},removeAll:function(){m=
|
||||
{};g=0;l={};n=p=null},destroy:function(){l=h=m=null;delete a[b]},info:function(){return E({},h,{size:g})}}}var a={};b.info=function(){var b={};q(a,function(a,e){b[e]=a.info()});return b};b.get=function(b){return a[b]};return b}}function ce(){this.$get=["$cacheFactory",function(b){return b("templates")}]}function gc(b,a){var c={},d="Directive",e=/^\s*directive\:\s*([\d\w_\-]+)\s+(.*)$/,f=/(([\d\w_\-]+)(?:\:([^;]+))?;?)/,g=/^(on[a-z]+|formaction)$/;this.directive=function m(a,e){Aa(a,"directive");C(a)?
|
||||
(Cb(e,"directiveFactory"),c.hasOwnProperty(a)||(c[a]=[],b.factory(a+d,["$injector","$exceptionHandler",function(b,d){var e=[];q(c[a],function(c,f){try{var g=b.invoke(c);Q(g)?g={compile:aa(g)}:!g.compile&&g.link&&(g.compile=aa(g.link));g.priority=g.priority||0;g.index=f;g.name=g.name||a;g.require=g.require||g.controller&&g.name;g.restrict=g.restrict||"A";e.push(g)}catch(m){d(m)}});return e}])),c[a].push(e)):q(a,Xb(m));return this};this.aHrefSanitizationWhitelist=function(b){return z(b)?(a.aHrefSanitizationWhitelist(b),
|
||||
this):a.aHrefSanitizationWhitelist()};this.imgSrcSanitizationWhitelist=function(b){return z(b)?(a.imgSrcSanitizationWhitelist(b),this):a.imgSrcSanitizationWhitelist()};this.$get=["$injector","$interpolate","$exceptionHandler","$http","$templateCache","$parse","$controller","$rootScope","$document","$sce","$animate","$$sanitizeUri",function(a,b,l,n,p,r,A,D,x,t,N,B){function v(a,b,c,d,e){a instanceof y||(a=y(a));q(a,function(b,c){3==b.nodeType&&b.nodeValue.match(/\S+/)&&(a[c]=y(b).wrap("<span></span>").parent()[0])});
|
||||
var f=L(a,b,a,c,d,e);ma(a,"ng-scope");return function(b,c,d){Cb(b,"scope");var e=c?Ja.clone.call(a):a;q(d,function(a,b){e.data("$"+b+"Controller",a)});d=0;for(var g=e.length;d<g;d++){var m=e[d].nodeType;1!==m&&9!==m||e.eq(d).data("$scope",b)}c&&c(e,b);f&&f(b,e,e);return e}}function ma(a,b){try{a.addClass(b)}catch(c){}}function L(a,b,c,d,e,f){function g(a,c,d,e){var f,k,l,r,n,p,A;f=c.length;var I=Array(f);for(n=0;n<f;n++)I[n]=c[n];A=n=0;for(p=m.length;n<p;A++)k=I[A],c=m[n++],f=m[n++],l=y(k),c?(c.scope?
|
||||
(r=a.$new(),l.data("$scope",r)):r=a,(l=c.transclude)||!e&&b?c(f,r,k,d,O(a,l||b)):c(f,r,k,d,e)):f&&f(a,k.childNodes,s,e)}for(var m=[],k,l,r,n,p=0;p<a.length;p++)k=new Lb,l=ca(a[p],[],k,0===p?d:s,e),(f=l.length?ea(l,a[p],k,b,c,null,[],[],f):null)&&f.scope&&ma(y(a[p]),"ng-scope"),k=f&&f.terminal||!(r=a[p].childNodes)||!r.length?null:L(r,f?f.transclude:b),m.push(f,k),n=n||f||k,f=null;return n?g:null}function O(a,b){return function(c,d,e){var f=!1;c||(c=a.$new(),f=c.$$transcluded=!0);d=b(c,d,e);if(f)d.on("$destroy",
|
||||
gb(c,c.$destroy));return d}}function ca(a,b,c,d,g){var m=c.$attr,k;switch(a.nodeType){case 1:T(b,na(Ka(a).toLowerCase()),"E",d,g);var l,r,n;k=a.attributes;for(var p=0,A=k&&k.length;p<A;p++){var x=!1,D=!1;l=k[p];if(!S||8<=S||l.specified){r=l.name;n=na(r);X.test(n)&&(r=ib(n.substr(6),"-"));var N=n.replace(/(Start|End)$/,"");n===N+"Start"&&(x=r,D=r.substr(0,r.length-5)+"end",r=r.substr(0,r.length-6));n=na(r.toLowerCase());m[n]=r;c[n]=l=ba(l.value);qc(a,n)&&(c[n]=!0);M(a,b,l,n);T(b,n,"A",d,g,x,D)}}a=
|
||||
a.className;if(C(a)&&""!==a)for(;k=f.exec(a);)n=na(k[2]),T(b,n,"C",d,g)&&(c[n]=ba(k[3])),a=a.substr(k.index+k[0].length);break;case 3:u(b,a.nodeValue);break;case 8:try{if(k=e.exec(a.nodeValue))n=na(k[1]),T(b,n,"M",d,g)&&(c[n]=ba(k[2]))}catch(t){}}b.sort(H);return b}function F(a,b,c){var d=[],e=0;if(b&&a.hasAttribute&&a.hasAttribute(b)){do{if(!a)throw ia("uterdir",b,c);1==a.nodeType&&(a.hasAttribute(b)&&e++,a.hasAttribute(c)&&e--);d.push(a);a=a.nextSibling}while(0<e)}else d.push(a);return y(d)}function R(a,
|
||||
b,c){return function(d,e,f,g,k){e=F(e[0],b,c);return a(d,e,f,g,k)}}function ea(a,c,d,e,f,g,m,n,p){function x(a,b,c,d){if(a){c&&(a=R(a,c,d));a.require=G.require;a.directiveName=u;if(O===G||G.$$isolateScope)a=uc(a,{isolateScope:!0});m.push(a)}if(b){c&&(b=R(b,c,d));b.require=G.require;b.directiveName=u;if(O===G||G.$$isolateScope)b=uc(b,{isolateScope:!0});n.push(b)}}function D(a,b,c,d){var e,f="data",g=!1;if(C(b)){for(;"^"==(e=b.charAt(0))||"?"==e;)b=b.substr(1),"^"==e&&(f="inheritedData"),g=g||"?"==
|
||||
e;e=null;d&&"data"===f&&(e=d[b]);e=e||c[f]("$"+b+"Controller");if(!e&&!g)throw ia("ctreq",b,a);}else K(b)&&(e=[],q(b,function(b){e.push(D(a,b,c,d))}));return e}function N(a,e,f,g,p){function x(a,b){var c;2>arguments.length&&(b=a,a=s);E&&(c=ca);return p(a,b,c)}var t,I,v,B,R,F,ca={},ob;t=c===f?d:ka(d,new Lb(y(f),d.$attr));I=t.$$element;if(O){var T=/^\s*([@=&])(\??)\s*(\w*)\s*$/;g=y(f);F=e.$new(!0);!ea||ea!==O&&ea!==O.$$originalDirective?g.data("$isolateScopeNoTemplate",F):g.data("$isolateScope",F);
|
||||
ma(g,"ng-isolate-scope");q(O.scope,function(a,c){var d=a.match(T)||[],f=d[3]||c,g="?"==d[2],d=d[1],m,l,n,p;F.$$isolateBindings[c]=d+f;switch(d){case "@":t.$observe(f,function(a){F[c]=a});t.$$observers[f].$$scope=e;t[f]&&(F[c]=b(t[f])(e));break;case "=":if(g&&!t[f])break;l=r(t[f]);p=l.literal?xa:function(a,b){return a===b};n=l.assign||function(){m=F[c]=l(e);throw ia("nonassign",t[f],O.name);};m=F[c]=l(e);F.$watch(function(){var a=l(e);p(a,F[c])||(p(a,m)?n(e,a=F[c]):F[c]=a);return m=a},null,l.literal);
|
||||
break;case "&":l=r(t[f]);F[c]=function(a){return l(e,a)};break;default:throw ia("iscp",O.name,c,a);}})}ob=p&&x;L&&q(L,function(a){var b={$scope:a===O||a.$$isolateScope?F:e,$element:I,$attrs:t,$transclude:ob},c;R=a.controller;"@"==R&&(R=t[a.name]);c=A(R,b);ca[a.name]=c;E||I.data("$"+a.name+"Controller",c);a.controllerAs&&(b.$scope[a.controllerAs]=c)});g=0;for(v=m.length;g<v;g++)try{B=m[g],B(B.isolateScope?F:e,I,t,B.require&&D(B.directiveName,B.require,I,ca),ob)}catch(G){l(G,ha(I))}g=e;O&&(O.template||
|
||||
null===O.templateUrl)&&(g=F);a&&a(g,f.childNodes,s,p);for(g=n.length-1;0<=g;g--)try{B=n[g],B(B.isolateScope?F:e,I,t,B.require&&D(B.directiveName,B.require,I,ca),ob)}catch(z){l(z,ha(I))}}p=p||{};for(var t=-Number.MAX_VALUE,B,L=p.controllerDirectives,O=p.newIsolateScopeDirective,ea=p.templateDirective,T=p.nonTlbTranscludeDirective,H=!1,E=p.hasElementTranscludeDirective,Z=d.$$element=y(c),G,u,W,Za=e,P,M=0,S=a.length;M<S;M++){G=a[M];var ra=G.$$start,X=G.$$end;ra&&(Z=F(c,ra,X));W=s;if(t>G.priority)break;
|
||||
if(W=G.scope)B=B||G,G.templateUrl||(J("new/isolated scope",O,G,Z),U(W)&&(O=G));u=G.name;!G.templateUrl&&G.controller&&(W=G.controller,L=L||{},J("'"+u+"' controller",L[u],G,Z),L[u]=G);if(W=G.transclude)H=!0,G.$$tlb||(J("transclusion",T,G,Z),T=G),"element"==W?(E=!0,t=G.priority,W=F(c,ra,X),Z=d.$$element=y(V.createComment(" "+u+": "+d[u]+" ")),c=Z[0],pb(f,y(ya.call(W,0)),c),Za=v(W,e,t,g&&g.name,{nonTlbTranscludeDirective:T})):(W=y(Jb(c)).contents(),Z.empty(),Za=v(W,e));if(G.template)if(J("template",
|
||||
ea,G,Z),ea=G,W=Q(G.template)?G.template(Z,d):G.template,W=Y(W),G.replace){g=G;W=Hb.test(W)?y(ba(W)):[];c=W[0];if(1!=W.length||1!==c.nodeType)throw ia("tplrt",u,"");pb(f,Z,c);S={$attr:{}};W=ca(c,[],S);var $=a.splice(M+1,a.length-(M+1));O&&tc(W);a=a.concat(W).concat($);z(d,S);S=a.length}else Z.html(W);if(G.templateUrl)J("template",ea,G,Z),ea=G,G.replace&&(g=G),N=w(a.splice(M,a.length-M),Z,d,f,Za,m,n,{controllerDirectives:L,newIsolateScopeDirective:O,templateDirective:ea,nonTlbTranscludeDirective:T}),
|
||||
S=a.length;else if(G.compile)try{P=G.compile(Z,d,Za),Q(P)?x(null,P,ra,X):P&&x(P.pre,P.post,ra,X)}catch(aa){l(aa,ha(Z))}G.terminal&&(N.terminal=!0,t=Math.max(t,G.priority))}N.scope=B&&!0===B.scope;N.transclude=H&&Za;p.hasElementTranscludeDirective=E;return N}function tc(a){for(var b=0,c=a.length;b<c;b++)a[b]=Zb(a[b],{$$isolateScope:!0})}function T(b,e,f,g,k,r,n){if(e===k)return null;k=null;if(c.hasOwnProperty(e)){var p;e=a.get(e+d);for(var A=0,x=e.length;A<x;A++)try{p=e[A],(g===s||g>p.priority)&&-1!=
|
||||
p.restrict.indexOf(f)&&(r&&(p=Zb(p,{$$start:r,$$end:n})),b.push(p),k=p)}catch(D){l(D)}}return k}function z(a,b){var c=b.$attr,d=a.$attr,e=a.$$element;q(a,function(d,e){"$"!=e.charAt(0)&&(b[e]&&b[e]!==d&&(d+=("style"===e?";":" ")+b[e]),a.$set(e,d,!0,c[e]))});q(b,function(b,f){"class"==f?(ma(e,b),a["class"]=(a["class"]?a["class"]+" ":"")+b):"style"==f?(e.attr("style",e.attr("style")+";"+b),a.style=(a.style?a.style+";":"")+b):"$"==f.charAt(0)||a.hasOwnProperty(f)||(a[f]=b,d[f]=c[f])})}function w(a,b,
|
||||
c,d,e,f,g,k){var m=[],l,r,A=b[0],x=a.shift(),D=E({},x,{templateUrl:null,transclude:null,replace:null,$$originalDirective:x}),N=Q(x.templateUrl)?x.templateUrl(b,c):x.templateUrl;b.empty();n.get(t.getTrustedResourceUrl(N),{cache:p}).success(function(n){var p,t;n=Y(n);if(x.replace){n=Hb.test(n)?y(ba(n)):[];p=n[0];if(1!=n.length||1!==p.nodeType)throw ia("tplrt",x.name,N);n={$attr:{}};pb(d,b,p);var v=ca(p,[],n);U(x.scope)&&tc(v);a=v.concat(a);z(c,n)}else p=A,b.html(n);a.unshift(D);l=ea(a,p,c,e,b,x,f,g,
|
||||
k);q(d,function(a,c){a==p&&(d[c]=b[0])});for(r=L(b[0].childNodes,e);m.length;){n=m.shift();t=m.shift();var B=m.shift(),R=m.shift(),v=b[0];if(t!==A){var F=t.className;k.hasElementTranscludeDirective&&x.replace||(v=Jb(p));pb(B,y(t),v);ma(y(v),F)}t=l.transclude?O(n,l.transclude):R;l(r,n,v,d,t)}m=null}).error(function(a,b,c,d){throw ia("tpload",d.url);});return function(a,b,c,d,e){m?(m.push(b),m.push(c),m.push(d),m.push(e)):l(r,b,c,d,e)}}function H(a,b){var c=b.priority-a.priority;return 0!==c?c:a.name!==
|
||||
b.name?a.name<b.name?-1:1:a.index-b.index}function J(a,b,c,d){if(b)throw ia("multidir",b.name,c.name,a,ha(d));}function u(a,c){var d=b(c,!0);d&&a.push({priority:0,compile:aa(function(a,b){var c=b.parent(),e=c.data("$binding")||[];e.push(d);ma(c.data("$binding",e),"ng-binding");a.$watch(d,function(a){b[0].nodeValue=a})})})}function P(a,b){if("srcdoc"==b)return t.HTML;var c=Ka(a);if("xlinkHref"==b||"FORM"==c&&"action"==b||"IMG"!=c&&("src"==b||"ngSrc"==b))return t.RESOURCE_URL}function M(a,c,d,e){var f=
|
||||
b(d,!0);if(f){if("multiple"===e&&"SELECT"===Ka(a))throw ia("selmulti",ha(a));c.push({priority:100,compile:function(){return{pre:function(c,d,m){d=m.$$observers||(m.$$observers={});if(g.test(e))throw ia("nodomevents");if(f=b(m[e],!0,P(a,e)))m[e]=f(c),(d[e]||(d[e]=[])).$$inter=!0,(m.$$observers&&m.$$observers[e].$$scope||c).$watch(f,function(a,b){"class"===e&&a!=b?m.$updateClass(a,b):m.$set(e,a)})}}}})}}function pb(a,b,c){var d=b[0],e=b.length,f=d.parentNode,g,m;if(a)for(g=0,m=a.length;g<m;g++)if(a[g]==
|
||||
d){a[g++]=c;m=g+e-1;for(var k=a.length;g<k;g++,m++)m<k?a[g]=a[m]:delete a[g];a.length-=e-1;break}f&&f.replaceChild(c,d);a=V.createDocumentFragment();a.appendChild(d);c[y.expando]=d[y.expando];d=1;for(e=b.length;d<e;d++)f=b[d],y(f).remove(),a.appendChild(f),delete b[d];b[0]=c;b.length=1}function uc(a,b){return E(function(){return a.apply(null,arguments)},a,b)}var Lb=function(a,b){this.$$element=a;this.$attr=b||{}};Lb.prototype={$normalize:na,$addClass:function(a){a&&0<a.length&&N.addClass(this.$$element,
|
||||
a)},$removeClass:function(a){a&&0<a.length&&N.removeClass(this.$$element,a)},$updateClass:function(a,b){var c=vc(a,b),d=vc(b,a);0===c.length?N.removeClass(this.$$element,d):0===d.length?N.addClass(this.$$element,c):N.setClass(this.$$element,c,d)},$set:function(a,b,c,d){var e=qc(this.$$element[0],a);e&&(this.$$element.prop(a,b),d=e);this[a]=b;d?this.$attr[a]=d:(d=this.$attr[a])||(this.$attr[a]=d=ib(a,"-"));e=Ka(this.$$element);if("A"===e&&"href"===a||"IMG"===e&&"src"===a)this[a]=b=B(b,"src"===a);!1!==
|
||||
c&&(null===b||b===s?this.$$element.removeAttr(d):this.$$element.attr(d,b));(c=this.$$observers)&&q(c[a],function(a){try{a(b)}catch(c){l(c)}})},$observe:function(a,b){var c=this,d=c.$$observers||(c.$$observers={}),e=d[a]||(d[a]=[]);e.push(b);D.$evalAsync(function(){e.$$inter||b(c[a])});return b}};var Z=b.startSymbol(),ra=b.endSymbol(),Y="{{"==Z||"}}"==ra?Ea:function(a){return a.replace(/\{\{/g,Z).replace(/}}/g,ra)},X=/^ngAttr[A-Z]/;return v}]}function na(b){return Ua(b.replace(te,""))}function vc(b,
|
||||
a){var c="",d=b.split(/\s+/),e=a.split(/\s+/),f=0;a:for(;f<d.length;f++){for(var g=d[f],h=0;h<e.length;h++)if(g==e[h])continue a;c+=(0<c.length?" ":"")+g}return c}function Od(){var b={},a=/^(\S+)(\s+as\s+(\w+))?$/;this.register=function(a,d){Aa(a,"controller");U(a)?E(b,a):b[a]=d};this.$get=["$injector","$window",function(c,d){return function(e,f){var g,h,m;C(e)&&(g=e.match(a),h=g[1],m=g[3],e=b.hasOwnProperty(h)?b[h]:fc(f.$scope,h,!0)||fc(d,h,!0),Sa(e,h,!0));g=c.instantiate(e,f);if(m){if(!f||"object"!=
|
||||
typeof f.$scope)throw u("$controller")("noscp",h||e.name,m);f.$scope[m]=g}return g}}]}function Pd(){this.$get=["$window",function(b){return y(b.document)}]}function Qd(){this.$get=["$log",function(b){return function(a,c){b.error.apply(b,arguments)}}]}function wc(b){var a={},c,d,e;if(!b)return a;q(b.split("\n"),function(b){e=b.indexOf(":");c=J(ba(b.substr(0,e)));d=ba(b.substr(e+1));c&&(a[c]=a[c]?a[c]+(", "+d):d)});return a}function xc(b){var a=U(b)?b:s;return function(c){a||(a=wc(b));return c?a[J(c)]||
|
||||
null:a}}function yc(b,a,c){if(Q(c))return c(b,a);q(c,function(c){b=c(b,a)});return b}function Td(){var b=/^\s*(\[|\{[^\{])/,a=/[\}\]]\s*$/,c=/^\)\]\}',?\n/,d={"Content-Type":"application/json;charset=utf-8"},e=this.defaults={transformResponse:[function(d){C(d)&&(d=d.replace(c,""),b.test(d)&&a.test(d)&&(d=ac(d)));return d}],transformRequest:[function(a){return U(a)&&"[object File]"!==wa.call(a)&&"[object Blob]"!==wa.call(a)?qa(a):a}],headers:{common:{Accept:"application/json, text/plain, */*"},post:ka(d),
|
||||
put:ka(d),patch:ka(d)},xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN"},f=this.interceptors=[],g=this.responseInterceptors=[];this.$get=["$httpBackend","$browser","$cacheFactory","$rootScope","$q","$injector",function(a,b,c,d,n,p){function r(a){function c(a){var b=E({},a,{data:yc(a.data,a.headers,d.transformResponse)});return 200<=a.status&&300>a.status?b:n.reject(b)}var d={method:"get",transformRequest:e.transformRequest,transformResponse:e.transformResponse},f=function(a){function b(a){var c;
|
||||
q(a,function(b,d){Q(b)&&(c=b(),null!=c?a[d]=c:delete a[d])})}var c=e.headers,d=E({},a.headers),f,g,c=E({},c.common,c[J(a.method)]);b(c);b(d);a:for(f in c){a=J(f);for(g in d)if(J(g)===a)continue a;d[f]=c[f]}return d}(a);E(d,a);d.headers=f;d.method=Ga(d.method);(a=Mb(d.url)?b.cookies()[d.xsrfCookieName||e.xsrfCookieName]:s)&&(f[d.xsrfHeaderName||e.xsrfHeaderName]=a);var g=[function(a){f=a.headers;var b=yc(a.data,xc(f),a.transformRequest);H(a.data)&&q(f,function(a,b){"content-type"===J(b)&&delete f[b]});
|
||||
H(a.withCredentials)&&!H(e.withCredentials)&&(a.withCredentials=e.withCredentials);return A(a,b,f).then(c,c)},s],h=n.when(d);for(q(t,function(a){(a.request||a.requestError)&&g.unshift(a.request,a.requestError);(a.response||a.responseError)&&g.push(a.response,a.responseError)});g.length;){a=g.shift();var k=g.shift(),h=h.then(a,k)}h.success=function(a){h.then(function(b){a(b.data,b.status,b.headers,d)});return h};h.error=function(a){h.then(null,function(b){a(b.data,b.status,b.headers,d)});return h};
|
||||
return h}function A(b,c,f){function g(a,b,c,e){t&&(200<=a&&300>a?t.put(s,[a,b,wc(c),e]):t.remove(s));m(b,a,c,e);d.$$phase||d.$apply()}function m(a,c,d,e){c=Math.max(c,0);(200<=c&&300>c?p.resolve:p.reject)({data:a,status:c,headers:xc(d),config:b,statusText:e})}function k(){var a=Na(r.pendingRequests,b);-1!==a&&r.pendingRequests.splice(a,1)}var p=n.defer(),A=p.promise,t,q,s=D(b.url,b.params);r.pendingRequests.push(b);A.then(k,k);(b.cache||e.cache)&&(!1!==b.cache&&"GET"==b.method)&&(t=U(b.cache)?b.cache:
|
||||
U(e.cache)?e.cache:x);if(t)if(q=t.get(s),z(q)){if(q.then)return q.then(k,k),q;K(q)?m(q[1],q[0],ka(q[2]),q[3]):m(q,200,{},"OK")}else t.put(s,A);H(q)&&a(b.method,s,c,g,f,b.timeout,b.withCredentials,b.responseType);return A}function D(a,b){if(!b)return a;var c=[];Sc(b,function(a,b){null===a||H(a)||(K(a)||(a=[a]),q(a,function(a){U(a)&&(a=qa(a));c.push(za(b)+"="+za(a))}))});0<c.length&&(a+=(-1==a.indexOf("?")?"?":"&")+c.join("&"));return a}var x=c("$http"),t=[];q(f,function(a){t.unshift(C(a)?p.get(a):
|
||||
p.invoke(a))});q(g,function(a,b){var c=C(a)?p.get(a):p.invoke(a);t.splice(b,0,{response:function(a){return c(n.when(a))},responseError:function(a){return c(n.reject(a))}})});r.pendingRequests=[];(function(a){q(arguments,function(a){r[a]=function(b,c){return r(E(c||{},{method:a,url:b}))}})})("get","delete","head","jsonp");(function(a){q(arguments,function(a){r[a]=function(b,c,d){return r(E(d||{},{method:a,url:b,data:c}))}})})("post","put");r.defaults=e;return r}]}function ue(b){if(8>=S&&(!b.match(/^(get|post|head|put|delete|options)$/i)||
|
||||
!P.XMLHttpRequest))return new P.ActiveXObject("Microsoft.XMLHTTP");if(P.XMLHttpRequest)return new P.XMLHttpRequest;throw u("$httpBackend")("noxhr");}function Ud(){this.$get=["$browser","$window","$document",function(b,a,c){return ve(b,ue,b.defer,a.angular.callbacks,c[0])}]}function ve(b,a,c,d,e){function f(a,b,c){var f=e.createElement("script"),g=null;f.type="text/javascript";f.src=a;f.async=!0;g=function(a){Va(f,"load",g);Va(f,"error",g);e.body.removeChild(f);f=null;var h=-1,A="unknown";a&&("load"!==
|
||||
a.type||d[b].called||(a={type:"error"}),A=a.type,h="error"===a.type?404:200);c&&c(h,A)};qb(f,"load",g);qb(f,"error",g);8>=S&&(f.onreadystatechange=function(){C(f.readyState)&&/loaded|complete/.test(f.readyState)&&(f.onreadystatechange=null,g({type:"load"}))});e.body.appendChild(f);return g}var g=-1;return function(e,m,k,l,n,p,r,A){function D(){t=g;B&&B();v&&v.abort()}function x(a,d,e,f,g){L&&c.cancel(L);B=v=null;0===d&&(d=e?200:"file"==sa(m).protocol?404:0);a(1223===d?204:d,e,f,g||"");b.$$completeOutstandingRequest(w)}
|
||||
var t;b.$$incOutstandingRequestCount();m=m||b.url();if("jsonp"==J(e)){var N="_"+(d.counter++).toString(36);d[N]=function(a){d[N].data=a;d[N].called=!0};var B=f(m.replace("JSON_CALLBACK","angular.callbacks."+N),N,function(a,b){x(l,a,d[N].data,"",b);d[N]=w})}else{var v=a(e);v.open(e,m,!0);q(n,function(a,b){z(a)&&v.setRequestHeader(b,a)});v.onreadystatechange=function(){if(v&&4==v.readyState){var a=null,b=null;t!==g&&(a=v.getAllResponseHeaders(),b="response"in v?v.response:v.responseText);x(l,t||v.status,
|
||||
b,a,v.statusText||"")}};r&&(v.withCredentials=!0);if(A)try{v.responseType=A}catch(s){if("json"!==A)throw s;}v.send(k||null)}if(0<p)var L=c(D,p);else p&&p.then&&p.then(D)}}function Rd(){var b="{{",a="}}";this.startSymbol=function(a){return a?(b=a,this):b};this.endSymbol=function(b){return b?(a=b,this):a};this.$get=["$parse","$exceptionHandler","$sce",function(c,d,e){function f(f,k,l){for(var n,p,r=0,A=[],D=f.length,x=!1,t=[];r<D;)-1!=(n=f.indexOf(b,r))&&-1!=(p=f.indexOf(a,n+g))?(r!=n&&A.push(f.substring(r,
|
||||
n)),A.push(r=c(x=f.substring(n+g,p))),r.exp=x,r=p+h,x=!0):(r!=D&&A.push(f.substring(r)),r=D);(D=A.length)||(A.push(""),D=1);if(l&&1<A.length)throw zc("noconcat",f);if(!k||x)return t.length=D,r=function(a){try{for(var b=0,c=D,g;b<c;b++){if("function"==typeof(g=A[b]))if(g=g(a),g=l?e.getTrusted(l,g):e.valueOf(g),null==g)g="";else switch(typeof g){case "string":break;case "number":g=""+g;break;default:g=qa(g)}t[b]=g}return t.join("")}catch(h){a=zc("interr",f,h.toString()),d(a)}},r.exp=f,r.parts=A,r}var g=
|
||||
b.length,h=a.length;f.startSymbol=function(){return b};f.endSymbol=function(){return a};return f}]}function Sd(){this.$get=["$rootScope","$window","$q",function(b,a,c){function d(d,g,h,m){var k=a.setInterval,l=a.clearInterval,n=c.defer(),p=n.promise,r=0,A=z(m)&&!m;h=z(h)?h:0;p.then(null,null,d);p.$$intervalId=k(function(){n.notify(r++);0<h&&r>=h&&(n.resolve(r),l(p.$$intervalId),delete e[p.$$intervalId]);A||b.$apply()},g);e[p.$$intervalId]=n;return p}var e={};d.cancel=function(a){return a&&a.$$intervalId in
|
||||
e?(e[a.$$intervalId].reject("canceled"),clearInterval(a.$$intervalId),delete e[a.$$intervalId],!0):!1};return d}]}function ad(){this.$get=function(){return{id:"en-us",NUMBER_FORMATS:{DECIMAL_SEP:".",GROUP_SEP:",",PATTERNS:[{minInt:1,minFrac:0,maxFrac:3,posPre:"",posSuf:"",negPre:"-",negSuf:"",gSize:3,lgSize:3},{minInt:1,minFrac:2,maxFrac:2,posPre:"\u00a4",posSuf:"",negPre:"(\u00a4",negSuf:")",gSize:3,lgSize:3}],CURRENCY_SYM:"$"},DATETIME_FORMATS:{MONTH:"January February March April May June July August September October November December".split(" "),
|
||||
SHORTMONTH:"Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" "),DAY:"Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" "),SHORTDAY:"Sun Mon Tue Wed Thu Fri Sat".split(" "),AMPMS:["AM","PM"],medium:"MMM d, y h:mm:ss a","short":"M/d/yy h:mm a",fullDate:"EEEE, MMMM d, y",longDate:"MMMM d, y",mediumDate:"MMM d, y",shortDate:"M/d/yy",mediumTime:"h:mm:ss a",shortTime:"h:mm a"},pluralCat:function(b){return 1===b?"one":"other"}}}}function Nb(b){b=b.split("/");for(var a=b.length;a--;)b[a]=
|
||||
hb(b[a]);return b.join("/")}function Ac(b,a,c){b=sa(b,c);a.$$protocol=b.protocol;a.$$host=b.hostname;a.$$port=Y(b.port)||we[b.protocol]||null}function Bc(b,a,c){var d="/"!==b.charAt(0);d&&(b="/"+b);b=sa(b,c);a.$$path=decodeURIComponent(d&&"/"===b.pathname.charAt(0)?b.pathname.substring(1):b.pathname);a.$$search=cc(b.search);a.$$hash=decodeURIComponent(b.hash);a.$$path&&"/"!=a.$$path.charAt(0)&&(a.$$path="/"+a.$$path)}function oa(b,a){if(0===a.indexOf(b))return a.substr(b.length)}function $a(b){var a=
|
||||
b.indexOf("#");return-1==a?b:b.substr(0,a)}function Ob(b){return b.substr(0,$a(b).lastIndexOf("/")+1)}function Cc(b,a){this.$$html5=!0;a=a||"";var c=Ob(b);Ac(b,this,b);this.$$parse=function(a){var e=oa(c,a);if(!C(e))throw Pb("ipthprfx",a,c);Bc(e,this,b);this.$$path||(this.$$path="/");this.$$compose()};this.$$compose=function(){var a=Bb(this.$$search),b=this.$$hash?"#"+hb(this.$$hash):"";this.$$url=Nb(this.$$path)+(a?"?"+a:"")+b;this.$$absUrl=c+this.$$url.substr(1)};this.$$rewrite=function(d){var e;
|
||||
if((e=oa(b,d))!==s)return d=e,(e=oa(a,e))!==s?c+(oa("/",e)||e):b+d;if((e=oa(c,d))!==s)return c+e;if(c==d+"/")return c}}function Qb(b,a){var c=Ob(b);Ac(b,this,b);this.$$parse=function(d){var e=oa(b,d)||oa(c,d),e="#"==e.charAt(0)?oa(a,e):this.$$html5?e:"";if(!C(e))throw Pb("ihshprfx",d,a);Bc(e,this,b);d=this.$$path;var f=/^\/[A-Z]:(\/.*)/;0===e.indexOf(b)&&(e=e.replace(b,""));f.exec(e)||(d=(e=f.exec(d))?e[1]:d);this.$$path=d;this.$$compose()};this.$$compose=function(){var c=Bb(this.$$search),e=this.$$hash?
|
||||
"#"+hb(this.$$hash):"";this.$$url=Nb(this.$$path)+(c?"?"+c:"")+e;this.$$absUrl=b+(this.$$url?a+this.$$url:"")};this.$$rewrite=function(a){if($a(b)==$a(a))return a}}function Rb(b,a){this.$$html5=!0;Qb.apply(this,arguments);var c=Ob(b);this.$$rewrite=function(d){var e;if(b==$a(d))return d;if(e=oa(c,d))return b+a+e;if(c===d+"/")return c};this.$$compose=function(){var c=Bb(this.$$search),e=this.$$hash?"#"+hb(this.$$hash):"";this.$$url=Nb(this.$$path)+(c?"?"+c:"")+e;this.$$absUrl=b+a+this.$$url}}function rb(b){return function(){return this[b]}}
|
||||
function Dc(b,a){return function(c){if(H(c))return this[b];this[b]=a(c);this.$$compose();return this}}function Vd(){var b="",a=!1;this.hashPrefix=function(a){return z(a)?(b=a,this):b};this.html5Mode=function(b){return z(b)?(a=b,this):a};this.$get=["$rootScope","$browser","$sniffer","$rootElement",function(c,d,e,f){function g(a){c.$broadcast("$locationChangeSuccess",h.absUrl(),a)}var h,m,k=d.baseHref(),l=d.url(),n;a?(n=l.substring(0,l.indexOf("/",l.indexOf("//")+2))+(k||"/"),m=e.history?Cc:Rb):(n=
|
||||
$a(l),m=Qb);h=new m(n,"#"+b);h.$$parse(h.$$rewrite(l));f.on("click",function(a){if(!a.ctrlKey&&!a.metaKey&&2!=a.which){for(var e=y(a.target);"a"!==J(e[0].nodeName);)if(e[0]===f[0]||!(e=e.parent())[0])return;var g=e.prop("href");U(g)&&"[object SVGAnimatedString]"===g.toString()&&(g=sa(g.animVal).href);if(m===Rb){var k=e.attr("href")||e.attr("xlink:href");if(0>k.indexOf("://"))if(g="#"+b,"/"==k[0])g=n+g+k;else if("#"==k[0])g=n+g+(h.path()||"/")+k;else{for(var l=h.path().split("/"),k=k.split("/"),p=
|
||||
0;p<k.length;p++)"."!=k[p]&&(".."==k[p]?l.pop():k[p].length&&l.push(k[p]));g=n+g+l.join("/")}}l=h.$$rewrite(g);g&&(!e.attr("target")&&l&&!a.isDefaultPrevented())&&(a.preventDefault(),l!=d.url()&&(h.$$parse(l),c.$apply(),P.angular["ff-684208-preventDefault"]=!0))}});h.absUrl()!=l&&d.url(h.absUrl(),!0);d.onUrlChange(function(a){h.absUrl()!=a&&(c.$evalAsync(function(){var b=h.absUrl();h.$$parse(a);c.$broadcast("$locationChangeStart",a,b).defaultPrevented?(h.$$parse(b),d.url(b)):g(b)}),c.$$phase||c.$digest())});
|
||||
var p=0;c.$watch(function(){var a=d.url(),b=h.$$replace;p&&a==h.absUrl()||(p++,c.$evalAsync(function(){c.$broadcast("$locationChangeStart",h.absUrl(),a).defaultPrevented?h.$$parse(a):(d.url(h.absUrl(),b),g(a))}));h.$$replace=!1;return p});return h}]}function Wd(){var b=!0,a=this;this.debugEnabled=function(a){return z(a)?(b=a,this):b};this.$get=["$window",function(c){function d(a){a instanceof Error&&(a.stack?a=a.message&&-1===a.stack.indexOf(a.message)?"Error: "+a.message+"\n"+a.stack:a.stack:a.sourceURL&&
|
||||
(a=a.message+"\n"+a.sourceURL+":"+a.line));return a}function e(a){var b=c.console||{},e=b[a]||b.log||w;a=!1;try{a=!!e.apply}catch(m){}return a?function(){var a=[];q(arguments,function(b){a.push(d(b))});return e.apply(b,a)}:function(a,b){e(a,null==b?"":b)}}return{log:e("log"),info:e("info"),warn:e("warn"),error:e("error"),debug:function(){var c=e("debug");return function(){b&&c.apply(a,arguments)}}()}}]}function fa(b,a){if("constructor"===b)throw Ca("isecfld",a);return b}function ab(b,a){if(b){if(b.constructor===
|
||||
b)throw Ca("isecfn",a);if(b.document&&b.location&&b.alert&&b.setInterval)throw Ca("isecwindow",a);if(b.children&&(b.nodeName||b.prop&&b.attr&&b.find))throw Ca("isecdom",a);}return b}function sb(b,a,c,d,e){e=e||{};a=a.split(".");for(var f,g=0;1<a.length;g++){f=fa(a.shift(),d);var h=b[f];h||(h={},b[f]=h);b=h;b.then&&e.unwrapPromises&&(ta(d),"$$v"in b||function(a){a.then(function(b){a.$$v=b})}(b),b.$$v===s&&(b.$$v={}),b=b.$$v)}f=fa(a.shift(),d);return b[f]=c}function Ec(b,a,c,d,e,f,g){fa(b,f);fa(a,f);
|
||||
fa(c,f);fa(d,f);fa(e,f);return g.unwrapPromises?function(g,m){var k=m&&m.hasOwnProperty(b)?m:g,l;if(null==k)return k;(k=k[b])&&k.then&&(ta(f),"$$v"in k||(l=k,l.$$v=s,l.then(function(a){l.$$v=a})),k=k.$$v);if(!a)return k;if(null==k)return s;(k=k[a])&&k.then&&(ta(f),"$$v"in k||(l=k,l.$$v=s,l.then(function(a){l.$$v=a})),k=k.$$v);if(!c)return k;if(null==k)return s;(k=k[c])&&k.then&&(ta(f),"$$v"in k||(l=k,l.$$v=s,l.then(function(a){l.$$v=a})),k=k.$$v);if(!d)return k;if(null==k)return s;(k=k[d])&&k.then&&
|
||||
(ta(f),"$$v"in k||(l=k,l.$$v=s,l.then(function(a){l.$$v=a})),k=k.$$v);if(!e)return k;if(null==k)return s;(k=k[e])&&k.then&&(ta(f),"$$v"in k||(l=k,l.$$v=s,l.then(function(a){l.$$v=a})),k=k.$$v);return k}:function(f,g){var k=g&&g.hasOwnProperty(b)?g:f;if(null==k)return k;k=k[b];if(!a)return k;if(null==k)return s;k=k[a];if(!c)return k;if(null==k)return s;k=k[c];if(!d)return k;if(null==k)return s;k=k[d];return e?null==k?s:k=k[e]:k}}function xe(b,a){fa(b,a);return function(a,d){return null==a?s:(d&&d.hasOwnProperty(b)?
|
||||
d:a)[b]}}function ye(b,a,c){fa(b,c);fa(a,c);return function(c,e){if(null==c)return s;c=(e&&e.hasOwnProperty(b)?e:c)[b];return null==c?s:c[a]}}function Fc(b,a,c){if(Sb.hasOwnProperty(b))return Sb[b];var d=b.split("."),e=d.length,f;if(a.unwrapPromises||1!==e)if(a.unwrapPromises||2!==e)if(a.csp)f=6>e?Ec(d[0],d[1],d[2],d[3],d[4],c,a):function(b,f){var g=0,h;do h=Ec(d[g++],d[g++],d[g++],d[g++],d[g++],c,a)(b,f),f=s,b=h;while(g<e);return h};else{var g="var p;\n";q(d,function(b,d){fa(b,c);g+="if(s == null) return undefined;\ns="+
|
||||
(d?"s":'((k&&k.hasOwnProperty("'+b+'"))?k:s)')+'["'+b+'"];\n'+(a.unwrapPromises?'if (s && s.then) {\n pw("'+c.replace(/(["\r\n])/g,"\\$1")+'");\n if (!("$$v" in s)) {\n p=s;\n p.$$v = undefined;\n p.then(function(v) {p.$$v=v;});\n}\n s=s.$$v\n}\n':"")});var g=g+"return s;",h=new Function("s","k","pw",g);h.toString=aa(g);f=a.unwrapPromises?function(a,b){return h(a,b,ta)}:h}else f=ye(d[0],d[1],c);else f=xe(d[0],c);"hasOwnProperty"!==b&&(Sb[b]=f);return f}function Xd(){var b={},a={csp:!1,unwrapPromises:!1,
|
||||
logPromiseWarnings:!0};this.unwrapPromises=function(b){return z(b)?(a.unwrapPromises=!!b,this):a.unwrapPromises};this.logPromiseWarnings=function(b){return z(b)?(a.logPromiseWarnings=b,this):a.logPromiseWarnings};this.$get=["$filter","$sniffer","$log",function(c,d,e){a.csp=d.csp;ta=function(b){a.logPromiseWarnings&&!Gc.hasOwnProperty(b)&&(Gc[b]=!0,e.warn("[$parse] Promise found in the expression `"+b+"`. Automatic unwrapping of promises in Angular expressions is deprecated."))};return function(d){var e;
|
||||
switch(typeof d){case "string":if(b.hasOwnProperty(d))return b[d];e=new Tb(a);e=(new bb(e,c,a)).parse(d);"hasOwnProperty"!==d&&(b[d]=e);return e;case "function":return d;default:return w}}}]}function Zd(){this.$get=["$rootScope","$exceptionHandler",function(b,a){return ze(function(a){b.$evalAsync(a)},a)}]}function ze(b,a){function c(a){return a}function d(a){return g(a)}var e=function(){var g=[],k,l;return l={resolve:function(a){if(g){var c=g;g=s;k=f(a);c.length&&b(function(){for(var a,b=0,d=c.length;b<
|
||||
d;b++)a=c[b],k.then(a[0],a[1],a[2])})}},reject:function(a){l.resolve(h(a))},notify:function(a){if(g){var c=g;g.length&&b(function(){for(var b,d=0,e=c.length;d<e;d++)b=c[d],b[2](a)})}},promise:{then:function(b,f,h){var l=e(),D=function(d){try{l.resolve((Q(b)?b:c)(d))}catch(e){l.reject(e),a(e)}},x=function(b){try{l.resolve((Q(f)?f:d)(b))}catch(c){l.reject(c),a(c)}},t=function(b){try{l.notify((Q(h)?h:c)(b))}catch(d){a(d)}};g?g.push([D,x,t]):k.then(D,x,t);return l.promise},"catch":function(a){return this.then(null,
|
||||
a)},"finally":function(a){function b(a,c){var d=e();c?d.resolve(a):d.reject(a);return d.promise}function d(e,f){var g=null;try{g=(a||c)()}catch(h){return b(h,!1)}return g&&Q(g.then)?g.then(function(){return b(e,f)},function(a){return b(a,!1)}):b(e,f)}return this.then(function(a){return d(a,!0)},function(a){return d(a,!1)})}}}},f=function(a){return a&&Q(a.then)?a:{then:function(c){var d=e();b(function(){d.resolve(c(a))});return d.promise}}},g=function(a){var b=e();b.reject(a);return b.promise},h=function(c){return{then:function(f,
|
||||
g){var h=e();b(function(){try{h.resolve((Q(g)?g:d)(c))}catch(b){h.reject(b),a(b)}});return h.promise}}};return{defer:e,reject:g,when:function(h,k,l,n){var p=e(),r,A=function(b){try{return(Q(k)?k:c)(b)}catch(d){return a(d),g(d)}},D=function(b){try{return(Q(l)?l:d)(b)}catch(c){return a(c),g(c)}},x=function(b){try{return(Q(n)?n:c)(b)}catch(d){a(d)}};b(function(){f(h).then(function(a){r||(r=!0,p.resolve(f(a).then(A,D,x)))},function(a){r||(r=!0,p.resolve(D(a)))},function(a){r||p.notify(x(a))})});return p.promise},
|
||||
all:function(a){var b=e(),c=0,d=K(a)?[]:{};q(a,function(a,e){c++;f(a).then(function(a){d.hasOwnProperty(e)||(d[e]=a,--c||b.resolve(d))},function(a){d.hasOwnProperty(e)||b.reject(a)})});0===c&&b.resolve(d);return b.promise}}}function fe(){this.$get=["$window","$timeout",function(b,a){var c=b.requestAnimationFrame||b.webkitRequestAnimationFrame||b.mozRequestAnimationFrame,d=b.cancelAnimationFrame||b.webkitCancelAnimationFrame||b.mozCancelAnimationFrame||b.webkitCancelRequestAnimationFrame,e=!!c,f=e?
|
||||
function(a){var b=c(a);return function(){d(b)}}:function(b){var c=a(b,16.66,!1);return function(){a.cancel(c)}};f.supported=e;return f}]}function Yd(){var b=10,a=u("$rootScope"),c=null;this.digestTtl=function(a){arguments.length&&(b=a);return b};this.$get=["$injector","$exceptionHandler","$parse","$browser",function(d,e,f,g){function h(){this.$id=eb();this.$$phase=this.$parent=this.$$watchers=this.$$nextSibling=this.$$prevSibling=this.$$childHead=this.$$childTail=null;this["this"]=this.$root=this;
|
||||
this.$$destroyed=!1;this.$$asyncQueue=[];this.$$postDigestQueue=[];this.$$listeners={};this.$$listenerCount={};this.$$isolateBindings={}}function m(b){if(p.$$phase)throw a("inprog",p.$$phase);p.$$phase=b}function k(a,b){var c=f(a);Sa(c,b);return c}function l(a,b,c){do a.$$listenerCount[c]-=b,0===a.$$listenerCount[c]&&delete a.$$listenerCount[c];while(a=a.$parent)}function n(){}h.prototype={constructor:h,$new:function(a){a?(a=new h,a.$root=this.$root,a.$$asyncQueue=this.$$asyncQueue,a.$$postDigestQueue=
|
||||
this.$$postDigestQueue):(this.$$childScopeClass||(this.$$childScopeClass=function(){this.$$watchers=this.$$nextSibling=this.$$childHead=this.$$childTail=null;this.$$listeners={};this.$$listenerCount={};this.$id=eb();this.$$childScopeClass=null},this.$$childScopeClass.prototype=this),a=new this.$$childScopeClass);a["this"]=a;a.$parent=this;a.$$prevSibling=this.$$childTail;this.$$childHead?this.$$childTail=this.$$childTail.$$nextSibling=a:this.$$childHead=this.$$childTail=a;return a},$watch:function(a,
|
||||
b,d){var e=k(a,"watch"),f=this.$$watchers,g={fn:b,last:n,get:e,exp:a,eq:!!d};c=null;if(!Q(b)){var h=k(b||w,"listener");g.fn=function(a,b,c){h(c)}}if("string"==typeof a&&e.constant){var m=g.fn;g.fn=function(a,b,c){m.call(this,a,b,c);Oa(f,g)}}f||(f=this.$$watchers=[]);f.unshift(g);return function(){Oa(f,g);c=null}},$watchCollection:function(a,b){var c=this,d,e,g,h=1<b.length,k=0,m=f(a),l=[],n={},p=!0,q=0;return this.$watch(function(){d=m(c);var a,b;if(U(d))if(db(d))for(e!==l&&(e=l,q=e.length=0,k++),
|
||||
a=d.length,q!==a&&(k++,e.length=q=a),b=0;b<a;b++)e[b]!==e[b]&&d[b]!==d[b]||e[b]===d[b]||(k++,e[b]=d[b]);else{e!==n&&(e=n={},q=0,k++);a=0;for(b in d)d.hasOwnProperty(b)&&(a++,e.hasOwnProperty(b)?e[b]!==d[b]&&(k++,e[b]=d[b]):(q++,e[b]=d[b],k++));if(q>a)for(b in k++,e)e.hasOwnProperty(b)&&!d.hasOwnProperty(b)&&(q--,delete e[b])}else e!==d&&(e=d,k++);return k},function(){p?(p=!1,b(d,d,c)):b(d,g,c);if(h)if(U(d))if(db(d)){g=Array(d.length);for(var a=0;a<d.length;a++)g[a]=d[a]}else for(a in g={},d)Ab.call(d,
|
||||
a)&&(g[a]=d[a]);else g=d})},$digest:function(){var d,f,g,h,k=this.$$asyncQueue,l=this.$$postDigestQueue,q,v,s=b,L,O=[],y,F,R;m("$digest");c=null;do{v=!1;for(L=this;k.length;){try{R=k.shift(),R.scope.$eval(R.expression)}catch(z){p.$$phase=null,e(z)}c=null}a:do{if(h=L.$$watchers)for(q=h.length;q--;)try{if(d=h[q])if((f=d.get(L))!==(g=d.last)&&!(d.eq?xa(f,g):"number"==typeof f&&"number"==typeof g&&isNaN(f)&&isNaN(g)))v=!0,c=d,d.last=d.eq?Fa(f,null):f,d.fn(f,g===n?f:g,L),5>s&&(y=4-s,O[y]||(O[y]=[]),F=
|
||||
Q(d.exp)?"fn: "+(d.exp.name||d.exp.toString()):d.exp,F+="; newVal: "+qa(f)+"; oldVal: "+qa(g),O[y].push(F));else if(d===c){v=!1;break a}}catch(C){p.$$phase=null,e(C)}if(!(h=L.$$childHead||L!==this&&L.$$nextSibling))for(;L!==this&&!(h=L.$$nextSibling);)L=L.$parent}while(L=h);if((v||k.length)&&!s--)throw p.$$phase=null,a("infdig",b,qa(O));}while(v||k.length);for(p.$$phase=null;l.length;)try{l.shift()()}catch(T){e(T)}},$destroy:function(){if(!this.$$destroyed){var a=this.$parent;this.$broadcast("$destroy");
|
||||
this.$$destroyed=!0;this!==p&&(q(this.$$listenerCount,gb(null,l,this)),a.$$childHead==this&&(a.$$childHead=this.$$nextSibling),a.$$childTail==this&&(a.$$childTail=this.$$prevSibling),this.$$prevSibling&&(this.$$prevSibling.$$nextSibling=this.$$nextSibling),this.$$nextSibling&&(this.$$nextSibling.$$prevSibling=this.$$prevSibling),this.$parent=this.$$nextSibling=this.$$prevSibling=this.$$childHead=this.$$childTail=this.$root=null,this.$$listeners={},this.$$watchers=this.$$asyncQueue=this.$$postDigestQueue=
|
||||
[],this.$destroy=this.$digest=this.$apply=w,this.$on=this.$watch=function(){return w})}},$eval:function(a,b){return f(a)(this,b)},$evalAsync:function(a){p.$$phase||p.$$asyncQueue.length||g.defer(function(){p.$$asyncQueue.length&&p.$digest()});this.$$asyncQueue.push({scope:this,expression:a})},$$postDigest:function(a){this.$$postDigestQueue.push(a)},$apply:function(a){try{return m("$apply"),this.$eval(a)}catch(b){e(b)}finally{p.$$phase=null;try{p.$digest()}catch(c){throw e(c),c;}}},$on:function(a,
|
||||
b){var c=this.$$listeners[a];c||(this.$$listeners[a]=c=[]);c.push(b);var d=this;do d.$$listenerCount[a]||(d.$$listenerCount[a]=0),d.$$listenerCount[a]++;while(d=d.$parent);var e=this;return function(){c[Na(c,b)]=null;l(e,1,a)}},$emit:function(a,b){var c=[],d,f=this,g=!1,h={name:a,targetScope:f,stopPropagation:function(){g=!0},preventDefault:function(){h.defaultPrevented=!0},defaultPrevented:!1},k=[h].concat(ya.call(arguments,1)),m,l;do{d=f.$$listeners[a]||c;h.currentScope=f;m=0;for(l=d.length;m<l;m++)if(d[m])try{d[m].apply(null,
|
||||
k)}catch(n){e(n)}else d.splice(m,1),m--,l--;if(g)break;f=f.$parent}while(f);return h},$broadcast:function(a,b){for(var c=this,d=this,f={name:a,targetScope:this,preventDefault:function(){f.defaultPrevented=!0},defaultPrevented:!1},g=[f].concat(ya.call(arguments,1)),h,k;c=d;){f.currentScope=c;d=c.$$listeners[a]||[];h=0;for(k=d.length;h<k;h++)if(d[h])try{d[h].apply(null,g)}catch(m){e(m)}else d.splice(h,1),h--,k--;if(!(d=c.$$listenerCount[a]&&c.$$childHead||c!==this&&c.$$nextSibling))for(;c!==this&&!(d=
|
||||
c.$$nextSibling);)c=c.$parent}return f}};var p=new h;return p}]}function bd(){var b=/^\s*(https?|ftp|mailto|tel|file):/,a=/^\s*(https?|ftp|file):|data:image\//;this.aHrefSanitizationWhitelist=function(a){return z(a)?(b=a,this):b};this.imgSrcSanitizationWhitelist=function(b){return z(b)?(a=b,this):a};this.$get=function(){return function(c,d){var e=d?a:b,f;if(!S||8<=S)if(f=sa(c).href,""!==f&&!f.match(e))return"unsafe:"+f;return c}}}function Ae(b){if("self"===b)return b;if(C(b)){if(-1<b.indexOf("***"))throw ua("iwcard",
|
||||
b);b=b.replace(/([-()\[\]{}+?*.$\^|,:#<!\\])/g,"\\$1").replace(/\x08/g,"\\x08").replace("\\*\\*",".*").replace("\\*","[^:/.?&;]*");return RegExp("^"+b+"$")}if(fb(b))return RegExp("^"+b.source+"$");throw ua("imatcher");}function Hc(b){var a=[];z(b)&&q(b,function(b){a.push(Ae(b))});return a}function ae(){this.SCE_CONTEXTS=ga;var b=["self"],a=[];this.resourceUrlWhitelist=function(a){arguments.length&&(b=Hc(a));return b};this.resourceUrlBlacklist=function(b){arguments.length&&(a=Hc(b));return a};this.$get=
|
||||
["$injector",function(c){function d(a){var b=function(a){this.$$unwrapTrustedValue=function(){return a}};a&&(b.prototype=new a);b.prototype.valueOf=function(){return this.$$unwrapTrustedValue()};b.prototype.toString=function(){return this.$$unwrapTrustedValue().toString()};return b}var e=function(a){throw ua("unsafe");};c.has("$sanitize")&&(e=c.get("$sanitize"));var f=d(),g={};g[ga.HTML]=d(f);g[ga.CSS]=d(f);g[ga.URL]=d(f);g[ga.JS]=d(f);g[ga.RESOURCE_URL]=d(g[ga.URL]);return{trustAs:function(a,b){var c=
|
||||
g.hasOwnProperty(a)?g[a]:null;if(!c)throw ua("icontext",a,b);if(null===b||b===s||""===b)return b;if("string"!==typeof b)throw ua("itype",a);return new c(b)},getTrusted:function(c,d){if(null===d||d===s||""===d)return d;var f=g.hasOwnProperty(c)?g[c]:null;if(f&&d instanceof f)return d.$$unwrapTrustedValue();if(c===ga.RESOURCE_URL){var f=sa(d.toString()),l,n,p=!1;l=0;for(n=b.length;l<n;l++)if("self"===b[l]?Mb(f):b[l].exec(f.href)){p=!0;break}if(p)for(l=0,n=a.length;l<n;l++)if("self"===a[l]?Mb(f):a[l].exec(f.href)){p=
|
||||
!1;break}if(p)return d;throw ua("insecurl",d.toString());}if(c===ga.HTML)return e(d);throw ua("unsafe");},valueOf:function(a){return a instanceof f?a.$$unwrapTrustedValue():a}}}]}function $d(){var b=!0;this.enabled=function(a){arguments.length&&(b=!!a);return b};this.$get=["$parse","$sniffer","$sceDelegate",function(a,c,d){if(b&&c.msie&&8>c.msieDocumentMode)throw ua("iequirks");var e=ka(ga);e.isEnabled=function(){return b};e.trustAs=d.trustAs;e.getTrusted=d.getTrusted;e.valueOf=d.valueOf;b||(e.trustAs=
|
||||
e.getTrusted=function(a,b){return b},e.valueOf=Ea);e.parseAs=function(b,c){var d=a(c);return d.literal&&d.constant?d:function(a,c){return e.getTrusted(b,d(a,c))}};var f=e.parseAs,g=e.getTrusted,h=e.trustAs;q(ga,function(a,b){var c=J(b);e[Ua("parse_as_"+c)]=function(b){return f(a,b)};e[Ua("get_trusted_"+c)]=function(b){return g(a,b)};e[Ua("trust_as_"+c)]=function(b){return h(a,b)}});return e}]}function be(){this.$get=["$window","$document",function(b,a){var c={},d=Y((/android (\d+)/.exec(J((b.navigator||
|
||||
{}).userAgent))||[])[1]),e=/Boxee/i.test((b.navigator||{}).userAgent),f=a[0]||{},g=f.documentMode,h,m=/^(Moz|webkit|O|ms)(?=[A-Z])/,k=f.body&&f.body.style,l=!1,n=!1;if(k){for(var p in k)if(l=m.exec(p)){h=l[0];h=h.substr(0,1).toUpperCase()+h.substr(1);break}h||(h="WebkitOpacity"in k&&"webkit");l=!!("transition"in k||h+"Transition"in k);n=!!("animation"in k||h+"Animation"in k);!d||l&&n||(l=C(f.body.style.webkitTransition),n=C(f.body.style.webkitAnimation))}return{history:!(!b.history||!b.history.pushState||
|
||||
4>d||e),hashchange:"onhashchange"in b&&(!g||7<g),hasEvent:function(a){if("input"==a&&9==S)return!1;if(H(c[a])){var b=f.createElement("div");c[a]="on"+a in b}return c[a]},csp:$b(),vendorPrefix:h,transitions:l,animations:n,android:d,msie:S,msieDocumentMode:g}}]}function de(){this.$get=["$rootScope","$browser","$q","$exceptionHandler",function(b,a,c,d){function e(e,h,m){var k=c.defer(),l=k.promise,n=z(m)&&!m;h=a.defer(function(){try{k.resolve(e())}catch(a){k.reject(a),d(a)}finally{delete f[l.$$timeoutId]}n||
|
||||
b.$apply()},h);l.$$timeoutId=h;f[h]=k;return l}var f={};e.cancel=function(b){return b&&b.$$timeoutId in f?(f[b.$$timeoutId].reject("canceled"),delete f[b.$$timeoutId],a.defer.cancel(b.$$timeoutId)):!1};return e}]}function sa(b,a){var c=b;S&&(X.setAttribute("href",c),c=X.href);X.setAttribute("href",c);return{href:X.href,protocol:X.protocol?X.protocol.replace(/:$/,""):"",host:X.host,search:X.search?X.search.replace(/^\?/,""):"",hash:X.hash?X.hash.replace(/^#/,""):"",hostname:X.hostname,port:X.port,
|
||||
pathname:"/"===X.pathname.charAt(0)?X.pathname:"/"+X.pathname}}function Mb(b){b=C(b)?sa(b):b;return b.protocol===Ic.protocol&&b.host===Ic.host}function ee(){this.$get=aa(P)}function kc(b){function a(d,e){if(U(d)){var f={};q(d,function(b,c){f[c]=a(c,b)});return f}return b.factory(d+c,e)}var c="Filter";this.register=a;this.$get=["$injector",function(a){return function(b){return a.get(b+c)}}];a("currency",Jc);a("date",Kc);a("filter",Be);a("json",Ce);a("limitTo",De);a("lowercase",Ee);a("number",Lc);a("orderBy",
|
||||
Mc);a("uppercase",Fe)}function Be(){return function(b,a,c){if(!K(b))return b;var d=typeof c,e=[];e.check=function(a){for(var b=0;b<e.length;b++)if(!e[b](a))return!1;return!0};"function"!==d&&(c="boolean"===d&&c?function(a,b){return Ra.equals(a,b)}:function(a,b){if(a&&b&&"object"===typeof a&&"object"===typeof b){for(var d in a)if("$"!==d.charAt(0)&&Ab.call(a,d)&&c(a[d],b[d]))return!0;return!1}b=(""+b).toLowerCase();return-1<(""+a).toLowerCase().indexOf(b)});var f=function(a,b){if("string"==typeof b&&
|
||||
"!"===b.charAt(0))return!f(a,b.substr(1));switch(typeof a){case "boolean":case "number":case "string":return c(a,b);case "object":switch(typeof b){case "object":return c(a,b);default:for(var d in a)if("$"!==d.charAt(0)&&f(a[d],b))return!0}return!1;case "array":for(d=0;d<a.length;d++)if(f(a[d],b))return!0;return!1;default:return!1}};switch(typeof a){case "boolean":case "number":case "string":a={$:a};case "object":for(var g in a)(function(b){"undefined"!=typeof a[b]&&e.push(function(c){return f("$"==
|
||||
b?c:c&&c[b],a[b])})})(g);break;case "function":e.push(a);break;default:return b}d=[];for(g=0;g<b.length;g++){var h=b[g];e.check(h)&&d.push(h)}return d}}function Jc(b){var a=b.NUMBER_FORMATS;return function(b,d){H(d)&&(d=a.CURRENCY_SYM);return Nc(b,a.PATTERNS[1],a.GROUP_SEP,a.DECIMAL_SEP,2).replace(/\u00A4/g,d)}}function Lc(b){var a=b.NUMBER_FORMATS;return function(b,d){return Nc(b,a.PATTERNS[0],a.GROUP_SEP,a.DECIMAL_SEP,d)}}function Nc(b,a,c,d,e){if(null==b||!isFinite(b)||U(b))return"";var f=0>b;
|
||||
b=Math.abs(b);var g=b+"",h="",m=[],k=!1;if(-1!==g.indexOf("e")){var l=g.match(/([\d\.]+)e(-?)(\d+)/);l&&"-"==l[2]&&l[3]>e+1?g="0":(h=g,k=!0)}if(k)0<e&&(-1<b&&1>b)&&(h=b.toFixed(e));else{g=(g.split(Oc)[1]||"").length;H(e)&&(e=Math.min(Math.max(a.minFrac,g),a.maxFrac));g=Math.pow(10,e+1);b=Math.floor(b*g+5)/g;b=(""+b).split(Oc);g=b[0];b=b[1]||"";var l=0,n=a.lgSize,p=a.gSize;if(g.length>=n+p)for(l=g.length-n,k=0;k<l;k++)0===(l-k)%p&&0!==k&&(h+=c),h+=g.charAt(k);for(k=l;k<g.length;k++)0===(g.length-k)%
|
||||
n&&0!==k&&(h+=c),h+=g.charAt(k);for(;b.length<e;)b+="0";e&&"0"!==e&&(h+=d+b.substr(0,e))}m.push(f?a.negPre:a.posPre);m.push(h);m.push(f?a.negSuf:a.posSuf);return m.join("")}function Ub(b,a,c){var d="";0>b&&(d="-",b=-b);for(b=""+b;b.length<a;)b="0"+b;c&&(b=b.substr(b.length-a));return d+b}function $(b,a,c,d){c=c||0;return function(e){e=e["get"+b]();if(0<c||e>-c)e+=c;0===e&&-12==c&&(e=12);return Ub(e,a,d)}}function tb(b,a){return function(c,d){var e=c["get"+b](),f=Ga(a?"SHORT"+b:b);return d[f][e]}}
|
||||
function Kc(b){function a(a){var b;if(b=a.match(c)){a=new Date(0);var f=0,g=0,h=b[8]?a.setUTCFullYear:a.setFullYear,m=b[8]?a.setUTCHours:a.setHours;b[9]&&(f=Y(b[9]+b[10]),g=Y(b[9]+b[11]));h.call(a,Y(b[1]),Y(b[2])-1,Y(b[3]));f=Y(b[4]||0)-f;g=Y(b[5]||0)-g;h=Y(b[6]||0);b=Math.round(1E3*parseFloat("0."+(b[7]||0)));m.call(a,f,g,h,b)}return a}var c=/^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;return function(c,e){var f="",g=[],h,m;e=e||"mediumDate";
|
||||
e=b.DATETIME_FORMATS[e]||e;C(c)&&(c=Ge.test(c)?Y(c):a(c));zb(c)&&(c=new Date(c));if(!Ma(c))return c;for(;e;)(m=He.exec(e))?(g=g.concat(ya.call(m,1)),e=g.pop()):(g.push(e),e=null);q(g,function(a){h=Ie[a];f+=h?h(c,b.DATETIME_FORMATS):a.replace(/(^'|'$)/g,"").replace(/''/g,"'")});return f}}function Ce(){return function(b){return qa(b,!0)}}function De(){return function(b,a){if(!K(b)&&!C(b))return b;a=Infinity===Math.abs(Number(a))?Number(a):Y(a);if(C(b))return a?0<=a?b.slice(0,a):b.slice(a,b.length):
|
||||
"";var c=[],d,e;a>b.length?a=b.length:a<-b.length&&(a=-b.length);0<a?(d=0,e=a):(d=b.length+a,e=b.length);for(;d<e;d++)c.push(b[d]);return c}}function Mc(b){return function(a,c,d){function e(a,b){return Qa(b)?function(b,c){return a(c,b)}:a}function f(a,b){var c=typeof a,d=typeof b;return c==d?("string"==c&&(a=a.toLowerCase(),b=b.toLowerCase()),a===b?0:a<b?-1:1):c<d?-1:1}if(!K(a)||!c)return a;c=K(c)?c:[c];c=Uc(c,function(a){var c=!1,d=a||Ea;if(C(a)){if("+"==a.charAt(0)||"-"==a.charAt(0))c="-"==a.charAt(0),
|
||||
a=a.substring(1);d=b(a);if(d.constant){var g=d();return e(function(a,b){return f(a[g],b[g])},c)}}return e(function(a,b){return f(d(a),d(b))},c)});for(var g=[],h=0;h<a.length;h++)g.push(a[h]);return g.sort(e(function(a,b){for(var d=0;d<c.length;d++){var e=c[d](a,b);if(0!==e)return e}return 0},d))}}function va(b){Q(b)&&(b={link:b});b.restrict=b.restrict||"AC";return aa(b)}function Pc(b,a,c,d){function e(a,c){c=c?"-"+ib(c,"-"):"";d.removeClass(b,(a?ub:vb)+c);d.addClass(b,(a?vb:ub)+c)}var f=this,g=b.parent().controller("form")||
|
||||
wb,h=0,m=f.$error={},k=[];f.$name=a.name||a.ngForm;f.$dirty=!1;f.$pristine=!0;f.$valid=!0;f.$invalid=!1;g.$addControl(f);b.addClass(La);e(!0);f.$addControl=function(a){Aa(a.$name,"input");k.push(a);a.$name&&(f[a.$name]=a)};f.$removeControl=function(a){a.$name&&f[a.$name]===a&&delete f[a.$name];q(m,function(b,c){f.$setValidity(c,!0,a)});Oa(k,a)};f.$setValidity=function(a,b,c){var d=m[a];if(b)d&&(Oa(d,c),d.length||(h--,h||(e(b),f.$valid=!0,f.$invalid=!1),m[a]=!1,e(!0,a),g.$setValidity(a,!0,f)));else{h||
|
||||
e(b);if(d){if(-1!=Na(d,c))return}else m[a]=d=[],h++,e(!1,a),g.$setValidity(a,!1,f);d.push(c);f.$valid=!1;f.$invalid=!0}};f.$setDirty=function(){d.removeClass(b,La);d.addClass(b,xb);f.$dirty=!0;f.$pristine=!1;g.$setDirty()};f.$setPristine=function(){d.removeClass(b,xb);d.addClass(b,La);f.$dirty=!1;f.$pristine=!0;q(k,function(a){a.$setPristine()})}}function pa(b,a,c,d){b.$setValidity(a,c);return c?d:s}function Je(b,a,c){var d=c.prop("validity");U(d)&&b.$parsers.push(function(c){if(b.$error[a]||!(d.badInput||
|
||||
d.customError||d.typeMismatch)||d.valueMissing)return c;b.$setValidity(a,!1)})}function yb(b,a,c,d,e,f){var g=a.prop("validity"),h=a[0].placeholder,m={};if(!e.android){var k=!1;a.on("compositionstart",function(a){k=!0});a.on("compositionend",function(){k=!1;l()})}var l=function(e){if(!k){var f=a.val();if(S&&"input"===(e||m).type&&a[0].placeholder!==h)h=a[0].placeholder;else if(Qa(c.ngTrim||"T")&&(f=ba(f)),d.$viewValue!==f||g&&""===f&&!g.valueMissing)b.$$phase?d.$setViewValue(f):b.$apply(function(){d.$setViewValue(f)})}};
|
||||
if(e.hasEvent("input"))a.on("input",l);else{var n,p=function(){n||(n=f.defer(function(){l();n=null}))};a.on("keydown",function(a){a=a.keyCode;91===a||(15<a&&19>a||37<=a&&40>=a)||p()});if(e.hasEvent("paste"))a.on("paste cut",p)}a.on("change",l);d.$render=function(){a.val(d.$isEmpty(d.$viewValue)?"":d.$viewValue)};var r=c.ngPattern;r&&((e=r.match(/^\/(.*)\/([gim]*)$/))?(r=RegExp(e[1],e[2]),e=function(a){return pa(d,"pattern",d.$isEmpty(a)||r.test(a),a)}):e=function(c){var e=b.$eval(r);if(!e||!e.test)throw u("ngPattern")("noregexp",
|
||||
r,e,ha(a));return pa(d,"pattern",d.$isEmpty(c)||e.test(c),c)},d.$formatters.push(e),d.$parsers.push(e));if(c.ngMinlength){var q=Y(c.ngMinlength);e=function(a){return pa(d,"minlength",d.$isEmpty(a)||a.length>=q,a)};d.$parsers.push(e);d.$formatters.push(e)}if(c.ngMaxlength){var D=Y(c.ngMaxlength);e=function(a){return pa(d,"maxlength",d.$isEmpty(a)||a.length<=D,a)};d.$parsers.push(e);d.$formatters.push(e)}}function Vb(b,a){b="ngClass"+b;return["$animate",function(c){function d(a,b){var c=[],d=0;a:for(;d<
|
||||
a.length;d++){for(var e=a[d],l=0;l<b.length;l++)if(e==b[l])continue a;c.push(e)}return c}function e(a){if(!K(a)){if(C(a))return a.split(" ");if(U(a)){var b=[];q(a,function(a,c){a&&(b=b.concat(c.split(" ")))});return b}}return a}return{restrict:"AC",link:function(f,g,h){function m(a,b){var c=g.data("$classCounts")||{},d=[];q(a,function(a){if(0<b||c[a])c[a]=(c[a]||0)+b,c[a]===+(0<b)&&d.push(a)});g.data("$classCounts",c);return d.join(" ")}function k(b){if(!0===a||f.$index%2===a){var k=e(b||[]);if(!l){var r=
|
||||
m(k,1);h.$addClass(r)}else if(!xa(b,l)){var q=e(l),r=d(k,q),k=d(q,k),k=m(k,-1),r=m(r,1);0===r.length?c.removeClass(g,k):0===k.length?c.addClass(g,r):c.setClass(g,r,k)}}l=ka(b)}var l;f.$watch(h[b],k,!0);h.$observe("class",function(a){k(f.$eval(h[b]))});"ngClass"!==b&&f.$watch("$index",function(c,d){var g=c&1;if(g!==(d&1)){var k=e(f.$eval(h[b]));g===a?(g=m(k,1),h.$addClass(g)):(g=m(k,-1),h.$removeClass(g))}})}}}]}var J=function(b){return C(b)?b.toLowerCase():b},Ab=Object.prototype.hasOwnProperty,Ga=
|
||||
function(b){return C(b)?b.toUpperCase():b},S,y,Ba,ya=[].slice,Ke=[].push,wa=Object.prototype.toString,Pa=u("ng"),Ra=P.angular||(P.angular={}),Ta,Ka,ja=["0","0","0"];S=Y((/msie (\d+)/.exec(J(navigator.userAgent))||[])[1]);isNaN(S)&&(S=Y((/trident\/.*; rv:(\d+)/.exec(J(navigator.userAgent))||[])[1]));w.$inject=[];Ea.$inject=[];var ba=function(){return String.prototype.trim?function(b){return C(b)?b.trim():b}:function(b){return C(b)?b.replace(/^\s\s*/,"").replace(/\s\s*$/,""):b}}();Ka=9>S?function(b){b=
|
||||
b.nodeName?b:b[0];return b.scopeName&&"HTML"!=b.scopeName?Ga(b.scopeName+":"+b.nodeName):b.nodeName}:function(b){return b.nodeName?b.nodeName:b[0].nodeName};var Xc=/[A-Z]/g,$c={full:"1.2.17",major:1,minor:2,dot:17,codeName:"quantum-disentanglement"},Wa=M.cache={},jb=M.expando="ng"+(new Date).getTime(),me=1,qb=P.document.addEventListener?function(b,a,c){b.addEventListener(a,c,!1)}:function(b,a,c){b.attachEvent("on"+a,c)},Va=P.document.removeEventListener?function(b,a,c){b.removeEventListener(a,c,!1)}:
|
||||
function(b,a,c){b.detachEvent("on"+a,c)};M._data=function(b){return this.cache[b[this.expando]]||{}};var he=/([\:\-\_]+(.))/g,ie=/^moz([A-Z])/,Gb=u("jqLite"),je=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,Hb=/<|&#?\w+;/,ke=/<([\w:]+)/,le=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,da={option:[1,'<select multiple="multiple">',"</select>"],thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>",
|
||||
"</tr></tbody></table>"],_default:[0,"",""]};da.optgroup=da.option;da.tbody=da.tfoot=da.colgroup=da.caption=da.thead;da.th=da.td;var Ja=M.prototype={ready:function(b){function a(){c||(c=!0,b())}var c=!1;"complete"===V.readyState?setTimeout(a):(this.on("DOMContentLoaded",a),M(P).on("load",a))},toString:function(){var b=[];q(this,function(a){b.push(""+a)});return"["+b.join(", ")+"]"},eq:function(b){return 0<=b?y(this[b]):y(this[this.length+b])},length:0,push:Ke,sort:[].sort,splice:[].splice},nb={};
|
||||
q("multiple selected checked disabled readOnly required open".split(" "),function(b){nb[J(b)]=b});var rc={};q("input select option textarea button form details".split(" "),function(b){rc[Ga(b)]=!0});q({data:nc,inheritedData:mb,scope:function(b){return y(b).data("$scope")||mb(b.parentNode||b,["$isolateScope","$scope"])},isolateScope:function(b){return y(b).data("$isolateScope")||y(b).data("$isolateScopeNoTemplate")},controller:oc,injector:function(b){return mb(b,"$injector")},removeAttr:function(b,
|
||||
a){b.removeAttribute(a)},hasClass:Kb,css:function(b,a,c){a=Ua(a);if(z(c))b.style[a]=c;else{var d;8>=S&&(d=b.currentStyle&&b.currentStyle[a],""===d&&(d="auto"));d=d||b.style[a];8>=S&&(d=""===d?s:d);return d}},attr:function(b,a,c){var d=J(a);if(nb[d])if(z(c))c?(b[a]=!0,b.setAttribute(a,d)):(b[a]=!1,b.removeAttribute(d));else return b[a]||(b.attributes.getNamedItem(a)||w).specified?d:s;else if(z(c))b.setAttribute(a,c);else if(b.getAttribute)return b=b.getAttribute(a,2),null===b?s:b},prop:function(b,
|
||||
a,c){if(z(c))b[a]=c;else return b[a]},text:function(){function b(b,d){var e=a[b.nodeType];if(H(d))return e?b[e]:"";b[e]=d}var a=[];9>S?(a[1]="innerText",a[3]="nodeValue"):a[1]=a[3]="textContent";b.$dv="";return b}(),val:function(b,a){if(H(a)){if("SELECT"===Ka(b)&&b.multiple){var c=[];q(b.options,function(a){a.selected&&c.push(a.value||a.text)});return 0===c.length?null:c}return b.value}b.value=a},html:function(b,a){if(H(a))return b.innerHTML;for(var c=0,d=b.childNodes;c<d.length;c++)Ha(d[c]);b.innerHTML=
|
||||
a},empty:pc},function(b,a){M.prototype[a]=function(a,d){var e,f;if(b!==pc&&(2==b.length&&b!==Kb&&b!==oc?a:d)===s){if(U(a)){for(e=0;e<this.length;e++)if(b===nc)b(this[e],a);else for(f in a)b(this[e],f,a[f]);return this}e=b.$dv;f=e===s?Math.min(this.length,1):this.length;for(var g=0;g<f;g++){var h=b(this[g],a,d);e=e?e+h:h}return e}for(e=0;e<this.length;e++)b(this[e],a,d);return this}});q({removeData:lc,dealoc:Ha,on:function a(c,d,e,f){if(z(f))throw Gb("onargs");var g=la(c,"events"),h=la(c,"handle");
|
||||
g||la(c,"events",g={});h||la(c,"handle",h=ne(c,g));q(d.split(" "),function(d){var f=g[d];if(!f){if("mouseenter"==d||"mouseleave"==d){var l=V.body.contains||V.body.compareDocumentPosition?function(a,c){var d=9===a.nodeType?a.documentElement:a,e=c&&c.parentNode;return a===e||!!(e&&1===e.nodeType&&(d.contains?d.contains(e):a.compareDocumentPosition&&a.compareDocumentPosition(e)&16))}:function(a,c){if(c)for(;c=c.parentNode;)if(c===a)return!0;return!1};g[d]=[];a(c,{mouseleave:"mouseout",mouseenter:"mouseover"}[d],
|
||||
function(a){var c=a.relatedTarget;c&&(c===this||l(this,c))||h(a,d)})}else qb(c,d,h),g[d]=[];f=g[d]}f.push(e)})},off:mc,one:function(a,c,d){a=y(a);a.on(c,function f(){a.off(c,d);a.off(c,f)});a.on(c,d)},replaceWith:function(a,c){var d,e=a.parentNode;Ha(a);q(new M(c),function(c){d?e.insertBefore(c,d.nextSibling):e.replaceChild(c,a);d=c})},children:function(a){var c=[];q(a.childNodes,function(a){1===a.nodeType&&c.push(a)});return c},contents:function(a){return a.contentDocument||a.childNodes||[]},append:function(a,
|
||||
c){q(new M(c),function(c){1!==a.nodeType&&11!==a.nodeType||a.appendChild(c)})},prepend:function(a,c){if(1===a.nodeType){var d=a.firstChild;q(new M(c),function(c){a.insertBefore(c,d)})}},wrap:function(a,c){c=y(c)[0];var d=a.parentNode;d&&d.replaceChild(c,a);c.appendChild(a)},remove:function(a){Ha(a);var c=a.parentNode;c&&c.removeChild(a)},after:function(a,c){var d=a,e=a.parentNode;q(new M(c),function(a){e.insertBefore(a,d.nextSibling);d=a})},addClass:lb,removeClass:kb,toggleClass:function(a,c,d){c&&
|
||||
q(c.split(" "),function(c){var f=d;H(f)&&(f=!Kb(a,c));(f?lb:kb)(a,c)})},parent:function(a){return(a=a.parentNode)&&11!==a.nodeType?a:null},next:function(a){if(a.nextElementSibling)return a.nextElementSibling;for(a=a.nextSibling;null!=a&&1!==a.nodeType;)a=a.nextSibling;return a},find:function(a,c){return a.getElementsByTagName?a.getElementsByTagName(c):[]},clone:Jb,triggerHandler:function(a,c,d){c=(la(a,"events")||{})[c];d=d||[];var e=[{preventDefault:w,stopPropagation:w}];q(c,function(c){c.apply(a,
|
||||
e.concat(d))})}},function(a,c){M.prototype[c]=function(c,e,f){for(var g,h=0;h<this.length;h++)H(g)?(g=a(this[h],c,e,f),z(g)&&(g=y(g))):Ib(g,a(this[h],c,e,f));return z(g)?g:this};M.prototype.bind=M.prototype.on;M.prototype.unbind=M.prototype.off});Xa.prototype={put:function(a,c){this[Ia(a)]=c},get:function(a){return this[Ia(a)]},remove:function(a){var c=this[a=Ia(a)];delete this[a];return c}};var pe=/^function\s*[^\(]*\(\s*([^\)]*)\)/m,qe=/,/,re=/^\s*(_?)(\S+?)\1\s*$/,oe=/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg,
|
||||
Ya=u("$injector"),Le=u("$animate"),Ld=["$provide",function(a){this.$$selectors={};this.register=function(c,d){var e=c+"-animation";if(c&&"."!=c.charAt(0))throw Le("notcsel",c);this.$$selectors[c.substr(1)]=e;a.factory(e,d)};this.classNameFilter=function(a){1===arguments.length&&(this.$$classNameFilter=a instanceof RegExp?a:null);return this.$$classNameFilter};this.$get=["$timeout","$$asyncCallback",function(a,d){return{enter:function(a,c,g,h){g?g.after(a):(c&&c[0]||(c=g.parent()),c.append(a));h&&
|
||||
d(h)},leave:function(a,c){a.remove();c&&d(c)},move:function(a,c,d,h){this.enter(a,c,d,h)},addClass:function(a,c,g){c=C(c)?c:K(c)?c.join(" "):"";q(a,function(a){lb(a,c)});g&&d(g)},removeClass:function(a,c,g){c=C(c)?c:K(c)?c.join(" "):"";q(a,function(a){kb(a,c)});g&&d(g)},setClass:function(a,c,g,h){q(a,function(a){lb(a,c);kb(a,g)});h&&d(h)},enabled:w}}]}],ia=u("$compile");gc.$inject=["$provide","$$sanitizeUriProvider"];var te=/^(x[\:\-_]|data[\:\-_])/i,zc=u("$interpolate"),Me=/^([^\?#]*)(\?([^#]*))?(#(.*))?$/,
|
||||
we={http:80,https:443,ftp:21},Pb=u("$location");Rb.prototype=Qb.prototype=Cc.prototype={$$html5:!1,$$replace:!1,absUrl:rb("$$absUrl"),url:function(a,c){if(H(a))return this.$$url;var d=Me.exec(a);d[1]&&this.path(decodeURIComponent(d[1]));(d[2]||d[1])&&this.search(d[3]||"");this.hash(d[5]||"",c);return this},protocol:rb("$$protocol"),host:rb("$$host"),port:rb("$$port"),path:Dc("$$path",function(a){return"/"==a.charAt(0)?a:"/"+a}),search:function(a,c){switch(arguments.length){case 0:return this.$$search;
|
||||
case 1:if(C(a))this.$$search=cc(a);else if(U(a))this.$$search=a;else throw Pb("isrcharg");break;default:H(c)||null===c?delete this.$$search[a]:this.$$search[a]=c}this.$$compose();return this},hash:Dc("$$hash",Ea),replace:function(){this.$$replace=!0;return this}};var Ca=u("$parse"),Gc={},ta,cb={"null":function(){return null},"true":function(){return!0},"false":function(){return!1},undefined:w,"+":function(a,c,d,e){d=d(a,c);e=e(a,c);return z(d)?z(e)?d+e:d:z(e)?e:s},"-":function(a,c,d,e){d=d(a,c);e=
|
||||
e(a,c);return(z(d)?d:0)-(z(e)?e:0)},"*":function(a,c,d,e){return d(a,c)*e(a,c)},"/":function(a,c,d,e){return d(a,c)/e(a,c)},"%":function(a,c,d,e){return d(a,c)%e(a,c)},"^":function(a,c,d,e){return d(a,c)^e(a,c)},"=":w,"===":function(a,c,d,e){return d(a,c)===e(a,c)},"!==":function(a,c,d,e){return d(a,c)!==e(a,c)},"==":function(a,c,d,e){return d(a,c)==e(a,c)},"!=":function(a,c,d,e){return d(a,c)!=e(a,c)},"<":function(a,c,d,e){return d(a,c)<e(a,c)},">":function(a,c,d,e){return d(a,c)>e(a,c)},"<=":function(a,
|
||||
c,d,e){return d(a,c)<=e(a,c)},">=":function(a,c,d,e){return d(a,c)>=e(a,c)},"&&":function(a,c,d,e){return d(a,c)&&e(a,c)},"||":function(a,c,d,e){return d(a,c)||e(a,c)},"&":function(a,c,d,e){return d(a,c)&e(a,c)},"|":function(a,c,d,e){return e(a,c)(a,c,d(a,c))},"!":function(a,c,d){return!d(a,c)}},Ne={n:"\n",f:"\f",r:"\r",t:"\t",v:"\v","'":"'",'"':'"'},Tb=function(a){this.options=a};Tb.prototype={constructor:Tb,lex:function(a){this.text=a;this.index=0;this.ch=s;this.lastCh=":";for(this.tokens=[];this.index<
|
||||
this.text.length;){this.ch=this.text.charAt(this.index);if(this.is("\"'"))this.readString(this.ch);else if(this.isNumber(this.ch)||this.is(".")&&this.isNumber(this.peek()))this.readNumber();else if(this.isIdent(this.ch))this.readIdent();else if(this.is("(){}[].,;:?"))this.tokens.push({index:this.index,text:this.ch}),this.index++;else if(this.isWhitespace(this.ch)){this.index++;continue}else{a=this.ch+this.peek();var c=a+this.peek(2),d=cb[this.ch],e=cb[a],f=cb[c];f?(this.tokens.push({index:this.index,
|
||||
text:c,fn:f}),this.index+=3):e?(this.tokens.push({index:this.index,text:a,fn:e}),this.index+=2):d?(this.tokens.push({index:this.index,text:this.ch,fn:d}),this.index+=1):this.throwError("Unexpected next character ",this.index,this.index+1)}this.lastCh=this.ch}return this.tokens},is:function(a){return-1!==a.indexOf(this.ch)},was:function(a){return-1!==a.indexOf(this.lastCh)},peek:function(a){a=a||1;return this.index+a<this.text.length?this.text.charAt(this.index+a):!1},isNumber:function(a){return"0"<=
|
||||
a&&"9">=a},isWhitespace:function(a){return" "===a||"\r"===a||"\t"===a||"\n"===a||"\v"===a||"\u00a0"===a},isIdent:function(a){return"a"<=a&&"z">=a||"A"<=a&&"Z">=a||"_"===a||"$"===a},isExpOperator:function(a){return"-"===a||"+"===a||this.isNumber(a)},throwError:function(a,c,d){d=d||this.index;c=z(c)?"s "+c+"-"+this.index+" ["+this.text.substring(c,d)+"]":" "+d;throw Ca("lexerr",a,c,this.text);},readNumber:function(){for(var a="",c=this.index;this.index<this.text.length;){var d=J(this.text.charAt(this.index));
|
||||
if("."==d||this.isNumber(d))a+=d;else{var e=this.peek();if("e"==d&&this.isExpOperator(e))a+=d;else if(this.isExpOperator(d)&&e&&this.isNumber(e)&&"e"==a.charAt(a.length-1))a+=d;else if(!this.isExpOperator(d)||e&&this.isNumber(e)||"e"!=a.charAt(a.length-1))break;else this.throwError("Invalid exponent")}this.index++}a*=1;this.tokens.push({index:c,text:a,literal:!0,constant:!0,fn:function(){return a}})},readIdent:function(){for(var a=this,c="",d=this.index,e,f,g,h;this.index<this.text.length;){h=this.text.charAt(this.index);
|
||||
if("."===h||this.isIdent(h)||this.isNumber(h))"."===h&&(e=this.index),c+=h;else break;this.index++}if(e)for(f=this.index;f<this.text.length;){h=this.text.charAt(f);if("("===h){g=c.substr(e-d+1);c=c.substr(0,e-d);this.index=f;break}if(this.isWhitespace(h))f++;else break}d={index:d,text:c};if(cb.hasOwnProperty(c))d.fn=cb[c],d.literal=!0,d.constant=!0;else{var m=Fc(c,this.options,this.text);d.fn=E(function(a,c){return m(a,c)},{assign:function(d,e){return sb(d,c,e,a.text,a.options)}})}this.tokens.push(d);
|
||||
g&&(this.tokens.push({index:e,text:"."}),this.tokens.push({index:e+1,text:g}))},readString:function(a){var c=this.index;this.index++;for(var d="",e=a,f=!1;this.index<this.text.length;){var g=this.text.charAt(this.index),e=e+g;if(f)"u"===g?(g=this.text.substring(this.index+1,this.index+5),g.match(/[\da-f]{4}/i)||this.throwError("Invalid unicode escape [\\u"+g+"]"),this.index+=4,d+=String.fromCharCode(parseInt(g,16))):d=(f=Ne[g])?d+f:d+g,f=!1;else if("\\"===g)f=!0;else{if(g===a){this.index++;this.tokens.push({index:c,
|
||||
text:e,string:d,literal:!0,constant:!0,fn:function(){return d}});return}d+=g}this.index++}this.throwError("Unterminated quote",c)}};var bb=function(a,c,d){this.lexer=a;this.$filter=c;this.options=d};bb.ZERO=E(function(){return 0},{constant:!0});bb.prototype={constructor:bb,parse:function(a){this.text=a;this.tokens=this.lexer.lex(a);a=this.statements();0!==this.tokens.length&&this.throwError("is an unexpected token",this.tokens[0]);a.literal=!!a.literal;a.constant=!!a.constant;return a},primary:function(){var a;
|
||||
if(this.expect("("))a=this.filterChain(),this.consume(")");else if(this.expect("["))a=this.arrayDeclaration();else if(this.expect("{"))a=this.object();else{var c=this.expect();(a=c.fn)||this.throwError("not a primary expression",c);a.literal=!!c.literal;a.constant=!!c.constant}for(var d;c=this.expect("(","[",".");)"("===c.text?(a=this.functionCall(a,d),d=null):"["===c.text?(d=a,a=this.objectIndex(a)):"."===c.text?(d=a,a=this.fieldAccess(a)):this.throwError("IMPOSSIBLE");return a},throwError:function(a,
|
||||
c){throw Ca("syntax",c.text,a,c.index+1,this.text,this.text.substring(c.index));},peekToken:function(){if(0===this.tokens.length)throw Ca("ueoe",this.text);return this.tokens[0]},peek:function(a,c,d,e){if(0<this.tokens.length){var f=this.tokens[0],g=f.text;if(g===a||g===c||g===d||g===e||!(a||c||d||e))return f}return!1},expect:function(a,c,d,e){return(a=this.peek(a,c,d,e))?(this.tokens.shift(),a):!1},consume:function(a){this.expect(a)||this.throwError("is unexpected, expecting ["+a+"]",this.peek())},
|
||||
unaryFn:function(a,c){return E(function(d,e){return a(d,e,c)},{constant:c.constant})},ternaryFn:function(a,c,d){return E(function(e,f){return a(e,f)?c(e,f):d(e,f)},{constant:a.constant&&c.constant&&d.constant})},binaryFn:function(a,c,d){return E(function(e,f){return c(e,f,a,d)},{constant:a.constant&&d.constant})},statements:function(){for(var a=[];;)if(0<this.tokens.length&&!this.peek("}",")",";","]")&&a.push(this.filterChain()),!this.expect(";"))return 1===a.length?a[0]:function(c,d){for(var e,f=
|
||||
0;f<a.length;f++){var g=a[f];g&&(e=g(c,d))}return e}},filterChain:function(){for(var a=this.expression(),c;;)if(c=this.expect("|"))a=this.binaryFn(a,c.fn,this.filter());else return a},filter:function(){for(var a=this.expect(),c=this.$filter(a.text),d=[];;)if(a=this.expect(":"))d.push(this.expression());else{var e=function(a,e,h){h=[h];for(var m=0;m<d.length;m++)h.push(d[m](a,e));return c.apply(a,h)};return function(){return e}}},expression:function(){return this.assignment()},assignment:function(){var a=
|
||||
this.ternary(),c,d;return(d=this.expect("="))?(a.assign||this.throwError("implies assignment but ["+this.text.substring(0,d.index)+"] can not be assigned to",d),c=this.ternary(),function(d,f){return a.assign(d,c(d,f),f)}):a},ternary:function(){var a=this.logicalOR(),c,d;if(this.expect("?")){c=this.ternary();if(d=this.expect(":"))return this.ternaryFn(a,c,this.ternary());this.throwError("expected :",d)}else return a},logicalOR:function(){for(var a=this.logicalAND(),c;;)if(c=this.expect("||"))a=this.binaryFn(a,
|
||||
c.fn,this.logicalAND());else return a},logicalAND:function(){var a=this.equality(),c;if(c=this.expect("&&"))a=this.binaryFn(a,c.fn,this.logicalAND());return a},equality:function(){var a=this.relational(),c;if(c=this.expect("==","!=","===","!=="))a=this.binaryFn(a,c.fn,this.equality());return a},relational:function(){var a=this.additive(),c;if(c=this.expect("<",">","<=",">="))a=this.binaryFn(a,c.fn,this.relational());return a},additive:function(){for(var a=this.multiplicative(),c;c=this.expect("+",
|
||||
"-");)a=this.binaryFn(a,c.fn,this.multiplicative());return a},multiplicative:function(){for(var a=this.unary(),c;c=this.expect("*","/","%");)a=this.binaryFn(a,c.fn,this.unary());return a},unary:function(){var a;return this.expect("+")?this.primary():(a=this.expect("-"))?this.binaryFn(bb.ZERO,a.fn,this.unary()):(a=this.expect("!"))?this.unaryFn(a.fn,this.unary()):this.primary()},fieldAccess:function(a){var c=this,d=this.expect().text,e=Fc(d,this.options,this.text);return E(function(c,d,h){return e(h||
|
||||
a(c,d))},{assign:function(e,g,h){return sb(a(e,h),d,g,c.text,c.options)}})},objectIndex:function(a){var c=this,d=this.expression();this.consume("]");return E(function(e,f){var g=a(e,f),h=d(e,f),m;if(!g)return s;(g=ab(g[h],c.text))&&(g.then&&c.options.unwrapPromises)&&(m=g,"$$v"in g||(m.$$v=s,m.then(function(a){m.$$v=a})),g=g.$$v);return g},{assign:function(e,f,g){var h=d(e,g);return ab(a(e,g),c.text)[h]=f}})},functionCall:function(a,c){var d=[];if(")"!==this.peekToken().text){do d.push(this.expression());
|
||||
while(this.expect(","))}this.consume(")");var e=this;return function(f,g){for(var h=[],m=c?c(f,g):f,k=0;k<d.length;k++)h.push(d[k](f,g));k=a(f,g,m)||w;ab(m,e.text);ab(k,e.text);h=k.apply?k.apply(m,h):k(h[0],h[1],h[2],h[3],h[4]);return ab(h,e.text)}},arrayDeclaration:function(){var a=[],c=!0;if("]"!==this.peekToken().text){do{if(this.peek("]"))break;var d=this.expression();a.push(d);d.constant||(c=!1)}while(this.expect(","))}this.consume("]");return E(function(c,d){for(var g=[],h=0;h<a.length;h++)g.push(a[h](c,
|
||||
d));return g},{literal:!0,constant:c})},object:function(){var a=[],c=!0;if("}"!==this.peekToken().text){do{if(this.peek("}"))break;var d=this.expect(),d=d.string||d.text;this.consume(":");var e=this.expression();a.push({key:d,value:e});e.constant||(c=!1)}while(this.expect(","))}this.consume("}");return E(function(c,d){for(var e={},m=0;m<a.length;m++){var k=a[m];e[k.key]=k.value(c,d)}return e},{literal:!0,constant:c})}};var Sb={},ua=u("$sce"),ga={HTML:"html",CSS:"css",URL:"url",RESOURCE_URL:"resourceUrl",
|
||||
JS:"js"},X=V.createElement("a"),Ic=sa(P.location.href,!0);kc.$inject=["$provide"];Jc.$inject=["$locale"];Lc.$inject=["$locale"];var Oc=".",Ie={yyyy:$("FullYear",4),yy:$("FullYear",2,0,!0),y:$("FullYear",1),MMMM:tb("Month"),MMM:tb("Month",!0),MM:$("Month",2,1),M:$("Month",1,1),dd:$("Date",2),d:$("Date",1),HH:$("Hours",2),H:$("Hours",1),hh:$("Hours",2,-12),h:$("Hours",1,-12),mm:$("Minutes",2),m:$("Minutes",1),ss:$("Seconds",2),s:$("Seconds",1),sss:$("Milliseconds",3),EEEE:tb("Day"),EEE:tb("Day",!0),
|
||||
a:function(a,c){return 12>a.getHours()?c.AMPMS[0]:c.AMPMS[1]},Z:function(a){a=-1*a.getTimezoneOffset();return a=(0<=a?"+":"")+(Ub(Math[0<a?"floor":"ceil"](a/60),2)+Ub(Math.abs(a%60),2))}},He=/((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,Ge=/^\-?\d+$/;Kc.$inject=["$locale"];var Ee=aa(J),Fe=aa(Ga);Mc.$inject=["$parse"];var cd=aa({restrict:"E",compile:function(a,c){8>=S&&(c.href||c.name||c.$set("href",""),a.append(V.createComment("IE fix")));if(!c.href&&!c.xlinkHref&&
|
||||
!c.name)return function(a,c){var f="[object SVGAnimatedString]"===wa.call(c.prop("href"))?"xlink:href":"href";c.on("click",function(a){c.attr(f)||a.preventDefault()})}}}),Eb={};q(nb,function(a,c){if("multiple"!=a){var d=na("ng-"+c);Eb[d]=function(){return{priority:100,link:function(a,f,g){a.$watch(g[d],function(a){g.$set(c,!!a)})}}}}});q(["src","srcset","href"],function(a){var c=na("ng-"+a);Eb[c]=function(){return{priority:99,link:function(d,e,f){var g=a,h=a;"href"===a&&"[object SVGAnimatedString]"===
|
||||
wa.call(e.prop("href"))&&(h="xlinkHref",f.$attr[h]="xlink:href",g=null);f.$observe(c,function(a){a&&(f.$set(h,a),S&&g&&e.prop(g,f[h]))})}}}});var wb={$addControl:w,$removeControl:w,$setValidity:w,$setDirty:w,$setPristine:w};Pc.$inject=["$element","$attrs","$scope","$animate"];var Qc=function(a){return["$timeout",function(c){return{name:"form",restrict:a?"EAC":"E",controller:Pc,compile:function(){return{pre:function(a,e,f,g){if(!f.action){var h=function(a){a.preventDefault?a.preventDefault():a.returnValue=
|
||||
!1};qb(e[0],"submit",h);e.on("$destroy",function(){c(function(){Va(e[0],"submit",h)},0,!1)})}var m=e.parent().controller("form"),k=f.name||f.ngForm;k&&sb(a,k,g,k);if(m)e.on("$destroy",function(){m.$removeControl(g);k&&sb(a,k,s,k);E(g,wb)})}}}}}]},dd=Qc(),qd=Qc(!0),Oe=/^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/,Pe=/^[a-z0-9!#$%&'*+/=?^_`{|}~.-]+@[a-z0-9-]+(\.[a-z0-9-]+)*$/i,Qe=/^\s*(\-|\+)?(\d+|(\d*(\.\d*)))\s*$/,Rc={text:yb,number:function(a,c,d,e,f,g){yb(a,
|
||||
c,d,e,f,g);e.$parsers.push(function(a){var c=e.$isEmpty(a);if(c||Qe.test(a))return e.$setValidity("number",!0),""===a?null:c?a:parseFloat(a);e.$setValidity("number",!1);return s});Je(e,"number",c);e.$formatters.push(function(a){return e.$isEmpty(a)?"":""+a});d.min&&(a=function(a){var c=parseFloat(d.min);return pa(e,"min",e.$isEmpty(a)||a>=c,a)},e.$parsers.push(a),e.$formatters.push(a));d.max&&(a=function(a){var c=parseFloat(d.max);return pa(e,"max",e.$isEmpty(a)||a<=c,a)},e.$parsers.push(a),e.$formatters.push(a));
|
||||
e.$formatters.push(function(a){return pa(e,"number",e.$isEmpty(a)||zb(a),a)})},url:function(a,c,d,e,f,g){yb(a,c,d,e,f,g);a=function(a){return pa(e,"url",e.$isEmpty(a)||Oe.test(a),a)};e.$formatters.push(a);e.$parsers.push(a)},email:function(a,c,d,e,f,g){yb(a,c,d,e,f,g);a=function(a){return pa(e,"email",e.$isEmpty(a)||Pe.test(a),a)};e.$formatters.push(a);e.$parsers.push(a)},radio:function(a,c,d,e){H(d.name)&&c.attr("name",eb());c.on("click",function(){c[0].checked&&a.$apply(function(){e.$setViewValue(d.value)})});
|
||||
e.$render=function(){c[0].checked=d.value==e.$viewValue};d.$observe("value",e.$render)},checkbox:function(a,c,d,e){var f=d.ngTrueValue,g=d.ngFalseValue;C(f)||(f=!0);C(g)||(g=!1);c.on("click",function(){a.$apply(function(){e.$setViewValue(c[0].checked)})});e.$render=function(){c[0].checked=e.$viewValue};e.$isEmpty=function(a){return a!==f};e.$formatters.push(function(a){return a===f});e.$parsers.push(function(a){return a?f:g})},hidden:w,button:w,submit:w,reset:w,file:w},hc=["$browser","$sniffer",function(a,
|
||||
c){return{restrict:"E",require:"?ngModel",link:function(d,e,f,g){g&&(Rc[J(f.type)]||Rc.text)(d,e,f,g,c,a)}}}],vb="ng-valid",ub="ng-invalid",La="ng-pristine",xb="ng-dirty",Re=["$scope","$exceptionHandler","$attrs","$element","$parse","$animate",function(a,c,d,e,f,g){function h(a,c){c=c?"-"+ib(c,"-"):"";g.removeClass(e,(a?ub:vb)+c);g.addClass(e,(a?vb:ub)+c)}this.$modelValue=this.$viewValue=Number.NaN;this.$parsers=[];this.$formatters=[];this.$viewChangeListeners=[];this.$pristine=!0;this.$dirty=!1;
|
||||
this.$valid=!0;this.$invalid=!1;this.$name=d.name;var m=f(d.ngModel),k=m.assign;if(!k)throw u("ngModel")("nonassign",d.ngModel,ha(e));this.$render=w;this.$isEmpty=function(a){return H(a)||""===a||null===a||a!==a};var l=e.inheritedData("$formController")||wb,n=0,p=this.$error={};e.addClass(La);h(!0);this.$setValidity=function(a,c){p[a]!==!c&&(c?(p[a]&&n--,n||(h(!0),this.$valid=!0,this.$invalid=!1)):(h(!1),this.$invalid=!0,this.$valid=!1,n++),p[a]=!c,h(c,a),l.$setValidity(a,c,this))};this.$setPristine=
|
||||
function(){this.$dirty=!1;this.$pristine=!0;g.removeClass(e,xb);g.addClass(e,La)};this.$setViewValue=function(d){this.$viewValue=d;this.$pristine&&(this.$dirty=!0,this.$pristine=!1,g.removeClass(e,La),g.addClass(e,xb),l.$setDirty());q(this.$parsers,function(a){d=a(d)});this.$modelValue!==d&&(this.$modelValue=d,k(a,d),q(this.$viewChangeListeners,function(a){try{a()}catch(d){c(d)}}))};var r=this;a.$watch(function(){var c=m(a);if(r.$modelValue!==c){var d=r.$formatters,e=d.length;for(r.$modelValue=c;e--;)c=
|
||||
d[e](c);r.$viewValue!==c&&(r.$viewValue=c,r.$render())}return c})}],Fd=function(){return{require:["ngModel","^?form"],controller:Re,link:function(a,c,d,e){var f=e[0],g=e[1]||wb;g.$addControl(f);a.$on("$destroy",function(){g.$removeControl(f)})}}},Hd=aa({require:"ngModel",link:function(a,c,d,e){e.$viewChangeListeners.push(function(){a.$eval(d.ngChange)})}}),ic=function(){return{require:"?ngModel",link:function(a,c,d,e){if(e){d.required=!0;var f=function(a){if(d.required&&e.$isEmpty(a))e.$setValidity("required",
|
||||
!1);else return e.$setValidity("required",!0),a};e.$formatters.push(f);e.$parsers.unshift(f);d.$observe("required",function(){f(e.$viewValue)})}}}},Gd=function(){return{require:"ngModel",link:function(a,c,d,e){var f=(a=/\/(.*)\//.exec(d.ngList))&&RegExp(a[1])||d.ngList||",";e.$parsers.push(function(a){if(!H(a)){var c=[];a&&q(a.split(f),function(a){a&&c.push(ba(a))});return c}});e.$formatters.push(function(a){return K(a)?a.join(", "):s});e.$isEmpty=function(a){return!a||!a.length}}}},Se=/^(true|false|\d+)$/,
|
||||
Id=function(){return{priority:100,compile:function(a,c){return Se.test(c.ngValue)?function(a,c,f){f.$set("value",a.$eval(f.ngValue))}:function(a,c,f){a.$watch(f.ngValue,function(a){f.$set("value",a)})}}}},id=va(function(a,c,d){c.addClass("ng-binding").data("$binding",d.ngBind);a.$watch(d.ngBind,function(a){c.text(a==s?"":a)})}),kd=["$interpolate",function(a){return function(c,d,e){c=a(d.attr(e.$attr.ngBindTemplate));d.addClass("ng-binding").data("$binding",c);e.$observe("ngBindTemplate",function(a){d.text(a)})}}],
|
||||
jd=["$sce","$parse",function(a,c){return function(d,e,f){e.addClass("ng-binding").data("$binding",f.ngBindHtml);var g=c(f.ngBindHtml);d.$watch(function(){return(g(d)||"").toString()},function(c){e.html(a.getTrustedHtml(g(d))||"")})}}],ld=Vb("",!0),nd=Vb("Odd",0),md=Vb("Even",1),od=va({compile:function(a,c){c.$set("ngCloak",s);a.removeClass("ng-cloak")}}),pd=[function(){return{scope:!0,controller:"@",priority:500}}],jc={};q("click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste".split(" "),
|
||||
function(a){var c=na("ng-"+a);jc[c]=["$parse",function(d){return{compile:function(e,f){var g=d(f[c]);return function(c,d,e){d.on(J(a),function(a){c.$apply(function(){g(c,{$event:a})})})}}}}]});var sd=["$animate",function(a){return{transclude:"element",priority:600,terminal:!0,restrict:"A",$$tlb:!0,link:function(c,d,e,f,g){var h,m,k;c.$watch(e.ngIf,function(f){Qa(f)?m||(m=c.$new(),g(m,function(c){c[c.length++]=V.createComment(" end ngIf: "+e.ngIf+" ");h={clone:c};a.enter(c,d.parent(),d)})):(k&&(k.remove(),
|
||||
k=null),m&&(m.$destroy(),m=null),h&&(k=Db(h.clone),a.leave(k,function(){k=null}),h=null))})}}}],td=["$http","$templateCache","$anchorScroll","$animate","$sce",function(a,c,d,e,f){return{restrict:"ECA",priority:400,terminal:!0,transclude:"element",controller:Ra.noop,compile:function(g,h){var m=h.ngInclude||h.src,k=h.onload||"",l=h.autoscroll;return function(g,h,q,s,D){var x=0,t,y,B,v=function(){y&&(y.remove(),y=null);t&&(t.$destroy(),t=null);B&&(e.leave(B,function(){y=null}),y=B,B=null)};g.$watch(f.parseAsResourceUrl(m),
|
||||
function(f){var m=function(){!z(l)||l&&!g.$eval(l)||d()},q=++x;f?(a.get(f,{cache:c}).success(function(a){if(q===x){var c=g.$new();s.template=a;a=D(c,function(a){v();e.enter(a,null,h,m)});t=c;B=a;t.$emit("$includeContentLoaded");g.$eval(k)}}).error(function(){q===x&&v()}),g.$emit("$includeContentRequested")):(v(),s.template=null)})}}}}],Jd=["$compile",function(a){return{restrict:"ECA",priority:-400,require:"ngInclude",link:function(c,d,e,f){d.html(f.template);a(d.contents())(c)}}}],ud=va({priority:450,
|
||||
compile:function(){return{pre:function(a,c,d){a.$eval(d.ngInit)}}}}),vd=va({terminal:!0,priority:1E3}),wd=["$locale","$interpolate",function(a,c){var d=/{}/g;return{restrict:"EA",link:function(e,f,g){var h=g.count,m=g.$attr.when&&f.attr(g.$attr.when),k=g.offset||0,l=e.$eval(m)||{},n={},p=c.startSymbol(),r=c.endSymbol(),s=/^when(Minus)?(.+)$/;q(g,function(a,c){s.test(c)&&(l[J(c.replace("when","").replace("Minus","-"))]=f.attr(g.$attr[c]))});q(l,function(a,e){n[e]=c(a.replace(d,p+h+"-"+k+r))});e.$watch(function(){var c=
|
||||
parseFloat(e.$eval(h));if(isNaN(c))return"";c in l||(c=a.pluralCat(c-k));return n[c](e,f,!0)},function(a){f.text(a)})}}}],xd=["$parse","$animate",function(a,c){var d=u("ngRepeat");return{transclude:"element",priority:1E3,terminal:!0,$$tlb:!0,link:function(e,f,g,h,m){var k=g.ngRepeat,l=k.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),n,p,r,s,D,x,t={$id:Ia};if(!l)throw d("iexp",k);g=l[1];h=l[2];(l=l[3])?(n=a(l),p=function(a,c,d){x&&(t[x]=a);t[D]=c;t.$index=d;return n(e,
|
||||
t)}):(r=function(a,c){return Ia(c)},s=function(a){return a});l=g.match(/^(?:([\$\w]+)|\(([\$\w]+)\s*,\s*([\$\w]+)\))$/);if(!l)throw d("iidexp",g);D=l[3]||l[1];x=l[2];var z={};e.$watchCollection(h,function(a){var g,h,l=f[0],n,t={},F,R,C,w,T,u,E=[];if(db(a))T=a,n=p||r;else{n=p||s;T=[];for(C in a)a.hasOwnProperty(C)&&"$"!=C.charAt(0)&&T.push(C);T.sort()}F=T.length;h=E.length=T.length;for(g=0;g<h;g++)if(C=a===T?g:T[g],w=a[C],w=n(C,w,g),Aa(w,"`track by` id"),z.hasOwnProperty(w))u=z[w],delete z[w],t[w]=
|
||||
u,E[g]=u;else{if(t.hasOwnProperty(w))throw q(E,function(a){a&&a.scope&&(z[a.id]=a)}),d("dupes",k,w);E[g]={id:w};t[w]=!1}for(C in z)z.hasOwnProperty(C)&&(u=z[C],g=Db(u.clone),c.leave(g),q(g,function(a){a.$$NG_REMOVED=!0}),u.scope.$destroy());g=0;for(h=T.length;g<h;g++){C=a===T?g:T[g];w=a[C];u=E[g];E[g-1]&&(l=E[g-1].clone[E[g-1].clone.length-1]);if(u.scope){R=u.scope;n=l;do n=n.nextSibling;while(n&&n.$$NG_REMOVED);u.clone[0]!=n&&c.move(Db(u.clone),null,y(l));l=u.clone[u.clone.length-1]}else R=e.$new();
|
||||
R[D]=w;x&&(R[x]=C);R.$index=g;R.$first=0===g;R.$last=g===F-1;R.$middle=!(R.$first||R.$last);R.$odd=!(R.$even=0===(g&1));u.scope||m(R,function(a){a[a.length++]=V.createComment(" end ngRepeat: "+k+" ");c.enter(a,null,y(l));l=a;u.scope=R;u.clone=a;t[u.id]=u})}z=t})}}}],yd=["$animate",function(a){return function(c,d,e){c.$watch(e.ngShow,function(c){a[Qa(c)?"removeClass":"addClass"](d,"ng-hide")})}}],rd=["$animate",function(a){return function(c,d,e){c.$watch(e.ngHide,function(c){a[Qa(c)?"addClass":"removeClass"](d,
|
||||
"ng-hide")})}}],zd=va(function(a,c,d){a.$watch(d.ngStyle,function(a,d){d&&a!==d&&q(d,function(a,d){c.css(d,"")});a&&c.css(a)},!0)}),Ad=["$animate",function(a){return{restrict:"EA",require:"ngSwitch",controller:["$scope",function(){this.cases={}}],link:function(c,d,e,f){var g=[],h=[],m=[],k=[];c.$watch(e.ngSwitch||e.on,function(d){var n,p;n=0;for(p=m.length;n<p;++n)m[n].remove();n=m.length=0;for(p=k.length;n<p;++n){var r=h[n];k[n].$destroy();m[n]=r;a.leave(r,function(){m.splice(n,1)})}h.length=0;k.length=
|
||||
0;if(g=f.cases["!"+d]||f.cases["?"])c.$eval(e.change),q(g,function(d){var e=c.$new();k.push(e);d.transclude(e,function(c){var e=d.element;h.push(c);a.enter(c,e.parent(),e)})})})}}}],Bd=va({transclude:"element",priority:800,require:"^ngSwitch",link:function(a,c,d,e,f){e.cases["!"+d.ngSwitchWhen]=e.cases["!"+d.ngSwitchWhen]||[];e.cases["!"+d.ngSwitchWhen].push({transclude:f,element:c})}}),Cd=va({transclude:"element",priority:800,require:"^ngSwitch",link:function(a,c,d,e,f){e.cases["?"]=e.cases["?"]||
|
||||
[];e.cases["?"].push({transclude:f,element:c})}}),Ed=va({link:function(a,c,d,e,f){if(!f)throw u("ngTransclude")("orphan",ha(c));f(function(a){c.empty();c.append(a)})}}),ed=["$templateCache",function(a){return{restrict:"E",terminal:!0,compile:function(c,d){"text/ng-template"==d.type&&a.put(d.id,c[0].text)}}}],Te=u("ngOptions"),Dd=aa({terminal:!0}),fd=["$compile","$parse",function(a,c){var d=/^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+group\s+by\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?$/,
|
||||
e={$setViewValue:w};return{restrict:"E",require:["select","?ngModel"],controller:["$element","$scope","$attrs",function(a,c,d){var m=this,k={},l=e,n;m.databound=d.ngModel;m.init=function(a,c,d){l=a;n=d};m.addOption=function(c){Aa(c,'"option value"');k[c]=!0;l.$viewValue==c&&(a.val(c),n.parent()&&n.remove())};m.removeOption=function(a){this.hasOption(a)&&(delete k[a],l.$viewValue==a&&this.renderUnknownOption(a))};m.renderUnknownOption=function(c){c="? "+Ia(c)+" ?";n.val(c);a.prepend(n);a.val(c);n.prop("selected",
|
||||
!0)};m.hasOption=function(a){return k.hasOwnProperty(a)};c.$on("$destroy",function(){m.renderUnknownOption=w})}],link:function(e,g,h,m){function k(a,c,d,e){d.$render=function(){var a=d.$viewValue;e.hasOption(a)?(w.parent()&&w.remove(),c.val(a),""===a&&x.prop("selected",!0)):H(a)&&x?c.val(""):e.renderUnknownOption(a)};c.on("change",function(){a.$apply(function(){w.parent()&&w.remove();d.$setViewValue(c.val())})})}function l(a,c,d){var e;d.$render=function(){var a=new Xa(d.$viewValue);q(c.find("option"),
|
||||
function(c){c.selected=z(a.get(c.value))})};a.$watch(function(){xa(e,d.$viewValue)||(e=ka(d.$viewValue),d.$render())});c.on("change",function(){a.$apply(function(){var a=[];q(c.find("option"),function(c){c.selected&&a.push(c.value)});d.$setViewValue(a)})})}function n(e,f,g){function h(){var a={"":[]},c=[""],d,k,s,u,v;u=g.$modelValue;v=y(e)||[];var A=n?Wb(v):v,E,I,B;I={};s=!1;var F,H;if(r)if(w&&K(u))for(s=new Xa([]),B=0;B<u.length;B++)I[m]=u[B],s.put(w(e,I),u[B]);else s=new Xa(u);for(B=0;E=A.length,
|
||||
B<E;B++){k=B;if(n){k=A[B];if("$"===k.charAt(0))continue;I[n]=k}I[m]=v[k];d=p(e,I)||"";(k=a[d])||(k=a[d]=[],c.push(d));r?d=z(s.remove(w?w(e,I):q(e,I))):(w?(d={},d[m]=u,d=w(e,d)===w(e,I)):d=u===q(e,I),s=s||d);F=l(e,I);F=z(F)?F:"";k.push({id:w?w(e,I):n?A[B]:B,label:F,selected:d})}r||(D||null===u?a[""].unshift({id:"",label:"",selected:!s}):s||a[""].unshift({id:"?",label:"",selected:!0}));I=0;for(A=c.length;I<A;I++){d=c[I];k=a[d];x.length<=I?(u={element:C.clone().attr("label",d),label:k.label},v=[u],x.push(v),
|
||||
f.append(u.element)):(v=x[I],u=v[0],u.label!=d&&u.element.attr("label",u.label=d));F=null;B=0;for(E=k.length;B<E;B++)s=k[B],(d=v[B+1])?(F=d.element,d.label!==s.label&&F.text(d.label=s.label),d.id!==s.id&&F.val(d.id=s.id),d.selected!==s.selected&&F.prop("selected",d.selected=s.selected)):(""===s.id&&D?H=D:(H=t.clone()).val(s.id).attr("selected",s.selected).text(s.label),v.push({element:H,label:s.label,id:s.id,selected:s.selected}),F?F.after(H):u.element.append(H),F=H);for(B++;v.length>B;)v.pop().element.remove()}for(;x.length>
|
||||
I;)x.pop()[0].element.remove()}var k;if(!(k=u.match(d)))throw Te("iexp",u,ha(f));var l=c(k[2]||k[1]),m=k[4]||k[6],n=k[5],p=c(k[3]||""),q=c(k[2]?k[1]:m),y=c(k[7]),w=k[8]?c(k[8]):null,x=[[{element:f,label:""}]];D&&(a(D)(e),D.removeClass("ng-scope"),D.remove());f.empty();f.on("change",function(){e.$apply(function(){var a,c=y(e)||[],d={},h,k,l,p,t,u,v;if(r)for(k=[],p=0,u=x.length;p<u;p++)for(a=x[p],l=1,t=a.length;l<t;l++){if((h=a[l].element)[0].selected){h=h.val();n&&(d[n]=h);if(w)for(v=0;v<c.length&&
|
||||
(d[m]=c[v],w(e,d)!=h);v++);else d[m]=c[h];k.push(q(e,d))}}else{h=f.val();if("?"==h)k=s;else if(""===h)k=null;else if(w)for(v=0;v<c.length;v++){if(d[m]=c[v],w(e,d)==h){k=q(e,d);break}}else d[m]=c[h],n&&(d[n]=h),k=q(e,d);1<x[0].length&&x[0][1].id!==h&&(x[0][1].selected=!1)}g.$setViewValue(k)})});g.$render=h;e.$watch(h)}if(m[1]){var p=m[0];m=m[1];var r=h.multiple,u=h.ngOptions,D=!1,x,t=y(V.createElement("option")),C=y(V.createElement("optgroup")),w=t.clone();h=0;for(var v=g.children(),E=v.length;h<E;h++)if(""===
|
||||
v[h].value){x=D=v.eq(h);break}p.init(m,D,w);r&&(m.$isEmpty=function(a){return!a||0===a.length});u?n(e,g,m):r?l(e,g,m):k(e,g,m,p)}}}}],hd=["$interpolate",function(a){var c={addOption:w,removeOption:w};return{restrict:"E",priority:100,compile:function(d,e){if(H(e.value)){var f=a(d.text(),!0);f||e.$set("value",d.text())}return function(a,d,e){var k=d.parent(),l=k.data("$selectController")||k.parent().data("$selectController");l&&l.databound?d.prop("selected",!1):l=c;f?a.$watch(f,function(a,c){e.$set("value",
|
||||
a);a!==c&&l.removeOption(c);l.addOption(a)}):l.addOption(e.value);d.on("$destroy",function(){l.removeOption(e.value)})}}}}],gd=aa({restrict:"E",terminal:!0});P.angular.bootstrap?console.log("WARNING: Tried to load angular more than once."):((Ba=P.jQuery)&&Ba.fn.on?(y=Ba,E(Ba.fn,{scope:Ja.scope,isolateScope:Ja.isolateScope,controller:Ja.controller,injector:Ja.injector,inheritedData:Ja.inheritedData}),Fb("remove",!0,!0,!1),Fb("empty",!1,!1,!1),Fb("html",!1,!1,!0)):y=M,Ra.element=y,Zc(Ra),y(V).ready(function(){Wc(V,
|
||||
dc)}))})(window,document);!window.angular.$$csp()&&window.angular.element(document).find("head").prepend('<style type="text/css">@charset "UTF-8";[ng\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide{display:none !important;}ng\\:form{display:block;}.ng-animate-block-transitions{transition:0s all!important;-webkit-transition:0s all!important;}.ng-hide-add-active,.ng-hide-remove{display:block!important;}</style>');
|
||||
//# sourceMappingURL=angular.min.js.map
|
8
trunk/research/console/js/3rdparty/angular.min.js.map
vendored
Normal file
8
trunk/research/console/js/3rdparty/angular.min.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
6167
trunk/research/console/js/3rdparty/bootstrap.css
vendored
Normal file
6167
trunk/research/console/js/3rdparty/bootstrap.css
vendored
Normal file
File diff suppressed because it is too large
Load diff
2280
trunk/research/console/js/3rdparty/bootstrap.js
vendored
Normal file
2280
trunk/research/console/js/3rdparty/bootstrap.js
vendored
Normal file
File diff suppressed because it is too large
Load diff
9
trunk/research/console/js/3rdparty/bootstrap.min.css
vendored
Normal file
9
trunk/research/console/js/3rdparty/bootstrap.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
6
trunk/research/console/js/3rdparty/bootstrap.min.js
vendored
Normal file
6
trunk/research/console/js/3rdparty/bootstrap.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
45
trunk/research/console/js/bravo_alert/alert.js
Executable file
45
trunk/research/console/js/bravo_alert/alert.js
Executable file
|
@ -0,0 +1,45 @@
|
|||
angular.module('bravoUiAlert', [])
|
||||
.directive('bravoAlert', function () {
|
||||
return {
|
||||
restrict: "A",
|
||||
transclude: true,
|
||||
template: '<div ng-transclude></div>',
|
||||
scope: {
|
||||
alert_show: '=alertShow',
|
||||
on_close: '&bravoAlertClose',
|
||||
on_closed: '&bravoAlertClosed'
|
||||
},
|
||||
compile: function (elem, attr) {
|
||||
var manual = attr['alertShow'];
|
||||
return function (scope, elem, attr) {
|
||||
elem.on('click', function(event) {
|
||||
var obj = angular.element(event.target);
|
||||
if (obj.attr('data-dismiss')) {
|
||||
scope.on_destory();
|
||||
}
|
||||
});
|
||||
scope.on_destory = function () {
|
||||
if (!manual) {
|
||||
scope.on_close();
|
||||
elem.addClass('ng-hide');
|
||||
scope.on_closed();
|
||||
} else {
|
||||
scope.on_close();
|
||||
scope.alert_show = false;
|
||||
scope.$apply();
|
||||
}
|
||||
};
|
||||
scope.$watch('alert_show', function (nv, ov) {
|
||||
if (nv != ov) {
|
||||
if (!nv) {
|
||||
elem.addClass('ng-hide');
|
||||
scope.on_closed();
|
||||
} else {
|
||||
elem.removeClass('ng-hide');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
233
trunk/research/console/js/bravo_popover/popover.js
Executable file
233
trunk/research/console/js/bravo_popover/popover.js
Executable file
|
@ -0,0 +1,233 @@
|
|||
angular.module('bravoUiPopover', [])
|
||||
.directive("bravoPopover", function($compile, $position, $sce){
|
||||
// $parse : ng表达式 {{1+2}} {{text}}
|
||||
// $compile : 编译一段html字符串(可以包括ng表达式)
|
||||
return {
|
||||
restrict: "A",
|
||||
scope: {
|
||||
confirm: '&bravoPopoverConfirm'
|
||||
},
|
||||
compile: function (elem, attr) {
|
||||
var confirm_template = attr['bravoPopoverConfirm'] ? '<span>' +
|
||||
'<a class="btn btn-danger" ng-click="on_confirm()">Confirm</a> ' +
|
||||
'<a class="btn btn-info" ng-click="on_cancel()">Cancel</a>' +
|
||||
'</span>' : '';
|
||||
var template =
|
||||
'<div class="popover fade {{placement}} in" ng-show="popoover_show == \'in\'">' +
|
||||
'<div class="arrow"></div>' +
|
||||
'<h3 class="popover-title">{{title}}</h3>' +
|
||||
'<div class="popover-content" ng-bind-html="content">' +
|
||||
'</div>' +
|
||||
'<div class="popover-content" ng-show="show_confirm_template">' +
|
||||
confirm_template +
|
||||
'</div>' +
|
||||
'</div>';
|
||||
var linker = $compile(template);
|
||||
return function (scope, elem, attr) {
|
||||
scope.popoover_show = "";
|
||||
scope.title = attr['title'];
|
||||
scope.content = $sce.trustAsHtml(attr['content']);
|
||||
scope.placement = attr['placement'] ? attr['placement'] : 'top';
|
||||
scope.trigger = attr['bravoPopoverConfirm'] ? 'click' : attr['trigger'];
|
||||
scope.show_confirm_template = attr['bravoPopoverConfirm'] ? true : false;
|
||||
|
||||
var tooltip = linker(scope, function (o) {
|
||||
elem.after(o);
|
||||
});
|
||||
tooltip.css({ top: 0, left: 0, display: 'block' });
|
||||
|
||||
if (!scope.trigger || scope.trigger == 'click') {
|
||||
elem.on('click', function (event) {
|
||||
toggle();
|
||||
});
|
||||
} else {
|
||||
var eventIn = scope.trigger == 'hover' ? 'mouseenter' : 'focus';
|
||||
var eventOut = scope.trigger == 'hover' ? 'mouseleave' : 'blur';
|
||||
elem.on(eventIn, function (event) {
|
||||
show_popover();
|
||||
});
|
||||
elem.on(eventOut, function () {
|
||||
hide_popover();
|
||||
});
|
||||
}
|
||||
|
||||
var toggle = function() {
|
||||
scope.popoover_show == 'in'? hide_popover() : show_popover();
|
||||
render_css(tooltip);
|
||||
};
|
||||
|
||||
var show_popover = function() {
|
||||
scope.popoover_show = "in";
|
||||
scope.$apply();
|
||||
render_css(tooltip);
|
||||
};
|
||||
|
||||
var hide_popover = function() {
|
||||
scope.popoover_show = "";
|
||||
scope.$apply();
|
||||
};
|
||||
|
||||
var render_css = function (scope_element) {
|
||||
var ttPosition = $position.positionElements(elem, scope_element, scope.placement, false);
|
||||
ttPosition.top += 'px';
|
||||
ttPosition.left += 'px';
|
||||
// Now set the calculated positioning.
|
||||
scope_element.css( ttPosition );
|
||||
};
|
||||
|
||||
render_css(tooltip);
|
||||
scope.on_cancel = function () {
|
||||
scope.popoover_show = "";
|
||||
};
|
||||
scope.on_confirm = function () {
|
||||
scope.confirm();
|
||||
scope.popoover_show = "";
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
})
|
||||
.factory('$position', ['$document', '$window', function ($document, $window) {
|
||||
|
||||
function getStyle(el, cssprop) {
|
||||
if (el.currentStyle) { //IE
|
||||
return el.currentStyle[cssprop];
|
||||
} else if ($window.getComputedStyle) {
|
||||
return $window.getComputedStyle(el)[cssprop];
|
||||
}
|
||||
// finally try and get inline style
|
||||
return el.style[cssprop];
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a given element is statically positioned
|
||||
* @param element - raw DOM element
|
||||
*/
|
||||
function isStaticPositioned(element) {
|
||||
return (getStyle(element, 'position') || 'static' ) === 'static';
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the closest, non-statically positioned parentOffset of a given element
|
||||
* @param element
|
||||
*/
|
||||
var parentOffsetEl = function (element) {
|
||||
var docDomEl = $document[0];
|
||||
var offsetParent = element.offsetParent || docDomEl;
|
||||
while (offsetParent && offsetParent !== docDomEl && isStaticPositioned(offsetParent) ) {
|
||||
offsetParent = offsetParent.offsetParent;
|
||||
}
|
||||
return offsetParent || docDomEl;
|
||||
};
|
||||
|
||||
return {
|
||||
/**
|
||||
* Provides read-only equivalent of jQuery's position function:
|
||||
* http://api.jquery.com/position/
|
||||
*/
|
||||
position: function (element) {
|
||||
var elBCR = this.offset(element);
|
||||
var offsetParentBCR = { top: 0, left: 0 };
|
||||
var offsetParentEl = parentOffsetEl(element[0]);
|
||||
if (offsetParentEl != $document[0]) {
|
||||
offsetParentBCR = this.offset(angular.element(offsetParentEl));
|
||||
offsetParentBCR.top += offsetParentEl.clientTop - offsetParentEl.scrollTop;
|
||||
offsetParentBCR.left += offsetParentEl.clientLeft - offsetParentEl.scrollLeft;
|
||||
}
|
||||
|
||||
var boundingClientRect = element[0].getBoundingClientRect();
|
||||
return {
|
||||
width: boundingClientRect.width || element.prop('offsetWidth'),
|
||||
height: boundingClientRect.height || element.prop('offsetHeight'),
|
||||
top: elBCR.top - offsetParentBCR.top,
|
||||
left: elBCR.left - offsetParentBCR.left
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Provides read-only equivalent of jQuery's offset function:
|
||||
* http://api.jquery.com/offset/
|
||||
*/
|
||||
offset: function (element) {
|
||||
var boundingClientRect = element[0].getBoundingClientRect();
|
||||
return {
|
||||
width: boundingClientRect.width || element.prop('offsetWidth'),
|
||||
height: boundingClientRect.height || element.prop('offsetHeight'),
|
||||
top: boundingClientRect.top + ($window.pageYOffset || $document[0].documentElement.scrollTop),
|
||||
left: boundingClientRect.left + ($window.pageXOffset || $document[0].documentElement.scrollLeft)
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Provides coordinates for the targetEl in relation to hostEl
|
||||
*/
|
||||
positionElements: function (hostEl, targetEl, positionStr, appendToBody) {
|
||||
|
||||
var positionStrParts = positionStr.split('-');
|
||||
var pos0 = positionStrParts[0], pos1 = positionStrParts[1] || 'center';
|
||||
|
||||
var hostElPos,
|
||||
targetElWidth,
|
||||
targetElHeight,
|
||||
targetElPos;
|
||||
|
||||
hostElPos = appendToBody ? this.offset(hostEl) : this.position(hostEl);
|
||||
|
||||
targetElWidth = targetEl.prop('offsetWidth');
|
||||
targetElHeight = targetEl.prop('offsetHeight');
|
||||
|
||||
var shiftWidth = {
|
||||
center: function () {
|
||||
return hostElPos.left + hostElPos.width / 2 - targetElWidth / 2;
|
||||
},
|
||||
left: function () {
|
||||
return hostElPos.left;
|
||||
},
|
||||
right: function () {
|
||||
return hostElPos.left + hostElPos.width;
|
||||
}
|
||||
};
|
||||
|
||||
var shiftHeight = {
|
||||
center: function () {
|
||||
return hostElPos.top + hostElPos.height / 2 - targetElHeight / 2;
|
||||
},
|
||||
top: function () {
|
||||
return hostElPos.top;
|
||||
},
|
||||
bottom: function () {
|
||||
return hostElPos.top + hostElPos.height;
|
||||
}
|
||||
};
|
||||
|
||||
switch (pos0) {
|
||||
case 'right':
|
||||
targetElPos = {
|
||||
top: shiftHeight[pos1](),
|
||||
left: shiftWidth[pos0]()
|
||||
};
|
||||
break;
|
||||
case 'left':
|
||||
targetElPos = {
|
||||
top: shiftHeight[pos1](),
|
||||
left: hostElPos.left - targetElWidth
|
||||
};
|
||||
break;
|
||||
case 'bottom':
|
||||
targetElPos = {
|
||||
top: shiftHeight[pos0](),
|
||||
left: shiftWidth[pos1]()
|
||||
};
|
||||
break;
|
||||
default:
|
||||
targetElPos = {
|
||||
top: hostElPos.top - targetElHeight,
|
||||
left: shiftWidth[pos1]()
|
||||
};
|
||||
break;
|
||||
}
|
||||
|
||||
return targetElPos;
|
||||
}
|
||||
};
|
||||
}]);
|
BIN
trunk/research/console/js/img/glyphicons-halflings-white.png
Normal file
BIN
trunk/research/console/js/img/glyphicons-halflings-white.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.6 KiB |
BIN
trunk/research/console/js/img/glyphicons-halflings.png
Normal file
BIN
trunk/research/console/js/img/glyphicons-halflings.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
106
trunk/research/console/js/srs.cn.js
Normal file
106
trunk/research/console/js/srs.cn.js
Normal file
|
@ -0,0 +1,106 @@
|
|||
var scApp = angular.module("scApp", ["ngRoute", "ngResource",
|
||||
"bravoUiAlert", "bravoUiPopover"
|
||||
]);
|
||||
|
||||
scApp.config(["$routeProvider", function($routeProvider){
|
||||
$routeProvider.otherwise({redirectTo:"/connect"})
|
||||
.when("/connect", {templateUrl:"views/connect.html", controller:"CSCConnect"})
|
||||
.when("/vhosts", {templateUrl:"views/vhosts.html", controller:"CSCVhosts"})
|
||||
.when("/vhosts/:id", {templateUrl:"views/vhost.html", controller:"CSCVhost"})
|
||||
.when("/streams", {templateUrl:"views/streams.html", controller:"CSCStreams"})
|
||||
.when("/streams/:id", {templateUrl:"views/stream.html", controller:"CSCStream"})
|
||||
.when("/clients", {templateUrl:"views/clients.html", controller:"CSCClients"})
|
||||
.when("/clients/:id", {templateUrl:"views/client.html", controller:"CSCClient"})
|
||||
.when("/configs", {templateUrl:"views/configs.html", controller:"CSCConfigs"})
|
||||
.when("/configs/:id", {templateUrl:"views/config.html", controller:"CSCConfig"})
|
||||
.when("/dvr", {templateUrl:"views/dvrs.html", controller:"CSCDvrs"})
|
||||
.when("/dvr/:vid/:sid/:app/:stream", {templateUrl:"views/dvr.html", controller:"CSCDvr"})
|
||||
.when("/summaries", {templateUrl:"views/summary.html", controller:"CSCSummary"});
|
||||
}]);
|
||||
|
||||
scApp.filter("sc_filter_time", function(){
|
||||
return function(v){
|
||||
var s = "";
|
||||
if (v > 3600 * 24) {
|
||||
s = Number(v / 3600 / 24).toFixed(0) + "天 ";
|
||||
v = v % (3600 * 24);
|
||||
}
|
||||
s += relative_seconds_to_HHMMSS(v);
|
||||
return s;
|
||||
};
|
||||
});
|
||||
|
||||
scApp.filter("sc_filter_yesno", function(){
|
||||
return function(v){
|
||||
return v? "是":"否";
|
||||
};
|
||||
});
|
||||
|
||||
scApp.filter("sc_filter_enabled", function(){
|
||||
return function(v){
|
||||
return v? "开启":"关闭";
|
||||
};
|
||||
});
|
||||
|
||||
scApp.filter("sc_filter_yn", function(){
|
||||
return function(v){
|
||||
return v? "Y":"N";
|
||||
};
|
||||
});
|
||||
|
||||
scApp.filter("sc_filter_has_stream", function(){
|
||||
return function(v){
|
||||
return v? "有流":"无流";
|
||||
};
|
||||
});
|
||||
|
||||
scApp.filter("sc_filter_ctype", function(){
|
||||
return function(v){
|
||||
return v? "推流":"播放";
|
||||
};
|
||||
});
|
||||
|
||||
scApp.filter("sc_filter_obj", function(){
|
||||
return function(v) {
|
||||
return v !== undefined? v : "未设置";
|
||||
};
|
||||
});
|
||||
|
||||
scApp.filter("sc_filter_security", function(){
|
||||
return function(v) {
|
||||
var action = v.action === "allow"? "允许":"禁止";
|
||||
var method = v.method === "all"? "任何操作": (v.method === "publish"? "推流":"播放");
|
||||
var entry = v.entry === "all"? "所有人" : v.entry;
|
||||
return action + " " + entry + " " + method;
|
||||
}
|
||||
});
|
||||
|
||||
var scDirectiveTemplate = ''
|
||||
+ '<td class="{{data.error| sc_filter_style_error}}">'
|
||||
+ '{{key}}'
|
||||
+ '</td>'
|
||||
+ '<td colspan="{{editing? 2:0}}" title="{{data.value}}" class="{{data.error| sc_filter_style_error}}">'
|
||||
+ '<div class="form-inline">'
|
||||
+ '<span class="{{!data.error && data.value == undefined?\'label\':\'\'}}" ng-show="!editing">'
|
||||
+ '<span ng-show="bool == \'true\' && data.value != undefined">{{data.value| sc_filter_enabled}}</span>'
|
||||
+ '<span ng-show="bool != \'true\' || data.value == undefined">{{data.value| sc_filter_obj| sc_filter_less}}</span>'
|
||||
+ '</span> '
|
||||
+ '<input type="text" class="{{span}} inline" ng-show="editing && bool != \'true\' && !select" ng-model="data.value"> '
|
||||
+ '<label class="checkbox" ng-show="editing && bool == \'true\'"><input type="checkbox" ng-model="data.value">开启</label> '
|
||||
+ '<select ng-model="data.value" ng-options="s as s for s in selects" ng-show="editing && select"></select>'
|
||||
+ '<a href="javascript:void(0)" ng-click="load_default()" ng-show="editing && default != undefined" title="使用默认值">使用默认值</a> '
|
||||
+ '</div>'
|
||||
+ '<div ng-show="editing">{{desc}}</div>'
|
||||
+ '</td>'
|
||||
+ '<td ng-show="!editing" class="{{data.error| sc_filter_style_error}}">'
|
||||
+ '{{desc}}'
|
||||
+ '</td>'
|
||||
+ '<td class="span1 {{data.error| sc_filter_style_error}}">'
|
||||
+ '<a href="javascript:void(0)" ng-click="edit()" ng-show="!editing" title="修改">修改</a> '
|
||||
+ '<a bravo-popover href="javascript:void(0)"'
|
||||
+ 'data-content="请确认是否修改?" data-title="请确认" data-placement="left"'
|
||||
+ 'bravo-popover-confirm="commit()" ng-show="editing">'
|
||||
+ '提交'
|
||||
+ '</a> '
|
||||
+ '<a href="javascript:void(0)" ng-click="cancel()" ng-show="editing" title="取消">放弃</a> '
|
||||
+ '</td>';
|
23
trunk/research/console/js/srs.console.css
Normal file
23
trunk/research/console/js/srs.console.css
Normal file
|
@ -0,0 +1,23 @@
|
|||
/* Footer
|
||||
-------------------------------------------------- */
|
||||
.footer {
|
||||
text-align: center;
|
||||
padding: 30px 0;
|
||||
margin-top: 10px;
|
||||
border-top: 1px solid #e5e5e5;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
.footer p {
|
||||
margin-bottom: 0;
|
||||
color: #777;
|
||||
}
|
||||
.footer-links {
|
||||
margin: 10px 0;
|
||||
}
|
||||
.footer-links li {
|
||||
display: inline;
|
||||
padding: 0 2px;
|
||||
}
|
||||
.footer-links li:first-child {
|
||||
padding-left: 0;
|
||||
}
|
1375
trunk/research/console/js/srs.console.js
Normal file
1375
trunk/research/console/js/srs.console.js
Normal file
File diff suppressed because it is too large
Load diff
107
trunk/research/console/js/srs.en.js
Normal file
107
trunk/research/console/js/srs.en.js
Normal file
|
@ -0,0 +1,107 @@
|
|||
var scApp = angular.module("scApp", ["ngRoute", "ngResource",
|
||||
"bravoUiAlert", "bravoUiPopover"
|
||||
]);
|
||||
|
||||
scApp.config(["$routeProvider", function($routeProvider){
|
||||
$routeProvider.otherwise({redirectTo:"/connect"})
|
||||
.when("/connect", {templateUrl:"views/connect_en.html", controller:"CSCConnect"})
|
||||
.when("/vhosts", {templateUrl:"views/vhosts_en.html", controller:"CSCVhosts"})
|
||||
.when("/vhosts/:id", {templateUrl:"views/vhost_en.html", controller:"CSCVhost"})
|
||||
.when("/streams", {templateUrl:"views/streams_en.html", controller:"CSCStreams"})
|
||||
.when("/streams/:id", {templateUrl:"views/stream_en.html", controller:"CSCStream"})
|
||||
.when("/clients", {templateUrl:"views/clients_en.html", controller:"CSCClients"})
|
||||
.when("/clients/:id", {templateUrl:"views/client_en.html", controller:"CSCClient"})
|
||||
.when("/configs", {templateUrl:"views/configs_en.html", controller:"CSCConfigs"})
|
||||
.when("/configs/:id", {templateUrl:"views/config_en.html", controller:"CSCConfig"})
|
||||
.when("/dvr", {templateUrl:"views/dvrs_en.html", controller:"CSCDvrs"})
|
||||
.when("/dvr/:vid/:sid/:app/:stream", {templateUrl:"views/dvr_en.html", controller:"CSCDvr"})
|
||||
.when("/summaries", {templateUrl:"views/summary_en.html", controller:"CSCSummary"});
|
||||
}]);
|
||||
|
||||
scApp.filter("sc_filter_time", function(){
|
||||
return function(v){
|
||||
var s = "";
|
||||
if (v > 3600 * 24) {
|
||||
s = Number(v / 3600 / 24).toFixed(0) + "d ";
|
||||
v = v % (3600 * 24);
|
||||
}
|
||||
s += relative_seconds_to_HHMMSS(v);
|
||||
return s;
|
||||
};
|
||||
});
|
||||
|
||||
scApp.filter("sc_filter_yesno", function(){
|
||||
return function(v){
|
||||
return v? "Yes":"No";
|
||||
};
|
||||
});
|
||||
|
||||
scApp.filter("sc_filter_enabled", function(){
|
||||
return function(v){
|
||||
return v? "Enabled":"Disabled";
|
||||
};
|
||||
});
|
||||
|
||||
scApp.filter("sc_filter_yn", function(){
|
||||
return function(v){
|
||||
return v? "Y":"N";
|
||||
};
|
||||
});
|
||||
|
||||
scApp.filter("sc_filter_has_stream", function(){
|
||||
return function(v){
|
||||
return v? "Y":"N";
|
||||
};
|
||||
});
|
||||
|
||||
scApp.filter("sc_filter_ctype", function(){
|
||||
return function(v){
|
||||
return v? "Publish":"Play";
|
||||
};
|
||||
});
|
||||
|
||||
scApp.filter("sc_filter_obj", function(){
|
||||
return function(v) {
|
||||
return v !== undefined? v : "Unknown";
|
||||
};
|
||||
});
|
||||
|
||||
scApp.filter("sc_filter_security", function(){
|
||||
return function(v) {
|
||||
var action = v.action === "allow"? "Allow":"Denied";
|
||||
var method = v.method === "all"? "Any": (v.method === "publish"? "Publish":"Play");
|
||||
var entry = v.entry === "all"? "All" : v.entry;
|
||||
return action + " " + entry + " " + method;
|
||||
}
|
||||
});
|
||||
|
||||
var scDirectiveTemplate = ''
|
||||
+ '<td class="{{data.error| sc_filter_style_error}}">'
|
||||
+ '{{key}}'
|
||||
+ '</td>'
|
||||
+ '<td colspan="{{editing? 2:0}}" title="{{data.value}}" class="{{data.error| sc_filter_style_error}}">'
|
||||
+ '<div class="form-inline">'
|
||||
+ '<span class="{{!data.error && data.value == undefined?\'label\':\'\'}}" ng-show="!editing">'
|
||||
+ '<span ng-show="bool == \'true\' && data.value != undefined">{{data.value| sc_filter_enabled}}</span>'
|
||||
+ '<span ng-show="bool != \'true\' || data.value == undefined">{{data.value| sc_filter_obj| sc_filter_less}}</span>'
|
||||
+ '</span> '
|
||||
+ '<input type="text" class="{{span}} inline" ng-show="editing && bool != \'true\' && !select" ng-model="data.value"> '
|
||||
+ '<label class="checkbox" ng-show="editing && bool == \'true\'"><input type="checkbox" ng-model="data.value">Enable</label> '
|
||||
+ '<select ng-model="data.value" ng-options="s as s for s in selects" ng-show="editing && select"></select>'
|
||||
+ '<a href="javascript:void(0)" ng-click="load_default()" ng-show="editing && default != undefined" title="Use Default Values">Restore</a> '
|
||||
+ '</div>'
|
||||
+ '<div ng-show="editing">{{desc}}</div>'
|
||||
+ '</td>'
|
||||
+ '<td ng-show="!editing" class="{{data.error| sc_filter_style_error}}">'
|
||||
+ '{{desc}}'
|
||||
+ '</td>'
|
||||
+ '<td class="span1 {{data.error| sc_filter_style_error}}">'
|
||||
+ '<a href="javascript:void(0)" ng-click="edit()" ng-show="!editing" title="Mofity it">Update</a> '
|
||||
+ '<a bravo-popover href="javascript:void(0)"'
|
||||
+ 'data-content="Confirm Update?" data-title="Please Confirm" data-placement="left"'
|
||||
+ 'bravo-popover-confirm="commit()" ng-show="editing">'
|
||||
+ 'Submit'
|
||||
+ '</a> '
|
||||
+ '<a href="javascript:void(0)" ng-click="cancel()" ng-show="editing" title="Cancel">Cancel</a> '
|
||||
+ '</td>';
|
||||
|
685
trunk/research/console/js/winlin.utility.js
Normal file
685
trunk/research/console/js/winlin.utility.js
Normal file
|
@ -0,0 +1,685 @@
|
|||
// winlin.utility.js
|
||||
|
||||
/**
|
||||
* common utilities
|
||||
* depends: jquery1.10
|
||||
* https://gitee.com/winlinvip/codes/rpn0c2ewbomj81augzk4y59
|
||||
* @see: http://blog.csdn.net/win_lin/article/details/17994347
|
||||
* v 1.0.22
|
||||
*/
|
||||
|
||||
/**
|
||||
* padding the output.
|
||||
* padding(3, 5, '0') is 00003
|
||||
* padding(3, 5, 'x') is xxxx3
|
||||
* @see http://blog.csdn.net/win_lin/article/details/12065413
|
||||
*/
|
||||
function padding(number, length, prefix) {
|
||||
if(String(number).length >= length){
|
||||
return String(number);
|
||||
}
|
||||
return padding(prefix+number, length, prefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* extends system array, to remove all specified elem.
|
||||
* @param arr the array to remove elem from.
|
||||
* @param elem the elem to remove.
|
||||
* @remark all elem will be removed.
|
||||
* for example,
|
||||
* arr = [10, 15, 20, 30, 20, 40]
|
||||
* system_array_remove(arr, 10) // arr=[15, 20, 30, 20, 40]
|
||||
* system_array_remove(arr, 20) // arr=[15, 30, 40]
|
||||
*/
|
||||
function system_array_remove(arr, elem) {
|
||||
if (!arr) {
|
||||
return;
|
||||
}
|
||||
|
||||
var removed = true;
|
||||
var i = 0;
|
||||
while (removed) {
|
||||
removed = false;
|
||||
for (; i < arr.length; i++) {
|
||||
if (elem == arr[i]) {
|
||||
arr.splice(i, 1);
|
||||
removed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* whether the array contains specified element.
|
||||
* @param arr the array to find.
|
||||
* @param elem_or_function the element value or compare function.
|
||||
* @returns true contains elem; otherwise false.
|
||||
* for example,
|
||||
* arr = [10, 15, 20, 30, 20, 40]
|
||||
* system_array_contains(arr, 10) // true
|
||||
* system_array_contains(arr, 11) // false
|
||||
* system_array_contains(arr, function(elem){return elem == 30;}); // true
|
||||
* system_array_contains(arr, function(elem){return elem == 60;}); // false
|
||||
*/
|
||||
function system_array_contains(arr, elem_or_function) {
|
||||
return system_array_get(arr, elem_or_function) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the specified element from array
|
||||
* @param arr the array to find.
|
||||
* @param elem_or_function the element value or compare function.
|
||||
* @returns the matched elem; otherwise null.
|
||||
* for example,
|
||||
* arr = [10, 15, 20, 30, 20, 40]
|
||||
* system_array_get(arr, 10) // 10
|
||||
* system_array_get(arr, 11) // null
|
||||
* system_array_get(arr, function(elem){return elem == 30;}); // 30
|
||||
* system_array_get(arr, function(elem){return elem == 60;}); // null
|
||||
*/
|
||||
function system_array_get(arr, elem_or_function) {
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
if (typeof elem_or_function == "function") {
|
||||
if (elem_or_function(arr[i])) {
|
||||
return arr[i];
|
||||
}
|
||||
} else {
|
||||
if (elem_or_function == arr[i]) {
|
||||
return arr[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* to iterate on array.
|
||||
* @param arr the array to iterate on.
|
||||
* @param pfn the function to apply on it. return false to break loop.
|
||||
* for example,
|
||||
* arr = [10, 15, 20, 30, 20, 40]
|
||||
* system_array_foreach(arr, function(elem, index){
|
||||
* console.log('index=' + index + ',elem=' + elem);
|
||||
* });
|
||||
* @return true when iterate all elems.
|
||||
*/
|
||||
function system_array_foreach(arr, pfn) {
|
||||
if (!pfn) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
if (!pfn(arr[i], i)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* whether the str starts with flag.
|
||||
*/
|
||||
function system_string_startswith(str, flag) {
|
||||
if (typeof flag == "object" && flag.constructor == Array) {
|
||||
for (var i = 0; i < flag.length; i++) {
|
||||
if (system_string_startswith(str, flag[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return str && flag && str.length >= flag.length && str.indexOf(flag) == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* whether the str ends with flag.
|
||||
*/
|
||||
function system_string_endswith(str, flag) {
|
||||
if (typeof flag == "object" && flag.constructor == Array) {
|
||||
for (var i = 0; i < flag.length; i++) {
|
||||
if (system_string_endswith(str, flag[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return str && flag && str.length >= flag.length && str.indexOf(flag) == str.length - flag.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* trim the start and end of flag in str.
|
||||
* @param flag a string to trim.
|
||||
*/
|
||||
function system_string_trim(str, flag) {
|
||||
if (!flag || !flag.length || typeof flag != "string") {
|
||||
return str;
|
||||
}
|
||||
|
||||
while (system_string_startswith(str, flag)) {
|
||||
str = str.substr(flag.length);
|
||||
}
|
||||
|
||||
while (system_string_endswith(str, flag)) {
|
||||
str = str.substr(0, str.length - flag.length);
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* array sort asc, for example:
|
||||
* [a, b] in [10, 11, 9]
|
||||
* then sort to: [9, 10, 11]
|
||||
* Usage, for example:
|
||||
obj.data.data.sort(function(a, b){
|
||||
return array_sort_asc(a.metadata.meta_id, b.metadata.meta_id);
|
||||
});
|
||||
* @see: http://blog.csdn.net/win_lin/article/details/17994347
|
||||
* @remark, if need desc, use -1*array_sort_asc(a,b)
|
||||
*/
|
||||
function array_sort_asc(elem_a, elem_b) {
|
||||
if (elem_a > elem_b) {
|
||||
return 1;
|
||||
}
|
||||
return (elem_a < elem_b)? -1 : 0;
|
||||
}
|
||||
function array_sort_desc(elem_a, elem_b) {
|
||||
return -1 * array_sort_asc(elem_a, elem_b);
|
||||
}
|
||||
function system_array_sort_asc(elem_a, elem_b) {
|
||||
return array_sort_asc(elem_a, elem_b);
|
||||
}
|
||||
function system_array_sort_desc(elem_a, elem_b) {
|
||||
return -1 * array_sort_asc(elem_a, elem_b);
|
||||
}
|
||||
|
||||
/**
|
||||
* parse the query string to object.
|
||||
* parse the url location object as: host(hostname:http_port), pathname(dir/filename)
|
||||
* for example, url http://192.168.1.168:1980/ui/players.html?vhost=player.vhost.com&app=test&stream=livestream
|
||||
* parsed to object:
|
||||
{
|
||||
host : "192.168.1.168:1980",
|
||||
hostname : "192.168.1.168",
|
||||
http_port : 1980,
|
||||
pathname : "/ui/players.html",
|
||||
dir : "/ui",
|
||||
filename : "/players.html",
|
||||
|
||||
vhost : "player.vhost.com",
|
||||
app : "test",
|
||||
stream : "livestream"
|
||||
}
|
||||
* @see: http://blog.csdn.net/win_lin/article/details/17994347
|
||||
*/
|
||||
function parse_query_string(){
|
||||
var obj = {};
|
||||
|
||||
// add the uri object.
|
||||
// parse the host(hostname:http_port), pathname(dir/filename)
|
||||
obj.host = window.location.host;
|
||||
obj.hostname = window.location.hostname;
|
||||
obj.http_port = (window.location.port == "")? 80:window.location.port;
|
||||
obj.pathname = window.location.pathname;
|
||||
if (obj.pathname.lastIndexOf("/") <= 0) {
|
||||
obj.dir = "/";
|
||||
obj.filename = "";
|
||||
} else {
|
||||
obj.dir = obj.pathname.substr(0, obj.pathname.lastIndexOf("/"));
|
||||
obj.filename = obj.pathname.substr(obj.pathname.lastIndexOf("/"));
|
||||
}
|
||||
|
||||
// pure user query object.
|
||||
obj.user_query = {};
|
||||
|
||||
// parse the query string.
|
||||
var query_string = String(window.location.search).replace(" ", "").split("?")[1];
|
||||
if(query_string === undefined){
|
||||
query_string = String(window.location.hash).replace(" ", "").split("#")[1];
|
||||
if(query_string === undefined){
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
__fill_query(query_string, obj);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
function __fill_query(query_string, obj) {
|
||||
// pure user query object.
|
||||
obj.user_query = {};
|
||||
|
||||
if (query_string.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// split again for angularjs.
|
||||
if (query_string.indexOf("?") >= 0) {
|
||||
query_string = query_string.split("?")[1];
|
||||
}
|
||||
|
||||
var queries = query_string.split("&");
|
||||
for (var i = 0; i < queries.length; i++) {
|
||||
var elem = queries[i];
|
||||
|
||||
var query = elem.split("=");
|
||||
obj[query[0]] = query[1];
|
||||
obj.user_query[query[0]] = query[1];
|
||||
}
|
||||
|
||||
// alias domain for vhost.
|
||||
if (obj.domain) {
|
||||
obj.vhost = obj.domain;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* parse the rtmp url,
|
||||
* for example: rtmp://demo.srs.com:1935/live...vhost...players/livestream
|
||||
* @return object {server, port, vhost, app, stream}
|
||||
* for exmaple, rtmp_url is rtmp://demo.srs.com:1935/live...vhost...players/livestream
|
||||
* parsed to object:
|
||||
{
|
||||
server: "demo.srs.com",
|
||||
port: 1935,
|
||||
vhost: "players",
|
||||
app: "live",
|
||||
stream: "livestream"
|
||||
}
|
||||
*/
|
||||
function parse_rtmp_url(rtmp_url) {
|
||||
// @see: http://stackoverflow.com/questions/10469575/how-to-use-location-object-to-parse-url-without-redirecting-the-page-in-javascri
|
||||
var a = document.createElement("a");
|
||||
a.href = rtmp_url.replace("rtmp://", "http://")
|
||||
.replace("webrtc://", "http://")
|
||||
.replace("rtc://", "http://");
|
||||
|
||||
var vhost = a.hostname;
|
||||
var app = a.pathname.substr(1, a.pathname.lastIndexOf("/") - 1);
|
||||
var stream = a.pathname.substr(a.pathname.lastIndexOf("/") + 1);
|
||||
|
||||
// parse the vhost in the params of app, that srs supports.
|
||||
app = app.replace("...vhost...", "?vhost=");
|
||||
if (app.indexOf("?") >= 0) {
|
||||
var params = app.substr(app.indexOf("?"));
|
||||
app = app.substr(0, app.indexOf("?"));
|
||||
|
||||
if (params.indexOf("vhost=") > 0) {
|
||||
vhost = params.substr(params.indexOf("vhost=") + "vhost=".length);
|
||||
if (vhost.indexOf("&") > 0) {
|
||||
vhost = vhost.substr(0, vhost.indexOf("&"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// when vhost equals to server, and server is ip,
|
||||
// the vhost is __defaultVhost__
|
||||
if (a.hostname === vhost) {
|
||||
var re = /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/;
|
||||
if (re.test(a.hostname)) {
|
||||
vhost = "__defaultVhost__";
|
||||
}
|
||||
}
|
||||
|
||||
// parse the schema
|
||||
var schema = "rtmp";
|
||||
if (rtmp_url.indexOf("://") > 0) {
|
||||
schema = rtmp_url.substr(0, rtmp_url.indexOf("://"));
|
||||
}
|
||||
|
||||
var port = a.port;
|
||||
if (!port) {
|
||||
if (schema === 'http') {
|
||||
port = 80;
|
||||
} else if (schema === 'https') {
|
||||
port = 443;
|
||||
} else if (schema === 'rtmp') {
|
||||
port = 1935;
|
||||
}
|
||||
}
|
||||
|
||||
var ret = {
|
||||
url: rtmp_url,
|
||||
schema: schema,
|
||||
server: a.hostname, port: port,
|
||||
vhost: vhost, app: app, stream: stream
|
||||
};
|
||||
__fill_query(a.search, ret);
|
||||
|
||||
// For webrtc API, we use 443 if page is https, or schema specified it.
|
||||
if (!ret.port) {
|
||||
if (schema === 'webrtc' || schema === 'rtc') {
|
||||
if (ret.user_query.schema === 'https') {
|
||||
ret.port = 443;
|
||||
} else if (window.location.href.indexOf('https://') === 0) {
|
||||
ret.port = 443;
|
||||
} else {
|
||||
ret.port = 80;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the agent.
|
||||
* @return an object specifies some browser.
|
||||
* for example, get_browser_agents().MSIE
|
||||
* @see: http://blog.csdn.net/win_lin/article/details/17994347
|
||||
*/
|
||||
function get_browser_agents() {
|
||||
var agent = navigator.userAgent;
|
||||
|
||||
/**
|
||||
WindowsPC platform, Win7:
|
||||
chrome 31.0.1650.63:
|
||||
Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36
|
||||
(KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36
|
||||
firefox 23.0.1:
|
||||
Mozilla/5.0 (Windows NT 6.1; WOW64; rv:23.0) Gecko/20100101
|
||||
Firefox/23.0
|
||||
safari 5.1.7(7534.57.2):
|
||||
Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.57.2
|
||||
(KHTML, like Gecko) Version/5.1.7 Safari/534.57.2
|
||||
opera 15.0.1147.153:
|
||||
Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36
|
||||
(KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36
|
||||
OPR/15.0.1147.153
|
||||
360 6.2.1.272:
|
||||
Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64;
|
||||
Trident/6.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729;
|
||||
.NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.2; .NET4.0C;
|
||||
.NET4.0E)
|
||||
IE 10.0.9200.16750(update: 10.0.12):
|
||||
Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64;
|
||||
Trident/6.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729;
|
||||
.NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.2; .NET4.0C;
|
||||
.NET4.0E)
|
||||
*/
|
||||
|
||||
return {
|
||||
// platform
|
||||
Android: agent.indexOf("Android") != -1,
|
||||
Windows: agent.indexOf("Windows") != -1,
|
||||
iPhone: agent.indexOf("iPhone") != -1,
|
||||
// Windows Browsers
|
||||
Chrome: agent.indexOf("Chrome") != -1,
|
||||
Firefox: agent.indexOf("Firefox") != -1,
|
||||
QQBrowser: agent.indexOf("QQBrowser") != -1,
|
||||
MSIE: agent.indexOf("MSIE") != -1,
|
||||
// Android Browsers
|
||||
Opera: agent.indexOf("Presto") != -1,
|
||||
MQQBrowser: agent.indexOf("MQQBrowser") != -1
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* format relative seconds to HH:MM:SS,
|
||||
* for example, 210s formated to 00:03:30
|
||||
* @see: http://blog.csdn.net/win_lin/article/details/17994347
|
||||
* @usage relative_seconds_to_HHMMSS(210)
|
||||
*/
|
||||
function relative_seconds_to_HHMMSS(seconds){
|
||||
var date = new Date();
|
||||
date.setTime(Number(seconds) * 1000);
|
||||
|
||||
var ret = padding(date.getUTCHours(), 2, '0')
|
||||
+ ":" + padding(date.getUTCMinutes(), 2, '0')
|
||||
+ ":" + padding(date.getUTCSeconds(), 2, '0');
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* format absolute seconds to HH:MM:SS,
|
||||
* for example, 1389146480s (2014-01-08 10:01:20 GMT+0800) formated to 10:01:20
|
||||
* @see: http://blog.csdn.net/win_lin/article/details/17994347
|
||||
* @usage absolute_seconds_to_HHMMSS(new Date().getTime() / 1000)
|
||||
*/
|
||||
function absolute_seconds_to_HHMMSS(seconds){
|
||||
var date = new Date();
|
||||
date.setTime(Number(seconds) * 1000);
|
||||
|
||||
var ret = padding(date.getHours(), 2, '0')
|
||||
+ ":" + padding(date.getMinutes(), 2, '0')
|
||||
+ ":" + padding(date.getSeconds(), 2, '0');
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* format absolute seconds to YYYY-mm-dd,
|
||||
* for example, 1389146480s (2014-01-08 10:01:20 GMT+0800) formated to 2014-01-08
|
||||
* @see: http://blog.csdn.net/win_lin/article/details/17994347
|
||||
* @usage absolute_seconds_to_YYYYmmdd(new Date().getTime() / 1000)
|
||||
*/
|
||||
function absolute_seconds_to_YYYYmmdd(seconds) {
|
||||
var date = new Date();
|
||||
date.setTime(Number(seconds) * 1000);
|
||||
|
||||
var ret = date.getFullYear()
|
||||
+ "-" + padding(date.getMonth() + 1, 2, '0')
|
||||
+ "-" + padding(date.getDate(), 2, '0');
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* parse the date in str to Date object.
|
||||
* @param str the date in str, format as "YYYY-mm-dd", for example, 2014-12-11
|
||||
* @returns a date object.
|
||||
* @usage YYYYmmdd_parse("2014-12-11")
|
||||
*/
|
||||
function YYYYmmdd_parse(str) {
|
||||
var date = new Date();
|
||||
date.setTime(Date.parse(str));
|
||||
return date;
|
||||
}
|
||||
|
||||
/**
|
||||
* async refresh function call. to avoid multiple call.
|
||||
* @remark AsyncRefresh is for jquery to refresh the speicified pfn in a page;
|
||||
* if angularjs, use AsyncRefresh2 to change pfn, cancel previous request for angularjs use singleton object.
|
||||
* @param refresh_interval the default refresh interval ms.
|
||||
* @see: http://blog.csdn.net/win_lin/article/details/17994347
|
||||
* the pfn can be implements as following:
|
||||
var async_refresh = new AsyncRefresh(pfn, 3000);
|
||||
function pfn() {
|
||||
if (!async_refresh.refresh_is_enabled()) {
|
||||
async_refresh.request(100);
|
||||
return;
|
||||
}
|
||||
$.ajax({
|
||||
type: 'GET', async: true, url: 'xxxxx',
|
||||
complete: function(){
|
||||
if (!async_refresh.refresh_is_enabled()) {
|
||||
async_refresh.request(0);
|
||||
} else {
|
||||
async_refresh.request(async_refresh.refresh_interval);
|
||||
}
|
||||
},
|
||||
success: function(res){
|
||||
// if donot allow refresh, directly return.
|
||||
if (!async_refresh.refresh_is_enabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// render the res.
|
||||
}
|
||||
});
|
||||
}
|
||||
*/
|
||||
function AsyncRefresh(pfn, refresh_interval) {
|
||||
this.refresh_interval = refresh_interval;
|
||||
|
||||
this.__handler = null;
|
||||
this.__pfn = pfn;
|
||||
|
||||
this.__enabled = true;
|
||||
}
|
||||
/**
|
||||
* disable the refresher, the pfn must check the refresh state.
|
||||
*/
|
||||
AsyncRefresh.prototype.refresh_disable = function() {
|
||||
this.__enabled = false;
|
||||
}
|
||||
AsyncRefresh.prototype.refresh_enable = function() {
|
||||
this.__enabled = true;
|
||||
}
|
||||
AsyncRefresh.prototype.refresh_is_enabled = function() {
|
||||
return this.__enabled;
|
||||
}
|
||||
/**
|
||||
* start new async request
|
||||
* @param timeout the timeout in ms.
|
||||
* user can use the refresh_interval of the AsyncRefresh object,
|
||||
* which initialized in constructor.
|
||||
*/
|
||||
AsyncRefresh.prototype.request = function(timeout) {
|
||||
if (this.__handler) {
|
||||
clearTimeout(this.__handler);
|
||||
}
|
||||
|
||||
this.__handler = setTimeout(this.__pfn, timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* async refresh v2, support cancellable refresh, and change the refresh pfn.
|
||||
* @remakr for angularjs. if user only need jquery, maybe AsyncRefresh is better.
|
||||
* @see: http://blog.csdn.net/win_lin/article/details/17994347
|
||||
* Usage:
|
||||
bsmControllers.controller('CServers', ['$scope', 'MServer', function($scope, MServer){
|
||||
async_refresh2.refresh_change(function(){
|
||||
// 获取服务器列表
|
||||
MServer.servers_load({}, function(data){
|
||||
$scope.servers = data.data.servers;
|
||||
async_refresh2.request();
|
||||
});
|
||||
}, 3000);
|
||||
|
||||
async_refresh2.request(0);
|
||||
}]);
|
||||
bsmControllers.controller('CStreams', ['$scope', 'MStream', function($scope, MStream){
|
||||
async_refresh2.refresh_change(function(){
|
||||
// 获取流列表
|
||||
MStream.streams_load({}, function(data){
|
||||
$scope.streams = data.data.streams;
|
||||
async_refresh2.request();
|
||||
});
|
||||
}, 3000);
|
||||
|
||||
async_refresh2.request(0);
|
||||
}]);
|
||||
*/
|
||||
function AsyncRefresh2() {
|
||||
/**
|
||||
* the function callback before call the pfn.
|
||||
* the protype is function():bool, which return true to invoke, false to abort the call.
|
||||
* null to ignore this callback.
|
||||
*
|
||||
* for example, user can abort the refresh by find the class popover:
|
||||
* async_refresh2.on_before_call_pfn = function() {
|
||||
* if ($(".popover").length > 0) {
|
||||
* async_refresh2.request();
|
||||
* return false;
|
||||
* }
|
||||
* return true;
|
||||
* };
|
||||
*/
|
||||
this.on_before_call_pfn = null;
|
||||
|
||||
// use a anonymous function to call, and check the enabled when actually invoke.
|
||||
this.__call = {
|
||||
pfn: null,
|
||||
timeout: 0,
|
||||
__enabled: false,
|
||||
__handler: null
|
||||
};
|
||||
}
|
||||
// singleton
|
||||
var async_refresh2 = new AsyncRefresh2();
|
||||
/**
|
||||
* initialize or refresh change. cancel previous request, setup new request.
|
||||
* @param pfn a function():void to request after timeout. null to disable refresher.
|
||||
* @param timeout the timeout in ms, to call pfn. null to disable refresher.
|
||||
*/
|
||||
AsyncRefresh2.prototype.initialize = function(pfn, timeout) {
|
||||
this.refresh_change(pfn, timeout);
|
||||
}
|
||||
/**
|
||||
* stop refresh, the refresh pfn is set to null.
|
||||
*/
|
||||
AsyncRefresh2.prototype.stop = function() {
|
||||
this.__call.__enabled = false;
|
||||
}
|
||||
/**
|
||||
* restart refresh, use previous config.
|
||||
*/
|
||||
AsyncRefresh2.prototype.restart = function() {
|
||||
this.__call.__enabled = true;
|
||||
this.request(0);
|
||||
}
|
||||
/**
|
||||
* change refresh pfn, the old pfn will set to disabled.
|
||||
*/
|
||||
AsyncRefresh2.prototype.refresh_change = function(pfn, timeout) {
|
||||
// cancel the previous call.
|
||||
if (this.__call.__handler) {
|
||||
clearTimeout(this.__handler);
|
||||
}
|
||||
this.__call.__enabled = false;
|
||||
|
||||
// setup new call.
|
||||
this.__call = {
|
||||
pfn: pfn,
|
||||
timeout: timeout,
|
||||
__enabled: true,
|
||||
__handler: null
|
||||
};
|
||||
}
|
||||
/**
|
||||
* start new request, we never auto start the request,
|
||||
* user must start new request when previous completed.
|
||||
* @param timeout [optional] if not specified, use the timeout in initialize or refresh_change.
|
||||
*/
|
||||
AsyncRefresh2.prototype.request = function(timeout) {
|
||||
var self = this;
|
||||
var this_call = this.__call;
|
||||
|
||||
// clear previous timeout.
|
||||
if (this_call.__handler) {
|
||||
clearTimeout(this_call.__handler);
|
||||
}
|
||||
|
||||
// override the timeout
|
||||
if (timeout == undefined) {
|
||||
timeout = this_call.timeout;
|
||||
}
|
||||
|
||||
// if user disabled refresher.
|
||||
if (this_call.pfn == null || timeout == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this_call.__handler = setTimeout(function(){
|
||||
// cancelled by refresh_change, ignore.
|
||||
if (!this_call.__enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
// callback if the handler installled.
|
||||
if (self.on_before_call_pfn) {
|
||||
if (!self.on_before_call_pfn()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// do the actual call.
|
||||
this_call.pfn();
|
||||
}, timeout);
|
||||
}
|
||||
|
68
trunk/research/console/ng_index.html
Normal file
68
trunk/research/console/ng_index.html
Normal file
|
@ -0,0 +1,68 @@
|
|||
<!DOCTYPE html>
|
||||
<html ng-app="scApp">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<title>SRS控制台</title>
|
||||
<link rel="stylesheet" type="text/css" href="js/3rdparty/bootstrap.min.css"/>
|
||||
<link rel="stylesheet" type="text/css" href="js/srs.console.css"/>
|
||||
<style>
|
||||
body {
|
||||
padding-top: 50px;
|
||||
}
|
||||
</style>
|
||||
<script type="text/javascript" src="js/3rdparty/angular.min.js"></script>
|
||||
<script type="text/javascript" src="js/3rdparty/angular-route.min.js"></script>
|
||||
<script type="text/javascript" src="js/3rdparty/angular-resource.min.js"></script>
|
||||
<script type="text/javascript" src="js/winlin.utility.js"></script>
|
||||
<script type="text/javascript" src="js/bravo_alert/alert.js"></script>
|
||||
<script type="text/javascript" src="js/bravo_popover/popover.js"></script>
|
||||
<script type="text/javascript" src="js/srs.cn.js"></script>
|
||||
<script type="text/javascript" src="js/srs.console.js"></script>
|
||||
</head>
|
||||
<body ng-controller="CSCMain">
|
||||
<img src='https://ossrs.net:8443/gif/v1/sls.gif?site=ossrs.net&path=/console/cnindex'/>
|
||||
<div class="navbar navbar-inverse navbar-fixed-top">
|
||||
<div class="navbar-inner">
|
||||
<div class="container">
|
||||
<a class="brand" href="https://github.com/ossrs/srs" target="_blank">SRS</a>
|
||||
<ul class="nav">
|
||||
<li class="{{'/console'| sc_filter_nav_active}}"><a href="javascript:void(0)" ng-click="gogogo('/connect')">连接SRS</a></li>
|
||||
<li class="{{'/summaries'| sc_filter_nav_active}}"><a href="javascript:void(0)" ng-click="gogogo('/summaries')">概览</a></li>
|
||||
<li class="{{'/vhosts'| sc_filter_nav_active}}"><a href="javascript:void(0)" ng-click="gogogo('/vhosts')">虚拟主机(Vhosts)</a></li>
|
||||
<li class="{{'/streams'| sc_filter_nav_active}}"><a href="javascript:void(0)" ng-click="gogogo('/streams')">视频流</a></li>
|
||||
<li class="{{'/clients'| sc_filter_nav_active}}"><a href="javascript:void(0)" ng-click="gogogo('/clients')">客户端</a></li>
|
||||
<li class="{{'/configs'| sc_filter_nav_active}}"><a href="javascript:void(0)" ng-click="gogogo('/configs')">配置</a></li>
|
||||
<li class="{{'/dvr'| sc_filter_nav_active}}"><a href="javascript:void(0)" ng-click="gogogo('/dvr')">DVR</a></li>
|
||||
<li><a href="javascript:void(0)" ng-click="redirect('ng_index.html', 'en_index.html')">English</a></li>
|
||||
<li>
|
||||
<a href="https://github.com/ossrs/srs-console">
|
||||
<img alt="GitHub Repo stars" src="https://img.shields.io/github/stars/ossrs/srs-console?style=social">
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container-fluid">
|
||||
<div ng-view></div>
|
||||
<div bravo-alert ng-repeat="log in logs" class="alert fade in {{log.level|sc_filter_log_level}}">
|
||||
<button type="button" class="close" data-dismiss="alert">×</button>
|
||||
<strong>{{log.level}}:</strong> {{log.msg}}
|
||||
</div>
|
||||
</div>
|
||||
<footer class="footer">
|
||||
<div class="container">
|
||||
<ul class="footer-links">
|
||||
<li>© SRS 2020</li>
|
||||
<li class="muted">|</li>
|
||||
<li><a href="http://ossrs.net/" target="_blank">Releases</a></li>
|
||||
<li class="muted">|</li>
|
||||
<li><a href="https://github.com/ossrs/srs" target="_blank">SRS</a></li>
|
||||
<li class="muted">|</li>
|
||||
<li><a href="https://github.com/ossrs/srs-console" target="_blank">Github</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
|
25
trunk/research/console/views/client.html
Normal file
25
trunk/research/console/views/client.html
Normal file
|
@ -0,0 +1,25 @@
|
|||
<div>
|
||||
<div class="accordion">
|
||||
<div class="accordion-group">
|
||||
<div class="accordion-heading">
|
||||
<a class="accordion-toggle" href="javascript:void(0)">
|
||||
客户端-{{client.id}}
|
||||
</a>
|
||||
</div>
|
||||
<div id="collapseOne" class="accordion-body collapse in">
|
||||
<div class="accordion-inner">
|
||||
<p>ID: {{client.id}}</p>
|
||||
<p>IP: {{client.ip}}</p>
|
||||
<p><a href="javascript:void(0)" ng-click="gogogo('/vhosts/' + client.vhost)">{{client.vhost}}</a></p>
|
||||
<p><a href="javascript:void(0)" ng-click="gogogo('/streams/' + client.stream)">{{client.stream}}</a></p>
|
||||
<p>Type: {{client.publish| sc_filter_ctype}}</p>
|
||||
<p>Alive: {{client.alive| sc_filter_time}}</p>
|
||||
<p>TcUrl: {{client.tcUrl}}</p>
|
||||
<p>PageUrl: {{client.pageUrl}}</p>
|
||||
<p>SwfUrl: {{client.swfUrl}}</p>
|
||||
<p><a ng-click="kickoff(client)" href="javascript:void(0)">踢Ta</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
25
trunk/research/console/views/client_en.html
Normal file
25
trunk/research/console/views/client_en.html
Normal file
|
@ -0,0 +1,25 @@
|
|||
<div>
|
||||
<div class="accordion">
|
||||
<div class="accordion-group">
|
||||
<div class="accordion-heading">
|
||||
<a class="accordion-toggle" href="javascript:void(0)">
|
||||
Client-{{client.id}}
|
||||
</a>
|
||||
</div>
|
||||
<div id="collapseOne" class="accordion-body collapse in">
|
||||
<div class="accordion-inner">
|
||||
<p>ID: {{client.id}}</p>
|
||||
<p>IP: {{client.ip}}</p>
|
||||
<p><a href="javascript:void(0)" ng-click="gogogo('/vhosts/' + client.vhost)">{{client.vhost}}</a></p>
|
||||
<p><a href="javascript:void(0)" ng-click="gogogo('/streams/' + client.stream)">{{client.stream}}</a></p>
|
||||
<p>Type: {{client.publish| sc_filter_ctype}}</p>
|
||||
<p>Alive: {{client.alive| sc_filter_time}}</p>
|
||||
<p>TcUrl: {{client.tcUrl}}</p>
|
||||
<p>PageUrl: {{client.pageUrl}}</p>
|
||||
<p>SwfUrl: {{client.swfUrl}}</p>
|
||||
<p><a ng-click="kickoff(client)" href="javascript:void(0)">Kickoff It</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
39
trunk/research/console/views/clients.html
Normal file
39
trunk/research/console/views/clients.html
Normal file
|
@ -0,0 +1,39 @@
|
|||
<div>
|
||||
<div class="accordion">
|
||||
<div class="accordion-group">
|
||||
<div class="accordion-heading" sc-collapse="in">
|
||||
<a class="accordion-toggle" href="javascript:void(0)">
|
||||
客户端(Clients)列表
|
||||
</a>
|
||||
</div>
|
||||
<div id="collapseOne" class="accordion-body collapse">
|
||||
<div class="accordion-inner">
|
||||
<table class="table table-striped table-bordered">
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>IP</th>
|
||||
<th>Vhost</th>
|
||||
<th>Stream</th>
|
||||
<th>类型</th>
|
||||
<th>时长</th>
|
||||
<th>TcUrl</th>
|
||||
<th>管理</th>
|
||||
</tr>
|
||||
<tr ng-repeat="client in clients">
|
||||
<td><a href="javascript:void(0)" ng-click="gogogo('/clients/' + client.id)">{{client.id}}</a></td>
|
||||
<td>{{client.ip}}</td>
|
||||
<td><a href="javascript:void(0)" ng-click="gogogo('/vhosts/' + client.vhost)">{{client.vhost}}</a></td>
|
||||
<td><a href="javascript:void(0)" ng-click="gogogo('/streams/' + client.stream)">{{client.stream}}</a></td>
|
||||
<td>{{client.publish| sc_filter_ctype}}</td>
|
||||
<td>{{client.alive| sc_filter_time}}</td>
|
||||
<td>{{client.tcUrl}}</td>
|
||||
<td>
|
||||
<a ng-click="kickoff(client)" href="javascript:void(0)">踢Ta</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
39
trunk/research/console/views/clients_en.html
Normal file
39
trunk/research/console/views/clients_en.html
Normal file
|
@ -0,0 +1,39 @@
|
|||
<div>
|
||||
<div class="accordion">
|
||||
<div class="accordion-group">
|
||||
<div class="accordion-heading" sc-collapse="in">
|
||||
<a class="accordion-toggle" href="javascript:void(0)">
|
||||
System Clients
|
||||
</a>
|
||||
</div>
|
||||
<div id="collapseOne" class="accordion-body collapse">
|
||||
<div class="accordion-inner">
|
||||
<table class="table table-striped table-bordered">
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>IP</th>
|
||||
<th>Vhost</th>
|
||||
<th>Stream</th>
|
||||
<th>Type</th>
|
||||
<th>Duration</th>
|
||||
<th>TcUrl</th>
|
||||
<th>Manage</th>
|
||||
</tr>
|
||||
<tr ng-repeat="client in clients">
|
||||
<td><a href="javascript:void(0)" ng-click="gogogo('/clients/' + client.id)">{{client.id}}</a></td>
|
||||
<td>{{client.ip}}</td>
|
||||
<td><a href="javascript:void(0)" ng-click="gogogo('/vhosts/' + client.vhost)">{{client.vhost}}</a></td>
|
||||
<td><a href="javascript:void(0)" ng-click="gogogo('/streams/' + client.stream)">{{client.stream}}</a></td>
|
||||
<td>{{client.publish| sc_filter_ctype}}</td>
|
||||
<td>{{client.alive| sc_filter_time}}</td>
|
||||
<td>{{client.tcUrl}}</td>
|
||||
<td>
|
||||
<a ng-click="kickoff(client)" href="javascript:void(0)">Kickoff It</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
1007
trunk/research/console/views/config.html
Normal file
1007
trunk/research/console/views/config.html
Normal file
File diff suppressed because it is too large
Load diff
1004
trunk/research/console/views/config_en.html
Normal file
1004
trunk/research/console/views/config_en.html
Normal file
File diff suppressed because it is too large
Load diff
452
trunk/research/console/views/configs.html
Normal file
452
trunk/research/console/views/configs.html
Normal file
|
@ -0,0 +1,452 @@
|
|||
<div>
|
||||
<div class="accordion">
|
||||
<div class="accordion-group" ng-show="!support_raw_api">
|
||||
<div class="accordion-heading" sc-collapse="in">
|
||||
<a class="accordion-toggle" href="javascript:void(0)">
|
||||
HTTP RAW API
|
||||
</a>
|
||||
</div>
|
||||
<div class="accordion-body collapse">
|
||||
<div class="accordion-inner">
|
||||
<div class="alert alert-block alert-danger" ng-show="warn_raw_api">
|
||||
该服务器不支持HTTP RAW API,或者配置中禁用了该功能。参考<a href='https://github.com/ossrs/srs/wiki/v3_CN_HTTPApi#http-raw-api'>WIKI</a>。
|
||||
</div>
|
||||
<table class="table table-striped table-hover table-bordered" ng-show="http_api">
|
||||
<tr>
|
||||
<th>Key</th>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
<th>Opt</th>
|
||||
</tr>
|
||||
<tr sc-pretty scp-key="http_api.enabled" scp-value="http_api.enabled" scp-bool="true"
|
||||
scp-desc="是否开启HTTP API,开启后就可以访问SRS提供的API管理服务器。默认: {{false| sc_filter_enabled}}">
|
||||
</tr>
|
||||
<tr sc-pretty scp-key="http_api.listen" scp-value="http_api.listen"
|
||||
scp-desc="HTTP API的侦听地址,格式是<[address:]port>。默认: 1985">
|
||||
</tr>
|
||||
<tr sc-pretty scp-key="http_api.crossdomain" scp-value="http_api.crossdomain" scp-bool="true"
|
||||
scp-desc="是否允许JS跨域,开启后JS可以直接跨域(还可以通过JSONP访问)。默认: {{true| sc_filter_enabled}}">
|
||||
</tr>
|
||||
<tr sc-pretty scp-key="http_api.raw_api.enabled" scp-value="http_api.raw_api.enabled" scp-bool="true"
|
||||
scp-desc="是否开启HTTP RAW API,允许API修改服务器配置。默认: {{false| sc_filter_enabled}}">
|
||||
</tr>
|
||||
<tr sc-pretty scp-key="http_api.raw_api.allow_reload" scp-value="http_api.raw_api.allow_reload" scp-bool="true"
|
||||
scp-desc="是否允许API进行Reload操作。默认: {{false| sc_filter_enabled}}">
|
||||
</tr>
|
||||
<tr sc-pretty scp-key="http_api.raw_api.allow_query" scp-value="http_api.raw_api.allow_query" scp-bool="true"
|
||||
scp-desc="是否允许API进行Query查询操作。默认: {{false| sc_filter_enabled}}">
|
||||
</tr>
|
||||
<tr sc-pretty scp-key="http_api.raw_api.allow_update" scp-value="http_api.raw_api.allow_update" scp-bool="true"
|
||||
scp-desc="是否允许API进行Update更新操作。默认: {{false| sc_filter_enabled}}">
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion-group" ng-show="support_raw_api">
|
||||
<div class="accordion-heading" sc-collapse="in">
|
||||
<a class="accordion-toggle" href="javascript:void(0)">
|
||||
服务器API配置(http_api)
|
||||
</a>
|
||||
</div>
|
||||
<div class="accordion-body collapse">
|
||||
<div class="accordion-inner">
|
||||
<table class="table table-striped table-hover table-bordered">
|
||||
<tr>
|
||||
<th>Key</th>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
<th>Opt</th>
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.http_api.enabled" scp-bool="true"
|
||||
scp-desc="是否开启HTTP API,开启后就可以访问SRS提供的API管理服务器。默认: {{false| sc_filter_enabled}}">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.http_api.listen.value"
|
||||
scp-desc="HTTP API的侦听地址,格式是<[address:]port>。默认: 1985">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.http_api.crossdomain" scp-bool="true"
|
||||
scp-desc="是否允许JS跨域,开启后JS可以直接跨域(还可以通过JSONP访问)。默认: {{true| sc_filter_enabled}}">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.http_api.raw_api.enabled" scp-bool="true"
|
||||
scp-desc="是否开启HTTP RAW API,允许API修改服务器配置。默认: {{false| sc_filter_enabled}}">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.http_api.raw_api.allow_reload" scp-bool="true"
|
||||
scp-desc="是否允许API进行Reload操作。默认: {{false| sc_filter_enabled}}">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.http_api.raw_api.allow_query" scp-bool="true"
|
||||
scp-desc="是否允许API进行Query查询操作。默认: {{false| sc_filter_enabled}}">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.http_api.raw_api.allow_update" scp-bool="true"
|
||||
scp-desc="是否允许API进行Update更新操作。默认: {{false| sc_filter_enabled}}">
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion-group" ng-show="support_raw_api">
|
||||
<div class="accordion-heading" sc-collapse="out">
|
||||
<a class="accordion-toggle" href="javascript:void(0)">
|
||||
服务器全局配置
|
||||
</a>
|
||||
</div>
|
||||
<div class="accordion-body collapse">
|
||||
<div class="accordion-inner">
|
||||
<div class="accordion-inner">
|
||||
<table class="table table-striped table-hover table-bordered">
|
||||
<tr>
|
||||
<th>Key</th>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
<th>Opt</th>
|
||||
</tr>
|
||||
<tr sc-directive scd-data="global.listen" scd-span="span3"
|
||||
scd-desc="RTMP服务器侦听的端口,提供RTMP服务,格式是<[address:]port>[,<addressN>portN]"
|
||||
scd-array="true" scd-default="1935"
|
||||
scd-submit="submit(global.listen)">
|
||||
</tr>
|
||||
<tr sc-directive scd-data="global.pid" scd-span="span3"
|
||||
scd-desc="服务器使用的PID文件,每个进程必须用一个,否则无法启动。默认: ./objs/srs.pid"
|
||||
scd-default="./objs/srs.pid"
|
||||
scd-submit="submit(global.pid)">
|
||||
</tr>
|
||||
<tr sc-directive scd-data="global.chunk_size" scd-span="span3"
|
||||
scd-desc="默认的ChunkSize,即RTMP分包的大小。默认: 60000"
|
||||
scd-default="60000"
|
||||
scd-submit="submit(global.chunk_size)">
|
||||
</tr>
|
||||
<tr sc-directive scd-data="global.ff_log_dir" scd-span="span4"
|
||||
scd-desc="默认的FFMPEG日志目录,/dev/null禁用日志。默认: ./objs"
|
||||
scd-default="./objs"
|
||||
scd-submit="submit(global.ff_log_dir)">
|
||||
</tr>
|
||||
<tr sc-directive scd-data="global.srs_log_tank" scd-span="span3"
|
||||
scd-desc="系统的日志容器,即存储方式。默认: file"
|
||||
scd-default="file", scd-select="file,console"
|
||||
scd-submit="submit(global.srs_log_tank)">
|
||||
</tr>
|
||||
<tr sc-directive scd-data="global.srs_log_level" scd-span="span3"
|
||||
scd-desc="系统的日志级别,低于该级别的日志不会打印。默认: trace"
|
||||
scd-default="trace" scd-select="verbose,info,trace,warn,error"
|
||||
scd-submit="submit(global.srs_log_level)">
|
||||
</tr>
|
||||
<tr sc-directive scd-data="global.srs_log_file" scd-span="span4"
|
||||
scd-desc="当日志容器为file,即日志写入文件时,日志文件的路径。默认: ./objs/srs.log"
|
||||
scd-default="./objs/srs.log"
|
||||
scd-submit="submit(global.srs_log_file)"
|
||||
ng-if="global.srs_log_tank.value == 'file'">
|
||||
</tr>
|
||||
<tr sc-directive scd-data="global.max_connections" scd-span="span3"
|
||||
scd-desc="系统的最大连接数,超过后将拒绝新连接。默认: 1000"
|
||||
scd-default="1000"
|
||||
scd-submit="submit(global.max_connections)">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.daemon" scp-bool="true"
|
||||
scp-desc="是否以后台启动SRS。默认: {{true| sc_filter_yesno}}">
|
||||
</tr>
|
||||
<tr sc-directive scd-data="global.utc_time" scd-span="span4"
|
||||
scd-desc="是否启用UTC时间格式,影响日志的时间和路径中包含时间变量的配置。默认: {{false| sc_filter_yesno}}"
|
||||
scd-default="false" scd-bool="true"
|
||||
scd-submit="submit(global.utc_time)">
|
||||
</tr>
|
||||
<tr sc-directive scd-data="global.pithy_print_ms" scd-span="span3"
|
||||
scd-desc="简化形式的日志打印间隔,单位: 毫秒。默认: 10000"
|
||||
scd-default="10000" scd-select="1000,3000,5000,10000,30000"
|
||||
scd-submit="submit(global.pithy_print_ms)">
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion-group" ng-show="support_raw_api">
|
||||
<div class="accordion-heading" sc-collapse="out">
|
||||
<a class="accordion-toggle" href="javascript:void(0)">
|
||||
虚拟主机(Vhosts)列表, 共配置有{{global.nb_vhosts.value}}个Vhost
|
||||
</a>
|
||||
</div>
|
||||
<div class="accordion-body collapse">
|
||||
<div class="accordion-inner">
|
||||
<table class="table table-striped table-hover table-bordered">
|
||||
<tr>
|
||||
<th>
|
||||
<a href="javscript:void(0)" ng-click="new_vhost()" class="icon-plus"></a>
|
||||
</th>
|
||||
<th>主机名称</th>
|
||||
<th>开启</th>
|
||||
<th>源</th>
|
||||
<th>DVR</th>
|
||||
<th>HTTP</th>
|
||||
<th>FLV</th>
|
||||
<th>HLS</th>
|
||||
<th>HDS</th>
|
||||
<th>回调</th>
|
||||
<th ng-show="false">Exec</th>
|
||||
<th ng-show="false">BWT</th>
|
||||
<th>转发</th>
|
||||
<th>安全</th>
|
||||
<th ng-show="false">盗链</th>
|
||||
<th ng-show="false">MR</th>
|
||||
<th ng-show="false">RTC</th>
|
||||
<th ng-show="false">GOP</th>
|
||||
<th ng-show="false">TcpNoDelay</th>
|
||||
<th ng-show="false">MixCorrect</th>
|
||||
<th ng-show="false">TimeJitter</th>
|
||||
<th ng-show="false">ATC</th>
|
||||
<th>转码</th>
|
||||
<th>采集</th>
|
||||
<th>
|
||||
<a href="javascript:void(0)" ng-click="new_vhost()">添加</a>
|
||||
</th>
|
||||
</tr>
|
||||
<tr ng-repeat="vhost in global.vhosts">
|
||||
<td><a href="#/vhosts/{{vhost.id}}" ng-show="vhost.id">{{vhost.id}}</a><span ng-show="!vhost.id">无流</span> </td>
|
||||
<td colspan="{{vhost.editable?13:1}}">
|
||||
<span ng-show="!vhost.editable">{{vhost.name}}</span>
|
||||
<span ng-show="vhost.editable">
|
||||
<input class="text span5" ng-model="vhost.name"><br/>
|
||||
请输入vhost的名称。
|
||||
</span>
|
||||
</td>
|
||||
<td ng-show="!vhost.editable">{{vhost.enabled| sc_filter_yesno}}</td>
|
||||
<td ng-show="!vhost.editable">{{vhost.origin| sc_filter_yn}}</td>
|
||||
<td ng-show="!vhost.editable">{{vhost.dvr| sc_filter_yn}}</td>
|
||||
<td ng-show="!vhost.editable">{{vhost.http_static| sc_filter_yn}}</td>
|
||||
<td ng-show="!vhost.editable">{{vhost.http_remux| sc_filter_yn}}</td>
|
||||
<td ng-show="!vhost.editable">{{vhost.hls| sc_filter_yn}}</td>
|
||||
<td ng-show="!vhost.editable">{{vhost.hds| sc_filter_yn}}</td>
|
||||
<td ng-show="!vhost.editable">{{vhost.http_hooks| sc_filter_yn}}</td>
|
||||
<td ng-show="false && !vhost.editable">{{vhost.exec| sc_filter_yn}}</td>
|
||||
<td ng-show="false && !vhost.editable">{{vhost.bandcheck| sc_filter_yn}}</td>
|
||||
<td ng-show="!vhost.editable">{{vhost.forward| sc_filter_yn}}</td>
|
||||
<td ng-show="!vhost.editable">{{vhost.security| sc_filter_yn}}</td>
|
||||
<td ng-show="false && !vhost.editable">{{vhost.refer| sc_filter_yn}}</td>
|
||||
<td ng-show="false && !vhost.editable">{{vhost.mr| sc_filter_yn}}</td>
|
||||
<td ng-show="false && !vhost.editable">{{vhost.min_latency| sc_filter_yn}}</td>
|
||||
<td ng-show="false && !vhost.editable">{{vhost.gop_cache| sc_filter_yn}}</td>
|
||||
<td ng-show="false && !vhost.editable">{{vhost.tcp_nodelay| sc_filter_yn}}</td>
|
||||
<td ng-show="false && !vhost.editable">{{vhost.mix_correct| sc_filter_yn}}</td>
|
||||
<td ng-show="false && !vhost.editable">{{vhost.time_jitter| sc_filter_yn}}</td>
|
||||
<td ng-show="false && !vhost.editable">{{vhost.atc| sc_filter_yn}}</td>
|
||||
<td ng-show="!vhost.editable">{{vhost.transcode| sc_filter_yn}}</td>
|
||||
<td ng-show="!vhost.editable">{{vhost.ingest| sc_filter_yn}}</td>
|
||||
<td>
|
||||
<span ng-show="vhost.editable">
|
||||
<!-- vhost exists in server -->
|
||||
<span ng-show="vhost.enabled != undefined">
|
||||
<a bravo-popover href="javascript:void(0)"
|
||||
data-content="请确认是否提交{{vhost.name}}?" data-title="请确认" data-placement="left"
|
||||
bravo-popover-confirm="update_vhost(vhost)">
|
||||
提交
|
||||
</a>
|
||||
<a href="javascript:void(0)" ng-click="cancel_vhost(vhost)">放弃</a>
|
||||
</span>
|
||||
<!-- vhost in adding. -->
|
||||
<span ng-show="vhost.enabled == undefined">
|
||||
<a bravo-popover href="javascript:void(0)"
|
||||
data-content="请确认是否提交{{vhost.name}}?" data-title="请确认" data-placement="left"
|
||||
bravo-popover-confirm="add_vhost(vhost)">
|
||||
提交
|
||||
</a>
|
||||
<a href="javascript:void(0)" ng-click="abort_vhost(vhost)">放弃</a>
|
||||
</span>
|
||||
</span>
|
||||
<span ng-show="!vhost.editable">
|
||||
<span ng-show="vhost.enabled">
|
||||
<span>编辑</span>
|
||||
<a bravo-popover href="javascript:void(0)"
|
||||
data-content="请确认是否禁用{{vhost.name}}?" data-title="请确认" data-placement="left"
|
||||
bravo-popover-confirm="disable_vhost(vhost)">
|
||||
禁用
|
||||
</a>
|
||||
<span>删除</span>
|
||||
</span>
|
||||
<span ng-show="!vhost.enabled">
|
||||
<a href="javascript:void(0)" ng-click="edit_vhost(vhost)">编辑</a>
|
||||
<a bravo-popover href="javascript:void(0)"
|
||||
data-content="请确认是否启用{{vhost.name}}?" data-title="请确认" data-placement="left"
|
||||
bravo-popover-confirm="enable_vhost(vhost)">
|
||||
启用
|
||||
</a>
|
||||
<a bravo-popover href="javascript:void(0)"
|
||||
data-content="请确认是否删除{{vhost.name}}?" data-title="请确认" data-placement="left"
|
||||
bravo-popover-confirm="delete_vhost(vhost)">
|
||||
删除
|
||||
</a>
|
||||
</span>
|
||||
<a href="#/configs/{{vhost.name}}" ng-show="!vhost.editable">详细</a>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion-group" ng-show="support_raw_api">
|
||||
<div class="accordion-heading" sc-collapse="hide">
|
||||
<a class="accordion-toggle" href="javascript:void(0)">
|
||||
Kafka集群配置(kafka)
|
||||
</a>
|
||||
</div>
|
||||
<div class="accordion-body collapse">
|
||||
<div class="accordion-inner">
|
||||
<table class="table table-striped table-hover table-bordered">
|
||||
<tr>
|
||||
<th>Key</th>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
<th>Opt</th>
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.kafka.enabled" scp-bool="true"
|
||||
scp-desc="是否开启Kafka,开启后SRS将数据汇报给Kafka集群。默认: {{false| sc_filter_enabled}}">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.kafka.brokers"
|
||||
scp-desc="Broker列表,首次连接到Broker获取集群信息,格式是<ip:port>。">
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion-group" ng-show="support_raw_api">
|
||||
<div class="accordion-heading" sc-collapse="hide">
|
||||
<a class="accordion-toggle" href="javascript:void(0)">
|
||||
服务器心跳汇报(heartbeat)
|
||||
</a>
|
||||
</div>
|
||||
<div class="accordion-body collapse">
|
||||
<div class="accordion-inner">
|
||||
<table class="table table-striped table-hover table-bordered">
|
||||
<tr>
|
||||
<th>Key</th>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
<th>Opt</th>
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.heartbeat.enabled"
|
||||
scp-desc="是否开启服务器心跳,向外部系统汇报。默认: {{false| sc_filter_enabled}}"
|
||||
scd-bool="true">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.heartbeat.interval"
|
||||
scp-desc="心跳间隔的时间,单位: 秒。默认: 9.9"
|
||||
ng-show="global.heartbeat.enabled.value">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.heartbeat.url"
|
||||
scp-desc="汇报的HTTP服务器地址,汇报信息格式是JSON。默认: http://127.0.0.1:8085/api/v1/servers"
|
||||
ng-show="global.heartbeat.enabled.value">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.heartbeat.device_id"
|
||||
scp-desc="设备ID,SRS会写入汇报信息中。"
|
||||
ng-show="global.heartbeat.enabled.value">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.heartbeat.smmaries"
|
||||
scp-desc="是否汇报摘要,即服务器的summaries信息。默认: {{false| sc_filter_yesno}}"
|
||||
scd-bool="true"
|
||||
scd-submit="submit(global.heartbeat.summaries)"
|
||||
ng-show="global.heartbeat.enabled.value">
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion-group" ng-show="support_raw_api">
|
||||
<div class="accordion-heading" sc-collapse="hide">
|
||||
<a class="accordion-toggle" href="javascript:void(0)">
|
||||
服务器统计信息配置(stats)
|
||||
</a>
|
||||
</div>
|
||||
<div class="accordion-body collapse">
|
||||
<div class="accordion-inner">
|
||||
<table class="table table-striped table-hover table-bordered">
|
||||
<tr>
|
||||
<th>Key</th>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
<th>Opt</th>
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.stats.network"
|
||||
scp-desc="统计的网卡索引,从0开始算第一块网卡。默认: 0">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.stats.disk"
|
||||
scp-desc="统计的磁盘名称,可以在/proc/diskstats中查看。"
|
||||
scd-array="true">
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion-group" ng-show="support_raw_api">
|
||||
<div class="accordion-heading" sc-collapse="hide">
|
||||
<a class="accordion-toggle" href="javascript:void(0)">
|
||||
HTTP服务器配置(http_server)
|
||||
</a>
|
||||
</div>
|
||||
<div class="accordion-body collapse">
|
||||
<div class="accordion-inner">
|
||||
<table class="table table-striped table-hover table-bordered">
|
||||
<tr>
|
||||
<th>Key</th>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
<th>Opt</th>
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.http_server.enabled"
|
||||
scp-desc="是否开启HTTP文件服务器和HTTP流服务器。默认: {{false| sc_filter_enabled}}"
|
||||
scd-bool="true">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.http_server.listen"
|
||||
scp-desc="HTTP服务器侦听的地址,格式是<[address:]port>。默认: 8080"
|
||||
ng-show="global.http_server.enabled.value">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.http_server.dir"
|
||||
scp-desc="HTTP服务器的主目录。默认: ./objs/nginx/html"
|
||||
ng-show="global.http_server.enabled.value">
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion-group" ng-show="support_raw_api">
|
||||
<div class="accordion-heading" sc-collapse="hide">
|
||||
<a class="accordion-toggle" href="javascript:void(0)">
|
||||
StreamCaster流转换器(stream_caster)
|
||||
</a>
|
||||
</div>
|
||||
<div class="accordion-body collapse">
|
||||
<div class="accordion-inner">
|
||||
<table class="table table-striped table-hover table-bordered">
|
||||
<tr>
|
||||
<th>Key</th>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
<td>Opt</td>
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.stream_caster.enabled"
|
||||
scp-desc="是否开启StreamCaster,即接收特殊的流后转换成RTMP送到SRS。默认: {{false| sc_filter_enabled}}"
|
||||
scd-bool="true">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.stream_caster.caster"
|
||||
scp-desc="转换器的类型,不同的类型需要不同的配置,mpegts_over_udp,rtsp,flv"
|
||||
scd-select="mpegts_over_udp,rtsp,flv"
|
||||
ng-show="global.stream_caster.enabled.value">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.stream_caster.output"
|
||||
scp-desc="输出的RTMP地址,转换器侦听端口,接收特定的流,转换成RTMP后送到SRS。"
|
||||
ng-show="global.stream_caster.enabled.value">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.stream_caster.listen"
|
||||
scp-desc="转换器侦听的地址,格式是<port>"
|
||||
ng-show="global.stream_caster.enabled.value">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.stream_caster.rtp_port_min"
|
||||
scp-desc="转换器会在[rtp_port_min, rtp_port_max]中间选择一个新端口并侦听,参考RTP协议。"
|
||||
ng-show="global.stream_caster.enabled.value && global.stream_caster.caster.value == 'rtsp'">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.stream_caster.rtp_port_max"
|
||||
scp-desc="转换器会在[rtp_port_min, rtp_port_max]中间选择一个新端口并侦听,参考RTP协议。"
|
||||
ng-show="global.stream_caster.enabled.value && global.stream_caster.caster.value == 'rtsp'">
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
452
trunk/research/console/views/configs_en.html
Normal file
452
trunk/research/console/views/configs_en.html
Normal file
|
@ -0,0 +1,452 @@
|
|||
<div>
|
||||
<div class="accordion">
|
||||
<div class="accordion-group" ng-show="!support_raw_api">
|
||||
<div class="accordion-heading" sc-collapse="in">
|
||||
<a class="accordion-toggle" href="javascript:void(0)">
|
||||
HTTP RAW API
|
||||
</a>
|
||||
</div>
|
||||
<div class="accordion-body collapse">
|
||||
<div class="accordion-inner">
|
||||
<div class="alert alert-block alert-danger" ng-show="warn_raw_api">
|
||||
HTTP RAW API is not supported or disabled. Read <a href='https://github.com/ossrs/srs/wiki/v3_EN_HTTPApi#http-raw-api'>WIKI</a>。
|
||||
</div>
|
||||
<table class="table table-striped table-hover table-bordered" ng-show="http_api">
|
||||
<tr>
|
||||
<th>Key</th>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
<th>Opt</th>
|
||||
</tr>
|
||||
<tr sc-pretty scp-key="http_api.enabled" scp-value="http_api.enabled" scp-bool="true"
|
||||
scp-desc="Whether enable HTTP API. Default is {{false| sc_filter_enabled}}">
|
||||
</tr>
|
||||
<tr sc-pretty scp-key="http_api.listen" scp-value="http_api.listen"
|
||||
scp-desc="The listen port for HTTP API, format is <[address:]port>. Default is 1985">
|
||||
</tr>
|
||||
<tr sc-pretty scp-key="http_api.crossdomain" scp-value="http_api.crossdomain" scp-bool="true"
|
||||
scp-desc="Whether allow js CORS(JSONP). Default is {{true| sc_filter_enabled}}">
|
||||
</tr>
|
||||
<tr sc-pretty scp-key="http_api.raw_api.enabled" scp-value="http_api.raw_api.enabled" scp-bool="true"
|
||||
scp-desc="Whether enable HTTP RAW API. Default is {{false| sc_filter_enabled}}">
|
||||
</tr>
|
||||
<tr sc-pretty scp-key="http_api.raw_api.allow_reload" scp-value="http_api.raw_api.allow_reload" scp-bool="true"
|
||||
scp-desc="Whether allow HTTP RAW API to reload. Default is {{false| sc_filter_enabled}}">
|
||||
</tr>
|
||||
<tr sc-pretty scp-key="http_api.raw_api.allow_query" scp-value="http_api.raw_api.allow_query" scp-bool="true"
|
||||
scp-desc="Whether allow HTTP RAW API to query. Default is {{false| sc_filter_enabled}}">
|
||||
</tr>
|
||||
<tr sc-pretty scp-key="http_api.raw_api.allow_update" scp-value="http_api.raw_api.allow_update" scp-bool="true"
|
||||
scp-desc="Whether allow HTTP RAW API to update. Default is {{false| sc_filter_enabled}}">
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion-group" ng-show="support_raw_api">
|
||||
<div class="accordion-heading" sc-collapse="in">
|
||||
<a class="accordion-toggle" href="javascript:void(0)">
|
||||
HTTP API Server
|
||||
</a>
|
||||
</div>
|
||||
<div class="accordion-body collapse">
|
||||
<div class="accordion-inner">
|
||||
<table class="table table-striped table-hover table-bordered">
|
||||
<tr>
|
||||
<th>Key</th>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
<th>Opt</th>
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.http_api.enabled" scp-bool="true"
|
||||
scp-desc="Whether enabel HTTP API. Default is {{false| sc_filter_enabled}}">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.http_api.listen.value"
|
||||
scp-desc="The HTTP API listen port, format is <[address:]port>. Default is 1985">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.http_api.crossdomain" scp-bool="true"
|
||||
scp-desc="Whether allow CORS for js(JSONP). Default is {{true| sc_filter_enabled}}">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.http_api.raw_api.enabled" scp-bool="true"
|
||||
scp-desc="Whether enable HTTP RAW API. Default is {{false| sc_filter_enabled}}">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.http_api.raw_api.allow_reload" scp-bool="true"
|
||||
scp-desc="Whether allow reload by HTTP API. Default is {{false| sc_filter_enabled}}">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.http_api.raw_api.allow_query" scp-bool="true"
|
||||
scp-desc="Whether allow query by HTTP API. Default is {{false| sc_filter_enabled}}">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.http_api.raw_api.allow_update" scp-bool="true"
|
||||
scp-desc="Whether allow update by HTTP API. Default is {{false| sc_filter_enabled}}">
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion-group" ng-show="support_raw_api">
|
||||
<div class="accordion-heading" sc-collapse="out">
|
||||
<a class="accordion-toggle" href="javascript:void(0)">
|
||||
SRS Global Config
|
||||
</a>
|
||||
</div>
|
||||
<div class="accordion-body collapse">
|
||||
<div class="accordion-inner">
|
||||
<div class="accordion-inner">
|
||||
<table class="table table-striped table-hover table-bordered">
|
||||
<tr>
|
||||
<th>Key</th>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
<th>Opt</th>
|
||||
</tr>
|
||||
<tr sc-directive scd-data="global.listen" scd-span="span3"
|
||||
scd-desc="RTMP listen port, format is <[address:]port>[,<addressN>portN]"
|
||||
scd-array="true" scd-default="1935"
|
||||
scd-submit="submit(global.listen)">
|
||||
</tr>
|
||||
<tr sc-directive scd-data="global.pid" scd-span="span3"
|
||||
scd-desc="The pid file for SRS. Default is ./objs/srs.pid"
|
||||
scd-default="./objs/srs.pid"
|
||||
scd-submit="submit(global.pid)">
|
||||
</tr>
|
||||
<tr sc-directive scd-data="global.chunk_size" scd-span="span3"
|
||||
scd-desc="RTMP chunk size. Default is 60000"
|
||||
scd-default="60000"
|
||||
scd-submit="submit(global.chunk_size)">
|
||||
</tr>
|
||||
<tr sc-directive scd-data="global.ff_log_dir" scd-span="span4"
|
||||
scd-desc="FFMPEG log directory, use /dev/null to disable log. Default is ./objs"
|
||||
scd-default="./objs"
|
||||
scd-submit="submit(global.ff_log_dir)">
|
||||
</tr>
|
||||
<tr sc-directive scd-data="global.srs_log_tank" scd-span="span3"
|
||||
scd-desc="System log store. Default is file"
|
||||
scd-default="file", scd-select="file,console"
|
||||
scd-submit="submit(global.srs_log_tank)">
|
||||
</tr>
|
||||
<tr sc-directive scd-data="global.srs_log_level" scd-span="span3"
|
||||
scd-desc="System log level. Default is trace"
|
||||
scd-default="trace" scd-select="verbose,info,trace,warn,error"
|
||||
scd-submit="submit(global.srs_log_level)">
|
||||
</tr>
|
||||
<tr sc-directive scd-data="global.srs_log_file" scd-span="span4"
|
||||
scd-desc="When log store is file, the log path. Default is ./objs/srs.log"
|
||||
scd-default="./objs/srs.log"
|
||||
scd-submit="submit(global.srs_log_file)"
|
||||
ng-if="global.srs_log_tank.value == 'file'">
|
||||
</tr>
|
||||
<tr sc-directive scd-data="global.max_connections" scd-span="span3"
|
||||
scd-desc="System maximum connections. Default is 1000"
|
||||
scd-default="1000"
|
||||
scd-submit="submit(global.max_connections)">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.daemon" scp-bool="true"
|
||||
scp-desc="Whether start SRS as daemon. Default is {{true| sc_filter_yesno}}">
|
||||
</tr>
|
||||
<tr sc-directive scd-data="global.utc_time" scd-span="span4"
|
||||
scd-desc="Whether use UTC time. Default is {{false| sc_filter_yesno}}"
|
||||
scd-default="false" scd-bool="true"
|
||||
scd-submit="submit(global.utc_time)">
|
||||
</tr>
|
||||
<tr sc-directive scd-data="global.pithy_print_ms" scd-span="span3"
|
||||
scd-desc="Pithy log print interval in ms. Default is 10000"
|
||||
scd-default="10000" scd-select="1000,3000,5000,10000,30000"
|
||||
scd-submit="submit(global.pithy_print_ms)">
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion-group" ng-show="support_raw_api">
|
||||
<div class="accordion-heading" sc-collapse="out">
|
||||
<a class="accordion-toggle" href="javascript:void(0)">
|
||||
System Vhosts, total {{global.nb_vhosts.value}} vhosts configed.
|
||||
</a>
|
||||
</div>
|
||||
<div class="accordion-body collapse">
|
||||
<div class="accordion-inner">
|
||||
<table class="table table-striped table-hover table-bordered">
|
||||
<tr>
|
||||
<th>
|
||||
<a href="javscript:void(0)" ng-click="new_vhost()" class="icon-plus"></a>
|
||||
</th>
|
||||
<th>Name</th>
|
||||
<th title="Whether Enabled">E</th>
|
||||
<th title="Whether Origin Server">O</th>
|
||||
<th title="DVR Configed">D</th>
|
||||
<th title="HTTP Server Configed">H</th>
|
||||
<th title="HTTP FLV Configed">FLV</th>
|
||||
<th title="HLS Configed">HLS</th>
|
||||
<th title="HDS Configed">HDS</th>
|
||||
<th title="HTTP Callback">CB</th>
|
||||
<th ng-show="false">Exec</th>
|
||||
<th ng-show="false">BWT</th>
|
||||
<th title="Forwarder">F</th>
|
||||
<th title="Security Configed">S</th>
|
||||
<th ng-show="false">Referer</th>
|
||||
<th ng-show="false">MR</th>
|
||||
<th ng-show="false">RTC</th>
|
||||
<th ng-show="false">GOP</th>
|
||||
<th ng-show="false">TcpNoDelay</th>
|
||||
<th ng-show="false">MixCorrect</th>
|
||||
<th ng-show="false">TimeJitter</th>
|
||||
<th ng-show="false">ATC</th>
|
||||
<th title="Transcode Configied">T</th>
|
||||
<th title="Ingester Configed">I</th>
|
||||
<th>
|
||||
<a href="javascript:void(0)" ng-click="new_vhost()">Add</a>
|
||||
</th>
|
||||
</tr>
|
||||
<tr ng-repeat="vhost in global.vhosts">
|
||||
<td><a href="#/vhosts/{{vhost.id}}" ng-show="vhost.id">{{vhost.id}}</a><span ng-show="!vhost.id">No Stream</span> </td>
|
||||
<td colspan="{{vhost.editable?13:1}}">
|
||||
<span ng-show="!vhost.editable">{{vhost.name}}</span>
|
||||
<span ng-show="vhost.editable">
|
||||
<input class="text span5" ng-model="vhost.name"><br/>
|
||||
Please input vhost name.
|
||||
</span>
|
||||
</td>
|
||||
<td ng-show="!vhost.editable">{{vhost.enabled| sc_filter_yesno}}</td>
|
||||
<td ng-show="!vhost.editable">{{vhost.origin| sc_filter_yn}}</td>
|
||||
<td ng-show="!vhost.editable">{{vhost.dvr| sc_filter_yn}}</td>
|
||||
<td ng-show="!vhost.editable">{{vhost.http_static| sc_filter_yn}}</td>
|
||||
<td ng-show="!vhost.editable">{{vhost.http_remux| sc_filter_yn}}</td>
|
||||
<td ng-show="!vhost.editable">{{vhost.hls| sc_filter_yn}}</td>
|
||||
<td ng-show="!vhost.editable">{{vhost.hds| sc_filter_yn}}</td>
|
||||
<td ng-show="!vhost.editable">{{vhost.http_hooks| sc_filter_yn}}</td>
|
||||
<td ng-show="false && !vhost.editable">{{vhost.exec| sc_filter_yn}}</td>
|
||||
<td ng-show="false && !vhost.editable">{{vhost.bandcheck| sc_filter_yn}}</td>
|
||||
<td ng-show="!vhost.editable">{{vhost.forward| sc_filter_yn}}</td>
|
||||
<td ng-show="!vhost.editable">{{vhost.security| sc_filter_yn}}</td>
|
||||
<td ng-show="false && !vhost.editable">{{vhost.refer| sc_filter_yn}}</td>
|
||||
<td ng-show="false && !vhost.editable">{{vhost.mr| sc_filter_yn}}</td>
|
||||
<td ng-show="false && !vhost.editable">{{vhost.min_latency| sc_filter_yn}}</td>
|
||||
<td ng-show="false && !vhost.editable">{{vhost.gop_cache| sc_filter_yn}}</td>
|
||||
<td ng-show="false && !vhost.editable">{{vhost.tcp_nodelay| sc_filter_yn}}</td>
|
||||
<td ng-show="false && !vhost.editable">{{vhost.mix_correct| sc_filter_yn}}</td>
|
||||
<td ng-show="false && !vhost.editable">{{vhost.time_jitter| sc_filter_yn}}</td>
|
||||
<td ng-show="false && !vhost.editable">{{vhost.atc| sc_filter_yn}}</td>
|
||||
<td ng-show="!vhost.editable">{{vhost.transcode| sc_filter_yn}}</td>
|
||||
<td ng-show="!vhost.editable">{{vhost.ingest| sc_filter_yn}}</td>
|
||||
<td>
|
||||
<span ng-show="vhost.editable">
|
||||
<!-- vhost exists in server -->
|
||||
<span ng-show="vhost.enabled != undefined">
|
||||
<a bravo-popover href="javascript:void(0)"
|
||||
data-content="Please confirm submit vhost {{vhost.name}}?" data-title="Confirm" data-placement="left"
|
||||
bravo-popover-confirm="update_vhost(vhost)">
|
||||
Submit
|
||||
</a>
|
||||
<a href="javascript:void(0)" ng-click="cancel_vhost(vhost)">Cancel</a>
|
||||
</span>
|
||||
<!-- vhost in adding. -->
|
||||
<span ng-show="vhost.enabled == undefined">
|
||||
<a bravo-popover href="javascript:void(0)"
|
||||
data-content="Please confirm submit vhost{{vhost.name}}?" data-title="Confirm" data-placement="left"
|
||||
bravo-popover-confirm="add_vhost(vhost)">
|
||||
Submit
|
||||
</a>
|
||||
<a href="javascript:void(0)" ng-click="abort_vhost(vhost)">Cancel</a>
|
||||
</span>
|
||||
</span>
|
||||
<span ng-show="!vhost.editable">
|
||||
<span ng-show="vhost.enabled">
|
||||
<span>Update</span>
|
||||
<a bravo-popover href="javascript:void(0)"
|
||||
data-content="Please confirm to disable {{vhost.name}}?" data-title="Confirm" data-placement="left"
|
||||
bravo-popover-confirm="disable_vhost(vhost)">
|
||||
Disable
|
||||
</a>
|
||||
<span>Delete</span>
|
||||
</span>
|
||||
<span ng-show="!vhost.enabled">
|
||||
<a href="javascript:void(0)" ng-click="edit_vhost(vhost)">编辑</a>
|
||||
<a bravo-popover href="javascript:void(0)"
|
||||
data-content="Please confirm to enable {{vhost.name}}?" data-title="Confirm" data-placement="left"
|
||||
bravo-popover-confirm="enable_vhost(vhost)">
|
||||
Enable
|
||||
</a>
|
||||
<a bravo-popover href="javascript:void(0)"
|
||||
data-content="Please confirm to delete {{vhost.name}}?" data-title="Confirm" data-placement="left"
|
||||
bravo-popover-confirm="delete_vhost(vhost)">
|
||||
Delete
|
||||
</a>
|
||||
</span>
|
||||
<a href="#/configs/{{vhost.name}}" ng-show="!vhost.editable">Detail</a>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion-group" ng-show="support_raw_api">
|
||||
<div class="accordion-heading" sc-collapse="hide">
|
||||
<a class="accordion-toggle" href="javascript:void(0)">
|
||||
Config KAFKA
|
||||
</a>
|
||||
</div>
|
||||
<div class="accordion-body collapse">
|
||||
<div class="accordion-inner">
|
||||
<table class="table table-striped table-hover table-bordered">
|
||||
<tr>
|
||||
<th>Key</th>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
<th>Opt</th>
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.kafka.enabled" scp-bool="true"
|
||||
scp-desc="Whether enable KAFKA. Default is {{false| sc_filter_enabled}}">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.kafka.brokers"
|
||||
scp-desc="The broker list, format is <ip:port>">
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion-group" ng-show="support_raw_api">
|
||||
<div class="accordion-heading" sc-collapse="hide">
|
||||
<a class="accordion-toggle" href="javascript:void(0)">
|
||||
SRS Heartbeat
|
||||
</a>
|
||||
</div>
|
||||
<div class="accordion-body collapse">
|
||||
<div class="accordion-inner">
|
||||
<table class="table table-striped table-hover table-bordered">
|
||||
<tr>
|
||||
<th>Key</th>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
<th>Opt</th>
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.heartbeat.enabled"
|
||||
scp-desc="Whether enable heartbet. Default is {{false| sc_filter_enabled}}"
|
||||
scd-bool="true">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.heartbeat.interval"
|
||||
scp-desc="The interval in seconds. Default is 9.9"
|
||||
ng-show="global.heartbeat.enabled.value">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.heartbeat.url"
|
||||
scp-desc="The report url in json. Default is http://127.0.0.1:8085/api/v1/servers"
|
||||
ng-show="global.heartbeat.enabled.value">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.heartbeat.device_id"
|
||||
scp-desc="The device ID."
|
||||
ng-show="global.heartbeat.enabled.value">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.heartbeat.smmaries"
|
||||
scp-desc="Whether report summaries. Default is {{false| sc_filter_yesno}}"
|
||||
scd-bool="true"
|
||||
scd-submit="submit(global.heartbeat.summaries)"
|
||||
ng-show="global.heartbeat.enabled.value">
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion-group" ng-show="support_raw_api">
|
||||
<div class="accordion-heading" sc-collapse="hide">
|
||||
<a class="accordion-toggle" href="javascript:void(0)">
|
||||
STAT Hardward Config
|
||||
</a>
|
||||
</div>
|
||||
<div class="accordion-body collapse">
|
||||
<div class="accordion-inner">
|
||||
<table class="table table-striped table-hover table-bordered">
|
||||
<tr>
|
||||
<th>Key</th>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
<th>Opt</th>
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.stats.network"
|
||||
scp-desc="The stat network index. Default is 0">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.stats.disk"
|
||||
scp-desc="The stat disk name."
|
||||
scd-array="true">
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion-group" ng-show="support_raw_api">
|
||||
<div class="accordion-heading" sc-collapse="hide">
|
||||
<a class="accordion-toggle" href="javascript:void(0)">
|
||||
HTTP Server Config
|
||||
</a>
|
||||
</div>
|
||||
<div class="accordion-body collapse">
|
||||
<div class="accordion-inner">
|
||||
<table class="table table-striped table-hover table-bordered">
|
||||
<tr>
|
||||
<th>Key</th>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
<th>Opt</th>
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.http_server.enabled"
|
||||
scp-desc="Whether enable HTTP Server. Default is {{false| sc_filter_enabled}}"
|
||||
scd-bool="true">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.http_server.listen"
|
||||
scp-desc="The HTTP Server listen port, format is <[address:]port>. Default is 8080"
|
||||
ng-show="global.http_server.enabled.value">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.http_server.dir"
|
||||
scp-desc="The HTTP Server root directory. Default is ./objs/nginx/html"
|
||||
ng-show="global.http_server.enabled.value">
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion-group" ng-show="support_raw_api">
|
||||
<div class="accordion-heading" sc-collapse="hide">
|
||||
<a class="accordion-toggle" href="javascript:void(0)">
|
||||
Stream Caster Config
|
||||
</a>
|
||||
</div>
|
||||
<div class="accordion-body collapse">
|
||||
<div class="accordion-inner">
|
||||
<table class="table table-striped table-hover table-bordered">
|
||||
<tr>
|
||||
<th>Key</th>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
<td>Opt</td>
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.stream_caster.enabled"
|
||||
scp-desc="Whether enable StreamCaster. Default is {{false| sc_filter_enabled}}"
|
||||
scd-bool="true">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.stream_caster.caster"
|
||||
scp-desc="The type of StreamCaster. For example, mpegts_over_udp,rtsp,flv"
|
||||
scd-select="mpegts_over_udp,rtsp,flv"
|
||||
ng-show="global.stream_caster.enabled.value">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.stream_caster.output"
|
||||
scp-desc="The output RTMP url."
|
||||
ng-show="global.stream_caster.enabled.value">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.stream_caster.listen"
|
||||
scp-desc="The listen port, format is <port>"
|
||||
ng-show="global.stream_caster.enabled.value">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.stream_caster.rtp_port_min"
|
||||
scp-desc="The RTP min port."
|
||||
ng-show="global.stream_caster.enabled.value && global.stream_caster.caster.value == 'rtsp'">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.stream_caster.rtp_port_max"
|
||||
scp-desc="The RTP max port."
|
||||
ng-show="global.stream_caster.enabled.value && global.stream_caster.caster.value == 'rtsp'">
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
40
trunk/research/console/views/connect.html
Normal file
40
trunk/research/console/views/connect.html
Normal file
|
@ -0,0 +1,40 @@
|
|||
<div>
|
||||
<div class="accordion">
|
||||
<div class="accordion-group">
|
||||
<div class="accordion-heading">
|
||||
<a class="accordion-toggle" href="javascript:void(0)">
|
||||
连接到您的SRS服务器
|
||||
</a>
|
||||
</div>
|
||||
<div class="accordion-body collapse in">
|
||||
<div class="accordion-inner">
|
||||
<div class="form-horizontal">
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="sscProtocol">协议</label>
|
||||
<div class="controls">
|
||||
<input type="text" id="sscProtocol" placeholder="SRS API Protocol, http or https" ng-model="server.schema">
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="sscServer">服务器IP</label>
|
||||
<div class="controls">
|
||||
<input type="text" id="sscServer" placeholder="SRS API Server IP" ng-model="server.ip">
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="sscPort">API端口</label>
|
||||
<div class="controls">
|
||||
<input type="text" id="sscPort" placeholder="SRS API Server Port" ng-model="server.port">
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<div class="controls">
|
||||
<button type="submit" class="btn" ng-click="connect()">连接到SRS</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
40
trunk/research/console/views/connect_en.html
Normal file
40
trunk/research/console/views/connect_en.html
Normal file
|
@ -0,0 +1,40 @@
|
|||
<div>
|
||||
<div class="accordion">
|
||||
<div class="accordion-group">
|
||||
<div class="accordion-heading">
|
||||
<a class="accordion-toggle" href="javascript:void(0)">
|
||||
Connect to your SRS
|
||||
</a>
|
||||
</div>
|
||||
<div class="accordion-body collapse in">
|
||||
<div class="accordion-inner">
|
||||
<div class="form-horizontal">
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="sscProtocol">Protocol</label>
|
||||
<div class="controls">
|
||||
<input type="text" id="sscProtocol" placeholder="SRS API Protocol, http or https" ng-model="server.schema">
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="sscServer">Server IP</label>
|
||||
<div class="controls">
|
||||
<input type="text" id="sscServer" placeholder="SRS API Server IP" ng-model="server.ip">
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="sscPort">SRS API Port</label>
|
||||
<div class="controls">
|
||||
<input type="text" id="sscPort" placeholder="SRS API Server Port" ng-model="server.port">
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<div class="controls">
|
||||
<button type="submit" class="btn" ng-click="connect()">Connect</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
62
trunk/research/console/views/dvr.html
Normal file
62
trunk/research/console/views/dvr.html
Normal file
|
@ -0,0 +1,62 @@
|
|||
<div>
|
||||
<div class="accordion">
|
||||
<div class="accordion-group">
|
||||
<div class="accordion-heading">
|
||||
<a class="accordion-toggle" href="javascript:void(0)">
|
||||
Vhost({{global.vid.value}})录制(DVR)配置
|
||||
</a>
|
||||
</div>
|
||||
<div class="accordion-body collapse in">
|
||||
<div class="accordion-inner">
|
||||
<table class="table table-striped table-hover table-bordered">
|
||||
<tr>
|
||||
<th>Key</th>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
<th>Opt</th>
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.name" scp-link="#/vhosts/{{global.id.value}}"
|
||||
scp-desc="录制的流所属的Vhost的名称">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.app"
|
||||
scp-desc="录制的流所属的App的名称">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.stream" scp-link="#/streams/{{global.sid.value}}"
|
||||
scp-desc="录制的流的Stream地址,即流名称">
|
||||
</tr>
|
||||
<tr sc-directive scd-data="global.dvr.apply" scd-span="span4"
|
||||
scd-desc="是否开始录制该流。"
|
||||
scd-default="false" scd-bool="true"
|
||||
scd-submit="dvr(global.dvr.apply)"
|
||||
ng-show="global.dvr.enabled.value">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.dvr.enabled"
|
||||
scp-desc="是否对Vhost启用DVR配置。默认: {{false| sc_filter_yesno}}"
|
||||
scp-bool="true">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.dvr.dvr_plan"
|
||||
scp-desc="录制计划,session按会话,segment分段,append单文件。默认: session"
|
||||
ng-show="global.dvr.enabled.value">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.dvr.dvr_path"
|
||||
scp-desc="录制文件的路径模板。默认: ./objs/nginx/html/[app]/[stream].[timestamp].flv"
|
||||
ng-show="global.dvr.enabled.value">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.dvr.dvr_duration"
|
||||
scp-desc="单位:秒。录制文件的时长。默认: 30"
|
||||
ng-show="global.dvr.enabled.value && global.dvr.dvr_plan && global.dvr.dvr_plan.value == 'segment'">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.dvr.dvr_wait_keyframe"
|
||||
scp-desc="是否等待关键帧。默认: {{true| sc_filter_yesno}}"
|
||||
ng-show="global.dvr.enabled.value && global.dvr.dvr_plan && global.dvr.dvr_plan.value == 'segment'">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.dvr.time_jitter"
|
||||
scp-desc="录制的时间戳校正算法。full完全,zero置零,off关闭。默认: full"
|
||||
ng-show="global.dvr.enabled.value">
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
62
trunk/research/console/views/dvr_en.html
Normal file
62
trunk/research/console/views/dvr_en.html
Normal file
|
@ -0,0 +1,62 @@
|
|||
<div>
|
||||
<div class="accordion">
|
||||
<div class="accordion-group">
|
||||
<div class="accordion-heading">
|
||||
<a class="accordion-toggle" href="javascript:void(0)">
|
||||
Vhost({{global.vid.value}}) DVR Config
|
||||
</a>
|
||||
</div>
|
||||
<div class="accordion-body collapse in">
|
||||
<div class="accordion-inner">
|
||||
<table class="table table-striped table-hover table-bordered">
|
||||
<tr>
|
||||
<th>Key</th>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
<th>Opt</th>
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.name" scp-link="#/vhosts/{{global.id.value}}"
|
||||
scp-desc="The vhost name to DVR.">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.app"
|
||||
scp-desc="The app name to DVR.">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.stream" scp-link="#/streams/{{global.sid.value}}"
|
||||
scp-desc="The stream url to DVR.">
|
||||
</tr>
|
||||
<tr sc-directive scd-data="global.dvr.apply" scd-span="span4"
|
||||
scd-desc="Whether record this stream."
|
||||
scd-default="false" scd-bool="true"
|
||||
scd-submit="dvr(global.dvr.apply)"
|
||||
ng-show="global.dvr.enabled.value">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.dvr.enabled"
|
||||
scp-desc="Whether enable DVR for vhost. Default is {{false| sc_filter_yesno}}"
|
||||
scp-bool="true">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.dvr.dvr_plan"
|
||||
scp-desc="The DVR plan, can be session, segment or append. Default is session."
|
||||
ng-show="global.dvr.enabled.value">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.dvr.dvr_path"
|
||||
scp-desc="The DVR file path template. Default is ./objs/nginx/html/[app]/[stream].[timestamp].flv"
|
||||
ng-show="global.dvr.enabled.value">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.dvr.dvr_duration"
|
||||
scp-desc="The DVR file duration in seconds. Default is 30"
|
||||
ng-show="global.dvr.enabled.value && global.dvr.dvr_plan && global.dvr.dvr_plan.value == 'segment'">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.dvr.dvr_wait_keyframe"
|
||||
scp-desc="Whether wait for keyframe when DVR. Default is {{true| sc_filter_yesno}}"
|
||||
ng-show="global.dvr.enabled.value && global.dvr.dvr_plan && global.dvr.dvr_plan.value == 'segment'">
|
||||
</tr>
|
||||
<tr sc-pretty2 scp-data="global.dvr.time_jitter"
|
||||
scp-desc="The time jitter algorithm for DVR, can be full, zero or off. Default is full."
|
||||
ng-show="global.dvr.enabled.value">
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
1
trunk/research/console/views/dvrs.html
Normal file
1
trunk/research/console/views/dvrs.html
Normal file
|
@ -0,0 +1 @@
|
|||
DVR信息请在每个Stream中单独配置, 请前往<a href="javascript:void(0)" ng-click="gogogo('/streams/')">Streams</a>配置。
|
1
trunk/research/console/views/dvrs_en.html
Normal file
1
trunk/research/console/views/dvrs_en.html
Normal file
|
@ -0,0 +1 @@
|
|||
Please config DVR in each stream by <a href="javascript:void(0)" ng-click="gogogo('/streams/')">here</a>.
|
27
trunk/research/console/views/stream.html
Normal file
27
trunk/research/console/views/stream.html
Normal file
|
@ -0,0 +1,27 @@
|
|||
<div>
|
||||
<div class="accordion">
|
||||
<div class="accordion-group">
|
||||
<div class="accordion-heading">
|
||||
<a class="accordion-toggle" href="javascript:void(0)">
|
||||
视频流-{{stream.id}}
|
||||
</a>
|
||||
</div>
|
||||
<div id="collapseOne" class="accordion-body collapse in">
|
||||
<div class="accordion-inner" ng-if="stream">
|
||||
<p>ID: {{stream.id}}</p>
|
||||
<p>Name: {{stream.name}}</p>
|
||||
<td><a href="javascript:void(0)" ng-click="gogogo('/vhosts/' + stream.vhost)">{{owner.name}}</a></td>
|
||||
<p>Publishing: {{stream.publish.active| sc_filter_has_stream}}</p>
|
||||
<p>Clients: {{stream.clients}}人</p>
|
||||
<p>Recv: {{stream.kbps.recv_30s| sc_filter_bitrate_k}}</p>
|
||||
<p>Send: {{stream.kbps.send_30s| sc_filter_bitrate_k}}</p>
|
||||
<p ng-if="stream.video">Video: <span>{{stream.video| sc_filter_video}}</span></p>
|
||||
<p ng-if="stream.audio">Audio: <span>{{stream.audio| sc_filter_audio}}</span></p>
|
||||
<p>管理: <a ng-href="{{stream| sc_filter_preview_url}}" target="_blank">预览</a></p>
|
||||
<p ng-show="stream.publish.active">管理: <a ng-click="kickoff(stream)" href="javascript:void(0)">踢流</a></p>
|
||||
<p ng-show="support_raw_api">管理: <a ng-click="dvr(stream)" href="javascript:void(0)">录制</a> </p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
27
trunk/research/console/views/stream_en.html
Normal file
27
trunk/research/console/views/stream_en.html
Normal file
|
@ -0,0 +1,27 @@
|
|||
<div>
|
||||
<div class="accordion">
|
||||
<div class="accordion-group">
|
||||
<div class="accordion-heading">
|
||||
<a class="accordion-toggle" href="javascript:void(0)">
|
||||
Stream-{{stream.id}}
|
||||
</a>
|
||||
</div>
|
||||
<div id="collapseOne" class="accordion-body collapse in">
|
||||
<div class="accordion-inner" ng-if="stream">
|
||||
<p>ID: {{stream.id}}</p>
|
||||
<p>Name: {{stream.name}}</p>
|
||||
<td><a href="javascript:void(0)" ng-click="gogogo('/vhosts/' + stream.vhost)">{{owner.name}}</a></td>
|
||||
<p>Publishing: {{stream.publish.active| sc_filter_has_stream}}</p>
|
||||
<p>Clients: {{stream.clients}} Clients</p>
|
||||
<p>Recv: {{stream.kbps.recv_30s| sc_filter_bitrate_k}}</p>
|
||||
<p>Send: {{stream.kbps.send_30s| sc_filter_bitrate_k}}</p>
|
||||
<p ng-if="stream.video">Video: <span>{{stream.video| sc_filter_video}}</span></p>
|
||||
<p ng-if="stream.audio">Audio: <span>{{stream.audio| sc_filter_audio}}</span></p>
|
||||
<p>Manage: <a ng-href="{{stream| sc_filter_preview_url}}" target="_blank">Preview</a></p>
|
||||
<p ng-show="stream.publish.active">Manage: <a ng-click="kickoff(stream)" href="javascript:void(0)">Kickoff</a></p>
|
||||
<p ng-show="support_raw_api">Manage: <a ng-click="dvr(stream)" href="javascript:void(0)">Record</a> </p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
47
trunk/research/console/views/streams.html
Normal file
47
trunk/research/console/views/streams.html
Normal file
|
@ -0,0 +1,47 @@
|
|||
<div>
|
||||
<div class="accordion">
|
||||
<div class="accordion-group">
|
||||
<div class="accordion-heading" sc-collapse="in">
|
||||
<a class="accordion-toggle" href="javascript:void(0)">
|
||||
视频流(Streams)列表
|
||||
</a>
|
||||
</div>
|
||||
<div id="collapseOne" class="accordion-body collapse">
|
||||
<div class="accordion-inner">
|
||||
<table class="table table-striped table-bordered">
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>流名称</th>
|
||||
<th>Vhost</th>
|
||||
<th>状态</th>
|
||||
<th>在线人数</th>
|
||||
<th>入口带宽</th>
|
||||
<th>出口带宽</th>
|
||||
<th>视频信息</th>
|
||||
<th>音频信息</th>
|
||||
<th>管理</th>
|
||||
</tr>
|
||||
<tr ng-repeat="stream in streams">
|
||||
<td><a href="javascript:void(0)" ng-click="gogogo('/streams/' + stream.id)">{{stream.id}}</a></td>
|
||||
<td>{{stream.name| sc_filter_less}}</td>
|
||||
<td><a href="javascript:void(0)" ng-click="gogogo('/vhosts/' + stream.vhost)">{{stream.owner.name}}</a></td>
|
||||
<td>{{stream.publish.active| sc_filter_has_stream}}</td>
|
||||
<td>{{stream.clients}}人</td>
|
||||
<td>{{stream.kbps.recv_30s| sc_filter_bitrate_k}}</td>
|
||||
<td>{{stream.kbps.send_30s| sc_filter_bitrate_k}}</td>
|
||||
<td><span ng-if="stream.video">{{stream.video| sc_filter_video}}</span></td>
|
||||
<td><span ng-if="stream.audio">{{stream.audio| sc_filter_audio}}</span></td>
|
||||
<td>
|
||||
<a ng-href="{{stream| sc_filter_preview_url}}" target="_blank">预览</a>
|
||||
<a ng-show="stream.publish.active" ng-click="kickoff(stream)" href="javascript:void(0)">踢流</a>
|
||||
<span ng-show="support_raw_api">
|
||||
<a href="javascript:void(0)" ng-click="dvr(stream)">录制</a>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
47
trunk/research/console/views/streams_en.html
Normal file
47
trunk/research/console/views/streams_en.html
Normal file
|
@ -0,0 +1,47 @@
|
|||
<div>
|
||||
<div class="accordion">
|
||||
<div class="accordion-group">
|
||||
<div class="accordion-heading" sc-collapse="in">
|
||||
<a class="accordion-toggle" href="javascript:void(0)">
|
||||
System Streams
|
||||
</a>
|
||||
</div>
|
||||
<div id="collapseOne" class="accordion-body collapse">
|
||||
<div class="accordion-inner">
|
||||
<table class="table table-striped table-bordered">
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Name</th>
|
||||
<th>Vhost</th>
|
||||
<th>Status</th>
|
||||
<th>Clients</th>
|
||||
<th>Inbound</th>
|
||||
<th>Outbound</th>
|
||||
<th>Video</th>
|
||||
<th>Audio</th>
|
||||
<th>Manage</th>
|
||||
</tr>
|
||||
<tr ng-repeat="stream in streams">
|
||||
<td><a href="javascript:void(0)" ng-click="gogogo('/streams/' + stream.id)">{{stream.id}}</a></td>
|
||||
<td>{{stream.name| sc_filter_less}}</td>
|
||||
<td><a href="javascript:void(0)" ng-click="gogogo('/vhosts/' + stream.vhost)">{{stream.owner.name}}</a></td>
|
||||
<td>{{stream.publish.active| sc_filter_has_stream}}</td>
|
||||
<td>{{stream.clients}}人</td>
|
||||
<td>{{stream.kbps.recv_30s| sc_filter_bitrate_k}}</td>
|
||||
<td>{{stream.kbps.send_30s| sc_filter_bitrate_k}}</td>
|
||||
<td><span ng-if="stream.video">{{stream.video| sc_filter_video}}</span></td>
|
||||
<td><span ng-if="stream.audio">{{stream.audio| sc_filter_audio}}</span></td>
|
||||
<td>
|
||||
<a ng-href="{{stream| sc_filter_preview_url}}" target="_blank">Preview</a>
|
||||
<a ng-show="stream.publish.active" ng-click="kickoff(stream)" href="javascript:void(0)">Kickoff</a>
|
||||
<span ng-show="support_raw_api">
|
||||
<a href="javascript:void(0)" ng-click="dvr(stream)">Record</a>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
137
trunk/research/console/views/summary.html
Normal file
137
trunk/research/console/views/summary.html
Normal file
|
@ -0,0 +1,137 @@
|
|||
<div>
|
||||
<div class="accordion">
|
||||
<div class="accordion-group">
|
||||
<div class="accordion-heading" sc-collapse="in">
|
||||
<a class="accordion-toggle" href="javascript:void(0)">
|
||||
服务器基本信息
|
||||
</a>
|
||||
</div>
|
||||
<div id="collapseOne" class="accordion-body collapse">
|
||||
<div class="accordion-inner">
|
||||
<div class="row">
|
||||
<div class="span3">
|
||||
<table class="table table-bordered" ng-if="server">
|
||||
<tr>
|
||||
<th colspan="2">SRS/{{server.version}}</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>运行</td>
|
||||
<td>{{server.srs_uptime| sc_filter_time}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>CPU</td>
|
||||
<td>{{server.cpu_percent| sc_filter_percentf}} / {{system.cpus_online| sc_filter_percentf}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>内存</td>
|
||||
<td>
|
||||
{{server.mem_percent| sc_filter_percentf2}}
|
||||
{{server.mem_kbyte| sc_filter_filesize_k2}} / {{system.mem_ram_kbyte| sc_filter_filesize_k2}}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>网络</td>
|
||||
<td>
|
||||
<span title="SRS的连接数">{{system.conn_srs}}</span> /
|
||||
<span title="SRS的入网带宽,即客户端上传带宽">{{kbps.in.srs| sc_filter_bitrate_k2}}</span> /
|
||||
<span title="SRS的出网带宽,即客户端下载带宽">{{kbps.out.srs| sc_filter_bitrate_k2}}</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="span3">
|
||||
<table class="table table-bordered" ng-if="system">
|
||||
<tr>
|
||||
<th colspan="2">OS信息</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>运行</td>
|
||||
<td>{{system.uptime| sc_filter_time}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>CPU</td>
|
||||
<td>{{system.cpu_percent * system.cpus_online| sc_filter_percentf}} / {{system.cpus_online| sc_filter_percentf}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>内存</td>
|
||||
<td>
|
||||
{{system.mem_ram_percent| sc_filter_percentf2}}
|
||||
{{system.mem_ram_kbyte * system.mem_ram_percent| sc_filter_filesize_k2}} / {{system.mem_ram_kbyte| sc_filter_filesize_k2}}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>负载</td>
|
||||
<td>{{system.load_1m| sc_filter_number}} / {{system.load_5m| sc_filter_number}} / {{system.load_15m| sc_filter_number}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="span3">
|
||||
<table class="table table-bordered" ng-if="system">
|
||||
<tr>
|
||||
<th colspan="2">负载信息</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>外网</td>
|
||||
<td>
|
||||
<span title="系统外网的入网带宽,即客户端上传带宽">{{kbps.in.sys| sc_filter_bitrate_k2}}</span> /
|
||||
<span title="系统外网的出网带宽,即客户端下载带宽">{{kbps.out.sys| sc_filter_bitrate_k2}}</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>内网</td>
|
||||
<td>
|
||||
<span title="系统内网的入网带宽,即客户端上传带宽">{{kbps.in.inner| sc_filter_bitrate_k2}}</span> /
|
||||
<span title="系统内网的出网带宽,即客户端下载带宽">{{kbps.out.inner| sc_filter_bitrate_k2}}</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>连接</td>
|
||||
<td>
|
||||
<span title="系统总连接数">{{system.conn_sys}}</span>
|
||||
<span title="系统ESTABLISHED状态的连接数">{{system.conn_sys_et}}</span>
|
||||
<span title="系统TIME_WAIT状态的连接数">{{system.conn_sys_tw}}</span>
|
||||
<span title="系统UDP绑定端口">{{system.conn_sys_udp}}</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>磁盘</td>
|
||||
<td>
|
||||
<span title="IO繁忙度">{{system.disk_busy_percent| sc_filter_percentf2}}</span>
|
||||
<span title="磁盘读取速度Bps">{{system.disk_read_KBps| sc_filter_filerate_k2}}</span>
|
||||
<span title="磁盘写入速度Bps">{{system.disk_write_KBps| sc_filter_filerate_k2}}</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="span2">
|
||||
<table class="table table-bordered" ng-if="system">
|
||||
<tr>
|
||||
<th colspan="2">其他信息</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td title="系统CPU信息">CPU</td>
|
||||
<td>
|
||||
<span title="CPU核心数">{{system.cpus}}</span> /
|
||||
<span title="在线CPU核心数">{{system.cpus_online}}</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td title="SRS的PID">PID</td>
|
||||
<td>{{server.pid}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td title="SRS的父PID">PPID</td>
|
||||
<td>{{server.ppid}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td title="SRS API是否有效">Ready</td>
|
||||
<td>{{global.ok| sc_filter_yesno}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
137
trunk/research/console/views/summary_en.html
Normal file
137
trunk/research/console/views/summary_en.html
Normal file
|
@ -0,0 +1,137 @@
|
|||
<div>
|
||||
<div class="accordion">
|
||||
<div class="accordion-group">
|
||||
<div class="accordion-heading" sc-collapse="in">
|
||||
<a class="accordion-toggle" href="javascript:void(0)">
|
||||
SRS Summary
|
||||
</a>
|
||||
</div>
|
||||
<div id="collapseOne" class="accordion-body collapse">
|
||||
<div class="accordion-inner">
|
||||
<div class="row">
|
||||
<div class="span3">
|
||||
<table class="table table-bordered" ng-if="server">
|
||||
<tr>
|
||||
<th colspan="2">SRS/{{server.version}}</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Alive</td>
|
||||
<td>{{server.srs_uptime| sc_filter_time}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>CPU</td>
|
||||
<td>{{server.cpu_percent| sc_filter_percentf}} / {{system.cpus_online| sc_filter_percentf}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Memory</td>
|
||||
<td>
|
||||
{{server.mem_percent| sc_filter_percentf2}}
|
||||
{{server.mem_kbyte| sc_filter_filesize_k2}} / {{system.mem_ram_kbyte| sc_filter_filesize_k2}}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Network</td>
|
||||
<td>
|
||||
<span title="SRS Connections">{{system.conn_srs}}</span> /
|
||||
<span title="SRS Inbound Bandwidth">{{kbps.in.srs| sc_filter_bitrate_k2}}</span> /
|
||||
<span title="SRS Outbound Bandwidth">{{kbps.out.srs| sc_filter_bitrate_k2}}</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="span3">
|
||||
<table class="table table-bordered" ng-if="system">
|
||||
<tr>
|
||||
<th colspan="2">OS System</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Alive</td>
|
||||
<td>{{system.uptime| sc_filter_time}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>CPU</td>
|
||||
<td>{{system.cpu_percent * system.cpus_online| sc_filter_percentf}} / {{system.cpus_online| sc_filter_percentf}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Memory</td>
|
||||
<td>
|
||||
{{system.mem_ram_percent| sc_filter_percentf2}}
|
||||
{{system.mem_ram_kbyte * system.mem_ram_percent| sc_filter_filesize_k2}} / {{system.mem_ram_kbyte| sc_filter_filesize_k2}}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Load</td>
|
||||
<td>{{system.load_1m| sc_filter_number}} / {{system.load_5m| sc_filter_number}} / {{system.load_15m| sc_filter_number}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="span3">
|
||||
<table class="table table-bordered" ng-if="system">
|
||||
<tr>
|
||||
<th colspan="2">IO Load</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Internet</td>
|
||||
<td>
|
||||
<span title="Internet Inbound Bandwidth">{{kbps.in.sys| sc_filter_bitrate_k2}}</span> /
|
||||
<span title="Internet Outbound Bandwidth">{{kbps.out.sys| sc_filter_bitrate_k2}}</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Intranet</td>
|
||||
<td>
|
||||
<span title="Intranet Inbound Bandwidth">{{kbps.in.inner| sc_filter_bitrate_k2}}</span> /
|
||||
<span title="Intranet Outbound Bandwidth">{{kbps.out.inner| sc_filter_bitrate_k2}}</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td title="Connections">Conns</td>
|
||||
<td>
|
||||
<span title="System">{{system.conn_sys}}</span>
|
||||
<span title="System ESTABLISHED">{{system.conn_sys_et}}</span>
|
||||
<span title="System TIME_WAIT">{{system.conn_sys_tw}}</span>
|
||||
<span title="System UDP Bind Ports">{{system.conn_sys_udp}}</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Disk</td>
|
||||
<td>
|
||||
<span title="IO Busy">{{system.disk_busy_percent| sc_filter_percentf2}}</span>
|
||||
<span title="Disk Read in Bps">{{system.disk_read_KBps| sc_filter_filerate_k2}}</span>
|
||||
<span title="Disk Write in Bps">{{system.disk_write_KBps| sc_filter_filerate_k2}}</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="span2">
|
||||
<table class="table table-bordered" ng-if="system">
|
||||
<tr>
|
||||
<th colspan="2">Others</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td title="System CPU Usage">CPU</td>
|
||||
<td>
|
||||
<span title="Number of CPU">{{system.cpus}}</span> /
|
||||
<span title="Online CPUs">{{system.cpus_online}}</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td title="PID of SRS">PID</td>
|
||||
<td>{{server.pid}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td title="PID of SRS's Parent">PPID</td>
|
||||
<td>{{server.ppid}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td title="Whether SRS API Ready?">Ready</td>
|
||||
<td>{{global.ok| sc_filter_yesno}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
23
trunk/research/console/views/vhost.html
Normal file
23
trunk/research/console/views/vhost.html
Normal file
|
@ -0,0 +1,23 @@
|
|||
<div>
|
||||
<div class="accordion">
|
||||
<div class="accordion-group">
|
||||
<div class="accordion-heading">
|
||||
<a class="accordion-toggle" href="javascript:void(0)">
|
||||
虚拟主机-{{vhost.id}}
|
||||
</a>
|
||||
</div>
|
||||
<div id="collapseOne" class="accordion-body collapse in">
|
||||
<div class="accordion-inner">
|
||||
<p>ID: {{vhost.id}}</p>
|
||||
<p>Name: {{vhost.name}}</p>
|
||||
<p>Enabled: {{vhost.enabled| sc_filter_enabled}}</p>
|
||||
<p>Streams: {{vhost.streams}}人</p>
|
||||
<p>Clients: {{vhost.clients}}人</p>
|
||||
<p>Recv: {{vhost.kbps.recv_30s| sc_filter_bitrate_k}}</p>
|
||||
<p>Send: {{vhost.kbps.send_30s| sc_filter_bitrate_k}}</p>
|
||||
<p>HLS: {{vhost.hls.enabled| sc_filter_enabled}}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
23
trunk/research/console/views/vhost_en.html
Normal file
23
trunk/research/console/views/vhost_en.html
Normal file
|
@ -0,0 +1,23 @@
|
|||
<div>
|
||||
<div class="accordion">
|
||||
<div class="accordion-group">
|
||||
<div class="accordion-heading">
|
||||
<a class="accordion-toggle" href="javascript:void(0)">
|
||||
Vhost-{{vhost.id}}
|
||||
</a>
|
||||
</div>
|
||||
<div id="collapseOne" class="accordion-body collapse in">
|
||||
<div class="accordion-inner">
|
||||
<p>ID: {{vhost.id}}</p>
|
||||
<p>Name: {{vhost.name}}</p>
|
||||
<p>Enabled: {{vhost.enabled| sc_filter_enabled}}</p>
|
||||
<p>Streams: {{vhost.streams}} Clients</p>
|
||||
<p>Clients: {{vhost.clients}} Clients</p>
|
||||
<p>Recv: {{vhost.kbps.recv_30s| sc_filter_bitrate_k}}</p>
|
||||
<p>Send: {{vhost.kbps.send_30s| sc_filter_bitrate_k}}</p>
|
||||
<p>HLS: {{vhost.hls.enabled| sc_filter_enabled}}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
37
trunk/research/console/views/vhosts.html
Normal file
37
trunk/research/console/views/vhosts.html
Normal file
|
@ -0,0 +1,37 @@
|
|||
<div>
|
||||
<div class="accordion">
|
||||
<div class="accordion-group">
|
||||
<div class="accordion-heading" sc-collapse="in">
|
||||
<a class="accordion-toggle" href="javascript:void(0)">
|
||||
虚拟主机(Vhosts)列表
|
||||
</a>
|
||||
</div>
|
||||
<div id="collapseOne" class="accordion-body collapse">
|
||||
<div class="accordion-inner">
|
||||
<table class="table table-striped table-bordered">
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>主机名称</th>
|
||||
<th>状态</th>
|
||||
<th>在线流</th>
|
||||
<th>在线人数</th>
|
||||
<th>入口带宽</th>
|
||||
<th>出口带宽</th>
|
||||
<th>HLS</th>
|
||||
</tr>
|
||||
<tr ng-repeat="vhost in vhosts">
|
||||
<td><a href="javascript:void(0)" ng-click="gogogo('/vhosts/' + vhost.id)">{{vhost.id}}</a></td>
|
||||
<td>{{vhost.name}}</td>
|
||||
<td>{{vhost.enabled| sc_filter_enabled}}</td>
|
||||
<td>{{vhost.streams}}个</td>
|
||||
<td>{{vhost.clients}}人</td>
|
||||
<td>{{vhost.kbps.recv_30s| sc_filter_bitrate_k}}</td>
|
||||
<td>{{vhost.kbps.send_30s| sc_filter_bitrate_k}}</td>
|
||||
<td>{{vhost.hls.enabled| sc_filter_enabled}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
37
trunk/research/console/views/vhosts_en.html
Normal file
37
trunk/research/console/views/vhosts_en.html
Normal file
|
@ -0,0 +1,37 @@
|
|||
<div>
|
||||
<div class="accordion">
|
||||
<div class="accordion-group">
|
||||
<div class="accordion-heading" sc-collapse="in">
|
||||
<a class="accordion-toggle" href="javascript:void(0)">
|
||||
System Vhosts
|
||||
</a>
|
||||
</div>
|
||||
<div id="collapseOne" class="accordion-body collapse">
|
||||
<div class="accordion-inner">
|
||||
<table class="table table-striped table-bordered">
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Name</th>
|
||||
<th>Status</th>
|
||||
<th>Streams</th>
|
||||
<th>Clients</th>
|
||||
<th>Inbound</th>
|
||||
<th>Outbound</th>
|
||||
<th>HLS</th>
|
||||
</tr>
|
||||
<tr ng-repeat="vhost in vhosts">
|
||||
<td><a href="javascript:void(0)" ng-click="gogogo('/vhosts/' + vhost.id)">{{vhost.id}}</a></td>
|
||||
<td>{{vhost.name}}</td>
|
||||
<td>{{vhost.enabled| sc_filter_enabled}}</td>
|
||||
<td>{{vhost.streams}}个</td>
|
||||
<td>{{vhost.clients}}人</td>
|
||||
<td>{{vhost.kbps.recv_30s| sc_filter_bitrate_k}}</td>
|
||||
<td>{{vhost.kbps.send_30s| sc_filter_bitrate_k}}</td>
|
||||
<td>{{vhost.hls.enabled| sc_filter_enabled}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -61,20 +61,20 @@ function is_default_port(schema, port) {
|
|||
|
||||
/**
|
||||
@param server the ip of server. default to window.location.hostname
|
||||
@param vhost the vhost of rtmp. default to window.location.hostname
|
||||
@param port the port of rtmp. default to 1935
|
||||
@param app the app of rtmp. default to live.
|
||||
@param stream the stream of rtmp. default to livestream.
|
||||
@param vhost the vhost of HTTP-FLV. default to window.location.hostname
|
||||
@param port the port of HTTP-FLV. default to 1935
|
||||
@param app the app of HTTP-FLV. default to live.
|
||||
@param stream the stream of HTTP-FLV. default to livestream.flv
|
||||
*/
|
||||
function build_default_rtmp_url() {
|
||||
function build_default_flv_url() {
|
||||
var query = parse_query_string();
|
||||
|
||||
var schema = (!query.schema)? "rtmp":query.schema;
|
||||
var schema = (!query.schema)? "http":query.schema;
|
||||
var server = (!query.server)? window.location.hostname:query.server;
|
||||
var port = (!query.port)? (schema==="http"? 80:1935) : Number(query.port);
|
||||
var port = (!query.port)? (schema==="http"? 8080:1935) : Number(query.port);
|
||||
var vhost = (!query.vhost)? window.location.hostname:query.vhost;
|
||||
var app = (!query.app)? "live":query.app;
|
||||
var stream = (!query.stream)? "livestream":query.stream;
|
||||
var stream = (!query.stream)? "livestream.flv":query.stream;
|
||||
|
||||
var queries = [];
|
||||
if (server !== vhost && vhost !== "__defaultVhost__") {
|
||||
|
@ -147,14 +147,14 @@ function build_default_rtc_url(query) {
|
|||
|
||||
/**
|
||||
* initialize the page.
|
||||
* @param rtmp_url the div id contains the rtmp stream url to play
|
||||
* @param flv_url the div id contains the flv stream url to play
|
||||
* @param hls_url the div id contains the hls stream url to play
|
||||
* @param modal_player the div id contains the modal player
|
||||
*/
|
||||
function srs_init_rtmp(rtmp_url, modal_player) {
|
||||
function srs_init_flv(flv_url, modal_player) {
|
||||
update_nav();
|
||||
if (rtmp_url) {
|
||||
$(rtmp_url).val(build_default_rtmp_url());
|
||||
if (flv_url) {
|
||||
$(flv_url).val(build_default_flv_url());
|
||||
}
|
||||
if (modal_player) {
|
||||
$(modal_player).width(srs_get_player_modal() + "px");
|
||||
|
|
|
@ -754,10 +754,9 @@
|
|||
var query = parse_query_string();
|
||||
|
||||
// get the vhost and port to set the default url.
|
||||
// for example: http://192.168.1.213/players/srs_player.html?port=1935&vhost=demo
|
||||
// url set to: rtmp://demo:1935/live/livestream
|
||||
srs_init_rtmp("#txt_url", "#main_modal");
|
||||
srs_init_rtmp("#txt_url", "#rtc_player_modal");
|
||||
// url set to: http://localhost:8080/live/livestream.flv
|
||||
srs_init_flv("#txt_url", "#main_modal");
|
||||
srs_init_flv("#txt_url", "#rtc_player_modal");
|
||||
|
||||
// consts for buffer and max buffer.
|
||||
var bts = [0.1, 0.2, 0.3, 0.5, 0.8, 1, 2, 3, 4, 5, 6, 8, 10, 15, 20, 30];
|
||||
|
|
|
@ -247,9 +247,8 @@
|
|||
var query = parse_query_string();
|
||||
|
||||
// get the vhost and port to set the default url.
|
||||
// for example: http://192.168.1.213/players/srs_player.html?port=1935&vhost=demo
|
||||
// url set to: rtmp://demo:1935/live/livestream
|
||||
srs_init_rtmp("#txt_url");
|
||||
// url set to: http://localhost:8080/live/livestream.flv
|
||||
srs_init_flv("#txt_url");
|
||||
|
||||
if (query.autostart === "true") {
|
||||
$('#video_player').prop('muted', true);
|
||||
|
|
|
@ -421,9 +421,8 @@
|
|||
var query = parse_query_string();
|
||||
|
||||
// get the vhost and port to set the default url.
|
||||
// for example: http://192.168.1.213/players/srs_player.html?port=1935&vhost=demo
|
||||
// url set to: rtmp://demo:1935/live/livestream
|
||||
srs_init_rtmp("#txt_url", "#main_modal");
|
||||
// url set to: http://localhost:8080/live/livestream.flv
|
||||
srs_init_flv("#txt_url", "#main_modal");
|
||||
|
||||
// consts for buffer and max buffer.
|
||||
var bts = [0.1, 0.2, 0.3, 0.5, 0.8, 1, 2, 3, 4, 5, 6, 8, 10, 15, 20, 30];
|
||||
|
|
|
@ -310,9 +310,8 @@
|
|||
var query = parse_query_string();
|
||||
var autoLoadPage = function() {
|
||||
// get the vhost and port to set the default url.
|
||||
// for example: http://192.168.1.213/players/srs_player.html?port=1935&vhost=demo
|
||||
// url set to: rtmp://demo:1935/live/livestream
|
||||
srs_init_rtmp("#txt_url", null);
|
||||
// url set to: http://localhost:8080/live/livestream.flv
|
||||
srs_init_flv("#txt_url", null);
|
||||
|
||||
if (query.agent == "true") {
|
||||
document.write(navigator.userAgent);
|
||||
|
|
|
@ -27,7 +27,7 @@ do
|
|||
case "$option" in
|
||||
-*=*)
|
||||
value=`echo "$option" | sed -e 's|[-_a-zA-Z0-9/]*=||'`
|
||||
option=`echo "$option" | sed -e 's|=[-_a-zA-Z0-9/]*||'`
|
||||
option=`echo "$option" | sed -e 's|=[-_a-zA-Z0-9/~]*||'`
|
||||
;;
|
||||
*) value="" ;;
|
||||
esac
|
||||
|
@ -59,6 +59,8 @@ if [ $help = yes ]; then
|
|||
--pi for pi platform, configure/make/package.
|
||||
--x86-64 alias for --x86-x64.
|
||||
--jobs Set the configure and make jobs.
|
||||
|
||||
--console The path for https://github.com/ossrs/srs-console
|
||||
END
|
||||
exit 0
|
||||
fi
|
||||
|
@ -151,6 +153,18 @@ ok_msg "start install srs"
|
|||
ret=$?; if [[ 0 -ne ${ret} ]]; then failed_msg "install srs failed"; exit $ret; fi
|
||||
ok_msg "install srs success"
|
||||
|
||||
# Copy srs-console
|
||||
HTTP_HOME="${package_dir}/${INSTALL}/objs/nginx/html/"
|
||||
(
|
||||
cp $work_dir/research/api-server/static-dir/index.html ${HTTP_HOME} &&
|
||||
cp $work_dir/research/api-server/static-dir/favicon.ico ${HTTP_HOME} &&
|
||||
cp $work_dir/research/api-server/static-dir/crossdomain.xml ${HTTP_HOME} &&
|
||||
cp -R $work_dir/research/players ${HTTP_HOME} &&
|
||||
cp -R $work_dir/research/console ${HTTP_HOME}
|
||||
) >> $log 2>&1
|
||||
ret=$?; if [[ 0 -ne ${ret} ]]; then failed_msg "copy utilities failed"; exit $ret; fi
|
||||
ok_msg "copy utilities success"
|
||||
|
||||
# copy extra files to package.
|
||||
ok_msg "start copy extra files to package"
|
||||
(
|
||||
|
|
|
@ -26,6 +26,6 @@
|
|||
|
||||
#define VERSION_MAJOR 3
|
||||
#define VERSION_MINOR 0
|
||||
#define SRS_VERSION3_REVISION 158
|
||||
#define SRS_VERSION3_REVISION 160
|
||||
|
||||
#endif
|
||||
|
|
|
@ -26,6 +26,6 @@
|
|||
|
||||
#define VERSION_MAJOR 4
|
||||
#define VERSION_MINOR 0
|
||||
#define VERSION_REVISION 89
|
||||
#define VERSION_REVISION 90
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue