0

I have the following code and I want to truncate the text in some elements with ellipsis

'use strict';

angular.module('some-module')
    .component('chipInput', {
        templateUrl: 'modules/some-module/views/chip-input.html',
        bindings: {
            initialValue: '<?',
            options: '<?',
            forceOptions: '<?',
            debounce: '<?',
            readTransformer: '&',
            writeTransformer: '&',
            onChange: '&',
            onSearch: '&',
            placeholder: '@'
        },
        controller: function ($attrs, $element, KEY_CODES) {
            let self = this;

            self.showOption = showOption;
            self.onOptionSelect = onOptionSelect;
            self.removeChip = removeChip;
            self.availableOptions = availableOptions;
            self.onFocus = onFocus;
            self.onBlur = onBlur;
            self.showOptionsDropdown = showOptionsDropdown;
            self.showNewChipInput = showNewChipInput;
            self.onInputChange = onInputChange;

            self.$onInit = onInit;

            function onInit() {
                self.newChip = "";
                self.showOptions = false;
                self.input = $element[0].querySelector(".chip-input-text");
                self.optionIndex = -1;
                self.initialValue = self.initialValue || [];

                self.keys = [
                    {
                        combination: [KEY_CODES.ARROW_UP],
                        action: () => {
                            if (self.optionIndex === -1) {
                                return;
                            }

                            self.optionIndex--;
                        }
                    },
                    {
                        combination: [KEY_CODES.ARROW_DOWN],
                        action: () => {
                            if (_.isEmpty(availableOptions(self.newChip)) || self.optionIndex >= availableOptions(self.newChip).length - 1) {
                                return;
                            }

                            self.optionIndex++;
                        }
                    },
                    {
                        combination: [KEY_CODES.TAB],
                        action: onSubmit
                    },
                    {
                        combination: [KEY_CODES.ENTER],
                        action: onSubmit
                    }
                ];

                if (!$attrs.$attr.readTransformer) {
                    self.readTransformer = value => value.option;
                }

                if (!$attrs.$attr.writeTransformer) {
                    self.writeTransformer = value => value.value;
                }

                if (!self.debounce) {
                    self.debounce = 0;
                }
            }


            function onInputChange () {
                self.optionIndex = -1;
                self.onSearch({test: self.newChip});
            }

            function onSubmit() {
                let valid = true;

                if (self.optionIndex === -1) {
                    valid = addChip(self.writeTransformer({value: self.newChip}));
                }
                else {
                    valid = addChip(self.availableOptions(self.newChip)[self.optionIndex]);
                }

                if (!valid) {
                    return;
                }

                self.newChip = "";
                self.optionIndex = -1;
            }

            function onBlur() {
                self.optionIndex = -1;
                self.showOptions = false;
            }

            function onFocus() {
                self.showOptions = true;
            }

            function availableOptions(search) {
                return _.filter(self.options, option => showOption(option, search));
            }

            function removeChip(chip) {
                _.remove(self.initialValue, val => val === chip);
                self.onChange({value: self.initialValue});
            }

            function addChip(option) {
                if (!option || (self.forceOptions && !searchInOptions(option)) || isOptionAlreadyExists(option)) {
                    return false;
                }

                self.initialValue.push(option);
                self.onChange({value: self.initialValue});

                return true;
            }

            function searchInOptions(optionToSearch) {
                return _.find(self.options, option => self.readTransformer({option}) === self.readTransformer({option: optionToSearch}));
            }

            function onOptionSelect(option) {
                addChip(option);
                self.input.focus();
            }

            function isOptionAlreadyExists(option) {
                return !!_.find(self.initialValue, chip => self.readTransformer({option: chip}) === (self.readTransformer({option: option})));
            }

            function showOption(option, search) {
                return !isOptionAlreadyExists(option) && (!search || (option && self.readTransformer({option}).toLowerCase().indexOf(search.toLowerCase()) !== -1));
            }

            function showOptionsDropdown() {
                return self.showOptions && self.availableOptions(self.newChip).length > 0;
            }

            function showNewChipInput() {
                return !self.forceOptions || !_.isEmpty(availableOptions(""));
            }
        }
    });
chip-input {
  position: relative;
  display: flex;
  cursor: pointer;
  align-content: center;
  text-decoration: none;
  color: #afafaf;
  flex-wrap: wrap;
  padding-right: 10px;
  border-bottom: 1px solid #dbdbdb;

  .chip-input-chips {
    display: flex;
    max-width: 100%;
    flex-wrap: wrap;

    .chip-input-chip {
      border-radius: 50px;
      padding: 3px 25px 3px 10px;
      position: relative;
      max-width: 100%;
      display: inline-block;
      align-items: center;
      margin: 3px 3px 3px 0;
      color: #666;
      background: #e0e7ea;
      font-size: 11px;

      .chip-input-remove-chip {
        font-size: 15px;
        color: gray;
        position: absolute;
        right: 7px;
        align-self: center;
      }
    }
  }

  .chip-input-text {
    border: none;
    outline: none;
    font-size: 12px;
    margin: 6px 0;
    color: rgba(0, 0, 0, .87);
    padding: 0 7px;

    &::placeholder { /* Chrome, Firefox, Opera, Safari 10.1+ */
      color: #afafaf;
      opacity: 1; /* Firefox */
    }

    &:-ms-input-placeholder { /* Internet Explorer 10-11 */
      color: #afafaf;

    }
    &::-ms-input-placeholder { /* Microsoft Edge */
      color: #afafaf;
    }
  }

  .chip-input-autocomplete {
    top: 100%;
    position: absolute;
    background: white;
    border: 1px #ebebeb solid;
    width: 100%;
    left: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    max-height: 300px;
    overflow-y: auto;
    box-shadow: 1px 1px 2px 0 #999999;
    z-index: 1;
    margin-top: 2px;
    margin-bottom: 4px;

    .chip-input-autocomplete-option {
      display: flex;
      height: 35px;
      align-items: center;
      flex: 1;
      flex-shrink: 0;
      padding: 0 10px 0;
      color: rgba(0, 0, 0, .87);

      &:hover, &.current-option {
        background: #ebebeb;
      }

      &:last-child {
        border-bottom: none;
      }
    }
  }
}

.ellipsis {
    white-space: nowrap;
    /* text-align: start; */
    text-overflow: ellipsis;
    overflow: hidden;
}
<div class="chip-input-chips ellipsis" ng-if="$ctrl.initialValue && $ctrl.initialValue.length !== 0">
    <div class="chip-input-chip ellipsis"
         ng-repeat="chip in $ctrl.initialValue">
        {{$ctrl.readTransformer({option: chip})}}
        <i class="mdi mdi-close-circle chip-input-remove-chip" ng-click="$ctrl.removeChip(chip)"></i>
    </div>
</div>
<input type="text"
       shortcut="$ctrl.keys"
       prevent-default-on="[9, 13]"
       placeholder="{{$ctrl.placeholder}}"
       ng-model="$ctrl.newChip"
       ng-focus="$ctrl.onFocus()"
       ng-change="$ctrl.onInputChange()"
       click-outside="$ctrl.onBlur()"
       whitelist="['.chip-input-autocomplete']"
       class="chip-input-text"
       ng-show="$ctrl.showNewChipInput()"
       ng-model-options="{debounce: $ctrl.debounce}"/>
<div class="chip-input-autocomplete" ng-if="$ctrl.showOptionsDropdown()">
    <div class="chip-input-autocomplete-option ellipsis"
         ng-repeat="(key, option) in $ctrl.availableOptions($ctrl.newChip)"
         ng-click="$ctrl.onOptionSelect(option)"
         ng-class="{'current-option': $ctrl.optionIndex === key}"
         title="{{$ctrl.readTransformer({option: option})}}">
        {{$ctrl.readTransformer({option: option})}}
    </div>
</div>

I want to truncate .chip-input-chip and .chip-input-autocomplete-option, but instead of truncating it's overflowing..

If I write overflow-x: hidden on chip-input it's creating vertical scroll..

how can I prevent the overflow and truncate the text?

Update: Image with overflow-x: hidden on the container (chip-input), as you can see, the text is truncated with ellipsis, but the overflow-x: hidden also added vertical scrollbar...

enter image description here

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
Nadav Shabtai
  • 687
  • 1
  • 7
  • 16
  • please edit with work code – לבני מלכה May 15 '18 at 11:37
  • Hi, I cant make this code work because it has missing dependencies that I cant post because it's confidential... – Nadav Shabtai May 15 '18 at 11:38
  • @NadavShabtai Could you not create a stripped down version which contains final compiled HTML and CSS in the smallest possible quantities required to reproduce the problem? – Scoots May 15 '18 at 11:53
  • What do you mean? remove the snippet and post it as regular code? – Nadav Shabtai May 15 '18 at 11:54
  • @NadavShabtai You've posted LESS in the CSS box - StackSnippets don't compile LESS, so most (maybe all?) of that is being lost. You've supplied HTML with pre-compiled variables so when we click run we just see something useless to us, and you've supplied JavaScript which just errors out. We want to help you but you've not made it easy for us to even try. Consider the advice in this help centre article: https://stackoverflow.com/help/mcve – Scoots May 15 '18 at 12:08
  • @NadavShabtai I will add that the act of creating a "MCVE" has on more than one occasion allowed me to answer my own question before I post it to the site. – Scoots May 15 '18 at 12:10
  • please add a working snippet that shows your issue. you may use lorem ipsum text & image to keep this confidential. Else, overflow here should be set on the parent , looks a lot like a typical issue and duplicate – G-Cyrillus May 15 '18 at 12:15
  • I'll upload images instead of the code... – Nadav Shabtai May 15 '18 at 12:31
  • To have your text truncate with an ellipsis, you need a set `width` or `max-width`, combined with `white-space: nowrap; overflow: hidden; text-overflow: ellipsis`. Please inspect your elements and see if all four of these are present. (see [this example](https://jsfiddle.net/nk49kt4c/) ) – Jesse May 15 '18 at 13:42
  • I have all of them and it's still not working... I'm Updating the question with one more image – Nadav Shabtai May 15 '18 at 13:47
  • see my [answer here](https://stackoverflow.com/a/50517037/2353523) for a way to do it for columns. The question in that link has another link to a codepen snippet showing how to do it as a row direction @NadavShabtai – soulshined May 26 '18 at 01:29

2 Answers2

0

try this.

.chip-input-chip, .chip-input-autocomplete-option{
    width:100%;
    overflow: hidden;
    white-space: nowrap;
}
Habeeb
  • 322
  • 1
  • 8
0

I believe you will need to give your text box a set height. Give this a shot. Same HTML and text just different style.

.truncate {
  display: flex;
  width: 200px;
  height: 40px;
  border: 1px solid red;
  overflow: hidden;
}

.no-truncate {
  display: flex;
  width: 200px;
  height: 40px;
  border: 1px solid red;
}
<div class="truncate">
    aasdf;lkajsdf alskdjf a;slkdjf ;laksjdf; lkajsdf; lkajs;dlfk ja;sldkfj as;ldkjf ;alskdjf ;laksjdf ;lkajsdf
</div>

<br/><br/>

<div class="no-truncate">
    aasdf;lkajsdf alskdjf a;slkdjf ;laksjdf; lkajsdf; lkajs;dlfk ja;sldkfj as;ldkjf ;alskdjf ;laksjdf ;lkajsdf
</div>
bnjmn.myers
  • 409
  • 2
  • 6
  • 15
  • It's not truncating, and I cant use overflow: hidden because I have absolute div that overflows the container (I can use overflow-x: hidden, but as I wrote, it's creating a vertical scroll).. Truncate I mean with ellipsis – Nadav Shabtai May 15 '18 at 11:57