Files
rappaurio-sae501_502/app/node_modules/cejs/interact/DnD.js
2023-09-25 13:27:24 +02:00

477 lines
15 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* @name CeL function for drag-and-drop
* @fileoverview
* 本檔案包含了 web 物件的滑鼠拖曳 functions。
* @since
*/
/*
http://www.w3.org/TR/html5/dnd.html#dnd
http://www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html
https://developer.mozilla.org/en/Using_files_from_web_applications
http://html5demos.com/drag
http://d.hatena.ne.jp/ksy_dev/20100731/p1?sid=810f738005e991c6
*/
'use strict';
if (typeof CeL === 'function')
CeL.run(
{
name:'interact.DnD',
require : 'interact.DOM.is_HTML_element|interact.DOM.get_element|interact.DOM.add_listener|interact.DOM.stop_event|interact.DOM.set_text|data.swap_key_value',
code : function(library_namespace) {
// requiring
var is_HTML_element = this.r('is_HTML_element'), get_element = this.r('get_element'), add_listener = this.r('add_listener'), stop_event = this.r('stop_event'), set_text = this.r('set_text'), swap_key_value = this.r('swap_key_value');
/**
* null module constructor
* @class web drag_and_drop 的 functions
*/
var _// JSDT:_module_
= function() {
// null module constructor
};
/**
* for JSDT: 有 prototype 才會將之當作 Class
*/
_// JSDT:_module_
.prototype = {
};
_// JSDT:_module_
.
move_element = function(element, target) {
target.appendChild(element.parentNode.removeChild(element));
};
function set_drop_target(element, drop_handler, drag_in_handler) {
if (!is_HTML_element(element)
&& !is_HTML_element(element = get_element(element)))
return;
//if(element.id) library_namespace.debug(element.id, 0, 'set_drop_target');
add_listener( {
// 拖進 target。
// 阻止 dragover 預定動作方能觸發 ondrop。
// http://fillano.blog.ithome.com.tw/post/257/81723
dragover : stop_event,
// 在 target 上拖動。
dragenter : stop_event,
// 在 target 上拖完放開滑鼠。
drop : function(event) {
// 處理 types: 將所有設定的 type 一一列出。IE9 沒有 dataTransfer.types。
var i = 0, list = event.dataTransfer.types || ['text', 'url'], l = list.length, data, type;
for (; i < l; i++) {
try {
// IE10 中拖拉外部檔案時dataTransfer.getData(list[i]) 可能會 throw "Invalid argument."
data = event.dataTransfer.getData(list[i]);
type = typeof data;
library_namespace.debug('[' + (i + 1) + '/' + l + '] [' + list[i] + ']: '
+ (data ? type === 'string' && /^[a-z\d\-]+:\/\//i.test(data) ?
'<a href="' + data + '" target="_blank">' + decodeURI(data) + '</a>'
: data
: '[' + type + '] ' + (String(data) || '<span class="gray">(null)</span>')),
1, 'set_drop_target.ondrop');
if (list[i] in set_drop_target.handler) {
type = set_drop_target.handler[list[i]];
for ( var h = 0, _t = this,
timeout_binder = (typeof setTimeout === 'function' || typeof setTimeout === 'object') &&
function() {
library_namespace.debug('準備執行。 (' + data + ')', 2, 'set_drop_target.ondrop');
//library_namespace.debug('' + type[h]);
type[this].call(_t, data);
library_namespace.debug('執行完畢。', 2, 'set_drop_target.ondrop');
}; h < type.length; h++) {
try {
if(timeout_binder) {
library_namespace.debug('use setTimeout to run:<br />'
+ type[h].toString().replace(/\n/g, '<br />'), 2,
'set_drop_target.ondrop');
setTimeout(timeout_binder.bind(h), 0);
} else {
library_namespace.debug('directly run. typeof setTimeout: [' + typeof setTimeout + '].', 2, 'set_drop_target.ondrop');
type[h].call(this, data);
}
} catch (e) {
library_namespace.warn('set_drop_target.ondrop: Error to run ' + list[i] + '.' + h);
library_namespace.error(e);
}
}
}
} catch (e) {
library_namespace.debug('Error to get data of [' + list[i] + ']: ' + e,
1, 'set_drop_target.ondrop');
//library_namespace.error(e);
}
}
// 處理 files. IE9 沒有 dataTransfer.files。
// http://www.html5rocks.com/en/tutorials/file/dndfiles/
// https://github.com/MrSwitch/dropfile
if((list = event.dataTransfer.files)
&& (l = list.length)){
library_namespace.debug('Drop ' + l + ' file object(s).', 1, 'set_drop_target.ondrop');
for (i = 0; i < l; i++) {
data = list[i];
library_namespace.debug('[' + (i + 1) + '/' + l + '] <em>'
+ data.name + '</em>' + (data.type ? ' (' + data.type + ')' : '') + ': ' + data.size + ' bytes.',
1, 'set_drop_target.ondrop');
// 若是小圖,則直接顯示出來。
if (/^image\/\w+/.test(data.type) && data.size < 1000000) {
_.read_file(data, function(event) {
var contents = event.target.result;
library_namespace.debug('<em>' + this.file.name + '</em>: <img title="' + this.file.name + '" src="'
+ contents + '" />' + contents.length
+ ' chars starting with [' + contents.slice(0, 30).replace(/</g, '&lt;') + ']',
1, 'set_drop_target.ondrop');
}, 'url');
}
}
_.read_files(list, function(event){
var contents = event.target.result;
library_namespace.debug('[' + this.file.name + '] loaded: ' + contents.length
+ ' chars starting with [' + contents.slice(0, 30).replace(/</g, '&lt;')
+ ']', 1, 'set_drop_target');
});
}
return stop_event(event);
}
}, element);
if (library_namespace.is_Object(drop_handler)) {
library_namespace.debug('adding drop handler.');
set_drop_target.add_handler(drop_handler);
}
return element;
}
set_drop_target.handler = Object.create(null);
/**
* 為 drop 的 type 設定 handler.
*
* @param {Object}handler_hash
* 欲設定的 handler.<br />
* e.g., {type_name : handler },<br />
* e.g., { type_name : { id : handler } }
*/
set_drop_target.add_handler = function add_handler(handler_hash) {
if (!library_namespace.is_Object(handler_hash)) {
return;
}
var type_name, handler_list, handler, id;
for (type_name in handler_hash) {
library_namespace.debug('adding [' + type_name + '].');
handler_list = set_drop_target.handler[type_name];
if (!Array.isArray(handler_list))
set_drop_target.handler[type_name] = handler_list = [];
handler = handler_hash[type_name];
library_namespace.debug('adding [' + type_name + '] ' + handler, 1, 'set_drop_target.add_handler');
if (library_namespace.is_Function(handler)) {
handler_list.push(handler);
} else if (library_namespace.is_Object(handler)) {
for (id in handler)
handler_list[id] = handler[id];
} else {
library_namespace.warn('unknown handler: ' + handler);
}
}
};
_// JSDT:_module_
.
set_drop_target = set_drop_target;
// <a href="http://www.w3.org/TR/FileAPI/" accessdate="2011/11/5 15:33">File API</a>
_// JSDT:_module_
.
read_files = function(files, handler, index) {
// check files type
if (!library_namespace.is_type(files, 'FileList')) {
if(handler && typeof handler.error === 'function')
//handler.error.call(null);
handler.error();
return;
}
if(isNaN(index)){
// 初始化 initialization
handler = _.read_file.regular_handler(handler);
index = 0;
}
// 依序讀入個別檔案內容。
_.read_file(files[index], [ handler, {
loadend : function() {
if (++index < files.length)
_.read_files(files, handler, index);
}
} ]);
};
// <a href="http://www.w3.org/TR/FileAPI/" accessdate="2011/11/5 15:33">File API</a>
function read_file(file, handler, encoding, start, end) {
var blob, reader = library_namespace.is_WWW(true)
//
&& window.FileReader && new window.FileReader();
if (!reader) {
library_namespace.error('read_file: This browser / platform does not support FileReader.');
return;
}
// check file type
if (!library_namespace.is_type(file, 'File')) {
if(handler && typeof handler.error === 'function')
//handler.error.call(null);
handler.error();
return;
}
// 非標準! 但這樣設定後event handler 中即可使用 this.file 取得相關資訊。
reader.file = file;
add_listener( [ _.read_file.regular_handler(handler), {
error : function(event) {
var error = event.target.error, code = error.code, message;
switch (code) {
case error.NOT_FOUND_ERR:
message = 'File [' + file.name + '] Not Found!';
break;
case error.NOT_READABLE_ERR:
message = 'File [' + file.name + '] is not readable!';
break;
case error.ABORT_ERR:
message = 'User aborted reading [' + file.name + '].';
break;
case error.SECURITY_ERR:
// 多是因不能 DnD local files.
message = 'Security error to read [' + file.name + '].';
break;
default:
error = _.read_file.code_to_name || (_.read_file.code_to_name = swap_key_value(error, [], /^[A-Z_\-\d]+$/));
if (code in error)
message = '<em>' + error[code] + '</em> to read [' + file.name + '].';
}
library_namespace.warn('read_file: ' + (message || 'Error ' + code + ' to read [' + file.name + '].'));
},
loadend : function() {
// 預防 memory leak.
delete reader.file;
//library_namespace.debug('reader.file deleted.', 2, 'read_file');
}
} ], reader);
if (start || end) {
if (isNaN(start = parseInt(start))
|| start < 0)
start = 0;
if (!isNaN(end = parseInt(end))
&& end > start && end < file.size)
blob = file.slice ? file.slice(start, end)
: file.webkitSlice ? file.webkitSlice(start, end)
: file.mozSlice && file.mozSlice(start, end);
}
if(!blob)
blob = file;
library_namespace.debug('read-in [' + file.name + ']' + (encoding ? ' as ' + encoding : '') + '.', 0, 'read_file');
if ((!encoding || encoding === 'binary')
// IE10 沒有 .readAsBinaryString
&& reader.readAsBinaryString)
reader.readAsBinaryString(blob);
else if(encoding === 'url')
reader.readAsDataURL(blob);
else
// UTF-8 is assumed if this parameter is not specified.
// https://developer.mozilla.org/en/DOM/FileReader
reader.readAsText(blob, encoding || 'UTF-8');
};
read_file.regular_handler = function(handler) {
if (typeof handler === 'function')
handler = {
load : handler
};
if (library_namespace.is_Object(handler)) {
if (typeof handler.status === 'string')
handler.status = get_element(handler.status);
if (is_HTML_element(handler.status)) {
// progress bar
var progress_bar = handler.status;
if(!handler.progress)
handler.progress = function(event) {
if (event.lengthComputable) {
// 讀取比例
//var percent_loaded;
set_text(progress_bar, '[' + this.file.name + '] ' +
(progress_bar.style.width = Math.round(event.loaded / event.total * 100) + '%'));
}
};
if(!handler.load)
handler.load = function(event) {
set_text(progress_bar, '[' + this.file.name + '] loaded.');
};
delete handler.status;
}
}
return handler;
};
_// JSDT:_module_
.
read_file = read_file;
// about drag-and-drop @ IE6 ---------------------------
/*
2008/1/24 0:51:17
*/
//CSS of body
get_drag_path.bCSS = 'margin:0;padding:.2em;color:#e42;background-color:#eff;';
// default contents in HTML
get_drag_path.dC = '<em>Drop Here</em> (不能拖曳多個物件)';
// show infomation after every drag
get_drag_path.show = 1;
// drag object
get_drag_path.o = 'dropT';
// 每次執行完是否應顯示
get_drag_path.shouldShow = function(o) {
return o == showM.so;
};
// href Object & Array
get_drag_path.href_hash = Object.create(null);
get_drag_path.href_list = [];
// 未設定目錄。拖曳功能只在 IE6 有效。
get_drag_path.able = function() {
var n = window ? window.navigator : 0;
try {
return n && (n = n.appVersion) && (n = n.match(/MSIE (\d+)/))
&& n[1] == 6;
} catch (e) {
// 呼叫 navigator.* 可能有 -2147024882 "存放裝置空間不足,無法完成此操作。"
// http://www.dotblogs.com.tw/alonstar/archive/2008/10/09/5625.aspx
// 結果原來是我的機碼不知道為什麼多了一大堆.NET CLR 3.0的版本,找了一台正常的比對之後,把多的機碼刪除就好了。
// HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings\5.0\User Agent\Post Platform
return !!get_drag_path.href_list;
}
};
get_drag_path.add = function(p) {
// sl('get_drag_path: add path ['+p+']');
// 不能計算數目:不準 可能會有 file:///, http:// 等
get_drag_path.href_hash[this.href = p] = 1;
};
// 每 get_drag_path.interval 執行一次
function get_drag_path() {
var _s = arguments.callee,
// 或者直接用 dropT.location.href不透過 document.getElementById.
o = document.getElementById(_s.o), w = o.contentWindow, bU = 'about:blank', i, t = [];
if (w.location.href != _s.href || w.location.href != bU) {
// 處理中隱藏,預防此時再被拖進。
o.style.display = 'none';
if (w.location.href != bU) {
// sl('get_drag_path: get href ['+w.location.href+']');
i = unescape(getPathOnly(w.location.href));
// sl('get_drag_path: get unescaped href ['+i+']');
// NOT GOOD: if(!i.indexOf('file:///'))i=getFP(getPathOnly(i));
// drag 的都是完整 path。getPathOnly 應該先於 unescape預防 # 等字元。
if (/^[a-z]:\//i.test(i))
i = getFP(i.replace(/\//g, '\\'));
_s.add(i);
w.location.href = bU;
if (_s.show)
_s.d(), _s.afterAdd && _s.afterAdd();
}
if (bU == w.location.href)
// 用 try: 有時 about:blank 還沒設定好
try {
// 無法用 className
var s = w.document.body;
s.style.cssText = _s.bCSS;
// 只能在 about:blank 設定
s.innerHTML = _s.dC;
var s = _s.shouldShow;
o.style.display = (typeof s === 'function' ? s(_s.o) : s) ? 'block'
: 'none';
} catch (e) {
}
}
return _s.href;
}
// delete url in collection
get_drag_path.d = function(u) {
if (u === 1) {
get_drag_path.href_hash = Object.create(null);
return;
} else if (u in get_drag_path.href_hash)
delete get_drag_path.href_hash[u];
get_drag_path.href_list = [];
var t = [];
for (i in get_drag_path.href_hash){
get_drag_path.href_list.push(i);
t.push('<div><b style="cursor:pointer;color:#e22;" onclick="get_drag_path.d(this.parentNode.childNodes[2].innerHTML);">[delete]</b> <span>'
+ i + '</span></div>');
}
// get_drag_path.href_list.sort();
sl('last dragged: '
+ this.href
+ (t.length > 1 ? '<hr />[' + t.length + '] get_drag_path.href_list:<br />'
+ t.join('') : ''));
return get_drag_path.href_list;
};
//get_drag_path.afterAdd = function() {};
return (
_// JSDT:_module_
);
}
});