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

Category Archives: Web Development

Notes and Domino v12 is here!

Posted on June 1, 2021 by Karl-Henry Martinsson Posted in Formula, HCL, Lotusscript, node.js, Notes/Domino, Sametime, Volt, Web Development, XPages Leave a comment

HCL Software is launching the new version of the collaboration platform HCL Domino on June 7, together with the latest version of the meeting platform Sametime. If you already are a customer with entitlement to the products, you can already download them from FlexNet today.

Some of the new features in Domino v12:

  • Support for storing DAOS files in Amazon S3, to offload your own servers
  • Active directory password sync
  • Two-factor authentication and additional enhancements to internet security
  • New mobile capabilities
  • New icons and view list styling options
  • Hide fields or view columns on devices with lower resolution
  • Bootstrap 4 for XPages
  • Support for formula language in DQL queries
  • Aggregate document collections (e.g. from a search) across Domino databases
  • Button in Administrator client to find all groups a user belongs to
  • Enhancements to mail-in databases

And much more. Find out at the launch!

It is not only the Domino server and the Notes client that is being launched. The latest version of HCL’s no-code/low-code development tool Domino Volt is also available, as is a new version of the AppDev Pack that allows node.js developers to work directly with data stored in the Domino NoSQL-database. But wait, there is more!

A very exciting product HCL will present at the launch is Nomad Web, a client for Domino built for the browser with no downloads or plugins required. The client is written in Web Assembly, so it runs native in modern browsers. It can execute formulas and Lotusscript code, everything you can do in the regular client can be done (with a few exceptions like XPages). There has even been new classes added to Lotusscript to access hardware common in mobile devices and laptops, e.g. the camera and GPS. Nomad for iOS and Android has already been released, but with this zero footprint web client it is incredibly easy to deploy existing Domino application without having to convert them to true web applications. They will simply work as-is. This is truly an impressive engineering feat by HCL.

If you haven’t done it yet, sign up for the launch of the new Domino and Sametime on June 7.

Busy, busy – But wait: There is help!

Posted on March 23, 2021 by Karl-Henry Martinsson Posted in #DominoForever, App Modernization, AppDev, Design, Reviews, Software, Web Development 2 Comments

For the last year and a half I have been very busy with different projects, and this blog had to be put on the back burner. And no, despite a number of blog posts about Microsoft Flight Simulator, I have actually not had much time to play it, less than 10 hours since it was released last August. But this leads me to today’s topic: tools that can help you save time.

As a Notes/Domino developer, administrator or power user, you often need to go deeper into the Domino database. This could be tasks like finding and resolving replication contacts, look closer at the fields (including hidden fields) in a document, or quickly locate all documents of a particular type, or matching a particular criteria that you don’t already have a view for. As an administrator you maybe would like to keep several Domino consoles visible side by side, so you can watch what is happening on all your servers at the same time. As a developer, what if you could copy the design of a view or an action bar to numerous other views to make all views look consistent, without having to edit and update every single view manually? Things like that makes your life easier and makes you more efficient, but you don’t have that in the native product.

One set of tools that stands in a class by itself is EZ Suite from Ytria. The EZ Suite tools are extremely powerful, and there is no way I will be able to cover all of them in one blog post. I will focus on some of the functions that have been useful to me, and even with that limitation I have to split this up in multiple blog posts.

The first tool from Ytria I ever tried was scanEZ. We had some issues with a database at my old work (I don’t remember the details anymore), so we purchased a time limited version of scanEZ. I think it was valid for a week, enough for us to salvage the documents in the database. My boss thought the tool could be useful in the future, so he immediately purchased a full license of it for himself. Eventually he purchased a license of EZ Suite for me, and I made frequent use of the tools, both while doing development and server administration, as well as when I had to troubleshoot database issues or replication conflicts.

You can purchase the full suite , or one of several bundles of tools geared to different types of users (developers, administrators or developer with some administration needs). Each tool can also be purchased individually.

The latest version is EZ Suite 20. This version contains a number of new functions and enhancements. Since I haven’t used the tool in the last couple of years, after my license expired, I have not been keeping up with all the new features, but as always Ytria is supporting the latest version of Notes and Domino.
Disclaimer: Ytria generously provided me with a license for the latest version, but I was previously a paying customer, and I have recommended their products for many years.

Let’s start with the first tool from Ytria I was ever exposed to, scanEZ. This tool makes it possible to explore a Domino database in depth, not only the documents but design elements, settings and even deletion stubs (the remains of deleted documents used to delete the document in replicas). Fields can be added, deleted and their content can be changed. You can even change the data type of a field, as well as many other attributes.

In scanEZ you can also look at and modify profile documents and replication conflicts, which often comes in very handy. But there is also a dedicated Conflict Solver tool within scanEZ. It will analyze the database, which can take a little bit of time, but then you can compare the conflict document with the parent and see which fields differs. This may even help you figuring out how the conflict was created, and how you can prevent that in the future.

This only scratched the surface of what scanEZ is capable of. I have not even mentioned the different ways to view and analyze data. You can for example dynamically categorize the documents through drag-and-drop, and even present the data in charts, thanks to the extensive capabilities of scanEZ.

The next tool I want to mention is consoleEZ. The easiest way to describe it is the Domino server console on steroids. You can view multiple consoles simultaneously, and also see a list of the tasks running on them. Your console commands are saved, and you can view them later if you like. It has many features you wish were in Domino Administrator out of the box, and even more features you did not even know you wanted.

You don’t have to be a hard-core administrator to appreciate consoleEZ. It was first released about six years ago, so it is one of the latest additions to EZ Suite. It quickly became one of my favorite tools.

I do quite a bit of modernization of Notes and Domino applications. Often this involves web enabling them, including creating a modern UI using HTML, CSS, and often a framework like Bootstrap. But there are still many Notes databases that works well, and instead of rewriting a lot of the existing logic for the web, a refresh of the Notes client UI is sufficient. This often involves adding a nicer background to the action bars, as well as changes to the views. Just a few small changes can make a huge difference, and make an old application look fresh again.

But even after you come up with a nice, more modern looking design, you have to duplicate it across all the action bars and views in your application. This is where actionBarEZ and viewEZ comes in. Those two tools makes it a breeze to apply a design to many action bars or views or copy the design from one view/action bar and apply it to any view or action bar you want.

Using actionBarEZ you select a number of view, pages or form, and change the properties across all the elements just like you would have done in Domino Designer, but there you can only make the changes on one view, form or page at a time. But the function I found the most useful function is that you can design a nice action bar in one view, then select that design and with the click of one button apply it to any views, forms or pages you like. This has saved me countless hours of work. The functionality of viewEZ is pretty much identical.

Stay tuned for the next part to be published in the next few days.

EZ Suite Ytria

Semantic UI – An alternative to Bootstrap?

Posted on August 30, 2020 by Karl-Henry Martinsson Posted in Frameworks, UI/UX, Web Development 1 Comment

Bootstrap is currently undisputedly the most popular CSS library. I have been using Bootstrap since 2012, starting with version 2.3. The current version is 4.5, with version 5 is under development and expected at the end of this year.

So why is Bootstrap so popular? There are several reasons, but perhaps the most important one is that it is very easy to get started and create attractive webpages, most components you need are available out-of-the-box, and there are  number of different themes to change the visual look of the sites. But perhaps the biggest reason for the popularity is its popularity. There are countless code snippets, samples and plugins available, as well as tutorial and a huge community you can tap into for help. There are currently over 98,000 questions on Stack Overflow for all versions of Bootstrap, and over 21,000 for the latest version.

But Bootstrap is of course not unchallenged. There are a number of other CSS frameworks available today, some more complete than others. One interesting framework I recently found is Semantic UI. It uses simple phrases, called behaviors, to trigger functions. Below is an example with a select box where the code is selecting two values from the list.

$('select.dropdown')
    .dropdown('set selected', ['meteor', 'ember'])
;

<select class="ui fluid dropdown" multiple="multiple" name="skills">
   <option value="">Skills</option>
   <option value="angular">Angular</option>
   <option value="css">CSS</option>
   <option value="ember">Ember</option>
   <option value="html">HTML</option>
   <option value="javascript">Javascript</option>
   <option value="meteor">Meteor</option>
   <option value="node">NodeJS</option>
   </select>

The resulting website looks very similar to one created in Bootstrap, if you use the default theme. One difference you might notice quickly is that the grid system is using 16 as the base, not 12 as Bootstrap does.

Semantic UI also contains several component you will not find natively in Bootstrap. On of them is dividers, which are available in horizontal and vertical variants.

The list component can very easily be configured in a multitude of different ways.

To create the horizontal list, the markup looks like this:

<div class="ui horizontal list">
  <div class="item">
    <img class="ui avatar image" src="/images/avatar/small/tom.jpg">
    <div class="content">
      <div class="header">Tom</div>
      Top Contributor
    </div>
  </div>
  <div class="item">
    <img class="ui avatar image" src="/images/avatar/small/christian.jpg">
    <div class="content">
      <div class="header">Christian Rocha</div>
      Admin
    </div>
  </div>
  <div class="item">
    <img class="ui avatar image" src="/images/avatar/small/matt.jpg">
    <div class="content">
      <div class="header">Matt</div>
      Top Rated User
    </div>
  </div>
</div>

Take a look at Semantic UI, maybe it will come in handy for your next web project!

alternative Bootstrap Semantic UI

HCL Volt – A real life use case

Posted on August 11, 2020 by Karl-Henry Martinsson Posted in AppDev, Domino 11, HCL, Notes/Domino, Programming, Volt, Web Development 3 Comments

The first update to HCL Volt is now available for download. In version 1.0.1 there are a number of improvements, so if you already have Volt installed, get this update from Flexnet. But this post is not about the technical details of Volt. No, it is an example of how I used the product the other day to quickly put together a small application to help with a very specific task.

Last month my wife and I went on a trip to Estes Park in Colorado, where we enjoyed sleeping with open windows, enjoying the fresh cool mountain air. We started talking about getting an RV, to allow us to leave the Texas heat during the summer. My wife started doing some research on different camping trailers, but soon there was too many models, weights, dimensions and features to keep track of easily. I started to create a spreadsheet in Excel to keep track of everything, but a few minutes later I realized I had a much better tool available: HCL Volt.

I started my browser and went to the Volt Application Manager, where I created a new application by importing the Excel spreadsheet I had started on.

Within a few seconds I had the beginning of my application. I added some additional fields, for example to upload images of the floorplans and to store links to the manufacturers webpages with more information.

It took me about 10 minutes to put the whole thing together. I sent my wife the links, and she logged in and started entering data, as she was researching. A little bit later she asked if it would be possible to add some more checkboxes to the list of features I had created. I gave her the access to modify the application, showed her where she needed to go, and she fixed it herself without me having to show her anything. That’s how intuitive Volt is!

We now have a simple but functional tool to record details about any camping trailer we find, and where we can later go back and review the different alternatives.

There is even a built-in summary page where we can see statistics of the different trailers. This is created automatically from the data entered, no code needed. As a matter of fact, I have not written one single line of code in this application.

This is just one example of how you can create a useful application in a few minutes. But don’t take my word for it. Try it yourself for free, no download required!

If you want to get this very affordable add-on product to HCL Domino, contact your HCL Business Partner.

Low Code

Switch between Edit and Read-Only mode on web form

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

A question on Stack Overflow made me remember some code I wrote a few years ago. It allows you switch a form between regular edit mode and read mode, without having to reload the page. It works just like you are used to in the Notes client. So I thought I would post it here on my blog as well.

It is not very complicated. I am using jQuery, but you can of course use plain Javascript if you like. What the code does is to locate all INPUT fields you want to make read-only. It then creates a regular DIV element and set the content of it to the value of the INPUT field. The id and a couple of other attributes are also copied over, then the new DIV is inserted in front of the INPUT field. Finally the INPUT field is deleted.

To make the DIV editable again, the same process is done in reverse.

Below is the jQuery code to make all elements with the data-attribute dominofield read-only. I am using this data-attribute to map input fields to fields in a Domino database. It makes it very easy to create HTML forms and submit them to a Domino database, with one generic agent that will process the Ajax call. The field names and values will be provided in the JSON payload, and the Domino document can then be created or updated and the fields populated with the proper values.

  // Get all input fields used for Domino
  var inputs = $('[data-dominofield]');
  // Process each field
  inputs.each(function() {
    // Build new DIV element
    var input = $(this);
    var div = '<div class="fieldReadOnly" ';
    div += 'data-dominofield="' + input.data('dominofield') + '" ';
    div += 'id="' + input.attr('id') + '">';
    div += input.val() + '</div>';
    // Insert ther new div element in front of input field
    input.before(div);
    // Remove input field
    input.remove();
  });

I also created a fiddle where you can test it yourself.

If you are using Bootstrap, you can also use the readonly attribute and the class .form-control-plaintext to get the same result. This is documented here.

 

CollabSphere 2019 – Submission deadline is closing soon!

Posted on August 17, 2019 by Karl-Henry Martinsson Posted in #DominoForever, #IBMChampion, CollabSphere, Community, HCL, IBM/Lotus, Notes/Domino, Sametime, Verse, Web Development Leave a comment

CollabSphere_2019

The deadline to submit an abstract for sessions at CollabSphere 2019 is tomorrow, Sunday August 18. If you want to speak at the conference, you don’t have much time to act.

So why would you like to speak at CollabSphere? Perhaps your reason is the same as mine was when I started speaking at conferences: I wanted to give back to the community from which I had learned so much over the years. I wanted to share my knowledge with other developers, and perhaps inspire them by showing what could be done with Notes and Domino.

What if you are afraid of public speaking? That is absolutely normal. With practice you get more used to it, and one place where you can practice it in a safe and encouraging environment is at Toastmasters, an international organization focused on public speaking and leadership. There are local Toastmasters clubs all over the world, and you can join at any time.

Even if you are not speaking, you can still register to attend the conference. This year it is held in Boston, close to the HCL office in Chelmsford, and we can expect a lot of exciting news about Notes and Domino 11 (which is due in the end of the year), and perhaps even about Domino 12. This is a can’t-miss conference!

Free Code – Wrapper for searches in NetSuite

Posted on November 24, 2018 by Karl-Henry Martinsson Posted in Javascript, NetSuite, Programming, SuiteScript Leave a comment

About a year ago I wrote a SuiteScript 1.0 class as a wrapper around the search functionality in NetSuite. I have updated the code over time, and I want to share the latest version. Among the new features is support for formulas and search expressions. The class should be backwards compatible with the original version, but in addition you can also pass an object to most functions, instead of passing separate parameters. This makes it more flexible and allows me to add more functionality.

Enjoy!

 

/**
 * Encapsulate NetSuite search functionality in an easy-to-use object for SuiteScript 1.0.
 *  
 * Version    Date            Author           Remarks
 * 1.0        11 Nov 2016     kmartinsson      Initial version
 * 1.5        06 Jul 2017     kmartinsson      Added record type to constructor
 * 2.0        23 Aug 2017     kmartinsson      Added Search2 function, with support for objects and adding multiple columns/filters
 * 2.0.1      01 Sep 2017     kmartinsson      Bug-fixes
 * 2.0.2      01 Sep 2017     kmartinsson      Fixed issue with join not being null, added hasOwnProperty check 
 * 3.0        20 Nov 2017     kmartinsson      Removed v1.x code stream, renamed Search2 to Search
 * 3.0.1      06 Dec 2017     kmartinsson      Added JSDoc style comments, updated comments to new JSDoc style
 * 3.0.2      28 Feb 2018     kmartinsson      Fixed bug in sort key which prevented proper sorting. Added alternative keys.
 * 3.0.3      15 Jul 2018     kmartinsson      Added filter expression support
 * 3.0.4      01 Oct 2018     kmartinsson      Added method removeColumns() for use on (external) saved search
 * 
 */

/**
 * Search object
 * @constructor
 * @param {string} recordtype - Optional NetSuite recordtype (internalid)
 */
function Search(recordtype) {
    this.recordType = null;
    this.columns = [];
    this.filters = [];
    this.filterExpressions = [];
    // Set internal id of saved search to null
    this.internalId = null;
    this.noSavedColumns = false;
    // If record type/ID is supplied, set it now, otherwise default to null
    if (recordtype != null && recordtype != "") {
        this.recordType = recordtype;
    }

    // Helper function to verify the value is empty or null
    function isNullOrEmpty(val) {
        if (val == null || val == '' || val ==[] || val == {}) {
            return true;
        } else {
            return false;
        }
    }

    
    /**
     * Remove all columns included in the search
     * @param none
     * 
     */
    this.removeColumns = function() {
        this.noSavedColumns = true;
    }

    /**
     * Add a column to include in the search
     * @param {object}|{string} column - Object specifying a column to return or string containing columnId
     * @param {string} join - Joined record (internalid) (optional)
     * @param {boolean}|{string} sorting - Sorting (optional)
     *         Options: true = descending, false = ascending, empty/null = no sorting, "yes" (ascending), 
     *         "no", "ascending", "descending" (can be abbreviated "a" and "d" respectively).
     */
    this.addColumn = function(column, join, sorting) {
            var nsSearchColumn = null;
            var paramColName = null;
            var paramJoin = null;
            var paramSummary = null;
            var paramSorted = null;
            // Check if first argument is string or object
            if (typeof column == "string") {
                paramColName = column;
                // Check if second argument is null (for no join)
                if (isNullOrEmpty(join)) {
                    paramJoin = null;
                    // Check if arguent for sorting was provided
                    if (!isNullOrEmpty(sorting)) {
                        paramSorted = sorting;
                    }
                } else {
                    // Check if second argument is boolean, then it is not 'join' but 'sorting'
                    if (typeof join == "boolean") {
                        paramSorted = join;
                        paramJoin = null;
                    } else {
                        paramSorted = sorting;//sorted;
                        paramJoin = join;
                    }
                }
                // Now paramJoin and paramSorted are assigned properly
                if (typeof paramSorted == "boolean") {
                    if (paramSorted == true) {
                        paramSorted = "des";
                    } else {
                        paramSorted = "asc";
                    }
                } else if (typeof paramSorted == "string") {
                    // Get first character of string, in lower case
                    var tmp = paramSorted.slice(0, 1).toLowerCase();
                    // y = ascending sorting, n = no sorting, a = ascending, d = descending
                    if (tmp == 'y' || tmp == 'a') {
                        paramSorted = "asc";
                    } else if (tmp == 'd') {
                        paramSorted = "des";
                    } else {
                        paramSorted = null;
                    }
                }

            } else {
                if (column.hasOwnProperty("name") && column.name != null) {
                    paramColName = column.name;
                } else if (column.hasOwnProperty("columnName") && column.columnName != null) {
                    paramColName = column.columnName;
                } else if (column.hasOwnProperty("columnname") && column.columnname != null) {
                    paramColName = column.columnname;
                } else if (column.hasOwnProperty("column") && column.column != null) {
                    paramColName = column.column;
                } else {
                    throw nlapiCreateError('search.addColumn() - Required Argument Missing', 'The required argument <em>columnName</em> is missing. This argument is required.<br>Received: ' + JSON.stringify(column));
                }
                if (column.hasOwnProperty("join") && column.join != null) {
                    paramJoin = column.join;
                }
                if (column.hasOwnProperty("summary") && column.summary != null) {
                    paramSummary = column.summary;
                }
            }
            nsSearchColumn = new nlobjSearchColumn(paramColName, paramJoin, paramSummary);
            // Check if 'sorted' value exists in object
            if (column.hasOwnProperty("sorted") && column.sorted != null) {
                // Get first 3 characters as lower case
                paramSorted = column.sorted.toLowerCase().substring(0, 3);
            } else if (column.hasOwnProperty("sorting") && column.sorting != null) {
                // Get first 3 characters as lower case
                paramSorted = column.sorting.toLowerCase().substring(0, 3);
            } else if (column.hasOwnProperty("sort") && column.sort != null) {
                // Get first 3 characters as lower case
                paramSorted = column.sort.toLowerCase().substring(0, 3);
            }
            if (paramSorted!= null && paramSorted!="") {
                if (paramSorted == "asc") {
                    nsSearchColumn.setSort(false);
                } else if (paramSorted == "des") {
                    nsSearchColumn.setSort(true);
                } else {
                }
            }
            // Check if 'formula' value exists in object, then add to column object
            if (column.hasOwnProperty("formula") && column.formula != null) {
                nsSearchColumn.setFormula(column.formula);
            }
            // Check if 'functionId' value exists in object, then add to column object
            if (column.hasOwnProperty("functionId") && column.functionId1 != null) {
                nsSearchColumn.setFunction(column.functionId);
                // Push new nlobjSearchColumn into array
            }
            // Check if 'label' value exists in object, then add to column object
            if (column.hasOwnProperty("label") && column.label != null) {
                nsSearchColumn.setLabel(column.label);
            }
            this.columns.push(nsSearchColumn);
            return nsSearchColumn;
        } // end function addColumn


    /**
     * Add multiple columns to include in the search
     * @param {array} columns - array of column objects
     */
    this.addColumns = function(columns) {
            for (var i = 0; i < columns.length; i++) {
                this.addColumn(columns[i]);
            }
        } // end function addColumns

    /**
     * Add a search filter
     * @param {object}|{string} filter - filter object or string containing fieldId
     * @param {string} fieldJoinId - field to use for join (optional)
     * @param {string} operator - operator for filter (optional)
     * @param {string} value - value to filter for (optional)
     */
    this.addFilter = function(filter, fieldJoinId, operator, value) {
            if (typeof filter == "object") {
                var obj = filter;
                var fieldId = obj.field;
                var fieldJoinId = null;
                if (filter.hasOwnProperty("join")) {
                    fieldJoinId = obj.join;
                }
                var operator = obj.operator;
                var value = obj.value;
                // Create filter object
                var nsSearchFilter = new nlobjSearchFilter(fieldId, fieldJoinId, operator, value);
                // Check if 'formula' value exists in object, then add to filter object
                if (obj.hasOwnProperty("formula") && obj.formula != null) {
                    nsSearchFilter.setFormula(obj.formula);
                }
                // Check if 'functionId' value exists in object,then add to filter object
                if (obj.hasOwnProperty("functionId") && obj.functionId != null) {
                    nsSearchFilter.setFunction(obj.functionId);
                }
                this.filters.push(nsSearchFilter);
            } else {
                var fieldId = filter;
                this.filters.push(new nlobjSearchFilter(fieldId, fieldJoinId, operator, value));
            }
        } // end function addFilter


    /**
     * Add multiple search filters
     * @param {array}filters - array of filter objects
     */
    this.addFilters = function(filters) {
            for (var i = 0; i < filters.length; i++) {
                this.addFilter(filters[i]);
            }
        } // end function addFilters

    /**
     * Add filter expression
     * @param {array} expression - array structure describing search expression
     */
    this.addFilterExpression = function(expression) {
        this.filters.push(JSON.parse(expression));
    }

    /**
     * Set filter expression - Replaces any existing filters
     * @param {array} expression - array structure describing search expression
     */
    this.setFilter = function(filterArray) {
        this.filters = filterArray;
    }
    
    /**
     * Set the type of record to search for
     * @param {string} type - internalid of record type to search for
     */
    this.setRecordType = function(type) {
            this.recordType = type;
        } // end function setRecordType


    /**
     * Use an existing saved search as starting point for this search
     * @param {string} internalid - internalid of existing saved search
     */
    this.useSavedSearch = function(internalid) {
        if (!isNullOrEmpty(internalid)) {
            this.internalId = internalid;
            // If internal id of a saved search is provided, load that saved search
            this.savedsearch = nlapiLoadSearch(this.recordType, this.internalId);
        }
    } // end function useSavedSearch


    /**
     * Return search results as a nlobjSearchResult object
     * @param {string} recordtype - Optional NetSuite recordtype (internalid)
     */
    this.getResults = function(recordtype) {
            var results = [];
            if (recordtype != null && recordtype != "") {
                this.recordType = recordtype;
            }
            if (this.internalId != null) {
                // If internal id of a saved search is provided, load that saved search
                var savedsearch = nlapiLoadSearch(this.recordType, this.internalId);
                // Add new filters to saved search filters
                var newfilters = savedsearch.getFilters().concat(this.filters);
                // If existing columns in saved search should not be use, replace then
                var newcolumns = [];
                if (this.noSavedColumns) {
                    savedsearch.setColumns(this.columns);
                    newcolumns = this.columns;
                } else {
                    // Add new columns to saved search columns
                    newcolumns = savedsearch.getColumns().concat(this.columns);
                }
                // Perform the search
                var newsearch = nlapiCreateSearch(savedsearch.getSearchType(), newfilters, newcolumns);
                // 
            } else {
                // Otherwise build the search ad-hoc and set columns and filters
                var newsearch = nlapiCreateSearch(this.recordType, this.filters, this.columns);
            }
            var resultset = newsearch.runSearch();
            // Loop through the search result set 900 results at a time and build an array
            // of results. This way the search can return more than 1000 records.
            var searchid = 0;
            do {
                var resultslice = resultset.getResults(searchid, searchid + 900);
                for (var rs in resultslice) {
                    results.push(resultslice[rs]);
                    searchid++;
                }
            } while (resultslice != null && resultslice != undefined && resultslice.length >= 900);
            return results;

        } // end function getResults

} // end class search
#freecode #netsuite

#DominoForever – Release Day

Posted on October 10, 2018 by Karl-Henry Martinsson Posted in Administration, AppDev, IBM/Lotus, Lotusscript, node.js, Notes/Domino, Web Development 1 Comment

Finally it is here, the new version of IBM Domino. After the world premiere yesterday in Frankfurt, the world-wide launch is taking place today.

The focus in this release is on application development and administration. Features like self-healing of databases and increase of the maximum database size to 256 GB are among the most popular with administrators, while developers have a number of exciting additions.

The two most talked about features are the new Domino Query Language and node.js integration with Domino. Domino Query Language has been written from the bottom up to be fast, and the demonstrations I have seen confirms this. It is fast, very fast! And it can handle searches that would not only take a long time to create in earlier versions of Domino, but would take forever to run. Now the result comes back in a second, or even less. This really blew my mind when I first saw it earlier this year. John Curtis, the engineer that pretty much single handed wrote this code, did an amazing job, fully on par with when Damien Katz rewrote the formula language in ND6 and increased the performance several times over.

The second big feature of Domino 10 is the integration with node.js through the domino-db connector. It will be delivered in a separate application development pack, which will enter beta this week. This is a slight disappointment, I had been hoping this functionality would be available at the launch. But I rather wait the time that is needed for IBM and HCL to make it a fully stable product, instead of rushing something unfinished to the market.

Another product announced today was Notes for iPad, which makes it possible to run existing Notes applications unmodified on an iPad. All the functions we know and love are supported, like replication, offline access to applications, Lotusscript, Formula language, and more.

To support mobile Notes applications, there are enhancements in Lotusscript, for example camera and GPS support. Lotusscript has also been extended with other new classes, for HTTP requests and JSON parsing directly in native Lotusscript. No need to call Java or system API:s anymore!

HCL has done an amazing job in a short time, and Domino is on its way to become a very powerful and extendable platform for modern web development. A company can now not only deploy their existing business applications on iPads, they can also hire young developers who have experience of node.js and modern frameworks/libraries like Angular and React, and have them develop new solutions that can access existing data in Domino databases. Why use Mongo DB for data storage, when you have the much more secure Domino server available?

Domino 10 is not the end point. Domino 11 will be out next year, and IBM/HCL have committed to a long future for Domino. Forget #domino2025, now it is #DominoForever!

If you were not able to attend any of the launch events, here is the live stream from Frankfurt :

https://m.facebook.com/story.php?story_fbid=310707186390803&id=111720058922703

#domino2025 #dominoforever #IBMChampion

Convert US state abbreviations in Javascript

Posted on December 12, 2017 by Karl-Henry Martinsson Posted in #IBMChampion, Javascript, NetSuite, Programming Leave a comment

I was working on a NetSuite project today, and I ran into a problem. I used DataTables to display sales orders. The data is retrieved through an Ajax call to a RESTlet on the server.

One of the columns to display is the state of the shipping address. The table had a number of columns, so I was happy that the state coming over during the early testing were the abbreviated state. But today I noticed that after real data had been entered into the system, the state was the full name. And I had no space left in the table for that.

So I did a quick search and found a snippet of code that converted between abbreviation and full name and vice versa. I made some minor modifications to the code, mainly to clean it up and also make the code easier to read. I introduced two constants to indicate which kind of conversion to use, and replaced the traditional loop through the array with a for…of iteration.

You can find the code here: https://github.com/TexasSwede/stateAbbreviations

And this is how you use it:

var stateName = convertRegion("TX",TO_NAME);                       // Returns 'Texas"
var stateAbbreviation = convertRegion("Florida",TO_ABBREVIATED):   // Returns "FL"

This code is of course not specific to NetSuite, it is plain Javascript. You can use it in a Domino web application or even in a Notes form. And naturally you can use it in pretty much any web application where you can use Javascript.

Enjoy!

Domino 10 and Beyond – my thoughts

Posted on December 3, 2017 by Karl-Henry Martinsson Posted in #Domino2025, #IBMChampion, App Modernization, IBM/Lotus, Javascript, Lotusscript, Notes/Domino, Watson, Web Development 5 Comments

It has now been a little over a month since IBM announced the new direction of IBM Notes, Domino, Verse and Sametime. I have been thinking through what I think this means for the product and the ecosystem of third-party tools and business partners. Some people view the move of development from IBM to HCL Technologies as an abandonment of the product family. But that is not how I see it.

IBM has, despite their size, limited resources to dedicate to development of the Domino family of products. They have new products and services they are trying to bring to market, and by having HCL take over the development and add more resources, this is a win both for IBM and for Notes/Domino.

With more developers dedicated to the product, I expect to see more frequent updates and new features added quicker than we have been used to the last 5-6 years. The product management and future direction of the platform is still managed by IBM, but with more non-IBM resources at their hands I hope the product managers will be able to push harder for the addition of new technology and updates, bringing Domino back to a first class development platform.

Domino was an outstanding product, but for the last 6-8 years the innovation mostly stopped. New technologies were not added at the pace they were adapted by the rest of the world, and the support for new protocols like TLS 1.2 was lagging. IBM also but on Dojo as the framework for XPages, while the rest of the world mostly went to jQuery.

But if IBM allows HCL to update some aging parts and add new functions, requested by the community, I can see this being a great platform. And IBM says they will listen to the community and the users. Starting this month, IBM is bringing the Domino 2025 Jam to four cities in North America: Toronto on 12/8, Dublin (Ohio) on 12/13, Chicago on 12/14 and Dallas on 12/15. here will also be several events in Europe as well as a virtual Jam sometime in the future.

At the Domino 2025 Jam developers and users will be able to suggest what features they find important, what needs to be fixed, and where they want to see the product go in the future. I don’t think the Jam will have a huge impact on the upcoming Domino 10 release next year, but it may help IBM prioritize where to put their effort. Where I see the Domino 2025 Jam being helpful is in the longer timeframe, especially if it is repeated every 12 to 18 months to verify that the product direction is still what the market is looking for.

I also would like to see IBM addressing at least the most requested changes on IdeaJam.

Let me describe some of the functions and features I want to see in an upcoming version of IBM Domino.

Javascript Everywhere

For the last 20+ years we have mainly been using Lotusscript, both in the client and for agents on the server. It is a powerful language, but if you have been working with other more modern languages (Lotusscript is based on Visual Basic) there are many limitations and functions you are missing.

I would like to see Javascript made into a fully supported language everywhere. Both in the client and on the server. Add support for jQuery, to make it easy to address elements, and create a Javascript API to complement the Lotusscript functions.

In addition to making it easier to create and parse JSON (used in and by most web applications today), it would open up the product to new developers who may come from a more traditional web development background.

I would love to see Lotusscript get a modernization, but I doubt that will happen. In order to improve Lotusscript, a quite lot of changes are needed. Instead I think the future improvements should be on the Javascript API side.

External API

Any modern product needs a public API so other tools and applications can integrate with it. I would like to see support in Domino for LoopBack, like IBM is doing in LiveGrid. When you create a view, there would be a matching API created to create, read, update and delete documents, as well as list all records, perform searches, etc.

But there should also be additional more specialized API:s available, perhaps the most common functions should be exposed as API calls out of the box.

Integration with External Services

Notes and Domino also needs integration with external services, e.g IBM Watson, Mongo DB or Node-RED. Why not support for IFFTT? Expose the calendar as a Google Calendar feed. But also make it easy to connect external services to Notes and Domino. Make it easy to use Oauth 2.0 to login to a Domino-hosted service and vice versa.

New Domino Designer

Unlink Domino Designer from the Notes client. Create a Eclipse plug-in (and make sure it stays updated to work with new versions of Eclipse). This will help new developers to start working with Domino, using tools they are already familiar with. The goal should be that someone familiar with Javascript should be able to open Eclipse and start writing code for Domino, and the only thing they need to learn is the Domino Object Model.

Add ready-to-use web components/plugins, so the developer can easily add for example a name-lookup into Domino Directory or a date/time selector. Support CSS frameworks like Bootstrap, and make it easy to modify the look of the applications.

Notes Client

The Notes client makes it easy to quickly build applications. You get a lot of the core functionality of the applications “for free”, like views, forms, etc. But you are also limited in how the application looks. You can change the look of views somewhat by selecting background colors, fonts and a few other attributes. On forms you can select between two different looks for some of the fields, while other fields can not be modified at all. What I would like to see is a way to easily restyle everything by using CSS. Then you can make the forms and views look much more modern. Let the developer create “themes”, a set of CSS rules and perhaps images that can be applied to new applications in seconds. These themes could be published online, for other developers to use.

These are just some of the ideas I have for improvements to Domino. What are you ideas?

HCL Ambassador 2020

HCL Ambassador 2020

IBM Champion 2014-2020

Stack Exchange

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

Notes/Domino Links

  • Planet Lotus Planet Lotus
  • IBM dW Forums IBM dW Forums
  • StackOverflow StackOverflow

Recent Posts

  • Notes and Domino v12 is here!
  • NTF Needs Your Help
  • Helpful Tools – Ytria EZ Suite (part 2)
  • Busy, busy – But wait: There is help!
  • Semantic UI – An alternative to Bootstrap?

Recent Comments

  • 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!
  • Lynn He on About This Blog

My Pages

  • How to write better code in Notes

Archives

  • 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 (9)
  • 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 (175)
    • #Domino2025 (14)
    • #DominoForever (8)
    • #IBMChampion (46)
    • Administration (7)
    • Cloud (7)
    • CollabSphere (8)
    • Community (47)
    • Connect (33)
    • ConnectED (12)
    • Connections (3)
    • HCL (12)
    • HCL Master (1)
    • IBM Think (1)
    • Lotusphere (46)
    • MWLUG (25)
    • Notes/Domino (97)
      • Domino 11 (7)
    • Sametime (8)
    • Verse (14)
    • Volt (2)
    • Watson (6)
  • Life (8)
  • Microsoft (7)
    • .NET (2)
    • C# (1)
    • Visual Studio (1)
  • Movies (3)
  • Old Blog Post (259)
  • Personal (23)
  • Programming (83)
    • App Modernization (11)
    • Formula (4)
    • Lotusscript (46)
    • 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 (6)
    • Texas (2)
    • United States (1)
  • Uncategorized (15)
  • Web Development (50)
    • Frameworks (23)
      • Bootstrap (14)
    • HTML/CSS (12)
    • Javascript (32)
      • jQuery (23)
  • 1
  • 2
  • 3
  • …
  • 5
  • Next

Administration

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

Tracking

Creeper
MediaCreeper
  • Family Pictures
© TexasSwede 2008-2014