Replace divgrow with more modern readmore.js
This commit is contained in:
parent
074be42e23
commit
7791d28a5d
171
library/readmore.js/README.md
Normal file
171
library/readmore.js/README.md
Normal file
@ -0,0 +1,171 @@
|
||||
# Readmore.js
|
||||
|
||||
A smooth, responsive jQuery plugin for collapsing and expanding long blocks of text with "Read more" and "Close" links.
|
||||
|
||||
The markup Readmore.js requires is so simple, you can probably use it with your existing HTML—there's no need for complicated sets of `div`'s or hardcoded classes, just call `.readmore()` on the element containing your block of text and Readmore.js takes care of the rest. Readmore.js plays well in a responsive environment, too.
|
||||
|
||||
Readmore.js is tested with—and supported on—all versions of jQuery greater than 1.9.1. All the "good" browsers are supported, as well as IE10+; IE8 & 9 _should_ work, but are not supported and the experience will not be ideal.
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
Install Readmore.js with Bower:
|
||||
|
||||
```
|
||||
$ bower install readmore
|
||||
```
|
||||
|
||||
Then include it in your HTML:
|
||||
|
||||
```html
|
||||
<script src="/bower_components/readmore/readmore.min.js"></script>
|
||||
```
|
||||
|
||||
|
||||
## Use
|
||||
|
||||
```javascript
|
||||
$('article').readmore();
|
||||
```
|
||||
|
||||
It's that simple. You can change the speed of the animation, the height of the collapsed block, and the open and close elements.
|
||||
|
||||
```javascript
|
||||
$('article').readmore({
|
||||
speed: 75,
|
||||
lessLink: '<a href="#">Read less</a>'
|
||||
});
|
||||
```
|
||||
|
||||
### The options:
|
||||
|
||||
* `speed: 100` in milliseconds
|
||||
* `collapsedHeight: 200` in pixels
|
||||
* `heightMargin: 16` in pixels, avoids collapsing blocks that are only slightly larger than `collapsedHeight`
|
||||
* `moreLink: '<a href="#">Read more</a>'`
|
||||
* `lessLink: '<a href="#">Close</a>'`
|
||||
* `embedCSS: true` insert required CSS dynamically, set this to `false` if you include the necessary CSS in a stylesheet
|
||||
* `blockCSS: 'display: block; width: 100%;'` sets the styling of the blocks, ignored if `embedCSS` is `false`
|
||||
* `startOpen: false` do not immediately truncate, start in the fully opened position
|
||||
* `beforeToggle: function() {}` called after a more or less link is clicked, but *before* the block is collapsed or expanded
|
||||
* `afterToggle: function() {}` called *after* the block is collapsed or expanded
|
||||
|
||||
If the element has a `max-height` CSS property, Readmore.js will use that value rather than the value of the `collapsedHeight` option.
|
||||
|
||||
### The callbacks:
|
||||
|
||||
The callback functions, `beforeToggle` and `afterToggle`, both receive the same arguments: `trigger`, `element`, and `expanded`.
|
||||
|
||||
* `trigger`: the "Read more" or "Close" element that was clicked
|
||||
* `element`: the block that is being collapsed or expanded
|
||||
* `expanded`: Boolean; `true` means the block is expanded
|
||||
|
||||
#### Callback example:
|
||||
|
||||
Here's an example of how you could use the `afterToggle` callback to scroll back to the top of a block when the "Close" link is clicked.
|
||||
|
||||
```javascript
|
||||
$('article').readmore({
|
||||
afterToggle: function(trigger, element, expanded) {
|
||||
if(! expanded) { // The "Close" link was clicked
|
||||
$('html, body').animate( { scrollTop: element.offset().top }, {duration: 100 } );
|
||||
}
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### Removing Readmore:
|
||||
|
||||
You can remove the Readmore.js functionality like so:
|
||||
|
||||
```javascript
|
||||
$('article').readmore('destroy');
|
||||
```
|
||||
|
||||
Or, you can be more surgical by specifying a particular element:
|
||||
|
||||
```javascript
|
||||
$('article:first').readmore('destroy');
|
||||
```
|
||||
|
||||
### Toggling blocks programmatically:
|
||||
|
||||
You can toggle a block from code:
|
||||
|
||||
```javascript
|
||||
$('article:nth-of-type(3)').readmore('toggle');
|
||||
```
|
||||
|
||||
|
||||
## CSS:
|
||||
|
||||
Readmore.js is designed to use CSS for as much functionality as possible: collapsed height can be set in CSS with the `max-height` property; "collapsing" is achieved by setting `overflow: hidden` on the containing block and changing the `height` property; and, finally, the expanding/collapsing animation is done with CSS3 transitions.
|
||||
|
||||
By default, Readmore.js inserts the following CSS, in addition to some transition-related rules:
|
||||
|
||||
```css
|
||||
selector + [data-readmore-toggle], selector[data-readmore] {
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
```
|
||||
|
||||
_`selector` would be the element you invoked `readmore()` on, e.g.: `$('selector').readmore()`_
|
||||
|
||||
You can override the base rules when you set up Readmore.js like so:
|
||||
|
||||
```javascript
|
||||
$('article').readmore({blockCSS: 'display: inline-block; width: 50%;'});
|
||||
```
|
||||
|
||||
If you want to include the necessary styling in your site's stylesheet, you can disable the dynamic embedding by setting `embedCSS` to `false`:
|
||||
|
||||
```javascript
|
||||
$('article').readmore({embedCSS: false});
|
||||
```
|
||||
|
||||
### Media queries and other CSS tricks:
|
||||
|
||||
If you wanted to set a `maxHeight` based on lines, you could do so in CSS with something like:
|
||||
|
||||
```css
|
||||
body {
|
||||
font: 16px/1.5 sans-serif;
|
||||
}
|
||||
|
||||
/* Show only 4 lines in smaller screens */
|
||||
article {
|
||||
max-height: 6em; /* (4 * 1.5 = 6) */
|
||||
}
|
||||
```
|
||||
|
||||
Then, with a media query you could change the number of lines shown, like so:
|
||||
|
||||
```css
|
||||
/* Show 8 lines on larger screens */
|
||||
@media screen and (min-width: 640px) {
|
||||
article {
|
||||
max-height: 12em;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Contributing
|
||||
|
||||
Pull requests are always welcome, but not all suggested features will get merged. Feel free to contact me if you have an idea for a feature.
|
||||
|
||||
Pull requests should include the minified script and this readme and the demo HTML should be updated with descriptions of your new feature.
|
||||
|
||||
You'll need NPM:
|
||||
|
||||
```
|
||||
$ npm install
|
||||
```
|
||||
|
||||
Which will install the necessary development dependencies. Then, to build the minified script:
|
||||
|
||||
```
|
||||
$ gulp compress
|
||||
```
|
||||
|
319
library/readmore.js/readmore.js
Normal file
319
library/readmore.js/readmore.js
Normal file
@ -0,0 +1,319 @@
|
||||
/*!
|
||||
* @preserve
|
||||
*
|
||||
* Readmore.js jQuery plugin
|
||||
* Author: @jed_foster
|
||||
* Project home: http://jedfoster.github.io/Readmore.js
|
||||
* Licensed under the MIT license
|
||||
*
|
||||
* Debounce function from http://davidwalsh.name/javascript-debounce-function
|
||||
*/
|
||||
|
||||
/* global jQuery */
|
||||
|
||||
(function($) {
|
||||
'use strict';
|
||||
|
||||
var readmore = 'readmore',
|
||||
defaults = {
|
||||
speed: 100,
|
||||
collapsedHeight: 200,
|
||||
heightMargin: 16,
|
||||
moreLink: '<a href="#">Read More</a>',
|
||||
lessLink: '<a href="#">Close</a>',
|
||||
embedCSS: true,
|
||||
blockCSS: 'display: block; width: 100%;',
|
||||
startOpen: false,
|
||||
|
||||
// callbacks
|
||||
beforeToggle: function(){},
|
||||
afterToggle: function(){}
|
||||
},
|
||||
cssEmbedded = {},
|
||||
uniqueIdCounter = 0;
|
||||
|
||||
function debounce(func, wait, immediate) {
|
||||
var timeout;
|
||||
|
||||
return function() {
|
||||
var context = this, args = arguments;
|
||||
var later = function() {
|
||||
timeout = null;
|
||||
if (! immediate) {
|
||||
func.apply(context, args);
|
||||
}
|
||||
};
|
||||
var callNow = immediate && !timeout;
|
||||
|
||||
clearTimeout(timeout);
|
||||
timeout = setTimeout(later, wait);
|
||||
|
||||
if (callNow) {
|
||||
func.apply(context, args);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function uniqueId(prefix) {
|
||||
var id = ++uniqueIdCounter;
|
||||
|
||||
return String(prefix == null ? 'rmjs-' : prefix) + id;
|
||||
}
|
||||
|
||||
function setBoxHeights(element) {
|
||||
var el = element.clone().css({
|
||||
height: 'auto',
|
||||
width: element.width(),
|
||||
maxHeight: 'none',
|
||||
overflow: 'hidden'
|
||||
}).insertAfter(element),
|
||||
expandedHeight = el.outerHeight(),
|
||||
cssMaxHeight = parseInt(el.css({maxHeight: ''}).css('max-height').replace(/[^-\d\.]/g, ''), 10),
|
||||
defaultHeight = element.data('defaultHeight');
|
||||
|
||||
el.remove();
|
||||
|
||||
var collapsedHeight = element.data('collapsedHeight') || defaultHeight;
|
||||
|
||||
if (!cssMaxHeight) {
|
||||
collapsedHeight = defaultHeight;
|
||||
}
|
||||
else if (cssMaxHeight > collapsedHeight) {
|
||||
collapsedHeight = cssMaxHeight;
|
||||
}
|
||||
|
||||
// Store our measurements.
|
||||
element.data({
|
||||
expandedHeight: expandedHeight,
|
||||
maxHeight: cssMaxHeight,
|
||||
collapsedHeight: collapsedHeight
|
||||
})
|
||||
// and disable any `max-height` property set in CSS
|
||||
.css({
|
||||
maxHeight: 'none'
|
||||
});
|
||||
}
|
||||
|
||||
var resizeBoxes = debounce(function() {
|
||||
$('[data-readmore]').each(function() {
|
||||
var current = $(this),
|
||||
isExpanded = (current.attr('aria-expanded') === 'true');
|
||||
|
||||
setBoxHeights(current);
|
||||
|
||||
current.css({
|
||||
height: current.data( (isExpanded ? 'expandedHeight' : 'collapsedHeight') )
|
||||
});
|
||||
});
|
||||
}, 100);
|
||||
|
||||
function embedCSS(options) {
|
||||
if (! cssEmbedded[options.selector]) {
|
||||
var styles = ' ';
|
||||
|
||||
if (options.embedCSS && options.blockCSS !== '') {
|
||||
styles += options.selector + ' + [data-readmore-toggle], ' +
|
||||
options.selector + '[data-readmore]{' +
|
||||
options.blockCSS +
|
||||
'}';
|
||||
}
|
||||
|
||||
// Include the transition CSS even if embedCSS is false
|
||||
styles += options.selector + '[data-readmore]{' +
|
||||
'transition: height ' + options.speed + 'ms;' +
|
||||
'overflow: hidden;' +
|
||||
'}';
|
||||
|
||||
(function(d, u) {
|
||||
var css = d.createElement('style');
|
||||
css.type = 'text/css';
|
||||
|
||||
if (css.styleSheet) {
|
||||
css.styleSheet.cssText = u;
|
||||
}
|
||||
else {
|
||||
css.appendChild(d.createTextNode(u));
|
||||
}
|
||||
|
||||
d.getElementsByTagName('head')[0].appendChild(css);
|
||||
}(document, styles));
|
||||
|
||||
cssEmbedded[options.selector] = true;
|
||||
}
|
||||
}
|
||||
|
||||
function Readmore(element, options) {
|
||||
var $this = this;
|
||||
|
||||
this.element = element;
|
||||
|
||||
this.options = $.extend({}, defaults, options);
|
||||
|
||||
$(this.element).data({
|
||||
defaultHeight: this.options.collapsedHeight,
|
||||
heightMargin: this.options.heightMargin
|
||||
});
|
||||
|
||||
embedCSS(this.options);
|
||||
|
||||
this._defaults = defaults;
|
||||
this._name = readmore;
|
||||
|
||||
window.addEventListener('load', function() {
|
||||
$this.init();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Readmore.prototype = {
|
||||
init: function() {
|
||||
var $this = this;
|
||||
|
||||
$(this.element).each(function() {
|
||||
var current = $(this);
|
||||
|
||||
setBoxHeights(current);
|
||||
|
||||
var collapsedHeight = current.data('collapsedHeight'),
|
||||
heightMargin = current.data('heightMargin');
|
||||
|
||||
if (current.outerHeight(true) <= collapsedHeight + heightMargin) {
|
||||
// The block is shorter than the limit, so there's no need to truncate it.
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
var id = current.attr('id') || uniqueId(),
|
||||
useLink = $this.options.startOpen ? $this.options.lessLink : $this.options.moreLink;
|
||||
|
||||
current.attr({
|
||||
'data-readmore': '',
|
||||
'aria-expanded': false,
|
||||
'id': id
|
||||
});
|
||||
|
||||
current.after($(useLink)
|
||||
.on('click', function(event) { $this.toggle(this, current[0], event); })
|
||||
.attr({
|
||||
'data-readmore-toggle': '',
|
||||
'aria-controls': id
|
||||
}));
|
||||
|
||||
if (! $this.options.startOpen) {
|
||||
current.css({
|
||||
height: collapsedHeight
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
window.addEventListener('resize', function() {
|
||||
resizeBoxes();
|
||||
});
|
||||
},
|
||||
|
||||
toggle: function(trigger, element, event) {
|
||||
if (event) {
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
if (! trigger) {
|
||||
trigger = $('[aria-controls="' + this.element.id + '"]')[0];
|
||||
}
|
||||
|
||||
if (! element) {
|
||||
element = this.element;
|
||||
}
|
||||
|
||||
var $this = this,
|
||||
$element = $(element),
|
||||
newHeight = '',
|
||||
newLink = '',
|
||||
expanded = false,
|
||||
collapsedHeight = $element.data('collapsedHeight');
|
||||
|
||||
if ($element.height() <= collapsedHeight) {
|
||||
newHeight = $element.data('expandedHeight') + 'px';
|
||||
newLink = 'lessLink';
|
||||
expanded = true;
|
||||
}
|
||||
else {
|
||||
newHeight = collapsedHeight;
|
||||
newLink = 'moreLink';
|
||||
}
|
||||
|
||||
// Fire beforeToggle callback
|
||||
// Since we determined the new "expanded" state above we're now out of sync
|
||||
// with our true current state, so we need to flip the value of `expanded`
|
||||
$this.options.beforeToggle(trigger, element, ! expanded);
|
||||
|
||||
$element.css({'height': newHeight});
|
||||
|
||||
// Fire afterToggle callback
|
||||
$element.on('transitionend', function() {
|
||||
$this.options.afterToggle(trigger, element, expanded);
|
||||
|
||||
$(this).attr({
|
||||
'aria-expanded': expanded
|
||||
}).off('transitionend');
|
||||
});
|
||||
|
||||
$(trigger).replaceWith($($this.options[newLink])
|
||||
.on('click', function(event) { $this.toggle(this, element, event); })
|
||||
.attr({
|
||||
'data-readmore-toggle': '',
|
||||
'aria-controls': $element.attr('id')
|
||||
}));
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
$(this.element).each(function() {
|
||||
var current = $(this);
|
||||
|
||||
current.attr({
|
||||
'data-readmore': null,
|
||||
'aria-expanded': null
|
||||
})
|
||||
.css({
|
||||
maxHeight: '',
|
||||
height: ''
|
||||
})
|
||||
.next('[data-readmore-toggle]')
|
||||
.remove();
|
||||
|
||||
current.removeData();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
$.fn.readmore = function(options) {
|
||||
var args = arguments,
|
||||
selector = this.selector;
|
||||
|
||||
options = options || {};
|
||||
|
||||
if (typeof options === 'object') {
|
||||
return this.each(function() {
|
||||
if ($.data(this, 'plugin_' + readmore)) {
|
||||
var instance = $.data(this, 'plugin_' + readmore);
|
||||
instance.destroy.apply(instance);
|
||||
}
|
||||
|
||||
options.selector = selector;
|
||||
|
||||
$.data(this, 'plugin_' + readmore, new Readmore(this, options));
|
||||
});
|
||||
}
|
||||
else if (typeof options === 'string' && options[0] !== '_' && options !== 'init') {
|
||||
return this.each(function () {
|
||||
var instance = $.data(this, 'plugin_' + readmore);
|
||||
if (instance instanceof Readmore && typeof instance[options] === 'function') {
|
||||
instance[options].apply(instance, Array.prototype.slice.call(args, 1));
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
})(jQuery);
|
||||
|
||||
|
@ -596,12 +596,10 @@ function updateConvItems(mode,data) {
|
||||
|
||||
function collapseHeight() {
|
||||
$(".wall-item-body, .contact-info").each(function() {
|
||||
if($(this).height() > divmore_height + 10) {
|
||||
if(! $(this).hasClass('divmore')) {
|
||||
$(this).divgrow({ initialHeight: divmore_height, moreText: aStr['divgrowmore'], lessText: aStr['divgrowless'], showBrackets: false });
|
||||
$(this).addClass('divmore');
|
||||
}
|
||||
}
|
||||
if(! $(this).hasClass('divmore')) {
|
||||
$(this).readmore({collapsedHeight: divmore_height, moreLink: '<a href="#">'+aStr['divgrowmore']+'</a>', lessLink: '<a href="#">'+aStr['divgrowless']+'</a>'});
|
||||
$(this).addClass('divmore');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@ head_add_js('autocomplete.js');
|
||||
head_add_js('library/jquery-textcomplete/jquery.textcomplete.js');
|
||||
head_add_js('library/fancybox/jquery.fancybox-1.3.4.js');
|
||||
head_add_js('library/jquery.timeago.js');
|
||||
head_add_js('library/jquery.divgrow/jquery.divgrow-1.3.1.js');
|
||||
head_add_js('library/readmore.js/readmore.js');
|
||||
head_add_js('library/jquery_ac/friendica.complete.js');
|
||||
head_add_js('library/tiptip/jquery.tipTip.minified.js');
|
||||
head_add_js('library/jgrowl/jquery.jgrowl_minimized.js');
|
||||
|
Reference in New Issue
Block a user