SlideShare a Scribd company logo
1 of 49
Download to read offline
Simplifying JavaScript Projects
with ReactJS and Friends
Kevin Dangoor, Sr. Computer Scientist, Adobe
1DevDay Detroit 2014
A modern, open source text editor that understands web design.
Brackets
• MIT-licensed open source
• Sponsored by Adobe with hundreds of contributors and a number of
non-Adobe committers
• 13th most starred project
• Hundreds of extensions are available
• 1.0 just released 10 days ago, with Extract for Brackets
function	
  _documentSelectionFocusChange()	
  {	
  
	
  	
  	
  	
  var	
  curFile	
  =	
  EditorManager.getCurrentlyViewedPath();	
  
	
  	
  	
  	
  if	
  (curFile	
  &&	
  _hasFileSelectionFocus())	
  {	
  
function	
  _documentSelectionFocusChange()	
  {	
  
	
  	
  	
  	
  var	
  curFile	
  =	
  EditorManager.getCurrentlyViewedPath();	
  
	
  	
  	
  	
  if	
  (curFile	
  &&	
  _hasFileSelectionFocus())	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  var	
  nodeFound	
  =	
  $("#project-­‐files-­‐container	
  li").is(function	
  (index)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  var	
  $treeNode	
  =	
  $(this),	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  entry	
  =	
  $treeNode.data("entry");	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  if	
  (entry	
  &&	
  entry.fullPath	
  ===	
  curFile)	
  {	
  
	
  
function	
  _documentSelectionFocusChange()	
  {	
  
	
  	
  	
  	
  var	
  curFile	
  =	
  EditorManager.getCurrentlyViewedPath();	
  
	
  	
  	
  	
  if	
  (curFile	
  &&	
  _hasFileSelectionFocus())	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  var	
  nodeFound	
  =	
  $("#project-­‐files-­‐container	
  li").is(function	
  (index)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  var	
  $treeNode	
  =	
  $(this),	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  entry	
  =	
  $treeNode.data("entry");	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  if	
  (entry	
  &&	
  entry.fullPath	
  ===	
  curFile)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  if	
  (!_projectTree.jstree("is_selected",	
  $treeNode))	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  if	
  ($treeNode.parents(".jstree-­‐closed").length)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  //don't	
  auto-­‐expand	
  tree	
  to	
  show	
  file	
  -­‐	
  but	
  remember	
  it	
  if	
  parent	
  is	
  manually	
  
expanded	
  later	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  _projectTree.jstree("deselect_all");	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  _lastSelected	
  =	
  $treeNode;	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }	
  else	
  {	
  
	
  
if	
  (!_projectTree.jstree("is_selected",	
  $treeNode))	
  {	
  
	
  	
  	
  	
  if	
  ($treeNode.parents(".jstree-­‐closed").length)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  //don't	
  auto-­‐expand	
  tree	
  to	
  show	
  file	
  -­‐	
  but	
  remember	
  it	
  if	
  parent	
  is	
  manually	
  expanded	
  later	
  
	
  	
  	
  	
  	
  	
  	
  	
  _projectTree.jstree("deselect_all");	
  
	
  	
  	
  	
  	
  	
  	
  	
  _lastSelected	
  =	
  $treeNode;	
  
	
  	
  	
  	
  }	
  else	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  //we	
  don't	
  want	
  to	
  trigger	
  another	
  selection	
  change	
  event,	
  so	
  manually	
  deselect	
  
	
  	
  	
  	
  	
  	
  	
  	
  //and	
  select	
  without	
  sending	
  out	
  notifications	
  
	
  	
  	
  	
  	
  	
  	
  	
  _projectTree.jstree("deselect_all");	
  
	
  	
  	
  	
  	
  	
  	
  	
  _projectTree.jstree("select_node",	
  $treeNode,	
  false);	
  //	
  sets	
  _lastSelected	
  
	
  	
  	
  	
  }	
  
}	
  
	
  
If it’s hard to test,
it won’t be tested.
http://www.infoq.com/presentations/Simple-Made-Easy
simple!
composed of one thing, not combined
complect!
interweave
function	
  _documentSelectionFocusChange()	
  {	
  
	
  	
  	
  	
  var	
  curFile	
  =	
  EditorManager.getCurrentlyViewedPath();	
  
	
  	
  	
  	
  if	
  (curFile	
  &&	
  _hasFileSelectionFocus())	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  var	
  nodeFound	
  =	
  $("#project-­‐files-­‐container	
  li").is(function	
  (index)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  var	
  $treeNode	
  =	
  $(this),	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  entry	
  =	
  $treeNode.data("entry");	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  if	
  (entry	
  &&	
  entry.fullPath	
  ===	
  curFile)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  if	
  (!_projectTree.jstree("is_selected",	
  $treeNode))	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  if	
  ($treeNode.parents(".jstree-­‐closed").length)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  //don't	
  auto-­‐expand	
  tree	
  to	
  show	
  file	
  -­‐	
  but	
  remember	
  it	
  if	
  parent	
  is	
  manually	
  
expanded	
  later	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  _projectTree.jstree("deselect_all");	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  _lastSelected	
  =	
  $treeNode;	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }	
  else	
  {	
  
	
  
Simple?
easy!
near at hand
React
https://www.destroyallsoftware.com/talks/boundaries
Functional core,
Integration shell
function	
  _documentSelectionFocusChange()	
  {	
  
	
  	
  	
  	
  var	
  curFile	
  =	
  EditorManager.getCurrentlyViewedPath();	
  
	
  	
  	
  	
  if	
  (curFile	
  &&	
  _hasFileSelectionFocus())	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  var	
  nodeFound	
  =	
  $("#project-­‐files-­‐container	
  li").is(function	
  (index)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  var	
  $treeNode	
  =	
  $(this),	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  entry	
  =	
  $treeNode.data("entry");	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  if	
  (entry	
  &&	
  entry.fullPath	
  ===	
  curFile)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  if	
  (!_projectTree.jstree("is_selected",	
  $treeNode))	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  if	
  ($treeNode.parents(".jstree-­‐closed").length)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  //don't	
  auto-­‐expand	
  tree	
  to	
  show	
  file	
  -­‐	
  but	
  remember	
  it	
  if	
  parent	
  is	
  manually	
  
expanded	
  later	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  _projectTree.jstree("deselect_all");	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  _lastSelected	
  =	
  $treeNode;	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }	
  else	
  {	
  
	
  
 	
  	
  	
  function	
  _documentSelectionFocusChange()	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  var	
  curFullPath	
  =	
  MainViewManager.getCurrentlyViewedPath(MainViewManager.ACTIVE_PANE);	
  
	
  	
  	
  	
  	
  	
  	
  	
  if	
  (curFullPath	
  &&	
  _hasFileSelectionFocus())	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  actionCreator.setSelected(curFullPath,	
  true);	
  
	
  	
  	
  	
  	
  	
  	
  	
  }	
  else	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  actionCreator.setSelected(null);	
  
	
  	
  	
  	
  	
  	
  	
  	
  }	
  
	
  	
  	
  	
  	
  	
  	
  	
  _fileViewControllerChange();	
  
	
  	
  	
  	
  }	
  
	
  
http://futurice.com/blog/reactive-mvc-and-the-virtual-dom/
ProjectModel
FileTreeViewModel
FileTreeView ActionCreator
React
 	
  	
  	
  function	
  render(element,	
  viewModel,	
  projectRoot,	
  actions,	
  forceRender,	
  platform)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  if	
  (!projectRoot)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  return;	
  
	
  	
  	
  	
  	
  	
  	
  	
  }	
  
	
  
	
  	
  	
  	
  	
  	
  	
  	
  React.renderComponent(fileTreeView({	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  treeData:	
  viewModel.treeData,	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  selectionViewInfo:	
  viewModel.selectionViewInfo,	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  sortDirectoriesFirst:	
  viewModel.sortDirectoriesFirst,	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  parentPath:	
  projectRoot.fullPath,	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  actions:	
  actions,	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  extensions:	
  _extensions,	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  platform:	
  platform,	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  forceRender:	
  forceRender	
  
	
  	
  	
  	
  	
  	
  	
  	
  }),	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  element);	
  
	
  	
  	
  	
  }
 	
  	
  	
  var	
  fileTreeView	
  =	
  React.createClass({	
  
	
  
	
  	
  	
  	
  	
  	
  	
  	
  /**	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  *	
  Update	
  for	
  any	
  change	
  in	
  the	
  tree	
  data	
  or	
  directory	
  sorting	
  preference.	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  */	
  
	
  	
  	
  	
  	
  	
  	
  	
  shouldComponentUpdate:	
  function	
  (nextProps,	
  nextState)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  return	
  nextProps.forceRender	
  ||	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  this.props.treeData	
  !==	
  nextProps.treeData	
  ||	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  this.props.sortDirectoriesFirst	
  !==	
  nextProps.sortDirectoriesFirst	
  ||	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  this.props.extensions	
  !==	
  nextProps.extensions	
  ||	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  this.props.selectionViewInfo	
  !==	
  nextProps.selectionViewInfo;	
  
	
  	
  	
  	
  	
  	
  	
  	
  },
 	
  	
  	
  	
  	
  	
  	
  render:	
  function	
  ()	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  var	
  contents	
  =	
  directoryContents({	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  isRoot:	
  true,	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  parentPath:	
  this.props.parentPath,	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  sortDirectoriesFirst:	
  this.props.sortDirectoriesFirst,	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  contents:	
  this.props.treeData,	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  extensions:	
  this.props.extensions,	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  actions:	
  this.props.actions,	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  forceRender:	
  this.props.forceRender,	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  platform:	
  this.props.platform	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  });	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  return	
  DOM.div(	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  null,	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  selectionBackground,	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  contextBackground,	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  extensionForSelection,	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  extensionForContext,	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  contents	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  );	
  
	
  	
  	
  	
  	
  	
  	
  	
  }	
  
	
  	
  	
  	
  });
 	
  	
  	
  directoryContents	
  =	
  React.createClass({	
  
	
  	
  	
  	
  	
  	
  	
  	
  render:	
  function	
  ()	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  var	
  extensions	
  =	
  this.props.extensions,	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  iconClass	
  =	
  extensions	
  &&	
  extensions.get("icons")	
  ?	
  "jstree-­‐icons"	
  :	
  "jstree-­‐no-­‐
icons",	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  ulProps	
  =	
  this.props.isRoot	
  ?	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  className:	
  "jstree-­‐brackets	
  jstree-­‐no-­‐dots	
  "	
  +	
  iconClass	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }	
  :	
  null;	
  
	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  var	
  contents	
  =	
  this.props.contents,	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  namesInOrder	
  =	
  _sortDirectoryContents(contents,	
  this.props.sortDirectoriesFirst);
 	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  return	
  DOM.ul(ulProps,	
  namesInOrder.map(function	
  (name)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  var	
  entry	
  =	
  contents.get(name);	
  
	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  if	
  (FileTreeViewModel.isFile(entry))	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  return	
  fileNode({	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  parentPath:	
  this.props.parentPath,	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  name:	
  name,	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  entry:	
  entry,	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  actions:	
  this.props.actions,	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  extensions:	
  this.props.extensions,	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  forceRender:	
  this.props.forceRender,	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  platform:	
  this.props.platform,	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  key:	
  name	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  });	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }	
  else	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  return	
  directoryNode({
 	
  	
  	
  directoryNode	
  =	
  React.createClass({	
  
	
  	
  	
  	
  	
  	
  	
  	
  mixins:	
  [contextSettable,	
  pathComputer,	
  extendable],	
  
	
  	
  	
  	
  	
  	
  	
  	
  render:	
  function	
  ()	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  var	
  entry	
  =	
  this.props.entry,	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  if	
  (entry.get("rename"))	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  renameInput	
  =	
  directoryRenameInput({	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  actions:	
  this.props.actions,	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  entry:	
  this.props.entry,	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  name:	
  this.props.name,	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  parentPath:	
  this.props.parentPath	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  });	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }
 	
  	
  	
  directoryNode	
  =	
  React.createClass({	
  
	
  	
  	
  	
  	
  	
  	
  	
  render:	
  function	
  ()	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  return	
  DOM.li({	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  className:	
  this.getClasses("jstree-­‐"	
  +	
  nodeClass),	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  onClick:	
  this.handleClick,	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  onMouseDown:	
  this.handleMouseDown	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  },	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  DOM.ins({	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  className:	
  "jstree-­‐icon"	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  },	
  "	
  "),	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  renameInput,	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  nameDisplay,	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  childNodes);	
  
	
  	
  	
  	
  	
  	
  	
  	
  }	
  
	
  	
  	
  	
  });
 	
  	
  	
  	
  	
  	
  	
  handleClick:	
  function	
  (event)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  var	
  isOpen	
  =	
  this.props.entry.get("open"),	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  setOpen	
  =	
  isOpen	
  ?	
  false	
  :	
  true;	
  
	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  if	
  (event.metaKey	
  ||	
  event.ctrlKey)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  //	
  ctrl-­‐alt-­‐click	
  toggles	
  this	
  directory	
  and	
  its	
  children	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  if	
  (event.altKey)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  if	
  (setOpen)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  //	
  when	
  opening,	
  we	
  only	
  open	
  the	
  immediate	
  children	
  because	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  //	
  opening	
  a	
  whole	
  subtree	
  could	
  be	
  really	
  slow	
  (consider	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  //	
  a	
  `node_modules`	
  directory,	
  for	
  example).	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  this.props.actions.toggleSubdirectories(this.myPath(),	
  setOpen);	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  this.props.actions.setDirectoryOpen(this.myPath(),	
  setOpen);	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }	
  else	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  //	
  When	
  closing,	
  we	
  recursively	
  close	
  the	
  whole	
  subtree.	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  this.props.actions.closeSubtree(this.myPath());	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }	
  else	
  {
 	
  	
  	
  ActionCreator.prototype.toggleSubdirectories	
  =	
  function	
  (path,	
  openOrClose)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  this.model.toggleSubdirectories(path,	
  openOrClose).then(_saveTreeState);	
  
	
  	
  	
  	
  };
 	
  	
  	
  ProjectModel.prototype.toggleSubdirectories	
  =	
  function	
  (path,	
  openOrClose)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  var	
  self	
  =	
  this,	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  d	
  =	
  new	
  $.Deferred();	
  
	
  
	
  	
  	
  	
  	
  	
  	
  	
  this.setDirectoryOpen(path,	
  true).then(function	
  ()	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  var	
  projectRelativePath	
  =	
  self.makeProjectRelativeIfPossible(path),	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  childNodes	
  =	
  self._viewModel.getChildDirectories(projectRelativePath);	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  Async.doInParallel(childNodes,	
  function	
  (node)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  return	
  self.setDirectoryOpen(path	
  +	
  node,	
  openOrClose);	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  },	
  true).then(function	
  ()	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  d.resolve();	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  },	
  function	
  (err)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  d.reject(err);	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  });	
  
	
  	
  	
  	
  	
  	
  	
  	
  });	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  return	
  d.promise();	
  
	
  	
  	
  	
  };
 	
  	
  	
  ProjectModel.prototype.setDirectoryOpen	
  =	
  function	
  (path,	
  open)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  var	
  projectRelative	
  =	
  this.makeProjectRelativeIfPossible(path),	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  needsLoading	
  	
  	
  	
  =	
  !this._viewModel.isPathLoaded(projectRelative),	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  d	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  =	
  new	
  $.Deferred(),	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  self	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  =	
  this;	
  
	
  	
  	
  	
  	
  	
  	
  	
  if	
  (open	
  &&	
  needsLoading)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  var	
  parentDirectory	
  =	
  FileUtils.getDirectoryPath(FileUtils.stripTrailingSlash(path));	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  this.setDirectoryOpen(parentDirectory,	
  true).then(function	
  ()	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  self._getDirectoryContents(path).then(onSuccess).fail(function	
  (err)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  d.reject(err);	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  });	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  },	
  function	
  (err)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  d.reject(err);	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  });	
  
	
  	
  	
  	
  	
  	
  	
  	
  }	
  else	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  onSuccess();	
  
	
  	
  	
  	
  	
  	
  	
  	
  }
 	
  	
  	
  	
  	
  	
  	
  function	
  onSuccess(contents)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  //	
  Update	
  the	
  view	
  model	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  if	
  (contents)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  self._viewModel.setDirectoryContents(projectRelative,	
  contents);	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }	
  
	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  if	
  (open)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  self._viewModel.openPath(projectRelative);	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  if	
  (self._focused)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  var	
  currentPathInProject	
  =	
  self.makeProjectRelativeIfPossible(self._currentPath);	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  if	
  (self._viewModel.isFilePathVisible(currentPathInProject))	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  self.setSelected(self._currentPath,	
  true);	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }	
  else	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  self.setSelected(null);	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }	
  else	
  {
branches
to test
 	
  	
  	
  FileTreeViewModel.prototype.openPath	
  =	
  function	
  (path)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  this._commit(_openPath(this._treeData,	
  path));	
  
	
  	
  	
  	
  };
{	
  
	
  	
  	
  	
  "subdir":	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  open:	
  true,	
  
	
  	
  	
  	
  	
  	
  	
  	
  children:	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "afile.js":	
  {},	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "subsubdir":	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  children:	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "thirdsub":	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  children:	
  {}	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }	
  
	
  	
  	
  	
  	
  	
  	
  	
  }	
  
	
  	
  	
  	
  }	
  
}
subdir/subsubdir/thirdsub/
{	
  
	
  	
  	
  	
  "subdir":	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  open:	
  true,	
  
	
  	
  	
  	
  	
  	
  	
  	
  children:	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "afile.js":	
  {},	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "subsubdir":	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  children:	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "thirdsub":	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  children:	
  {}	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }	
  
	
  	
  	
  	
  	
  	
  	
  	
  }	
  
	
  	
  	
  	
  }	
  
}
subdir/subsubdir/thirdsub/
treeData.subdir.subsubdir.open	
  =	
  true;	
  
treeData.subdir.subsubdir.thirdsub.open	
  =	
  true;
thirdsub	
  =	
  treeData.subdir.subsubdir.thirdsub;	
  
newThirdSub	
  =	
  thirdsub.set("open",	
  true);	
  
	
  
thirdsub	
  !==	
  newThirdSub;	
  //	
  true	
  
treeData.subdir.subsubdir.thirdsub	
  !==	
  newThirdSub	
  //	
  true	
  
treeData.subdir.subsubdir.thirdsub.open	
  ===	
  undefined;	
  //	
  true
Attack of the clones
https://www.flickr.com/photos/hjmediastudios/7910348016/
thirdsub	
  =	
  treeData.subdir.subsubdir.thirdsub;	
  
newThirdSub	
  =	
  thirdsub.set("open",	
  true);	
  
	
  
thirdsub	
  !==	
  newThirdSub;	
  //	
  true	
  
treeData.subdir.subsubdir.thirdsub	
  !==	
  newThirdSub	
  //	
  true	
  
treeData.subdir.subsubdir.thirdsub.open	
  ===	
  undefined;	
  //	
  true
thirdsub	
  =	
  treeData.subdir.subsubdir.thirdsub;	
  
newThirdSub	
  =	
  thirdsub.set("open",	
  true);	
  
newSubSubDir	
  =	
  subsubdir.set("thirdsub",	
  newThirdSub);	
  
newSubDir	
  =	
  subdir.set("subsubdir",	
  newSubSubDir);	
  
treeData	
  =	
  treeData.set("subdir",	
  newSubDir);
 	
  	
  	
  function	
  _openPath(treeData,	
  path)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  var	
  objectPath	
  =	
  _filePathToObjectPath(treeData,	
  path);	
  
	
  	
  	
  	
  	
  	
  	
  	
  function	
  setOpen(node)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  return	
  node.set("open",	
  true);	
  
	
  	
  	
  	
  	
  	
  	
  	
  }	
  
	
  	
  	
  	
  	
  	
  	
  	
  while	
  (objectPath	
  &&	
  objectPath.length)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  var	
  node	
  =	
  treeData.getIn(objectPath);	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  if	
  (isFile(node))	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  objectPath.pop();	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }	
  else	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  if	
  (!node.get("open"))	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  treeData	
  =	
  treeData.updateIn(objectPath,	
  setOpen);	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  objectPath.pop();	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  if	
  (objectPath.length)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  objectPath.pop();	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }	
  
	
  	
  	
  	
  	
  	
  	
  	
  }	
  
	
  	
  	
  	
  	
  	
  	
  	
  return	
  treeData;	
  
	
  	
  	
  	
  }
mutable?
 	
  	
  	
  FileTreeViewModel.prototype.openPath	
  =	
  function	
  (path)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  this._commit(_openPath(this._treeData,	
  path));	
  
	
  	
  	
  	
  };
 	
  	
  	
  FileTreeViewModel.prototype._commit	
  =	
  function	
  (treeData,	
  selectionViewInfo)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  var	
  changed	
  =	
  false;	
  
	
  	
  	
  	
  	
  	
  	
  	
  if	
  (treeData	
  &&	
  treeData	
  !==	
  this._treeData)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  this._treeData	
  =	
  treeData;	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  changed	
  =	
  true;	
  
	
  	
  	
  	
  	
  	
  	
  	
  }	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  if	
  (selectionViewInfo	
  &&	
  selectionViewInfo	
  !==	
  this._selectionViewInfo)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  this._selectionViewInfo	
  =	
  selectionViewInfo;	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  changed	
  =	
  true;	
  
	
  	
  	
  	
  	
  	
  	
  	
  }	
  
	
  	
  	
  	
  	
  	
  	
  	
  if	
  (changed)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  $(this).trigger(EVENT_CHANGE);	
  
	
  	
  	
  	
  	
  	
  	
  	
  }	
  
	
  	
  	
  	
  };
–C.A.R. Hoare
“There are two ways of constructing a software design: One way
is to make it so simple that there are obviously no
deficiencies, and the other way is to make it so complicated
that there are no obvious deficiencies. The first method is far
more difficult.”
Simple?
simple!
composed of one thing, not combined
http://www.shaffner.us/cs/papers/tarpit.pdf
Simple Architecture
• Each part does one thing with side effects in few, known places
• React lets you generate a whole UI functionally
• Immutable-JS allows you to control when data updates occur
• Every part of your application can have a consistent state
• Object identity tells you when something has changed
A modern, open source text editor that understands web design.
http://brackets.io

More Related Content

What's hot

Drupal Javascript for developers
Drupal Javascript for developersDrupal Javascript for developers
Drupal Javascript for developersDream Production AG
 
Magento Dependency Injection
Magento Dependency InjectionMagento Dependency Injection
Magento Dependency InjectionAnton Kril
 
Introduction to Web Components
Introduction to Web ComponentsIntroduction to Web Components
Introduction to Web ComponentsFelix Arntz
 
Drupal & javascript
Drupal & javascriptDrupal & javascript
Drupal & javascriptAlmog Baku
 
Virtual Madness @ Etsy
Virtual Madness @ EtsyVirtual Madness @ Etsy
Virtual Madness @ EtsyNishan Subedi
 
Beyond DOMReady: Ultra High-Performance Javascript
Beyond DOMReady: Ultra High-Performance JavascriptBeyond DOMReady: Ultra High-Performance Javascript
Beyond DOMReady: Ultra High-Performance Javascriptaglemann
 
Upgrade your javascript to drupal 8
Upgrade your javascript to drupal 8Upgrade your javascript to drupal 8
Upgrade your javascript to drupal 8Théodore Biadala
 
Functionality Focused Code Organization
Functionality Focused Code OrganizationFunctionality Focused Code Organization
Functionality Focused Code OrganizationRebecca Murphey
 
Render API - Pavel Makhrinsky
Render API - Pavel MakhrinskyRender API - Pavel Makhrinsky
Render API - Pavel MakhrinskyDrupalCampDN
 
Django Class-based views (Slovenian)
Django Class-based views (Slovenian)Django Class-based views (Slovenian)
Django Class-based views (Slovenian)Luka Zakrajšek
 
AngularJS - $http & $resource Services
AngularJS - $http & $resource ServicesAngularJS - $http & $resource Services
AngularJS - $http & $resource ServicesEyal Vardi
 
HirshHorn theme: how I created it
HirshHorn theme: how I created itHirshHorn theme: how I created it
HirshHorn theme: how I created itPaul Bearne
 
Geodaten & Drupal 7
Geodaten & Drupal 7Geodaten & Drupal 7
Geodaten & Drupal 7Michael Milz
 
AngularJS Compile Process
AngularJS Compile ProcessAngularJS Compile Process
AngularJS Compile ProcessEyal Vardi
 
Opencast Admin UI - Introduction to developing using AngularJS
Opencast Admin UI - Introduction to developing using AngularJSOpencast Admin UI - Introduction to developing using AngularJS
Opencast Admin UI - Introduction to developing using AngularJSbuttyx
 

What's hot (19)

Drupal Javascript for developers
Drupal Javascript for developersDrupal Javascript for developers
Drupal Javascript for developers
 
Magento Dependency Injection
Magento Dependency InjectionMagento Dependency Injection
Magento Dependency Injection
 
Java Assignment Help
Java  Assignment  HelpJava  Assignment  Help
Java Assignment Help
 
Introduction to Web Components
Introduction to Web ComponentsIntroduction to Web Components
Introduction to Web Components
 
Drupal & javascript
Drupal & javascriptDrupal & javascript
Drupal & javascript
 
Hibernate
HibernateHibernate
Hibernate
 
Virtual Madness @ Etsy
Virtual Madness @ EtsyVirtual Madness @ Etsy
Virtual Madness @ Etsy
 
Beyond DOMReady: Ultra High-Performance Javascript
Beyond DOMReady: Ultra High-Performance JavascriptBeyond DOMReady: Ultra High-Performance Javascript
Beyond DOMReady: Ultra High-Performance Javascript
 
Upgrade your javascript to drupal 8
Upgrade your javascript to drupal 8Upgrade your javascript to drupal 8
Upgrade your javascript to drupal 8
 
Functionality Focused Code Organization
Functionality Focused Code OrganizationFunctionality Focused Code Organization
Functionality Focused Code Organization
 
Render API - Pavel Makhrinsky
Render API - Pavel MakhrinskyRender API - Pavel Makhrinsky
Render API - Pavel Makhrinsky
 
Django Class-based views (Slovenian)
Django Class-based views (Slovenian)Django Class-based views (Slovenian)
Django Class-based views (Slovenian)
 
AngularJS - $http & $resource Services
AngularJS - $http & $resource ServicesAngularJS - $http & $resource Services
AngularJS - $http & $resource Services
 
jQuery Presentasion
jQuery PresentasionjQuery Presentasion
jQuery Presentasion
 
HirshHorn theme: how I created it
HirshHorn theme: how I created itHirshHorn theme: how I created it
HirshHorn theme: how I created it
 
Drupal 8: Fields reborn
Drupal 8: Fields rebornDrupal 8: Fields reborn
Drupal 8: Fields reborn
 
Geodaten & Drupal 7
Geodaten & Drupal 7Geodaten & Drupal 7
Geodaten & Drupal 7
 
AngularJS Compile Process
AngularJS Compile ProcessAngularJS Compile Process
AngularJS Compile Process
 
Opencast Admin UI - Introduction to developing using AngularJS
Opencast Admin UI - Introduction to developing using AngularJSOpencast Admin UI - Introduction to developing using AngularJS
Opencast Admin UI - Introduction to developing using AngularJS
 

Viewers also liked

React Next Conference slides: ReactJS Worst practices
React Next Conference slides: ReactJS Worst practicesReact Next Conference slides: ReactJS Worst practices
React Next Conference slides: ReactJS Worst practicesKateryna Porshnieva
 
Starting with Reactjs
Starting with ReactjsStarting with Reactjs
Starting with ReactjsThinh VoXuan
 
React.js in real world apps.
React.js in real world apps. React.js in real world apps.
React.js in real world apps. Emanuele DelBono
 
An Introduction to ReactJS
An Introduction to ReactJSAn Introduction to ReactJS
An Introduction to ReactJSAll Things Open
 
React in Native Apps - Meetup React - 20150409
React in Native Apps - Meetup React - 20150409React in Native Apps - Meetup React - 20150409
React in Native Apps - Meetup React - 20150409Minko3D
 
Rethinking Best Practices
Rethinking Best PracticesRethinking Best Practices
Rethinking Best Practicesfloydophone
 
React JS and why it's awesome
React JS and why it's awesomeReact JS and why it's awesome
React JS and why it's awesomeAndrew Hull
 

Viewers also liked (11)

Intro to ReactJS
Intro to ReactJSIntro to ReactJS
Intro to ReactJS
 
React Webinar Slides
React Webinar SlidesReact Webinar Slides
React Webinar Slides
 
React Next Conference slides: ReactJS Worst practices
React Next Conference slides: ReactJS Worst practicesReact Next Conference slides: ReactJS Worst practices
React Next Conference slides: ReactJS Worst practices
 
Starting with Reactjs
Starting with ReactjsStarting with Reactjs
Starting with Reactjs
 
React.js in real world apps.
React.js in real world apps. React.js in real world apps.
React.js in real world apps.
 
An Introduction to ReactJS
An Introduction to ReactJSAn Introduction to ReactJS
An Introduction to ReactJS
 
React js
React jsReact js
React js
 
React in Native Apps - Meetup React - 20150409
React in Native Apps - Meetup React - 20150409React in Native Apps - Meetup React - 20150409
React in Native Apps - Meetup React - 20150409
 
Why Play Framework is fast
Why Play Framework is fastWhy Play Framework is fast
Why Play Framework is fast
 
Rethinking Best Practices
Rethinking Best PracticesRethinking Best Practices
Rethinking Best Practices
 
React JS and why it's awesome
React JS and why it's awesomeReact JS and why it's awesome
React JS and why it's awesome
 

Similar to Simplifying JavaScript Projects with ReactJS

JQuery In Drupal
JQuery In DrupalJQuery In Drupal
JQuery In Drupalkatbailey
 
8 things to know about theming in drupal 8
8 things to know about theming in drupal 88 things to know about theming in drupal 8
8 things to know about theming in drupal 8Logan Farr
 
BlackBerry DevCon 2011 - PhoneGap and WebWorks
BlackBerry DevCon 2011 - PhoneGap and WebWorksBlackBerry DevCon 2011 - PhoneGap and WebWorks
BlackBerry DevCon 2011 - PhoneGap and WebWorksmwbrooks
 
Dicoding Developer Coaching #27: Android | Membuat Aplikasi Support Online Ma...
Dicoding Developer Coaching #27: Android | Membuat Aplikasi Support Online Ma...Dicoding Developer Coaching #27: Android | Membuat Aplikasi Support Online Ma...
Dicoding Developer Coaching #27: Android | Membuat Aplikasi Support Online Ma...DicodingEvent
 
Doctrine 2
Doctrine 2Doctrine 2
Doctrine 2zfconfua
 
Zend Framework 2 - Basic Components
Zend Framework 2  - Basic ComponentsZend Framework 2  - Basic Components
Zend Framework 2 - Basic ComponentsMateusz Tymek
 
jQuery: Tips, tricks and hints for better development and Performance
jQuery: Tips, tricks and hints for better development and PerformancejQuery: Tips, tricks and hints for better development and Performance
jQuery: Tips, tricks and hints for better development and PerformanceJonas De Smet
 
Building Large jQuery Applications
Building Large jQuery ApplicationsBuilding Large jQuery Applications
Building Large jQuery ApplicationsRebecca Murphey
 
J query b_dotnet_ug_meet_12_may_2012
J query b_dotnet_ug_meet_12_may_2012J query b_dotnet_ug_meet_12_may_2012
J query b_dotnet_ug_meet_12_may_2012ghnash
 
Understanding backbonejs
Understanding backbonejsUnderstanding backbonejs
Understanding backbonejsNick Lee
 
How Kris Writes Symfony Apps
How Kris Writes Symfony AppsHow Kris Writes Symfony Apps
How Kris Writes Symfony AppsKris Wallsmith
 
jQuery: out with the old, in with the new
jQuery: out with the old, in with the newjQuery: out with the old, in with the new
jQuery: out with the old, in with the newRemy Sharp
 
Multilingualism makes better programmers
Multilingualism makes better programmersMultilingualism makes better programmers
Multilingualism makes better programmersAlexander Varwijk
 
Drupal II: The SQL
Drupal II: The SQLDrupal II: The SQL
Drupal II: The SQLddiers
 
How to increase Performance of Web Application using JQuery
How to increase Performance of Web Application using JQueryHow to increase Performance of Web Application using JQuery
How to increase Performance of Web Application using JQuerykolkatageeks
 
Taming that client side mess with Backbone.js
Taming that client side mess with Backbone.jsTaming that client side mess with Backbone.js
Taming that client side mess with Backbone.jsJarod Ferguson
 

Similar to Simplifying JavaScript Projects with ReactJS (20)

JQuery In Drupal
JQuery In DrupalJQuery In Drupal
JQuery In Drupal
 
8 things to know about theming in drupal 8
8 things to know about theming in drupal 88 things to know about theming in drupal 8
8 things to know about theming in drupal 8
 
Having Fun with Play
Having Fun with PlayHaving Fun with Play
Having Fun with Play
 
Unittests für Dummies
Unittests für DummiesUnittests für Dummies
Unittests für Dummies
 
BlackBerry DevCon 2011 - PhoneGap and WebWorks
BlackBerry DevCon 2011 - PhoneGap and WebWorksBlackBerry DevCon 2011 - PhoneGap and WebWorks
BlackBerry DevCon 2011 - PhoneGap and WebWorks
 
Dicoding Developer Coaching #27: Android | Membuat Aplikasi Support Online Ma...
Dicoding Developer Coaching #27: Android | Membuat Aplikasi Support Online Ma...Dicoding Developer Coaching #27: Android | Membuat Aplikasi Support Online Ma...
Dicoding Developer Coaching #27: Android | Membuat Aplikasi Support Online Ma...
 
Doctrine 2
Doctrine 2Doctrine 2
Doctrine 2
 
Zend Framework 2 - Basic Components
Zend Framework 2  - Basic ComponentsZend Framework 2  - Basic Components
Zend Framework 2 - Basic Components
 
jQuery: Tips, tricks and hints for better development and Performance
jQuery: Tips, tricks and hints for better development and PerformancejQuery: Tips, tricks and hints for better development and Performance
jQuery: Tips, tricks and hints for better development and Performance
 
Building Large jQuery Applications
Building Large jQuery ApplicationsBuilding Large jQuery Applications
Building Large jQuery Applications
 
Drupal 8 migrate!
Drupal 8 migrate!Drupal 8 migrate!
Drupal 8 migrate!
 
J query b_dotnet_ug_meet_12_may_2012
J query b_dotnet_ug_meet_12_may_2012J query b_dotnet_ug_meet_12_may_2012
J query b_dotnet_ug_meet_12_may_2012
 
Understanding backbonejs
Understanding backbonejsUnderstanding backbonejs
Understanding backbonejs
 
How Kris Writes Symfony Apps
How Kris Writes Symfony AppsHow Kris Writes Symfony Apps
How Kris Writes Symfony Apps
 
jQuery: out with the old, in with the new
jQuery: out with the old, in with the newjQuery: out with the old, in with the new
jQuery: out with the old, in with the new
 
Introducing jQuery
Introducing jQueryIntroducing jQuery
Introducing jQuery
 
Multilingualism makes better programmers
Multilingualism makes better programmersMultilingualism makes better programmers
Multilingualism makes better programmers
 
Drupal II: The SQL
Drupal II: The SQLDrupal II: The SQL
Drupal II: The SQL
 
How to increase Performance of Web Application using JQuery
How to increase Performance of Web Application using JQueryHow to increase Performance of Web Application using JQuery
How to increase Performance of Web Application using JQuery
 
Taming that client side mess with Backbone.js
Taming that client side mess with Backbone.jsTaming that client side mess with Backbone.js
Taming that client side mess with Backbone.js
 

Recently uploaded

Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software DevelopersVinodh Ram
 
why an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfwhy an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfjoe51371421
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVshikhaohhpro
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantAxelRicardoTrocheRiq
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)OPEN KNOWLEDGE GmbH
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about usDynamic Netsoft
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideChristina Lin
 
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...OnePlan Solutions
 
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfThe Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfkalichargn70th171
 
Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackVICTOR MAESTRE RAMIREZ
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsJhone kinadey
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionSolGuruz
 
Project Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationProject Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationkaushalgiri8080
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...MyIntelliSource, Inc.
 
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataAdobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataBradBedford3
 
Active Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdfActive Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdfCionsystems
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfkalichargn70th171
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...harshavardhanraghave
 
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...soniya singh
 

Recently uploaded (20)

Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software Developers
 
why an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfwhy an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdf
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service Consultant
 
Call Girls In Mukherjee Nagar 📱 9999965857 🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
Call Girls In Mukherjee Nagar 📱  9999965857  🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...Call Girls In Mukherjee Nagar 📱  9999965857  🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
Call Girls In Mukherjee Nagar 📱 9999965857 🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about us
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
 
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
 
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfThe Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
 
Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStack
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial Goals
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with Precision
 
Project Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationProject Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanation
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
 
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataAdobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
 
Active Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdfActive Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdf
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
 
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
 

Simplifying JavaScript Projects with ReactJS

  • 1. Simplifying JavaScript Projects with ReactJS and Friends Kevin Dangoor, Sr. Computer Scientist, Adobe 1DevDay Detroit 2014
  • 2. A modern, open source text editor that understands web design.
  • 3. Brackets • MIT-licensed open source • Sponsored by Adobe with hundreds of contributors and a number of non-Adobe committers • 13th most starred project • Hundreds of extensions are available • 1.0 just released 10 days ago, with Extract for Brackets
  • 4.
  • 5. function  _documentSelectionFocusChange()  {          var  curFile  =  EditorManager.getCurrentlyViewedPath();          if  (curFile  &&  _hasFileSelectionFocus())  {  
  • 6. function  _documentSelectionFocusChange()  {          var  curFile  =  EditorManager.getCurrentlyViewedPath();          if  (curFile  &&  _hasFileSelectionFocus())  {                  var  nodeFound  =  $("#project-­‐files-­‐container  li").is(function  (index)  {                          var  $treeNode  =  $(this),                                  entry  =  $treeNode.data("entry");                          if  (entry  &&  entry.fullPath  ===  curFile)  {    
  • 7. function  _documentSelectionFocusChange()  {          var  curFile  =  EditorManager.getCurrentlyViewedPath();          if  (curFile  &&  _hasFileSelectionFocus())  {                  var  nodeFound  =  $("#project-­‐files-­‐container  li").is(function  (index)  {                          var  $treeNode  =  $(this),                                  entry  =  $treeNode.data("entry");                          if  (entry  &&  entry.fullPath  ===  curFile)  {                                  if  (!_projectTree.jstree("is_selected",  $treeNode))  {                                          if  ($treeNode.parents(".jstree-­‐closed").length)  {                                                  //don't  auto-­‐expand  tree  to  show  file  -­‐  but  remember  it  if  parent  is  manually   expanded  later                                                  _projectTree.jstree("deselect_all");                                                  _lastSelected  =  $treeNode;                                          }  else  {    
  • 8. if  (!_projectTree.jstree("is_selected",  $treeNode))  {          if  ($treeNode.parents(".jstree-­‐closed").length)  {                  //don't  auto-­‐expand  tree  to  show  file  -­‐  but  remember  it  if  parent  is  manually  expanded  later                  _projectTree.jstree("deselect_all");                  _lastSelected  =  $treeNode;          }  else  {                  //we  don't  want  to  trigger  another  selection  change  event,  so  manually  deselect                  //and  select  without  sending  out  notifications                  _projectTree.jstree("deselect_all");                  _projectTree.jstree("select_node",  $treeNode,  false);  //  sets  _lastSelected          }   }    
  • 9. If it’s hard to test, it won’t be tested.
  • 11. simple! composed of one thing, not combined complect! interweave
  • 12. function  _documentSelectionFocusChange()  {          var  curFile  =  EditorManager.getCurrentlyViewedPath();          if  (curFile  &&  _hasFileSelectionFocus())  {                  var  nodeFound  =  $("#project-­‐files-­‐container  li").is(function  (index)  {                          var  $treeNode  =  $(this),                                  entry  =  $treeNode.data("entry");                          if  (entry  &&  entry.fullPath  ===  curFile)  {                                  if  (!_projectTree.jstree("is_selected",  $treeNode))  {                                          if  ($treeNode.parents(".jstree-­‐closed").length)  {                                                  //don't  auto-­‐expand  tree  to  show  file  -­‐  but  remember  it  if  parent  is  manually   expanded  later                                                  _projectTree.jstree("deselect_all");                                                  _lastSelected  =  $treeNode;                                          }  else  {     Simple?
  • 14. React
  • 17. function  _documentSelectionFocusChange()  {          var  curFile  =  EditorManager.getCurrentlyViewedPath();          if  (curFile  &&  _hasFileSelectionFocus())  {                  var  nodeFound  =  $("#project-­‐files-­‐container  li").is(function  (index)  {                          var  $treeNode  =  $(this),                                  entry  =  $treeNode.data("entry");                          if  (entry  &&  entry.fullPath  ===  curFile)  {                                  if  (!_projectTree.jstree("is_selected",  $treeNode))  {                                          if  ($treeNode.parents(".jstree-­‐closed").length)  {                                                  //don't  auto-­‐expand  tree  to  show  file  -­‐  but  remember  it  if  parent  is  manually   expanded  later                                                  _projectTree.jstree("deselect_all");                                                  _lastSelected  =  $treeNode;                                          }  else  {    
  • 18.        function  _documentSelectionFocusChange()  {                  var  curFullPath  =  MainViewManager.getCurrentlyViewedPath(MainViewManager.ACTIVE_PANE);                  if  (curFullPath  &&  _hasFileSelectionFocus())  {                          actionCreator.setSelected(curFullPath,  true);                  }  else  {                          actionCreator.setSelected(null);                  }                  _fileViewControllerChange();          }    
  • 19.
  • 22.        function  render(element,  viewModel,  projectRoot,  actions,  forceRender,  platform)  {                  if  (!projectRoot)  {                          return;                  }                    React.renderComponent(fileTreeView({                          treeData:  viewModel.treeData,                          selectionViewInfo:  viewModel.selectionViewInfo,                          sortDirectoriesFirst:  viewModel.sortDirectoriesFirst,                          parentPath:  projectRoot.fullPath,                          actions:  actions,                          extensions:  _extensions,                          platform:  platform,                          forceRender:  forceRender                  }),                              element);          }
  • 23.        var  fileTreeView  =  React.createClass({                    /**                    *  Update  for  any  change  in  the  tree  data  or  directory  sorting  preference.                    */                  shouldComponentUpdate:  function  (nextProps,  nextState)  {                          return  nextProps.forceRender  ||                                  this.props.treeData  !==  nextProps.treeData  ||                                  this.props.sortDirectoriesFirst  !==  nextProps.sortDirectoriesFirst  ||                                  this.props.extensions  !==  nextProps.extensions  ||                                  this.props.selectionViewInfo  !==  nextProps.selectionViewInfo;                  },
  • 24.                render:  function  ()  {                          var  contents  =  directoryContents({                                          isRoot:  true,                                          parentPath:  this.props.parentPath,                                          sortDirectoriesFirst:  this.props.sortDirectoriesFirst,                                          contents:  this.props.treeData,                                          extensions:  this.props.extensions,                                          actions:  this.props.actions,                                          forceRender:  this.props.forceRender,                                          platform:  this.props.platform                                  });                                                    return  DOM.div(                                  null,                                  selectionBackground,                                  contextBackground,                                  extensionForSelection,                                  extensionForContext,                                  contents                          );                  }          });
  • 25.        directoryContents  =  React.createClass({                  render:  function  ()  {                          var  extensions  =  this.props.extensions,                                  iconClass  =  extensions  &&  extensions.get("icons")  ?  "jstree-­‐icons"  :  "jstree-­‐no-­‐ icons",                                  ulProps  =  this.props.isRoot  ?  {                                          className:  "jstree-­‐brackets  jstree-­‐no-­‐dots  "  +  iconClass                                  }  :  null;                            var  contents  =  this.props.contents,                                  namesInOrder  =  _sortDirectoryContents(contents,  this.props.sortDirectoriesFirst);
  • 26.                        return  DOM.ul(ulProps,  namesInOrder.map(function  (name)  {                                  var  entry  =  contents.get(name);                                    if  (FileTreeViewModel.isFile(entry))  {                                          return  fileNode({                                                  parentPath:  this.props.parentPath,                                                  name:  name,                                                  entry:  entry,                                                  actions:  this.props.actions,                                                  extensions:  this.props.extensions,                                                  forceRender:  this.props.forceRender,                                                  platform:  this.props.platform,                                                  key:  name                                          });                                  }  else  {                                          return  directoryNode({
  • 27.        directoryNode  =  React.createClass({                  mixins:  [contextSettable,  pathComputer,  extendable],                  render:  function  ()  {                          var  entry  =  this.props.entry,                          if  (entry.get("rename"))  {                                  renameInput  =  directoryRenameInput({                                          actions:  this.props.actions,                                          entry:  this.props.entry,                                          name:  this.props.name,                                          parentPath:  this.props.parentPath                                  });                          }
  • 28.        directoryNode  =  React.createClass({                  render:  function  ()  {                          return  DOM.li({                                  className:  this.getClasses("jstree-­‐"  +  nodeClass),                                  onClick:  this.handleClick,                                  onMouseDown:  this.handleMouseDown                          },                                  DOM.ins({                                          className:  "jstree-­‐icon"                                  },  "  "),                                  renameInput,                                  nameDisplay,                                  childNodes);                  }          });
  • 29.                handleClick:  function  (event)  {                          var  isOpen  =  this.props.entry.get("open"),                                  setOpen  =  isOpen  ?  false  :  true;                            if  (event.metaKey  ||  event.ctrlKey)  {                                  //  ctrl-­‐alt-­‐click  toggles  this  directory  and  its  children                                  if  (event.altKey)  {                                          if  (setOpen)  {                                                  //  when  opening,  we  only  open  the  immediate  children  because                                                  //  opening  a  whole  subtree  could  be  really  slow  (consider                                                  //  a  `node_modules`  directory,  for  example).                                                  this.props.actions.toggleSubdirectories(this.myPath(),  setOpen);                                                  this.props.actions.setDirectoryOpen(this.myPath(),  setOpen);                                          }  else  {                                                  //  When  closing,  we  recursively  close  the  whole  subtree.                                                  this.props.actions.closeSubtree(this.myPath());                                          }                                  }  else  {
  • 30.        ActionCreator.prototype.toggleSubdirectories  =  function  (path,  openOrClose)  {                  this.model.toggleSubdirectories(path,  openOrClose).then(_saveTreeState);          };
  • 31.        ProjectModel.prototype.toggleSubdirectories  =  function  (path,  openOrClose)  {                  var  self  =  this,                          d  =  new  $.Deferred();                    this.setDirectoryOpen(path,  true).then(function  ()  {                          var  projectRelativePath  =  self.makeProjectRelativeIfPossible(path),                                  childNodes  =  self._viewModel.getChildDirectories(projectRelativePath);                                                    Async.doInParallel(childNodes,  function  (node)  {                                  return  self.setDirectoryOpen(path  +  node,  openOrClose);                          },  true).then(function  ()  {                                  d.resolve();                          },  function  (err)  {                                  d.reject(err);                          });                  });                                    return  d.promise();          };
  • 32.        ProjectModel.prototype.setDirectoryOpen  =  function  (path,  open)  {                  var  projectRelative  =  this.makeProjectRelativeIfPossible(path),                          needsLoading        =  !this._viewModel.isPathLoaded(projectRelative),                          d                              =  new  $.Deferred(),                          self                        =  this;                  if  (open  &&  needsLoading)  {                          var  parentDirectory  =  FileUtils.getDirectoryPath(FileUtils.stripTrailingSlash(path));                          this.setDirectoryOpen(parentDirectory,  true).then(function  ()  {                                  self._getDirectoryContents(path).then(onSuccess).fail(function  (err)  {                                          d.reject(err);                                  });                          },  function  (err)  {                                  d.reject(err);                          });                  }  else  {                          onSuccess();                  }
  • 33.                function  onSuccess(contents)  {                          //  Update  the  view  model                          if  (contents)  {                                  self._viewModel.setDirectoryContents(projectRelative,  contents);                          }                            if  (open)  {                                  self._viewModel.openPath(projectRelative);                                  if  (self._focused)  {                                          var  currentPathInProject  =  self.makeProjectRelativeIfPossible(self._currentPath);                                          if  (self._viewModel.isFilePathVisible(currentPathInProject))  {                                                  self.setSelected(self._currentPath,  true);                                          }  else  {                                                  self.setSelected(null);                                          }                                  }                          }  else  { branches to test
  • 34.        FileTreeViewModel.prototype.openPath  =  function  (path)  {                  this._commit(_openPath(this._treeData,  path));          };
  • 35. {          "subdir":  {                  open:  true,                  children:  {                          "afile.js":  {},                          "subsubdir":  {                                  children:  {                                          "thirdsub":  {                                                  children:  {}                                          }                                  }                          }                  }          }   } subdir/subsubdir/thirdsub/
  • 36. {          "subdir":  {                  open:  true,                  children:  {                          "afile.js":  {},                          "subsubdir":  {                                  children:  {                                          "thirdsub":  {                                                  children:  {}                                          }                                  }                          }                  }          }   } subdir/subsubdir/thirdsub/ treeData.subdir.subsubdir.open  =  true;   treeData.subdir.subsubdir.thirdsub.open  =  true;
  • 37. thirdsub  =  treeData.subdir.subsubdir.thirdsub;   newThirdSub  =  thirdsub.set("open",  true);     thirdsub  !==  newThirdSub;  //  true   treeData.subdir.subsubdir.thirdsub  !==  newThirdSub  //  true   treeData.subdir.subsubdir.thirdsub.open  ===  undefined;  //  true
  • 38. Attack of the clones https://www.flickr.com/photos/hjmediastudios/7910348016/
  • 39. thirdsub  =  treeData.subdir.subsubdir.thirdsub;   newThirdSub  =  thirdsub.set("open",  true);     thirdsub  !==  newThirdSub;  //  true   treeData.subdir.subsubdir.thirdsub  !==  newThirdSub  //  true   treeData.subdir.subsubdir.thirdsub.open  ===  undefined;  //  true
  • 40. thirdsub  =  treeData.subdir.subsubdir.thirdsub;   newThirdSub  =  thirdsub.set("open",  true);   newSubSubDir  =  subsubdir.set("thirdsub",  newThirdSub);   newSubDir  =  subdir.set("subsubdir",  newSubSubDir);   treeData  =  treeData.set("subdir",  newSubDir);
  • 41.        function  _openPath(treeData,  path)  {                  var  objectPath  =  _filePathToObjectPath(treeData,  path);                  function  setOpen(node)  {                          return  node.set("open",  true);                  }                  while  (objectPath  &&  objectPath.length)  {                          var  node  =  treeData.getIn(objectPath);                          if  (isFile(node))  {                                  objectPath.pop();                          }  else  {                                  if  (!node.get("open"))  {                                          treeData  =  treeData.updateIn(objectPath,  setOpen);                                  }                                  objectPath.pop();                                  if  (objectPath.length)  {                                          objectPath.pop();                                  }                          }                  }                  return  treeData;          } mutable?
  • 42.        FileTreeViewModel.prototype.openPath  =  function  (path)  {                  this._commit(_openPath(this._treeData,  path));          };
  • 43.        FileTreeViewModel.prototype._commit  =  function  (treeData,  selectionViewInfo)  {                  var  changed  =  false;                  if  (treeData  &&  treeData  !==  this._treeData)  {                          this._treeData  =  treeData;                          changed  =  true;                  }                                    if  (selectionViewInfo  &&  selectionViewInfo  !==  this._selectionViewInfo)  {                          this._selectionViewInfo  =  selectionViewInfo;                          changed  =  true;                  }                  if  (changed)  {                          $(this).trigger(EVENT_CHANGE);                  }          };
  • 44. –C.A.R. Hoare “There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult.”
  • 46. simple! composed of one thing, not combined
  • 48. Simple Architecture • Each part does one thing with side effects in few, known places • React lets you generate a whole UI functionally • Immutable-JS allows you to control when data updates occur • Every part of your application can have a consistent state • Object identity tells you when something has changed
  • 49. A modern, open source text editor that understands web design. http://brackets.io