Around four months ago we launched our service for managing copy text in web applications: Copycopter. If you’re already riding the choppa, you’ve probably noticed steady improvements in the user interface. Today, we rolled out another change to make things nicer for non-technical users that want to edit copy text: a simpler editor.
What you see is what you get
We’ve done a lot to keep Copycopter simple to use. However, we also didn’t want to limit developers and designers by enforcing a limited language like textile, so we stuck to good old HTML. The draw back of this approach is that nontechnical users were occasionally confused by the markup in the copy text they wanted to edit. Worse, it was easy for such a user to break the page by accidentally changing the HTML to be invalid. We didn’t think it was acceptable for every user to be one “<” away from a broken page, so we changed this:
To this:
If you’d rather see HTML, don’t worry - we’re not leaving anyone out in the cold. One click will bring you back to the HTML editor you know and love:
We used the excellent jwysiwyg library to create our simple editor. Getting the editor up and running was easy, but making our integration tests work with the editor to ensure that it continued to work was a bit of a challenge.
TDDWYSIWYG
We used Cucumber to make sure that users could apply formatting to blurbs:
@javascript
Scenario: Apply formatting to blurbs
Given the following blurb exists:
| project | key | draft content |
| name: Breakfast | test.key | <p>hello</p> |
When I go to the edit blurb page for "test.key" on "Breakfast"
And I apply the "bold" editor function to "ell"
And I apply the "italic" editor function to "el"
And I press "Save Blurb"
And I go to the blurbs index for the "Breakfast" project
Then I should see "<p>h<b><i>el_l</i></b>o</p>"
To apply editor functions, we use this step:
When /^I apply the "([^"]+)" editor function to "([^"]+)"$/ do |function, selection|
steps %{
When I select "#{selection}" from the editor
And I click the "#{function}" editor button
And I unfocus the editor
}
end
The secret sauce there is being able to select text. We used capybara-webkit to run Javascript scenarios in Copycopter, so we can use the DOM range and selection API:
When /^I select "([^"]+)" from the editor$/ do |text|
within_editor do
page.execute_script(<<-JS)
var xpath = "//*/child::text()[contains(., '#{text}')]";
var node = document.evaluate(xpath, document, null, XPathResult. ANY_UNORDERED_NODE_TYPE, null).singleNodeValue;
if (!node)
throw("Couldn't find text to select");
var start = node.data.indexOf('#{text}');
var end = start + #{text.size};
var selection = window.getSelection();
var range = window.document.createRange();
range.setStart(node, start);
range.setEnd(node, end);
selection.removeAllRanges();
selection.addRange(range);
JS
end
end
The within_editor
method selects the iframe created by jwysiwyg, which is
possible because of Aaron Gibralter’s contributions to capybara-webkit. We have
several other scenarios for switching modes, handling newlines, and so on.
If you want to see our new editor in action, you should check out Copycopter!