Skip to content

Commit

Permalink
💪 reactivity and fallback fix
Browse files Browse the repository at this point in the history
  • Loading branch information
Frondor committed Feb 3, 2018
1 parent 7e0622e commit 4dc34e0
Show file tree
Hide file tree
Showing 18 changed files with 715 additions and 89 deletions.
3 changes: 0 additions & 3 deletions .babelrc

This file was deleted.

11 changes: 8 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,22 @@ Vue.use(lineClamp, {
### Usage

```html
<p v-line-clamp="2">Some long text with multiple lines that needs to be truncated to a fixed number, which is 2 in this case.</p>
<p v-line-clamp:20="2">Some long text that needs to be truncated to a fixed number, which is 2 in this case. And if the browser doesn't support `-webkit-line-clamp`, then a line-height of 20px is going to be used in order to truncate this text, thus calculating its max-height.</p>
```
**NOTE:** the argument passed to the directive must be a number, and its used as the `line-height` value for non-webkit browsers, as part of the fallback method.
In some upcoming version it may be able to detect this value automatically.

### Plugin options

| property | type | default | description |
| --- | --- | --- | --- |
| includeCss | Boolean | true | Set to false if you're providing your own style, or just importing it from within your style bundler or pre-processor

| importCss | Boolean | false | Set to `true` in order to import styles into `<head>` automatically, element.style is used by default


### 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.

### Changelog

**v1.2** - Lines parameter passed to `v-line-clamp` is now reactive.
76 changes: 76 additions & 0 deletions demo/dist/vue-line-clamp.cjs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
'use strict';

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

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

if (needsFallback) {
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');
lineHeight = 16;
}

let maxHeight = lineHeight * lines;

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 = '';
}
}
else {
el.style.webkitLineClamp = lines ? lines : '';
}
}
};

const VueLineClamp = {
install (Vue, options) {
options = Object.assign({
importCss: false
}, options);

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

const needsFallback = 'webkitLineClamp' in document.body.style ? false : true;

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

},
inserted: (el, bindings) => truncateText(el, bindings, needsFallback),
updated: (el, bindings) => truncateText(el, bindings, needsFallback),
componentUpdated: (el, bindings) => truncateText(el, bindings, needsFallback)
});
}
};

module.exports = VueLineClamp;
74 changes: 74 additions & 0 deletions demo/dist/vue-line-clamp.esm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
const css = 'display:block;display:-webkit-box;-webkit-box-orient:vertical;overflow:hidden;text-overflow:ellipsis';

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

if (needsFallback) {
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');
lineHeight = 16;
}

let maxHeight = lineHeight * lines;

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 = '';
}
}
else {
el.style.webkitLineClamp = lines ? lines : '';
}
}
};

const VueLineClamp = {
install (Vue, options) {
options = Object.assign({
importCss: false
}, options);

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

const needsFallback = 'webkitLineClamp' in document.body.style ? false : true;

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

},
inserted: (el, bindings) => truncateText(el, bindings, needsFallback),
updated: (el, bindings) => truncateText(el, bindings, needsFallback),
componentUpdated: (el, bindings) => truncateText(el, bindings, needsFallback)
});
}
};

export default VueLineClamp;
82 changes: 82 additions & 0 deletions demo/dist/vue-line-clamp.umd.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global.VueLineClamp = factory());
}(this, (function () { 'use strict';

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

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

if (needsFallback) {
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');
lineHeight = 16;
}

let maxHeight = lineHeight * lines;

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 = '';
}
}
else {
el.style.webkitLineClamp = lines ? lines : '';
}
}
};

const VueLineClamp = {
install (Vue, options) {
options = Object.assign({
importCss: false
}, options);

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

const needsFallback = 'webkitLineClamp' in document.body.style ? false : true;

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

},
inserted: (el, bindings) => truncateText(el, bindings, needsFallback),
updated: (el, bindings) => truncateText(el, bindings, needsFallback),
componentUpdated: (el, bindings) => truncateText(el, bindings, needsFallback)
});
}
};

return VueLineClamp;

})));
32 changes: 32 additions & 0 deletions demo/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<!DOCTYPE html>
<html>
<head>
<!-- THIS FILE IS USED FOR DEVELOPMENT -->
<meta charset="UTF-8">
<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>
</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 // (default) or true to inline css within element's style attr
})

new Vue({
el: '#app',
data: {
lines: 2
}
})
</script>
</body>
</html>
63 changes: 63 additions & 0 deletions demo/vue-line-clamp.umd.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global.VueLineClamp = factory());
}(this, (function () { 'use strict';

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

const truncateText = function (el, lines, needsFallback) {
if (needsFallback) {
let lineHeight = parseFloat(window.getComputedStyle(el).lineHeight),
maxHeight = lineHeight * lines;
el.style.maxHeight = maxHeight ? maxHeight+'px' : '';
el.style.overflowX = 'hidden';
}
else {
el.style.webkitLineClamp = lines;
}
};

const VueLineClamp = {
install (Vue, options) {
options = Object.assign({
importCss: null
}, options);

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

let needsFallback = 'webkitLineClamp' in document.body.style ? false : true;
Vue.directive('line-clamp', {
bind (el) {
if (!options.importCss) {
el.style.cssText += css;
}
else {
el.classList.add('vue-line-clamp');
}

},
inserted (el, bindings) {
truncateText(el, bindings.value, needsFallback);
},
updated (el, bindings) {
truncateText(el, bindings.value, needsFallback);
}
});
}
};

return VueLineClamp;

})));
2 changes: 0 additions & 2 deletions dist/main.min.js

This file was deleted.

Loading

0 comments on commit 4dc34e0

Please sign in to comment.