4

[JSFIDDLE]

The code works perfectly in every browser except Safari:

enter image description here

For unknown reason Safari can't dynamically change the input type to file.

First of all: why this happening?

And then, is there any workaroud to perform dynamically changing the input type to file in Safari?

Limon Monte
  • 44,025
  • 43
  • 163
  • 189

1 Answers1

5

I've only seen this problem on Safari and old versions of IE. Regarding the reason, I've never found anything documented on this matter.

At one point, jQuery itself was disabling changes on the type attribute for an input because it was causing problems in IE. It was documented as:

// We can't allow the type property to be changed (since it causes problems in IE)
if ( name == "type" && jQuery.nodeName( elem, "input" ) && elem.parentNode )
  throw "type property can't be changed";

You can find more informations regarding this issue in this question.

Nowadays, it seems to no longer be the case but Safari is still silently failing when changing the type to file. On the other hand, changing it from file works without any problem. Since this is not documented, I've always assumed it was for "security" measures but I've never found any concrete evidence.

The workaround I'm using is to detect when the new type will be file and in this special case, create a new input element, set its type to file, set its id and replace the existing input with the new one.

var input = $('#input');

$('button[id^=type-]').on('click', function() {
  var type = $(this).attr('id').replace('type-', '');

  if (type === 'file') {
    var newElement = document.createElement('input');
    newElement.type = type;
    newElement.id = input.attr('id');

    input.replaceWith(newElement);
    input = $('#input');
  } else {
    input.attr('type', type);
  }

  $('#debug-info').html(
    'Trying to change the input type to <strong>' + type + '</strong>.<br>' +
    'Actual input type is <strong>' + input.attr('type') + '<strong>.'
  );

  if (type == input.attr('type')) {
    $('#debug-info').css('color', 'green');
  } else {
    $('#debug-info').css('color', 'red');
  }
});

You can check it in this fiddle.

Community
  • 1
  • 1
HiDeo
  • 9,900
  • 8
  • 40
  • 43
  • Great answer @HiDeo! – Limon Monte Jul 24 '16 at 11:28
  • My guess regarding the security issues is that it might give someone the ability to set the value of the input to a filename in the OS of the user, and on submit that file will be uploaded to the server without the user know it, however this is only a wild guess and not something that 1 line of code (in the browser's source) cannot fix. – Dekel Jul 24 '16 at 12:18