initial commit (work in progress)
This commit is contained in:
parent
13fdb60f66
commit
559369016d
83 changed files with 10461 additions and 0 deletions
211
examples/dbmonster/ENV.js
Normal file
211
examples/dbmonster/ENV.js
Normal file
|
|
@ -0,0 +1,211 @@
|
|||
var ENV = ENV || (function() {
|
||||
|
||||
var first = true;
|
||||
var counter = 0;
|
||||
var data;
|
||||
var _base;
|
||||
(_base = String.prototype).lpad || (_base.lpad = function(padding, toLength) {
|
||||
return padding.repeat((toLength - this.length) / padding.length).concat(this);
|
||||
});
|
||||
|
||||
function formatElapsed(value) {
|
||||
str = parseFloat(value).toFixed(2);
|
||||
if (value > 60) {
|
||||
minutes = Math.floor(value / 60);
|
||||
comps = (value % 60).toFixed(2).split('.');
|
||||
seconds = comps[0].lpad('0', 2);
|
||||
ms = comps[1];
|
||||
str = minutes + ":" + seconds + "." + ms;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
function getElapsedClassName(elapsed) {
|
||||
var className = 'Query elapsed';
|
||||
if (elapsed >= 10.0) {
|
||||
className += ' warn_long';
|
||||
}
|
||||
else if (elapsed >= 1.0) {
|
||||
className += ' warn';
|
||||
}
|
||||
else {
|
||||
className += ' short';
|
||||
}
|
||||
return className;
|
||||
}
|
||||
|
||||
function countClassName(queries) {
|
||||
var countClassName = "label";
|
||||
if (queries >= 20) {
|
||||
countClassName += " label-important";
|
||||
}
|
||||
else if (queries >= 10) {
|
||||
countClassName += " label-warning";
|
||||
}
|
||||
else {
|
||||
countClassName += " label-success";
|
||||
}
|
||||
return countClassName;
|
||||
}
|
||||
|
||||
function updateQuery(object) {
|
||||
if (!object) {
|
||||
object = {};
|
||||
}
|
||||
var elapsed = Math.random() * 15;
|
||||
object.elapsed = elapsed;
|
||||
object.formatElapsed = formatElapsed(elapsed);
|
||||
object.elapsedClassName = getElapsedClassName(elapsed);
|
||||
object.query = "SELECT blah FROM something";
|
||||
object.waiting = Math.random() < 0.5;
|
||||
if (Math.random() < 0.2) {
|
||||
object.query = "<IDLE> in transaction";
|
||||
}
|
||||
if (Math.random() < 0.1) {
|
||||
object.query = "vacuum";
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
function cleanQuery(value) {
|
||||
if (value) {
|
||||
value.formatElapsed = "";
|
||||
value.elapsedClassName = "";
|
||||
value.query = "";
|
||||
value.elapsed = null;
|
||||
value.waiting = null;
|
||||
} else {
|
||||
return {
|
||||
query: "***",
|
||||
formatElapsed: "",
|
||||
elapsedClassName: ""
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function generateRow(object, keepIdentity, counter) {
|
||||
var nbQueries = Math.floor((Math.random() * 10) + 1);
|
||||
if (!object) {
|
||||
object = {};
|
||||
}
|
||||
object.lastMutationId = counter;
|
||||
object.nbQueries = nbQueries;
|
||||
if (!object.lastSample) {
|
||||
object.lastSample = {};
|
||||
}
|
||||
if (!object.lastSample.topFiveQueries) {
|
||||
object.lastSample.topFiveQueries = [];
|
||||
}
|
||||
if (keepIdentity) {
|
||||
// for Angular optimization
|
||||
if (!object.lastSample.queries) {
|
||||
object.lastSample.queries = [];
|
||||
for (var l = 0; l < 12; l++) {
|
||||
object.lastSample.queries[l] = cleanQuery();
|
||||
}
|
||||
}
|
||||
for (var j in object.lastSample.queries) {
|
||||
var value = object.lastSample.queries[j];
|
||||
if (j <= nbQueries) {
|
||||
updateQuery(value);
|
||||
} else {
|
||||
cleanQuery(value);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
object.lastSample.queries = [];
|
||||
for (var j = 0; j < 12; j++) {
|
||||
if (j < nbQueries) {
|
||||
var value = updateQuery(cleanQuery());
|
||||
object.lastSample.queries.push(value);
|
||||
} else {
|
||||
object.lastSample.queries.push(cleanQuery());
|
||||
}
|
||||
}
|
||||
}
|
||||
for (var i = 0; i < 5; i++) {
|
||||
var source = object.lastSample.queries[i];
|
||||
object.lastSample.topFiveQueries[i] = source;
|
||||
}
|
||||
object.lastSample.nbQueries = nbQueries;
|
||||
object.lastSample.countClassName = countClassName(nbQueries);
|
||||
return object;
|
||||
}
|
||||
|
||||
function getData(keepIdentity) {
|
||||
var oldData = data;
|
||||
if (!keepIdentity) { // reset for each tick when !keepIdentity
|
||||
data = [];
|
||||
for (var i = 1; i <= ENV.rows; i++) {
|
||||
data.push({ dbname: 'cluster' + i, query: "", formatElapsed: "", elapsedClassName: "" });
|
||||
data.push({ dbname: 'cluster' + i + ' slave', query: "", formatElapsed: "", elapsedClassName: "" });
|
||||
}
|
||||
}
|
||||
if (!data) { // first init when keepIdentity
|
||||
data = [];
|
||||
for (var i = 1; i <= ENV.rows; i++) {
|
||||
data.push({ dbname: 'cluster' + i });
|
||||
data.push({ dbname: 'cluster' + i + ' slave' });
|
||||
}
|
||||
oldData = data;
|
||||
}
|
||||
for (var i in data) {
|
||||
var row = data[i];
|
||||
if (!keepIdentity && oldData && oldData[i]) {
|
||||
row.lastSample = oldData[i].lastSample;
|
||||
}
|
||||
if (!row.lastSample || Math.random() < ENV.mutations()) {
|
||||
counter = counter + 1;
|
||||
if (!keepIdentity) {
|
||||
row.lastSample = null;
|
||||
}
|
||||
generateRow(row, keepIdentity, counter);
|
||||
} else {
|
||||
data[i] = oldData[i];
|
||||
}
|
||||
}
|
||||
first = false;
|
||||
return {
|
||||
toArray: function() {
|
||||
return data;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
var mutationsValue = 0.5;
|
||||
|
||||
function mutations(value) {
|
||||
if (value) {
|
||||
mutationsValue = value;
|
||||
return mutationsValue;
|
||||
} else {
|
||||
return mutationsValue;
|
||||
}
|
||||
}
|
||||
|
||||
var body = document.querySelector('body');
|
||||
var theFirstChild = body.firstChild;
|
||||
|
||||
var sliderContainer = document.createElement( 'div' );
|
||||
sliderContainer.style.cssText = "display: flex";
|
||||
var slider = document.createElement('input');
|
||||
var text = document.createElement('label');
|
||||
text.innerHTML = 'mutations : ' + (mutationsValue * 100).toFixed(0) + '%';
|
||||
text.id = "ratioval";
|
||||
slider.setAttribute("type", "range");
|
||||
slider.style.cssText = 'margin-bottom: 10px; margin-top: 5px';
|
||||
slider.addEventListener('change', function(e) {
|
||||
ENV.mutations(e.target.value / 100);
|
||||
document.querySelector('#ratioval').innerHTML = 'mutations : ' + (ENV.mutations() * 100).toFixed(0) + '%';
|
||||
});
|
||||
sliderContainer.appendChild( text );
|
||||
sliderContainer.appendChild( slider );
|
||||
body.insertBefore( sliderContainer, theFirstChild );
|
||||
|
||||
return {
|
||||
generateData: getData,
|
||||
rows: 50,
|
||||
timeout: 0,
|
||||
mutations: mutations
|
||||
};
|
||||
})();
|
||||
7
examples/dbmonster/bootstrap.min.css
vendored
Normal file
7
examples/dbmonster/bootstrap.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
101
examples/dbmonster/memory-stats.js
Normal file
101
examples/dbmonster/memory-stats.js
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
* @author jetienne / http://jetienne.com/
|
||||
* @author paulirish / http://paulirish.com/
|
||||
*/
|
||||
var MemoryStats = function (){
|
||||
|
||||
var msMin = 100;
|
||||
var msMax = 0;
|
||||
|
||||
var container = document.createElement( 'div' );
|
||||
container.id = 'stats';
|
||||
container.style.cssText = 'width:80px;opacity:0.9;cursor:pointer';
|
||||
|
||||
var msDiv = document.createElement( 'div' );
|
||||
msDiv.id = 'ms';
|
||||
msDiv.style.cssText = 'padding:0 0 3px 3px;text-align:left;background-color:#020;';
|
||||
container.appendChild( msDiv );
|
||||
|
||||
var msText = document.createElement( 'div' );
|
||||
msText.id = 'msText';
|
||||
msText.style.cssText = 'color:#0f0;font-family:Helvetica,Arial,sans-serif;font-size:9px;font-weight:bold;line-height:15px';
|
||||
msText.innerHTML= 'Memory';
|
||||
msDiv.appendChild( msText );
|
||||
|
||||
var msGraph = document.createElement( 'div' );
|
||||
msGraph.id = 'msGraph';
|
||||
msGraph.style.cssText = 'position:relative;width:74px;height:30px;background-color:#0f0';
|
||||
msDiv.appendChild( msGraph );
|
||||
|
||||
while ( msGraph.children.length < 74 ) {
|
||||
|
||||
var bar = document.createElement( 'span' );
|
||||
bar.style.cssText = 'width:1px;height:30px;float:left;background-color:#131';
|
||||
msGraph.appendChild( bar );
|
||||
|
||||
}
|
||||
|
||||
var updateGraph = function ( dom, height, color ) {
|
||||
|
||||
var child = dom.appendChild( dom.firstChild );
|
||||
child.style.height = height + 'px';
|
||||
if( color ) child.style.backgroundColor = color;
|
||||
|
||||
}
|
||||
|
||||
var perf = window.performance || {};
|
||||
// polyfill usedJSHeapSize
|
||||
if (!perf && !perf.memory){
|
||||
perf.memory = { usedJSHeapSize : 0 };
|
||||
}
|
||||
if (perf && !perf.memory){
|
||||
perf.memory = { usedJSHeapSize : 0 };
|
||||
}
|
||||
|
||||
// support of the API?
|
||||
if( perf.memory.totalJSHeapSize === 0 ){
|
||||
console.warn('totalJSHeapSize === 0... performance.memory is only available in Chrome .')
|
||||
}
|
||||
|
||||
// TODO, add a sanity check to see if values are bucketed.
|
||||
// If so, reminde user to adopt the --enable-precise-memory-info flag.
|
||||
// open -a "/Applications/Google Chrome.app" --args --enable-precise-memory-info
|
||||
|
||||
var lastTime = Date.now();
|
||||
var lastUsedHeap= perf.memory.usedJSHeapSize;
|
||||
return {
|
||||
domElement: container,
|
||||
|
||||
update: function () {
|
||||
|
||||
// refresh only 30time per second
|
||||
if( Date.now() - lastTime < 1000/30 ) return;
|
||||
lastTime = Date.now()
|
||||
|
||||
var delta = perf.memory.usedJSHeapSize - lastUsedHeap;
|
||||
lastUsedHeap = perf.memory.usedJSHeapSize;
|
||||
var color = delta < 0 ? '#830' : '#131';
|
||||
|
||||
var ms = perf.memory.usedJSHeapSize;
|
||||
msMin = Math.min( msMin, ms );
|
||||
msMax = Math.max( msMax, ms );
|
||||
msText.textContent = "Mem: " + bytesToSize(ms, 2);
|
||||
|
||||
var normValue = ms / (30*1024*1024);
|
||||
var height = Math.min( 30, 30 - normValue * 30 );
|
||||
updateGraph( msGraph, height, color);
|
||||
|
||||
function bytesToSize( bytes, nFractDigit ){
|
||||
var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
|
||||
if (bytes == 0) return 'n/a';
|
||||
nFractDigit = nFractDigit !== undefined ? nFractDigit : 0;
|
||||
var precision = Math.pow(10, nFractDigit);
|
||||
var i = Math.floor(Math.log(bytes) / Math.log(1024));
|
||||
return Math.round(bytes*precision / Math.pow(1024, i))/precision + ' ' + sizes[i];
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
72
examples/dbmonster/mithril/app.js
Normal file
72
examples/dbmonster/mithril/app.js
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
"use strict"
|
||||
|
||||
var m = require("../../../render/hyperscript")
|
||||
var render = require("../../../render/render")(window).render
|
||||
|
||||
var data = []
|
||||
|
||||
var root = document.getElementById("app")
|
||||
update()
|
||||
|
||||
function update() {
|
||||
data = ENV.generateData().toArray()
|
||||
|
||||
Monitoring.renderRate.ping()
|
||||
|
||||
render(root, [view()])
|
||||
|
||||
setTimeout(update, ENV.timeout)
|
||||
}
|
||||
|
||||
function view() {
|
||||
return m("div", [
|
||||
m("table", { class: "table table-striped latest-data" }, [
|
||||
m("tbody",
|
||||
data.map(function(db) {
|
||||
return m("tr", {key: db.dbname}, [
|
||||
m("td", { class: "dbname" }, db.dbname),
|
||||
m("td", { class: "query-count" }, [
|
||||
m("span", { class: db.lastSample.countclassName }, db.lastSample.nbQueries)
|
||||
]),
|
||||
db.lastSample.topFiveQueries.map(function(query) {
|
||||
return m("td", { class: query.elapsedclassName }, [
|
||||
m("span", query.formatElapsed),
|
||||
m("div", { class: "popover left" }, [
|
||||
m("div", { class: "popover-content" }, query.query),
|
||||
m("div", { class: "arrow" })
|
||||
])
|
||||
])
|
||||
})
|
||||
])
|
||||
})
|
||||
)
|
||||
])
|
||||
])
|
||||
}
|
||||
/*
|
||||
function view() {
|
||||
return m("div", [
|
||||
m("table.table.table-striped.latest-data", [
|
||||
m("tbody",
|
||||
data.map(function(db) {
|
||||
return m("tr", {key: db.dbname}, [
|
||||
m("td.dbname", db.dbname),
|
||||
m("td.query-count", [
|
||||
m("span", { class: db.lastSample.countclassName }, db.lastSample.nbQueries)
|
||||
]),
|
||||
db.lastSample.topFiveQueries.map(function(query) {
|
||||
return m("td", { class: query.elapsedclassName }, [
|
||||
m("span", query.formatElapsed),
|
||||
m("div.popover.left", [
|
||||
m("div.popover-content", query.query),
|
||||
m("div.arrow")
|
||||
])
|
||||
])
|
||||
})
|
||||
])
|
||||
})
|
||||
)
|
||||
])
|
||||
])
|
||||
}
|
||||
*/
|
||||
20
examples/dbmonster/mithril/index.html
Normal file
20
examples/dbmonster/mithril/index.html
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta name="description" content="DBMON Mithril" />
|
||||
<meta charset="utf-8">
|
||||
<link href="../styles.css" rel="stylesheet" type="text/css" />
|
||||
<title>dbmon (Mithril)</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script src="../../../module/module.js"></script>
|
||||
<script src="../../../render/normalizeChildren.js"></script>
|
||||
<script src="../../../render/hyperscript.js"></script>
|
||||
<script src="../../../render/render.js"></script>
|
||||
<script src="../ENV.js"></script>
|
||||
<script src="../memory-stats.js"></script>
|
||||
<script src="../monitor.js"></script>
|
||||
<script src="app.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
60
examples/dbmonster/monitor.js
Normal file
60
examples/dbmonster/monitor.js
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
var Monitoring = Monitoring || (function() {
|
||||
|
||||
var stats = new MemoryStats();
|
||||
stats.domElement.style.position = 'fixed';
|
||||
stats.domElement.style.right = '0px';
|
||||
stats.domElement.style.bottom = '0px';
|
||||
document.body.appendChild( stats.domElement );
|
||||
requestAnimationFrame(function rAFloop(){
|
||||
stats.update();
|
||||
requestAnimationFrame(rAFloop);
|
||||
});
|
||||
|
||||
var RenderRate = function () {
|
||||
var container = document.createElement( 'div' );
|
||||
container.id = 'stats';
|
||||
container.style.cssText = 'width:150px;opacity:0.9;cursor:pointer;position:fixed;right:80px;bottom:0px;';
|
||||
|
||||
var msDiv = document.createElement( 'div' );
|
||||
msDiv.id = 'ms';
|
||||
msDiv.style.cssText = 'padding:0 0 3px 3px;text-align:left;background-color:#020;';
|
||||
container.appendChild( msDiv );
|
||||
|
||||
var msText = document.createElement( 'div' );
|
||||
msText.id = 'msText';
|
||||
msText.style.cssText = 'color:#0f0;font-family:Helvetica,Arial,sans-serif;font-size:9px;font-weight:bold;line-height:15px';
|
||||
msText.innerHTML= 'Repaint rate: 0/sec';
|
||||
msDiv.appendChild( msText );
|
||||
|
||||
var bucketSize = 20;
|
||||
var bucket = [];
|
||||
var lastTime = Date.now();
|
||||
return {
|
||||
domElement: container,
|
||||
ping: function () {
|
||||
var start = lastTime;
|
||||
var stop = Date.now();
|
||||
var rate = 1000 / (stop - start);
|
||||
bucket.push(rate);
|
||||
if (bucket.length > bucketSize) {
|
||||
bucket.shift();
|
||||
}
|
||||
var sum = 0;
|
||||
for (var i = 0; i < bucket.length; i++) {
|
||||
sum = sum + bucket[i];
|
||||
}
|
||||
msText.textContent = "Repaint rate: " + (sum / bucket.length).toFixed(2) + "/sec";
|
||||
lastTime = stop;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var renderRate = new RenderRate();
|
||||
document.body.appendChild( renderRate.domElement );
|
||||
|
||||
return {
|
||||
memoryStats: stats,
|
||||
renderRate: renderRate
|
||||
};
|
||||
|
||||
})();
|
||||
84
examples/dbmonster/react/app.js
Normal file
84
examples/dbmonster/react/app.js
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
"use strict";
|
||||
|
||||
var h = React.createElement
|
||||
|
||||
var Query = React.createClass({
|
||||
shouldComponentUpdate: function shouldComponentUpdate(nextProps, nextState) {
|
||||
if (nextProps.elapsedClassName !== this.props.elapsedClassName) return true;
|
||||
if (nextProps.formatElapsed !== this.props.formatElapsed) return true;
|
||||
if (nextProps.query !== this.props.query) return true;
|
||||
return false;
|
||||
},
|
||||
render: function render() {
|
||||
return h("td", { className: "Query " + this.props.elapsedClassName },
|
||||
this.props.formatElapsed,
|
||||
h("div", { className: "popover left" },
|
||||
h("div", { className: "popover-content" }, this.props.query),
|
||||
h("div", { className: "arrow" })
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var Database = React.createClass({
|
||||
shouldComponentUpdate: function shouldComponentUpdate(nextProps, nextState) {
|
||||
if (nextProps.lastMutationId === this.props.lastMutationId) return false;
|
||||
return true;
|
||||
},
|
||||
render: function render() {
|
||||
var lastSample = this.props.lastSample;
|
||||
return h("tr", { key: this.props.dbname },
|
||||
h("td", { className: "dbname" }, this.props.dbname),
|
||||
h("td", { className: "query-count" },
|
||||
h("span", { className: this.props.lastSample.countClassName }, this.props.lastSample.nbQueries)
|
||||
),
|
||||
this.props.lastSample.topFiveQueries.map(function (query, index) {
|
||||
return h(Query, {
|
||||
key: index,
|
||||
query: query.query,
|
||||
elapsed: query.elapsed,
|
||||
formatElapsed: query.formatElapsed,
|
||||
elapsedClassName: query.elapsedClassName
|
||||
});
|
||||
})
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var DBMon = React.createClass({
|
||||
getInitialState: function getInitialState() {
|
||||
return {
|
||||
databases: []
|
||||
};
|
||||
},
|
||||
|
||||
loadSamples: function loadSamples() {
|
||||
this.setState({
|
||||
databases: ENV.generateData(true).toArray()
|
||||
});
|
||||
Monitoring.renderRate.ping();
|
||||
setTimeout(this.loadSamples, ENV.timeout);
|
||||
},
|
||||
|
||||
componentDidMount: function componentDidMount() {
|
||||
this.loadSamples();
|
||||
},
|
||||
|
||||
render: function render() {
|
||||
return h("div", null,
|
||||
h("table", { className: "table table-striped latest-data" },
|
||||
h("tbody", null, this.state.databases.map(function (database) {
|
||||
return h(Database, {
|
||||
key: database.dbname,
|
||||
lastMutationId: database.lastMutationId,
|
||||
dbname: database.dbname,
|
||||
samples: database.samples,
|
||||
lastSample: database.lastSample
|
||||
});
|
||||
}))
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
ReactDOM.render(h(DBMon, null), document.getElementById('app'));
|
||||
18
examples/dbmonster/react/index.html
Normal file
18
examples/dbmonster/react/index.html
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta name="description" content="DBMON Mithril" />
|
||||
<meta charset="utf-8">
|
||||
<link href="../styles.css" rel="stylesheet" type="text/css" />
|
||||
<title>dbmon (React)</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script src="https://fb.me/react-15.0.1.js"></script>
|
||||
<script src="https://fb.me/react-dom-15.0.1.js"></script>
|
||||
<script src="../ENV.js"></script>
|
||||
<script src="../memory-stats.js"></script>
|
||||
<script src="../monitor.js"></script>
|
||||
<script src="app.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
27
examples/dbmonster/styles.css
Normal file
27
examples/dbmonster/styles.css
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
body {color:#333;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;margin:0;}
|
||||
label {display:inline-block;font-weight:700;margin-bottom:5px;}
|
||||
input[type=range] {display:block;width:100%;}
|
||||
table {border-collapse:collapse;border-spacing:0;}
|
||||
:before,:after {box-sizing: border-box;}
|
||||
|
||||
.table > thead > tr > th,.table > tbody > tr > th,.table > tfoot > tr > th,.table > thead > tr > td,.table > tbody > tr > td,.table > tfoot > tr > td {border-top:1px solid #ddd;line-height:1.42857143;padding:8px;vertical-align:top;}
|
||||
.table {width:100%;}
|
||||
.table-striped > tbody > tr:nth-child(odd) > td,.table-striped > tbody > tr:nth-child(odd) > th {background:#f9f9f9;}
|
||||
|
||||
.label {border-radius:.25em;color:#fff;display:inline;font-size:75%;font-weight:700;line-height:1;padding:.2em .6em .3em;text-align:center;vertical-align:baseline;white-space:nowrap;}
|
||||
.label-success {background-color:#5cb85c;}
|
||||
.label-warning {background-color:#f0ad4e;}
|
||||
|
||||
.popover {background-color:#fff;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;box-shadow:0 5px 10px rgba(0,0,0,.2);display:none;left:0;max-width:276px;padding:1px;position:absolute;text-align:left;top:0;white-space:normal;z-index:1010;}
|
||||
.popover>.arrow:after {border-width:10px;content:"";}
|
||||
.popover.left {margin-left:-10px;}
|
||||
.popover.left > .arrow {border-right-width:0;border-left-color:rgba(0,0,0,.25);margin-top:-11px;right:-11px;top:50%;}
|
||||
.popover.left > .arrow:after {border-left-color:#fff;border-right-width:0;bottom:-10px;content:" ";right:1px;}
|
||||
.popover > .arrow {border-width:11px;}
|
||||
.popover > .arrow,.popover>.arrow:after {border-color:transparent;border-style:solid;display:block;height:0;position:absolute;width:0;}
|
||||
|
||||
.popover-content {padding:9px 14px;}
|
||||
|
||||
.Query {position:relative;}
|
||||
.Query:hover .popover {display:block;left:-100%;width:100%;}
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue