(note (code cslai))

Proof of Concept: YQuery

After the last post, I found that it may be fun to write a wrapper for YUI in order to make it behave like jQuery. Therefore, the code below is clearly mainly for self-amusement and is not intended to be used in production projects. However, through coding this, I found that although the difference in design, but YUI is obviously capable to do what jQuery offers (if not more). I will not continue working on this so whoever interested may just copy and paste the code to further developing it.

/**
 * Proof of concept : jQuery-like syntax in YUI
 */
(function() {

var yui_builder = (function(Selector, Element, DOM, Event) {
    return function(_selector) {
        var Result = function() {};

        var init = function(_selector) {
            var result = [];

            if(typeof _selector == 'object') {
                result = [ new Element(_selector) ];
            } else {
                result = query_elements.call(this, _selector);
            }

            return result;
        };

        var delegate = function(_scope, _function) {
            return function() {
                return _function.apply(_scope, arguments);
            };
        };

        var query_elements = function(_selector) {
            var result = new Result;
            var elements = wrap_elements(Selector.query(_selector));

            for(var i in elements) {
                result[i] = elements[i];
            }

            return result;
        };

        var unwrap_elements = function(_elements) {
            var result = [];

            for(var i in _elements) {
                result[i] = _elements[i].get('element');
            }

            return result;
        };

        var wrap_elements = function(_elements) {
            var result = [];

            for(var i in _elements) {
                result[i] = new Element(_elements[i]);
            }

            return result;
        };

        return (function(_elements) {
            _this = new Result;

            _this.addClass = function(_class) {
                for(var i in _elements) {
                    _elements[i].addClass(_class);
                }

                return this;
            };

            _this.append = function(_content) {
                if(typeof _content == 'string') {
                    for(var i in _elements) {
                        _elements[i].set(
                            'innerHTML',
                            _elements[i].get('innerHTML') + _content
                        );
                    }
                } else if(typeof _content == 'object') {
                    _elements[0].appendChild(_content);
                }

                return this;
            };

            _this.appendTo = function(_selector) {
                var _parent = yui_builder(_selector);

                for(var i in _elements) {
                    _elements[i].appendTo(_parent.get(0));
                }

                return this;
            }

            _this.attr = function() {
                var result = this;

                if(arguments.length == 1 && typeof arguments[0] == 'string') {
                    result = _elements[0].get(arguments[0]);

                    if(!result) {
                        result = undefined;
                    }
                } else if(arguments.length == 1 && typeof arguments[0] == 'object') {
                    for(var i in _elements) {
                        for(var attribute in arguments[0]) {
                            _elements[i].set(attribute, arguments[0][attribute]);
                        }
                    }
                } else if(typeof arguments[1] == 'function') {
                    for(var i in _elements) {
                        _elements[i].set(arguments[0], arguments[1].call(_elements[i].get('element'), i));
                    }
                } else {
                    for(var i in _elements) {
                        _elements[i].set(arguments[0], arguments[1]);
                    }
                }

                return result;
            };

            _this.each = function(_callback) {
                for(var i in _elements) {
                    _callback.call(_elements[i].get('element'), i, _elements[i].get('element'));
                }

                return this;
            };

            _this.eq = function(_index) {
                return yui_builder(_elements[_index]);
            };

            _this.get = function() {
                var result = [];

                if(arguments.length == 0) {
                    result = unwrap_elements.call(this, _elements);
                } else {
                    result = _elements[arguments[0]].get('element');
                }

                return result;
            };

            _this.hasClass = function(_class) {
                var result = false;

                for(var i in _elements) {
                    if(_elements[i].hasClass(_class)) {
                        result = true;
                        break;
                    }
                }

                return result;
            };

            _this.html = function() {
                var result = this;

                if(arguments.length == 0) {
                    result = _elements[0].get('innerHTML');
                } else {
                    _elements[0].set('innerHTML', arguments[0]);
                }

                return result;
            }

            _this.index = function(_subject) {
                var result = -1;

                for(var i in _elements) {
                    if(_elements[i].get('element') === _subject) {
                        result = i;
                    }
                }

                return result;
            };

            _this.removeClass = function(_class) {
                for(var i in _elements) {
                    _elements[i].removeClass(_class);
                }

                return this;
            }

            _this.size = function() {
                return _elements.length;
            };

            _this.toggleClass = function() {
                if(arguments.length == 0) {
                    for(var i in _elements) {
                        if(_elements[i].hasClass) {
                            _elements[i].removeClass(arguments[0]);
                        } else {
                            _elements[i].addClass(arguments[0]);
                        }
                    }
                } else {
                    for(var i in _elements) {
                        if(arguments[1]) {
                            _elements[i].addClass(arguments[0]);
                        } else {
                            _elements[i].removeClass(arguments[0]);
                        }
                    }
                }

                return this;
            };

            _this.val = function() {
                var result = this;

                if(arguments.length == 0) {
                    result = this.attr('value');
                } else {
                    for(var i in _elements) {
                        this.attr('value', arguments[0]);
                    }
                }

                return result;
            };

            (function() {
                for(var i in _elements) {
                    _this[i] = _elements[i];
                }
            }).call(_this)

            return _this;
        }).call(this, init.apply(this, arguments));
    }
})(YAHOO.util.Selector, YAHOO.util.Element, YAHOO.util.Dom, YAHOO.util.Event);

})();

Most of the implemented functions are similar to what jQuery offers, therefore to use the yui_builder:


(function($) {
    // everyone loves $ function
    $(document.createElement('a'));
        .attr('href', 'test')
        .html('test')
        .appendTo(document.body);
})(yui_builder);

Exit mobile version