Создание методов на лету

Привет я пытаюсь создать плагин jQuery, и у меня должны быть методы, доступные для элементов после того, как они инициализируются как такой объект, например:

$('.list').list({some options}); //This initializes .list as a list

//now I want it to have certain methods like:
$('.list').find('List item'); //does some logic that I need

Я попробовал

$.fn.list = function (options) {
    return this.each(function() {
        // some code here
        this.find = function(test) {
            //function logic
        }
    }
}

и несколько других различных попыток, я просто не могу выяснить, как сделать это.

Править:

Я попытаюсь объяснить это лучше.

Я пытаюсь превратить таблицу в список, в основном как список на компьютере с заголовками столбцов и поддающимися сортировке объектами и всем промежуточным. Вы инициируете таблицу с командой как

$(this).list({
    data: [{id: 1, name:'My First List Item', date:'2010/06/26'}, {id:2, name:'Second', date:'2010/05/20'}]
});

.list сделает <tbody> поддающийся сортировке и делают несколько других начальных задач, затем добавляют следующие методы к элементу:
.findItem(condition) позволит Вам находить определенный объект условием (как findItem('name == "Second"')
.list(condition) перечислит все объекты, которые соответствуют данному условию
.sort(key) отсортирует все объекты по данному ключу
и т.д.

Что лучший способ состоит в том, чтобы пойти о выполнении этого?

10
задан Rob 26 June 2010 в 22:58
поделиться

3 ответа

Я нашел вот это решение: http://www.virgentech.com/blog/2009/10/building-object-oriated-jquery-plugin.html

Кажется, это именно то, что мне нужно.

(function($) {
    var TaskList = function(element, options)
    {
        var $elem = $(element);
        var options = $.extend({
            tasks: [],
            folders: []
        }, options || {});

        this.changed = false;
        this.selected = {};

        $elem.sortable({
            revert: true,
            opacity: 0.5
        });

        this.findTask = function(test, look) {
            var results = [];

            for (var i = 0,l = options.tasks.length; i < l; i++)
            {
                var t = options['tasks'][i];
                if (eval(test))
                {
                    results.push(options.tasks[i]);
                }
            }
            return results;
        }

        var debug = function(msg) {
            if (window.console) {
                console.log(msg);
            }
        }
    }

    $.fn.taskList = function(options)
    {
        return this.each(function() {
            var element = $(this);

            if (element.data('taskList')) { return; }

            var taskList = new TaskList(this, options);

            element.data('taskList', taskList);

        });
    }

})(jQuery);

Затем у меня есть

    $('.task-list-table').taskList({
        tasks: eval('(<?php echo mysql_real_escape_string(json_encode($tasks)); ?>)'),
        folders: eval('(<?php echo mysql_real_escape_string(json_encode($folders)); ?>)')
    });
    var taskList = $('.task-list-table').data('taskList');

, и я могу использовать taskList.findTask (condition);

А поскольку в конструкторе есть $ elem , я также могу редактировать экземпляр jQuery для таких методов, как список (условие) и т. Д. Работает отлично.

2
ответ дан 4 December 2019 в 04:01
поделиться

this.each не требуется. Это должно сделать:

$.fn.list = function (options) {
    this.find = function(test) {
        //function logic
    };
    return this;
};

Обратите внимание, что вы перезаписываете собственный метод jQuery find , и делать это не рекомендуется.


Кроме того, как бы то ни было, я не думаю, что это хорошая идея. Предполагается, что экземпляры jQuery имеют только методы, унаследованные от объекта-прототипа jQuery, и поэтому я чувствую, что то, что вы хотите сделать, не будет согласовываться с общепринятым поведением плагина jQuery, т.е. вернуть объект this ( экземпляр jQuery) без изменений.

0
ответ дан 4 December 2019 в 04:01
поделиться

Если вы хотите, чтобы эти методы были доступны для любого объекта jQuery, вам нужно будет добавить каждый из них в прототип jQuery. Причина в том, что каждый раз, когда вы вызываете $ (". List") , создается новый новый объект, и любые методы, которые вы прикрепили к предыдущему такому объекту, будут потеряны.

Назначьте каждый метод прототипу jQuery следующим образом:

jQuery.fn.extend({
    list: function() { .. },
    findItem: function() { .. },
    sort: function() { .. }
});

Метод list здесь особенный, поскольку его можно вызвать в двух случаях. Во-первых, при инициализации списка, а во-вторых, при поиске определенных элементов по условию. Вам придется как-то различать эти два случая - либо по типу аргумента, либо по другому параметру.

Вы также можете использовать data API, чтобы генерировать исключение, если эти методы вызываются для объекта, который не был инициализирован с помощью плагина списка. При первом вызове ('xyz'). List ({..}) сохраните некоторую переменную состояния в кэше данных для этого объекта. Когда позже вызывается любой из других методов - «list», «findItem» или «sort», проверьте, содержит ли объект эту переменную состояния в своем кэше данных.

Лучшим подходом было бы пространство имен вашего плагина, чтобы list () возвращал расширенный объект. По возвращаемому значению можно вызвать три расширенных метода. Интерфейс будет иметь вид:

$('selector').list({ ... });
$('selector').list().findOne(..);
$('selector').list().findAll(..);
$('selector').list().sort();

Или сохраните ссылку на возвращенный объект в первый раз и вызовите методы для него напрямую.

var myList = $('selector').list({ ... });
myList.findOne(..);
myList.findAll(..);
myList.sort();
2
ответ дан 4 December 2019 в 04:01
поделиться
Другие вопросы по тегам:

Похожие вопросы: