ViewManager: Persistent Views in Single-Page Web Apps

JavaScript frameworks like backbone.js make it easy to create web app content based on the path using Router and View objects. But what if you want some views, and their state, to persist across certain routes? That can be tricky, so I created a simple ViewManager class to take care of the hard parts.

For a concrete example, consider an application that shows a search form (SearchView) and displays the results (ResultView) when it's submitted. You might want to keep displaying the search form along with the results, in case the user wants to modify their search (this is exactly the case that inspired ViewManager while I was working on MediaMeter Dashboard). Following best practices for single-page apps, you put the search results under a different path from the blank search form to allow links directly to the results. But now it gets complicated. If the user gets to the results from the search page, the SearchView already exists, but if the user is coming from a link, the SearchView needs to be created. Same route, different behavior based on the previous route. One approach would be to remove and destroy all views and create them anew every time the route changes. But on top of potentially hindering performance, creating a new view every time destroys useful View state, for instance: whether components of the view are expanded or collapsed.

ViewManager makes it easy to persist views across routes by providing a factory to create views when needed, and a method to automatically hide/show views (similar to the d3.js general update pattern). The getView() factory method takes a View constructor as an argument and either returns the existing view of that class, or creates a new one. The client code doesn't need to keep track of which views already exist, just always call getView() and you don't have to worry about creating duplicates.

The showViews() function is the other half of ViewManager. This function takes a list of views to display, hides any existing views not in the list, and adds any new views that aren't already displayed. If one of the views is already displayed, it won't be recreated and all of the DOM elements will maintain their state. This functionality is also really helpful if you want to add a fade or slide transition when a view is shown or hidden, but don't want to trigger it on route changes.

Abuse Is Not a Choice, Empathy Is

When we label someone an "abuser," we let them off too easily and invite future abuse into our communities.

Willow Brugh recently wrote a thoughtful post about how communities respond to abusive behavior. She writes, "If we simply kick out anyone who messes up, we end up with empty communities, and that’s not a new future." She calls for alternatives. The post sparked a lively twitter debate, with many arguing that abusers are aware of what they're doing and that placing the onus of "reforming" them on a community is overly burdensome. But, the rare sociopath aside, the very idea of an "abuser" is an anti-bogeyman that prevents us from dealing with the realities of abusive behavior in our communities, and importantly, in ourselves.

At this point, I should note that I'm no stranger to abuse. As a hackerspace director for many years, I was often in the position of responding when someone posed a threat to the safety and comfort of other members, and proudly, often the first person those members turned to for help. I've seen friends and family affected by abuse from strangers, relatives, police, lovers, and spouses. And, I've experienced abuse myself. I know the sting of betrayal, and the long-lingering doubt that comes from being mistreated by someone you trusted. I also know how difficult it is to recognize when your actions are hurting someone you care about, and how much work, dedication, and time it takes to change the thinking and habits behind those behaviors.

Discussions of abuse often insist it's a conscious choice. When asked about dealing with mean people, the terrific advice columnist Captain Awkward wrote:

I vote that you believe hard in the Mean Guy and view the rest of his personality through that lens. Because Sexy Guy is mean. And Sad Guy is mean. And I get it, because when you hate yourself and feel terrible, it makes it more likely that terrible things will escape your mouth. But at the end of the day, being depressed does not excuse being mean. Mean is a choice.

Yes, abuse is inexcusable, but the belief that it's a choice is both incorrect and harmful.

Consider the way a typical two-year-old treats others. They hit, lie, steal, threaten, scream, and any number of other behaviors that, if committed by an adult, would be undeniably abusive. But those children are not evil, they have not made a calculated decision to harm others. Their behavior stems from the inability to look past their own needs and consider the needs of others: in short, an underdeveloped sense of empathy. When I've worked to resolve conflicts in the hackerspace community, the abusive behavior I've seen has always stemmed from the exact same thing. If the offenders had been able to look past their own needs and emotions, they would have had to be either stupid or evil to act as they did (apologies to the Daily Show) but they couldn't.

Crucially, if someone believes abusive behavior is the result of a conscious choice, and they never made such a choice, they conclude that there is nothing wrong with their behavior. They then believe the problem must lie entirely with someone else. In other words, abuse is not a conscious choice, it is a lack of the conscious choice to empathize. Similarly, the false binary of "abuser" and "non-abuser" allows victims of abuse to assume that they could never become abusers themselves, when in fact, victims of abuse are the ones most likely become abusive (see Breaking the Cycle of Abuse: How to Move Beyond Your Past to Create an Abuse-Free Future). This is absolutely not an excuse for abusive behavior, but it suggests a completely different approach to understanding and responding to it. Have you ever looked critically at your own behavior towards others and considered that it might be abusive? If not, there's a good chance that, at times, it has been.

So how should we respond to abusive behavior within a community? I think Willow is right that we need something better than vilification and ostracization. When we say "we're kicking that person out because they're bad" we lose a crucial opportunity for the community to have a dialog about which behaviors are appropriate, and why. Also, no one sees themselves as "bad," so in such a system, they have no incentive to reflect on their own actions. In a wonderful video about how to tell someone they sound racist, Jay Smooth favors the "what you did" conversation over the "who you are" conversation, saying:

That conversation takes us away from the facts of what they did, into speculation about their motives and intention. And those are things you can only guess at, you can't ever prove, and that makes it way to easy for them to derail your whole argument.

What's more, when we label someone an "abuser" we fail to see them as people, modeling the very lack of empathy that causes abuse in the first place, furthering a vicious cycle. Should the recipient of abuse be forced to empathize with their abuser? No, of course not. But the response of the community, if it is to remain healthy, must be based in empathy. In practice, this means first and foremost, supporting and protecting the safety of anyone who was abused, and if at all possible, providing clear expectations to the perpetrator, along with an opportunity to meet them, and the consequences for not doing so. Some people will choose to continue harmful behaviors, and in doing so, choose to remove themselves from the community, but those who remain learn not to place blame, but rather to empathize and take responsibility for their own actions. People aren't problems. Problems are problems and people are people.