blob: 565e8ce32925e57bd71156efdbb2388f7bcb500b [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* The sling javascript client gives access to a JCR repository
* from client-side java code, using the sling post servlet as a back-end.
*
* @version $Rev: $, $Date: 2007-03-27 16:30:52 +0200 (Tue, 27 Mar 2007) $
*/
var Sling = null;
// start sling code scope
(function() {
Sling = new Object();
Sling.NAME_OF_THIS_FILE = "sling.js";
Sling.PATH_OF_THIS_FILE = "/system/sling.js";
/** This method tries to figure out what to do with a page */
Sling.wizard = function() {
//TODO add lots of magic here
var form=document.getElementById("slingform");
if (!form) form=document.forms[0];
if (form) {
var sp=new Object();
sp.formElement=form;
Sling.setupPage(sp);
}
}
/** Call this to merge sling data in an HTML page
TODO deprecate other functions
*/
Sling.setupPage = function(options) {
var tree = Sling.getContent(Sling._getJsonUrl(),1);
if(options.formElement) {
Sling._setFormValues(options.formElement,Sling._getJsonUrl(),tree);
}
if(options.displayElement) {
Sling.displayValues(options.displayElement,tree);
}
}
/**
* HTTP GET XHR Helper
* @param {String} url The URL
* @param {Function} optional second parameter for async version of the method.
* The callback will get the XHR object, method returns immediately
* @return the XHR object, use .responseText for the data
* @type String
*/
Sling.httpGet = function(url, callback) {
var httpcon = Sling.getXHR();
if (httpcon) {
if(callback) {
httpcon.onload = function() { callback(this); };
httpcon.open('GET', url);
httpcon.send(null);
} else {
httpcon.open('GET', url, false);
httpcon.send(null);
return httpcon;
}
} else {
return null;
}
}
/**
* Produces a "sort-of-json" string representation of a object
* for debugging purposes only
* @param {Object} obj The object
* @param {int} level The indentation level
* @return The result
* @type String
*/
Sling.dumpObj = function(obj, level) {
var res = "";
for (var a in obj) {
if (typeof(obj[a])!="object") {
res+=a+":"+obj[a]+" ";
} else {
res+=a+": { ";
res+=Sling.dumpObj(obj[a])+"} ";
}
}
return (res);
}
/** Produces an aggregate of get all the property names used
* in a tree as a helper for table oriented display
* @param {Object} obj The Content Tree object
* @param {Object} names internal object used for collecting all
* the names during the recursion
* @return An Array of names of properties that exist in a tree
* @type Array
*/
Sling.getAllPropNames = function(obj, names) {
var root = false;
if (!names) {
names=new Object();
root=true;
}
for (var a in obj) {
if (typeof(obj[a])!="object") {
names[a]="1";
} else {
getAllPropNames(obj[a], names);
}
}
if (root) {
var ar=new Array();
var i=0;
for (var a in ar) {
ar[i]=a;
i++;
}
names=ar;
}
return (names);
}
/** Reads a tree of items given a maxlevel from the repository as JSON
* @param {String} path Path into the current workspace
* @param {int} maxlevel maximum depth to traverse to
* @param {Array} filters filter only these properties
* @return An Object tree of content nodes and properties, null if not found
* @type Object
*/
Sling.getContent = function(path, maxlevels, filter) {
var obj=new Object();
if (!path) {
path=Sling.currentPath;
}
if (path.indexOf("/")==0) {
/*
this assumes that paths that start with a slash
are meant to be workspace paths rather than URLs
and therefore need some additions before they are sent
to the server
*/
if(maxlevels == "0" || maxlevels) {
maxlevels = "." + maxlevels;
} else {
maxlevels = "";
}
path=Sling.baseurl + path + maxlevels + ".json";
}
//checking for a trailing "/*"
if (path.indexOf("/*")>=0) return obj;
// TODO for now we explicitely defeat caching on this...there must be a better way
// but in tests IE6 tends to cache too much
var passThroughCacheParam = "?clock=" + new Date().getTime();
var res=Sling.httpGet(path + passThroughCacheParam + (maxlevels?"&maxlevels="+maxlevels:""));
if(res.status == 200) {
var obj=Sling.evalString(res.responseText);
if (!filter) {
for (var a in obj) {
if (a.indexOf("jcr:")==0) delete(obj[a]);
}
}
return obj;
}
return null;
}
/** Remove content by path */
Sling.removeContent = function(path) {
var httpcon = Sling.getXHR();
if (httpcon) {
var params = ":operation=delete";
httpcon.open('POST', Sling.baseurl + path, false);
// Send the proper header information along with the request
httpcon.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
httpcon.setRequestHeader("Content-length", params.length);
httpcon.setRequestHeader("Connection", "close");
httpcon.send(params);
return httpcon;
} else {
return false;
}
}
/** eval str, accepting various object delimiters */
Sling.evalString = function(str) {
return JSON.parse(str);
}
/** Get "session info" from repository. Mainly answers the question: "Who am I"
* and "Which workspace am I logged into.
* @return An Object tree containing the session information, null if server status <> 200
* @type Object
*/
Sling.getSessionInfo = function() {
var res=Sling.httpGet(Sling.baseurl+"/system/sling/info.sessionInfo.json");
if(res.status == 200) {
return Sling.evalString(res.responseText);
}
return null;
}
/** Get "session info" from repository. Mainly answers the question: "Who am I"
* and "Which workspace am I logged into. Async version of getSessionInfo
* @param {Function} callback function, will get an An Object tree as first argument
* containing the session information, null if server status <> 200
*/
Sling.getSessionInfoAsync = function(callback) {
var res = Sling.httpGet(Sling.baseurl+"/system/sling/info.sessionInfo.json",
function(res) {
if(res.status == 200) {
var info = Sling.evalString(res.responseText);
callback(info);
} else {
callback(null);
}
});
}
/** Replace extension in a path */
Sling._replaceExtension = function(path,newExtension) {
var i = path.lastIndexOf(".");
if(i >= 0) path = path.substring(0,i);
i = path.lastIndexOf(".");
if(i >= 0) path = path.substring(0,i);
return path + newExtension;
}
/** Get the JSON data URL that for the current page
* (assuming a .extension for the current page, .html or something else)
*/
Sling._getJsonUrl = function() {
return Sling._replaceExtension(window.location.href,".json");
}
/** Get the content repository path from the URL
* (assuming a .extension for the current page, .html or something else)
*/
Sling._getPath = function() {
var noextensions=Sling._replaceExtension(window.location.href,"");
var path=noextensions.substring(Sling.baseurl.length);
return (path);
}
/** Display values inside a container: an element inside given container,
* with an id like ./stuff, has its innerHTML set to the value of stuff
* in the tree, if it exists.
*/
Sling.displayValues = function(container,tree) {
if(!tree) {
tree = Sling.getContent(Sling._getJsonUrl(),1);
}
var elements = container.getElementsByTagName("*");
var toSet = new Array();
for (var i = 0; i < elements.length; i++) {
var value = Sling._getElementValue(elements[i],tree);
if(value) {
toSet[toSet.length] = { e:elements[i], v:value };
}
}
for(var i = 0; i < toSet.length; i++) {
toSet[i].e.innerHTML = toSet[i].v;
}
}
/** If e has an ID that matches a property of tree, set e's innerHTML accordingly */
Sling._getElementValue = function(e,tree) {
var id = e.getAttribute("id");
if(id) {
return tree[id.substring(2)];
}
}
/** Set form elements based on the tree of items passed into the method
* @param {IdOrElement} form the Form element to set, or its id
* @param {String} path passes a string specifying the path
* @param {Object} tree optionally pass the content that you want the
* form to be populated with. This assumes an item tree as returned by
* getContent().
* Returns an object indicating whether data was found on the server.
*
*/
Sling._setFormValues = function(form, path, tree) {
var result = new Object();
/** TODO: deal with abolute paths?
* TODO: deal with @ValueFrom
*/
if (!path) return;
form.setAttribute("action", path);
if (!tree) {
tree=Sling.getContent(path,1);
}
var elems=form.elements;
var i=0;
formfieldprefix="";
while (elems.length > i) {
var elem=elems[i];
var a=elem.name;
if (a.indexOf("./")==0) {
formfieldprefix="./";
break;
}
i++;
}
var i=0;
while (elems.length > i) {
var elem=elems[i];
var a=elem.name;
if (a.indexOf("/")==0) {
var nodepath=a.substring(0,a.lastIndexOf("/"));
var propname=a.substring(a.lastIndexOf("/")+1);
var node=Sling.getContent(nodepath);
var propval=node[propname];
} else if (a.indexOf(formfieldprefix)==0) {
var propname=a.substring(formfieldprefix.length);
var propval=tree[propname];
}
if (propval) {
if (elem.type == "file") {
// cannot edit uplodaded files for now
} else if (elem.type == "checkbox") {
var vals;
if (typeof(propval)=="object") vals=propval;
else {
vals=new Array();
vals[0]=propval;
}
var j=0;
while (vals.length > j) {
if (vals[j] == elem.value) elem.checked=true;
j++;
}
} else {
elem.value=propval;
}
}
i++;
}
}
/** return Path as specified as the URL Parameter
* @param URL
* @return The Path parameter isolated from the URL
* @type String
*/
Sling.TODO_NOT_USED_isolatePathFromUrl = function(url) {
var pattern = "[\\?&]Path=([^&#]*)";
var regex = new RegExp( pattern );
var results = regex.exec( url );
if( results == null )
// none found
return "";
else
// found
return unescape(results[1]);
}
/**
* Get an XMLHttpRequest in a portable way
*
*/
Sling.getXHR = function () {
var xhr=null;
if(!xhr) {
try {
// built-in (firefox, recent Opera versions, etc)
xhr=new XMLHttpRequest();
} catch (e) {
// ignore
}
}
if(!xhr) {
try {
// IE, newer versions
xhr=new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
// ignore
}
}
if(!xhr) {
try {
// IE, older versions
xhr=new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {
// ignore
}
}
if(!xhr) {
alert("Unable to access XMLHttpRequest object, sling will not work!");
}
return xhr;
}
// obtain the base_url to communicate with sling on the server
var scripts = document.getElementsByTagName("SCRIPT")
for (var i = 0; i < scripts.length; i++) {
var scriptSrc = scripts[i].src
if (scriptSrc.match(Sling.PATH_OF_THIS_FILE+"$")) {
Sling.baseurl = scriptSrc.substring(0,scriptSrc.length - Sling.PATH_OF_THIS_FILE.length);
Sling.currentPath = Sling._getPath();
Sling.isNew = (Sling.currentPath.indexOf("/*")>=0)?true:false;
break;
}
}
// end sling code scope
})();