TexasSwede
texasswede@gmail.com
  • About this blog
  • My Website
  • My Resume
  • XML Export Tool
  • Photos

Category Archives: Javascript

Free Software – Password Reset for Notes/Domino

Posted on September 24, 2014 by Karl-Henry Martinsson Posted in Administration, Bootstrap, HTML/CSS, IBM/Lotus, jQuery, Notes/Domino, Open Source, Software 7 Comments

Earlier this year I was asked to research some alternatives for a web-based password reset function at my work. One of the larger support burdens are users who forget the passwords, especially in the first few days after changing it. We have a 90 day password lifespan, then a new password need to be picked. Some users wait until the last minute, which usually is Friday afternoon right before they go home, making it very likely that they will forget the new password over the weekend. Another big group is auditors, who may come in every 6 months or so, and by then their passwords have of course already expired.

I first looked at some COTS solutions from HADSL (FirM) and BCC (AdminSuite). They were both very competent, and in addition have several other functions that I really would like to have in my environment (like synchronization between Domino Directory and Active Directory). However, as my company is in a cost saving phase, I was asked if I could build something myself, so I played around a little, and came up with a small and simple application.

The application contains two web pages. The first page (Setup) is where the user will setup the security questions used for password recovery as well as entering an external email address that they have access to even if locked out from the Domino account at work. This page is protected by regular Notes security, so the users need to set this up before they lose access to their account.

The second page (Request)is where the user can request the password to be reset. After entering their Notes name, the user is presented with one of the security questions. If the question as answered correctly, the user can now enter a new password. If the question is wrong, another of the questions is presented to the user. I am also using regexp to make sure that the password match the requirement our organisation have for password strength.

Both pages are built using Bootstrap (v3.2.0),  jQuery (v1.11.0), and for the icons I use Font Awesome (v4.2.0), all loaded from BootstrapCDN. I also use a few local CSS and Javascript files to handle older versions of Internet Explorer. The process steps were created using code by jamro and you can find the code here. By the way, Bootsnipp is a great resource to avoid having to invent the wheel again. There are hundreds of free snippets of code there to build neat Bootstrap functionality.

When the user fill out and submit the setup page, a document is created in a Notes database. When the user need to reset the password, the security questions and answers are retrieved from that document. To prevent unauthorised access to the Notes documents, they use Readers fields to prevent them from being visible to anyone but the signer of the agents running on the server.

This application can of course be updated with more functionality. Instead of allowing the user to pick a password, one could be generated by the server and sent through email to the address entered during setup. There are probably other things that can be done to adapt this application to the needs of your organization. And you probably want to change the logo on the pages to fit your organisation.

You can download the application here. It is licensed under Apache 2.0. I will try to get it up on OpenNTF.org soon as well.

Read the “About” page for instructions on installation and setup, as well as full license and attribution. Enjoy!

jQuery – A flexible way to show/hide sections

Posted on August 27, 2014 by Karl-Henry Martinsson Posted in Javascript, jQuery, Web Development Leave a comment

Yesterday Stephen Gainer blogged about a small Javascript problem he had.

Brilliant!  I gave my customer exactly what he wanted!  No muss no fuss!  I’m sure you see where I’m going with this.  As soon as this was done, my customer came back to me and said he needed four more of these.

My solution, which is terrible, was to duplicate the above four more times (me2Show, me2Hide, me3Show, me3Hide and on and on and …..)  Now I realize how stupid this is, but remember how I said above that there are certain simple things that I never really learned because I never had to?  Well this is one, and this is where I would like YOUR help!

I know there has to be some way to loop through all of my element ID’s with a simple piece of JavaScript, but I can’t for the life of me figure out how to do that.  Can anyone help me out here?

I commented on Stephen’s post and suggested that he use jQuery to easily loop though all elements with a specific class and add a listener function to them to detect a click. Since it is hard to get all information into a comment, I decided to post a simple code sample here instead. My code is easy to expand on, e.g by adding more sections.

There are of course many different ways to do this. You can of course use .toggle(), but I prefer to have better control of when to hide and show the sections. You can break out the lines $(“.mySection”).hide(); into a separate function and call it from the two locations. This is of course not saving anything in this particular code sample, but in more complex code it would make sense to break down the code into separate functions if they are called from multiple lines.

Hopefully this code will help someone, or inspire someone to start playing with jQuery. I like jQuery, as it easily integrates with classic Domino web applications, and even can be used with Xpages.

<html>
<head>
    <title>jQuery hide/show</title>
	<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script> 
	<script>
		$(document).ready(function () {
		// Hide all sections when the page is first loaded
		$(".mySection").hide();
		// Setup all elements with class "myButton" to react on click
		$(".myButton").click( function() {
			// Check if the section is already displayed
			if ($(this).html()=="Hide") {
				// Hide the current section
				var sectionID = $(this).attr("data-showsection");
				$("#"+sectionID).hide();
				// Set the button label to "Show"
				$(this).html("Show");
			} else {
				// Hide all sections, using the class mySection
				$(".mySection").hide();
				// Set all button labels to "Show"
				$(".myButton").html("Show");
				// Show the section we want to display
				var sectionID = $(this).attr("data-showsection");
				$("#"+sectionID).show();
				// Set the button label to "hide"
				$(this).html("Show");
			}
		});
	});	
	</script>
</head>
<body>
    <button id="btnOne" class="myButton" data-showsection="sectionOne">Show</button>
    <div id="sectionOne" class="mySection" data-btnID="btnOne">This is the 1st section.</div>
    <br>
    <button id="btnTwo" class="myButton" data-showsection="sectionTwo">Show</button>
    <div id="sectionTwo" class="mySection" data-btnID="btnTwo">You are now seeing the 2nd section.</div>
    <br>
    <button id="btnThree" class="myButton" data-showsection="sectionThree">Show</button>
    <div id="sectionThree" class="mySection" data-btnID="btnThree">This is the 3rd section.</div>
    <br>
    <button id="btnFour" class="myButton" data-showsection="sectionFour">Show</button>
    <div id="sectionFour" class="mySection" data-btnID="btnFour">The 4th and last section.</div>
    <br>
</body>

Code snippet – jQuery

Posted on March 15, 2014 by Karl-Henry Martinsson Posted in HTML/CSS, jQuery, Lotusscript, Notes/Domino, Programming 6 Comments

This morning I was working on a web application, and I came up with a pretty neat and simple little solution. So I just wanted to share it, in case anyone else need something similar.

I have a webpage with an HTML form. Each input tag has an attribute called notesfield, matching the name of the field in Notes where the value is stored:

<div class="col-md-3">
    <label>First Name</label>
    <input class="form-control" type="text" notesfield="FirstName" value="" />
</div>
<div class="col-md-2">
    <label>Initial</label>
    <input class="form-control" type="text" notesfield="MiddleInitial" value="" />
</div>
<div class="col-md-3">
    <label>Last Name</label>
    <input class="form-control" type="text" notesfield="LastName" value="" />
</div>

Then I created a simple function that will call an agent on the Domino server, which will return all the fields on the specified document as JSON. This function is called after the HTML page is fully loaded.

function loadNotesFields(docunid) {
	var notesfieldname = "";
	$.ajax({
		url: "/database.nsf/ajax_GetNotesFieldFields?OpenAgent", 
		data: {"NotesUNID":docunid},
		cache: false
	}).done(function(data) {
		$('input[notesfield]').each(function() {
			notesfieldname = $(this).attr("notesfield");
			$(this).val(data[notesfieldname]);
		});
	});
}

The function is actually extremely simple, and here you can see the power of jQuery. What I do is to perform an Ajax call to a Domino URL, passing a UNID to the agent to use in the lookup. I set cache to false, to avoid the browser from reusing previously retrieved data (this is a good thing to do if the data retrieved can be suspected to change frequently).

The jQuery .ajax() functions returns the JSON in the data object, and when the call is done, the callback function loops through each input element with an attribute of notesfield, reads the value of said attribute and then sets the value of the input element to the corresponding Notes value.

The only thing left is to write the agent that will return the JSON. It could look something like this:

Dim urldata List As String

Sub Initialize
	Dim session As New NotesSession
	Dim webform As NotesDocument
	Dim db As NotesDatabase
	Dim doc As NotesDocument
	Dim urlstring As String
	Dim urlarr As Variant
	Dim urlvaluename As Variant
	Dim i As Integer
	Dim json As String

	Set webform = session.DocumentContext
	'*** Remove leading "OpenAgent" from Query_String
	urlstring = StrRight(webform.Query_String_Decoded(0),"&")
	'*** Create list of arguments passed to agent
	urlarr = Split(urlstring,"&")
	For i = LBound(urlarr) To UBound(urlarr)
		urlvaluename = Split(urlarr(i),"=")
		urldata(urlvaluename(0)) = urlvaluename(1)
	Next
	Set thisdb = session.CurrentDatabase
	'*** Create content header for return data
	Print "content-type: application/json"
	'*** Get Notes document baed on NotesUIND argument
	Set doc = db.GetDocumentByUNID(urldata("NotesUNID"))
	'*** Build JSON for all fields in document except $fields
	json = "{" + Chr$(13)
	ForAll item In doc.Items
		If Left$(item.Name,1)<>"$" Then
			json = json + |"| + item.Name + |":"| + item.Text + |",|+ Chr$(13)
		End If
	End ForAll
	'*** Remove trailing comma and line break
	json = Left$(json,Len(json)-2)	
	json = json + "}"
	'*** Return JSON
	Print json	
End Sub

Happy coding!

Excellent Bootstrap select plugin with great support

Posted on October 16, 2013 by Karl-Henry Martinsson Posted in Bootstrap, Frameworks, Javascript, jQuery, Web Development 1 Comment

For a Domino-based web application I am currently working on, I needed a nicer looking select box (drop down) than what Bootstrap offers out of the box. I did some searches and found a handful of free ones, most of them pretty good but not exactly what I wanted. Some did not handle different themes, other had additional functionality I did not want/need, etc. I probably been looking for a good alternative for 3 weeks by now.

Then the other day I found an inexpensive plugin at CodeCanyon. Custom Select for Twitter Bootstrap 3 is just $5 if you use it for a public site, or $25 if you use it on a site where you charge the users for access. It’s well worth it. The control is nice and clean, and very easy to use.

Custom Select for Twitter Bootstrap 3

Custom Select for Twitter Bootstrap 3

What really impressed me was how the author of the plugin, Lisa Stoz, fixed an issue I ran into. It was not a bug in the plugin, but I had a need to use custom tag attributes, and the plugin did not support that originally. The next day Lisa had a new version available with that functionality added. She also helped me with some additional questions that I had. I am very impressed with the quick response and the professional support.

I am new to CodeCanyon, but that site seems very nice. It contains a large number of jQuery and javascript plugins, Bootstrap themes and plugins, and much more. There is also a section with WordPress plugins, as well as a separate site for WordPress themes called ThemeForrest. That site also have other themes and templates. If you build websites, but like me is not a graphics genius, ThemeForrest is a great place to find themes or just inspiration for your site. The themes (as are the plugins) are very modestly priced, between $5 and $10 in most cases.

I have just started to scratch the surface of what’s available there, but I already think this is a great resource. The next time I need a plugin for Bootstrap, jQuery or WordPress, I will probably start at CodeCanyon.

Disclaimer: The links above uses an affiliate code, giving me a small credit at the site if you purchase anything.

Bootstrap – An Overview

Posted on August 29, 2013 by Karl-Henry Martinsson Posted in Bootstrap, Frameworks, HTML/CSS, jQuery, Web Development 1 Comment

As I mentioned in a previous article, my boss asked me to write some short summaries of a couple of common web technologies and frameworks. I already wrote about jQuery, and now the turn has come to Twitter Bootstrap, commonly called just Bootstrap.

Twitter Bootstrap is one of the durrent darlings of web developers. It is a CSS framework, and it also includes some Javascript and the icon set GlyphIcons. Personally I use Font Awesome, a larger set (currently 361 icons) of icons compatible with GlyphIcons.

Just like jQuery, you can use Bootstrap from a CDN (Content Delivery Network). There are also several themes available (both free and premium), so you can quickly get a different look than with the default Bootstrap colors. The free themes are also available through a CDN.

With Bootstrap it is very easy to quickly create nice looking websites/applications. There are several ready-made templates on the Bootstrap site, and there are many more available all over the internet.

So what you typically do is to download a template that fit your project, and then start customizing it. A couple of weeks ago I needed to quickly put up a one-page marketing website. I simply downloaded one of the templates, changed the headline, added my content and removed the sign-up button. In 30 minutes I had the site up, and that included writing the inital text. Then I spent another hour or so tweaking and editing the text, but the actual design part took just minutes.

I am also currently working on a larger web application (which I hope to be able to blog about later this fall), and I choose to use Bootstrap there as well. One of the issues I always had in the past was to find a nice menu system to use on my sites, and this actually caused me to abandon the redesign of my personal website for over a year. When I discovered Bootstrap it just took me a few hours to totally revamp my website (including adding some functionality), and I now have a nice and functional menu system. The site also include icons for the menu entries, using Font Awesome.

Bootstrap contains a large number of elements: buttons, dropdowns, tables, labels, input controls, alert messages, a grid system (totally redesigned in Bootstrap version 3), etc. There is plenty of documentation available online, both at the official Bootstrap website and on other sites and forums.

Bootstrap Documentation

So if you haven’t looked at Bootstrap yet, see if it might help you in your next web project!

Some useful jQuery plugins – Part 1

Posted on July 26, 2013 by Karl-Henry Martinsson Posted in Javascript, jQuery, Web Development 4 Comments

I often find cool and (sometimes) useful jQuery plugins, so I want to share a few that I like. I plan to share more in the future.

 

Adipoli jQuery Image Hover Plugin

Includes several different effects to highlight images as the mouse hovers over them.

Adipoli Hover jQuery

http://cube3x.com/demo/adipoli-jquery-image-hover-plugin/

 

jQuery File Upload

File Upload widget with multiple file selection, drag&drop support, progress bars and preview of images, audio and videoy. Supports cross-domain, chunked and resumable file uploads and client-side image resizing.

jquery-upload

https://github.com/blueimp/jQuery-File-Upload

 

iCheck

Customized checkboxes and radion buttons for your forms.

iCheck

http://damirfoy.com/iCheck/

 

Chosen

A plugin to make dropdown-boxes (especially long ones) easier to use. I looked at using this in a project, but ultimately opted to use another plugin, for different reasons. Chosen is still a good tool.

Chosen

http://harvesthq.github.io/chosen/

 

MagicSuggest

This is the plugin I selected over Chosen. The content of the dropdown can be supplied using an Ajax call, returning JSON, and there are a large number of configuartion options. The plugin support filtering and type-ahead, as well as many other useful functions.

MagicSuggest

http://nicolasbize.github.io/magicsuggest/

 

SuperScrollorama

A jQuery plugin for scroll animations.

scrollorama

http://johnpolacek.github.io/superscrollorama/

 

Sticky

Sticky is a jQuery plugin that gives you the ability to make any element on your page always stay visible.

sticky

http://stickyjs.com/

 

jQuery – An Overview

Posted on July 19, 2013 by Karl-Henry Martinsson Posted in Frameworks, Javascript, jQuery, Notes/Domino, Programming, Web Development 1 Comment

Yesterday my boss asked me about a simple overview/tutorial explaining jQuery, Bootstrap and some other web technologies, and how they work together. I decided to also post the result on my blog, so here is the first part. You may recognize some code from a previous blog entry.

jQuery is a currently very popular Javascript framework/library. There are other ones, like Dojo (used by IBM in XPages) and YUI (originally developed by Yahoo), but jQuery is right now at the top when it comes to usage.
jQuery contains the plumbing behind the scene, it contains functions to let the different elements on the page talk to each other and interact, for example trigger events on click or change. It also have functions to hide and show elements (either directly or fade in or out).

One of the big benefits with jQuery is that many functions are much easier to do than in traditional Javascript. It also addresses browser inconsistency, so you don’t have to write different code for Firefox and Internet Explorer. jQuery is Javascript, just packaged in a nice library and simplified. There are also UI components and mobile components, found in jQuery UI and jQuery Mobile. Here are a couple of examples, comparing plain Javascript with jQuery: http://blog.jbstrickler.com/2010/06/vanilla-javascript-vs-jquery/.

jQuery ties into the DOM (Document Object model) of the browser/webpage in a very easy-to-use way. The way elements are addressed is identical to how you do it in CSS, using . (dot) for classes and # for individual elements.

It is not hard to start with jQuery. You do not even have to host the library on your own server, several companies (including Microsoft and Google) host jQuery (as well as other libraries and frameworks) in what is called a CDN (Content Delivery Network). You simply include a line of code in the head section of your HTML, telling the browser to load jQuery from a specified location, and you are all set:

<head>
    <title>Hello, jQuery</title>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script>
</head>

Notice that you don’t use http: or https: at the start of the URL. This is a trick that makes it work both on a http or a https site. However, if you have the code locally in the file system on your computer (like many do before uploading the html file to a server), you must add http: at the beginning for it to load.

Let take a look at our first jQuery example. Below we have a very simple piece of HTML code:

<body>
    <button id="btnSave">Save</button>
    <div id="messageBox"></div>
</body>

What we want to do is that when the button is clicked, a message should be displayed in the div with ID messageBox. That is done with the following piece of jQuery:

$("#btnSave").click( function() { 
    $("#messageBox").html("You clicked the Save button."); 
});

What this do is to replace everything inside the div with the text/HTML code we specify. The second line is the code to execute when the event specified triggers/fires. You can put triggers on almost any element, and depending on the element type, you have different triggers.

The code between the first and last curly brackets { } is being executed when the event is triggered. As you can see, I have the code I showed earlier nested inside this code. What all this does is to wait until the page is loaded, then start creating event triggers.

There are two schools when it comes to where you put the jQuery code. Soem developers prefer to put the code inside <script> tags at the end of the page, after all HTML code and right before </body>. That is is so that the code is not executed until the page (and all the elements on it) have been loaded.

There is another way to do it, as well. This one allows you to put the code in the <script> section of the header section, but it us using jQuery to not load any code until the page has finished loading:

$(document).ready(function () {
    // Setup the element with id "btnSave" to react on click
    $("#btnSave").click( function() {
        // When clicked, set the innerHTML of the element with
        // id "messageBox" to the specified html string.
        $("#messageBox").html("You clicked the Save button.");
    });
});

The important thing is that you can not start put events on elements until they have been created on the page, or nothing will work.

One of the really cool features with jQuery is how easy it is to call another page/url and get something back. This is commonly called Ajax (Asynchronous Javascript and XML), even if it these days more often than not involves getting JSON back instead of XML.
JSON stands for Javascript Object Notation and is a way to package data in the same way you would do if you created a Javascript object. A simple example would look like this:

{
    "FirstName":"Karl-Henry",
    "LastName":"Martinsson",
    "Department:"IT"
}

I can now assign the object to a variable (let’s call it employee) and I can then access the values using regular Javascript:

alert(employee.FirstName + " " + employee.LastName + " works in " + employee.Department);

This ease of parsing makes JSON ideal to use to retrieve values from a data source and display them on a webpage, using Javascript.

Let’s look at a more complicated example. I will call a URL on a server, which will trigger an agent to run to retrieve data from a database and return it in HTML format. This particular URL points to a Domino agent written in Lotusscript, but it could be written in any language supported by the server, like php. For a Domino server, you could also use an XPages agent.

Here is the Javascript code to call a URL and put the content returned into a element on the web page:

function loadProgressNotes(clientunid) {
    $.ajax({
        url: "/mydatabase.nsf/GetProgressNotes?OpenAgent",
        data: {"ClientUNID":clientunid,"Start":"1","Count":"10"},
        cache: false
    }).done(function(returndata) {
        $("#progressNotes").html(returndata);
    });
}

I broke this code out as a separate function, as I need/want to call it in several places. The function just contains one single jQuery function call, .ajax(). I pass a Javascript object to the function, containing the data needed by the function. Many jQuery functions works like this, you pass a Javascript object with arguments instead of passing a large number of individual arguments. You can do the same in Lotusscript, by passing an object or a custom data type to a function instead of numerous arguments.

In this particular case, I am calling .ajax() with 3 arguments. The first one is the URL to go to, the second one is the data to send to that URL, and the last one is a flag telling jQuery to add a cache buster to the end of the URL it constructs. If I would not add that, and I had recently made the same call, I would get old data, as web servers and browsers cache data for performance reasons.
The interesting thing in the code above is perhaps that the data I pass to the URL are itself a Javascript object, so we have a Javascript object where one of the elements is another object.

So what happens is that jQuery performs a call to www.domain.com/mydatabase.nsf/GetProgressNotes?OpenAgent&ClientUNID=something&Start=1&Count=10&_15614312653

The last number is the cache buster, simply a timestamp (milliseconds since midnight, Jan 1, 1970).
The program/agent on the server reads the arguments, performs whatever database lookup it needs, and generates HTML based on that. This HTML is returned by the .ajax() call in data above. The jQuery call is sitting in the background and waiting for the agent to return the data. When this is done, the .done() event is triggered.
In that event, I have written some jQuery code to update the contents of the element called “progressNotes” with whatever the AJAX call returns, in this case some HTML.

It may be more common to have the agent return JSON and parse it, putting different values into different elements on the page. Here is an example, where I go through all the input fields and text area fields on a HTML form and collect the field values/contents for any of the fields having the custom attribute called notesfield. The value of the attribute is the field name in the Domino database, making it very easy to send the data to the correct place on the server.  A typical input field could look like this:

<input notesfield="FirstName" type="text" value="" placeholder="First Name">

Below is the Javascript code, using jQuery to update the record in the Domino database and return JSON that will indicate success or failure, as well as a custom message that will either explain the reason for failure or a message that the document was updated.

var json = new Object();

myjson["ClientUNID"] = "E7A2D820EE10123C86257BAD0056A5F4";

$('input[notesfield]').each(function() {
    fieldname = $(this).attr("notesfield");
    fieldvalue = $(this).val();
    myjson[fieldname] = fieldvalue;
});

$('textarea[notesfield]').each(function() {
    fieldname = $(this).attr("notesfield");
    fieldvalue = $(this).val();
    myjson[fieldname] = fieldvalue;
});

$.ajax({
    url: "/mydatabase.nsf/UpdateClient?OpenAgent", 
    data: myjson,
    cache: false
}).done(function(returndata) {
    if (returndata.status=="Error") {
        $(".errorMessageClient").html("Error! " + returndata.msg).show();
    } else if (returndata.status=="Success") {
        $(".successMessageClient").html("Success! " + returndata.msg).show();
    });
});

As you can see, it is easy to retrieve values from the JSON you get back.

That’s all for now. Next time I will talk about Bootstrap.

Free Bootstrap tools

Posted on June 3, 2013 by Karl-Henry Martinsson Posted in Frameworks, HTML/CSS, Javascript, Web Development Leave a comment

I started using Bootstrap a while back, and really enjoy the fact that I quickly can build a website/application using the framework. But there is always room for improvement. I found some useful tools that will help you, if you are using Bootstrap, to build your pages even quicker.

The first resource is Divshot, a online tool/interface builder where you can design your pages, then get the HTML code and insert it into your page. I just started using it this weekend, but it is a brilliant tool, easy to use and very helpful. It’s currently in free beta, you just need to register.

DivShot editor

DivShot editor

Update: DivShot is now a commercial product, but you can use it for free if you just have one single project.

Bootbox.js is a Javascript library that help you create programatic dialog boxes.

prettyCheckable replaces the standard checkboxes with nicer looking ones.

Datepicker for Bootstrap is (as the name indicates) a datepicker, made to match the Bootstrap look.

jQuery Form Validation is using the Bootstrap stylesshet to make it match the rest of the framework. I haven’t tried this one yet, but it looks very useful.

Fuel UX is another way to extend Bootstrap with additional controls. Very nice looking!

Lavish is a cool online tool that takes an image and creates a color scheme based on it for use in Bootstrap.

 

You can find these tools and more here.

Show and Tell – Dynamic Web Calendar

Posted on November 27, 2012 by Karl-Henry Martinsson Posted in Frameworks, IBM/Lotus, Javascript, Lotusscript, Notes/Domino, Programming, Web Development 1 Comment

In this post in the developerWorks forum, Andy Herlihy is asking about how to create a small calendar that can be embedded into an existing intranet website. As Carl Tyler points out, Andy could simply use Dojo.

However, this is a good example to show some jQuery combined with the power of IBM Lotus Domino.  Lets’ break it down into a few smaller steps.

The first one is to create a Domino web agent that will take the current date and build a calendar for that month. There will be no links or javascript code in the HTML generated, just plain HTML code, with some id attributes to make it easy to address different cells later.

The next step is to create a very simple webpage, with some Javascript to load jQuery and set up the calendar to detect clicks. The clicks will cause another call to the Domino server, this time to a view using RestrictToCategories to only get the entries for the specified date. The entries are returned as HTML and through jQuery they are displayed in a div on the webpage. We also want to add a little bit of CSS to make the calendar pretty. The CSS also lives on the HTML page.

Finally we create the view, it’s associated view template form and a form to create some entries that we can use for testing.

 

Let’s look at the code. First the Domino web agent. It should be pretty self explanatory:

%REM
    Agent WebCalendar
    Created Nov 26, 2012 by Karl-Henry Martinsson/Deep-South
    Description: Returns HTML for a calendar for current month
%END REM
Option Public
Option Declare

Sub Initialize
    '*** Used to get URL params
    Dim session As New NotesSession
    Dim webform As NotesDocument
    Dim urlstring As String
    Dim urlarr As Variant
    Dim urlvaluename As Variant
    Dim urldata List As String
    Dim webservername As String
    '*** Agent specific
    Dim startDate As NotesDateTime
    Dim endDate As NotesDateTime
    Dim i As Integer
    Dim j As Integer
    Dim startweekday As Integer
    Dim thisMonth As Integer
    Dim currDate As Double
    Dim cellclass As String

    Set webform = session.DocumentContext
    '*** Calculate path for this database, for image/icon file references later
    webservername = webform.GetItemValue("Server_Name")(0)
    '*** Remove leading "OpenAgent"
    urlstring = StrRight(webform.Query_String_Decoded(0),"&")

    If urlstring <> "" Then
        '*** Get all params passed to agent
        urlarr = Split(urlstring,"&")
        For i = LBound(urlarr) To UBound(urlarr)
            urlvaluename = Split(urlarr(i),"=")
            urldata(urlvaluename(0)) = urlvaluename(1)
        Next

        If IsElement(urldata("date")) = False Then
            urldata("date") = Format$(Now(),"mm/dd/yyyy")
        End If
    Else
        urldata("date") = Format$(Now(),"mm/dd/yyyy")
    End If

    '*** Get first and last date of current month
    Set startDate = New NotesDateTime(Format$(urldata("date"),"mm/01/yyyy"))
    Set endDate = New NotesDateTime(startdate.DateOnly)
    Call endDate.AdjustMonth(1)
    Call endDate.AdjustDay(-1)

    currDate = CDbl(CDat(startDate.DateOnly))
    startweekday = Weekday(Cdat(startDate.Dateonly))

    '*** HTML header
    Print "Content-type: text/html" ' & CRLF
    Print |<table class="calendar">|
    '*** Create calendar header with weekdays
    Print |<tr><td colspan=7 class="labelMonthYear">| + Format$(CDat(startDate.DateOnly),"mmmm yyyy") + |</td></tr>|
    Print |<tr class="calendarHeader">|
    Print |<td>S</td><td>M</td><td>T</td><td>W</td><td>T</td><td>F</td><td>S</td>|
    Print |</tr>|

    '*** Build rows for the weeks
    For i = 1 To 6
        Print |<!-- Start row | & i & | -->|
        Print |<tr class="calendarRow" id="calendarRow| & i & |">|
        For j = 1 To 7
            If j < startweekday And i = 1 Then
                Print |<td class="emptyCell"></td>|            ' Blank cell before dates
            ElseIf currDate >= CDbl(CDat(startDate.DateOnly)) And currDate <= CDbl(CDat(endDate.DateOnly)) Then
                cellclass = "calendarCell"
                If j = 1 Then
                    cellclass = cellclass + " sundayCell"
                End If
                If j = 7 Then
                    cellclass = cellclass + " saturdayCell"
                End If
                Print |<td class="| + cellclass + |" id="| + Format$(CDat(currDate),"yyyy-mm-dd") + |">|
                Print Day(CDat(currDate))    ' Day number
                Print |</td>|
                currDate = currDate + 1
            Else
                Print |<td class="emptyCell"></td>|            ' Blank cell after dates
            End If
        Next
        Print |</tr>|
        Print |<!-- End row | & i & | -->|
        Print ""
        If currDate >= CDbl(CDat(endDate.DateOnly)) Then
            Exit For
        End If
    Next
    Print |</table>|
End Sub

I am setting the id attribute on the cells to the date in yyyy-mm-dd format, and I will also use that in the categorized view that will later use. Using ISO 8601 for dates have several advantages, in our case particular because we don’t have to worry about the / character that will mess up the URL to the Domino view we will call later.
I also use class attributes on the cells, so CSS can be used to easily format the calendar.
Next we create the web page where we will insert the calendar and also display the entries for any selected day. We load jQuery from Googles CDN, and after the DOM is fully loaded by the browser, we make an ajax call to the Domino server and get the HTML of the calendar back.

After the calendar is retrieved, we use jQuery to trigger a Javascript function on click on any date cell. The code will detect the id of the cell, which just happens to be the date, and then performs another ajax call to teh Domino server, this time to the view to return all entries for the selected date. The data returned is then inserted into a div.

<!doctype html> 
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>Calendar Test</title>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script>
</head>
<script>
    // The following function is executed after page is fully loaded
    $(document).ready(function () {
        var remoteURL = "http://www.texasswede.com/test/calendar.nsf/WebCalendar?OpenAgent";
        var viewURL = "http://www.texasswede.com/test/calendar.nsf/CalendarView?OpenView";
        // Load the calendar HTML from our Domino server using ajax
        $.get(remoteURL,
        function(data) {
                // Update div with id 'ajaxCalendar' with HTML calendar from server
                $("#ajaxCalendar").html(data);
                // Set all calendar cells to trigger on click
                $(".calendarCell").each( function(i) { 
                        // Get the id (i.e. selected day) of the cell clicked
                        var id = $(this).attr("id");               
                        $(this).click( function() {
                        // Call view on Domino server and return entries for selected day
                        $.get(viewURL, { RestrictToCategory: id },
                                function(data) {
                                        // Put list of entries in viewData div
                                        $("#viewData").html(data);
                                 });
                        });
                } );
        });
});
</script>
<style>
    td.calendarCell {
        border: 1px dotted black;
        height: 30px;
        width: 30px;
        text-align: center;
        vertical-align: middle;
    }
    td.emptyCell {
        background-color: #EFEFEF;
        height: 30px;
        width: 30px;
    }
    td.sundayCell {
        background-color: #DDDDDD;
        color: #DD0000;
    }
    td.saturdayCell {
        background-color: #DDDDDD;
    }
    .labelMonthYear {
        font-family: Arial;
        font-size: 12pt;
        text-align: center;
    }
  </style>
  <body>
    <div id="ajaxCalendar"></div>
    <br>
    <div id="viewData"></div>
  </body>
</html>

What’s left to do to get this all to work is to create the following Domino design elements:

  1. A form to use for entering calendar data. I called it “Calendar Entry”, and just put two fields on it, ‘CreatedDate’ (computed for display, using @Now) and ‘Title’ (text field).
  2. A view called ‘CalendarView’, with two columns. The first one is categorized and is displaying the created date in yyyy-mm-dd format, while the second one is displaying the title field and adding an HTML line break after. The view is set to treat content as HTML.
  3. A form called ‘$$ViewTemplate for CalendarView’, set to treat form as HTML. The form only contains an embedded view element, pointing to ‘CalendarView’, and it is set to return data as HTML as well.

This is the formula I used in the first column of the ‘CalendarView’ view:

y:= @Year(CreatedDate);
m:= @Month(CreatedDate);
d:= @Day(CreatedDate);
yyyy:=@Text(y);
mm:=@If(m<10;"0";"") + @Text(m);
dd:=@If(d<10;"0";"") + @Text(d);
yyyy + "-" + mm + "-" + dd

And this is what it looks like when finished:

This is just one example of how you can combine Domino (agents, views and forms) with jQuery in order to integrate Domino based data into your web applications.

Happy coding!

Using jQuery to emulate Notes hide-when

Posted on November 6, 2012 by Karl-Henry Martinsson Posted in Frameworks, Javascript, Notes/Domino, Web Development 1 Comment

We have all built applications in Lotus Notes where we use the value of a checkbox, radio button or dropdown box to show or hide additional fields, like you can see in this clip.

But the hide-when formula will not work this way on the web. The Domino HTTP stack will simply render the page before sending it to the browser, and even if you make a selection in the browser, the hidden section will not display or vice versa.
So what can you do? One easy way is to use jQuery (or Dojo, if you rather fancy that). You can then detect if a checkbox/radio button is clicked on or if a dropdown box is changed. Then you read the value of the button/box and hide/show the content you like.

 

In this example, you can also see that that one of the dropdown boxes actually switch which dropdown box to display next to it, you can see that the available choices are different, in addition to performing the more visible hiding of the last row when recommendations is not set to “n/a”.
So how do you actually do this? It is fairly easy.
First you add a reference to the jQuery library to the HTML Head Content section of the form. Remember that you need to prefix any quote marks with a \ when you put it in as a string. Here I am calling the Google-hosted jQuery library:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script>
Next, remove any hide-when formulas from the form you are going to expose on the web. That is important, since the Domino server will otherwise not render all the HTML you need. Then give each element you want to hide a unique id. You are probably using tables to create the layout you want, then you can use the table cell id to address the element.

 

In this case, I give the cell containing the label the id “ReasonNALabel” and the cell containing the dropdown box the id “ReasonNA”. The field ‘Recommendation’, which is the one where we are detecting the click and if it has the value “n/a” should display the two cells below it, has an id of “Recommendations”.
One more thing, we want to detect the value as soon as the page is loaded, and display/hide the section accordingly. I will break out the code that perform the check of the value and does the hide/show, so I can call one function insted of duplicating the code.
 

$(document).ready( function () {
    // Check value and do initial show/hide after page is finished loading
    refreshRecommendations();
    // Set trigger for click on radio button to call function
    $("input[name='Recommendations']").click( function() {
        refreshRecommendations();
    });
});

function refreshRecommendations() {
    var checked = $('input[name=Recommendations]:checked').val();
    if (checked == "n/a") {
        $("#ReasonNA").show();
        $("#ReasonNALabel").show();
    } else {
        $("#ReasonNA").hide();
        $("#ReasonNALabel").hide();
    }
}

 

If you want to check the value if a checkbox, use  $(“#checkboxID”).is(“:checked”) and to check the value of a dropdown box, use $(“#dropdownboxID”).val(). For the dropdown box, use .change() instead of .click(), otherwise the code is identical.

 

That is it, a few lines of jQuery to duplicate your hide-when functionality on the web.
Bonus tip: If you want the ítems to fade in and out gradually, you can use jQuery for that as well. You just replace .show() with .fadeIn(‘slow’) and .hide() with .fadeOut(‘slow’). Now you get a nice slow (about 1 second) fade effect instead of instant change.
You can also set the duration of the fade in milliseconds instead, for example .fadeIn(500) for a half-second fade. Another neat thing is that you can define a call-back function to execute after the fade is done. Below is an example of that, where one div is faded out in 750 milliseconds. When that is done, another one is faded in (for half a second) and finally a message is displayed when everything is done.
$("#Section1").fadeOut(750, function() {
    $("#Section2").fadeIn(500, function() {
        alert("Done.");
    });
});

Stack Exchange

profile for Karl-Henry Martinsson on Stack Exchange, a network of free, community-driven Q&A sites

Recent Posts

  • Domino 14 is now available
  • Domino 14 Early Access Program
  • Announced: Engage 2024
  • Integrate Node-RED with Notes and Domino
  • Notes and Domino v12 is here!

Recent Comments

  • Theo Heselmans on Announced: Engage 2024
  • Lotus Script Multi-thread Message Box [SOLVED] – Wanted Solution on ProgressBar class for Lotusscript
  • Viet Nguyen on Keep up with COVID-19 though Domino!
  • Viet Nguyen on Keep up with COVID-19 though Domino!
  • Mark Sullivan on Looking for a HP calculator? Look no further!

My Pages

  • How to write better code in Notes

Archives

  • December 2023 (1)
  • October 2023 (2)
  • September 2023 (1)
  • June 2021 (1)
  • April 2021 (2)
  • March 2021 (1)
  • August 2020 (3)
  • July 2020 (2)
  • April 2020 (2)
  • March 2020 (1)
  • December 2019 (2)
  • September 2019 (1)
  • August 2019 (2)
  • July 2019 (2)
  • June 2019 (3)
  • April 2019 (2)
  • December 2018 (1)
  • November 2018 (1)
  • October 2018 (5)
  • August 2018 (2)
  • July 2018 (3)
  • June 2018 (2)
  • May 2018 (1)
  • April 2018 (2)
  • March 2018 (1)
  • February 2018 (2)
  • January 2018 (4)
  • December 2017 (3)
  • November 2017 (2)
  • October 2017 (2)
  • September 2017 (1)
  • August 2017 (2)
  • July 2017 (6)
  • May 2017 (4)
  • February 2017 (1)
  • January 2017 (2)
  • December 2016 (2)
  • October 2016 (3)
  • September 2016 (4)
  • August 2016 (1)
  • July 2016 (2)
  • June 2016 (2)
  • May 2016 (3)
  • April 2016 (1)
  • March 2016 (4)
  • February 2016 (2)
  • January 2016 (4)
  • December 2015 (3)
  • November 2015 (2)
  • October 2015 (1)
  • September 2015 (2)
  • August 2015 (1)
  • July 2015 (5)
  • June 2015 (2)
  • April 2015 (2)
  • March 2015 (3)
  • February 2015 (2)
  • January 2015 (10)
  • December 2014 (1)
  • November 2014 (3)
  • October 2014 (3)
  • September 2014 (13)
  • August 2014 (6)
  • July 2014 (5)
  • May 2014 (3)
  • March 2014 (2)
  • January 2014 (10)
  • December 2013 (5)
  • November 2013 (2)
  • October 2013 (5)
  • September 2013 (4)
  • August 2013 (7)
  • July 2013 (3)
  • June 2013 (1)
  • May 2013 (4)
  • April 2013 (7)
  • March 2013 (8)
  • February 2013 (9)
  • January 2013 (5)
  • December 2012 (7)
  • November 2012 (13)
  • October 2012 (10)
  • September 2012 (2)
  • August 2012 (1)
  • July 2012 (1)
  • June 2012 (3)
  • May 2012 (11)
  • April 2012 (3)
  • March 2012 (2)
  • February 2012 (5)
  • January 2012 (14)
  • December 2011 (4)
  • November 2011 (7)
  • October 2011 (8)
  • August 2011 (4)
  • July 2011 (1)
  • June 2011 (2)
  • May 2011 (4)
  • April 2011 (4)
  • March 2011 (7)
  • February 2011 (5)
  • January 2011 (17)
  • December 2010 (9)
  • November 2010 (21)
  • October 2010 (4)
  • September 2010 (2)
  • July 2010 (3)
  • June 2010 (2)
  • May 2010 (3)
  • April 2010 (8)
  • March 2010 (3)
  • January 2010 (5)
  • November 2009 (4)
  • October 2009 (7)
  • September 2009 (1)
  • August 2009 (7)
  • July 2009 (1)
  • June 2009 (4)
  • May 2009 (1)
  • April 2009 (1)
  • February 2009 (1)
  • January 2009 (3)
  • December 2008 (1)
  • November 2008 (1)
  • October 2008 (7)
  • September 2008 (7)
  • August 2008 (6)
  • July 2008 (5)
  • June 2008 (2)
  • May 2008 (5)
  • April 2008 (4)
  • March 2008 (11)
  • February 2008 (10)
  • January 2008 (8)

Categories

  • AppDev (10)
  • Blogging (11)
    • WordPress (5)
  • Design (5)
    • Graphics (1)
    • UI/UX (2)
  • Featured (5)
  • Financial (2)
  • Food (5)
    • Baking (3)
    • Cooking (3)
  • Generic (11)
  • History (5)
  • Hobbies (10)
    • LEGO (4)
    • Photography (4)
  • Humor (1)
  • IBM/Lotus (178)
    • #Domino2025 (14)
    • #DominoForever (8)
    • #IBMChampion (46)
    • Administration (7)
    • Cloud (7)
    • CollabSphere (9)
    • Community (49)
    • Connect (33)
    • ConnectED (12)
    • Connections (3)
    • HCL (15)
    • HCL Master (1)
    • IBM Think (1)
    • Lotusphere (46)
    • MWLUG (25)
    • Notes/Domino (99)
      • Domino 11 (7)
    • Sametime (8)
    • Verse (14)
    • Volt (3)
    • Watson (6)
  • Life (8)
  • Microsoft (7)
    • .NET (2)
    • C# (1)
    • Visual Studio (1)
  • Movies (3)
  • Old Blog Post (259)
  • Personal (23)
  • Programming (84)
    • App Modernization (11)
    • Formula (4)
    • Lotusscript (47)
    • NetSuite (4)
      • SuiteScript (3)
    • node.js (4)
    • XPages (4)
  • Reviews (9)
  • Sci-Fi (4)
  • Software (24)
    • Flight Simulator (2)
    • Games (4)
    • Open Source (2)
    • Utilities (6)
  • Technology (37)
    • Aviation (3)
    • Calculators (2)
    • Computers (6)
    • Gadgets (7)
    • Mobile Phones (7)
    • Science (3)
    • Tablets (2)
  • Travel (7)
    • Europe (1)
    • Texas (2)
    • United States (1)
  • Uncategorized (16)
  • Web Development (50)
    • Frameworks (23)
      • Bootstrap (14)
    • HTML/CSS (12)
    • Javascript (32)
      • jQuery (23)
  • Prev
  • 1
  • 2
  • 3
  • 4
  • Next

Administration

  • Log in
  • Entries feed
  • Comments feed
  • WordPress.org

Tracking

Creeper
MediaCreeper
  • Family Pictures
© TexasSwede 2008-2014