Showing posts with label AJAX. Show all posts
Showing posts with label AJAX. Show all posts

Sunday 24 May 2009

A rogue pair of FLEX purple underpants have mounted an assault on the yellow-only wash of my lotus web dev laundry

I have been a bit remiss with the Flex series I started a while back and I do apologise for the discontinuity and I have started doing some more examples that I will pop up on here in the next few days.

There is a part of me that is a wee bit ... embarrassed is not the right word ... concerned is perhaps better ... that whilst the movers and shakers in the Domino world are "Doing it" the Xpage way I have veered off into another RIA technology.

I have never been a fanboy of any particular technology I am more inclined to use the tools that I have access to and which get the job done. Now I have had a bit of a play with X-Pages and they are indeed a wonderful if slightly not-quite-there-yet thing. As the new Domino techniques develop I have found myself moving towards a place where Domino is a back end data store, like DB2, MySQL or Oracle

I am not sure quite why I this is happening, but technologies & frameworks like AJAX, FLEX etc do take a fair bit of the drudgery out of coding for the web. I found that it was easier to have a slight dichotomy between the app as seen on the web and the app as seen in the notes client rather than to have to make concessions in one or the other for the sake of conformity.

Taking this approach also means I can deliver web apps for a broader range of server installs. Back to V6.* rather than confine myself to V8.* servers thus giving more of my user base a nice warm feeling of being included in the "new" stuff.

This is not to say that I am leaving all of the tools of Notes/Domino behind. I still use Domino Security, Author and Reader fields and loads of LS and JAVA based agents to provide the data handling facilities.

I suppose that another reason that I am heading in this direction is that Domino does not exist in isolation in my sphere of reference. It exists along side data silos in DB2 and Oracle which in the client we can now leverage with Live text linking to composite apps, widgets and side bar apps in the 8* client, which is of course marvellous for those folk on the Full Version 8 client. In the real world where I code not all my users are on V8 and it will (given the current economic climate etc etc) be some time until some of the non-power users have the tin capable of running the full client to its full advantage. In the interim so as not to exclude these users from the momentum of change, I will use the power of non-yellow-tech then it seems prudent to do so.

In several conversations I have had on this topic, there has been an air of disapproval from some that I am at snubbing all the work done to improve things on the platform in the last couple of years. I do not think that I am , I leverage the best for my users with the tools that I have and the facilities they have to use it, if that appears "disloyal" well so be it. I am paid to service my users not some ethereal dogma of yellow oneness. ;-)

For those of you not yet on Version 8 and perhaps held back by budgetary constraints my message would be that you can move forward if you step outside what some refer to as "the bubble" and look at other methods that will maintain your creative momentum with the tools and servers you have to hand.

Saturday 18 October 2008

Create a web based Drag and Drop Calendar

As part of my "spreading the domnio love" I have for the past year or so been a "yoda" to a Notes Developer who wanted to start branching out into more web based apps. Now in typical DYM form fate does not thrust me an apprentice with whom I can share the odd beer at the weekend. Oh NO! My "Luke Skywalker" does not live in Ireland! C'est la vie :-)

Anyway she asked me the other day how she could make one of her CRM calendar facilities a bit flashier and more modern and I like a fool said "why don't you do it in AJAX and while you are at it incorporate Drag and Drop?"
"Oh that would be good" she said "How would I do that?". My bluff was well and truly called! I said I would have a look at it this evening and send her an example over the weekend. After a certain amount of head scratching and asking myself "How would Chris Blatnick do it?" I fired up the DYM PC and started to code.

One of the problems with calendars and domino has been how absolutely SHITE they look on the web and building any sort of functionality into them was a labour of hercules which involved far to much futtering about with $ fields and the like. My non-domino alter ego PHPYouWillYouWill (tm) gave me a stout dig in the ribs and whispered in my ear, go on break the 11th commandment, use the domino server as a back end server and do nearly everything in JS. I know that this in some quarters sufficient for my domino woggle to be ceremonially crushed as LS. However in mitigation my design runs quite happily on servers V6 and above and the Domino Web Server way back then was a bit ... well it was a lot ... EUCK.

The premise of this example is simple, you have two forms Customer which stores customer data and Appt which stores an Appointment with a customer on a particular day. This data needs to be presented in a MONTH view to the user. The users need to be able to schedule a meeting with a customer on a particular day so they also need to be able to
a) Find a customer in the application
b) Drag the customer onto a date cell which will create an APPT form in the back end NSF

I am used to the YUI framework and one of these days I will get all DOJO but for the moment I know what I am doing with YUI and it has a nice easy D&D implementation.
You register the dragable object and target objects, define a couple of handler functions and Robert is your mothers brother.

Now please remember this is a simple app written as an example of "how I would start to" rather than an actual full functioning app and it was written in 3 hours this evening. Anyway it looks like this, (Click on image for a better look see)


A: Controls for moving the viewable month around.
B: Search Bar á la Google that allows typeahead look up of the customers.
C: Results from the search appear here.
D: An Item being dragged from the list to the calendar.
E: As the Customer passes over a calendar cell the cell is highlighted.
F: An existing Appointment in the calendar.

I used YUI 2.2.4. as the framework for the AJAX calls and DOM manipulation.

Like I said it looks kinda better than the ordinary one and isn't all that complicated at all (it took me 3 hours to code up from scratch!) and will run happily on a V6 onwards server you don't need any on the V8 fancy pants stuff and all the YUI stuff is contained in the NSF.

If anyone is interested an uncommented version of the file can be downloaded here.
Download it, Sign it, pop it on your server and goto crm.nsf/calendar.html

If you think it is useful let me know and I will definitely pop the commented version up on OpenNtf (once i have commented it that is!)

Monday 30 June 2008

Adobe pushes Acrobat into Multimedia and challenges a little bit of the Domino world


Geeky followers here is something to have a play with if you are bored. Adobe9 (currently beta and due for gilding in July) introduces flash integration, portfolios and hosted collaboration services. I used to hate PDF it was "printer monkey" world and I spent long enough there in the early 80's. My dislike a side PDF has become fairly pervasive. Open Office exports documents to PDF, M$ Orrifice does it with a free add on (soon I am told to changed to there as standard) But now your 'umble PDF will be able to hold Video!...

I sensed 10,000 notes Mail Admin's buttocks clench there at the thought of the potential increase in mail size and how will we weed out ordinary PDF's from someone trying to sneak "Lavidious Linda Licks Loins III"
onto the corporate network by calling it Quarter_4_Returns.pdf .. sure without things like that the world would be a boring place. This is where Adobe's new hosted collaborative service comes in. You can find here it is beta it is free and you get 5gb of space to fill up with documents you create with BUZZWORD their online Word Processor or with file formats. CONNECTNOW is the other tool and is like a Sametime web conference. I have had a play with BUZZWORD and it is Google.Docs in a party frock with a hint of potential excitement once the kids are in bed.

Go have a play ... it is interesting and the design (all flash) is excellcent

I think it will, given the inroads the PDF format has made into our IT lives, yet more people a glimpse of the value what Web 2 and Enterprise 2 is capable of.

Sunday 22 June 2008

Getting intimate with Javascript objects part #1


Gentle reader,
This evening I am going to start a series of posts where I will have a little poke around JavaScript objects and Object-Oritented JS in my own weird manner. So for my non-geek readers it is probably best that you leave now - no one will think the worse of you if you do:-)

OK let the geeky fiddling and poking begin!

Objects are composite data types. There we go, RGQ (Required Geekiness Quotient) achieved, I managed to get the word "composite" shoe-horned into the first sentence! Mind you in the context of JS objects it is also very apt because a JS object is a composite object that clumps together lots of related values and functions into one unordered, named collection.

A. Creating Objects

Objects can be created with the new operator followed by the constructor function for the object

The most basic of these would be
var MyThing = new Object();
This object exists at the same usefulness quantum level as a "glass hammer" or a "chocolate BBQ" as it contains no properties and has no methods. Think of MyThing as the Paris Hilton of JS variables. Rather than an "it-girl" it is a "it-var", superficially interesting enough to take on one date, but the resulting sex tape would be crap.

Ohh slipped in some more Object Jargon there ... just so you know

The Values stored in an Object are called Properties
The Functions stored in an Object are called Methods

Moving quickly on, you are bound to have used constructor functions before, like these

var MyDate = new Date();
or
var MyNextHangover = new Date(2009,01,01)
are examples of creating an object that represents a date and time. You can do lots of interesting things with the JS date object which you can explore here.

BUT!!!!! just to make JS interesting ... you don't have to create an object using a constructor you can use the Object Literal method to create and initialize new objects. An Object literal is a comma-separated list of property-name: value pairs enclosed in curly brackets (or braces if you have to call them that) for example
var MyCockTail = {
name: "Sex on the beach",
price: 3.50,
type: "Fruity",
glass: "Highball",
garnish: "Lime Wedge"
}
Would create a JS object that holds the details of a particularly tasty if oddly named cocktail.

You are not constrained when it comes to the type of Properties you can store in an object, any of the JS data types can be stored as a property in an object. I emboldened that because it is important and I WILL be mentioning it again so it is best that you make a "note to self" now .. s'ok I will wait here while you do it

[..waits...]

For example
var MyCockTail = {
name: "Sex on the beach",
price: 3.50,
type: "Fruity",
glass: "Highball",
garnish: "Lime Wedge",
mix: {
shotA: "2 x Vodka",
shotB: "1 x Peach schnapps",
shotC: "3 x Orange Juice",
shotD: "3 x Cranberry Juice"
}
}
This is the same as the previous example except I have added a new property to the object named mix which is an object itself containing the properties shotA,shotB,shotC and shotD.

B. Accessing ,Setting Object Properties and deleting a Property when you are done

OK got that now how do I access these things in my code. well that is dead easy use the period operator, period. .o0(oh the savage wit!) Seriously you use the . character to access the value of an objects property. For example using the MyCockTail object we created above we can pull out the name thusly :

MyCockTail.name
or
MyCockTail.price
or
MyCockTail.mix.shotA

So we could have a piece of JS that goes like this

alert("You have selected "+MyCockTail.name+" which is a "+MyCockTail.type+" drink")

Easy init? :-)

But what happens if if want to change the value of a property in code? That is easy, just set it the same way you would if it was an ordinary variable. like this

MyCockTail.name = "Entirely innocent frolic on the beach";

Would make the name of the cocktail in the example above acceptable at a church social.

"But...", I hear the brighter of you ask "..what happens if i try to access a property that either doesn't exist or has yet to be set?" Well if you do this, a large boxing glove will materialize from the screen and get all Evander Holyfield with your nose ... I jest but dont' you wish you could do that? ... anyway all that happens is that the you end up retrieving the undefined value. For example

alert(MyCockTail.hasUmbrella)

would result in the alert dialog appearing with undefined in it like this


"OK", the smart arse in the audience says "How do I delete a property?"

I look smug and reply "like this...."

delete MyCockTail.name

but be careful this does not just set the value of MyCockTail.name to undefined. It deletes the entire property from the object. It is gone completely!

Ok that is enough for today ... in the next posts in this series I will look in more detail at rolling your own constructor method ,prototypes and inheritance, and how to fool JS into the notion that it has formal classes.

Monday 12 May 2008

HTML Check Boxes values when Disabled by Javascript clear themselves when saved

Caught this one today.

You have a check box on a form
For one reason or another you use the JS
document.forms[0].myCheckBox.disabled = true;
to stop users changing it on the form.

However if you then SAVE the form back to the Domino server with the disabled status of the field still set to TRUE. Any values the checkbox had will disappear and the field will saved as empty!

This does not happen with RADIO , TEXT and TEXTAREA elements. The only affected one appears to be CHECKBOX. I came across this because I was using AJAX to go back to the server to get some information and based on that one of three sets of CheckBoxes would become available the other 2 would be set to fixed values and then disabled to stop the user breaking the logic.

Simply puting an onSubmit functions that turns the CHECKBOXes Disabled status back to FALSE prevents this from happening.

Wednesday 9 April 2008

Controlling the use of BACK and FORWARD on AJAX pages

Here is a wee trick that will have me branded the demon of scripting cos it is (i am told) very naughty to play with the action of BACK and FORWARD and REFRESH buttons.

This method works on both IE and FF I believe (well the modern ones).

Basically this came out of a need to stop users, who being users, will click BACK and FORWARD REFRESH with gay abandon usually at the most inopportune times, even more so when it as an AJAXy form.

Here is the code.. Bung it in your [head] Section
[script language='javascript']
window.beforeunload = isthatwise;
window.onunload = smug;
function smug(){
alert("OK you know best.. Bye-Bye Now!");
}
function isthatwise(evt){
return "Now listen you!\nThis is your programmer speaking\nI worked long and hard on this code\nand i think you maybe about to do something silly\nare you sure you want to do that?"
}
[/script]



I think it would probably be a good idea to change the text of the messages unless your users are as understanding of my foibles when it comes to error messages as mine are.

And then put this on your BODY tag

[body onBeforeUnload="return smugcomment();"]

When you get to a point on your form where unload is ok simply set the two events to null

window.beforeunload = null;
window.onunload = null;


It is also wise when AJAXing to ensure that there is no page cacheing so that they (the users) cant actually go back to a page in the middle of a transaction.

Thursday 27 March 2008

The never ending Web page like Gmail's on domino, is it feasible?

Today I have been thinking about SJAX (I think it should be more corretly PSJAX Pseudo Synchonous JAX) and methods that would allow me to keep the connection open to a client from the server.

I was asked about the feasibility of creating a real time trading room where Ebay Type bidding takes place, but in real time. Bidding rooms last no longer than an hour multiple supplier attendee's each able to see the requirements but not their competitors bids. Where like betting in poker the "current bidder" is passed between the participants.

My intial reaction was to think Java Applet .. then a couple of seconds later an AJAX pages with a timer that polled the server every couple of seconds.. and then what about the never ending web page senario I read about in connection with gmail.

My idea goes along these lines.. (I am sure there is a flashy geeky name for this .. apologies i have no idea what it is)

01. Client logs on to server
02. Client enters bidding "room" by using the normal AJAX method of calling a web agent
03. The agent (one per client) runs and creates Send 99% of the HTML,CSS,JS for the ROOM
04. Then it goes into a loop without closing the connection
while
{
reads "room control" file
is there a response for this client
YES - Send response in an script envelope like this [script]do([actionkey],[actiondata])[/script]
wait for n seconds
}

04. On the client.. I think this is what GMAIL does .. I have a JS function called do() that processes the data as it comes down and does whatever it needs to do based on the key.

05. The client sends data up stream not to this agent but another normal AJAX agent. That agent processes the data and closes with a nominal response BUT updates the ROOM CONTROL file accordingly so that the user gets the response as a DO() command.
this would be how the agent would terminate normally when the client sends a CLOSE request

Now I havent had a go at doing this yet, i will prob have a bash this weekend and see at least if it works. But if any of you have done anything similar I would appreciate your feedback, esp on the admin front. Having long running agents is not a problem for me as a DEV as an ADMIN it makes me nervous, very very nervous.

Steve

Monday 24 March 2008

Converting Web Posted Data into a Notes List collection in an agent

When you use a POST (or for that matter GET) transaction directly to an agent from an AJAX connection call you generally have to do something with the data. I find that converting the arguement name value pairs into a Notes List makes life so much easier. This is how I do it,

' *****************************************
Dim ThisSession as new NotesSession
Dim ThisDoc as NotesDocument
Dim TheParms List as String
' *****************************************
Set ThisDoc = ThisSession.DocumentContext
EvalString = |@URLDecode("Domino";"|+ThisDoc.Request_Content(0)+|")|
RawParms = Evaluate(EvalString)
AmpArray = Split(RawParms(0),"&")
Forall pairs In AmpArray
EquArray = Split(pairs,"=")
TheParms(EquArray(0)) = EquArray(1)
End Forall
' *****************************************

When this code is run you have a Notes List that comprises of all the argument pairs Posted
to to the agent.

Say for example the posted data was :

type=GD&vn=wibble&qi=wobble&dt=01010111

the resultant list would be :

TheParms("type") contains GD
TheParms("vn") contains wibble
TheParms("qi") contains wobble
TheParms("dt") contains 01010111

You can then access any of the arguments passed by name.

If you want to use this with a get you can get rid of the lines

EvalString = |@URLDecode("Domino";"|+ThisDoc.Request_Content(0)+|")|
RawParms = Evaluate(EvalString)
AmpArray = Split(RawParms(0),"&")

and use the Query_String_Decoded cgi variable

AmpArray = Split(ThisDoc.Query_String_Decoded(0),"&")

However remember that unlike the POST the GET string will start with a "&" so your ForAll
will need to test for AmpArray being equal to "" to avoid the first element of the AmpArray.

Steve

Friday 21 March 2008

Thinking about Views, particularly large ones

A few weeks ago i blogged about very large datasets in views, that post came from a desire to maximize performance without usability in a web client. Nathan Freeman amongst others pointed out that very large views should really have a filtering system in both the notes client and on the web.

Thinking about this yes the notes client does make you lazy, categorized views work are easy to get around in, users are used to them and we as developers sometimes fall prone to following the path of least (in this case user) resistance.

So over the past few weeks I have been doing some head scratching about the whole UI thing. Spurred on by posts that posted this toon about design I have tried to do some paper prototypes about a new way (for me) of looking at view navigation.

Needless to say I tried to avoid thinking about coverlfow for fear of band wagon jumping .. that and I having used it on my own iPlod the novelty lasted about a week mainly caused by to many albums to be able to recognize all the covers that and i couldn't be arsed spending the time to get the album art. The more I ignored it the more I came back to variants of the same thing as a potential good idea.

This is the idea I have is something like this:
When the control is unloaded it looks like Fig 1
The user selectes "Content" or "Actions"

Clicking "Content" loads the scroll to The first Level Document types like in Figure 2. For Example approvals , requests etc

Clicking on the scroller moves thru the choices

Clicking on the picture loads the Scroller with the next level down of categorisation.

Using keys or the mouse wheel moves the user thru the levels ... no quite sure how this would work.. prob via a cache.




There would also be a breadcrumb trail below the control So the user would have a visual representation of where they were.

Keyboarders could type "App.." and the scroller would postion the flow at Approvals and you could also use <- and -> to navigate thru the options.

Clicking on Actions would do give the user a list of actions available like .. Create new .. Email to .. etc that would be used in the same way.

Below the control there would be the space where the results of the user selection would appear in table form.

I know this is do-able with a composite application. But i am thinking of doing this all in JS so that the V6 and V7 population can us it as well.

I have the cover flow bit 70% done (for the web) the resizing animations are proving awkward in JS, but i will have a play over easter and see if I can get to grips with that. I am still not sure whether this will be a runner usability wise .. there is rather a lot of clicking

If I manage to get something working i will pop it onto OpenNtf and let the world play with it

Thursday 13 March 2008

My NamePicker OpenNTF project updated and an apology

Just upgraded my NamePicker on Openntf to V1.2.4 because Martjin De Jong wanted keyboard controls in the drop downs, so I added them, which is a bit embarrassing cos i really should have thought of that myself ... god and i used to be a mouse hater! Ohhh its not lovely like what Chris creates, its not particulary whizzbangy like Jake does and not state of the art like what IBM does... but it does what it says on the tin (apart i see from Safari) its mine and it is my first bit of Open Source and 590 people have downloaded it.... :-)

And while i am at the Ooops.. an apology to Carl Tyler ... alas your mail from OpenNtf notifying me about the safari problem with Name picker ended up in my Junk Mail folder, not quite sure why. So I am downloading Safari and I will have a look at the problem this weekend rugby-permitting 8o) . Sadly I dont have a mac or access to a mac to test it on an "apule"... Does anyone know is Winderz Safari near as damn it the same as Apule Safari as far as its JS and DOM handlers are concerned?

Slán
Steve

Thursday 6 March 2008

Log In into Domino using AJAX sample code available


With reference to the post two down from this i have placed a small sample NSF in the "code bin" of OPENNTF.... here

If you are interested in how I got a log in screen like the screen shot above, then this download will show you how.

Down load the file
Sign it with an ID for your organisation
Change the ACL so you have authoritty to it
Change the DEFAULT access to be NO ACCESS but leave the READ PUBLIC DOCS ticked
Place it on your server
Goto http://[yourserver]/[your path]/wteam.nsf/wteam.html
Try to sign in
If successful you should see some information from the PAB appear in a panel under the logon

All my code is in wteam.js, wteam.css and agents wt_logonok and wt_getuser.
It is all fairly self explanatory if not ping me with the details.

Steve

Log In into Domino using AJAX

The other gurus have probably covered this already, but I only worked this out today and if you haven't this is really a rather cool trick.

Domino allows you to login to the server using the following URL structure if you have session authentication turned on.

http://[server]/names.nsf?login&username=[username]&password=[password]&redirectto=[url]

and similarly logout using

http://[server]/names.nsf?logout

So it occured to me that if the browser allowed a session cookie to be set by and AJAX call to these URLs then it would be possible to override the default notes logon and have an application specific login or out functions on any page or form.

So basically what you do is use this to your advantage by constructing a AJAX connection using whatever framework you want using either GET or POST that calls the LOGIN or LOGOUT parameter and populate the &username= and &password= from values in your form. Now comes the cheeky part, instead of a page have an agent in the &redirectto= parameter. This agent is a very simple beast like this

Sub Initialize
Print |Content-Type:text/plain|
Print |***Logged IN***|
End Sub


This will be returned to the browser as plain text .. do a simple test for ***Logged IN*** being present and act accordingly by redirecting to another page or doing something on the page your are on This text will ONLY be present if you logged on successfully.. if your sign-on fails the text is not there so you can act accordingly for a log-in failure.

You do have to remember to make your login page or form available to Public Users and ensure
that all other pages and views are not available to Public users. Also setting the ACL of your application so that DEFAULT has no access but IS allowed to READ PUBLIC DOCS.

I have used this technique in an application and it works, sadly I cannot share the application it being company property and all that. But if anyone is interested I could throw together a sample file and post it in the code bin on OpenNTF .. let me know if you want it.


** UPDATE **
As has been pointed out in the comments by both Radu Cadiru and Jake Howlett. There are BIG security issues with using the GET option in that this will expose your USERNAME and PASSWORDS both on the network and in the various web logs on the server and in browser caches.

I would strongly recommend you use the POST method to pass the data and to do so over your SSL port. *** Especially if this in on the INTERNET *** This will make it difficult for your user's username&password data to be "snooped".




Slaun
Steve

Tuesday 4 March 2008

Jake Howlett's Frameworks Poll and other questions

Something close to my heart came up as browsed the PL feed at coffee time today.
Jake Howlett has asked a very pertinent question in a poll .
What framework should codestore downloads use?
This is something that has troubled me for some time now. I have divided views on which one is best because some are better at one thing than others - by better in this case I generally mean easier for me and/or gives a better result for the user experience.

I encourage all your developers to nip over and take the poll on the link above.
I for one will be watching with interest.

It also leads me on to thinking how this will dovetail into the the whole "interface matters" ethos espoused by the like of Chris Blatnik we can now do all sort of whizzbang web UI's some of which are difficult to replicate in the Domino client. Do we as developers push the lovely and usable web things we can now do, or do we concentrate on the Dom Client making it as lovely and usable as we can? Do we have to sacrifice look an feel for function (or vice a versa)? In which do we lead our project planners and managers? Widgetry and Composites have further complicated matters in that we could potentially have widgets that will greatly supplement our Dom Client UI's ... oh it is going to be an exciting few years! :-)

I don't have answers for these questions but I would be interested to hear where the Domino community believes the thrust of new development will take us in the next few years, web facing, client facing or a mixture of the two.

Steve

Sunday 24 February 2008

AJAX and viewing very large datasets (50K+ documents)

Problem: How to facilitate a user request to get rid of the "paging" options at the bottom of a AJAX enabled web view and allow them to use only the scroll bar to navigate very large datasets (50k + documents).

I have been thinking about this all weekend and have drawn numerous wee drawings trying to get my head around what is required. The bull in a china shop approach would be download the 50k+ view data and then allow the JS or XSLT to render 50,000 documents .... Tried it .. OOOOO it was slow and required lots of answers to "this script is taking a long time it may be looping do you want to end it?" messages.

So the next option and the currently active one is to have 20 records per page and have the standard sort of page that has Page x of 2500 and allows the user to set x the background process goes off gets that page from the server and displays it. This has the benefit that the browser only has to get 20 documents from the server and render them which is quick and easy. BUT the user group doesn't really like this and reports back that they prefer a UI that has a scroll bar. Their main complaint is when you are looking at a Categorized view and the category is large when expanded then the data may be take several pages which you have to shuttle back and forth between.

And finally the last option.. what the user wants... a scroll bar option like in the client...This is the idea I am playing with at the minute,all be it as a mind game. My thoughts are these.

  1. To ensure the Scrollbar accurately reflects the size of the dataset the holding element must be as near as possible the correct size to contain the dataset, but it does not necessarily need to be full of data. The size of this containing object will equal
    height of a single row * total number of rows in the dataset

  2. The viewport need only contain the grid of Visible Rows say for example a table of 20
    rows. The size of the viewport if defined in rows is
    height of a single row * total number of rows in the viewport

  3. When a scroll bar is clicked on either the down or up arrows the viewport is moved up or down by one row.

  4. When the scroll bar is clicked either above or below the scroll tab the viewport is moved up or down by one page.

  5. The current pixel position of the scroll bar in the holding element is returned by the scrollTop value. This can be used to work out the row that is at the top of the view port
    current position as returned by scrollTop / height of a row given as an integer value
that need to have a height of 50,000 *14 = 700,000px
So...lets say we have a view that is 50,000 rows long, we want to display this in a grid that has 20 visible rows and each row has a height of 14px.

Step 1 - Create a viewport which we know needs to have a height of 20*14 = 280px
Step 2 - Inside the viewport create a holder [div] which has a height of 700000px (50,000*14)
Step 3 - Place a grid inside in the Holder [div] which contains 20 rows 14px high
Step 4 - Register an event handler on the "scroll" event of the Holder [div]
Step 5 - When this event is triggered return the scrollTop and calculate the new starting row.
Step 6 - Ask the server to return 20 view entries from this starting row
Step 7 - Populate the table with these entries.
Step 8 - Position the table at scrollTop,0 within the holder [div]

Basically this will move the table which holds only the data visible in the UI to be centered in the viewport [div], the holder [div] has a height of 700,000px but only contains the table of visible data thus preserving the scale of the scroll bar without the requirement for having it full of data.

I have had a play and this seems to be "do-able" although there are some browser specific niceties that I have to get my head around as well as how to do interesting things like sortable columns, searches and how to return categorized views.

Has anyone else done something similar I wonder or would anyone be interested in the proof of concept I am working on? If so let me know ....

Ohh I wonder ...how does Ext.ND cope with large datasets?

UPDATE - In the comments below Joerg Michael didn't think this was a good idea...and Nathan Freeman followed up with the the point that ... perhaps the Notes Client view should be redesigned too.. :) Bum.. I was distracted by a user saying something that sounded like a good idea.. LOL...
Oh well ...being distracted are sunday afternoons in Feb are for :) However a non-notes solution of a similar nature has been looked at and put forward as a user extension for Ext as pointed out by Rich Waters as something to look at and as a point to think on... :)



Tuesday 19 February 2008

NiftyFifty - I have finally started something

After my comversation with Chuck re the niftyfity on lotusmb
Having been delayed by a recalcitrant server at work and the start of a major project I eventually got around to starting to think about what Chuck#s suggestion should look like. He thought that a simple something that fell between a blog and a wiki.

I started with the front end UI yesterday and have a fair bit of the HTML and JS sorted at least in my head. You can have a look at the rough start i have made here
Please note the following..
1. This is not yet "notesed" it is a static page with a 1000 record data island and some JS
2. You can log on either as admin with a password of admin or as user1 with a password of user1
however nothing much will happen other than the menu bar changing :)
3, The navigation buttons dont work yet.. but the search selects do and number of records per page do if you click on the arrow that points right after the selects


Have a look see.. and if this grabs your fancy as an idea for a nifty-fifty app let me know.. infact let me know if you hate it as well... LOL...

Steve

Friday 15 February 2008

AJAX YAHOO Domino - a Beginner's Guide Conclusion

OK in the Previous posts in this thread I worked my way thru a worked example of using the YAHOO UI framework to get data from a domino server. In summary what you do is

a. Place the required Yahoo JS files in your application (or access them from the YUI site)
b. Create a global Var to hold your returned data in
c. Create the SUCCESS var containing the code to run when you get data
d. Create the FAILURE var containing the code to run when the connection fails
e. Create the CALLBACK var containing the vars from (c) and (d) above along with any arguments
f. Create an agent to do the work on the server
g. Create a JS function to process the data when you get it back.

And that is really all there is to it.
This was a very simple example but you can, like in the case of the Ext.ND project on OpenNTF get really clever with the YAHOO UI's myriad of other capabilities. But if all you want is data the method I described below should be ample to get you started.

So all you V5 and V6 people out there that would like to try your hand at AJAX don't be shy, it isn't that hard and if you get stuck ... well please drop me a line and I will do what I can to help. :)

AJAX YAHOO DOMINO - A beginners Guide 7

Righty Ho!

We have built the AJAX objects
We have built an event that instantiated the AJAX objects and passes the request to the server
We have built a Web Agent that catches, processes the request and returns it to the browser.When When the data comes back it is picked up by the success function code which loads the JS we prepared on the server into the DOM.... what now?

Well lets do something with the data!

Cast your mind back to this bit of code

var mySuccessCode = function(o)
{
ProcessMe = evaluate(o.responseText);
RunMe = evaluate(o.argument.nextFunction);
}


The second line RunMe= is the important bit here, once again we use the JS evaluate function to "run" whatever is in o.argument.nextFunction. Which if you remember we set here

myCallBack.argument.nextFunction="dspCars(o.argument.target);"


The last bit of coding we need is the dspCars() function. As you can see the function is passed o.argument.target which was set to be "fordinfo" back in the getData() function.The code looks like this : -


function dspCars(target)
{
myHTML = "";
myHTML = myHTML+"[table border='0' cellpadding='0' cellspacing='0']";
myHTML = myHTML+"[tbody][tr][td]Model[/td][td]Year[/td][td]Price[/td][/tr]";
for(t=0;t[cardata.length;t++)
{
myhtml=myHTML+"[tr]"
myHTML = myHTML+"[td]"+CarData[t].Model+"[/td]";
myHTML = myHTML+"[td]"+CarData[t].Year+"[/td]";
myHTML = myHTML+"[td]"+CarData[t].Price+"[/td]";
myHTML = myHTML+"[/tr]";
}
myHTML = myHTML+"[/table]";
document.getElementById(target).innerHTML = myHTML;
}


(remember to replace all the [] with <>)
This simple agent build a text string of and HTML table with the contents of the CarData array and then "injects" it into the target element.

and as Elmer Fudd would say ... thats all folks...

AJAX YAHOO DOMINO - A beginners Guide Part 6


Continuing with the worked example .. the next thing we need is an agent to do the work If you remember back in Part 5 we created a URL that called an agent called getDataLS and that is what you want to create next.

Create an agent and give it the details opposite
and make it a lotusscript agent








Then in the INITIALISE section code something like this

Dim ThisSession As New NotesSession
Dim ThisDoc As NotesDocument
Dim ThisDB As NotesDatabase
Dim ThisView As NotesView
Dim ThisCollection As NotesDocumentCollection
Dim CarDoc As NotesDocument
Dim ParmString As String
Dim ParmArray As Variant
Dim MakeKey As Variant

Set ThisDoc = ThisSession.DocumentContext
Set ThisDB = ThisSession.CurrentDatabase
Set ThisView = ThisDB.getView("autos")

ParmString = ThisDoc.Query_String_DeCoded(0)
ParmArray = Split(ParmString,"=")
MakeKey = Split(ParmArray(1),"&")
Set ThisCollection = ThisView.GetAllDocumentsByKey(MakeKey(1))

Print |Content-Type:text/plain|
Print |CarData.length=0;|
If ThisCollection.count <> 0 Then
Set CarDoc = ThisCollection.GetFirstDocument()
Do While Not (CarDoc Is Nothing)
Print |CarData.push( { Model: "|+CarDoc.Model(0)+|",Year: "|+CarDoc.Yead(0)+|",Price:|+Format(CarDoc.Price(0),"#####0")+|} );|
Set CarDoc = ThisCollection.GetNextDocument(CarDoc)
Loop
End If

Lets look at this agent.

The DIMs are doing what DIMs always do
The SETs similarly are SETing things. of note is the view, this is a standard notes view that selected Car forms and has the first column set to the MAKE field and it is sorted

I load a CGI field, these fields are automatically added to the document extractable by the session's documentcontext. Query_string_decoded holds the data passed using the URL
from the ? onward.

Query_String_Decoded(0) in this instance will hold
openagent&key=Ford&seed=1234567890

I then SPLIT this on the & Character into an array called ParmArray
So ParmArray now contains

ParmArray[0] = "openagent"
ParmArray[1] = "key=Ford"
ParmArray[2] = "seed=1234567890"

The bit i am interested in is in ParmArray[1]
So I split this down on the = character into array MakeKey which now contains

MakeKey[0] = "key"
MakeKey[1] = "Ford"


As I now have the Key with which to search my view I create a NotesDocumentCollection
using that key.
 Print |Content-Type:text/plain|
Print |CarData.length=0;|


The lines above are the start of the data that will be returned to the browser. The first line tells the browser to expect plain text. You could set this to use XML at this point, but for the sake of this example we are using plain text.

The second line sets the public array to have no entries (0 length)

Then I loop around the documentcollection and for each document found I return using PRINT a raw javascript statement. If i substitute the field names for values the browser would get something like this

CarData.length=0;
CarData.push( {Model: "Focus",Year: "2005",Price: 2500) );
CarData.push( {Model: "Puma",Year: "2007",Price: 3800) );
CarData.push( {Model: "Granda",Year: "1973",Price: 100) );
CarData.push( {Model: "Ka",Year: "2006",Price: 1500) );


When the loop finishes and all the PRINT statements processed the agent finishes
and the PRINTed data is returned to the browser by the HTTP server.


Because data was successfully received by the browser the CallBack.success code is triggered and the data returned (which is in o.responseText) is "evaluated" which in effect runs all the lines of JS that you sent back from the server.

Once this has happened the DOM now contains a popluated CarData array which you can
do something with which i will talk about in the next post.

Wednesday 13 February 2008

AJAX YAHOO DOMINO - A beginners guide Part 5

Asking the server for data ...

OK for the sake of this example lets say we want to get some data on Fords from a database of used cars. So we put a button on our web page and when a user clicks a button it will go off to the server and return a list of data about all the documents relating to Ford cars.

First we place a [div] on the page to put the data in followed by a button that the user can click to get the data from the server.
<div id='fordinfo'></div>
<input type='button' onclick="getData('fordinfo','Ford')" value='Get details of Fords'>
Then we go back to the JS header of our page and code up the getdData() function
function getData(target,myKey)
{
uniqueSeed = new Date().getTime();
myCallBack.argument.target=target;
myCallBack.argument.nextFunction="dspCars(o.argument.target);"
url = Location.href.substring(0,location.href.indexOf(".nsf") + 4);
url = url+"/getDataLS?openagent&key="+escape(myKey)+"&seed="+uniqueSeed;
request=YAHOO.util.Connect.asyncRequest("GET", url, myCallBack)
}
Ok what this bit of code is doing line by line
Line 1: uniqueSeed = new Date().getTime();

I build a uniqueSeed value from the current time. I do this so that i can add it to the end of the url so that the URL becomes unique and is never (esp in IE) retrieved from the cache. It plays no part in getting the data other than to ensure "fresh" data.

Line 2: myCallBack.argument.target=target;
I am storing the ID of the DIV i am going to populate so that I can use it later.

Line 3: url = Location.href....
I am building the URL that i am going to pass to the server. This line gets me everthing up to and including the .nsf from the current URL.

Line 4: url = url+"/getDataLS?openagent&key....
I add the agent that I am going to call to the URL along with the key string (which in this example will be FORD along with the unique seed to fool IE into ignoring the cache.

Line 5: request=YAHOO.util.Connect.asyncRequest ...
This is the call to the YAHOO process that will send the request to the server. Note the parms that are passed to it
"GET" means that it is GET rather than a POST operation.
url is the url i have constucted along with the key pairs
myCallBack is the CallBack object I built earlier.

When this function invokes the YAHOO.util.Connect function control returns to the browser and we wait for data to be returned.

...next... the LotusScript Agent

AJAX YAHOO DOMINO - A beginners guide Part 4

... Continuing on from the last post ...

OK you have now got your NSF with the YAHOO UI files imported and embedded in the form or page you want to have some AJAX functionality on ... what now?

Part 4. Creating the YUI AJAX objects you will use

There are a couple of Javascript objects you have to create before you can "talk" to your server

1. Some code to run when you get data back from the server
2. Some code to run when the call to the server errors
3. A place to hold information you may rely on later

The important thing to remember here is that A of AJAX stands for Asynchronous. Which means in basic terms when you send your request to the server the calling JS ends
and the browser sits twiddling its thumbs. Because the calling procedure has ended any variables you set up inside that calling function disappear. Which is rather unfortunate if you are relying on them in the code you use to process the data you get back from the server.

So your AJAX objects need to be defined so that they are global and not private to a particular function. Generally you do this by defining them before you define any functions. They can exist as explict vars or as part of a JS class but either way you need to ensure that they are globally available in the DOM or you will run in to problems.

If you are not familiar with JS the next bit may be a bit difficult to follow.
JS variables can hold just about anything ... including code ...
Soooooo you can set up a variable that rather than hold a number or the name of your pet cat holds a chunk of executable code ... OK?

Before we do the AJAX objects we have to create a global variable to store the returned data in in this instance i will use

var CarData = new Array();



The first variable you need is one thats holds some executable code. You can call it whatever you want so it will appear as something like this. Dont worry about what the code does just at the minute

var mySuccessCode = function(o)
{
ProcessMe = evaluate(o.responseText);
RunMe = evaluate(o.argument.nextFunction);
}
This is the code that will run when data is returned from the server.
Please note that the (o) is a lower case letter o not a zero!
Next comes
var myFailureCode = function(o)
{
alert(" **AJAX Error ** \n_
Please report this error\n"+o.tId+"\\" _
+o.status+"-"+o.statusText);
}
This is the code that will run when something nasty happens to the AJAX request, like the server is down or the user has pulled the network cable out of their PC.Again ... Please note that the (o) is a lower case letter o not a zero!

And Lastly, we wrap these two vars up in another object that we will pass to the YUI connection function.
var myCallBack = {
success: mySuccessCode,
failure: myFailureCode,
argument: {
target: "",
nextFunction: ""
}
}
As you can see this object has 3 Properties, success, failure and argument.

success and failure hold the code we have already defined in the mySucccesCode and myFailureCode variables.

The last property argument is another object which is entirely user definable. You can create as many properties as you need. For the sake of this example I am using 2 target and nextFunction. You will see how these properties are used shortly.

And those are all the JS objects defined and they should look like this .. for now put this code in the JS header section of the page or form you want to have an AJAX function on.
var mySuccessCode = function(o)
{
ProcessMe = evaluate(o.responseText);
RunMe = evaluate(o.argument.nextFunction);
}
var myFailureCode = function(o)
{
alert(" **AJAX Error ** \n_
Please report this error\n"+o.tId_
+"\\"+o.status+"-"+o.statusText);
}
var myCallBack = {
success: mySuccessCode,
failure: myFailureCode,
argument: {
target: "",
nextFunction: ""
}
}
and now on to Part 5: Asking the server for data ...

Disqus for Domi-No-Yes-Maybe