├── .gitignore ├── README.md ├── ex ├── 2 │ ├── 2-1.html │ └── 2-2.html ├── 3 │ ├── 3-1.html │ ├── 3-2.html │ ├── 3-3-1.html │ └── 3-3-2.html ├── 4 │ ├── 4-1.html │ └── 4-2.html ├── 5 │ ├── 5-1.html │ └── 5-2.html ├── 6 │ ├── 6-1-1.html │ ├── 6-1-2.html │ ├── 6-1-3.html │ ├── 6-1-4.html │ ├── 6-2-1.html │ ├── 6-2-2.html │ ├── 6-2-3.html │ ├── 6-3-1.html │ └── 6-3-2.html ├── 7 │ ├── 7-1.html │ └── 7-2.html ├── 8 │ ├── 8-1.html │ ├── 8-2.html │ ├── 8-3.html │ ├── 8-4.html │ ├── 8-5.html │ ├── 8-6.html │ └── 8-7.html ├── 9 │ ├── 9-1.html │ └── 9-2.html ├── 10 │ ├── 10-1.html │ ├── 10-2.html │ ├── 10-3.html │ ├── 10-4.html │ └── 10-5.html ├── 11 │ ├── 11-1.html │ ├── 11-2.html │ ├── 11-3-1.html │ ├── 11-3-2.html │ └── 11-3-3.html ├── 12 │ ├── 12-1.html │ ├── 12-2-1.html │ └── 12-2-2.html ├── 13 │ ├── 13-1.html │ ├── 13-2.html │ └── 13-3.html ├── 14 │ ├── 14-1-1.html │ ├── 14-1-2.html │ ├── 14-1-3.html │ ├── 14-1-4.html │ ├── 14-1-5.html │ ├── 14-2-1.html │ ├── 14-2-2.html │ ├── 14-3.html │ └── 14-4.html ├── 15 │ ├── 15-1.html │ ├── 15-2.html │ └── 15-3.html ├── 16 │ ├── 16-1.html │ ├── 16-2.html │ └── 16-3.html └── 17 │ ├── 17-1.html │ ├── 17-2-1.html │ ├── 17-2-2.html │ └── 17-3.html ├── ext ├── img_preview │ ├── index01.html │ └── index02.html ├── img_rotate │ ├── fetch.html │ ├── jquery.html │ ├── jquery.ui.rotatable.css │ ├── jquery.ui.rotatable.js │ └── linestickers.php ├── lottery │ ├── custom.js │ └── index.html ├── tts │ ├── fetch.html │ ├── jquery.highlight-within-textarea.css │ ├── jquery.highlight-within-textarea.js │ ├── jquery.html │ ├── sound.php │ └── tmp │ │ └── .gitignore ├── upload_progress │ └── xhr.html └── web_api │ ├── fetch.html │ ├── web_api_coffee.php │ └── xhr.html ├── javascript_basics.docx └── javascript_basics.pdf /.gitignore: -------------------------------------------------------------------------------- 1 | test.html -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # javascript_basics 2 | - JavaScript 課程 - 基礎篇 3 | 4 | ## 安裝工具 5 | 請先安裝 Visual Studio Code,包括以下擴充功能(extensions): 6 | - ~~HTML Boilerplate~~ 7 | - ~~HTML Snippets~~ 8 | - Live Server 9 | 10 | ## 目次 11 | 1. 測試及除錯工具 1 12 | 2. 常數和變數宣告 8 13 | 3. 運算子 13 14 | 4. 字串 19 15 | 5. 取得標籤「元素」 21 16 | 6. 流程控制 26 17 | 7. Object 物件 34 18 | 8. Array陣列 37 19 | 9. JSON 47 20 | 10. 函式的定義 51 21 | 11. 時間與計時器 58 22 | 12. window物件 64 23 | 13. 事件處理 67 24 | 14. 操作DOM 73 25 | 15. 正規表示法 87 26 | 16. AJAX 97 -------------------------------------------------------------------------------- /ex/10/10-1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /ex/10/10-2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /ex/10/10-3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /ex/10/10-4.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 | 36 | 37 | -------------------------------------------------------------------------------- /ex/10/10-5.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /ex/11/11-1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /ex/11/11-2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /ex/11/11-3-1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /ex/11/11-3-2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 | 11 | 12 | 13 | 35 | 36 | -------------------------------------------------------------------------------- /ex/11/11-3-3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 | 11 | 12 | 13 | 14 | 54 | 55 | -------------------------------------------------------------------------------- /ex/12/12-1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /ex/12/12-2-1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /ex/12/12-2-2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 | 11 | 12 | 24 | 25 | -------------------------------------------------------------------------------- /ex/13/13-1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 |
請用滑鼠移過此元素
14 | 15 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /ex/13/13-2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 | 11 |
12 |
請用滑鼠移過此元素
13 |
14 | 15 | 16 | 46 | 47 | -------------------------------------------------------------------------------- /ex/13/13-3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 | 11 | 12 | 28 | 29 | -------------------------------------------------------------------------------- /ex/14/14-1-1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 | 30 | 31 | -------------------------------------------------------------------------------- /ex/14/14-1-2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 | 15 | 16 | 32 | 33 | -------------------------------------------------------------------------------- /ex/14/14-1-3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 | 15 | 16 | 33 | 34 | -------------------------------------------------------------------------------- /ex/14/14-1-4.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 | 15 | 16 | 33 | 34 | -------------------------------------------------------------------------------- /ex/14/14-1-5.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 | 15 | 16 | 26 | 27 | -------------------------------------------------------------------------------- /ex/14/14-2-1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 | 11 | 12 | 13 | 14 | 29 | 30 | -------------------------------------------------------------------------------- /ex/14/14-2-2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 | 11 | 12 | 25 | 26 | -------------------------------------------------------------------------------- /ex/14/14-3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 |

Hello World
Good job!

11 | 12 | 25 | 26 | -------------------------------------------------------------------------------- /ex/14/14-4.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 |

請輸入 5 到 10 之間的數字

11 | 12 | 13 |

14 | 15 | 45 | 46 | -------------------------------------------------------------------------------- /ex/15/15-1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 | 155 | 156 | -------------------------------------------------------------------------------- /ex/15/15-2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 |
11 | 您的身分證字號: 12 | 13 | 14 |
15 | 16 | 31 | 32 | -------------------------------------------------------------------------------- /ex/15/15-3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 |
11 | 您的姓名: 12 | 13 |
14 | 您的 E-mail: 15 | 16 |
17 | 18 |
19 | 20 | 52 | 53 | -------------------------------------------------------------------------------- /ex/16/16-1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 | 11 | 12 | 13 | 14 | 83 | 84 | -------------------------------------------------------------------------------- /ex/16/16-2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 | 11 | 12 | 13 | 14 | 93 | 94 | -------------------------------------------------------------------------------- /ex/16/16-3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 72 | 73 | -------------------------------------------------------------------------------- /ex/17/17-1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /ex/17/17-2-1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /ex/17/17-2-2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /ex/17/17-3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 | 11 | 12 |
13 | 14 | 36 | 37 | -------------------------------------------------------------------------------- /ex/2/2-1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Document 9 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /ex/2/2-2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /ex/3/3-1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Document 9 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /ex/3/3-2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /ex/3/3-3-1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /ex/3/3-3-2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /ex/4/4-1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /ex/4/4-2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /ex/5/5-1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 |

問世間,

11 |

情是何物,

12 |

直教生死相許。

13 | 14 | 19 | -------------------------------------------------------------------------------- /ex/5/5-2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 |

問世間,

11 |

情是何物,

12 |

直教生死相許。

13 | 14 | 24 | 25 | -------------------------------------------------------------------------------- /ex/6/6-1-1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /ex/6/6-1-2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /ex/6/6-1-3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /ex/6/6-1-4.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /ex/6/6-2-1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /ex/6/6-2-2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /ex/6/6-2-3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /ex/6/6-3-1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /ex/6/6-3-2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /ex/7/7-1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /ex/7/7-2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /ex/8/8-1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /ex/8/8-2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 85 | 86 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /ex/8/8-3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /ex/8/8-4.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /ex/8/8-5.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /ex/8/8-6.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /ex/8/8-7.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /ex/9/9-1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 54 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /ex/9/9-2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /ext/img_preview/index01.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 |
14 | 15 | 16 | 17 |

請選擇所要上傳的檔案

18 | 19 | 20 |
21 | 22 | 23 | 選擇檔案 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 | 124 | 125 | -------------------------------------------------------------------------------- /ext/img_preview/index02.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 |
14 | 15 | 16 | 17 |

請選擇所要上傳的檔案

18 | 19 | 20 |
21 | 22 | 23 | 選擇檔案 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 161 | 162 | -------------------------------------------------------------------------------- /ext/img_rotate/fetch.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 21 | 22 | 23 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 138 | 139 | -------------------------------------------------------------------------------- /ext/img_rotate/jquery.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 21 | 22 | 23 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 113 | 114 | -------------------------------------------------------------------------------- /ext/img_rotate/jquery.ui.rotatable.css: -------------------------------------------------------------------------------- 1 | .ui-rotatable-handle { 2 | height: 16px; 3 | width: 16px; 4 | cursor: pointer; 5 | background-image: url(rotate.png); 6 | background-size: 100%; 7 | left: 2px; 8 | bottom: 2px; 9 | } -------------------------------------------------------------------------------- /ext/img_rotate/jquery.ui.rotatable.js: -------------------------------------------------------------------------------- 1 | /* globals define jQuery */ 2 | (function (factory) { 3 | if (typeof define === 'function' && define.amd) { 4 | // AMD. Register as an anonymous module. 5 | define(['jquery'], factory) 6 | } else { 7 | // Browser globals 8 | factory(jQuery) 9 | } 10 | }(function ($) { 11 | $.widget('ui.rotatable', $.ui.mouse, { 12 | widgetEventPrefix: 'rotate', 13 | 14 | options: { 15 | angle: false, // specify an angle in radians (for backward compatability) 16 | degrees: false, // specify angle in degrees 17 | handle: false, // an image to use for a handle 18 | handleOffset: { // where the handle should appear 19 | top: 0, 20 | left: 0 21 | }, 22 | radians: false, // specify angle in radians 23 | rotate: null, // a callback for during rotation 24 | rotationCenterOffset: { // offset the center of the element for rotation 25 | top: 0, 26 | left: 0 27 | }, 28 | snap: false, // boolean flag, should the element snap to a certain rotation? 29 | start: null, // callback when rotation starts 30 | step: 22.5, // angle in degrees that the rotation should be snapped to 31 | stop: null, // callback when rotation stops 32 | transforms: null, // other transforms to performed on the element 33 | wheelRotate: true // boolean flag, should the element rotate when the mousewheel is rotated? 34 | }, 35 | 36 | // accessor for the angle in radians 37 | angle: function (angle) { 38 | if (angle === undefined) { 39 | return this.options.angle 40 | } 41 | this.options.angle = angle 42 | this.elementCurrentAngle = angle 43 | this._performRotation(this.options.angle) 44 | }, 45 | 46 | // calculates the element center if needed and returns it 47 | getElementCenter: function () { 48 | this.elementCenter = this._calculateElementCenter() 49 | return this.elementCenter 50 | }, 51 | 52 | // accessor for the handle 53 | handle: function (handle) { 54 | if (handle === undefined) { 55 | return this.options.handle 56 | } 57 | this.options.handle = handle 58 | }, 59 | 60 | plugins: {}, 61 | 62 | /* accessor for the center of rotation 63 | * takes an object with keys of top and left 64 | */ 65 | rotationCenterOffset: function (offset) { 66 | if (offset === undefined) { 67 | return this.options.rotationCenterOffset 68 | } 69 | if (offset.top !== null) { 70 | this.options.rotationCenterOffset.top = offset.top 71 | } 72 | if (offset.left !== null) { 73 | this.options.rotationCenterOffset.left = offset.left 74 | } 75 | }, 76 | 77 | // listener for rotating the element 78 | rotateElement: function (event) { 79 | if (!this.element || this.element.disabled || this.options.disabled) { 80 | return false 81 | } 82 | 83 | if (!event.which) { 84 | this.stopRotate(event) 85 | return false 86 | } 87 | 88 | var rotateAngle = this._calculateRotateAngle(event) 89 | var previousRotateAngle = this.elementCurrentAngle 90 | this.elementCurrentAngle = rotateAngle 91 | 92 | // Plugins callbacks need to be called first. 93 | this._propagate('rotate', event) 94 | 95 | if (this._propagate('rotate', event) === false) { 96 | this.elementCurrentAngle = previousRotateAngle 97 | return false 98 | } 99 | var ui = this.ui() 100 | if (this._trigger('rotate', event, ui) === false) { 101 | this.elementCurrentAngle = previousRotateAngle 102 | return false 103 | } else if (ui.angle.current !== rotateAngle) { 104 | rotateAngle = ui.angle.current 105 | this.elementCurrentAngle = rotateAngle 106 | } 107 | 108 | this._performRotation(rotateAngle) 109 | 110 | if (previousRotateAngle !== rotateAngle) { 111 | this.hasRotated = true 112 | } 113 | 114 | return false 115 | }, 116 | 117 | // listener for starting rotation 118 | startRotate: function (event) { 119 | var center = this.getElementCenter() 120 | var startXFromCenter = event.pageX - center.x 121 | var startYFromCenter = event.pageY - center.y 122 | this.mouseStartAngle = Math.atan2(startYFromCenter, startXFromCenter) 123 | this.elementStartAngle = this.elementCurrentAngle 124 | this.hasRotated = false 125 | 126 | this._propagate('start', event) 127 | 128 | $(document).bind('mousemove', this.listeners.rotateElement) 129 | $(document).bind('mouseup', this.listeners.stopRotate) 130 | 131 | return false 132 | }, 133 | 134 | // listener for stopping rotation 135 | stopRotate: function (event) { 136 | if (!this.element || this.element.disabled) { 137 | return 138 | } 139 | 140 | $(document).unbind('mousemove', this.listeners.rotateElement) 141 | $(document).unbind('mouseup', this.listeners.stopRotate) 142 | 143 | this.elementStopAngle = this.elementCurrentAngle 144 | 145 | this._propagate('stop', event) 146 | 147 | setTimeout(function () { this.element = false }, 10) 148 | return false 149 | }, 150 | 151 | // listener for mousewheel rotation 152 | wheelRotate: function (event) { 153 | if (!this.element || this.element.disabled || this.options.disabled) { 154 | return 155 | } 156 | event.preventDefault() 157 | var angle = this._angleInRadians(Math.round(event.originalEvent.deltaY / 10)) 158 | if (this.options.snap || event.shiftKey) { 159 | angle = this._calculateSnap(angle) 160 | } 161 | angle = this.elementCurrentAngle + angle 162 | this.angle(angle) 163 | this._trigger('rotate', event, this.ui()) 164 | }, 165 | 166 | // for callbacks 167 | ui: function () { 168 | return { 169 | api: this, 170 | element: this.element, 171 | angle: { 172 | start: this.elementStartAngle, 173 | current: this.elementCurrentAngle, 174 | degrees: this._normalizeDegrees(this._angleInDegrees(this.elementCurrentAngle)), 175 | stop: this.elementStopAngle 176 | } 177 | } 178 | }, 179 | 180 | /* *********************** private functions ************************** */ 181 | // calculates the radians for a given angle in degrees 182 | _angleInRadians: function (degrees) { 183 | return degrees * Math.PI / 180 184 | }, 185 | 186 | // calculates the degrees for a given angle in radians 187 | _angleInDegrees: function (radians) { 188 | return radians * 180 / Math.PI 189 | }, 190 | 191 | _normalizeDegrees: function (degrees) { 192 | return ((degrees % 360) + 360) % 360; 193 | }, 194 | 195 | // calculates the center of the element 196 | _calculateElementCenter: function () { 197 | var elementOffset = this._getElementOffset() 198 | 199 | // Rotation center given via options 200 | if (this._isRotationCenterSet()) { 201 | return { 202 | x: elementOffset.left + this.rotationCenterOffset().left, 203 | y: elementOffset.top + this.rotationCenterOffset().top 204 | } 205 | } 206 | 207 | // Deduce rotation center from transform-origin 208 | if (this.element.css('transform-origin') !== undefined) { 209 | var originPx = this.element.css('transform-origin').match(/([\d.]+)px +([\d.]+)px/) 210 | if (originPx != null) { 211 | return { 212 | x: elementOffset.left + parseFloat(originPx[1]), 213 | y: elementOffset.top + parseFloat(originPx[2]) 214 | } 215 | } 216 | } 217 | 218 | // Default rotation center: middle of the element 219 | return { 220 | x: elementOffset.left + this.element.width() / 2, 221 | y: elementOffset.top + this.element.height() / 2 222 | } 223 | }, 224 | 225 | // calculates the angle that the element should snap to and returns it in radians 226 | _calculateSnap: function (radians) { 227 | var degrees = this._angleInDegrees(radians) 228 | degrees = Math.round(degrees / this.options.step) * this.options.step 229 | return this._angleInRadians(degrees) 230 | }, 231 | 232 | // calculates the angle to rotate the element to, based on input 233 | _calculateRotateAngle: function (event) { 234 | var center = this.getElementCenter() 235 | 236 | var xFromCenter = event.pageX - center.x 237 | var yFromCenter = event.pageY - center.y 238 | var mouseAngle = Math.atan2(yFromCenter, xFromCenter) 239 | var rotateAngle = mouseAngle - this.mouseStartAngle + this.elementStartAngle 240 | 241 | if (this.options.snap || event.shiftKey) { 242 | rotateAngle = this._calculateSnap(rotateAngle) 243 | } 244 | 245 | return rotateAngle 246 | }, 247 | 248 | // constructor 249 | _create: function () { 250 | var handle 251 | if (!this.options.handle) { 252 | handle = $(document.createElement('div')) 253 | handle.addClass('ui-rotatable-handle') 254 | if (this.options.handleOffset.top !== 0 || this.options.handleOffset.left !== 0) { 255 | handle.css('position', 'relative') 256 | handle.css('top', this.options.handleOffset.top + 'px') 257 | handle.css('left', this.options.handleOffset.left + 'px') 258 | } 259 | } else { 260 | handle = this.options.handle 261 | } 262 | 263 | this.listeners = { 264 | rotateElement: $.proxy(this.rotateElement, this), 265 | startRotate: $.proxy(this.startRotate, this), 266 | stopRotate: $.proxy(this.stopRotate, this), 267 | wheelRotate: $.proxy(this.wheelRotate, this) 268 | } 269 | 270 | if (this.options.wheelRotate) { 271 | this.element.bind('wheel', this.listeners.wheelRotate) 272 | } 273 | 274 | handle.draggable({ helper: 'clone', start: this._dragStart, handle: handle }) 275 | handle.bind('mousedown', this.listeners.startRotate) 276 | 277 | if (!handle.closest(this.element).length) { 278 | handle.appendTo(this.element) 279 | } 280 | this.rotationCenterOffset(this.options.rotationCenterOffset) 281 | 282 | if (this.options.degrees) { 283 | this.elementCurrentAngle = this._angleInRadians(this.options.degrees) 284 | } 285 | else { 286 | this.elementCurrentAngle = this.options.radians || this.options.angle || 0 287 | } 288 | this._performRotation(this.elementCurrentAngle) 289 | }, 290 | 291 | // destructor 292 | _destroy: function () { 293 | this.element.removeClass('ui-rotatable') 294 | this.element.find('.ui-rotatable-handle').remove() 295 | 296 | if (this.options.wheelRotate) { 297 | this.element.unbind('wheel', this.listeners.wheelRotate) 298 | } 299 | }, 300 | 301 | // used for the handle 302 | _dragStart: function (event) { 303 | if (this.element) { 304 | return false 305 | } 306 | }, 307 | 308 | // retrieves the element offset 309 | _getElementOffset: function () { 310 | this._performRotation(0) 311 | var offset = this.element.offset() 312 | this._performRotation(this.elementCurrentAngle) 313 | return offset 314 | }, 315 | 316 | _getTransforms: function (angle) { 317 | var transforms = 'rotate(' + angle + 'rad)' 318 | 319 | if (this.options.transforms) { 320 | transforms += ' ' + (function (transforms) { 321 | var t = [] 322 | for (var i in transforms) { 323 | if (transforms.hasOwnProperty(i) && transforms[i]) { 324 | t.push(i + '(' + transforms[i] + ')') 325 | } 326 | } 327 | return t.join(' ') 328 | }(this.options.transforms)) 329 | } 330 | return transforms 331 | }, 332 | 333 | // checks to see if the element has a rotationCenterOffset set 334 | _isRotationCenterSet: function () { 335 | return (this.options.rotationCenterOffset.top !== 0 || this.options.rotationCenterOffset.left !== 0) 336 | }, 337 | 338 | // performs the actual rotation on the element 339 | _performRotation: function (angle) { 340 | if (this._isRotationCenterSet()) { 341 | this.element.css('transform-origin', this.options.rotationCenterOffset.left + 'px ' + this.options.rotationCenterOffset.top + 'px') 342 | this.element.css('-ms-transform-origin', this.options.rotationCenterOffset.left + 'px ' + this.options.rotationCenterOffset.top + 'px') /* IE 9 */ 343 | this.element.css('-webkit-transform-origin', this.options.rotationCenterOffset.left + 'px ' + this.options.rotationCenterOffset + 'px') /* Chrome, Safari, Opera */ 344 | } 345 | 346 | var transforms = this._getTransforms(angle) 347 | 348 | this.element.css('transform', transforms) 349 | this.element.css('-moz-transform', transforms) 350 | this.element.css('-webkit-transform', transforms) 351 | this.element.css('-o-transform', transforms) 352 | }, 353 | 354 | // propagates events 355 | _propagate: function (n, event) { 356 | $.ui.plugin.call(this, n, [event, this.ui()]); 357 | (n !== 'rotate' && this._trigger(n, event, this.ui())) 358 | } 359 | }) 360 | 361 | return $.ui.rotatable 362 | })) 363 | -------------------------------------------------------------------------------- /ext/img_rotate/linestickers.php: -------------------------------------------------------------------------------- 1 | /"; 34 | 35 | //執行正規表達式 36 | if( preg_match_all($regex, $html, $matches) ){ 37 | //設定成功訊息 38 | $obj['success'] = true; 39 | $obj['info'] = '下載成功'; 40 | $obj['results'] = []; //設定 result => array 41 | 42 | //將比對到的資料,各別放至 $obj['result'] 當中 43 | for($i = 0; $i < count($matches[1]); $i++){ 44 | //將特殊符號,轉成正常的文字 (例如 $nbsp; 和 " 等) 45 | $strJson = htmlspecialchars_decode($matches[1][$i]); 46 | 47 | //將字串格式的 json,轉成 物件 (object) 48 | $o = json_decode($strJson, true); 49 | 50 | //將比對到的每一張貼圖資訊,附在陣列尾端 51 | $obj['results'][] = [ 52 | "animationUrl" => $o["animationUrl"], 53 | "id" => $o["id"], 54 | "popupUrl" => $o["popupUrl"], 55 | "soundUrl" => $o["soundUrl"], 56 | "staticUrl" => $o["staticUrl"] 57 | ]; 58 | } 59 | } 60 | } 61 | 62 | //將 $obj 轉成 json,並加以輸出 63 | echo json_encode($obj, JSON_UNESCAPED_UNICODE); -------------------------------------------------------------------------------- /ext/lottery/custom.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 威力彩 遊戲介紹 3 | * https://www.taiwanlottery.com.tw/Superlotto638/index.asp 4 | */ 5 | 6 | //取得亂數 7 | function getRandom(x) { 8 | /** 9 | * 假設 x 為 38,產生的值就落在 0 - 37 之間, 10 | * 此時程式後面再加 1, 11 | * 代表產生的值落在 1 - 38 之間, 12 | * 再進行回傳 13 | */ 14 | return Math.floor(Math.random() * x) + 1; 15 | } 16 | 17 | //產生威力彩號碼 18 | function getPowerNum() { 19 | //放置第一區 6 個號碼的陣列變數 20 | let arr = []; 21 | 22 | //一注威力彩號碼有 6 個所以我們讓迴圈跑六次 23 | for (i = 1; i <= 6; i++) { 24 | /** 25 | * 用 indexOf 判斷該數字之前有沒有出現過, 26 | * 如果有,就將 i 遞減,等於讓這輪重跑一次。 27 | */ 28 | 29 | //隨機取得 1 ~ 38 之間的數字 30 | let num = getRandom(38); 31 | 32 | //檢查是否有出現過(重複) 33 | if (arr.indexOf(num) > -1) { 34 | i--; 35 | continue; 36 | } else { 37 | //沒出現過的話就寫進陣列裡 38 | arr.push(num); 39 | } 40 | } 41 | 42 | /** 43 | * 排序陣列當中的值,由小至大 44 | * 45 | * 參考網頁: 46 | * https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Global_Objects/Array/sort 47 | */ 48 | arr.sort(function(a, b) { 49 | /** 50 | * 用數字排序 51 | * a - b 指的是由小到大 52 | * b - a 指的是由大到小 53 | * 54 | * 若只有 arr.sort(),括號裡面沒有排序用的 function, 55 | * 則以字串作為排序依據,例如 [20, 5, 9, 10], 56 | * 就會變成 [10, 20, 5, 9] 57 | */ 58 | return a - b; 59 | }); 60 | 61 | //回傳第一區 6 個號碼 62 | return arr; 63 | } 64 | 65 | /** 66 | * 回傳結果範例 67 | * 第一區號碼為: 8,9,22,25,35,37,第二區號碼為: 7 68 | * 第一區號碼為: 3,14,17,18,31,36,第二區號碼為: 4 69 | */ 70 | 71 | //取得第一區的號碼陣列,陣列長度為 6 (代表 6 個號碼) 72 | let arr = getPowerNum(); 73 | 74 | /** 75 | * 使用「,」將第一區號碼從陣列進行合併,轉成字串, 76 | * 例如 [2,4,6,8,10],透過 arr.join(","), 77 | * 就會變成字串型態的 "2,4,6,8,10", 78 | */ 79 | let num01 = arr.join(","); 80 | 81 | //取得第二區號碼 82 | let num02 = getRandom(8); 83 | 84 | console.log(`第一區號碼為 ${num01},第二區號碼為: ${num02}`); -------------------------------------------------------------------------------- /ext/lottery/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /ext/tts/fetch.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 | 11 | 12 | 26 | 27 | 28 | 29 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 160 | 161 | -------------------------------------------------------------------------------- /ext/tts/jquery.highlight-within-textarea.css: -------------------------------------------------------------------------------- 1 | .hwt-container { 2 | display: inline-block; 3 | position: relative; 4 | overflow: hidden !important; 5 | -webkit-text-size-adjust: none !important; 6 | } 7 | 8 | .hwt-backdrop { 9 | position: absolute !important; 10 | top: 0 !important; 11 | right: -99px !important; 12 | bottom: 0 !important; 13 | left: 0 !important; 14 | padding-right: 99px !important; 15 | overflow-x: hidden !important; 16 | overflow-y: auto !important; 17 | } 18 | 19 | .hwt-highlights { 20 | width: auto !important; 21 | height: auto !important; 22 | border-color: transparent !important; 23 | white-space: pre-wrap !important; 24 | word-wrap: break-word !important; 25 | color: transparent !important; 26 | overflow: hidden !important; 27 | } 28 | 29 | .hwt-input { 30 | display: block !important; 31 | position: relative !important; 32 | margin: 0; 33 | padding: 0; 34 | border-radius: 0; 35 | font: inherit; 36 | overflow-x: hidden !important; 37 | overflow-y: auto !important; 38 | } 39 | 40 | .hwt-content { 41 | border: 1px solid; 42 | background: none transparent !important; 43 | } 44 | 45 | .hwt-content mark { 46 | padding: 0 !important; 47 | color: inherit; 48 | } 49 | -------------------------------------------------------------------------------- /ext/tts/jquery.highlight-within-textarea.js: -------------------------------------------------------------------------------- 1 | /* 2 | * highlight-within-textarea 3 | * 4 | * @author Will Boyd 5 | * @github https://github.com/lonekorean/highlight-within-textarea 6 | */ 7 | 8 | (function($) { 9 | let ID = 'hwt'; 10 | 11 | let HighlightWithinTextarea = function($el, config) { 12 | this.init($el, config); 13 | }; 14 | 15 | HighlightWithinTextarea.prototype = { 16 | init: function($el, config) { 17 | this.$el = $el; 18 | 19 | // backwards compatibility with v1 (deprecated) 20 | if (this.getType(config) === 'function') { 21 | config = { highlight: config }; 22 | } 23 | 24 | if (this.getType(config) === 'custom') { 25 | this.highlight = config; 26 | this.generate(); 27 | } else { 28 | console.error('valid config object not provided'); 29 | } 30 | }, 31 | 32 | // returns identifier strings that aren't necessarily "real" JavaScript types 33 | getType: function(instance) { 34 | let type = typeof instance; 35 | if (!instance) { 36 | return 'falsey'; 37 | } else if (Array.isArray(instance)) { 38 | if (instance.length === 2 && typeof instance[0] === 'number' && typeof instance[1] === 'number') { 39 | return 'range'; 40 | } else { 41 | return 'array'; 42 | } 43 | } else if (type === 'object') { 44 | if (instance instanceof RegExp) { 45 | return 'regexp'; 46 | } else if (instance.hasOwnProperty('highlight')) { 47 | return 'custom'; 48 | } 49 | } else if (type === 'function' || type === 'string') { 50 | return type; 51 | } 52 | 53 | return 'other'; 54 | }, 55 | 56 | generate: function() { 57 | this.$el 58 | .addClass(ID + '-input ' + ID + '-content') 59 | .on('input.' + ID, this.handleInput.bind(this)) 60 | .on('scroll.' + ID, this.handleScroll.bind(this)); 61 | 62 | this.$highlights = $('
', { class: ID + '-highlights ' + ID + '-content' }); 63 | 64 | this.$backdrop = $('
', { class: ID + '-backdrop' }) 65 | .append(this.$highlights); 66 | 67 | this.$container = $('
', { class: ID + '-container' }) 68 | .insertAfter(this.$el) 69 | .append(this.$backdrop, this.$el) // moves $el into $container 70 | .on('scroll', this.blockContainerScroll.bind(this)); 71 | 72 | this.browser = this.detectBrowser(); 73 | switch (this.browser) { 74 | case 'firefox': 75 | this.fixFirefox(); 76 | break; 77 | case 'ios': 78 | this.fixIOS(); 79 | break; 80 | } 81 | 82 | // plugin function checks this for success 83 | this.isGenerated = true; 84 | 85 | // trigger input event to highlight any existing input 86 | this.handleInput(); 87 | }, 88 | 89 | // browser sniffing sucks, but there are browser-specific quirks to handle 90 | // that are not a matter of feature detection 91 | detectBrowser: function() { 92 | let ua = window.navigator.userAgent.toLowerCase(); 93 | if (ua.indexOf('firefox') !== -1) { 94 | return 'firefox'; 95 | } else if (!!ua.match(/msie|trident\/7|edge/)) { 96 | return 'ie'; 97 | } else if (!!ua.match(/ipad|iphone|ipod/) && ua.indexOf('windows phone') === -1) { 98 | // Windows Phone flags itself as "like iPhone", thus the extra check 99 | return 'ios'; 100 | } else { 101 | return 'other'; 102 | } 103 | }, 104 | 105 | // Firefox doesn't show text that scrolls into the padding of a textarea, so 106 | // rearrange a couple box models to make highlights behave the same way 107 | fixFirefox: function() { 108 | // take padding and border pixels from highlights div 109 | let padding = this.$highlights.css([ 110 | 'padding-top', 'padding-right', 'padding-bottom', 'padding-left' 111 | ]); 112 | let border = this.$highlights.css([ 113 | 'border-top-width', 'border-right-width', 'border-bottom-width', 'border-left-width' 114 | ]); 115 | this.$highlights.css({ 116 | 'padding': '0', 117 | 'border-width': '0' 118 | }); 119 | 120 | this.$backdrop 121 | .css({ 122 | // give padding pixels to backdrop div 123 | 'margin-top': '+=' + padding['padding-top'], 124 | 'margin-right': '+=' + padding['padding-right'], 125 | 'margin-bottom': '+=' + padding['padding-bottom'], 126 | 'margin-left': '+=' + padding['padding-left'], 127 | }) 128 | .css({ 129 | // give border pixels to backdrop div 130 | 'margin-top': '+=' + border['border-top-width'], 131 | 'margin-right': '+=' + border['border-right-width'], 132 | 'margin-bottom': '+=' + border['border-bottom-width'], 133 | 'margin-left': '+=' + border['border-left-width'], 134 | }); 135 | }, 136 | 137 | // iOS adds 3px of (unremovable) padding to the left and right of a textarea, 138 | // so adjust highlights div to match 139 | fixIOS: function() { 140 | this.$highlights.css({ 141 | 'padding-left': '+=3px', 142 | 'padding-right': '+=3px' 143 | }); 144 | }, 145 | 146 | handleInput: function() { 147 | let input = this.$el.val(); 148 | let ranges = this.getRanges(input, this.highlight); 149 | let unstaggeredRanges = this.removeStaggeredRanges(ranges); 150 | let boundaries = this.getBoundaries(unstaggeredRanges); 151 | this.renderMarks(boundaries); 152 | }, 153 | 154 | getRanges: function(input, highlight) { 155 | let type = this.getType(highlight); 156 | switch (type) { 157 | case 'array': 158 | return this.getArrayRanges(input, highlight); 159 | case 'function': 160 | return this.getFunctionRanges(input, highlight); 161 | case 'regexp': 162 | return this.getRegExpRanges(input, highlight); 163 | case 'string': 164 | return this.getStringRanges(input, highlight); 165 | case 'range': 166 | return this.getRangeRanges(input, highlight); 167 | case 'custom': 168 | return this.getCustomRanges(input, highlight); 169 | default: 170 | if (!highlight) { 171 | // do nothing for falsey values 172 | return []; 173 | } else { 174 | console.error('unrecognized highlight type'); 175 | } 176 | } 177 | }, 178 | 179 | getArrayRanges: function(input, arr) { 180 | let ranges = arr.map(this.getRanges.bind(this, input)); 181 | return Array.prototype.concat.apply([], ranges); 182 | }, 183 | 184 | getFunctionRanges: function(input, func) { 185 | return this.getRanges(input, func(input)); 186 | }, 187 | 188 | getRegExpRanges: function(input, regex) { 189 | let ranges = []; 190 | let match; 191 | while (match = regex.exec(input), match !== null) { 192 | ranges.push([match.index, match.index + match[0].length]); 193 | if (!regex.global) { 194 | // non-global regexes do not increase lastIndex, causing an infinite loop, 195 | // but we can just break manually after the first match 196 | break; 197 | } 198 | } 199 | return ranges; 200 | }, 201 | 202 | getStringRanges: function(input, str) { 203 | let ranges = []; 204 | let inputLower = input.toLowerCase(); 205 | let strLower = str.toLowerCase(); 206 | let index = 0; 207 | while (index = inputLower.indexOf(strLower, index), index !== -1) { 208 | ranges.push([index, index + strLower.length]); 209 | index += strLower.length; 210 | } 211 | return ranges; 212 | }, 213 | 214 | getRangeRanges: function(input, range) { 215 | return [range]; 216 | }, 217 | 218 | getCustomRanges: function(input, custom) { 219 | let ranges = this.getRanges(input, custom.highlight); 220 | if (custom.className) { 221 | ranges.forEach(function(range) { 222 | // persist class name as a property of the array 223 | if (range.className) { 224 | range.className = custom.className + ' ' + range.className; 225 | } else { 226 | range.className = custom.className; 227 | } 228 | }); 229 | } 230 | return ranges; 231 | }, 232 | 233 | // prevent staggered overlaps (clean nesting is fine) 234 | removeStaggeredRanges: function(ranges) { 235 | let unstaggeredRanges = []; 236 | ranges.forEach(function(range) { 237 | let isStaggered = unstaggeredRanges.some(function(unstaggeredRange) { 238 | let isStartInside = range[0] > unstaggeredRange[0] && range[0] < unstaggeredRange[1]; 239 | let isStopInside = range[1] > unstaggeredRange[0] && range[1] < unstaggeredRange[1]; 240 | return isStartInside !== isStopInside; // xor 241 | }); 242 | if (!isStaggered) { 243 | unstaggeredRanges.push(range); 244 | } 245 | }); 246 | return unstaggeredRanges; 247 | }, 248 | 249 | getBoundaries: function(ranges) { 250 | let boundaries = []; 251 | ranges.forEach(function(range) { 252 | boundaries.push({ 253 | type: 'start', 254 | index: range[0], 255 | className: range.className 256 | }); 257 | boundaries.push({ 258 | type: 'stop', 259 | index: range[1] 260 | }); 261 | }); 262 | 263 | this.sortBoundaries(boundaries); 264 | return boundaries; 265 | }, 266 | 267 | sortBoundaries: function(boundaries) { 268 | // backwards sort (since marks are inserted right to left) 269 | boundaries.sort(function(a, b) { 270 | if (a.index !== b.index) { 271 | return b.index - a.index; 272 | } else if (a.type === 'stop' && b.type === 'start') { 273 | return 1; 274 | } else if (a.type === 'start' && b.type === 'stop') { 275 | return -1; 276 | } else { 277 | return 0; 278 | } 279 | }); 280 | }, 281 | 282 | renderMarks: function(boundaries) { 283 | let input = this.$el.val(); 284 | boundaries.forEach(function(boundary, index) { 285 | let markup; 286 | if (boundary.type === 'start') { 287 | markup = '{{hwt-mark-start|' + index + '}}'; 288 | } else { 289 | markup = '{{hwt-mark-stop}}'; 290 | } 291 | input = input.slice(0, boundary.index) + markup + input.slice(boundary.index); 292 | }); 293 | 294 | // this keeps scrolling aligned when input ends with a newline 295 | input = input.replace(/\n(\{\{hwt-mark-stop\}\})?$/, '\n\n$1'); 296 | 297 | // encode HTML entities 298 | input = input.replace(//g, '>'); 299 | 300 | if (this.browser === 'ie') { 301 | // IE/Edge wraps whitespace differently in a div vs textarea, this fixes it 302 | input = input.replace(/ /g, ' '); 303 | } 304 | 305 | // replace start tokens with opening tags with class name 306 | input = input.replace(/\{\{hwt-mark-start\|(\d+)\}\}/g, function(match, submatch) { 307 | var className = boundaries[+submatch].className; 308 | if (className) { 309 | return ''; 310 | } else { 311 | return ''; 312 | } 313 | }); 314 | 315 | // replace stop tokens with closing tags 316 | input = input.replace(/\{\{hwt-mark-stop\}\}/g, ''); 317 | 318 | this.$highlights.html(input); 319 | }, 320 | 321 | handleScroll: function() { 322 | let scrollTop = this.$el.scrollTop(); 323 | this.$backdrop.scrollTop(scrollTop); 324 | 325 | // Chrome and Safari won't break long strings of spaces, which can cause 326 | // horizontal scrolling, this compensates by shifting highlights by the 327 | // horizontally scrolled amount to keep things aligned 328 | let scrollLeft = this.$el.scrollLeft(); 329 | this.$backdrop.css('transform', (scrollLeft > 0) ? 'translateX(' + -scrollLeft + 'px)' : ''); 330 | }, 331 | 332 | // in Chrome, page up/down in the textarea will shift stuff within the 333 | // container (despite the CSS), this immediately reverts the shift 334 | blockContainerScroll: function() { 335 | this.$container.scrollLeft(0); 336 | }, 337 | 338 | destroy: function() { 339 | this.$backdrop.remove(); 340 | this.$el 341 | .unwrap() 342 | .removeClass(ID + '-text ' + ID + '-input') 343 | .off(ID) 344 | .removeData(ID); 345 | }, 346 | }; 347 | 348 | // register the jQuery plugin 349 | $.fn.highlightWithinTextarea = function(options) { 350 | return this.each(function() { 351 | let $this = $(this); 352 | let plugin = $this.data(ID); 353 | 354 | if (typeof options === 'string') { 355 | if (plugin) { 356 | switch (options) { 357 | case 'update': 358 | plugin.handleInput(); 359 | break; 360 | case 'destroy': 361 | plugin.destroy(); 362 | break; 363 | default: 364 | console.error('unrecognized method string'); 365 | } 366 | } else { 367 | console.error('plugin must be instantiated first'); 368 | } 369 | } else { 370 | if (plugin) { 371 | plugin.destroy(); 372 | } 373 | plugin = new HighlightWithinTextarea($this, options); 374 | if (plugin.isGenerated) { 375 | $this.data(ID, plugin); 376 | } 377 | } 378 | }); 379 | }; 380 | })(jQuery); 381 | -------------------------------------------------------------------------------- /ext/tts/jquery.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 | 11 | 12 | 26 | 27 | 28 | 29 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 132 | 133 | -------------------------------------------------------------------------------- /ext/tts/sound.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 | 11 |

請選擇所要上傳的檔案

12 | 13 | 14 |
15 | 16 | 17 | 18 |
19 | 20 |
21 | 22 | 69 | 70 | -------------------------------------------------------------------------------- /ext/web_api/fetch.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 | 11 | 12 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 |
idcitynameaddressurlsocketlatitudelongitude
40 | 41 | 42 | 43 | 44 | 45 | 95 | 96 | -------------------------------------------------------------------------------- /ext/web_api/web_api_coffee.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |
_id餐廳名稱餐館電話餐館地址
27 | 28 | 52 | 53 | -------------------------------------------------------------------------------- /javascript_basics.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/telunyang/javascript_basics/92a1e89c7fabdfaf1e67dff981bbb14996f05c53/javascript_basics.docx -------------------------------------------------------------------------------- /javascript_basics.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/telunyang/javascript_basics/92a1e89c7fabdfaf1e67dff981bbb14996f05c53/javascript_basics.pdf --------------------------------------------------------------------------------