Question

I'm trying to create a small Javascript "framework" that I can use in my greasemonkey scripts. I only need very basic functions, so this is why I choose not to use mooTools or DOMAssistant. Besides, I'm not going to be silly and put DOMAssitant in a 20KB Greasemonkey script! I just want a small, neat snippet of code.

I have a small problem with the below code. I think its because I am returning an array in $() so I get .setStyle is not a function error message.


var fmini = {  
  $ : function(a) {
    var i=0,obj,d;
    var e = [];

    while (obj = arguments[i++]) {
      d = document.getElementById(obj);
      d.setStyle = fmini.setStyle;
      d.each = fmini.each;
      e.push(d);
    }

    return e;
  },
  setStyle : function(style, value) {
    if (typeof this.style.cssText !== 'undefined') {
      var styleToSet = this.style.cssText;
      if (typeof style === 'object') {
        for (var i in style) 
          if (typeof i === 'string') styleToSet += ';' + i + ':' + style[i];
      }
      else styleToSet += ';' + style + ':' + value;
      this.style.cssText = styleToSet;
    }
    return this;
  },
  each : function (functionCall) {
                for (var i=0, il=this.length; i < il; i++) 
                    functionCall.call(this[i]);
                return this;
    },
}
window.$ = fmini.$;

I would like this to work when I do


  $('bob','amy').setStyle({
    'border' : '5px solid #ff0000',
    'background-color' : '#ccc'
    });
Was it helpful?

Solution

Write your methods to operate on the set of nodes returned from $. That way both $('bob').setStyle() and $('bob', 'amy').setStyle() will work. I see you have a generic forEach or each method which is a good start.

var fmini = {
    $: function() {
        var i=0, obj;
        var e = [];
        e.setStyle = fmini.setStyle;
        e.each = fmini.each;

        while (obj = arguments[i++]) {
            e.push(document.getElementById(obj));
        }

        return e;
    },

    setStyle : function(style, value) {
        return this.each(function() {
            if (typeof this.style.cssText !== 'undefined') {
                var styleToSet = this.style.cssText;
                if (typeof style === 'object') {
                    for (var i in style) 
                        if (typeof i === 'string') styleToSet += ';' + i + ':' + style[i];
                }
                else styleToSet += ';' + style + ':' + value;
                this.style.cssText = styleToSet;
            }
        })
    }
}

Incidentally this is something jQuery was the first to do/popularze.

OTHER TIPS

Like you had suspected the return of $ in this case is an array of the elements, you have to extend array with setStyle or add the extension when the array is populated before you pass the array back. Then you shouldn't get an error saying .setStyle is not a function. However you will have to also make sure you handle your object context binding when you are chaining like this otherwise this is referring to the current scope and not an element in your array.

The $ function is returning an array; it should either be returning the element object itself (d) on which you augment the setStyle method, or just another object.

If you want you could use my library.

It's called Ally and you can download it here: http://github.com/AllyToolkit/Ally

I noticed you said you want something lightweight, and the stock version of Ally is currently just over 1300 lines, 25KB unminified, and you could easily cut out the parts you don't want.

I wrote it with the intention of being very easy to modify, yet still very powerful, and full of useful features.

I'm releasing the 2nd beta soon tonight. It should be up on the release branch ( http://github.com/AllyToolkit/Ally/tree/release ) within the next hour.

If you decide to try it I hope you enjoy. :)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top