Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> Jak zrozumieć wtyczki jQuery?
Adi32
post
Post #1





Grupa: Zarejestrowani
Postów: 348
Pomógł: 26
Dołączył: 8.10.2008
Skąd: Lublin

Ostrzeżenie: (0%)
-----


Witajcie,

Robię różne wtyczki JS między innymi za pomocą takich artykułów:
http://www.altcontroldelete.pl/artykuly/ja...yczki-w-jquery/
ale te moje wtyczki często potrzebują działać niestandardowo a ja nie moge nic zrobić bo nie rozumiem jak to działa...
Szukam po necie jakichś wytłumaczeń ale nic konkretnego nie działa...

Nie widzę w tym żadnej logiki i nawet jak działa to nie wiem dlaczego.

Dziwność zaczyna się w momencie
...return this.each(function() {...

Co do wieloinstancyjności i kłopotach z tym związanych spędziłem dziesiątki godzin...

Znacie może jakiś dobry artykuł na ten tenat w języku polskim? A może ktoś potrafi sam wyjaśnić jak to jest z tymi wtyczkami jQuery....


--------------------
Wolałem języki z rodziny C ale poszedłem na łatwizne...
Go to the top of the page
+Quote Post
 
Start new topic
Odpowiedzi (1 - 6)
iwosz
post
Post #2





Grupa: Zarejestrowani
Postów: 62
Pomógł: 3
Dołączył: 30.07.2009

Ostrzeżenie: (0%)
-----


Cześć,

generalnie według mnie najpierw powinno się nauczyć pisać w jQuery a potem brać za tworzenie pluginów smile.gif wydaje mi się że Ty zacząłeś od tego drugiego i dlatego masz problemy ze zrozumieniem kodu zamieszczonego pod linkiem który podałeś.
Mogę Ci to w skrócie wytłumaczyć ale to Ty sam musisz przysiąść i poćwiczyć korzystanie z jQuery, zachęcam do tego bo warto! wink.gif

Co do tego kodu, przede wszystkim składnia jQuery opiera się na podstawowym obiekcie o takiej samej nazwie, zapisywany skrótowo jako "$". Natomiast każdy plugin to tak na prawdę definicja nowej funkcji która albo rozszerza już istniejące mechanizmy w jQuery ($.extend) albo wprowadza zupełnie nowe. Dlatego definicja tego pluginu zaczyna się od "(function($)", a kończy się zwróceniem obiektu jQuery czyli "(jQuery);".

Kawałek kodu który wymieniłeś
  1. return this.each(function() {...}

zwraca wykonanie funkcji jQuery.each(), w tym przypadku jest to samo co:
  1. this.each(function() {
  2. var oElement = $(this);
  3. oElement.data('myplugin', {
  4. pluginoptions: oOptions
  5. });
  6. // init operations....
  7. initExampleHelperFunction();
  8. if(null != oElement.data('myplugin')
  9. .pluginoptions.ExtraInitFunction){
  10. oElement.data('myplugin').pluginoptions.ExtraInitFunction();
  11. }
  12. });
  13. return;

Zobacz tutaj po polski opis: http://www.i-mateusz.com/news/jak-napisac-...gin-jquery.html polecam też dokumentację jQuery: http://api.jquery.com/

Cytat("Adi32")
Co do wieloinstancyjności i kłopotach z tym związanych spędziłem dziesiątki godzin...
to nie wiem czy dobrze rozumiem, chciałbyś wdrożyć wzorzec Singleton w JS? Może coś takiego:

http://www.dofactory.com/javascript-singleton-pattern.aspx

Ten post edytował iwosz 24.03.2014, 15:41:13


--------------------
Pozdrawiam,

iwosz.
Go to the top of the page
+Quote Post
trueblue
post
Post #3





Grupa: Zarejestrowani
Postów: 6 806
Pomógł: 1828
Dołączył: 11.03.2014

Ostrzeżenie: (0%)
-----


Cytat(Adi32 @ 13.03.2014, 09:44:19 ) *
Dziwność zaczyna się w momencie
...return this.each(function() {...

Jeśli twoja wtyczka nazywa się superWtyczka i wywołasz ją tak:
  1. $(selektor).superWtyczka

to wewnątrz powyższej funkcji, w zmiennej this otrzymasz kolejne elementy, które wybrał selektor.


--------------------
Go to the top of the page
+Quote Post
Adi32
post
Post #4





Grupa: Zarejestrowani
Postów: 348
Pomógł: 26
Dołączył: 8.10.2008
Skąd: Lublin

Ostrzeżenie: (0%)
-----


Dzięki za odpowiedź Panowie.

Napisałem już dość sporo działających wtyczek i innych rzeczy pomocy jQuery także zdaje mi się, że podstawy już znam.

Żeby lepiej pokazać o co mi chodzi napisze co robiłem ostatnio:
Napisałem wtyczkę do jQuery (kod mam w pracy, jutro wrzucę) która nazywa się Validate.

Potrzebowałem aby konkretne pola konkretnych formularzy były walidowane tylko w konkretnych przypadkach dynamicznie.

Ostatecznie działa to tak, że powiedzmy mamy formularz (#loginForm) na stronie z dwoma polami - email, hasło:

  1. oValidate = new Validate('loginForm')
  2. oValidate.add('inputEmail', 'email') // pierwszy parametr to nazwa pola, drugi to typ walidacji, jeśli nie podamy typu walidacji to załaduje się domyślny noEmpty


W tym momencie jeśli spróbujemy dać submit albo blur na inpucie klasa Validate odpala domyślny komunikat przy polu o błędnych danych, dla każdego pola możemy też przypisać konkretny komunikat.

  1. oValidate.remove('inputEmail') // a ta linia powoduje, że pole nie jest już walidowane, sensu niby nie ma ale to tylko przykład. W procesie zamówienia który tworze takie rozwiązanie jest niezbędne.


Problemy zaczęły pojawiać się, gdy na stronie pojawiały się 2 formularze. Mają działać pod klasą Validate bez kolidacji, to właśnie miałem na myśli mówiąc o wielo-instancyjności, czyli raczej odwrotności singletona. Problem wyglądał tak że nie dawało się kliknąć w submit jeśli w którymkolwiek formularzu coś się nie walidowało.

Z tym też sobie poradziłem, ale raczej metodą prób i błędów tworząc kod którego nie rozumiem dlatego postanowiłem założyć ten temat. Wciąż nie rozumiem return this.each... each to jak mniemam pętla po wszystkich "obiektach obiektu" (tak mi się przynajmniej wydaje) także jaki jest sens takiego zapisu? Wierzę , że jak to zrozumiem to zrozumiem i resztę.

Jak mówiłem, wrzucam kod:

  1. (function($) {
  2. var m_oDefaults = {
  3. nTestSetting: 0,
  4. sTestSetting: 'test',
  5. ExtraInitFunction: null,
  6. formName: null
  7. };
  8.  
  9. var initExampleHelperFunction = function(oElement){
  10. self = m_aoFunctions;
  11.  
  12. oElement.find('input').on('blur', function(){
  13. return self.blur($(this).attr('name'), oElement);
  14. });
  15. oElement.find('input[type="submit"]').on('click', function(){
  16. return self.checkAll(oElement);
  17. });
  18.  
  19. };
  20.  
  21. var m_aoFunctions = {
  22.  
  23. init: function(oOptions){
  24. oOptions = $.extend({}, m_oDefaults, oOptions);
  25. return this.each(function() {
  26. var oElement = $(this);
  27. oElement.data('validate', {
  28. pluginoptions: oOptions,
  29. fields: []
  30. });
  31. // init operations....
  32. initExampleHelperFunction(oElement);
  33.  
  34. if(null != oElement.data('validate').pluginoptions.ExtraInitFunction){
  35. oElement.data('validate').pluginoptions.ExtraInitFunction();
  36. }
  37. });
  38. },
  39. myInit: function(formName) {
  40.  
  41. },
  42. option: function(oOptions){
  43. $.extend($(this).data('validate').pluginoptions, oOptions);
  44. },
  45. getTestSettingText: function(){
  46. return $(this).data('validate').pluginoptions.sTestSetting;
  47. },
  48. add: function(fieldName, validationType) {
  49. if (!$('input[name="'+fieldName+'"]').length) return false;
  50. if (typeof validationType == "undefined") validationType = 'noEmpty';
  51.  
  52. this.remove(fieldName); // jakby przypadkiem to pole było już walidowane
  53.  
  54. $(this).data('validate').fields.push({fieldName: fieldName, validationType: validationType, formName: this.formName});
  55. return this;
  56. },
  57. remove: function(name) {
  58. var flds = $(this).data('validate').fields;
  59. for (i in flds) {
  60. if (flds[i].fieldName == name) {
  61. $(this).data('validate').fields.splice(i,1);
  62. console.log('Spliced element: '+i+ ' => '+name)
  63. }
  64. }
  65. },
  66. getFields: function(oElement) {
  67. if (typeof oElement != "undefined")
  68. return oElement.data('validate').fields;
  69. },
  70. blur: function(field,oElement) {
  71.  
  72. this.oElement = oElement;
  73. var f = 0, fields = this.getFields(oElement);
  74.  
  75. for (i in fields) {
  76. if (fields[i].fieldName == field) {
  77. if (!this.check(oElement.data('validate').fields[i].fieldName, oElement.data('validate').fields[i].validationType)) {
  78. f++;
  79. }
  80. }
  81. }
  82. return !f;
  83. },
  84. check: function(fieldName, validationType) {
  85. field = this.oElement.find('input[name="'+fieldName+'"]');
  86. return eval('this.'+validationType+'(field)');
  87. },
  88. checkAll: function(oElement) {
  89. var f = 0, fields = this.getFields(oElement);
  90. this.oElement = oElement;
  91. for (i in fields) {
  92.  
  93. if (!this.check(oElement.data('validate').fields[i].fieldName, oElement.data('validate').fields[i].validationType)) {
  94. f++;
  95. }
  96. }
  97. return !f;
  98. },
  99. isObserved: function(name) {
  100. for (i in oElement.data('validate').fields) {
  101. if (oElement.data('validate').fields[i].fieldName == name) {
  102. return true;
  103. }
  104. }
  105. return false;
  106. },
  107. email: function(field) {
  108.  
  109. self = this;
  110.  
  111. var errorSpan = this.oElement.find('.'+field.attr('name')+'.error-info');
  112.  
  113. var regex = /^[a-zA-Z0-9._-]+@([a-zA-Z0-9.-]+\.)+[a-zA-Z0-9.-]{2,4}$/;
  114.  
  115.  
  116. if ( !regex.test(field.val()) ) {
  117. errorSpan.show();
  118. return false;
  119. } else {
  120. errorSpan.hide();
  121. return true;
  122. }
  123.  
  124. },
  125. password: function(field) {
  126. self = this;
  127.  
  128. var errorSpan = $('.'+field.attr('name')+'.error-info');
  129.  
  130. if ( !field.val().length ) {
  131. errorSpan.show();
  132. return false;
  133. } else {
  134. errorSpan.hide();
  135. return true;
  136. }
  137. },
  138. radio: function(field) {
  139. var errorSpan = $('.deliveryAddress.error-info');
  140.  
  141. if (!field.is(':checked')) {
  142. errorSpan.show();
  143. return false;
  144. } else {
  145. errorSpan.hide();
  146. return true;
  147. }
  148. },
  149. noEmpty: function(field) {
  150. self = this;
  151.  
  152. var errorSpan = $('.'+field.attr('name')+'.error-info');
  153.  
  154. if ( !field.val().length ) {
  155. errorSpan.show();
  156. return false;
  157. } else {
  158. errorSpan.hide();
  159. return true;
  160. }
  161. }
  162. };
  163.  
  164. $.fn.validate = function(oFunction) {
  165.  
  166. if (m_aoFunctions[oFunction]) {
  167. return m_aoFunctions[oFunction].apply(this, Array.prototype.slice.call(arguments, 1));
  168. } else if ((typeof oFunction === 'object') || !oFunction) {
  169. return m_aoFunctions.init.apply(this, arguments);
  170. } else {
  171. $.error('Funkcja ' + oFunction + ' nie istnieje w przestrzenii jQuery.myplugin');
  172. }
  173. };
  174. })(jQuery);


Przykłady użycia:

  1. $validatorAddresses = $('form[name="addresses"]').validate();
  2. $validatorAddresses.validate('add', 'deliveryAddress', 'radio'); // czyli konieczność wyboru któregoś adresu z radio
  3. $validatorAddresses.validate('remove', 'deliveryAddress'); // usuniecie z walidacji


Trochę się to różni od tego co napisałem wczoraj. Coś mi sie widać popieprzyło.

Moje szczere oczekiwania odnośnie tego tematu są takie, że ktoś napisze: "Co żeś napisał, powinieneś to zrobić inaczej"...

Pozdrawiam.

Ten post edytował Adi32 1.04.2014, 20:24:32


--------------------
Wolałem języki z rodziny C ale poszedłem na łatwizne...
Go to the top of the page
+Quote Post
trueblue
post
Post #5





Grupa: Zarejestrowani
Postów: 6 806
Pomógł: 1828
Dołączył: 11.03.2014

Ostrzeżenie: (0%)
-----


Cytat(Adi32 @ 2.04.2014, 13:43:13 ) *
Wciąż nie rozumiem return this.each... each to jak mniemam pętla po wszystkich "obiektach obiektu" (tak mi się przynajmniej wydaje) także jaki jest sens takiego zapisu?

this.each iteruje po wszystkich elementach, które podlegają selektorowi, który to podałeś jako parametr przy inicjalizacji pluginu.
Jeśli Twój plugin wywołasz tak:
  1. new Validate('form')

to pętla obejmie wszystkie formularze w dokumencie,
jeśli tak:
  1. new Validate('form.blabla')

to wszystkie formularze z klasą "blabla".
Wszystko co dotyczy danego elementu musisz deklarować jako zmienną wewnątrz pętli each, a nie jako zmienne globalne. Również opcje musisz sobie kopiować do zmiennej w środku each.


--------------------
Go to the top of the page
+Quote Post
Adi32
post
Post #6





Grupa: Zarejestrowani
Postów: 348
Pomógł: 26
Dołączył: 8.10.2008
Skąd: Lublin

Ostrzeżenie: (0%)
-----


Z Twojej wypowiedzi wnioskuje, że this.each zaprzecza nieco wieloinstancyjności.
Inaczej mówiąc powiedzmy, że wczytuje objekt:
  1. new Validate($('form'))

Zakłądając, że mam dwa formularze na stronie, mogę się spodziewać, że będą ze sobą kolidować.
Idąc tym tokiem myślenia, wychodzi, że problem wieloinstancyjności nie powinien występować w przypadku takiego uruchomienia:
  1. oForm1 = new Validate($('form[name="deliveryAddress"]'));
  2. oForm2 = new Validate($('form[name="invoiceAddress"]'));

questionmark.gif? Dobrze to rozumiem?



--------------------
Wolałem języki z rodziny C ale poszedłem na łatwizne...
Go to the top of the page
+Quote Post
trueblue
post
Post #7





Grupa: Zarejestrowani
Postów: 6 806
Pomógł: 1828
Dołączył: 11.03.2014

Ostrzeżenie: (0%)
-----


Jak to zaprzecza?
Jeśli w this.each będziesz odnosił się do zmiennej "a" zdefiniowanej poza tą pętlą, to przy ustawianiu będziesz ją nadpisywał lub dopisywał do niej (jeśli to tablica), a przy pobieraniu będzie to wspólna zmienna dla każdej iteracji w this.each. Nie ma tu nic magicznego. Każda iteracja this.each wywołuje funkcję. To tak jakbyś deklarował zmienne lokalne w dwóch osobnych funkcjach, albo jedną zmienną globalną i odwoływał się do niej z tych dwóch funkcji.

Co do drugiej kwestii, w takim przypadku, to powinno zapewnić bezkolizyjność.


--------------------
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Aktualny czas: 21.08.2025 - 22:57