Anonymous
Domino 2.0 Rich Internet Applications with IBM Lotus Notes/Domino
You are here: Today » Owners and Authors field with ACL popup dialog
« Redesigning this blog
Adding and controlling Flickr badges »

Owners and Authors field with ACL popup dialog

To fill an Owners and an Authors field on a web form, I needed a popup that allows to pick groups or people from the NAB and roles from the database ACL. Instead of doing a popup window, I decided to show a floating iframe with the dialog. But first I had to build the dialog itself.

The dialog

I made the dialog in a Form element so that I could use a QueryOpen agent and @formulas. For all the options, I use a select tag with optgroups to group the roles, groups and people. A second select tag holds the selected elements. Finally, I've added some buttons for the actions:

<h1 id="title"></h1>
<div>
<div><select id="fSelectList" size="14" multiple="multiple">
<optgroup label="Roles">
    <option value="One">One</option>
    <option value="Two">Two</option>
    <option value="Three">Three</option>
</optgroup>
<optgroup label="Groups">
    <option value="Four">Four</option>
    <option value="Five">Five</option>
    <option value="Six">Six</option>
</optgroup>
<optgroup label="People">
    <option value="Ten">Ten</option>
    <option value="Twenty">Twenty</option>
    <option value="Fourty">Fourty</option>
</optgroup>
</select></div>
<div><button onclick="G.dialog.append()">&gt;</button><button onclick="G.dialog.remove()">&lt;</button></div>
<div><select id="fSelected" size="10" multiple="multiple"></select></div>
</div>
<p>
<button onclick="G.dialog.submit()">OK</button>
<button onclick="G.dialog.close()">Cancel</button>
</p>

The JavaScript

I made a singleton G.dialog which holds all the functions. On page load, G.dialog.init() gets the title, the field to fill in and its value from the page the iframe on. The rest of the code processes the actions of the user:

G.dialog={
init:function(){
    var m=this,f=m.from=window.top.document,v=m.field=$(G.mid(location.search, 'field=', '&'),f),o=$('fSelected'),s=$('fSelectList'),i
    $('title').innerHTML=$$('label',v.parentNode)[0].innerHTML
    if(v.value=='')return
    v=v.value.split(', ')
    for(i=0;i<v.length;i++){m.hideOption(s,v[i]);m.addOption(o,v[i])}
},
addOption:function(a,b){
var y=G.create('option',{text:b,value:b})
try{a.add(y,null)}catch(e){a.add(y)}
},
hideOption:function(a,b,c){
    var o=a.options,i,n=o.length
    for(i=0;i<n;i++){
        if(o[i].value==b){o[i].style.display=c?'':'none';o[i].style.color=c?'':'#ccc';i=n}
    }
},
append:function(){
    var m=G.dialog,o=$('fSelected'),s=$('fSelectList').options,i
    for(i=0; i<s.length;i++){
        if(s[i].selected && s[i].style.display==''){G.set(s[i].style,{display:'none',color:'#ccc'})
            s[i].selected=false
            m.addOption(o,s[i].value)
        }
    }
},
remove:function(){
    var m=G.dialog,o=$('fSelected'),oo=o.options,s=$('fSelectList'),i
    for(i=0;i<oo.length;i++){if(oo[i].selected){m.hideOption(s,oo[i].value,true);o.remove(i);i--}}
},
submit:function(){
    var m=G.dialog,o=$('fSelected').options,i,v=[]
    for(i=0;i<o.length;i++)v.push(o[i].value)
    m.field.value=v.join(', ')
    m.close()
},
close:function(){var m=G.dialog;$('if-dlg',m.from).style.display='none'}
}

The code to fill the options

I use two computed for display fields to get the lists of groups and people from the NAB. Then I use a QueryOpen agent to fill the content of the fSelectList select box:

Field dwUserNames

a:=@DbColumn(""; "":@GetAddressBooks([FirstOnly]); "($VIMPeople)"; 1);
@If(@IsError(a); @Text(a); @Name([CN]; a))

Field dwUserGroups

a:=@DbColumn(""; "":@GetAddressBooks([FirstOnly]); "($VIMGroups)"; 1);
@If(@IsError(a); @Text(a); a)

The QueryOpen agent

Sub Initialize
    On Error Goto catch
    Dim s As New notessession
    Dim db As notesdatabase    
    Dim doc As NotesDocument
    Dim out As New stringbuffer(20)
    Dim v, i As Integer
    
    Set db=s.CurrentDatabase
    Set doc=s.DocumentContext
    v=db.ACL.Roles
    
    out.add |<optgroup label="Roles">|
    For i=0 To Ubound(v)
        out.add |<option value="| & v(i) & |">| & v(i) & |</option>|
    Next
    out.add |</optgroup><optgroup label="Groups">|
    v=doc.dwUserGroups
    For i=0 To Ubound(v)
        out.add |<option value="| & v(i) & |">| & v(i) & |</option>|
    Next
    out.add |</optgroup><optgroup label="People">|
    v=doc.dwUserNames
    For i=0 To Ubound(v)
        out.add |<option value="| & v(i) & |">| & v(i) & |</option>|
    Next
    out.add |</optgroup>|
    
    doc.ReplaceItemValue "dwAclList", out.collapse(NEWLINE)
    
    Goto finally
catch:
    doc.ReplaceItemValue "dwAclList", "Error " & Err & " in line " & Erl & ": " & Error$
    Resume finally
finally:
End Sub

Adding the popup to the form

The popup button and the iframe

<li>
<label for="fOwnerList">Owners: </label>
<input id="fOwnerList" name="OwnerList" value="[Admin]">

<input type="button" class="small" onclick="G.dialog('acl','fOwnerList')" value="..." />
</li>
<li>
<label for="fAuthorList">Authors: </label>
<input id="fAuthorList" name="AuthorList" value="Axi Sitebuilder Managers, d-works-people">
<input type="button" class="small" onclick="G.dialog('acl','fAuthorList')" value="..." />
</li>
<iframe src="" id="if-dlg" frameborder="0"></iframe>

The CSS for the iframe:

#if-dlg{width:470px;height:270px;border:solid 1px #ccc;position:absolute;display:none}

And finally, the JavaScript to open the popup, centered in the window:

G.dialog=function(a,b){
var w=window,dd=document.documentElement,o=$('if-dlg'),os=o.style,tp,lf
os.display='block'
tp=parseInt((w.pageYOffset||dd.scrollTop)+((w.innerHeight||dd.clientHeight)-o.offsetHeight)/2)+'px'
lf=parseInt((w.pageXOffset||dd.scrollLeft)+((w.innerWidth||dd.clientWidth)-o.offsetWidth)/2)+'px'
G.set(os,{top:tp,left:lf})
o.src=G.base+'.dlg-'+a+"?readform&field="+b
}

Screenshot

screenshot of the dialog box

Some things are not so obvious to achieve. This simple dialog box took me 12 hours. And yes, I know it is not very scalable.

Star rating

0%

Comments

  1. 07/04/2008 03:59:41 AM, Jean Daigle

    Hi, your code is interesting but I am very confused about how to apply it in my environment. You seem to be saying that some of the code goes in a Form - as pass-thru HTML? And then you say that you have a QueryOpen agent - how do you call this and from where?

    Thanks,

    Jean A beginner programmer with LS

To add a comment, log in or register as new user. It's free and safe.