Category Archives: Tips

Manipulating table child elements in AJAX callback considered harmful?

This is one of those small bugs that eats away entire day. You find a workaround rather quickly, but can’t let go until you know what to heck is going on.

This happened in rather large AngularJS application, which meant I had to chip away everything that is not necessary to reproduce the issue for hours.

Application screen consists of a table with several rows, with number input boxes. When user changes a value and leaves the input field, application sends a web request to perform some kind of calculation to 3rd party service. It then replaces the row that contains the changed field (performing web callbacks onblur is due to hard requirements that customer has placed. Not mine to judge). If blur event occurred due to clicking (not tabbing) into another input in same row, buttons don’t receive click events anymore. I have to stress, that there is no flicker to indicate elements moving around the page. If you click anywhere within the table again, click events start getting fired again.

You can see the issue in action here

Wait for table to load, click one input, then click second input in same row. Now go to bottom of the table and click “Can’t click this!”. It should show an alert. More often than not, it will not fire if you are using IE.

After removing almost all of the code of the application, conclusion is following:

  • happens only in IE (even version 11)
  • happens only when modifying inputs within TABLE element
  • happens only when modifying DOM within an AJAX callback
  • happens only when inputs within a table are defocused+focused
  • disappears when something is focused again after the manipulation

Why this happens?

Can’t really give you inner workings of the browser, but a hint is that AngularJS doesn’t seem to update values in inputs when you swap the object under it. It removes the inputs, and places new ones (we’re talking about ngRepeat directive to generate table rows). If you actually modify values within bound objects, this problem doesn’t happen.

Workaround? Why, there’s an ugly workaround always, of course!

Actually, there are two.

Focus something after modifying the DOM:

document.body.focus();

Or, modify the objects to which Angular model is bound. You can use angular.copy() function for that. It’s primary use is for creating copies of objects, but it takes an optional second parameter using which you can provide destination object.

angular.copy(newItem, $scope.ItemArray[idxToReplace]);
// instead of 
$scope.ItemArray[idxToReplace] = newItem;

Although second workaround seems nicer, I prefer the first one. I don’t want workarounds to seem nice. Broken line of code shown in workaround is actually more optimal, so I assume someone may want to ‘fix’ the workaround. I prefer that fixes for ugly bugs be obvious.

Update 2015-06-18:
This also happens with current version of Spartan browser.

Creating screen scraper that works in background

Recently I needed to share information which I could effectively do only by capturing screen and uploading the screenshot to a public location. This kind of things cause my primitive laziness instinct to kick in and I start grasping for automated solution. I say primitive instinct because automation effort in most cases takes more time than performing the work by hand. But that is a topic for a longer post, so I’ll go back to my problem.

There are few tools which provide functionality of capturing part of a screen and uploading result to a hosting service, which is nice but doesn’t solve my problem completely. Additionally, I needed to do screen capturing at set time intervals, navigate to a different window and send out the link after image has been uploaded. Perfect, I thought! I’ll fire up Visual Studio and write something up! I won’t go into details of how to do all this, as it’s not technically interesting (I might publish source code in the future). Main problem which I initially didn’t think about was, how to do screen capturing of specific window without using a dedicated machine for this task. Using the tool in my user session is clearly not a solution since I don’t want to share random state of my screen, but specific windows at specific times.

Idea 1
Create Windows user account and keep it logged in in the background.
Failed because Windows doesn’t do any drawing once user session goes to background.

Idea 2
Log into Remote Desktop session and close the connection without logging out.
Failed for same reason as idea 1. Even if you ignore that you need Windows Server OS and appropriate license to have multiple RDP sessions at the same time, problem of idea 1 remains. This idea might have worked if I had access to a Windows Server newer than Windows 2000.

Idea 3
Host a virtual machine in Hyper-V.
Success! Worked like a charm in first attempt! Things to remember are that you must connect to the machine using Hyper-V VM Connection and not RDP, that Hyper-V video driver supports resolutions only up to 1600×1200. This solution seems obvious, but when you’re working on such seemingly simple problem, first solution that comes to mind isn’t to get a dedicated machine or sacrifice CPU and memory of your machine to host a VM. But thanks to Moores law I was able to accept that it’s cheaper for me to give up 512MB of RAM than to spend a week trying to come up with an elegant solution (and probably failing).