This project has evolved a lot since I started learning Angular. I'm pretty happy with it now, and I'm wondering if there's anything I can improve upon, or have forgotten at this point...
HTML
<h1 data-fittext>FitText</h1>
<h1 data-fittext=".315" data-fittext-min="12" data-fittext-max="50">ng-FitText</h1>
Inclusion & Customization
var myApp = angular.module( 'myApp', [ 'ngFitText' ] );
myApp.config( function( fitTextConfigProvider ) {
fitTextConfigProvider.config = {
debounce: true, //default is false
delay: 1000 //default is 250
};
// OR
fitTextConfigProvider.config.debounce = true;
fitTextConfigProvider.config.delay = 1000;
});
The Module
'use strict';
angular.module( 'ngFitText', [] )
.value( 'config', {
'debounce': false,
'delay': 250
})
.directive( 'fittext', [ 'config', 'fitTextConfig', function( config, fitTextConfig ) {
return {
restrict: 'A',
scope: true,
transclude: true,
replace: true,
template: function( element, attrs ) {
var tag = element[0].nodeName;
return "<"+tag+" data-ng-transclude data-ng-style='{fontSize:fontSize}'></"+tag+">";
},
link: function( scope, element, attrs ) {
angular.extend(config, fitTextConfig.config);
scope.compressor = attrs.fittext || 1;
scope.minFontSize = attrs.fittextMin || Number.NEGATIVE_INFINITY;
scope.maxFontSize = attrs.fittextMax || Number.POSITIVE_INFINITY;
scope.elementWidth = element[0].offsetWidth;
( scope.resizer = function() {
scope.elementWidth = element[0].offsetWidth;
scope.fontSize = Math.max(
Math.min(
scope.elementWidth / ( scope.compressor * 10 ),
parseFloat( scope.maxFontSize )
),
parseFloat( scope.minFontSize )
) + 'px';
if( !scope.$$phase ) scope.$digest();
})();
config.debounce == true
? angular.element( window ).bind( 'resize', debounce( scope.resizer, config.delay ))
: angular.element( window ).bind( 'resize', scope.resizer);
function debounce(a,b,c){var d;return function(){var e=this,f=arguments;clearTimeout(d),d=setTimeout(function(){d=null,c||a.apply(e,f)},b),c&&!d&&a.apply(e,f)}}
}
}
}])
.provider( 'fitTextConfig', function() {
var self = this;
this.config = {};
this.$get = function() {
var extend = {};
extend.config = self.config;
return extend;
};
return this;
});
1 Answer 1
As personal opinion, I wouldn't use
config
as name for.value
, it sounds too generic and can be confused with.config
method of themodule
API.Putting comments like
//default is false
looks confusing - why are these not default? Also it is easy to change the defaults and forget to adjust comments. Uncle Bob recommends to minimize comments and use expressive code with descriptive names instead.function debounce(a,b,c)
is great for minimizers but cryptic for code readersIn my view, using
.provider
is possibly an overkill as there is not much configuration logic here.The last two comments here also apply. Instead the config JSON can be kept inside
.value
and decoupled from the provider.
-
\$\begingroup\$ Thanks for your points. The debounce function is taken from Underscore and stated as such in the module comments. Overkill doesn't concern me, but is there another way to extend configuration? As far as I'm concerned it's not a configurable module if config settings are blown away upon updating the module... \$\endgroup\$Patrick– Patrick2014年04月22日 17:00:30 +00:00Commented Apr 22, 2014 at 17:00
-
\$\begingroup\$ Could you explain how
$$phase
, in this context, is an anti-pattern? It seems pretty legitimate to me as$apply
is already called on load, but is required when the window resizes to apply the updated font size. I've modified the code to remove this anti-pattern, but you essentially end up with something fairly messy in comparison: github.com/patrickmarabeas/ng-FitText.js/blob/master/… I can understand in a lot of cases its usage means you are probably doing something wrong - but it seems like a more succinct readable solution here? \$\endgroup\$Patrick– Patrick2014年04月29日 07:56:30 +00:00Commented Apr 29, 2014 at 7:56 -
\$\begingroup\$ I understand that
$$phase
is Angular's internal method, and as such is not intended for regular use. Please see here for more specific details: stackoverflow.com/questions/22346990/…. \$\endgroup\$Dmitri Zaitsev– Dmitri Zaitsev2014年04月29日 14:04:12 +00:00Commented Apr 29, 2014 at 14:04 -
\$\begingroup\$ Concerning
debounce
, you could take it instead from the non-minimized version with comments, then another reader would better see what it does. \$\endgroup\$Dmitri Zaitsev– Dmitri Zaitsev2014年04月29日 14:06:26 +00:00Commented Apr 29, 2014 at 14:06 -
\$\begingroup\$ See also bennadel.com/blog/… about
$$phase
\$\endgroup\$Dmitri Zaitsev– Dmitri Zaitsev2014年12月29日 08:40:53 +00:00Commented Dec 29, 2014 at 8:40