Skip to content

Commit

Permalink
feature(options): add textOverflow option
Browse files Browse the repository at this point in the history
  • Loading branch information
Frondor committed Nov 1, 2018
1 parent 78271d3 commit 3fb5a75
Show file tree
Hide file tree
Showing 7 changed files with 177 additions and 169 deletions.
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,19 @@ In some upcoming version it may be able to detect this value automatically.
| property | type | default | description |
| --- | --- | --- | --- |
| importCss | Boolean | false | Set to `true` in order to import styles into `<head>` automatically, element.style is used by default
| textOverflow | String | `ellipsis` | Set the value for [`text-overflow`](https://developer.mozilla.org/en-US/docs/Web/CSS/text-overflow) property in modern browsers
| fallbackFunc | Function | defaultFallbackFunc | Provide your own default method to handle the truncation strategy on unsupported browsers. Accepts all directive params: `element (Node)`, `bindings (Object)`, `lines (Number)`


### Caveats

Probably there may be problems when loading custom fonts. I've done some tests and couldn't detect any inconsistence so far, so feel free to open an issue and provide code to reproduce any bug or glitch you find.
1. Probably there may be problems when loading custom fonts. I've done some tests and couldn't detect any inconsistence so far, so feel free to open an issue and provide code to reproduce any bug or glitch you find.
2. The fallback method for older browsers won't show up the ellipsis (`...`) since we can't control the part of the text node that may get "clamped".

### Changelog

**v1.2.4** - Implemented `textOverflow` option.

**v1.2.1** - Implemented `fallbackFunc` options, fixed multiple elements clamping on same page.

**v1.2** - Lines parameter passed to `v-line-clamp` is now reactive.
82 changes: 41 additions & 41 deletions dev/index.html
Original file line number Diff line number Diff line change
@@ -1,41 +1,41 @@
<!DOCTYPE html>
<html>
<head>
<!-- THIS FILE IS USED FOR DEVELOPMENT -->
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<title>Vue Line Clamp - A multi-line ellipsis for Vue</title>
</head>
<body>
<div id="app">
<label for="range">Number of lines: {{ lines }} </label> <br>
<input type="range" v-model="lines" min="0" max="5" id="range">

<p v-line-clamp:26="lines" style="width: 200px">
Truncate my lorem ipsum dolor, sit amet consectetur adipisicing elit. Dolore, neque minima libero voluptatibus voluptate enim earum qui tempora sed sequi fugiat aut commodi laboriosam iste cupiditate quo veritatis quam obcaecati.
</p>

<p v-line-clamp:26="1" style="width: 200px">
Truncate my lorem ipsum dolor, sit amet consectetur adipisicing elit. Dolore, neque minima libero voluptatibus voluptate enim earum qui tempora sed sequi fugiat aut commodi laboriosam iste cupiditate quo veritatis quam obcaecati.
</p>

<p v-line-clamp:26="lines" style="width: 200px">
Truncate my lorem ipsum dolor, sit amet consectetur adipisicing elit. Dolore, neque minima libero voluptatibus voluptate enim earum qui tempora sed sequi fugiat aut commodi laboriosam iste cupiditate quo veritatis quam obcaecati.
</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<script src="dist/vue-line-clamp.umd.js"></script>
<script>
Vue.use(VueLineClamp, {
importCss: false
})

new Vue({
el: '#app',
data: {
lines: 2
}
})
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<!-- THIS FILE IS USED FOR DEVELOPMENT -->
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<title>Vue Line Clamp - A multi-line ellipsis for Vue</title>
</head>
<body>
<div id="app">
<label for="range">Number of lines: {{ lines }} </label> <br>
<input type="range" v-model="lines" min="0" max="5" id="range">

<p v-line-clamp:26="lines" style="width: 200px">
Truncate my lorem ipsum dolor, sit amet consectetur adipisicing elit. Dolore, neque minima libero voluptatibus voluptate enim earum qui tempora sed sequi fugiat aut commodi laboriosam iste cupiditate quo veritatis quam obcaecati.
</p>

<p v-line-clamp:26="1" style="width: 200px">
Truncate my lorem ipsum dolor, sit amet consectetur adipisicing elit. Dolore, neque minima libero voluptatibus voluptate enim earum qui tempora sed sequi fugiat aut commodi laboriosam iste cupiditate quo veritatis quam obcaecati.
</p>

<p v-line-clamp:26="lines" style="width: 200px">
Truncate my lorem ipsum dolor, sit amet consectetur adipisicing elit. Dolore, neque minima libero voluptatibus voluptate enim earum qui tempora sed sequi fugiat aut commodi laboriosam iste cupiditate quo veritatis quam obcaecati.
</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<script src="dist/vue-line-clamp.umd.js"></script>
<script>
Vue.use(VueLineClamp, {
importCss: false
})

new Vue({
el: '#app',
data: {
lines: 2
}
})
</script>
</body>
</html>
64 changes: 33 additions & 31 deletions dist/vue-line-clamp.cjs.js
Original file line number Diff line number Diff line change
@@ -1,82 +1,84 @@
'use strict';

const css = 'display:block;display:-webkit-box;-webkit-box-orient:vertical;overflow:hidden;text-overflow:ellipsis';
const currentValueProp = "vLineClampValue";

function defaultFallbackFunc(el, bindings, lines) {
if(lines){
if (lines) {
let lineHeight = parseInt(bindings.arg);
if (isNaN(lineHeight)) {
console.warn('line-height argument for vue-line-clamp must be a number (of pixels), falling back to 16px');
console.warn(
"line-height argument for vue-line-clamp must be a number (of pixels), falling back to 16px"
);
lineHeight = 16;
}

let maxHeight = lineHeight * lines;

el.style.maxHeight = maxHeight ? maxHeight+'px' : '';
el.style.overflowX = 'hidden';
el.style.lineHeight = lineHeight+'px'; // to ensure consistency
el.style.maxHeight = maxHeight ? maxHeight + "px" : "";
el.style.overflowX = "hidden";
el.style.lineHeight = lineHeight + "px"; // to ensure consistency
} else {
el.style.maxHeight = el.style.overflowX = '';
el.style.maxHeight = el.style.overflowX = "";
}
}

const truncateText = function (el, bindings, useFallbackFunc) {
const truncateText = function(el, bindings, useFallbackFunc) {
let lines = parseInt(bindings.value);
if (isNaN(lines)) {
console.error('Parameter for vue-line-clamp must be a number');
return
}
else if (lines !== el[currentValueProp]) {
console.error("Parameter for vue-line-clamp must be a number");
return;
} else if (lines !== el[currentValueProp]) {
el[currentValueProp] = lines;

if (useFallbackFunc) {
useFallbackFunc(el, bindings, lines);
}
else {
el.style.webkitLineClamp = lines ? lines : '';
} else {
el.style.webkitLineClamp = lines ? lines : "";
}
}
};

const VueLineClamp = {
install (Vue, options) {
options = Object.assign({
importCss: false
}, options);
install(Vue, options) {
options = Object.assign(
{ importCss: false, textOverflow: "ellipsis" },
options
);
const styles =
"display:block;display:-webkit-box;-webkit-box-orient:vertical;overflow:hidden;text-overflow:" +
options.textOverflow;

if (options.importCss) {
const stylesheets = window.document.styleSheets,
rule = `.vue-line-clamp{${css}}`;
rule = `.vue-line-clamp{${styles}}`;
if (stylesheets && stylesheets[0] && stylesheets.insertRule) {
stylesheets.insertRule(rule);
} else {
let link = window.document.createElement('style');
link.id = 'vue-line-clamp';
let link = window.document.createElement("style");
link.id = "vue-line-clamp";
link.appendChild(window.document.createTextNode(rule));
window.document.head.appendChild(link);
}
}

const useFallbackFunc =
"webkitLineClamp" in document.body.style
"webkitLineClamp" in document.body.style
? undefined
: options.fallbackFunc || defaultFallbackFunc;

Vue.directive('line-clamp', {
Vue.directive("line-clamp", {
currentValue: 0,
bind (el) {
bind(el) {
if (!options.importCss) {
el.style.cssText += css;
el.style.cssText += styles;
} else {
el.classList.add("vue-line-clamp");
}
else {
el.classList.add('vue-line-clamp');
}

},
inserted: (el, bindings) => truncateText(el, bindings, useFallbackFunc),
updated: (el, bindings) => truncateText(el, bindings, useFallbackFunc),
componentUpdated: (el, bindings) => truncateText(el, bindings, useFallbackFunc)
componentUpdated: (el, bindings) =>
truncateText(el, bindings, useFallbackFunc)
});
}
};
Expand Down
64 changes: 33 additions & 31 deletions dist/vue-line-clamp.esm.js
Original file line number Diff line number Diff line change
@@ -1,80 +1,82 @@
const css = 'display:block;display:-webkit-box;-webkit-box-orient:vertical;overflow:hidden;text-overflow:ellipsis';
const currentValueProp = "vLineClampValue";

function defaultFallbackFunc(el, bindings, lines) {
if(lines){
if (lines) {
let lineHeight = parseInt(bindings.arg);
if (isNaN(lineHeight)) {
console.warn('line-height argument for vue-line-clamp must be a number (of pixels), falling back to 16px');
console.warn(
"line-height argument for vue-line-clamp must be a number (of pixels), falling back to 16px"
);
lineHeight = 16;
}

let maxHeight = lineHeight * lines;

el.style.maxHeight = maxHeight ? maxHeight+'px' : '';
el.style.overflowX = 'hidden';
el.style.lineHeight = lineHeight+'px'; // to ensure consistency
el.style.maxHeight = maxHeight ? maxHeight + "px" : "";
el.style.overflowX = "hidden";
el.style.lineHeight = lineHeight + "px"; // to ensure consistency
} else {
el.style.maxHeight = el.style.overflowX = '';
el.style.maxHeight = el.style.overflowX = "";
}
}

const truncateText = function (el, bindings, useFallbackFunc) {
const truncateText = function(el, bindings, useFallbackFunc) {
let lines = parseInt(bindings.value);
if (isNaN(lines)) {
console.error('Parameter for vue-line-clamp must be a number');
return
}
else if (lines !== el[currentValueProp]) {
console.error("Parameter for vue-line-clamp must be a number");
return;
} else if (lines !== el[currentValueProp]) {
el[currentValueProp] = lines;

if (useFallbackFunc) {
useFallbackFunc(el, bindings, lines);
}
else {
el.style.webkitLineClamp = lines ? lines : '';
} else {
el.style.webkitLineClamp = lines ? lines : "";
}
}
};

const VueLineClamp = {
install (Vue, options) {
options = Object.assign({
importCss: false
}, options);
install(Vue, options) {
options = Object.assign(
{ importCss: false, textOverflow: "ellipsis" },
options
);
const styles =
"display:block;display:-webkit-box;-webkit-box-orient:vertical;overflow:hidden;text-overflow:" +
options.textOverflow;

if (options.importCss) {
const stylesheets = window.document.styleSheets,
rule = `.vue-line-clamp{${css}}`;
rule = `.vue-line-clamp{${styles}}`;
if (stylesheets && stylesheets[0] && stylesheets.insertRule) {
stylesheets.insertRule(rule);
} else {
let link = window.document.createElement('style');
link.id = 'vue-line-clamp';
let link = window.document.createElement("style");
link.id = "vue-line-clamp";
link.appendChild(window.document.createTextNode(rule));
window.document.head.appendChild(link);
}
}

const useFallbackFunc =
"webkitLineClamp" in document.body.style
"webkitLineClamp" in document.body.style
? undefined
: options.fallbackFunc || defaultFallbackFunc;

Vue.directive('line-clamp', {
Vue.directive("line-clamp", {
currentValue: 0,
bind (el) {
bind(el) {
if (!options.importCss) {
el.style.cssText += css;
el.style.cssText += styles;
} else {
el.classList.add("vue-line-clamp");
}
else {
el.classList.add('vue-line-clamp');
}

},
inserted: (el, bindings) => truncateText(el, bindings, useFallbackFunc),
updated: (el, bindings) => truncateText(el, bindings, useFallbackFunc),
componentUpdated: (el, bindings) => truncateText(el, bindings, useFallbackFunc)
componentUpdated: (el, bindings) =>
truncateText(el, bindings, useFallbackFunc)
});
}
};
Expand Down
Loading

0 comments on commit 3fb5a75

Please sign in to comment.