source: SRUAggregator/trunk/src/main/resources/assets/js/search.jsx @ 5900

Last change on this file since 5900 was 5900, checked in by emanuel.dima@uni-tuebingen.de, 9 years ago
  1. alpha 9: corpus view UI improvements, bug fixes
File size: 6.3 KB
Line 
1/** @jsx React.DOM */
2(function() {
3"use strict";
4
5var React = window.React;
6var PT = React.PropTypes;
7var ReactCSSTransitionGroup = window.React.addons.CSSTransitionGroup;
8// own components
9var InfoPopover = window.MyReact.InfoPopover;
10var Panel = window.MyReact.Panel;
11
12
13/////////////////////////////////
14
15var SearchBox = React.createClass({
16        propTypes: {
17                search: PT.func.isRequired,
18                placeholder: PT.string.isRequired,
19        },
20
21        getInitialState: function () {
22                return {
23                        query: "",
24                };
25        },
26
27        handleChange: function(event) {
28        this.setState({query: event.target.value});
29        },
30
31        handleKey: function(event) {
32        if (event.keyCode==13) {
33                this.search();
34        }
35        },
36
37        search: function() {
38                this.props.search(this.state.query);
39        },
40
41        render: function() {
42                return  <input className="form-control input-lg search"
43                                        name="query"
44                                        type="text"
45                                        value={this.state.query}
46                                        placeholder={this.props.placeholder}
47                                        tabIndex="1"
48                                        onChange={this.handleChange}
49                                        onKeyDown={this.handleKey} />  ;
50        }
51});
52
53/////////////////////////////////
54
55var Results = React.createClass({
56        propTypes: {
57                requests: PT.array.isRequired,
58                results: PT.array.isRequired,
59        },
60
61        getInitialState: function () {
62                return { displayKwic: false };
63        },
64
65        toggleKwic: function() {
66                this.setState({displayKwic:!this.state.displayKwic});
67        },
68
69        renderRowsAsHits: function(hit,i) {
70                function renderTextFragments(tf, idx) {
71                        return <span key={idx} className={tf.hit?"keyword":""}>{tf.text}</span>;
72                }
73                return  <p key={i} className="hitrow">
74                                        {hit.fragments.map(renderTextFragments)}
75                                </p>;
76        },
77
78        renderRowsAsKwic: function(hit,i) {
79                var sleft={textAlign:"left", verticalAlign:"middle", width:"50%"};
80                var scenter={textAlign:"center", verticalAlign:"middle", maxWidth:"50%"};
81                var sright={textAlign:"right", verticalAlign:"middle", maxWidth:"50%"};
82                return  <tr key={i} className="hitrow">
83                                        <td style={sright}>{hit.left}</td>
84                                        <td style={scenter} className="keyword">{hit.keyword}</td>
85                                        <td style={sleft}>{hit.right}</td>
86                                </tr>;
87        },
88
89        renderPanelTitle: function(corpus) {
90                var inline = {display:"inline-block"};
91                return  <div style={inline}>
92                                        <span className="corpusName"> {corpus.title ? corpus.title : corpus.displayName}</span>
93                                        <span className="institutionName"> — {corpus.institution.name}</span>
94                                </div>;
95        },
96
97        renderPanelInfo: function(corpus) {
98                var inline = {display:"inline-block"};
99                return  <div>
100                                        <InfoPopover placement="left"
101                                                        title={corpus.title ? corpus.title : corpus.displayName}>
102                                                <dl className="dl-horizontal">
103                                                        <dt>Institution</dt>
104                                                        <dd>{corpus.institution.name}</dd>
105
106                                                        {corpus.description ? <dt>Description</dt>:false}
107                                                        {corpus.description ? <dd>{corpus.description}</dd>: false}
108
109                                                        {corpus.landingPage ? <dt>Landing Page</dt> : false }
110                                                        {corpus.landingPage ?
111                                                                <dd><a href={corpus.landingPage}>{corpus.landingPage}</a></dd>:
112                                                                false}
113
114                                                        <dt>Languages</dt>
115                                                        <dd>{corpus.languages.join(", ")}</dd>
116                                                </dl>
117                                        </InfoPopover>
118                                        {" "}
119                                        <div style={inline}>
120                                                <button className="btn btn-default btn-xs" onClick={this.zoom}>
121                                                        <span className="glyphicon glyphicon-fullscreen"/>
122                                                </button>
123                                        </div>
124                                </div>;
125        },
126
127        renderPanelBody: function(corpusHit) {
128                var fulllength = {width:"100%"};               
129                if (this.state.displayKwic) {
130                        return  <table className="table table-condensed table-hover" style={fulllength}>
131                                                <tbody>{corpusHit.kwics.map(this.renderRowsAsKwic)}</tbody>
132                                        </table>;
133                } else {
134                        return  <div>{corpusHit.kwics.map(this.renderRowsAsHits)}</div>;
135                }
136        },
137
138        renderResultPanels: function(corpusHit) {
139                if (corpusHit.kwics.length === 0) {
140                        return false;
141                }
142                return  <Panel key={corpusHit.corpus.displayName}
143                                                title={this.renderPanelTitle(corpusHit.corpus)}
144                                                info={this.renderPanelInfo(corpusHit.corpus)}>
145                                        {this.renderPanelBody(corpusHit)}
146                                </Panel>;
147        },
148
149        renderProgressBar: function() {
150                var percents = 100 * this.props.results.length / (this.props.requests.length + this.props.results.length);
151                var sperc = Math.round(percents);
152                var styleperc = {width: sperc+"%"};
153                return this.props.requests.length > 0 ?
154                        <div className="progress" style={{marginBottom:10}}>
155                                <div className="progress-bar progress-bar-striped active" role="progressbar"
156                                        aria-valuenow={sperc} aria-valuemin="0" aria-valuemax="100" style={styleperc} />
157                        </div> :
158                        <span />;
159        },
160
161        renderSearchingMessage: function() {
162                return false;
163                // if (this.props.requests.length === 0)
164                //      return false;
165                // return "Searching in " + this.props.requests.length + " collections...";
166        },
167
168        renderFoundMessage: function(hits) {
169                if (this.props.results.length === 0)
170                        return false;
171                var total = this.props.results.length;
172                return hits + " collections with results found in " + total + " searched collections";
173        },
174
175        renderKwicCheckbox: function() {
176                return  <div key="-option-KWIC-" className="row">
177                                        <div className="float-right" style={{marginRight:17}}>
178                                                <div className="btn-group" style={{display:"inline-block"}}>
179                                                        <label forHtml="inputKwic" className="btn-default">
180                                                                { this.state.displayKwic ?
181                                                                        <input id="inputKwic" type="checkbox" value="kwic" checked onChange={this.toggleKwic} /> :
182                                                                        <input id="inputKwic" type="checkbox" value="kwic" onChange={this.toggleKwic} />
183                                                                }
184                                                                &nbsp;
185                                                                Display as Key Word In Context
186                                                        </label>
187                                                </div>
188                                        </div>
189                                </div>;
190        },
191
192        render: function() {
193                var hits = this.props.results.filter(function(corpusHit) { return corpusHit.kwics.length > 0; }).length;
194                var margintop = {marginTop:"10px"};
195                var margin = {marginTop:"0", padding:"20px"};
196                var inlinew = {display:"inline-block", margin:"0 5px 0 0", width:"240px;"};
197                var right= {float:"right"};
198                return  <div>
199                                        <ReactCSSTransitionGroup transitionName="fade">
200                                                <div key="-searching-message-" style={margintop}>{this.renderSearchingMessage()} </div>
201                                                <div key="-found-message-" style={margintop}>{this.renderFoundMessage(hits)} </div>
202                                                <div key="-progress-" style={margintop}>{this.renderProgressBar()}</div>
203                                                {hits > 0 ? this.renderKwicCheckbox() : false}
204                                                {this.props.results.map(this.renderResultPanels)}
205                                        </ReactCSSTransitionGroup>
206                                </div>;
207        }
208});
209
210if (!window.MyAggregator) {
211        window.MyAggregator = {};
212}
213window.MyAggregator.SearchBox = SearchBox;
214window.MyAggregator.Results = Results;
215})();
Note: See TracBrowser for help on using the repository browser.