Revision: 15279
http://gate.svn.sourceforge.net/gate/?rev=15279&view=rev
Author: ian_roberts
Date: 2012-01-31 15:00:54 +0000 (Tue, 31 Jan 2012)
Log Message:
-----------
Changed the Ajax closingProgress callback to return JSON rather than a complete
progress bar, and have the indexAdmin view update its progress bar dynamically
as the closing process progresses. This also allows us to auto-refresh the
page when the index has finished closing.
Modified Paths:
--------------
mimir/trunk/mimir-cloud/grails-app/views/indexAdmin/admin.gsp
mimir/trunk/mimir-web/grails-app/controllers/gate/mimir/web/IndexAdminController.groovy
mimir/trunk/mimir-web/grails-app/taglib/gate/mimir/web/MimirTagLib.groovy
mimir/trunk/mimir-web/grails-app/views/indexAdmin/admin.gsp
Added Paths:
-----------
mimir/trunk/mimir-web/web-app/js/json2.min.js
Modified: mimir/trunk/mimir-cloud/grails-app/views/indexAdmin/admin.gsp
===================================================================
--- mimir/trunk/mimir-cloud/grails-app/views/indexAdmin/admin.gsp
2012-01-31 12:18:55 UTC (rev 15278)
+++ mimir/trunk/mimir-cloud/grails-app/views/indexAdmin/admin.gsp
2012-01-31 15:00:54 UTC (rev 15279)
@@ -1,167 +1,175 @@
<%@page import="gate.mimir.web.LocalIndex"%>
<%@ page import="gate.mimir.web.Index" %>
-<%@ page import="org.codehaus.groovy.grails.commons.ConfigurationHolder" %>
<html>
- <head>
- <meta http-equiv="Content-Type" content="text/html;
charset=UTF-8" />
- <meta name="layout" content="mimir" />
- <link rel="stylesheet"
href="${resource(dir:'css',file:'progressbar.css')}" />
- <g:javascript library="prototype" />
- <mimir:load/>
- <title>Mimir index "${indexInstance.name}"</title>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <meta name="layout" content="mimir" />
+ <link rel="stylesheet"
href="${resource(dir:'css',file:'progressbar.css',plugin:'mimir-web')}" />
+ <g:javascript library="prototype" />
+ <title>Mimir index "${indexInstance.name}"</title>
+ <mimir:load/>
- <g:javascript>
- function pageLoaded() {
- <g:if test="${indexInstance.state == Index.CLOSING}">
- // start regular updates of the progress bar
- new Ajax.PeriodicalUpdater('closeProgress',
- '${g.createLink(controller:"indexAdmin",
- action:"closingProgress",
-
params:[indexId:indexInstance.indexId]).encodeAsJavaScript()}', {
- frequency: 5
- });
- </g:if>
- }
+ <g:if test="${indexInstance.state == Index.CLOSING}">
+ <g:javascript src="json2.min.js" plugin="mimir-web" />
+ <g:javascript>
+ function updateProgress() {
+ <g:remoteFunction
+ url="[controller:'indexAdmin', action:'closingProgress',
params:[indexId:indexInstance.indexId]]"
+ method="GET" onSuccess="doProgressUpdate(e)"
+ onFailure="progressUpdateFailed(e)" />;
+ }
- // can't do body onLoad="..." so use a prototype event
handler instead
- Event.observe(window, 'load', pageLoaded, false);
- </g:javascript>
- </head>
- <body>
- <div class="nav">
+ function doProgressUpdate(response) {
+ var result = JSON.parse(response.responseText);
+ if(result.complete) {
+ window.location.reload();
+ } else {
+ document.getElementById('closingProgress-bar').style.width =
result.progress;
+ document.getElementById('closingProgress-value').innerHTML =
result.progress;
+ setTimeout(updateProgress, 5000);
+ }
+ }
+
+ function progressUpdateFailed(response) {
+ var progValue = document.getElementById('closingProgress-value');
+ progValue.innerHTML = progValue.innerHTML + ' (unable to update
dynamically, please reload to check progress)';
+ }
+ </g:javascript>
+ </g:if>
+ </head>
+ <body>
+ <div class="nav">
<span class="menuButton"> <g:link class="home"
controller="mimirStaticPages" action="admin">Admin Home</g:link>
</span>
- <%--
- <span class="menuButton">
- <g:link class="list" action="list">LocalIndex
List</g:link>
- </span>
- --%>
- </div>
- <div class="body">
- <g:if test="${flash.message}">
- <div class="message">${flash.message}</div>
- </g:if>
- <h1>Mimir index "${indexInstance.name}"</h1>
- <div class="dialog">
- <g:set var="row" value="${0}" />
- <table>
- <tbody>
- <tr class="${row++ % 2 == 0 ?
'even' :'odd'}">
- <td valign="top"
class="name">Index Name:</td>
- <td valign="top"
class="value">${indexInstance.name}</td>
- </tr>
- <tr class="${row++ % 2 == 0 ?
'even' :'odd'}">
- <td valign="top"
class="name">Index URL:</td>
- <td valign="top"
class="value">
- <g:if
test="${ConfigurationHolder.config.gate.mimir.indexUrlBase}">
-
<mimir:createIndexUrl indexId="${indexInstance.indexId}"
-
urlBase="${ConfigurationHolder.config.gate.mimir.indexUrlBase}" />
- </g:if>
- <g:else>
-
<mimir:createIndexUrl indexId="${indexInstance.indexId}" />
- </g:else>
- <br />
- <p>This URL can be used
for API access to the index, for example
- when creating a
federated index or when configuring the output of
- a GATECloud.net
Annotation Job.</p>
- <p>When running inside the
GATECloud.net cloud, the URL of your
- index <u>changes every time
you restart your Mímir
- server</u>! If you use it to
create a federated index, then you
- will need to re-create your
Remote index instance every time you
- restart.</p>
- <p>For security reasons, the
firewall only allows this URL to be
- accessed by other
Mímir servers that you own (so that you
- can create federated indexes)
and by your Annotation Jobs. If you
- have other requirements
please contact the GATECloud.net team.</p>
- </td>
- </tr>
-
- <tr class="${row++ % 2 == 0 ?
'even' :'odd'}">
- <td valign="top"
class="name">State:</td>
- <td valign="top"
class="value">${indexInstance.state}</td>
- </tr>
- <tr class="${row++ % 2 == 0 ? 'even' :'odd'}">
- <td>Annotations indexed:</td>
- <td><mimir:revealAnchor
id="annotsConf">Detail...</mimir:revealAnchor>
- <mimir:revealBlock
id="annotsConf"><mimir:indexAnnotationsConfig
index="${indexInstance}"/></mimir:revealBlock>
- </td>
- </tr>
- <g:if test="${indexInstance instanceof LocalIndex}" >
- <tr class="${row++ % 2 == 0 ? 'even' :'odd'}">
- <td valign="top" class="name">Scorer:</td>
- <td valign="top" class="value">
- ${indexInstance.scorer?:'No Scoring'}</td>
- </tr>
- </g:if>
+ </div>
+ <div class="body">
+ <g:if test="${flash.message}">
+ <div class="message">${flash.message}</div>
+ </g:if>
+ <h1>Mimir index "${indexInstance.name}"</h1>
+ <div class="dialog">
+ <g:set var="row" value="${0}" />
+ <table>
+ <tbody>
+ <tr class="${row++ % 2 == 0 ? 'even' :'odd'}">
+ <td valign="top" class="name">Index Name:</td>
+ <td valign="top" class="value">${indexInstance.name}</td>
+ </tr>
+ <tr class="${row++ % 2 == 0 ? 'even' :'odd'}">
+ <td valign="top" class="name">Index URL:</td>
+ <td valign="top" class="value">
+ <g:if test="${grailsApplication.config.gate.mimir.indexUrlBase}">
+ <mimir:createIndexUrl indexId="${indexInstance.indexId}"
+
urlBase="${grailsApplication.config.gate.mimir.indexUrlBase}" />
+ </g:if>
+ <g:else>
+ <mimir:createIndexUrl indexId="${indexInstance.indexId}" />
+ </g:else>
+ <br />
+ <p>This URL can be used for API access to the index, for example
+ when creating a federated index or when configuring the output of
+ a GATECloud.net Annotation Job.</p>
+ <p>When running inside the GATECloud.net cloud, the URL of your
+ index <u>changes every time you restart your Mímir
+ server</u>! If you use it to create a federated index, then you
+ will need to re-create your Remote index instance every time you
+ restart.</p>
+ <p>For security reasons, the firewall only allows this URL to be
+ accessed by other Mímir servers that you own (so that you
+ can create federated indexes) and by your Annotation Jobs. If you
+ have other requirements please contact the GATECloud.net
team.</p>
+ </td>
+ </tr>
+
+ <tr class="${row++ % 2 == 0 ? 'even' :'odd'}">
+ <td valign="top" class="name">State:</td>
+ <td valign="top" class="value">${indexInstance.state}</td>
+ </tr>
+ <tr class="${row++ % 2 == 0 ? 'even' :'odd'}">
+ <td>Annotations indexed:</td>
+ <td><mimir:revealAnchor
id="annotsConf">Detail...</mimir:revealAnchor>
+ <mimir:revealBlock id="annotsConf"><mimir:indexAnnotationsConfig
index="${indexInstance}"/></mimir:revealBlock>
+ </td>
+ </tr>
+ <g:if test="${indexInstance instanceof LocalIndex}" >
+ <tr class="${row++ % 2 == 0 ? 'even' :'odd'}">
+ <td valign="top" class="name">Scorer:</td>
+ <td valign="top" class="value">
+ ${indexInstance.scorer?:'No Scoring'}</td>
+ </tr>
+ </g:if>
- <g:if
test="${indexInstance.state == Index.SEARCHING}">
- <tr class="${row++ % 2
== 0 ? 'even' :'odd'}">
- <td colspan="2">
- <g:link
controller="search" action="index"
-
params="[indexId:indexInstance.indexId]" title="Search this index">Search this
-
index using the web interface.</g:link><br />
-
<g:link controller="search" action="help"
+ <g:if test="${indexInstance.state == Index.SEARCHING}">
+ <tr class="${row++ % 2 == 0 ? 'even' :'odd'}">
+ <td colspan="2">
+ <g:link controller="search" action="index"
params="[indexId:indexInstance.indexId]" title="Search
this index">Search this
- index using the XML service interface.</g:link>
- </td>
- </tr>
- </g:if>
- <g:elseif
test="${indexInstance.state == Index.CLOSING}">
- <tr class="${row++ % 2
== 0 ? 'even' :'odd'}">
- <td>Index
Closing Progress:</td>
- <td
id="closeProgress"></td>
- </tr>
- </g:elseif>
- </tbody>
- </table>
- </div>
- <div class="buttons">
- <table>
- <tr>
- <g:form
-
controller="${grails.util.GrailsNameUtils.getPropertyNameRepresentation(indexInstance.getClass())}">
- <input type="hidden" name="id"
value="${indexInstance?.id}" />
- <td><span class="button">
- <g:actionSubmit
class="show" action="Show" value="Details"
- title="Click to
see more information about this index." />
- </span></td>
- <td><span class="button">
- <g:actionSubmit
class="edit" value="Edit" title="Click to modify this index."/>
- </span></td>
- <td><span class="button">
- <g:actionSubmit
class="delete"
- title="Click to
delete this index."
- onclick="return
confirm('Are you sure?');" value="Delete" />
- </span></td>
- </g:form>
- <g:if test="${indexInstance.state == Index.INDEXING}">
- <g:form action="close"
params="[indexId:indexInstance?.indexId]">
- <input type="hidden" name="indexId"
value="${indexInstance?.indexId}" />
+ index using the web interface.</g:link><br />
+ <g:link controller="search" action="help"
+ params="[indexId:indexInstance.indexId]" title="Search
this index">Search this
+ index using the XML service interface.</g:link><br />
+ <g:link action="deletedDocuments"
+ params="[indexId:indexInstance.indexId]"
+ title="Add or remove 'deleted' markers for
documents">Manage deleted documents.</g:link>
+ </td>
+ </tr>
+ </g:if>
+ <g:elseif test="${indexInstance.state == Index.CLOSING}">
+ <tr class="${row++ % 2 == 0 ? 'even' :'odd'}">
+ <td>Index Closing Progress:</td>
+ <td><mimir:progressbar id="closingProgress"
value="${indexInstance.closingProgress()}"
/><g:javascript>setTimeout(updateProgress, 5000);</g:javascript></td>
+ </tr>
+ </g:elseif>
+ </tbody>
+ </table>
+ </div>
+ <div class="buttons">
+ <table>
+ <tr>
+ <g:form
+
controller="${grails.util.GrailsNameUtils.getPropertyNameRepresentation(indexInstance.getClass())}">
+ <input type="hidden" name="id" value="${indexInstance?.id}" />
+ <td><span class="button">
+ <g:actionSubmit class="show" action="Show" value="Details"
+ title="Click to see more information about this index." />
+ </span></td>
+ <td><span class="button">
+ <g:actionSubmit class="edit" value="Edit" title="Click to modify
this index."/>
+ </span></td>
+ <td><span class="button">
+ <g:actionSubmit class="delete"
+ title="Click to delete this index."
+ onclick="return confirm('Are you sure?');" value="Delete" />
+ </span></td>
+ </g:form>
+ <g:if test="${indexInstance.state == Index.INDEXING}">
+ <g:form action="close" params="[indexId:indexInstance?.indexId]">
+ <input type="hidden" name="indexId"
value="${indexInstance?.indexId}" />
<td><span class="button">
<g:submitButton class="close"
title="Click to stop the indexing process and prepare this
index for searching."
onclick="return confirm('Are you sure?');" name="Close"/>
- </span></td>
- </g:form>
- </g:if>
- <g:elseif test="${indexInstance instanceof
gate.mimir.web.LocalIndex && indexInstance.state == Index.SEARCHING}">
- <g:form action="download" controller="indexDownload"
id="${indexInstance?.id}" method="GET">
+ </span></td>
+ </g:form>
+ </g:if>
+ <g:elseif test="${indexInstance instanceof gate.mimir.web.LocalIndex
&& indexInstance.state == Index.SEARCHING}">
+ <g:form action="download" controller="indexDownload"
id="${indexInstance?.id}" method="GET">
<td><span class="button"><input type="submit" class="download"
value="Download"
title="Click to download this index." />
- </span></td>
- </g:form>
- <g:form action="downloadNew" controller="indexDownload"
id="${indexInstance?.id}" method="GET">
+ </span></td>
+ </g:form>
+ <g:form action="downloadNew" controller="indexDownload"
id="${indexInstance?.id}" method="GET">
<td><span class="button">
<input type="submit" class="download"
title="Click to force the creation of a new index archive
and then download it."
value="[Re-]Archive and Download"/>
</span></td>
- </g:form>
- </g:elseif>
+ </g:form>
+ </g:elseif>
</tr>
</table>
- </div>
- </div>
- </body>
+ </div>
+ </div>
+ </body>
</html>
Modified:
mimir/trunk/mimir-web/grails-app/controllers/gate/mimir/web/IndexAdminController.groovy
===================================================================
---
mimir/trunk/mimir-web/grails-app/controllers/gate/mimir/web/IndexAdminController.groovy
2012-01-31 12:18:55 UTC (rev 15278)
+++
mimir/trunk/mimir-web/grails-app/controllers/gate/mimir/web/IndexAdminController.groovy
2012-01-31 15:00:54 UTC (rev 15279)
@@ -14,6 +14,9 @@
import gate.mimir.web.Index;
+import grails.converters.JSON
+
+import java.text.NumberFormat;
import javax.servlet.http.HttpServletResponse;
/**
@@ -22,6 +25,13 @@
class IndexAdminController {
static defaultAction = "admin"
+ static NumberFormat percentNumberInstance =
NumberFormat.getPercentInstance(Locale.US)
+
+ static{
+ percentNumberInstance.setMaximumFractionDigits(2)
+ percentNumberInstance.setMinimumFractionDigits(2)
+ }
+
def admin = {
def indexInstance = Index.findByIndexId(params.indexId)
if(!indexInstance) {
@@ -41,7 +51,11 @@
}
double progress = indexInstance.closingProgress()
- render(mimir.progressbar(value:progress))
+ if(indexInstance.state == Index.CLOSING) {
+ render([progress:percentNumberInstance.format(progress)] as JSON)
+ } else {
+ render([complete:true] as JSON)
+ }
}
def close = {
Modified:
mimir/trunk/mimir-web/grails-app/taglib/gate/mimir/web/MimirTagLib.groovy
===================================================================
--- mimir/trunk/mimir-web/grails-app/taglib/gate/mimir/web/MimirTagLib.groovy
2012-01-31 12:18:55 UTC (rev 15278)
+++ mimir/trunk/mimir-web/grails-app/taglib/gate/mimir/web/MimirTagLib.groovy
2012-01-31 15:00:54 UTC (rev 15279)
@@ -120,16 +120,19 @@
* be shown? Permitted values are <tt>true</tt> (default) and
* <tt>false</tt>.</li>
* <li><b>id</b>: a value for the id attribute of the span element created.
- * </li>
+ * If this is provided, the nested span class="progress" will also be given
+ * an id of "<i>id</i>-bar" and the span showing the percentage
+ * as text will be given an id of "<i>id</i>-value", allowing
+ * them to be easily updated dynamically using JavaScript.</li>
* </ul>
*/
def progressbar = { attrs, body ->
/* What we're trying to create looks like this:
-<span>
+<span id="myProgress">
<div class="progressbar" style="width:20em; height:1em;
display:inline-block; margin-right:5px;vertical-align:middle;">
- <span class="progress" style="width:30%">
+ <span id="myProgress-bar" class="progress" style="width:30%">
</span>
- </div><span style="vertical-align:middle;">30%</span>
+ </div><span id="myProgress-value" style="vertical-align:middle;">30%</span>
</span>
*/
double value = attrs.value
@@ -147,11 +150,15 @@
out << "height:" + (heightStr ? heightStr : "1em") + "; "
out << "width:" + (widthStr ? widthStr : "20em") + "; "
out << (showText ? "margin-right:5px; vertical-align:middle;\">" : "\">")
- out << "<span class=\"progress\" style=\"width:"
+ out << "<span"
+ if(idStr) out << " id=\"" + idStr + "-bar\""
+ out << " class=\"progress\" style=\"width:"
out << percentNumberInstance.format(value)
out << "\"></span></div>"
if(showText){
- out << "<span style=\"vertical-align:middle;\">"
+ out << "<span"
+ if(idStr) out << " id=\"" + idStr + "-value\""
+ out << " style=\"vertical-align:middle;\">"
out << percentNumberInstance.format(value)
out << "</span>"
}
Modified: mimir/trunk/mimir-web/grails-app/views/indexAdmin/admin.gsp
===================================================================
--- mimir/trunk/mimir-web/grails-app/views/indexAdmin/admin.gsp 2012-01-31
12:18:55 UTC (rev 15278)
+++ mimir/trunk/mimir-web/grails-app/views/indexAdmin/admin.gsp 2012-01-31
15:00:54 UTC (rev 15279)
@@ -9,33 +9,40 @@
<title>Mimir index "${indexInstance.name}"</title>
<mimir:load/>
-<g:javascript>
- function pageLoaded() {
- <g:if test="${indexInstance.state == Index.CLOSING}">
- // start regular updates of the progress bar
- new Ajax.PeriodicalUpdater('closeProgress',
- '${g.createLink(controller:"indexAdmin",
- action:"closingProgress",
-
params:[indexId:indexInstance.indexId]).encodeAsJavaScript()}', {
- frequency: 5
- });
- </g:if>
- }
+<g:if test="${indexInstance.state == Index.CLOSING}">
+ <g:javascript src="json2.min.js" />
+ <g:javascript>
+ function updateProgress() {
+ <g:remoteFunction
+ url="[controller:'indexAdmin', action:'closingProgress',
params:[indexId:indexInstance.indexId]]"
+ method="GET" onSuccess="doProgressUpdate(e)"
+ onFailure="progressUpdateFailed(e)" />;
+ }
- // can't do body onLoad="..." so use a prototype event
handler instead
- Event.observe(window, 'load', pageLoaded, false);
- </g:javascript>
+ function doProgressUpdate(response) {
+ var result = JSON.parse(response.responseText);
+ if(result.complete) {
+ window.location.reload();
+ } else {
+ document.getElementById('closingProgress-bar').style.width =
result.progress;
+ document.getElementById('closingProgress-value').innerHTML =
result.progress;
+ setTimeout(updateProgress, 5000);
+ }
+ }
+
+ function progressUpdateFailed(response) {
+ var progValue = document.getElementById('closingProgress-value');
+ progValue.innerHTML = progValue.innerHTML + ' (unable to update
dynamically, please reload to check progress)';
+ }
+ </g:javascript>
+</g:if>
+
</head>
<body>
<div class="nav">
<span class="menuButton"> <g:link class="home"
controller="mimirStaticPages" action="admin">Admin Home</g:link>
</span>
- <%--
- <span class="menuButton">
- <g:link class="list" action="list">LocalIndex
List</g:link>
- </span>
- --%>
</div>
<div class="body">
<g:if test="${flash.message}">
@@ -96,7 +103,7 @@
<g:elseif test="${indexInstance.state == Index.CLOSING}">
<tr class="prop">
<td>Index Closing Progress:</td>
- <td id="closeProgress"></td>
+ <td><mimir:progressbar id="closingProgress"
value="${indexInstance.closingProgress()}"
/><g:javascript>setTimeout(updateProgress, 5000);</g:javascript></td>
</tr>
</g:elseif>
</tbody>
Added: mimir/trunk/mimir-web/web-app/js/json2.min.js
===================================================================
--- mimir/trunk/mimir-web/web-app/js/json2.min.js
(rev 0)
+++ mimir/trunk/mimir-web/web-app/js/json2.min.js 2012-01-31 15:00:54 UTC
(rev 15279)
@@ -0,0 +1,27 @@
+/* Minified version of json2.js from
+ * https://github.com/douglascrockford/JSON-js */
+var JSON;if(!JSON){JSON={};}
+(function(){'use strict';function f(n){return n<10?'0'+n:n;}
+if(typeof
Date.prototype.toJSON!=='function'){Date.prototype.toJSON=function(key){return
isFinite(this.valueOf())?this.getUTCFullYear()+'-'+
+f(this.getUTCMonth()+1)+'-'+
+f(this.getUTCDate())+'T'+
+f(this.getUTCHours())+':'+
+f(this.getUTCMinutes())+':'+
+f(this.getUTCSeconds())+'Z':null;};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(key){return
this.valueOf();};}
+var
cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'},rep;function
quote(string){escapable.lastIndex=0;return
escapable.test(string)?'"'+string.replace(escapable,function(a){var
c=meta[a];return typeof
c==='string'?c:'\\u'+('0000'+a.charCodeAt(0).toString(16)).slice(-4);})+'"':'"'+string+'"';}
+function str(key,holder){var
i,k,v,length,mind=gap,partial,value=holder[key];if(value&&typeof
value==='object'&&typeof value.toJSON==='function'){value=value.toJSON(key);}
+if(typeof rep==='function'){value=rep.call(holder,key,value);}
+switch(typeof value){case'string':return quote(value);case'number':return
isFinite(value)?String(value):'null';case'boolean':case'null':return
String(value);case'object':if(!value){return'null';}
+gap+=indent;partial=[];if(Object.prototype.toString.apply(value)==='[object
Array]'){length=value.length;for(i=0;i<length;i+=1){partial[i]=str(i,value)||'null';}
+v=partial.length===0?'[]':gap?'[\n'+gap+partial.join(',\n'+gap)+'\n'+mind+']':'['+partial.join(',')+']';gap=mind;return
v;}
+if(rep&&typeof
rep==='object'){length=rep.length;for(i=0;i<length;i+=1){if(typeof
rep[i]==='string'){k=rep[i];v=str(k,value);if(v){partial.push(quote(k)+(gap?':
':':')+v);}}}}else{for(k in
value){if(Object.prototype.hasOwnProperty.call(value,k)){v=str(k,value);if(v){partial.push(quote(k)+(gap?':
':':')+v);}}}}
+v=partial.length===0?'{}':gap?'{\n'+gap+partial.join(',\n'+gap)+'\n'+mind+'}':'{'+partial.join(',')+'}';gap=mind;return
v;}}
+if(typeof
JSON.stringify!=='function'){JSON.stringify=function(value,replacer,space){var
i;gap='';indent='';if(typeof space==='number'){for(i=0;i<space;i+=1){indent+='
';}}else if(typeof space==='string'){indent=space;}
+rep=replacer;if(replacer&&typeof replacer!=='function'&&(typeof
replacer!=='object'||typeof replacer.length!=='number')){throw new
Error('JSON.stringify');}
+return str('',{'':value});};}
+if(typeof JSON.parse!=='function'){JSON.parse=function(text,reviver){var
j;function walk(holder,key){var k,v,value=holder[key];if(value&&typeof
value==='object'){for(k in
value){if(Object.prototype.hasOwnProperty.call(value,k)){v=walk(value,k);if(v!==undefined){value[k]=v;}else{delete
value[k];}}}}
+return reviver.call(holder,key,value);}
+text=String(text);cx.lastIndex=0;if(cx.test(text)){text=text.replace(cx,function(a){return'\\u'+
+('0000'+a.charCodeAt(0).toString(16)).slice(-4);});}
+if(/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,'@').replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,']').replace(/(?:^|:|,)(?:\s*\[)+/g,''))){j=eval('('+text+')');return
typeof reviver==='function'?walk({'':j},''):j;}
+throw new SyntaxError('JSON.parse');};}}());
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
------------------------------------------------------------------------------
Keep Your Developer Skills Current with LearnDevNow!
The most comprehensive online learning library for Microsoft developers
is just $99.99! Visual Studio, SharePoint, SQL - plus HTML5, CSS3, MVC3,
Metro Style Apps, more. Free future releases when you subscribe now!
http://p.sf.net/sfu/learndevnow-d2d
_______________________________________________
GATE-cvs mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/gate-cvs