mirror of
https://scm.univ-tours.fr/22107988t/rappaurio-sae501_502.git
synced 2025-08-29 22:25:58 +02:00
477 lines
15 KiB
JavaScript
477 lines
15 KiB
JavaScript
|
||
/**
|
||
* @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, '<') + ']',
|
||
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, '<')
|
||
+ ']', 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_
|
||
);
|
||
}
|
||
|
||
|
||
});
|
||
|