2019年3月8日 星期五
一個 promise 再包裝的例子
'use strict';
/**
* Promise
*
* Inspired by https://gist.github.com/RubaXa/8501359 from RubaXa <trash@rubaxa.org>
*
* @param {Function} handler Called as handler(resolve: Function, reject: Function)
* @param {Promise} [parent] Parent promise for propagation of cancel and timeout
*/
function Promise(handler, parent) {
var me = this;
if (!(this instanceof Promise)) {
throw new SyntaxError('Constructor must be called with the new operator');
}
if (typeof handler !== 'function') {
throw new SyntaxError('Function parameter handler(resolve, reject) missing');
}
var _onSuccess = [];
var _onFail = [];
// status
this.resolved = false;
this.rejected = false;
this.pending = true;
/**
* Process onSuccess and onFail callbacks: add them to the queue.
* Once the promise is resolve, the function _promise is replace.
* @param {Function} onSuccess
* @param {Function} onFail
* @private
*/
var _process = function (onSuccess, onFail) {
_onSuccess.push(onSuccess);
_onFail.push(onFail);
};
/**
* Add an onSuccess callback and optionally an onFail callback to the Promise
* @param {Function} onSuccess
* @param {Function} [onFail]
* @returns {Promise} promise
*/
this.then = function (onSuccess, onFail) {
return new Promise(function (resolve, reject) {
var s = onSuccess ? _then(onSuccess, resolve, reject) : resolve;
var f = onFail ? _then(onFail, resolve, reject) : reject;
_process(s, f);
}, me);
};
/**
* Resolve the promise
* @param {*} result
* @type {Function}
*/
var _resolve = function (result) {
// update status
me.resolved = true;
me.rejected = false;
me.pending = false;
_onSuccess.forEach(function (fn) {
fn(result);
});
_process = function (onSuccess, onFail) {
onSuccess(result);
};
_resolve = _reject = function () { };
return me;
};
/**
* Reject the promise
* @param {Error} error
* @type {Function}
*/
var _reject = function (error) {
// update status
me.resolved = false;
me.rejected = true;
me.pending = false;
_onFail.forEach(function (fn) {
fn(error);
});
_process = function (onSuccess, onFail) {
onFail(error);
};
_resolve = _reject = function () { }
return me;
};
/**
* Cancel te promise. This will reject the promise with a CancellationError
* @returns {Promise} self
*/
this.cancel = function () {
if (parent) {
parent.cancel();
} else {
_reject(new CancellationError());
}
return me;
};
/**
* Set a timeout for the promise. If the promise is not resolved within
* the time, the promise will be cancelled and a TimeoutError is thrown.
* If the promise is resolved in time, the timeout is removed.
* @param {number} delay Delay in milliseconds
* @returns {Promise} self
*/
this.timeout = function (delay) {
if (parent) {
parent.timeout(delay);
} else {
var timer = setTimeout(function () {
_reject(new TimeoutError('Promise timed out after ' + delay + ' ms'));
}, delay);
me.always(function () {
clearTimeout(timer);
});
}
return me;
};
// attach handler passing the resolve and reject functions
handler(function (result) {
_resolve(result);
}, function (error) {
_reject(error);
});
}
/**
* Execute given callback, then call resolve/reject based on the returned result
* @param {Function} callback
* @param {Function} resolve
* @param {Function} reject
* @returns {Function}
* @private
*/
function _then(callback, resolve, reject) {
return function (result) {
try {
var res = callback(result);
if (res && typeof res.then === 'function' && typeof res['catch'] === 'function') {
// method returned a promise
res.then(resolve, reject);
} else {
resolve(res);
}
} catch (error) {
reject(error);
}
}
}
/**
* Add an onFail callback to the Promise
* @param {Function} onFail
* @returns {Promise} promise
*/
Promise.prototype['catch'] = function (onFail) {
return this.then(null, onFail);
};
// TODO: add support for Promise.catch(Error, callback)
// TODO: add support for Promise.catch(Error, Error, callback)
/**
* Execute given callback when the promise either resolves or rejects.
* @param {Function} fn
* @returns {Promise} promise
*/
Promise.prototype.always = function (fn) {
return this.then(fn, fn);
};
/**
* Create a promise which resolves when all provided promises are resolved,
* and fails when any of the promises resolves.
* @param {Promise[]} promises
* @returns {Promise} promise
*/
Promise.all = function (promises) {
return new Promise(function (resolve, reject) {
var remaining = promises.length,
results = [];
if (remaining) {
promises.forEach(function (p, i) {
p.then(function (result) {
results[i] = result;
remaining--;
if (remaining == 0) {
resolve(results);
}
}, function (error) {
remaining = 0;
reject(error);
});
});
} else {
resolve(results);
}
});
};
/**
* Create a promise resolver
* @returns {{promise: Promise, resolve: Function, reject: Function}} resolver
*/
Promise.defer = function () {
var resolver = {};
resolver.promise = new Promise(function (resolve, reject) {
resolver.resolve = resolve;
resolver.reject = reject;
});
return resolver;
};
/**
* Create a cancellation error
* @param {String} [message]
* @extends Error
*/
function CancellationError(message) {
this.message = message || 'promise cancelled';
this.stack = (new Error()).stack;
}
CancellationError.prototype = new Error();
CancellationError.prototype.constructor = Error;
CancellationError.prototype.name = 'CancellationError';
Promise.CancellationError = CancellationError;
/**
* Create a timeout error
* @param {String} [message]
* @extends Error
*/
function TimeoutError(message) {
this.message = message || 'timeout exceeded';
this.stack = (new Error()).stack;
}
TimeoutError.prototype = new Error();
TimeoutError.prototype.constructor = Error;
TimeoutError.prototype.name = 'TimeoutError';
Promise.TimeoutError = TimeoutError;
module.exports = Promise;
2019年3月7日 星期四
worker 環境判定
if(typeof Window !== 'undefined'){
// browser
}else if(typeof WorkerGlobalScope !== 'undefined'){
// browser worker
}else if(typeof module !== 'undefined'){
// node.js
const {isMainThread} = require('worker_threads');
if(isMainThread){
// MainThread
}else{
// worker
}
}
// browser
}else if(typeof WorkerGlobalScope !== 'undefined'){
// browser worker
}else if(typeof module !== 'undefined'){
// node.js
const {isMainThread} = require('worker_threads');
if(isMainThread){
// MainThread
}else{
// worker
}
}
2019年3月5日 星期二
不同系統的換行符號
str.replace(/(\r\n|\n)/, '')
|一、概念:
換行符‘\n’和回車符‘\r’
(1)換行符就是另起一行 — ‘\n‘ 10 換行(newline)
(2)回車符就是回到一行的開頭 — ‘\r‘ 13 回車(return)
所以我們平時編寫檔案的回車符應該確切來說叫做回車換行符
CR: 回車(Carriage Return) \r
LF: 換行(Line Feed) \n
二、應用:
(1)在微軟的MS-DOS和Windows中,使用“回車CR(‘\r’)”和“換行LF(‘\n’)”兩個字元作為換行符;
(2)Windows系統裡面,每行結尾是 回車 換行(CR LF),即“\r\n”;
(3)Unix系統裡,每行結尾只有 換行LF,即“\n”;
(4)Mac系統裡,每行結尾是 回車CR 即’\r’。
Mac OS 9 以及之前的系統的換行符是 CR,從 Mac OS X (後來改名為“OS X”)開始的換行符是 LF即‘\n’,和Unix/Linux統一了。
三、影響:
(1)一個直接後果是,Unix/Mac系統下的檔案在Windows裡開啟的話,所有文字會變成一行;
(2)而Windows裡的檔案在Unix/Mac下開啟的話,在每行的結尾可能會多出一個^M符號。
(3)Linux儲存的檔案在windows上用記事本看的話會出現黑點。
四、可以相互轉換:
在linux下,命令unix2dos 是把linux檔案格式轉換成windows檔案格式,命令dos2unix 是把windows格式轉換成linux檔案格式。
在不同平臺間使用FTP軟體傳送檔案時, 在ascii文字模式傳輸模式下, 一些FTP客戶端程式會自動對換行格式進行轉換. 經過這種傳輸的檔案位元組數可能會發生變化.
如果你不想ftp修改原檔案, 可以使用bin模式(二進位制模式)傳輸文字。
一個程式在windows上執行就生成CR/LF換行格式的文字檔案,而在Linux上執行就生成LF格式換行的文字檔案。
|一、概念:
換行符‘\n’和回車符‘\r’
(1)換行符就是另起一行 — ‘\n‘ 10 換行(newline)
(2)回車符就是回到一行的開頭 — ‘\r‘ 13 回車(return)
所以我們平時編寫檔案的回車符應該確切來說叫做回車換行符
CR: 回車(Carriage Return) \r
LF: 換行(Line Feed) \n
二、應用:
(1)在微軟的MS-DOS和Windows中,使用“回車CR(‘\r’)”和“換行LF(‘\n’)”兩個字元作為換行符;
(2)Windows系統裡面,每行結尾是 回車 換行(CR LF),即“\r\n”;
(3)Unix系統裡,每行結尾只有 換行LF,即“\n”;
(4)Mac系統裡,每行結尾是 回車CR 即’\r’。
Mac OS 9 以及之前的系統的換行符是 CR,從 Mac OS X (後來改名為“OS X”)開始的換行符是 LF即‘\n’,和Unix/Linux統一了。
三、影響:
(1)一個直接後果是,Unix/Mac系統下的檔案在Windows裡開啟的話,所有文字會變成一行;
(2)而Windows裡的檔案在Unix/Mac下開啟的話,在每行的結尾可能會多出一個^M符號。
(3)Linux儲存的檔案在windows上用記事本看的話會出現黑點。
四、可以相互轉換:
在linux下,命令unix2dos 是把linux檔案格式轉換成windows檔案格式,命令dos2unix 是把windows格式轉換成linux檔案格式。
在不同平臺間使用FTP軟體傳送檔案時, 在ascii文字模式傳輸模式下, 一些FTP客戶端程式會自動對換行格式進行轉換. 經過這種傳輸的檔案位元組數可能會發生變化.
如果你不想ftp修改原檔案, 可以使用bin模式(二進位制模式)傳輸文字。
一個程式在windows上執行就生成CR/LF換行格式的文字檔案,而在Linux上執行就生成LF格式換行的文字檔案。
2019年2月26日 星期二
拖曳一個小方塊.......不錯用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="./js_lib/jquery-3.3.1.js"></script>
<style>
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
body {
position: relative;
}
div.container_1 {
height: 1000px;
background-color: #ffc;
position: relative;
}
#moveEvent {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
border: 1px dashed;
z-index: 99999;
display: none;
user-select: none;
opacity: 0;
}
#box_1 {
width: 100px;
height: 100px;
position: absolute;
top: 50px;
left: 100px;
z-index: 100;
background-color: #00F;
user-select: none;
}
</style>
</head>
<body>
<div id="moveEvent">
<!-- 全螢幕的畫布 -->
</div>
<div class="container_1">
<p id="box_1">
box
</p>
</div>
<script>
// screen 與 #box_1 的座標差
let topOffset;
let leftOffset;
let callback;
$('#box_1').on('mousedown', function (e) {
console.dir(e);
let { left, top } = $(this).position();
topOffset = top - e.screenY;
leftOffset = left - e.screenX;
//-----------------------
callback = (function (leftOffset, topOffset, x, y) {
let left = x + leftOffset;
let top = y + topOffset;
$('#box_1').css({
top: top,
left: left
});
}).bind(this, leftOffset, topOffset);
//-----------------------
$('#moveEvent').css('display', 'block');
});
$('#moveEvent').on('mousemove', function (e) {
console.log('offset:(%s, %s)', e.offsetX, e.offsetY);
console.log('screen(%s, %s)', e.screenX, e.screenY);
if(callback){
callback(e.screenX, e.screenY);
}
});
$('#moveEvent').on('mouseup', function () {
callback = undefined;
$('#moveEvent').css('display', '');
});
</script>
</body>
</html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="./js_lib/jquery-3.3.1.js"></script>
<style>
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
body {
position: relative;
}
div.container_1 {
height: 1000px;
background-color: #ffc;
position: relative;
}
#moveEvent {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
border: 1px dashed;
z-index: 99999;
display: none;
user-select: none;
opacity: 0;
}
#box_1 {
width: 100px;
height: 100px;
position: absolute;
top: 50px;
left: 100px;
z-index: 100;
background-color: #00F;
user-select: none;
}
</style>
</head>
<body>
<div id="moveEvent">
<!-- 全螢幕的畫布 -->
</div>
<div class="container_1">
<p id="box_1">
box
</p>
</div>
<script>
// screen 與 #box_1 的座標差
let topOffset;
let leftOffset;
let callback;
$('#box_1').on('mousedown', function (e) {
console.dir(e);
let { left, top } = $(this).position();
topOffset = top - e.screenY;
leftOffset = left - e.screenX;
//-----------------------
callback = (function (leftOffset, topOffset, x, y) {
let left = x + leftOffset;
let top = y + topOffset;
$('#box_1').css({
top: top,
left: left
});
}).bind(this, leftOffset, topOffset);
//-----------------------
$('#moveEvent').css('display', 'block');
});
$('#moveEvent').on('mousemove', function (e) {
console.log('offset:(%s, %s)', e.offsetX, e.offsetY);
console.log('screen(%s, %s)', e.screenX, e.screenY);
if(callback){
callback(e.screenX, e.screenY);
}
});
$('#moveEvent').on('mouseup', function () {
callback = undefined;
$('#moveEvent').css('display', '');
});
</script>
</body>
</html>
2019年2月25日 星期一
yahoo serialize
/*
Copyright (c) 2014, Yahoo! Inc. All rights reserved.
Copyrights licensed under the New BSD License.
See the accompanying LICENSE file for terms.
*/
'use strict';
// Generate an internal UID to make the regexp pattern harder to guess.
var UID = Math.floor(Math.random() * 0x10000000000).toString(16);
var PLACE_HOLDER_REGEXP = new RegExp('"@__(F|R|D)-' + UID + '-(\\d+)__@"', 'g');
var IS_NATIVE_CODE_REGEXP = /\{\s*\[native code\]\s*\}/g;
var UNSAFE_CHARS_REGEXP = /[<>\/\u2028\u2029]/g;
// Mapping of unsafe HTML and invalid JavaScript line terminator chars to their
// Unicode char counterparts which are safe to use in JavaScript strings.
var ESCAPED_CHARS = {
'<' : '\\u003C',
'>' : '\\u003E',
'/' : '\\u002F',
'\u2028': '\\u2028',
'\u2029': '\\u2029'
};
function escapeUnsafeChars(unsafeChar) {
return ESCAPED_CHARS[unsafeChar];
}
module.exports = function serialize(obj, options) {
options || (options = {});
// Backwards-compatability for `space` as the second argument.
if (typeof options === 'number' || typeof options === 'string') {
options = {space: options};
}
var functions = [];
var regexps = [];
var dates = [];
// Returns placeholders for functions and regexps (identified by index)
// which are later replaced by their string representation.
function replacer(key, value) {
if (!value) {
return value;
}
// If the value is an object w/ a toJSON method, toJSON is called before
// the replacer runs, so we use this[key] to get the non-toJSONed value.
var origValue = this[key];
var type = typeof origValue;
if (type === 'object') {
if(origValue instanceof RegExp) {
return '@__R-' + UID + '-' + (regexps.push(origValue) - 1) + '__@';
}
if(origValue instanceof Date) {
return '@__D-' + UID + '-' + (dates.push(origValue) - 1) + '__@';
}
}
if (type === 'function') {
return '@__F-' + UID + '-' + (functions.push(origValue) - 1) + '__@';
}
return value;
}
var str;
// Creates a JSON string representation of the value.
// NOTE: Node 0.12 goes into slow mode with extra JSON.stringify() args.
if (options.isJSON && !options.space) {
str = JSON.stringify(obj);
} else {
str = JSON.stringify(obj, options.isJSON ? null : replacer, options.space);
}
// Protects against `JSON.stringify()` returning `undefined`, by serializing
// to the literal string: "undefined".
if (typeof str !== 'string') {
return String(str);
}
// Replace unsafe HTML and invalid JavaScript line terminator chars with
// their safe Unicode char counterpart. This _must_ happen before the
// regexps and functions are serialized and added back to the string.
str = str.replace(UNSAFE_CHARS_REGEXP, escapeUnsafeChars);
if (functions.length === 0 && regexps.length === 0 && dates.length === 0) {
return str;
}
// Replaces all occurrences of function, regexp and date placeholders in the
// JSON string with their string representations. If the original value can
// not be found, then `undefined` is used.
return str.replace(PLACE_HOLDER_REGEXP, function (match, type, valueIndex) {
if (type === 'D') {
return "new Date(\"" + dates[valueIndex].toISOString() + "\")";
}
if (type === 'R') {
return regexps[valueIndex].toString();
}
var fn = functions[valueIndex];
var serializedFn = fn.toString();
if (IS_NATIVE_CODE_REGEXP.test(serializedFn)) {
throw new TypeError('Serializing native function: ' + fn.name);
}
return serializedFn;
});
}
Copyright (c) 2014, Yahoo! Inc. All rights reserved.
Copyrights licensed under the New BSD License.
See the accompanying LICENSE file for terms.
*/
'use strict';
// Generate an internal UID to make the regexp pattern harder to guess.
var UID = Math.floor(Math.random() * 0x10000000000).toString(16);
var PLACE_HOLDER_REGEXP = new RegExp('"@__(F|R|D)-' + UID + '-(\\d+)__@"', 'g');
var IS_NATIVE_CODE_REGEXP = /\{\s*\[native code\]\s*\}/g;
var UNSAFE_CHARS_REGEXP = /[<>\/\u2028\u2029]/g;
// Mapping of unsafe HTML and invalid JavaScript line terminator chars to their
// Unicode char counterparts which are safe to use in JavaScript strings.
var ESCAPED_CHARS = {
'<' : '\\u003C',
'>' : '\\u003E',
'/' : '\\u002F',
'\u2028': '\\u2028',
'\u2029': '\\u2029'
};
function escapeUnsafeChars(unsafeChar) {
return ESCAPED_CHARS[unsafeChar];
}
module.exports = function serialize(obj, options) {
options || (options = {});
// Backwards-compatability for `space` as the second argument.
if (typeof options === 'number' || typeof options === 'string') {
options = {space: options};
}
var functions = [];
var regexps = [];
var dates = [];
// Returns placeholders for functions and regexps (identified by index)
// which are later replaced by their string representation.
function replacer(key, value) {
if (!value) {
return value;
}
// If the value is an object w/ a toJSON method, toJSON is called before
// the replacer runs, so we use this[key] to get the non-toJSONed value.
var origValue = this[key];
var type = typeof origValue;
if (type === 'object') {
if(origValue instanceof RegExp) {
return '@__R-' + UID + '-' + (regexps.push(origValue) - 1) + '__@';
}
if(origValue instanceof Date) {
return '@__D-' + UID + '-' + (dates.push(origValue) - 1) + '__@';
}
}
if (type === 'function') {
return '@__F-' + UID + '-' + (functions.push(origValue) - 1) + '__@';
}
return value;
}
var str;
// Creates a JSON string representation of the value.
// NOTE: Node 0.12 goes into slow mode with extra JSON.stringify() args.
if (options.isJSON && !options.space) {
str = JSON.stringify(obj);
} else {
str = JSON.stringify(obj, options.isJSON ? null : replacer, options.space);
}
// Protects against `JSON.stringify()` returning `undefined`, by serializing
// to the literal string: "undefined".
if (typeof str !== 'string') {
return String(str);
}
// Replace unsafe HTML and invalid JavaScript line terminator chars with
// their safe Unicode char counterpart. This _must_ happen before the
// regexps and functions are serialized and added back to the string.
str = str.replace(UNSAFE_CHARS_REGEXP, escapeUnsafeChars);
if (functions.length === 0 && regexps.length === 0 && dates.length === 0) {
return str;
}
// Replaces all occurrences of function, regexp and date placeholders in the
// JSON string with their string representations. If the original value can
// not be found, then `undefined` is used.
return str.replace(PLACE_HOLDER_REGEXP, function (match, type, valueIndex) {
if (type === 'D') {
return "new Date(\"" + dates[valueIndex].toISOString() + "\")";
}
if (type === 'R') {
return regexps[valueIndex].toString();
}
var fn = functions[valueIndex];
var serializedFn = fn.toString();
if (IS_NATIVE_CODE_REGEXP.test(serializedFn)) {
throw new TypeError('Serializing native function: ' + fn.name);
}
return serializedFn;
});
}
2019年2月13日 星期三
java swing 刊誤
p525>>
import java.awt.event.*;
import java.awt.Window;
public class BasicWindowMonitor extends WindowAdapter {
public void windowClosing(WindowEvent e) {
Window w = e.getWindow();
w.setVisible(false);
w.dispose();
System.exit(0);
}
}
2019年2月9日 星期六
node.js 路徑
// 專案目錄位置
const root = fs.realpathSync('./');
require(`${root}/node_modules/..........`);
process.cwd()
批配套嵌的 script 標籤
// 否定式前向搜索
target = '<script><script>555</script></script>'
reg = <script>(?!.*<script>).*?</script>
2019年2月3日 星期日
java 取得物件資訊
static void getClassInfo(Object o) {
Class c = o.getClass();
// 取得套件代表物件
Package p = c.getPackage();
out.printf("package %s;%n", p.getName());
// 取得型態修飾,像是public、final
int m = c.getModifiers();
out.print(Modifier.toString(m) + " ");
// 如果是介面
if (Modifier.isInterface(m)) {
out.print("interface ");
} else {
out.print("class ");
}
out.println(c.getName() + " {");
//-----------------------
// 取得宣告的資料成員代表物件
Field[] fields = c.getDeclaredFields();
for (Field field : fields) {
// 顯示權限修飾,像是public、protected、private
out.print("\t"
+ Modifier.toString(field.getModifiers()));
// 顯示型態名稱
out.print(" "
+ field.getType().getName() + " ");
// 顯示資料成員名稱
out.println(field.getName() + ";");
}
out.println("----------------------");
//-----------------------
Method[] methods = c.getDeclaredMethods();
for (Method method : methods) {
// 顯示權限修飾,像是public、protected、private
out.print("\t"
+ Modifier.toString(
method.getModifiers()));
// 顯示返回值型態名稱
out.print(" "
+ method.getReturnType().getName() + " ");
// 顯示方法名稱
out.println(method.getName() + "();");
}
out.println("}");
}
Class c = o.getClass();
// 取得套件代表物件
Package p = c.getPackage();
out.printf("package %s;%n", p.getName());
// 取得型態修飾,像是public、final
int m = c.getModifiers();
out.print(Modifier.toString(m) + " ");
// 如果是介面
if (Modifier.isInterface(m)) {
out.print("interface ");
} else {
out.print("class ");
}
out.println(c.getName() + " {");
//-----------------------
// 取得宣告的資料成員代表物件
Field[] fields = c.getDeclaredFields();
for (Field field : fields) {
// 顯示權限修飾,像是public、protected、private
out.print("\t"
+ Modifier.toString(field.getModifiers()));
// 顯示型態名稱
out.print(" "
+ field.getType().getName() + " ");
// 顯示資料成員名稱
out.println(field.getName() + ";");
}
out.println("----------------------");
//-----------------------
Method[] methods = c.getDeclaredMethods();
for (Method method : methods) {
// 顯示權限修飾,像是public、protected、private
out.print("\t"
+ Modifier.toString(
method.getModifiers()));
// 顯示返回值型態名稱
out.print(" "
+ method.getReturnType().getName() + " ");
// 顯示方法名稱
out.println(method.getName() + "();");
}
out.println("}");
}
2019年2月2日 星期六
操控點位移(不錯的版本)
<pre>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style media="screen">
*{
padding: 0;
margin: 0;
box-sizing: border-box;
}
.main_container{
width: 400px;
height:300px;
background-color: #FCC;
position: relative;
}
.symbol {
width: 100%;
height: 100%;
}
.operator{
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
}
p.box{
position: absolute;
left: 0;
top: 0;
width: 20px;
height: 20px;
background-color: #666;
}
</style>
<script src="./js_lib/jquery-3.3.1.min.js" charset="utf-8"></script>
</head>
<body>
<div>
<button type="button" onclick=t_1()>go</button>
</div>
<div class="main_container">
<div id="symbol" class="symbol">
</div>
<div id="operator" class="operator">
<p class="box" id="box_1"></p>
</div>
</div>
<script>
function V(){
this.symbol;
this.operator;
this.box;
this.box_click_left;
this.box_click_top;
this.__construct();
};
(function(){
this.__construct = function(){
debugger;
this.symbol = document.querySelector('#symbol');
this.operator = document.querySelector('#operator');
this.box = document.querySelector('#box_1');
$(this.box).on('mousedown', (function(e){
this.event_1(e);
}).bind(this));
$(this.operator).on('mouseup', (function(e){
this.event_2(e);
}).bind(this));
};
//----------------------------
this.event_1 = function(e){
// debugger;
this.box_click_left = e.offsetX;
this.box_click_top = e.offsetY;
$(this.box).appendTo(this.symbol);
$(this.operator).on('mousemove', (function(e){
this.event_3(e);
}).bind(this));
};
//----------------------------
this.event_2 = function(e){
$(this.operator).off('mousemove');
$(this.box).appendTo(this.operator);
};
//----------------------------
this.event_3 = function(e){
console.log('(%s, %s)', e.offsetX, e.offsetY);
let x= e.offsetX - this.box_click_left;
let y = e.offsetY - this.box_click_top;
$(this.box).css({
left: x,
top: y
});
};
}).call(V.prototype);
new V();
</script>
</body>
</html>
</pre>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style media="screen">
*{
padding: 0;
margin: 0;
box-sizing: border-box;
}
.main_container{
width: 400px;
height:300px;
background-color: #FCC;
position: relative;
}
.symbol {
width: 100%;
height: 100%;
}
.operator{
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
}
p.box{
position: absolute;
left: 0;
top: 0;
width: 20px;
height: 20px;
background-color: #666;
}
</style>
<script src="./js_lib/jquery-3.3.1.min.js" charset="utf-8"></script>
</head>
<body>
<div>
<button type="button" onclick=t_1()>go</button>
</div>
<div class="main_container">
<div id="symbol" class="symbol">
</div>
<div id="operator" class="operator">
<p class="box" id="box_1"></p>
</div>
</div>
<script>
function V(){
this.symbol;
this.operator;
this.box;
this.box_click_left;
this.box_click_top;
this.__construct();
};
(function(){
this.__construct = function(){
debugger;
this.symbol = document.querySelector('#symbol');
this.operator = document.querySelector('#operator');
this.box = document.querySelector('#box_1');
$(this.box).on('mousedown', (function(e){
this.event_1(e);
}).bind(this));
$(this.operator).on('mouseup', (function(e){
this.event_2(e);
}).bind(this));
};
//----------------------------
this.event_1 = function(e){
// debugger;
this.box_click_left = e.offsetX;
this.box_click_top = e.offsetY;
$(this.box).appendTo(this.symbol);
$(this.operator).on('mousemove', (function(e){
this.event_3(e);
}).bind(this));
};
//----------------------------
this.event_2 = function(e){
$(this.operator).off('mousemove');
$(this.box).appendTo(this.operator);
};
//----------------------------
this.event_3 = function(e){
console.log('(%s, %s)', e.offsetX, e.offsetY);
let x= e.offsetX - this.box_click_left;
let y = e.offsetY - this.box_click_top;
$(this.box).css({
left: x,
top: y
});
};
}).call(V.prototype);
new V();
</script>
</body>
</html>
</pre>
訂閱:
文章 (Atom)