Revision 31555
Added by Claudio Atzori about 10 years ago
modules/dnet-modular-oai-explorer-ui/tags/dnet-modular-oai-explorer-ui-1.0/pom.xml | ||
---|---|---|
1 |
<?xml version="1.0" encoding="UTF-8"?> |
|
2 |
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> |
|
3 |
<parent> |
|
4 |
<groupId>eu.dnetlib</groupId> |
|
5 |
<artifactId>dnet-parent</artifactId> |
|
6 |
<version>1.0.0</version> |
|
7 |
<relativePath /> |
|
8 |
</parent> |
|
9 |
<modelVersion>4.0.0</modelVersion> |
|
10 |
<groupId>eu.dnetlib</groupId> |
|
11 |
<artifactId>dnet-modular-oai-explorer-ui</artifactId> |
|
12 |
<packaging>jar</packaging> |
|
13 |
<version>1.0</version> |
|
14 |
<scm> |
|
15 |
<developerConnection>scm:svn:https://svn.driver.research-infrastructures.eu/driver/dnet40/modules/dnet-modular-oai-explorer-ui/tags/dnet-modular-oai-explorer-ui-1.0</developerConnection> |
|
16 |
</scm> |
|
17 |
<dependencies> |
|
18 |
<dependency> |
|
19 |
<groupId>eu.dnetlib</groupId> |
|
20 |
<artifactId>dnet-modular-ui</artifactId> |
|
21 |
<version>[2.0.0,3.0.0)</version> |
|
22 |
</dependency> |
|
23 |
<dependency> |
|
24 |
<groupId>javax.servlet</groupId> |
|
25 |
<artifactId>javax.servlet-api</artifactId> |
|
26 |
<version>${javax.servlet.version}</version> |
|
27 |
<scope>provided</scope> |
|
28 |
</dependency> |
|
29 |
<dependency> |
|
30 |
<groupId>commons-httpclient</groupId> |
|
31 |
<artifactId>commons-httpclient</artifactId> |
|
32 |
<version>3.1</version> |
|
33 |
</dependency> |
|
34 |
<dependency> |
|
35 |
<groupId>junit</groupId> |
|
36 |
<artifactId>junit</artifactId> |
|
37 |
<version>${junit.version}</version> |
|
38 |
<scope>test</scope> |
|
39 |
</dependency> |
|
40 |
</dependencies> |
|
41 |
</project> |
modules/dnet-modular-oai-explorer-ui/tags/dnet-modular-oai-explorer-ui-1.0/deploy.info | ||
---|---|---|
1 |
{"type_source": "SVN", "goal": "package -U -T 4C source:jar", "url": "http://svn-public.driver.research-infrastructures.eu/driver/dnet40/modules/dnet-modular-oai-explorer-ui/trunk/", "deploy_repository": "dnet4-snapshots", "version": "4", "mail": "sandro.labruzzo@isti.cnr.it,michele.artini@isti.cnr.it, claudio.atzori@isti.cnr.it, alessia.bardi@isti.cnr.it", "deploy_repository_url": "http://maven.research-infrastructures.eu/nexus/content/repositories/dnet4-snapshots", "name": "dnet-modular-oai-explorer-ui"} |
modules/dnet-modular-oai-explorer-ui/tags/dnet-modular-oai-explorer-ui-1.0/src/main/resources/eu/dnetlib/functionality/modular/ui/xslt/oai.xslt | ||
---|---|---|
1 |
<?xml version="1.0" encoding="utf-8"?> |
|
2 |
|
|
3 |
<xsl:stylesheet version="1.0" |
|
4 |
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:oai="http://www.openarchives.org/OAI/2.0/" |
|
5 |
xmlns:oai_dc="http://www.openarchives.org/OAI/2.0/oai_dc/" |
|
6 |
xmlns:dc="http://purl.org/dc/doc:elements/1.1/" |
|
7 |
exclude-result-prefixes="oai oai_dc dc"> |
|
8 |
|
|
9 |
<xsl:output method="html" omit-xml-declaration="yes" encoding="UTF-8" standalone="no" /> |
|
10 |
|
|
11 |
<xsl:template match="/"> |
|
12 |
<xsl:apply-templates select="oai:OAI-PMH/oai:error" /> |
|
13 |
<xsl:apply-templates select="oai:OAI-PMH/oai:Identify" /> |
|
14 |
<xsl:apply-templates select="oai:OAI-PMH/oai:ListSets" /> |
|
15 |
<xsl:apply-templates select="oai:OAI-PMH/oai:ListRecords" /> |
|
16 |
<xsl:apply-templates select="oai:OAI-PMH/oai:ListIdentifiers" /> |
|
17 |
<xsl:apply-templates select="oai:OAI-PMH/oai:ListMetadataFormats" /> |
|
18 |
<xsl:apply-templates select="oai:OAI-PMH/oai:GetRecord" /> |
|
19 |
</xsl:template> |
|
20 |
|
|
21 |
<xsl:template match="oai:OAI-PMH/oai:error"> |
|
22 |
<div class="alert alert-danger"> |
|
23 |
<h4>Error</h4> |
|
24 |
<p> |
|
25 |
<xsl:value-of select="text()"></xsl:value-of> |
|
26 |
</p> |
|
27 |
</div> |
|
28 |
</xsl:template> |
|
29 |
|
|
30 |
<xsl:template match="oai:OAI-PMH/oai:Identify"> |
|
31 |
<xsl:call-template name="verbTitle"> |
|
32 |
<xsl:with-param name="title" select="string('Repository Information')"/> |
|
33 |
</xsl:call-template> |
|
34 |
|
|
35 |
<table class="table table-striped table-bordered"> |
|
36 |
<tr> |
|
37 |
<td> |
|
38 |
<b>Repository Name</b> |
|
39 |
</td> |
|
40 |
<td> |
|
41 |
<xsl:value-of select="oai:repositoryName/text()" /> |
|
42 |
</td> |
|
43 |
</tr> |
|
44 |
<xsl:for-each select="oai:adminEmail"> |
|
45 |
<tr> |
|
46 |
<td> |
|
47 |
<b>E-Mail Contact</b> |
|
48 |
</td> |
|
49 |
<td> |
|
50 |
<a href="{concat('mailto:', text())}"> |
|
51 |
<xsl:value-of select="text()" /> |
|
52 |
</a> |
|
53 |
</td> |
|
54 |
</tr> |
|
55 |
</xsl:for-each> |
|
56 |
<tr> |
|
57 |
<td> |
|
58 |
<b>Description</b> |
|
59 |
</td> |
|
60 |
<td> |
|
61 |
<xsl:value-of select="oai:description/node()/text()" /> |
|
62 |
</td> |
|
63 |
|
|
64 |
</tr> |
|
65 |
<tr> |
|
66 |
<td> |
|
67 |
<b>Protocol Version</b> |
|
68 |
</td> |
|
69 |
<td> |
|
70 |
<xsl:value-of select="oai:protocolVersion/text()" /> |
|
71 |
</td> |
|
72 |
|
|
73 |
</tr> |
|
74 |
<tr> |
|
75 |
<td> |
|
76 |
<b>Earliest Registered Date</b> |
|
77 |
</td> |
|
78 |
<td> |
|
79 |
<xsl:value-of select="translate(oai:earliestDatestamp/text(), 'TZ' ,' ')" /> |
|
80 |
</td> |
|
81 |
|
|
82 |
</tr> |
|
83 |
<tr> |
|
84 |
<td> |
|
85 |
<b>Date Granularity</b> |
|
86 |
</td> |
|
87 |
<td> |
|
88 |
<xsl:value-of select="translate(oai:granularity/text(), 'TZ', ' ')" /> |
|
89 |
</td> |
|
90 |
|
|
91 |
</tr> |
|
92 |
<tr> |
|
93 |
<td> |
|
94 |
<b>Deletion Mode</b> |
|
95 |
</td> |
|
96 |
<td> |
|
97 |
<xsl:value-of select="oai:deletedRecord/text()" /> |
|
98 |
</td> |
|
99 |
|
|
100 |
</tr> |
|
101 |
</table> |
|
102 |
</xsl:template> |
|
103 |
|
|
104 |
<xsl:template match="oai:OAI-PMH/oai:ListSets"> |
|
105 |
<xsl:call-template name="verbTitle"> |
|
106 |
<xsl:with-param name="title" select="string('Available Sets')"/> |
|
107 |
<xsl:with-param name="countPath" select="oai:set" /> |
|
108 |
</xsl:call-template> |
|
109 |
|
|
110 |
<div class="list-group"> |
|
111 |
<xsl:for-each select="oai:set"> |
|
112 |
<div class="list-group-item"> |
|
113 |
<h5 class="list-group-item-heading"> |
|
114 |
<xsl:choose> |
|
115 |
<xsl:when test="string-length(oai:setName/text()) > 83"> |
|
116 |
<xsl:value-of select="substring(oai:setName/text(),0, 80 )" /> |
|
117 |
... |
|
118 |
</xsl:when> |
|
119 |
<xsl:otherwise> |
|
120 |
<xsl:value-of select="oai:setName/text()" /> |
|
121 |
</xsl:otherwise> |
|
122 |
</xsl:choose> |
|
123 |
<small> |
|
124 |
[ |
|
125 |
<xsl:value-of select="oai:setSpec/text()" /> |
|
126 |
] |
|
127 |
</small> |
|
128 |
</h5> |
|
129 |
<div class="spec"> |
|
130 |
<div class="btn-group"> |
|
131 |
<button type="button" class="btn btn-default btn-sm" ng-click="listRecords('oai_dc', '{oai:setSpec/text()}')">Records</button> |
|
132 |
<button type="button" class="btn btn-default btn-sm" ng-click="listIdentifiers('oai_dc', '{oai:setSpec/text()}')">Identifiers</button> |
|
133 |
</div> |
|
134 |
</div> |
|
135 |
</div> |
|
136 |
</xsl:for-each> |
|
137 |
</div> |
|
138 |
|
|
139 |
<xsl:apply-templates select="oai:resumptionToken" /> |
|
140 |
</xsl:template> |
|
141 |
|
|
142 |
<xsl:template match="oai:OAI-PMH/oai:ListRecords|oai:OAI-PMH/oai:GetRecord"> |
|
143 |
|
|
144 |
<xsl:choose> |
|
145 |
<xsl:when test="local-name() = 'GetRecord'"> |
|
146 |
<xsl:call-template name="verbTitle"> |
|
147 |
<xsl:with-param name="title" select="string('Record Details')"/> |
|
148 |
<xsl:with-param name="countPath" select="oai:record" /> |
|
149 |
</xsl:call-template> |
|
150 |
</xsl:when> |
|
151 |
<xsl:otherwise> |
|
152 |
<xsl:call-template name="verbTitle"> |
|
153 |
<xsl:with-param name="title" select="string('List of Records')"/> |
|
154 |
<xsl:with-param name="countPath" select="oai:record" /> |
|
155 |
</xsl:call-template> |
|
156 |
</xsl:otherwise> |
|
157 |
</xsl:choose> |
|
158 |
|
|
159 |
<xsl:apply-templates select="oai:resumptionToken" /> |
|
160 |
|
|
161 |
<xsl:for-each select="oai:record"> |
|
162 |
<div class="panel panel-default"> |
|
163 |
<div class="panel-body"> |
|
164 |
<table class="table"> |
|
165 |
<tr> |
|
166 |
<th>Identifier</th> |
|
167 |
<td><xsl:value-of select="oai:header/oai:identifier/text()" /></td> |
|
168 |
</tr> |
|
169 |
<tr> |
|
170 |
<th>Last Modfied</th> |
|
171 |
<td><xsl:value-of select="translate(oai:header/oai:datestamp/text(), 'TZ', ' ')"></xsl:value-of></td> |
|
172 |
</tr> |
|
173 |
<tr> |
|
174 |
<th>Sets</th> |
|
175 |
<td> |
|
176 |
<xsl:for-each select="oai:header/oai:setSpec"> |
|
177 |
<xsl:if test="position() > 1">, </xsl:if> |
|
178 |
<a href="javascript:void(0)" ng-click="listRecords('oai_dc', '{text()}')"> |
|
179 |
<xsl:value-of select="text()" /> |
|
180 |
</a> |
|
181 |
</xsl:for-each> |
|
182 |
</td> |
|
183 |
</tr> |
|
184 |
<tr> |
|
185 |
<th>Record</th> |
|
186 |
<td> |
|
187 |
<xsl:choose> |
|
188 |
<xsl:when test="count(oai:metadata/*) > 0"> |
|
189 |
<xsl:for-each select="oai:metadata/*"> |
|
190 |
<xsl:call-template name="showRecord" /> |
|
191 |
</xsl:for-each> |
|
192 |
</xsl:when> |
|
193 |
<xsl:otherwise> |
|
194 |
<span class="label label-warning">Missing Metadata</span> |
|
195 |
</xsl:otherwise> |
|
196 |
</xsl:choose> |
|
197 |
</td> |
|
198 |
</tr> |
|
199 |
</table> |
|
200 |
<!-- <button class="btn btn-default btn-sm pull-right" ng-click="getRecord('{oai:header/oai:identifier/text()}', 'oai_dc')">View Details</button> --> |
|
201 |
</div> |
|
202 |
</div> |
|
203 |
</xsl:for-each> |
|
204 |
|
|
205 |
<xsl:apply-templates select="oai:resumptionToken" /> |
|
206 |
</xsl:template> |
|
207 |
|
|
208 |
|
|
209 |
<xsl:template name="showRecord"> |
|
210 |
<xsl:param name="indent" select="string('')" /> |
|
211 |
<xsl:value-of select="$indent" /> |
|
212 |
<strong><xsl:value-of select="local-name()"/>: </strong><xsl:value-of select="text()"/> |
|
213 |
<xsl:if test="count(@*) > 0"> |
|
214 |
[<xsl:for-each select="@*"> |
|
215 |
<xsl:if test="position() > 1">, </xsl:if> |
|
216 |
<xsl:value-of select="local-name()" />: <xsl:value-of select="." /> |
|
217 |
</xsl:for-each>] |
|
218 |
</xsl:if> |
|
219 |
<br /> |
|
220 |
<xsl:for-each select="*"> |
|
221 |
<xsl:call-template name="showRecord"> |
|
222 |
<xsl:with-param name="indent" select="concat('    ', $indent)" /> |
|
223 |
</xsl:call-template> |
|
224 |
</xsl:for-each> |
|
225 |
</xsl:template> |
|
226 |
|
|
227 |
<xsl:template match="oai:OAI-PMH/oai:ListIdentifiers"> |
|
228 |
<xsl:call-template name="verbTitle"> |
|
229 |
<xsl:with-param name="title" select="string('List of Identifiers')"/> |
|
230 |
<xsl:with-param name="countPath" select="oai:header" /> |
|
231 |
</xsl:call-template> |
|
232 |
|
|
233 |
<xsl:apply-templates select="oai:resumptionToken" /> |
|
234 |
|
|
235 |
<xsl:for-each select="oai:header"> |
|
236 |
<div class="panel panel-default"> |
|
237 |
<div class="panel-body"> |
|
238 |
<table class="table"> |
|
239 |
<tr> |
|
240 |
<th>Identifier</th> |
|
241 |
<td><xsl:value-of select="oai:identifier/text()" /></td> |
|
242 |
</tr> |
|
243 |
<tr> |
|
244 |
<th>Last Modfied</th> |
|
245 |
<td><xsl:value-of select="translate(oai:datestamp/text(), 'TZ', ' ')"></xsl:value-of></td> |
|
246 |
</tr> |
|
247 |
<tr> |
|
248 |
<th>Sets</th> |
|
249 |
<td> |
|
250 |
<xsl:for-each select="oai:setSpec"> |
|
251 |
<xsl:if test="position() > 1">, </xsl:if> |
|
252 |
<a href="javascript:void(0)" ng-click="listRecords('oai_dc', '{text()}')"> |
|
253 |
<xsl:value-of select="text()" /> |
|
254 |
</a> |
|
255 |
</xsl:for-each> |
|
256 |
</td> |
|
257 |
</tr> |
|
258 |
</table> |
|
259 |
<button class="btn btn-default btn-sm pull-right" ng-click="getRecord('{oai:identifier/text()}', 'oai_dc')">View Details</button> |
|
260 |
</div> |
|
261 |
</div> |
|
262 |
</xsl:for-each> |
|
263 |
|
|
264 |
<xsl:apply-templates select="oai:resumptionToken" /> |
|
265 |
</xsl:template> |
|
266 |
|
|
267 |
<xsl:template match="oai:OAI-PMH/oai:ListMetadataFormats"> |
|
268 |
<xsl:call-template name="verbTitle"> |
|
269 |
<xsl:with-param name="title" select="string('List of Metadata Formats')"/> |
|
270 |
<xsl:with-param name="countPath" select="oai:metadataFormat" /> |
|
271 |
</xsl:call-template> |
|
272 |
|
|
273 |
<xsl:for-each select="oai:metadataFormat"> |
|
274 |
<div class="panel panel-default"> |
|
275 |
<div class="panel-heading"> |
|
276 |
<div class="row"> |
|
277 |
<div class="col-lg-9"> |
|
278 |
<h5> |
|
279 |
<xsl:value-of select="oai:metadataPrefix/text()"></xsl:value-of> |
|
280 |
</h5> |
|
281 |
</div> |
|
282 |
<div class="col-lg-3"> |
|
283 |
<button class="btn btn-default btn-sm pull-right" ng-click="listRecords('{oai:metadataPrefix/text()}', null)"> |
|
284 |
List Records |
|
285 |
</button> |
|
286 |
</div> |
|
287 |
</div> |
|
288 |
</div> |
|
289 |
<div class="panel-body"> |
|
290 |
<div class="row"> |
|
291 |
<div class="col-lg-9"> |
|
292 |
<h5> |
|
293 |
<strong>Namespace: </strong><xsl:value-of select="oai:metadataNamespace/text()" /> |
|
294 |
</h5> |
|
295 |
<h5> |
|
296 |
<strong>Schema: </strong><xsl:value-of select="oai:schema/text()"/> |
|
297 |
</h5> |
|
298 |
</div> |
|
299 |
</div> |
|
300 |
</div> |
|
301 |
</div> |
|
302 |
</xsl:for-each> |
|
303 |
</xsl:template> |
|
304 |
|
|
305 |
<xsl:template match="oai:resumptionToken"> |
|
306 |
<xsl:if test="text() != ''"> |
|
307 |
<div class="text-center"> |
|
308 |
<button class="btn btn-primary btn-sm" ng-click="nextPage('{text()}')">Show More</button> |
|
309 |
</div> |
|
310 |
<br /> |
|
311 |
</xsl:if> |
|
312 |
</xsl:template> |
|
313 |
|
|
314 |
<xsl:template name="result-count"> |
|
315 |
<xsl:param name="path" /> |
|
316 |
<xsl:variable name="cursor" select="$path/../oai:resumptionToken/@cursor" /> |
|
317 |
<xsl:variable name="total" select="$path/../oai:resumptionToken/@completeListSize" /> |
|
318 |
<xsl:variable name="count" select="count($path)" /> |
|
319 |
<xsl:choose> |
|
320 |
<xsl:when test="$cursor"> |
|
321 |
<xsl:choose> |
|
322 |
<xsl:when test="normalize-space($path/../oai:resumptionToken/text()) = ''"> |
|
323 |
<xsl:value-of select="$total - $count" /> |
|
324 |
- |
|
325 |
<xsl:value-of select="$total" /> |
|
326 |
</xsl:when> |
|
327 |
<xsl:otherwise> |
|
328 |
<xsl:value-of select="$cursor+1" /> |
|
329 |
- |
|
330 |
<xsl:value-of select="$cursor + $count" /> |
|
331 |
</xsl:otherwise> |
|
332 |
</xsl:choose> |
|
333 |
</xsl:when> |
|
334 |
<xsl:otherwise> |
|
335 |
<xsl:value-of select="$count" /> |
|
336 |
</xsl:otherwise> |
|
337 |
</xsl:choose> |
|
338 |
<xsl:if test="$total"> |
|
339 |
of |
|
340 |
<xsl:value-of select="$total" /> |
|
341 |
</xsl:if> |
|
342 |
</xsl:template> |
|
343 |
|
|
344 |
<xsl:template name="verbTitle"> |
|
345 |
<xsl:param name="title" /> |
|
346 |
<xsl:param name="count" select="string('')"/> |
|
347 |
<xsl:param name="countPath" select="string('')"/> |
|
348 |
|
|
349 |
<h2><xsl:value-of select="$title"></xsl:value-of></h2> |
|
350 |
<h5><strong>Response Date: </strong><xsl:value-of select="translate(/oai:OAI-PMH/oai:responseDate/text(), 'TZ', ' ')" /></h5> |
|
351 |
<xsl:if test="$count"> |
|
352 |
<h5><strong>Number of results: </strong><xsl:value-of select="$count" /></h5> |
|
353 |
</xsl:if> |
|
354 |
<xsl:if test="$countPath"> |
|
355 |
<h5> |
|
356 |
<strong>Number of entries: </strong> |
|
357 |
<xsl:call-template name="result-count"> |
|
358 |
<xsl:with-param name="path" select="$countPath" /> |
|
359 |
</xsl:call-template> |
|
360 |
</h5> |
|
361 |
</xsl:if> |
|
362 |
<br /> |
|
363 |
</xsl:template> |
|
364 |
|
|
365 |
</xsl:stylesheet> |
modules/dnet-modular-oai-explorer-ui/tags/dnet-modular-oai-explorer-ui-1.0/src/main/resources/eu/dnetlib/functionality/modular/ui/views/ui/oaiExplorer.st | ||
---|---|---|
1 |
$common/master( header={ |
|
2 |
<script type="text/javascript" src="../resources/js/angular.min.js" ></script> |
|
3 |
<script type="text/javascript" src="../resources/js/ng-grid-2.0.7.min.js"></script> |
|
4 |
<script type="text/javascript" src="../resources/js/dnet_oai_explorer.js"></script> |
|
5 |
<script type="text/javascript" src="../resources/js/jquery.flot.js"></script> |
|
6 |
|
|
7 |
<link rel="stylesheet" type="text/css" href="../resources/css/ng-grid.min.css" /> |
|
8 |
<script type="text/javascript"> |
|
9 |
function getInitialBaseUrl() { |
|
10 |
return $if(oaiBaseUrl)$'$oaiBaseUrl$'$else$''$endif$; |
|
11 |
} |
|
12 |
</script> |
|
13 |
}, body={ |
|
14 |
<div ng-app="oaiExplorerUI" ng-controller="oaiExplorerCtrl"> |
|
15 |
<div class="row"> |
|
16 |
<div class="form-inline col-xs-12 col-md-6"> |
|
17 |
<form role="form"> |
|
18 |
<div class="form-group has-feedback" ng-class="{ 'has-error' : !isValidUrl(tmpBaseUrl), 'has-success' : isValidUrl(tmpBaseUrl) }"> |
|
19 |
<label for="inputBaseUrl" class="control-label">Base URL</label> |
|
20 |
<input type="text" style="width: 400px" class="form-control" id="inputBaseUrl" placeholder="Enter base url" ng-model="tmpBaseUrl" /> |
|
21 |
<span class="glyphicon form-control-feedback" ng-class="{ 'glyphicon-warning-sign' : !isValidUrl(tmpBaseUrl), 'glyphicon-ok' : isValidUrl(tmpBaseUrl) }"></span> |
|
22 |
</div> |
|
23 |
<button type="button" class="btn btn-primary" ng-click="verifyBaseUrl(tmpBaseUrl)" ng-disabled="!isValidUrl(tmpBaseUrl)">update</button> |
|
24 |
</form> |
|
25 |
</div> |
|
26 |
<div class="col-xs-12 col-md-6"> |
|
27 |
<div class="well well-sm pull-right" style="top: 4px"><a href="{{oaiUrl}}" target="_blank">{{oaiUrl}}</a></div> |
|
28 |
</div> |
|
29 |
</div> |
|
30 |
<div class="row" ng-show="baseUrl.length > 0"> |
|
31 |
<div class="col-xs-12 col-sm-12 col-md-4 col-lg-3"> |
|
32 |
<div class="panel panel-default"> |
|
33 |
<div class="panel-heading">Oai verbs</div> |
|
34 |
<div class="panel-body"> |
|
35 |
<ul class="nav nav-pills nav-stacked"> |
|
36 |
<li ng-class="{'active' : currentAction == 'Identify' }"><a href="javascript:void(0)" ng-click="identify()">Identify</a></li> |
|
37 |
<li ng-class="{'active' : currentAction == 'ListMetadataFormats' }"><a href="javascript:void(0)" ng-click="listMetadataFormats()">ListMetadataFormats</a></li> |
|
38 |
<li ng-class="{'active' : currentAction == 'ListSets' }"><a href="javascript:void(0)" ng-click="listSets()">ListSets</a></li> |
|
39 |
<li ng-class="{'active' : currentAction == 'ListRecords' }"><a href="javascript:void(0)" ng-click="listRecords('oai_dc')">ListRecords</a></li> |
|
40 |
<li ng-class="{'active' : currentAction == 'ListIdentifiers' }"><a href="javascript:void(0)" ng-click="listIdentifiers('oai_dc')">ListIdentifiers</a></li> |
|
41 |
<li ng-class="{'active' : currentAction == 'GetRecord' }"><a href="javascript:void(0)" ng-click="getRecord()">GetRecord</a></li> |
|
42 |
</ul> |
|
43 |
</div> |
|
44 |
</div> |
|
45 |
|
|
46 |
<div class="panel panel-default"> |
|
47 |
<div class="panel-heading">Oai Tests</div> |
|
48 |
<div class="panel-body"> |
|
49 |
<ul class="nav nav-pills nav-stacked"> |
|
50 |
<li ng-class="{'active' : currentAction == 'testAllVerbs' }"><a href="javascript:void(0)" ng-click="testAllVerbs()">Test all verbs</a></li> |
|
51 |
<li ng-class="{'active' : currentAction == 'testHarvesting' }"><a href="javascript:void(0)" ng-click="testHarvesting()">Test harvesting</a></li> |
|
52 |
</ul> |
|
53 |
</div> |
|
54 |
</div> |
|
55 |
</div> |
|
56 |
<div class="col-xs-12 col-sm-12 col-md-8 col-lg-9"> |
|
57 |
<div class="well"> |
|
58 |
<div ng-show="oaiDataHTML" ng-bind-html="oaiDataHTML" compile-template></div> |
|
59 |
<div ng-show="currentAction == 'testAllVerbs'"> |
|
60 |
<h2>Test of all OAI verbs</h2> |
|
61 |
<table class="table"> |
|
62 |
<thead> |
|
63 |
<tr> |
|
64 |
<th>verb</th> |
|
65 |
<th class="text-center col-xs-2">http code</th> |
|
66 |
<th class="text-center col-xs-2">is valid</th> |
|
67 |
<th class="text-right col-xs-2">time</th> |
|
68 |
</tr> |
|
69 |
</thead> |
|
70 |
<tbody> |
|
71 |
<tr ng-repeat="r in testAllVerbsData" ng-class="{'success' : r.valid, 'danger' : !r.valid}"> |
|
72 |
<th>{{r.verb}}</th> |
|
73 |
<td class="text-center">{{r.httpCode}}</td> |
|
74 |
<td class="text-center"> |
|
75 |
<span ng-show="r.valid" class="glyphicon glyphicon-ok" title="Good"></span> |
|
76 |
<span ng-hide="r.valid" class="glyphicon glyphicon-warning-sign" title="{{r.error}}"></span> |
|
77 |
</td> |
|
78 |
<td class="text-right">{{r.time / 1000}} sec.</td> |
|
79 |
</tr> |
|
80 |
</tbody> |
|
81 |
</table> |
|
82 |
<p ng-show="continueIteration">Running...</p> |
|
83 |
<p ng-hide="continueIteration">Completed !</p> |
|
84 |
</div> |
|
85 |
<div ng-show="currentAction == 'testHarvesting'"> |
|
86 |
<h2>Test Harvesting</h2> |
|
87 |
<p> |
|
88 |
<form class="form-inline"> |
|
89 |
<button ng-hide="continueIteration" class="btn btn-primary btn-sm" ng-click="startTestHarvesting()">start harvesting</button> |
|
90 |
<button ng-show="continueIteration" class="btn btn-primary btn-sm" ng-click="stopTestHarvesting()">stop harvesting</button> |
|
91 |
<button ng-hide="continueIteration || testHarvestingData.length == 0" class="btn btn-primary btn-sm" ng-click="updateGraph(testHarvestingData, 'time')" data-toggle="modal" data-target="#harvestingGraphModal">show time graph</button> |
|
92 |
<span ng-show="continueIteration">still running...</span> |
|
93 |
</form> |
|
94 |
</p> |
|
95 |
<div style="height: 400px; overflow-y:scroll"> |
|
96 |
<table class="table" ng-show="testHarvestingData.length > 0"> |
|
97 |
<thead> |
|
98 |
<tr> |
|
99 |
<th></th> |
|
100 |
<th class="text-right col-xs-1">size</th> |
|
101 |
<th class="text-right col-xs-1">cursor</th> |
|
102 |
<th class="text-right col-xs-1">total</th> |
|
103 |
<th class="text-center col-xs-1">http code</th> |
|
104 |
<th class="text-center col-xs-1">is valid</th> |
|
105 |
<th class="text-right col-xs-1">time</th> |
|
106 |
</tr> |
|
107 |
</thead> |
|
108 |
<tbody> |
|
109 |
<tr ng-repeat="r in testHarvestingData" ng-class="{'success' : r.valid, 'danger' : !r.valid}"> |
|
110 |
<th>{{r.verb}} - call {{\$index + 1}}</th> |
|
111 |
<td class="text-right">{{r.size >= 0 ? r.size : '-'}}</td> |
|
112 |
<td class="text-right">{{r.cursor >= 0 ? r.cursor : '-'}}</td> |
|
113 |
<td class="text-right">{{r.total >= 0 ? r.total : '-'}}</td> |
|
114 |
<td class="text-center">{{r.httpCode}}</td> |
|
115 |
<td class="text-center"> |
|
116 |
<span ng-show="r.valid" class="glyphicon glyphicon-ok" title="Good"></span> |
|
117 |
<span ng-hide="r.valid" class="glyphicon glyphicon-warning-sign" title="{{r.error}}"></span> |
|
118 |
</td> |
|
119 |
<td class="text-right">{{r.time / 1000}} sec.</td> |
|
120 |
</tr> |
|
121 |
</tbody> |
|
122 |
</table> |
|
123 |
|
|
124 |
|
|
125 |
<br /> |
|
126 |
<div id="endPage"></div> |
|
127 |
</div> |
|
128 |
<table class="table table condensed"> |
|
129 |
<tr> |
|
130 |
<th class="col-xs-1">Min</th> |
|
131 |
<td class="col-xs-1">{{time_min.toFixed(3)}} sec.</td> |
|
132 |
<th class="col-xs-1">Max</th> |
|
133 |
<td class="col-xs-1">{{time_max.toFixed(3)}} sec.</td> |
|
134 |
<th class="col-xs-1">Avg</th> |
|
135 |
<td class="col-xs-1">{{time_avg.toFixed(3)}} sec.</td> |
|
136 |
<th class="col-xs-1">Std Dev</th> |
|
137 |
<td class="col-xs-1">{{time_stddev.toFixed(3)}} sec.</td> |
|
138 |
</tr> |
|
139 |
</table> |
|
140 |
</div> |
|
141 |
</div> |
|
142 |
</div> |
|
143 |
</div> |
|
144 |
|
|
145 |
<div class="modal fade" id="harvestingGraphModal" tabindex="-1" role="dialog"> |
|
146 |
<div class="modal-dialog modal-lg"> |
|
147 |
<div class="modal-content"> |
|
148 |
<div class="modal-header"> |
|
149 |
<button type="button" class="close" data-dismiss="modal">×</button> |
|
150 |
<h4 class="modal-title">Harvesting Graph</h4> |
|
151 |
</div> |
|
152 |
<div class="modal-body"> |
|
153 |
<div class="row"> |
|
154 |
<div id="harvestingGraph" class="col-xs-12" style="height: 400px; width: 800px"></div> |
|
155 |
</div> |
|
156 |
</div> |
|
157 |
<div class="modal-footer"> |
|
158 |
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button> |
|
159 |
</div> |
|
160 |
</div> |
|
161 |
</div> |
|
162 |
</div> |
|
163 |
|
|
164 |
|
|
165 |
</div> |
|
166 |
} )$ |
modules/dnet-modular-oai-explorer-ui/tags/dnet-modular-oai-explorer-ui-1.0/src/main/resources/eu/dnetlib/functionality/modular/ui/oai/applicationContext-dnet-modular-oai-explorer-ui.xml | ||
---|---|---|
1 |
<?xml version="1.0" encoding="UTF-8"?> |
|
2 |
<beans xmlns="http://www.springframework.org/schema/beans" |
|
3 |
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" |
|
4 |
xmlns:util="http://www.springframework.org/schema/util" |
|
5 |
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd |
|
6 |
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"> |
|
7 |
|
|
8 |
</beans> |
modules/dnet-modular-oai-explorer-ui/tags/dnet-modular-oai-explorer-ui-1.0/src/main/resources/eu/dnetlib/functionality/modular/ui/oai/webContext-dnet-modular-oai-explorer-ui.xml | ||
---|---|---|
1 |
<beans xmlns="http://www.springframework.org/schema/beans" |
|
2 |
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" |
|
3 |
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> |
|
4 |
|
|
5 |
<bean name="/ui/oaiExplorer.do" |
|
6 |
class="eu.dnetlib.functionality.modular.ui.oai.OaiExplorerEntryPointController" |
|
7 |
p:menu="Oai explorer" p:title="Oai explorer" |
|
8 |
p:description="It is used to test the an OAI repository" p:group="DataSource Management" |
|
9 |
p:order="30" |
|
10 |
p:groupOrder="10"> |
|
11 |
<property name="permissionLevels"> |
|
12 |
<set> |
|
13 |
<value>DS_ADMIN</value> |
|
14 |
</set> |
|
15 |
</property> |
|
16 |
</bean> |
|
17 |
|
|
18 |
</beans> |
modules/dnet-modular-oai-explorer-ui/tags/dnet-modular-oai-explorer-ui-1.0/src/main/resources/eu/dnetlib/web/resources/js/dnet_oai_explorer.js | ||
---|---|---|
1 |
var module = angular.module('oaiExplorerUI', ['ngGrid']); |
|
2 |
|
|
3 |
|
|
4 |
module.directive('compileTemplate', function($compile, $parse){ |
|
5 |
return { |
|
6 |
link: function(scope, element, attr){ |
|
7 |
var parsed = $parse(attr.ngBindHtml); |
|
8 |
|
|
9 |
function getStringValue() { return (parsed(scope) || '').toString(); } |
|
10 |
|
|
11 |
//Recompile if the template changes |
|
12 |
scope.$watch(getStringValue, function() { |
|
13 |
$compile(element, null, -9999)(scope); //The -9999 makes it skip directives so that we do not recompile ourselves |
|
14 |
}); |
|
15 |
} |
|
16 |
} |
|
17 |
}); |
|
18 |
|
|
19 |
function oaiExplorerCtrl($scope, $http, $sce) { |
|
20 |
$scope.tmpBaseUrl = getInitialBaseUrl(); |
|
21 |
$scope.baseUrl = ""; |
|
22 |
$scope.currentAction = ""; |
|
23 |
$scope.oaiUrl = ""; |
|
24 |
$scope.testAllVerbsData = []; |
|
25 |
$scope.testHarvestingData = []; |
|
26 |
$scope.continueIteration = false; |
|
27 |
|
|
28 |
$scope.identifyData = ""; |
|
29 |
|
|
30 |
$scope.isValidUrl = function(url) { |
|
31 |
return (/^http/).test(url); |
|
32 |
} |
|
33 |
|
|
34 |
$scope.verifyBaseUrl = function(url) { |
|
35 |
$scope.baseUrl = ""; |
|
36 |
$scope.currentAction = ""; |
|
37 |
if ($scope.isValidUrl(url)) { |
|
38 |
$scope.baseUrl = url; |
|
39 |
$scope.identify(); |
|
40 |
} |
|
41 |
} |
|
42 |
|
|
43 |
initSpinner(); |
|
44 |
$scope.showError = function(error) { show_notification("error", error); } |
|
45 |
$scope.showNotification = function(message) { show_notification("info", message); } |
|
46 |
$scope.showSpinner = function() { showSpinner(); } |
|
47 |
$scope.hideSpinner = function() { hideSpinner(); } |
|
48 |
|
|
49 |
|
|
50 |
$scope.identify = function() { |
|
51 |
$scope.oaiUrl = $scope.baseUrl + "?verb=Identify"; |
|
52 |
|
|
53 |
$scope.callRemoteMethod('Identify', { |
|
54 |
'baseUrl' : $scope.baseUrl, |
|
55 |
'verb' : 'Identify' |
|
56 |
}); |
|
57 |
} |
|
58 |
|
|
59 |
$scope.listMetadataFormats = function() { |
|
60 |
$scope.oaiUrl = $scope.baseUrl + "?verb=ListMetadataFormats"; |
|
61 |
|
|
62 |
$scope.callRemoteMethod('ListMetadataFormats', { |
|
63 |
'baseUrl' : $scope.baseUrl, |
|
64 |
'verb' : 'ListMetadataFormats' |
|
65 |
}); |
|
66 |
} |
|
67 |
|
|
68 |
$scope.listSets = function() { |
|
69 |
$scope.oaiUrl = $scope.baseUrl + "?verb=ListSets"; |
|
70 |
|
|
71 |
$scope.callRemoteMethod('ListSets', { |
|
72 |
'baseUrl' : $scope.baseUrl, |
|
73 |
'verb' : 'ListSets' |
|
74 |
}); |
|
75 |
} |
|
76 |
|
|
77 |
$scope.listRecords = function(mdf, set) { |
|
78 |
$scope.oaiUrl = $scope.baseUrl + "?verb=ListRecords&metadataPrefix=" + mdf; |
|
79 |
if (set) { |
|
80 |
$scope.oaiUrl += "&set=" + set; |
|
81 |
} |
|
82 |
|
|
83 |
$scope.callRemoteMethod('ListRecords', { |
|
84 |
'baseUrl' : $scope.baseUrl, |
|
85 |
'verb' : 'ListRecords', |
|
86 |
'mdf' : mdf, |
|
87 |
'set' : set |
|
88 |
}); |
|
89 |
} |
|
90 |
|
|
91 |
$scope.listIdentifiers = function(mdf, set) { |
|
92 |
$scope.oaiUrl = $scope.baseUrl + "?verb=ListIdentifier&metadataPrefix=" + mdf; |
|
93 |
if (set) { |
|
94 |
$scope.oaiUrl += "&set=" + set; |
|
95 |
} |
|
96 |
|
|
97 |
$scope.callRemoteMethod('ListIdentifiers', { |
|
98 |
'baseUrl' : $scope.baseUrl, |
|
99 |
'verb' : 'ListIdentifiers', |
|
100 |
'mdf' : mdf, |
|
101 |
'set' : set |
|
102 |
}); |
|
103 |
} |
|
104 |
|
|
105 |
$scope.getRecord = function(id, mdf) { |
|
106 |
$scope.currentAction = "GetRecord"; |
|
107 |
$scope.oaiUrl = $scope.baseUrl + "?verb=GetRecord&metadataPrefix=" + mdf + "&identifier=" + id; |
|
108 |
$scope.callRemoteMethod('GetRecord', { |
|
109 |
'baseUrl' : $scope.baseUrl, |
|
110 |
'verb' : 'GetRecord', |
|
111 |
'mdf' : mdf, |
|
112 |
'id' : id |
|
113 |
}); |
|
114 |
} |
|
115 |
|
|
116 |
$scope.nextPage = function(token) { |
|
117 |
$scope.oaiUrl = $scope.baseUrl + "?verb=" + $scope.currentAction + "&resumptionToken=" + token; |
|
118 |
$scope.callRemoteMethod($scope.currentAction, { |
|
119 |
'baseUrl': $scope.baseUrl, |
|
120 |
'verb': $scope.currentAction, |
|
121 |
'token' : token |
|
122 |
}); |
|
123 |
} |
|
124 |
|
|
125 |
|
|
126 |
$scope.testAllVerbs = function() { |
|
127 |
$scope.currentAction = "testAllVerbs"; |
|
128 |
$scope.oaiDataHTML = ""; |
|
129 |
$scope.oaiUrl = $scope.baseUrl + "?verb=Identify"; |
|
130 |
$scope.testAllVerbsData = []; |
|
131 |
$scope.testHarvestingData = []; |
|
132 |
$scope.continueIteration = true; |
|
133 |
|
|
134 |
$scope.time_min = 9999999; |
|
135 |
$scope.time_max = 0; |
|
136 |
$scope.time_total = 0; |
|
137 |
$scope.time_sqrTotal = 0; |
|
138 |
$scope.time_avg = 0; |
|
139 |
$scope.time_stddev = 0; |
|
140 |
|
|
141 |
$scope.testVerb($scope.testAllVerbsData, "test_oai_verb", { |
|
142 |
'baseUrl' : $scope.baseUrl, |
|
143 |
'verb' : 'Identify', |
|
144 |
}); |
|
145 |
} |
|
146 |
|
|
147 |
$scope.testHarvesting = function() { |
|
148 |
$scope.currentAction = "testHarvesting"; |
|
149 |
$scope.oaiUrl = $scope.baseUrl + "?verb=ListRecords&metadataPrefix=oai_dc"; |
|
150 |
$scope.oaiDataHTML = ""; |
|
151 |
$scope.testAllVerbsData = []; |
|
152 |
$scope.testHarvestingData = []; |
|
153 |
$scope.continueIteration = false; |
|
154 |
|
|
155 |
$scope.time_min = 9999999; |
|
156 |
$scope.time_max = 0; |
|
157 |
$scope.time_total = 0; |
|
158 |
$scope.time_sqrTotal = 0; |
|
159 |
$scope.time_avg = 0; |
|
160 |
$scope.time_stddev = 0; |
|
161 |
} |
|
162 |
|
|
163 |
$scope.startTestHarvesting = function() { |
|
164 |
$scope.continueIteration = true; |
|
165 |
$scope.time_min = 9999999; |
|
166 |
$scope.time_max = 0; |
|
167 |
$scope.time_total = 0; |
|
168 |
$scope.time_sqrTotal = 0; |
|
169 |
$scope.time_avg = 0; |
|
170 |
$scope.time_stddev = 0; |
|
171 |
|
|
172 |
$scope.testHarvestingData = []; |
|
173 |
$scope.testVerb($scope.testHarvestingData, "test_harvesting", { |
|
174 |
'baseUrl' : $scope.baseUrl, |
|
175 |
'verb' : 'ListRecords', |
|
176 |
'mdf' : 'oai_dc' |
|
177 |
}); |
|
178 |
} |
|
179 |
|
|
180 |
$scope.stopTestHarvesting = function() { |
|
181 |
$scope.continueIteration = false; |
|
182 |
} |
|
183 |
|
|
184 |
$scope.testVerb = function(list, method, params) { |
|
185 |
//$scope.showSpinner(); |
|
186 |
$http.post(method, params).success(function(data) { |
|
187 |
list.push(data); |
|
188 |
|
|
189 |
if (data.time) { |
|
190 |
var curr = data.time / 1000; |
|
191 |
|
|
192 |
$scope.time_min = Math.min($scope.time_min, curr); |
|
193 |
$scope.time_max = Math.max($scope.time_max, curr); |
|
194 |
$scope.time_total += curr; |
|
195 |
$scope.time_sqrTotal += curr*curr; |
|
196 |
$scope.time_avg = ($scope.time_total/list.length); |
|
197 |
$scope.time_stddev = Math.sqrt((list.length * $scope.time_sqrTotal) - ($scope.time_total * $scope.time_total)) / list.length; |
|
198 |
} |
|
199 |
|
|
200 |
location.href="#endPage"; |
|
201 |
//$scope.hideSpinner(); |
|
202 |
if ($scope.continueIteration && data.nextCall && data.nextCall.verb) { |
|
203 |
$scope.testVerb(list, method, data.nextCall); |
|
204 |
} else { |
|
205 |
$scope.continueIteration = false; |
|
206 |
} |
|
207 |
}).error( |
|
208 |
function() { |
|
209 |
$scope.showError('Something really bad must have happened to our fellow hamster..'); |
|
210 |
//$scope.hideSpinner(); |
|
211 |
} |
|
212 |
); |
|
213 |
} |
|
214 |
|
|
215 |
$scope.callRemoteMethod = function(name, params) { |
|
216 |
$scope.currentAction = name; |
|
217 |
$scope.oaiDataHTML = ""; |
|
218 |
$scope.testAllVerbsData = []; |
|
219 |
$scope.testHarvestingData = []; |
|
220 |
|
|
221 |
$scope.showSpinner(); |
|
222 |
|
|
223 |
$http.post('oai_verb', params).success(function(data) { |
|
224 |
$scope.oaiDataHTML = $sce.trustAsHtml(data); |
|
225 |
$scope.hideSpinner(); |
|
226 |
}).error( |
|
227 |
function() { |
|
228 |
$scope.showError('Something really bad must have happened to our fellow hamster..'); |
|
229 |
$scope.hideSpinner(); |
|
230 |
} |
|
231 |
); |
|
232 |
} |
|
233 |
|
|
234 |
$scope.updateGraph = function(list, field) { |
|
235 |
var i = 1; |
|
236 |
var d = []; |
|
237 |
angular.forEach(list, function(obj) { |
|
238 |
if (obj[field]) { |
|
239 |
d[i] = [i, obj[field]]; |
|
240 |
} |
|
241 |
i++; |
|
242 |
}); |
|
243 |
jQuery.plot("#harvestingGraph", [ d ]); |
|
244 |
} |
|
245 |
|
|
246 |
|
|
247 |
if ($scope.tmpBaseUrl && $scope.isValidUrl($scope.tmpBaseUrl)) { |
|
248 |
$scope.verifyBaseUrl($scope.tmpBaseUrl); |
|
249 |
} |
|
250 |
|
|
251 |
} |
modules/dnet-modular-oai-explorer-ui/tags/dnet-modular-oai-explorer-ui-1.0/src/main/resources/eu/dnetlib/web/resources/js/jquery.flot.js | ||
---|---|---|
1 |
/* Javascript plotting library for jQuery, version 0.8.3. |
|
2 |
|
|
3 |
Copyright (c) 2007-2014 IOLA and Ole Laursen. |
|
4 |
Licensed under the MIT license. |
|
5 |
|
|
6 |
*/ |
|
7 |
|
|
8 |
// first an inline dependency, jquery.colorhelpers.js, we inline it here |
|
9 |
// for convenience |
|
10 |
|
|
11 |
/* Plugin for jQuery for working with colors. |
|
12 |
* |
|
13 |
* Version 1.1. |
|
14 |
* |
|
15 |
* Inspiration from jQuery color animation plugin by John Resig. |
|
16 |
* |
|
17 |
* Released under the MIT license by Ole Laursen, October 2009. |
|
18 |
* |
|
19 |
* Examples: |
|
20 |
* |
|
21 |
* $.color.parse("#fff").scale('rgb', 0.25).add('a', -0.5).toString() |
|
22 |
* var c = $.color.extract($("#mydiv"), 'background-color'); |
|
23 |
* console.log(c.r, c.g, c.b, c.a); |
|
24 |
* $.color.make(100, 50, 25, 0.4).toString() // returns "rgba(100,50,25,0.4)" |
|
25 |
* |
|
26 |
* Note that .scale() and .add() return the same modified object |
|
27 |
* instead of making a new one. |
|
28 |
* |
|
29 |
* V. 1.1: Fix error handling so e.g. parsing an empty string does |
|
30 |
* produce a color rather than just crashing. |
|
31 |
*/ |
|
32 |
(function($){$.color={};$.color.make=function(r,g,b,a){var o={};o.r=r||0;o.g=g||0;o.b=b||0;o.a=a!=null?a:1;o.add=function(c,d){for(var i=0;i<c.length;++i)o[c.charAt(i)]+=d;return o.normalize()};o.scale=function(c,f){for(var i=0;i<c.length;++i)o[c.charAt(i)]*=f;return o.normalize()};o.toString=function(){if(o.a>=1){return"rgb("+[o.r,o.g,o.b].join(",")+")"}else{return"rgba("+[o.r,o.g,o.b,o.a].join(",")+")"}};o.normalize=function(){function clamp(min,value,max){return value<min?min:value>max?max:value}o.r=clamp(0,parseInt(o.r),255);o.g=clamp(0,parseInt(o.g),255);o.b=clamp(0,parseInt(o.b),255);o.a=clamp(0,o.a,1);return o};o.clone=function(){return $.color.make(o.r,o.b,o.g,o.a)};return o.normalize()};$.color.extract=function(elem,css){var c;do{c=elem.css(css).toLowerCase();if(c!=""&&c!="transparent")break;elem=elem.parent()}while(elem.length&&!$.nodeName(elem.get(0),"body"));if(c=="rgba(0, 0, 0, 0)")c="transparent";return $.color.parse(c)};$.color.parse=function(str){var res,m=$.color.make;if(res=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(str))return m(parseInt(res[1],10),parseInt(res[2],10),parseInt(res[3],10));if(res=/rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(str))return m(parseInt(res[1],10),parseInt(res[2],10),parseInt(res[3],10),parseFloat(res[4]));if(res=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(str))return m(parseFloat(res[1])*2.55,parseFloat(res[2])*2.55,parseFloat(res[3])*2.55);if(res=/rgba\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(str))return m(parseFloat(res[1])*2.55,parseFloat(res[2])*2.55,parseFloat(res[3])*2.55,parseFloat(res[4]));if(res=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(str))return m(parseInt(res[1],16),parseInt(res[2],16),parseInt(res[3],16));if(res=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(str))return m(parseInt(res[1]+res[1],16),parseInt(res[2]+res[2],16),parseInt(res[3]+res[3],16));var name=$.trim(str).toLowerCase();if(name=="transparent")return m(255,255,255,0);else{res=lookupColors[name]||[0,0,0];return m(res[0],res[1],res[2])}};var lookupColors={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0]}})(jQuery); |
|
33 |
|
|
34 |
// the actual Flot code |
|
35 |
(function($) { |
|
36 |
|
|
37 |
// Cache the prototype hasOwnProperty for faster access |
|
38 |
|
|
39 |
var hasOwnProperty = Object.prototype.hasOwnProperty; |
|
40 |
|
|
41 |
// A shim to provide 'detach' to jQuery versions prior to 1.4. Using a DOM |
|
42 |
// operation produces the same effect as detach, i.e. removing the element |
|
43 |
// without touching its jQuery data. |
|
44 |
|
|
45 |
// Do not merge this into Flot 0.9, since it requires jQuery 1.4.4+. |
|
46 |
|
|
47 |
if (!$.fn.detach) { |
|
48 |
$.fn.detach = function() { |
|
49 |
return this.each(function() { |
|
50 |
if (this.parentNode) { |
|
51 |
this.parentNode.removeChild( this ); |
|
52 |
} |
|
53 |
}); |
|
54 |
}; |
|
55 |
} |
|
56 |
|
|
57 |
/////////////////////////////////////////////////////////////////////////// |
|
58 |
// The Canvas object is a wrapper around an HTML5 <canvas> tag. |
|
59 |
// |
|
60 |
// @constructor |
|
61 |
// @param {string} cls List of classes to apply to the canvas. |
|
62 |
// @param {element} container Element onto which to append the canvas. |
|
63 |
// |
|
64 |
// Requiring a container is a little iffy, but unfortunately canvas |
|
65 |
// operations don't work unless the canvas is attached to the DOM. |
|
66 |
|
|
67 |
function Canvas(cls, container) { |
|
68 |
|
|
69 |
var element = container.children("." + cls)[0]; |
|
70 |
|
|
71 |
if (element == null) { |
|
72 |
|
|
73 |
element = document.createElement("canvas"); |
|
74 |
element.className = cls; |
|
75 |
|
|
76 |
$(element).css({ direction: "ltr", position: "absolute", left: 0, top: 0 }) |
|
77 |
.appendTo(container); |
|
78 |
|
|
79 |
// If HTML5 Canvas isn't available, fall back to [Ex|Flash]canvas |
|
80 |
|
|
81 |
if (!element.getContext) { |
|
82 |
if (window.G_vmlCanvasManager) { |
|
83 |
element = window.G_vmlCanvasManager.initElement(element); |
|
84 |
} else { |
|
85 |
throw new Error("Canvas is not available. If you're using IE with a fall-back such as Excanvas, then there's either a mistake in your conditional include, or the page has no DOCTYPE and is rendering in Quirks Mode."); |
|
86 |
} |
|
87 |
} |
|
88 |
} |
|
89 |
|
|
90 |
this.element = element; |
|
91 |
|
|
92 |
var context = this.context = element.getContext("2d"); |
|
93 |
|
|
94 |
// Determine the screen's ratio of physical to device-independent |
|
95 |
// pixels. This is the ratio between the canvas width that the browser |
|
96 |
// advertises and the number of pixels actually present in that space. |
|
97 |
|
|
98 |
// The iPhone 4, for example, has a device-independent width of 320px, |
|
99 |
// but its screen is actually 640px wide. It therefore has a pixel |
|
100 |
// ratio of 2, while most normal devices have a ratio of 1. |
|
101 |
|
|
102 |
var devicePixelRatio = window.devicePixelRatio || 1, |
|
103 |
backingStoreRatio = |
|
104 |
context.webkitBackingStorePixelRatio || |
|
105 |
context.mozBackingStorePixelRatio || |
|
106 |
context.msBackingStorePixelRatio || |
|
107 |
context.oBackingStorePixelRatio || |
|
108 |
context.backingStorePixelRatio || 1; |
|
109 |
|
|
110 |
this.pixelRatio = devicePixelRatio / backingStoreRatio; |
|
111 |
|
|
112 |
// Size the canvas to match the internal dimensions of its container |
|
113 |
|
|
114 |
this.resize(container.width(), container.height()); |
|
115 |
|
|
116 |
// Collection of HTML div layers for text overlaid onto the canvas |
|
117 |
|
|
118 |
this.textContainer = null; |
|
119 |
this.text = {}; |
|
120 |
|
|
121 |
// Cache of text fragments and metrics, so we can avoid expensively |
|
122 |
// re-calculating them when the plot is re-rendered in a loop. |
|
123 |
|
|
124 |
this._textCache = {}; |
|
125 |
} |
|
126 |
|
|
127 |
// Resizes the canvas to the given dimensions. |
|
128 |
// |
|
129 |
// @param {number} width New width of the canvas, in pixels. |
|
130 |
// @param {number} width New height of the canvas, in pixels. |
|
131 |
|
|
132 |
Canvas.prototype.resize = function(width, height) { |
|
133 |
|
|
134 |
if (width <= 0 || height <= 0) { |
|
135 |
throw new Error("Invalid dimensions for plot, width = " + width + ", height = " + height); |
|
136 |
} |
|
137 |
|
|
138 |
var element = this.element, |
|
139 |
context = this.context, |
|
140 |
pixelRatio = this.pixelRatio; |
|
141 |
|
|
142 |
// Resize the canvas, increasing its density based on the display's |
|
143 |
// pixel ratio; basically giving it more pixels without increasing the |
|
144 |
// size of its element, to take advantage of the fact that retina |
|
145 |
// displays have that many more pixels in the same advertised space. |
|
146 |
|
|
147 |
// Resizing should reset the state (excanvas seems to be buggy though) |
|
148 |
|
|
149 |
if (this.width != width) { |
|
150 |
element.width = width * pixelRatio; |
|
151 |
element.style.width = width + "px"; |
|
152 |
this.width = width; |
|
153 |
} |
|
154 |
|
|
155 |
if (this.height != height) { |
|
156 |
element.height = height * pixelRatio; |
|
157 |
element.style.height = height + "px"; |
|
158 |
this.height = height; |
|
159 |
} |
|
160 |
|
|
161 |
// Save the context, so we can reset in case we get replotted. The |
|
162 |
// restore ensure that we're really back at the initial state, and |
|
163 |
// should be safe even if we haven't saved the initial state yet. |
|
164 |
|
|
165 |
context.restore(); |
|
166 |
context.save(); |
|
167 |
|
|
168 |
// Scale the coordinate space to match the display density; so even though we |
|
169 |
// may have twice as many pixels, we still want lines and other drawing to |
|
170 |
// appear at the same size; the extra pixels will just make them crisper. |
|
171 |
|
|
172 |
context.scale(pixelRatio, pixelRatio); |
|
173 |
}; |
|
174 |
|
|
175 |
// Clears the entire canvas area, not including any overlaid HTML text |
|
176 |
|
|
177 |
Canvas.prototype.clear = function() { |
|
178 |
this.context.clearRect(0, 0, this.width, this.height); |
|
179 |
}; |
|
180 |
|
|
181 |
// Finishes rendering the canvas, including managing the text overlay. |
|
182 |
|
|
183 |
Canvas.prototype.render = function() { |
|
184 |
|
|
185 |
var cache = this._textCache; |
|
186 |
|
|
187 |
// For each text layer, add elements marked as active that haven't |
|
188 |
// already been rendered, and remove those that are no longer active. |
|
189 |
|
|
190 |
for (var layerKey in cache) { |
|
191 |
if (hasOwnProperty.call(cache, layerKey)) { |
|
192 |
|
|
193 |
var layer = this.getTextLayer(layerKey), |
|
194 |
layerCache = cache[layerKey]; |
|
195 |
|
|
196 |
layer.hide(); |
|
197 |
|
|
198 |
for (var styleKey in layerCache) { |
|
199 |
if (hasOwnProperty.call(layerCache, styleKey)) { |
|
200 |
var styleCache = layerCache[styleKey]; |
|
201 |
for (var key in styleCache) { |
|
202 |
if (hasOwnProperty.call(styleCache, key)) { |
|
203 |
|
|
204 |
var positions = styleCache[key].positions; |
|
205 |
|
|
206 |
for (var i = 0, position; position = positions[i]; i++) { |
|
207 |
if (position.active) { |
|
208 |
if (!position.rendered) { |
|
209 |
layer.append(position.element); |
|
210 |
position.rendered = true; |
|
211 |
} |
|
212 |
} else { |
|
213 |
positions.splice(i--, 1); |
|
214 |
if (position.rendered) { |
|
215 |
position.element.detach(); |
|
216 |
} |
|
217 |
} |
|
218 |
} |
|
219 |
|
|
220 |
if (positions.length == 0) { |
|
221 |
delete styleCache[key]; |
|
222 |
} |
|
223 |
} |
|
224 |
} |
|
225 |
} |
|
226 |
} |
|
227 |
|
|
228 |
layer.show(); |
|
229 |
} |
|
230 |
} |
|
231 |
}; |
|
232 |
|
|
233 |
// Creates (if necessary) and returns the text overlay container. |
|
234 |
// |
|
235 |
// @param {string} classes String of space-separated CSS classes used to |
|
236 |
// uniquely identify the text layer. |
|
237 |
// @return {object} The jQuery-wrapped text-layer div. |
|
238 |
|
|
239 |
Canvas.prototype.getTextLayer = function(classes) { |
|
240 |
|
|
241 |
var layer = this.text[classes]; |
|
242 |
|
|
243 |
// Create the text layer if it doesn't exist |
|
244 |
|
|
245 |
if (layer == null) { |
|
246 |
|
|
247 |
// Create the text layer container, if it doesn't exist |
|
248 |
|
|
249 |
if (this.textContainer == null) { |
|
250 |
this.textContainer = $("<div class='flot-text'></div>") |
|
251 |
.css({ |
|
252 |
position: "absolute", |
|
253 |
top: 0, |
|
254 |
left: 0, |
|
255 |
bottom: 0, |
|
256 |
right: 0, |
|
257 |
'font-size': "smaller", |
|
258 |
color: "#545454" |
|
259 |
}) |
|
260 |
.insertAfter(this.element); |
|
261 |
} |
|
262 |
|
|
263 |
layer = this.text[classes] = $("<div></div>") |
|
264 |
.addClass(classes) |
|
265 |
.css({ |
|
266 |
position: "absolute", |
|
267 |
top: 0, |
|
268 |
left: 0, |
|
269 |
bottom: 0, |
|
270 |
right: 0 |
|
271 |
}) |
|
272 |
.appendTo(this.textContainer); |
|
273 |
} |
|
274 |
|
|
275 |
return layer; |
|
276 |
}; |
|
277 |
|
|
278 |
// Creates (if necessary) and returns a text info object. |
|
279 |
// |
|
280 |
// The object looks like this: |
|
281 |
// |
|
282 |
// { |
|
283 |
// width: Width of the text's wrapper div. |
|
284 |
// height: Height of the text's wrapper div. |
|
285 |
// element: The jQuery-wrapped HTML div containing the text. |
|
286 |
// positions: Array of positions at which this text is drawn. |
|
287 |
// } |
|
288 |
// |
|
289 |
// The positions array contains objects that look like this: |
|
290 |
// |
|
291 |
// { |
|
292 |
// active: Flag indicating whether the text should be visible. |
|
293 |
// rendered: Flag indicating whether the text is currently visible. |
|
294 |
// element: The jQuery-wrapped HTML div containing the text. |
|
295 |
// x: X coordinate at which to draw the text. |
|
296 |
// y: Y coordinate at which to draw the text. |
|
297 |
// } |
|
298 |
// |
|
299 |
// Each position after the first receives a clone of the original element. |
|
300 |
// |
|
301 |
// The idea is that that the width, height, and general 'identity' of the |
|
302 |
// text is constant no matter where it is placed; the placements are a |
|
303 |
// secondary property. |
|
304 |
// |
|
305 |
// Canvas maintains a cache of recently-used text info objects; getTextInfo |
|
306 |
// either returns the cached element or creates a new entry. |
|
307 |
// |
|
308 |
// @param {string} layer A string of space-separated CSS classes uniquely |
|
309 |
// identifying the layer containing this text. |
|
310 |
// @param {string} text Text string to retrieve info for. |
|
311 |
// @param {(string|object)=} font Either a string of space-separated CSS |
|
312 |
// classes or a font-spec object, defining the text's font and style. |
|
313 |
// @param {number=} angle Angle at which to rotate the text, in degrees. |
|
314 |
// Angle is currently unused, it will be implemented in the future. |
|
315 |
// @param {number=} width Maximum width of the text before it wraps. |
|
316 |
// @return {object} a text info object. |
|
317 |
|
|
318 |
Canvas.prototype.getTextInfo = function(layer, text, font, angle, width) { |
|
319 |
|
|
320 |
var textStyle, layerCache, styleCache, info; |
|
321 |
|
|
322 |
// Cast the value to a string, in case we were given a number or such |
|
323 |
|
|
324 |
text = "" + text; |
|
325 |
|
|
326 |
// If the font is a font-spec object, generate a CSS font definition |
|
327 |
|
|
328 |
if (typeof font === "object") { |
|
329 |
textStyle = font.style + " " + font.variant + " " + font.weight + " " + font.size + "px/" + font.lineHeight + "px " + font.family; |
|
330 |
} else { |
|
331 |
textStyle = font; |
|
332 |
} |
|
333 |
|
|
334 |
// Retrieve (or create) the cache for the text's layer and styles |
|
335 |
|
|
336 |
layerCache = this._textCache[layer]; |
|
337 |
|
|
338 |
if (layerCache == null) { |
|
339 |
layerCache = this._textCache[layer] = {}; |
|
340 |
} |
|
341 |
|
|
342 |
styleCache = layerCache[textStyle]; |
|
343 |
|
|
344 |
if (styleCache == null) { |
|
345 |
styleCache = layerCache[textStyle] = {}; |
|
346 |
} |
|
347 |
|
|
348 |
info = styleCache[text]; |
|
349 |
|
|
350 |
// If we can't find a matching element in our cache, create a new one |
|
351 |
|
|
352 |
if (info == null) { |
|
353 |
|
|
354 |
var element = $("<div></div>").html(text) |
|
355 |
.css({ |
|
356 |
position: "absolute", |
|
357 |
'max-width': width, |
|
358 |
top: -9999 |
|
359 |
}) |
|
360 |
.appendTo(this.getTextLayer(layer)); |
|
361 |
|
|
362 |
if (typeof font === "object") { |
|
363 |
element.css({ |
|
364 |
font: textStyle, |
|
365 |
color: font.color |
|
366 |
}); |
|
367 |
} else if (typeof font === "string") { |
|
368 |
element.addClass(font); |
|
369 |
} |
|
370 |
|
|
371 |
info = styleCache[text] = { |
|
372 |
width: element.outerWidth(true), |
|
373 |
height: element.outerHeight(true), |
|
374 |
element: element, |
|
375 |
positions: [] |
|
376 |
}; |
|
377 |
|
|
378 |
element.detach(); |
|
379 |
} |
|
380 |
|
|
381 |
return info; |
|
382 |
}; |
|
383 |
|
|
384 |
// Adds a text string to the canvas text overlay. |
|
385 |
// |
|
386 |
// The text isn't drawn immediately; it is marked as rendering, which will |
|
387 |
// result in its addition to the canvas on the next render pass. |
|
388 |
// |
|
389 |
// @param {string} layer A string of space-separated CSS classes uniquely |
|
390 |
// identifying the layer containing this text. |
|
391 |
// @param {number} x X coordinate at which to draw the text. |
|
392 |
// @param {number} y Y coordinate at which to draw the text. |
|
393 |
// @param {string} text Text string to draw. |
|
394 |
// @param {(string|object)=} font Either a string of space-separated CSS |
|
395 |
// classes or a font-spec object, defining the text's font and style. |
|
396 |
// @param {number=} angle Angle at which to rotate the text, in degrees. |
|
397 |
// Angle is currently unused, it will be implemented in the future. |
|
398 |
// @param {number=} width Maximum width of the text before it wraps. |
|
399 |
// @param {string=} halign Horizontal alignment of the text; either "left", |
|
400 |
// "center" or "right". |
|
401 |
// @param {string=} valign Vertical alignment of the text; either "top", |
|
402 |
// "middle" or "bottom". |
|
403 |
|
|
404 |
Canvas.prototype.addText = function(layer, x, y, text, font, angle, width, halign, valign) { |
|
405 |
|
|
406 |
var info = this.getTextInfo(layer, text, font, angle, width), |
|
407 |
positions = info.positions; |
|
408 |
|
|
409 |
// Tweak the div's position to match the text's alignment |
|
410 |
|
|
411 |
if (halign == "center") { |
|
412 |
x -= info.width / 2; |
|
413 |
} else if (halign == "right") { |
|
414 |
x -= info.width; |
|
415 |
} |
|
416 |
|
|
417 |
if (valign == "middle") { |
|
418 |
y -= info.height / 2; |
|
419 |
} else if (valign == "bottom") { |
|
420 |
y -= info.height; |
|
421 |
} |
|
422 |
|
|
423 |
// Determine whether this text already exists at this position. |
|
424 |
// If so, mark it for inclusion in the next render pass. |
|
425 |
|
|
426 |
for (var i = 0, position; position = positions[i]; i++) { |
|
427 |
if (position.x == x && position.y == y) { |
|
428 |
position.active = true; |
|
429 |
return; |
|
430 |
} |
|
431 |
} |
|
432 |
|
|
433 |
// If the text doesn't exist at this position, create a new entry |
|
434 |
|
|
435 |
// For the very first position we'll re-use the original element, |
|
436 |
// while for subsequent ones we'll clone it. |
|
437 |
|
|
438 |
position = { |
|
439 |
active: true, |
|
440 |
rendered: false, |
|
441 |
element: positions.length ? info.element.clone() : info.element, |
|
442 |
x: x, |
|
443 |
y: y |
|
444 |
}; |
|
445 |
|
|
446 |
positions.push(position); |
|
447 |
|
|
448 |
// Move the element to its final position within the container |
|
449 |
|
|
450 |
position.element.css({ |
|
451 |
top: Math.round(y), |
|
452 |
left: Math.round(x), |
|
453 |
'text-align': halign // In case the text wraps |
|
454 |
}); |
|
455 |
}; |
|
456 |
|
|
457 |
// Removes one or more text strings from the canvas text overlay. |
|
458 |
// |
|
459 |
// If no parameters are given, all text within the layer is removed. |
|
460 |
// |
|
461 |
// Note that the text is not immediately removed; it is simply marked as |
|
462 |
// inactive, which will result in its removal on the next render pass. |
|
463 |
// This avoids the performance penalty for 'clear and redraw' behavior, |
|
464 |
// where we potentially get rid of all text on a layer, but will likely |
|
465 |
// add back most or all of it later, as when redrawing axes, for example. |
|
466 |
// |
|
467 |
// @param {string} layer A string of space-separated CSS classes uniquely |
|
468 |
// identifying the layer containing this text. |
|
469 |
// @param {number=} x X coordinate of the text. |
|
470 |
// @param {number=} y Y coordinate of the text. |
|
471 |
// @param {string=} text Text string to remove. |
|
472 |
// @param {(string|object)=} font Either a string of space-separated CSS |
|
473 |
// classes or a font-spec object, defining the text's font and style. |
|
474 |
// @param {number=} angle Angle at which the text is rotated, in degrees. |
|
475 |
// Angle is currently unused, it will be implemented in the future. |
|
476 |
|
|
477 |
Canvas.prototype.removeText = function(layer, x, y, text, font, angle) { |
|
478 |
if (text == null) { |
|
479 |
var layerCache = this._textCache[layer]; |
|
480 |
if (layerCache != null) { |
|
481 |
for (var styleKey in layerCache) { |
|
482 |
if (hasOwnProperty.call(layerCache, styleKey)) { |
|
483 |
var styleCache = layerCache[styleKey]; |
|
484 |
for (var key in styleCache) { |
|
485 |
if (hasOwnProperty.call(styleCache, key)) { |
|
486 |
var positions = styleCache[key].positions; |
|
487 |
for (var i = 0, position; position = positions[i]; i++) { |
|
488 |
position.active = false; |
|
489 |
} |
|
490 |
} |
|
491 |
} |
|
492 |
} |
|
493 |
} |
|
494 |
} |
|
495 |
} else { |
|
496 |
var positions = this.getTextInfo(layer, text, font, angle).positions; |
|
497 |
for (var i = 0, position; position = positions[i]; i++) { |
|
498 |
if (position.x == x && position.y == y) { |
|
499 |
position.active = false; |
|
500 |
} |
|
501 |
} |
|
502 |
} |
|
503 |
}; |
|
504 |
|
|
505 |
/////////////////////////////////////////////////////////////////////////// |
|
506 |
// The top-level container for the entire plot. |
|
507 |
|
|
508 |
function Plot(placeholder, data_, options_, plugins) { |
|
509 |
// data is on the form: |
|
510 |
// [ series1, series2 ... ] |
|
511 |
// where series is either just the data as [ [x1, y1], [x2, y2], ... ] |
|
512 |
// or { data: [ [x1, y1], [x2, y2], ... ], label: "some label", ... } |
|
513 |
|
|
514 |
var series = [], |
|
515 |
options = { |
|
516 |
// the color theme used for graphs |
|
517 |
colors: ["#edc240", "#afd8f8", "#cb4b4b", "#4da74d", "#9440ed"], |
|
518 |
legend: { |
|
519 |
show: true, |
|
520 |
noColumns: 1, // number of colums in legend table |
|
521 |
labelFormatter: null, // fn: string -> string |
|
522 |
labelBoxBorderColor: "#ccc", // border color for the little label boxes |
|
523 |
container: null, // container (as jQuery object) to put legend in, null means default on top of graph |
|
524 |
position: "ne", // position of default legend container within plot |
|
525 |
margin: 5, // distance from grid edge to default legend container within plot |
|
526 |
backgroundColor: null, // null means auto-detect |
|
527 |
backgroundOpacity: 0.85, // set to 0 to avoid background |
|
528 |
sorted: null // default to no legend sorting |
|
529 |
}, |
|
530 |
xaxis: { |
|
531 |
show: null, // null = auto-detect, true = always, false = never |
|
532 |
position: "bottom", // or "top" |
|
533 |
mode: null, // null or "time" |
|
534 |
font: null, // null (derived from CSS in placeholder) or object like { size: 11, lineHeight: 13, style: "italic", weight: "bold", family: "sans-serif", variant: "small-caps" } |
|
535 |
color: null, // base color, labels, ticks |
|
536 |
tickColor: null, // possibly different color of ticks, e.g. "rgba(0,0,0,0.15)" |
|
537 |
transform: null, // null or f: number -> number to transform axis |
|
538 |
inverseTransform: null, // if transform is set, this should be the inverse function |
|
539 |
min: null, // min. value to show, null means set automatically |
|
540 |
max: null, // max. value to show, null means set automatically |
|
541 |
autoscaleMargin: null, // margin in % to add if auto-setting min/max |
|
542 |
ticks: null, // either [1, 3] or [[1, "a"], 3] or (fn: axis info -> ticks) or app. number of ticks for auto-ticks |
|
543 |
tickFormatter: null, // fn: number -> string |
|
544 |
labelWidth: null, // size of tick labels in pixels |
|
545 |
labelHeight: null, |
|
546 |
reserveSpace: null, // whether to reserve space even if axis isn't shown |
|
547 |
tickLength: null, // size in pixels of ticks, or "full" for whole line |
|
548 |
alignTicksWithAxis: null, // axis number or null for no sync |
|
549 |
tickDecimals: null, // no. of decimals, null means auto |
|
550 |
tickSize: null, // number or [number, "unit"] |
|
551 |
minTickSize: null // number or [number, "unit"] |
|
552 |
}, |
|
553 |
yaxis: { |
|
554 |
autoscaleMargin: 0.02, |
|
555 |
position: "left" // or "right" |
|
556 |
}, |
|
557 |
xaxes: [], |
|
558 |
yaxes: [], |
|
559 |
series: { |
|
560 |
points: { |
|
561 |
show: false, |
|
562 |
radius: 3, |
|
563 |
lineWidth: 2, // in pixels |
|
564 |
fill: true, |
|
565 |
fillColor: "#ffffff", |
|
566 |
symbol: "circle" // or callback |
|
567 |
}, |
|
568 |
lines: { |
|
569 |
// we don't put in show: false so we can see |
|
570 |
// whether lines were actively disabled |
|
571 |
lineWidth: 2, // in pixels |
|
572 |
fill: false, |
|
573 |
fillColor: null, |
|
574 |
steps: false |
|
575 |
// Omit 'zero', so we can later default its value to |
|
576 |
// match that of the 'fill' option. |
|
577 |
}, |
|
578 |
bars: { |
|
579 |
show: false, |
|
580 |
lineWidth: 2, // in pixels |
|
581 |
barWidth: 1, // in units of the x axis |
|
582 |
fill: true, |
|
583 |
fillColor: null, |
|
584 |
align: "left", // "left", "right", or "center" |
|
585 |
horizontal: false, |
|
586 |
zero: true |
|
587 |
}, |
|
588 |
shadowSize: 3, |
|
589 |
highlightColor: null |
|
590 |
}, |
|
591 |
grid: { |
|
592 |
show: true, |
|
593 |
aboveData: false, |
|
594 |
color: "#545454", // primary color used for outline and labels |
|
595 |
backgroundColor: null, // null for transparent, else color |
|
596 |
borderColor: null, // set if different from the grid color |
|
597 |
tickColor: null, // color for the ticks, e.g. "rgba(0,0,0,0.15)" |
|
598 |
margin: 0, // distance from the canvas edge to the grid |
|
599 |
labelMargin: 5, // in pixels |
|
600 |
axisMargin: 8, // in pixels |
|
601 |
borderWidth: 2, // in pixels |
|
602 |
minBorderMargin: null, // in pixels, null means taken from points radius |
|
603 |
markings: null, // array of ranges or fn: axes -> array of ranges |
|
604 |
markingsColor: "#f4f4f4", |
|
605 |
markingsLineWidth: 2, |
|
606 |
// interactive stuff |
|
607 |
clickable: false, |
Also available in: Unified diff
[maven-release-plugin] copy for tag dnet-modular-oai-explorer-ui-1.0