2013-07-19 3 views
7

Это разметка я использую:Polyfill HTML5 атрибут формы (для поля ввода)

<input type="text" form="myform" name="inp1" /> 
<form id="myform" name="myform"> 
    ...   
</form> 

Теперь я понял, что это не работает для старых IE и поэтому я искал HTML 5 polyfill.

Кто-нибудь знает о каком-то полиполке, который покрывает эту функцию HTML5?

+0

Невозможно поползть, если есть ajax и логика до/после, которая не запускается непосредственно с .submit(). Я потратил час или около того, чтобы понять, что быстрее будет делать onClick() во всем проекте вместо polyfilling form = id. –

ответ

1

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

http://afarkas.github.io/webshim/demos/demos/webforms.html

+1

Новые URL-адреса: http://afarkas.github.io/webshim/demos/#Forms и http://afarkas.github.io/webshim/demos/demos/forms.html –

+2

Я не нашел решения, подходящего для вопрос в нем ... – CodeColorist

12

Я написал эту polyfill эмулировать такую ​​функцию путем дублирования полей на форме представления, испытанное в IE6, и она работала отлично.

(function($) { 
    /** 
    * polyfill for html5 form attr 
    */ 

    // detect if browser supports this 
    var sampleElement = $('[form]').get(0); 
    var isIE11 = !(window.ActiveXObject) && "ActiveXObject" in window; 
    if (sampleElement && window.HTMLFormElement && (sampleElement.form instanceof HTMLFormElement || sampleElement instanceof window.HTMLFormElement) && !isIE11) { 
    // browser supports it, no need to fix 
    return; 
    } 

    /** 
    * Append a field to a form 
    * 
    */ 
    $.fn.appendField = function(data) { 
    // for form only 
    if (!this.is('form')) return; 

    // wrap data 
    if (!$.isArray(data) && data.name && data.value) { 
     data = [data]; 
    } 

    var $form = this; 

    // attach new params 
    $.each(data, function(i, item) { 
     $('<input/>') 
     .attr('type', 'hidden') 
     .attr('name', item.name) 
     .val(item.value).appendTo($form); 
    }); 

    return $form; 
    }; 

    /** 
    * Find all input fields with form attribute point to jQuery object 
    * 
    */ 
    $('form[id]').submit(function(e) { 
    // serialize data 
    var data = $('[form='+ this.id + ']').serializeArray(); 
    // append data to form 
    $(this).appendField(data); 
    }).each(function() { 
    var form = this, 
     $fields = $('[form=' + this.id + ']'); 

    $fields.filter('button, input').filter('[type=reset],[type=submit]').click(function() { 
     var type = this.type.toLowerCase(); 
     if (type === 'reset') { 
     // reset form 
     form.reset(); 
     // for elements outside form 
     $fields.each(function() { 
      this.value = this.defaultValue; 
      this.checked = this.defaultChecked; 
     }).filter('select').each(function() { 
      $(this).find('option').each(function() { 
      this.selected = this.defaultSelected; 
      }); 
     }); 
     } else if (type.match(/^submit|image$/i)) { 
     $(form).appendField({name: this.name, value: this.value}).submit(); 
     } 
    }); 
    }); 


})(jQuery); 
+2

Я добавил это в список [многочислений] [список модернизированных] (https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-Browser-Polyfills#web-forms). –

+0

@HughGuiney Спасибо! – CodeColorist

+0

Часть '' $ ('[form]'). Get (0) .form'' в первой строке кода может поднять «Невозможно прочитать свойство« формы »неопределенной« ошибки, если '' .get (0) '' возвращает undefined.Я сохранил '' $ ('[form]') '' в переменной и возвратил, если этот .length был 0. –

1

Потребуется некоторое время, чтобы отправить обновление для этого полинаполнения, потому что оно не работает с MS Edge.

добавить 2 строки, чтобы исправить это:

 var isEdge = navigator.userAgent.indexOf("Edge"); 
     if (sampleElement && window.HTMLFormElement && sampleElement.form instanceof HTMLFormElement && !isIE11 && isEdge == -1) { 
     // browser supports it, no need to fix 
     return; 
     } 
+1

Было бы лучше, если бы у нас был полиполк, который использовал обнаружение функции, хотя, поскольку Edge, вероятно, поддержит его в будущем. – patstuart

4

polyfill выше, не принимать во внимание пограничный браузер. Я изменил его, чтобы использовать обнаружение функции, которое я тестировал в IE7 +, Edge, Firefox (мобильный/рабочий стол), Chrome (мобильный/рабочий стол), Safari (мобильный/рабочий) и Android-браузер 4.0.

(function($) { 
    /** 
    * polyfill for html5 form attr 
    */ 

    // detect if browser supports this 
    var SAMPLE_FORM_NAME = "html-5-polyfill-test"; 
    var sampleForm = $("<form id='" + SAMPLE_FORM_NAME + "'/>"); 
    var sampleFormAndHiddenInput = sampleForm.add($("<input type='hidden' form='" + SAMPLE_FORM_NAME + "'/>"));  
    sampleFormAndHiddenInput.prependTo('body'); 
    var sampleElementFound = sampleForm[0].elements[0]; 
    sampleFormAndHiddenInput.remove(); 
    if (sampleElementFound) { 
     // browser supports it, no need to fix 
     return; 
    } 

    /** 
    * Append a field to a form 
    * 
    */ 
    $.fn.appendField = function(data) { 
     // for form only 
     if (!this.is('form')) return; 

     // wrap data 
     if (!$.isArray(data) && data.name && data.value) { 
     data = [data]; 
     } 

     var $form = this; 

     // attach new params 
     $.each(data, function(i, item) { 
     $('<input/>') 
      .attr('type', 'hidden') 
      .attr('name', item.name) 
      .val(item.value).appendTo($form); 
     }); 

     return $form; 
    }; 

    /** 
    * Find all input fields with form attribute point to jQuery object 
    * 
    */ 
    $('form[id]').submit(function(e) { 
     // serialize data 
     var data = $('[form='+ this.id + ']').serializeArray(); 
     // append data to form 
     $(this).appendField(data); 
    }).each(function() { 
     var form = this, 
     $fields = $('[form=' + this.id + ']'); 

     $fields.filter('button, input').filter('[type=reset],[type=submit]').click(function() { 
     var type = this.type.toLowerCase(); 
     if (type === 'reset') { 
      // reset form 
      form.reset(); 
      // for elements outside form 
      $fields.each(function() { 
      this.value = this.defaultValue; 
      this.checked = this.defaultChecked; 
      }).filter('select').each(function() { 
      $(this).find('option').each(function() { 
       this.selected = this.defaultSelected; 
      }); 
      }); 
     } else if (type.match(/^submit|image$/i)) { 
      $(form).appendField({name: this.name, value: this.value}).submit(); 
     } 
     }); 
    }); 


    })(jQuery); 
+2

Спасибо, он отлично работает. Я надеюсь, что это получит больше голосов – monxas

1

я улучшил polyfill patstuart, такое, что:

  • форма теперь могут быть представлены несколько раз, например, При использовании целевого атрибута (внешние поля были дублированы ранее)

  • кнопки сброса теперь работает должным образом

Здесь:

(function($) { 
/** 
* polyfill for html5 form attr 
*/ 

// detect if browser supports this 
var SAMPLE_FORM_NAME = "html-5-polyfill-test"; 
var sampleForm = $("<form id='" + SAMPLE_FORM_NAME + "'/>"); 
var sampleFormAndHiddenInput = sampleForm.add($("<input type='hidden' form='" + SAMPLE_FORM_NAME + "'/>"));  
sampleFormAndHiddenInput.prependTo('body'); 
var sampleElementFound = sampleForm[0].elements[0]; 
sampleFormAndHiddenInput.remove(); 
if (sampleElementFound) { 
    // browser supports it, no need to fix 
    return; 
} 

/** 
* Append a field to a form 
* 
*/ 
var CLASS_NAME_POLYFILL_MARKER = "html-5-polyfill-form-attr-marker"; 
$.fn.appendField = function(data) { 
    // for form only 
    if (!this.is('form')) return; 

    // wrap data 
    if (!$.isArray(data) && data.name && data.value) { 
    data = [data]; 
    } 

    var $form = this; 

    // attach new params 
    $.each(data, function(i, item) { 
    $('<input/>') 
     .attr('type', 'hidden') 
     .attr('name', item.name) 
     .attr('class', CLASS_NAME_POLYFILL_MARKER) 
     .val(item.value).appendTo($form); 
    }); 

    return $form; 
}; 

/** 
* Find all input fields with form attribute point to jQuery object 
* 
*/ 
$('form[id]').submit(function(e, origSubmit) { 
    // clean up form from last submit 
    $('.'+CLASS_NAME_POLYFILL_MARKER, this).remove(); 
    // serialize data 
    var data = $('[form='+ this.id + ']').serializeArray(); 
    // add data from external submit, if needed: 
    if (origSubmit && origSubmit.name) 
    data.push({name: origSubmit.name, value: origSubmit.value}) 
    // append data to form 
    $(this).appendField(data); 
}) 

//submit and reset behaviour 
$('button[type=reset], input[type=reset]').click(function() { 
    //extend reset buttons to fields with matching form attribute 
    // reset form 
    var formId = $(this).attr("form"); 
    var formJq = $('#'+formId); 
    if (formJq.length) 
    formJq[0].reset(); 
    // for elements outside form 
    if (!formId) 
    formId = $(this).closest("form").attr("id"); 
    $fields = $('[form=' + formId + ']'); 
    $fields.each(function() { 
    this.value = this.defaultValue; 
    this.checked = this.defaultChecked; 
    }).filter('select').each(function() { 
    $(this).find('option').each(function() { 
     this.selected = this.defaultSelected; 
    }); 
    }); 
}); 
$('button[type=submit], input[type=submit], input[type=image]').click(function() { 
    var formId = $(this).attr("form") || $(this).closest("form").attr("id"); 
    $('#'+formId).trigger('submit', this); //send clicked submit as extra parameter 
}); 

}) (Jquery);

0

Я сделал ванильный JavaScript-полиполк на основе вышеуказанных полиполков и загрузил его на GitHub: https://github.com/Ununnilium/form-attribute-polyfill. Я также добавил пользовательское событие для обработки дела, когда submit обрабатывается JavaScript, а не напрямую браузером. Я проверил код только в IE 11, поэтому, пожалуйста, проверьте его перед использованием. Вероятно, опрос должен быть заменен более эффективной функцией обнаружения.

function browserNeedsPolyfill() { 
    var TEST_FORM_NAME = "form-attribute-polyfill-test"; 
    var testForm = document.createElement("form"); 
    testForm.setAttribute("id", TEST_FORM_NAME); 
    testForm.setAttribute("type", "hidden"); 
    var testInput = document.createElement("input"); 
    testInput.setAttribute("type", "hidden"); 
    testInput.setAttribute("form", TEST_FORM_NAME); 
    testForm.appendChild(testInput); 
    document.body.appendChild(testInput); 
    document.body.appendChild(testForm); 
    var sampleElementFound = testForm.elements.length === 1; 
    document.body.removeChild(testInput); 
    document.body.removeChild(testForm); 
    return !sampleElementFound; 
} 

// Ideas from jQuery form attribute polyfill https://stackoverflow.com/a/26696165/2372674 
function executeFormPolyfill() { 
    function appendDataToForm(data, form) { 
     Object.keys(data).forEach(function(name) { 
      var inputElem = document.createElement("input"); 
      inputElem.setAttribute("type", "hidden"); 
      inputElem.setAttribute("name", name); 
      inputElem.value = data[name]; 
      form.appendChild(inputElem); 
     }); 
    } 

    var forms = document.body.querySelectorAll("form[id]"); 
    Array.prototype.forEach.call(forms, function (form) { 
     var fields = document.querySelectorAll('[form="' + form.id + '"]'); 
     var dataFields = []; 
     Array.prototype.forEach.call(fields, function (field) { 
      if (field.disabled === false && field.hasAttribute("name")) { 
       dataFields.push(field); 
      } 
     }); 
     Array.prototype.forEach.call(fields, function (field) { 
      if (field.type === "reset") { 
       field.addEventListener("click", function() { 
        form.reset(); 
        Array.prototype.forEach.call(dataFields, function (dataField) { 
         if (dataField.nodeName === "SELECT") { 
          Array.prototype.forEach.call(dataField.querySelectorAll('option'), function (option) { 
           option.selected = option.defaultSelected; 
          }); 
         } else { 
          dataField.value = dataField.defaultValue; 
          dataField.checked = dataField.defaultChecked; 
         } 
        }); 
       }); 
      } else if (field.type === "submit" || field.type === "image") { 
       field.addEventListener("click", function() { 
        var obj = {}; 
        obj[field.name] = field.value; 
        appendDataToForm(obj, form); 
        form.dispatchEvent(eventToDispatch); 
       }); 
      } 
     }); 
     form.addEventListener("submit", function() { 
      var data = {}; 
      Array.prototype.forEach.call(dataFields, function (dataField) { 
       data[dataField.name] = dataField.value; 
      }); 
      appendDataToForm(data, form); 
     }); 
    }); 
} 

// Poll for new forms and execute polyfill for them 
function detectedNewForms() { 
    var ALREADY_DETECTED_CLASS = 'form-already-detected'; 
    var newForms = document.querySelectorAll('form:not([class="' + ALREADY_DETECTED_CLASS + '"])'); 
    if (newForms.length !== 0) { 
     Array.prototype.forEach.call(newForms, function (form) { 
      form.className += ALREADY_DETECTED_CLASS; 
     }); 
     executeFormPolyfill(); 
    } 
    setTimeout(detectedNewForms, 100); 
} 


// Source: https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent 
function polyfillCustomEvent() { 
    if (typeof window.CustomEvent === "function") { 
     return false; 
    } 

    function CustomEvent(event, params) { 
     params = params || {bubbles: false, cancelable: false, detail: undefined}; 
     var evt = document.createEvent('CustomEvent'); 
     evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail); 
     return evt; 
    } 

    CustomEvent.prototype = window.Event.prototype; 
    window.CustomEvent = CustomEvent; 
} 

if (browserNeedsPolyfill()) { 
    polyfillCustomEvent(); // IE is missing CustomEvent 

    // This workaround is needed if submit is handled by JavaScript instead the browser itself 
    // Source: https://stackoverflow.com/a/35155789/2372674 
    var eventToDispatch = new CustomEvent("submit", {"bubbles": true, "cancelable": true}); 
    detectedNewForms(); // Poll for new forms and execute form attribute polyfill for new forms 
}