1. Refactored/Cleaned the front-end for the co-author vis.

2. Added Gson library for making use of json. 
3. Added capability to send information in json format. We will use this especially in getting non-specific information on the fly about an individual.
This commit is contained in:
cdtank 2010-06-29 22:07:55 +00:00
parent e58927661e
commit 94755a7f73
7 changed files with 345 additions and 231 deletions

BIN
webapp/lib/gson-1.4.jar Normal file

Binary file not shown.

View file

@ -7,8 +7,10 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.TreeMap; import java.util.TreeMap;
import com.google.gson.Gson;
import com.hp.hpl.jena.iri.IRIFactory; import com.hp.hpl.jena.iri.IRIFactory;
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.GenericQueryMap;
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.Node; import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.Node;
public class TestJava { public class TestJava {
@ -46,10 +48,10 @@ public class TestJava {
} }
Map<String, Integer> yearToPublicationCount = new TreeMap<String, Integer>(); Map<String, Integer> yearToPublicationCount = new TreeMap<String, Integer>();
// yearToPublicationCount.put("2003", 5); yearToPublicationCount.put("2003", 5);
// yearToPublicationCount.put("2001", 5); yearToPublicationCount.put("2001", 5);
// yearToPublicationCount.put("2002", 5); yearToPublicationCount.put("2002", 5);
// yearToPublicationCount.put("2090", 7); yearToPublicationCount.put("2090", 7);
yearToPublicationCount.put("Unknown", 6); yearToPublicationCount.put("Unknown", 6);
Node egoNode; Node egoNode;
@ -97,12 +99,32 @@ public class TestJava {
} }
GenericQueryMap stringToSetOfStrings = new GenericQueryMap();
stringToSetOfStrings.put("A", yearToPublicationCount.keySet());
stringToSetOfStrings.put("B", yearToPublicationCount.keySet());
stringToSetOfStrings.put("C", yearToPublicationCount.keySet());
stringToSetOfStrings.put("imageOffset", keySet);
Set<String> what = new HashSet<String>();
what.add("sup");
stringToSetOfStrings.put("imageOffset2", what);
String emptyString = ""; String emptyString = "";
System.out.println(emptyString.isEmpty()); System.out.println(emptyString.isEmpty());
System.out.println(yearToPublicationCount); System.out.println(stringToSetOfStrings);
Gson gson = new Gson();
String json = gson.toJson(stringToSetOfStrings);
System.out.println(json);
// System.out.println(Collections.max(yearToPublicationCount.keySet())); // System.out.println(Collections.max(yearToPublicationCount.keySet()));
// System.out.println(Collections.min(yearToPublicationCount.keySet())); // System.out.println(Collections.min(yearToPublicationCount.keySet()));

View file

@ -49,11 +49,6 @@ public class VisualizationRequestHandler {
String visContainer = vitroRequest.getParameter(VisualizationFrameworkConstants.VIS_CONTAINER_URL_HANDLE); String visContainer = vitroRequest.getParameter(VisualizationFrameworkConstants.VIS_CONTAINER_URL_HANDLE);
System.out.println("******************************************************");
System.out.println(VisualizationFrameworkConstants.VIS_MODE_URL_HANDLE);
System.out.println(vitroRequest.getParameter(VisualizationFrameworkConstants.VIS_MODE_URL_HANDLE));
System.out.println(VisualizationFrameworkConstants.IMAGE_VIS_MODE_URL_VALUE);
QueryHandler queryManager = QueryHandler queryManager =
new QueryHandler(egoURIParam, new QueryHandler(egoURIParam,
resultFormatParam, resultFormatParam,

View file

@ -14,6 +14,7 @@ import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import com.google.gson.Gson;
import com.hp.hpl.jena.query.DataSource; import com.hp.hpl.jena.query.DataSource;
import edu.cornell.mannlib.vitro.webapp.beans.Portal; import edu.cornell.mannlib.vitro.webapp.beans.Portal;
@ -51,6 +52,7 @@ public class VisualizationRequestHandler {
String visMode = vitroRequest.getParameter(VisualizationFrameworkConstants.VIS_MODE_URL_HANDLE); String visMode = vitroRequest.getParameter(VisualizationFrameworkConstants.VIS_MODE_URL_HANDLE);
String profileInfoMode = "PROFILE_INFO";
String profileVisMode = "PROFILE_URL"; String profileVisMode = "PROFILE_URL";
String coAuthorVisMode = "COAUTHORSHIP_URL"; String coAuthorVisMode = "COAUTHORSHIP_URL";
String imageVisMode = "IMAGE_URL"; String imageVisMode = "IMAGE_URL";
@ -62,11 +64,51 @@ public class VisualizationRequestHandler {
try { try {
/*
* If the info being requested is about a profile which includes the name, moniker
* & image url.
* */
if (profileInfoMode.equalsIgnoreCase(visMode)) {
String filterRule = "?predicate = vitro:imageThumb || ?predicate = vitro:moniker || ?predicate = rdfs:label";
GenericQueryHandler imageQueryHandler = new GenericQueryHandler(individualURIParam,
filterRule,
resultFormatParam,
rdfResultFormatParam,
dataSource,
log);
try {
GenericQueryMap profilePropertiesToValues = imageQueryHandler.getJavaValueObjects();
profilePropertiesToValues.addEntry("imageContextPath", request.getContextPath() + "/images/");
Gson profileInformation = new Gson();
prepareVisualizationQueryResponse(profileInformation.toJson(profilePropertiesToValues));
return;
} catch (MalformedQueryParametersException e) {
try {
handleMalformedParameters(e.getMessage());
} catch (ServletException e1) {
log.error(e1.getStackTrace());
} catch (IOException e1) {
log.error(e1.getStackTrace());
}
return;
}
} else if (imageVisMode.equalsIgnoreCase(visMode)) {
/* /*
* If the url being requested is about a standalone image, which is used when we want * If the url being requested is about a standalone image, which is used when we want
* to render an image & other info for a co-author OR ego for that matter. * to render an image & other info for a co-author OR ego for that matter.
* */ * */
if (imageVisMode.equalsIgnoreCase(visMode)) {
String filterRule = "?predicate = vitro:imageThumb"; String filterRule = "?predicate = vitro:imageThumb";
@ -82,9 +124,7 @@ public class VisualizationRequestHandler {
GenericQueryMap imagePropertyToValues = imageQueryHandler.getJavaValueObjects(); GenericQueryMap imagePropertyToValues = imageQueryHandler.getJavaValueObjects();
String imagePath = ""; String imagePath = "";
/*
* If there is no imageThumb property we want to give the link to "No Image" snap.
* */
if (imagePropertyToValues.size() > 0) { if (imagePropertyToValues.size() > 0) {
String vitroSparqlNamespace = QueryConstants.PREFIX_TO_NAMESPACE.get("vitro"); String vitroSparqlNamespace = QueryConstants.PREFIX_TO_NAMESPACE.get("vitro");
@ -97,10 +137,8 @@ public class VisualizationRequestHandler {
* expression power. * expression power.
* */ * */
for (String providedImagePath : personImageThumbPaths) { for (String providedImagePath : personImageThumbPaths) {
imagePath = "/images/" + providedImagePath; imagePath = request.getContextPath() + "/images/" + providedImagePath;
} }
} }
prepareVisualizationQueryResponse(imagePath); prepareVisualizationQueryResponse(imagePath);
@ -119,12 +157,11 @@ public class VisualizationRequestHandler {
} }
} } else if (coAuthorVisMode.equalsIgnoreCase(visMode)) {
/* /*
* By default we will be generating profile url else some specific url like coAuthorShip vis * By default we will be generating profile url else some specific url like coAuthorShip vis
* url for that individual. * url for that individual.
* */ * */
else if (coAuthorVisMode.equalsIgnoreCase(visMode)) {
preparedURL += request.getContextPath() preparedURL += request.getContextPath()
+ "/admin/visQuery" + "/admin/visQuery"

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View file

@ -0,0 +1,174 @@
function getWellFormedURLs(given_uri, type) {
// general best practice is to put javascript code inside document.ready
// but in this case when i do that the function does not get called
// properly.
// so removing it for now.
// $(document).ready(function() {
if (type == "coauthorship") {
var finalURL = $.ajax({
url: contextPath + "/admin/visQuery",
data: ({vis: "utilities", vis_mode: "COAUTHORSHIP_URL", uri: given_uri}),
dataType: "text",
async: false,
success:function(data){
// console.log("COA - " + data);
}
}).responseText;
return finalURL;
} else if (type == "profile") {
var finalURL = $.ajax({
url: contextPath + "/admin/visQuery",
data: ({vis: "utilities", vis_mode: "PROFILE_URL", uri: given_uri}),
dataType: "text",
async: false,
success:function(data){
console.log("PROF - " + data);
}
}).responseText;
return finalURL;
} else if (type == "image") {
var finalURL = $.ajax({
url: contextPath + "/admin/visQuery",
data: ({vis: "utilities", vis_mode: "IMAGE_URL", uri: given_uri}),
dataType: "text",
async: false,
success:function(data){
console.log("IMAGE - " + data);
}
}).responseText;
return contextPath + finalURL;
// return finalURL;
}
// });
}
$.fn.image = function(src, successFunc, failureFunc){
return this.each(function(){
var i = new Image();
i.src = src;
i.onerror = failureFunc;
i.onload = successFunc;
// console.dir(i);
// this.appendChild(i);
return i;
});
}
function nodeClickedJS(obj){
$("#newsLetter").attr("style","visibility:visible");
$("#authorName").empty().append(obj[0]);
$("#works").empty().append(obj[1]);
/*
* Here obj[7] points to the uri of that individual
*/
if(obj[7]){
$("#profileUrl").attr("href", getWellFormedURLs(obj[7], "profile"));
$("#coAuthorshipVisUrl").attr("href", getWellFormedURLs(obj[7], "coauthorship"));
var imageLink = getWellFormedURLs(obj[7], "image");
} else{
$("#profileUrl").attr("href","#");
$("#coAuthorshipVisUrl").attr("href","#");
}
var imageContainer = $("#profileImage");
imageContainer.image(imageLink,
function(){
imageContainer.append(this);
},
function(){
/*
* For performing any action on failure to
* find the image.
*/
}
);
$("#coAuthorName").empty().append(obj[name]);
$("#coAuthors").empty().append(obj[5]);
$("#firstPublication").empty().append((obj[3])?obj[3]+" First Publication":"");
$("#lastPublication").empty().append((obj[4])?obj[4]+" Last Publication":"");
// obj[7]:the url parameter for node
}
function renderVisualization() {
//Version check for the Flash Player that has the ability to start Player
//Product Install (6.0r65)
var hasProductInstall = DetectFlashVer(6, 0, 65);
//Version check based upon the values defined in globals
var hasRequestedVersion = DetectFlashVer(requiredMajorVersion, requiredMinorVersion, requiredRevision);
if ( hasProductInstall && !hasRequestedVersion ) {
// DO NOT MODIFY THE FOLLOWING FOUR LINES
// Location visited after installation is complete if installation is
// required
var MMPlayerType = (isIE == true) ? "ActiveX" : "PlugIn";
var MMredirectURL = window.location;
document.title = document.title.slice(0, 47) + " - Flash Player Installation";
var MMdoctitle = document.title;
AC_FL_RunContent(
"src", "playerProductInstall",
"FlashVars", "MMredirectURL="+MMredirectURL+'&MMplayerType='+MMPlayerType+'&MMdoctitle='+MMdoctitle+"",
"width", "600",
"height", "800",
"align", "middle",
"id", "CoAuthor",
"quality", "high",
"bgcolor", "#ffffff",
"name", "CoAuthor",
"allowScriptAccess","sameDomain",
"type", "application/x-shockwave-flash",
"pluginspage", "http://www.adobe.com/go/getflashplayer"
);
} else if (hasRequestedVersion) {
// if we've detected an acceptable version
// embed the Flash Content SWF when all tests are passed
AC_FL_RunContent(
"src", swfLink,
"flashVars", "graphmlUrl=" + egoCoAuthorshipDataURL,
"width", "600",
"height", "800",
"align", "middle",
"id", "CoAuthor",
"quality", "high",
"bgcolor", "#ffffff",
"name", "CoAuthor",
"allowScriptAccess","sameDomain",
"type", "application/x-shockwave-flash",
"pluginspage", "http://www.adobe.com/go/getflashplayer"
);
} else { // flash is too old or we can't detect the plugin
var alternateContent = 'Alternate HTML content should be placed here. '
+ 'This content requires the Adobe Flash Player. '
+ '<a href=http://www.adobe.com/go/getflash/>Get Flash</a>';
document.write(alternateContent); // insert non-flash content
}
}

View file

@ -2,8 +2,12 @@
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%>
<c:set var="portalBean" value="${requestScope.portalBean}" /> <c:set var="portalBean" value="${requestScope.portalBean}" />
<c:set var="themeDir"><c:out value="${portalBean.themeDir}" /></c:set> <c:set var="themeDir">
<c:set var="contextPath"><c:out value="${pageContext.request.contextPath}" /></c:set> <c:out value="${portalBean.themeDir}" />
</c:set>
<c:set var="contextPath">
<c:out value="${pageContext.request.contextPath}" />
</c:set>
<c:url var="egoCoAuthorshipDataURL" value="/admin/visQuery"> <c:url var="egoCoAuthorshipDataURL" value="/admin/visQuery">
<c:param name="vis" value="coauthorship" /> <c:param name="vis" value="coauthorship" />
@ -13,10 +17,16 @@
</c:url> </c:url>
<c:url var="jquery" value="/js/jquery.js" /> <c:url var="jquery" value="/js/jquery.js" />
<c:url var="adobeFlashDetector" value="/js/visualization/coauthorship/AC_OETags.js"/> <c:url var="adobeFlashDetector"
<c:url var="style" value="/${themeDir}css/visualization/coauthorship/style.css"/> value="/js/visualization/coauthorship/AC_OETags.js" />
<c:url var="noImage" value="/${themeDir}site_icons/visualization/coauthorship/no_image.png"/> <c:url var="coAuthorShipJavaScript"
<c:url var="swfLink" value="/${themeDir}site_icons/visualization/coauthorship/CoAuthor.swf"/> value="/js/visualization/coauthorship/co_authorship.js" />
<c:url var="style"
value="/${themeDir}css/visualization/coauthorship/style.css" />
<c:url var="noImage"
value="/${themeDir}site_icons/visualization/coauthorship/no_image.png" />
<c:url var="swfLink"
value="/${themeDir}site_icons/visualization/coauthorship/CoAuthor.swf" />
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
@ -29,6 +39,7 @@
<script type="text/javascript" src="${adobeFlashDetector}"></script> <script type="text/javascript" src="${adobeFlashDetector}"></script>
<script language="JavaScript" type="text/javascript"> <script language="JavaScript" type="text/javascript">
<!-- <!--
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -40,12 +51,22 @@ var requiredMinorVersion = 0;
// Minor version of Flash required // Minor version of Flash required
var requiredRevision = 0; var requiredRevision = 0;
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
var swfLink = "${swfLink}";
var egoCoAuthorshipDataURL = "${egoCoAuthorshipDataURL}";
var contextPath = "${contextPath}";
// --> // -->
</script> </script>
<script type="text/javascript" src="${jquery}"></script> <script type="text/javascript" src="${jquery}"></script>
<link href="${style}" rel="stylesheet" type="text/css" /> <link href="${style}" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="${coAuthorShipJavaScript}"></script>
</head> </head>
<body> <body>
@ -56,201 +77,54 @@ var requiredRevision = 0;
</div> </div>
<div id="body"> <div id="body">
<div id="topShadow"></div> <div id="topShadow"></div>
<div id="bodyPannel" style="height:900px;"> <div id="bodyPannel" style="height: 900px;"><br class="spacer" />
<br class="spacer" />
<div id="visPanel" style="float: left; width: 610px;"> <div id="visPanel" style="float: left; width: 610px;">
<script language="JavaScript" type="text/javascript">
function getWellFormedURLs(given_uri, type) { <script type="text/javascript">
//general best practice is to put javascript code inside document.ready
//but in this case when i do that the function does not get called properly.
//so removing it for now.
//$(document).ready(function() {
if (type == "coauthorship") {
var finalURL = $.ajax({
url: "${contextPath}/admin/visQuery",
data: ({vis: "utilities", vis_mode: "COAUTHORSHIP_URL", uri: given_uri}),
dataType: "text",
async: false,
success:function(data){
//console.log("COA - " + data);
}
}).responseText;
return finalURL;
} else if (type == "profile") {
var finalURL = $.ajax({
url: "${contextPath}/admin/visQuery",
data: ({vis: "utilities", vis_mode: "PROFILE_URL", uri: given_uri}),
dataType: "text",
async: false,
success:function(data){
//console.log("PROF - " + data);
}
}).responseText;
return finalURL;
} else if (type == "image") {
var finalURL = $.ajax({
url: "${contextPath}/admin/visQuery",
data: ({vis: "utilities", vis_mode: "IMAGE_URL", uri: given_uri}),
dataType: "text",
async: false,
success:function(data){
//console.log("PROF - " + data);
}
}).responseText;
return finalURL;
}
//});
}
$.fn.image = function(src, successFunc, failureFunc){
return this.each(function(){
var i = new Image();
i.src = src;
i.onerror = failureFunc;
i.onload = successFunc;
//console.dir(i);
//this.appendChild(i);
return i;
});
}
function nodeClickedJS(obj){
$("#newsLetter").attr("style","visibility:visible");
$("#authorName").empty().append(obj[0]);
//$("#works").append("<img src='assets/Garfield.jpg'/><br /><br />");
$("#works").empty().append(obj[1]);
/*
Here obj[7] points to the uri of that individual
*/
if(obj[7]){
$("#profileUrl").attr("href", getWellFormedURLs(obj[7], "profile"));
$("#coAuthorshipVisUrl").attr("href", getWellFormedURLs(obj[7], "coauthorship"));
var imageLink = getWellFormedURLs(obj[7], "image");
} else{
$("#profileUrl").attr("href","#");
$("#coAuthorshipVisUrl").attr("href","#");
}
var imageContainer = $("#profileImage");
imageContainer.image(imageLink,
function(){
imageContainer.append(this);
console.log("The image is loaded now");
},
function(){console.log("The image is NOT loaded");}
);
$("#coAuthorName").empty().append(obj[name]);
$("#coAuthors").empty().append(obj[5]);
$("#firstPublication").empty().append((obj[3])?obj[3]+" First Publication":"");
$("#lastPublication").empty().append((obj[4])?obj[4]+" Last Publication":"");
//obj[7]:the url parameter for node
}
<!-- <!--
// Version check for the Flash Player that has the ability to start Player Product Install (6.0r65)
var hasProductInstall = DetectFlashVer(6, 0, 65);
// Version check based upon the values defined in globals renderVisualization();
var hasRequestedVersion = DetectFlashVer(requiredMajorVersion, requiredMinorVersion, requiredRevision);
if ( hasProductInstall && !hasRequestedVersion ) {
// DO NOT MODIFY THE FOLLOWING FOUR LINES
// Location visited after installation is complete if installation is required
var MMPlayerType = (isIE == true) ? "ActiveX" : "PlugIn";
var MMredirectURL = window.location;
document.title = document.title.slice(0, 47) + " - Flash Player Installation";
var MMdoctitle = document.title;
AC_FL_RunContent(
"src", "playerProductInstall",
"FlashVars", "MMredirectURL="+MMredirectURL+'&MMplayerType='+MMPlayerType+'&MMdoctitle='+MMdoctitle+"",
"width", "600",
"height", "800",
"align", "middle",
"id", "CoAuthor",
"quality", "high",
"bgcolor", "#ffffff",
"name", "CoAuthor",
"allowScriptAccess","sameDomain",
"type", "application/x-shockwave-flash",
"pluginspage", "http://www.adobe.com/go/getflashplayer"
);
} else if (hasRequestedVersion) {
// if we've detected an acceptable version
// embed the Flash Content SWF when all tests are passed
AC_FL_RunContent(
"src", "${swfLink}",
"flashVars", "graphmlUrl=${egoCoAuthorshipDataURL}",
"width", "600",
"height", "800",
"align", "middle",
"id", "CoAuthor",
"quality", "high",
"bgcolor", "#ffffff",
"name", "CoAuthor",
"allowScriptAccess","sameDomain",
"type", "application/x-shockwave-flash",
"pluginspage", "http://www.adobe.com/go/getflashplayer"
);
} else { // flash is too old or we can't detect the plugin
var alternateContent = 'Alternate HTML content should be placed here. '
+ 'This content requires the Adobe Flash Player. '
+ '<a href=http://www.adobe.com/go/getflash/>Get Flash</a>';
document.write(alternateContent); // insert non-flash content
}
//--> //-->
</script> </script>
</div> </div>
<div id="dataPanel" style="float:left; width:150px;"> <div id="dataPanel" style="float: left; width: 150px;"><br />
<br/><br/><br/><br/><br/><br/> <br />
<div id="newsLetter" style="visibility:hidden"> <span class="nltop"></span> <br />
<br />
<br />
<br />
<div id="newsLetter" style="visibility: hidden">
<span class="nltop"></span>
<div class="middle" id="nodeData"> <div class="middle" id="nodeData">
<div id="profileImage"></div> <div id="profileImage"></div>
<div class="bold"><strong><span id="authorName">&nbsp;</span></strong></div> <div class="bold"><strong><span id="authorName">&nbsp;</span></strong></div>
<!-- <div class="italicize">Professor</div> <!-- <div class="italicize">Professor</div>
<div class="italicize">Department of <span>???</span></div> <div class="italicize">Department of <span>???</span></div>
--> --> <br />
<div class="works"><span class="numbers" style="width: 40px;"
id="works">6</span>&nbsp;&nbsp;<span class="title">Works</span></div>
<div class="works"><span class="numbers" style="width: 40px;"
id="coAuthors">78</span>&nbsp;&nbsp;<span>Co-author(s)</span></div>
<br /> <br />
<div class="works"><span class="numbers" style="width:40px;" id="works">6</span>&nbsp;&nbsp;<span class="title">Works</span></div> <div id="firstPublication"><span></span>&nbsp;<span>First
<div class="works"><span class="numbers" style="width:40px;" id="coAuthors">78</span>&nbsp;&nbsp;<span>Co-author(s)</span></div> Publication</span></div>
<br/>
<div id="firstPublication"><span ></span>&nbsp;<span>First Publication</span></div>
<div id="lastPublication"><span></span>&nbsp;Last Publication</div> <div id="lastPublication"><span></span>&nbsp;Last Publication</div>
<br /> <br />
<div><a href="#" id="profileUrl">Go to VIVO profile</a></div> <div><a href="#" id="profileUrl">Go to VIVO profile</a></div>
<br /> <br />
<div><a href="#" id="coAuthorshipVisUrl">Go to ego-centric co-author network of <span id="coAuthorName"></span></a></div> <div><a href="#" id="coAuthorshipVisUrl">Go to ego-centric
co-author network of <span id="coAuthorName"></span></a></div>
</div> </div>
<div id="image_test"></div> <div id="image_test"></div>
<br class="spacer"> <br class="spacer"> <span class="nlbottom"></span>
<span class="nlbottom"></span></div> </div>
</div> </div>
</div> </div>
<div id="bottomShadow"></div> <div id="bottomShadow"></div>
@ -259,7 +133,19 @@ if ( hasProductInstall && !hasRequestedVersion ) {
<script> <script>
$(document).ready(function(){ $(document).ready(function(){
var obj = jQuery.parseJSON('{"name":"John"}');
console.log(obj)
var obj = jQuery.parseJSON('{"imageOffset2":["sup"],"A":["2001","2002","2003","2090","Unknown"],"B":["2001","2002","2003","2090","Unknown"],"C":["2001","2002","2003","2090","Unknown"],"imageOffset":["2090","2002","2003","2001"]}');
console.log(obj)
$.each(obj, function(i, item){
console.log("i - " + i + " item - " + item);
$.each(item, function(index, vals) {
console.log(index + " - val - " + vals);
});
});
}); });
</script> </script>