Recently we developed one feature where we wanted to present a new tab view for an existing smaller form interface whereby users can use the full screen of the new window to move around and use the feature with ease. While we were developing the feature, we came across few challenges and thereby few learnings which we thought would be good to share.

1. Caching existing values.

We have around 8-9 forms from where we can use this feature but each of them have different implementation based on the requirement. So before we open the new tab - we wanted to cache those different values so we can accordingly manipulate the view on new tab based on different forms.

Also user may enter few values in form before they open the new tab, even those values needs to be cached.

Passing those values via javascript will not be safe and also those form values are heavy. To cache values we created a redis object with a secured key.

JS code to serialize the form and create an js object to store the values for the form -

var email_params = email_form.serializeArray().reduce(function(obj, item) {
  obj[item.name] = item.value;
  return obj;
}, {});

The above object with few more parameters was sent to backend to be stored using a secured key in redis cache.

Rails code to save the js object.

 redis_hash = Redis::HashKey.new(EmailStore.key_generator(uuid), marshal: true, expiration: 1.hour)
 redis_hash['email'] = email_obj

2. Open new window and close new window.

  #open the new tab/window -
  var full_email_window = window.open(url_to_be_opened, 'abc', "height=768,width=1024,scrollbars=1");

height and width options is needed to open it in new window, without those options a new tab will be opened.

#To close the new tab/window - 
full_email_window.close();

But we wanted new window to be closed via events from the same window we just opened - which is not possible although there are some hack arounds but not reliable.

close method is only allowed to be called for windows that were opened by a script using the window.open method.

Solution we adopted was -

# open new window
var full_email_window = window.open(url, windowName, "height=768,width=1024,scrollbars=1");

# create a localStorageObject which can be shared by both Window.
window.localStorage.setItem(new_tab_uuid, 'init');

# child window updates the localStorageObject when Window is to be closed.
window.localStorage.setItem(new_tab_uuid, 'close');

# parent window polls to listen when Window is to be closed.
setTimeout(function(){ pollEmailWindow(new_tab_uuid, full_email_window) }, 1000);
function pollEmailWindow(uuid, full_email_window) {
  var new_tab_option = window.localStorage.getItem(uuid);
  if(new_tab_option == 'done' || new_tab_option == 'close'){
    full_email_window.close();
    window.localStorage.removeItem(uuid);
  }
  else
    setTimeout(function(){ pollEmailWindow(uuid, full_email_window) }, 1000);
}

# also we wanted to warn users when they try to close the parent window having child windows opened and 
# close the child windows on close of parent window - that way we dont leave child windows orphan which will not close.

window.onunload = function() {
  if (full_email_window && !full_email_window.closed) {
      full_email_window.close();
  }
};

window.onbeforeunload = function(){
  if (full_email_window && !full_email_window.closed) {
      return 'Are you sure?';
  }
};

3. Caching existing values and open new window.

As mentioned in step 1 we cached the values before we open the new window. So we make an ajax call to save the values in redis. Ideally we should open the new tab on ajax:success but there is one caveat here - When we open a new browser window in ajax success - it is blocked as a popup. This is not a good user experience. So we make a call to cache and open the window one after another but not after ajax success - this sometimes did not work as new window was opened well before caching was performed.

Solution -

# open a blank window - with some windowName
var initWindow = window.open("about:blank", windowName, "height=768,width=1024,scrollbars=1");

# after ajax success - assign the url to be opened using same windowName, 
# once we know that our values have been cached. 
window.open(url_to_be_opened, windowName, "height=768,width=1024,scrollbars=1");

Hope this help someone looking develop a feature around JS Window object.

Reference Links -

Window Close

Window Object