all files / component/templates/ bold-query.component.ts

98.65% Statements 73/74
93.55% Branches 29/31
100% Functions 13/13
98.59% Lines 70/71
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145                                          23×                                                                                     23× 23× 15× 15× 15× 15× 15× 15× 15× 15× 15× 15× 15× 42× 28× 28×   42× 27× 27× 27×     27× 25×   27× 27× 25×   27×   42×   15×          
/*
 *  @license
 *  Copyright Hôpitaux Universitaires de Genève. All Rights Reserved.
 *
 *  Use of this source code is governed by an Apache-2.0 license that can be
 *  found in the LICENSE file at https://github.com/DSI-HUG/dejajs-components/blob/master/LICENSE
 */
 
import { Component, Input, ViewEncapsulation } from '@angular/core';
import { Diacritics } from '../../common/core/diacritics/diacritics';
import { RegExpUtils } from '../../common/util';
 
@Component({
    encapsulation: ViewEncapsulation.None,
    selector: 'deja-bold-query',
    styles: [
        require('./bold-query.component.scss'),
    ],
    template: `<div [innerHTML]="content"></div>`,
})
export class DejaBoldQueryComponent {
    private _query: string;
    private _value: any;
    private _content: string;
    private _regexpOptions = 'i';
    private _firstOccurenceOnly = false;
    private _firstOccurencePerWordOnly = false;
    private _atTheBeginningOfWordOnly = false;
    private _highlightClassName = 'highlight | yellowBackgroundColorHighlight';
 
    public get content() {
        return this._content;
    }
 
    @Input()
    /*
     * The search term query.
     *
     */
    public set query(value: string) {
        value = Diacritics.remove(value);
        Eif (this._query !== value) {
            this._query = value;
            this.refresh();
        }
    }
 
    @Input()
    /*
     * The model value. Usually the model display label.
     */
    public set value(value: any) {
        this._value = value;
        this.refresh();
    }
 
    @Input()
    /*
     * The RegExp optional Flags. Optional. Default value is 'i' (case insensitive).
     *
     */
    public set regexpOption(value: string) {
        this._regexpOptions = value;
        this.refresh();
    }
 
    @Input()
    /*
     * If true, highlight only the first occurence. False by default.
     */
    public set firstOccurenceOnly(value: boolean) {
        this._firstOccurenceOnly = value;
        this.refresh();
    }
 
    @Input()
    public set firstOccurencePerWordOnly(value: boolean) {
        this._firstOccurencePerWordOnly = value;
        this.refresh();
    }
 
    @Input()
    public set atTheBeginningOfWordOnly(value: boolean) {
        this._atTheBeginningOfWordOnly = value;
        this.refresh();
    }
 
    public get highlightClassName() {
        return this._highlightClassName;
    }
 
    @Input()
    public set highlightClassName(value: string) {
        this._highlightClassName = value;
        Iif (!this._highlightClassName) {
            this._highlightClassName = 'highlight';
        }
        this.refresh();
    }
 
    private refresh() {
        if (this._value && this._query && this._query.length > 0) {
            const regexpPattern = this._atTheBeginningOfWordOnly ? (`\\b${RegExpUtils.escapeRegExp(this._query)}`) : RegExpUtils.escapeRegExp(this._query);
            const sc = new RegExp(regexpPattern, this._regexpOptions);
            const value = this._value.toString() as string;
            const search = Diacritics.remove(value);
            const splitted = search.split(sc);
            let position = 0;
            const queryLength = this._query.length;
            const contents = [] as string[];
            let firstOccurence = true;
            let nbOccurence = 0;
            splitted.forEach((text) => {
                if (text) {
                    contents.push(value.slice(position, position + text.length));
                    position += text.length;
                }
                if (position + queryLength <= value.length) {
                    nbOccurence += 1;
                    let skipHighlight = false;
                    if (this._firstOccurencePerWordOnly && nbOccurence > 1) {
                        const words = text.split(/[^a-zA-Z\d]/g);
                        if (words.length === 1) {
                            skipHighlight = true;
                        }
                    }
                    if (!skipHighlight && (!this._firstOccurenceOnly || firstOccurence)) {
                        contents.push(`<span class="${this._highlightClassName}">`);
                    }
                    contents.push(value.slice(position, position + queryLength));
                    if (!skipHighlight && (!this._firstOccurenceOnly || firstOccurence)) {
                        contents.push('</span>');
                    }
                    position += queryLength;
                }
                firstOccurence = false;
            });
            this._content = contents.join('');
        } else {
            this._content = this._value;
        }
    }
}