javascript - creating a "responsive number" directive with angular and bootstrap -


i'm working on directive allow numeric field displayed in friendly way based on amount of space available number if, instance, have field value of 10,000,000,000 show 10b (b billion) if there not enough space full value of 10,000,000,000.

i wanted work bootstrap. best approach think of involved wrapping element in parent element sized bootstrap (and target element react accordingly). able working, imagine there's better approach.

here html example (the directive "responsive-number" attribute):

<div class="container-fluid">     <div class="row">         <div class="col-md-4">some label: </div>         <div class="col-md-8">             <div responsive-number ng-model="somevalue"></div>         </div>     </div> </div> 

the directive, upon initial rendering, sets element's max-width parent node's innerwidth(). limitation here can't have other element contained within parent node figure there must better, perhaps more passive, way approach responding responsive-number element being resized (i'm not sure how while forcing responsive-number element remain within bounds of parent container).

below javascript working me based on above html. detect value large responsive-number container setting text-overflow style such overflow hidden via clipping - parent container comes in need set max-size of element size of parent container:

a jsfiddle example can found here, modified use jquery event sake of convenience (but note aware bad practice): http://jsfiddle.net/f52y5/63/

'use strict';  function myctrl($scope) {     $scope.somevalue = 100000000000000000; }  app.directive('responsivenumber', ['$filter', function ($filter) {     return {         require: 'ngmodel',         restrict: 'a',         scope: true,         link: function (scope, element, attrs, ctrl) {             var scrollwidth = element[0].scrollwidth;             var parentwidth = getparentwidth();             var displayfriendlyvalue = false;              initializeresponsivenumber();             ctrl.$render();              ctrl.$render = function (isresizeevent) {               var temp = shouldrenderfriendlyvalue();                if(isresizeevent){                 // window resized , element formatted                 // if fits, that's wrote..                 if (displayfriendlyvalue == temp) {                     return;                 }               }                displayfriendlyvalue = temp;               var viewvalue = gettransformedviewvalue(ctrl.$modelvalue, displayfriendlyvalue);               ctrl.$viewvalue = viewvalue;               element.html(ctrl.$viewvalue);                // after we've formatted number may not fit anymore               // if shouldrenderfriendlyvalue() returned false               // means unformatted number not overflowing,               // formatted number may overflow               if (!displayfriendlyvalue) {                   // check shouldrenderfriendlyvalue() again                   // because sizing can change after set                    // element.html(ctrl.$viewvalue);                   displayfriendlyvalue = shouldrenderfriendlyvalue();                   if (displayfriendlyvalue) {                     viewvalue = gettransformedviewvalue(ctrl.$modelvalue, displayfriendlyvalue);                     ctrl.$viewvalue = viewvalue;                     element.html(ctrl.$viewvalue);                     return;                   }               }             };              function gettransformedviewvalue(modelvalue, displayfriendlyvalue){               var result;               // add support specifying native filter types                // (currency, instance), not necessary example               if(displayfriendlyvalue){                 result = makefriendlynumber(modelvalue, 'number');               } else {                 result = $filter('number')(modelvalue);               }                return result;             }              function cleannumber(num) {                 return (math.round(num * 10) / 10);             }              function makefriendlynumber(num, filter) {                 var result;                  if (num >= 1000000000) {                     result = $filter(filter)(cleannumber(num / 1000000000)) + 'b';                 } else if (num >= 1000000) {                     result = $filter(filter)(cleannumber(num / 1000000)) + 'm';                 } else if (num >= 1000) {                     result = $filter(filter)(cleannumber(num / 1000)) + 'k';                 } else {                     result = $filter(filter)(num);                 }                  return result.tostring().replace(/(\.[\d]*)/, '');             }              function initializeresponsivenumber() {                 element[0].style['overflow'] = 'hidden';                 element[0].style['-moz-text-overflow'] = 'clip';                 element[0].style['text-overflow'] = 'clip';                  updateelementsize(parentwidth);                  var debouncedresizeevent = $scope.$on('debouncedresize', function (event) {                     scope.$apply(function () {                          var newparentwidth = getparentwidth();                         if (newparentwidth == parentwidth) { return; }                          parentwidth = newparentwidth;                         updateelementsize(parentwidth);                         ctrl.$render(true);                     });                 });                  $scope.$on('$destroy', debouncedresizeevent()};             }              function getparentwidth() {                 var innerwidth = angular.element(element[0].parentnode).innerwidth();                 return innerwidth;             }              function shouldrenderfriendlyvalue() {                 scrollwidth = element[0].scrollwidth;                 if (element.innerwidth() < scrollwidth) {                     return true;                 }                  return false;             }              function updateelementsize(width) {                 element[0].style.width = width + 'px';             }         }     } }]); 

any suggestions appreciated!

also worth noting i'm aware function renders more times necessary in cases - there's no sense in optimizing if there's better approach.

---------------update-------------

there has been confusion here wanted try simplify problem statement:

how know if there enough space show full value or if have abbreviate it?

i've demonstrated 1 way approach this, i'm not convinced it's best way.

my recommendation be: don't this. here of reasons:

  • responsive design should controlled , consistent, not chaotic

    if approach responsive design way you're suggesting here (adjust elements individually based on run-time allocated space), you'll end little no idea various results (because there many possibilities). additionally, results may pretty inconsistent (e.g. different digits have different widths - numbers of same number of digits same ammount of space may or may not shortened).

    it's better give content enough space. if know you're running out of space, might provide multiple alternatives of content , switch alternative based on display size (consistently). e.g. on screens under 480px wide, might hide "long number" alternative , show "short number" instead.

  • content formatting should aim optimal readability

    large numbers not readable. might want shorten them (and provide units) better readability in general, not in places can't fit in expanded format.

    keep in mind users don't read single number. comparing multiple numbers is, example, common use-case, , can hurt lot inconsistent formatting.

  • watching dimensions on per-element basis can hurt performance

    afaik, there's no event notifying of element dimension changes , lot of things can trigger such changes (for example adding non-related element dom might trigger different styling). watching changes therefore requires sort of periodic checking, can have performance impact when used on large number of elements.


Comments

Popular posts from this blog

python - mat is not a numerical tuple : openCV error -

c# - MSAA finds controls UI Automation doesn't -

wordpress - .htaccess: RewriteRule: bad flag delimiters -