ToolTip Performance in XPages - tooltip

I have a large XPage with about 170 fields on it. I have tooltips for a fair number of the fields. The tooltip does a lookup into a help DB and returns the related text. They work fine but they significantly slow down the load process because of the number of times the lookup is performed. I put a dBar.info statement in the JS that loads the text and in one load the document and put it into edit mode it would appear to have fired that one tooltip lookup 6 times. If it does that for every one of the tooltips then clearly that is the reason for the slow performance of the XPage. I did it both with the DynamicContent set to both true and false with similar results. I'm tempted to just remove the tool tips but that kind of defeats the purpose.
Is there a way to limit the tooltip to only fire the lookup when called? Like something linked to the MouseOver event. It seems to me the tooltip in the extension Library works OK if there are only a few fields requiring inline help but does not scale well.
Just as a test I removed all the tooltips from the XPage and while the loading is slow it is probably acceptable, but the tooltips slow it to the point of unacceptability.

Bill,
This is an excellent use case for an ApplicationScope bean. Create a bean that implements Map and uses an internal HashMap as cache. Let's call it tooltip. In your tooltip you define the label as EL e.g. tooltip['Manager']. XPages will call the get function. In it you check the internal HashMap if you have the value, otherwise you look it up. So lookup happens once only.
You could instead of looking up on demand opt for loading when initialized. Using a view navigator that should be very fast. Since it would be an Application scope only loaded once.
Makes sense?

You can use view.isRenderingPhase() to minimise the lookups during a partial refresh. With the tooltip you can also change the showDelay property so the tooltip has a delay before showing. This is a good thing to do for a view, so it doesn't try to load each tooltip as the mouse moves down the page. dynamicContent="true" may also mean it's not loaded with the page, but only when called - I haven't checked this so I'm not certain.

Related

ui-grid 'renderComplete' event after rendering rows in DOM

I'm using ui-grid 3.2.1.
Trying for a long time now to find an event that notifies me when rows are rendered in the DOM.
I looked a lot in SO, and in their issues in Github.
My test to see if rows are rendered is basically $('.ui-grid-row').length > 0.
I tried rowsRendered event, modifyRows(data), all sorts of $timeout(0) in almost every spot I could, nothing worked, all callbacks are called when the above jQuery still doesn't have results.
As a last resort I found a very inefficient solution - I $watch the .html() changes of .ui-grid-contents-wrapper, which contains the .ui-grid-row elements, and when I find one, I turn off the watcher and call the callback. It's bad but it works.
Note - The rows/columns somtimes contain inner directives which may take some time to render. I don't think it should influence rowsRendered() event.
Please, can anybody help with this?
No support from ui-grid team sadly.
EDIT:
plunkr that show there are no .ui-grid-row in DOM when rowsRendered() is called:
https://plnkr.co/edit/8clwC5hkwhAEjvoLZ6vO?p=preview
Try
var rows= gridApi.core.getAllVisibleRows(gridApi.grid);
inside rowsRendered function.

Loading select options after setting value

My program flow requires that I first set the value of a select option in the Viewmodel and then I load the available options into the Viewmodel. This causes problems, typically the first available option will be seen in the selection list after this, while the selected option value stays at the specified value.
I was hoping that setting the new "valueAllowUnset" would help, but instead my page becomes unresponsive when using it.
Therefore I currently set the original value again after loading the options. Strangely, this only works when I set the value, set a different value and then set the value again, e.g.
self.data()[field](orgValue);
self.data()[field]({});
self.data()[field](orgValue);
(I store values for multiple selection lists in the self.data observable and access them with the property index "field".)
I tried to strip this down to a simple JSFiddle (http://jsfiddle.net/timvdh/HN6DE/), but the behavior does not show there, although the example pretty much resembles my actual application. However, I am using about 30 select lists there.
So I was hoping, that someone can make an educated guess about what goes wrong in my application, I am hoping that the fact that I have to set the original value three times maybe gives a clue.
EDIT: This fiddle demonstrates, that setting the selected option before and after filling the options list does work with "valueAllowUnset": http://jsfiddle.net/timvdh/HT5Tp/
I am using JQuery Mobile with knockout.js and that caused the problem (sorry I did not even think about JQM being the problem in the first place). I am now setting the option before filling the list and after filling the list I call
$("#selectmenuID").selectmenu("refresh");
to display the option.
The hanging browser was not caused by knockout, there are additional subscriptions to the selectmenus in my app. "valueAllowUnset" changed the behavior of the selectmenus and triggered loops caused by problems in my code.

Speed up jQueryUI button

I have a webpage with a lot of checkboxes that I turn into pushbuttons with jQueryUI button() call. This slows the rendering of the page down to a crawl. Is it possible to speed this up?
I do the call in document.ready with selector
$("#containingdiv input[type='checkbox']).button()
I am building a control for a bracket cup. And i am showing the brackts for all agegroups, that is the reason for so many checkboxes. The ones marked in red boxes ar checkboxes and the other ones is normal buttons. There are up to 30 agegroups so i need to show alot of them.
Looks like i should build the ui myself instead of using the pushbuttons from jqueryui. When i profile i chrome it looks like it is building all the nodes that uses all the time.
Try the following trick. Instead of converting them all at once, convert first hundred (or how many user immidiately sees on the screen), and delay the rest with setTimeout(). This releases the UI thread almost immidiately, therefore browser can do other things like rendering and processing events. Initialization actually becomes longer, but the page is never frozen.
Something like:
var checkboxes_left = $("#containingdiv input[type='checkbox']");
convertRest();
// Convert the first 100 checkboxes, then schedule converting the rest
function convertRest() {
checkboxes_left.slice(0, 100).button();
checkboxes_left = checkboxes_left.slice(100);
if (checkboxes_left.length > 0) {
window.setTimeout(convertRest, 50);
}
}

Bind functions to elements inserted in the DOM? (Implicitly?)

This is probably jquery basics, but I can't find a solution after much googling.
How do you attach "non-events" to elements inserted in the DOM?
For events, like click, we can use live() or bind().
How would you, for instance, initialize tabs() or addClass() to a new element?
Specifically, I'm trying to get tabs() to work in the content of an ajax loaded dialog, but I think the correct solution should be applicable to any situation.
I did see a trick that involved $('body').mousemove() which did work, but that is still binding to an event and obviously a hack.
For instance, how would you get addClass() to fire on a newly inserted table row?
I mean to do this implicitly, meaning that I don't want to write out specific instructions for every event that adds nodes to the dom, I just want it to "run in the background".
Let me know if this needs clarification, I see many similar questions on SO but no answers that have helped.
EDIT: Simple example: A page calls $('a').addClass('highlight') which works on all anchors in the page. A new anchor is then added to the page dynamically by jQuery, but does not get the class added.
EDIT: I have tried all kinds of bind(), trigger() and change() methods but I'm afraid I'm barking up the wrong tree.
you need to look at livequery it will allow you to apply things to newly added elements
also if your adding the element you can do
$('body')append('<div>some content</div>').tabs();
or something like that
I know that I may contradicting your "non-event" rule here, but just by saying that you want something "triggered", you're already implying some kind of event.
In that case, may I suggest jQuery custom events? You may want to create a custom event, then trigger it manually somewhere in your code. It's not automatic (like when you add a row, BOOM, it fires™), but that's the closest thing I can think of with what you were describing.
Specifically, you may want to look at jQuery's .bind() and .trigger() methods.

Progressive Loading, ASP.NET MVC

I have a page that has to render a huge set of query results - most of them with very, very small images. It is already paginated, so that won't solve my problem.
The query executes fine - it's very zippy, returns in about .0004 seconds, paginates itself out to the View - all is well in the land of Oz.
However there is some big trouble in that ASP.NET MVC dumps the page when it is ready, not as it is loaded. Is there any way around this?
I tried using jQuery to lace through div layers and draw partial views - this alleviated some of the problem, but it still just 'hangs' on the page until the whole thing is ready to be drawn.
I was looking around and found a few suggestions about using Response.Write - but I couldn't uncover anything relevant to my case. Any ideas? The structure is as follows...
PartialView
- Category
- IEnumerable<Models.Images> (List)
PartialView
- Page
- IEnumerable<Models.Images> (List) (Paginated View)
View
- Gallery
-- Index
--- Categories (Ajax Loaded on Demand, not on View render.)
---- ViewPage (No specific model passed)
The problem is clearly the images, I've tested it several times. If I remove the tags from the code, it renders quickly with just any data I tell it to. Each image is around 4 kb in size - so compressing them isn't likely.
Any help would be greatly appreciated.
There are a couple of things that you can do.
First, make sure the results themselves are not inside tables. IE (and perhaps other browsers) have to wait until the table has been fully loaded before rendering to the browser.
Secondly, there is a command called Response.Flush which will push the buffered output to the client. You can call this repeatedly. You may want to call it for every 10 items or so, for example. If you can incorporate this into your code it should do the trick for you.
About how many images are being loaded in a given request? As I'm sure you're aware the issue is less the size of the files and more the quantity of them- it takes longer to move a bunch of small files than an equally sized large file.
One thing to consider would be to send the page down with a specific sized set of results already populated and then use JavaScript (and perhaps scroll events) to dynamically load the rest. Ideally you should try to minimize the size of the initial request so that the page doesn't block user interaction for long; after that initial loading period you could then start pulling in the rest of the results.

Resources