Skip to main content link. Accesskey S
  • HCL Logo
  • HCL Notes and Domino wiki
  • THIS WIKI IS READ-ONLY. Individual names altered for privacy purposes.
  • HCL Forums and Blogs
  • Home
  • Product Documentation
  • Community Articles
  • Learning Center
  • API Documentation
Search
Community Articles > Lotus iNotes > Lotus iNotes customization > Lotus iNotes Customization example: "iNote"
  • Share Show Menu▼
  • Subscribe Show Menu▼

Recent articles by this author

Lotus iNotes Customization example: "iNote"

This example demonstrates several customization concepts within DWA. For 8.5.2, all of these modifications live in "Forms85x.nsf". No changes to Forms85.nsf are necessary. Techniques demonstrated are: lazy-load script code, LotusScript agent to save a document, create and manage movable ...
Community articleLotus iNotes Customization example: "iNote"
Added by ~Chloe Opfreestergon | Edited by IBM contributor~Chloe Opfreestergon on November 22, 2010 | Version 7
  • Actions Show Menu▼
expanded Abstract
collapsed Abstract
This example demonstrates several customization concepts within DWA. For 8.5.2, all of these modifications live in "Forms85_x.nsf". No changes to Forms85.nsf are necessary. Techniques demonstrated are: lazy-load script code, LotusScript agent to save a document, create and manage movable dialogs.
Tags: lazy-loading, customization, movable
ShowTable of Contents
HideTable of Contents
    • 0.1 Forms85_x.nsf Code
    • 0.2 LotusScript Agent Code
The best way to demonstrate concepts is with code.  This is sample code for educational purposes only.

This example demonstrates several customization concepts within Lotus iNotes.   For 8.5.2, all of these modifications live in "Forms85_x.nsf".  No changes to Forms85.nsf are necessary.  Techniques demonstrated are: 
  • Lazy-load script code
  • LotusScript agent to save a document
  • Create and manage movable-dialogs
Each tag represents a Notes SubForm element in the Forms85_x.nsf database.  Attached, you'll find the icon image that should be added as a File Resource design element in Forms85_x.nsf.  And at the bottom, you'll find code for the (iNoteSave) agent.  Be sure to set the 2nd tab of the agents properties to "Run as web user".  Also, the agent should not act on any selected documents.  The documentContext will be passed into the agent by Domino's HTTP server.
 
This code will add  an image to the right of the "Search" panel in Lotus iNotes, like this:
    inote-icon
 
When the user clicks the icon, a simple, movable dialog will pop up allowing notes to be entered.  
    inote-dialog 
 
Clicking "OK" will save the note to the "Notebook" section of Lotus iNotes.
 
 
Enjoy!
 

Forms85_x.nsf Code




<NotesSubForm name="Custom_CSS">
.s-masthead-height {
overflow:visible;
}
.inote-icon{
background:transparent url(/iNotes/Forms85_x.nsf/inote-icon.gif?openfileresource) no-repeat scroll left top;
height:2.3em;
vertical-align: middle;
}
.inote-title-text {
font-size:75%;font-weight: bold;color: <dwa:property id="D_COLOR_DIVDIALOG_SHADOW" quotes="none"/>;
}
.inote-title {
background-color: <dwa:property id="D_COLOR_DIVDIALOG_TITLE" quotes="none"/>;
border-bottom: 1px solid <dwa:property id="D_COLOR_DIVDIALOG_TITLE_BORDER" quotes="none"/>;
}
</NotesSubForm>

<NotesSubForm name="Custom_LazyLoad_Subforms">
<NotesDictionary>
<NotesVar name="s_inote_library" AllowPreset="yes">
</NotesDictionary>
<InsertNotesSubForm optional="yes" name=@{@If(s_inote_library="1"; "x_inote_library"; "")}>
</NotesSubForm>

<NotesSubForm name="x_inote_library">
/************/

/* This library is lazy-loaded.  It is not loaded until after the first press of the "New iNote" icon. */
/************/
function x_new_inote(sId)
{
// x_new_inote creates a new dialog to enter a note.  Using "new" allows us to create as many dialogs as we want.

var EJs=ELU.EJs[this.sId=sId];
var EcK=AAA.EcK;
var EoR='e-dialog-inote-' + (x_new_inote.YT++);
var EFb=EoR + ':x_inote_dialog';
var nTop=(x_new_inote.YT % 10) * 20;
var nLeft=(x_new_inote.YT % 10) * 20;
var oDtFmt=new EJw('yyyy-MM-dd');
var sTitle=oDtFmt.format((new EYB).setDate(new Date()));
var ETv=EcK.getElementById(EoR);
if (!ETv) {
var sHtml=''
+ '<div id="' + EoR + '" class="s-popup" style="z-index:99;display:none;top:' + nTop + 'px;left:' + nLeft + 'px;height:' + Math.min(200, EcK.body.clientHeight) + 'px;width:' + Math.min(300, EcK.body.clientWidth) + 'px;"'
+ ' com_ibm_dwa_ui_widget_class="x_inote_dialog"'
+ '>'
// DIALOG TITLE
+ '<div id="' + EoR + '-title"'
+ ' com_ibm_dwa_ui_draggable="true"'
+ ' com_ibm_dwa_ui_draggable_ids="' + EoR + '"'
+ '>'
+ '<table width="100%" class="inote-title" cellpadding="2" cellspacing="0"><tr><td width="100%" class="inote-title-text">iNote</td>'
+ '<td width="5"><button onclick="AAA.DSq.EKc.prototype.EYl[\'' + EFb + '\'].save();"><dwa:string id="L_OK" quotes="none"/></button></td>'
+ '<td width="5"><button onclick="AAA.DSq.EKc.prototype.EYl[\'' + EFb + '\'].close();">X</button></td>'
+ '</tr></table>'
+ '</div>'
+ '<div>'
// DIALOG BODY


+ '<form name="' + EoR + '-form" id="' + EoR + '-form"'
+ ' onsubmit="AAA.DSq.EKc.prototype.EYl[\'' + EFb + '\'].save();"'
+ '><table border="0">'
+ '<tr><td><dwa:string id="L_SUBJECT" quotes="none"/></td>'
+ '<td><input name="Subject" id="' + EoR + '-subj" type="text" size="32" value="' + sTitle + '" /></td></tr>'
+ '<tr><td colspan="2"><textarea name="Body" id="' + EoR + '-body" cols="32" rows="6"></textarea></td></tr>'
+ '</table>'
+ '</form>'
+ '</div>'
+ '</div>';

// show popup by adding html to main page, then tell DWA to load the x_inote_dialog widget
var oDiv=EcK.createElement('DIV');
oDiv.innerHTML=sHtml;
EcK.body.appendChild(oDiv.firstChild);

// main widget initialization function
EKc.prototype.ESH[EFb]=function() {
AAA.EcK.getElementById(EoR).style.display='block';
}

// load all widgets defined by the attribute "com_ibm_dwa_ui_widget_class"
EPl(EcK.getElementById(EoR));
} else{
EKc.prototype.ESH[EFb]();
}
}
x_new_inote.YT=1;

function x_inote_dialog(sId)
{
this.sId=sId;
}
x_inote_dialog.prototype.close=function x_inote_dialog_close()
{
AAA.EcK.getElementById(this.sId).style.display='none';
};
x_inote_dialog.prototype.save=function x_inote_dialog_save()
{
var EcK=AAA.EcK;
var oForm=EcK.forms[this.sId + '-form'];
var EFb=this.sId + ':x_inote_dialog';
this.close();
if(!AAA.FyN) {
var BRQ=EcK.createElement('div');
BRQ.className='s-hidden-iframe';
BRQ.innerHTML =
'<iframe name="iframeToRedirect" src="'
+ AAA.EuR
+ s_FF
+ '/iNotes/Proxy/?OpenDocument&Form=s_Blank'
+ AAA.ELM.s_StaticHTMLXHRArgs
+'"></iframe>';
BRQ=EcK.body.appendChild(BRQ);
AAA.FyN=BRQ;
}
oForm.encoding='multipart/form-data';
oForm.method='POST';
oForm.target='iframeToRedirect';
oForm.action    =
AAA.MO
+ '/0/$new/?EditDocument&Form=s_RunAgent'
+ (AAA.ELM.s_Charset ? ('&charset=' + AAA.ELM.s_Charset) : '');
var DXX=[
{id:'%%Nonce', value:AAA.getNonce()}
,{id:'fnCB', value:'parent.AAA.DSq.EKc.prototype.EYl[\'' + EFb + '\'].DlJ'}
,{id:'AgentName', value:'wInoteSave'}
,{id:'CommonAgent', value:'2'}
,{id:'NotesItems', value:'Form=JournalEntry;TitleFormula=Subject;Categories=iNote;WebCategories=iNote;Subject;Body;'}
];
for (var i=0; i<DXX.length; i++)
{
var oItem=DXX[i];
var oInp=oForm[oItem.name];
if (!oInp) {
var oInp=EcK.createElement('INPUT');
oInp.name=oItem.id;
oInp.id=this.sid + '-' + oItem.id;
oInp.value=oItem.value;
oInp.type='hidden';
oForm.appendChild(oInp);
} else {
oInp.value=oItem.value;
}
}
oForm.submit();
this.EiW=EKc.prototype.EYl[AAA.Enm];
if (this.EiW)
this.EiW.Enl(1);
AAA.EVI.sr(
2
,''
,<dwa:string id="L_SAVING_DATA" quotes="single"/>
);
this.Elp=setTimeout('AAA.DSq.EKc.prototype.EYl[\'' + EFb + '\'].DlJ()',20000);
};
x_inote_dialog.prototype.DlJ=function x_inote_dialog_onDatasetComplete(oData)
{
if (this.Elp) {
clearTimeout(this.Elp);
this.Elp=null;
}
if (this.EiW) {
this.EiW.Enl(-1);
this.EiW=null;
}
if (!oData || !oData.items || oData.error.status) {
parent.alert(<dwa:string id="L_NPW_COPY_ERROR" quotes="single"/>);
return;
}
AAA.EVI.sr(
2
,''
, (x_inote_dialog.kDOCUMENT_VALID == oData.items[1].status ? 'Saved: ' : 'Error saving: ') + oData.items[1].id
);
};
x_inote_dialog.kDOCUMENT_VALID=1001;
x_inote_dialog.kDOCUMENT_DUPLICATE=1002;
x_inote_dialog.kDOCUMENT_ERROR=1003;
x_inote_dialog.kDOCUMENT_DUMMY=9999;
EKc.prototype.FKd['inote_library']=true;
</NotesSubForm>

<NotesSubForm name="Custom_JS_Lite">
function Custom_Scene_PostLoad_Lite(s_SceneName)
{
if (s_SceneName == 'e-panelmanager:EVy') {
setTimeout('inote_initialize()', 0);
}
}
function inote_initialize()
{
AAA.DSq.EKc.prototype.EQj['x_new_inote']=['inote_library'];
var tf=AAA.BYp('transparent.gif');
var sHtml=''
+ '<div id="e-new-inote" class="s-rightpanel inote-icon"'
+ ' onclick="AAA.DSq.ELU(event, \'e-new-inote\', \'x_new_inote\');return false;"'
+ ' onmouseover="this.style.backgroundColor=\'rgb(251,215,116)\'"'
+ ' onmouseout="this.style.backgroundColor=\'\'"'
+ '>'
+ '<img border="0"'
+ ' alt="iNote" title="iNote"'
+ ' width="21" height="21"'
+ ' src="' + tf + '"'
+ ' /></div>';
AAA.EcK.getElementById('e-ftsearch-container').style.right='22px';
var oDiv=AAA.EcK.createElement('DIV');
oDiv.innerHTML=sHtml;
AAA.EcK.getElementById('e-ftsearch-container').parentNode.appendChild(oDiv.firstChild);
}
</NotesSubForm>

<NotesSubForm name="Custom_About">
<NotesDictionary>
<NotesVar name=CustomExtFormsVersion value={L_ABOUT_RELEASE_NUM}>
<NotesVar name=CustomUserVersion value={1.0}>
</NotesDictionary>
</NotesSubForm>

<NotesFileResource mimetype="image/gif" name="inote-icon.gif" value="../customization/x-inote/inote-icon.gif" hide_from_web="no" hide_from_notes="yes" language_specific="no"></NotesFileResource>
<NotesAgent name="(wInoteSave)" copy_from_template="../customization/x-inote/resources.nsf"></NotesAgent>
 


 
 

LotusScript Agent Code

Agent name: wInoteSave
Trigger:  Agent list selection
Target:  None

 
Option Public
Option Explicit

Const kNOERROR% = 0
Const kERR_CGI_INVALID_DATA% = 1097

Const kDOCUMENT_VALID% = 1001
Const kDOCUMENT_DUPLICATE% = 1002
Const kDOCUMENT_ERROR% = 1003
Const kDOCUMENT_DUMMY% = 9999

Const kDOCUMENT_BODY$ = "Body"
Const kDOCUMENT_TITLE_FORMULA$ = "TitleFormula"

Class HTMLOutput
    '// Properties
    m_txt As String
    m_err As String
    m_fn  As String
    m_escText(0 To 0) As String
    m_escFind(0 To 0) As String
    m_escRepl(0 To 0) As String

    '// Methods
    Sub New( )
        m_txt = ||
        m_err = ||
        m_fn  = |parent.alert|
        m_escFind(0) = |'|
        m_escRepl(0) = |\'|
    End Sub

    Sub SetCB( fnCB$ )
        Me.m_fn = fnCB
    End Sub

    Function GetOutput() As String
        Dim sRtn$
        If (Len(m_fn)>0) Then
            sRtn = |<script>| & Chr(10) & |function fn0(){return {items:[{id:'',status:| & kDOCUMENT_DUMMY & |}| & m_txt & |],error:{| & m_err & |}};}| & m_fn & |(fn0());| & Chr(10) & |</script>|
        End If
        GetOutput = sRtn
    End Function

    Sub Append( sName$, nCode% )
        m_txt = m_txt & |,{id:'| & Me.EscapeJson(sName) & |',status:| & CStr(nCode) & |}|
    End Sub
    
    Sub SetError()
        m_err = |id:'| & Me.EscapeJson(Error$) & |',status:| & CStr(Err())
    End Sub
    
    Function EscapeJson(sText$) As String
        Dim vName As Variant
        m_escText(0) = sText
        vName = Replace(m_escText, m_escFind, m_escRepl)
        EscapeJson = vName(0)
    End Function
End Class
Dim g_ns As NotesSession
Dim g_debug%

Sub Initialize()
    Set g_ns = New NotesSession
    g_debug = False
    If (True=g_ns.IsOnServer) Then
        Call HandleWebPost()
    Else
        '// error
    End If
End Sub
Sub HandleWebPost()
    Dim oDocCtx As NotesDocument
    Dim oHtml As Variant
    On Error Goto Err_Agent
    
    '// DocumentContext is the submitted HTML Form
    Set oDocCtx = g_ns.DocumentContext
    DebugMsg g_ns.EffectiveUserName

    '// Dump all doc values
    If (True=g_debug) Then
        ForAll oItem in oDocCtx.items
            DebugMsg ">" & oItem.Name & ": " & oItem.Text
        End ForAll
    End If

    '// HTML-Script Printer
    Set oHtml = New HTMLOutput()
    If (False=oDocCtx.HasItem("fnCB")) Then
        Error kERR_CGI_INVALID_DATA, ""
    End If
    Call oHtml.SetCB( oDocCtx.GetItemValue("fnCB")(0) )

    '// Process Content
    Call ProcessContent(oHtml, oDocCtx.ParentDatabase, oDocCtx)

Exit_Agent:
    On Error Resume Next
    Print oHtml.GetOutput()
    Exit Sub

Err_Agent:
    DebugMsg CStr(Err()) & ": " & Error$
    Call oHtml.SetError()
    Resume Exit_Agent
End Sub
Function ProcessContent( oHtml As Variant, oMailDb As NotesDatabase, oDocCtx As NotesDocument ) As Integer
    Dim oDocNew As NotesDocument
    Dim oBody As NotesRichTextItem
    Dim sDocTitle$, sDocFormula$
    Dim vNotesItems As Variant
    Dim vValue As Variant
    Dim nStatus%
    On Error Goto Err_ProcessContent

    nStatus = kNOERROR

    Set oDocNew = oMailDB.CreateDocument
    Set oBody = oDocNew.CreateRichTextItem(kDOCUMENT_BODY)

    '// save all known fields and values
    vNotesItems = Split(oDocCtx.GetItemValue("NotesItems")(0), ";")
    ForAll v in vNotesItems
        DebugMsg "v: " & CStr(v)
        If (Instr(CStr(v), "=") > 0) Then
            vValue = Split(CStr(v), "=")
            Call oDocNew.ReplaceItemValue(vValue(0), vValue(1))
        Else
            If (kDOCUMENT_BODY = v) Then
                Call oBody.AppendText( oDocCtx.GetItemValue(CStr(v))(0) )
            Else
                Call oDocNew.ReplaceItemValue(CStr(v), oDocCtx.GetItemValue(CStr(v))(0))
            End If
        End If
    End ForAll
        
    '// doc title
    sDocTitle = "Notes document"
    If (oDocNew.HasItem(kDOCUMENT_TITLE_FORMULA)) Then
        sDocFormula = oDocNew.GetItemValue(kDOCUMENT_TITLE_FORMULA)(0)
        vValue = Evaluate(sDocFormula, oDocNew)
        sDocTitle = vValue(0)
    End If
    DebugMsg "Title: " & sDocTitle

    If (True=g_debug) Then
        ForAll oItem in oDocNew.items
            DebugMsg ">" & oItem.Name & ": " & oItem.Text
        End ForAll
    End If

    '// ensure this document is valid
    If (True=oDocNew.ComputeWithForm(False, True)) Then
        '// save new entry
        Call oDocNew.Save(True, False, False)
        Call oHtml.Append( sDocTitle, kDOCUMENT_VALID )
        DebugMsg "Saved: " & sDocTitle
    Else
        Call oHtml.Append( sDocTitle, kDOCUMENT_ERROR )
        DebugMsg "ComputeWithForm Error"
    End If

Exit_ProcessContent:
    On Error Resume Next
    ProcessContent = nStatus
    Exit Function
    
Err_ProcessContent:
    nStatus = Err()
    DebugMsg CStr(Err()) & ": " & Error$
    Call oHtml.SetError()
    Resume Exit_ProcessContent
End Function
Sub DebugMsg( sMsg$ )
    If (True=g_debug) Then
        MessageBox sMsg
    End If
End Sub

 

  • Actions Show Menu▼


expanded Attachments (2)
collapsed Attachments (2)
Edit the article to add or modify attachments.
File TypeSizeFile NameCreated OnDelete file
image/gif 1 KB inote-icon.gif 11/18/10, 8:48 PM
image/gif 6 KB inote-dialog.gif 11/22/10, 4:42 PM
expanded Versions (1)
collapsed Versions (1)
Version Comparison     
VersionDateChanged by              Summary of changes
This version (7)Nov 22, 2010, 4:48:01 PM~Chloe Opfreestergon  IBM contributor
expanded Comments (0)
collapsed Comments (0)
Copy and paste this wiki markup to link to this article from another article in this wiki.
Go ElsewhereStay ConnectedAbout
  • HCL Software
  • HCL Digital Solutions community
  • HCL Software support
  • BlogsDigital Solutions blog
  • Community LinkHCL Software forums and blogs
  • About HCL Software
  • Privacy
  • Accessibility