Lotus Notes Xpages, How to get "Content-Range" in api document - xpages

I have a url /{database}/api/data/collections/name/{name}.
How to get all entry of view {name} with getResponseHeader("Content-Range")?

SSJS
You can get all response header fields with HttpURLConnection's method getHeaderFields().
Pick your wanted header field with get('Content-Range').
Example:
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
<xp:text escape="true" id="computedField1">
<xp:this.value><![CDATA[#{javascript:
var url = new java.net.URL(
"http://yourServer/yourDatabase.nsf/api/data/collections/name/All");
var conn:java.net.HttpURLConnection = url.openConnection();
conn.setRequestProperty("Accept", "application/json");
if (conn.getResponseCode() == "200") {
try {
return conn.getHeaderFields().get('Content-Range');
} catch(e) {
return 'Error reading header field "Content-Range"';
}
} else {
return 'Error ' + conn.getResponseCode() + " " + conn.getResponseMessage();
}
}]]></xp:this.value>
</xp:text>
</xp:view>
This example XPage renders as result e.g. items 0-9/35 and indicates that the response includes entries 0 through 9 of a total of 35 entries.
If you want to get the total number of entries only then change the line
return conn.getHeaderFields().get('Content-Range');
to
var range = conn.getHeaderFields().get('Content-Range').get(0);
var total = range.substr(range.indexOf('/') + 1);
return total;
This will render for the same URL 35 only.
CSJS
Use XMLHttpRequest's method getResponseHeader() on client side:
var xhr = new XMLHttpRequest();
xhr.open('GET', url, false);
xhr.send(null);
var range = xhr.getResponseHeader("Content-Range");
var total = range.substr(range.indexOf('/') + 1);
return total

Related

Enforce unique values based on multiple columns

I'm trying to enforce unique values based on 3 columns. i'm trying for SharePoint online.
Lookup column
Choice
Calendar (only date)
I tried with below code, able to retrieve the existing values from the list but Calendar date selection is getting failed. not able to figure out what can be done. can anyone help on this,
<script type="text/javascript" src="/sites/Mysite/SiteAssets/jquery.min.js"></script><script type="text/javascript">
//variable to hold Ajax result
var dataResults;
var call = $.ajax({
url: _spPageContextInfo.webAbsoluteUrl + "/_api/Web/Lists/GetByTitle('Mylist')/Items?" + "$select=Title,Engagement,Period",
//Title is a lookup column
type: "GET",
dataType: "json",
async:false,
headers: {
Accept: "application/json;odata=verbose"
},
success: function(data) {
dataResults = data.d;
}
});
function PeriodValue(fullDate){
var orderDateString = "2016-10-19T22:00.00Z"; //UTC datetime value from REST response
var orderDate = new Date(orderDateString);
var value= TimeZoneUtilities.utcToLocalTime(_spPageContextInfo.webAbsoluteUrl,orderDate);
alert(value);
var dateValue=null,twoDigitDate=null,twoDigitMonth=null,twoDigitYear,currentDate=null;
dateValue = fullDate.split("T")[0];
twoDigitDate = dateValue.split("-")[2];
twoDigitMonth = dateValue.split("-")[1];
twoDigitYear = dateValue.split("-")[0];
currentDate = twoDigitDate + "/" + twoDigitMonth + "/" + twoDigitYear;
return currentDate;
}
//function to compare user input and existing data
function PreSaveAction(){
var ClientName = document.querySelector('[title="Client Name Required Field"]');
var engagement = document.querySelector('[title="Engagement Required Field"]');
var period = document.querySelector('[title="Period Required Field"]');
ClientName=ClientName.options[ClientName.selectedIndex].text;
engagement=engagement.options[engagement.selectedIndex].text;
period=period.value;
var c = null;
$.each(dataResults, function(i, item){
c = true;
$.each(item, function(i, dt){
console.log(dt.Engagement + ' ' + dt.Period + ' ' +dt.Title);
if (dt.Engagement == engagement && dt.Period == period && dt.Title==ClientName){
c = false;
alert("Already exist");
return c;
}
});
});
return c;
}
</script>​​

restricting the numbers of items to be added tosharepoint list per day

is there anyway that we could restrict the number of items to be added to a list for instance 30 items can be only added in 1 day. and then a message should appear if the number 31 tried to add new item, and tomorrow users will also be able to add 30 items and so on.
I found the below script that could limit the over all number of items to be added to 60.
<input type="button" value="Sign Up Now!" onclick="createItemIfBelowLimit()" />
<script>
function createItemIfBelowLimit(){
var max = 60;
var listTitle = "Your List Title";
var clientContext = new SP.ClientContext();
var list = clientContext.get_web().get_lists().getByTitle(listTitle);
clientContext.load(list);
clientContext.executeQueryAsync(function(){
var itemCount = list.get_itemCount();
if(itemCount < max){
createItem(listTitle,{
"Title":"Example title text",
"Body":"Example body text"
});
}else{
alert("This sign-up list is full. Sorry!");
}
},function(sender,args){
alert(args.get_message());
});
}
function createItem(listTitle,values){
var clientContext = new SP.ClientContext();
var list = clientContext.get_web().get_lists().getByTitle(listTitle);
var newItem = list.addItem();
for(var key in values){
newItem.set_item(key,values[key]);
}
newItem.update();
clientContext.load(newItem);
var rootFolder = list.get_rootFolder(); // Note: use a list's root folder to determine its server relative URL
clientContext.load(rootFolder);
clientContext.executeQueryAsync(function(){
var itemId = newItem.get_item("ID");
SP.UI.ModalDialog.showModalDialog(
{
title: "Item #"+itemId+" Created Successfully!",
url: rootFolder.get_serverRelativeUrl() + "/DispForm.aspx?ID="+itemId
}
);
},function(sender,args){
alert(args.get_message());
});
}
</script>
If you can use SharePoint server object model then solid solution would be to implement SharePoint list item event receiver class based on SPItemEventReceiver class where you can override method
public override void ItemAdding(SPItemEventProperties properties)
and then cancel adding new list item to list by using code:
properties.Status = SPEventReceiverStatus.CancelNoError;
Modify the code as below to achieve it, add the CAML Query to get all today added items, and check the item count.
<script type="text/javascript" language="javascript">
ExecuteOrDelayUntilScriptLoaded(createItemIfBelowLimit, "sp.js");
function createItemIfBelowLimit(){
var max = 30;
var listTitle = "Your List Title";
var clientContext = new SP.ClientContext();
var list = clientContext.get_web().get_lists().getByTitle(listTitle);
var camlQuery = new SP.CamlQuery();
var query="<View Scope='RecursiveAll'><Query><Where><Eq><FieldRef Name='Created'/><Value Type='DateTime' IncludeTimeValue='FALSE'><Today/></Value></Eq></Where></Query></View>";
camlQuery.set_viewXml(query);
this.collListItem = list.getItems(camlQuery);
clientContext.load(collListItem);
clientContext.executeQueryAsync(function(){
var itemCount = collListItem.get_count();
if(itemCount < max){
createItem(listTitle,{
"Title":"Example title text",
"Body":"Example body text"
});
}else{
alert("This sign-up list is full. Sorry!");
}
},function(sender,args){
alert(args.get_message());
});
}
function createItem(listTitle,values){
var clientContext = new SP.ClientContext();
var list = clientContext.get_web().get_lists().getByTitle(listTitle);
var newItem = list.addItem();
for(var key in values){
newItem.set_item(key,values[key]);
}
newItem.update();
clientContext.load(newItem);
var rootFolder = list.get_rootFolder(); // Note: use a list's root folder to determine its server relative URL
clientContext.load(rootFolder);
clientContext.executeQueryAsync(function(){
var itemId = newItem.get_item("ID");
SP.UI.ModalDialog.showModalDialog(
{
title: "Item #"+itemId+" Created Successfully!",
url: rootFolder.get_serverRelativeUrl() + "/DispForm.aspx?ID="+itemId
}
);
},function(sender,args){
alert(args.get_message());
});
}
</script>

Xpages - Return correct documents using getDocumentByKey(unid, true)

I have a list, but I only want to narrow down my list to only documents with the current unid which appears on the browser, I did this by calling on the getDocumentByKey method of the viewEv object and pass in the unid arguement.
Strangly, this worked for only the newest document. The other documents, just shows all the list not belonging to the unid on the browser.
Any help will be appreciated.
Below is my code:
function getCalObj(){
var viewEv:NotesView = database.getView("Diary");
viewEv.setAutoUpdate(false);
var docEv:NotesDocument = viewEv.getFirstDocument();
var doc:NotesDocument = diaryDoc.getDocument();
var sUNID = doc.getUniversalID();
print("unid: " + sUNID);
docEv = viewEv.getDocumentByKey(sUNID, true);
while (docEv != null) {
........
}
}
Use getAllDocumentsByKey() to get all documents with this sUNID.
var dcEv:NotesDocumentCollection = viewEv.getAllDocumentsByKey(sUNID);
if (dcEv.getCount() > 0) {
var docEv:NotesDocument = dcEv.getFirstDocument();
while (docEv != null) {
........
}

getting values from first categorized view column in typeAhead in XPages

I would like to use typeAhead functionality in a inputBox. Values should get only the first categorized column( Column[0]); Because I have so many document belong to the same customer. I only need customer names as unique. Please find what i tried so far below. in this view only the first column is categorized. Others are not.
I think i miss something :(
<xp:inputText id="inpCustomer" value="#{document1.CustomerName}">
<xp:typeAhead mode="partial" minChars="2" ignoreCase="true" var="lupkey" valueMarkup="true" id="typeAhead1">
<xp:this.valueList><![CDATA[#{javascript:try
{
var procedureName = "fonck1";
var searchOutput:Array = [];
var v:NotesView = database.getView("(ctgViewName)");
var nav:NotesViewNavigator = v.createViewNavFromCategory(lupkey);
var viewEnt:NotesViewEntry = nav.getFirstDocument();
var tmp:NotesViewEntry;
while (viewEnt !== null)
{
searchOutput.push(entry.getColumnValues()[0]);
tmp = viewEnt;
viewEnt = nav.getNextCategory();
tmp.recycle();
}
var result ="<ul><li><span class='informal'></span></li>";
var limit = Math.min(hits,200);
for (j=0; j<limit; j++)
{
var name = searchOutput[j].toString();
var start = name.indexOfIgnoreCase(lupkey)
var stop = start + lupkey.length;
name = name.insert("</b>",stop).insert("<b>",start);
result += "<li>" + name + "</li>";
}
result += "</ul>";
return result;
}
catch(e)
{
print(e.toString());
throw(e);
}}]]></xp:this.valueList>
</xp:typeAhead>
<xp:this.attrs>
<xp:attr name="placeholder" value="Please enter customer name..." />
</xp:this.attrs>
</xp:inputText>
Reduce searchOutput array to just the names which start with the entered characters.
Start view navigator at first occurence of such a name:
var v:NotesView = database.getView("(ctgViewName)");
var viewEnt:NotesViewEntry = v.getEntryByKey(lupkey, false)
var nav:NotesViewNavigator = v.createViewNavFrom(viewEnt);
Stop putting names into searchOutput array when name starts different than lupkey.
Replace your first line in while statement with:
var name:String = entry.getColumnValues()[0];
if (!name.startsWith(lupkey)) {
break;
}
searchOutput.push(name);

CAML query contains does not work

I've got this code, which takes a part of the title to perform a query and filter part of the content of a list:
<script type="text/javascript">
var items_lista;
SP.SOD.executeFunc('sp.js', 'SP.ClientContext', Initialize);
function Initialize() {
var PDP_Link_Filter = $("title").text().split("-")[1].split(".")[0];
PDP_Link_Filter = "Link_" + PDP_Link_Filter + "_";
var contexto = SP.ClientContext.get_current();
var web = contexto.get_web();
var listas = web.get_lists();
var parametros = listas.getByTitle('Parametrizacion_WF');
var query = new SP.CamlQuery();
query.set_viewXml("<Query><Where><Contains><FieldRef Name='Title'/>" +
"<Value Type='Text'>" + PDP_Link_Filter + "</Value></Contains></Where></Query>");
console.log(query);
items_lista = parametros.getItems(query);
contexto.load(items_lista);
contexto.executeQueryAsync(Function.createDelegate(this, this.onRequestSucceeded), Function.createDelegate(this, this.onRequestFailed));
} //Initialize
function onRequestSucceeded()
{
console.log(items_lista);
for(i = 0; i < items_lista.get_count(); i++)
{
console.log(items_lista.get_item(i).get_item('Title'));
}
}
function onRequestFailed() { console.log('Error'); }
</script>
The query filter that it generates (obtained through console.log()):
<Query><Where><Contains><FieldRef Name='Title'/><Value Type='Text'>P000</Value></Contains></Where></Query>
But when the for loop runs it shows all the content of the list not just the rows that match the filter.
What am I doing wrong?
This is most probably related with malformed value for SP.CamlQuery.viewXml property. Since this property expects XML schema that defines the list view, the root element has to be View element, for example:
var ctx = SP.ClientContext.get_current();
var list = ctx.get_web().get_lists().getByTitle(listTitle);
var items = list.getItems('<View Scope="RecursiveAll"><Query></Query></View>');
In your case enclose the query with View element:
<View>
<Query>...</Query>
</View>

Resources