2010-11-11 10 views
16

CZĘŚĆ A:HTML5 Type Detection i Plugin Inicjalizacja

Wiem, że istnieje wiele rzeczy, które obecnie nie powiedzą Ci czy przeglądarka obsługuje pewną cechę HTML5, na przykład http://diveintohtml5.info/detect.html, ale don” t powiedzieć, jak uzyskać typ z poszczególnych elementów i użyć tych informacji, aby zainicjować wtyczki.

Tak próbowałem:

alert($("input:date")); 
//returns "[object Object]" 

alert($("input[type='date']")); 
//returns "[object Object]" 

alert($("input").attr("type")); 
//returns "text" ... which is a lie. it should have been "date" 

Brak tych pracował.

I w końcu wpadł na to (to działa):

var inputAttr = $('<div>').append($(this).clone()).remove().html().toLowerCase(); 
alert(inputAttr); 
// returns "<input min="-365" max="365" type="date">" 

podziękowań: http://jquery-howto.blogspot.com/2009/02/how-to-get-full-html-string-including.html

więc moje pierwsze pytanie: 1. Dlaczego nie mogę odczytać atrybut "Typ" w przeglądarkach, które nie obsługują html5? Możesz wymyślić dowolny inny atrybut i fałszywą wartość i przeczytać go. 2. Dlaczego moje rozwiązanie działa? Dlaczego ma to znaczenie, jeśli jest w DOM, czy nie?

CZĘŚĆ B:

Poniżej jest podstawowym przykładem tego, co używam detektor dla:

<script type="text/javascript" > 
    $(function() { 
    var tM = document.createElement("input"); 
    tM.setAttribute("type", "date"); 
     if (tM.type == "text") { 
      alert("No date type support on a browser level. Start adding date, week, month, and time fallbacks"); 
     // Thanks: http://diveintohtml5.ep.io/detect.html 

      $("input").each(function() { 
       // If we read the type attribute directly from the DOM (some browsers) will return unknown attributes as text (like the first detection). Making a clone allows me to read the input as a clone in a variable. I don't know why. 
       var inputAttr = $('<div>').append($(this).clone()).remove().html().toLowerCase(); 

        alert(inputAttr); 

        if (inputAttr.indexOf("month") !== -1) 

        { 
         //get HTML5 attributes from element 
         var tMmindate = $(this).attr('min'); 
         var tMmaxdate = $(this).attr('max'); 
         //add datepicker with attributes support and no animation (so we can use -ms-filter gradients for ie) 
         $(this).datepick({ 
          renderer: $.datepick.weekOfYearRenderer, 
          onShow: $.datepick.monthOnly, 
          minDate: tMmindate, 
          maxDate: tMmaxdate, 
          dateFormat: 'yyyy-mm', 
          showAnim: ''}); 
        } 
        else 
        { 

         $(this).css('border', '5px solid red'); 
         // test for more input types and apply init to them 
        } 

       });   
      } 
     }); 

     </script> 

żywo przykład: http://joelcrawfordsmith.com/sandbox/html5-type-detection.html

I przysługę/pytanie: Can Czy ktoś pomógł mi odciąć trochę tłuszczu w moim fixerze typu HTML5?

mam funkcjonalność w dół (dodaje fallbacks do IE6-IE8 i FF z obecnie dodawania klas init off)

Czy istnieją bardziej efektywne metody iteracji nad DOM dla typów wejść tajemnica? I czy powinienem używać If If, lub funkcji, lub przypadku w moim przykładzie?

Dzięki wszystkim,

Joel

Odpowiedz

3

Atrybut type nie jest "made-up" elementem, jest zdefiniowane tutaj:

http://www.w3.org/TR/REC-html40/interact/forms.html#h-17.4

... i przeglądarek tylko " wiedzieć "o zdefiniowanych tam wartościach @ty (chyba że są one świadome HTML5 - które zdefiniowały pewne nowe wartości, takie jak" data "," e-mail "itp.)

Kiedy wyszukujesz atrybut type, niektóre przeglądarki zwracają ci "tekst", ponieważ jeśli przeglądarka nie obsługuje typu "date" (lub czegokolwiek, czego nie rozumie), to powraca do wartości domyślnej - która jest typem = "text"

Czy myślisz o dodaniu nazwy klasy (class = "date") do danych wejściowych, a następnie możesz po prostu $ (". date"). each(), a następnie wykrywasz na tym zestawie

+0

Och, oczywiście! Nie chcę sugerować, że atrybut typu nie jest prawdziwy. Pytałem, dlaczego nie można zwrócić wartości typu w taki sam sposób, w jaki można zwrócić utworzony atrybut. –

+0

Myślałem o dodaniu klasy, ale chciałem mieć awarię, która była kompleksowa. –

1

Nie można uzyskać typu = "date" w przeglądarce, która tego nie obsługuje.Jeśli przeglądarka wykryje atrybut typu, którego nie rozumie, zastępuje go typem "tekst" (domyślnie).

Sposób obejścia tego (przy użyciu jQuery) polega po prostu na dodaniu daty klasy.

Następnie można zrobić coś takiego

$('input.date').each(function() { 
    var $this = $(this); 
    if($this.attr('type') != 'date') $this.datepicker(); 
}); 
+1

Rzeczywiście można uzyskać atrybut typu w jQuery, o czym jest mój post i co dowodzi. Miałem nadzieję, że ktoś może wyjaśnić, dlaczego musimy wykonać sztuczki, aby odczytać atrybut typu. –

+0

To nie jest "otrzymywanie" tego typu, to otrzymywanie oryginalnego html i "patrzenie" na typ. Nie możesz o to zapytać. – Alxandr

+0

Myślę, że możesz się mylić. W IE11 na pulpicie i telefonie otrzymuję "date" zwróconą przez użycie jQuery do pobrania typu danych wejściowych, ale żadna z nich nie oferuje dostarczonego z platformy wyboru daty. –

27

Przede wszystkim zaprzestać używania alert zrobić swoją debugowania! Złap kopię Firebug i FireQuery i użyj zamiast tego tych z console.log(). Nawet jeśli pracujesz z alert(), naprawdę powinieneś używać $("input[type='date']").length, aby znaleźć, czy selektor zwrócił cokolwiek - object [object] nie mówi ci nic przydatnego tutaj.


znacznie lepszy sposób wykrywania obsługiwanych typów wejściowych jest po prostu utworzyć element wejściowy i pętlę za pośrednictwem wszystkich różnych typów wejściowych dostępnych i sprawdzić, czy kije type zmiana:

var supported = { date: false, number: false, time: false, month: false, week: false }, 
    tester = document.createElement('input'); 

for (var i in supported){ 
    try { 
     tester.type = i; 
     if (tester.type === i){ 
      supported[i] = true; 
     } 
    } catch (e) { 
     // IE raises an exception if you try to set the type to 
     // an invalid value, so we just swallow the error 
    } 
} 

To rzeczywiście korzysta z tego, że przeglądarki, które nie obsługują tego typu danych wejściowych, będą korzystać z tekstu, co pozwoli na sprawdzenie, czy są one obsługiwane.

Można na przykład użyć numeru supported['week'], aby sprawdzić dostępność typu wejściowego week i wykonać operacje awaryjne. Zobacz prosty pokaz tego tutaj: http://www.jsfiddle.net/yijiang/r5Wsa/2/. Możesz także rozważyć użycie Modernizr dla bardziej niezawodnego wykrywania funkcji HTML5.


I wreszcie, lepszy sposób, aby uzyskać outerHTML jest, wierzcie lub nie, użyj outerHTML. Zamiast

var inputAttr = $('<div>').append($(this).clone()).remove().html().toLowerCase(); 

Dlaczego nie wystarczy użyć:

var inputAttr = this.outerHTML || new XMLSerializer().serializeToString(this); 

(Tak, jak widać, jest pewien wyjątek - outerHTML nie jest obsługiwana przez Firefoksa, więc będziemy potrzebować proste obejście, od this Stack Overflow question).


Edit: Znaleziony sposób wykonać test dla natywnego wsparcia forma UI, z tej strony: http://miketaylr.com/code/html5-forms-ui-support.html. Przeglądarki obsługujące interfejs użytkownika dla tych typów w jakiś sposób powinny również zapobiec nieprawidłowe wartości z już weszła w tych dziedzinach, więc logicznym rozszerzeniem testu robimy powyżej byłoby to:

var supported = {date: false, number: false, time: false, month: false, week: false}, 
    tester = document.createElement('input'); 

for(var i in supported){ 
    tester.type = i; 
    tester.value = ':('; 

    if(tester.type === i && tester.value === ''){ 
     supported[i] = true; 
    } 
} 

Ponownie, nie jest w 100% niezawodny - jest to dobre tylko dla typów, które mają pewne ograniczenia co do ich wartości, i zdecydowanie niezbyt dobre, ale jest to krok we właściwym kierunku iz pewnością rozwiąże problem teraz.

Zobacz zaktualizowany demo tutaj: http://www.jsfiddle.net/yijiang/r5Wsa/3/

+0

Dziękujemy za szczegółową odpowiedź! Dostarczył on bardzo przydatnych informacji, które pomogłyby mi zwiększyć wydajność skryptu, wykorzystując więcej JS zamiast jQuery.Dokładnie rodzaju informacji, których szukałem. Czy możesz podać mi jakieś wyjaśnienia dotyczące kilku przedmiotów? W jaki sposób przykład kodu wykrywania typu wejściowego zezwala starszym przeglądarkom na nieobsługiwane wartości atrybutów typu HTML5? To jest mój cel. wydajne wykrywanie nieobsługiwanych wartości .... nie tylko wykrywanie wsparcia (jak robi Modernizr). Być może błędnie interpretuję ten cel dotyczący próbek. Dzięki jeszcze raz! –

+0

@Joel To nie próbuje emulować zachowania dla starszej przeglądarki, ponieważ ta część została wykonana poprawnie. To część wykrywania cech, która moim zdaniem jest problematyczna - wiem, że próbujesz użyć selektora atrybutu do tego, ale w rzeczywistości ogólnie rzecz biorąc istnieje lepszy identyfikator dla tych elementów formularza - na przykład "id", który jest wymagany dla ' etykiety do pracy. Parsowanie HTML elementu 'input' jest tutaj bardzo brudnym rozwiązaniem. –

+0

To dość ironia, że ​​kod używany do wykrywania funkcji moderatora nie działa, jeśli przeglądarka nie obsługuje nowoczesnych funkcji przeglądarki (var ... in .. syntax). Skrzypce nie działa na IE 11, który obsługuje datę wejścia ... –

3

Uważam, że jest to błąd w JQuery! Jeśli spojrzysz na funkcję attr() w samym kodzie JQuery, JQuery najpierw spróbuje uzyskać wartość dla nazwy, którą przekazałeś używając notacji nawiasów. Jeśli nie jest niezdefiniowana, zwraca tę wartość. Jeśli jest niezdefiniowana, używa zamiast tego metody getAttribute().

Jquery robi coś podobnego do tego na $ ("# Elem") attr (name).

if (elem[ name ] !== undefined) 
{ 
    return elem[name]; 
} 
else 
{ 
    return elem.getAttribute(name) 
} 

Problemem jest jQuery jest przy założeniu, jeśli elem [nazwa] nie jest zdefiniowana, wówczas Elem [ nazwa] jest poprawna.

Rozważmy następujący przykład:

<input type="date" id="myInput" name="myInput" joel="crawford" />  

var myInput = document.getElementById('myInput'); 

alert(myInput['type']);//returns text  
alert(myInput.getAttribute('type'));//returns date 
alert($("#myInput").attr('type'));//returns text 

alert(myInput['joel']);//returns undefined 
alert(myInput.getAttribute('joel'));//returns crawford 
alert($("#myInput").attr('joel'));//returns crawford 

Po przejechaniu w .attr ("typ"), myInput [ 'typu'] zwraca "tekst", więc Jquery powraca "tekst". Jeśli przeszedłeś w .attr ("joel"), myInput ['joel'] zwraca undefined, więc Jquery zamiast tego używa getAttribute ("joel"), który zwraca "crawford".

7

Pytanie o atrybut typu nie działa we wszystkich przeglądarkach giełdowych systemu Android. Udają, że obsługują inputType = "date", ale nie oferują interfejsu użytkownika (np. Datepicker) dla danych wejściowych.

Ta funkcja wykrywania pracował dla mnie:

(function() { 
     var el = document.createElement('input'), 
      notADateValue = 'not-a-date'; 
     el.setAttribute('type','date'); 
     el.setAttribute('value', notADateValue); 
     return el.value !== notADateValue; 
    })(); 

Sztuką jest, aby ustawić niedozwoloną wartość w polu data. Jeśli przeglądarka usunie to wejście, może również zaoferować datepicker.

0

Po prostu tester.type = i; zgłasza wyjątek w IE. Poprawiona wersja:

var get_supported_html5_input_types = function() { 
 
    var supported = { 
 
      date: false, 
 
      number: false, 
 
      time: false, 
 
      datetime: false, 
 
      'datetime-local':false, 
 
      month: false, 
 
      week: false 
 
     }, 
 
     tester = document.createElement('input'); 
 
    for(var i in supported){ 
 
     // Do nothing - IE throws, FF/Chrome just ignores 
 
     try { tester.type = i; } catch (err) {} 
 
     if(tester.type === i){ 
 
      supported[i] = true; 
 
     } 
 
    } 
 
    return supported; 
 
}; 
 

 
console.log(get_supported_html5_input_types());

Test Zawsze, nigdy ślepo kopiować, wklejać!

0

Oto skrypt jQuery, który wykrywa czy przeglądarka obsługuje format HTML5 date, a jeśli tak, to zmienia wszystkie date wartości pól do formatu yyyy-mm-dd i wszystkie datetime wartości pól do formatu yyyy-mm-dd hh:mm:ss.

// From https://stackoverflow.com/a/10199306 
// If the browser supports HTML5 input type="date", change all the values from y/m/dddd format to yyyy-mm-dd format, so they appear properly: 
function fix_date_inputs() { 
    try { 
     var input = document.createElement('input'); 
     input.setAttribute('type','date'); 

     var notADateValue = 'not-a-date'; 
     input.setAttribute('value', notADateValue); 

     var r = (input.value !== notADateValue); 

     if (r) { 
      $('input').each(function() { 
       if (
        $(this).attr('type').match(/^date/) // date or datetime 
       ) { 
        var m_d_y = $(this).context.attributes.value.value; // Because $(this).val() does not work (returns '') 

        var d = new Date(m_d_y); 

        var month = '' + (d.getMonth() + 1); 
        var day = '' + d.getDate(); 
        var year = d.getFullYear(); 

        if (month.length < 2) month = '0' + month; 
        if (day.length < 2) day = '0' + day; 

        var yyyy_mm_dd = [ year, month, day ].join('-'); 

        // If we're processing a datetime, add the time: 
        if (
         $(this).attr('type') == 'datetime' 
        ) { 
         var h = '' + d.getHours(); 
         var i = '' + d.getMinutes(); 
         var s = '' + d.getSeconds(); 

         if (h.length < 2) h = '0' + h; 
         if (i.length < 2) i = '0' + i; 
         if (s.length < 2) s = '0' + s; 

         yyyy_mm_dd += ' ' + [ h, i, s ].join(':'); 
        } 

        $(this).val(yyyy_mm_dd); // Here, val() works to set the new value. Go figure. 
       } 
      }); 

     } 
    } catch(e) { 
     alert('Internal error: ' + e.message); 
    } 
} 
Powiązane problemy