2010-06-26 14 views
10

Hi Próbuję autorowi plugin jQuery i muszę mieć metod dostępnych dla elementów po ich zainicjowany jako tego rodzaju obiektu, npTworzenie metody w locie

$('.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 

Próbowałem z

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

i kilka innych różnych prób, po prostu nie mogę wymyślić, jak to zrobić.

EDIT:

postaram się wyjaśnić to lepiej.

Próbuję zamienić tabelę na listę, w zasadzie jak listę na komputerze z nagłówkami kolumn i elementami sortowalnymi oraz wszystko pomiędzy nimi. Zainicjować tablicę z poleceniem

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

.list uczyni <tbody> sortable i zrobić kilka innych początkowych zadań, a następnie dodaj następujące metody elementu:
.findItem(condition) pozwoli Ci znaleźć pewien element, warunek (jak findItem('name == "Second"')
.list(condition) wyświetli wszystkie elementy, które pasują do danego stanu
.sort(key) sortuje wszystkie przedmioty przez dany klucz
itp

Jaki jest najlepszy sposób na zrobienie tego?

+1

Czy możesz podać nieco więcej przykładu? Trudno powiedzieć, o co nam chodzi ... i już zrobiono [.find() '] (http://api.jquery.com/find/) :) –

+1

możliwy duplikat [Jak utworzyć jQuery wtyczka z metodami?] (http://stackoverflow.com/questions/1117086/how-to-create-a-jquery-plugin-with-methods) – redsquare

+0

Tytuł jest mylący, to nie są metody tworzone w locie. – Anurag

Odpowiedz

2

znalazłem to rozwiązanie tutaj: http://www.virgentech.com/blog/2009/10/building-object-oriented-jquery-plugin.html

Wydaje się to dokładnie to, czego potrzebuję zrobić.

(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); 

Wtedy mam

$('.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'); 

i mogę używać taskList.findTask(condition);

A ponieważ konstruktor ma $elem Mogę również edytować instancję jQuery metod takich jak list(condition) itp to działa doskonale.

+0

+1 - Podoba mi się to podejście. – Anurag

0

this.each nie jest potrzebny. Należy to zrobić:

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

Zauważ, że chcesz być nadpisywania natywną find metody jQuery, a robi tak nie jest zalecane.


Ponadto, nie wiem, czy to jest dobry pomysł. Przypuszcza się, że instancje jQuery mają tylko metody odziedziczone po prototypowym obiekcie jQuery i jako takie czuję, że to, co chcesz zrobić, nie byłoby zgodne z ogólnie przyjętym zachowaniem wtyczki jQuery - tzn. nie zmieniono obiektu this (instancji jQuery).

+0

Chociaż zgadzam się * zwykle *, nie zawsze tak jest, głównym przykładem, który mogę wymyślić jest wtyczka sprawdzania poprawności ... to wszystko zależy od twoich potrzeb są. –

+0

Próbowałem właśnie to zrobić (zmieniono .find na .findItem) i skończyło się na błędzie $ ('. List-box'). FindItem nie jest funkcją – Rob

+0

Przepraszamy, zapomniałem dodać, że musisz " zwróć to; '... – James

2

Jeśli chcesz, aby te metody były dostępne w dowolnym obiekcie jQuery, musisz dodać każdy z nich do prototypu jQuery. Powodem jest to, że za każdym razem, gdy wywołujesz $(".list"), tworzony jest nowy nowy obiekt i wszelkie metody dołączone do poprzedniego takiego obiektu zostaną utracone.

przypisać każdej metody prototyp jQuery jako:

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

list metoda tutaj jest wyjątkowy, ponieważ może się powoływać na dwóch okazjach. Po pierwsze, podczas inicjowania listy, a po drugie podczas wyszukiwania określonych elementów według warunku. Musiałbyś w jakiś sposób rozróżnić te dwa przypadki - albo według typu argumentu, albo jakiegoś innego parametru.

Można również użyć interfejsu API data, aby wygenerować wyjątek, jeśli metody te są wywoływane dla obiektu, który nie został zainicjowany za pomocą wtyczki listy.Po pierwszym wywołaniu ('xyz').list({ .. }) zapisz pewną zmienną stanu w pamięci podręcznej danych dla tego obiektu. Gdy jakakolwiek inna metoda - "list", "findItem" lub "sort" zostaną później wywołane, sprawdź, czy obiekt zawiera tę zmienną stanu w swojej pamięci podręcznej danych.

Lepszym rozwiązaniem byłoby użycie przestrzeni nazw wtyczki, aby list() zwrócił rozszerzony obiekt. Trzy rozszerzone metody można wywołać na podstawie wartości zwracanej. Interfejs będzie wyglądał następująco:

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

Lub zapisz odniesienie do zwróconego obiektu za pierwszym razem i bezpośrednio na niego nawiąż metody.

var myList = $('selector').list({ ... }); 
myList.findOne(..); 
myList.findAll(..); 
myList.sort(); 
+0

Dzięki za informację, to było naprawdę bardzo pomocne, w końcu zrozumiałem, dlaczego moje metody nie istniały. Nie mogłem zrobić '$ list = $ ('. List') .list ({options});' i użyć listy $ od tego miejsca? W każdym razie znalazłem inne rozwiązanie, zamierzam opublikować to jako odpowiedź. +1, ale dziękuję – Rob

+0

@Rob - Możesz to zrobić, pod warunkiem, że wewnątrz metody 'list' rozszerzysz obiekt jQuery o wszystkie potrzebne funkcje, i od tego momentu powołaj' $ list', aby wywołać te funkcje. To powiedziawszy, myślę, że twoje podejście jest lepsze. – Anurag