Wednesday, April 24, 2013

Deferred Loading

On my job we are trying to decrease time for loading pages as much as it is possible, we simply want 'fast pages'. We don't want our users waited for 2 seconds each time they load page. We are focusing to keep not more then 0.5-1 second per page and we are doing really a lot in that area. Nowadays It's quite common for most of websites to include javascripts just in head area (or at bottom area) as static html so each time we load pages they will be not responsive till all resources will be loaded. I want to share how to load of javascript files (or any another resouces) just after page loads. It could increase speed dramatically. This solution loads all javascrip files deferred after page load on onload event. That snippet should be minimized and be present on every page where you want to use deferred loading.

Snippet of deferred loader
(function(){
 function deferred(success){
    if (typeof window.onload != 'function') {
   window.onload = success;
  } else {
   var old = window.onload ;
   window.onload = function() {
    old();
    success();
   }
  }
 }

 function getScript(url,success){
  var script=document.createElement('script');
  script.src=url;
  var head=document.getElementsByTagName('head')[0],done=false;
  script.onload=script.onreadystatechange = function(){
    if ( !done && (!this.readyState || this.readyState == 'loaded' || this.readyState == 'complete') ) {
   done=true;
   success();
   script.onload = script.onreadystatechange = null;
   head.removeChild(script);
    }
  };
  head.appendChild(script);
 }

 function getScripts(urls, success){
  var total = 0;
  function trySuccess(){
   total++;
   if(total == urls.length)success();
  }
  
  for (var i = 0; i < urls.length; i++) {
   getScript(urls[i],trySuccess);
  }
 }
 
 var DeferredLoader = window.DeferredLoader = {};
 DeferredLoader.getScript = getScript;
 DeferredLoader.getScripts = getScripts;
 DeferredLoader.deferred= deferred;
})();

How to use loading, in that example we load jQuery, then when it's loaded we load kissmetrics libraries and only then utils.
var urls = {
 jquery: "/javascript/jquery-1.9.1.min.js",
 dependent: ["/javascript/util-2013-04-10m.js"],
 kissmetrics:['//i.kissmetrics.com/i.js','//doug1izaerwt3.cloudfront.net/' + window._kmk + '.1.js' ]
};

DeferredLoader.deferred(function () {
 DeferredLoader.getScript(urls.jquery, function () {
  DeferredLoader.getScripts(urls.kissmetrics, function () {
   DeferredLoader.getScripts(urls.dependent, function(){})
  })
 })
})

Wednesday, March 06, 2013

Rewriting URL in Domino using DSAPI

I will briefly describe what we were aiming to achieve. In order to open page with parameters Domino requires to add ?open or ?opendocument action and only after that Domino allows to add parameters. It's quite annoying for us due to some integration with another systems, those systems expect they can simply add parameters just after our pages, i.e.: http://www.host/page?parameter=123 etc. Also important reason - we simply do not like this ?open or ?opendocument in URL.

we want to be able to that:
www.host/page?opendocument&parameter=123 ==> www.host/page?parameter=123

I got couple helpful comments in my previous article about URL control in Domino, that helped me to look on different solutions, thanks guys. However I decided that those solutions a bit complicated to setup and they could do some impact on page load time.

I've been working on DSAPI solution last days and finally with some help I've made it! Now we have full control with our URLs, at least I've such feeling :). Let me share my small success to all of you.

Here you can find main steps you need to do. Please keep in mind, I've updated my code a bit as our logic has many rules when exactly to add parameters.

1. Enable flag to catch Rewrite URL event.
filterInitData->eventFlags = kFilterRewriteURL;
2. Link 'rewrite URL' event with you function.
DLLEXPORT unsigned int HttpFilterProc(FilterContext* context, unsigned int eventType, void* eventData) {
 switch (eventType) {
  case kFilterRewriteURL:
   return RewriteURL(context, (FilterMapURL *) eventData);
  default:
   return kFilterNotHandled;
 }
}
3. Finally the main logic, that makes URL rewriting.
int RewriteURL(FilterContext* context, FilterMapURL* pEventData) {
 FilterParsedRequestLine pReqData;
 unsigned int errid=0;

 // if there are no parameters in URL - nothing to do.
 if (strstr(pEventData->url, "?")==NULL) return kFilterNotHandled;
 // read request as we are going to update query.
 context->ServerSupport(context, kGetParsedRequest, &pReqData, NULL, NULL, &errid);
 // if query starts from opendocument - nothing to do
 if (strncmp(pReqData.pQueryUri, "opendocument", strlen("opendocument"))==0) return kFilterNotHandled;
 // adding opendocument before query and put result in pEventData->pathBuffer
 sprintf(pEventData->pathBuffer, "%s?opendocument&%s", pReqData.pPathUri, pReqData.pQueryUri);

 return kFilterHandledEvent;
}
Solution we did works like a charm and what is very important it does not affect page load time (we measured of course)

Related topics
DSAPI for Domino
Solution for Lotus Domino to the trailing slash problem
Replacement for DSAPI in Java/XPages

Sunday, March 03, 2013

Mongodb - Enable Authentication

Basically it is very easy to do,
  • 1. open mongodb shell
  • 2. open admin db and add admin user (you need to have 1 user otherwise you can' lose access to your databases at all)
  • use admin
    db.addUser("admin","12345")
    
  • 3. Enable authentication auth=true (simply un-comment it) in config file 'sudo vi /etc/mongodb.conf', save changes and restart mongodb service
  • sudo service mongodb restart
    
For more information please read Security Practices and Management

Wednesday, February 27, 2013

Fighting for control of URL in Domino

We have really annoying problem for years with our URLs on all websites based on Domino. We use classic approach because we want control all tags + we like jQuery more etc. Our problem is about mandatory action [?open | ?opendocument] for pages with parameters, so if you want to add parameters to your page (i.e. param1=123) you have to add [?open | ?opendocument] just after your URL and only then you are allowed to add parameters.

Not really a huge problem, however we want to use new tracking code from google. That tracking has problems with [?open | ?opendocument]: it does not work correctly in case if first parameter is ?open. So now its blocker for us and we want to fix it for all another cases as well. We want to have possibility get rid off ?open | ?opendocument

Question in few words: "is it possible to get this URL working?"
http://www.e-conomic.com/accountingsoftware?parameter=123
instead of this
http://www.e-conomic.com/accountingsoftware?open&parameter=123

We've tried redirect, substitutions - no success ofc :(.

Next in my queue is DSAPI and I'm sure it can solve that problem (at least from documentation) however I'm not able to do that due to my experience with DSAPI and very very low information in the web.

I've played with different events in DSAPI: kFilterStartRequest, kFilterRawRequest and kFilterRewriteURL and tried to change incoming URL from request but did not success with it. Does any of you guys can give me tips :) what I do wrong or maybe there is another solution how to achieve that quest?

Tuesday, February 05, 2013

Nodejs and compression of HTML, JS, CSS

To decrease loading time for pages, it is always nice to minify your HTML, CSS and JS. Also to decrease number of requests we inject our minified CSS/JS directly on our pages (ofc we will do that unless our CSS/JS have small size), so minus 2 requests to all pages.

Now time to write couple lines of real code

1. UglifyJS - compress JS

var uglifyJS = require("uglify-js");

var result = uglifyJS.minify("filename.js");
console.log(result.code);

2. Sqwish - compress CSS

var sqwish = require('sqwish');
var filename=app.get('filename.css');
fs.readFile(filename, 'utf8', function(err, data) {
    if (err) throw err;
    var minifiedCss = sqwish.minify(data)
    console.log(minifiedCss);
})

3. HTMLMinifier - compress HTML

var htmlminifier = require('html-minifier');
var minifiedHTML = htmlminifier.minify(data, {
 removeComments: true,
 removeCommentsFromCDATA: true,
 collapseWhitespace: true,
 collapseBooleanAttributes: true,
 removeAttributeQuotes: true,
 removeEmptyAttributes: true
});
So at the result we decreased size of our pages a lot and also decreased number of requests which is also nice, we all love "fast pages".

Wednesday, January 30, 2013

Node.js first experience and first simple project

From 2013 I've started to learn (as much as I've free time) Node.js. 'Domino/Notes' still my main, however it is always nice to learn something new.

Node.js is a platform built on Chrome's JavaScript runtime for easily building fast,
scalable network applications. Node.js uses an event-driven, non-blocking I/O model 
that makes it lightweight and efficient, perfect for data-intensive real-time 
applications that run across distributed devices.

Together with Andrew Kuba (who guide me how to 'node') we are doing simple website for one game which is very popular right now, we are aiming to have hundreds users/month :) at some points + it is always nice to do something that is real and online
We are using only couple modules for our first application:
  • Express - minimal and flexible node.js web application framework, providing a robust set of features for building single and multi-page, and hybrid web applications.
  • Underscore is a utility-belt library for JavaScript that provides a lot of the functional programming support that you would expect in Prototype.js (or Ruby), but without extending any of the built-in JavaScript objects
  • mustache is a logic-less templates.
  • yuicompressor compressor to minify our JS/CSS (we do compress all our CSS/JS and put it directly on page to avoid additional lookups)
  • html-minifier compressor to minify our HTML
We do not use database right now, however we are planning to use mongodb with mongoose in near future.

Pick LoL is our website (first version) we are working on to get some experience with Node.js

During next couple months I will write more posts about node.js which I'm going to like hopefully :).

Monday, December 17, 2012

First couple days with IBM Domino Designer 9.0 Social Edition

Worked 2 days already with Domino Designer 9 (I do not really care about changes in Notes 9, as I believe in 'web' direction). I did not find something really new/impressive for developers, however worked only 2 days and also I do not forget that it is just a beta. My impression:
  • It is fast enough, however I do not feel difference compare to my 8.5.3, perhaps my laptop just too good.
  • Ext Library is included by default.
  • I've also read that now we have an API (Java, LS, C API) for C&S, would be great to have it few years ago, now its too late :), but still thanks!
  • Special places for JAR, I guess it is only for xPages, but not for Java libraries/Agents, need to verify.
  • Server-side JavaScript debugger for use with xPages (need to verify how it works, but options are present, I saw that :))
  • $DesignerVersion still says: "8.5.3" when you save elements. I think that would be changed with Release candidate.
  • There are some new options to "Manage working sets drop-down" I really like, waited for those changes for a long time.
  • Application Properties got 'Xsp Properties'.
  • There are also changes to xPages, but I had no time to look on them.
  • All 'old staff': old window to work with @formula, properties dialog still looks same (and that is sad).
Some words about API for C&S.
I've been working on synchronization Lotus Notes 6.5-8.5 Calendar & Scheduling with huge CRM on my previous job (synchronization in 2 side, from LN to CRM and back) and we spent months to manage that correctly, oh dat recurrent events :), it would help us really a lot if we get such API earlier.

I've read also on some blogs that Domino 9 may have dojo 1.8. which would be nice to have and use.

That's all for now.

Sunday, December 16, 2012

Moved from Ukraine to Denmark


From 1-st December I work and live in Denmark. It's really interesting experience for me and my family. I had been working with e-conomic from Kiev for more than 3 years and at some point company decided that it had sense to invite me to work in main office. Now I'm here, so wanna tell 'hi' to those who live here :)

Couple fresh photos of Copenhagen.

City is ready for Christmas:
Now most funny thing :), we met hundred well organized girls, they marched along the main shop-street of the city and cried slogans about Justin Bieber. It was really funny.

Tuesday, October 09, 2012

What is comfort zone for Domino developers our days?

Lotus Script is no longer in my 'comfort zone' anymore but Java/JavaScript. That's actually it. We already moved all (well 90%) of backend to Java. Now Lotus Script serves only to provide validation/picklist/msgbox on forms/views for existing 'classic' applications. Now we are slowly moving everything to web and I like that.

We are aiming in few years to let our users to un-install LN and simply use browsers and that would be perfect. That time we should have no even 1 line LS and @Formula.

Friday, August 03, 2012

Exception occurred calling method NotesAgent.runWithDocumentContext(lotus.domino.local.Document) null

Tried to run agent with 'context document' in xPage (via SSJS) and got this problem. I did not find a way how to solve that except to enable checkbox 'Run as Web User' for agent, however I need to run agent from 'signer' as 'runner' has Reader access and my agent update should document. It's terrible with this problem (if it is problem ofc :)). What should I do know?

Tuesday, July 03, 2012

ViewEntry and Show multiple values as separate entries

When your view has column with option 'Show multiple values as separate entries' and you use ViewEntry to read data from that column you will have a problem. Result of your getColumnValues() can be different, f.x. in 1 case it can be 'Vector' and in another case 'String'. It depends if entry was really split on few entries because of multi-value. I've lookup around and found this issue already reported on IBM ~3 years ago (IBM whats up?)

Full description of problem

Here is a solution I made
Vector v = entry.getColumnValues();
Object o = v.get(0);
String title = "";
if (o.getClass().equals(String.class)) {
 title = (String) o;
}
else if (o.getClass().equals(Vector.class)) {
 Vector tmp = (Vector)o;
 title = (String) tmp.get(0);
}

Monday, June 18, 2012

Content Is Not Allowed In Prolog

Got this issue in the morning. We have service that "aggregate" data from multiple RSS into 1 RSS. The issue appeared because at one of RSS we enabled encode option [encode UTF-8] but not [encode UTF-8 without BOM]:
encode in UTF-8
encode in UTF-8 without BOM.
our Java parse does not understand this BOM (byte order mark). So we just swtiched to one without BOM byte. I've made tests using this online tool, it worked just as I expected XMLValidator

Wednesday, June 13, 2012

Cool trick which I never saw in LotusScript. Pass function as parameter.

Read this code
'Comments for SetValue
Sub SetValue(src As Variant, target As Variant)
 If IsObject(src) Then
  Set target = src
 Else
  target = src
 End If
End Sub

'Comments for Test
Function Test(value As Variant) As Variant
 SetValue value, Test
End Function
You can call Test(now) or Test(customobject) or Test("ABC") it will return you just same object/value. nice, isn't it?
msgbox Test(now).DateOnly
msgbox Test("Helllo")
msgbox Test(customobject).customProperty
Do not see right now really huge benefits from this but just nice to know this.

Monday, June 11, 2012

Default sort order

Guys, does anybody make it (Default sort order) working? I played to much with it without success, my Domino server still ignore sorting (as Swedish) for my application.



Tuesday, June 05, 2012

Predefined NoteID for design elements and applications

Sometime those NoteIDs can be quite useful, so I decided to gather all of them into place I can easy find.

FFFF0002 "About This Database" document
FFFF0004 Default form
FFFF0008 Default view
FFFF0010 Database icon
FFFF0020 Database Design Collection (view)
FFFF0040 Database ACL
FFFF0100 "Using This Database" document
FFFF0800 Replication Formula

ReplicaID for few databases:

0000000000000E00 Mail database
0000000000000E01 Personal Address Book
0000000000000E02 Subscription Database
0000000000000E03 Bookmark

Friday, March 30, 2012

Create Lotus Notes views on fly

I'm wondering if somebody know how to use views that I created on fly, lets say we have document with embedded view which is not created yet. Before we open this document we create view (but simple triggering agent). However we can't use this view as embedded view on document till we reopen database. Anybody has any idea how we can avoid this problem?

Thursday, February 02, 2012

Hope to see this feature at next version of DDE

That is actually how it should be instead of keeping everything inside of Library. Do you agree? It would solve the problem I described in my previous post which is about working with java libraries in LDD.

Hey, IBM please do that and make our team happy :)

How do you work with Java libraries in LDD?

Hi guys,

We have faced up (actually long time ago) with problem which is related to Java libraries. Back-end of our applications on Domino is written on Java fully. Each Java library has ofc own classes and packages. However LDD allows to work only 1 person with 1 library at same time and it is really painful for us as we have to wait till another developer finish his job. Does anybody know if there is a way (SVN?) which may resolve our problem?
What we really would like to get - possibility to sync java classes with library, so developers would be able to work with same library and just sync changes to it.
We need something like on screen: java library transform into files and each of file represent own class. So we would sync it in both side...



Any help would be appreciated :)

Tuesday, January 24, 2012

Error pages in Domino

First of all I'd like to briefly describe few another ways we can use to manage error pages in Domino.
Also notice, I will definitely update post few times more after all.

1. Lazy solution $$ReturnGeneralError and MessageString
It's the most fast and easy solutions, it require to create 1 design element (form) $$ReturnGeneralError, style it and add MessageString somewhere to explain what is wrong
Benefits:
- I see only 1 advantage compare to another approaches, its time to implement. Once you create $$ReturnGeneralError it starts to work. So few clicks and few minutes to manage output UI and you have solution.
Disadvantages:
- works inside of application only. So if you have 10 web applications, you need to manage error page in each of it. However you can setup inheritance and manage all error pages from 1 place etc.
- not very flexible on my opinion as we can operate with form-design elements only.

2. HTTP response headers
Simply create error page as design element or as document (does not matter) and create rule for your website in Domino Directory database. It does not require special knowledge and it is simple to use.

Benefits:
- easy to manage
- path to Error page (means we can use different database to keep error pages)
- we can use both: Design Elements and Documents as error page.
Disadvantages:
- require minor Administration of Domino skills.
it works in the same way as client side redirection. i.e. user will see “blink” of standard 404 page before loading custom 404 page.

3. "Whole server" solution
Use HTTPMultiErrorPage property in the Notes.ini file, for example HTTPMultiErrorPage=/error.html. Create rule on the Domino server for /error.html to be substituted corresponding page.
Benefits:
Disadvatages:

4. DSPAI as error handler for Domino
Most complicated approach but also most flexible from my point of view. There is quite low information about how to use it. It requires knowledge of Notes C Api as well. If you want to see how it looks, here is very good exampe (it helped me a lot) on loggin using DSAPI
Company I worked in use DSAPI for handling URL already, and now we are near to implement error handling using DSAPI as well (it already implemented it on development server, so soon I will show you real links etc).
DSAPI allows us to catch responses Domino generated for users and we can replace output in case if responce 400, 404 or any another.

I will post most important part of logic here, just to how overview how DSAPI works and what is gives to us. Notice I've changed code a bit, to show only most important part of it (I will copy comments from Paul's example just to make things faster) 

1. initiation of filter and register for response event
/*
* FilterInit() - Required filter entry point. Called upon
* filter startup, which occurs when HTTP server task is started.
*/
DLLEXPORT unsigned int FilterInit(FilterInitData* filterInitData) {
   filterInitData->eventFlags = kFilterResponse;
}
so what we did there, say to filter that we want to process response events
2. Link events we registered with functions
/*
* HttpFilterProc() - Required filter entry point. Dispatches the event notifications to the appropriate functions for handling the events.
*/
DLLEXPORT DWORD HttpFilterProc(FilterContext *pContext, DWORD dwEventType, void *pEventData)
{
 switch (dwEventType) {
  case kFilterResponse:
   return Response(pContext, pEventData);
 }

 return kFilterNotHandled;
}
Now we can process Responses to users
3. This is how we process Response to users
int Response(FilterContext* context, FilterResponseHeaders* eventData) {
 int responce = eventData->responseCode;

 if (responce==404) {
  if (Send404(context) == TRUE) {
   return kFilterHandledRequest;
  }
 }
 return kFilterNotHandled;
}
4. Finally code for Send404() how we replace content to users
While you read code you need to know that when we load filter we also initiate a table with KEY-HTML arrays. Yes we keep in memory Error HTML pages with keys we need. Our Keys - domain, we handle error pages on domain level, means for domain1.com - is 1 error page, for domain2.com is another error page. But you can do it in another way its up to you.
int Send404(FilterContext* context) {
 FilterResponseHeaders         response;
 unsigned int   errID = 0;
 char     szBuffer[DEFAULT_BUFFER_SIZE]={0};
 char     pszErrorPage[ERRRO_PAGE_SIZE]={0};
 FilterParsedRequestLine pRequestLine;
 unsigned int   pErrID;
 int      i;

 // As we are returning the entire page to the browser, we can 
 // set the response code to 404 (so the domino web log will show the error)
 response.responseCode=404;
 response.reasonText="Bad Request";
 
 // get domain name (its our key), could be done faster? right now its simple walk via 10-20 documents which is fine for now
 context->ServerSupport(context, kGetParsedRequest, &pRequestLine, NULL, NULL, &pErrID);
 for(i=0; i<errorPagesCount;i++) {
  if (strcmp(errorKey[i], pRequestLine.pHostName)==0) {
   strcpy(pszErrorPage, errorHTML[i]);
   i=errorPagesCount;
  }
 }

 if(strlen(pszErrorPage)<10) {
  sprintf(szBuffer, "Error page on %s is very small, something wrong", pRequestLine.pHostName);
  writeToLog(CRITICAL_MSG, szBuffer);
  return FALSE;
 }

 sprintf(szBuffer, "Content-Type: text/html; charset=UTF-8\n\nContent-length: %i\n\n", strlen(pszErrorPage));
 response.headerText = szBuffer;

 if (context->ServerSupport(context, kWriteResponseHeaders, &response, 0, 0, &errID) != TRUE) {
  sprintf(szBuffer, "Error sending redirect, code: %d", errID);
  writeToLog(CRITICAL_MSG, szBuffer);
  return FALSE;
 }
    if (context->WriteClient(context, pszErrorPage, (unsigned int) strlen(pszErrorPage), 0, &errID) != TRUE) {
  sprintf(szBuffer, "Error sending redirect, code: %d", errID);
  writeToLog(CRITICAL_MSG, szBuffer);
  return FALSE;
 }
 return TRUE;
}
OK guys, I've shared most complicated part of this DSAPI for error handling, rest you have complete yourself (homework :)), but feel free to ask my help here if you need.
benefits:
- most flexible approach (at least from those which I know)
- our logic control everything we want and we clearly see what is going on
disadvantages:
- most complicated ways from all I described
- require knowledge of Notes C API
- I did not try yet this solution with Linux servers (but I know it is possible to do)
- it may crash your Domino server in case if you did you filter wrong (memory leak etc)


5. xPage error handling is on way (on pause actually) and would be nice if somebody help me with that. I've read few articles in past from Per Henrik: XPages custom 404 and error page and Controlling the HTTP response status code in XPages, I think they can be very useful for those who doing in xPages. We will try this approach as we have ongoing huge projects based on xPage. 

Hey:
- ask to update/more details to article
- notify me about issues
- let me know if you know better way to handle errors

strongly recommended as it can help to many developers in future.

Monday, December 12, 2011

Using Velocity in Domino

We are using velocity framework to solve our task with html templates and when we started to work with velocity we faced up with problem below
java.util.MissingResourceException: Can't find resource for bundle java.util.PropertyResourceBundle, key member_access_not_allowed at
java.util.MissingResourceException.(MissingResourceException.java:50) at 
java.util.ResourceBundle.getObject(ResourceBundle.java:400) at 
java.util.ResourceBundle.getString(ResourceBundle.java:421) at 
lotus.notes.JavaString.getFormattedString(Unknown Source) at 
lotus.notes.AgentSecurityManager.checkMemberAccess(Unknown Source) at 
java.lang.Class.checkMemberAccess(Class.java:112) at 
java.lang.Class.getDeclaredMethods(Class.java:675) at 
org.apache.velocity.util.introspection.ClassMap.populateMethodCacheWith(ClassMap.java:167)
We have found the issue in velocity's source (well it is an issue only for Domino).
org.apache.velocity.util.introspection.ClassMap.populateMethodCacheWith(MethodCache, Class)
that line we have to change to get only Public methods but not all declared as it requires more access then Domino gives by default (we are not able to to get all private methods into Domino for security reason), so we just changed getDeclaredMethods to getMethods and problem has gone.

Tuesday, November 01, 2011

Solution for Lotus Domino to the trailing slash problem

2 months ago I've posted article about solution which can solve our problem in Domino with last trailing slash in URL. As I mentioned in my previous post, Domino does not care about url with/without last trailing slash, both way would work for Domino. Well, some of you maybe even find this feature useful because it gives less problems, however what if we talk about SEO (Search Engine Optimisation)?

There is actually article from google about to slash or not to slash, where they explain that they handle similar URL with and without last trailing slash as 2 different URL, they also propose ways how to solve this. If you ask what is bad here, answer is quite simple: just image that each URL has it's power/score for google. In case if we have only 1 possible URL for our page all score go to it, otherwise we will split them (high score will go to URL which is more often used by people in web).

Now about solution we implemented on our website. We used DSAPI to solve it as it does not do affect speed so much as different solutions. If you want to read more deeply about technical staff, you may want to read this article: solution to the trailing slash problem.

Yes it works like it should, no impact to page load's speed which was "very-very" important to us. And I heared google start to love us a bit more after that.

Related topics
DSAPI for Domino
Rewriting URL in Domino using DSAPI
Replacement for DSAPI in Java/XPages

Saturday, October 08, 2011

JavaScript: use power of console

console.log() - is pretty nice way to display debug information without interrupting user's actions. But do you know that 'console object' has lot of other useful methods? In this article I will try to show another important method in console object.


1. power of output
most common case for using console object is:
console.log("hello word")
but here few more ways how we can use it
console.log("string1", "string2", 1, 2, {proper1:"val1", proper2: 5});
console.log("Do you know that word %s same for all language except english %s. %d < %d", "ananas", "pineapple", 1, 2);
There are few another kind of log (works same as log but has different status)
console.debug(), console.info(), console.warn(), console.error()


console.group() and console.groupEnd() allow you to format very nice output with categories, it is very usefull when you have tons of data in log so you can easy control what is related to etc.
console.group("Food")
console.group("Fruit")
console.log("Apple")
console.groupEnd("Fruit")
console.group("Vegetables")
console.log("Potato")
console.groupEnd("Vegetables")
console.groupEnd("Food")
2. power of time
just put console.time()/console.timeEnd() before/after code where you want to measure time .
Aslo there are profile methods console.profile() and console.profileEnd() which allow to see "stack".


3. power of inspection
I guess most of us often want to see specific properties in HTML fragment, for such tasks we can use console.dir(object) or console.dirxml(element)


Some usefull articles about logging: Firebug about logging and Joe Hewitts about console

Tuesday, September 20, 2011

Page-layout rel = «next | prev»

Along with the attribute rel = «canonical» to specify a 'search robot' to duplicate content, it is now possible to use the HTML reference value rel = "next" and rel = "prev" to indicate the position of the current page with neighbors in the navigation box. F.x. you have article splitted on 10 pages and you use next/prev buttons in order to move from one page to another. If you want to be sure that most of 'score' from 'google spider' will go to main page red="next"/"prev" is the very good options.

Here is more details about our example


Now about rel="next" and rel="prev"
www.example.com/article?id=123page=1
<link rel="next" href="http://www.example.com/article?id=123&page=2" />
www.example.com/article?id=123page=2
<link rel="next" href="http://www.example.com/article?id=123&page=3" />
<link rel="prev" href="http://www.example.com/article?id=123&page=1" />
www.example.com/article?id=123page=3
<link rel="next" href="http://www.example.com/article?id=123&page=4" />
<link rel="prev" href="http://www.example.com/article?id=123&page=2" />www.example.com/article?id=123page=10
<link rel="prev" href="http://www.example.com/article?id=123&page=9" />


Few notes:

  • First page should have only rel=«next». 
  • All pages between 1-st and last usually should have both only rel=«next» and rel="prev".
  • Last page should have olny rel=«prev». 
  • Allowed to use the value rel=«previous» as an alternative to rel=”prev”. Not sure if it has sence :) 
  • In case if you fail with that Google will continue to index your content with own heuristic logic.

Tuesday, August 02, 2011

Domino resolve URL with and without trailing as same URL, wrong?

We are faced with a problem (for us) with Domino. The problem is that Domino processes those 2 URL as similar same URL:

http://host/0/unid
http://host/0/unid/

the difference in 'trailing' (for those who thinks in same way as Domino :]). Well, it would be not a problem at all if you do internal staff, even very useful, problems start when we talk about SEO.

It actually affects our websites, as f.x. google 'eats' 2 URL (I mentioned above) as 2 different URL so their 'value' will be split on 2 part + 2 URL with same content also very bad as it is duplicate.

We should be able to either make 301's from the NOT CORRECT to the CORRECT URLs, or respond with a 404 (not found). Both options would be good.

Does anybody know ways how to do it?

[update from 28 October 2011] we've found solution with DSAPI filter, here you can read Solution to the trailing slash problem in Lotus Domino

Saturday, July 23, 2011

How to prevent text selection

There are few ways

1. Apply 'preventDefault' for events 'onselectstart' and 'onmousedown'

var element = document.getElementById('content');
element.onselectstart = function () { return false; }
element.onmousedown = function () { return false; }

2. Add attribute 'unselectable'

$(document.body).attr('unselectable', 'on')

3. Add style 'user-select: none'

.g-unselectable {
  -moz-user-select: none;
  -khtml-user-select: none;
  -webkit-user-select: none;
  user-select: none;
}

4. Use disabled textarea
<textarea disabled="disabled" style="border:none;color:#000;background:#fff; font-family:Arial;">
    how to prevent text selection?
textarea>

source (ru): javascript tips #2 

Monday, June 27, 2011

IBM Domino Java: No trusted certificate found. Fail?

I've faced with quite major problem when use IBM Java (the one from Domino 8.5.2 FP2). Our Domino grabs data from some webservices via 'https' (webservice does not have authentication, its free to everybody). Using simple Java Agent in Domino we grabbed data and was very happy :), here is few lines what we do
 URL url = new URL("https://here url");  
 URLConnection connection = url.openConnection();  
 HttpsURLConnection httpConn = (HttpsURLConnection) connection;  
 httpConn.setRequestMethod("POST");  
 httpConn.setDoOutput(true);  
 httpConn.setDoInput(true);  
 byte[] bytes = msg.getBytes("UTF-8");  
 httpConn.setRequestProperty("Content-length", String.valueOf(bytes.length));  
 OutputStream out = httpConn.getOutputStream(); // and on this line we now have an error: "no trusted certificate found"  
It worked fine for years but their (webservice provide) certificate has expired and they generate new one using same official CA. After they did it, Domino refuse to use new certificate and we can't grab data anymore from Domino.

We did some tests and noticed that non Domino JVM works just fine (we did tests in Eclipse with Oracles JVM) with exactly same code and it worked fine.

Of course we tried much more thing i.e.: we tried to add new certificate to cacerts storage in Domino and it did not work, we also tried to replace cacerts on Domino and use the one from Oracle JVM and lot of more things without any luck. Also when we tried to add new cert to cacerts in Domino it started to report about another issue: certificate chaining error.

Maybe Domino or Domino's JVM has problem/issue or we need to do something we just do not know. Would be nice to get more details about it because we are stacked now, does anybody know why we get this problem and if it is really problem in IBM Java?
There is also post on IBM with exactly same problem with not trusted certificates.
Would be nice if somebody share his suggestions/opinions.

Related topics:
IBM Domino Java: No trusted certificate found. Fail?
Domino and No trusted certificate found
Disabling certificate validation in Java

Thursday, June 23, 2011

How to add much more debug information to your Java Project

Go to Run\Configuration manu and switch to tab Arguments and add: -Djavax.net.debug=ssl,handshake (as I did on screen) and you will get much more debug information that could be useful for you.

Tuesday, June 07, 2011

Thank you MS for second update of Skype

Most of day Skype does not work and same situation in most of my friends. Only in such moments you understand how things are important like Skype :).

Tuesday, May 31, 2011

Copy/Paste substitutions freezes my Lotus Notes

Have you ever tried to copy and paste substitutions in server's names.nsf? I'm having problem there for last few years (if I recall correctly). Problem is quite simple, after you tried to paste substitution your Lotus Notes always freeze.


Previously I used ctrl+pause to avoid this freeze but I got new laptop and pause is absent :) (and I do not know how to simulate ctrl+pause).


Hope IBM will fix that in 8.5.3 :)

Tuesday, March 22, 2011

have you already download new FireFox?

I've just updated it to version 4. It works fine. Unfortunately I expected it would run faster then 3.X but it did not happen. FF can't beat Chrome in this area. But there is another good news: all my plug-in work fine. Only firebug required re-installation.

Saturday, March 19, 2011

I've moved my applications to google code.

I've upload some of my small application to google code. There are couple reasons why I did it:
- backup.
- we can use SVN now as on some projects I work with another people, so now we can get benefits from that as well.
- I just feel that it is much much more correctly :)

If you wish to create project your own project on google code, just fill google code form. After that using SVN do checkout and
input as URL repository https://*******.googlecode.com/svn/trunk/
[Username] is your email
[password] is available on google code setting page.

So go on and do your first commit to google code

Friday, March 04, 2011

SVN plug-in problems

Hi guys, we are moving our Domino applications to SVN and everything going really well except one thing.
We are having problems with elements that really do not modified but during synchronization they get new values (look on image). It is major problem for us, because applications have many design elements and most of them often get news values (modified, noteid etc) and then we are not able to determine what elements were really changed.
We do have workaround: do 1 more step and apply XSLT approch on exported elements and just remove these Noteinfo, modified, lastaccessed etc tags, but that is not the really correct way.

Does anybody know solution for that? If you use SVN - how you live with that?

IBM did forum on xPage, nice

Just noticed that IBM did forum for xPage based on xPage. I can't say it looks great, I feel it still require lot of work.

Tuesday, February 15, 2011

Introducing LotusLive Symphony

I've been using Google Documents for couple years already, I've even do not have office installed on my laptop at all. Now IBM did something similar? I've tried it already and should notice that Live Symphony is still far-far from Google. First what I've found - no support of right click mouse, only action bar. From another side, I'm happy that IBM tried to do that. Test link. That's nice.

Friday, February 11, 2011

xPage view with categories + readers fields + don't show empty categories

I'm doing simple application right now on xPage, nothing really difficult. This application has view with couple columns as category, documents that I display into that view have readers/authors fields and I need to be able do collapse and expand of that view. Simple things, right? but not for xPage, to difficult, it just does not work :-), I've found paper on
IBM LO58079: XPAGE VIEW CONTROL WITH EXPANDLEVEL, VIEW WITH 'DON'T SHOW EMPTY CATEGORIES', DOCUMENTS WITH A READERS FIELDS
Actually this paper describes my situation and there is really smart solution there!
Local fix
Remove any one of these three factors:
- The readers fields from the documents.
- The "Don't show empty categories" property from the view.
- The 'expandLevel' property from the view control.

Is it joke? Would it not be better to remove whole application at all? nice that they do not say to use another sofrware for web development, but who know... probably next 'Loal fix'...  :-)

Wednesday, January 19, 2011

trying to get full control over xPage auto generated html

I know xPage is great especially for RAD but I feel bad when I see how Domino generates HTML for xPage's application and dojo why it loads even if I do not want to use it? yea, I know that most of xPage's controls use it but anywhere I want to keep control over each html-tag. I want nice html. I want to know what is going on with my html. I'm sure all of you saw what html we get from xPage, and I want to repeat once again "I'm not fan of that".
Here are couple steps for those who want to get some more control over xPage. I will show example with new application that has only one xPage.

so let's start. we created new application and created new xPage, let's call it 'index'. Open it in browser. what do you see? My Domino generates already lot of staff.

1. included dojo.
2. included css.
3. created form and put there ~6 fields for some reasons. I do not know why.
4. html, head, title, body tags and !DOCTYPE

So instead to display empty page, Domino generated ~1Kb of some data we did not ask.

1-st step: disable default dojo in xPage.
You can disable the loading of the default Dojo, for example in order to use a more recent version of Dojo. In the Package Explorer in Domino Designer open your database and find the WebContent/WEB-INF/xp.properties file.
Edit the file and addxsp.client.script.libraries=none
Switch to Java perspective and Package Explorer there by default, so go there and make update. Save and check results. 2 line disappeared.

2-nd step: disable CSS.
create new Theme and remove extends="webstandard" and add this Theme in application properties as one we want to use. check hmtl source again - 3 lines with css went out.

open our index xPage and go to properties, tab Basic and set CreateForm = false. Save. Check. 
nice! we are quite near :)

4-th step. get empty blank xPage.
I do not know yet the way how correctly suppress rest of these tags and how to change doctype, so next time when I found solution I will update article.

Funny, while I was looking for solution for 4-th step, I found absolutely similar article from Chris, so you can read more older one This is an xPage.

Tuesday, January 18, 2011

Google Maps API - MarkerClusterer

If you ever did some job linked with google map (f.x. show markers with popup) you probably noticed problem with huge amount of markers (f.x.1000 markers). It does slow performance of webpage + it looks not very nice on UI (just mass of markers on same place). There is solution for such situation: MurkerClusterer, it allows to join markers into cluster with possibility to have different cluster on different zoom.
Here is an article about it - markerClusterer solution to the Too Many Markers problem
For those who works with Google Maps API this article is mandatory to read.

short dojo + ajax example how to get data from db

There are 3 most useful ahax-approaches I use when working with Lotus Domino:
- getting view as JSON. database.nsf/viewname?readviewentries& OutputFormat=JSON (fast and modern)

- agent approach (example here, most flexible and probably most slow approach)
- page/form/view as elelemnts, f.x. database.nsf/myform?openform&unid=123123 (easy to use but not  flexible, I use it very rarely)

Very small and known example of dojo's ajax, I'm getting some information from agent and then will use it in my JS later.

var jsondata;
dojo.xhrGet({
url: "database/agentGetData?Openagent&param1=id1",
sync: true,
load: function(data) {
jsondata = data;
}
});

I'm interesting in any another 'smart' approaches, so if u have some interesting idea we can discuss in comments them.

Sunday, January 16, 2011

nice command lotus\notes\nsd.exe -kill

Previously I've used kman.exe utilites to kill lotus notes processes, but now switch to this command.

Thursday, January 06, 2011

Merry Christmas, dear Orthodox !

christmas-2011

Improving SEO for blogspot bloggers. Lesson #1.

Everybody wants to have at least not worst SEO on own blogs. In case if you have you own blog on Domino or another platform, use your hands and do updates but if you are one who use blogspot, here it couple tips I would like to suggest to do. It is quite simple and fast.

1. Title tag. Check it on main page, does it says what you wanted?
looks on different pages as well. If you want to update it go to Design of your blog and open it as HTML, find area with title and replace it on such one

<b:if cond='data:blog.pageType == &quot;item&quot;'>
<title><data:blog.pageName/> | <data:blog.title/></title>
<b:else/>
<title><data:blog.pageTitle/> | Your additional keywords</title>
</b:if>

Actually you are free to put there whatever you want. Mostly all says that ideal length for title tag is 69-70 chars. So remember that and try to make it near to that.

2. By default blogspot does not include meta tags such as description and keywords, so we have to add that manually (at least my blog did not have these tags). Good length for this tags are: meta description ~156, meta keywords is about 180 chars. Here is snapshot of what you need to add to your template.

<b:if cond='data:blog.url == data:blog.homepageUrl'>
<meta content='bla bla bla' name='description'/>
<meta content='lotus, motus, fotus, focus, etc' name='keywords'/>

if you read logic carefully you will see that it says: add meta tags only for main page, that's because otherwise we will get these tags on all pages and that's very bad, google does not like same meta description on pages. that's duplicate and you will decrease PR. Later I will add some information how we can have unique meta tags on pages.

3. sitemap. I believe it is not necessary as we are already you google so it does this automatically, but anywhere, better to do :), I hope you have already enabled RSS on your blog. So just open Google Web Master add you site there and find menu Sitemap and try to add next /atom.xml?redirect=false&start-index=1&max-results=300you can update max-results as u wish. If everything went fine you should see Status 'OK' and number of of URL should be same as you have in you atom.xml.

4. that's is not linked to blogspot problem, but just remember that:
- Images should have title and alt.
- Tag <strong> is better that <b>, but as I see it requires go fix it into HTML of your entry.

Summary
These tips are legal and easy to implement, but remember, unique and interesting content is the key.

Monday, January 03, 2011

Native JSON

var jsonObjStr = '{"name":"Erast Fandorin", "speciality":"detective"}';
var object_person = JSON.parse(jsonString);
// object_person is object now with 2 properties

var personString = JSON.stringify(person);
// personString now keeps the string '{"name":"Erast Fandorin", "speciality":"detective"}'

this native JSON is now supported mostof browsers, so just use it :)