I would go per feature. So take every issue (bulk edits, inline edits, actions) as a separate task. Then I would setup a new page, so both can be functional at the same time, with the new library.
Basic steps
Per issue I would do the following:
Review the end-to-end tests and check if they are complete so all functionality is covered.
Redirect the end-to-end tests for this issue to the new page (so now they are broken). You can do this one at a time off course. If you want you can even duplicate them so you keep running them both at the same time for the new and old implementation.
Make the new feature working so your tests start passing.
Review the relevant unit tests for this feature and duplicate them to test the new code. For example if you have a event handler being tested with the unit tests: Decide where the business logic should live, likely in an object. So, copy the rule but now test the object. Again you can keep the old ones running but mark them so you know that you have integrated this business rule in the new solution.
In this there are a lot of decisions to make like:
Decisions to make
Is the client side code implemented in a separate object or just inline event handlers? If inline I would move them to an object first, then let the new grid call the object. So you get separated responsibilities. Like a bulk edit object.
I would NOT try to touch all layers at the same time. If the controllers are fine just leave them for now. In case you need to change them you are still safe because the end-to-end tests you checked.
If inline it's likely not well-tested. Create (and re-use) tests to ensure the functionality now is stable.
Review layout issues/changes because the new grid might look different.
Consider updating manuals / screenshots.
When done you can return to the old url when preferred.
Next time it will be easier to replace the grid because it's quite separated.
Example on unit test:
Old:
Test.add('Add row', function (test) {
var Grid = newGrid(3); // get grid with 3 rows
Grid.events.trigger('addRow'); // Old event handler call
// Can even be outside the object on a global, more ugly:
// Events.call('grid1', 'addRow');
test.equals(4, Grid.length);
});
New:
Test.add('Add row', function (test) {
var Grid = newGrid(3);
Grid.addRow(); // new event handler call
test.equals(4, Grid.length);
});
No need to remove all unit tests. Just change the relevant pieces in your new copy should be sufficient. Clearly you will have old tests which become irrelevant and you will need to add new tests where new code is written.