summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorroot2014-12-04 17:10:49 +0100
committerroot2014-12-04 17:10:49 +0100
commitbf3847219714d71e59bfa04569089ab52f852960 (patch)
tree1eaa8255ea1a522c16f7267cf3639bb1681279c9
parentbbe481a7fa159db107c7005f8b024bf4657c0bd6 (diff)
downloadtools.iamfabulous.de-bf3847219714d71e59bfa04569089ab52f852960.tar.gz
Finished tool for checking downtime
-rw-r--r--down/ajax.php (renamed from isup/ajax.php)20
-rw-r--r--down/http.php (renamed from isup/http.php)0
-rw-r--r--down/index.php18
-rw-r--r--down/ping.php (renamed from isup/ping.php)0
-rw-r--r--down/view/templ-index.php117
-rw-r--r--down/view/templ-noscript.php87
-rw-r--r--isup/index.php25
-rw-r--r--tools/footer.php2
-rw-r--r--tools/navbar.php3
-rw-r--r--tools/static/sweet-alert.css564
-rwxr-xr-xtools/static/sweet-alert.js711
-rw-r--r--tools/static/sweet-alert.min.js1
-rw-r--r--tools/style.css2
13 files changed, 1519 insertions, 31 deletions
diff --git a/isup/ajax.php b/down/ajax.php
index 3e21a20..63a63d1 100644
--- a/isup/ajax.php
+++ b/down/ajax.php
@@ -20,13 +20,19 @@ function ipv6($host){
return false;
}
+header("Content-Type: application/json");
+// response
+$r = array("host" => $_REQUEST["url"]);
+
switch($_REQUEST["action"]){
case("ping"):
require 'ping.php';
if ( ping( sanitizeHost($_REQUEST["url"]), ipv6($_REQUEST["url"]) ) ){
- echo "up";
+ $r["status"] = "Looks like it's up from here.";
+ $r["data"] = 1;
} else {
- echo "down";
+ $r["status"] = "Seems down. :(";
+ $r["data"] = 0;
}
break;
case("http"):
@@ -35,14 +41,20 @@ switch($_REQUEST["action"]){
echo "not valid";
} else {
if( isUp($_REQUEST["url"]) ){
- echo "up";
+ $r["status"] = "Looks like it's up from here.";
+ $r["data"] = 1;
} else {
- echo "down";
+ $r["status"] = "Seems down. :(";
+ $r["data"] = 0;
}
}
break;
default:
header($_SERVER["SERVER_PROTOCOL"] . " 400 Bad Request");
header("X-Debug: Please define a valid action.");
+ $r["status"] = "not valid";
+ $r["data"] = 0;
break;
}
+
+echo json_encode($r);
diff --git a/isup/http.php b/down/http.php
index 9973cb4..9973cb4 100644
--- a/isup/http.php
+++ b/down/http.php
diff --git a/down/index.php b/down/index.php
new file mode 100644
index 0000000..e71e76a
--- /dev/null
+++ b/down/index.php
@@ -0,0 +1,18 @@
+<?php
+
+if( !isset($_REQUEST["action"]) || $_REQUEST["action"] == "" ){
+ require 'view/templ-index.php';
+} else {
+ if ( isset($_SERVER["HTTP_X_REQUESTED_WITH"]) && strtolower($_SERVER["HTTP_X_REQUESTED_WITH"]) == "xmlhttprequest"){
+ require 'ajax.php';
+ } else {
+ ob_start();
+ require 'ajax.php';
+ $json = json_decode(ob_get_contents(), true);
+ ob_end_clean();
+ header("Content-Type: text/html; charset=UTF-8");
+
+ require 'view/templ-noscript.php';
+
+ }
+}
diff --git a/isup/ping.php b/down/ping.php
index 4c1bea7..4c1bea7 100644
--- a/isup/ping.php
+++ b/down/ping.php
diff --git a/down/view/templ-index.php b/down/view/templ-index.php
new file mode 100644
index 0000000..cc554e1
--- /dev/null
+++ b/down/view/templ-index.php
@@ -0,0 +1,117 @@
+<!doctype html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
+ <link href="//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
+ <link rel="stylesheet" href="../tools/static/sweet-alert.css">
+ <style>
+ <?php echo file_get_contents("../tools/style.css"); ?>
+ </style>
+ <noscript><style>.navbar{margin-bottom:0;}</style></noscript>
+ <title>Is it down? | iamfabulous.de</title>
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <link rel='shortcut icon' href='../tools/favicon.ico' type='image/x-icon'>
+</head>
+<body>
+ <?php require("../tools/navbar.php"); ?>
+<div class="container">
+ <div class="text-center">
+ <div class="row">
+
+ <form id="theform" class="form-horizontal">
+ <fieldset>
+
+ <!-- Form Name -->
+ <legend>
+ <h1>Uptime is the game</h1>
+ <h4>Is your favourite website down?</h4>
+ </legend>
+
+ <!-- Text input-->
+ <div class="form-group">
+ <label class="col-md-4 control-label" for="url">Check if up: </label>
+ <div class="col-md-4">
+ <?php if ( isset($_REQUEST["url"]) && $_REQUEST["url"] != "" ){
+ ?>
+ <input id="url" name="url" placeholder="kernel.org" class="form-control input-md" required="" type="text" <?php echo 'value="'.htmlentities($_REQUEST["url"]) . '"'; ?> autofocus>
+ <?php
+ } else {
+ ?>
+ <input id="url" name="url" placeholder="kernel.org" class="form-control input-md" required="" type="text" autofocus>
+ <?php
+ }
+ ?>
+ </div>
+ </div>
+
+ <!-- Multiple Radios (inline) -->
+ <div class="form-group">
+ <label class="col-md-4 control-label" for="action">Check Type:</label>
+ <div class="col-md-4 text-left">
+ <label class="radio-inline" for="action-0">
+ <input name="action" id="action-0" value="ping" checked="checked" type="radio">
+ Ping
+ </label>
+ <label class="radio-inline" for="action-1">
+ <input name="action" id="action-1" value="http" type="radio">
+ HTTP
+ </label>
+ </div>
+ </div>
+
+ <!-- Button -->
+ <div class="form-group">
+ <label class="col-md-4 control-label" for="submit"></label>
+ <div class="col-md-4">
+ <button type="submit" id="submit" name="" value="" class="btn btn-success">Check it</button>
+ </div>
+ </div>
+
+ </fieldset>
+ </form>
+
+ </div>
+ </div>
+</div>
+
+ <?php require("../tools/footer.php"); ?>
+ <script>
+ window.onload = function(){
+
+ $("#theform").submit( function(e){
+
+ $.ajax({
+ url: "",
+ data: $("#theform").serialize(),
+ dataType: "json",
+ type: "GET",
+
+ success: function( response ){
+
+ if ( response.data == 1 ) {
+ var type = "success";
+ var button= "btn-success";
+ } else {
+ var type= "error";
+ var button= "btn-danger";
+ }
+ swal({
+ title: response.host,
+ text: response.status,
+ type: type,
+ confirmButtonClass: button
+ });
+
+ $("#url").val('');
+ },
+ });
+
+ e.preventDefault();
+ });
+
+ $(".fa-spinner").addClass("fa-spin");
+
+ };
+ </script>
+ <script defer src="../tools/static/sweet-alert.js"></script>
diff --git a/down/view/templ-noscript.php b/down/view/templ-noscript.php
new file mode 100644
index 0000000..d15b665
--- /dev/null
+++ b/down/view/templ-noscript.php
@@ -0,0 +1,87 @@
+<!doctype html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
+ <link href="//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
+ <style>
+ <?php echo file_get_contents("../tools/style.css"); ?>
+ </style>
+ <noscript><style>.navbar{margin-bottom:0;}</style></noscript>
+ <title>Is it down? | iamfabulous.de</title>
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <link rel='shortcut icon' href='../tools/favicon.ico' type='image/x-icon'>
+</head>
+<body>
+ <?php require("../tools/navbar.php"); ?>
+<div class="container">
+ <div class="text-center">
+ <div class="row">
+
+
+ <h1>Uptime is the game</h1>
+ <h4>Is your favourite website down?</h4>
+ <hr>
+
+ <?php
+ if($json["data"] == 1){
+ ?>
+ <div class="alert alert-success" role="alert">
+ <?php
+ } else {
+ ?>
+ <div class="alert alert-danger" role="alert">
+ <?php
+ }
+ ?>
+ <h1><?php echo htmlentities($json["host"]); ?></h1>
+ <h4><?php echo htmlentities($json["status"]); ?></h4>
+ </div>
+
+ <form id="theform" class="form-horizontal">
+ <fieldset>
+
+ <!-- Form Name -->
+ <legend>
+ <h1>Check another one</h1>
+ </legend>
+
+ <!-- Text input-->
+ <div class="form-group">
+ <label class="col-md-4 control-label" for="url">Check if up: </label>
+ <div class="col-md-4">
+ <input id="url" name="url" placeholder="kernel.org" class="form-control input-md" required="" type="text" autofocus>
+ </div>
+ </div>
+
+ <!-- Multiple Radios (inline) -->
+ <div class="form-group">
+ <label class="col-md-4 control-label" for="action">Check Type:</label>
+ <div class="col-md-4 text-left">
+ <label class="radio-inline" for="action-0">
+ <input name="action" id="action-0" value="ping" checked="checked" type="radio">
+ Ping
+ </label>
+ <label class="radio-inline" for="action-1">
+ <input name="action" id="action-1" value="http" type="radio">
+ HTTP
+ </label>
+ </div>
+ </div>
+
+ <!-- Button -->
+ <div class="form-group">
+ <label class="col-md-4 control-label" for="submit"></label>
+ <div class="col-md-4">
+ <button type="submit" id="submit" name="" value="" class="btn btn-success">Check it</button>
+ </div>
+ </div>
+
+ </fieldset>
+ </form>
+
+ </div>
+ </div>
+</div>
+
+ <?php require("../tools/footer.php"); ?>
diff --git a/isup/index.php b/isup/index.php
deleted file mode 100644
index 9c856c8..0000000
--- a/isup/index.php
+++ /dev/null
@@ -1,25 +0,0 @@
-<!doctype html>
-<html>
-<head>
- <meta charset="utf-8">
- <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
- <link href="//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
- <style>
- <?php echo file_get_contents("../tools/style.css"); ?>
- </style>
- <noscript><style>.navbar{margin-bottom:0;}</style></noscript>
- <title>IsUP | iamfabulous.de</title>
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <link rel='shortcut icon' href='../tools/favicon.ico' type='image/x-icon'>
-</head>
-<body>
- <?php require("../tools/navbar.php"); ?>
-<div class="container">
- <div class="text-center">
- <div class="row">
-
- </div>
- </div>
-</div>
-
- <?php require("../tools/footer.php"); ?>
diff --git a/tools/footer.php b/tools/footer.php
index 81978a4..fb8df47 100644
--- a/tools/footer.php
+++ b/tools/footer.php
@@ -25,5 +25,5 @@
}
addClass("<?php echo trim(str_replace("/index.php", "", $_SERVER["PHP_SELF"] ), "/");?>", "actives");
</script>
- <script src="//code.jquery.com/jquery-1.11.1.min.js" defer=""></script>
+ <script src="//code.jquery.com/jquery-1.11.1.min.js" defer></script>
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js" defer=""></script>
diff --git a/tools/navbar.php b/tools/navbar.php
index d0b9108..1e483e4 100644
--- a/tools/navbar.php
+++ b/tools/navbar.php
@@ -19,6 +19,9 @@
<li id="ifconfig">
<a href="<?php echo __domain_; ?>/ifconfig/" title="Simple IP API"><span class="glyphicon glyphicon-transfer"></span> ifconfig</a>
</li>
+ <li id="down">
+ <a href="<?php echo __domain_; ?>/down/" title="Check if your favourite website is up or not!"><span class="fa fa-spinner"></span> Up Or Down?</a>
+ </li>
</ul>
</div>
</div>
diff --git a/tools/static/sweet-alert.css b/tools/static/sweet-alert.css
new file mode 100644
index 0000000..7075866
--- /dev/null
+++ b/tools/static/sweet-alert.css
@@ -0,0 +1,564 @@
+@-webkit-keyframes showSweetAlert {
+ 0% {
+ transform: scale(0.7);
+ -webkit-transform: scale(0.7);
+ }
+ 45% {
+ transform: scale(1.05);
+ -webkit-transform: scale(1.05);
+ }
+ 80% {
+ transform: scale(0.95);
+ -webkit-tranform: scale(0.95);
+ }
+ 100% {
+ transform: scale(1);
+ -webkit-transform: scale(1);
+ }
+}
+@keyframes showSweetAlert {
+ 0% {
+ transform: scale(0.7);
+ -webkit-transform: scale(0.7);
+ }
+ 45% {
+ transform: scale(1.05);
+ -webkit-transform: scale(1.05);
+ }
+ 80% {
+ transform: scale(0.95);
+ -webkit-tranform: scale(0.95);
+ }
+ 100% {
+ transform: scale(1);
+ -webkit-transform: scale(1);
+ }
+}
+@-webkit-keyframes hideSweetAlert {
+ 0% {
+ transform: scale(1);
+ -webkit-transform: scale(1);
+ }
+ 100% {
+ transform: scale(0.5);
+ -webkit-transform: scale(0.5);
+ }
+}
+@keyframes hideSweetAlert {
+ 0% {
+ transform: scale(1);
+ -webkit-transform: scale(1);
+ }
+ 100% {
+ transform: scale(0.5);
+ -webkit-transform: scale(0.5);
+ }
+}
+.showSweetAlert {
+ -webkit-animation: showSweetAlert 0.3s;
+ animation: showSweetAlert 0.3s;
+}
+.hideSweetAlert {
+ -webkit-animation: hideSweetAlert 0.2s;
+ animation: hideSweetAlert 0.2s;
+}
+@-webkit-keyframes animateSuccessTip {
+ 0% {
+ width: 0;
+ left: 1px;
+ top: 19px;
+ }
+ 54% {
+ width: 0;
+ left: 1px;
+ top: 19px;
+ }
+ 70% {
+ width: 50px;
+ left: -8px;
+ top: 37px;
+ }
+ 84% {
+ width: 17px;
+ left: 21px;
+ top: 48px;
+ }
+ 100% {
+ width: 25px;
+ left: 14px;
+ top: 45px;
+ }
+}
+@keyframes animateSuccessTip {
+ 0% {
+ width: 0;
+ left: 1px;
+ top: 19px;
+ }
+ 54% {
+ width: 0;
+ left: 1px;
+ top: 19px;
+ }
+ 70% {
+ width: 50px;
+ left: -8px;
+ top: 37px;
+ }
+ 84% {
+ width: 17px;
+ left: 21px;
+ top: 48px;
+ }
+ 100% {
+ width: 25px;
+ left: 14px;
+ top: 45px;
+ }
+}
+@-webkit-keyframes animateSuccessLong {
+ 0% {
+ width: 0;
+ right: 46px;
+ top: 54px;
+ }
+ 65% {
+ width: 0;
+ right: 46px;
+ top: 54px;
+ }
+ 84% {
+ width: 55px;
+ right: 0px;
+ top: 35px;
+ }
+ 100% {
+ width: 47px;
+ right: 8px;
+ top: 38px;
+ }
+}
+@keyframes animateSuccessLong {
+ 0% {
+ width: 0;
+ right: 46px;
+ top: 54px;
+ }
+ 65% {
+ width: 0;
+ right: 46px;
+ top: 54px;
+ }
+ 84% {
+ width: 55px;
+ right: 0px;
+ top: 35px;
+ }
+ 100% {
+ width: 47px;
+ right: 8px;
+ top: 38px;
+ }
+}
+@-webkit-keyframes rotatePlaceholder {
+ 0% {
+ transform: rotate(-45deg);
+ -webkit-transform: rotate(-45deg);
+ }
+ 5% {
+ transform: rotate(-45deg);
+ -webkit-transform: rotate(-45deg);
+ }
+ 12% {
+ transform: rotate(-405deg);
+ -webkit-transform: rotate(-405deg);
+ }
+ 100% {
+ transform: rotate(-405deg);
+ -webkit-transform: rotate(-405deg);
+ }
+}
+@keyframes rotatePlaceholder {
+ 0% {
+ transform: rotate(-45deg);
+ -webkit-transform: rotate(-45deg);
+ }
+ 5% {
+ transform: rotate(-45deg);
+ -webkit-transform: rotate(-45deg);
+ }
+ 12% {
+ transform: rotate(-405deg);
+ -webkit-transform: rotate(-405deg);
+ }
+ 100% {
+ transform: rotate(-405deg);
+ -webkit-transform: rotate(-405deg);
+ }
+}
+.animateSuccessTip {
+ -webkit-animation: animateSuccessTip 0.75s;
+ animation: animateSuccessTip 0.75s;
+}
+.animateSuccessLong {
+ -webkit-animation: animateSuccessLong 0.75s;
+ animation: animateSuccessLong 0.75s;
+}
+.icon.success.animate::after {
+ -webkit-animation: rotatePlaceholder 4.25s ease-in;
+ animation: rotatePlaceholder 4.25s ease-in;
+}
+@-webkit-keyframes animateErrorIcon {
+ 0% {
+ transform: rotateX(100deg);
+ -webkit-transform: rotateX(100deg);
+ opacity: 0;
+ }
+ 100% {
+ transform: rotateX(0deg);
+ -webkit-transform: rotateX(0deg);
+ opacity: 1;
+ }
+}
+@keyframes animateErrorIcon {
+ 0% {
+ transform: rotateX(100deg);
+ -webkit-transform: rotateX(100deg);
+ opacity: 0;
+ }
+ 100% {
+ transform: rotateX(0deg);
+ -webkit-transform: rotateX(0deg);
+ opacity: 1;
+ }
+}
+.animateErrorIcon {
+ -webkit-animation: animateErrorIcon 0.5s;
+ animation: animateErrorIcon 0.5s;
+}
+@-webkit-keyframes animateXMark {
+ 0% {
+ transform: scale(0.4);
+ -webkit-transform: scale(0.4);
+ margin-top: 26px;
+ opacity: 0;
+ }
+ 50% {
+ transform: scale(0.4);
+ -webkit-transform: scale(0.4);
+ margin-top: 26px;
+ opacity: 0;
+ }
+ 80% {
+ transform: scale(1.15);
+ -webkit-transform: scale(1.15);
+ margin-top: -6px;
+ }
+ 100% {
+ transform: scale(1);
+ -webkit-transform: scale(1);
+ margin-top: 0;
+ opacity: 1;
+ }
+}
+@keyframes animateXMark {
+ 0% {
+ transform: scale(0.4);
+ -webkit-transform: scale(0.4);
+ margin-top: 26px;
+ opacity: 0;
+ }
+ 50% {
+ transform: scale(0.4);
+ -webkit-transform: scale(0.4);
+ margin-top: 26px;
+ opacity: 0;
+ }
+ 80% {
+ transform: scale(1.15);
+ -webkit-transform: scale(1.15);
+ margin-top: -6px;
+ }
+ 100% {
+ transform: scale(1);
+ -webkit-transform: scale(1);
+ margin-top: 0;
+ opacity: 1;
+ }
+}
+.animateXMark {
+ -webkit-animation: animateXMark 0.5s;
+ animation: animateXMark 0.5s;
+}
+@-webkit-keyframes pulseWarning {
+ 0% {
+ border-color: #F8D486;
+ }
+ 100% {
+ border-color: #F8BB86;
+ }
+}
+@keyframes pulseWarning {
+ 0% {
+ border-color: #F8D486;
+ }
+ 100% {
+ border-color: #F8BB86;
+ }
+}
+.pulseWarning {
+ -webkit-animation: pulseWarning 0.75s infinite alternate;
+ animation: pulseWarning 0.75s infinite alternate;
+}
+@-webkit-keyframes pulseWarningIns {
+ 0% {
+ background-color: #F8D486;
+ }
+ 100% {
+ background-color: #F8BB86;
+ }
+}
+@keyframes pulseWarningIns {
+ 0% {
+ background-color: #F8D486;
+ }
+ 100% {
+ background-color: #F8BB86;
+ }
+}
+.pulseWarningIns {
+ -webkit-animation: pulseWarningIns 0.75s infinite alternate;
+ animation: pulseWarningIns 0.75s infinite alternate;
+}
+.sweet-overlay {
+ background-color: rgba(0, 0, 0, 0.4);
+ position: fixed;
+ left: 0;
+ right: 0;
+ top: 0;
+ bottom: 0;
+ display: none;
+ z-index: 1040;
+}
+.sweet-alert {
+ background-color: #ffffff;
+ width: 478px;
+ padding: 17px;
+ border-radius: 5px;
+ text-align: center;
+ position: fixed;
+ left: 50%;
+ top: 50%;
+ margin-left: -256px;
+ margin-top: -200px;
+ overflow: hidden;
+ display: none;
+ z-index: 2000;
+}
+@media all and (max-width: 767px) {
+ .sweet-alert {
+ width: auto;
+ margin-left: 0;
+ margin-right: 0;
+ left: 15px;
+ right: 15px;
+ }
+}
+.sweet-alert .icon {
+ width: 80px;
+ height: 80px;
+ border: 4px solid gray;
+ border-radius: 50%;
+ margin: 20px auto;
+ position: relative;
+ box-sizing: content-box;
+}
+.sweet-alert .icon.error {
+ border-color: #d43f3a;
+}
+.sweet-alert .icon.error .x-mark {
+ position: relative;
+ display: block;
+}
+.sweet-alert .icon.error .line {
+ position: absolute;
+ height: 5px;
+ width: 47px;
+ background-color: #d9534f;
+ display: block;
+ top: 37px;
+ border-radius: 2px;
+}
+.sweet-alert .icon.error .line.left {
+ -webkit-transform: rotate(45deg);
+ transform: rotate(45deg);
+ left: 17px;
+}
+.sweet-alert .icon.error .line.right {
+ -webkit-transform: rotate(-45deg);
+ transform: rotate(-45deg);
+ right: 16px;
+}
+.sweet-alert .icon.warning {
+ border-color: #eea236;
+}
+.sweet-alert .icon.warning .body {
+ position: absolute;
+ width: 5px;
+ height: 47px;
+ left: 50%;
+ top: 10px;
+ border-radius: 2px;
+ margin-left: -2px;
+ background-color: #f0ad4e;
+}
+.sweet-alert .icon.warning .dot {
+ position: absolute;
+ width: 7px;
+ height: 7px;
+ border-radius: 50%;
+ margin-left: -3px;
+ left: 50%;
+ bottom: 10px;
+ background-color: #f0ad4e;
+}
+.sweet-alert .icon.info {
+ border-color: #46b8da;
+}
+.sweet-alert .icon.info::before {
+ content: "";
+ position: absolute;
+ width: 5px;
+ height: 29px;
+ left: 50%;
+ bottom: 17px;
+ border-radius: 2px;
+ margin-left: -2px;
+ background-color: #5bc0de;
+}
+.sweet-alert .icon.info::after {
+ content: "";
+ position: absolute;
+ width: 7px;
+ height: 7px;
+ border-radius: 50%;
+ margin-left: -3px;
+ top: 19px;
+ background-color: #5bc0de;
+}
+.sweet-alert .icon.success {
+ border-color: #4cae4c;
+}
+.sweet-alert .icon.success::before,
+.sweet-alert .icon.success::after {
+ content: '';
+ border-radius: 50%;
+ position: absolute;
+ width: 60px;
+ height: 120px;
+ background: white;
+ -webkit-transform: rotate(45deg);
+ transform: rotate(45deg);
+}
+.sweet-alert .icon.success::before {
+ border-radius: 120px 0 0 120px;
+ top: -7px;
+ left: -33px;
+ -webkit-transform: rotate(-45deg);
+ transform: rotate(-45deg);
+ -webkit-transform-origin: 60px 60px;
+ transform-origin: 60px 60px;
+}
+.sweet-alert .icon.success::after {
+ border-radius: 0 120px 120px 0;
+ top: -11px;
+ left: 30px;
+ -webkit-transform: rotate(-45deg);
+ transform: rotate(-45deg);
+ -webkit-transform-origin: 0px 60px;
+ transform-origin: 0px 60px;
+}
+.sweet-alert .icon.success .placeholder {
+ width: 80px;
+ height: 80px;
+ border: 4px solid rgba(92, 184, 92, 0.2);
+ border-radius: 50%;
+ box-sizing: content-box;
+ position: absolute;
+ left: -4px;
+ top: -4px;
+ z-index: 2;
+}
+.sweet-alert .icon.success .fix {
+ width: 5px;
+ height: 90px;
+ background-color: #ffffff;
+ position: absolute;
+ left: 28px;
+ top: 8px;
+ z-index: 1;
+ -webkit-transform: rotate(-45deg);
+ transform: rotate(-45deg);
+}
+.sweet-alert .icon.success .line {
+ height: 5px;
+ background-color: #5cb85c;
+ display: block;
+ border-radius: 2px;
+ position: absolute;
+ z-index: 2;
+}
+.sweet-alert .icon.success .line.tip {
+ width: 25px;
+ left: 14px;
+ top: 46px;
+ -webkit-transform: rotate(45deg);
+ transform: rotate(45deg);
+}
+.sweet-alert .icon.success .line.long {
+ width: 47px;
+ right: 8px;
+ top: 38px;
+ -webkit-transform: rotate(-45deg);
+ transform: rotate(-45deg);
+}
+.sweet-alert .icon.custom {
+ background-size: contain;
+ border-radius: 0;
+ border: none;
+ background-position: center center;
+ background-repeat: no-repeat;
+}
+.sweet-alert .btn-default:focus {
+ border-color: #cccccc;
+ outline: 0;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(204, 204, 204, 0.6);
+ box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(204, 204, 204, 0.6);
+}
+.sweet-alert .btn-success:focus {
+ border-color: #4cae4c;
+ outline: 0;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(76, 174, 76, 0.6);
+ box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(76, 174, 76, 0.6);
+}
+.sweet-alert .btn-info:focus {
+ border-color: #46b8da;
+ outline: 0;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(70, 184, 218, 0.6);
+ box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(70, 184, 218, 0.6);
+}
+.sweet-alert .btn-danger:focus {
+ border-color: #d43f3a;
+ outline: 0;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(212, 63, 58, 0.6);
+ box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(212, 63, 58, 0.6);
+}
+.sweet-alert .btn-warning:focus {
+ border-color: #eea236;
+ outline: 0;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(238, 162, 54, 0.6);
+ box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(238, 162, 54, 0.6);
+}
+.sweet-alert button::-moz-focus-inner {
+ border: 0;
+}
diff --git a/tools/static/sweet-alert.js b/tools/static/sweet-alert.js
new file mode 100755
index 0000000..ee598d5
--- /dev/null
+++ b/tools/static/sweet-alert.js
@@ -0,0 +1,711 @@
+// SweetAlert
+// 2014 (c) - Tristan Edwards
+// github.com/t4t5/sweetalert
+(function(window, document) {
+
+ var modalClass = '.sweet-alert',
+ overlayClass = '.sweet-overlay',
+ alertTypes = ['error', 'warning', 'info', 'success'],
+ defaultParams = {
+ title: '',
+ text: '',
+ type: null,
+ allowOutsideClick: false,
+ showCancelButton: false,
+ closeOnConfirm: true,
+ closeOnCancel: true,
+ confirmButtonText: 'OK',
+ confirmButtonClass: 'btn-primary',
+ cancelButtonText: 'Cancel',
+ cancelButtonClass: 'btn-default',
+ imageUrl: null,
+ imageSize: null,
+ timer: null
+ };
+
+
+ /*
+ * Manipulate DOM
+ */
+
+ var getModal = function() {
+ return document.querySelector(modalClass);
+ },
+ getOverlay = function() {
+ return document.querySelector(overlayClass);
+ },
+ hasClass = function(elem, className) {
+ return new RegExp(' ' + className + ' ').test(' ' + elem.className + ' ');
+ },
+ addClass = function(elem, className) {
+ if (!hasClass(elem, className)) {
+ elem.className += ' ' + className;
+ }
+ },
+ removeClass = function(elem, className) {
+ var newClass = ' ' + elem.className.replace(/[\t\r\n]/g, ' ') + ' ';
+ if (hasClass(elem, className)) {
+ while (newClass.indexOf(' ' + className + ' ') >= 0) {
+ newClass = newClass.replace(' ' + className + ' ', ' ');
+ }
+ elem.className = newClass.replace(/^\s+|\s+$/g, '');
+ }
+ },
+ escapeHtml = function(str) {
+ var div = document.createElement('div');
+ div.appendChild(document.createTextNode(str));
+ return div.innerHTML;
+ },
+ _show = function(elem) {
+ elem.style.opacity = '';
+ elem.style.display = 'block';
+ },
+ show = function(elems) {
+ if (elems && !elems.length) {
+ return _show(elems);
+ }
+ for (var i = 0; i < elems.length; ++i) {
+ _show(elems[i]);
+ }
+ },
+ _hide = function(elem) {
+ elem.style.opacity = '';
+ elem.style.display = 'none';
+ },
+ hide = function(elems) {
+ if (elems && !elems.length) {
+ return _hide(elems);
+ }
+ for (var i = 0; i < elems.length; ++i) {
+ _hide(elems[i]);
+ }
+ },
+ isDescendant = function(parent, child) {
+ var node = child.parentNode;
+ while (node !== null) {
+ if (node === parent) {
+ return true;
+ }
+ node = node.parentNode;
+ }
+ return false;
+ },
+ getTopMargin = function(elem) {
+ elem.style.left = '-9999px';
+ elem.style.display = 'block';
+
+ var height = elem.clientHeight;
+ var padding = parseInt(getComputedStyle(elem).getPropertyValue('padding'), 10);
+
+ elem.style.left = '';
+ elem.style.display = 'none';
+ return ('-' + parseInt(height / 2 + padding) + 'px');
+ },
+ fadeIn = function(elem, interval) {
+ if(+elem.style.opacity < 1) {
+ interval = interval || 16;
+ elem.style.opacity = 0;
+ elem.style.display = 'block';
+ var last = +new Date();
+ var tick = function() {
+ elem.style.opacity = +elem.style.opacity + (new Date() - last) / 100;
+ last = +new Date();
+
+ if (+elem.style.opacity < 1) {
+ setTimeout(tick, interval);
+ }
+ };
+ tick();
+ }
+ },
+ fadeOut = function(elem, interval) {
+ interval = interval || 16;
+ elem.style.opacity = 1;
+ var last = +new Date();
+ var tick = function() {
+ elem.style.opacity = +elem.style.opacity - (new Date() - last) / 100;
+ last = +new Date();
+
+ if (+elem.style.opacity > 0) {
+ setTimeout(tick, interval);
+ } else {
+ elem.style.display = 'none';
+ }
+ };
+ tick();
+ },
+ fireClick = function(node) {
+ // Taken from http://www.nonobtrusive.com/2011/11/29/programatically-fire-crossbrowser-click-event-with-javascript/
+ // Then fixed for today's Chrome browser.
+ if (MouseEvent) {
+ // Up-to-date approach
+ var mevt = new MouseEvent('click', {
+ view: window,
+ bubbles: false,
+ cancelable: true
+ });
+ node.dispatchEvent(mevt);
+ } else if ( document.createEvent ) {
+ // Fallback
+ var evt = document.createEvent('MouseEvents');
+ evt.initEvent('click', false, false);
+ node.dispatchEvent(evt);
+ } else if( document.createEventObject ) {
+ node.fireEvent('onclick') ;
+ } else if (typeof node.onclick === 'function' ) {
+ node.onclick();
+ }
+ },
+ stopEventPropagation = function(e) {
+ // In particular, make sure the space bar doesn't scroll the main window.
+ if (typeof e.stopPropagation === 'function') {
+ e.stopPropagation();
+ e.preventDefault();
+ } else if (window.event && window.event.hasOwnProperty('cancelBubble')) {
+ window.event.cancelBubble = true;
+ }
+ };
+
+ // Remember state in cases where opening and handling a modal will fiddle with it.
+ var previousActiveElement,
+ previousDocumentClick,
+ previousWindowKeyDown,
+ lastFocusedButton;
+
+ /*
+ * Add modal + overlay to DOM
+ */
+
+ window.sweetAlertInitialize = function() {
+ var sweetHTML = '<div class="sweet-overlay" tabIndex="-1"></div><div class="sweet-alert" tabIndex="-1"><div class="icon error"><span class="x-mark"><span class="line left"></span><span class="line right"></span></span></div><div class="icon warning"> <span class="body"></span> <span class="dot"></span> </div> <div class="icon info"></div> <div class="icon success"> <span class="line tip"></span> <span class="line long"></span> <div class="placeholder"></div> <div class="fix"></div> </div> <div class="icon custom"></div> <h2>Title</h2><p class="lead text-muted">Text</p><p><button class="cancel btn btn-lg" tabIndex="2">Cancel</button> <button class="confirm btn btn-lg" tabIndex="1">OK</button></p></div>',
+ sweetWrap = document.createElement('div');
+
+ sweetWrap.innerHTML = sweetHTML;
+
+ // For readability: check sweet-alert.html
+ document.body.appendChild(sweetWrap);
+
+ // For development use only!
+ /*jQuery.ajax({
+ url: '../lib/sweet-alert.html', // Change path depending on file location
+ dataType: 'html'
+ })
+ .done(function(html) {
+ jQuery('body').append(html);
+ });*/
+ }
+
+ /*
+ * Global sweetAlert function
+ */
+
+ window.sweetAlert = window.swal = function() {
+ if (arguments[0] === undefined) {
+ window.console.error('sweetAlert expects at least 1 attribute!');
+ return false;
+ }
+
+ var params = extend({}, defaultParams);
+
+ switch (typeof arguments[0]) {
+
+ case 'string':
+ params.title = arguments[0];
+ params.text = arguments[1] || '';
+ params.type = arguments[2] || '';
+
+ break;
+
+ case 'object':
+ if (arguments[0].title === undefined) {
+ window.console.error('Missing "title" argument!');
+ return false;
+ }
+
+ params.title = arguments[0].title;
+ params.text = arguments[0].text || defaultParams.text;
+ params.type = arguments[0].type || defaultParams.type;
+ params.allowOutsideClick = arguments[0].allowOutsideClick || defaultParams.allowOutsideClick;
+ params.showCancelButton = arguments[0].showCancelButton !== undefined ? arguments[0].showCancelButton : defaultParams.showCancelButton;
+ params.closeOnConfirm = arguments[0].closeOnConfirm !== undefined ? arguments[0].closeOnConfirm : defaultParams.closeOnConfirm;
+ params.closeOnCancel = arguments[0].closeOnCancel !== undefined ? arguments[0].closeOnCancel : defaultParams.closeOnCancel;
+ params.timer = arguments[0].timer || defaultParams.timer;
+
+ // Show "Confirm" instead of "OK" if cancel button is visible
+ params.confirmButtonText = (defaultParams.showCancelButton) ? 'Confirm' : defaultParams.confirmButtonText;
+ params.confirmButtonText = arguments[0].confirmButtonText || defaultParams.confirmButtonText;
+ params.confirmButtonClass = arguments[0].confirmButtonClass || defaultParams.confirmButtonClass;
+ params.cancelButtonText = arguments[0].cancelButtonText || defaultParams.cancelButtonText;
+ params.cancelButtonClass = arguments[0].cancelButtonClass || defaultParams.cancelButtonClass;
+ params.imageUrl = arguments[0].imageUrl || defaultParams.imageUrl;
+ params.imageSize = arguments[0].imageSize || defaultParams.imageSize;
+ params.doneFunction = arguments[1] || null;
+
+ break;
+
+ default:
+ window.console.error('Unexpected type of argument! Expected "string" or "object", got ' + typeof arguments[0]);
+ return false;
+
+ }
+
+ setParameters(params);
+ fixVerticalPosition();
+ openModal();
+
+
+ // Modal interactions
+ var modal = getModal();
+
+ // Mouse interactions
+ var onButtonEvent = function(e) {
+
+ var target = e.target || e.srcElement,
+ targetedConfirm = (target.className.indexOf('confirm') > -1),
+ modalIsVisible = hasClass(modal, 'visible'),
+ doneFunctionExists = (params.doneFunction && modal.getAttribute('data-has-done-function') === 'true');
+
+ switch (e.type) {
+ case ("click"):
+ if (targetedConfirm && doneFunctionExists && modalIsVisible) { // Clicked "confirm"
+
+ params.doneFunction(true);
+
+ if (params.closeOnConfirm) {
+ closeModal();
+ }
+ } else if (doneFunctionExists && modalIsVisible) { // Clicked "cancel"
+
+ // Check if callback function expects a parameter (to track cancel actions)
+ var functionAsStr = String(params.doneFunction).replace(/\s/g, '');
+ var functionHandlesCancel = functionAsStr.substring(0, 9) === "function(" && functionAsStr.substring(9, 10) !== ")";
+
+ if (functionHandlesCancel) {
+ params.doneFunction(false);
+ }
+
+ if (params.closeOnCancel) {
+ closeModal();
+ }
+ } else {
+ closeModal();
+ }
+
+ break;
+ }
+ };
+
+ var $buttons = modal.querySelectorAll('button');
+ for (var i = 0; i < $buttons.length; i++) {
+ $buttons[i].onclick = onButtonEvent;
+ }
+
+ // Remember the current document.onclick event.
+ previousDocumentClick = document.onclick;
+ document.onclick = function(e) {
+ var target = e.target || e.srcElement;
+
+ var clickedOnModal = (modal === target),
+ clickedOnModalChild = isDescendant(modal, e.target),
+ modalIsVisible = hasClass(modal, 'visible'),
+ outsideClickIsAllowed = modal.getAttribute('data-allow-ouside-click') === 'true';
+
+ if (!clickedOnModal && !clickedOnModalChild && modalIsVisible && outsideClickIsAllowed) {
+ closeModal();
+ }
+ };
+
+
+ // Keyboard interactions
+ var $okButton = modal.querySelector('button.confirm'),
+ $cancelButton = modal.querySelector('button.cancel'),
+ $modalButtons = modal.querySelectorAll('button:not([type=hidden])');
+
+
+ function handleKeyDown(e) {
+ var keyCode = e.keyCode || e.which;
+
+ if ([9,13,32,27].indexOf(keyCode) === -1) {
+ // Don't do work on keys we don't care about.
+ return;
+ }
+
+ var $targetElement = e.target || e.srcElement;
+
+ var btnIndex = -1; // Find the button - note, this is a nodelist, not an array.
+ for (var i = 0; i < $modalButtons.length; i++) {
+ if ($targetElement === $modalButtons[i]) {
+ btnIndex = i;
+ break;
+ }
+ }
+
+ if (keyCode === 9) {
+ // TAB
+ if (btnIndex === -1) {
+ // No button focused. Jump to the confirm button.
+ $targetElement = $okButton;
+ } else {
+ // Cycle to the next button
+ if (btnIndex === $modalButtons.length - 1) {
+ $targetElement = $modalButtons[0];
+ } else {
+ $targetElement = $modalButtons[btnIndex + 1];
+ }
+ }
+
+ stopEventPropagation(e);
+ $targetElement.focus();
+
+ } else {
+ if (keyCode === 13 || keyCode === 32) {
+ if (btnIndex === -1) {
+ // ENTER/SPACE clicked outside of a button.
+ $targetElement = $okButton;
+ } else {
+ // Do nothing - let the browser handle it.
+ $targetElement = undefined;
+ }
+ } else if (keyCode === 27 && !($cancelButton.hidden || $cancelButton.style.display === 'none')) {
+ // ESC to cancel only if there's a cancel button displayed (like the alert() window).
+ $targetElement = $cancelButton;
+ } else {
+ // Fallback - let the browser handle it.
+ $targetElement = undefined;
+ }
+
+ if ($targetElement !== undefined) {
+ fireClick($targetElement, e);
+ }
+ }
+ }
+
+ previousWindowKeyDown = window.onkeydown;
+ window.onkeydown = handleKeyDown;
+
+ function handleOnBlur(e) {
+ var $targetElement = e.target || e.srcElement,
+ $focusElement = e.relatedTarget,
+ modalIsVisible = hasClass(modal, 'visible');
+
+ if (modalIsVisible) {
+ var btnIndex = -1; // Find the button - note, this is a nodelist, not an array.
+
+ if ($focusElement !== null) {
+ // If we picked something in the DOM to focus to, let's see if it was a button.
+ for (var i = 0; i < $modalButtons.length; i++) {
+ if ($focusElement === $modalButtons[i]) {
+ btnIndex = i;
+ break;
+ }
+ }
+
+ if (btnIndex === -1) {
+ // Something in the dom, but not a visible button. Focus back on the button.
+ $targetElement.focus();
+ }
+ } else {
+ // Exiting the DOM (e.g. clicked in the URL bar);
+ lastFocusedButton = $targetElement;
+ }
+ }
+ }
+
+ $okButton.onblur = handleOnBlur;
+ $cancelButton.onblur = handleOnBlur;
+
+ window.onfocus = function() {
+ // When the user has focused away and focused back from the whole window.
+ window.setTimeout(function() {
+ // Put in a timeout to jump out of the event sequence. Calling focus() in the event
+ // sequence confuses things.
+ if (lastFocusedButton !== undefined) {
+ lastFocusedButton.focus();
+ lastFocusedButton = undefined;
+ }
+ }, 0);
+ };
+ };
+
+ /**
+ * Set default params for each popup
+ * @param {Object} userParams
+ */
+ window.swal.setDefaults = function(userParams) {
+ if (!userParams) {
+ throw new Error('userParams is required');
+ }
+ if (typeof userParams !== 'object') {
+ throw new Error('userParams has to be a object');
+ }
+
+ extend(defaultParams, userParams);
+ };
+
+ /*
+ * Set type, text and actions on modal
+ */
+
+ function setParameters(params) {
+ var modal = getModal();
+
+ var $title = modal.querySelector('h2'),
+ $text = modal.querySelector('p'),
+ $cancelBtn = modal.querySelector('button.cancel'),
+ $confirmBtn = modal.querySelector('button.confirm');
+
+ // Title
+ $title.innerHTML = escapeHtml(params.title).split("\n").join("<br>");
+
+ // Text
+ $text.innerHTML = escapeHtml(params.text || '').split("\n").join("<br>");
+ if (params.text) {
+ show($text);
+ }
+
+ // Icon
+ hide(modal.querySelectorAll('.icon'));
+ if (params.type) {
+ var validType = false;
+ for (var i = 0; i < alertTypes.length; i++) {
+ if (params.type === alertTypes[i]) {
+ validType = true;
+ break;
+ }
+ }
+ if (!validType) {
+ window.console.error('Unknown alert type: ' + params.type);
+ return false;
+ }
+ var $icon = modal.querySelector('.icon.' + params.type);
+ show($icon);
+
+ // Animate icon
+ switch (params.type) {
+ case "success":
+ addClass($icon, 'animate');
+ addClass($icon.querySelector('.tip'), 'animateSuccessTip');
+ addClass($icon.querySelector('.long'), 'animateSuccessLong');
+ break;
+ case "error":
+ addClass($icon, 'animateErrorIcon');
+ addClass($icon.querySelector('.x-mark'), 'animateXMark');
+ break;
+ case "warning":
+ addClass($icon, 'pulseWarning');
+ addClass($icon.querySelector('.body'), 'pulseWarningIns');
+ addClass($icon.querySelector('.dot'), 'pulseWarningIns');
+ break;
+ }
+
+ }
+
+ // Custom image
+ if (params.imageUrl) {
+ var $customIcon = modal.querySelector('.icon.custom');
+
+ $customIcon.style.backgroundImage = 'url(' + params.imageUrl + ')';
+ show($customIcon);
+
+ var _imgWidth = 80,
+ _imgHeight = 80;
+
+ if (params.imageSize) {
+ var imgWidth = params.imageSize.split('x')[0];
+ var imgHeight = params.imageSize.split('x')[1];
+
+ if (!imgWidth || !imgHeight) {
+ window.console.error("Parameter imageSize expects value with format WIDTHxHEIGHT, got " + params.imageSize);
+ } else {
+ _imgWidth = imgWidth;
+ _imgHeight = imgHeight;
+
+ $customIcon.css({
+ 'width': imgWidth + 'px',
+ 'height': imgHeight + 'px'
+ });
+ }
+ }
+ $customIcon.setAttribute('style', $customIcon.getAttribute('style') + 'width:' + _imgWidth + 'px; height:' + _imgHeight + 'px');
+ }
+
+ // Cancel button
+ modal.setAttribute('data-has-cancel-button', params.showCancelButton);
+ if (params.showCancelButton) {
+ $cancelBtn.style.display = 'inline-block';
+ } else {
+ hide($cancelBtn);
+ }
+
+ // Edit text on cancel and confirm buttons
+ if (params.cancelButtonText) {
+ $cancelBtn.innerHTML = escapeHtml(params.cancelButtonText);
+ }
+ if (params.confirmButtonText) {
+ $confirmBtn.innerHTML = escapeHtml(params.confirmButtonText);
+ }
+
+ // Reset confirm buttons to default class (Ugly fix)
+ $confirmBtn.className = 'confirm btn btn-lg'
+
+ // Set confirm button to selected class
+ addClass($confirmBtn, params.confirmButtonClass);
+
+ // Set cancel button to selected class
+ addClass($cancelBtn, params.cancelButtonClass);
+
+ // Allow outside click?
+ modal.setAttribute('data-allow-ouside-click', params.allowOutsideClick);
+
+ // Done-function
+ var hasDoneFunction = (params.doneFunction) ? true : false;
+ modal.setAttribute('data-has-done-function', hasDoneFunction);
+
+ // Close timer
+ modal.setAttribute('data-timer', params.timer);
+ }
+
+
+ /*
+ * Set hover, active and focus-states for buttons (source: http://www.sitepoint.com/javascript-generate-lighter-darker-color)
+ */
+
+ function colorLuminance(hex, lum) {
+ // Validate hex string
+ hex = String(hex).replace(/[^0-9a-f]/gi, '');
+ if (hex.length < 6) {
+ hex = hex[0]+hex[0]+hex[1]+hex[1]+hex[2]+hex[2];
+ }
+ lum = lum || 0;
+
+ // Convert to decimal and change luminosity
+ var rgb = "#", c, i;
+ for (i = 0; i < 3; i++) {
+ c = parseInt(hex.substr(i*2,2), 16);
+ c = Math.round(Math.min(Math.max(0, c + (c * lum)), 255)).toString(16);
+ rgb += ("00"+c).substr(c.length);
+ }
+
+ return rgb;
+ }
+
+ function extend(a, b){
+ for (var key in b) {
+ if (b.hasOwnProperty(key)) {
+ a[key] = b[key];
+ }
+ }
+
+ return a;
+ }
+
+ function hexToRgb(hex) {
+ var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
+ return result ? parseInt(result[1], 16) + ', ' + parseInt(result[2], 16) + ', ' + parseInt(result[3], 16) : null;
+ }
+
+ // Add box-shadow style to button (depending on its chosen bg-color)
+ function setFocusStyle($button, bgColor) {
+ var rgbColor = hexToRgb(bgColor);
+ $button.style.boxShadow = '0 0 2px rgba(' + rgbColor +', 0.8), inset 0 0 0 1px rgba(0, 0, 0, 0.05)';
+ }
+
+
+ /*
+ * Animations
+ */
+
+ function openModal() {
+ var modal = getModal();
+ fadeIn(getOverlay(), 10);
+ show(modal);
+ addClass(modal, 'showSweetAlert');
+ removeClass(modal, 'hideSweetAlert');
+
+ previousActiveElement = document.activeElement;
+ var $okButton = modal.querySelector('button.confirm');
+ $okButton.focus();
+
+ setTimeout(function() {
+ addClass(modal, 'visible');
+ }, 500);
+
+ var timer = modal.getAttribute('data-timer');
+ if (timer !== "null" && timer !== "") {
+ setTimeout(function() {
+ closeModal();
+ }, timer);
+ }
+ }
+
+ function closeModal() {
+ var modal = getModal();
+ fadeOut(getOverlay(), 5);
+ fadeOut(modal, 5);
+ removeClass(modal, 'showSweetAlert');
+ addClass(modal, 'hideSweetAlert');
+ removeClass(modal, 'visible');
+
+
+ // Reset icon animations
+
+ var $successIcon = modal.querySelector('.icon.success');
+ removeClass($successIcon, 'animate');
+ removeClass($successIcon.querySelector('.tip'), 'animateSuccessTip');
+ removeClass($successIcon.querySelector('.long'), 'animateSuccessLong');
+
+ var $errorIcon = modal.querySelector('.icon.error');
+ removeClass($errorIcon, 'animateErrorIcon');
+ removeClass($errorIcon.querySelector('.x-mark'), 'animateXMark');
+
+ var $warningIcon = modal.querySelector('.icon.warning');
+ removeClass($warningIcon, 'pulseWarning');
+ removeClass($warningIcon.querySelector('.body'), 'pulseWarningIns');
+ removeClass($warningIcon.querySelector('.dot'), 'pulseWarningIns');
+
+
+ // Reset the page to its previous state
+ window.onkeydown = previousWindowKeyDown;
+ document.onclick = previousDocumentClick;
+ if (previousActiveElement) {
+ previousActiveElement.focus();
+ }
+ lastFocusedButton = undefined;
+ }
+
+
+ /*
+ * Set "margin-top"-property on modal based on its computed height
+ */
+
+ function fixVerticalPosition() {
+ var modal = getModal();
+ modal.style.marginTop = getTopMargin(getModal());
+ }
+
+
+ /*
+ * If library is injected after page has loaded
+ */
+
+ (function () {
+ if (document.readyState === "complete" || document.readyState === "interactive" && document.body) {
+ sweetAlertInitialize();
+ } else {
+ if (document.addEventListener) {
+ document.addEventListener('DOMContentLoaded', function factorial() {
+ document.removeEventListener('DOMContentLoaded', arguments.callee, false);
+ sweetAlertInitialize();
+ }, false);
+ } else if (document.attachEvent) {
+ document.attachEvent('onreadystatechange', function() {
+ if (document.readyState === 'complete') {
+ document.detachEvent('onreadystatechange', arguments.callee);
+ sweetAlertInitialize();
+ }
+ });
+ }
+ }
+ })();
+
+})(window, document);
diff --git a/tools/static/sweet-alert.min.js b/tools/static/sweet-alert.min.js
new file mode 100644
index 0000000..3940548
--- /dev/null
+++ b/tools/static/sweet-alert.min.js
@@ -0,0 +1 @@
+!function(a,b){function c(b){var c=p(),d=c.querySelector("h2"),e=c.querySelector("p"),f=c.querySelector("button.cancel"),g=c.querySelector("button.confirm");if(d.innerHTML=u(b.title).split("\n").join("<br>"),e.innerHTML=u(b.text||"").split("\n").join("<br>"),b.text&&w(e),y(c.querySelectorAll(".icon")),b.type){for(var h=!1,i=0;i<n.length;i++)if(b.type===n[i]){h=!0;break}if(!h)return a.console.error("Unknown alert type: "+b.type),!1;var j=c.querySelector(".icon."+b.type);switch(w(j),b.type){case"success":s(j,"animate"),s(j.querySelector(".tip"),"animateSuccessTip"),s(j.querySelector(".long"),"animateSuccessLong");break;case"error":s(j,"animateErrorIcon"),s(j.querySelector(".x-mark"),"animateXMark");break;case"warning":s(j,"pulseWarning"),s(j.querySelector(".body"),"pulseWarningIns"),s(j.querySelector(".dot"),"pulseWarningIns")}}if(b.imageUrl){var k=c.querySelector(".icon.custom");k.style.backgroundImage="url("+b.imageUrl+")",w(k);var l=80,m=80;if(b.imageSize){var o=b.imageSize.split("x")[0],q=b.imageSize.split("x")[1];o&&q?(l=o,m=q,k.css({width:o+"px",height:q+"px"})):a.console.error("Parameter imageSize expects value with format WIDTHxHEIGHT, got "+b.imageSize)}k.setAttribute("style",k.getAttribute("style")+"width:"+l+"px; height:"+m+"px")}c.setAttribute("data-has-cancel-button",b.showCancelButton),b.showCancelButton?f.style.display="inline-block":y(f),b.cancelButtonText&&(f.innerHTML=u(b.cancelButtonText)),b.confirmButtonText&&(g.innerHTML=u(b.confirmButtonText)),g.className="confirm btn btn-lg",s(g,b.confirmButtonClass),c.setAttribute("data-allow-ouside-click",b.allowOutsideClick);var r=b.doneFunction?!0:!1;c.setAttribute("data-has-done-function",r),c.setAttribute("data-timer",b.timer)}function d(a,b){for(var c in b)b.hasOwnProperty(c)&&(a[c]=b[c]);return a}function e(){var a=p();B(q(),10),w(a),s(a,"showSweetAlert"),t(a,"hideSweetAlert"),h=b.activeElement;var c=a.querySelector("button.confirm");c.focus(),setTimeout(function(){s(a,"visible")},500);var d=a.getAttribute("data-timer");"null"!==d&&""!==d&&setTimeout(function(){f()},d)}function f(){var c=p();C(q(),5),C(c,5),t(c,"showSweetAlert"),s(c,"hideSweetAlert"),t(c,"visible");var d=c.querySelector(".icon.success");t(d,"animate"),t(d.querySelector(".tip"),"animateSuccessTip"),t(d.querySelector(".long"),"animateSuccessLong");var e=c.querySelector(".icon.error");t(e,"animateErrorIcon"),t(e.querySelector(".x-mark"),"animateXMark");var f=c.querySelector(".icon.warning");t(f,"pulseWarning"),t(f.querySelector(".body"),"pulseWarningIns"),t(f.querySelector(".dot"),"pulseWarningIns"),a.onkeydown=j,b.onclick=i,h&&h.focus(),k=void 0}function g(){var a=p();a.style.marginTop=A(p())}var h,i,j,k,l=".sweet-alert",m=".sweet-overlay",n=["error","warning","info","success"],o={title:"",text:"",type:null,allowOutsideClick:!1,showCancelButton:!1,closeOnConfirm:!0,closeOnCancel:!0,confirmButtonText:"OK",confirmButtonClass:"btn-primary",cancelButtonText:"Cancel",imageUrl:null,imageSize:null,timer:null},p=function(){return b.querySelector(l)},q=function(){return b.querySelector(m)},r=function(a,b){return new RegExp(" "+b+" ").test(" "+a.className+" ")},s=function(a,b){r(a,b)||(a.className+=" "+b)},t=function(a,b){var c=" "+a.className.replace(/[\t\r\n]/g," ")+" ";if(r(a,b)){for(;c.indexOf(" "+b+" ")>=0;)c=c.replace(" "+b+" "," ");a.className=c.replace(/^\s+|\s+$/g,"")}},u=function(a){var c=b.createElement("div");return c.appendChild(b.createTextNode(a)),c.innerHTML},v=function(a){a.style.opacity="",a.style.display="block"},w=function(a){if(a&&!a.length)return v(a);for(var b=0;b<a.length;++b)v(a[b])},x=function(a){a.style.opacity="",a.style.display="none"},y=function(a){if(a&&!a.length)return x(a);for(var b=0;b<a.length;++b)x(a[b])},z=function(a,b){for(var c=b.parentNode;null!==c;){if(c===a)return!0;c=c.parentNode}return!1},A=function(a){a.style.left="-9999px",a.style.display="block";var b=a.clientHeight,c=parseInt(getComputedStyle(a).getPropertyValue("padding"),10);return a.style.left="",a.style.display="none","-"+parseInt(b/2+c)+"px"},B=function(a,b){if(+a.style.opacity<1){b=b||16,a.style.opacity=0,a.style.display="block";var c=+new Date,d=function(){a.style.opacity=+a.style.opacity+(new Date-c)/100,c=+new Date,+a.style.opacity<1&&setTimeout(d,b)};d()}},C=function(a,b){b=b||16,a.style.opacity=1;var c=+new Date,d=function(){a.style.opacity=+a.style.opacity-(new Date-c)/100,c=+new Date,+a.style.opacity>0?setTimeout(d,b):a.style.display="none"};d()},D=function(c){if(MouseEvent){var d=new MouseEvent("click",{view:a,bubbles:!1,cancelable:!0});c.dispatchEvent(d)}else if(b.createEvent){var e=b.createEvent("MouseEvents");e.initEvent("click",!1,!1),c.dispatchEvent(e)}else b.createEventObject?c.fireEvent("onclick"):"function"==typeof c.onclick&&c.onclick()},E=function(b){"function"==typeof b.stopPropagation?(b.stopPropagation(),b.preventDefault()):a.event&&a.event.hasOwnProperty("cancelBubble")&&(a.event.cancelBubble=!0)};a.sweetAlertInitialize=function(){var a='<div class="sweet-overlay" tabIndex="-1"></div><div class="sweet-alert" tabIndex="-1"><div class="icon error"><span class="x-mark"><span class="line left"></span><span class="line right"></span></span></div><div class="icon warning"> <span class="body"></span> <span class="dot"></span> </div> <div class="icon info"></div> <div class="icon success"> <span class="line tip"></span> <span class="line long"></span> <div class="placeholder"></div> <div class="fix"></div> </div> <div class="icon custom"></div> <h2>Title</h2><p class="lead text-muted">Text</p><p><button class="cancel btn btn-default btn-lg" tabIndex="2">Cancel</button> <button class="confirm btn btn-lg" tabIndex="1">OK</button></p></div>',c=b.createElement("div");c.innerHTML=a,b.body.appendChild(c)},a.sweetAlert=a.swal=function(){function h(a){var b=a.keyCode||a.which;if(-1!==[9,13,32,27].indexOf(b)){for(var c=a.target||a.srcElement,d=-1,e=0;e<w.length;e++)if(c===w[e]){d=e;break}9===b?(c=-1===d?u:d===w.length-1?w[0]:w[d+1],E(a),c.focus()):(c=13===b||32===b?-1===d?u:void 0:27!==b||v.hidden||"none"===v.style.display?void 0:v,void 0!==c&&D(c,a))}}function l(a){var b=a.target||a.srcElement,c=a.relatedTarget,d=r(n,"visible");if(d){var e=-1;if(null!==c){for(var f=0;f<w.length;f++)if(c===w[f]){e=f;break}-1===e&&b.focus()}else k=b}}if(void 0===arguments[0])return a.console.error("sweetAlert expects at least 1 attribute!"),!1;var m=d({},o);switch(typeof arguments[0]){case"string":m.title=arguments[0],m.text=arguments[1]||"",m.type=arguments[2]||"";break;case"object":if(void 0===arguments[0].title)return a.console.error('Missing "title" argument!'),!1;m.title=arguments[0].title,m.text=arguments[0].text||o.text,m.type=arguments[0].type||o.type,m.allowOutsideClick=arguments[0].allowOutsideClick||o.allowOutsideClick,m.showCancelButton=void 0!==arguments[0].showCancelButton?arguments[0].showCancelButton:o.showCancelButton,m.closeOnConfirm=void 0!==arguments[0].closeOnConfirm?arguments[0].closeOnConfirm:o.closeOnConfirm,m.closeOnCancel=void 0!==arguments[0].closeOnCancel?arguments[0].closeOnCancel:o.closeOnCancel,m.timer=arguments[0].timer||o.timer,m.confirmButtonText=o.showCancelButton?"Confirm":o.confirmButtonText,m.confirmButtonText=arguments[0].confirmButtonText||o.confirmButtonText,m.confirmButtonClass=arguments[0].confirmButtonClass||o.confirmButtonClass,m.cancelButtonText=arguments[0].cancelButtonText||o.cancelButtonText,m.imageUrl=arguments[0].imageUrl||o.imageUrl,m.imageSize=arguments[0].imageSize||o.imageSize,m.doneFunction=arguments[1]||null;break;default:return a.console.error('Unexpected type of argument! Expected "string" or "object", got '+typeof arguments[0]),!1}c(m),g(),e();for(var n=p(),q=function(a){var b=a.target||a.srcElement,c=b.className.indexOf("confirm")>-1,d=r(n,"visible"),e=m.doneFunction&&"true"===n.getAttribute("data-has-done-function");switch(a.type){case"click":if(c&&e&&d)m.doneFunction(!0),m.closeOnConfirm&&f();else if(e&&d){var g=String(m.doneFunction).replace(/\s/g,""),h="function("===g.substring(0,9)&&")"!==g.substring(9,10);h&&m.doneFunction(!1),m.closeOnCancel&&f()}else f()}},s=n.querySelectorAll("button"),t=0;t<s.length;t++)s[t].onclick=q;i=b.onclick,b.onclick=function(a){var b=a.target||a.srcElement,c=n===b,d=z(n,a.target),e=r(n,"visible"),g="true"===n.getAttribute("data-allow-ouside-click");!c&&!d&&e&&g&&f()};var u=n.querySelector("button.confirm"),v=n.querySelector("button.cancel"),w=n.querySelectorAll("button:not([type=hidden])");j=a.onkeydown,a.onkeydown=h,u.onblur=l,v.onblur=l,a.onfocus=function(){a.setTimeout(function(){void 0!==k&&(k.focus(),k=void 0)},0)}},a.swal.setDefaults=function(a){if(!a)throw new Error("userParams is required");if("object"!=typeof a)throw new Error("userParams has to be a object");d(o,a)},function(){"complete"===b.readyState||"interactive"===b.readyState&&b.body?sweetAlertInitialize():b.addEventListener?b.addEventListener("DOMContentLoaded",function(){b.removeEventListener("DOMContentLoaded",arguments.callee,!1),sweetAlertInitialize()},!1):b.attachEvent&&b.attachEvent("onreadystatechange",function(){"complete"===b.readyState&&(b.detachEvent("onreadystatechange",arguments.callee),sweetAlertInitialize())})}()}(window,document); \ No newline at end of file
diff --git a/tools/style.css b/tools/style.css
index 304eff7..2da531b 100644
--- a/tools/style.css
+++ b/tools/style.css
@@ -63,7 +63,7 @@ a {
.actives {
color: white !important;
- text-decoration: underline;
+/* text-decoration: underline; */
font-weight: bold;
}