Sharepoint encodes the URLs with unicode, so we’ll see many \u002f to represent /.
If you want to decode those unicode strings, you can use this short code:
unescape(JSON.parse('"' + s.replace('"', '\\"') + '"'))
Sharepoint encodes the URLs with unicode, so we’ll see many \u002f to represent /.
If you want to decode those unicode strings, you can use this short code:
unescape(JSON.parse('"' + s.replace('"', '\\"') + '"'))
When I open a dialog for an EditFrom and use the “Delete Item” button from the ribbon, then the main page is redirected to the related Sharepoint list. This behavior is very bad for the user experience.
To change it I used the below Javascript code:
// replace the Delete Item default action when into a popup
$(document).ready(function() {
// if it's in a popup
if (window !== window.top) {
$('a[id$="_toolBarTbl_RptControls_diidIODeleteItem"]').attr("href","javascript:commonDeleteItem(); return false")
}
})
// now when clicking on the Delete item it will call my own function
// here I use http://aymkdn.github.io/SharepointPlus/ to show a waiting message and to delete the current item, and then close the modal
function commonDeleteItem() {
$SP().waitModalDialog("Deleting...");
$SP().list("{"+WPQ2FormCtx.ListAttributes.Id+"}").remove({ID:GetUrlKeyValue("ID")}, {
after:function() {
$SP().closeModalDialog();
$SP().closeModalDialog(2);
}
})
}
With Sharepoint 2010, when you use Internet Explorer you can open an Office document in readonly or in edit mode. Also, when trying to open an Excel file in Firefox/Chrome it will probably open the ugly xslviewer and won’t let you deal with your file.
After searching a bit about it, I found a clue that helped me to find a good solution: on Firefox/Chrome when you click on an Excel file, you’ll now have a modal asking if you want to open it in edit or readonly mode!

To achieve this result you have to insert the below Javascript code somewhere into your masterpage:
/**
* fix problem with Excel documents on Firefox/Chrome
* @param {HTMLElement} p the <A> element
* @param {HTMLEvent} a the click event
* @param {Boolean} h TRUE
* @param {Boolean} e FALSE
* @param {Boolean} g FALSE
* @param {Strin} k the ActiveX command (e.g. "SharePoint.OpenDocuments.3")
* @param {Number} c 0
* @param {String} o the activeX command, here we look at "SharePoint.OpenDocuments"
* @param {String} m
* @param {String} b the replacement URL to the xslviewer
*/
var bak_DispEx;
var modalOpenDocument; // it will be use with the modal
SP.SOD.executeOrDelayUntilEventNotified(function() {
bak_DispEx = _DispEx;
_DispEx=function(p, a, h, e, g, k, c, o, m, b, j, l, i, f, d) {
// if o==="SharePoint.OpenDocuments" && !IsClientAppInstalled(o)
// in that case we want to open ask the user if he/she wants to readonly or edit the file
var fileURL = b.replace(/.*_layouts\/xlviewer\.aspx\?id=(.*)/, "$1");
if (o === "SharePoint.OpenDocuments" && !IsClientAppInstalled(o) && /\.xlsx?$/.test(fileURL)) {
// if the URL doesn't start with http
if (!/^http/.test(fileURL)) {
fileURL = window.location.protocol + "//" + window.location.host + fileURL;
}
var ohtml = document.createElement('div');
ohtml.style.padding = "10px";
ohtml.style.display = "inline-block";
ohtml.style.width = "200px";
ohtml.style.width = "200px";
ohtml.innerHTML = '<style>'
+ '.opendocument_button { background-color:#fdfdfd; border:1px solid #ababab; color:#444; display:inline-block; padding: 7px 10px; }'
+ '.opendocument_button:hover { box-shadow: none }'
+ '#opendocument_readonly,#opendocument_edit { float:none; font-size: 100%; line-height: 1.15; margin: 0; overflow: visible; box-sizing: border-box; padding: 0; height:auto }'
+ '.opendocument_ul { list-style-type:none;margin-top:10px;margin-bottom:10px;padding-top:0;padding-bottom:0 }'
+ '</style>'
+ 'You are about to open:'
+ '<ul class="opendocument_ul">'
+ ' <li>Name: <b>'+fileURL.split("/").slice(-1)+'</b></li>'
+ ' <li>From: <b>'+window.location.hostname+'</b></li>'
+ '</ul>'
+ 'How would like to open this file?'
+ '<ul class="opendocument_ul">'
+ ' <li><label><input type="radio" name="opendocument_choices" id="opendocument_readonly" checked> Read Only</label></li>'
+ ' <li><label><input type="radio" name="opendocument_choices" id="opendocument_edit"> Edit</label></li>'
+ '</ul>'
+ '<div style="text-align: center;margin-top: 20px;"><button type="button" class="opendocument_button" style="background-color: #2d9f2d;color: #fff;" onclick="modalOpenDocument.close(document.getElementById(\'opendocument_edit\').checked)">Open</button> <button type="button" class="opendocument_button" style="margin-left:10px" onclick="modalOpenDocument.close(-1)">Cancel</button></div>';
// show the modal
modalOpenDocument=SP.UI.ModalDialog.showModalDialog({
html:ohtml,
dialogReturnValueCallback:function(ret) {
if (ret!==-1) {
if (ret === true) { // edit
// reformat the fileURL
var ext;
if (/\.xlsx?$/.test(b)) ext = "ms-excel";
if (/\.docx?$/.test(b)) ext = "ms-word"; // not currently supported
fileURL = ext + ":ofe|u|" + fileURL;
}
window.location.href = fileURL; // open the file
}
}
});
a.preventDefault();
a.stopImmediatePropagation()
a.cancelBubble = true;
a.returnValue = false;
return false;
}
return bak_DispEx.apply(this, arguments);
}
}, "sp.scriptloaded-core.js")
This is an update of this article.
This time the JS Link file’s content is the one below:
// loadExt permits to load JS and CSS files
// https://gist.github.com/Aymkdn/98acfbb46fbe7c1f00cdd3c753520ea8
function loadExt(e,t){var s=this;s.files=e,s.js=[],s.head=document.getElementsByTagName("head")[0],s.after=t||function(){},s.loadStyle=function(e){var t=document.createElement("link");t.rel="stylesheet",t.type="text/css",t.href=e,s.head.appendChild(t)},s.loadScript=function(e){var t=document.createElement("script");t.type="text/javascript",t.src=s.js[e];var a=function(){++e<s.js.length?s.loadScript(e):s.after()};t.onload=function(){a()},s.head.appendChild(t)};for(var a=0;a<s.files.length;a++)/\.js$|\.js\?/.test(s.files[a])&&s.js.push(s.files[a]),/\.css$|\.css\?/.test(s.files[a])&&s.loadStyle(s.files[a]);s.js.length>0?s.loadScript(0):s.after()}
(function() {
// some "global" variables
var lookupFieldsToFix = [];
var storageThrottledLookup = localStorage.getItem("ThrottledLookup");
if (storageThrottledLookup) storageThrottledLookup=JSON.parse(storageThrottledLookup);
// onLoad() is called when all the fields in the form have been proceed
function onLoad(ctx) {
// we'll need jQuery (or nanoajax... see SharepointPlus doc) and SharepointPlus
loadExt([
"/Toolbox/Documents/js/jQuery/jquery-1.12.4.min.js",
"/Toolbox/Documents/js/SharepointPlus/3.14/sharepointplus-3.14.js"
], function() {
// if some lookup fields need to be fixed
if (lookupFieldsToFix.length>0) {
var aDeferred=[];
for (var i=0; i<lookupFieldsToFix.length; i++) {
aDeferred.push(fixLookup(lookupFieldsToFix[i]));
}
$.when.apply(this, aDeferred).done(function() {
var save={}, count=0, i;
for (i=arguments.length; i--;) {
if (arguments[i]) {
save[arguments[i].field] = arguments[i].choices; // save it as {fieldName:choices}
count++;
}
}
if (count > 0) {
// we use localStorage to store the data retrieve from the Lists
localStorage.setItem('ThrottledLookup', JSON.stringify(save));
// now reload the page
$SP().closeModalDialog();
$('#aspnetForm').hide().after('<h1 style="margin-top:50vh;transform:translateY(-50%);text-align:center">Reloading...</h1>');
window.location.reload();
}
})
} else {
// delete all existing localStorage
localStorage.removeItem('ThrottledLookup');
// here you can start doing anything you want on this form
}
});
}
/**
* Fix the broken lookup fields
* @param {String} field Name of the field to fix
* @return {Deferred}
*/
function fixLookup(field) {
var deferred = jQuery.Deferred();
var choices=[], modal;
WPQ2FormCtx.ListSchema[field].ChoiceCount=0;
WPQ2FormCtx.ListSchema[field].Choices=[];
// show a Waiting message
modal = $SP().getModalDialog('loading-throttled');
if (!modal) {
$SP().showModalDialog({
wait:true,
title:"Loading some data...",
id:"loading-throttled"
});
}
// and we get data from the list
// here we'll use "ID" as the data returned by our field in the form
var fieldID="ID";
$SP().list('{'+WPQ2FormCtx.ListSchema[field].LookupListId+'}').get({fields:fieldID, paging:true}, function(data) {
var res=[];
for (var i=0, len=data.length; i<len; i++) {
res.push({LookupId:data[i].getAttribute(fieldID), LookupValue:data[i].getAttribute(fieldID)});
}
deferred.resolve({field:field, choices:res});
});
return deferred;
}
// do some actions as soon as the fields are shown
var loadAfterForm = {
Templates: {
OnPreRender:function(ctx) {
// we want to show Lookup fields even if there are more than 5000 items in those lists
if (ctx.ListSchema.Field[0].Throttled === true) {
if (storageThrottledLookup) {
// we use the stored data to create our dropdown
ctx.ListSchema.Field[0].Throttled=false;
ctx.ListSchema.Field[0].ChoiceCount=storageThrottledLookup[ctx.ListSchema.Field[0].Name].length;
ctx.ListSchema.Field[0].Choices=storageThrottledLookup[ctx.ListSchema.Field[0].Name];
}
else {
lookupFieldsToFix.push(ctx.ListSchema.Field[0].Name);
}
}
},
OnPostRender:function(ctx) {
// only trigger when everything is loaded
// --> ctx.ListData.Items[0] all the fields
if (ctx.ListSchema.Field[0].Name === "Attachments") {
onLoad(ctx)
}
}
}
}
// don't do it when editing the page
if (GetUrlKeyValue("PageView") !== "Shared" && GetUrlKeyValue("DisplayMode") !== "Design") SPClientTemplates.TemplateManager.RegisterTemplateOverrides(loadAfterForm);
})();
To reply to this blog post I wanted to share the same thing but with SharepointPlus.
To use the paging option and get all the content from a large Sharepoint list you can simply do the below code:
$SP().list("My List").get({
fields:"ID,Title",
rowlimit:5000,
paging:true,
progress:function progress(nbItemsLoaded) {
// for each new page this function will be called
console.log("It's still loading... already "+nbItemsLoaded+" items have been loaded!");
}
}, function(data) {
console.log(data.length); // -> 23587
for (var i=0, len=data.length; i<len; i++) {
console.log(data[i].getAttribute("ID"))
}
})
If you only want to get the first 15,000 items, you can use the option page:3. See the documentation to know more.
Il n’existe pas de commande directe qui permette de savoir si le Player est éteint (en veille) ou allumé… Cependant il existe une astuce qui consiste à faire une requête en utilisant les paramètres suivants :
{
url:"http://mafreebox.freebox.fr/api/v3/airmedia/receivers/Freebox%20Player/",
headers:{
"X-Fbx-App-Auth": client.app.session_token
},
method:"POST",
json: {
"action":"stop",
"media_type":"video"
},
encode:"utf-8"
}
La Freebox va alors retourner { success:true } si elle est allumée, ou { success:false } si elle est éteinte/en veille.
Let’s say you want to do an asynchronous request just before saving a Sharepoint form, but after Sharepoint verified all the fields in your form (for mandatory ones, or for format, …). Here is my solution to do it (using jQuery.Deferred):
// this function will do our asynchronous check
function beforeSaving() {
var deferred=jQuery.Deferred();
setTimeout(function() {
alert("Test Complete!")
deferred.reject(); // if the test failed
// or deferred.resolve() to valid the test
}, 2000)
return deferred;
}
// force PostBackRequired to true in the context, otherwise it won't work if you open it into a modal
WPQ2FormCtx.PostBackRequired=true;
// we override SPClientForms.ClientFormManager.SubmitClientForm
SPClientForms.ClientFormManager.SubmitClientForm=function(b){
var a=SPClientForms.ClientFormManager.GetClientForm(b);
var res = (a!=null&&a.SubmitClientForm());
// if the form is not valid, then res===true
if (res === true) return true;
else {
// at this stage, all fields' value have been saved into a hidden input
// e.g. document.querySelector('input[type="hidden"][id$="Field_x0020_Name"]')
// all these saved values will be sent back to the server when "WebForm_DoPostBackWithOptions" is executed
// if the form is valid we now want to do our asynchronous check
beforeSaving().done(function() {
// our test is valid too so we can send the form to the server
WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions($get(WPQ2FormCtx.SubmitButtonID).name, "", true, "", "", false, true))
}).fail(function() {
// if it fails we just unblock the save button
$get(WPQ2FormCtx.SubmitButtonID).disabled=false;
})
}
// to make sure the form won't be submitted yet
return true;
};
I needed to communicate with an iframe on Sharepoint, however Sharepoint returned Load denied by X-Frame-Options … To override this limitation you have to create a Webpart page where you’ll add the code <WebPartPages:AllowFraming runat="server" /> into the <asp:Content> section (that might work somewhere else, but I did this way).
You can also add it into your masterpage to allow it everywhere on your website. Add it into your <head> block:

Now you can use postMessage() to communicate with your iframe.
I wanted to debug an Android app that uses HTTPS requests with a JSON API. Thanks to this article I’ve been able to use my Windows 10 computer to get all the network from my Android phone thru my local network and decode the HTTPS requests !
I’m going to summarize the steps from the above article:
You’re now ready to capture the traffic on Fiddler!
Once you’re done you can switch back to normal by following the below steps:
On Sharepoint 2013 I was trying to hide a field (the complete row) based on some elements into its description.
To do so we will call our file using the JSLink (see my previous post about it).
The JS file looks like that:
(function() {
// do some actions as soon as the fields are shown
var loadAfterForm = {
Templates: {
OnPostRender:function(ctx) {
// hide the field/row when "[INTERNAL USE - DO NOT CHANGE]" is detected in the field's description
if (ctx.ListSchema.Field[0].Description.indexOf('[INTERNAL USE - DO NOT CHANGE]') > -1) {
// get the element that represents the field
var elem = document.querySelector('[id^="'+ctx.ListSchema.Field[0].Name +'_'+ ctx.ListSchema.Field[0].Id+'"]');
while (elem) {
elem = elem.parentNode;
if (elem) {
if (elem.tagName==="BODY") break;
if (elem.tagName === "TD" && elem.className.indexOf("ms-formbody") > -1) {
// hide the whole row
elem.parentNode.style.display="none";
break;
}
}
}
}
}
}
}
SPClientTemplates.TemplateManager.RegisterTemplateOverrides(loadAfterForm);
})();