GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

Code Duplication    Length = 254-254 lines in 3 locations

third-party/angularjs-modules-plugins/ng-file-upload-12.2.12/demo/src/main/webapp/js/ng-file-upload-all.js 1 location

@@ 1118-1371 (lines=254) @@
1115
  return upload;
1116
}]);
1117
1118
ngFileUpload.directive('ngfSelect', ['$parse', '$timeout', '$compile', 'Upload', function ($parse, $timeout, $compile, Upload) {
1119
  var generatedElems = [];
1120
1121
  function isDelayedClickSupported(ua) {
1122
    // fix for android native browser < 4.4 and safari windows
1123
    var m = ua.match(/Android[^\d]*(\d+)\.(\d+)/);
1124
    if (m && m.length > 2) {
1125
      var v = Upload.defaults.androidFixMinorVersion || 4;
1126
      return parseInt(m[1]) < 4 || (parseInt(m[1]) === v && parseInt(m[2]) < v);
1127
    }
1128
1129
    // safari on windows
1130
    return ua.indexOf('Chrome') === -1 && /.*Windows.*Safari.*/.test(ua);
1131
  }
1132
1133
  function linkFileSelect(scope, elem, attr, ngModel, $parse, $timeout, $compile, upload) {
1134
    /** @namespace attr.ngfSelect */
1135
    /** @namespace attr.ngfChange */
1136
    /** @namespace attr.ngModel */
1137
    /** @namespace attr.ngfModelOptions */
1138
    /** @namespace attr.ngfMultiple */
1139
    /** @namespace attr.ngfCapture */
1140
    /** @namespace attr.ngfValidate */
1141
    /** @namespace attr.ngfKeep */
1142
    var attrGetter = function (name, scope) {
1143
      return upload.attrGetter(name, attr, scope);
1144
    };
1145
1146
    function isInputTypeFile() {
1147
      return elem[0].tagName.toLowerCase() === 'input' && attr.type && attr.type.toLowerCase() === 'file';
1148
    }
1149
1150
    function fileChangeAttr() {
1151
      return attrGetter('ngfChange') || attrGetter('ngfSelect');
1152
    }
1153
1154
    function changeFn(evt) {
1155
      if (upload.shouldUpdateOn('change', attr, scope)) {
1156
        var fileList = evt.__files_ || (evt.target && evt.target.files), files = [];
1157
        /* Handle duplicate call in  IE11 */
1158
        if (!fileList) return;
1159
        for (var i = 0; i < fileList.length; i++) {
1160
          files.push(fileList[i]);
1161
        }
1162
        upload.updateModel(ngModel, attr, scope, fileChangeAttr(),
1163
          files.length ? files : null, evt);
1164
      }
1165
    }
1166
1167
    upload.registerModelChangeValidator(ngModel, attr, scope);
1168
1169
    var unwatches = [];
1170
    if (attrGetter('ngfMultiple')) {
1171
      unwatches.push(scope.$watch(attrGetter('ngfMultiple'), function () {
1172
        fileElem.attr('multiple', attrGetter('ngfMultiple', scope));
1173
      }));
1174
    }
1175
    if (attrGetter('ngfCapture')) {
1176
      unwatches.push(scope.$watch(attrGetter('ngfCapture'), function () {
1177
        fileElem.attr('capture', attrGetter('ngfCapture', scope));
1178
      }));
1179
    }
1180
    if (attrGetter('ngfAccept')) {
1181
      unwatches.push(scope.$watch(attrGetter('ngfAccept'), function () {
1182
        fileElem.attr('accept', attrGetter('ngfAccept', scope));
1183
      }));
1184
    }
1185
    unwatches.push(attr.$observe('accept', function () {
1186
      fileElem.attr('accept', attrGetter('accept'));
1187
    }));
1188
    function bindAttrToFileInput(fileElem, label) {
1189
      function updateId(val) {
1190
        fileElem.attr('id', 'ngf-' + val);
1191
        label.attr('id', 'ngf-label-' + val);
1192
      }
1193
1194
      for (var i = 0; i < elem[0].attributes.length; i++) {
1195
        var attribute = elem[0].attributes[i];
1196
        if (attribute.name !== 'type' && attribute.name !== 'class' && attribute.name !== 'style') {
1197
          if (attribute.name === 'id') {
1198
            updateId(attribute.value);
1199
            unwatches.push(attr.$observe('id', updateId));
1200
          } else {
1201
            fileElem.attr(attribute.name, (!attribute.value && (attribute.name === 'required' ||
1202
            attribute.name === 'multiple')) ? attribute.name : attribute.value);
1203
          }
1204
        }
1205
      }
1206
    }
1207
1208
    function createFileInput() {
1209
      if (isInputTypeFile()) {
1210
        return elem;
1211
      }
1212
1213
      var fileElem = angular.element('<input type="file">');
1214
1215
      var label = angular.element('<label>upload</label>');
1216
      label.css('visibility', 'hidden').css('position', 'absolute').css('overflow', 'hidden')
1217
        .css('width', '0px').css('height', '0px').css('border', 'none')
1218
        .css('margin', '0px').css('padding', '0px').attr('tabindex', '-1');
1219
      bindAttrToFileInput(fileElem, label);
1220
1221
      generatedElems.push({el: elem, ref: label});
1222
1223
      document.body.appendChild(label.append(fileElem)[0]);
1224
1225
      return fileElem;
1226
    }
1227
1228
    function clickHandler(evt) {
1229
      if (elem.attr('disabled')) return false;
1230
      if (attrGetter('ngfSelectDisabled', scope)) return;
1231
1232
      var r = detectSwipe(evt);
1233
      // prevent the click if it is a swipe
1234
      if (r != null) return r;
1235
1236
      resetModel(evt);
1237
1238
      // fix for md when the element is removed from the DOM and added back #460
1239
      try {
1240
        if (!isInputTypeFile() && !document.body.contains(fileElem[0])) {
1241
          generatedElems.push({el: elem, ref: fileElem.parent()});
1242
          document.body.appendChild(fileElem.parent()[0]);
1243
          fileElem.bind('change', changeFn);
1244
        }
1245
      } catch (e) {/*ignore*/
1246
      }
1247
1248
      if (isDelayedClickSupported(navigator.userAgent)) {
1249
        setTimeout(function () {
1250
          fileElem[0].click();
1251
        }, 0);
1252
      } else {
1253
        fileElem[0].click();
1254
      }
1255
1256
      return false;
1257
    }
1258
1259
1260
    var initialTouchStartY = 0;
1261
    var initialTouchStartX = 0;
1262
1263
    function detectSwipe(evt) {
1264
      var touches = evt.changedTouches || (evt.originalEvent && evt.originalEvent.changedTouches);
1265
      if (touches) {
1266
        if (evt.type === 'touchstart') {
1267
          initialTouchStartX = touches[0].clientX;
1268
          initialTouchStartY = touches[0].clientY;
1269
          return true; // don't block event default
1270
        } else {
1271
          // prevent scroll from triggering event
1272
          if (evt.type === 'touchend') {
1273
            var currentX = touches[0].clientX;
1274
            var currentY = touches[0].clientY;
1275
            if ((Math.abs(currentX - initialTouchStartX) > 20) ||
1276
              (Math.abs(currentY - initialTouchStartY) > 20)) {
1277
              evt.stopPropagation();
1278
              evt.preventDefault();
1279
              return false;
1280
            }
1281
          }
1282
          return true;
1283
        }
1284
      }
1285
    }
1286
1287
    var fileElem = elem;
1288
1289
    function resetModel(evt) {
1290
      if (upload.shouldUpdateOn('click', attr, scope) && fileElem.val()) {
1291
        fileElem.val(null);
1292
        upload.updateModel(ngModel, attr, scope, fileChangeAttr(), null, evt, true);
1293
      }
1294
    }
1295
1296
    if (!isInputTypeFile()) {
1297
      fileElem = createFileInput();
1298
    }
1299
    fileElem.bind('change', changeFn);
1300
1301
    if (!isInputTypeFile()) {
1302
      elem.bind('click touchstart touchend', clickHandler);
1303
    } else {
1304
      elem.bind('click', resetModel);
1305
    }
1306
1307
    function ie10SameFileSelectFix(evt) {
1308
      if (fileElem && !fileElem.attr('__ngf_ie10_Fix_')) {
1309
        if (!fileElem[0].parentNode) {
1310
          fileElem = null;
1311
          return;
1312
        }
1313
        evt.preventDefault();
1314
        evt.stopPropagation();
1315
        fileElem.unbind('click');
1316
        var clone = fileElem.clone();
1317
        fileElem.replaceWith(clone);
1318
        fileElem = clone;
1319
        fileElem.attr('__ngf_ie10_Fix_', 'true');
1320
        fileElem.bind('change', changeFn);
1321
        fileElem.bind('click', ie10SameFileSelectFix);
1322
        fileElem[0].click();
1323
        return false;
1324
      } else {
1325
        fileElem.removeAttr('__ngf_ie10_Fix_');
1326
      }
1327
    }
1328
1329
    if (navigator.appVersion.indexOf('MSIE 10') !== -1) {
1330
      fileElem.bind('click', ie10SameFileSelectFix);
1331
    }
1332
1333
    if (ngModel) ngModel.$formatters.push(function (val) {
1334
      if (val == null || val.length === 0) {
1335
        if (fileElem.val()) {
1336
          fileElem.val(null);
1337
        }
1338
      }
1339
      return val;
1340
    });
1341
1342
    scope.$on('$destroy', function () {
1343
      if (!isInputTypeFile()) fileElem.parent().remove();
1344
      angular.forEach(unwatches, function (unwatch) {
1345
        unwatch();
1346
      });
1347
    });
1348
1349
    $timeout(function () {
1350
      for (var i = 0; i < generatedElems.length; i++) {
1351
        var g = generatedElems[i];
1352
        if (!document.body.contains(g.el[0])) {
1353
          generatedElems.splice(i, 1);
1354
          g.ref.remove();
1355
        }
1356
      }
1357
    });
1358
1359
    if (window.FileAPI && window.FileAPI.ngfFixIE) {
1360
      window.FileAPI.ngfFixIE(elem, fileElem, changeFn);
1361
    }
1362
  }
1363
1364
  return {
1365
    restrict: 'AEC',
1366
    require: '?ngModel',
1367
    link: function (scope, elem, attr, ngModel) {
1368
      linkFileSelect(scope, elem, attr, ngModel, $parse, $timeout, $compile, Upload);
1369
    }
1370
  };
1371
}]);
1372
1373
(function () {
1374

third-party/angularjs-modules-plugins/ng-file-upload-12.2.12/demo/src/main/webapp/js/ng-file-upload.js 1 location

@@ 696-949 (lines=254) @@
693
  return upload;
694
}]);
695
696
ngFileUpload.directive('ngfSelect', ['$parse', '$timeout', '$compile', 'Upload', function ($parse, $timeout, $compile, Upload) {
697
  var generatedElems = [];
698
699
  function isDelayedClickSupported(ua) {
700
    // fix for android native browser < 4.4 and safari windows
701
    var m = ua.match(/Android[^\d]*(\d+)\.(\d+)/);
702
    if (m && m.length > 2) {
703
      var v = Upload.defaults.androidFixMinorVersion || 4;
704
      return parseInt(m[1]) < 4 || (parseInt(m[1]) === v && parseInt(m[2]) < v);
705
    }
706
707
    // safari on windows
708
    return ua.indexOf('Chrome') === -1 && /.*Windows.*Safari.*/.test(ua);
709
  }
710
711
  function linkFileSelect(scope, elem, attr, ngModel, $parse, $timeout, $compile, upload) {
712
    /** @namespace attr.ngfSelect */
713
    /** @namespace attr.ngfChange */
714
    /** @namespace attr.ngModel */
715
    /** @namespace attr.ngfModelOptions */
716
    /** @namespace attr.ngfMultiple */
717
    /** @namespace attr.ngfCapture */
718
    /** @namespace attr.ngfValidate */
719
    /** @namespace attr.ngfKeep */
720
    var attrGetter = function (name, scope) {
721
      return upload.attrGetter(name, attr, scope);
722
    };
723
724
    function isInputTypeFile() {
725
      return elem[0].tagName.toLowerCase() === 'input' && attr.type && attr.type.toLowerCase() === 'file';
726
    }
727
728
    function fileChangeAttr() {
729
      return attrGetter('ngfChange') || attrGetter('ngfSelect');
730
    }
731
732
    function changeFn(evt) {
733
      if (upload.shouldUpdateOn('change', attr, scope)) {
734
        var fileList = evt.__files_ || (evt.target && evt.target.files), files = [];
735
        /* Handle duplicate call in  IE11 */
736
        if (!fileList) return;
737
        for (var i = 0; i < fileList.length; i++) {
738
          files.push(fileList[i]);
739
        }
740
        upload.updateModel(ngModel, attr, scope, fileChangeAttr(),
741
          files.length ? files : null, evt);
742
      }
743
    }
744
745
    upload.registerModelChangeValidator(ngModel, attr, scope);
746
747
    var unwatches = [];
748
    if (attrGetter('ngfMultiple')) {
749
      unwatches.push(scope.$watch(attrGetter('ngfMultiple'), function () {
750
        fileElem.attr('multiple', attrGetter('ngfMultiple', scope));
751
      }));
752
    }
753
    if (attrGetter('ngfCapture')) {
754
      unwatches.push(scope.$watch(attrGetter('ngfCapture'), function () {
755
        fileElem.attr('capture', attrGetter('ngfCapture', scope));
756
      }));
757
    }
758
    if (attrGetter('ngfAccept')) {
759
      unwatches.push(scope.$watch(attrGetter('ngfAccept'), function () {
760
        fileElem.attr('accept', attrGetter('ngfAccept', scope));
761
      }));
762
    }
763
    unwatches.push(attr.$observe('accept', function () {
764
      fileElem.attr('accept', attrGetter('accept'));
765
    }));
766
    function bindAttrToFileInput(fileElem, label) {
767
      function updateId(val) {
768
        fileElem.attr('id', 'ngf-' + val);
769
        label.attr('id', 'ngf-label-' + val);
770
      }
771
772
      for (var i = 0; i < elem[0].attributes.length; i++) {
773
        var attribute = elem[0].attributes[i];
774
        if (attribute.name !== 'type' && attribute.name !== 'class' && attribute.name !== 'style') {
775
          if (attribute.name === 'id') {
776
            updateId(attribute.value);
777
            unwatches.push(attr.$observe('id', updateId));
778
          } else {
779
            fileElem.attr(attribute.name, (!attribute.value && (attribute.name === 'required' ||
780
            attribute.name === 'multiple')) ? attribute.name : attribute.value);
781
          }
782
        }
783
      }
784
    }
785
786
    function createFileInput() {
787
      if (isInputTypeFile()) {
788
        return elem;
789
      }
790
791
      var fileElem = angular.element('<input type="file">');
792
793
      var label = angular.element('<label>upload</label>');
794
      label.css('visibility', 'hidden').css('position', 'absolute').css('overflow', 'hidden')
795
        .css('width', '0px').css('height', '0px').css('border', 'none')
796
        .css('margin', '0px').css('padding', '0px').attr('tabindex', '-1');
797
      bindAttrToFileInput(fileElem, label);
798
799
      generatedElems.push({el: elem, ref: label});
800
801
      document.body.appendChild(label.append(fileElem)[0]);
802
803
      return fileElem;
804
    }
805
806
    function clickHandler(evt) {
807
      if (elem.attr('disabled')) return false;
808
      if (attrGetter('ngfSelectDisabled', scope)) return;
809
810
      var r = detectSwipe(evt);
811
      // prevent the click if it is a swipe
812
      if (r != null) return r;
813
814
      resetModel(evt);
815
816
      // fix for md when the element is removed from the DOM and added back #460
817
      try {
818
        if (!isInputTypeFile() && !document.body.contains(fileElem[0])) {
819
          generatedElems.push({el: elem, ref: fileElem.parent()});
820
          document.body.appendChild(fileElem.parent()[0]);
821
          fileElem.bind('change', changeFn);
822
        }
823
      } catch (e) {/*ignore*/
824
      }
825
826
      if (isDelayedClickSupported(navigator.userAgent)) {
827
        setTimeout(function () {
828
          fileElem[0].click();
829
        }, 0);
830
      } else {
831
        fileElem[0].click();
832
      }
833
834
      return false;
835
    }
836
837
838
    var initialTouchStartY = 0;
839
    var initialTouchStartX = 0;
840
841
    function detectSwipe(evt) {
842
      var touches = evt.changedTouches || (evt.originalEvent && evt.originalEvent.changedTouches);
843
      if (touches) {
844
        if (evt.type === 'touchstart') {
845
          initialTouchStartX = touches[0].clientX;
846
          initialTouchStartY = touches[0].clientY;
847
          return true; // don't block event default
848
        } else {
849
          // prevent scroll from triggering event
850
          if (evt.type === 'touchend') {
851
            var currentX = touches[0].clientX;
852
            var currentY = touches[0].clientY;
853
            if ((Math.abs(currentX - initialTouchStartX) > 20) ||
854
              (Math.abs(currentY - initialTouchStartY) > 20)) {
855
              evt.stopPropagation();
856
              evt.preventDefault();
857
              return false;
858
            }
859
          }
860
          return true;
861
        }
862
      }
863
    }
864
865
    var fileElem = elem;
866
867
    function resetModel(evt) {
868
      if (upload.shouldUpdateOn('click', attr, scope) && fileElem.val()) {
869
        fileElem.val(null);
870
        upload.updateModel(ngModel, attr, scope, fileChangeAttr(), null, evt, true);
871
      }
872
    }
873
874
    if (!isInputTypeFile()) {
875
      fileElem = createFileInput();
876
    }
877
    fileElem.bind('change', changeFn);
878
879
    if (!isInputTypeFile()) {
880
      elem.bind('click touchstart touchend', clickHandler);
881
    } else {
882
      elem.bind('click', resetModel);
883
    }
884
885
    function ie10SameFileSelectFix(evt) {
886
      if (fileElem && !fileElem.attr('__ngf_ie10_Fix_')) {
887
        if (!fileElem[0].parentNode) {
888
          fileElem = null;
889
          return;
890
        }
891
        evt.preventDefault();
892
        evt.stopPropagation();
893
        fileElem.unbind('click');
894
        var clone = fileElem.clone();
895
        fileElem.replaceWith(clone);
896
        fileElem = clone;
897
        fileElem.attr('__ngf_ie10_Fix_', 'true');
898
        fileElem.bind('change', changeFn);
899
        fileElem.bind('click', ie10SameFileSelectFix);
900
        fileElem[0].click();
901
        return false;
902
      } else {
903
        fileElem.removeAttr('__ngf_ie10_Fix_');
904
      }
905
    }
906
907
    if (navigator.appVersion.indexOf('MSIE 10') !== -1) {
908
      fileElem.bind('click', ie10SameFileSelectFix);
909
    }
910
911
    if (ngModel) ngModel.$formatters.push(function (val) {
912
      if (val == null || val.length === 0) {
913
        if (fileElem.val()) {
914
          fileElem.val(null);
915
        }
916
      }
917
      return val;
918
    });
919
920
    scope.$on('$destroy', function () {
921
      if (!isInputTypeFile()) fileElem.parent().remove();
922
      angular.forEach(unwatches, function (unwatch) {
923
        unwatch();
924
      });
925
    });
926
927
    $timeout(function () {
928
      for (var i = 0; i < generatedElems.length; i++) {
929
        var g = generatedElems[i];
930
        if (!document.body.contains(g.el[0])) {
931
          generatedElems.splice(i, 1);
932
          g.ref.remove();
933
        }
934
      }
935
    });
936
937
    if (window.FileAPI && window.FileAPI.ngfFixIE) {
938
      window.FileAPI.ngfFixIE(elem, fileElem, changeFn);
939
    }
940
  }
941
942
  return {
943
    restrict: 'AEC',
944
    require: '?ngModel',
945
    link: function (scope, elem, attr, ngModel) {
946
      linkFileSelect(scope, elem, attr, ngModel, $parse, $timeout, $compile, Upload);
947
    }
948
  };
949
}]);
950
951
(function () {
952

third-party/angularjs-modules-plugins/ng-file-upload-12.2.12/src/select.js 1 location

@@ 1-254 (lines=254) @@
1
ngFileUpload.directive('ngfSelect', ['$parse', '$timeout', '$compile', 'Upload', function ($parse, $timeout, $compile, Upload) {
2
  var generatedElems = [];
3
4
  function isDelayedClickSupported(ua) {
5
    // fix for android native browser < 4.4 and safari windows
6
    var m = ua.match(/Android[^\d]*(\d+)\.(\d+)/);
7
    if (m && m.length > 2) {
8
      var v = Upload.defaults.androidFixMinorVersion || 4;
9
      return parseInt(m[1]) < 4 || (parseInt(m[1]) === v && parseInt(m[2]) < v);
10
    }
11
12
    // safari on windows
13
    return ua.indexOf('Chrome') === -1 && /.*Windows.*Safari.*/.test(ua);
14
  }
15
16
  function linkFileSelect(scope, elem, attr, ngModel, $parse, $timeout, $compile, upload) {
17
    /** @namespace attr.ngfSelect */
18
    /** @namespace attr.ngfChange */
19
    /** @namespace attr.ngModel */
20
    /** @namespace attr.ngfModelOptions */
21
    /** @namespace attr.ngfMultiple */
22
    /** @namespace attr.ngfCapture */
23
    /** @namespace attr.ngfValidate */
24
    /** @namespace attr.ngfKeep */
25
    var attrGetter = function (name, scope) {
26
      return upload.attrGetter(name, attr, scope);
27
    };
28
29
    function isInputTypeFile() {
30
      return elem[0].tagName.toLowerCase() === 'input' && attr.type && attr.type.toLowerCase() === 'file';
31
    }
32
33
    function fileChangeAttr() {
34
      return attrGetter('ngfChange') || attrGetter('ngfSelect');
35
    }
36
37
    function changeFn(evt) {
38
      if (upload.shouldUpdateOn('change', attr, scope)) {
39
        var fileList = evt.__files_ || (evt.target && evt.target.files), files = [];
40
        /* Handle duplicate call in  IE11 */
41
        if (!fileList) return;
42
        for (var i = 0; i < fileList.length; i++) {
43
          files.push(fileList[i]);
44
        }
45
        upload.updateModel(ngModel, attr, scope, fileChangeAttr(),
46
          files.length ? files : null, evt);
47
      }
48
    }
49
50
    upload.registerModelChangeValidator(ngModel, attr, scope);
51
52
    var unwatches = [];
53
    if (attrGetter('ngfMultiple')) {
54
      unwatches.push(scope.$watch(attrGetter('ngfMultiple'), function () {
55
        fileElem.attr('multiple', attrGetter('ngfMultiple', scope));
56
      }));
57
    }
58
    if (attrGetter('ngfCapture')) {
59
      unwatches.push(scope.$watch(attrGetter('ngfCapture'), function () {
60
        fileElem.attr('capture', attrGetter('ngfCapture', scope));
61
      }));
62
    }
63
    if (attrGetter('ngfAccept')) {
64
      unwatches.push(scope.$watch(attrGetter('ngfAccept'), function () {
65
        fileElem.attr('accept', attrGetter('ngfAccept', scope));
66
      }));
67
    }
68
    unwatches.push(attr.$observe('accept', function () {
69
      fileElem.attr('accept', attrGetter('accept'));
70
    }));
71
    function bindAttrToFileInput(fileElem, label) {
72
      function updateId(val) {
73
        fileElem.attr('id', 'ngf-' + val);
74
        label.attr('id', 'ngf-label-' + val);
75
      }
76
77
      for (var i = 0; i < elem[0].attributes.length; i++) {
78
        var attribute = elem[0].attributes[i];
79
        if (attribute.name !== 'type' && attribute.name !== 'class' && attribute.name !== 'style') {
80
          if (attribute.name === 'id') {
81
            updateId(attribute.value);
82
            unwatches.push(attr.$observe('id', updateId));
83
          } else {
84
            fileElem.attr(attribute.name, (!attribute.value && (attribute.name === 'required' ||
85
            attribute.name === 'multiple')) ? attribute.name : attribute.value);
86
          }
87
        }
88
      }
89
    }
90
91
    function createFileInput() {
92
      if (isInputTypeFile()) {
93
        return elem;
94
      }
95
96
      var fileElem = angular.element('<input type="file">');
97
98
      var label = angular.element('<label>upload</label>');
99
      label.css('visibility', 'hidden').css('position', 'absolute').css('overflow', 'hidden')
100
        .css('width', '0px').css('height', '0px').css('border', 'none')
101
        .css('margin', '0px').css('padding', '0px').attr('tabindex', '-1');
102
      bindAttrToFileInput(fileElem, label);
103
104
      generatedElems.push({el: elem, ref: label});
105
106
      document.body.appendChild(label.append(fileElem)[0]);
107
108
      return fileElem;
109
    }
110
111
    function clickHandler(evt) {
112
      if (elem.attr('disabled')) return false;
113
      if (attrGetter('ngfSelectDisabled', scope)) return;
114
115
      var r = detectSwipe(evt);
116
      // prevent the click if it is a swipe
117
      if (r != null) return r;
118
119
      resetModel(evt);
120
121
      // fix for md when the element is removed from the DOM and added back #460
122
      try {
123
        if (!isInputTypeFile() && !document.body.contains(fileElem[0])) {
124
          generatedElems.push({el: elem, ref: fileElem.parent()});
125
          document.body.appendChild(fileElem.parent()[0]);
126
          fileElem.bind('change', changeFn);
127
        }
128
      } catch (e) {/*ignore*/
129
      }
130
131
      if (isDelayedClickSupported(navigator.userAgent)) {
132
        setTimeout(function () {
133
          fileElem[0].click();
134
        }, 0);
135
      } else {
136
        fileElem[0].click();
137
      }
138
139
      return false;
140
    }
141
142
143
    var initialTouchStartY = 0;
144
    var initialTouchStartX = 0;
145
146
    function detectSwipe(evt) {
147
      var touches = evt.changedTouches || (evt.originalEvent && evt.originalEvent.changedTouches);
148
      if (touches) {
149
        if (evt.type === 'touchstart') {
150
          initialTouchStartX = touches[0].clientX;
151
          initialTouchStartY = touches[0].clientY;
152
          return true; // don't block event default
153
        } else {
154
          // prevent scroll from triggering event
155
          if (evt.type === 'touchend') {
156
            var currentX = touches[0].clientX;
157
            var currentY = touches[0].clientY;
158
            if ((Math.abs(currentX - initialTouchStartX) > 20) ||
159
              (Math.abs(currentY - initialTouchStartY) > 20)) {
160
              evt.stopPropagation();
161
              evt.preventDefault();
162
              return false;
163
            }
164
          }
165
          return true;
166
        }
167
      }
168
    }
169
170
    var fileElem = elem;
171
172
    function resetModel(evt) {
173
      if (upload.shouldUpdateOn('click', attr, scope) && fileElem.val()) {
174
        fileElem.val(null);
175
        upload.updateModel(ngModel, attr, scope, fileChangeAttr(), null, evt, true);
176
      }
177
    }
178
179
    if (!isInputTypeFile()) {
180
      fileElem = createFileInput();
181
    }
182
    fileElem.bind('change', changeFn);
183
184
    if (!isInputTypeFile()) {
185
      elem.bind('click touchstart touchend', clickHandler);
186
    } else {
187
      elem.bind('click', resetModel);
188
    }
189
190
    function ie10SameFileSelectFix(evt) {
191
      if (fileElem && !fileElem.attr('__ngf_ie10_Fix_')) {
192
        if (!fileElem[0].parentNode) {
193
          fileElem = null;
194
          return;
195
        }
196
        evt.preventDefault();
197
        evt.stopPropagation();
198
        fileElem.unbind('click');
199
        var clone = fileElem.clone();
200
        fileElem.replaceWith(clone);
201
        fileElem = clone;
202
        fileElem.attr('__ngf_ie10_Fix_', 'true');
203
        fileElem.bind('change', changeFn);
204
        fileElem.bind('click', ie10SameFileSelectFix);
205
        fileElem[0].click();
206
        return false;
207
      } else {
208
        fileElem.removeAttr('__ngf_ie10_Fix_');
209
      }
210
    }
211
212
    if (navigator.appVersion.indexOf('MSIE 10') !== -1) {
213
      fileElem.bind('click', ie10SameFileSelectFix);
214
    }
215
216
    if (ngModel) ngModel.$formatters.push(function (val) {
217
      if (val == null || val.length === 0) {
218
        if (fileElem.val()) {
219
          fileElem.val(null);
220
        }
221
      }
222
      return val;
223
    });
224
225
    scope.$on('$destroy', function () {
226
      if (!isInputTypeFile()) fileElem.parent().remove();
227
      angular.forEach(unwatches, function (unwatch) {
228
        unwatch();
229
      });
230
    });
231
232
    $timeout(function () {
233
      for (var i = 0; i < generatedElems.length; i++) {
234
        var g = generatedElems[i];
235
        if (!document.body.contains(g.el[0])) {
236
          generatedElems.splice(i, 1);
237
          g.ref.remove();
238
        }
239
      }
240
    });
241
242
    if (window.FileAPI && window.FileAPI.ngfFixIE) {
243
      window.FileAPI.ngfFixIE(elem, fileElem, changeFn);
244
    }
245
  }
246
247
  return {
248
    restrict: 'AEC',
249
    require: '?ngModel',
250
    link: function (scope, elem, attr, ngModel) {
251
      linkFileSelect(scope, elem, attr, ngModel, $parse, $timeout, $compile, Upload);
252
    }
253
  };
254
}]);
255