1
1
/**
2
2
* @description
3
- * 简单上传:点击按钮,直接选择文件上传
4
- * @author Jinqn
5
- * @date 2014-03-31
3
+ * 简单上传:点击按钮,直接选择文件上传。
4
+ * 原 UEditor 作者使用了 form 表单 + iframe 的方式上传
5
+ * 但由于同源策略的限制,父页面无法访问跨域的 iframe 内容
6
+ * 导致无法获取接口返回的数据,使得单图上传无法在跨域的情况下使用
7
+ * 这里改为普通的XHR上传,兼容到IE10+
8
+ * @author HaoChuan9421 <hc199421@gmail.com>
9
+ * @date 2018-12-20
6
10
*/
7
- UE . plugin . register ( 'simpleupload' , function ( ) {
8
- var me = this ,
9
- isLoaded = false ,
10
- containerBtn ;
11
-
12
- function initUploadBtn ( ) {
13
- var w = containerBtn . offsetWidth || 20 ,
14
- h = containerBtn . offsetHeight || 20 ,
15
- btnIframe = document . createElement ( 'iframe' ) ,
16
- btnStyle = 'display:block;width:' + w + 'px;height:' + h + 'px;overflow:hidden;border:0;margin:0;padding:0;position:absolute;top:0;left:0;filter:alpha(opacity=0);-moz-opacity:0;-khtml-opacity: 0;opacity: 0;cursor:pointer;' ;
17
-
18
- domUtils . on ( btnIframe , 'load' , function ( ) {
19
-
20
- var timestrap = ( + new Date ( ) ) . toString ( 36 ) ,
21
- wrapper ,
22
- btnIframeDoc ,
23
- btnIframeBody ;
24
-
25
- btnIframeDoc = ( btnIframe . contentDocument || btnIframe . contentWindow . document ) ;
26
- btnIframeBody = btnIframeDoc . body ;
27
- wrapper = btnIframeDoc . createElement ( 'div' ) ;
28
-
29
- wrapper . innerHTML = '<form id="edui_form_' + timestrap + '" target="edui_iframe_' + timestrap + '" method="POST" enctype="multipart/form-data" action="' + me . getOpt ( 'serverUrl' ) + '" ' +
30
- 'style="' + btnStyle + '">' +
31
- '<input id="edui_input_' + timestrap + '" type="file" accept="image/*" name="' + me . options . imageFieldName + '" ' +
32
- 'style="' + btnStyle + '">' +
33
- '</form>' +
34
- '<iframe id="edui_iframe_' + timestrap + '" name="edui_iframe_' + timestrap + '" style="display:none;width:0;height:0;border:0;margin:0;padding:0;position:absolute;"></iframe>' ;
35
-
36
- wrapper . className = 'edui-' + me . options . theme ;
37
- wrapper . id = me . ui . id + '_iframeupload' ;
38
- btnIframeBody . style . cssText = btnStyle ;
39
- btnIframeBody . style . width = w + 'px' ;
40
- btnIframeBody . style . height = h + 'px' ;
41
- btnIframeBody . appendChild ( wrapper ) ;
42
-
43
- if ( btnIframeBody . parentNode ) {
44
- btnIframeBody . parentNode . style . width = w + 'px' ;
45
- btnIframeBody . parentNode . style . height = w + 'px' ;
46
- }
47
-
48
- var form = btnIframeDoc . getElementById ( 'edui_form_' + timestrap ) ;
49
- var input = btnIframeDoc . getElementById ( 'edui_input_' + timestrap ) ;
50
- var iframe = btnIframeDoc . getElementById ( 'edui_iframe_' + timestrap ) ;
51
-
52
- domUtils . on ( input , 'change' , function ( ) {
53
- if ( ! input . value ) return ;
54
- var loadingId = 'loading_' + ( + new Date ( ) ) . toString ( 36 ) ;
55
- var params = utils . serializeParam ( me . queryCommandValue ( 'serverparam' ) ) || '' ;
56
-
57
- var imageActionUrl = me . getActionUrl ( me . getOpt ( 'imageActionName' ) ) ;
58
- var allowFiles = me . getOpt ( 'imageAllowFiles' ) ;
59
-
60
- me . focus ( ) ;
61
- me . execCommand ( 'inserthtml' , '<img class="loadingclass" id="' + loadingId + '" src="' + me . options . themePath + me . options . theme + '/images/spacer.gif" title="' + ( me . getLang ( 'simpleupload.loading' ) || '' ) + '" >' ) ;
62
-
63
- function callback ( ) {
64
- try {
65
- var link , json , loader ,
66
- body = ( iframe . contentDocument || iframe . contentWindow . document ) . body ,
67
- result = body . innerText || body . textContent || '' ;
68
- json = ( new Function ( "return " + result ) ) ( ) ;
69
- link = me . options . imageUrlPrefix + json . url ;
70
- if ( json . state == 'SUCCESS' && json . url ) {
71
- loader = me . document . getElementById ( loadingId ) ;
72
- loader . setAttribute ( 'src' , link ) ;
73
- loader . setAttribute ( '_src' , link ) ;
74
- loader . setAttribute ( 'title' , json . title || '' ) ;
75
- loader . setAttribute ( 'alt' , json . original || '' ) ;
76
- loader . removeAttribute ( 'id' ) ;
77
- domUtils . removeClasses ( loader , 'loadingclass' ) ;
78
- me . fireEvent ( "contentchange" ) ; // HaoChuan9421
79
- } else {
80
- showErrorLoader && showErrorLoader ( json . state ) ;
81
- }
82
- } catch ( er ) {
83
- showErrorLoader && showErrorLoader ( me . getLang ( 'simpleupload.loadError' ) ) ;
84
- }
85
- form . reset ( ) ;
86
- domUtils . un ( iframe , 'load' , callback ) ;
87
- }
88
- function showErrorLoader ( title ) {
89
- if ( loadingId ) {
90
- var loader = me . document . getElementById ( loadingId ) ;
91
- loader && domUtils . remove ( loader ) ;
92
- me . fireEvent ( 'showmessage' , {
93
- 'id' : loadingId ,
94
- 'content' : title ,
95
- 'type' : 'error' ,
96
- 'timeout' : 4000
97
- } ) ;
98
- }
99
- }
100
-
101
- /* 判断后端配置是否没有加载成功 */
102
- if ( ! me . getOpt ( 'imageActionName' ) ) {
103
- errorHandler ( me . getLang ( 'autoupload.errorLoadConfig' ) ) ;
104
- return ;
105
- }
106
- // 判断文件格式是否错误
107
- var filename = input . value ,
108
- fileext = filename ? filename . substr ( filename . lastIndexOf ( '.' ) ) :'' ;
109
- if ( ! fileext || ( allowFiles && ( allowFiles . join ( '' ) + '.' ) . indexOf ( fileext . toLowerCase ( ) + '.' ) == - 1 ) ) {
110
- showErrorLoader ( me . getLang ( 'simpleupload.exceedTypeError' ) ) ;
111
- return ;
112
- }
113
-
114
- domUtils . on ( iframe , 'load' , callback ) ;
115
- form . action = utils . formatUrl ( imageActionUrl + ( imageActionUrl . indexOf ( '?' ) == - 1 ? '?' :'&' ) + params ) ;
116
- form . submit ( ) ;
117
- } ) ;
118
-
119
- var stateTimer ;
120
- me . addListener ( 'selectionchange' , function ( ) {
121
- clearTimeout ( stateTimer ) ;
122
- stateTimer = setTimeout ( function ( ) {
123
- var state = me . queryCommandState ( 'simpleupload' ) ;
124
- if ( state == - 1 ) {
125
- input . disabled = 'disabled' ;
126
- } else {
127
- input . disabled = false ;
128
- }
129
- } , 400 ) ;
130
- } ) ;
131
- isLoaded = true ;
132
- } ) ;
133
-
134
- btnIframe . style . cssText = btnStyle ;
135
- containerBtn . appendChild ( btnIframe ) ;
136
- }
137
-
138
- return {
139
- bindEvents :{
140
- 'ready' : function ( ) {
141
- //设置loading的样式
142
- utils . cssRule ( 'loading' ,
143
- '.loadingclass{display:inline-block;cursor:default;background: url(\''
144
- + this . options . themePath
145
- + this . options . theme + '/images/loading.gif\') no-repeat center center transparent;border:1px solid #cccccc;margin-right:1px;height: 22px;width: 22px;}\n' +
146
- '.loaderrorclass{display:inline-block;cursor:default;background: url(\''
147
- + this . options . themePath
148
- + this . options . theme + '/images/loaderror.png\') no-repeat center center transparent;border:1px solid #cccccc;margin-right:1px;height: 22px;width: 22px;' +
149
- '}' ,
150
- this . document ) ;
151
- } ,
152
- /* 初始化简单上传按钮 */
153
- 'simpleuploadbtnready' : function ( type , container ) {
154
- containerBtn = container ;
155
- me . afterConfigReady ( initUploadBtn ) ;
156
- }
157
- } ,
158
- outputRule : function ( root ) {
159
- utils . each ( root . getNodesByTagName ( 'img' ) , function ( n ) {
160
- if ( / \b ( l o a d e r r o r c l a s s ) | ( b l o a d e r r o r c l a s s ) \b / . test ( n . getAttr ( 'class' ) ) ) {
161
- n . parentNode . removeChild ( n ) ;
162
- }
163
- } ) ;
164
- } ,
165
- commands : {
166
- 'simpleupload' : {
167
- queryCommandState : function ( ) {
168
- return isLoaded ? 0 :- 1 ;
169
- }
170
- }
11
+ UE . plugin . register ( 'simpleupload' , function ( ) {
12
+ var me = this ,
13
+ containerBtn ,
14
+ timestrap = ( + new Date ( ) ) . toString ( 36 ) ;
15
+
16
+ function initUploadBtn ( ) {
17
+ var w = containerBtn . offsetWidth || 20 ,
18
+ h = containerBtn . offsetHeight || 20 ,
19
+ btnStyle = 'display:block;width:' + w + 'px;height:' + h + 'px;overflow:hidden;border:0;margin:0;padding:0;position:absolute;top:0;left:0;filter:alpha(opacity=0);-moz-opacity:0;-khtml-opacity: 0;opacity: 0;cursor:pointer;' ;
20
+
21
+ containerBtn . innerHTML = '<form id="edui_form_' + timestrap + '" enctype="multipart/form-data" style="' + btnStyle + '">' +
22
+ '<input id="edui_input_' + timestrap + '" type="file" accept="image/*" name="' + me . options . imageFieldName + '"style="' + btnStyle + '" />' +
23
+ '</form>'
24
+
25
+ var form = document . getElementById ( 'edui_form_' + timestrap )
26
+ var input = document . getElementById ( 'edui_input_' + timestrap )
27
+
28
+ input . addEventListener ( 'change' , function ( event ) {
29
+ if ( ! input . value ) return ;
30
+ var loadingId = 'loading_' + ( + new Date ( ) ) . toString ( 36 ) ;
31
+ var imageActionUrl = me . getActionUrl ( me . getOpt ( 'imageActionName' ) ) ;
32
+ var params = utils . serializeParam ( me . queryCommandValue ( 'serverparam' ) ) || '' ;
33
+ var action = utils . formatUrl ( imageActionUrl + ( imageActionUrl . indexOf ( '?' ) == - 1 ? '?' : '&' ) + params ) ;
34
+ var allowFiles = me . getOpt ( 'imageAllowFiles' ) ;
35
+ me . focus ( ) ;
36
+ me . execCommand ( 'inserthtml' , '<img class="loadingclass" id="' + loadingId + '" src="' + me . options . themePath + me . options . theme + '/images/spacer.gif" title="' + ( me . getLang ( 'simpleupload.loading' ) || '' ) + '" >' ) ;
37
+
38
+ function showErrorLoader ( title ) {
39
+ if ( loadingId ) {
40
+ var loader = me . document . getElementById ( loadingId ) ;
41
+ loader && domUtils . remove ( loader ) ;
42
+ me . fireEvent ( 'showmessage' , {
43
+ 'id' : loadingId ,
44
+ 'content' : title ,
45
+ 'type' : 'error' ,
46
+ 'timeout' : 4000
47
+ } ) ;
48
+ }
49
+ }
50
+ /* 判断后端配置是否没有加载成功 */
51
+ if ( ! me . getOpt ( 'imageActionName' ) ) {
52
+ showErrorLoader ( me . getLang ( 'autoupload.errorLoadConfig' ) ) ;
53
+ return ;
54
+ }
55
+ // 判断文件格式是否错误
56
+ var filename = input . value ,
57
+ fileext = filename ? filename . substr ( filename . lastIndexOf ( '.' ) ) : '' ;
58
+ if ( ! fileext || ( allowFiles && ( allowFiles . join ( '' ) + '.' ) . indexOf ( fileext . toLowerCase ( ) + '.' ) == - 1 ) ) {
59
+ showErrorLoader ( me . getLang ( 'simpleupload.exceedTypeError' ) ) ;
60
+ return ;
61
+ }
62
+
63
+ var xhr = new XMLHttpRequest ( )
64
+ xhr . open ( 'post' , action , true )
65
+ if ( me . options . headers && Object . prototype . toString . apply ( me . options . headers ) === "[object Object]" ) {
66
+ for ( var key in me . options . headers ) {
67
+ xhr . setRequestHeader ( key , me . options . headers [ key ] )
68
+ }
69
+ }
70
+ xhr . onload = function ( ) {
71
+ if ( ( xhr . status >= 200 && xhr . status < 300 ) || xhr . status == 304 ) {
72
+ var res = JSON . parse ( xhr . responseText )
73
+ var link = me . options . imageUrlPrefix + res . url ;
74
+
75
+ if ( res . state == 'SUCCESS' && res . url ) {
76
+ loader = me . document . getElementById ( loadingId ) ;
77
+ loader . setAttribute ( 'src' , link ) ;
78
+ loader . setAttribute ( '_src' , link ) ;
79
+ loader . setAttribute ( 'title' , res . title || '' ) ;
80
+ loader . setAttribute ( 'alt' , res . original || '' ) ;
81
+ loader . removeAttribute ( 'id' ) ;
82
+ domUtils . removeClasses ( loader , 'loadingclass' ) ;
83
+ me . fireEvent ( "contentchange" ) ;
84
+ } else {
85
+ showErrorLoader ( res . state ) ;
86
+ }
87
+ } else {
88
+ showErrorLoader ( me . getLang ( 'simpleupload.loadError' ) ) ;
89
+ }
90
+ } ;
91
+ xhr . onerror = function ( ) {
92
+ showErrorLoader ( me . getLang ( 'simpleupload.loadError' ) ) ;
93
+ } ;
94
+ xhr . send ( new FormData ( form ) ) ;
95
+ form . reset ( ) ;
96
+ } )
97
+ }
98
+
99
+ return {
100
+ bindEvents : {
101
+ 'ready' : function ( ) {
102
+ //设置loading的样式
103
+ utils . cssRule ( 'loading' ,
104
+ '.loadingclass{display:inline-block;cursor:default;background: url(\'' +
105
+ this . options . themePath +
106
+ this . options . theme + '/images/loading.gif\') no-repeat center center transparent;border:1px solid #cccccc;margin-right:1px;height: 22px;width: 22px;}\n' +
107
+ '.loaderrorclass{display:inline-block;cursor:default;background: url(\'' +
108
+ this . options . themePath +
109
+ this . options . theme + '/images/loaderror.png\') no-repeat center center transparent;border:1px solid #cccccc;margin-right:1px;height: 22px;width: 22px;' +
110
+ '}' ,
111
+ this . document ) ;
112
+ } ,
113
+ /* 初始化简单上传按钮 */
114
+ 'simpleuploadbtnready' : function ( type , container ) {
115
+ containerBtn = container ;
116
+ me . afterConfigReady ( initUploadBtn ) ;
117
+ }
118
+ } ,
119
+ outputRule : function ( root ) {
120
+ utils . each ( root . getNodesByTagName ( 'img' ) , function ( n ) {
121
+ if ( / \b ( l o a d e r r o r c l a s s ) | ( b l o a d e r r o r c l a s s ) \b / . test ( n . getAttr ( 'class' ) ) ) {
122
+ n . parentNode . removeChild ( n ) ;
171
123
}
124
+ } ) ;
172
125
}
126
+ }
173
127
} ) ;
0 commit comments