From 4009ece74e3aaa967719b1796c21b30c93138bd1 Mon Sep 17 00:00:00 2001 From: Aaron Boodman Date: Fri, 4 Jul 2014 21:33:27 -0700 Subject: [PATCH] Replace cam.Nav with cam.NavReact. We weren't using the non-React one anymore. Change-Id: I9369dda7ed4b9fc45a1fd91ef0c6343f37e3baf5 --- server/camlistored/ui/index.js | 26 +-- server/camlistored/ui/nav.js | 300 ++++++++++++++--------------- server/camlistored/ui/nav_react.js | 199 ------------------- 3 files changed, 159 insertions(+), 366 deletions(-) delete mode 100644 server/camlistored/ui/nav_react.js diff --git a/server/camlistored/ui/index.js b/server/camlistored/ui/index.js index 1fdff7c5e..b0f92cce2 100644 --- a/server/camlistored/ui/index.js +++ b/server/camlistored/ui/index.js @@ -36,7 +36,7 @@ goog.require('cam.ContainerDetail'); goog.require('cam.DetailView'); goog.require('cam.DirectoryDetail'); goog.require('cam.Navigator'); -goog.require('cam.NavReact'); +goog.require('cam.Nav'); goog.require('cam.PermanodeDetail'); goog.require('cam.reactUtil'); goog.require('cam.SearchSession'); @@ -72,7 +72,7 @@ cam.IndexPage = React.createClass({ history: React.PropTypes.shape({pushState:React.PropTypes.func.isRequired, replaceState:React.PropTypes.func.isRequired, go:React.PropTypes.func.isRequired, state:React.PropTypes.object}).isRequired, location: React.PropTypes.shape({href:React.PropTypes.string.isRequired, reload:React.PropTypes.func.isRequired}).isRequired, serverConnection: React.PropTypes.instanceOf(cam.ServerConnection).isRequired, - timer: cam.NavReact.originalSpec.propTypes.timer, + timer: cam.Nav.originalSpec.propTypes.timer, }, componentWillMount: function() { @@ -214,17 +214,17 @@ cam.IndexPage = React.createClass({ if (!this.isSearchMode_(this.state.currentURL)) { return null; } - return cam.NavReact({key:'nav', ref:'nav', timer:this.props.timer, open:this.state.isNavOpen, onOpen:this.handleNavOpen_, onClose:this.handleNavClose_}, [ - cam.NavReact.SearchItem({key:'search', ref:'search', iconSrc:'magnifying_glass.svg', onSearch:this.setSearch_}, 'Search'), + return cam.Nav({key:'nav', ref:'nav', timer:this.props.timer, open:this.state.isNavOpen, onOpen:this.handleNavOpen_, onClose:this.handleNavClose_}, [ + cam.Nav.SearchItem({key:'search', ref:'search', iconSrc:'magnifying_glass.svg', onSearch:this.setSearch_}, 'Search'), this.getCreateSetWithSelectionItem_(), - cam.NavReact.Item({key:'roots', iconSrc:'icon_27307.svg', onClick:this.handleShowSearchRoots_}, 'Search roots'), + cam.Nav.Item({key:'roots', iconSrc:'icon_27307.svg', onClick:this.handleShowSearchRoots_}, 'Search roots'), this.getSelectAsCurrentSetItem_(), this.getAddToCurrentSetItem_(), this.getClearSelectionItem_(), this.getDeleteSelectionItem_(), - cam.NavReact.Item({key:'up', iconSrc:'up.svg', onClick:this.handleEmbiggen_}, 'Moar bigger'), - cam.NavReact.Item({key:'down', iconSrc:'down.svg', onClick:this.handleEnsmallen_}, 'Less bigger'), - cam.NavReact.LinkItem({key:'logo', iconSrc:'/favicon.ico', href:this.baseURL_.toString(), extraClassName:'cam-logo'}, 'Camlistore'), + cam.Nav.Item({key:'up', iconSrc:'up.svg', onClick:this.handleEmbiggen_}, 'Moar bigger'), + cam.Nav.Item({key:'down', iconSrc:'down.svg', onClick:this.handleEnsmallen_}, 'Less bigger'), + cam.Nav.LinkItem({key:'logo', iconSrc:'/favicon.ico', href:this.baseURL_.toString(), extraClassName:'cam-logo'}, 'Camlistore'), ]); }, @@ -381,14 +381,14 @@ cam.IndexPage = React.createClass({ return null; } - return cam.NavReact.Item({key:'selectascurrent', iconSrc:'target.svg', onClick:this.handleSelectAsCurrentSet_}, 'Select as current set'); + return cam.Nav.Item({key:'selectascurrent', iconSrc:'target.svg', onClick:this.handleSelectAsCurrentSet_}, 'Select as current set'); }, getAddToCurrentSetItem_: function() { if (!this.currentSet_ || !goog.object.getAnyKey(this.state.selection)) { return null; } - return cam.NavReact.Item({key:'addtoset', iconSrc:'icon_16716.svg', onClick:this.handleAddToSet_}, 'Add to current set'); + return cam.Nav.Item({key:'addtoset', iconSrc:'icon_16716.svg', onClick:this.handleAddToSet_}, 'Add to current set'); }, getCreateSetWithSelectionItem_: function() { @@ -399,14 +399,14 @@ cam.IndexPage = React.createClass({ } else if (numItems > 1) { label += goog.string.subs(' with %s items', numItems); } - return cam.NavReact.Item({key:'createsetwithselection', iconSrc:'circled_plus.svg', onClick:this.handleCreateSetWithSelection_}, label); + return cam.Nav.Item({key:'createsetwithselection', iconSrc:'circled_plus.svg', onClick:this.handleCreateSetWithSelection_}, label); }, getClearSelectionItem_: function() { if (!goog.object.getAnyKey(this.state.selection)) { return null; } - return cam.NavReact.Item({key:'clearselection', iconSrc:'clear.svg', onClick:this.handleClearSelection_}, 'Clear selection'); + return cam.Nav.Item({key:'clearselection', iconSrc:'clear.svg', onClick:this.handleClearSelection_}, 'Clear selection'); }, getDeleteSelectionItem_: function() { @@ -421,7 +421,7 @@ cam.IndexPage = React.createClass({ label += goog.string.subs(' (%s) selected items', numItems); } // TODO(mpl): better icon in another CL, with Font Awesome. - return cam.NavReact.Item({key:'deleteselection', iconSrc:'trash.svg', onClick:this.handleDeleteSelection_}, label); + return cam.Nav.Item({key:'deleteselection', iconSrc:'trash.svg', onClick:this.handleDeleteSelection_}, label); }, handleSelectionChange_: function(newSelection) { diff --git a/server/camlistored/ui/nav.js b/server/camlistored/ui/nav.js index 18afb950e..703c5f836 100644 --- a/server/camlistored/ui/nav.js +++ b/server/camlistored/ui/nav.js @@ -1,5 +1,5 @@ /* -Copyright 2013 The Camlistore Authors. +Copyright 2014 The Camlistore Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -19,189 +19,181 @@ goog.provide('cam.Nav.Item'); goog.provide('cam.Nav.LinkItem'); goog.provide('cam.Nav.SearchItem'); -goog.require('goog.dom'); -goog.require('goog.dom.classes'); goog.require('goog.events.KeyCodes'); -goog.require('goog.ui.Container'); -goog.require('goog.ui.Component'); -goog.require('goog.ui.Control'); -goog.require('goog.ui.Button'); +goog.require('cam.object'); +goog.require('cam.reactUtil'); goog.require('cam.style'); -goog.require('cam.Navigator'); -// A vertical, fixed-position expandy collapsy navigation bar thingy. -cam.Nav = function(domHelper, opt_delegate) { - goog.base(this, null, null, domHelper); +cam.Nav = React.createClass({ + displayName: 'Nav', - this.delegate_ = opt_delegate; - this.expandTimer_ = 0; -}; -goog.inherits(cam.Nav, goog.ui.Container); + propTypes: { + onOpen: React.PropTypes.func.isRequired, + onClose: React.PropTypes.func.isRequired, + open: React.PropTypes.bool.isRequired, + timer: React.PropTypes.shape({setTimeout: React.PropTypes.func.isRequired, clearTimeout: React.PropTypes.func.isRequired,}).isRequired, + }, -cam.Nav.prototype.createDom = function() { - this.setElementInternal(this.dom_.createDom('div')); - goog.dom.classes.add(this.element_, 'cam-nav'); + componentWillMount: function() { + this.expandTimer_ = 0; + }, - this.closeButton_ = this.dom_.createDom('img', 'cam-nav-close'); - this.closeButton_.src = 'close.svg'; - this.getElement().appendChild(this.closeButton_); + render: function() { + return React.DOM.div({ + className: React.addons.classSet({ + 'cam-nav': true, + 'cam-nav-collapsed': !this.props.open, + }), + onMouseEnter: this.handleMouseEnter_, + onMouseLeave: this.handleMouseLeave_, + onKeyUp: this.handleKeyUp_, + }, + React.DOM.img({className:'cam-nav-close', src:'close.svg', onClick: this.handleCloseClick_}), + this.props.children + ); + }, - this.close(); -}; + open: function() { + this.clearExpandTimer_(); + this.props.onOpen(); + }, -cam.Nav.prototype.enterDocument = function() { - goog.base(this, 'enterDocument'); + close: function() { + this.clearExpandTimer_(); + this.props.onClose(); + }, - this.getHandler().listen(this.getElement(), 'mouseover', this.handleMouseOver_); - this.getHandler().listen(this.getElement(), 'mouseout', this.handleMouseOut_); + handleMouseEnter_: function(e) { + this.clearExpandTimer_(); + this.expandTimer_ = this.props.timer.setTimeout(this.open, 250); + }, - this.getHandler().listen(this.closeButton_, 'click', function(e) { - e.stopPropagation(); - this.close(); - }.bind(this)); - - this.getHandler().listen(this.getElement(), 'keyup', function(e) { - if (e.keyCode == goog.events.KeyCodes.ESC) { - this.close(); - e.preventDefault(); + clearExpandTimer_: function() { + if (this.expandTimer_) { + this.props.timer.clearTimeout(this.expandTimer_); + this.expandTimer_ = 0; } - }); -}; + }, -cam.Nav.prototype.open = function() { - if (this.delegate_) { - this.delegate_.onNavOpen(); - } - goog.dom.classes.remove(this.getElement(), 'cam-nav-collapsed'); -}; + handleMouseLeave_: this.clearExpandTimer_, -cam.Nav.prototype.close = function() { - if (this.delegate_) { - this.delegate_.onNavClose(); - } + handleKeyUp_: function(e) { + if (e.keyCode == goog.events.KeyCodes.ESC) { + e.preventDefault(); + this.close(); + } + }, - goog.dom.classes.add(this.getElement(), 'cam-nav-collapsed'); -}; - -cam.Nav.prototype.isOpen = function() { - return !goog.dom.classes.has(this.getElement(), 'cam-nav-collapsed'); -}; - -cam.Nav.prototype.toggle = function() { - if (this.isOpen()) { + handleCloseClick_: function(e) { + e.stopPropagation(); this.close(); - return false; - } else { - this.open(); - return true; - } + }, +}); + +cam.Nav.ItemBase = { + propTypes: { + iconSrc: React.PropTypes.string.isRequired, + }, + + getRootProps_: function(opt_extraClassName) { + var className = 'cam-nav-item'; + if (opt_extraClassName) { + className += ' ' + opt_extraClassName; + } + return { + className: className, + style: {backgroundImage:cam.style.getURLValue(this.props.iconSrc)}, + }; + }, }; -cam.Nav.prototype.handleMouseOver_ = function() { - this.expandTimer_ = window.setTimeout(function() { - this.expandTimer_ = 0; - this.open(); - }.bind(this), 250); -}; +cam.Nav.Item = React.createClass(cam.reactUtil.extend(cam.Nav.ItemBase, { + propTypes: { + onClick: React.PropTypes.func, + }, -cam.Nav.prototype.handleMouseOut_ = function() { - if (this.expandTimer_) { - window.clearTimeout(this.expandTimer_); - this.expandTimer_ = 0; - } -}; + render: function() { + return React.DOM.button(cam.object.extend(this.getRootProps_(), { + onClick: this.props.onClick + }), this.props.children); + }, +})); -cam.Nav.Item = function(domHelper, iconSrc, content) { - goog.base(this, content, null, domHelper); - this.iconSrc_ = iconSrc; - this.addClassName('cam-nav-item'); -}; -goog.inherits(cam.Nav.Item, goog.ui.Button); +cam.Nav.SearchItem = React.createClass(cam.reactUtil.extend(cam.Nav.ItemBase, { + propTypes: { + value: React.PropTypes.string, + onSearch: React.PropTypes.func.isRequired, + }, -cam.Nav.Item.prototype.onClick = function() {}; + getDefaultProps: function() { + return { + value: '', + } + }, -cam.Nav.Item.prototype.createDom = function() { - goog.base(this, 'createDom'); - this.setIcon(this.iconSrc_); -}; + render: function() { + if (!goog.isString(this.props.children)) { + throw new Error('Children of cam.Nav.SearchItem must be a single string.'); + } -cam.Nav.Item.prototype.enterDocument = function() { - this.getHandler().listen(this.getElement(), 'click', function(e) { - this.onClick(); - e.stopPropagation(); - }); -}; + return React.DOM.div(this.getRootProps_('cam-nav-searchitem'), + React.DOM.form({onClick:this.focus, onSubmit:this.handleSubmit_}, + React.DOM.input({ + ref:'input', + placeholder:this.props.children, + defaultValue: this.props.value, + onChange: this.handleChange_, + onMouseEnter: this.focus, + }) + ) + ); + }, -cam.Nav.Item.prototype.setIcon = function(src) { - this.iconSrc_ = src; - if (this.element_) { - this.element_.style.backgroundImage = cam.style.getURLValue(src); - } -}; + focus: function() { + this.getInputNode_().focus(); + }, + blur: function() { + this.getInputNode_().blur(); + }, -cam.Nav.SearchItem = function(domHelper, iconSrc, label) { - goog.base(this, domHelper, iconSrc, label); - this.setAllowTextSelection(true); - this.addClassName('cam-nav-searchitem'); -}; -goog.inherits(cam.Nav.SearchItem, cam.Nav.Item); + clear: function() { + this.getInputNode_().value = ''; + }, -cam.Nav.SearchItem.prototype.onSearch = function(value) {}; - -cam.Nav.SearchItem.prototype.setText = function(text) { - if (this.input_) { - this.input_.value = text; - } -}; - -cam.Nav.SearchItem.prototype.focus = function() { - this.input_.focus(); -}; - -cam.Nav.SearchItem.prototype.blur = function() { - this.input_.blur(); -}; - -cam.Nav.SearchItem.prototype.createDom = function() { - this.setElementInternal(this.dom_.createDom('div', this.getExtraClassNames())); - this.form_ = this.dom_.createDom('form'); - this.input_ = this.dom_.createDom('input', {'placeholder': this.getContent()}); - this.form_.appendChild(this.input_); - this.getElement().appendChild(this.form_); - this.setIcon(this.iconSrc_); -}; - -cam.Nav.SearchItem.prototype.enterDocument = function() { - goog.base(this, 'enterDocument'); - - this.getHandler().listen(this.input_, 'mouseover', this.input_.focus.bind(this.input_)); - - this.getHandler().listen(this.getElement(), 'click', function(e) { - this.input_.focus(); - e.stopPropagation(); - }.bind(this)); - - this.getHandler().listen(this.form_, 'submit', function(e) { - this.onSearch(this.input_.value); + handleSubmit_: function(e) { + this.props.onSearch(this.getInputNode_().value); e.preventDefault(); - }); -}; + }, + + getInputNode_: function() { + return this.refs.input.getDOMNode(); + } +})); -cam.Nav.LinkItem = function(domHelper, iconSrc, label, linkUrl) { - goog.base(this, domHelper, iconSrc, label); - this.linkUrl_ = linkUrl; - this.addClassName('cam-nav-linkitem'); -}; -goog.inherits(cam.Nav.LinkItem, cam.Nav.Item); +cam.Nav.LinkItem = React.createClass(cam.reactUtil.extend(cam.Nav.ItemBase, { + propTypes: { + extraClassName: React.PropTypes.string, + href: React.PropTypes.string.isRequired, + }, -cam.Nav.LinkItem.prototype.onClick = function(url) {}; + getDefaultProps: function() { + return { + extraClassName: '', + }; + }, -cam.Nav.LinkItem.prototype.createDom = function() { - this.setElementInternal(this.dom_.createDom('a', this.getExtraClassNames(), this.getContent())); - this.getElement().href = this.linkUrl_; - this.setIcon(this.iconSrc_); -}; + render: function() { + var extraClassName = 'cam-nav-linkitem'; + if (this.props.extraClassName != '') { + extraClassName += ' ' + this.props.extraClassName; + } + return React.DOM.a( + cam.object.extend(this.getRootProps_(extraClassName), {href:this.props.href}), + this.props.children + ); + }, +})); diff --git a/server/camlistored/ui/nav_react.js b/server/camlistored/ui/nav_react.js deleted file mode 100644 index 647fd84fd..000000000 --- a/server/camlistored/ui/nav_react.js +++ /dev/null @@ -1,199 +0,0 @@ -/* -Copyright 2014 The Camlistore Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -goog.provide('cam.NavReact'); -goog.provide('cam.NavReact.Item'); -goog.provide('cam.NavReact.LinkItem'); -goog.provide('cam.NavReact.SearchItem'); - -goog.require('goog.events.KeyCodes'); - -goog.require('cam.object'); -goog.require('cam.reactUtil'); -goog.require('cam.style'); - -cam.NavReact = React.createClass({ - displayName: 'NavReact', - - propTypes: { - onOpen: React.PropTypes.func.isRequired, - onClose: React.PropTypes.func.isRequired, - open: React.PropTypes.bool.isRequired, - timer: React.PropTypes.shape({setTimeout: React.PropTypes.func.isRequired, clearTimeout: React.PropTypes.func.isRequired,}).isRequired, - }, - - componentWillMount: function() { - this.expandTimer_ = 0; - }, - - render: function() { - return React.DOM.div({ - className: React.addons.classSet({ - 'cam-nav': true, - 'cam-nav-collapsed': !this.props.open, - }), - onMouseEnter: this.handleMouseEnter_, - onMouseLeave: this.handleMouseLeave_, - onKeyUp: this.handleKeyUp_, - }, - React.DOM.img({className:'cam-nav-close', src:'close.svg', onClick: this.handleCloseClick_}), - this.props.children - ); - }, - - open: function() { - this.clearExpandTimer_(); - this.props.onOpen(); - }, - - close: function() { - this.clearExpandTimer_(); - this.props.onClose(); - }, - - handleMouseEnter_: function(e) { - this.clearExpandTimer_(); - this.expandTimer_ = this.props.timer.setTimeout(this.open, 250); - }, - - clearExpandTimer_: function() { - if (this.expandTimer_) { - this.props.timer.clearTimeout(this.expandTimer_); - this.expandTimer_ = 0; - } - }, - - handleMouseLeave_: this.clearExpandTimer_, - - handleKeyUp_: function(e) { - if (e.keyCode == goog.events.KeyCodes.ESC) { - e.preventDefault(); - this.close(); - } - }, - - handleCloseClick_: function(e) { - e.stopPropagation(); - this.close(); - }, -}); - -cam.NavReact.ItemBase = { - propTypes: { - iconSrc: React.PropTypes.string.isRequired, - }, - - getRootProps_: function(opt_extraClassName) { - var className = 'cam-nav-item'; - if (opt_extraClassName) { - className += ' ' + opt_extraClassName; - } - return { - className: className, - style: {backgroundImage:cam.style.getURLValue(this.props.iconSrc)}, - }; - }, -}; - -cam.NavReact.Item = React.createClass(cam.reactUtil.extend(cam.NavReact.ItemBase, { - propTypes: { - onClick: React.PropTypes.func, - }, - - render: function() { - return React.DOM.button(cam.object.extend(this.getRootProps_(), { - onClick: this.props.onClick - }), this.props.children); - }, -})); - - -cam.NavReact.SearchItem = React.createClass(cam.reactUtil.extend(cam.NavReact.ItemBase, { - propTypes: { - value: React.PropTypes.string, - onSearch: React.PropTypes.func.isRequired, - }, - - getDefaultProps: function() { - return { - value: '', - } - }, - - render: function() { - if (!goog.isString(this.props.children)) { - throw new Error('Children of cam.NavReact.SearchItem must be a single string.'); - } - - return React.DOM.div(this.getRootProps_('cam-nav-searchitem'), - React.DOM.form({onClick:this.focus, onSubmit:this.handleSubmit_}, - React.DOM.input({ - ref:'input', - placeholder:this.props.children, - defaultValue: this.props.value, - onChange: this.handleChange_, - onMouseEnter: this.focus, - }) - ) - ); - }, - - focus: function() { - this.getInputNode_().focus(); - }, - - blur: function() { - this.getInputNode_().blur(); - }, - - clear: function() { - this.getInputNode_().value = ''; - }, - - handleSubmit_: function(e) { - this.props.onSearch(this.getInputNode_().value); - e.preventDefault(); - }, - - getInputNode_: function() { - return this.refs.input.getDOMNode(); - } -})); - - -cam.NavReact.LinkItem = React.createClass(cam.reactUtil.extend(cam.NavReact.ItemBase, { - propTypes: { - extraClassName: React.PropTypes.string, - href: React.PropTypes.string.isRequired, - }, - - getDefaultProps: function() { - return { - extraClassName: '', - }; - }, - - render: function() { - var extraClassName = 'cam-nav-linkitem'; - if (this.props.extraClassName != '') { - extraClassName += ' ' + this.props.extraClassName; - } - return React.DOM.a( - cam.object.extend(this.getRootProps_(extraClassName), {href:this.props.href}), - this.props.children - ); - }, -}));