Logo text Governance.io - Governance.com
  • Benefits

  • Information

  • Customer area

  • More...

    • Benefits
      • Information
        • Careers
          • Contact
          • Customer area
            • License order form
              • Cart
                • General terms and conditions
                  • Privacy Policy
                    • User Agreement
                    LINKS
                    ABOUT
                    SOCIAL
                    • Grey Twitter Icon
                    • Grey Facebook Icon
                    • Grey LinkedIn Icon

                    2Gears S.A.

                    Creators of Governance.io - Governance.com

                    ​

                    Visiting address:

                    29, Boulevard GD Charlotte

                    "The Office"

                    L-1331 Luxembourg

                    ​

                    Registered address:

                    17, Boulevard Prince Henri

                    L-1724 Luxembourg

                    VAT: LU28166771
                    RCS: B0164267 

                    © 2016 2Gears SA

                    Logo Governance.io - Governance.com
                    THE PLATFORM

                    IMF: Luxembourg Financial Sector Assessment Program 2017

                    September 2, 2017

                    The Innovators — A Conversation with Bert Boerman, CEO of Governance.io

                    August 3, 2017

                    Governance.io welcomes Business Development Director Olus Kayacan

                    June 16, 2017

                    Trident Trust applies RegTech to lead in Alternative Investment Fund services

                    June 9, 2017

                    Governance.io listed on the European Hot Ten list of FinTech50

                    June 7, 2017

                    Governance.io team at ICT Spring in Luxembourg

                    May 23, 2017

                    Sneak preview of Governance.io VisualWorkBench™

                    April 8, 2017

                    Bert Boerman selected as RegTech book author

                    March 22, 2017

                    A TASTE OF FINTECH FROM 2 ANGLES... AND 2 SIDES OF THE WORLD

                    March 17, 2017

                    FINTECH AWARDS 2017 - who will take over the title "FinTech Startup of the Year" from Governance.io?

                    March 15, 2017

                    Please reload

                    Recent Posts
                    Sencha Touch
                    Tips and tricks

                    Sprintf formatter for Sencha Touch and ExtJS

                    September 27, 2012

                    After programming in multiple languages I have come to depend on sprintf quite a lot. Almost every language I know of provides a fairly decent version of the sprintf formatter. Unfortunately JavaScript is not one of them. For a lot of projects we use ExtJS and Sencha Touch. While both frameworks offer quite some string formatting functionalities using the String and Format classes, personally I feel sprintf gives me as a developer much more freedom to format strings the way I want them. Luckily it can be easily integrated in ExtJS and Sencha Touch.

                     

                    In Sencha Touch and ExtJS we use string formatting separately, but also a lot in XTemplates (which are great for creating all sorts of templates). As an example I might want to use an XTemplate to create an invoice. The XTemplate would then consume an object containing the line items that are calculated by my controller and some summary information. A (stupid simple) example would be:

                    1. var template = new Ext.XTemplate(

                    2. '<h1>Invoice number {invoicenumber}</h1>',

                    3. '<h2>Items:</h2>',

                    4. '<ol>',

                    5. '<tpl for="lineitems">',

                    6. '<li><strong>{name}</strong> - {price}</li>',

                    7. '</tpl>',

                    8. '</ol>',

                    9. 'Total: {total}<br>',

                    10. 'Tax: {tax}'

                    11. );

                    My controller fetches the line items from a local store and calculates the total and tax using simple formulas. The prices in the resulting invoice object for the XTemplate to render are all floats or integers.

                    1. var invoice = {

                    2. invoicenumber: 235,

                    3. total: 125.5,

                    4. tax: 23.85,

                    5. lineitems: [{

                    6. name: 'Some amazing product',

                    7. price: 80

                    8. },{

                    9. name: 'Some less amazing product',

                    10. price: 45.5

                    11. }]

                    12. };

                    I render the XTemplate using ‘template.apply(invoice);’ and….

                    1. <h1>Invoice number 235</h1>

                    2. <h2>Items:</h2>

                    3. <ol>

                    4. <li><strong>Some amazing product</strong> - 80</li>

                    5. <li><strong>Some less amazing product</strong> - 45.5</li>

                    6. </ol>

                    7. Total: 125.5<br>

                    8. Tax: 23.85

                    Clearly not what I want. The prices have to be formatted with 2 decimals and the invoice number has to be 0-padded up to 6 chracters.
                    With the additions below, this becomes as easy as… well… sprintf.

                    1. var template = new Ext.XTemplate(

                    2. '<h1>Invoice number {invoicenumber:printf("%06d")}</h1>',

                    3. '<h2>Items:</h2>',

                    4. '<ol>',

                    5. '<tpl for="lineitems">',

                    6. '<li><strong>{name}</strong> - {price:printf("€ %.2f")}</li>',

                    7. '</tpl>',

                    8. '</ol>',

                    9. 'Total: {total:printf("€ %.2f")}<br>',

                    10. 'Tax: {tax:printf("€ %.2f")}'

                    11. );

                    And voila

                    1. <h1>Invoice number 000235</h1>

                    2. <h2>Items:</h2>

                    3. <ol>

                    4. <li><strong>Some amazing product</strong> - € 80.00</li>

                    5. <li><strong>Some less amazing product</strong> - € 45.50</li>

                    6. </ol>

                    7. Total: € 125.50<br>

                    8. Tax: € 23.85

                    All you have to do is drop the code below into your app. It injects an sprintf function into the Ext.String class and a custom printf formatter to the Ext.util.Format class. The code can also be downloaded as a js file here. Almost all general use sprintf formats are supported. If you like the solution, let me know and consider sharing this post it with others. Good luck.

                    1. /**

                    2. sprintf() for JavaScript 0.7-beta1

                    3.  

                    4. http://www.diveintojavascript.com/projects/javascript-sprintf

                    5.  

                    6. Copyright (c) Alexandru Marasteanu

                    7. All rights reserved.

                    8.  

                    9. Redistribution and use in source and binary forms, with or without

                    10. modification, are permitted provided that the following conditions are met:

                    11. * Redistributions of source code must retain the above copyright

                    12. notice, this list of conditions and the following disclaimer.

                    13. * Redistributions in binary form must reproduce the above copyright

                    14. notice, this list of conditions and the following disclaimer in the

                    15. documentation and/or other materials provided with the distribution.

                    16. * Neither the name of sprintf() for JavaScript nor the

                    17. names of its contributors may be used to endorse or promote products

                    18. derived from this software without specific prior written permission.

                    19.  

                    20. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND

                    21. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED

                    22. WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE

                    23. DISCLAIMED. IN NO EVENT SHALL Alexandru Marasteanu BE LIABLE FOR ANY

                    24. DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES

                    25. (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;

                    26. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND

                    27. ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

                    28. (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS

                    29. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

                    30.  

                    31. Changelog:

                    32. 2010.09.06 - 0.7-beta1

                    33. - features: vsprintf, support for named placeholders

                    34. - enhancements: format cache, reduced global namespace pollution

                    35.  

                    36. 2010.05.22 - 0.6:

                    37. - reverted to 0.4 and fixed the bug regarding the sign of the number 0

                    38. Note:

                    39. Thanks to Raphael Pigulla (http://www.n3rd.org/)

                    40. who warned me about a bug in 0.5, I discovered that the last update was

                    41. a regress. I appologize for that.

                    42.  

                    43. 2010.05.09 - 0.5:

                    44. - bug fix: 0 is now preceeded with a + sign

                    45. - bug fix: the sign was not at the right position on padded results (Kamal Abdali)

                    46. - switched from GPL to BSD license

                    47.  

                    48. 2007.10.21 - 0.4:

                    49. - unit test and patch (David Baird)

                    50.  

                    51. 2007.09.17 - 0.3:

                    52. - bug fix: no longer throws exception on empty paramenters (Hans Pufal)

                    53.  

                    54. 2007.09.11 - 0.2:

                    55. - feature: added argument swapping

                    56.  

                    57. 2007.04.03 - 0.1:

                    58. - initial release

                    59. **/

                    60.  

                    61. Ext.onReady(function() {

                    62. function get_type(variable) {

                    63. return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase();

                    64. }

                    65. function str_repeat(input, multiplier) {

                    66. for (var output = []; multiplier > 0; output[--multiplier] = input) {/* do nothing */}

                    67. return output.join('');

                    68. }

                    69.  

                    70. var str_format = function() {

                    71. if (!str_format.cache.hasOwnProperty(arguments[0])) {

                    72. str_format.cache[arguments[0]] = str_format.parse(arguments[0]);

                    73. }

                    74. return str_format.format.call(null, str_format.cache[arguments[0]], arguments);

                    75. };

                    76.  

                    77. str_format.format = function(parse_tree, argv) {

                    78. var cursor = 1, tree_length = parse_tree.length, node_type = '', arg, output = [], i, k, match, pad, pad_character, pad_length;

                    79. for (i = 0; i < tree_length; i++) {

                    80. node_type = get_type(parse_tree[i]);

                    81. if (node_type === 'string') {

                    82. output.push(parse_tree[i]);

                    83. }

                    84. else if (node_type === 'array') {

                    85. match = parse_tree[i]; // convenience purposes only

                    86. if (match[2]) { // keyword argument

                    87. arg = argv[cursor];

                    88. for (k = 0; k < match[2].length; k++) { if (!arg.hasOwnProperty(match[2][k])) { throw(Ext.String.sprintf('[sprintf] property "%s" does not exist', match[2][k])); } arg = arg[match[2][k]]; } } else if (match[1]) { // positional argument (explicit) arg = argv[match[1]]; } else { // positional argument (implicit) arg = argv[cursor++]; } if (/[^s]/.test(match[8]) && (get_type(arg) != 'number')) { throw(Ext.String.sprintf('[sprintf] expecting number but found %s', get_type(arg))); } switch (match[8]) { case 'b': arg = arg.toString(2); break; case 'c': arg = String.fromCharCode(arg); break; case 'd': arg = parseInt(arg, 10); break; case 'e': arg = match[7] ? arg.toExponential(match[7]) : arg.toExponential(); break; case 'f': arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg); break; case 'o': arg = arg.toString(8); break; case 's': arg = ((arg = String(arg)) && match[7] ? arg.substring(0, match[7]) : arg); break; case 'u': arg = Math.abs(arg); break; case 'x': arg = arg.toString(16); break; case 'X': arg = arg.toString(16).toUpperCase(); break; } arg = (/[def]/.test(match[8]) && match[3] && arg >= 0 ? '+'+ arg : arg);

                    89. pad_character = match[4] ? match[4] == '0' ? '0' : match[4].charAt(1) : ' ';

                    90. pad_length = match[6] - String(arg).length;

                    91. pad = match[6] ? str_repeat(pad_character, pad_length) : '';

                    92. output.push(match[5] ? arg + pad : pad + arg);

                    93. }

                    94. }

                    95. return output.join('');

                    96. };

                    97.  

                    98. str_format.cache = {};

                    99.  

                    100. str_format.parse = function(fmt) {

                    101. var _fmt = fmt, match = [], parse_tree = [], arg_names = 0;

                    102. while (_fmt) {

                    103. if ((match = /^[^x25]+/.exec(_fmt)) !== null) {

                    104. parse_tree.push(match[0]);

                    105. }

                    106. else if ((match = /^x25{2}/.exec(_fmt)) !== null) {

                    107. parse_tree.push('%');

                    108. }

                    109. else if ((match = /^x25(?:([1-9]d*)$|(([^)]+)))?(+)?(0|'[^$])?(-)?(d+)?(?:.(d+))?([b-fosuxX])/.exec(_fmt)) !== null) {

                    110. if (match[2]) {

                    111. arg_names |= 1;

                    112. var field_list = [], replacement_field = match[2], field_match = [];

                    113. if ((field_match = /^([a-z_][a-z_d]*)/i.exec(replacement_field)) !== null) {

                    114. field_list.push(field_match[1]);

                    115. while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') {

                    116. if ((field_match = /^.([a-z_][a-z_d]*)/i.exec(replacement_field)) !== null) {

                    117. field_list.push(field_match[1]);

                    118. }

                    119. else if ((field_match = /^[(d+)]/.exec(replacement_field)) !== null) {

                    120. field_list.push(field_match[1]);

                    121. }

                    122. else {

                    123. throw('[sprintf] huh?');

                    124. }

                    125. }

                    126. }

                    127. else {

                    128. throw('[sprintf] huh?');

                    129. }

                    130. match[2] = field_list;

                    131. }

                    132. else {

                    133. arg_names |= 2;

                    134. }

                    135. if (arg_names === 3) {

                    136. throw('[sprintf] mixing positional and named placeholders is not (yet) supported');

                    137. }

                    138. parse_tree.push(match);

                    139. }

                    140. else {

                    141. throw('[sprintf] huh?');

                    142. }

                    143. _fmt = _fmt.substring(match[0].length);

                    144. }

                    145. return parse_tree;

                    146. };

                    147.  

                    148. Ext.String.sprintf = str_format;

                    149.  

                    150. Ext.apply(Ext.util.Format, {

                    151. printf: function(v, format) {

                    152. if (typeof v != "number") {

                    153. Ext.Logger.warn('value in printf format is not numeric, trying to cast to float');

                    154. v = parseFloat(v,10);

                    155. }

                    156. return Ext.String.sprintf(format, v);

                    157. }

                    158. });

                    159. });

                       

                       

                       

                       

                       

                       

                       

                       

                       

                    Tags:

                    Sencha

                    Touch

                    ExtJS

                    Share on Facebook
                    Share on Twitter
                    Please reload

                    Follow Us

                    September 2017 (1)

                    August 2017 (1)

                    June 2017 (3)

                    May 2017 (1)

                    April 2017 (1)

                    March 2017 (4)

                    February 2017 (1)

                    January 2017 (3)

                    December 2016 (1)

                    October 2016 (2)

                    June 2016 (1)

                    May 2016 (1)

                    August 2014 (2)

                    July 2013 (2)

                    September 2012 (1)

                    July 2012 (1)

                    Please reload

                    Archive
                    • Facebook Basic Square
                    • Twitter Basic Square
                    • Google+ Basic Square