Flourish PHP Unframework
This is an archived copy of the forum for reference purposes

Flourish JavaScript ports

posted by audvare 8 years ago

Thinking about starting a project. Global Flourish object, just useful static methods.

Here is humanize() and underscorize() as close as possible to PHP implementation:

Flourish = {};

Flourish.humanizeCache = {};
Flourish.underscorizeCache = {};

/**
 * Port of fGrammar::underscorize from Flourish.
 *
 * @param {string} str
 * @return {string}
 */
Flourish.underscorize = function (str) {
  if (Flourish.underscorizeCache[str]) {
    return Flourish.underscorizeCache[str];
  }

  var original = str;
  str = str.charAt(0).toLowerCase() + str.substr(1);

  if (str.indexOf('_') !== -1 && str.toLowerCase() === str) {
  }
  else {
    var old;
    do {
      old = str;
      str = str.replace(/([a-zA-Z])([0-9])/, '$1_$2');
      str = str.replace(/([a-z0-9A-Z])([A-Z])/, '$1_$2');
    } while (old !== str);

    str = str.toLowerCase(str);
  }

  Flourish.underscorizeCache[original] = str;

  return str;
};

/**
 * Port of fGrammar::humanize() from Flourish.
 *
 * @param {string} str
 * @return {string}
 */
Flourish.humanize = function (str) {
  if (Flourish.humanizeCache[str]) {
    return Flourish.humanizeCache[str];
  }

  var original = str;

  if (str.indexOf(' ') === -1) {
    if (str.indexOf('_') !== -1) {
      str = Flourish.underscorize(str);
    }
  }

  var regex = /(\\b(api|css|gif|html|id|jpg|js|mp3|pdf|php|png|sql|swf|url|xhtml|xml)\\b|\\b\\w)/;
  str = str.replace(/_/g, ' ').replace(regex, function (str, p1) {
    return p1.charAt(0).toUpperCase();
  });

  Flourish.humanizeCache[original] = str;

  return str;
};

Just for fun here's what Closure Compiler spits out pretty-printed:

Flourish = {b: {},d: {}};
Flourish.i = function(a) {
    if (Flourish.d[a])
        return Flourish.d[a];
    var b = a, a = a.charAt(0).toLowerCase() + a.substr(1);
    if (!(a.indexOf("_") !== -1 && a.toLowerCase() === a)) {
        var c;
        do
            c = a, a = a.replace(/([a-zA-Z])([0-9])/, "$1_$2"), a = a.replace(/([a-z0-9A-Z])([A-Z])/, "$1_$2");
        while (c !== a);
        a = a.toLowerCase(a)
    }
    return Flourish.d[b] = a
};
Flourish.h = function(a) {
    if (Flourish.b[a])
        return Flourish.b[a];
    var b = a;
    a.indexOf(" ") === -1 && a.indexOf("_") !== -1 && (a = Flourish.i(a));
    a = a.replace(/_/g, " ").replace(/(\\b(api|css|gif|html|id|jpg|js|mp3|pdf|php|png|sql|swf|url|xhtml|xml)\\b|\\b\\w)/, function(a, b) {
        return b.charAt(0).toUpperCase()
    });
    return Flourish.b[b] = a
};

The Flourish for JavaScript is called: underscore.js

http://documentcloud.github.com/underscore/

Really awesome set of functions for JavaScript, just like Flourish is for php.

posted by mblarsen 8 years ago

I'll have to disagree. While underscore.js provides useful functionality it parallels with the many other libraries that bring concepts like Collections to JavaScript. I am really leaning more towards what is in the fGrammar class and a few others that make sense to have available in JavaScript.

posted by audvare 8 years ago

I see your point. I mentioned underscore, because it's similar character/philosophy of bridging or leveraging the programmers tool belt. More tool-set than framework.

fGrammar does provide some very useful functionality, that I would love to see on the client-side. See please keep posting ;)

posted by mblarsen 8 years ago

Some fURL and fRequest. fRequest.get() only supports 'number' and 'float' at this time. 'number' is the equivalent to 'int' or 'integer' in JavaScript.

fRequest.get() will NOT return NaN.

var fURL = {
  /**
   * @access public
   * @return {string}
   */
  getQueryString: function () {
    return location.search ? location.search.substr(1) : '';
  },
  /**
   * @access public
   * @return {string}
   */
  get: function () {
    var url = location.href;
    var qs = fURL.getQueryString();
    if (qs) {
      url = url.replace(location.search, '').replace(/^https?\\:\\/\\//, '').replace(/\\/$/, '');
    }
    return url;
  }
};

var fRequest = {
  _REQUEST: null,
  /**
   * @access private
   */
  _cast: function (value, to) {
    switch (to) {
      case 'number':
        return parseInt(value, 10);

      case 'float':
        return parseFloat(value);
    }

    return value;
  },
  /**
   * @access private
   */
  _initialize: function () {
    if (fRequest._REQUEST === null) {
      var qs = fURL.getQueryString();
      var items = qs.split('&');
      var itemsAsObject = {}, current;
      
      for (var i = 0; i < items.length; i++) {
        current = items[i].split('=');
        itemsAsObject[current[0]] = current[1];
      }
      
      fRequest._REQUEST = itemsAsObject;
    }
  },
  /**
   * @access public
   */
  get: function (name, castTo, defaultValue) {
    fRequest._initialize();
    
    if (!fURL.getQueryString()) {
      if (defaultValue !== undefined) {
        return defaultValue;
      }
      else {
        return null;
      }
    }

    if (fRequest._REQUEST[name]) {
      if (castTo !== undefined) {
        var ret = fRequest._cast(fRequest._REQUEST[name], castTo);

        // To be more like PHP
        if (isNaN(ret) && (castTo === 'number')) {
          ret = 0;
        }
      }

      return fRequest._REQUEST[name];
    }
    else if (defaultValue !== undefined) {
      return defaultValue;
    }

    return null;
  }
};
posted by audvare 7 years ago
/**
 * @const {object}
 */
var fCore = {
  /**
   * @const {boolean}
   */
  debuggingEnabled: false,
  /**
   * @param {boolean} true or false.
   * @return {object}
   */
  enableDebugging: function (bool) {
    if (!bool) {
      bool = false;
    }
    
    fCore.debuggingEnabled = bool;
    return fCore;
  },
  /**
   * @param {string} message The debug message.
   * @param {force} If debugging should be forced even when global debugging is
   *   off.
   */
  debug: function (message, force) {
    if (!fCore.debuggingEnabled) {
      return;
    }

    if (window.console) {
      console.log(message);
    }
    else if (window.Debug) { // IE 7 and lower, need VS and debugging to be enabled
      Debug.writeln(message);
    }
  }
};
posted by audvare 7 years ago

http://demos.tatsh.net/fGrammar.js

http://demos.tatsh.net/fGrammar.min.js (minified)

Version of fGrammar with the following methods:

camelize() -- same as Flourish
underscorize() -- same as Flourish
inflectOnQuantity() -- same as Flourish
camelize(str, upper, delimiter) -- delimiter argument is by default '_' (like Flourish); I use '-' at times

Also has the sGrammar 'class' which has the same methods copied from fGrammar but adds dashize():

dashize() -- this is the same as underscorize() but instead uses dashes to transform a string (example: ABC -> a-b-c)
posted by audvare 7 years ago

Nice work audvare.

posted by mblarsen 7 years ago

Maintaining all my ports here https://github.com/tatsh/flourish-js

posted by audvare 7 years ago

Just a general idea on how to implement fActiveRecord on the client side. Ultimately the goal would be to have the store() method call upon the server-side in a documented way (where the server-side may need to return data in exact specific ways, fORMJSON could be involved and make this process easy). This is somewhat similar to backbone's modelling technique.

For now though, the only difficulty is making this compile with Closure Compiler. I haven't found a way where the names of the objects can be 'destroyed' in the advanced optimisations mode. It's not a big deal, but I would prefer it.

https://gist.github.com/2425947

posted by audvare 7 years ago