Просмотр исходного кода

refs #237
- component のコードを整理
- FB 対応 ※focus() 処理を jQuery 利用しないようにする方法は未実装

Ryu Sato 8 лет назад
Родитель
Сommit
a7ead2e0b6

+ 15 - 33
resource/js/components/NewPageNameInputter.js

@@ -15,24 +15,17 @@ export default class NewPageNameInputter extends React.Component {
 
     super(props);
 
-    this.crowi = window.crowi; // FIXME
-
     this.state = {
       input: '',
       keyword: '',
-      searchedKeyword: '',
-      pages: [],
       isLoading: false,
       searchError: null,
     };
-
-    this.crowi = window.crowi; // FIXME
+    this.crowi = this.props.crowi;
 
     this.onSearchSuccess = this.onSearchSuccess.bind(this);
     this.onSearchError = this.onSearchError.bind(this);
-    this.restoreForm = this.restoreForm.bind(this);
-    this.renderMenuItemChildren = this.renderMenuItemChildren.bind(this);
-    this.onInputChange = this.onInputChange.bind(this);
+    this.getParentPageName = this.getParentPageName.bind(this);
   }
 
   componentDidMount() {
@@ -56,50 +49,39 @@ export default class NewPageNameInputter extends React.Component {
     });
   }
 
-  onInputChange(text) {
-    this.setState({input: text});
-  }
+  getParentPageName(path) {
+    if (path == '/') {
+      return path;
+    }
 
-  /**
-   * Initialize keyword
-   */
-  restoreForm() {
-    this._searchtypeahead._typeahead.getInstance().clear();
-    this._searchtypeahead._typeahead.getInstance()._updateText(this.props.parentPageName);
-  }
+    if (path.match(/.+\/$/)) {
+      return path;
+    }
 
-  renderMenuItemChildren(option, props, index) {
-    const page = option;
-    return (
-      <span>
-        <UserPicture user={page.revision.author} />
-        <PagePath page={page} />
-        <PageListMeta page={page} />
-      </span>
-    );
+    return path + '/';
   }
 
   render() {
     const emptyLabel = (this.state.searchError !== null)
-        ? 'Error on searching.'
-        : 'No matches found on title...';
+      ? 'Error on searching.'
+      : 'No matches found on title...';
 
     return (
       <SearchTypeahead
-        ref={(searchTypeahead) => this._searchtypeahead = searchTypeahead}
         crowi={this.crowi}
         onSearchSuccess={this.onSearchSuccess}
         onSearchError={this.onSearchError}
-        onResetButton={this.restoreForm}
         emptyLabel={emptyLabel}
-        keywordOnInit={this.props.parentPageName}
+        keywordOnInit={this.getParentPageName(this.props.parentPageName)}
       />
     );
   }
 }
 
 NewPageNameInputter.propTypes = {
+  crowi:          PropTypes.object.isRequired,
   parentPageName: PropTypes.string.isRequired,
 };
+
 NewPageNameInputter.defaultProps = {
 };

+ 68 - 23
resource/js/components/SearchTypeahead.js

@@ -1,5 +1,4 @@
 import React from 'react';
-import { FormGroup, Button, InputGroup } from 'react-bootstrap';
 
 import { AsyncTypeahead } from 'react-bootstrap-typeahead';
 
@@ -14,8 +13,6 @@ export default class SearchTypeahead extends React.Component {
 
     super(props);
 
-    this.crowi = window.crowi; // FIXME
-
     this.state = {
       input: '',
       keyword: '',
@@ -24,21 +21,50 @@ export default class SearchTypeahead extends React.Component {
       isLoading: false,
       searchError: null,
     };
+    this.crowi = this.props.crowi;
+    this.emptyLabel = props.emptyLabel;
 
     this.search = this.search.bind(this);
     this.onInputChange = this.onInputChange.bind(this);
     this.onChange = this.onChange.bind(this);
     this.getRestoreFormButton = this.getRestoreFormButton.bind(this);
     this.renderMenuItemChildren = this.renderMenuItemChildren.bind(this);
-    this.emptyLabel = props.emptyLabel;
+    this.restoreInitialData = this.restoreInitialData.bind(this);
+    this.getTypeahead = this.getTypeahead.bind(this);
+    this.forceToFocus = this.forceToFocus.bind(this);
+  }
+
+  /**
+   * Get instance of AsyncTypeahead
+   */
+  getTypeahead() {
+    return this.refs.typeahead ? this.refs.typeahead.getInstance() : null;
   }
 
   componentDidMount() {
+    /*
+    this.forceToFocus(); // cf. It is needed for displaing placeholder.
+                         //     And cannot focus on if set autoFocus=true to AsyncTypeahead,
+                         //       also set to inputProps of AsyncTypeahead.
+    */
   }
 
   componentWillUnmount() {
   }
 
+  /**
+   * force to focus
+   */
+  forceToFocus() {
+    const typeahead = this.getTypeahead();
+    const intervalId = setInterval(() => {
+      this.getTypeahead().focus();
+      if (typeahead.state.isFocused) {
+        clearInterval(intervalId);
+      }
+    }, 100);
+  }
+
   search(keyword) {
 
     if (keyword === '') {
@@ -57,7 +83,7 @@ export default class SearchTypeahead extends React.Component {
   }
 
   /**
-   * Occured when search is exit successfully
+   * Callback function which is occured when search is exit successfully
    * @param {*} pages
    */
   _onSearchSuccess(res) {
@@ -70,7 +96,7 @@ export default class SearchTypeahead extends React.Component {
   }
 
   /**
-   * Occured when search is exit abnormaly
+   * Callback function which is occured when search is exit abnormaly
    * @param {*} err
    */
   _onSearchError(err) {
@@ -81,16 +107,6 @@ export default class SearchTypeahead extends React.Component {
     this.props.onSearchError(err);
   }
 
-  getRestoreFormButton() {
-    let isHidden = (this.state.input.length === 0);
-
-    return isHidden ? <span></span> : (
-      <a className="btn btn-link search-top-clear" onClick={this.props.onResetButton} hidden={isHidden}>
-        <i className="fa fa-times-circle" />
-      </a>
-    );
-  }
-
   onInputChange(text) {
     this.setState({input: text});
   }
@@ -115,10 +131,31 @@ export default class SearchTypeahead extends React.Component {
     );
   }
 
+  /**
+   * Initialize keyword
+   */
+  restoreInitialData() {
+    this.refs.typeahead.getInstance().clear();
+    this.refs.typeahead.getInstance()._updateText(this.props.keywordOnInit);
+  }
+
+  /**
+   * Get restore form button to initialize button
+   */
+  getRestoreFormButton() {
+    let isHidden = (this.state.input.length === 0);
+
+    return isHidden ? <span></span> : (
+      <a className="btn btn-link search-top-clear" onClick={this.restoreInitialData} hidden={isHidden}>
+        <i className="fa fa-times-circle" />
+      </a>
+    );
+  }
+
   render() {
     const emptyLabel = (this.state.searchError !== null)
-        ? 'Error on searching.'
-        : 'No matches found on title...';
+      ? 'Error on searching.'
+      : 'No matches found on title...';
     const restoreFormButton = this.getRestoreFormButton();
 
     return (
@@ -127,12 +164,12 @@ export default class SearchTypeahead extends React.Component {
         className=""
         >
       <AsyncTypeahead
-        ref={(typeahead) => this._typeahead = typeahead}
+        ref="typeahead"
         inputProps={{name: "q", autoComplete: "off"}}
         isLoading={this.state.isLoading}
         labelKey="path"
         minLength={2}
-        options={this.state.pages} // 検索結果
+        options={this.state.pages} // Search result (Some page names)
         placeholder="Input page name"
         emptyLabel={this.emptyLabel ? this.emptyLabel : emptyLabel}
         align='left'
@@ -145,21 +182,29 @@ export default class SearchTypeahead extends React.Component {
       />
       {restoreFormButton}
       {/* [TODO] デバッグ用の表示。実装が完了したら削除する。 */}
-      <span>keyword: {this.state.keyword}, keywordOnInit: {this.props.keywordOnInit}</span>
+      <span>keyword: {this.state.keyword}, keywordOnInit: {this.props.keywordOnInit}, typeahead.state.isFocused: {this.getTypeahead() ? this.refs.typeahead.state.isFocused : '-' }</span>
       </form>
     );
   }
 }
 
+/**
+ * Properties
+ */
 SearchTypeahead.propTypes = {
+  crowi:           PropTypes.object.isRequired,
   onSearchSuccess: PropTypes.func,
   onSearchError:   PropTypes.func,
-  onResetButton:   PropTypes.func,
-  restoreAction:   PropTypes.func,
   emptyLabel:      PropTypes.string,
   keywordOnInit:   PropTypes.string,
 };
 
+/**
+ * Properties
+ */
 SearchTypeahead.defaultProps = {
+  onSearchSuccess: {},
+  onSearchError:   {},
+  emptyLabel:      null,
   keywordOnInit:   "",
 };

+ 1 - 1
resource/js/legacy/crowi.js

@@ -239,7 +239,7 @@ $(function() {
       - $('#create-page-today .page-today-suffix').outerWidth()
       - 42
       ;
-    $('#page-name-inputter .form-control').focus(); // focus() を実行しないと placeholder が表示されない。
+    //$('#page-name-inputter .form-control').focus(); // focus() を実行しないと placeholder が表示されない。[TODO] jQuery から focus() を実行せずにフォーカスを当てる
     $('#create-page-today .form-control.page-today-input2').css({width: newWidth}).focus();
 
   });