basic ui structure addded

This commit is contained in:
Hamza Zia 2012-06-04 22:08:46 +08:00
parent 3573209150
commit 708bbd1ea0
3 changed files with 743 additions and 39 deletions

View File

@ -20,13 +20,37 @@
<script src="js/libs/modernizr-2.5.3.min.js"></script> <script src="js/libs/modernizr-2.5.3.min.js"></script>
<script src="js/libs/jquery-1.7.2.js"></script> <script src="js/libs/jquery-1.7.2.js"></script>
<script src="js/libs/bootstrap.js"></script> <script src="js/libs/bootstrap.js"></script>
<script src="js/libs/mustache.js"></script>
<style>
body {
padding-top: 60px;
}
</style>
</head> </head>
<body class="hero-unit"> <body>
<h1>ARIA2 Webclient</h1> <div class="navbar navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</a>
<a class="brand" href="#">Aria2 Web-Client</a>
<div class="nav-collapse">
<ul class="nav">
<li class="active"><a href="#">Active Downloads</a></li>
<li><a href="#watiting_downloads">Passive Downloads</a></li>
<li><a id="newDownload" href="#">Add Download</a></li>
</ul>
</div><!--/.nav-collapse -->
</div>
</div>
</div>
<div role="main"> <div role="main" class="container">
<p id="console"></p>
<h2>Pending Downloads</h2> <h2>Pending Downloads</h2>
<table id="d_table" class="table table-bordered"> <table id="d_table" class="table table-bordered">
<tr> <tr>
@ -36,13 +60,35 @@
<th>Download Speed</th> <th>Download Speed</th>
</tr> </tr>
</table> </table>
<div id="downloads">
<h2>Current Downloads</h2>
<div class="download_item">
<div class="row">
<div class="span8">
<h3>Sample Download</h3>
</div>
<div class="span4">
<button class="btn btn-mini"><i class="icon-pause"></i>Pause</button>
<button class="btn btn-mini btn-danger"><i class="icon-remove"></i> Delete</button>
<span class="label label-success">Status: Downloading 43%</span>
</div>
<br><br>
<div class="span12 progress progress-striped active">
<div class="bar" style="width: 40%"></div>
</div>
</div>
</div>
</div>
<h3 id="console"></h3>
<footer>
intital footer!!
</footer>
</div> </div>
<footer>
intital footer!!
</footer>
<!-- Hidden dialogs and out of screen HTML elements --> <!-- Hidden dialogs and out of screen HTML elements -->
<!-- error connection template -->
<div class="modal fade" id="error_connect"> <div class="modal fade" id="error_connect">
<div class="modal-header"> <div class="modal-header">
<button class="close" data-dismiss="modal">x</button> <button class="close" data-dismiss="modal">x</button>
@ -55,8 +101,65 @@
</p> </p>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<a href="#" class="btn">Retry</a> <a href="#" onclick="window.location.reload(true)" class="btn">Retry</a>
<a href="#" class="btn btn-primary">Use custom IP and port settings</a> <a href="#" onclick="custom_aria2_connect()" class="btn btn-primary">Use custom IP and port settings</a>
</div>
</div>
<!-- change aria2 rpc host and port template -->
<div class="modal fade" id="change_conf">
<div class="modal-header">
<button class="close" data-dismiss="modal">x</button>
<h3>Please enter the aria2 RPC port and host</h3>
</div>
<div class="modal-body">
<form class="form-horizontal">
<fieldset>
<legend>Server Configuration</legend>
<div class="control-group">
<label class="control-label" for="input_host">Enter the host:</label>
<div class="controls">
<div class="input-prepend"><span class="add-on">http://</span><input type="text" class="input-xlarge" id="input_host" placeholder="localhost"/></div>
<p class="help-block">Enter the ip or dns name of the server on which the rpc for aria2 is running (default = localhost)</p>
</div>
<label class="control-label" for="input_port">Enter the port:</label>
<div class="controls">
<input type="text" class="input-xlarge" placeholder="6800" id="input_port"/>
<p class="help-block">Enter the port of the server on which the rpc for aria2 is running (default = 6800)</p>
</div>
</div>
</fieldset>
</form>
</div>
<div class="modal-footer">
<a href="#" onclick="window.location.reload(true)" class="btn">Retry with default configuration</a>
<a href="#" onclick="update_server_conf()" class="btn btn-primary">Use custom IP and port settings</a>
</div>
</div>
<!-- new Download template -->
<div class="modal fade" id="newDownload_modal">
<div class="modal-header">
<button class="close" data-dismiss="modal">x</button>
<h3>Add a new Download</h3>
</div>
<div class="modal-body">
<form class="form-horizontal">
<fieldset>
<legend>New Download</legend>
<div class="control-group">
<label class="control-label" for="newDownload_url">Enter url for the Download:</label>
<div class="controls">
<input type="text" class="input-xlarge" id="newDownload_url" placeholder="http://example.com"/>
</div>
</div>
</fieldset>
</form>
</div>
<div class="modal-footer">
<button id="addNewDownload" class="btn">Add Download</button>
</div> </div>
</div> </div>

536
js/libs/mustache.js Normal file
View File

@ -0,0 +1,536 @@
/*!
* mustache.js - Logic-less {{mustache}} templates with JavaScript
* http://github.com/janl/mustache.js
*/
var Mustache = (typeof module !== "undefined" && module.exports) || {};
(function (exports) {
exports.name = "mustache.js";
exports.version = "0.5.0-dev";
exports.tags = ["{{", "}}"];
exports.parse = parse;
exports.compile = compile;
exports.render = render;
exports.clearCache = clearCache;
// This is here for backwards compatibility with 0.4.x.
exports.to_html = function (template, view, partials, send) {
var result = render(template, view, partials);
if (typeof send === "function") {
send(result);
} else {
return result;
}
};
var _toString = Object.prototype.toString;
var _isArray = Array.isArray;
var _forEach = Array.prototype.forEach;
var _trim = String.prototype.trim;
var isArray;
if (_isArray) {
isArray = _isArray;
} else {
isArray = function (obj) {
return _toString.call(obj) === "[object Array]";
};
}
var forEach;
if (_forEach) {
forEach = function (obj, callback, scope) {
return _forEach.call(obj, callback, scope);
};
} else {
forEach = function (obj, callback, scope) {
for (var i = 0, len = obj.length; i < len; ++i) {
callback.call(scope, obj[i], i, obj);
}
};
}
var spaceRe = /^\s*$/;
function isWhitespace(string) {
return spaceRe.test(string);
}
var trim;
if (_trim) {
trim = function (string) {
return string == null ? "" : _trim.call(string);
};
} else {
var trimLeft, trimRight;
if (isWhitespace("\xA0")) {
trimLeft = /^\s+/;
trimRight = /\s+$/;
} else {
// IE doesn't match non-breaking spaces with \s, thanks jQuery.
trimLeft = /^[\s\xA0]+/;
trimRight = /[\s\xA0]+$/;
}
trim = function (string) {
return string == null ? "" :
String(string).replace(trimLeft, "").replace(trimRight, "");
};
}
var escapeMap = {
"&": "&amp;",
"<": "&lt;",
">": "&gt;",
'"': '&quot;',
"'": '&#39;'
};
function escapeHTML(string) {
return String(string).replace(/&(?!\w+;)|[<>"']/g, function (s) {
return escapeMap[s] || s;
});
}
/**
* Adds the `template`, `line`, and `file` properties to the given error
* object and alters the message to provide more useful debugging information.
*/
function debug(e, template, line, file) {
file = file || "<template>";
var lines = template.split("\n"),
start = Math.max(line - 3, 0),
end = Math.min(lines.length, line + 3),
context = lines.slice(start, end);
var c;
for (var i = 0, len = context.length; i < len; ++i) {
c = i + start + 1;
context[i] = (c === line ? " >> " : " ") + context[i];
}
e.template = template;
e.line = line;
e.file = file;
e.message = [file + ":" + line, context.join("\n"), "", e.message].join("\n");
return e;
}
/**
* Looks up the value of the given `name` in the given context `stack`.
*/
function lookup(name, stack, defaultValue) {
if (name === ".") {
return stack[stack.length - 1];
}
var names = name.split(".");
var lastIndex = names.length - 1;
var target = names[lastIndex];
var value, context, i = stack.length, j, localStack;
while (i) {
localStack = stack.slice(0);
context = stack[--i];
j = 0;
while (j < lastIndex) {
context = context[names[j++]];
if (context == null) {
break;
}
localStack.push(context);
}
if (context && typeof context === "object" && target in context) {
value = context[target];
break;
}
}
// If the value is a function, call it in the current context.
if (typeof value === "function") {
value = value.call(localStack[localStack.length - 1]);
}
if (value == null) {
return defaultValue;
}
return value;
}
function renderSection(name, stack, callback, inverted) {
var buffer = "";
var value = lookup(name, stack);
if (inverted) {
// From the spec: inverted sections may render text once based on the
// inverse value of the key. That is, they will be rendered if the key
// doesn't exist, is false, or is an empty list.
if (value == null || value === false || (isArray(value) && value.length === 0)) {
buffer += callback();
}
} else if (isArray(value)) {
forEach(value, function (value) {
stack.push(value);
buffer += callback();
stack.pop();
});
} else if (typeof value === "object") {
stack.push(value);
buffer += callback();
stack.pop();
} else if (typeof value === "function") {
var scope = stack[stack.length - 1];
var scopedRender = function (template) {
return render(template, scope);
};
buffer += value.call(scope, callback(), scopedRender) || "";
} else if (value) {
buffer += callback();
}
return buffer;
}
/**
* Parses the given `template` and returns the source of a function that,
* with the proper arguments, will render the template. Recognized options
* include the following:
*
* - file The name of the file the template comes from (displayed in
* error messages)
* - tags An array of open and close tags the `template` uses. Defaults
* to the value of Mustache.tags
* - debug Set `true` to log the body of the generated function to the
* console
* - space Set `true` to preserve whitespace from lines that otherwise
* contain only a {{tag}}. Defaults to `false`
*/
function parse(template, options) {
options = options || {};
var tags = options.tags || exports.tags,
openTag = tags[0],
closeTag = tags[tags.length - 1];
var code = [
'var buffer = "";', // output buffer
"\nvar line = 1;", // keep track of source line number
"\ntry {",
'\nbuffer += "'
];
var spaces = [], // indices of whitespace in code on the current line
hasTag = false, // is there a {{tag}} on the current line?
nonSpace = false; // is there a non-space char on the current line?
// Strips all space characters from the code array for the current line
// if there was a {{tag}} on it and otherwise only spaces.
var stripSpace = function () {
if (hasTag && !nonSpace && !options.space) {
while (spaces.length) {
code.splice(spaces.pop(), 1);
}
} else {
spaces = [];
}
hasTag = false;
nonSpace = false;
};
var sectionStack = [], updateLine, nextOpenTag, nextCloseTag;
var setTags = function (source) {
tags = trim(source).split(/\s+/);
nextOpenTag = tags[0];
nextCloseTag = tags[tags.length - 1];
};
var includePartial = function (source) {
code.push(
'";',
updateLine,
'\nvar partial = partials["' + trim(source) + '"];',
'\nif (partial) {',
'\n buffer += render(partial,stack[stack.length - 1],partials);',
'\n}',
'\nbuffer += "'
);
};
var openSection = function (source, inverted) {
var name = trim(source);
if (name === "") {
throw debug(new Error("Section name may not be empty"), template, line, options.file);
}
sectionStack.push({name: name, inverted: inverted});
code.push(
'";',
updateLine,
'\nvar name = "' + name + '";',
'\nvar callback = (function () {',
'\n return function () {',
'\n var buffer = "";',
'\nbuffer += "'
);
};
var openInvertedSection = function (source) {
openSection(source, true);
};
var closeSection = function (source) {
var name = trim(source);
var openName = sectionStack.length != 0 && sectionStack[sectionStack.length - 1].name;
if (!openName || name != openName) {
throw debug(new Error('Section named "' + name + '" was never opened'), template, line, options.file);
}
var section = sectionStack.pop();
code.push(
'";',
'\n return buffer;',
'\n };',
'\n})();'
);
if (section.inverted) {
code.push("\nbuffer += renderSection(name,stack,callback,true);");
} else {
code.push("\nbuffer += renderSection(name,stack,callback);");
}
code.push('\nbuffer += "');
};
var sendPlain = function (source) {
code.push(
'";',
updateLine,
'\nbuffer += lookup("' + trim(source) + '",stack,"");',
'\nbuffer += "'
);
};
var sendEscaped = function (source) {
code.push(
'";',
updateLine,
'\nbuffer += escapeHTML(lookup("' + trim(source) + '",stack,""));',
'\nbuffer += "'
);
};
var line = 1, c, callback;
for (var i = 0, len = template.length; i < len; ++i) {
if (template.slice(i, i + openTag.length) === openTag) {
i += openTag.length;
c = template.substr(i, 1);
updateLine = '\nline = ' + line + ';';
nextOpenTag = openTag;
nextCloseTag = closeTag;
hasTag = true;
switch (c) {
case "!": // comment
i++;
callback = null;
break;
case "=": // change open/close tags, e.g. {{=<% %>=}}
i++;
closeTag = "=" + closeTag;
callback = setTags;
break;
case ">": // include partial
i++;
callback = includePartial;
break;
case "#": // start section
i++;
callback = openSection;
break;
case "^": // start inverted section
i++;
callback = openInvertedSection;
break;
case "/": // end section
i++;
callback = closeSection;
break;
case "{": // plain variable
closeTag = "}" + closeTag;
// fall through
case "&": // plain variable
i++;
nonSpace = true;
callback = sendPlain;
break;
default: // escaped variable
nonSpace = true;
callback = sendEscaped;
}
var end = template.indexOf(closeTag, i);
if (end === -1) {
throw debug(new Error('Tag "' + openTag + '" was not closed properly'), template, line, options.file);
}
var source = template.substring(i, end);
if (callback) {
callback(source);
}
// Maintain line count for \n in source.
var n = 0;
while (~(n = source.indexOf("\n", n))) {
line++;
n++;
}
i = end + closeTag.length - 1;
openTag = nextOpenTag;
closeTag = nextCloseTag;
} else {
c = template.substr(i, 1);
switch (c) {
case '"':
case "\\":
nonSpace = true;
code.push("\\" + c);
break;
case "\r":
// Ignore carriage returns.
break;
case "\n":
spaces.push(code.length);
code.push("\\n");
stripSpace(); // Check for whitespace on the current line.
line++;
break;
default:
if (isWhitespace(c)) {
spaces.push(code.length);
} else {
nonSpace = true;
}
code.push(c);
}
}
}
if (sectionStack.length != 0) {
throw debug(new Error('Section "' + sectionStack[sectionStack.length - 1].name + '" was not closed properly'), template, line, options.file);
}
// Clean up any whitespace from a closing {{tag}} that was at the end
// of the template without a trailing \n.
stripSpace();
code.push(
'";',
"\nreturn buffer;",
"\n} catch (e) { throw {error: e, line: line}; }"
);
// Ignore `buffer += "";` statements.
var body = code.join("").replace(/buffer \+= "";\n/g, "");
if (options.debug) {
if (typeof console != "undefined" && console.log) {
console.log(body);
} else if (typeof print === "function") {
print(body);
}
}
return body;
}
/**
* Used by `compile` to generate a reusable function for the given `template`.
*/
function _compile(template, options) {
var args = "view,partials,stack,lookup,escapeHTML,renderSection,render";
var body = parse(template, options);
var fn = new Function(args, body);
// This anonymous function wraps the generated function so we can do
// argument coercion, setup some variables, and handle any errors
// encountered while executing it.
return function (view, partials) {
partials = partials || {};
var stack = [view]; // context stack
try {
return fn(view, partials, stack, lookup, escapeHTML, renderSection, render);
} catch (e) {
throw debug(e.error, template, e.line, options.file);
}
};
}
// Cache of pre-compiled templates.
var _cache = {};
/**
* Clear the cache of compiled templates.
*/
function clearCache() {
_cache = {};
}
/**
* Compiles the given `template` into a reusable function using the given
* `options`. In addition to the options accepted by Mustache.parse,
* recognized options include the following:
*
* - cache Set `false` to bypass any pre-compiled version of the given
* template. Otherwise, a given `template` string will be cached
* the first time it is parsed
*/
function compile(template, options) {
options = options || {};
// Use a pre-compiled version from the cache if we have one.
if (options.cache !== false) {
if (!_cache[template]) {
_cache[template] = _compile(template, options);
}
return _cache[template];
}
return _compile(template, options);
}
/**
* High-level function that renders the given `template` using the given
* `view` and `partials`. If you need to use any of the template options (see
* `compile` above), you must compile in a separate step, and then call that
* compiled function.
*/
function render(template, view, partials) {
return compile(template)(view, partials);
}
})(Mustache);

View File

@ -1,56 +1,121 @@
$(function() { var modals = {
/* load and connect with aria instance */ err_connect: undefined,
var err_connect = $("#error_connect").modal('hide'); change_conf: undefined,
newDownload_modal: undefined
var log = $("#console"); };
log.append("connecting!!!<br>"); var server_conf = {
host: 'localhost',
port: 6800
};
var custom_aria2_connect = function() {
modals.err_connect.modal('hide');
modals.change_conf.modal('show');
};
var update_server_conf = function() {
server_conf.host = $('#input_host').val();
server_conf.port = $('#input_port').val();
update_ui();
};
var aria_syscall = function(conf) {
$.ajax({ $.ajax({
url: "http://localhost:6800/jsonrpc", url: 'http://' + server_conf.host + ':' + server_conf.port + '/jsonrpc',
timeout: 3000, timeout: 3000,
data: { data: {
jsonrpc: 2.0, jsonrpc: 2.0,
id: "webui", id: 'webui',
method: "aria2.getVersion" method: 'aria2.' + conf.func.toString(),
params: conf.params
}, },
success: function(data) { success: conf.sucess,
log.append(JSON.stringify(data) + "<br>"); error: conf.error,
dataType: 'jsonp',
jsonp: 'jsoncallback'
});
}
var log = $('#console');
var update_ui = function() {
modals.err_connect = $('#error_connect').modal('hide');
modals.change_conf = $('#change_conf').modal('hide');
modals.newDownload_modal = $('#newDownload_modal').modal('hide');
log.append('connecting!!!<br>');
aria_syscall({
func: 'getVersion',
sucess: function(data) {
log.append(JSON.stringify(data) + '<br>');
updateDownloads(); updateDownloads();
}, },
error: function() { error: function() {
err_connect.modal('show'); modals.err_connect.modal('show');
log.append("error connecting!!<br>"); log.append('error connecting!!<br>');
}, }
dataType: "jsonp",
jsonp: "jsoncallback"
}); });
};
$(function() {
update_ui();
$('#newDownload').click(function() {
modals.newDownload_modal.modal('show');
});
$('#addNewDownload').click(newDownload);
}); });
function updateDownloads() { /*function updateDownloads() {
updateDownloads(); updateDownloads();
updateWaiting(); updateWaiting();
updateStopDownloads(); updateStopDownloads();
}*/
function newDownload() {
var url = $('#newDownload_url').val();
aria_syscall({
func: 'addUri',
params: [["google.com"]],
sucess: function() {
update_ui();
}
});
alert(url);
} }
var d_files = []; var d_files = [];
function d_fill() { function d_fill() {
for(var i = 0; i < 10; i++) { for(var i = 0; i < 10; i++) {
addDownload({ addDownload({
name: 'final name:' + i,
gid: i, gid: i,
status: "active", status: 'active',
totalLength: (i + 15) * 20, totalLength: (i + 15) * 20,
completedLength: (i + 15) * 19; completedLength: (i + 15) * 19,
downloadSpeed: 200 + i downloadSpeed: 200 + i
}); });
} }
} }
function addDownload(conf) { function addDownload(conf) {
d_files.push(conf); d_files.push(conf);
var d_table = $("#d_table");
var d_table = $('#d_table');
var down = $('<tr></tr>');
down.append($('<td></td>').text(conf.name));
down.append($('<td></td>').text(conf.completedLength));
down.append($('<td></td>').text(conf.totalLength));
down.append($('<td></td>').text(conf.downloadSpeed));
console.log(down.html());
down.appendTo(d_table);
} }
function updateDownloads() { function updateDownloads() {
aria_syscall({
func: 'tellActive',
sucess: function(data) {
log.append("download Active are:" + JSON.stringify(data) + '<br>');
},
error: function() {
modals.err_connect.modal('show');
log.append('error connecting!!<br>');
}
});
d_fill(); d_fill();
var d_table = $("#d_table");
} }
function updateWaiting() { function updateWaiting() {