Below you will find pages that utilize the taxonomy term “Javascript”
MagicMirror2 and Chuvash
This post is about my setup of the popular MagicMirror2 application. I show the steps needed to set it up on a Raspberry Pi Zero W and connect it to a TV set. As a bonus, I share my thoughts on the Chuvash localization work.
MagicMirror2 is a DIY project and an open-source application, voted to number one of the best Raspberry Pi Projects. In essence, it shows information of your choice (weather, calendar, news) on a screen that is embedded in a mirror.
Filtering Azure Table Data directly in the Azure Function Binding
Instead of filtering values from an Azure Storage Table, you can do it directly in the bindings. It might not be a solution for everything, but in the right place, it is fantastic. I was very surprised to see how little code was needed after this binding change:
For that to work, define the filter attribute in the bindings: “filter”: “(PartitionKey eq ‘{package}’)”
To try it out, add a new row in a table defined in the bindings (“metadata” in my case):
Update Field.JSLink using JSOM or REST
Today I have just a little code snippet to share. This code snippet shows how to update the JSLink property for an existing field using JSOM and REST. For REST I use sharepoint-utilities. [code language=“javascript”] var updateJsLinkCsom = function(config) { var ctx = SP.ClientContext.get_current(); var web = ctx.get_web(); var lists = web.get_lists(); var list = lists.getByTitle(config.listTitle) var fields = list.get_fields(); var field = fields.getByInternalNameOrTitle(config.fieldTitle) field.set_jsLink(config.jsLink) field.update() ctx.executeQueryAsync() }; var updateJsLinkRest = function(config) { SP.SOD.registerSod(‘sputils.js’, ‘/sputils.min.js’) SP.SOD.executeFunc(‘sputils.js’, ‘’, function() { var url = _spPageContextInfo.webAbsoluteUrl + ‘/_api/web/lists/getbytitle(\’’ + config.listTitle + ‘\’)/fields/getbyinternalnameortitle(\’’+ config.fieldTitle + ‘\’)’; var payload = {’__metadata’: {’type’: ‘SP.Field’}, ‘JSLink’: config.jsLink}; var config = {‘headers’ : {‘X-HTTP-Method’: ‘MERGE’ }}; sputils.rest.post(url, payload, config); }); }; var config = { listTitle: ‘’, fieldTitle: ‘’, jsLink: ‘~site/’ }; updateJsLinkCsom(config); updateJsLinkRest(config); [/code] A couple of notes, to update a field we need:
Trigger SP2010 Workflows using JSOM
Today I found out how to start workflows in JSOM (JavaScript Object Model in SharePoint). Nothing special, but since it is not documented, it took me a while to find a solution. Here is the code which I want to keep as simple as possible. What you need to start a SP2010 Workflow for a list item or a document in JSOM, you need to load SP.WorkflowServices.js and you need to create the manager and get the service, then you can trigger a workflow using the workflow name, the list guid and the guid of the list item: [code language=“javascript”] var ctx = SP.ClientContext.get_current(); var workflowServicesManager = SP.WorkflowServices.WorkflowServicesManager.newObject(ctx, ctx.get_web()); var service = workflowServicesManager.getWorkflowInteropService(); service.startWorkflow(workflowName, null, listGuid, plainItem.guid, initiationParams); [/code] Here is the code to trigger a workflow for multiple items: [code language=“javascript”] //fire the workflows function fire2010WorkflowForListItems(ctx, listGuid, plainItems) { var workflowServicesManager = SP.WorkflowServices.WorkflowServicesManager.newObject(ctx, ctx.get_web()); var service = workflowServicesManager.getWorkflowInteropService(); for(var i = 0; i < plainItems.length; i++) { var plainItem = plainItems[i]; console.log(‘scheduling workflow for id: ‘, plainItem.id); service.startWorkflow(options.workflowName, null, listGuid, plainItem.guid, options.initiationParams); } console.log(’now executing…’); ctx.executeQueryAsync(function() { console.info(‘yes, workflows completed for ’ + items.length + ’ items’); }, function() { console.error(‘it didnt go well’); }); } [/code] The code above is inspired from this gist and sharepoint stackexchange. It is a simplified version that only works for list item workflows and SharePoint 2010 workflows. Here is an example how you can get multiple items and batch start a workflow: [code language=“javascript”] //just a couple of variables var options = { workflowName: ‘Behörigheter’, listName: ‘Documents’, initiationParams: {} }; //load list items function startWorfklows() { //Start 2010 Workflow for a List Item var ctx = SP.ClientContext.get_current(); var web = ctx.get_web(); var lists = web.get_lists(); var list = lists.getByTitle(options.listName); ctx.load(list); var items = list.getItems(new SP.CamlQuery()); ctx.load(items); ctx.executeQueryAsync(function() { var listGuid = list.get_id() + ‘’; var en = items.getEnumerator(); var plainItems = []; while (en.moveNext()) { var it = en.get_current(); //do not take checked out files, it won’t work if (!it.get_item(‘CheckoutUser’)) { plainItems.push({id: it.get_id(), guid: it.get_item(‘GUID’) + ’’ }); } } fire2010WorkflowForListItems(ctx, listGuid, plainItems); }, function() { alert(‘boom’); }); } //Load Worfklow Js dependency var wfScript = ‘SP.WorkflowServices.js’ SP.SOD.registerSod(wfScript, _spPageContextInfo.webAbsoluteUrl + ‘/_layouts/15/SP.WorkflowServices.js’); SP.SOD.executeFunc(wfScript, ‘’, startWorfklows); [/code]
Create and download a file in javascript
Phew, I spent a lot of time to get this to work:
- Create a text based file in javascript - a simple csv or txt
- Download a file in Chrome and Internet Explorer
- Make Excel understand Unicode characters (å ä ö and many more) in csv directly.
I found many solutions on the Internet that I used to find out a solution that works for me A deep diving jsfiddle about unicode encodings, bom, line endings: http://jsfiddle.net/kimiliini/HM4rW (unfortunately, does not work in IE). There I learned one important thing: we need a BOM in order to make Excel understand that it is not just ASCII. The BOM (byte order mark) for utf-8 is %ef%bb%bf for utf-8. Without this bom you’ll see the right characters in a text editor (except Notepad of course), but if you open the csv file directly in Excel, you’ll see wrong letters. Other good resources are FileSaver.js: https://github.com/eligrey/FileSaver.js and download.js: http://danml.com/download.html and a discussion on that github repository issue: https://github.com/mholt/PapaParse/issues/175 This is my solution that is tested in Chrome and IE10: [code language=“javascript”] function downloadContent(options) { if (!options || !options.content) { throw ‘You have at least to provide content to download’; } options.filename = options.filename || ’tolle.txt’; options.type = options.type || ’text/plain;charset=utf-8’; options.bom = options.bom || decodeURIComponent(’%ef%bb%bf’); if (window.navigator.msSaveBlob) { var blob = new Blob([options.bom + options.content], {type: options.type }); window.navigator.msSaveBlob(blob, options.filename); } else { var link = document.createElement(‘a’); var content = options.bom + options.content; var uriScheme = [‘data:’, options.type, ‘,’].join(’’); link.href = uriScheme + content; link.download = options.filename; //FF requires the link in actual DOM document.body.appendChild(link); link.click(); document.body.removeChild(link); } } //test var separator = ‘;’; downloadContent({ type: ’text/csv;charset=utf-8’, filename: ’tolle.csv’, content: [‘ASCII’, separator, ‘Åbäcka sig’, separator, ’to się podoba: żźćąęłć’, separator, ‘Яшлӑхӑма туйаймарӑм’].join(’’) }); [/code]
Minimal Download Strategy. Simple
There are many correct ways (1, 2, 3, 4, 5…) of making scripts work with the Minimal Download Strategy Feature (MDS) in SharePoint 2013 and 2016. But to be honest - every time I need it, I get confused. So now it is time to find a simple solution for that. Who is better at it than the developers of the SharePoint themselves? Look at the MDS code in the built-in Display Templates: Let’s keep it as simple as Item_Default.js, let’s take it as it is and create our own scripts. Here is a skeletton of and MDS-ready script: [code language=“javascript”] function runMyCode() { var time = new Date().toISOString(); console.log(‘runMyCode’, time ); } runMyCode(); if (typeof(RegisterModuleInit) == ‘function’) { var scriptUrl = ‘/Style Library/runMyCode.js’; RegisterModuleInit(scriptUrl, runMyCode); } [/code] Which boils down to this in pseudocode:
Minimal Display Template
We want to use our own Display Templates on Non-publishing sites - our team sites. Without the Publishing Feature activated you have to create an own javascript file. Here is short and concise instructions how to install it: Display Templates on Non-publishing Sites. As described on that blog, you can make copy of an existing Item_Default.js and adjust to your needs. I also asked Elio Struyf and I got the same tip. I did create my starter template. Here I want to share this very minimal javascript based Display Template. The real Minimal Display Template is in the SPCSR github repository: Item_Minimal.js It has been improved by Elio Stuyf himself :) [code language=“javascript”] (function () { // Config contains variables that are defined in one place var config = { propertyMappings: { ‘Path’:null, ‘Title’:[‘Title’] } }; var templateUrl; var register = function () { if (“undefined” !== typeof (Srch) && “undefined” !== typeof (Srch.U) && typeof (Srch.U.registerRenderTemplateByName) === “function”) { Srch.U.registerRenderTemplateByName(templateUrl, render); } }; render = function (ctx) { // Display template data var cachePreviousTemplateData = ctx.DisplayTemplateData; ctx.DisplayTemplateData = { ‘TemplateUrl’: templateUrl, ‘TemplateType’: ‘Item’, ‘TargetControlType’: [‘SearchResults’, ‘Content Web Parts’], ‘ManagedPropertyMapping’: config.propertyMappings }; var cachePreviousItemValuesFunction = ctx.ItemValues; ctx.ItemValues = function(slotOrPropName) { return Srch.ValueInfo.getCachedCtxItemValue(ctx, slotOrPropName); }; // Retrieve managed property data var path = $getItemValue(ctx, ‘Path’); var title = $getItemValue(ctx, ‘Title’); // HTML markup for an item var htmlMarkup = String.format( ‘’ + ‘{1}’ + ‘’, path, title); // Caching ctx.ItemValues = cachePreviousItemValuesFunction; ctx.DisplayTemplateData = cachePreviousTemplateData; // Return the HTML markup return htmlMarkup; }; // Retrieve all the loaded scripts var allScripts = document.getElementsByTagName(“script”); // Get the last script file (this is the current DT file) var scriptUrl = allScripts[allScripts.length - 1].src; if (scriptUrl.indexOf(’/_catalogs/’) > 0) { // Remove the query string if (scriptUrl.indexOf(’?’) > 0) { scriptUrl = scriptUrl.split("?")[0]; } // Insert the site collection token templateUrl = ‘~sitecollection’ + scriptUrl.substr(scriptUrl.indexOf(’/_catalogs/’)) // Register the template to load register(); if (typeof (RegisterModuleInit) === “function” && typeof(Srch.U.replaceUrlTokens) === “function”) { RegisterModuleInit(Srch.U.replaceUrlTokens(templateUrl), register); } } })(); [/code]
SharePoint Utilities - a promising JavaScript Framework
My colleagues at Bool have developed a new JavaScript framework for SharePoint - sharepoint utilities. It started on our DevDay last year - a whole free day when we could learn new things, try out new techniques or build something that was not even requested from a customer. I was not working on sharepoint utilities, so I almost forgot it until… I recently re-discovered sharepoint utilities. It is on Github, it is MIT licensed and contributions are welcome. The core of sharepoint utilities (sputils) is a set of wrappers for Search, TermStore, REST that allow you be more productive as a developer. What I find especially compelling with that it contains some other fundamental stuff that every SharePoint developer needs:
A tiny tool for User Custom Actions
Everybody loves User Custom Actions in SharePoint. That’s the only recommended way of customizing SharePoint. You have heard about it. Unfortunately there is no convinient way of administering them. People have their console applications or powershell scripts to add, update and delete user custom actions. It works but it is hard to open up Visual Studio or PowerShell every time you will try out an idea on a test site. To overcome this, I have created a tiny little tool, packaged as a bookmarklet for your browser. When you click on it, it will show your existing user custom actions and you can add new user custom actions. It is an ongoing little project, available on github, contributions are welcome. What’s left is:
Copy SharePoint WebDav Address to Clipboard
While configuring SharePoint sites and helping users I often use File Explorer View for editing pages, resources like css and javascript. In IE there is a dedicated button in the ribbon for that. Sometimes it works, sometimes it doesn’t, because of permissions or other restrictions. Anyway, I use Firefox and Chrome while troubleshooting and developing, so I have created a bookmarklet for copying the webdav address of a site that is open in the browser. [source language=“javascript”] var uri = _spPageContextInfo.webAbsoluteUrl.replace(/https?:\/\//i, “\\\\”).replace(/\//g, “\\”); window.prompt(“Copy to clipboard: Ctrl+C, Enter”, uri); [/source] Unfortunately, there is no copy function in javascript, the prompt solution plus Ctrl-C works fine. The bookmarklet: [source language=“html”] javascript:void%20function(){var%20o=_spPageContextInfo.webAbsoluteUrl.replace(/https%3F:\/\//i,%22\\\\%22).replace(/\//g,%22\\%22);window.prompt(%22Copy%20to%20clipboard:%20Ctrl+C,%20Enter%22,o)}(); [/source] Enjoy
Export Any Web Part using a Bookmarklet
My blog post about exporting any webpart from a SharePoint Page is one of the most read articles on my blog. I use this method a lot. Now what I want to do is to simplify the process. Inspired by my colleague Dan Saedén’s awesome bookmarklet for reading and updating web properties, I decided to make my own bookmarklet. That was easy. Now we can export any web part from any SharePoint page without even looking at any ids in the html markup and assembling the export url manually. Just add the bookmarklet or run the javascript code in the browser console. The code (js and bookmarklet) is on Github. Here is an animated gif that explains how to use it:
Bypass all custom jslink
Client Side Rendering (CSR) and jslink are great for customizing lists and forms in SharePoint. In my current project we use it a lot of it. A disadvantage of that path, although, is that it might occur javascript errors, during the development phase, but also in production. We do, of course, our best to leverage the best jslink code, but unfortunately we have to live with the fact that errors can occur, especially when we use it for NewForm, EditForm, DisplayForm and View (in list and grid). If an error occurs, it won’t stop the rest of javascript (it is wrapped in try and catch by SharePoint), but the fields will still not function as intended. It can also be some “corrupt” or old data in the field value that will “break” the jslink code. I would like to suggest one little fix, an idea I’ve come up to in my jslink-heavy project:
Client Side Rendering with Async dependencies
Yesterday I asked a question on SharePoint StackExchange:
I also asked Elio Struyf on Twitter: https://twitter.com/eliostruyf/status/540473976255152128 Good idea, Elio Struyf! Now I want to try it out.
Preparations
In this case I’ll be using my example from my blog post yesterday: Drag and Drop Image using Client Side Rendering I have created a new list and added a lookup field to my previous list. What I get is a Title of the lookup item, but not my custom field called DragAndDrop. In my test I will try to load the DragAndDrop Image using an ajax call and rendering it after Client Side Rendering is done with my item. To be complete, I want to show some screenshots for my lookup field: It will result in this OOTB rendering:
Drag and Drop Image using Client Side Rendering
I continue my series about Client Side Rendering (CSR) and jsgrid. Today I want to try a custom field where users can drag and drop images. The inspiration comes from:
- AutoUpload field written by Anton Vishnyakov and
- Base64 Drag and drop written by oroboto
What I want to achieve is:
- A custom field that is rendered with jslink
- Users can drag and drop small pictures (thumbnails) into the field
- A base64 image representation is saved as the field value
- Optionally implement pasting images using Clipboard API
Step 1 Create a field with a custom jslink
Create a field of type Note. I am using the PnP Core Extensions to make it quickier: ’ My jslink file is very simple to begin with: [code language=“javascript”] (function () { ‘use strict’; function view(ctx, field) { return “hello”; } var overrideContext = {}; overrideContext.Templates = overrideContext.Templates || {}; overrideContext.Templates.Fields = { ‘DragAndDropImage’: { ‘View’: view, ‘DisplayForm’: view //‘EditForm’: verySimpleNewAndEdit, //‘NewForm’: verySimpleNewAndEdit } }; SPClientTemplates.TemplateManager.RegisterTemplateOverrides(overrideContext); })(); [/code] This will result in the following display form. Just outputting “hello” indicates that my field is jslink are registered correctly:
Disabling a column in Quick Edit
In my project I have a column called Request Status. This column is not shown in any forms, meaning users should not edit, because it is controlled through the app. Nevertheless it is editable in the Quick Edit. Yesterday I wrote about jsgrid in my blog. Now comes more. Today I’ll share a little practical solution how one can disable editing a field in Quick Edit. The field is edited in jsgrid, but to disable it, we only have set the property called AllowGridEditing to false on our column (not even touching the heavy jsgrid api). We can do in the OnPreRender event in our Client Side Rendering (CSR) registration. Having the context object we have access to the Fields (ContextInfo.ListSchema.Field): [code language=“javascript” highlight=“6,9”] (function () { var overrideContext = {}; overrideContext.Templates = overrideContext.Templates || {}; overrideContext.Templates.OnPreRender = function(ctx) { var statusField = ctx.ListSchema.Field.filter(function(f) { return f.Name === ‘Request_x0020_Status’; }); if (statusField) { statusField[0].AllowGridEditing = false; } } SPClientTemplates.TemplateManager.RegisterTemplateOverrides(overrideContext); })(); [/code] Another way is to implement the display form: [code language=“javascript”] (function () { var view = function (ctx, field) { if (ctx.inGridMode) { field.AllowGridEditing = false; } return window.RenderFieldValueDefault(ctx); }; var overrideContext = {}; overrideContext.Templates = overrideContext.Templates || {}; overrideContext.Templates.Fields = { ‘Request_x0020_Status’: { ‘View’: view } }; SPClientTemplates.TemplateManager.RegisterTemplateOverrides(overrideContext); })(); [/code]
JSGrid Basics
JSGrid is the javascript framework in SharePoint used in Quick Edit View (previously Datasheet View). There are a few very good blog posts on this topic (See below in “Sources”). Nevertheless the fact is that jsgrid and working with quick edit from a developer’s perspective is a huge undiscovered area. Articles I have seen are intended for advanced developers. The goal with my post today is to outline the very basics of working with JSGrid. When you know the basics you will be more comfortable to discover and try out more. The example I want to show is a jsgrid code for a “VerySimpleColumn”. The source code can be found on gist.github.com To focus on jsgrid, I assume you have knowledge and some experience of working with jslink, which is related to jsgrid.
Improving the web performance of an intranet
[caption id=“attachment_3437” align=“alignnone” width=“480”] All the “small” app parts, web parts, delegate controls, user controls, and other “packages” that “must” be delivered to the users on every page load of the Start Page of your Intranet.[/caption] Recently we made an investment to improve the performance of our intranet. We made many changes in different layers: SQL, Network, Browser upgrade and code. Here I want to tell about what code changes we did to improve the web browser performance. Please leave feedback if you find it useful. You can also share your suggestions. We measured the performance before our code changes and after them. We had amazing results. Unfortunately I can not share any numbers, but we improved the Time to First Byte, time to load event firing in the browser, memory consumption in the clients and, perhaps, the most important, we improved the perceived performance of the Intranet, the way how users experience the speed and UI responsiveness. To do this I got many ideas of my project colleagues and branch colleagues. Here is the list of changes we’ve implemented:
AppLoader Concept for SharePoint apps
In this post I want to share an unusual, nevertheless interesting conceptual idea of loading content from SharePoint 2013 apps on many pages. The original awesome concept was proposed and developed by my colleague Martin Villysson at Bool.
The problem we are trying to solve
SharePoint apps are great to extend functionality in SharePoint and integrate other systems (full page apps available through Site Contents), they also provide tools to enrich the default SharePoint experience by App Parts (Client Web Parts) and Custom Actions (additional menus).
Using CAML with SharePoint REST API
Do you prefer REST over CSOM as I do? I’ll skip the whys. Andrew Connell put it already in wrtiting so nicely. Well, if you do prefer REST, then you must have discovered some shortcomings of REST, or its incompleteness compared to CSOM. I think of:
- Inability to filter items based on multivalued taxonomy fields
- Inability to filter items based on user fields where user is added through a group, rather than directly, e.g. AssignedTo=[Me] combined with a SharePoint group.
- …
In such situations I was forced to use CSOM. Until yesterday. Yesterday I learned that we can actually use CAML queries in REST requests. This enables using REST in all situations. The REST API is still developed and many features are added. Maybe a particular operation that needs a CAML query today, can be supported in the core REST API and can be easily refactored then. But until then, we can use CAML queries in REST requests. Here are the important things about it:
Pragmatic Responsive Design
I have been curious about the responsive design but have not had time to try it out. To learn more I decided to make an existing website more responsive. A friend of mine drives a Chuvash Dictionary website: samah.chv.su. Today it looks like this in a mobile browser: The site is a classic 1000px-ish centered page with header and two columns. The left column is for the main content and the right column for additional “aside” information. Can it be more classic? This current version works, you can still use the dictionary on a mobile phone. But there are several improvements that can be done:
Count lines of code with PowerShell
Today I got a question:
How many lines of code are there in our SharePoint solution?
After a little search, I found that PowerShell is really a nice tool to count lines of code:
I wanted to count lines for different types of code:
- Code Behind written in C#, the files have .cs file extension
- JavaScript code (except jQuery, angular or knockout frameworks)
- PowerShell files (.ps1 and psm1)
- Xml files (all the SharePoint .xml files)
Here is the powershell code that counts lines of code: [code language=“powershell”] # go to the solution folder cd #count lines in .cs files ls -include *.cs -recurse | select-string . | measure | select count #count lines in our .js files ls -include *.js -recurse ` -exclude *min.js, jquery*, _*, jsrender*, CamlBuilder*, knockout* ` | select-string . ` | measure ` | select Count #count lines in our powershell scripts ls -include *.xml -recurse | select-string . | measure | select count #count lines in our powershell scripts ls -include *.ps1, *.psm1 -recurse | select-string . | measure | select count [/code] Just a curious fact, I can’t tell you how many lines of code we have in our solution, but I can reveal the proportions. If I used the flexible box model in css3, it would look like this: There are as many lines of code written in javascript as it is in C#. The main reason that for the big js code base are the SharePoint hosted apps. The PowerShell scripts are as big the javascript code base. Xml files are 4 times bigger than C# code, and it is even bigger than the sum of all lines of code written in C#, JavaScript and PowerShell. It isn’t strange that xml is dominating, almost everything in SharePoint is defined in xml. Fortunately, there are less cases where you have to write raw xml in Visual Studio 2012/2013 and SharePoint 2013. How does it look in your project? What language is dominating in your SharePoint project?
Debugging OOB SharePoint. Unable to post comments on SharePoint blogs (SP2013 June CU)
I have had a strange bug. The comment text box in a OOB SharePoint 2013 blog doesn’t appear. It only says: “There are no comments for this post.” In this blog post I’ll tell you how I found the bug and I’ll show you how you can temporarily bring the commenting to life. I have had luck. While it doesn’t work on the Test Environment, it does actually work on my development machine. The comments text box is rendered as an OnPostRender action in the blog comments display template. After debugging the javascript in hours and comparing the two environments, I just could confirm that displaytemplates are the same. There are two main javascript files that are involved:
Log to ULS using javascript
The more javascript code is produced in SharePoint solutions, the more need we have to log information and possible errors to a central logging place in SharePoint: ULS. This blog post is about logging to ULS from javascript. For a while ago I read a blog post:
The author @avishnyakov mentions the ability log to ULS from javascript. I want to dive deeper. [sourcecode language=“javascript”] ULS.enable = true ULSOnError(“Hello from javascript”, location.href, 0); [/sourcecode] What this function actually does, is that it calls a web service called _vti_bin/diagnostics.asmx
We can follow the function in the init.debug.js [sourcecode language=“javascript”] function ULSOnError(msg, url, line) { return ULSSendExceptionImpl(msg, url, line, ULSOnError.caller); } [/sourcecode] ULSOnError invokes ULSSendExceptionImpl: [sourcecode language=“javascript”] function ULSSendExceptionImpl(msg, url, line, oCaller) { if (Boolean(ULS) && ULS.enable) { ULS.enable = false; window.onerror = ULS.OriginalOnError; ULS.WebServiceNS = “http://schemas.microsoft.com/sharepoint/diagnostics/"; try { ULS.message = msg; if (url.indexOf(’?’) != -1) url = url.substr(0, url.indexOf(’?’)); ULS.file = url.substr(url.lastIndexOf(’/’) + 1); ULS.line = line; ULS.teamName = “”; ULS.originalFile = “”; ULS.callStack = ‘\n’ + ULSGetCallstack(oCaller) + ‘’; ULS.clientInfo = ‘\n’ + ULSGetClientInfo() + ‘’; ULSSendReport(true); } catch (e) { } } if (Boolean(ULS) && Boolean(ULS.OriginalOnError)) return ULS.OriginalOnError(msg, url, String(line)); else return false; } [/sourcecode] ULSSendExceptionImpl invokes ULSSendReport: [sourcecode language=“javascript”] function ULSSendReport(async) { ULS.request = new XMLHttpRequest(); ULS.request.onreadystatechange = ULSHandleWebServiceResponse; ULS.request.open(“POST”, ULSGetWebServiceUrl(), async); ULS.request.setRequestHeader(“Content-Type”, “text/xml; charset=utf-8”); ULS.request.setRequestHeader(“SOAPAction”, ULS.WebServiceNS + “SendClientScriptErrorReport”); ULS.request.send(’’ + ‘<soap:Envelope xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd=“http://www.w3.org/2001/XMLSchema" xmlns:soap=“http://schemas.xmlsoap.org/soap/envelope/">' + ‘soap:Body’ + ‘’ + ‘’ + ULSEncodeXML(ULS.message) + ‘’ + ‘’ + ULSEncodeXML(ULS.file) + ‘’ + ‘’ + String(ULS.line) + ‘’ + ‘’ + ULSEncodeXML(ULS.callStack) + ‘’ + ‘’ + ULSEncodeXML(ULS.clientInfo) + ‘’ + ‘’ + ULSEncodeXML(ULS.teamName) + ‘’ + ‘’ + ULSEncodeXML(ULS.originalFile) + ‘’ + ‘’ + ‘</soap:Body>’ + ‘</soap:Envelope>’); } [/sourcecode]
javascript: Alert Me on a Page
Recently I needed to add an Alert Me link on Pages. Alert Me is a well known SharePoint functionality for notifying users about changes in list or list items. It is availabe in OOB SharePoint as a command in Ribbon if you go to a list view: When you click on this ribbon command, SharePoint opens a modal dialog and takes you to layouts page: SubNew.aspx. To open a modal dialog and load a page is not a rocket science. So a custom “Alert Me” link is doable. As the first step I copied the html markup from the ribbon and adjusted it a little bit. [sourcecode language=“html”] Alert Me [/sourcecode] Then the javascript code which gets the List ID and Page ID is very simple because this information is there in the magic _spPageContextInfo: [sourcecode language=“javascript”] var takana = window.takana || {}; takana.alertMe = function () { var url = String.format("{0}/{1}/SubNew.aspx?List={2}&ID={3}" , _spPageContextInfo.webAbsoluteUrl , _spPageContextInfo.layoutsUrl , encodeURI(_spPageContextInfo.pageListId) , _spPageContextInfo.pageItemId); OpenPopUpPage(url); } [/sourcecode] This code will open a modal dialog in exactly the same way as the ribbon command in OOB SharePoint and let you subscribe to changes on that page. In this code I use String.format which is available on SharePoint pages and _spPageContextInfo which has existed since SharePoint 2010 and has been extended with more useful information about the current context.
javascript: Remove illegal characters in url
Recently I needed to create valid urls for pages using javascript. Also this time I thought it must be some out-of-the-box code for that in SharePoint. The first thing I came up was the “Add page” dialog. I found that the actual dialog was in the _layouts virtual folder:
/\_layouts/15/CreatePublishingPageDialog.aspx
```Bingo, it does the validation in the client side. This is the responsible javascript function that resides directly in the page: \[sourcecode language="javascript"\] function UpdateUrl() { LoadTermContextInfo(); var hiddenPageUrlLabelExtensionClientId = "<%=hiddenPageUrlLabelExtension.ClientID%>"; var hiddenPageUrlLabelExtension = document.getElementById(hiddenPageUrlLabelExtensionClientId); var pageNamePreviewUrlLabelClientId = "<%=pageNamePreviewUrlLabel.ClientID%>"; var pageNamePreviewUrlLabel = document.getElementById(pageNamePreviewUrlLabelClientId); if( pageNamePreviewUrlLabel != null ) { var nameInputTextBoxClientId = "<%=nameInput.ClientID%>"; var nameInputTextBox = document.getElementById(nameInputTextBoxClientId); var allowSpaces = false; if( GetInnerText(hiddenPageUrlLabelExtension) != "" ) { var suggestUrlValue = ""; for (var i=0; i < nameInputTextBox.value.length; i++) { var currentChar = nameInputTextBox.value.charAt(i); if (IndexOfIllegalCharInUrlLeafName(currentChar) == -1 && !(currentChar == ' ' && allowSpaces == false) && currentChar != '.' && currentChar != '+') { suggestUrlValue += currentChar; } else if (currentChar == ' ' || currentChar == '+' || (currentChar == '.' && i > 0 && i < (nameInputTextBox.value.length - 1))) { suggestUrlValue += '-'; } } UpdatePreviewUrl( suggestUrlValue ); } else { if( g\_timerId != 0 ) { window.clearTimeout(g\_timerId); } g\_timerId = window.setTimeout(OnFriendlyUrlNameChanged, 500); } } } \[/sourcecode\] This function iterates through all the characters in the page url and removes the illegal characters. The space, plus sign and the dot become a hyphen. To determine if a character is illegal, it relies on another javascript function called: `IndexOfIllegalCharInUrlLeafName`. This function can be found in the init.js or init.debug.js: \[sourcecode language="javascript"\] function IndexOfIllegalCharInUrlLeafName(strLeafName) { for (var i = 0; i < strLeafName.length; i++) { var ch = strLeafName.charCodeAt(i); if (strLeafName.charAt(i) == '.' && (i == 0 || i == strLeafName.length - 1)) return i; if (ch < 160 && (strLeafName.charAt(i) == '/' || !LegalUrlChars\[ch\])) return i; } return -1; } \[/sourcecode\] This function checks a char against an array of all characters: `LegalUrlChars` from the same file: init.js. [![ill_002](https://sharepointkunskap.files.wordpress.com/2013/06/ill_002.png)](https://sharepointkunskap.files.wordpress.com/2013/06/ill_002.png) To use this UpdateUrl function, we have to remove the references to the fields from the Add Page Dialog. Of course, we won't overwrite this original function, we don't want to break the SharePoint OOB functionality. Here is how my new function looks like: \[sourcecode language="javascript"\] var takana = {}; function takana.updateUrl(url) { var allowSpaces = false; if( url ) { var suggestUrlValue = ""; var length = url.length; for (var i=0; i < length; i++) { var currentChar = url.charAt(i); if (IndexOfIllegalCharInUrlLeafName(currentChar) == -1 && !(currentChar == ' ' && allowSpaces == false) && currentChar != '.' && currentChar != '+') { suggestUrlValue += currentChar; } else if (currentChar == ' ' || currentChar == '+' || (currentChar == '.' && i > 0 && i < (nameInputTextBox.value.length - 1))) { suggestUrlValue += '-'; } } } } \[/sourcecode\]
#### Server Side
For those of you who want run this operation on the server, here is the code written in C#: \[sourcecode language="csharp"\] //" # % & \* : < > ? \\ / { } ~ | var illegalChars = @"\[""#%&\\\*:\\<\\>\\?\\\\\\/\\{\\}~\\|\]"; pageName = Regex.Replace(pageName, illegalChars, string.Empty); var punctuation = @"\[\\s\\.;\\+\]"; pageName = Regex.Replace(pageName, punctuation, "-"); //remove "--" pageName = Regex.Replace(pageName, @"\\-{2,}", "-"); pageName = string.Format("{0}.aspx", pageName); //do it like the built-in dialog, lower case pageName = pageName.ToLower(); \[/sourcecode\] Don't forget to leave a comment if you find this post useful.
## Comments from Wordpress.com
####
[Johannes Milling](http://discoveringsharepoint.wordpress.com "johannesmilling@hotmail.com") - <time datetime="2013-08-23 09:53:30">Aug 5, 2013</time>
Good post! :)
<hr />
The CDN concept in SharePoint
How many instances of jquery are there in your SharePoint farm? [sourcecode language=“powershell”] Get-SPWebApplication http://dev ` | Select -Expand Sites ` | Select -Expand AllWebs ` | Select -Expand Lists ` | Select -Expand Items ` | ? { $_.Url -match “jquery.*.js” } ` | select Name, Url [/sourcecode] Have you more than two (jquery and jquery-ui), then you have too much. You can save much place and performance by using Content Delivery Network (CDN) links for the resources like javascript, css, fonts and icons. Consider those Content Delivery Networks:
Convert any web app to a SharePoint app
Have you noticed that you can right-click a web application project in Visual Studio and convert it to a provider hosted app? Well why not? Basically your own website and a SharePoint manifest is all what you need for a provider hosted app. This discovery today made me think about all legacy web apps out there that can be converted to SharePoint apps. Traditionally we had to add plain links to external applications or embed them into an IFrame by hardcoding it in an .aspx page or a Page Viewer WebPart. A web application that should be converted to a SharePoint app can be any web app, not only asp.net web site. For a year ago, I had a little nodejs project to try out mongodb and knockout.js: Anvaska which I published as a heroku app:
SharePoint Apps: "Provider Hosted First" Approach
Recently I had an exciting mail conversation with Thomas Deutsch. He came up with an idea how to fasten the development of apps. This smart approach is called “Provider Hosted First”. See Thomas’ original blog post. Here are some highlights: What you actually do is a local website which runs in grunt server
:
localhost:9000
```Then a SharePoint-hosted app is created with an SPAppIframe that refers to that local app site. Genious!!! Some key features of this approach:
* This local app contains a livereload script. Your sharepoint app is updated every time you save your css, js, html file in your IDE
* Grunt minifies, bundles your assets
* Grunt runs your tests automatically when your content is modified
* The SharePoint app can be on Premises, on Office 365, wherever you want it.
#### Video
\[caption id="attachment\_2808" align="alignnone" width="630"\][![See the video how it looks like to develop using this approach](https://sharepointkunskap.files.wordpress.com/2013/07/sp-app-002.png?w=630)](http://www.screenr.com/LA8H) See the video how it looks like to develop using this approach\[/caption\]
## Comments from Wordpress.com
####
[Paul Tavares](http://paultavares.wordpress.com "paultavares1@gmail.com") - <time datetime="2013-07-10 02:59:34">Jul 3, 2013</time>
This is pretty cool and very similar to my current setup for developing javascript applications for SharePoint. I use a script to "deploy" updates from my PC to the folder in a document library. I'll try this out when I get around to playing with SP2013.
<hr />
####
[Björn]( "bjorn.roberg@bool.se") - <time datetime="2013-07-02 11:07:08">Jul 2, 2013</time>
Awesome! I'm gonna try that out!
<hr />
####
[Anatoly Mironov]( "mirontoli@gmail.com") - <time datetime="2013-07-02 15:31:33">Jul 2, 2013</time>
Great! When you go to Thomas Deutsch blog, you can download the source code for the solution.
<hr />
Make javascript code work with Minimal Download Strategy Part 2
I have a newer blog post about MDS, that provides a much simpler solution. Please check it before reading further.
Minimal Download Strategy (MDS) is an important feature in SharePoint 2013. It lets you download only a page delta, only changes. There is still issues with the MDS and custom scripts and almost no documentation on msdn or technet. In this blog post I want to learn more about adjusting custom scripts for MDS. As in my previous post, I want to take a real problem and try to solve it. The goal is to find a solution, not nececerilly the most optimal solution, at least for now.
Make javascript code work with Minimal Download Strategy Part 1
I have a newer blog post about MDS, that provides a much simpler solution. Please check it before reading further.
This is a part 1 of the blog post about Minimal Download Strategy and javascript adjustments for user code. What I initially thought should be enough for one post, is not enough, so I see it as a part 1. I wrote this post after I had read Chris O’Brien’s post about JSLink Here I want investigate how we can get his accordion list view working with MDS. Minimal Dowload Strategy or MDS is a new feature in SharePoint 2013. By now, if you read this post, you already know about it. The simplest way to see if MDS is enabled on your site, you can recognize it on the “ugly” urls. I don’t think they are so ugly. But it is a matter of taste and habit. No matter if you like MDS or not, MDS is enabled on many site templates and is a huge step towards a faster, more responsive architecture in SharePoint, I would say, towards the Single Page Application concept in SharePoint (but it is a long way to go). We have to keep the MDS in mind, when we write our customizations in javascript. SharePoint 2013 loves javascript and the probability is high that you write a lot of javascript. If it doesn’t work with MDS, your code breaks and the user doesn’t see the functionality, or the site owner must disable the Minimal Download Strategy feature. I wouldn’t like to have disabling of an improvement feature as a prerequisite for my code. In this blog post I want to dig into the techniques for getting the javascript code working with MDS. For a while ago I read a wonderful blog post in Chris O’Brien’s blog:
REST API: Add a plain text file as an attachment to a list item
SharePoint 2013 REST API has been enhanced and extended. The old _vti_bin/listdata.svc is still there, but the new api for working with lists and list items is much more and obviously a part of a bigger api: _api/web/lists Yesterday I saw an interesting question on SharePoint StackExchange:
The instructions in the MSDN resource are not so detailed, the cannot be. The guy who asked the question did as it stood in the examples. But sometimes solutions for SharePoint need some small adjustments :) Here is the simplest code to create an attachment in plain text for a list item 1 in the list called List1 in the root web. That’s it. But it works: [sourcecode language=“javascript”] var content = “Hello, this text is inside the file created with REST API”; var digest = $("#__REQUESTDIGEST").val(); var composedUrl = “/_api/web/lists/GetByTitle(‘List1’)/items(1)/AttachmentFiles/add(FileName=‘readme.txt’)”; $.ajax({ url: composedUrl, type: “POST”, data: content, headers: { “X-RequestDigest”: digest } }) [/sourcecode] This example is of course just for demonstration. It uses only hard-coded values. But it shows how simple it is to create a list item attachment using SharePoint 2013 REST API and “upload” plain text asynchronously to the server.
SharePoint Modal Dialog as AngularJS directive
It has already become a series of posts in my blog about the combination of AngularJS and SharePoint:
- AngularJS: prevent form validation in Page Edit Mode
- angular jQuery UI autocomplete
- AngularJS: sync $location.search with an input value
And it will be more. Some of them are a pure angular stuff, some of them are really for SharePoint. In this post post I’ll show how to create a directive for a sharepoint modal dialog (SP.UI.ModalDialog). There is already a modal dialog implementation in the Angular UI project, but it uses the bootstrap modal dialog. But it custom attributes for angular">is not that hard to create an own directive for showing sharepoint modal dialogs. I’ve called the new directive ng-sp-modal
(ngSpModal). Here is this: [sourcecode language=“javascript”] var ngSpModal = function() { link: function (scope, element, attrs, controller) { var dialog, defaults = { html: element.get(0), showClose: false }, getOptions = function () { var options = scope.$eval(attrs.ngSpModal); return angular.extend(defaults, options); }; fireSpModal: function (value) { if (value) { var opts = getOptions(); dialog = SP.UI.ModalDialog.showModalDialog(opts); } else { dialog && dialog.close(); } }; // Watch for changes to the directives options scope.$watch(attrs.ngShow, fireSpModal, true); } return { require: ‘?ngShow’, link: link }; }; window.myApp = angular.module(‘myApp’, [‘ui.directives’]); myApp.directive(’ngSpModal’, [ngSpModal]); [/sourcecode] The new ng-sp-modal directive depends on ng-show. When your expression or value for ng-show for your html area is true, then a sharepoint modal dialog will open. This is achieved through a $watch command. The html area which is used to create will be copied to the modal dialog. I have used it for forms. To use it, just place this directive into your html element that you want be shown in a modal dialog. Here is a simple example to achieve what it is shown in the screenshot pasted above. [sourcecode language=“html”] Here is the html markup for your modal dialog [/sourcecode] Here is the very simple angular controller to let it work: [sourcecode language=“javascript”] function someCtrl($scope) { $scope.modalOptions = { height: 100, width: 300, title: “Yeah” }; } [/sourcecode]
JavaScript Localization in SharePoint
Yesterday Waldek Mastykarz published a cool post: Globalizing JavaScript in SharePoint 2013. This is a very cool technique to localize your client code in javascript and reuse your resx files in Server Side and Client Side. This is actually not new for SharePoint 2013 despite it has become more needed with the huge client focus in the new SharePoint. I have used this in SharePoint 2010 for a long time. In my blog post: ScriptResx.ashx in SharePoint I told about that technique. What I didn’t know that you can define your javascript namespace directly in the resx file. Waldek wrote in his comment that SP.Publishing.Resources.en-US.resx automatically are SP.Publishing.Resources in javascript. That was not the case for my own localization files. A simple look at SP.Publishing.Resources.en-US.resx helped: [sourcecode language=“xml”] true SP.Publishing.Resources [/sourcecode] This results in: [sourcecode language=“javascript”] _EnsureJSNamespace(‘SP.Publishing’); [/sourcecode] So what we have to do for our custom resx file is to add classFullName resheader: [sourcecode language=“xml”] Takana.Res [/sourcecode]
AngularJS: prevent form validation in Page Edit Mode
I work on a cool project where AngularJS is used for rendering of business data in a SharePoint portal. One of the beautiful parts of AngularJS is the client validation. AngularJS understands the new html5 attributes like “required” and pattern, which makes the markup and javascript concise and semantic. Recently I ran into a problem: The SharePoint webparts which had html forms with required fields were impossible to add to a page in the web browser, neither was it possible to edit the pages with these webparts. When I clicked on “Save”, the page tried to validate and failed. The solution for this is very elegant, like much of the AngularJS. If you don’t show your angular form, it won’t validate. So just use any method to detect the edit mode on a SharePoint page. I created a helper function for that. [sourcecode language=“javascript”] function isEditMode() { var publishingEdit = window.g_disableCheckoutInEditMode, form = document.forms[MSOWebPartPageFormName], input = form.MSOLayout_InDesignMode || form._wikiPageMode; return !!(publishingEdit || (input && input.value)); } [/sourcecode] In the angular controller, just define the part of it which shouldn’t be there when you are editing a page, by using ng-hide="editMode"
: [sourcecode language=“html”] [/sourcecode] editMode
is a $scope variable in your controller. So the last thing to do is to get the editMode value by invoking the previously defined isEditMode
function: [sourcecode language=“javascript”] function PhoneCallCtrl($scope, $http) { $scope.editMode = isEditMode(); } [/sourcecode]
angular jQuery UI autocomplete
Angular JS is one of the most developed MVC frameworks in the javascript world. Angular UI is a huge UI-centric extension of AngularJS (it is more or less like jQuery UI to the jQuery). It uses much jQuery UI and Twitter Bootstrap and provides many own components like modal dialogs, maps, tooltips, masked inputs and much more. And all this is easy to implement in your code just by adding a directive: [sourcecode language=“html”][/sourcecode] Much cleaner than listening on $(document).ready, traversing the DOM and appending the datepicker in your code: [sourcecode language=“html”][/sourcecode] [sourcecode language=“javascript”]$(document).ready(function() { var input = $("#myDate"); input.datepicker(); });[/sourcecode] All this code is invoked but outside your app code.
javascript: show only a part of a long string (ellipsis)
Ellipsis (…) is a character which indicates that the content is to wide. There are many solutions to truncate the text and show an ellipsis: in javascript and css. I want to share my humble function which extends the String.prototype: [sourcecode language=“javascript”]String.prototype.ellipsize = function(maxLength) { maxLength = maxLength || 100; if (this.length <= maxLength) { return this; } var text = this.toString().replace(/[\r\n]/g, “”), max = maxLength, min = maxLength - 20, elipsized, tryExtract = function () { var regex = new RegExp("^.{" + min + “,” + max + “}\\s”), match = text.match(regex); if (match) { elipsized = match[0].replace(/\.?\s$/, ‘…’); } else { //well, there were no \s between min and max min = min - 20; tryExtract(); } }; if (min <= 0) { return text; } tryExtract(); return elipsized || text; };[/sourcecode] To use it, just call the function from a string property in your favorite templating engine: Angular, jsRender, Knockout….: [sourcecode language=“javascript”]order.description.ellipsize();[/sourcecode] This function takes an argument maxLength
(default 100 chars). It doesn’t cut your text in the middle of a word, that’s why it looks after a whitespace in range of maxLength-20 and maxLength.
Cool presentation about web performance optimization
by Chris Love [slideshare id=15218139&doc=webperformanceoptimizationformodernwebapplications-121116224847-phpapp01]
AngularJS: sync $location.search with an input value
I have used AngularJS for a while and to me this seems to be the best MVC javascript framework. Today I wanted to implement a search which uses an input and a hash query string like in google. The input value and url have to be synced like:
index.html#?term=something
To do this we have to inject $location
into our angular control. See the Angular Guide about $location. Then we have to observe both the $scope.term (which is bound to the input value) and $location.search().
Determine if Silverlight is installed (javascript)
For a while ago I needed to provide an alternative solution when Silverlight isn’t installed. I searched for javascript code for this and found this:
- A blog post about that: Piotr Puszkiewicz’s Silverlight Blog. Determining if Silverlight is installed using Javascript.
- A more advanced javascript function which can even determine the version of the Silerlight can be pulled from Silverlight.js library.
I didn’t need to determine the version of Silverlight, so I wrote a simplified js function (but it works in all browsers): [sourcecode language=“javascript”] var isSilverlightInstalled = function() { var installed = false; try { installed = !!navigator.plugins[“Silverlight Plug-In”] || !!(window.ActiveXObject && new ActiveXObject(‘AgControl.AgControl’)); } catch (e) {} return installed; };[/sourcecode] This function first checks if a Silverlight plugin is installed in almost all web browsers except IE, then if it is not it tries to create an ActiveXObject (IE) for Silverlight. If an error occurs, the function returns false and indicates that Silverlight is not available.
JSOM: Alter a column's DisplayName
Here is another article in my JSOM series. For one month ago I showed how to alter a column’s ShowInDisplayForm property with JSOM. This time I’ll show a code sample for changing a column’s (field’s) display name. If you want to alter the displayname with Server Object Model, grab the code in the sharepoint.stackexchange.com: Change Field’s DisplayName in a List. [sourcecode language=“javascript”]var ctx = SP.ClientContext.get_current(), //SP.ClientContext field = ctx.get_web() //SP.Web .get_lists() //SP.ListCollection .getByTitle(‘MyList’) //SP.List .get_fields() //SP.FieldCollection .getByInternalNameOrTitle(“Body”); //SP.Field ctx.load(field, “Title”); //load only Title ctx.executeQueryAsync(function() { field.set_title(“Beskrivning”); field.update(); ctx.executeQueryAsync(); });[/sourcecode]
Delete all list items with jsom
Today I needed to “clean” a list, meaning to remove all list items. For some time ago I wrote a post about different ways of removing list items in bulk: Server Object Model, SPLinq and RPC. This time I had only the web browser. So I tried the jsom way. By the way, the javascript documentation for jsom on msdn is getting really good. Don’t miss that: How to: Complete basic operations using JavaScript library code in SharePoint 2013. Now here comes theworking code I used to remove all items in my list:
TypeScript in SharePoint
By now TypeScript shouldn’t be something one has to introduce.
TypeScript is a typed superset of JavaScript that compiles to plain JavaScript.
If you haven’t already done it, go and see the intro video for TypeScript, check out a tutorial and visit the typescript playground. There are other javascript libraries which extend javascript and are compatible/compile to javascript: Dart and CoffeeScript. To be honest I had never time to try those. The fact that TypeScript is well integrated into Visual Studio which I happen to work within all the days (intellisense, compilation checks and more) did me curious. This post is actually not about TypeScript itself, but a test to use it in SharePoint. In this short “lab” I even had Web Essentials 2012 which automatically compile typescript files into plain javascript files on save. This is what I did: Install TypeScript and Web Essentials 2012 Create a SharePoint-hosted app: Create a new TypeScript file in the autogenerated “Scripts”-module and call it “Greeter.ts” Just save the file as it is. The new file is created: Greeter.js Now we don’t need to copy this file to the app, so remove Greeter.ts from the Elements.xml file (or comment it out): Open the Default.aspx from the Pages module and add the reference to the new javascript file:
GeoLocation Field in SharePoint 2013
In SharePoint 2013 Preview there is a new type of field: GeoLocation which is, like the old SPUrlField, a pair of values. The geolocation is described as longitude and latitude. Unfortunately you can’t add this field in list settings. You have to create this in code. In the provided link you can find the code C# code which uses the Client Object Model. In another link you can find an example how to create the geolocation file using Server Object Model (in FeatureActivated EventReceiver). If you know me, you might already know that I will propose a JavaScript solution. Here is the code to create a geolocation field in an existing list using JSOM:
Callouts in SharePoint 2013 Preview
While ModalDialog is not default for editing list items in SharePoint 2013 Preview, there is a new “popup” element in SharePoint - callout or popover. I would like to recommend these two blogs when you want discover more: Andrey Markeev: Callouts (popovers) в SharePoint 2013 Preview (in Russian) Alex Boev: a three part series: 1. Custom Callouts in the SharePoint 2013 Metro UI: Part 1: Basics 2. Custom Callouts in the SharePoint 2013 Metro UI, Part 2: Actions 3. Custom Callouts in the SharePoint 2013 Metro UI, Part 3: CalloutManager To get introduced with callouts in SharePoint 2013, you can run this code (from Andrey Markeev’s blog):
Masked Inputs
Just a quick tip today. If you are looking after masked inputs like the old ASP.NET Ajax Control Toolkit MaskedEdit, you can try jQuery plugin called Masked Input from DigitalBush or even better jquery.inputmask.
Paging with JSOM
If there are many list items you try retrieve with javascript object model,paging could be very useful. Today I came across a wonderful blog post series about javascript object model in SharePoint: The SharePoint javascript object model - Resources and Real World Examples posted by David Mann and published on Aptilon Blog. There is an example how to achieve paging with JSOM. The key is items.get_listItemCollectionPosition() and query.set_listItemCollectionPosition() I have refactored David’s example to avoid global variables and to put into a module. Here is it. If you have a Tasks list in your site with many items, just hit F12 to open the console and paste this and see the result:
Simplify js and css development with Web Essentials (Visual Studio Extension)
If you develop much javascript and css, this is the exension to Visual Studio you just can’t live without: Web Essentials (It is even released for VS2012). You can do many things with it. Here are two examples for simple but very useful functions: 1. Show which browsers support a css attribute: 2. Collapse javascript functions and create #region areas like in C# code: There is much more, like less and coffeescript parsing. Just check the documentation. And it is fully appliable in SharePoint development.
Toastr.js and SharePoint
Have you used SharePoint javascript Notifications (SP.UI.Notify)? Are you looking for something new and fresh? Well then check out the Toastr.js - a simple, beautiful, fully responsive and light-weight javascript lib for notifications, developed by John Papa and Hans Fjällemark and released under the MIT License. By the way, toastr was one of many things I discovered and learned on John Papa’s online course by pluralsight: Single Page Apps with HTML5, Web API, Knockout and jQuery. It is a really awesome course, where you learn how to create an amazing SPA. Well, how’s about SharePoint. While whatching the course videos about toastr, I thought: Can we use it in SharePoint? Yes we can! Just load the toastr css and js and start using it:
Multiple events listeners in jQuery
Maybe it is not so often we face this situation where we one event handler for different events in javascript. But in my project I use many custom events and in some situations it is the same handler which listens to different events. What I found you can define multiple event listeners at the same time.
function myClick() { console.log("tada"); }
$(".selector").on({
"click mouseover": myClick
});
JSOM: Alter a column's ShowInDisplayForm property
When you create a content type, you can define if your fields will be shown in DisplayForm, EditForm, NewForm. You can hide or show them, just as Yaroslav Pentsarsky says. If your list is already provisioned, you can change them with Server Object Model, why not in PowerShell: Technet: Setting ShowInDisplayForm, ShowInEditForm, ShowInNewForm properties with powershell. If you don’t have access to the server, then the same can be done with JSOM. Here is the code:
JSOM: Last Modified Date of a List
The data transfer between server and client can heavily affect the performance. One of the measures to reduce the amount data transferred from the server to the client is storing data on the client. In many modern browsers we can use html5 localStorage. Even in older browsers there are ways to store data. I would recommend a nice js lib called amplify.js. The interface is much easier, then:
amplify.store("key", { title: "value" });
```It comes in nicely, if we have much data which we get with JSOM. But we have to care about eventual changes to list items done after we got them the last time. So we have to store the [last modified date](http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.splist.lastitemmodifieddate.aspx). This property is also available in JSOM:
var ctx = SP.ClientContext.get_current(); var web = ctx.get_web(); var lists = web.get_lists(); var list = lists.getByTitle(“Tasks”); ctx.load(list, “LastItemModifiedDate”); ctx.executeQueryAsync( function() { var lastmodified = list.get_lastItemModifiedDate(); }, function() {} );
Using SharePoint tooltips
I found a great post about using sharepoint tooltips on Andrey Markeev’s (@amarkeev, omlin) blog: JavaScript ToolTip’ы для SharePoint. He describes how he found the standard sharepoint tooltips and how they can be reused. The best part of it his “research”. Andrey’s conclusion is to create an own, simplified javascript class which enables “sharepoint” tooltips. I modified it somewhat. I think there is no need to instantiate a TooltipManager…
var Takana = window.Takana || {};
Takana.ToolTipManager = function () {
var \_divId = "my\_tooltip";
var \_innerDivId = "my\_tooltip\_inner";
function createTitleAndDescriptionHtml(title, description) {
return String.format(
'<div>{0}</div><div>{1}</div>',
title,
description);
}
function showTooltip(element, rawHtml) {
var tooltipDiv = $get(\_divId);
if (tooltipDiv == null)
tooltipDiv = createTooltip();
$get(\_innerDivId).innerHTML = rawHtml;
displayTooltipNextToElement(tooltipDiv, element);
}
function displayTooltipNextToElement(tooltipDiv, element) {
tooltipDiv.style.display = '';
var loc = Sys.UI.DomElement.getLocation(element);
tooltipDiv.style.left = loc.x + 'px';
tooltipDiv.style.top = loc.y + element.offsetHeight + 2 + 'px';
if (tooltipDiv.curTimeout != null)
clearTimeout(tooltipDiv.curTimeout);
}
function createTooltip() {
var mainDiv = document.createElement('span')
mainDiv.id = \_divId;
mainDiv.className = 'ms-cui-tooltip';
mainDiv.style.width = 'auto';
mainDiv.style.position = 'absolute';
var bodyDiv = document.createElement('div');
bodyDiv.className = 'ms-cui-tooltip-body';
bodyDiv.style.width = 'auto';
var innerDiv = document.createElement('div');
innerDiv.id = \_innerDivId;
innerDiv.className = 'ms-cui-tooltip-glow';
innerDiv.style.width = 'auto';
bodyDiv.appendChild(innerDiv);
mainDiv.appendChild(bodyDiv);
document.body.appendChild(mainDiv);
return mainDiv;
}
function hideDiv() {
$get(\_divId).style.display = 'none';
}
var manager = {};
manager.attachToolTip = function (element, title, description) {
$addHandler(element, 'mouseover', function (e) {
showTooltip(element, createTitleAndDescriptionHtml(title, description));
});
$addHandler(element, 'mouseout', hideDiv);
}
manager.attachToolTipRaw = function (element, rawHtml) {
$addHandler(element, 'mouseover', function (e) {
showTooltip(element, rawHtml);
});
$addHandler(element, 'mouseout', hideDiv);
}
return manager;
}();
Now a manager is created on a page per default. To add a tooltip, just use the TooltipManager:
Chuvash localization of moment.js
For three months ago I added Chuvash localization of moment.js. For 16 days ago moment.js 1.7.0 was officially released which included the Chuvash translation.
Wait a sec… What is moment.js?
moment.js is the best datetime tool for javascript. It supports many languages (now even Chuvash) for displaying date and time. Another very handy functionality is showing relative time which has a simple interface: fromNow().
Here is a simple example from a web browser console:
Chuvash translation of Wikipedia Mobile
The official Wikipedia mobile app is now translated into Chuvash language and available to use:
What does Chuvash mean?
I am Chuvash. Chuvash is the name of an ethnicity which counts up to 2 milions peoply (mostly in Russia). Chuvashes talk the Chuvash language which is also an official language in Chuvash Republic (besides Russian). Chuvash language is a Turkic language and has a status “Vulnerable” in the UNESCO list of languages in danger. There is a Chuvash Wikipedia cv.wikipedia.org.
Multiple instances of javascript webparts on the same page
Javascript has become popular among many SharePoint developers thanks to easy and fast jQuery, CSOM, SPServices and many other javascript libraries. That can make solutions modern and fast. On the other hand developers should be aware of more things (some of them at Bamboo Team Blog). One of those is scoping of javascript webparts. The problem a developer has to consider: what happens if a user creates two or more instances of the same beautiful webpart on the page? Let’s go and lab :) I’ll create a solution for this lab: sp-lend-id.ikkelen. This time it will be a sandboxed solution. This solution contains a webpart:
Three ways to get the id of last created SPListItem
An interesting question came on SharePoint StackExchange: How to retrieve the guid of the last uploaded file. It is only possible in CSOM as far as I know. But if we simplify the task, how to get the id of the last item, the we can compare three ways of getting them: SPServices, jQuery + listdata.svc and CSOM.
SPServices
The most easiest way, but not available in async:
$().SPServices.SPGetLastItemId({
listName: "Documents"
});
listdata.svc
Just combine some query strings and try in the browsers address bar:
Web Application Properties as JSON
I saw an interesting question on sharepoint.stackexchange: How to access a Web application/Farm level property bag via jQuery/Javascript/ClientContext. Some time ago I tested a custom http handler, so I wanted to try a custom httphandler for this as well. It worked. Here more details: Just deploy sp-lend-id.tupsam from the solution. If you don’t have any properties in your web application, just add some:
asnp microsoft.sharepoint.powershell
$app = get-spwebapplication http://dev
$app.Properties.Add("Santa", "Claus")
$app.Properties.Add("Ded", "Moroz")
$app.Properties.Add("Hel", "Muci")
$app.Update()
Then just to test open the httphandler directly in the browser:
Using javascript objects passed from closed popup
It is not a rocket science to pass objects from child window (popup) to main window. The problem I encountered today was IE and passing complex objects. So it is just an IE issue as far as I know. The problem occurs when you pass some object (not a simple String or Number) to main window:
window.opener.takeAnObjectFromChild = {
title: "Should even be available when I close the child"
};
and you then close the child window, next time the main window tries to access the passed object:
javascript: developing for performance
Many words have been said about the importance of performance when working with javascript files. Here I want to summarize what developers can do to increase the performance related to javascript. I found many tips on blogs. Here comes my aggregated list of actions one can do to speed up sharepoint (and not only) sites with focus on javascript:
1. Load only sharepoint stuff you need
Use prefetch option to only load sharepoint javascript files that needed. To see the difference, just add ?prefetch=0
to your sharepoint url in the browser. The downside of this lazy loading is that you wrap all sharepoint related javascript into ExecuteOrDelayUntilScriptLoaded otherwise you maybe invoke some of javascript objects and functions that are not loaded. So the prize of this huge performance improvement is a high awareness by a developer when and which scripts are loaded and run.
nodeunit and SharePoint: unit tests in javascript
nodeunit is a (relatively) new test framework for javascript, mainly for node, but it can be run in a browser as well. The most popular framework for testing javascript is Qunit, but I’ll lab with it another time. I found nodeunit tests in moment.js - the best date handling framework for javascript and it worked very well. So first of all, why should we test? The best answer is actually: Life is to short for manual testing (it was actually the slogan at the Google London Test Automation Conference 2007.
$ in cmssitemanager.js conflicts with $ in jQuery
In SharePoint 2010 if CMSSiteManager.js library is loaded besides jQuery, then much of stuff stops working. The reason is that the dollar sign ($) is used in cmssitemanager.js as well which conflicts with jQuery. Mostly it appears on pages where you load jQuery and have an image library with thumbnails. To avoid this, just replace all $ with jQuery in your custom scripts. A more crazy situation is when avoiding $ isn’t enough. It is when you load jQuery to page head automatically on all pages. The Asset picker (AssetPortalBrowser.aspx) invokes $ itself and gets with jQuery in conflict without you write a single line of custom javascript code. You usually get the following error:
javascript toolkit on text file
Referencing javascript libraries from Content Delivery Networks (CDN) like jQuery can have many benefits. The self-hosted javascript files are on the other hand give you more control. But in one situation it is much better with cdns: the development. Like Marc D Anderson pointed:
I didn’t realize it at the time, but this txt file has become a standard part of my toolkit already. I’ve added it to three client environments just since last week. It’s the A #1 fastest way to get something up and running, even if you know you’re going to host the files locally later.
jQuery mobile and SharePoint
In this post I want to explore how to build a mobile app using jQuery mobile. Recently I discovered two great blog posts about this:
- Building SharePoint web apps using Sencha Touch by Luc Stakenborg
- jQuery mobile and SharePoint by Chris Quick
In my post I’ll use their findings and share some of mine thougts. I’ll focus mostly on how to get started with jQuery mobile and SharePoint. So go ahead and create your jQuery mobile app, just drag’n’drop some controls: Download it and yout get an “app.html” file and “my.css”. For now ignore my.css. app.html is something like that:
Clone javascript objects
In javascript, if we copy objects or their properties, the reference still remains and by changing the new object the old one is changed, too. To clone or do a clean copy of an object I found a very useful solution by Jan Turoň on StackOverflow:
Object.prototype.clone = function() {
if(this.cloneNode) return this.cloneNode(true);
var copy = this instanceof Array ? \[\] : {};
for(var attr in this) {
if(typeof this\[attr\] == "function" || this\[attr\]==null || !this\[attr\].clone)
copy\[attr\] = this\[attr\];
else if(this\[attr\]==this) copy\[attr\] = copy;
else copy\[attr\] = this\[attr\].clone();
}
return copy;
}
Date.prototype.clone = function() {
var copy = new Date();
copy.setTime(this.getTime());
return copy;
}
Number.prototype.clone =
Boolean.prototype.clone =
String.prototype.clone = function() {
return this;
}
clearInterval in Chrome doesn't work on window blur
If you want to reset all interval jobs when a browser tab is inactive, the best way would be to use clearInterval on window blur. But unfortunately Chrome fires window focus and window blur two times. Here is an embryo to a solution:
var M = window.M || {};
M.counter = 0;
M.focused = true;
M.tick = function() {
if (M.focused) {
console.log("tic tac " + ++M.counter);
}
};
M.start = function(e) {
console.log("starting...");
M.focused = true;
};
M.stop = function(e) {
console.log("stopping...");
M.focused = false;
};
$(window).on({
focus: M.start,
blur: M.stop
});
M.ticker = window.setInterval(M.tick, 1000);
shorthand for jQuery(document).ready
jQuery(document).ready is used very often, why not use the shorthand variant of that?
$(function() {
// Code here
});
moment.js - the best javascript tool for working with dates
Just look at moment.js. Everybody who have worked with dates in javascript are going to love it.
Comments from Wordpress.com
Justin Cooney - Mar 3, 2012
Interesting, I hadn’t heard of moment.js. I’m taking a look at the site right now; it looks to have some very handy functionality for date manipulation!
The great thing with moment.js is e.g. that one can create a date object from asp.net date format like /Date(123543534)/
Kalendae - new javascript utility for calendars
An alternative to jQuery UI datepicker is Kalendae. (MIT License). Highly customizable and no dependencies to other javascript libraries. Here is the highlights:
Kalendae is an attempt to do something that nobody has yet been able to do: make a date picker that doesn’t suck. Kalendae provides the following features:
- Fully portable, no dependencies. No jQuery, no Prototype, no MooTools; just add the script and the stylesheet and you’re good to go.
- Fully and easily skinable. The default theme uses only one image file (a mask for the previous and next buttons), everything else is styled using CSS.
- Supports all modern browsers and IE8.
- Support single day, multiple day, or day range selection.
- Configurable number of months to be displayed at once.
- Can be displayed on the page as an inline widget, or attached to one or more input fields as a popup control.
- Can be attached to any page element, not just named elements.
- Configurable blackouts, defined either as an array of dates or via a callback function
- Output selected dates in a variety of formats
- Leverages moment.js for smart and easy date parsing.
Found through daily.js
fallback for html5 placeholders
Placeholders are very handy in html5, we don’t need to fool with input values. But in SharePoint and IE we must provide fallback for placeholders if we want use them in other browsers. Here is an jQuery extension to do that:
(function ($) {
$.fn.extend({
ensurePlaceholders: function () {
var input = document.createElement('input');
var placeholderSupported = ('placeholder' in input);
if (placeholderSupported) {
return;
}
function setHints(elem) {
var $elem = $(elem);
var value = $elem.val();
if (value == "") {
var placeholder = $elem.attr("placeholder");
$elem.val(placeholder);
$elem.addClass("empty-text");
}
}
function removeHints(elem) {
var $elem = $(elem);
$elem.removeClass("empty-text");
var value = $elem.val();
var placeholder = $elem.attr("placeholder");
if (value == placeholder) {
$elem.val("");
}
}
this.find("\[placeholder\]").each(function() {
setHints(this);
});
this.on("focus", "\[placeholder\]", function(e) {
removeHints(this);
});
this.on("blur", "\[placeholder\]", function(e) {
setHints(this);
});
}
});
})(jQuery);
```Then "ensure placeholders" by running this function on a wrapper element which contains fields with the placeholder attribute:
jQuery("#form-wrapper").ensurePlaceholders();
SP.UI.Notify in Modal Dialog
If you open a custom page (not a list item form) in a modal dialog, your notification won’t be shown. The reason is that the notification area (#notificationArea) is inside a hidden div (#s4-ribbonrow). To show this notificationArea we must display the notification area:
var $ribbon = jQuery("#s4-ribbonrow");
if ($ribbon.is(":hidden")) {
$ribbon.css({"min-height": 0, "height": "0px"})
.show().children().hide()
.filter("#notificationArea").show()
}
Comments from Wordpress.com
Jens Malmberg - Jan 3, 2013
private variables in javascript
Found a nice post about private variables and “methods” in javascript. Consider this example:
function Pizza() {
var price = 0;
this.setPrice = function(p) {
price = p;
};
this.getPrice = function() {
return price;
};
}
```Every variable and function inside the main function is private unless it is appended to "this".
javascript: Umbrella pattern
There are two great patterns for organizing javascript code: Prototype and Module pattern. More about them later in this post. But in reality I still see much of spagghetti Just an example: SharePoint 101 code samples. They are indeed very simple and isolated examples. And many projects use this simple way in mind when they begin. But when javascript code grows, it becomes a monster. Have you seen this biest? How is this monster created? Through good intentions (like everything else) in form of KISS mantra, to little time and the “commit and run”-behavior, or the worst: “I am c#-er, not Front-End-Developer”-spirit. In this post I’ll introduce a kind of compromise the Umbrella pattern. But before that, let’s see how to recognize the spagghetti monster in javascript:
Hello world in node.js
I know, node.js has been present for a while. But I actually had no time to try it. I was surprised that now it is very straight forward to start with node.js. Allright, everything begins with Hello world. Eventhough it is available for allmost all combinations of operating systems and servers, the easiest way to test it was actually Ubuntu. To install just run:
sudo apt-get install nodejs
```Then make a new directory and create the hello.js:
mkdir hello cd hello vi hello.js
New functions in jQuery 1.7+ on and off
A simpler interface for event handling in jQuery. Just read Dan Wahlin’s blog.
cross browser console.log
console.log
is the best tool for debugging javascript. In Firefox Firebug and Chrome Dev Tools you can even log objects which are represented as tree nodes of properties. If Firebug or Dev Tools in Chrome and IE9 are not opened, all these messages are ignored. But IE8 doesn’t understand console (if Dev Tools are closed) and raises an error: To avoid these errors, just declare an empty function just for IE8–:
javascript: passing arguments from popup to main window
To show a popup, we just have to invoke “window.open”, and provide some options to prevent opening this in a new tab:
var wnd = window.open('', '\_blank', 'width=750, height=400, location=no, resizable=1, menubar=0, scrollbars=0');
wnd.document.write('');
wnd.document.close(); wnd.document.close(); wnd.focus();
To communicate between parent and child we can refer to parent as window.opener. We can even invoke a function from parent window. Let’s create the most useful function:
javascript: serialize as xml
Why should we need to serialize javascript objects as XML. I don’t know. It is of course more a server side need. And there actually a need for javascript serialization as xml in node.js. To serialize as json is very simple: JSON.stringify(myobjects). I was just curious if there was a tool for xml serialization in javascript. There is a nice javascript tool called XMLWriter, developed by Ariel Flesler. Consider you have articles and want to serialize them as xml, let’s create a function for serializing:
Enable Save in IE9 mode
Wouldn’t it be nice to use html5 and css3 in SharePoint? No problems, there is actually v5 master out there, created by Kyle Schaefer. Or just use h5ml5 and css3 right away in your webparts and pages. But there is a big problem. It doesn’t work in IE9–. One of the issues (even listed by Kyle) is that “save” doesn’t work in modal dialogs where Rich Text Editor is used. Especialy it is for modal dialogs. The problem is not IE9, neither html5 and css3. After some digging in javascript code which is shipped with SharePoint I found out that the problem is some legacy javascript code which is not supported by IE9 but in IE8– (and compatibility mode). When we set IE9 mode in IE9 Dev Tools (F12) and go to Tasks list and try to create a task, we’ll get an error: It is RTE_GetEditorIFrame from init.js:
$().SPServices is best for SOAP
SPServices is a great tool, really nice work, Marc Anderson (@sympmarc). It has been there all the time I have developed for SharePoint. But the fact that you work with XML and you must parse the attributes (!) was the reason why I prefered listdata.svc and Client Object Model, where you get objects in JSON or you have a nice API to get objects and their properties. But there is an area where SPServices are really the best tool: SharePoint Web Services which only understand SOAP like SocialDataService.asmx.
$ and jQuery in SharePoint
Do you still use $ for jQuery? Well, don’t. If your code with $ resides with a SharePoint Images webpart, it will stop working. You’ll get errors like
Uncaught TypeError: Cannot call method 'empty' of null
The reason is that SharePoint uses $ in its own javascript code: CMSSiteManager.js
function $()
{ULSjlC:;
var elements=new Array();
for (var i=0; i < arguments.length; i++)
{
var element=arguments\[i\];
if (typeof element=='string')
element=document.getElementById(element);
if (arguments.length==1) return element;
elements.push(element);
}
return elements;
}
onchange isn't firing in IE
I don’t know why, but (not always, just sometimes) IE doesn’t fire the onchange event (which is added as an attribute on an html element). A better “workaround” is to add an eventlistener in javascript. Or a lazy workaround is to use the onclick event even for checkboxes.
ScriptResx.ashx in SharePoint
In my previous post I showed a little proof-of-concept for an httphandler which I want to use to dynamically get the localization resources from SharePoint as javascript object. But wait a moment. How does SharePoint handle localization on client? When you look in Script tab in Chrome dev tools, you’ll find:
ScriptResource.axd
It is added to the server when deployed. See a good introduction to WebResource.axd and ScriptResource.axd by Brian Chavez.
Custom HttpHandler in SharePoint for getting dynamic javascript code
Sometimes I want to add some dynamic javascript code. E.g. I had an idea to get javascript code for localization dynamically. Kirk Evan provides a very clean approach to add ASP.NET HttpHandler to SharePoint. This is just a little lab: Create a SharePoint empty project. I call it Jerkelle. Create a class called Resx2JsHandler and implement the IHttpHandler interface Add the mapped folder Layouts and create Jerkelle.ashx file Here is the project. I probably will publish it on my github account: The Jerkelle.ashx file is very simple, it references to the code file (Resx2JsHandler.cs):
XMLHttpRequest the hard way
$.ajax is great, it hides much of the complexity. But sometimes we need to work with “raw” javascript :) So let’s look behind the scenes. The XMLHttpRequest (or just XHR) is used to open a connection to a server without a page reload. Internet Explorer calls it ActiveXObject and it differs in IE versions. Wikipedia article gives a good example how to create one constructor for all browsers: [sourcecode language=“javascript”]if (typeof XMLHttpRequest == “undefined”) XMLHttpRequest = function () { try { return new ActiveXObject(“Msxml2.XMLHTTP.6.0”); } catch (e) {} try { return new ActiveXObject(“Msxml2.XMLHTTP.3.0”); } catch (e) {} try { return new ActiveXObject(“Microsoft.XMLHTTP”); } catch (e) {} //Microsoft.XMLHTTP points to Msxml2.XMLHTTP and is redundant throw new Error(“This browser does not support XMLHttpRequest.”); };[/sourcecode] The remainder is more or less the same among the browsers. We open a connection defining the HTTP verb, URI and async mode (true or false): [sourcecode language=“javascript”]var xhr = new XMLHttpRequest(); xhr.open(“GET”, “/_vti_bin/listdata.svc”, true); xhr.onreadystatechange = onStateChange; xhr.send(null);[/sourcecode] Pay attention to onreadystatechange (only lower case letters). If we choose async=false, the UI waits for the response which is not so kind to users, but maybe it is easier to write a program. Well, there is actually no option but to have async=true. To provide the callback for success and error we can write the responding function onreadystatechange. This function will be called every time the state is changed. There are 5 states:
Loading notification
When you load some data with ajax, you will probably want to show the users in some way, that data is loading. To show the text “loading…” would be enough. Another, very common way to do it to show a spinner, a rotating image. In sharepoint we can use the built-in gif which can be found in /_layouts/images/loading16.gif. Well, it is actually not so good, because this image is not so beautiful. A better way is to create your own gif image which is exactly suited for our needs. Or even better: don’t use any images. Use the light-weight javascript library called spin.js for creating spinners. It is fully customizable, compatible with older browsers. You can customize it interactively on the spin.js homepage.
javascript trim()
String.trim() is quite useful in many situations. Unfortunately not all browsers have this function on String prototype (e.g. IE8): I see many people use jQuery.trim(), but isn’t it better to just use String.trim and provide a backup function if it is not implemented, like we did with Date.toISOString:
if(!String.prototype.trim) {
String.prototype.trim = function() {
return this.replace(/^\\s+|\\s+$/g, "");
}
}
```EDIT: [found this solution on SO](http://stackoverflow.com/a/8522376/632117). Did we think the same?
Push a copy of Resources to client in javascript
In one of my previous posts I told about pushing a copy of an object into client. Now I’ll try to copy my resource values into client. The problem is often that we must create multiple localization resources: first as resx-file. If we use much ajax and client side rendering, we must provide some localization there, too. If they are different subsets of localization resources, it isn’t a problem. But when you get overlapping, it becomes more difficult to manage and sync them. See how Microsoft Ajax Library provides some strings: What if we just copy the values from resx file into client? If there are not business constraint it can make the development much easier. Let’s try it. For that we need Reflection. We start with changing the access modifiers on resx file to public: Then we must get all static properties of the auto-generated class (ResXFileCodeGenerator):
Simple select unselect all
I have a simple html table, every row in tbody has a checkbox. thead has a checkbox. When it is checked/unchecked, all checkboxes have to be selected/ unselected. Here is a very simple javascript to achieve this:
$("#mytable thead :checkbox").live({
change: function () {
var checked = $(this).is(":checked");
$("#mytable tbody :checkbox").attr("checked", checked);
}
});
Nested templates in jQuery.tmpl
I have used jQuery tmpl for a while and it is really awesome. Now I want to use some nested templates. And the thing is: it is very simple to do it: Here is the code to achieve this:
<div onclick="doo()">test</div>
<div id="container"></div>
<script id="parent-template" type="text/html">
<li>
{{tmpl t }}
</li>
</script>
<script id="red" type="text/html">
<span style="color:red">{{= title}}</span>
</script>
<script id="green" type="text/html">
<span style="color:green">{{= title}}</span>
</script>
<script type="text/javascript">
var d = \[\];
d.push({ title: "one", t: "red" });
d.push({ title: "two", t: "green" });
$.template("red", $("#red").template());
$.template("green", $("#green").template());
function doo() {
$("#parent-template").tmpl(d).appendTo("#container");
}
</script>
jQuery: select elements with a specific text
There are situations when you want to select only dom elements which only have a specific content. jQuery provides a beautiful selector :contains:
$("a:contains(Pages)")
```But what if it isn't enough to just get all the elements which contain some word? Let's check what we get if we traverse all anchors on http://sv.wikipedia.org containing "wiki":
$(“a:contains(wiki)”).each(function(i) { console.log($(this).text()); });
[![](https://sharepointkunskap.files.wordpress.com/2012/02/jquery-contains-wiki.png "jquery-contains-wiki")](https://sharepointkunskap.files.wordpress.com/2012/02/jquery-contains-wiki.png) There is another, a generic way, to filter out elements, and it is called "filter". So a little regex check will do the trick.
$(“a”).filter(function() { return /look_for/i.test($(this).text()); }
Parameterize a javascript object and create url
If you want to add some parameters to an url which you want to open, you can use jQuery.param function:
var url = "some\_url";
var params = {
name: "Setner",
email: "setner@narspi.name",
mobile: "123456789"
};
var search = "?" + $.param(p);
url += search;
```It is handy, indeed. In an environment without jQuery (are there some?:) ) you can just iterate an object and join properties:
var url = “some_url”; var params = { name: “Setner”, email: “setner@narspi.name”, mobile: “123456789” }; if (url.match("/\?/g") == null) { url += “?”; } else { url += “&”; } var search = “”; for(var p in params) { search += [p, params[p]].join("="); } url += search;
Save an excel sheet as a clean table
To save an excel sheet as a html table is very easy. Just select the needed area, then go to Save as and check the selection and choose html as output format. It works fine. It even looks like it did in Excel. But what if you don’t want all this junk, you want only the plain html table (e.g. for pasting into WP). When I saved my permission levels to html, I used this javascript code. First open the html page which Excel has created in Chrome, open the Dev Tools console, load the latest jQuery into the page, and remove all unnecessary attributes and styling, remove the comments, after that you can just copy the outerHTML of the table and paste into a text editor:
Datetime in ASP.NET javascript and $.ajax
In one of my previous blogs I wrote about serializing of javascript objects. You can do it with JSON.stringify or Sys.Serialization.JavaScriptSerializer.serialize. Both methods work fine… almost. There is a big difference when it comes to datetime objects. MS treats dates a little bit different (like RegEx and much more). Let’s try this one:
var writer = { name: "Ajgi", birthdate: new Date(1934, 8-1, 21) };
var json = JSON.stringify(writer);
var msjson = Sys.Serialization.JavaScriptSerializer.serialize(writer);
What happens if we try to parse back msjson with JSON.parse: Well, the date isn’t a valid date anymore. How can we improve it. Rick Strahl gives a solution with custom functions for serializing and deserializing of ms date. But the thing is: we don’t need any custom functions for this, not if you run ASP.NET. The only thing we need is to use serialize and deserialize functions from Sys.Serialization.JavascriptSerializer namespace which you get automatically when you add ScriptManager in ASP.NET (and you get it even automagically in SharePoint). But what about $.ajax and functions I wrote about for retrieving list items and populating them, and updating list items with listdata.svc? Well, there comes the really nice tip from Rick Strahl: not to force $.ajax to parse the response. So instead of dataType: “json”, use the plain dataType: “text”. As the result we’ll get just a text, which we, of course, will deserialize with the native code for Microsoft:…. Use text when possible. When you define json as response format:
Simple stopwatch in javascript
If some javascript code takes too much time to execute, you probably want to see what time your code or a part of the code takes to run. I found an idea in Dave Cranes Ajax in Action. The book is a little bit old and the code provided below has been changed and simplified:
var stopwatch = {};
stopwatch.watches = \[\];
stopwatch.getWatch = function(id, startNow) {
var watch = stopwatch.watches\[id\];
if (!watch) {
watch = new stopwatch.StopWatch(id);
}
if (startNow) {
watch.start();
}
return watch;
};
stopwatch.StopWatch = function (id) {
this.id = id;
stopwatch.watches\[id\] = this;
this.events = \[\];
this.total = 0;
this.count = 0;
};
stopwatch.StopWatch.prototype.start = function() {
this.current = new stopwatch.TimedEvent();
};
stopwatch.StopWatch.prototype.stop = function() {
if (this.current) {
this.current.stop();
this.events.push(this.current);
this.count++;
this.total += this.current.duration;
this.current = null;
}
};
stopwatch.TimedEvent = function () {
this.start = new Date();
this.duration = 0;
};
stopwatch.TimedEvent.prototype.stop = function() {
var stop = new Date();
this.duration = stop - this.start;
};
Get url parameters with javascript
There is a question in Stackoverflow and this one, too. There is a fine solution for jQuery. The only thing we need is window.location.search. Say we have http://domain.com?q=hello&a=good#home, then it takes only ?q=hello&a=good, and leaves #home and the main url. Anchors can be retrieved with hash. Here are all properties of window.location: Google Chrome provides a fine function: window.location.getParameter: I like the name of this function. So why not to use it or create this one if a browser doesn’t have it? Well here we go:
Reload page in js: RefreshPage
There are many ways to reload / refresh a page in javascript. One of them is as in discoveringsharepoint.wordpress.com describes:
window.location.reload()
```Today I found some tools which are shipped with ASP.NET/SharePoint to reload a page. The big advantage of them they are designed to work with SharePoint and take all possible aspects of page life cycle into account. The javascript function to refresh a page is just called, guess..: **RefreshPage** and it resides in init.js:
//init.js: function RefreshPageTo(evt, url, bForceSubmit) {ULSA13:; CoreInvoke(’_RefreshPageTo’, evt, url, bForceSubmit); }
Run javascript code except it is inside a modal dialog
Want to run some javascript code everywhere, but not in a modal dialog. Because errors are occured, or this code is unnecessary i dialogs. Well here is a solution I have found after some experiments:
$(document).ready(function() {
if (!window.location.href.match(/isdlg=1/i)) {
onDocumentReadyExceptItIsInDialog();
}
});
function onDocumentReadyExceptItIsInDialog() {}
```This code checks with Regular Expressions if the url of the parent window contains IsDlg=1, if so nothing happens. In the usual case (not inside a dialog), the javascript code runs. EDIT: after I wrote this I actually found that this is the way SharePoint itself does: [![](https://sharepointkunskap.files.wordpress.com/2012/01/isdlg.png "isdlg")](https://sharepointkunskap.files.wordpress.com/2012/01/isdlg.png) So now I update the previous function to this:
$(document).ready(function() { if (window.location.search.match(/[?&]isdlg=1/i)) { return; } onDocumentReadyExceptItIsInDialog(); });
Simplifying jQuery tmpl interface
In one of my previous posts I showed a simple example how to retrieve data from a web service and render it with jQuery tmpl. To render this I used an id for a template and the container:
<script id="contactTemplate" type="text/html">
<div>
Name: {{= Name }} <br>
Phone: {{= Phone }}
</div>
</script>
<div id="contactContainer"></div>
```To render we select the template and container with jQuery selectors:
function onSuccess(data) { $("#contactTemplate").tmpl(data.d.results).appendTo("#contactContainer"); }
(function ($, undefined) { if ($ === undefined) { throw “Dependency: jQuery is not defined. Please check javascript imports.”; } $.extend($.expr[’:’], { // :template(name) template: function (current, index, metadata, elements) { var arg = metadata[3], d = $(current).data(“template-for”); if (d === undefined) { return false; } return arg ? arg === d : true; }, // :container(name) container: function (current, index, metadata, elements) { var arg = metadata[3], d = $(current).data(“container-for”); if (d === undefined) { return false; } return arg ? arg === d : true; } }); } (jQuery));
listdata.svc vs CSOM for retrieving and manipulation of list items
What is better and where and when… I’ll try to find out.. This post will be updated soon. Take a look at this so far: http://sharepoint.stackexchange.com/questions/23209/sharepoint-2010-javascript-client-object-model-cross-site-collections
String.format for javascript
sprintf is actually the best javascript implementation of sprintf (string.format). But wait, shouldn’t it be some more .NET-like stuff in SharePoint environment? Indeed there is! (Well, not only in SP, but ASP.NET) String.format(“Hello {0}”, “world”) does exactly the same thing as on server side. Wow, it opens for many opportunities, e.g. in jQuery tmpl: String.format validates arguments, and if all is OK, it invokes another function String._toFormattedString:
function String$\_toFormattedString(useLocale, args) {
var result = '';
var format = args\[0\];
for (var i=0;;) {
var open = format.indexOf('{', i);
var close = format.indexOf('}', i);
if ((open < 0) && (close < 0)) {
result += format.slice(i);
break;
}
if ((close > 0) && ((close < open) || (open < 0))) {
if (format.charAt(close + 1) !== '}') {
throw Error.argument('format', Sys.Res.stringFormatBraceMismatch);
}
result += format.slice(i, close + 1);
i = close + 2;
continue;
}
result += format.slice(i, open);
i = open + 1;
if (format.charAt(i) === '{') {
result += '{';
i++;
continue;
}
if (close < 0) throw Error.argument('format', Sys.Res.stringFormatBraceMismatch);
var brace = format.substring(i, close);
var colonIndex = brace.indexOf(':');
var argNumber = parseInt((colonIndex < 0)? brace : brace.substring(0, colonIndex), 10) + 1;
if (isNaN(argNumber)) throw Error.argument('format', Sys.Res.stringFormatInvalid);
var argFormat = (colonIndex < 0)? '' : brace.substring(colonIndex + 1);
var arg = args\[argNumber\];
if (typeof(arg) === "undefined" || arg === null) {
arg = '';
}
if (arg.toFormattedString) {
result += arg.toFormattedString(argFormat);
}
else if (useLocale && arg.localeFormat) {
result += arg.localeFormat(argFormat);
}
else if (arg.format) {
result += arg.format(argFormat);
}
else
result += arg.toString();
i = close + 1;
}
return result;
}
```By the way, take a look at summary part of String.format:
/// /// /// ///
Batch remove
To add items to a list in bulk, or remove them in bulk. Well to do that you can use SPLinq, Server Object Model and … web.ProcessBatchData, which is the most effective. I did an experiment today. I created 1000 tasks in my task list three times and removed all items in three different ways and took time. First I put 1000 items with ajax and listdata.svc:
function pad(n) {
if (n >= 10000) return n;
if (n >= 1000) return '0' + n;
if (n >= 100) return '00' + n;
if (n >= 10) return '000' + n;
return '0000' + n;
}
var s;
var counter = 0;
var title = "task "
function foo() {
counter++;
if (counter > 10000) {
window.clearInterval(s);
}
else {
var value = {};
value.title = title + pad(counter);
createNewTask(value);
}
}
s = setInterval(foo, 200);
Then I ran three different scenarios. Here is the resut for VMWare machine Windows Server 2008 R2, 4GB RAM, SharePoint 2010 SP1:
use two different versions of jQuery on the same page
jQuery is very popular. The chance that you’ll get two or more jQuery files loaded on the same page is very high. As long as it doesn’t conflict, it is fine. But what if there are differences, and another version of jQuery destroys your functionality. To solve it we can ensure that we invoke “our”, the right version of jQuery. To do so, create a pointer to your jQuery:
var myJq = jQuery.noConfict();
```So if you can, avoid invoking $ or jQuery directly. Here is the original example from [jQuery forum](http://forum.jquery.com/topic/multiple-versions-of-jquery-on-the-same-page):
this.data in jQuery tmpl
In jQuery tmpl we can render properties with {{= SomeProperty }}. Here is an example:
<script type="text/javascript">
Writer = function (firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
};
Writer.prototype = {
getFullName: function () {
return this.firstName + " " + this.lastName;
}
};
$(document).ready(function () {
var writers = \[\];
writers.push(new Writer("Gennady", "Ajgi"));
writers.push(new Writer("Mišši", "Şeşpĕl"));
writers.push(new Writer("Ille", "Tuktaš"));
writers.push(new Writer("Kĕştenttin", "Ivanov"));
$("#tmpl").tmpl(writers).appendTo("#writers");
});
</script>
<script id="tmpl" type="text/html">
<li>
{{= firstName }} {{= lastName }}
</li>
</script>
<div id="writers"></div>
```It will render like:
* Gennady Ajgi
* Mišši Şeşpĕl
* Ille Tuktaš
* Kĕştenttin Ivanov
But what if we want to access the object itself, not one of the properties. Say, you want to pass the object from the array into a js function as a parameter to decide how it will be rendered, or if you want show a "calculated" property. The key word is...: this.data. this.data has the current object. After it has been rendered, we can access this object with $(this).tmplItem().data.
format javascript date in ISO 8601
There is a solution in StackOverflow:
/\* use a function for the exact format desired... \*/
function ISODateString(d){
function pad(n){return n<10 ? '0'+n : n}
return d.getUTCFullYear()+'-'
+ pad(d.getUTCMonth()+1)+'-'
+ pad(d.getUTCDate())+'T'
+ pad(d.getUTCHours())+':'
+ pad(d.getUTCMinutes())+':'
+ pad(d.getUTCSeconds())+'Z'}
var d = new Date();
print(ISODateString(d)); // prints something like 2009-09-28T19:03:12Z
```But there is already a function for this: toISOString, it came with ecmascript 5. [Unfortunately, not all browsers support this](http://kangax.github.com/es5-compat-table/ "See the best comparision for ecmascript 5 support"), to solve this problem, we can provide our own prototype function for Date if it doesn't exist:
if (!Date.prototype.toISOString) { Date.prototype.toISOString = function() { function pad(n) { return n < 10 ? ‘0’ + n : n } return this.getUTCFullYear() + ‘-’ + pad(this.getUTCMonth() + 1) + ‘-’ + pad(this.getUTCDate()) + ‘T’ + pad(this.getUTCHours()) + ‘:’ + pad(this.getUTCMinutes()) + ‘:’ + pad(this.getUTCSeconds()) + ‘Z’; }; }
javascript Module pattern
Want organize your js code in a kind of namespaces, or modules, then use the module pattern. I’ll take the dummy example for getting the current anchor. Let’s look how it would be if the prototype based approach is used:
var Contoso.Utils = function() {};
Contoso.Utils.prototype = {
getCurrentAnchor: function() {
var url = window.location;
var anchor=url.hash; //anchor with the # character
var anchor2=url.hash.substring(1); //anchor without the # character
return anchor2;
}
};
var util = new Contoso.Utils();
var anchor = util.getCurrentAnchor();
```The [prototype pattern](http://weblogs.asp.net/dwahlin/archive/2011/08/01/techniques-strategies-and-patterns-for-structuring-javascript-code-the-prototype-pattern.aspx) reminds the classic object oriented programming. Now, how would it look in the module pattern:
var Contoso = Contoso || {}; Contoso.Utils = function() { //private var invokeCounter = 0; var logInvokeCounter = function() { invokeCounter++; console.log(“invoked: " + invokeCounter + " times”); } //public return { getCurrentAnchor: function() { var url = window.location; var anchor=url.hash; //anchor with the # character var anchor2=url.hash.substring(1); //anchor without the # character logInvokeCounter(); return anchor2; } } }(); var anchor = Contoso.Utils.getCurrentAnchor();
Get the current anchor in javascript
To get the current anchor, we can use hash property::
var url = window.location;
var anchor=url.hash; //anchor with the # character
var anchor2=url.hash.substring(1); //anchor without the # character
Pass arguments from/to Modal Dialog
To pass arguments from a ModalDialog is easy. Provide some buttons and invoke close function:
SP.UI.ModalDialog.commonModalDialogClose(SP.UI.DialogResult.OK, someValue);
```The first argument is result, [it is a enumeration with three alternatives](http://msdn.microsoft.com/en-us/library/ff409060.aspx): cancel, invalid and OK. The value you pass back to the main window can be a simple string, or a complex javascript object. In this example I'll create a html element which is hidden (id="modal-form" [class="s4-die"](/2011/10/14/s4-die/)):
Pass arguments to Modal Dialog and use it
In options you pass to SP.UI.ModalDialog.showModalDialog you can define args property. It can be any object with any complexity.
Get current user and handle a success callback
In my previous post I needed the accound id of the current user for posting new list items. To retrieve the id, we can push this to the client from the code behind, or get the current user using Client Object Model. To provide a more generic way we can write a js function which get the current user. But we must even provide some callback functionality, otherwise we don’t know if the operation was successful or not. Let’s be inspired by success and error properties in $.ajax:
jQuery tmplItem and no ids
tmplItem() works even without ids. To get the current data:
$(this).tmplItem().data;
```If you want to remove, just invoke the ajax and remove with [$.parents](http://api.jquery.com/parents/):
$(this).parents(“li”).remove();
##### Updating data inside tmplItems
If you want to achieve some fancy dependency tracking, consider [knockout.js](http://knockoutjs.com/). But if you just want to update the data object inside a tmplItem, just change the object and call update:
var t = $(this).tmplItem(); var obj = t.data; obj.Address = “hello avenue”; t.update();
Update list items with listdata.svc
In one of my previous posts I showed how to retrieve data from listdata.svc with jQuery $.getJSON method. Getting data is very simple, listdata.svc provides a powerful restful interface with filtering, expanding and other features. Read the best and short introduction to listdata.svc by Suneet Sharma or a more detailed and technical article about filters, functions and operators by Mike Flasko at Microsoft with short examples here. Now back to listdata.svc in the SharePoint environment. Corey Roth provides a good images and sample results. For REST the “http verbs” are very important: GET, POST, PUT, DELETE.. SharePoint RESTful interface defines these verbs like that:
The cleanest auto resize for a textarea
The cleanest way to auto-resize a textarea while typing (like wall post on Facebook) is George Papadakis solution. It uses only standard javascript and provides eventlisteners for IE (attachEvent) and other browsers (addEventListener): [sourcecode language=“javascript”] window.onload = function() { var t = document.getElementsByTagName(’textarea’)[0]; var offset= !window.opera ? (t.offsetHeight - t.clientHeight) : (t.offsetHeight + parseInt(window.getComputedStyle(t, null).getPropertyValue(‘border-top-width’))) ; var resize = function(t) { t.style.height = ‘auto’; t.style.height = (t.scrollHeight + offset ) + ‘px’; } t.addEventListener && t.addEventListener(‘input’, function(event) { resize(t); }); t[‘attachEvent’] && t.attachEvent(‘onkeyup’, function() { resize(t); }); } [/sourcecode] Other solutions are <a href=“https://github.com/padolsey/jQuery.fn.autoResize/blob/master/jquery.autoresize.js, jQuery.autogrow, elastic
javascript load callback for UpdatePanel
Using asp:UpdatePanel isn’t so easy with jQuery(document).ready() or jQuery(window).load(). The jQuery selectors can’t find elements which are not shown in the beginning. All other elements which are loaded dynamically are difficult to catch. I found a solution in forums.asp.net. A user called germanz creates an jQuery event listener AjaxReady, he uses the ASP.NET built-in PageRequestManager. If there only few usages of it it can be invoked directly from a PageRequestManager instance:
jQuery UI Datepicker
As an alternative to asp:Calendar we can use the fancy jQuery UI Datepicker:
$(document).ready(function () {
$.datepicker.setDefaults($.datepicker.regional\["sv"\]);
$("#").datepicker({
changeMonth: true,
changeYear: true,
yearRange: "-120:+0"
});
});
```I found this a much simple and best solution for an [birthdate input](http://stackoverflow.com/questions/339956/whats-the-best-ui-for-entering-date-of-birth). We can set [international options](http://stackoverflow.com/questions/1865091/jquery-datepicker-language-problem), [year range](http://stackoverflow.com/questions/269545/jquery-datepicker-years-shown), [year](http://stackoverflow.com/questions/3164898/jquery-ui-datepicker-next-and-previous-year) and [month navigation](http://jqueryui.com/demos/datepicker/dropdown-month-year.html). Other options I have tried are asp:Calendar, ajaxtoolkit:CalendarExtender and DateJs. jQuery UI is the most simple much more than datepicker and works smoothily with SharePoint.
Push a copy of an object to client
To reduce postbacks and database calls, a copy of the current object(s) can be pushed down to the client in JSON format. Say a webpart renders information about a person, another webpart shows related information which is retrieved dynamically (like web services). Instead of getting the current person from the database in the second webpart again, we can reuse the same person object from the first webpart. To do so we must provide a DataContract for the Person class:
json serializer in Sharepoint
There is a very handy JSON lib for serializing javascript objects. It is hosted on github under douglas crockford. Download json2.js and serialize with JSON.stringify function: EDIT: There is actually this function in core javascript. It exists since javascript 1.7 and ecmascript 5. So you don’t have to add anything to get this functionality:
var t = { name: "dev", city: "new york" };
JSON.stringify(t);
```There are actually built-in goodies for serializing javascript objects in [ASP.NET](http://msdn.microsoft.com/en-us/library/bb310857.aspx): Sys.Serialization.JavaScriptSerializer.serialize
var t = { name: “dev”, city: “new york” }; Sys.Serialization.JavaScriptSerializer.serialize(t);
Load Profile Image with javascript
See a great post in “Learning Sharepoint” with an example how to get a picture of user with Client Object Model and javascript.
jQuery timeago and the localization
If you have used SPUtility.TimeDeltaAsString you must know how useful it is. There is also the jQuery plugin that can perform counting of time deltas and (!) translate it. jQuery timeago is available for many languages, Swedish among others:
// Swedish
jQuery.timeago.settings.strings = {
prefixAgo: "för",
prefixFromNow: "om",
suffixAgo: "sedan",
suffixFromNow: "",
seconds: "mindre än en minut",
minute: "ungefär en minut",
minutes: "%d minuter",
hour: "ungefär en timme",
hours: "ungefär %d timmar",
day: "en dag",
days: "%d dagar",
month: "ungefär en månad",
months: "%d månader",
year: "ungefär ett år",
years: "%d år"
};
```The code is hosted on [Github](https://github.com/rmm5t/jquery-timeago). In order the time deltas to be localized in SharePoint a ScriptLink has to be used:
<SharePoint:ScriptLink ID=“timeagoLanguage” runat=“server” Language=“javascript” Name=“jquery.timeago.lang.js” Localizable=“True” LoadAfterUI=“True” OnDemand=“False” ></SharePoint:ScriptLink>
Filtering in javascript
The simplest and the best way to filter an array is to extend the Array.prototype as described here:
if (!Array.prototype.filter) {
Array.prototype.filter = function (func) {
var len = this.length;
if (typeof func != "function")
throw new TypeError();
var res = new Array();
var thisp = arguments\[1\];
for (var i = 0; i < len; i++) {
if (i in this) {
var val = this\[i\];
if (func.call(thisp, val, i, this))
res.push(val);
}
}
return res;
};
}
```Then let's filter on [titles](/2011/11/21/sorting-dates-in-javascript/ "See an example for Sorting with Titles"), which [start with](http://stackoverflow.com/questions/646628/javascript-startswith "See the solution for startsWith in javascript on Stackoverflow") "N":
function startsWithN(element, index, array) { return element.toLowerCase().indexOf(“n”) == 0; }
Extend an event in javascript
If you use jQuery, you don’t need it. But if you for some reason must use javascript you must beware of adding events. The most dangerous is window.onload. Consider this scenario:
function doSomethingGreat() {};
window.onload = doSomethingGreat;
```It works fine if you are the only person who writes window.onload handler. But on such platforms like SharePoint you can't know which events exist. And if you just write **window.onload = doSomethingGreat;** you override all other window.onload events. Again, in jQuery you have nothing to worry. jQuery(window).load(doSomethingGreat) will just add your event, not override. In this post I'll show how to extend an event handler the pure javascript way. We have to create our own function for adding event handlers. First the old events have to be temporary saved and then the new event has to be added. [Like this](http://jsfiddle.net/mirontoli/cnN6s/):
function addOnclick(elem, func) {
var old = elem.onclick;
if (typeof elem.onclick != ‘function’) {
elem.onclick = func;
} else {
elem.onclick = function () {
if (old) {
old();
}
func();
};
}
}
Sorting Dates in javascript
To sort an array in javascript, just run sort():
array = \["skåne", "blekinge", "halland"\];
array.sort();
```To [perform a more intelligent sorting](http://stackoverflow.com/questions/3859239/sort-json-by-date "See the original answer in stackoverflow") we can define our sorting logic. What if an array has objects with different properties? For example, an object has title and lastupdated. We want to sort on lastupdated. Just create a function for this with two parameters:
function custom_sort(a, b) { return new Date(a.lastUpdated).getTime() - new Date(b.lastUpdated).getTime(); }
$.getJSON, jQuery.tmpl and _vti_bin
Javascript is very fast, responsive and unburdens the cpu at the server. Here I show a little example how to use jQuery.getJSON, jQuery.tmpl (wonderful plugin for rendering repeating data, repo hosted on Github) and REST-based service listdata.svc from /_layouts/_vti_bin/ folder. For this example I created a generic list “Contacts”, added two text fields Name and Phone. Add some phone numbers and try to go to /_vti_bin/ListData.svc/Contacts If you get 404-error, install a ADO.NET Data Services v1.5 CTP2, as described at dotnetmafia. If you want to know more about how to sort and filter, skip and limit results, read more at nothingbutsharepoint. If you encounter problems, follow Michaël’s blog post and download and install Windows6.1-KB976127-v6-x64.msu (if you have Windows Server 2008 R2), or NDP35SP1-KB976126-v2-x64.exe (if you have Windows Server 2008). After installing the version of the System.Data.Services.dll file is 3.5.30729.5004 (Windows Server 2008 R2), and 3.5.30729.4466 (Windows Server 2008). Allright, the remainder is pure javascript. In order to get it working you have to run the script from the same domain, meaning you can’t run javascript to retrieve the data from a html-file from your home folder. Create a webpart and add it to your page.
Remove links to user profiles on list with javascript
Well, if you need remove links to user profiles, you can iterate all td-elements with class ms-vb-user using jQuery each function and remove a elements. Here is a little script:
$(document).ready(function() {
$(".ms-vb-user a").each(function() {
var text = $(this).text();
var span = document.createElement("span");
var user = document.createTextNode(text);
span.appendChild(user);
var parent = $(this).parent()\[0\];
parent.removeChild(this);
parent.appendChild(span);
});
});
```EDIT 2012-02-05 A much more better way to do it is [to use replaceWith in jQuery](http://stackoverflow.com/a/2409163/632117 "See a similar question and an answer on StackOverflow"):
$(".ms-vb-user a").each(function() { $(this).replaceWith(this.childNodes); });
Reset favicon cache
Favicon is one of the hardest. Ctrl-F5 doesn’t help. You can of course see the source, find the location of the favicon, click on it (if you use Firefox or Chrome), otherwise copy the url and paste it in the address bar. When you load it separately, the favicon cache is renewed. It works. But if you want to make it easier for your users, set a version to your favicon file in the masterpage:
Go back in javascript
Add link for “Go Back” in javascript (inspired by Webmasters tips):
<a href="javascript:location.href=document.referrer;">Back</a>
```If you have access to the code behind you can [do the same](http://www.beansoftware.com/ASP.NET-FAQ/Referrer-URL.aspx) with:
Request.UrlReferrer.ToString()
```If you want to go to site collection root, it is simple, too: <SharePoint:SPLinkButton runat="server" NavigateUrl="<% $SPUrl:~SiteCollection/%>">Start</SharePoint:SPLinkButton>
Auto-resize the main container in master page
If you have a master page with fixed size (perhaps in a centered layout). Here is a simplistic js-script to auto-resize:
$(window).load(function(){
$wider = false;
$pagecontainer = $("#pagecontainer");
$elementsToCareAbout = $("#ctl00\_MSO\_ContentDiv > \*, #ctl00\_MSO\_ContentDiv table")
$elementsToCareAbout.each(function(){
if($(this).width() > $pagecontainer.width())
{
$wider = true;
}
});
if ($wider) $pagecontainer.width(1200);
});
Any improvement ideas and suggestions are more than welcome.
Check if an html element is hidden using jQuery
Well, sometimes we need to calculate width and so on. In my next post I will write about how to fix auto-resize on fixed sized master pages. But now: a very nice stuff: how to check if an element is hidden or not:
$("#s4-leftpanel").is(":visible")
```It is a pure poetry. It reminds me of the beauty of [symbols in Ruby](http://rubylearning.com/satishtalim/ruby_symbols.html).
MongoDB shell, learn directly in browser
Are you also curious about NoSQL databases. Well, MongoDB is one of the most known ones. MongoDB has a javascript syntax (json), I like it. Try out the interactive shell at the mongodb site.
Quickstart on Ubuntu
To test it on Ubuntu, just install an existing apt-package:
sudo apt-get install mongodb
Good pattern for javascript files
SP.js exists in two variants in debug mode and in modified. When you develop it is better to use debug mode. When it goes to production it is better to use minified files. The same you can do with your files. Wictor Wilen explains how to do minify your custom javascript files. I think it is a good pattern to create javascript files and call them something-something**.debug.js**. Then when you are done, run the custom tools to minify them.
Show html in ModalDialog
We can use ModalDialogs to show not only pages, but some html:
var htmlElement = document.createElement('p');
var helloWorldNode = document.createTextNode('Hello world!');
htmlElement.appendChild(helloWorldNode);
var options = {
html: htmlElement,
autoSize:true,
allowMaximize:true,
title: 'Test dialog',
showClose: true,
};
var dialog = SP.UI.ModalDialog.showModalDialog(options);
Resize image with jQuery to fit the div
There are many interesting jQuery plugins for resizing and cropping of images. Among them are jrac and image scale. I have tested the latter: It works very fine
$(window).load(function() {
var $imgContainer = $("#layout-news-image");
var $newsImg = $("#layout-news-image img\[rel!='sp\_DialogLinkIgnore'\]");
$imgContainer.css("width", $imgContainer.parent().width());
if ($newsImg.length > 0) {
if ($newsImg.width() < $imgContainer.width()) {
$imgContainer.width($newsImg.width());
}
if ($newsImg.height() < $imgContainer.height()) {
$imgContainer.height($newsImg.height());
}
$newsImg.imgscale({
parent : '#layout-news-image',
center: "true",
scale: "fill"
});
}
});
```This script checks if the original image is lesser than container div and doesn't resize if it is so. **#layout-news-image img\[rel!='sp\_DialogLinkIgnore'\]** means that do not resize if there is a hidden image with rel="sp\_DialogLinkIgnore". See the [jQuery selectors](http://api.jquery.com/category/selectors/) for more info. This script can be improved by adding window resize event in javascript. I use **$(window).load** instead of the usual _$(document).ready_ because [ready-function in jQuery runs when DOM is loaded, if the page is not cached it happens before the image is loaded](http://web.enavu.com/daily-tip/daily-tip-difference-between-document-ready-and-window-load-in-jquery/). $(document).ready doesn't work.
## Comments from Wordpress.com
####
[sdfsdf](http://sdsdfsdf "sdfsdf@ssdf.sdd") - <time datetime="2012-06-28 19:28:51">Jun 4, 2012</time>
doesn't work: it's just squeeze the picture. No examples included == no possibility to check.
<hr />
####
[Anatoly Mironov]( "mirontoli@gmail.com") - <time datetime="2012-11-05 10:06:01">Nov 1, 2012</time>
Thank you Alejandro for the awesome js lib and sharing it. I will absolutely recommend it.
<hr />
####
[Alejandro Emparan (@krc_ale)](http://twitter.com/krc_ale "krc_ale@twitter.example.com") - <time datetime="2012-11-02 20:21:55">Nov 5, 2012</time>
I wrote a jQuery plugin for that: https://github.com/karacas/imgLiquid
<hr />
Show a presence bubble
There is no built-in sharepoint control for the presence bubble. If you want to add this functionality on your pages you have to add it as html. Here is a sample:
private static int \_COUNTER = 0;
private const string PresenceBubble =
"<a class='ms-imnlink' href='javascript:;'>" +
"<img width='12' height='12' id='imn\_pawn\_{0}' onload=\\"IMNRC('{1}')\\" alt='My SID' " +
"src='/\_layouts/images/imnoff.png' border='0' " +
"showofflinepawn='1' sip='{2}'></a> {3}";
private static string FormatUser(SPUser user)
{
\_COUNTER++;
return string.Format(PresenceBubble, \_COUNTER, user.Email, user.GetSipAddress(SPContext.Current.Web), user.Name);
}
less.js
Det finns ett intressant projekt som kan hjälpa att strukturera css-filer. Du skriver regler i en kombination av css och javascript. Det omvandlas med hjälp av js till css. Projektet heter less.js, läs mer om detta på sharepointoverflow.
window.onload
Sharepoint ger en annan lösning för window.onload och jQuery(document).ready(function() {}); _spBodyOnLoadFunctionNames.push(‘gerdaRibbonInit’);"
jQuery validation with asp.net
De kan var lite jobbigt att få till jQuery validate att funka ihop med aspnetForm…
$(document).ready(function () {
newsLetterForm = $("#aspnetForm");
newsLetterForm.validate({
onsubmit: false,
rules: {
"<%= emailTextBox.UniqueID %>": {
required: true,
email: true
}
}
});
$("#<%= sendButton.ClientID %>").live("click", function {
var isValid = newsLetterForm.valid();
if (!isValid) {
e.preventDefault();
}
});
});
jQuery validate kräver name på elementen inuti formen. För att ta reda på name, måste man använda Control.UniqueId För att det ska fungera måste du köra preventDefault()
Vänta tills sp.js laddats
Här är en funktion som man kan använda för att vänta till sp.js laddats och köra sin funktion:
ExecuteOrDelayUntilScriptLoaded(myjsfucntion, "sp.js");
Eftersom det kan vara så att sp.js laddas med lazy loading:
<SharePoint:ScriptLink Name="SP.js"
runat="server" OnDemand="true"
Localizable="false"
Uppdatera web med js
Här är ett litet exempel:
function updateTitle() {
var ctx = new SP.ClientContext.get\_current();
this.web = ctx.get\_web();
web.set\_title('Examensarbete 2011');
this.web.update();
ctx.executeQueryAsync(
Function.createDelegate(this, this.onUpdate),
Function.createDelegate(this, this.onFail)); }
function onUpdate(sender, args) {
alert('title updated');
}
function onFail(sender, args) {
alert('failed to update title. Error:'+args.get\_message());
}
Registrera javascript i feature
Om det inte passar att javascript i masterpage eller egen webpart, registrera det som customaction och aktivera feature. Läs mer här. Här är ett exempel:
<CustomAction
Location="ScriptLink"
ScriptSrc="~sitecollection/\_layouts/MyProject/awesome.js"
Sequence="101">
</CustomAction>
Aktivera intellisense för javascript i VS
Det finns ett sätt att aktivera intellisense för javascript i VS: Klistra in det i ditt js-fil eller aspx:
/// <reference name="MicrosoftAjax.js" />
/// <reference path="file://C:/Program Files/Common Files/Microsoft Shared/Web Server Extensions/14/TEMPLATE/LAYOUTS/SP.core.debug.js" />
/// <reference path="file://C:/Program Files/Common Files/Microsoft Shared/Web Server Extensions/14/TEMPLATE/LAYOUTS/SP.debug.js" />
```Men tyvärr [kommer det inte funka om du har installerat Resharper](http://devnet.jetbrains.net/thread/297493). Eller lägg till vanliga script-taggar som beskrivet i boken Sharepoint As Developer Platform:
<asp:PlaceHolder ID=“PlaceHolder1” runat=“server” Visible=“false”> </asp:PlaceHolder>
javascript API i Sharepoint
Det är supersmidigt. Här är ett exempel:
function createAnnouncement(title, body) {
var ctx = new SP.ClientContext.get\_current();
var list = ctx.get\_web().get\_lists().getByTitle('Meddelanden');
var itemCreationInfo = new SP.ListItemCreationInformation();
this.newListItem = list.addItem(itemCreationInfo);
this.newListItem.set\_item("Title", title);
this.newListItem.set\_item("Body", body);
this.newListItem.update();
ctx.executeQueryAsync(
Function.createDelegate(this, this.onSucceededCallback), Function.createDelegate(this, this.onFailedCallback));
}
function onSucceededCallback(sender, args) {
SP.UI.Status.addStatus("Info", "It worked!",true);
}
function onFailedCallback(sender, args) {
SP.UI.Status.addStatus("Info", "It didn't work!",true);
}
Comments from Wordpress.com
westerdaled - Feb 0, 2013
Validera din form på klienten
Det finns ett mycket bra jQuery-tillägg som kan validera din data i en formulär på ett enkelt sätt. Se en demo. Referera till validate.js och ange rätt css-klasser på dina inputs: “required”, “error”, “url”, “valid”. Mycket smidigt.
cloud9 web ide
Skapa javascript-appar i din webbläsare. Mycket smidigt. Direkt kontakt till github.
Ladda jQuery dynamiskt till din sida
Vill du ändra innehåll, testa olika javascript-funktioner på din sida, prova något direkt i webbläsaren (utan att behöva deploya om), så är DevTools i Chrome, eller Firebug i Firefox väldigt bra verktyg. Om du har jQuery på din sida, så är det ännu bättre. Men om du inte har det, så ladda det i efterhand genom att öppna konsolen (Ctrl-Shift-J i Chrome) och kör följande rader kod (klistra in dem på en gång, och tryck på Enter):
Get coordinates from Google Maps
To get longitude and latitude can be tricky at the first time. There are many ways to do this, e.g. getlatlon.com. Good enough, but not so practical if you want to collect many coordinates. You can’t search after street names, you only can scroll and drag. Another way is to use javascript to show the longitude and latitude. See this example. This works in all web browsers.Just find your object in Google Maps and paste this javascript in URL bar: javascript:void(prompt('',gApplication.getMap().getCenter()));
You’ll be prompted the coordinates values. Just be sure the map is centered on your object. There is a third, even better way. Use javascript, but don’t be annoyed with prompts. In Chromium (or Google Chrome) navigate to maps.google.com find your object, open the Console in DevTools (press Ctrl-Shift-J). Right click on the object → Center the map here In console write: copy ( gApplication.getMap().getCenter().toString() )
So now you can paste it wherever you need it. But the best with it is: you can do whatever you want and need before copying. In LUSites, I save the coordinates another way, first latitude and then longitude. So I can shift values, trim unnecessary stuff and so on. Look at it: var loc = gApplication.getMap().getCenter().toString(); var locTrimmed = loc.replace(/[() ]/gi,""); var locArray = loc.split(","); var newLoc = locArray[1] + "," + locArray[0]; copy (newLoc)
First I get the string of the coordinates. Then I erase the unnecessary stuff: (), blank space. After splitting I shift the longitude and the latitude and create a new string which is copied. Or, we can shorten this: var coordinates = gApplication .getMap() .getCenter() .toString() .replace(/[() ]/gi,"") .split(","); copy (coordinates[1] + "," + coordinates[0]);
The same in one row (to copy-paste): var coordinates = gApplication.getMap().getCenter().toString().replace(/[() ]/gi,"").split(","); copy (coordinates[1] + "," + coordinates[0]);
To avoid to copy this line of code, just press up arrow in the DevTools console.
Undvika postback i button
Äntligen har jag kommit på hur man kan skippa oönskad postback i button. Det finns många olika lösningar. Här är ett intressant inlägg på stackoverflow om det. Men det enklaste sättet är egentligen bara lägga till
return false;
```i onclick... Här är lösningen
using System.Web.UI.HtmlControls;
…
HtmlButton HtmlButtonSendMail;
protected override void CreateChildControls()
{
…
#region Configure Send Email
HtmlButtonSendMail = new HtmlButton();
HtmlButtonSendMail.InnerText = “Send Email”;
HtmlButtonSendMail.ID = “HtmlButtonSendMail”;
string script = “”;
script += “SP.UI.Notify.addNotification(‘Loading..’, false);”;
script += “var options = {”;
script += " url: \"../_layouts/Toolbox/SendMail.aspx\",";
script += " width: 800,";
script += " height: 680,";
script += " allowMaximize: false";
script += “};”;
script += “SP.UI.ModalDialog.showModalDialog(options);”;
script += “return false;”;
HtmlButtonSendMail.Attributes.Add(“onclick”, script);
HtmlButtonSendMail.Attributes.Add(“title”,
“Skicka mail till\r\nde här personerna”);
Controls.Add(HtmlButtonSendMail);
#endregion
…
}
…
protected override void Render(HtmlTextWriter writer)
{
…
writer.RenderBeginTag(HtmlTextWriterTag.Div);
HtmlButtonSendMail.RenderControl(writer);
writer.RenderEndTag();//div
…
}
… other javascript stuff needed to work with your ajax solution
Polymorfi och javascript
En skräckscenario: du använder två javascript-bibliotek. Men de har var sin funktion som har samma namn. Det spelar även ingen roll om antalet inparametrar är olika. Så det blir samma sak som myfunc(param1, param2) och myfunc(param1). Grejen är att funktionen som laddas sist är den som kommer köras. Katastrof! Men det finns lösningar. Börja läsa här om hur man kan simulera polymorfi i javascript på about.com. Säg vi har en funktion som heter MoveToDate(strdate, ctxid) den ingår i init.debug.js (som används av Sharepoint kalenderwebpart). Sedan har vi något annat javascript-bibliotek som också har MoveToDate(param). Låt oss göra det polymorfiskt. Här är koden:
Felsök på clientsidan med Chrome DevTools
Här är en väldigt bra video som berättar om nya devtools i Google Chrome 10. Den visar 12 tricks hur man kan underlätta felsökning av html, css och javascript. Att kunna ändra html,css och js on-the-fly är faktiskt häftigt. För mig som länge har använt Firebug i Firefox (som nu inte funkar på FF4 RC) känns devtools väldigt bra. [youtube http://www.youtube.com/watch?v=nOEw9iiopwI&w=530&h=335]
Comments from Wordpress.com
Ändra utseendet på sidan direkt i webbläsaren « Sharepoint. Kunskap. Upptäckter på resan. - Mar 1, 2011
Använd inbyggd ModalDialog
Vill du visa någon formulär, eller längre information kan du använda en snygg (snygg och snygg?) ruta som är default i Sharepoint. Den är i alla fall användbar. Här är ett litet enkelt exempel, för att illustrera:
var options = {
url: "http://sverigesradio.se",
width: 800,
height: 600,
allowMaximize: false
};
SP.UI.ModalDialog.showModalDialog(options);
Det finns även möjlighet att ha OK-knappen, alltså som alert i javascript. Kolla den här länken.
Visa en popup-ruta
Visst är det fint med en formulär eller ruta som dyker upp medan ursprungssidan blir mörklagd. I grunden så ändras opacity på hela sidan, blir mörkare. En iframe med högre z-index dyker upp. I den iframe finns en annan sida. Hur gör man för att ta fram den rutan? Här berättar jag lite om det:
javascript i Webpart
Här är en bra länk hur man kan använda javascript: http://dotnetslackers.com/articles/aspnet/JavaScript_with_ASP_NET_2_0_Pages_Part1.aspx
this.Page.ClientScript.RegisterStartupScript(this.GetType(),
"ButtonSendMailConfirm\_Click",
"alert('mail skickat!')", true);