mirror of https://github.com/ossrs/srs.git
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
687 lines
20 KiB
JavaScript
687 lines
20 KiB
JavaScript
// 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.23
|
|
*/
|
|
|
|
/**
|
|
* 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 {
|
|
// For WebRTC, SRS use 1985 as default API port.
|
|
ret.port = 1985;
|
|
}
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
|