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

Last change on this file since 5954 was 5954, checked in by emanuel.dima@uni-tuebingen.de, 9 years ago
  1. alpha14: collections view stable sorting, better filtering; upfront diagnostic messages for search
File size: 23.1 KB
Line 
1/** @jsx React.DOM */
2(function() {
3"use strict";
4
5window.MyAggregator = window.MyAggregator || {};
6
7var React = window.React;
8var PT = React.PropTypes;
9var ReactCSSTransitionGroup = React.addons.CSSTransitionGroup;
10
11var CorpusSelection = window.MyAggregator.CorpusSelection;
12var HitNumber = window.MyAggregator.HitNumber;
13var CorpusView = window.MyAggregator.CorpusView;
14var Popover = window.MyReact.Popover;
15var InfoPopover = window.MyReact.InfoPopover;
16var Panel = window.MyReact.Panel;
17var Modal = window.MyReact.Modal;
18
19var multipleLanguageCode = "mul"; // see ISO-693-3
20
21var layers = [
22        {
23                id: "sampa",
24                name: "Phonetic Transcriptions",
25                searchPlaceholder: "stA:z",
26                searchLabel: "SAMPA query",
27                searchLabelBkColor: "#eef",
28        },
29        {
30                id: "text",
31                name: "Text Resources",
32                searchPlaceholder: "Elephant",
33                searchLabel: "Search text",
34                searchLabelBkColor: "#fed",
35        },
36];
37var layerMap = {
38        sampa: layers[0], 
39        text: layers[1],
40};
41
42function Corpora(corpora, updateFn) {
43        var that = this;
44        this.corpora = corpora;
45        this.update = function() { 
46                updateFn(that); 
47        };
48       
49        var sortFn = function(x, y) {
50                var r = x.institution.name.localeCompare(y.institution.name);
51                if (r !== 0) {
52                        return r;
53                }
54                var t1 = x.title ? x.title : x.displayName;
55                var t2 = y.title ? y.title : y.displayName;
56                return t1.toLowerCase().localeCompare(t2.toLowerCase()); 
57        };
58
59        this.recurse(function(corpus) { corpus.subCorpora.sort(sortFn); });
60        this.corpora.sort(sortFn);
61
62        this.recurse(function(corpus, index) {
63                corpus.visible = true; // visible in the corpus view
64                corpus.selected = true; // selected in the corpus view
65                corpus.expanded = false; // not expanded in the corpus view
66                corpus.priority = 1; // priority in corpus view
67                corpus.index = index; // original order, used for stable sort
68        });
69}
70
71Corpora.prototype.recurseCorpus = function(corpus, fn) {
72        if (false === fn(corpus)) {             
73                // no recursion
74        } else {
75                this.recurseCorpora(corpus.subCorpora, fn);
76        }
77};
78
79Corpora.prototype.recurseCorpora = function(corpora, fn) {
80        var recfn = function(corpus, index){
81                if (false === fn(corpus, index)) {
82                        // no recursion
83                } else {
84                        corpus.subCorpora.forEach(recfn);
85                }
86        };
87        corpora.forEach(recfn);
88};
89
90Corpora.prototype.recurse = function(fn) {
91        this.recurseCorpora(this.corpora, fn);
92};
93
94Corpora.prototype.getLanguageCodes = function() {
95        var languages = {};
96        this.recurse(function(corpus) {
97                corpus.languages.forEach(function(lang) {
98                        languages[lang] = true;
99                });
100                return true;
101        });
102        return languages;
103};
104
105Corpora.prototype.isCorpusVisible = function(corpus, layerId, languageCode) {
106        if (layerId !== "text") {
107                return false;
108        }
109        // yes for any language
110        if (languageCode === multipleLanguageCode) {
111                return true;
112        }
113        // yes if the corpus is in only that language
114        if (corpus.languages && corpus.languages.length === 1 && corpus.languages[0] === languageCode) {
115                return true;
116        }       
117
118        // ? yes if the corpus also contains that language
119        if (corpus.languages && corpus.languages.indexOf(languageCode) >=0) {
120                return true;
121        }
122
123        // ? yes if the corpus has no language
124        // if (!corpus.languages || corpus.languages.length === 0) {
125        //      return true;
126        // }
127        return false;
128};
129
130Corpora.prototype.setVisibility = function(layerId, languageCode) {
131        // top level
132        this.corpora.forEach(function(corpus) {
133                corpus.visible = this.isCorpusVisible(corpus, layerId, languageCode);
134                this.recurseCorpora(corpus.subCorpora, function(c) { c.visible = corpus.visible; });
135        }.bind(this));
136};
137
138Corpora.prototype.getSelectedIds = function() {
139        var ids = [];
140        this.recurse(function(corpus) {
141                if (corpus.visible && corpus.selected) {
142                        ids.push(corpus.id);
143                        return false; // top-most collection in tree, don't delve deeper
144                }
145                return true;
146        });
147
148        // console.log("ids: ", ids.length, {ids:ids});
149        return ids;
150};
151
152Corpora.prototype.getSelectedMessage = function() {
153        var selected = this.getSelectedIds().length;
154        if (this.corpora.length === selected) {
155                return "All available collections";
156        } else if (selected === 1) {
157                return "1 selected collection";
158        }
159        return selected+" selected collections";
160};
161
162
163var AggregatorPage = window.MyAggregator.AggregatorPage = React.createClass({displayName: 'AggregatorPage',
164        propTypes: {
165                ajax: PT.func.isRequired
166        },
167
168        timeout: 0,
169        nohits: { 
170                requests: [],
171                results: [],
172        },
173        anyLanguage: [multipleLanguageCode, "Any Language"],
174
175        getInitialState: function () {
176                return {
177                        corpora: new Corpora([], this.updateCorpora),
178                        languageMap: {},
179                        language: this.anyLanguage,
180                        languageFilter: 'byMeta',
181                        searchLayerId: "text",
182                        numberOfResults: 10,
183
184                        searchId: null,
185                        hits: this.nohits,
186                };
187        },
188
189        componentDidMount: function() {
190                this.refreshCorpora();
191                this.refreshLanguages();
192        },
193
194        refreshCorpora: function() {
195                this.props.ajax({
196                        url: 'rest/corpora',
197                        success: function(json, textStatus, jqXHR) {
198                                this.setState({corpora : new Corpora(json, this.updateCorpora)});
199                        }.bind(this),
200                });
201        },
202
203        refreshLanguages: function() {
204                this.props.ajax({
205                        url: 'rest/languages',
206                        success: function(json, textStatus, jqXHR) {
207                                this.setState({languageMap : json});
208                        }.bind(this),
209                });
210        },
211
212        updateCorpora: function(corpora) {
213                this.setState({corpora:corpora});
214        },
215
216        search: function(query) {
217                // console.log(query);
218                if (!query) {
219                        this.setState({ hits: this.nohits, searchId: null });
220                        return;                 
221                }
222                this.props.ajax({
223                        url: 'rest/search',
224                        type: "POST",
225                        data: {
226                                layer: this.state.searchLayerId,
227                                language: this.state.language[0],
228                                query: query,
229                                numberOfResults: this.state.numberOfResults,
230                                corporaIds: this.state.corpora.getSelectedIds(),
231                        },
232                        success: function(searchId, textStatus, jqXHR) {
233                                // console.log("search ["+query+"] ok: ", searchId, jqXHR);
234                                this.setState({searchId : searchId});
235                                this.timeout = 250;
236                                setTimeout(this.refreshSearchResults, this.timeout);
237                        }.bind(this),
238                });
239        },
240
241        refreshSearchResults: function() {
242                if (!this.state.searchId) {
243                        return;
244                }
245                this.props.ajax({
246                        url: 'rest/search/'+this.state.searchId,
247                        success: function(json, textStatus, jqXHR) {
248                                if (json.requests.length > 0) {
249                                        if (this.timeout < 10000) {
250                                                this.timeout = 1.5 * this.timeout;
251                                        }
252                                        setTimeout(this.refreshSearchResults, this.timeout);
253                                        // console.log("new search in: " + this.timeout+ "ms");
254                                } else {
255                                        // console.log("search ended");
256                                }
257                                this.setState({hits:json});
258                                // console.log("hits:", json);
259                        }.bind(this),
260                });
261        },
262
263        setLanguageAndFilter: function(languageObj, languageFilter) {
264                this.state.corpora.setVisibility(this.state.searchLayerId, 
265                        languageFilter === 'byGuess' ? multipleLanguageCode : languageObj[0]);
266                this.setState({language: languageObj, languageFilter: languageFilter});
267                this.state.corpora.update();
268        },
269
270        setLayer: function(layerId) {
271                this.state.corpora.setVisibility(layerId, this.state.language[0]);
272                this.state.corpora.update();
273                this.setState({searchLayerId: layerId});
274        },
275
276        setNumberOfResults: function(e) {
277                var n = e.target.value;
278                if (n < 10) n = 10;
279                if (n > 250) n = 250;
280                this.setState({numberOfResults: n});
281                e.preventDefault();
282                e.stopPropagation();
283        },
284
285        stop: function(e) {
286                e.stopPropagation();
287        },
288
289        filterResults: function() {
290                var langCode = this.state.language[0];
291                return this.state.hits.results.map(function(corpusHit) { 
292                        return {
293                                corpus: corpusHit.corpus,
294                                startRecord: corpusHit.startRecord,
295                                endRecord: corpusHit.endRecord,
296                                exception: corpusHit.exception,
297                                diagnostics: corpusHit.diagnostics,
298                                searchString: corpusHit.searchString,
299                                kwics: corpusHit.kwics.filter(function(kwic){
300                                        return kwic.language === langCode || langCode === multipleLanguageCode || langCode === null; 
301                                }),
302                        };
303                });
304        },
305
306        toggleLanguageSelection: function(e) {
307                $(this.refs.languageModal.getDOMNode()).modal();
308                e.preventDefault();
309                e.stopPropagation();
310        },
311
312        toggleCorpusSelection: function(e) {
313                $(this.refs.corporaModal.getDOMNode()).modal();
314                e.preventDefault();
315                e.stopPropagation();
316        },
317
318        renderAggregator: function() {
319                var layer = layerMap[this.state.searchLayerId];
320                return  (
321                        React.createElement("div", {className: "top-gap"}, 
322                                React.createElement("div", {className: "row"}, 
323                                        React.createElement("div", {className: "aligncenter", style: {marginLeft:16, marginRight:16}}, 
324                                                React.createElement("div", {className: "input-group"}, 
325                                                        React.createElement("span", {className: "input-group-addon", style: {backgroundColor:layer.searchLabelBkColor}}, 
326                                                                layer.searchLabel
327                                                        ), 
328
329                                                        React.createElement(SearchBox, {search: this.search, placeholder: layer.searchPlaceholder}), 
330                                                        React.createElement("div", {className: "input-group-btn"}, 
331                                                                React.createElement("button", {className: "btn btn-default input-lg", type: "button", onClick: this.search}, 
332                                                                        React.createElement("i", {className: "glyphicon glyphicon-search"})
333                                                                )
334                                                        )
335                                                )
336                                        )
337                                ), 
338
339                                React.createElement("div", {className: "wel", style: {marginTop:20}}, 
340                                        React.createElement("div", {className: "aligncenter"}, 
341                                                React.createElement("form", {className: "form-inline", role: "form"}, 
342
343                                                        React.createElement("div", {className: "input-group"}, 
344                                                               
345                                                                React.createElement("span", {className: "input-group-addon nobkg"}, "Search for"), 
346                                                               
347                                                                React.createElement("div", {className: "input-group-btn"}, 
348                                                                        React.createElement("button", {className: "form-control btn btn-default", 
349                                                                                        onClick: this.toggleLanguageSelection}, 
350                                                                                this.state.language[1], " ", React.createElement("span", {className: "caret"})
351                                                                        ), 
352                                                                        React.createElement("span", null)
353                                                                ), 
354
355                                                                React.createElement("div", {className: "input-group-btn"}, 
356                                                                        React.createElement("ul", {ref: "layerDropdownMenu", className: "dropdown-menu"}, 
357                                                                                        layers.map(function(l) { 
358                                                                                                return React.createElement("li", {key: l.id}, " ", React.createElement("a", {tabIndex: "-1", href: "#", 
359                                                                                                        onClick: this.setLayer.bind(this, l.id)}, " ", l.name, " "));
360                                                                                        }.bind(this))
361                                                                               
362                                                                        ),                                                             
363                                                                        React.createElement("button", {className: "form-control btn btn-default", 
364                                                                                        'aria-expanded': "false", 'data-toggle': "dropdown"}, 
365                                                                                layer.name, " ", React.createElement("span", {className: "caret"})
366                                                                        )
367                                                                )
368
369                                                        ), 
370
371                                                        React.createElement("div", {className: "input-group"}, 
372                                                                React.createElement("span", {className: "input-group-addon nobkg"}, "in"), 
373                                                                React.createElement("button", {type: "button", className: "btn btn-default", onClick: this.toggleCorpusSelection}, 
374                                                                        this.state.corpora.getSelectedMessage(), " ", React.createElement("span", {className: "caret"})
375                                                                )
376                                                        ),                                                     
377
378                                                        React.createElement("div", {className: "input-group"}, 
379                                                                React.createElement("span", {className: "input-group-addon nobkg"}, "and show up to"), 
380                                                                React.createElement("div", {className: "input-group-btn"}, 
381                                                                        React.createElement("input", {type: "number", className: "form-control input", min: "10", max: "250", 
382                                                                                style: {width:60}, 
383                                                                                onChange: this.setNumberOfResults, value: this.state.numberOfResults, 
384                                                                                onKeyPress: this.stop})
385                                                                ), 
386                                                                React.createElement("span", {className: "input-group-addon nobkg"}, "hits")
387                                                        )
388                                                )
389                                        )
390                                ), 
391
392                    React.createElement(Modal, {ref: "corporaModal", title: "Collections"}, 
393                                        React.createElement(CorpusView, {corpora: this.state.corpora, languageMap: this.state.languageMap})
394                    ), 
395
396                    React.createElement(Modal, {ref: "languageModal", title: "Select Language"}, 
397                                        React.createElement(LanguageSelector, {anyLanguage: this.anyLanguage, 
398                                                                          languageMap: this.state.languageMap, 
399                                                                          selectedLanguage: this.state.language, 
400                                                                          languageFilter: this.state.languageFilter, 
401                                                                          languageChangeHandler: this.setLanguageAndFilter})
402                    ), 
403
404                                React.createElement("div", {className: "top-gap"}, 
405                                        React.createElement(Results, {requests: this.state.hits.requests, 
406                                                 results: this.filterResults(), 
407                                                 searchedLanguage: this.state.language})
408                                )
409                        )
410                        );
411        },
412        render: function() {
413                return this.renderAggregator();
414        }
415});
416
417
418
419/////////////////////////////////
420
421var LanguageSelector = React.createClass({displayName: 'LanguageSelector',
422        propTypes: {
423                anyLanguage: PT.array.isRequired,
424                languageMap: PT.object.isRequired,
425                selectedLanguage: PT.array.isRequired,
426                languageFilter: PT.string.isRequired,
427                languageChangeHandler: PT.func.isRequired,
428        },
429        mixins: [React.addons.LinkedStateMixin],
430
431        selectLang: function(language) {
432                this.props.languageChangeHandler(language, this.props.languageFilter);
433        },
434
435        setFilter: function(filter) {
436                this.props.languageChangeHandler(this.props.selectedLanguage, filter);
437        },
438
439        renderLanguageObject: function(lang) {
440                var desc = lang[1] + " [" + lang[0] + "]";
441                var style = {
442                        whiteSpace: "nowrap",
443                        fontWeight: lang[0] === this.props.selectedLanguage[0] ? "bold":"normal",
444                };
445                return  React.createElement("div", {key: lang[0]}, 
446                                        React.createElement("a", {tabIndex: "-1", href: "#", style: style, onClick: this.selectLang.bind(this, lang)}, desc)
447                                );
448        },
449
450        renderRadio: function(option) {
451                return  this.props.languageFilter === option ? 
452                                React.createElement("input", {type: "radio", name: "filterOpts", value: option, checked: true, onChange: this.setFilter.bind(this, option)})
453                                : React.createElement("input", {type: "radio", name: "filterOpts", value: option, onChange: this.setFilter.bind(this, option)});
454        },
455
456        render: function() {
457                var languages = _.pairs(this.props.languageMap)
458                                 .sort(function(l1, l2){return l1[1].localeCompare(l2[1]); });
459                languages.unshift(this.props.anyLanguage);
460                languages = languages.map(this.renderLanguageObject);
461                var third = Math.round(languages.length/3);
462                var l1 = languages.slice(0, third);
463                var l2 = languages.slice(third, 2*third);
464                var l3 = languages.slice(2*third, languages.length);
465
466                return  React.createElement("div", null, 
467                                        React.createElement("div", {className: "row"}, 
468                                                React.createElement("div", {className: "col-sm-4"}, l1), 
469                                                React.createElement("div", {className: "col-sm-4"}, l2), 
470                                                React.createElement("div", {className: "col-sm-4"}, l3), 
471                                                React.createElement("div", {className: "col-sm-12", style: {marginTop:10, marginBottom:10, borderBottom:"1px solid #eee"}})
472                                        ), 
473                                        React.createElement("form", {className: "form", role: "form"}, 
474                                                React.createElement("div", {className: "input-group"}, 
475                                                        React.createElement("div", null, 
476                                                        React.createElement("label", {style: {color:'black'}}, 
477                                                                 this.renderRadio('byMeta'), " ", 
478                                                                "Use the collections", "'", " specified language to filter results" 
479                                                        )
480                                                        ), 
481                                                        React.createElement("div", null, 
482                                                        React.createElement("label", {style: {color:'black'}}, 
483                                                                 this.renderRadio('byGuess'), " ", 
484                                                                "Filter results by using a language detector" 
485                                                        )
486                                                        ), 
487                                                        React.createElement("div", null, 
488                                                        React.createElement("label", {style: {color:'black'}}, 
489                                                                 this.renderRadio('byMetaAndGuess'), " ", 
490                                                                "First use the collections", "'", " specified language then also use a language detector"
491                                                        )
492                                                        )
493                                                )
494                                        )
495                                );
496        }
497});
498/////////////////////////////////
499
500var SearchBox = React.createClass({displayName: 'SearchBox',
501        propTypes: {
502                search: PT.func.isRequired,
503                placeholder: PT.string.isRequired,
504        },
505
506        getInitialState: function () {
507                return {
508                        query: "",
509                };
510        },
511
512        handleChange: function(event) {
513        this.setState({query: event.target.value});
514        },
515
516        handleKey: function(event) {
517        if (event.keyCode==13) {
518                this.search();
519        }
520        },
521
522        search: function() {
523                this.props.search(this.state.query);
524        },
525
526        render: function() {
527                return  React.createElement("input", {className: "form-control input-lg search", 
528                                        name: "query", 
529                                        type: "text", 
530                                        value: this.state.query, 
531                                        placeholder: this.props.placeholder, 
532                                        tabIndex: "1", 
533                                        onChange: this.handleChange, 
534                                        onKeyDown: this.handleKey})  ;
535        }
536});
537
538/////////////////////////////////
539
540var Results = React.createClass({displayName: 'Results',
541        propTypes: {
542                requests: PT.array.isRequired,
543                results: PT.array.isRequired,
544                searchedLanguage: PT.array.isRequired,
545        },
546
547        getInitialState: function () {
548                return { 
549                        displayKwic: false,
550                };
551        },
552
553        toggleKwic: function() {
554                this.setState({displayKwic:!this.state.displayKwic});
555        },
556
557        renderRowLanguage: function(hit) {
558                return false; //<span style={{fontFace:"Courier",color:"black"}}>{hit.language} </span> ;
559        },
560
561        renderRowsAsHits: function(hit,i) {
562                function renderTextFragments(tf, idx) {
563                        return React.createElement("span", {key: idx, className: tf.hit?"keyword":""}, tf.text);
564                }
565                return  React.createElement("p", {key: i, className: "hitrow"}, 
566                                        this.renderRowLanguage(hit), 
567                                        hit.fragments.map(renderTextFragments)
568                                );
569        },
570
571        renderRowsAsKwic: function(hit,i) {
572                var sleft={textAlign:"left", verticalAlign:"top", width:"50%"};
573                var scenter={textAlign:"center", verticalAlign:"top", maxWidth:"50%"};
574                var sright={textAlign:"right", verticalAlign:"top", maxWidth:"50%"};
575                return  React.createElement("tr", {key: i, className: "hitrow"}, 
576                                        React.createElement("td", null, this.renderRowLanguage(hit)), 
577                                        React.createElement("td", {style: sright}, hit.left), 
578                                        React.createElement("td", {style: scenter, className: "keyword"}, hit.keyword), 
579                                        React.createElement("td", {style: sleft}, hit.right)
580                                );
581        },
582
583        renderPanelTitle: function(corpus) {
584                var inline = {display:"inline-block"};
585                return  React.createElement("div", {style: inline}, 
586                                        React.createElement("span", {className: "corpusName"}, " ", corpus.title ? corpus.title : corpus.displayName), 
587                                        React.createElement("span", {className: "institutionName"}, " — ", corpus.institution.name)
588                                );
589        },
590
591        renderPanelInfo: function(corpus) {
592                var inline = {display:"inline-block"};
593                return  React.createElement("div", null, 
594                                        React.createElement(InfoPopover, {placement: "left", 
595                                                        title: corpus.title ? corpus.title : corpus.displayName}, 
596                                                React.createElement("dl", {className: "dl-horizontal"}, 
597                                                        React.createElement("dt", null, "Institution"), 
598                                                        React.createElement("dd", null, corpus.institution.name), 
599
600                                                        corpus.description ? React.createElement("dt", null, "Description"):false, 
601                                                        corpus.description ? React.createElement("dd", null, corpus.description): false, 
602
603                                                        corpus.landingPage ? React.createElement("dt", null, "Landing Page") : false, 
604                                                        corpus.landingPage ? 
605                                                                React.createElement("dd", null, React.createElement("a", {href: corpus.landingPage}, corpus.landingPage)):
606                                                                false, 
607
608                                                        React.createElement("dt", null, "Languages"), 
609                                                        React.createElement("dd", null, corpus.languages.join(", "))
610                                                )
611                                        ), 
612                                        " ", 
613                                        React.createElement("div", {style: inline}, 
614                                                React.createElement("button", {className: "btn btn-default btn-xs", onClick: this.zoom}, 
615                                                        React.createElement("span", {className: "glyphicon glyphicon-fullscreen"})
616                                                )
617                                        )
618                                );
619        },
620
621        renderDiagnostics: function(corpusHit) {
622                if (!corpusHit.diagnostics || corpusHit.diagnostics.length === 0) {
623                        return false;
624                }
625
626                return corpusHit.diagnostics.map(function(d) {
627                        return  React.createElement("div", {className: "alert alert-danger", role: "alert"}, 
628                                                d.dgnMessage, ": ", d.dgnDiagnostic
629                                        );
630                });
631        },
632
633        renderPanelBody: function(corpusHit) {
634                var fulllength = {width:"100%"};
635                if (this.state.displayKwic) {
636                        return  React.createElement("div", null, 
637                                                this.renderDiagnostics(corpusHit), 
638                                                React.createElement("table", {className: "table table-condensed table-hover", style: fulllength}, 
639                                                        React.createElement("tbody", null, corpusHit.kwics.map(this.renderRowsAsKwic))
640                                                )
641                                        );
642                } else {
643                        return  React.createElement("div", null, 
644                                                this.renderDiagnostics(corpusHit), 
645                                                corpusHit.kwics.map(this.renderRowsAsHits)
646                                        );
647                }
648        },
649
650        renderResultPanels: function(corpusHit) {
651                if (corpusHit.kwics.length === 0 &&
652                        corpusHit.diagnostics.length === 0) {
653                        return false;
654                }
655                return  React.createElement(Panel, {key: corpusHit.corpus.displayName, 
656                                                title: this.renderPanelTitle(corpusHit.corpus), 
657                                                info: this.renderPanelInfo(corpusHit.corpus)}, 
658                                        this.renderPanelBody(corpusHit)
659                                );
660        },
661
662        renderProgressBar: function() {
663                var percents = 100 * this.props.results.length / (this.props.requests.length + this.props.results.length);
664                var sperc = Math.round(percents);
665                var styleperc = {width: sperc+"%"};
666                return this.props.requests.length > 0 ? 
667                        React.createElement("div", {className: "progress", style: {marginBottom:10}}, 
668                                React.createElement("div", {className: "progress-bar progress-bar-striped active", role: "progressbar", 
669                                        'aria-valuenow': sperc, 'aria-valuemin': "0", 'aria-valuemax': "100", style: styleperc})
670                        ) : 
671                        React.createElement("span", null);
672        },
673
674        renderSearchingMessage: function() {
675                return false;
676                // if (this.props.requests.length === 0)
677                //      return false;
678                // return "Searching in " + this.props.requests.length + " collections...";
679        },
680
681        renderFoundMessage: function(hits) {
682                if (this.props.results.length === 0)
683                        return false;
684                var total = this.props.results.length;
685                return hits + " collections with results found in " + total + " searched collections";
686        },
687
688        renderKwicCheckbox: function() {
689                return  React.createElement("div", {className: "float-right", style: {marginRight:17}}, 
690                                        React.createElement("div", {className: "btn-group", style: {display:"inline-block"}}, 
691                                                React.createElement("label", {forHtml: "inputKwic", className: "btn-default"}, 
692                                                         this.state.displayKwic ? 
693                                                                React.createElement("input", {id: "inputKwic", type: "checkbox", value: "kwic", checked: true, onChange: this.toggleKwic}) :
694                                                                React.createElement("input", {id: "inputKwic", type: "checkbox", value: "kwic", onChange: this.toggleKwic}), 
695                                                       
696                                                        " " + ' ' +
697                                                        "Display as Key Word In Context"
698                                                )
699                                        )
700                                );
701        },
702
703        render: function() {
704                var hits = this.props.results.filter(function(corpusHit) { return corpusHit.kwics.length > 0; }).length;
705                var margintop = {marginTop:"10px"};
706                var margin = {marginTop:"0", padding:"20px"};
707                var inlinew = {display:"inline-block", margin:"0 5px 0 0", width:"240px;"};
708                var right= {float:"right"};
709                return  React.createElement("div", null, 
710                                        React.createElement(ReactCSSTransitionGroup, {transitionName: "fade"}, 
711                                                React.createElement("div", {key: "-searching-message-", style: margintop}, this.renderSearchingMessage(), " "), 
712                                                React.createElement("div", {key: "-found-message-", style: margintop}, this.renderFoundMessage(hits), " "), 
713                                                React.createElement("div", {key: "-progress-", style: margintop}, this.renderProgressBar()), 
714                                                hits > 0 ? 
715                                                        React.createElement("div", {key: "-option-KWIC-", className: "row"}, 
716                                                                this.renderKwicCheckbox()
717                                                        )
718                                                        : false, 
719                                                this.props.results.map(this.renderResultPanels)
720                                        )
721                                );
722        }
723});
724
725var _ = window._ = window._ || {
726        keys: function() {
727                var ret = [];
728                for (var x in o) {
729                        if (o.hasOwnProperty(x)) {
730                                ret.push(x);
731                        }
732                }
733                return ret;
734        },
735
736        pairs: function(o){
737                var ret = [];
738                for (var x in o) {
739                        if (o.hasOwnProperty(x)) {
740                                ret.push([x, o[x]]);
741                        }
742                }
743                return ret;
744        },
745};
746
747})();
Note: See TracBrowser for help on using the repository browser.