среда, 2 марта 2011 г.

Ядро YUI3

Частью ядра стал загрузчик. Параметры для него предаются в метод создание экземпляра юай.
YUI({......})



Загрузчик ожидает следующие параметры:

  • lang: The list of preferred languages, as BCP 47 language tags, in order of preference. The loader uses this list to determine the best language to use for modules with language sensitive behavior and to load the necessary resource bundles. See the Internationalization module for more information.
  • base: The base dir
  • secureBase: The secure base dir (not implemented)
  • comboBase: The YUI combo service base dir. Ex: http://yui.yahooapis.com/combo?
  • root: The root path to prepend to module names for the combo service. Ex: 2.5.2/build/
  • filter: A filter to apply to result urls. This filter will modify the default path for all modules. The default path for the YUI library is the minified version of the files (e.g., event-min.js). The filter property can be a predefined filter or a custom filter. The valid predefined filters are:
    • DEBUG: Selects the debug versions of the library (e.g., event-debug.js).
    • RAW: Selects the non-minified version of the library (e.g., event.js).
    You can also define a custom filter, which must be an object literal containing a search expression and a replace string:
    myFilter: { 
    'searchExp': "-min\\.js", 
    'replaceStr': "-debug.js"
    }
  • combine: Use the YUI combo service to reduce the number of http connections required to load your dependencies
  • ignore: A list of modules that should never be dynamically loaded
  • force: A list of modules that should always be loaded when required, even if already present on the page
  • insertBefore: Node or id for a node that should be used as the insertion point for new nodes
  • charset: charset for dynamic nodes
  • jsAttributes: attributes to apply to dynamic script nodes
  • cssAttributes: attributes to apply to dynamic link nodes
  • timeout: number of milliseconds before a timeout occurs when dynamically loading nodes. in not set, there is no timeout
  • context: execution context for all callbacks
  • modules: A list of module definitions. The valid module configuration data is as follows:
    • name: required, the component name
    • type: required, the component type (js or css)
    • path: required if fullpath is not specified, the path to the script from "base"
    • fullpath: required if path isn't specified, the full path to the script. "base" will not be used to build the url
    • requires: array of modules required by this component
    • optional: array of optional modules for this component
    • supersedes: array of the modules this component replaces
    • after: array of modules the components which, if present, should be sorted above this one
    • rollup: the number of superseded modules required for automatic rollup
    • lang: array of BCP 47 language tags of languages for which this module has localized resource bundles
  • groups: in 3.1.0, the groups config was added as an enhancement over the 'modules' config. Each group can the base, comboBase, root, combine, and modules configs listed above. These values are used for all of the modules listed in the group

Еще одна часть ядра это Y.lang -- это библиотечка которая содрежит яваскриптовые функции (просто обвертки, а в некоторых браузерах реализации, родных яваскриптовых функций):

var Y = YUI();
 
// true, an array literal is an array
Y.Lang.isArray([1, 2]);
 
// false, an object literal is not an array
Y.Lang.isArray({"one": "two"});
 
// however, when declared as an array, it is true
function() {
    var a = new Array();
    a["one"] = "two";
    return Y.Lang.isArray(a);
}();
 
// false, a collection of elements is like an array, but isn't
Y.Lang.isArray(document.getElementsByTagName("body"));
 
// true, false is a boolean
Y.Lang.isBoolean(false);
 
// false, 1 and the string "true" are not booleans
Y.Lang.isBoolean(1);
Y.Lang.isBoolean("true");
 
// null is null, but false, undefined and "" are not
Y.Lang.isNull(null); // true
Y.Lang.isNull(undefined); // false
Y.Lang.isNull(""); // false
 
// a function is a function, but an object is not
Y.Lang.isFunction(function(){}); // true
Y.Lang.isFunction({foo: "bar"}); // false
 
// true, ints and floats are numbers
Y.Lang.isNumber(0);
Y.Lang.isNumber(123.123);
 
// false, strings that can be cast to numbers aren't really numbers
Y.Lang.isNumber("123.123");
 
// false, undefined numbers and infinity are not numbers we want to use
Y.Lang.isNumber(1/0);
 
// true, objects, functions, and arrays are objects
Y.Lang.isObject({});
Y.Lang.isObject(function(){});
Y.Lang.isObject([1,2]);
 
// false, primitives are not objects
Y.Lang.isObject(1);
Y.Lang.isObject(true);
Y.Lang.isObject("{}");
 
// strings
Y.Lang.isString("{}"); // true
Y.Lang.isString({foo: "bar"}); // false
Y.Lang.isString(123); // false
Y.Lang.isString(true); // false
 
// undefined is undefined, but null and false are not
Y.Lang.isUndefined(undefined); // true
Y.Lang.isUndefined(false); // false
Y.Lang.isUndefined(null); // false

Инструменты классовой архитектуры
1) Наследование
Юай реализовывает наследования на классах через метод Y.extend, при этом такое наследование не создает не нужный обьект, если бы мы просто присвоили наследника протототипу обьект отца. Instanseof покажет что обьект является экземпляром как своего класса, так и родительского.
YUI().use("node", function(Y) {
    // This method is in the 'oop' module.  Since we require 'node'
    // for this example, and 'node' requires 'oop', the 'oop' module
    // will be loaded automatically.
 
    function Bird(name) {
        this.name = name;
    }
 
    Bird.prototype.flighted   = true;  // Default for all Birds
    Bird.prototype.isFlighted = function () { return this.flighted };
    Bird.prototype.getName    = function () { return this.name };
 
    function Chicken(name) {
        // Chain the constructors
        Chicken.superclass.constructor.call(this, name);
    }
 
    // Chickens are birds
    Y.extend(Chicken, Bird);
 
    // Define the Chicken prototype methods/members
    Chicken.prototype.flighted = false; // Override default for all Chickens
 
    function showInheritance() {
        var chicken = new Chicken('Little'),
            results = Y.one('#demo');
 
        results.append(((chicken instanceof Object) ?
            "chicken IS an instance of Object.
" :
            "chicken IS NOT an instance of Object.
"));
 
        results.append(((chicken instanceof Bird) ?
            "chicken IS an instance of Y.example.Bird.
" :
            "chicken IS NOT an instance of Y.example.Bird.
"));
 
        results.append(((chicken instanceof Chicken) ?
            "chicken IS an instance of Y.example.Chicken.
" :
            "chicken IS NOT an instance of Y.example.Chicken.
"));
 
        // Chicken instances inherit Bird methods and members
        results.append(((chicken.isFlighted()) ?
            "chicken CAN fly.
" :
            "chicken CAN NOT fly.
"));
 
        results.append("chicken's name is " + chicken.getName() + ".
");
    }
 
    Y.on('click', showInheritance, '#demo_btn');
});

Комозиционирование(a composition-style class architecture)
Когда нам нужно придать некоему классу функциональность, которая разделаяется между несколькими иерархическими ветками классов, наследование тут не совсем верное решение. Это типа как множественное наследование, но при этом instanseof не подтвердит нам то, что это потомок композиционированного класса:

YUI().use("node", function(Y) {
    // This method is in the 'oop' module.  Since we require 'node'
    // for this example, and 'node' requires 'oop', the 'oop' module
    // will be loaded automatically.
 
    var Foo = function() {
        /* code specific to Foo */
        this.publish('interestingMoment');
    };
 
    Foo.prototype.doSomething = function() {
 
        var eventData = {};
 
        // -- do something interesting, add results to eventData --
 
        eventData.statusText = 'bar';
 
        // notify the subscribers, passing the event data
        this.fire('interestingMoment', eventData);
    }
 
    Y.augment(Foo, Y.EventTarget);
 
    var foo = new Foo();
 
    // add some event listeners
    foo.on('interestingMoment', function (data) {
        var p = Y.one('#demo_p1');
        p.setConten('I was notified of an interesting moment: ' + data.statusText);
    });
 
    foo.on('interestingMoment', function (data) {
        var p = Y.one('#demo_p2');
        p.setContent('I was also notified of an interesting moment: ' + data.statusText);
    });
 
    Y.on('click', function() { 
        foo.doSomething();
    }, '#demo');
});



YUI().use('oop', function(Y) {
 
    function Foo() {}
    Foo.prototype.doSomething = function () { /* something */ };
 
    function Bar() {}
    Y.augment(Bar, Foo);
 
    var b = new Bar();
    if (b instanceof Bar) {} // true 
    if (b instanceof Foo) {} // FALSE
});

Расширение статических классов
Если мы имеем дело со статическими классами, то их расширять нужно с помощью метода mix (этот метод используется в augment).

Есть понятие статических методов и понитие прототипных методов.
Статические -- это методы, которые могут использоваться только в инстанции поточного обьекта (нельзя создать с помощью этого обьекта другой, в котором будут доступны для использования эти методы).
Прототипные -- это методы, находящиеся в обьекте, на который ссылается свойство функции-обькта(Function) prototype. Этот обьект-функцию можно использовать как контруктор для создания новых обьектов, которым в прототип(свойство __proto__) будет передаваться обьект с "прототипными методами".
Статичским классом можно считать любой обьект с методами, который не может создавать новые инстанции обьектов и передавать им свои методы. Он просто живет и предоствляет в пользование свои методы.

//очень важно заметить, что следующим переменным
//присваиваются не функции, а результаты вызова безымянных функций;)
var Logging = function () {
    var logger = null;
 
    return {
        initLogger : function (logNode) {
            if (!logger) {
                logger = Y.one(logNode);
            }
        },
 
        log : function (message) {
            if (logger) {
                logger.append('' + message + '
');
            }
        }
    }
}();
 
var PageController = function () {
    var app_const = 12345;
 
    return {
 
        getConst : function () { 
            return app_const;
        },
 
        logConst : function () {
            this.initLogger('#demo_logger');
            this.log('PageController class constant = ' + this.getConst() +
                      ', logged courtesy of object augmentation via Y.mix.');
        }
    };
}();
 
Y.mix(PageController, Logging);
 
Y.on('click', PageController.logConst, '#demo_btn', PageController); 

Слияние обьектов
Это удобно для обьектов, которые играют роль массивов с параметрами. Мы передаем в этот метод в неком порядке обьекты, а метод все их свойства обьединяет в один обькт, при этом если имена свойст совпадают, то свойства позднее переданных обьектов будут перегружать свойства первых:
var set1 = { foo : "foo" };
var set2 = { foo : "BAR", bar : "bar" };
var set3 = { foo : "FOO", baz : "BAZ" };
var result = Y.one('#demo_result');
 
var doMerge = function () {
 
    Y.log('set1 = ' + Y.dump(set1));
    Y.log('set2 = ' + Y.dump(set2));
    Y.log('set3 = ' + Y.dump(set3));
 
    Y.log('Merging set1, set2, and set3');
    var merged = Y.merge(set1, set2, set3);
    Y.log('merged = ' + Y.dump(merged));
 
    result.setContent('' + Y.dump(merged) + '
');
};
 
Y.on('click', doMerge, '#demo_btn');

С помощью мерджа мы также можем делать "неглубокие" копии, если передадим в него один обьект, то на выходе мы получим его shallow copy:
var doCopy = function () {
 
    // Create set4 with an object property 'obj'
    var set4 = {
        obj: {}
    };
 
    // Create a shallow copy of set4
    var copy = Y.merge(set4);
 
    // Add a property to the copy inside of the 'obj' property
    copy.obj.addedToCopy = true;
 
    Y.log('After modifying the copy: ');
 
    // The result object is not the same as the original, but
    var msg = ('"copy" should NOT be equal to the "original" (false expected): ' + (copy === set4));
 
    // objects in the result object will reference the same object in
    // the input object.
    msg += '
copy.obj.addedToCopy should be equal to original.obj.addedToCopy (true expected): ' + 
            (copy.obj.addedToCopy === set4.obj.addedToCopy);
 
    Y.log(msg);
    result.setContent('' + msg + '
');
};


Для "глубоких" копий нужно использовать clone.

Комментариев нет:

Отправить комментарий