Browse Source

Improved web test impl

pull/41/head
Kalle Stenflo 11 years ago
parent
commit
167b360700
  1. 6
      json-path-web-test/pom.xml
  2. 8
      json-path-web-test/src/main/java/com/jayway/jsonpath/web/boot/Main.java
  3. 63
      json-path-web-test/src/main/java/com/jayway/jsonpath/web/resource/ApiResource.java
  4. 115
      json-path-web-test/src/main/java/com/jayway/jsonpath/web/resource/IndexResource.java
  5. 33
      json-path-web-test/src/main/java/com/jayway/jsonpath/web/resource/StaticResource.java
  6. 5785
      json-path-web-test/src/main/resources/css/bootstrap.css
  7. 7
      json-path-web-test/src/main/resources/css/bootstrap.min.css
  8. 4
      json-path-web-test/src/main/resources/css/font-awesome.min.css
  9. 1
      json-path-web-test/src/main/resources/css/prettify.css
  10. 196
      json-path-web-test/src/main/resources/html/index.html
  11. 1951
      json-path-web-test/src/main/resources/js/bootstrap.js
  12. 6
      json-path-web-test/src/main/resources/js/bootstrap.min.js
  13. 4
      json-path-web-test/src/main/resources/js/jquery.min.js
  14. 30
      json-path-web-test/src/main/resources/js/prettify.js
  15. 463
      json-path-web-test/src/main/resources/js/tooltip.js

6
json-path-web-test/pom.xml

@ -23,17 +23,11 @@
<artifactId>jetty-all</artifactId>
<version>9.2.0.v20140526</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>2.9.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-mvc-mustache</artifactId>
<version>2.9.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>

8
json-path-web-test/src/main/java/com/jayway/jsonpath/web/boot/Main.java

@ -1,6 +1,6 @@
package com.jayway.jsonpath.web.boot;
import com.jayway.jsonpath.web.resource.IndexResource;
import com.jayway.jsonpath.web.resource.ApiResource;
import com.jayway.jsonpath.web.resource.StaticResource;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Server;
@ -9,7 +9,6 @@ import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.glassfish.jersey.jackson.JacksonFeature;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.server.mvc.mustache.MustacheMvcFeature;
import org.glassfish.jersey.servlet.ServletContainer;
import java.io.IOException;
@ -55,12 +54,9 @@ public class Main {
private static ServletContainer createJerseyServlet() throws IOException {
ResourceConfig resourceConfig = new ResourceConfig();
resourceConfig.property(MustacheMvcFeature.TEMPLATE_BASE_PATH, "templates");
resourceConfig.register(MustacheMvcFeature.class);
resourceConfig.register(JacksonFeature.class);
resourceConfig.register(new IndexResource());
resourceConfig.register(new ApiResource());
resourceConfig.register(new StaticResource());
return new ServletContainer(resourceConfig);

63
json-path-web-test/src/main/java/com/jayway/jsonpath/web/resource/ApiResource.java

@ -0,0 +1,63 @@
package com.jayway.jsonpath.web.resource;
import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.web.bench.Bench;
import com.jayway.jsonpath.web.bench.Result;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.ws.rs.Consumes;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.Collections;
import java.util.Map;
@Path("/api/")
@Produces(MediaType.TEXT_HTML)
public class ApiResource {
private static final Logger logger = LoggerFactory.getLogger(ApiResource.class);
@GET
@Path("validate")
@Produces(MediaType.APPLICATION_JSON)
public Response validate(@QueryParam("path") String path){
int result = -1;
try {
JsonPath compiled = JsonPath.compile(path);
result = compiled.isDefinite()?0:1;
} catch (Exception e){
}
return Response.ok(Collections.singletonMap("result", result)).build();
}
@POST
@Path("eval")
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Produces(MediaType.APPLICATION_JSON)
public Response getTemplate(@FormParam("json") String json,
@FormParam("path") String path,
@FormParam("type") String type,
@FormParam("flagWrap") boolean flagWrap,
@FormParam("flagMerge") boolean flagMerge,
@FormParam("flagSuppress") boolean flagSuppress ){
boolean value = "VALUE".equalsIgnoreCase(type);
Map<String, Result> resultMap = new Bench(json, path, value, flagWrap, flagMerge, flagSuppress).runAll();
return Response.ok(resultMap).build();
}
}

115
json-path-web-test/src/main/java/com/jayway/jsonpath/web/resource/IndexResource.java

@ -1,115 +0,0 @@
package com.jayway.jsonpath.web.resource;
import com.jayway.jsonpath.web.bench.Bench;
import com.jayway.jsonpath.web.bench.Result;
import org.apache.commons.io.IOUtils;
import org.glassfish.jersey.server.mvc.Viewable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.ws.rs.Consumes;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static java.util.Arrays.asList;
@Path("/")
@Produces(MediaType.TEXT_HTML)
public class IndexResource {
private static final Logger logger = LoggerFactory.getLogger(IndexResource.class);
public final static Map<String, String> TEMPLATES = loadTemplates();
@GET
@Path("templates/{template}")
@Produces(MediaType.APPLICATION_JSON)
public Response getTemplate(@PathParam("template") @DefaultValue("goessner") String template){
return Response.ok(TEMPLATES.get(template)).build();
}
@POST
@Path("eval")
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Produces(MediaType.APPLICATION_JSON)
public Response getTemplate(@FormParam("json") String json,
@FormParam("path") String path,
@FormParam("type") String type,
@FormParam("flagWrap") boolean flagWrap,
@FormParam("flagMerge") boolean flagMerge,
@FormParam("flagSuppress") boolean flagSuppress ){
boolean value = "VALUE".equalsIgnoreCase(type);
Map<String, Result> resultMap = new Bench(json, path, value, flagWrap, flagMerge, flagSuppress).runAll();
return Response.ok(resultMap).build();
}
@GET
public Viewable get(@QueryParam("template") @DefaultValue("goessner") String template){
return createView(TEMPLATES.get(template), "$.store.book[0].title", true, template, null);
}
private Viewable createView(String json, String path, boolean value, String selectedTemplate, List<Result> results){
Map<String, Object> res = new HashMap<String, Object>();
res.put("results", results);
res.put("json", json);
res.put("path", path);
res.put("value-checked", value?"checked":"");
res.put("path-checked", (!value)?"checked":"");
res.put("templates", asList(new Template("goessner", "goessner", selectedTemplate), new Template("twitter" , "twitter", selectedTemplate), new Template("webapp", "webapp", selectedTemplate), new Template("20k", "20k", selectedTemplate)));
return new Viewable("/index", res);
}
private static Map<String, String> loadTemplates(){
try {
String goessner = IOUtils.toString(Thread.currentThread().getContextClassLoader().getResourceAsStream("json/goessner.json"), "UTF-8");
String twitter = IOUtils.toString(Thread.currentThread().getContextClassLoader().getResourceAsStream("json/twitter.json"));
String webapp = IOUtils.toString(Thread.currentThread().getContextClassLoader().getResourceAsStream("json/webxml.json"));
String twentyK = IOUtils.toString(Thread.currentThread().getContextClassLoader().getResourceAsStream("json/20k.json"));
Map<String, String> templates = new HashMap<String, String>();
templates.put("blank", "null");
templates.put("goessner", goessner);
templates.put("twitter", twitter);
templates.put("webapp", webapp);
templates.put("20k", twentyK);
return templates;
} catch (Exception e){
throw new RuntimeException(e);
}
}
private static class Template {
public final String value;
public final String name;
public final String selected;
private Template(String value, String name, String selectedValue) {
this.value = value;
this.name = name;
this.selected = value.equalsIgnoreCase(selectedValue)?"selected":"";
}
}
}

33
json-path-web-test/src/main/java/com/jayway/jsonpath/web/resource/StaticResource.java

@ -4,31 +4,50 @@ import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
import java.io.InputStream;
@Path("/static/")
@Path("/")
public class StaticResource {
@GET
public InputStream index(@Context UriInfo uriInfo){
return Thread.currentThread().getContextClassLoader().getResourceAsStream("html/index.html");
}
@GET
@Path("{resource}")
public InputStream html(@Context UriInfo uriInfo){
return Thread.currentThread().getContextClassLoader().getResourceAsStream("html/" + uriInfo.getPathParameters().getFirst("resource"));
}
@GET
@Path("fonts/{resource}")
//@Produces("text/javascript")
public InputStream getFonts(@Context UriInfo uriInfo){
public InputStream font(@Context UriInfo uriInfo){
return Thread.currentThread().getContextClassLoader().getResourceAsStream("fonts/" + uriInfo.getPathParameters().getFirst("resource"));
}
@GET
@Path("js/{resource}")
@Produces("text/javascript")
public InputStream getJs(@Context UriInfo uriInfo){
public InputStream js(@Context UriInfo uriInfo){
return Thread.currentThread().getContextClassLoader().getResourceAsStream("js/" + uriInfo.getPathParameters().getFirst("resource"));
}
@GET
@Path("css/{resource}")
@Produces("text/css")
public InputStream getCss(@Context UriInfo uriInfo){
public InputStream css(@Context UriInfo uriInfo){
return Thread.currentThread().getContextClassLoader().getResourceAsStream("css/" + uriInfo.getPathParameters().getFirst("resource"));
}
@GET
@Path("json/{resource}")
@Produces(MediaType.APPLICATION_JSON)
public InputStream getTemplate(@Context UriInfo uriInfo){
if(uriInfo.getPathParameters().getFirst("resource").contains("blank")){
return null;
}
return Thread.currentThread().getContextClassLoader().getResourceAsStream("json/" + uriInfo.getPathParameters().getFirst("resource"));
}
}

5785
json-path-web-test/src/main/resources/css/bootstrap.css vendored

File diff suppressed because it is too large Load Diff

7
json-path-web-test/src/main/resources/css/bootstrap.min.css vendored

File diff suppressed because one or more lines are too long

4
json-path-web-test/src/main/resources/css/font-awesome.min.css vendored

File diff suppressed because one or more lines are too long

1
json-path-web-test/src/main/resources/css/prettify.css

@ -0,0 +1 @@
.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee}

196
json-path-web-test/src/main/resources/templates/index.mustache → json-path-web-test/src/main/resources/html/index.html

@ -3,92 +3,88 @@
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>JsonPath</title>
<link rel="stylesheet" href="/static/css/bootstrap.css">
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css">
<link rel="stylesheet" href="//google-code-prettify.googlecode.com/svn/loader/prettify.css">
<title>JSONPath evaluator</title>
<link rel="stylesheet" href="/css/bootstrap.min.css">
<link rel="stylesheet" href="/css/prettify.css">
<link rel="stylesheet" href="/css/font-awesome.min.css">
<script type="text/javascript" src="//google-code-prettify.googlecode.com/svn/loader/prettify.js?autoload=false"></script>
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.4/jquery-ui.min.js"></script>
<script type="text/javascript" src="/static/js/jsonpath-0.8.0.js"></script>
<script type="text/javascript" src="/static/js/bootstrap.js"></script>
<script type="text/javascript" src="/js/prettify.js"></script>
<script type="text/javascript" src="/js/jquery.min.js"></script>
<script type="text/javascript" src="/js/jsonpath-0.8.0.js"></script>
<script type="text/javascript" src="/js/bootstrap.min.js"></script>
</head>
<body role="document">
<div class="container">
<h3>JSONPath evaluator</h3>
<div class="row">
<div class="col-md-6">
<form id="form">
<div class="form-group">
<select id="selTemplates" name="template" class="form-control">
<option value="blank"></option>
<option value="goessner">goessner</option>
<option value="twitter">twitter</option>
<option value="webapp">webapp</option>
<option value="20k">20k</option>
</select>
</div>
<div class="form-group">
<select id="selTemplates" name="template" class="form-control">
<option value="blank"></option>
<option value="goessner.json">goessner</option>
<option value="twitter.json">twitter</option>
<option value="webxml.json">webapp</option>
<option value="20k.json">20k</option>
</select>
</div>
<div class="form-group">
<textarea id="txtJson" name="json" rows="15" class="form-control" placeholder="Select a template above or enter JSON"></textarea>
</div>
<div class="form-group">
<textarea id="txtJson" name="json" rows="15" class="form-control" placeholder="Select a template above or enter JSON"></textarea>
</div>
<div class="input-group">
<input id="txtPath" name="path" value="{{path}}" placeholder="Enter path" class="form-control"/>
<span class="input-group-btn">
<button id="submit" class="btn btn-default" type="button">Go!</button>
</span>
</div>
<div class="input-group">
<span id="path-status-tool" class="input-group-addon" data-toggle="tooltip" data-placement="top" title="Invalid path"><span id="path-status" class="glyphicon glyphicon-ban-circle"></span></span>
<input id="txtPath" name="path" placeholder="Enter path" autocomplete="off" class="form-control"/>
<span class="input-group-btn">
<button id="submit" class="btn btn-primary" type="button">Go!</button>
</span>
</div>
<br/>
<div class="row">
<div class="col-md-6">
<fieldset>
<legend>Result options</legend>
<div class="radio">
<label>
<input type="radio" name="rbType" value="VALUE" checked/>
Matching values
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="rbType" value="PATH"/>
Normalized path expressions
</label>
</div>
</fieldset>
</div>
<br/>
<div class="col-md-6">
<fieldset>
<legend>Jayway options</legend>
<div class="checkbox">
<label>
<input type="checkbox" name="flagWrap" id="cbFlagWrap" />
Always return result as list
</label>
</div>
<div class="checkbox">
<label>
<input type="checkbox" name="flagMerge" id="cbFlagMerge" />
Merge multi props to new object
</label>
</div>
<div class="checkbox">
<label>
<input type="checkbox" name="flagSuppress" id="cbFlagSuppress" />
Suppress exceptions
</label>
</div>
</fieldset>
<div class="row">
<div class="col-md-6">
<fieldset>
<legend>Result options</legend>
<div class="radio">
<label>
<input type="radio" name="rbType" value="VALUE" checked/>
Matching values
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="rbType" value="PATH"/>
Normalized path expressions
</label>
</div>
</fieldset>
</div>
</form>
<div class="col-md-6">
<fieldset>
<legend>Jayway options</legend>
<div class="checkbox">
<label>
<input type="checkbox" name="flagWrap" id="cbFlagWrap" />
Always return result as list
</label>
</div>
<div class="checkbox">
<label>
<input type="checkbox" name="flagMerge" id="cbFlagMerge" />
Merge multi props to new object
</label>
</div>
<div class="checkbox">
<label>
<input type="checkbox" name="flagSuppress" id="cbFlagSuppress" />
Suppress exceptions
</label>
</div>
</fieldset>
</div>
</div>
</div>
<div class="col-md-6">
@ -156,10 +152,15 @@
<script>
$( document ).ready(function() {
$('#path-status-tool').tooltip({
container: 'body',
delay: 0
});
$('#selTemplates').on('change', function() {
var val = this.value;
$.ajax({
url: "/templates/" + val,
url: "/json/" + val,
success: function(data){
if(data){
data = JSON.stringify(data, null, ' ');
@ -169,6 +170,42 @@
});
});
$('#txtPath').keyup(function(e) {
clearTimeout($.data(this, 'timer'));
if (e.keyCode === 13) {
$('#submit').click();
e.preventDefault();
} else {
$(this).data('timer', setTimeout(checkPath, 500));
}
});
function checkPath(force) {
var pathString = $("#txtPath").val();
if (!force && pathString.length < 1) return;
$.get('/api/validate/?path=' + pathString, function(data) {
if(data){
if(data.result === -1){
$('#path-status').removeClass().addClass('glyphicon glyphicon-ban-circle');
$('#path-status-tool').attr('data-original-title', 'Invalid path').tooltip('fixTitle');
}
else if(data.result === 0){
$('#path-status').removeClass().addClass('glyphicon glyphicon-record');
$('#path-status-tool').attr('data-original-title', 'Definite').tooltip('fixTitle');
}
else if(data.result === 1){
$('#path-status').removeClass().addClass('glyphicon glyphicon-align-justify');
$('#path-status-tool').attr('data-original-title', 'Not definite').tooltip('fixTitle');
}
}
});
}
$('#submit').on('click', function() {
var json = $('#txtJson').val();
@ -177,21 +214,21 @@
var data = {
json: json,
path: path,
type: $('input[name=rbType]:checked', '#form').val(),
type: $('input[name=rbType]:checked').val(),
flagWrap: $('#cbFlagWrap').prop('checked'),
flagMerge: $('#cbFlagMerge').prop('checked'),
flagSuppress: $('#cbFlagSuppress').prop('checked')
}
console.log(data);
$.ajax({
url: "/eval",
url: "/api/eval",
type: 'POST',
dataType: 'json',
data: data,
success: function(data) {
$('#jayway-time').text(data.jayway.time);
$('#jayway-res').text(data.jayway.result).effect( "highlight", {color: '#428bca'} );
$('#jayway-res').hide().text(data.jayway.result).fadeIn();
if(data.jayway.error){
$('#jayway-error').text(data.jayway.error).show();
} else {
@ -200,7 +237,7 @@
$('#boon-time').text(data.boon.time);
$('#boon-res').text(data.boon.result).effect( "highlight", {color: '#428bca'} );
$('#boon-res').hide().text(data.boon.result).fadeIn();
if(data.boon.error){
$('#boon-error').text(data.boon.error).show();
} else {
@ -208,7 +245,7 @@
}
$('#nebhale-time').text(data.nebhale.time);
$('#nebhale-res').text(data.nebhale.result).effect( "highlight", {color: '#428bca'} );
$('#nebhale-res').hide().text(data.nebhale.result).fadeIn();
if(data.nebhale.error){
$('#nebhale-error').text(data.nebhale.error).show();
} else {
@ -220,9 +257,10 @@
var elapsed = new Date().getTime() - start;
$("#goessner-time").text(elapsed);
$("#goessner-res").text(JSON.stringify(res, null, ' '));
$("#goessner-res").hide().text(JSON.stringify(res, null, ' ')).fadeIn();;
$('.prettyprinted').removeClass('prettyprinted');
prettyPrint();
}
});

1951
json-path-web-test/src/main/resources/js/bootstrap.js vendored

File diff suppressed because it is too large Load Diff

6
json-path-web-test/src/main/resources/js/bootstrap.min.js vendored

File diff suppressed because one or more lines are too long

4
json-path-web-test/src/main/resources/js/jquery.min.js vendored

File diff suppressed because one or more lines are too long

30
json-path-web-test/src/main/resources/js/prettify.js

@ -0,0 +1,30 @@
!function(){var q=null;window.PR_SHOULD_USE_CONTINUATION=!0;
(function(){function S(a){function d(e){var b=e.charCodeAt(0);if(b!==92)return b;var a=e.charAt(1);return(b=r[a])?b:"0"<=a&&a<="7"?parseInt(e.substring(1),8):a==="u"||a==="x"?parseInt(e.substring(2),16):e.charCodeAt(1)}function g(e){if(e<32)return(e<16?"\\x0":"\\x")+e.toString(16);e=String.fromCharCode(e);return e==="\\"||e==="-"||e==="]"||e==="^"?"\\"+e:e}function b(e){var b=e.substring(1,e.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),e=[],a=
b[0]==="^",c=["["];a&&c.push("^");for(var a=a?1:0,f=b.length;a<f;++a){var h=b[a];if(/\\[bdsw]/i.test(h))c.push(h);else{var h=d(h),l;a+2<f&&"-"===b[a+1]?(l=d(b[a+2]),a+=2):l=h;e.push([h,l]);l<65||h>122||(l<65||h>90||e.push([Math.max(65,h)|32,Math.min(l,90)|32]),l<97||h>122||e.push([Math.max(97,h)&-33,Math.min(l,122)&-33]))}}e.sort(function(e,a){return e[0]-a[0]||a[1]-e[1]});b=[];f=[];for(a=0;a<e.length;++a)h=e[a],h[0]<=f[1]+1?f[1]=Math.max(f[1],h[1]):b.push(f=h);for(a=0;a<b.length;++a)h=b[a],c.push(g(h[0])),
h[1]>h[0]&&(h[1]+1>h[0]&&c.push("-"),c.push(g(h[1])));c.push("]");return c.join("")}function s(e){for(var a=e.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),c=a.length,d=[],f=0,h=0;f<c;++f){var l=a[f];l==="("?++h:"\\"===l.charAt(0)&&(l=+l.substring(1))&&(l<=h?d[l]=-1:a[f]=g(l))}for(f=1;f<d.length;++f)-1===d[f]&&(d[f]=++x);for(h=f=0;f<c;++f)l=a[f],l==="("?(++h,d[h]||(a[f]="(?:")):"\\"===l.charAt(0)&&(l=+l.substring(1))&&l<=h&&
(a[f]="\\"+d[l]);for(f=0;f<c;++f)"^"===a[f]&&"^"!==a[f+1]&&(a[f]="");if(e.ignoreCase&&m)for(f=0;f<c;++f)l=a[f],e=l.charAt(0),l.length>=2&&e==="["?a[f]=b(l):e!=="\\"&&(a[f]=l.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return a.join("")}for(var x=0,m=!1,j=!1,k=0,c=a.length;k<c;++k){var i=a[k];if(i.ignoreCase)j=!0;else if(/[a-z]/i.test(i.source.replace(/\\u[\da-f]{4}|\\x[\da-f]{2}|\\[^UXux]/gi,""))){m=!0;j=!1;break}}for(var r={b:8,t:9,n:10,v:11,
f:12,r:13},n=[],k=0,c=a.length;k<c;++k){i=a[k];if(i.global||i.multiline)throw Error(""+i);n.push("(?:"+s(i)+")")}return RegExp(n.join("|"),j?"gi":"g")}function T(a,d){function g(a){var c=a.nodeType;if(c==1){if(!b.test(a.className)){for(c=a.firstChild;c;c=c.nextSibling)g(c);c=a.nodeName.toLowerCase();if("br"===c||"li"===c)s[j]="\n",m[j<<1]=x++,m[j++<<1|1]=a}}else if(c==3||c==4)c=a.nodeValue,c.length&&(c=d?c.replace(/\r\n?/g,"\n"):c.replace(/[\t\n\r ]+/g," "),s[j]=c,m[j<<1]=x,x+=c.length,m[j++<<1|1]=
a)}var b=/(?:^|\s)nocode(?:\s|$)/,s=[],x=0,m=[],j=0;g(a);return{a:s.join("").replace(/\n$/,""),d:m}}function H(a,d,g,b){d&&(a={a:d,e:a},g(a),b.push.apply(b,a.g))}function U(a){for(var d=void 0,g=a.firstChild;g;g=g.nextSibling)var b=g.nodeType,d=b===1?d?a:g:b===3?V.test(g.nodeValue)?a:d:d;return d===a?void 0:d}function C(a,d){function g(a){for(var j=a.e,k=[j,"pln"],c=0,i=a.a.match(s)||[],r={},n=0,e=i.length;n<e;++n){var z=i[n],w=r[z],t=void 0,f;if(typeof w==="string")f=!1;else{var h=b[z.charAt(0)];
if(h)t=z.match(h[1]),w=h[0];else{for(f=0;f<x;++f)if(h=d[f],t=z.match(h[1])){w=h[0];break}t||(w="pln")}if((f=w.length>=5&&"lang-"===w.substring(0,5))&&!(t&&typeof t[1]==="string"))f=!1,w="src";f||(r[z]=w)}h=c;c+=z.length;if(f){f=t[1];var l=z.indexOf(f),B=l+f.length;t[2]&&(B=z.length-t[2].length,l=B-f.length);w=w.substring(5);H(j+h,z.substring(0,l),g,k);H(j+h+l,f,I(w,f),k);H(j+h+B,z.substring(B),g,k)}else k.push(j+h,w)}a.g=k}var b={},s;(function(){for(var g=a.concat(d),j=[],k={},c=0,i=g.length;c<i;++c){var r=
g[c],n=r[3];if(n)for(var e=n.length;--e>=0;)b[n.charAt(e)]=r;r=r[1];n=""+r;k.hasOwnProperty(n)||(j.push(r),k[n]=q)}j.push(/[\S\s]/);s=S(j)})();var x=d.length;return g}function v(a){var d=[],g=[];a.tripleQuotedStrings?d.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?d.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/,
q,"'\"`"]):d.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&g.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var b=a.hashComments;b&&(a.cStyleComments?(b>1?d.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):d.push(["com",/^#(?:(?:define|e(?:l|nd)if|else|error|ifn?def|include|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),g.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h(?:h|pp|\+\+)?|[a-z]\w*)>/,q])):d.push(["com",
/^#[^\n\r]*/,q,"#"]));a.cStyleComments&&(g.push(["com",/^\/\/[^\n\r]*/,q]),g.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));if(b=a.regexLiterals){var s=(b=b>1?"":"\n\r")?".":"[\\S\\s]";g.push(["lang-regex",RegExp("^(?:^^\\.?|[+-]|[!=]=?=?|\\#|%=?|&&?=?|\\(|\\*=?|[+\\-]=|->|\\/=?|::?|<<?=?|>>?>?=?|,|;|\\?|@|\\[|~|{|\\^\\^?=?|\\|\\|?=?|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*("+("/(?=[^/*"+b+"])(?:[^/\\x5B\\x5C"+b+"]|\\x5C"+s+"|\\x5B(?:[^\\x5C\\x5D"+b+"]|\\x5C"+
s+")*(?:\\x5D|$))+/")+")")])}(b=a.types)&&g.push(["typ",b]);b=(""+a.keywords).replace(/^ | $/g,"");b.length&&g.push(["kwd",RegExp("^(?:"+b.replace(/[\s,]+/g,"|")+")\\b"),q]);d.push(["pln",/^\s+/,q," \r\n\t\u00a0"]);b="^.[^\\s\\w.$@'\"`/\\\\]*";a.regexLiterals&&(b+="(?!s*/)");g.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/,
q],["pun",RegExp(b),q]);return C(d,g)}function J(a,d,g){function b(a){var c=a.nodeType;if(c==1&&!x.test(a.className))if("br"===a.nodeName)s(a),a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)b(a);else if((c==3||c==4)&&g){var d=a.nodeValue,i=d.match(m);if(i)c=d.substring(0,i.index),a.nodeValue=c,(d=d.substring(i.index+i[0].length))&&a.parentNode.insertBefore(j.createTextNode(d),a.nextSibling),s(a),c||a.parentNode.removeChild(a)}}function s(a){function b(a,c){var d=
c?a.cloneNode(!1):a,e=a.parentNode;if(e){var e=b(e,1),g=a.nextSibling;e.appendChild(d);for(var i=g;i;i=g)g=i.nextSibling,e.appendChild(i)}return d}for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),d;(d=a.parentNode)&&d.nodeType===1;)a=d;c.push(a)}for(var x=/(?:^|\s)nocode(?:\s|$)/,m=/\r\n?|\n/,j=a.ownerDocument,k=j.createElement("li");a.firstChild;)k.appendChild(a.firstChild);for(var c=[k],i=0;i<c.length;++i)b(c[i]);d===(d|0)&&c[0].setAttribute("value",d);var r=j.createElement("ol");
r.className="linenums";for(var d=Math.max(0,d-1|0)||0,i=0,n=c.length;i<n;++i)k=c[i],k.className="L"+(i+d)%10,k.firstChild||k.appendChild(j.createTextNode("\u00a0")),r.appendChild(k);a.appendChild(r)}function p(a,d){for(var g=d.length;--g>=0;){var b=d[g];F.hasOwnProperty(b)?D.console&&console.warn("cannot override language handler %s",b):F[b]=a}}function I(a,d){if(!a||!F.hasOwnProperty(a))a=/^\s*</.test(d)?"default-markup":"default-code";return F[a]}function K(a){var d=a.h;try{var g=T(a.c,a.i),b=g.a;
a.a=b;a.d=g.d;a.e=0;I(d,b)(a);var s=/\bMSIE\s(\d+)/.exec(navigator.userAgent),s=s&&+s[1]<=8,d=/\n/g,x=a.a,m=x.length,g=0,j=a.d,k=j.length,b=0,c=a.g,i=c.length,r=0;c[i]=m;var n,e;for(e=n=0;e<i;)c[e]!==c[e+2]?(c[n++]=c[e++],c[n++]=c[e++]):e+=2;i=n;for(e=n=0;e<i;){for(var p=c[e],w=c[e+1],t=e+2;t+2<=i&&c[t+1]===w;)t+=2;c[n++]=p;c[n++]=w;e=t}c.length=n;var f=a.c,h;if(f)h=f.style.display,f.style.display="none";try{for(;b<k;){var l=j[b+2]||m,B=c[r+2]||m,t=Math.min(l,B),A=j[b+1],G;if(A.nodeType!==1&&(G=x.substring(g,
t))){s&&(G=G.replace(d,"\r"));A.nodeValue=G;var L=A.ownerDocument,o=L.createElement("span");o.className=c[r+1];var v=A.parentNode;v.replaceChild(o,A);o.appendChild(A);g<l&&(j[b+1]=A=L.createTextNode(x.substring(t,l)),v.insertBefore(A,o.nextSibling))}g=t;g>=l&&(b+=2);g>=B&&(r+=2)}}finally{if(f)f.style.display=h}}catch(u){D.console&&console.log(u&&u.stack||u)}}var D=window,y=["break,continue,do,else,for,if,return,while"],E=[[y,"auto,case,char,const,default,double,enum,extern,float,goto,inline,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"],
"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],M=[E,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,delegate,dynamic_cast,explicit,export,friend,generic,late_check,mutable,namespace,nullptr,property,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],N=[E,"abstract,assert,boolean,byte,extends,final,finally,implements,import,instanceof,interface,null,native,package,strictfp,super,synchronized,throws,transient"],
O=[N,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,internal,into,is,let,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var,virtual,where"],E=[E,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],P=[y,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"],
Q=[y,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],W=[y,"as,assert,const,copy,drop,enum,extern,fail,false,fn,impl,let,log,loop,match,mod,move,mut,priv,pub,pure,ref,self,static,struct,true,trait,type,unsafe,use"],y=[y,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],R=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)\b/,
V=/\S/,X=v({keywords:[M,O,E,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",P,Q,y],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),F={};p(X,["default-code"]);p(C([],[["pln",/^[^<?]+/],["dec",/^<!\w[^>]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",
/^<xmp\b[^>]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^<script\b[^>]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^<style\b[^>]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);p(C([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/],
["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css",/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);p(C([],[["atv",/^[\S\s]+/]]),["uq.val"]);p(v({keywords:M,hashComments:!0,cStyleComments:!0,types:R}),["c","cc","cpp","cxx","cyc","m"]);p(v({keywords:"null,true,false"}),["json"]);p(v({keywords:O,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:R}),
["cs"]);p(v({keywords:N,cStyleComments:!0}),["java"]);p(v({keywords:y,hashComments:!0,multiLineStrings:!0}),["bash","bsh","csh","sh"]);p(v({keywords:P,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}),["cv","py","python"]);p(v({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:2}),["perl","pl","pm"]);p(v({keywords:Q,
hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb","ruby"]);p(v({keywords:E,cStyleComments:!0,regexLiterals:!0}),["javascript","js"]);p(v({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,throw,true,try,unless,until,when,while,yes",hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);p(v({keywords:W,cStyleComments:!0,multilineStrings:!0}),["rc","rs","rust"]);
p(C([],[["str",/^[\S\s]+/]]),["regex"]);var Y=D.PR={createSimpleLexer:C,registerLangHandler:p,sourceDecorator:v,PR_ATTRIB_NAME:"atn",PR_ATTRIB_VALUE:"atv",PR_COMMENT:"com",PR_DECLARATION:"dec",PR_KEYWORD:"kwd",PR_LITERAL:"lit",PR_NOCODE:"nocode",PR_PLAIN:"pln",PR_PUNCTUATION:"pun",PR_SOURCE:"src",PR_STRING:"str",PR_TAG:"tag",PR_TYPE:"typ",prettyPrintOne:D.prettyPrintOne=function(a,d,g){var b=document.createElement("div");b.innerHTML="<pre>"+a+"</pre>";b=b.firstChild;g&&J(b,g,!0);K({h:d,j:g,c:b,i:1});
return b.innerHTML},prettyPrint:D.prettyPrint=function(a,d){function g(){for(var b=D.PR_SHOULD_USE_CONTINUATION?c.now()+250:Infinity;i<p.length&&c.now()<b;i++){for(var d=p[i],j=h,k=d;k=k.previousSibling;){var m=k.nodeType,o=(m===7||m===8)&&k.nodeValue;if(o?!/^\??prettify\b/.test(o):m!==3||/\S/.test(k.nodeValue))break;if(o){j={};o.replace(/\b(\w+)=([\w%+\-.:]+)/g,function(a,b,c){j[b]=c});break}}k=d.className;if((j!==h||e.test(k))&&!v.test(k)){m=!1;for(o=d.parentNode;o;o=o.parentNode)if(f.test(o.tagName)&&
o.className&&e.test(o.className)){m=!0;break}if(!m){d.className+=" prettyprinted";m=j.lang;if(!m){var m=k.match(n),y;if(!m&&(y=U(d))&&t.test(y.tagName))m=y.className.match(n);m&&(m=m[1])}if(w.test(d.tagName))o=1;else var o=d.currentStyle,u=s.defaultView,o=(o=o?o.whiteSpace:u&&u.getComputedStyle?u.getComputedStyle(d,q).getPropertyValue("white-space"):0)&&"pre"===o.substring(0,3);u=j.linenums;if(!(u=u==="true"||+u))u=(u=k.match(/\blinenums\b(?::(\d+))?/))?u[1]&&u[1].length?+u[1]:!0:!1;u&&J(d,u,o);r=
{h:m,c:d,j:u,i:o};K(r)}}}i<p.length?setTimeout(g,250):"function"===typeof a&&a()}for(var b=d||document.body,s=b.ownerDocument||document,b=[b.getElementsByTagName("pre"),b.getElementsByTagName("code"),b.getElementsByTagName("xmp")],p=[],m=0;m<b.length;++m)for(var j=0,k=b[m].length;j<k;++j)p.push(b[m][j]);var b=q,c=Date;c.now||(c={now:function(){return+new Date}});var i=0,r,n=/\blang(?:uage)?-([\w.]+)(?!\S)/,e=/\bprettyprint\b/,v=/\bprettyprinted\b/,w=/pre|xmp/i,t=/^code$/i,f=/^(?:pre|code|xmp)$/i,
h={};g()}};typeof define==="function"&&define.amd&&define("google-code-prettify",[],function(){return Y})})();}()

463
json-path-web-test/src/main/resources/js/tooltip.js

@ -0,0 +1,463 @@
/* ========================================================================
* Bootstrap: tooltip.js v3.1.1
* http://getbootstrap.com/javascript/#tooltip
* Inspired by the original jQuery.tipsy by Jason Frame
* ========================================================================
* Copyright 2011-2014 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */
+function () { 'use strict';
(function (o_o) {
typeof define == 'function' && define.amd ? define(['jquery'], o_o) :
typeof exports == 'object' ? o_o(require('jquery')) : o_o(jQuery)
})(function ($) {
// TOOLTIP PUBLIC CLASS DEFINITION
// ===============================
var Tooltip = function (element, options) {
this.type =
this.options =
this.enabled =
this.timeout =
this.hoverState =
this.$element = null
this.init('tooltip', element, options)
}
Tooltip.VERSION = '3.1.1'
Tooltip.DEFAULTS = {
animation: true,
placement: 'top',
selector: false,
template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
trigger: 'hover focus',
title: '',
delay: 0,
html: false,
container: false,
viewport: {
selector: 'body',
padding: 0
}
}
Tooltip.prototype.init = function (type, element, options) {
this.enabled = true
this.type = type
this.$element = $(element)
this.options = this.getOptions(options)
this.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport)
var triggers = this.options.trigger.split(' ')
for (var i = triggers.length; i--;) {
var trigger = triggers[i]
if (trigger == 'click') {
this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
} else if (trigger != 'manual') {
var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin'
var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'
this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
}
}
this.options.selector ?
(this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
this.fixTitle()
}
Tooltip.prototype.getDefaults = function () {
return Tooltip.DEFAULTS
}
Tooltip.prototype.getOptions = function (options) {
options = $.extend({}, this.getDefaults(), this.$element.data(), options)
if (options.delay && typeof options.delay == 'number') {
options.delay = {
show: options.delay,
hide: options.delay
}
}
return options
}
Tooltip.prototype.getDelegateOptions = function () {
var options = {}
var defaults = this.getDefaults()
this._options && $.each(this._options, function (key, value) {
if (defaults[key] != value) options[key] = value
})
return options
}
Tooltip.prototype.enter = function (obj) {
var self = obj instanceof this.constructor ?
obj : $(obj.currentTarget).data('bs.' + this.type)
if (!self) {
self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
$(obj.currentTarget).data('bs.' + this.type, self)
}
clearTimeout(self.timeout)
self.hoverState = 'in'
if (!self.options.delay || !self.options.delay.show) return self.show()
self.timeout = setTimeout(function () {
if (self.hoverState == 'in') self.show()
}, self.options.delay.show)
}
Tooltip.prototype.leave = function (obj) {
var self = obj instanceof this.constructor ?
obj : $(obj.currentTarget).data('bs.' + this.type)
if (!self) {
self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
$(obj.currentTarget).data('bs.' + this.type, self)
}
clearTimeout(self.timeout)
self.hoverState = 'out'
if (!self.options.delay || !self.options.delay.hide) return self.hide()
self.timeout = setTimeout(function () {
if (self.hoverState == 'out') self.hide()
}, self.options.delay.hide)
}
Tooltip.prototype.show = function () {
var e = $.Event('show.bs.' + this.type)
if (this.hasContent() && this.enabled) {
this.$element.trigger(e)
var inDom = $.contains(document.documentElement, this.$element[0])
if (e.isDefaultPrevented() || !inDom) return
var that = this
var $tip = this.tip()
var tipId = this.getUID(this.type)
this.setContent()
$tip.attr('id', tipId)
this.$element.attr('aria-describedby', tipId)
if (this.options.animation) $tip.addClass('fade')
var placement = typeof this.options.placement == 'function' ?
this.options.placement.call(this, $tip[0], this.$element[0]) :
this.options.placement
var autoToken = /\s?auto?\s?/i
var autoPlace = autoToken.test(placement)
if (autoPlace) placement = placement.replace(autoToken, '') || 'top'
$tip
.detach()
.css({ top: 0, left: 0, display: 'block' })
.addClass(placement)
.data('bs.' + this.type, this)
this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
var pos = this.getPosition()
var actualWidth = $tip[0].offsetWidth
var actualHeight = $tip[0].offsetHeight
if (autoPlace) {
var orgPlacement = placement
var $parent = this.$element.parent()
var parentDim = this.getPosition($parent)
placement = placement == 'bottom' && pos.top + pos.height + actualHeight - parentDim.scroll > parentDim.height ? 'top' :
placement == 'top' && pos.top - parentDim.scroll - actualHeight < 0 ? 'bottom' :
placement == 'right' && pos.right + actualWidth > parentDim.width ? 'left' :
placement == 'left' && pos.left - actualWidth < parentDim.left ? 'right' :
placement
$tip
.removeClass(orgPlacement)
.addClass(placement)
}
var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
this.applyPlacement(calculatedOffset, placement)
this.hoverState = null
var complete = function () {
that.$element.trigger('shown.bs.' + that.type)
}
$.support.transition && this.$tip.hasClass('fade') ?
$tip
.one('bsTransitionEnd', complete)
.emulateTransitionEnd(150) :
complete()
}
}
Tooltip.prototype.applyPlacement = function (offset, placement) {
var $tip = this.tip()
var width = $tip[0].offsetWidth
var height = $tip[0].offsetHeight
// manually read margins because getBoundingClientRect includes difference
var marginTop = parseInt($tip.css('margin-top'), 10)
var marginLeft = parseInt($tip.css('margin-left'), 10)
// we must check for NaN for ie 8/9
if (isNaN(marginTop)) marginTop = 0
if (isNaN(marginLeft)) marginLeft = 0
offset.top = offset.top + marginTop
offset.left = offset.left + marginLeft
// $.fn.offset doesn't round pixel values
// so we use setOffset directly with our own function B-0
$.offset.setOffset($tip[0], $.extend({
using: function (props) {
$tip.css({
top: Math.round(props.top),
left: Math.round(props.left)
})
}
}, offset), 0)
$tip.addClass('in')
// check to see if placing tip in new offset caused the tip to resize itself
var actualWidth = $tip[0].offsetWidth
var actualHeight = $tip[0].offsetHeight
if (placement == 'top' && actualHeight != height) {
offset.top = offset.top + height - actualHeight
}
var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)
if (delta.left) offset.left += delta.left
else offset.top += delta.top
var arrowDelta = delta.left ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
var arrowPosition = delta.left ? 'left' : 'top'
var arrowOffsetPosition = delta.left ? 'offsetWidth' : 'offsetHeight'
$tip.offset(offset)
this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], arrowPosition)
}
Tooltip.prototype.replaceArrow = function (delta, dimension, position) {
this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + '%') : '')
}
Tooltip.prototype.setContent = function () {
var $tip = this.tip()
var title = this.getTitle()
$tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
$tip.removeClass('fade in top bottom left right')
}
Tooltip.prototype.hide = function () {
var that = this
var $tip = this.tip()
var e = $.Event('hide.bs.' + this.type)
this.$element.removeAttr('aria-describedby')
function complete() {
if (that.hoverState != 'in') $tip.detach()
that.$element.trigger('hidden.bs.' + that.type)
}
this.$element.trigger(e)
if (e.isDefaultPrevented()) return
$tip.removeClass('in')
$.support.transition && this.$tip.hasClass('fade') ?
$tip
.one('bsTransitionEnd', complete)
.emulateTransitionEnd(150) :
complete()
this.hoverState = null
return this
}
Tooltip.prototype.fixTitle = function () {
var $e = this.$element
if ($e.attr('title') || typeof ($e.attr('data-original-title')) != 'string') {
$e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
}
}
Tooltip.prototype.hasContent = function () {
return this.getTitle()
}
Tooltip.prototype.getPosition = function ($element) {
$element = $element || this.$element
var el = $element[0]
var isBody = el.tagName == 'BODY'
return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : null, {
scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop(),
width: isBody ? $(window).width() : $element.outerWidth(),
height: isBody ? $(window).height() : $element.outerHeight()
}, isBody ? { top: 0, left: 0 } : $element.offset())
}
Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } :
placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } :
placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
/* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width }
}
Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
var delta = { top: 0, left: 0 }
if (!this.$viewport) return delta
var viewportPadding = this.options.viewport && this.options.viewport.padding || 0
var viewportDimensions = this.getPosition(this.$viewport)
if (/right|left/.test(placement)) {
var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll
var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
if (topEdgeOffset < viewportDimensions.top) { // top overflow
delta.top = viewportDimensions.top - topEdgeOffset
} else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset
}
} else {
var leftEdgeOffset = pos.left - viewportPadding
var rightEdgeOffset = pos.left + viewportPadding + actualWidth
if (leftEdgeOffset < viewportDimensions.left) { // left overflow
delta.left = viewportDimensions.left - leftEdgeOffset
} else if (rightEdgeOffset > viewportDimensions.width) { // right overflow
delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
}
}
return delta
}
Tooltip.prototype.getTitle = function () {
var title
var $e = this.$element
var o = this.options
title = $e.attr('data-original-title')
|| (typeof o.title == 'function' ? o.title.call($e[0]) : o.title)
return title
}
Tooltip.prototype.getUID = function (prefix) {
do prefix += ~~(Math.random() * 1000000)
while (document.getElementById(prefix))
return prefix
}
Tooltip.prototype.tip = function () {
return (this.$tip = this.$tip || $(this.options.template))
}
Tooltip.prototype.arrow = function () {
return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow'))
}
Tooltip.prototype.validate = function () {
if (!this.$element[0].parentNode) {
this.hide()
this.$element = null
this.options = null
}
}
Tooltip.prototype.enable = function () {
this.enabled = true
}
Tooltip.prototype.disable = function () {
this.enabled = false
}
Tooltip.prototype.toggleEnabled = function () {
this.enabled = !this.enabled
}
Tooltip.prototype.toggle = function (e) {
var self = this
if (e) {
self = $(e.currentTarget).data('bs.' + this.type)
if (!self) {
self = new this.constructor(e.currentTarget, this.getDelegateOptions())
$(e.currentTarget).data('bs.' + this.type, self)
}
}
self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
}
Tooltip.prototype.destroy = function () {
clearTimeout(this.timeout)
this.hide().$element.off('.' + this.type).removeData('bs.' + this.type)
}
// TOOLTIP PLUGIN DEFINITION
// =========================
function Plugin(option) {
return this.each(function () {
var $this = $(this)
var data = $this.data('bs.tooltip')
var options = typeof option == 'object' && option
if (!data && option == 'destroy') return
if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
if (typeof option == 'string') data[option]()
})
}
var old = $.fn.tooltip
$.fn.tooltip = Plugin
$.fn.tooltip.Constructor = Tooltip
// TOOLTIP NO CONFLICT
// ===================
$.fn.tooltip.noConflict = function () {
$.fn.tooltip = old
return this
}
})
}();
Loading…
Cancel
Save