├── css └── style.css ├── README.md ├── index.html └── js ├── angular-readmore.js └── app.js /css/style.css: -------------------------------------------------------------------------------- 1 | a.read-more, a.read-less { 2 | cursor: pointer; 3 | color: blue; 4 | } 5 | span.more-text { 6 | display: none; 7 | } 8 | span.more-text.show { 9 | display: inline !important 10 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | angular-readmore 2 | ================ 3 | 4 | Angular Read More Directive 5 | 6 | Simple and easy-to-implement angular read more directive. 7 | 8 | #### Demo 9 | [http://plnkr.co/edit/Tsqkv1nd6CC8e5Kr9pdU?p=preview](http://plnkr.co/edit/Tsqkv1nd6CC8e5Kr9pdU?p=preview) 10 | 11 | #### Requirements 12 | 13 | + Latest jQuery 14 | + AngularJS 1.3+ 15 | 16 | 17 | #### Markup 18 | 19 |

Lorem ipsum dolor sit amet, consectetur adipiscing elit. 20 | Maecenas sit amet ultrices urna. Donec sagittis euismod diam eget luctus. 21 | Aenean imperdiet justo sed dui vehicula porttitor. 22 | Nulla commodo elementum malesuada. 23 | Mauris lacinia pharetra mi, id ornare lacus venenatis non.

24 | 25 | or 26 | 27 | 28 |

29 | 30 | 31 | #### Options 32 | 33 | | Attributes | Default | | 34 | | ------------- |:-------------:| -----:| 35 | | moreText | "Read More..." | (string) | 36 | | lessText | "Less ^" | (string) | 37 | | ellipsis | "" | (string) | 38 | | words | null | null | 39 | | char | null (default active) | null | 40 | | limit | 150 | (int) | 41 | | content | null | {{scope}}, (string) | 42 | 43 | 44 | #### Other Examples 45 | 46 | + (Default) Separated by number of characters 47 | 48 | `

Lorem ipsum dolor sit amet.

` 49 | 50 | + Separated by number of words 51 | 52 | `

` 53 | 54 | 55 | + Change *Read More...* text 56 | 57 | `

` 58 | 59 | 60 | + Change *Less ^* text 61 | 62 | `

` 63 | 64 | 65 | + Change ellipsis 66 | 67 | `

` 68 | 69 | 70 | + Change character/word limit 71 | 72 | `

` 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Angular Read More Directive 7 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec rutrum vehicula tortor, vitae ornare nunc semper eu. Vivamus varius, eros vel tristique accumsan, libero nulla cursus ante, eu eleifend risus orci scelerisque nibh. Curabitur feugiat, augue 18 | ut commodo bibendum, nisi leo porttitor diam, tincidunt auctor tellus ante sit amet nibh. Duis velit libero, aliquam at felis eu, pellentesque mollis mi. Nam a est orci. Ut bibendum sagittis semper. Cras eget arcu non augue mollis aliquam. Ut ut gravida 19 | ligula. Nulla imperdiet lacinia mi, nec fringilla mauris interdum at. Phasellus gravida tempor varius. Cras molestie et nulla eget maximus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris aliquet malesuada feugiat. Curabitur fermentum 20 | bibendum nulla, non dictum ipsum tincidunt non. Quisque convallis pharetra tempor. Donec id pretium leo. Pellentesque luctus massa non elit viverra pellentesque. Cras vitae neque molestie, rhoncus ipsum sit amet, lobortis dui. Fusce in urna sem. Vivamus 21 | vehicula dignissim augue et scelerisque. Etiam quam nisi, molestie ac dolor in, tincidunt tincidunt arcu. Praesent sed justo finibus, fringilla velit quis, porta erat. Donec blandit metus ut arcu iaculis iaculis. Cras nec dolor fringilla justo ullamcorper 22 | auctor. Aliquam eget pretium velit. Morbi urna justo, pulvinar id lobortis in, aliquet placerat orci.

23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /js/angular-readmore.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Joyce Cam on 30/12/2014. 3 | * 4 | * Simple and easy-to-implement angular read more directive. 5 | * 6 | */ 7 | 8 | var readMore = angular.module('readMore', []); 9 | 10 | readMore.directive('readMore', function() { 11 | return { 12 | restrict: 'A', 13 | transclude: true, 14 | replace: true, 15 | template: '

', 16 | scope: { 17 | moreText: '@', 18 | lessText: '@', 19 | words: '@', 20 | ellipsis: '@', 21 | char: '@', 22 | limit: '@', 23 | content: '@' 24 | }, 25 | link: function(scope, elem, attr, ctrl, transclude) { 26 | var moreText = angular.isUndefined(scope.moreText) ? ' Read More...' : ' ' + scope.moreText + '', 27 | lessText = angular.isUndefined(scope.lessText) ? ' Less ^' : ' ' + scope.lessText + '', 28 | ellipsis = angular.isUndefined(scope.ellipsis) ? '' : scope.ellipsis, 29 | limit = angular.isUndefined(scope.limit) ? 150 : scope.limit; 30 | 31 | attr.$observe('content', function(str) { 32 | readmore(str); 33 | }); 34 | 35 | transclude(scope.$parent, function(clone, scope) { 36 | readmore(clone.text().trim()); 37 | }); 38 | 39 | function readmore(text) { 40 | 41 | var text = text, 42 | orig = text, 43 | regex = /\s+/gi, 44 | charCount = text.length, 45 | wordCount = text.trim().replace(regex, ' ').split(' ').length, 46 | countBy = 'char', 47 | count = charCount, 48 | foundWords = [], 49 | markup = text, 50 | more = ''; 51 | 52 | if (!angular.isUndefined(attr.words)) { 53 | countBy = 'words'; 54 | count = wordCount; 55 | } 56 | 57 | if (countBy === 'words') { // Count words 58 | 59 | foundWords = text.split(/\s+/); 60 | 61 | if (foundWords.length > limit) { 62 | text = foundWords.slice(0, limit).join(' ') + ellipsis; 63 | more = foundWords.slice(limit, count).join(' '); 64 | markup = text + moreText + '' + more + lessText + ''; 65 | } 66 | 67 | } else { // Count characters 68 | 69 | if (count > limit) { 70 | text = orig.slice(0, limit) + ellipsis; 71 | more = orig.slice(limit, count); 72 | markup = text + moreText + '' + more + lessText + ''; 73 | } 74 | 75 | } 76 | 77 | elem.append(markup); 78 | elem.find('.read-more').on('click', function() { 79 | $(this).hide(); 80 | elem.find('.more-text').addClass('show').slideDown(); 81 | }); 82 | elem.find('.read-less').on('click', function() { 83 | elem.find('.read-more').show(); 84 | elem.find('.more-text').hide().removeClass('show'); 85 | }); 86 | 87 | } 88 | } 89 | }; 90 | }); 91 | -------------------------------------------------------------------------------- /js/app.js: -------------------------------------------------------------------------------- 1 | var app = angular.module('readMore', []); 2 | 3 | app.controller('MainCtrl', function($scope) { 4 | $scope.desc = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec rutrum vehicula tortor, vitae ornare nunc semper eu. Vivamus varius, eros vel tristique accumsan, libero nulla cursus ante, eu eleifend risus orci scelerisque nibh. Curabitur feugiat, augue ut commodo bibendum, nisi leo porttitor diam, tincidunt auctor tellus ante sit amet nibh. Duis velit libero, aliquam at felis eu, pellentesque mollis mi. Nam a est orci. Ut bibendum sagittis semper. Cras eget arcu non augue mollis aliquam. Ut ut gravida ligula. Nulla imperdiet lacinia mi, nec fringilla mauris interdum at. Phasellus gravida tempor varius. Cras molestie et nulla eget maximus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris aliquet malesuada feugiat. Curabitur fermentum bibendum nulla, non dictum ipsum tincidunt non. Quisque convallis pharetra tempor. Donec id pretium leo. Pellentesque luctus massa non elit viverra pellentesque. Cras vitae neque molestie, rhoncus ipsum sit amet, lobortis dui. Fusce in urna sem. Vivamus vehicula dignissim augue et scelerisque. Etiam quam nisi, molestie ac dolor in, tincidunt tincidunt arcu. Praesent sed justo finibus, fringilla velit quis, porta erat. Donec blandit metus ut arcu iaculis iaculis. Cras nec dolor fringilla justo ullamcorper auctor. Aliquam eget pretium velit. Morbi urna justo, pulvinar id lobortis in, aliquet placerat orci.'; 5 | }); 6 | 7 | 8 | app.directive('readMore', function() { 9 | return { 10 | restrict: 'A', 11 | transclude: true, 12 | replace: true, 13 | template: '

', 14 | scope: { 15 | moreText: '@', 16 | lessText: '@', 17 | words: '@', 18 | ellipsis: '@', 19 | char: '@', 20 | limit: '@', 21 | content: '@' 22 | }, 23 | link: function(scope, elem, attr, ctrl, transclude) { 24 | var moreText = angular.isUndefined(scope.moreText) ? ' Read More...' : ' ' + scope.moreText + '', 25 | lessText = angular.isUndefined(scope.lessText) ? ' Less ^' : ' ' + scope.lessText + '', 26 | ellipsis = angular.isUndefined(scope.ellipsis) ? '' : scope.ellipsis, 27 | limit = angular.isUndefined(scope.limit) ? 150 : scope.limit; 28 | 29 | attr.$observe('content', function(str) { 30 | readmore(str); 31 | }); 32 | 33 | transclude(scope.$parent, function(clone, scope) { 34 | readmore(clone.text().trim()); 35 | }); 36 | 37 | function readmore(text) { 38 | 39 | var text = text, 40 | orig = text, 41 | regex = /\s+/gi, 42 | charCount = text.length, 43 | wordCount = text.trim().replace(regex, ' ').split(' ').length, 44 | countBy = 'char', 45 | count = charCount, 46 | foundWords = [], 47 | markup = text, 48 | more = ''; 49 | 50 | if (!angular.isUndefined(attr.words)) { 51 | countBy = 'words'; 52 | count = wordCount; 53 | } 54 | 55 | if (countBy === 'words') { // Count words 56 | 57 | foundWords = text.split(/\s+/); 58 | 59 | if (foundWords.length > limit) { 60 | text = foundWords.slice(0, limit).join(' ') + ellipsis; 61 | more = foundWords.slice(limit, count).join(' '); 62 | markup = text + moreText + '' + more + lessText + ''; 63 | } 64 | 65 | } else { // Count characters 66 | 67 | if (count > limit) { 68 | text = orig.slice(0, limit) + ellipsis; 69 | more = orig.slice(limit, count); 70 | markup = text + moreText + '' + more + lessText + ''; 71 | } 72 | 73 | } 74 | 75 | elem.append(markup); 76 | elem.find('.read-more').on('click', function() { 77 | $(this).hide(); 78 | elem.find('.more-text').addClass('show').slideDown(); 79 | }); 80 | elem.find('.read-less').on('click', function() { 81 | elem.find('.read-more').show(); 82 | elem.find('.more-text').hide().removeClass('show'); 83 | }); 84 | 85 | } 86 | } 87 | }; 88 | }); 89 | --------------------------------------------------------------------------------